:root {
    /* ============================================================
     * Profit Calc visual system
     * Near-black primary, white cards, muted gray-green surfaces.
     * Green = profit/success, mint = one insight/completion,
     * coral = problem/loss, platform colors = ad sources only.
     * ============================================================ */
    --pc-primary-ink: #171A18;
    --pc-chart-ink: #3D4540;
    --pc-muted: #7B837D;
    --pc-neutral: #99A19C;

    /* Shared charcoal surface for table headers, sidebar active state,
     * Mission Control card headers, and primary actions. Softer than
     * --pc-primary-ink (#171A18) so it reads as graphite rather than pure
     * black, and stays consistent with the historical graphite (#393e44)
     * used across buttons/headers elsewhere in the app. */
    --pc-header-bg: #393e44;
    --pc-action-bg: #393e44;
    --pc-action-hover-bg: #2f3439;

    /* App-wide page background tokens. The gradient lives on the main
     * content wrapper (.dashboard-finance), never on the sidebar shell,
     * so navigation stays flat while the app surface carries a subtle
     * light-gray gradient that radiates from the top-right and fades
     * across the page. */
    --pc-app-bg: #FAFAFA;
    --pc-app-bg-gradient: radial-gradient(ellipse at 88% 0%, rgba(210, 215, 211, 0.42) 0%, rgba(226, 229, 226, 0.28) 28%, rgba(240, 242, 240, 0.14) 52%, rgba(250, 250, 250, 0) 76%);
    /* Sidebar is a flat white surface so the content-area gradient can never
     * show through or read as a tinted/gradient background behind the nav. */
    --pc-sidebar-bg: #FFFFFF;

    /* Backward-compatible aliases. Legacy token names still resolve to the
     * new app surface tokens so existing references inherit the new system. */
    --pc-bg: var(--pc-app-bg);
    --pc-bg-gradient: var(--pc-app-bg-gradient);

    --pc-card: #FFFFFF;
    --pc-border: #E5E9E4;
    --pc-card-border: #CFD4CE;

    --pc-positive: #32B36F;
    --pc-mint: #62E99A;
    --pc-mint-soft: #E9FFF0;

    --pc-negative: #DF716A;
    --pc-negative-soft: #FDEDED;

    --pc-inactive: #D9DEDA;

    /* Placeholder/helper text inside form inputs. Intentionally lighter and
     * italicized (see the ::placeholder rule below) so example values such as
     * '111-111-1111' or '0.00' never read as real entered data. */
    --pc-placeholder: #8F978F;

    /* Neutral hover surface for generic interactive states (table rows,
     * sidebar links). Keeps green/mint reserved for semantic profit/success. */
    --pc-hover-neutral: #EEF1EF;

    /* Ad-platform colors — muted, used only in ad-platform surfaces. */
    --pc-platform-facebook: #929DCA;
    --pc-platform-google: #83B39A;
    --pc-platform-bing: #8BB8BE;
    --pc-platform-snapchat: #D1B987;
    --pc-platform-pinterest: #AA9BC9;
    --pc-platform-tiktok: #747A76;
    --pc-platform-reddit: #C4938C;

    /* Backward-compatible aliases. Legacy token names still referenced by
     * older components now resolve to the new palette so every surface
     * inherits the new visual system without per-file rewrites. */
    --pc-surface: var(--pc-bg);
    --pc-surface-raised: var(--pc-card);
    --pc-graphite: var(--pc-primary-ink);
    --pc-ink: var(--pc-primary-ink);
    --pc-coral: var(--pc-negative);
    --pc-sky: var(--pc-platform-bing);
    --pc-radius: 12px;
    --pc-radius-sm: 10px;
    --pc-shadow-soft: 0 1px 2px rgba(23, 26, 24, 0.04);
    --pc-shadow-hover: 0 8px 22px rgba(23, 26, 24, 0.08);
}

/* ============================================================
 * App-wide surfaces, typography, cards, controls
 * Layout is intentionally left unchanged — only color/surface.
 * ============================================================ */

/* html/body are the base surface (flat near-white). The light-gray gradient
 * is applied only to .dashboard-finance (the innermost content wrapper), not
 * its parent .dashboard-wrapper, so the two layers don't double-stack and
 * wash out the gradient into a flat tint. The sidebar — which lives in
 * .dashboard-main-wrapper — never inherits the gradient. */
html,
body {
    background: var(--pc-app-bg);
    color: var(--pc-primary-ink);
}

.dashboard-wrapper {
    background: var(--pc-app-bg);
    color: var(--pc-primary-ink);
}

.dashboard-finance {
    background: var(--pc-app-bg-gradient), var(--pc-app-bg);
    color: var(--pc-primary-ink);
}

.dashboard-content {
    color: var(--pc-primary-ink);
}

h1, h2, h3, h4, h5, h6,
.page-title,
.page-title-section h1 {
    color: var(--pc-primary-ink);
}

.metric-label,
.text-muted,
small,
.small {
    color: var(--pc-muted);
}

/* ============================================================
 * Dashboard metric typography
 * The .metric-value wrapper owns the number size via a custom property
 * (--metric-number-size). The number h1 inherits at 1em and the currency
 * symbol at 0.7em, so the 70% ratio holds at every card size without
 * hardcoding separate pixel values for each element.
 * ============================================================ */

/* Bootstrap .d-inline-block on the same element sets display:inline-block
 * !important, which would silently defeat the flex layout. Override with
 * !important so the symbol and number share a baseline. */
.metric-value,
.metric-value.d-inline-block {
    --metric-number-size: 30px;
    display: inline-flex !important;
    align-items: center;
    font-size: var(--metric-number-size);
    white-space: nowrap;
}

/* Top-row KPI cards use a slightly larger value. */
.metric-value--top {
    --metric-number-size: 34px;
}

.metric-value > h1 {
    display: inline-block;
    font-size: 1em;
    font-weight: 650;
    letter-spacing: -0.02em;
    line-height: 1.1;
}

/* Currency symbol: 70% of the number size (0.7em), muted so it reads as a
 * supporting prefix. The inline-flex parent uses align-items: center so
 * the symbol is vertically centered against the number — no manual
 * vertical offset needed. */
.metric-value > .metric-currency-symbol {
    color: var(--pc-muted);
    font-size: 0.7em;
    font-weight: inherit;
    letter-spacing: inherit;
    line-height: 1;
    margin-right: 0.08em;
}

/* Profit cards carry a health color (green/red/neutral). The symbol on
 * those cards should match the number, not the muted default. */
.profit-accent-card .metric-value > .metric-currency-symbol {
    color: var(--profit-health-color);
}

@media (max-width: 576px) {
    .metric-value,
    .metric-value.d-inline-block {
        --metric-number-size: 26px;
    }

    .metric-value--top {
        --metric-number-size: 29px;
    }
}

/* Cards: white, slightly stronger border so they read as distinct surfaces,
 * soft radius, no heavy shadows. */
.card,
.card-dashboard,
.dashboard-chart-card,
.mc-card,
.mission-control-title-card,
.mission-control-notes-card,
.report-guide-card,
.report-guide-title-card {
    background-color: var(--pc-card);
    border: 1.5px solid var(--pc-card-border);
    border-radius: var(--pc-radius);
    box-shadow: var(--pc-shadow-soft);
}

.card-dashboard {
    transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}

.card-dashboard:hover {
    transform: translateY(-2px);
    border-color: var(--pc-primary-ink);
    box-shadow: var(--pc-shadow-hover);
}

/* Card headers: flat and quiet, no divider line under the title. */
.card-header {
    background-color: transparent;
    border-bottom: 0;
    color: var(--pc-primary-ink);
}

.dashboard-chart-card > .card-header {
    background: transparent;
    border-bottom: 0;
}

/* Revenue Overview loads after the dashboard cards so the page becomes useful
 * quickly. Keep that deferred work visible without blocking the chart once it
 * is ready for interaction. */
.dashboard-chart-card #line-chart-section {
    min-height: 200px;
    position: relative;
}

.dashboard-chart-loading {
    align-items: center;
    color: var(--pc-primary-ink);
    display: flex;
    font-size: 0.9rem;
    font-weight: 700;
    gap: 0.5rem;
    inset: 0;
    justify-content: center;
    pointer-events: none;
    position: absolute;
    z-index: 1;
}

.dashboard-chart-loading.hidden {
    display: none;
}

.dashboard-chart-error {
    align-items: center;
    color: var(--pc-primary-ink);
    display: flex;
    flex-direction: column;
    font-size: 0.9rem;
    font-weight: 700;
    gap: 0.75rem;
    inset: 0;
    justify-content: center;
    position: absolute;
    text-align: center;
    z-index: 1;
}

.dashboard-chart-error.hidden {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .dashboard-chart-loading .fa-spin {
        animation: none;
    }
}

/* Profit is the primary business outcome, so only Profit cards carry a
 * colored left accent. A single card-level variable (--profit-health-color)
 * drives BOTH the left border and the profit value text so they always
 * match. The active state class is toggled by updateUI.js once profit known. */
.profit-accent-card {
    --profit-health-color: var(--pc-neutral);
    border-left: 4px solid var(--profit-health-color);
    transition: border-color 0.2s ease;
}

.profit-accent-card.profit-accent-card--positive {
    --profit-health-color: var(--pc-positive);
}

.profit-accent-card.profit-accent-card--negative {
    --profit-health-color: var(--pc-negative);
}

.profit-accent-card.profit-accent-card--neutral {
    --profit-health-color: var(--pc-neutral);
}

/* The profit value number inside the card reads in the same health color. */
.profit-accent-card #profit-top,
.profit-accent-card #profit {
    color: var(--profit-health-color);
}

/* Buttons: primary = graphite charcoal, secondary = white/border. Primary
 * and hover differ slightly so the hover state is visible (the previous
 * rule made normal and hover identical, so Submit buttons never changed). */
.btn-primary,
.btn-success,
.btn-outline-success {
    background-color: var(--pc-action-bg);
    border-color: var(--pc-action-bg);
    color: #ffffff;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.btn-primary:hover,
.btn-success:hover,
.btn-outline-success:hover {
    background-color: var(--pc-action-hover-bg);
    border-color: var(--pc-action-hover-bg);
    color: #ffffff;
}

.btn-outline-dark {
    background-color: var(--pc-card);
    border-color: var(--pc-border);
    color: var(--pc-primary-ink);
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

/* Outline-dark (generic Edit/secondary actions) hover to graphite charcoal
 * with white text, matching the primary action family rather than mint/green. */
.btn-outline-dark:hover {
    background-color: var(--pc-action-bg);
    border-color: var(--pc-action-bg);
    color: #ffffff;
}

/* Outline-light buttons (used for CSV export / report actions) read as
 * primary actions on light surfaces, so render as ink-on-white. */
.btn-outline-light {
    background-color: var(--pc-card);
    border-color: var(--pc-border);
    color: var(--pc-primary-ink);
}

.btn-outline-light:hover {
    background-color: var(--pc-primary-ink);
    border-color: var(--pc-primary-ink);
    color: #ffffff;
}

/* Destructive stays coral. */
.btn-danger,
.btn-outline-danger {
    background-color: var(--pc-card);
    border-color: var(--pc-negative);
    color: var(--pc-negative);
}

.btn-danger:hover,
.btn-outline-danger:hover {
    background-color: var(--pc-negative);
    border-color: var(--pc-negative);
    color: #ffffff;
}

/* Form controls / filters. */
.form-control,
.custom-select,
input.form-control.date-selector {
    background-color: var(--pc-card);
    border: 1px solid var(--pc-border);
    color: var(--pc-primary-ink);
}

.form-control:focus,
.custom-select:focus,
input.form-control.date-selector:focus {
    border-color: var(--pc-primary-ink);
    box-shadow: 0 0 0 3px rgba(23, 26, 24, 0.16);
}

/* ============================================================
 * Placeholder / helper text
 * Placeholder hints (e.g. '111-111-1111', '0.00', search
 * prompts) must read clearly as examples rather than entered
 * values. They use a muted gray token and italic styling so
 * they stay distinct from real input text. opacity: 1 unifies
 * Firefox/Safari which otherwise dim placeholders differently.
 * Vendor-prefixed selectors are grouped alongside the standard
 * ::placeholder rule for older browsers.
 * ============================================================ */
input::placeholder,
textarea::placeholder,
.form-control::placeholder,
input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder,
.form-control::-webkit-input-placeholder,
input::-moz-placeholder,
textarea::-moz-placeholder,
.form-control::-moz-placeholder {
    color: var(--pc-placeholder);
    font-style: italic;
    opacity: 1;
}

/* ============================================================
 * Date range picker
 * Selected calendar days, range endpoints, and active preset
 * ranges use the primary ink (near-black) so the selection state
 * reads as a primary action rather than semantic success green.
 * The vendor stylesheet is loaded before this file (see base
 * layouts) so these rules win without !important.
 * ============================================================ */
.daterangepicker td.active,
.daterangepicker td.active:hover,
.daterangepicker td.start-date,
.daterangepicker td.start-date.end-date,
.daterangepicker td.end-date {
    background-color: var(--pc-primary-ink);
    color: #ffffff;
}

/* Interior days of a multi-day range: neutral gray surface so the
 * range reads as a selection band, never as a green/mint wash. */
.daterangepicker td.in-range,
.daterangepicker td.in-range:hover {
    background-color: var(--pc-hover-neutral);
    color: var(--pc-primary-ink);
}

/* Active preset chip in the ranges list mirrors the selected day. */
.daterangepicker .ranges li.active,
.daterangepicker .ranges li:hover {
    background-color: var(--pc-primary-ink);
    color: #ffffff;
}

/* Tables: graphite headers for readability, faint row dividers. */
.table {
    color: var(--pc-primary-ink);
}

/* Column headers: a little taller with more horizontal padding so labels
 * never feel crammed against their neighbors. Header background uses the
 * shared graphite token so it matches the sidebar active state and the
 * historical #393e44 header color rather than reading as pure black. */
.table thead th,
.table .thead-dark th,
table.table thead.thead-dark th {
    background-color: var(--pc-header-bg);
    border-color: var(--pc-header-bg);
    color: #ffffff;
    font-weight: 700;
    padding-top: 0.85rem;
    padding-bottom: 0.85rem;
    padding-left: 1rem;
    padding-right: 1rem;
    white-space: nowrap;
}

.table th,
.table td {
    border-color: var(--pc-border);
}

/* Faint, neutral row hover applied to every data table, not only the
 * .table-hover variant. Bootstrap paints the cell background, so the
 * child td/th must carry the surface too. A neutral gray is used rather
 * than green/mint so the hover never reads as a semantic state. */
.table tbody tr:hover,
.table tbody tr:hover > td,
.table tbody tr:hover > th,
.table-hover tbody tr:hover,
.table-hover tbody tr:hover > td,
.table-hover tbody tr:hover > th,
.entry-month-group .table tbody tr:hover {
    background-color: var(--pc-hover-neutral);
}

/* Sticky first columns (e.g. the P&L metric label) must still adopt the
 * hover surface, otherwise the row hover reads as broken where it meets
 * the pinned cell. */
.metric-column:hover,
.metric-column:focus {
    background-color: var(--pc-hover-neutral);
}

/* ============================================================
 * Financial table presentation
 * Tabular numerals + right alignment so decimals line up vertically.
 * Profit is the only bold financial endpoint per row; other money
 * reads in a slightly larger medium weight so key figures (Revenue,
 * COGS, Fees, Margin, Profit) scan clearly without dominating.
 * Non-financial metadata (Gateway, Country, UTM Source) is de-emphasized
 * with the muted gray token.
 * ============================================================ */

.pc-financial-table tbody td,
.pc-financial-table tbody th {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1, "lnum" 1;
}

/* Right-aligned, medium-weight numbers. Used for money, percentages,
 * ratios, and counts alike — anything where columnar alignment matters. */
.pc-table-number,
.pc-table-money,
.pc-table-percent,
.pc-table-count {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1, "lnum" 1;
    font-size: 0.95rem;
    font-weight: 500;
    white-space: nowrap;
}

.pc-table-money {
    font-size: 0.96rem;
}

/* Profit is the single clear endpoint of each row: bold, same tabular
 * figure treatment so it still aligns with the other money columns. */
.pc-table-profit {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1, "lnum" 1;
    font-size: 0.96rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Bold inside a profit cell should not stack weights or spacing. */
.pc-table-profit strong,
.pc-table-profit b {
    font-weight: 700;
}

/* De-emphasize non-financial metadata so it recedes behind the numbers. */
.pc-table-meta {
    color: var(--pc-muted);
    font-weight: 400;
}

/* Inputs that hold financial values inside tables align with the
 * surrounding numeric cells. */
td input.form-control.pc-table-number,
td input.pc-table-number {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1, "lnum" 1;
}

/* Semantic value classes for metric deltas. */
.text-success {
    color: var(--pc-positive) !important;
}

.text-neg-profit {
    color: var(--pc-negative) !important;
}

.text-secondary {
    color: var(--pc-negative) !important;
}

/* A neutral 0% / flat state must read as muted gray, never green. */
.text-neutral-metric {
    color: var(--pc-muted) !important;
}

/* Alerts/states. */
.alert-success {
    background-color: var(--pc-mint-soft);
    border-color: var(--pc-border);
    color: var(--pc-primary-ink);
}

.alert-danger {
    background-color: var(--pc-negative-soft);
    border-color: var(--pc-border);
    color: var(--pc-negative);
}

/* Warnings are informational nudges (e.g. the P&L "separate processing"
 * note), not errors, so they must not read as red/coral. A soft amber
 * surface keeps them distinct from both danger and success. */
.alert-warning {
    background-color: #FFF8E8;
    border-color: #EADFBF;
    color: var(--pc-chart-ink);
}

.alert-light {
    background-color: var(--pc-card);
    border-color: var(--pc-border);
    color: var(--pc-muted);
}

/* ============================================================
 * Sidebar / navigation
 * Light, near-black-led. Active item = primary ink + white text,
 * with a thin mint indicator. Inactive items = muted gray-green.
 * ============================================================ */
/* Sidebar / navigation: flat white surface. The sidebar shell and its parent
 * wrapper (.dashboard-main-wrapper) are kept solid white (no gradient) so the
 * navigation always reads as a single clean surface. background-image: none
 * plus the explicit background-color guarantees no gradient layer — inherited
 * from the content area or any prior rule — can bleed through. */
.dashboard-main-wrapper,
.nav-left-sidebar,
.nav-left-sidebar.sidebar-dark,
.sidebar-dark.nav-left-sidebar {
    background-color: var(--pc-sidebar-bg) !important;
    background-image: none !important;
    border-right: 1px solid var(--pc-card-border);
    box-shadow: none !important;
}

/* Inner sidebar regions are kept on the same flat app surface rather than
 * transparent or white, so the content-area gradient can never show through
 * the navigation internals. */
.nav-left-sidebar .navbar,
.nav-left-sidebar .menu-list,
.nav-left-sidebar .navbar-collapse,
.nav-left-sidebar .navbar-nav,
.nav-left-sidebar .nav {
    background-color: var(--pc-sidebar-bg) !important;
    background-image: none !important;
}

.nav-left-sidebar .nav-link {
    font-weight: 600;
    color: var(--pc-muted);
    border-radius: var(--pc-radius-sm);
    transition: background-color 0.15s ease, color 0.15s ease;
}

.nav-left-sidebar .nav-link:hover {
    background-color: var(--pc-hover-neutral);
    color: var(--pc-primary-ink);
}

.nav-left-sidebar .nav-link.active,
.nav-left-sidebar .nav-link[aria-current="page"] {
    margin: 6px 0;
    background-color: var(--pc-header-bg);
    color: #ffffff;
    position: relative;
}

.nav-left-sidebar .nav-link.active::before,
.nav-left-sidebar .nav-link[aria-current="page"]::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 60%;
    border-radius: 0 3px 3px 0;
    background-color: var(--pc-mint);
}

.nav-left-sidebar .nav-divider {
    color: var(--pc-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.72rem;
    font-weight: 700;
    opacity: 0.8;
}

/* ============================================================
 * COGS settings: Shopify shipping label backfill link
 * The backfill action is rendered inline as a "Click here" link
 * within the Shipping Sync Settings card rather than its own
 * standalone button section.
 * ============================================================ */
#cogs-settings-page .shopify-shipping-label-sync-link.disabled {
    opacity: 0.6;
    pointer-events: none;
}

#cogs-settings-page #shopify-shipping-label-sync-status {
    min-height: 1.2em;
}

/* ============================================================
 * Loading brand logo
 * ProfitCalc wordmark shown at a fixed location near the top of the
 * sync overlay and the analytics "profit building" loaders so the
 * user always knows where they are while waiting. It floats
 * independently (position: fixed) so it shares one identical anchor
 * point across both screens and does not participate in the centered
 * animation stack.
 * ============================================================ */
.loading-brand-header {
    left: 0;
    right: 0;
    margin: 0;
    pointer-events: none;
    position: fixed;
    text-align: center;
    top: 164px;
    transform: none;
    z-index: 2;
}

.loading-brand-logo {
    display: inline-block;
    width: min(192px, 58vw);
    height: auto;
    margin: 0 auto;
}

@media (max-width: 575.98px) {
    .loading-brand-logo {
        width: min(182px, 62vw);
    }
}

/* On short viewports the fixed logo could overlap the centered overlay
 * content, so pull it closer to the top and shrink it slightly. */
@media (max-height: 520px) {
    .loading-brand-header {
        top: 72px;
    }

    .loading-brand-logo {
        width: min(154px, 50vw);
    }
}

/* ============================================================
 * Branded "profit building" loading animation
 * A compact line chart that draws upward with subtle dips and a
 * gently pulsing endpoint. Used by the dashboard + report loaders.
 * ============================================================ */
.profit-building-loader {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    text-align: center;
}

.profit-building-loader__chart {
    width: 180px;
    height: 64px;
    display: block;
    overflow: visible;
}

.profit-building-loader__line {
    fill: none;
    stroke: var(--pc-graphite, #393e44);
    stroke-width: 3.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: profit-building-loader-draw 1.8s cubic-bezier(0.45, 0.05, 0.25, 1) forwards;
}

.profit-building-loader__area {
    fill: var(--pc-graphite, #393e44);
    fill-opacity: 0;
    animation: profit-building-loader-area 1.8s cubic-bezier(0.45, 0.05, 0.25, 1) forwards;
}

.profit-building-loader__endpoint {
    fill: var(--pc-graphite, #393e44);
    opacity: 0;
    transform-box: fill-box;
    transform-origin: center;
    animation: profit-building-loader-endpoint 2s 1.5s ease-in-out infinite;
}

.profit-building-loader__title {
    margin: 0;
    color: var(--pc-graphite, #393e44);
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.25;
}

.profit-building-loader__step {
    margin: 0;
    min-height: 1.2em;
    color: var(--pc-muted, #5f6368);
    font-size: 0.9rem;
    font-weight: 600;
    transition: opacity 0.3s ease, transform 0.3s ease;
}

.profit-building-loader__step.is-fading {
    opacity: 0;
    transform: translateY(4px);
}

/* Static (completed or reduce-motion) chart: draw immediately. */
.profit-building-loader.is-static .profit-building-loader__line {
    animation: none;
    stroke-dashoffset: 0;
}

.profit-building-loader.is-static .profit-building-loader__area {
    animation: none;
    fill-opacity: 0.12;
}

.profit-building-loader.is-static .profit-building-loader__endpoint {
    animation: none;
    opacity: 1;
}

@keyframes profit-building-loader-draw {
    from { stroke-dashoffset: 1; }
    to { stroke-dashoffset: 0; }
}

@keyframes profit-building-loader-area {
    from { fill-opacity: 0; }
    to { fill-opacity: 0.12; }
}

@keyframes profit-building-loader-endpoint {
    0% { opacity: 0.85; transform: scale(1); }
    50% { opacity: 1; transform: scale(1.3); }
    100% { opacity: 0.85; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .profit-building-loader__line,
    .profit-building-loader__area,
    .profit-building-loader__endpoint,
    .profit-building-loader__step {
        animation: none;
        transition: none;
    }

    .profit-building-loader__line {
        stroke-dashoffset: 0;
    }

    .profit-building-loader__area {
        fill-opacity: 0.12;
    }

    .profit-building-loader__endpoint {
        opacity: 1;
    }
}

/* ============================================================
 * Shopify sync loader
 * Three order cards visibly travel into a single receiver. Their SVG x/y
 * attributes animate directly, while the receiver foreground hides the final
 * descent so each card appears to sink into the inbox.
 * ============================================================ */
.sync-orders-loader {
    display: flex;
    align-items: center;
    justify-content: center;
}

.sync-orders-loader__svg {
    width: min(240px, calc(100vw - 48px));
    height: auto;
    display: block;
}

.sync-orders-loader__card-sheet,
.sync-orders-loader__receiver-body {
    fill: var(--pc-surface-raised, #ffffff);
    stroke: var(--pc-graphite, #393e44);
    stroke-width: 4.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.sync-orders-loader__card-line {
    stroke: var(--pc-graphite, #393e44);
    stroke-width: 2;
    stroke-linecap: round;
    opacity: 0.48;
}

.sync-orders-loader__card-line--short {
    opacity: 0.25;
}

.sync-orders-loader__static-card {
    display: none;
}

.sync-orders-loader__receiver-check {
    stroke: var(--pc-graphite, #393e44);
    stroke-width: 3.5;
    opacity: 0;
    animation: sync-orders-loader-receive 4.2s ease-in-out infinite;
}

@keyframes sync-orders-loader-receive {
    0%, 13%, 23%, 46%, 56%, 79%, 89%, 100% { opacity: 0; }
    17%, 50%, 83% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .sync-orders-loader__moving-card,
    .sync-orders-loader__receiver-check {
        display: none;
    }

    .sync-orders-loader__static-card {
        display: inline;
    }

    .sync-orders-loader__receiver-check {
        display: inline;
        opacity: 1;
    }
}

/* Subtle completion pulse when the final profit amount is revealed. */
.profit-result-pop {
    animation: profit-result-pop 0.5s ease-out;
}

@keyframes profit-result-pop {
    0% { transform: scale(1); }
    35% { transform: scale(1.06); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .profit-result-pop {
        animation: none;
    }
}

/* ============================================================
 * Shared SweetAlert2 colored toast styling
 * Mirrors the rules in profit-calc-app.css so the same toasts
 * render consistently on welcome/onboarding pages that do not
 * load profit-calc-app.css. Identical rules are harmless where
 * both stylesheets are present.
 * ============================================================ */
.colored-toast.swal2-icon-success {
    background-color: #393e44 !important;
}

.colored-toast.swal2-icon-error {
    background-color: #f27474 !important;
}

.colored-toast.swal2-icon-warning {
    background-color: #f8bb86 !important;
}

.colored-toast.swal2-icon-info {
    background-color: #3fc3ee !important;
}

.colored-toast.swal2-icon-question {
    background-color: #87adbd !important;
}

.colored-toast .swal2-title,
.colored-toast .swal2-html-container,
.colored-toast .swal2-close {
    color: #ffffff;
}

/* Persistent loading/syncing toast used while ad-platform data
 * syncs (e.g. Meta login). Neutral graphite surface with a small
 * CSS spinner so the state reads as "in progress" without
 * relying on a confirm-dialog loader. */
.colored-toast.colored-toast-loading {
    background-color: #393e44 !important;
}

.colored-toast.colored-toast-loading .swal2-title {
    color: #ffffff;
    display: inline-flex;
    align-items: center;
}

.colored-toast.colored-toast-loading .swal2-title::before {
    content: '';
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-right: 10px;
    flex-shrink: 0;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #ffffff;
    border-radius: 50%;
    animation: pc-toast-spin 0.7s linear infinite;
}

@keyframes pc-toast-spin {
    to {
        transform: rotate(360deg);
    }
}

@media (prefers-reduced-motion: reduce) {
    .colored-toast.colored-toast-loading .swal2-title::before {
        animation: none;
    }
}

/* ============================================================
 * Dashboard metric hierarchy
 * Scoped to [data-dashboard-page] so report pages are unaffected.
 *
 * Core rule: black numbers carry the information; green/coral only
 * explain direction; mint quietly marks the best outcomes; gray
 * makes zero/inactive values recede.
 * ============================================================ */

/* Tabular numerals for all dashboard metric numbers and deltas so
 * digits align across cards and don't shift width on refresh. */
[data-dashboard-page] .metric-value > h1,
[data-dashboard-page] .metric-currency-symbol,
[data-dashboard-page] .metric-label h7 {
    font-variant-numeric: tabular-nums;
}

/* Currency symbol alignment: center the smaller symbol vertically
 * against the larger number so it reads as a natural prefix, neither
 * sunk to the baseline nor floating at the top. Tight line-heights on
 * both the h1 and the symbol keep the centering precise. */
[data-dashboard-page] .metric-value,
[data-dashboard-page] .metric-value.d-inline-block {
    align-items: center;
}

/* All main values use the same strong black weight. The .text-success /
 * .text-neg-profit classes on Profit and Gross Margin override this. */
[data-dashboard-page] .metric-value > h1 {
    font-weight: 700;
    color: var(--pc-primary-ink);
    line-height: 1;
}

/* Currency symbol: attached to the value, same weight so it reads as
 * part of the number. Slightly muted relative to the numeral but not
 * ghosted. line-height:1 keeps the box tight so centering is precise. */
[data-dashboard-page] .metric-value > .metric-currency-symbol {
    color: var(--pc-chart-ink);
    font-weight: 700;
    line-height: 1;
}

/* ---- Outcome cards (Profit, Gross Margin, ROAS) ---- */
/* The outcome cards no longer carry a green/mint background wash; they
 * render on the same flat white surface as the other dashboard cards.
 * The class is retained as a semantic hook for future styling. */
[data-dashboard-page] .dashboard-outcome-card {
    background-color: var(--pc-card);
}

/* ---- Softer card borders, hover-only shadow ---- */
/* Default: lighter border, no shadow. Hover: slightly stronger border +
 * soft lift shadow. Makes the dashboard feel less boxed-in. */
[data-dashboard-page] .card-dashboard {
    border: 1px solid var(--pc-border);
    box-shadow: none;
}

[data-dashboard-page] .card-dashboard:hover {
    border-color: var(--pc-card-border);
    box-shadow: var(--pc-shadow-hover);
}

/* Restore the Profit left accent stripe that the card-dashboard border
 * shorthand above would otherwise reset. The --profit-health-color
 * variable is set by .profit-accent-card and its modifier classes
 * (positive/negative/neutral) toggled by updateUI.js. */
[data-dashboard-page] .profit-accent-card {
    border-left: 4px solid var(--profit-health-color);
}

/* ---- Label contrast: slightly darker than the old --pc-muted ---- */
[data-dashboard-page] .card-dashboard .card-header {
    color: #5A625C;
    font-weight: 700;
    font-size: 0.84rem;
    letter-spacing: -0.005em;
}

/* ---- Zero state: muted value that recedes but stays readable ---- */
/* --pc-inactive (#D9DEDA) is too pale against white cards; --pc-muted
 * keeps zeros legible while still quieter than the strong primary ink. */
[data-dashboard-page] .metric-value--zero > h1,
[data-dashboard-page] .metric-value--zero > .metric-currency-symbol {
    color: var(--pc-muted);
}

/* ---- Percentage deltas: smaller, lighter, hover for context ---- */
/* nowrap prevents the icon + delta text from wrapping to two lines in
 * narrow cards (especially the em-dash zero-state text). */
[data-dashboard-page] .metric-label {
    white-space: nowrap;
}

[data-dashboard-page] .metric-label h7 {
    font-size: 0.8rem;
    font-weight: 600;
    opacity: 0.72;
    white-space: nowrap;
    line-height: 1;
    transition: opacity 0.15s ease;
}

[data-dashboard-page] .card-dashboard:hover .metric-label h7 {
    opacity: 1;
}

/* Direction icons next to deltas stay compact. */
[data-dashboard-page] .metric-label .fa {
    font-size: 0.72rem;
}

/* ---- Gentle value refresh transition ---- */
/* Applied by JS after a value changes. Not used for profit (which has
 * its own count-up) to avoid double-animation. */
.metric-value-flash {
    animation: metric-value-flash 0.35s ease-out;
}

/* Deferred customer and cohort cards remain useful after first paint while
 * their slower identity-based calculations finish. */
.metric-value--loading > h1 {
    display: inline-flex;
    gap: 0.04em;
}

.metric-loading-dot {
    animation: metric-loading-dot 1.2s ease-in-out infinite;
    opacity: 0.25;
}

.metric-loading-dot:nth-child(2) {
    animation-delay: 0.15s;
}

.metric-loading-dot:nth-child(3) {
    animation-delay: 0.3s;
}

@keyframes metric-loading-dot {
    0%, 60%, 100% { opacity: 0.25; transform: translateY(0); }
    30% { opacity: 1; transform: translateY(-0.12em); }
}

@keyframes metric-value-flash {
    0% { opacity: 0.45; transform: translateY(2px); }
    100% { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .metric-value-flash,
    .metric-loading-dot {
        animation: none;
    }

    .metric-loading-dot {
        opacity: 0.65;
    }
}
