/* =====================================================================
   SURFACE HIERARCHY (the rule for white vs grey vs canvas)

   Three surfaces, layered top → bottom:

   1. CANVAS  (--surface-canvas)
      - The page body. `.body-app` carries this.
      - Off-white in light, near-black in dark.
      - Section-less chrome lives directly on canvas: tab bars, filter
        rows, search inputs that aren't inside a card, page-level
        pagination controls.

   2. RAISED  (--surface-raised) + 1px var(--border-color)
      - Chrome containers (`.app-rail`, `.app-topbar`).
      - Every content section card (`.app-card`) — anything that's a
        heading + content group, a standalone data table, a form, a
        empty-state container.
      - Pure white in light, dark slate in dark.
      - RULE: any element with a heading or that holds primary page
        content lives in a `.app-card`. No naked sections on canvas.

   3. SUBTLE  (--surface-subtle) + 1px var(--border-subtle)
      - NESTED elements INSIDE a raised card: stat tiles, sub-panels,
        list-row backgrounds, table thead, input fills.
      - Slight grey in light, slightly lighter than raised in dark.
      - RULE: never put a raised card inside another raised card. The
        second level always steps DOWN to subtle. Use `.app-stat-tile`
        for the common stat-tile pattern.

   Anti-patterns this prevents:
     - "Naked section": heading + content with no card wrapper, sitting
       directly on canvas (looks unstyled).
     - "White-on-white": a `.app-card` containing more `.app-card`s
       (borders barely visible, no surface depth).
     - "Asymmetric chrome": sidebar grey while topbar white, or
       vice-versa (must both be raised).

   When in doubt: heading + content → wrap in `.app-card`. Tile inside
   a card → use `.app-stat-tile`. Anything that's just a row of inputs
   or pills with no logical grouping → leave on canvas.
   ===================================================================== */

/* hoastnow Design System — editorial serif + charcoal action, red as brand accent */

/* ---------------------------------------------------------------------------
   Self-hosted webfonts (previously pulled in from Google's font CDN).
   Both families are variable fonts, so one file covers the whole weight range
   rather than one file per weight. Only latin + latin-ext are shipped — that
   covers en / es / pt-BR; Google's cyrillic, greek and vietnamese subsets are
   dead weight for us.

   Self-hosted because the cross-origin fetch was a liability: a Cloudflare
   agent-readiness scan got every gstatic font blocked at CORS preflight, and
   third-party font hosting costs a DNS lookup, a TLS handshake and a
   render-blocking round trip on a domain we do not control. Serving from
   /lib/fonts also lets font-src drop to 'self' in the CSP.

   Fraunces and Inter are SIL Open Font License 1.1 — redistribution is
   explicitly permitted. Refresh with scripts/update-webfonts.sh.
   --------------------------------------------------------------------------- */

/* Fraunces — variable (opsz 9..144, wght 400..900), upright */
@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-weight: 400 900;
    font-display: swap;
    src: url('/lib/fonts/fraunces-normal-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-weight: 400 900;
    font-display: swap;
    src: url('/lib/fonts/fraunces-normal-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Fraunces — variable, italic */
@font-face {
    font-family: 'Fraunces';
    font-style: italic;
    font-weight: 400 900;
    font-display: swap;
    src: url('/lib/fonts/fraunces-italic-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Fraunces';
    font-style: italic;
    font-weight: 400 900;
    font-display: swap;
    src: url('/lib/fonts/fraunces-italic-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Inter — variable (wght 100..900); one file spans the 300–900 range we use */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('/lib/fonts/inter-normal-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('/lib/fonts/inter-normal-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    /* Brand — used for accents (badges, hover states, brand moments). Not for primary actions. */
    --primary-color: #FF385C;
    --primary-hover: #E31C5F;
    --secondary-color: #00A699;

    /* Action — primary call-to-action color. Confident, neutral, editorial. */
    --action-color: #1A1A1A;
    --action-hover: #000000;
    /* Text that sits ON --action-color (and on inverted --text-primary fills).
       Follows the fill: white on charcoal in light, charcoal on near-white in dark. */
    --on-action: #FFFFFF;

    /* Surfaces */
    --surface-color: #FFFFFF;
    --surface-subtle: #F8FAFC;
    --surface-highlight: #F0F9FF;
    --surface-dark: #0F172A;
    --surface-charcoal: #1E293B;
    --surface-warm: #F1F5F9;
    --surface-white: #FFFFFF;
    /* Stage-1 semantic surface tokens */
    --surface-canvas: #F1F5F9;     /* Page background (behind cards) — visibly off-white */
    --surface-raised: #FFFFFF;     /* Card / panel background (sits on canvas) */

    /* Text */
    --text-inverse: #FFFFFF;
    --text-on-dark: rgba(255, 255, 255, 0.85);
    --text-primary: #1E293B;
    --text-secondary: #64748B;

    /* Borders & backgrounds */
    --border-color: #E2E8F0;
    --background-light: #F1F5F9;
    --border-subtle: #E2E8F0;      /* Hairline divider — visible on light canvas */

    /* Focus ring */
    --focus-ring: #FF385C;         /* Accent focus ring — brand red, both modes */

    /* Overlays */
    --overlay-soft: rgba(15, 23, 42, 0.10);
    --overlay-strong: rgba(15, 23, 42, 0.20);
    --accent-muted: rgba(255, 56, 92, 0.10);
    --badge-color: #D92D20;

    /* Semantic — success */
    --color-success: #16A34A;
    --color-success-bg: #F0FDF4;
    --color-success-border: #BBF7D0;

    /* Semantic — warning */
    --color-warning: #D97706;
    --color-warning-bg: #FFFBEB;
    --color-warning-border: #FDE68A;

    /* Semantic — danger */
    --color-danger: #DC2626;
    --color-danger-bg: #FEF2F2;
    --color-danger-border: #FECACA;

    /* Semantic — info */
    --color-info: #2563EB;
    --color-info-bg: #EFF6FF;
    --color-info-border: #BFDBFE;

    /* Shadows */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.06);
    --shadow-lg: 0 8px 20px rgba(0, 0, 0, 0.09), 0 4px 8px rgba(0, 0, 0, 0.06);
    --shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.10), 0 8px 16px rgba(0, 0, 0, 0.07);

    /* Motion */
    --motion-fast: 150ms;
    --motion-base: 250ms;
    --motion-slow: 400ms;
    --ease-standard: cubic-bezier(0.2, 0, 0, 1);
    --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

    /* Hover elevation (pairs with .hover-lift utility) */
    --shadow-lift: 0 12px 28px rgba(15, 23, 42, 0.14);

    /* Skeleton loading surfaces */
    --skeleton-base: var(--border-color);
    --skeleton-sheen: var(--surface-subtle);

    /* Border radii — legacy aliases preserved; new code uses the --radius-* scale below */
    --border-radius: 12px;
    --border-radius-lg: 16px;
    --border-radius-pill: 9999px;

    /* Radius scale (preferred) */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 14px;
    --radius-xl: 20px;
    --radius-pill: 9999px;

    /* Focus ring shadow — 3px halo in brand red at 25% opacity */
    --shadow-focus: 0 0 0 3px rgba(255, 56, 92, 0.25);

    /* Typography */
    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-display: 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif;

    /* Spacing scale — 8-point grid. Legacy section-pad-y kept for marketing pages. */
    --section-pad-y: 96px;
    --section-pad-y-sm: 56px;
    --space-0: 0;
    --space-1: 0.25rem;   /*  4px */
    --space-2: 0.5rem;    /*  8px */
    --space-3: 0.75rem;   /* 12px */
    --space-4: 1rem;      /* 16px */
    --space-5: 1.25rem;   /* 20px */
    --space-6: 1.5rem;    /* 24px */
    --space-8: 2rem;      /* 32px */
    --space-10: 2.5rem;   /* 40px */
    --space-12: 3rem;     /* 48px */
    --space-16: 4rem;     /* 64px */
    --space-20: 5rem;     /* 80px */
    --space-24: 6rem;     /* 96px */

    /* Authenticated mobile bottom tab bar (excludes safe-area inset) */
    --mobile-bottom-nav-height: 52px;

    /* Authenticated desktop chrome — icon rail + top bar (AppSidebar docks drawers beside the rail) */
    --app-rail-width: 64px;
    --app-topbar-height: 64px;

    /* Typography scale */
    --fs-xs:   0.75rem;   /* 12px */
    --fs-sm:   0.8125rem; /* 13px */
    --fs-base: 0.875rem;  /* 14px */
    --fs-md:   0.9375rem; /* 15px */
    --fs-lg:   1.0625rem; /* 17px */
    --fs-xl:   1.25rem;   /* 20px */
    --fs-2xl:  1.5rem;    /* 24px */
    --fs-3xl:  2rem;      /* 32px */
    --fs-display: clamp(2rem, 4vw, 2.875rem); /* content-page hero titles */

    --lh-tight:   1.2;
    --lh-snug:    1.35;
    --lh-normal:  1.5;
    --lh-relaxed: 1.65;

    --fw-regular:  400;
    --fw-medium:   500;
    --fw-semibold: 600;
    --fw-bold:     700;

    /* Z-index scale */
    --z-base:     0;
    --z-sticky:   10;
    --z-dropdown: 100;
    --z-drawer:   1000;
    --z-modal:    1050;
    --z-toast:    1100;
    --z-tooltip:  1200;

    /* ── Role badge colors ──────────────────────────────────────────────────
       Used in AdminUsers, AdminUserDetail, and PlatformBackoffice user drawer.
       bg variants are the subtle container fill; the fg colors are the identity
       hue used across both light and dark modes. */
    --role-platform:      #6D28D9;          /* deep violet — Platform / Administrator */
    --role-platform-bg:   #F5F3FF;
    --role-referral:      #0891B2;          /* cyan — Referral */
    --role-referral-bg:   #ECFEFF;
    --role-brand:         var(--primary-color);
    --role-brand-bg:      var(--accent-muted);
    --role-property:      var(--color-success);
    --role-property-bg:   var(--color-success-bg);

    /* ── Chart channel colors ───────────────────────────────────────────────
       Categorical palette for series differentiation in financial dashboards.
       Order matters: chart-1 is the primary series, chart-2 the secondary, etc. */
    --chart-1: #0EA5E9;  /* sky blue  — primary channel */
    --chart-2: #8B5CF6;  /* violet    — secondary channel */
    --chart-3: #16A34A;  /* green     — aligned with --color-success */
    --chart-4: #6B7280;  /* cool gray — neutral / cancelled */
    --chart-5: #F59E0B;  /* amber     — aligned with --color-warning */
    --chart-6: #EC4899;  /* pink      — sixth series */

    /* ── Code block dark theme ─────────────────────────────────────────────
       Syntax-highlight theme colors used in /developers/* pages.
       These stay dark in BOTH light and dark mode (intentional) — they are
       theme colors for code samples, not chrome. */
    --code-bg:            #0D1117;   /* GitHub Dark page bg */
    --code-bg-elevated:   #161B22;   /* GitHub Dark code block bg */
    --code-text:          #E6EDF3;   /* GitHub Dark default text */
    --code-text-muted:    #CDD9E5;
    --code-method-get:    #047857;   /* HTTP GET  — green */
    --code-method-post:   #1E40AF;   /* HTTP POST — blue */
    --code-method-warn:   #92400E;   /* Warning amber on dark */
}

/* Light mode page surface — chrome (topbar + sidebar) sits white on top of
   the canvas off-white; cards re-elevate to white via .app-card.
   The dark block below overrides this for dark theme. */
.body-app {
    background-color: var(--surface-canvas);
    color: var(--text-primary);
    min-height: 100vh;
}

/* ================================================================
   Dark mode — all authenticated chrome.
   Activated when BOTH:
     1. <html data-theme="dark"> is set (by the early-paint script in
        App.razor or by the runtime toggle), AND
     2. The layout-root element carries the class "body-app", which
        MainLayout adds whenever an authenticated user is on a
        non-public page (Brand, Property, Admin, Referral — all roles).
   Public/marketing pages and auth pages (login, register, etc.) stay
   forced-light regardless of the user's theme preference.
   The brand red stays unchanged across themes — it is brand, not
   chrome. Surfaces are hue-neutral charcoal (Slack / Messages), not
   Tailwind slate. Semantic colors get desaturated dark-mode bg
   variants so alerts read at the right intensity on a dark surface.
   ================================================================ */
[data-theme="dark"] .body-app {
    /* Surfaces — hue-neutral charcoal (Slack / Google Messages), not Tailwind slate.
       Slate (#0B1220 / #1E293B) reads as navy; these values keep R≈G≈B so brand
       red and semantic colors are the only hue in the chrome. */
    --surface-color: #1A1C1E;
    --surface-subtle: #2A2C2E;
    --surface-highlight: #2A2C2E;
    --surface-warm: #2A2C2E;
    --surface-white: #222426;
    /* Inverted dark surfaces — used by section-dark callouts; flip to
       a slightly lighter elevated surface so the contrast inverts too. */
    --surface-dark: #121314;
    --surface-charcoal: #1A1C1E;

    /* Text — Material / Messages off-white, not slate-200/400 */
    --text-primary: #E8EAED;
    --text-secondary: #9AA0A6;
    --text-on-dark: rgba(232, 234, 237, 0.85);

    /* Borders & backgrounds */
    --border-color: #3C4043;
    --background-light: #2A2C2E;
    --border-subtle: #2D2F31;      /* Hairline / very-low-contrast divider — dark */
    /* Stage-1 semantic surface tokens — dark overrides */
    --surface-canvas: #1A1C1E;     /* Page background (behind cards) — charcoal */
    --surface-raised: #222426;     /* Card / panel background (sits on canvas) */
    /* --focus-ring stays brand red in both modes — no override needed */

    /* Action — keep dark CTA but invert to light surface fill on hover */
    --action-color: #F1F3F4;
    --action-hover: #FFFFFF;
    --on-action: var(--surface-dark);

    /* Native form controls / scrollbars follow the charcoal scheme */
    color-scheme: dark;
    --bs-body-bg: #1A1C1E;
    --bs-body-color: #E8EAED;
    --bs-body-bg-rgb: 26, 28, 30;
    --bs-body-color-rgb: 232, 234, 237;
    --bs-border-color: #3C4043;
    --bs-secondary-bg: #222426;
    --bs-tertiary-bg: #2A2C2E;
    --bs-secondary-color: #9AA0A6;

    /* Overlays */
    --overlay-soft: rgba(0, 0, 0, 0.30);
    --overlay-strong: rgba(0, 0, 0, 0.55);
    --accent-muted: rgba(255, 56, 92, 0.18);

    /* Semantic — bg is a visible tint on charcoal, not a near-black hole.
       Foreground stays the light-mode solid (used as button fills). Small
       on-dark labels (KPI deltas) get their own brighter overrides below. */
    --color-success-bg: #0F3D28;
    --color-success-border: #166534;

    --color-warning-bg: #3D2A08;
    --color-warning-border: #A16207;

    --color-danger-bg: #4C151C;
    --color-danger-border: #B91C1C;

    --color-info-bg: #0F2744;
    --color-info-border: #1D4ED8;

    /* Role badge bg variants — fg identity colors stay the same across modes */
    --role-platform-bg:  #1E1B3A;
    --role-referral-bg:  #082F35;
    --role-brand-bg:     rgba(255, 56, 92, 0.15);
    --role-property-bg:  #052E1F;

    /* Chart channel colors — brightened ~12% for legibility on dark surfaces */
    --chart-1: #38BEF8;  /* sky blue  — lighter */
    --chart-2: #A78BFA;  /* violet    — lighter */
    --chart-3: #4ADE80;  /* green     — lighter */
    --chart-4: #9CA3AF;  /* cool gray — lighter */
    --chart-5: #FCD34D;  /* amber     — lighter */
    --chart-6: #F472B6;  /* pink      — lighter */

    /* Slightly stronger shadows so cards still feel lifted on dark */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.40), 0 1px 2px rgba(0, 0, 0, 0.30);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.30);
    --shadow-lg: 0 8px 20px rgba(0, 0, 0, 0.50), 0 4px 8px rgba(0, 0, 0, 0.32);
    --shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.55), 0 8px 16px rgba(0, 0, 0, 0.34);
    --shadow-lift: 0 12px 28px rgba(0, 0, 0, 0.45);
    --skeleton-base: #3C4043;
    --skeleton-sheen: #4A4D50;

    /* Page background — same token as light mode for consistency */
    background-color: var(--surface-canvas);
    color: var(--text-primary);
}

/* Viewport scrollbars / native widgets follow charcoal on authenticated
   dark pages. :has(.body-app) keeps marketing/auth pages on the light
   color-scheme even if the cookie is dark. */
html[data-theme="dark"]:has(.body-app) {
    color-scheme: dark;
    background-color: #1A1C1E;
}

/* The action button (.btn-primary) uses --action-color which we've inverted
   above to a near-white in dark mode. Re-tone the text fill so the high-
   contrast button reads as a light pill with dark text. Isolated CSS that
   still pairs action-color with --text-inverse (white) is caught here too. */
[data-theme="dark"] .body-app .btn-primary,
[data-theme="dark"] .body-app .btn-primary:hover,
[data-theme="dark"] .body-app .btn-outline-primary:hover,
[data-theme="dark"] .body-app .skip-link,
[data-theme="dark"] .body-app .reserve-button,
[data-theme="dark"] .body-app .mobile-reserve-btn,
[data-theme="dark"] .body-app .issue-key-btn,
[data-theme="dark"] .body-app .issue-key-btn:hover,
[data-theme="dark"] .body-app .add-webhook-btn,
[data-theme="dark"] .body-app .add-webhook-btn:hover,
[data-theme="dark"] .body-app .gated-cta-button,
[data-theme="dark"] .body-app .gated-cta-button:hover,
[data-theme="dark"] .body-app .btn-dev-primary,
[data-theme="dark"] .body-app .btn-dev-primary:hover,
[data-theme="dark"] .body-app .btn-get-keys,
[data-theme="dark"] .body-app .btn-get-keys:hover,
[data-theme="dark"] .body-app .btn-getkeys-primary,
[data-theme="dark"] .body-app .btn-getkeys-primary:hover,
[data-theme="dark"] .body-app .gate-btn-primary,
[data-theme="dark"] .body-app .gate-btn-primary:hover,
[data-theme="dark"] .body-app .btn-how-cta,
[data-theme="dark"] .body-app .btn-how-cta:hover,
[data-theme="dark"] .body-app .pricing-card-header,
[data-theme="dark"] .body-app .filter-tab.active,
[data-theme="dark"] .body-app .space-type-btn.active,
[data-theme="dark"] .body-app .package-pillar-badge,
[data-theme="dark"] .body-app .earnings-calc-chip.is-active,
[data-theme="dark"] .body-app .avatar-circle,
[data-theme="dark"] .body-app .user-drawer-avatar,
[data-theme="dark"] .body-app .step-card .step-number,
[data-theme="dark"] .body-app .value-prop-icon,
[data-theme="dark"] .body-app .gated-pagination .page-item.active .page-link,
[data-theme="dark"] .body-app .book-wizard .wizard-progress .step.active .step-number,
[data-theme="dark"] .body-app .public-auth-link.btn-primary {
    color: var(--on-action);
}

[data-theme="dark"] .body-app .btn-outline-primary {
    color: var(--action-color);
    background-color: transparent;
    border-color: var(--action-color);
}

[data-theme="dark"] .body-app .btn-outline-primary:hover {
    color: var(--on-action);
    background-color: var(--action-color);
    border-color: var(--action-color);
}

[data-theme="dark"] .body-app .btn-outline-secondary {
    color: var(--text-secondary);
    background-color: transparent;
    border-color: var(--border-color);
}

[data-theme="dark"] .body-app .btn-outline-secondary:hover {
    color: var(--text-primary);
    background-color: var(--background-light);
    border-color: var(--text-primary);
}

/* Cards: tokenized background so they pick up the dark surface. Sub-component
   .razor.css files that hardcoded `background: white` are also handled below. */
[data-theme="dark"] .body-app .card {
    background: var(--surface-subtle);
    color: var(--text-primary);
}

[data-theme="dark"] .body-app .card:hover {
    border-color: var(--text-secondary);
}

/* app-card and app-table dark overrides — token-based so most rules need no
   change; only tr:hover uses a semantic token that differs from Bootstrap's
   default hover background. */
[data-theme="dark"] .body-app .app-card {
    background: var(--surface-raised);
}

[data-theme="dark"] .body-app .app-table tbody tr:hover td {
    background: var(--surface-subtle);
}

/* Form controls */
[data-theme="dark"] .body-app .form-control,
[data-theme="dark"] .body-app .form-select {
    background-color: var(--surface-color);
    color: var(--text-primary);
    border-color: var(--border-color);
}

[data-theme="dark"] .body-app .form-control:focus,
[data-theme="dark"] .body-app .form-select:focus {
    background-color: var(--surface-color);
    color: var(--text-primary);
    border-color: var(--text-primary);
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.12);
}

[data-theme="dark"] .body-app .form-control::placeholder {
    color: var(--text-secondary);
    opacity: 0.7;
}

/* Sticky header chrome turns dark on backoffice surfaces. */
[data-theme="dark"] .body-app header.sticky-top,
[data-theme="dark"] .body-app .bg-white {
    background-color: var(--surface-color) !important;
    border-bottom-color: var(--border-color);
    color: var(--text-primary);
}

[data-theme="dark"] .body-app .navbar-brand .logo-word-secondary,
[data-theme="dark"] .body-app .topbar-logo-link .logo-word-secondary {
    fill: #FFFFFF;
}

/* Page background under main — same canvas token as body-app for consistency */
[data-theme="dark"] .body-app main {
    background-color: var(--surface-canvas);
}

/* Tables on dark — clean odd-row hover, no hardcoded #fafafa */
[data-theme="dark"] .body-app .table tbody tr:hover td,
[data-theme="dark"] .body-app .bookings-table tbody tr:hover td,
[data-theme="dark"] .body-app .backoffice-table tbody tr:hover td {
    background-color: rgba(255, 255, 255, 0.03);
}

/* Inputs / textareas in dark */
[data-theme="dark"] .body-app textarea.form-control,
[data-theme="dark"] .body-app input[type="text"].form-control,
[data-theme="dark"] .body-app input[type="email"].form-control,
[data-theme="dark"] .body-app input[type="url"].form-control,
[data-theme="dark"] .body-app input[type="search"].form-control,
[data-theme="dark"] .body-app input[type="number"].form-control,
[data-theme="dark"] .body-app input[type="password"].form-control {
    background-color: var(--surface-color);
    color: var(--text-primary);
}

/* Modal / dialog overlays — keep readable cards on dark backdrops */
[data-theme="dark"] .body-app .modal-content,
[data-theme="dark"] .body-app .release-modal-content {
    background-color: var(--surface-subtle);
    color: var(--text-primary);
    border-color: var(--border-color);
}

/* Backoffice content area uses --surface-canvas so child .app-card tiles elevate correctly */
[data-theme="dark"] .body-app .backoffice-shell,
[data-theme="dark"] .body-app .backoffice-content {
    background: var(--surface-canvas);
}

/* Icon rail dark mode is fully token-driven (AppSidebar.razor.css uses
   --surface-raised/--border-color/--primary-color, all of which have dark
   variants) — no rail-specific dark overrides needed. */

/* Mobile bottom nav — hardcoded white */
[data-theme="dark"] .body-app .mobile-bottom-nav {
    background: var(--surface-subtle);
    border-top-color: var(--border-color);
}

/* nav-link hover background — uses --background-light (ok), but specific
   active underline uses --primary-color which is fine. */

/* Reconnect toast on dark — flip to light pill text */
[data-theme="dark"] .body-app ~ #components-reconnect-modal .reconnect-toast-connecting,
[data-theme="dark"] #components-reconnect-modal .reconnect-toast-connecting {
    /* Toast lives outside body-app scope — keep current dark pill */
}

/* Backoffice content header divider sits on a dark surface — already token-driven */

/* Status filter buttons — active state uses --text-primary which we've
   inverted to near-white; ensure the label inside contrasts. */
[data-theme="dark"] .body-app .status-filter-btn {
    background: var(--surface-subtle);
    border-color: var(--border-color);
}

[data-theme="dark"] .body-app .status-filter-btn:hover {
    color: var(--text-primary);
    border-color: var(--text-primary);
}

[data-theme="dark"] .body-app .status-filter-btn.active {
    background: var(--text-primary);
    border-color: var(--text-primary);
    color: var(--on-action);
}

[data-theme="dark"] .body-app .status-filter-btn.active .status-count {
    background: rgba(0, 0, 0, 0.20);
    color: var(--on-action);
}

[data-theme="dark"] .body-app .status-count {
    background: rgba(255, 255, 255, 0.10);
    color: var(--text-secondary);
}

/* Booking stats row — the 1px gap between tiles uses the border colour;
   tile background was hardcoded white. Token it via the override. */
[data-theme="dark"] .body-app .booking-stat,
[data-theme="dark"] .body-app a.booking-stat,
[data-theme="dark"] .body-app a.booking-stat-sub {
    background: var(--surface-subtle);
    color: var(--text-primary);
}

[data-theme="dark"] .body-app .booking-stat-link:hover,
[data-theme="dark"] .body-app a.booking-stat-sub:hover {
    background: rgba(255, 255, 255, 0.04);
}

[data-theme="dark"] .body-app .record-count-badge {
    background: var(--surface-subtle);
    border-color: var(--border-color);
    color: var(--text-secondary);
}

/* Bootstrap's .table class sets cell backgrounds via box-shadow:inset using
   `--bs-table-bg` (default #fff via --bs-body-bg). Our `tr` selectors lose
   that paint because the inset shadow covers the row's bg. Override the
   Bootstrap table CSS variables directly so EVERY `.table` instance picks
   up dark surface, foreground, border, hover, and striped colors at once.
   This covers .backoffice-table, .bookings-table, .attribution-table,
   .api-keys-table, .transactions-table, .financial-panel table, etc. */
[data-theme="dark"] .body-app .table {
    --bs-table-bg: var(--surface-color);
    --bs-table-color: var(--text-primary);
    --bs-table-border-color: var(--border-color);
    --bs-table-hover-bg: rgba(255, 255, 255, 0.04);
    --bs-table-hover-color: var(--text-primary);
    --bs-table-striped-bg: var(--surface-subtle);
    --bs-table-striped-color: var(--text-primary);
    --bs-table-active-bg: rgba(255, 255, 255, 0.06);
    --bs-table-active-color: var(--text-primary);
    color: var(--text-primary);
    border-color: var(--border-color);
}

/* Mobile-card variants of backoffice/bookings tables hardcode white +
   #f3f3f3 borders. Override into the dark palette. */
[data-theme="dark"] .body-app .backoffice-table tbody tr:not(.span-row),
[data-theme="dark"] .body-app .bookings-table tbody tr:not(.span-row),
[data-theme="dark"] .body-app .attribution-table tbody tr {
    background: var(--surface-subtle);
    border-color: var(--border-color);
}

[data-theme="dark"] .body-app .backoffice-table tbody td,
[data-theme="dark"] .body-app .bookings-table tbody td {
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .backoffice-table thead th,
[data-theme="dark"] .body-app .bookings-table thead th,
[data-theme="dark"] .body-app .table thead th {
    background: var(--surface-subtle);
    color: var(--text-secondary);
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .row-selected td {
    background: rgba(255, 255, 255, 0.08) !important;
}

[data-theme="dark"] .body-app .row-clickable:hover td {
    background: rgba(255, 255, 255, 0.04);
}

[data-theme="dark"] .body-app .reject-panel {
    background: rgba(127, 29, 29, 0.20);
    border-top-color: var(--color-danger-border);
    border-bottom-color: var(--color-danger-border);
}

[data-theme="dark"] .body-app .email-template-pill {
    background: var(--surface-subtle);
    border-color: var(--border-color);
    color: var(--text-primary);
}

[data-theme="dark"] .body-app .email-template-pill:hover {
    background: var(--background-light);
    border-color: var(--text-secondary);
}

[data-theme="dark"] .body-app .invite-role-info,
[data-theme="dark"] .body-app .user-drawer-card {
    background: var(--surface-subtle);
    border-color: var(--border-color);
}

[data-theme="dark"] .body-app .user-drawer-info-list,
[data-theme="dark"] .body-app .user-drawer-info-item {
    border-color: var(--border-color);
}

/* User-drawer role badges — keep their hue but darken bg + lighten text */
[data-theme="dark"] .body-app .user-drawer-role-administrator { background: rgba(220, 38, 38, 0.20); color: #FCA5A5; }
[data-theme="dark"] .body-app .user-drawer-role-platform      { background: rgba(37, 99, 235, 0.20); color: #93C5FD; }
[data-theme="dark"] .body-app .user-drawer-role-property      { background: rgba(22, 163, 74, 0.20); color: #86EFAC; }
[data-theme="dark"] .body-app .user-drawer-role-brand         { background: rgba(217, 119, 6, 0.20); color: #FCD34D; }
[data-theme="dark"] .body-app .user-drawer-role-referral      { background: rgba(139, 92, 246, 0.20); color: #C4B5FD; }
[data-theme="dark"] .body-app .user-drawer-role-none          { background: var(--background-light); color: var(--text-secondary); }

[data-theme="dark"] .body-app .user-drawer-status.status-locked { background: var(--border-color); color: var(--text-primary); }

[data-theme="dark"] .body-app .community-admin-card {
    background: var(--surface-subtle);
    border-color: var(--border-color);
}

[data-theme="dark"] .body-app .community-admin-card:hover {
    border-color: var(--text-secondary);
}

[data-theme="dark"] .body-app .community-admin-placeholder {
    background: var(--background-light);
    color: var(--text-secondary);
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .community-admin-card .card-header {
    background: var(--surface-subtle);
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .brand-admin-banner-placeholder {
    background: linear-gradient(135deg, var(--surface-subtle) 0%, var(--surface-dark) 100%);
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .brand-admin-logo-circle {
    background: var(--surface-subtle);
    border-color: var(--surface-subtle);
}

/* Mobile section tabs scoped to backoffice */
[data-theme="dark"] .body-app .mobile-section-tabs {
    background: var(--surface-subtle);
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .mobile-tab-btn.active {
    background: var(--surface-color);
    color: var(--text-primary);
}

[data-theme="dark"] .body-app .mobile-tab-btn:hover:not(.active) {
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-primary);
}

/* CSS-only tooltip — already uses a dark pill, ensure it stays readable */

/* Confirm-icon circles inside modals (release-confirm-icon) — desaturate bg */
[data-theme="dark"] .body-app .release-confirm-icon {
    background: rgba(217, 119, 6, 0.20);
    color: #FCD34D;
}

[data-theme="dark"] .body-app .declined-circle {
    background: rgba(220, 38, 38, 0.20);
    color: #FCA5A5;
}

[data-theme="dark"] .body-app .error-circle {
    background: rgba(217, 119, 6, 0.20);
    color: #FCD34D;
}

/* Drawer nav (mobile drawer / shared) on dark */
[data-theme="dark"] .body-app .drawer-nav-item.active {
    background: rgba(255, 255, 255, 0.08);
    border-left-color: var(--text-primary);
}

/* ================================================================
   Dark-mode overrides — component-level hardcoded colors
   All selectors here correspond to hardcoded white / light-tint
   values found in individual .razor.css files. Concentrating them
   here keeps each component file clean for light-mode and avoids
   scattering 15+ dark blocks across the component tree.
   ================================================================ */

/* ── AccountMenu — account-menu-item card ───────────────────── */
[data-theme="dark"] .body-app .account-menu-item {
    background: var(--surface-subtle);
}

[data-theme="dark"] .body-app .account-menu-item:hover,
[data-theme="dark"] .body-app .account-menu-item:focus {
    background: var(--background-light);
}

/* ── AppSidebar — mobile bottom nav ─────────────────────────── */
/* Bar background is token-driven in AppSidebar.razor.css. The dark
   override above covers the phone bar and the in-app bar at any width. */

/* ── AdminUsers — role badges ───────────────────────────────── */
[data-theme="dark"] .body-app .role-brand        { background: rgba(2, 119, 189, 0.20);   color: #7DD3FC; }
[data-theme="dark"] .body-app .role-property     { background: rgba(46, 125, 50, 0.20);   color: #86EFAC; }
[data-theme="dark"] .body-app .role-platform     { background: rgba(123, 31, 162, 0.20);  color: #D8B4FE; }
[data-theme="dark"] .body-app .role-administrator{ background: rgba(230, 81, 0, 0.20);    color: #FDBA74; }
[data-theme="dark"] .body-app .role-none         { background: var(--background-light);   color: var(--text-secondary); }

/* ── AdminUsers — status badges ─────────────────────────────── */
[data-theme="dark"] .body-app .status-pending    { background: rgba(245, 127, 23, 0.18);  color: #FCD34D; }
[data-theme="dark"] .body-app .status-approved   { background: rgba(46, 125, 50, 0.18);   color: #86EFAC; }
[data-theme="dark"] .body-app .status-rejected   { background: rgba(198, 40, 40, 0.18);   color: #FCA5A5; }
[data-theme="dark"] .body-app .status-inactive   { background: var(--background-light);   color: var(--text-secondary); }
[data-theme="dark"] .body-app .status-locked     { background: var(--border-color); color: var(--text-primary); }

/* ── AdminUsers — table cell borders, reject form ───────────── */
[data-theme="dark"] .body-app .users-table tbody td {
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .reject-form-inline {
    background: var(--color-warning-bg);
    border-color: var(--color-warning-border);
}

/* Mobile card rows for users-table */
[data-theme="dark"] .body-app .users-table tbody tr {
    background: var(--surface-subtle);
}

[data-theme="dark"] .body-app .users-table tbody td {
    border-bottom-color: var(--border-color);
}

/* ── AdminUserDetail — status badges (reuse above) ──────────── */
/* role-badge / status-badge classes shared — overrides above     */
/* cover AdminUserDetail too since class names are the same.      */

/* AdminUserDetail reject panel + profile-info-item border */
[data-theme="dark"] .body-app .reject-panel {
    background: var(--color-danger-bg);
    border-color: var(--color-danger-border);
}

[data-theme="dark"] .body-app .profile-info-item {
    border-bottom-color: var(--border-color);
}

/* AdminUserDetail action-tab active state */
[data-theme="dark"] .body-app .action-tab.active {
    background: var(--surface-color);
}

/* ── PlatformBackoffice — table hover/border hardcodes ──────── */
/* bookings-table and generic .table hover rows */
[data-theme="dark"] .body-app .bookings-table tbody td {
    border-bottom-color: var(--border-color);
}

[data-theme="dark"] .body-app .bookings-table tbody tr:hover td,
[data-theme="dark"] .body-app .table tbody tr:hover td {
    background: rgba(255, 255, 255, 0.03);
}

/* backoffice-table td borders */
[data-theme="dark"] .body-app .backoffice-table tbody td {
    border-bottom-color: var(--border-color);
}

/* Clickable row hover and selected row */
[data-theme="dark"] .body-app .row-clickable:hover td {
    background: rgba(255, 255, 255, 0.04);
}

[data-theme="dark"] .body-app .row-selected td {
    background: rgba(255, 255, 255, 0.08) !important;
}

/* PlatformBackoffice reject panel (same class, different component scope) */
/* Already covered by the .reject-panel rule above. */

/* Email template pills */
[data-theme="dark"] .body-app .email-template-pill {
    background: var(--surface-subtle);
}

/* Mobile card rows — backoffice-table / bookings-table */
/* (Also declared in the mobile-card-variants block above as var(--surface-subtle).
   These explicit rules ensure the mobile card rows also pick it up.) */
[data-theme="dark"] .body-app .backoffice-table tbody tr:not(.span-row),
[data-theme="dark"] .body-app .bookings-table tbody tr:not(.span-row) {
    background: var(--surface-subtle);
}

[data-theme="dark"] .body-app .backoffice-table tbody td:not([colspan]),
[data-theme="dark"] .body-app .bookings-table tbody td:not([colspan]) {
    border-bottom-color: var(--border-color);
}

/* Attribution nested table mobile cards */
[data-theme="dark"] .body-app .attribution-table tbody tr {
    background: var(--surface-subtle);
}

[data-theme="dark"] .body-app .attribution-table tbody td {
    border-bottom-color: var(--border-color);
}

/* Community admin card header */
[data-theme="dark"] .body-app .community-admin-card .card-header {
    background: var(--surface-subtle);
}

/* Brand admin banner placeholder gradient */
[data-theme="dark"] .body-app .brand-admin-banner-placeholder {
    background: linear-gradient(135deg, var(--surface-subtle) 0%, var(--surface-dark) 100%);
}

/* Brand admin logo circle border */
[data-theme="dark"] .body-app .brand-admin-logo-circle {
    border-color: var(--surface-subtle);
    background: var(--surface-subtle);
}

/* User drawer card */
[data-theme="dark"] .body-app .user-drawer-card {
    background: var(--surface-subtle);
}

/* User-drawer role badges — same class names used in PlatformBackoffice.razor.css */
/* (Already defined in the block starting ~line 399 above — those cover both files.) */

[data-theme="dark"] .body-app .financial-panel table tbody tr {
    background: var(--surface-subtle);
}

[data-theme="dark"] .body-app .financial-panel table tbody td {
    border-bottom-color: var(--border-color);
}

/* ── IntelEnginePanel — subtab active ───────────────────────── */
/* .intel-subtab.active uses background: var(--surface-color) which flips
   correctly via the token. No additional override needed.         */

/* ── IntelligencePanel — top-level tab active ───────────────── */
/* .intelligence-tab.active uses --primary-color border + color.
   Stays brand red in both themes. No override needed.            */

/* ── IssueApiKeyDialog — scope-toggle-btn active ────────────── */
/* .scope-toggle-btn.active uses --primary-color fill.
   Stays brand red in both themes. No override needed.            */

/* ── BlogManagementPanel — locale tab active ────────────────── */
/* .blog-locale-tabs .nav-link.active uses var(--surface-color) bg +
   var(--border-color) border — both flip via tokens. No override. */

/* ── ApiKeysPanel — mobile card row borders ─────────────────── */
[data-theme="dark"] .body-app .api-keys-table tbody td {
    border-bottom-color: var(--border-color);
}

/* ── Global btn-outline variants — transparent bg on dark ────── */
[data-theme="dark"] .body-app .btn-outline-primary,
[data-theme="dark"] .body-app .btn-outline-secondary,
[data-theme="dark"] .body-app .btn-outline-danger,
[data-theme="dark"] .body-app .btn-outline-success,
[data-theme="dark"] .body-app .btn-outline-warning,
[data-theme="dark"] .body-app .btn-outline-info {
    background-color: transparent;
}

/* ── LoginDisplay dropdown — Bootstrap utility classes ──────────
   The auth-state dropdown in LoginDisplay.razor uses raw Bootstrap
   utilities (.bg-white, .text-dark, .dropdown-item) instead of design
   tokens. .bg-white already gets a dark override (line 215). Below
   covers the foreground + dropdown-item state so the menu is readable. */
[data-theme="dark"] .body-app .text-dark,
[data-theme="dark"] .body-app .dropdown-item.text-dark,
[data-theme="dark"] .body-app .dropdown-item {
    color: var(--text-primary) !important;
}
[data-theme="dark"] .body-app .dropdown-item:hover,
[data-theme="dark"] .body-app .dropdown-item:focus {
    background-color: var(--background-light);
    color: var(--text-primary) !important;
}
/* The dropdown panel itself uses .bg-white .border .rounded .shadow-sm
   utilities; .bg-white is overridden, but the border becomes invisible
   on the dark surface — re-tone it so the panel reads as a card. */
[data-theme="dark"] .body-app .bg-white.border,
[data-theme="dark"] .body-app .bg-white.border-bottom,
[data-theme="dark"] .body-app .bg-white.border-top {
    border-color: var(--border-color) !important;
}

/* ── Bootstrap utility — .text-muted ────────────────────────────
   Bootstrap's .text-muted is ~#6c757d — readable on light, nearly
   invisible on very dark surfaces.  We remap it to the project's
   --text-secondary token so it stays at the right contrast level. */
[data-theme="dark"] .body-app .text-muted {
    color: var(--text-secondary) !important;
}

/* ── Bootstrap utility — .bg-light ──────────────────────────────
   .bg-light renders as #f8f9fa on light — blindingly pale on a dark
   surface. Remap to --background-light which is already dark-aware. */
[data-theme="dark"] .body-app .bg-light {
    background-color: var(--background-light) !important;
    color: var(--text-primary);
}

/* ── Bootstrap .badge.bg-warning.text-dark / .bg-info.text-dark ─
   Used for "DCR" and "Community #N" / "Brand #N" badges in
   OAuthClientsPanel and Payabli drawer rows.  In dark mode Bootstrap's
   bg-warning is still vivid yellow but text-dark (#212529) becomes
   illegible on a dark surface chrome.  Remap both to themed palette. */
[data-theme="dark"] .body-app .badge.bg-warning {
    background-color: rgba(217, 119, 6, 0.25) !important;
    color: #FCD34D !important;
}
[data-theme="dark"] .body-app .badge.bg-info {
    background-color: rgba(37, 99, 235, 0.25) !important;
    color: #93C5FD !important;
}
/* bg-white badge used in PlatformBackoffice brand/community card
   for campaign/space counts. Already overridden via .bg-white rule
   but the text-primary foreground should stay readable. */
[data-theme="dark"] .body-app .badge.bg-white {
    background-color: var(--surface-subtle) !important;
    color: var(--text-primary) !important;
}

/* ── IntelEnginePanel — .intel-filter-chip.active anti-pattern ───
   Same pattern: background: var(--text-primary) → near-white on dark.
   Re-tone to an elevated surface so the chip reads as "selected". */
[data-theme="dark"] .body-app .intel-filter-chip.active {
    background: var(--surface-color);
    color: var(--text-primary);
    border-color: var(--text-secondary);
    box-shadow: var(--shadow-sm);
}

/* ── IssueApiKeyDialog — .step-indicator.completed anti-pattern ──
   `.step-number` inside `.step-indicator.completed` uses
   `background: var(--text-primary); color: white` — same white-on-white
   bug.  Re-tone completed steps to a subtle elevated look. */
[data-theme="dark"] .body-app .step-indicator.completed .step-number {
    background: var(--surface-subtle);
    color: var(--text-primary);
    border-color: var(--text-secondary);
}
[data-theme="dark"] .body-app .step-indicator.completed {
    color: var(--text-secondary);
}

/* ── NextBestActionCard — hardcoded `background: white` ─────────
   .nba-card uses `background: white` which bypasses the token. */
[data-theme="dark"] .body-app .nba-card {
    background: var(--surface-subtle);
    border-color: var(--border-color);
    color: var(--text-primary);
}
[data-theme="dark"] .body-app .nba-card:hover {
    border-color: var(--text-secondary);
    color: var(--text-primary);
}
/* Light-mode pill is text-inverse on text-primary. In dark that becomes
   white on off-white. Invert so the "Next best action" label stays readable. */
[data-theme="dark"] .body-app .nba-pill {
    background: var(--text-primary);
    color: var(--on-action);
}
[data-theme="dark"] .body-app .nba-icon {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-primary);
}

/* ── KPI delta pills — tiny type needs a visible wash, not a near-black
   semantic bg. Negative red is the one that disappeared on charcoal. */
[data-theme="dark"] .body-app .kpi-tile-delta.delta-down {
    background: rgba(248, 113, 113, 0.22);
    color: #FECACA;
    box-shadow: inset 0 0 0 1px rgba(248, 113, 113, 0.45);
}
[data-theme="dark"] .body-app .kpi-tile-delta.delta-up {
    background: rgba(74, 222, 128, 0.20);
    color: #BBF7D0;
    box-shadow: inset 0 0 0 1px rgba(74, 222, 128, 0.40);
}
[data-theme="dark"] .body-app .kpi-tile-delta.delta-flat {
    background: rgba(255, 255, 255, 0.10);
    color: var(--text-primary);
}

/* Pending-queue chips sit inside a raised card — step DOWN to subtle so
   they lift off the card instead of using canvas (which recedes). */
[data-theme="dark"] .body-app .pd-status-chip {
    background: var(--surface-subtle);
    border-color: var(--border-color);
}
[data-theme="dark"] .body-app .pd-status-chip:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--text-secondary);
}
[data-theme="dark"] .body-app .pd-status-chip i {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-primary);
}

[data-theme="dark"] .body-app .sparkline-fill {
    opacity: 0.28;
}

/* ── ActionDialog — hardcoded `background: #ffffff` ─────────────
   .action-dialog-card uses a literal white — needs dark surface. */
[data-theme="dark"] .body-app .action-dialog-card {
    background: var(--surface-subtle);
    border-color: var(--border-color);
    color: var(--text-primary);
}

/* ── FinancialDashboardPanel — hardcoded mobile table row border ─
   .financial-panel table tbody td has `border-bottom: 1px solid #f3f3f3`
   inside the @media (max-width: 767px) block — override to token. */
[data-theme="dark"] .body-app .financial-panel table tbody td {
    border-bottom-color: var(--border-color);
}

/* ── BlogManagementPanel / ApiKeysPanel — hardcoded #f3f3f3 row borders ─
   Mobile card layout uses `border-bottom: 1px solid #f3f3f3` — too light
   for dark surfaces. Token it via the broad table-cell override already
   covering .backoffice-table / .bookings-table; the blog panel uses the
   same .backoffice-table class so it's already covered. */

/* ── BackofficeSidebar — .nav-item.active low-alpha tint ────────
   Light-mode rgba(30,41,59,0.07) is invisible on charcoal. Use a
   white overlay so the active indicator reads without a blue cast. */
[data-theme="dark"] .body-app .backoffice-sidebar .nav-item.active {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-primary);
    border-left-color: var(--text-primary);
}
[data-theme="dark"] .body-app .backoffice-sidebar .nav-item.active .nav-badge {
    background: rgba(255, 255, 255, 0.12);
    color: var(--text-primary);
}

/* Backoffice sidebar mobile bottom border active indicator mirrors same fix */
[data-theme="dark"] .body-app .backoffice-sidebar .nav-item.active {
    border-bottom-color: var(--text-primary);
}


html, body {
    font-family: var(--font-sans);
    color: var(--text-primary);
    line-height: 1.6;
    margin: 0;
    padding: 0;
}

* {
    box-sizing: border-box;
}

/* Global accessible focus ring — brand red accent, both themes */
*:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

/* Skip-to-main link — visually hidden until focused, then flies in at top */
.skip-link {
    position: fixed;
    top: -100%;
    left: 0.5rem;
    z-index: 9999;
    padding: 0.5rem 1rem;
    background: var(--action-color);
    color: var(--on-action);
    font-weight: 700;
    font-size: 0.9rem;
    border-radius: 0 0 var(--border-radius) var(--border-radius);
    text-decoration: none;
    transition: top 0.15s ease;
}

.skip-link:focus {
    top: 0;
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

/* Typography */
h1, h2 {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
    letter-spacing: -0.02em;
    font-optical-sizing: auto;
}

h3, h4 {
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
    letter-spacing: -0.01em;
}

h5, h6 {
    font-weight: 500;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

h1:focus {
    outline: none;
}

/* Links */
a {
    color: var(--text-primary);
    text-decoration: none;
    transition: color 0.2s ease;
}

a:hover {
    color: var(--primary-color);
}

/* Buttons — modest 10px radius, flat solids, subtle hover lift. No gradients. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    font-weight: 600;
    padding: 12px 24px;
    line-height: 1.25;
    transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
    border: 1.5px solid transparent;
    white-space: nowrap;
}

.btn-primary {
    color: var(--on-action);
    background-color: var(--action-color);
    border-color: var(--action-color);
}

.btn-primary:hover {
    background-color: var(--action-hover);
    border-color: var(--action-hover);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.16);
    transform: translateY(-1px);
    color: var(--on-action);
}

.btn-outline-primary {
    color: var(--action-color);
    background-color: var(--surface-raised);
    border: 1.5px solid var(--action-color);
}

.btn-outline-primary:hover {
    background-color: var(--action-color);
    border-color: var(--action-color);
    color: var(--on-action);
}

.btn-outline-secondary {
    color: var(--text-secondary);
    background-color: var(--surface-raised);
    border: 1.5px solid var(--border-color);
}

.btn-outline-secondary:hover {
    background-color: var(--surface-warm);
    border-color: var(--text-primary);
    color: var(--text-primary);
}

.btn-outline-danger {
    color: var(--color-danger);
    background-color: var(--surface-raised);
    border: 1.5px solid var(--color-danger);
}

.btn-outline-danger:hover {
    background-color: var(--color-danger-bg);
    border-color: #B91C1C;
    color: #B91C1C;
}

.btn-success {
    color: var(--text-inverse);
    background-color: var(--color-success);
    border-color: var(--color-success);
}

.btn-success:hover {
    background-color: #15803D;
    border-color: #15803D;
    box-shadow: 0 6px 18px rgba(22, 163, 74, 0.22);
    transform: translateY(-1px);
    color: var(--text-inverse);
}

.btn-warning {
    color: var(--text-inverse);
    background-color: var(--color-warning);
    border-color: var(--color-warning);
}

.btn-warning:hover {
    background-color: #B45309;
    border-color: #B45309;
    box-shadow: 0 6px 18px rgba(217, 119, 6, 0.22);
    transform: translateY(-1px);
    color: var(--text-inverse);
}

.btn-danger {
    color: var(--text-inverse);
    background-color: var(--color-danger);
    border-color: var(--color-danger);
}

.btn-danger:hover {
    background-color: #B91C1C;
    border-color: #B91C1C;
    box-shadow: 0 6px 18px rgba(220, 38, 38, 0.22);
    transform: translateY(-1px);
    color: var(--text-inverse);
}

.btn-info {
    color: var(--text-inverse);
    background-color: var(--color-info);
    border-color: var(--color-info);
}

.btn-info:hover {
    background-color: #1D4ED8;
    border-color: #1D4ED8;
    box-shadow: 0 6px 18px rgba(37, 99, 235, 0.22);
    transform: translateY(-1px);
    color: var(--text-inverse);
}

.btn-outline-success {
    color: var(--color-success);
    background-color: var(--surface-raised);
    border: 1.5px solid var(--color-success);
}

.btn-outline-success:hover {
    background-color: var(--color-success-bg);
    border-color: #15803D;
    color: #15803D;
}

.btn-outline-warning {
    color: var(--color-warning);
    background-color: var(--surface-raised);
    border: 1.5px solid var(--color-warning);
}

.btn-outline-warning:hover {
    background-color: var(--color-warning-bg);
    border-color: #B45309;
    color: #B45309;
}

.btn-outline-info {
    color: var(--color-info);
    background-color: var(--surface-raised);
    border: 1.5px solid var(--color-info);
}

.btn-outline-info:hover {
    background-color: var(--color-info-bg);
    border-color: #1D4ED8;
    color: #1D4ED8;
}

.btn-sm {
    padding: 5px 14px;
    font-size: 0.8125rem;
    min-height: unset;
    border-radius: 8px;
}

.btn-lg {
    padding: 14px 32px;
    font-size: 1.0625rem;
    border-radius: 12px;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 4px rgba(26, 26, 26, 0.12);
    outline: none;
}

.btn-link {
    color: var(--text-primary);
}

.btn-link:hover {
    color: var(--primary-color);
}

/* Cards */
.card {
    border-radius: var(--border-radius);
    border: 1px solid var(--border-color);
    background: var(--surface-raised);
    box-shadow: none;
    transition: box-shadow 0.2s ease, border-color 0.2s ease;
}

.card:hover {
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
    border-color: #CBD5E1;
}

.card-img-top {
    border-radius: var(--border-radius) var(--border-radius) 0 0;
}

/* ── Canonical app-card ─────────────────────────────────────────────────── */
.app-card {
    background: var(--surface-raised);
    border: 1px solid var(--border-subtle);
    border-radius: var(--border-radius);
    padding: 1.25rem;
    box-shadow: var(--shadow-sm);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

/* Flush: card contains a table or element that needs edge-to-edge layout */
.app-card.app-card-flush {
    padding: 0;
}

/* Elevated: slightly more prominent surface */
.app-card.app-card-elevated {
    box-shadow: var(--shadow-md);
}

/* Interactive: subtle lift on hover */
.app-card.app-card-interactive:hover {
    border-color: var(--text-secondary);
    box-shadow: var(--shadow-md);
    cursor: pointer;
}

/* Card header row: title on the left, optional action on the right */
.app-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0 0 1rem 0;
    border-bottom: 1px solid var(--border-subtle);
    margin-bottom: 1rem;
}

.app-card-header h2,
.app-card-header h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-primary);
}

.app-card-header .app-card-subtitle {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin-top: 0.25rem;
    display: block;
}

/* When the card is flush, the header gets its own padding instead */
.app-card.app-card-flush .app-card-header {
    padding: 1.25rem 1.25rem 1rem;
    margin-bottom: 0;
}

/* ── Canonical app-table ────────────────────────────────────────────────── */
.app-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

.app-table thead th {
    background: var(--surface-subtle);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.75rem 1.25rem;
    text-align: left;
    border-bottom: 1px solid var(--border-subtle);
    position: sticky;
    top: 0;
    z-index: 1;
}

.app-table tbody td {
    padding: 0.85rem 1.25rem;
    border-bottom: 1px solid var(--border-subtle);
    color: var(--text-primary);
    vertical-align: middle;
}

.app-table tbody tr:last-child td {
    border-bottom: none;
}

.app-table tbody tr:hover td {
    background: var(--surface-subtle);
}

.app-table .app-table-actions {
    text-align: right;
    width: 1%;
    white-space: nowrap;
}

/* ── Canonical app-stat-tile ────────────────────────────────────────── */
/* Nested stat tile — for grids of metrics INSIDE a parent .app-card.
   Steps down to --surface-subtle so the inner tiles are visibly
   distinct from their white parent without re-using the raised level. */
.app-stat-tile {
    background: var(--surface-subtle);
    border: 1px solid var(--border-subtle);
    border-radius: var(--border-radius);
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.app-stat-tile-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    font-weight: 600;
}

.app-stat-tile-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
}

/* Standalone variant — when a stat tile sits ALONE on canvas (not
   inside a parent card), it should be raised, not subtle. */
.app-stat-tile.app-stat-tile-standalone {
    background: var(--surface-raised);
    border-color: var(--border-color);
}

/* Dark mode — ensure tile border stays visible against raised dark surface */
[data-theme="dark"] .body-app .app-stat-tile {
    border-color: var(--border-color);
}

/* ── Canonical app-action-row ───────────────────────────────────────── */
/* Action row — used on dashboards' "Actions" tabs to surface insights /
   recommended next steps. Severity modifier tints the left accent strip
   and icon to communicate urgency without sacrificing the card surface. */
.app-action-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.15rem;
    background: var(--surface-raised);
    border: 1px solid var(--border-color);
    border-left-width: 4px;
    border-left-color: var(--text-secondary);
    border-radius: var(--border-radius);
    color: var(--text-primary);
    text-decoration: none;
    transition: background-color 0.2s ease, border-color 0.2s ease;
}

.app-action-row:hover {
    background: var(--surface-subtle);
    border-color: var(--border-color);
    color: var(--text-primary);
    text-decoration: none;
}

.app-action-row.severity-info {
    border-left-color: var(--color-info);
}

.app-action-row.severity-warning {
    border-left-color: var(--color-warning);
}

.app-action-row.severity-danger {
    border-left-color: var(--color-danger);
}

.app-action-row.severity-success {
    border-left-color: var(--color-success);
}

.app-action-row-icon {
    width: 44px;
    height: 44px;
    border-radius: 12px;
    background: var(--background-light);
    color: var(--text-primary);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    flex-shrink: 0;
}

.app-action-row.severity-info .app-action-row-icon {
    background: var(--color-info-bg);
    color: var(--color-info);
}

.app-action-row.severity-warning .app-action-row-icon {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.app-action-row.severity-danger .app-action-row-icon {
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

.app-action-row.severity-success .app-action-row-icon {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.app-action-row-body {
    flex: 1;
    min-width: 0;
}

.app-action-row-title {
    font-weight: 700;
    font-size: 1rem;
    color: var(--text-primary);
    margin: 0;
}

.app-action-row-description {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin: 0;
    line-height: 1.4;
}

.app-action-row-meta {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    margin-top: 0.25rem;
}

.app-action-row-arrow {
    color: var(--text-secondary);
    flex-shrink: 0;
}

.app-action-list {
    display: grid;
    gap: 0.75rem;
}

/* Badges */
.badge {
    border-radius: var(--border-radius-pill);
    padding: 4px 12px;
    font-weight: 600;
    font-size: 0.75rem;
}

.bg-primary {
    background-color: var(--primary-color) !important;
}

.text-primary {
    color: var(--primary-color) !important;
}

.bg-primary-subtle {
    background-color: rgba(255, 56, 92, 0.1) !important;
}

.bg-success {
    background-color: var(--color-success) !important;
}

.bg-warning {
    background-color: var(--color-warning) !important;
}

.bg-danger {
    background-color: var(--color-danger) !important;
}

.bg-info {
    background-color: var(--color-info) !important;
}

.bg-success-subtle {
    background-color: var(--color-success-bg) !important;
}

.bg-warning-subtle {
    background-color: var(--color-warning-bg) !important;
}

.bg-danger-subtle {
    background-color: var(--color-danger-bg) !important;
}

.bg-info-subtle {
    background-color: var(--color-info-bg) !important;
}

.text-success {
    color: var(--color-success) !important;
}

.text-warning {
    color: var(--color-warning) !important;
}

.text-danger {
    color: var(--color-danger) !important;
}

.text-info {
    color: var(--color-info) !important;
}

/* Navbar */
.navbar {
    padding: 12px 0;
}

.navbar-brand {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--primary-color) !important;
}

.nav-link {
    font-weight: 500;
    color: var(--text-primary);
    padding: 8px 16px;
    border-radius: 8px;
    transition: background-color 0.2s ease, color 0.2s ease;
    position: relative;
    text-decoration: none;
}

.nav-link.nav-link-active {
    font-weight: 700;
    color: var(--text-primary);
}

.nav-link.nav-link-active::after {
    content: '';
    position: absolute;
    bottom: 2px;
    left: 16px;
    right: 16px;
    height: 2px;
    background: var(--primary-color);
    border-radius: 1px;
}

/* Sticky header */
.sticky-top {
    z-index: 1020;
}

header.sticky-top {
    background-color: var(--surface-raised);
    border-bottom: 1px solid var(--border-color);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

/* Nav tabs — underline-only active state */
.nav-tabs {
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
    gap: 0;
}

.nav-tabs .nav-link {
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--text-secondary);
    font-weight: 500;
    padding: 0.625rem 1rem;
    margin-bottom: -1px;
    background: transparent;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.nav-tabs .nav-link.active {
    border-bottom: 2px solid var(--text-primary);
    color: var(--text-primary);
    font-weight: 700;
    background: transparent;
}

.nav-tabs .nav-link:hover:not(.active) {
    border-bottom-color: rgba(0, 0, 0, 0.2);
    color: var(--text-primary);
    background: transparent;
}

/* Content spacing - REDUCED */
.content, main {
    padding-top: 0;
}

main > div {
    padding: 0;
}

/* Container improvements */
.container {
    max-width: 1280px;
    padding-left: 20px;
    padding-right: 20px;
}

/* Section surface helpers */
.section-dark {
    background: var(--surface-dark);
    color: var(--text-inverse);
}

.section-warm {
    background: var(--surface-warm);
    color: var(--text-primary);
}

.section-white {
    background: var(--surface-white);
    color: var(--text-primary);
}

/* Rounded utilities */
.rounded-pill {
    border-radius: var(--border-radius-pill) !important;
}

.rounded-3 {
    border-radius: 12px !important;
}

.rounded-4 {
    border-radius: 16px !important;
}

/* Image styling */
img {
    max-width: 100%;
    height: auto;
}

/* Shadow utilities */
.shadow-sm {
    box-shadow: var(--shadow-sm) !important;
}

.shadow {
    box-shadow: var(--shadow-md) !important;
}

.shadow-lg {
    box-shadow: var(--shadow-lg) !important;
}

/* Form styling */
.form-control {
    border-radius: 8px;
    border: 1px solid rgba(0, 0, 0, 0.15);
    padding: 12px 16px;
    background: var(--surface-raised);
}

.form-control:focus {
    border-color: var(--text-primary);
    box-shadow: 0 0 0 3px rgba(34, 34, 34, 0.08);
}

/* Validation */
.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e52000;
}

.validation-message {
    color: #e52000;
}

/* Error boundary */
.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTcuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: "An error has occurred."
}

/* Wizard Progress Styles */
.wizard-progress {
    margin: 2rem 0;
}

.wizard-progress .step {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
    flex: 1;
}

.wizard-progress .step-number {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: #e9ecef;
    color: #6c757d;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    font-size: 1rem;
    transition: all 0.3s ease;
    position: relative;
    z-index: 2;
}

.wizard-progress .step.active .step-number {
    background-color: var(--primary-color, #0d6efd);
    color: white;
    box-shadow: 0 4px 12px rgba(13, 110, 253, 0.3);
}

.wizard-progress .step.completed .step-number {
    background-color: #28a745;
    color: transparent;  /* hides the digit */
    font-size: 0;        /* belt-and-suspenders */
}

.wizard-progress .step.completed .step-number::after {
    content: "";  /* remove checkmark */
}

.wizard-progress .step-label {
    margin-top: 0.5rem;
    font-size: 0.875rem;
    color: #6c757d;
    text-align: center;
    transition: all 0.3s ease;
}

.wizard-progress .step.active .step-label {
    color: var(--primary-color, #0d6efd);
    font-weight: 600;
}

.wizard-progress .step.completed .step-label {
    color: #28a745;
}

.wizard-progress .step-line {
    height: 2px;
    background-color: #e9ecef;
    flex: 1;
    margin: 0 10px;
    align-self: center;
    position: relative;
    top: -15px;
    transition: background-color 0.3s ease;
}

.wizard-progress .step-line.completed {
    background-color: #28a745;
}

.step-content {
    animation: fadeIn 0.3s ease-in;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Responsive utilities */
@media (max-width: 768px) {
    .container {
        padding-left: 16px;
        padding-right: 16px;
    }
    
    .navbar {
        padding: 10px 0;
    }

    .wizard-progress .step-label {
        font-size: 0.75rem;
    }

    .wizard-progress .step-number {
        width: 32px;
        height: 32px;
        font-size: 0.875rem;
    }

    .wizard-progress .step-line {
        margin: 0 5px;
    }
}

/* Custom Map Marker Styles */
.custom-map-marker {
    background: transparent;
}

.custom-map-marker .marker-pin {
    width: 30px;
    height: 30px;
    border-radius: 50% 50% 50% 0;
    background: var(--primary-color, #FF385C);
    position: absolute;
    transform: rotate(-45deg);
    left: 50%;
    top: 50%;
    margin: -15px 0 0 -15px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

.custom-map-marker .marker-pin::after {
    content: '';
    width: 14px;
    height: 14px;
    margin: 8px 0 0 8px;
    background: var(--surface-raised);
    position: absolute;
    border-radius: 50%;
}

/* Leaflet popup customization */
.leaflet-popup-content-wrapper {
    border-radius: 8px;
    box-shadow: 0 3px 14px rgba(0, 0, 0, 0.4);
}

.leaflet-popup-content {
    margin: 13px 19px;
    line-height: 1.4;
    font-size: 14px;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* ── Backoffice shell layout (PlatformBackoffice + AdminUserDetail) ──────────── */
.backoffice-shell {
    display: flex;
    min-height: calc(100vh - 64px); /* 64px = AppTopBar height */
    background: white;
}

.backoffice-content {
    flex: 1;
    min-width: 0;
    padding: 1.25rem 1.75rem;
    background: var(--surface-canvas);
}

@media (max-width: 768px) {
    .backoffice-shell {
        flex-direction: column;
        min-height: unset;
    }

    .backoffice-content {
        padding: 1.25rem 1rem;
    }
}

/* ── Blazor reconnection toast ───────────────────────────────────────────────
   Subtle bottom-center pill. Blazor toggles show / hide / failed / rejected /
   resume-failed. "rejected" is not shown: circuit-reconnect.js reloads the
   page. The pill is the offline (failed) fallback, and the guard fallback
   when a second reload is suppressed.
   ─────────────────────────────────────────────────────────────────────────── */
#components-reconnect-modal {
    display: none;
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9999;
    pointer-events: none;
}

#components-reconnect-modal.components-reconnect-show {
    display: flex;
    animation: reconnect-slide-up 0.25s ease;
    pointer-events: auto;
}

#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-resume-failed,
#components-reconnect-modal.reconnect-reload-blocked {
    display: flex;
    animation: reconnect-slide-up 0.25s ease;
    pointer-events: auto;
}

#components-reconnect-modal.components-reconnect-hide {
    display: none;
}

.reconnect-toast {
    display: none;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border-radius: 40px;
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.14);
}

.components-reconnect-show .reconnect-toast-connecting {
    display: flex;
    background: rgba(34, 34, 34, 0.92);
    color: #ffffff;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

.components-reconnect-failed .reconnect-toast-failed,
.components-reconnect-resume-failed .reconnect-toast-failed,
.reconnect-reload-blocked .reconnect-toast-failed {
    display: flex;
    background: var(--color-warning-bg);
    color: var(--color-warning);
    border: 1px solid var(--color-warning-border);
}

.reconnect-spinner {
    width: 14px;
    height: 14px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #ffffff;
    border-radius: 50%;
    animation: reconnect-spin 0.7s linear infinite;
    flex-shrink: 0;
}

.reconnect-icon {
    font-size: 0.95rem;
    flex-shrink: 0;
}

.reconnect-reload {
    margin-left: 4px;
    font-weight: 700;
    color: #7b5800;
    text-decoration: underline;
    cursor: pointer;
}

.reconnect-reload:hover {
    color: #4a3500;
}

@keyframes reconnect-slide-up {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(12px);
    }
    to {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

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

/* ── Payabli embedded component ───────────────────────────────────────────── */
/* Strips Bootstrap grid padding so the single-row card layout renders flush   */

#payabli-container .row {
    margin: 0;
    align-items: center;
    flex-wrap: nowrap;
}

#payabli-container .row + .row {
    border-top: 1px solid var(--border-color);
}

#payabli-container [class*="col-"],
#payabli-container .col {
    padding: 0;
}

#payabli-container iframe {
    display: block;
    border: none;
    width: 100%;
}

#payabli-container [class*="col-"] + [class*="col-"] iframe,
#payabli-container .col + .col iframe {
    border-left: 1px solid var(--border-color);
}

#payabli-container .form-group,
#payabli-container .mb-3 {
    margin: 0;
}

#payabli-container label,
#payabli-container .form-label {
    display: none;
}

/* ── Mobile / WebView global utilities ───────────────────────────────────────
   Safe-area insets for iOS notch + home indicator.
   Applied via viewport-fit=cover in App.razor.
   ─────────────────────────────────────────────────────────────────────────── */

/* Prevent iOS Safari auto-zoom on focused inputs (font-size < 16px triggers it) */
@media (max-width: 767px) {
    input[type="text"],
    input[type="email"],
    input[type="password"],
    input[type="number"],
    input[type="tel"],
    input[type="url"],
    input[type="search"],
    input[type="date"],
    input[type="time"],
    textarea,
    select {
        font-size: 16px;
    }
}

/* Enforce 44px minimum touch targets on interactive elements */
@media (max-width: 767px) {
    .btn {
        min-height: 44px;
        padding-left: 16px;
        padding-right: 16px;
    }

    /* btn-sm still needs adequate touch area but can be smaller */
    .btn-sm {
        min-height: 40px;
    }

    .form-control,
    .form-select {
        min-height: 44px;
    }
}

/* Prevent horizontal overflow on mobile — Bootstrap row gutters can bleed past viewport */
@media (max-width: 767px) {
    .content-area,
    main {
        overflow-x: hidden;
    }

    /* Reduce Bootstrap container horizontal padding on phones */
    .container-fluid.px-4,
    .px-4 {
        padding-left: 1rem !important;
        padding-right: 1rem !important;
    }

    /* Ensure page content never exceeds viewport width */
    .backoffice-content {
        padding-left: 0.875rem;
        padding-right: 0.875rem;
    }
}

/* Reconnect toast: lift above mobile bottom nav bar */
@media (max-width: 767px) {
    #components-reconnect-modal {
        bottom: calc(var(--mobile-bottom-nav-height) + env(safe-area-inset-bottom, 0px) + 16px);
    }
}

/* Backoffice shell: add bottom padding on phones for mobile nav */
@media (max-width: 767px) {
    .backoffice-shell {
        padding-bottom: calc(var(--mobile-bottom-nav-height) + env(safe-area-inset-bottom, 0px));
    }
}

/* ============================================================
   Backoffice section header — shared between PlatformBackoffice
   tabs and any panel components rendered inside it (e.g.
   TransactionsPanel). Lives globally so CSS isolation does not
   strip it from sub-components.
   ============================================================ */
.content-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-color);
}

.content-title {
    font-size: 1.5rem;
    font-weight: 800;
    color: var(--text-primary);
    margin: 0 0 0.25rem;
    letter-spacing: -0.02em;
}

.content-subtitle {
    font-size: 0.875rem;
    color: var(--text-secondary);
    margin: 0;
}

.record-count-badge {
    flex-shrink: 0;
    background: var(--background-light);
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    font-size: 0.8rem;
    font-weight: 600;
    padding: 0.3rem 0.75rem;
    border-radius: var(--border-radius-pill);
    white-space: nowrap;
    margin-top: 0.25rem;
}

.status-filter-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.4rem 0.875rem;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-pill);
    background: var(--surface-raised);
    color: var(--text-secondary);
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s ease;
}

.status-filter-btn:hover {
    border-color: var(--text-primary);
    color: var(--text-primary);
}

.status-filter-btn.active {
    background: var(--text-primary);
    border-color: var(--text-primary);
    color: white;
}

.status-count {
    font-size: 0.75rem;
    font-weight: 700;
    background: rgba(0, 0, 0, 0.12);
    border-radius: 6px;
    padding: 0.05rem 0.4rem;
}

.status-filter-btn.active .status-count {
    background: rgba(255, 255, 255, 0.25);
}

/* Draws the eye to a non-active filter that has items needing review
   (e.g. Pending users awaiting approval). */
.status-filter-btn.needs-attention {
    border-color: var(--color-warning);
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.status-filter-btn.needs-attention:hover {
    border-color: var(--color-warning);
    color: var(--color-warning);
    background: white;
}

.status-filter-btn.needs-attention .status-count {
    background: var(--color-warning);
    color: white;
}

@media (max-width: 768px) {
    .content-header {
        flex-direction: column;
        gap: 0.5rem;
        align-items: flex-start;
    }

    .content-header .btn {
        width: 100%;
        justify-content: center;
    }
}

/* ============================================================
   Backoffice header stat bar — shared design system pattern
   Used by the bookings tab, platform dashboard, and financial
   dashboard for consolidated header metric rows.
   ============================================================ */
.booking-stats-row {
    display: flex;
    gap: 1px;
    background: var(--border-color);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    overflow: hidden;
}

.booking-stat {
    flex: 1;
    background: var(--surface-raised);
    padding: 0.625rem 1rem;
    border: none;
    text-align: left;
    cursor: default;
    min-width: 0;
}

.booking-stat-link {
    cursor: pointer;
    transition: background 0.15s ease;
}

.booking-stat-link:hover {
    background: var(--background-light);
}

a.booking-stat,
a.booking-stat-sub {
    text-decoration: none;
    color: inherit;
}

a.booking-stat:hover,
a.booking-stat:focus-visible {
    color: inherit;
}

.booking-stat-label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-secondary);
    margin-bottom: 0.1rem;
}

.booking-stat-value {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
}

.booking-stat-link .summary-card-link {
    font-size: 0.75rem;
    margin-top: 0.15rem;
    color: var(--primary-color);
    font-weight: 600;
}

.booking-stat-pair {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
}

.booking-stat-sub {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    min-width: 0;
    padding: 0.25rem 0.4rem;
    margin: -0.25rem -0.4rem;
    border-radius: 6px;
    transition: background 0.15s ease;
}

a.booking-stat-sub {
    cursor: pointer;
}

a.booking-stat-sub:hover,
a.booking-stat-sub:focus-visible {
    background: var(--background-light);
    color: inherit;
}

.booking-stat-sub-value {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
}

.booking-stat-sub-label {
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    white-space: nowrap;
}

.booking-stats-row.booking-stats-row-wrap {
    flex-wrap: wrap;
}

@media (max-width: 991px) {
    .booking-stats-row {
        flex-wrap: wrap;
    }

    .booking-stat {
        flex: 1 1 calc(50% - 1px);
    }
}

@media (max-width: 575px) {
    .booking-stat {
        flex: 1 1 100%;
    }

    .booking-stat-pair {
        gap: 1rem;
    }

    .booking-stat-sub-value {
        font-size: 1.2rem;
    }
}

/* ============================================================
   .NET MAUI shell ("hoastnow-mobile" UA) — chrome stripping
   The inline script in App.razor adds `in-mobile-app` to <html>
   when the WebView UA contains "hoastnow-mobile". CSS does the
   rest so there is no SSR/interactive flash.
   ============================================================ */

/* Hide marketing chrome (top header, footer, public chat) inside the app. */
html.in-mobile-app .app-chrome-public {
    display: none !important;
}

/* Hide authenticated web chrome inside the MAUI shell — the native app
   shell supplies only a minimal top bar (MobileAppHeader). The web still
   renders the role-specific mobile bottom tab bar (.mobile-bottom-nav) so
   logged-in users (esp. Platform/Community roles) retain access to primary
   navigation items. We continue to suppress the desktop rail + wide top bar
   to avoid doubling with the in-app header. */
html.in-mobile-app .app-topbar,
html.in-mobile-app .search-filters-band,
html.in-mobile-app .rail-shell {
    display: none !important;
}

/* Native shell hides the desktop rail, so the wizard dock must not keep the rail inset. */
html.in-mobile-app .wizard-navigation {
    left: 0;
}

/* NOTE: .mobile-bottom-nav is intentionally NOT hidden here.
   The phone media query shows it below 768px. Inside the native shell the
   bar also stays up at wider widths, because the rail is suppressed and a
   landscape WebView would otherwise have no menu. Pad content in that case
   too — the phone rule in MainLayout.razor.css only applies under 768px. */
html.in-mobile-app .content-area.has-mobile-nav,
html.in-mobile-app .backoffice-shell {
    padding-bottom: calc(var(--mobile-bottom-nav-height) + env(safe-area-inset-bottom, 0px));
}

/* Reveal the X-style top bar inside the app. */
html.in-mobile-app .mobile-app-header {
    display: flex;
}

/* ------------------------------------------------------------
   Auth pages (/login, /register) — restyle to match the native
   RoleSelectPage / WelcomePage chrome so the WebView feels like
   a continuation of the native flow, not a separate website.
   ------------------------------------------------------------ */

/* Drop the split-panel shell — inside the native app the auth pages
   should feel edge-to-edge and top-aligned, like a native form screen.
   (Auth pages render inside <AuthShell>; the brand panel is web-only.) */
html.in-mobile-app .auth-shell {
    display: block;
    min-height: auto;
}

html.in-mobile-app .auth-shell-panel {
    display: none;
}

/* Auth-shell logos are branding only inside the native app — never a home link.
   Force the form-column logo visible even on wide WebViews (the brand panel
   is hidden in-app, so the <991px media query is not enough). */
html.in-mobile-app .auth-shell-logo-link,
html.in-mobile-app .auth-shell-mobile-logo {
    pointer-events: none;
    cursor: default;
}

html.in-mobile-app .auth-shell-mobile-logo {
    display: block;
}

html.in-mobile-app .auth-shell-form {
    align-items: flex-start;
    background: transparent;
    padding: 1.5rem;
}

html.in-mobile-app .auth-shell-form-inner {
    max-width: 100%;
    animation: none;
}

html.in-mobile-app .login-card,
html.in-mobile-app .register-card {
    border: none !important;
    box-shadow: none !important;
    background: transparent !important;
    border-radius: 0 !important;
}

html.in-mobile-app .login-card .card-body,
html.in-mobile-app .register-card .card-body {
    padding: 0.5rem 0 !important;
}

html.in-mobile-app .login-card .card-title,
html.in-mobile-app .register-card .register-heading {
    text-align: left !important;
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.25rem !important;
}

/* Form controls — match native Entry styling: 16px text, 1px border,
   12px corners, comfortable height. */
html.in-mobile-app .login-card .form-control,
html.in-mobile-app .register-card .form-control {
    font-size: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    min-height: 48px;
}

html.in-mobile-app .login-card .form-control:focus,
html.in-mobile-app .register-card .form-control:focus {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(255, 56, 92, 0.15);
}

html.in-mobile-app .login-card .form-label,
html.in-mobile-app .register-card .form-label {
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 0.4rem;
}

/* Primary submit — match the native 52px brand-red CTA. */
html.in-mobile-app .login-card .btn-primary,
html.in-mobile-app .register-card .btn-primary {
    height: 52px;
    border-radius: var(--border-radius);
    font-size: 1rem;
    font-weight: 700;
}

/* Hide "Remember me" inside the app — refresh-token + biometrics
   already handle persistence transparently. */
html.in-mobile-app .login-card .form-check {
    display: none;
}

/* Tighten the "Don't have an account?" / "Login here" link rows. */
html.in-mobile-app .login-card hr,
html.in-mobile-app .register-card hr {
    margin: 1.5rem 0 1rem;
    border-color: var(--border-color);
    opacity: 0.6;
}

/* ── In-app entrance motion suppression ─────────────────────────────────
   Inside the MAUI WebView, entrance animations read as web jank rather
   than a polished native feel. We suppress only Reveal-driven entrances
   (opacity:0 → is-visible) by forcing the visible state immediately.
   The !important overrides the .reveal:not(.is-visible) will-change guard
   and the reveal class's opacity/transform/transition declarations — which
   are scoped to a component stylesheet so specificity alone is not enough.

   Decision: CSS stagger-entrance classes (250–400ms, used in a handful of
   marketing/landing grids) are accepted in-app — they are subtle and
   targeting them would require brittle per-page selectors. Skeleton shimmer
   keyframes (e.g. .placeholder-wave, -skeleton classes) are intentionally
   left untouched: they represent loading state, not entrance motion, and
   must keep animating inside the app.

   Drag/interaction feedback transitions (hover/press color/transform) also
   stay — the filter is semantic: entrance-only. */
html.in-mobile-app .reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
}

/* ============================================================
   CSS-only tooltip — apply with [data-tooltip="..."] on any
   element. Works on hover and keyboard focus, no JS required,
   appears immediately (unlike the native title attribute which
   is delayed and unreliable on touch devices).

   Bootstrap .btn-close also gets a default "Dismiss" tooltip
   without any markup change (override with data-tooltip="...").

   Usage:
     <button data-tooltip="Restore" aria-label="Restore" ...>
   By default the tooltip sits ABOVE the trigger; add
   data-tooltip-placement="bottom" / "left" / "right" to flip it.
   ============================================================ */
[data-tooltip],
.btn-close {
    position: relative;
}

[data-tooltip]::after,
.btn-close::after {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    padding: 0.35rem 0.6rem;
    background: rgba(26, 28, 30, 0.95);
    color: #ffffff;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: 0.01em;
    white-space: nowrap;
    border-radius: 6px;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    z-index: 1080;
    transition: opacity 0.12s ease, transform 0.12s ease, visibility 0s linear 0.12s;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
}

[data-tooltip]::after {
    content: attr(data-tooltip);
}

/* Default tooltip text for Bootstrap dismiss buttons that don't carry an
   explicit data-tooltip override. */
.btn-close:not([data-tooltip])::after {
    content: "Dismiss";
}

[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after,
.btn-close:hover::after,
.btn-close:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
    transition: opacity 0.12s ease, transform 0.12s ease, visibility 0s;
}

[data-tooltip][data-tooltip-placement="bottom"]::after {
    bottom: auto;
    top: calc(100% + 6px);
    transform: translateX(-50%) translateY(-4px);
}

[data-tooltip][data-tooltip-placement="bottom"]:hover::after,
[data-tooltip][data-tooltip-placement="bottom"]:focus-visible::after {
    transform: translateX(-50%) translateY(0);
}

[data-tooltip][data-tooltip-placement="right"]::after {
    bottom: auto;
    top: 50%;
    left: calc(100% + 6px);
    transform: translate(-4px, -50%);
}

[data-tooltip][data-tooltip-placement="right"]:hover::after,
[data-tooltip][data-tooltip-placement="right"]:focus-visible::after {
    transform: translate(0, -50%);
}

[data-tooltip][data-tooltip-placement="left"]::after {
    bottom: auto;
    top: 50%;
    left: auto;
    right: calc(100% + 6px);
    transform: translate(4px, -50%);
}

[data-tooltip][data-tooltip-placement="left"]:hover::after,
[data-tooltip][data-tooltip-placement="left"]:focus-visible::after {
    transform: translate(0, -50%);
}

/* Disabled buttons should not show a tooltip — pointer-events:none on the
   button means :hover doesn't fire; this is just a safeguard. */
[data-tooltip][disabled]::after,
.btn-close[disabled]::after {
    display: none;
}

/* Suppress the tooltip on coarse-pointer (touch) devices where it would
   never naturally dismiss. The aria-label still carries the accessible
   name for screen readers. */
@media (hover: none) and (pointer: coarse) {
    [data-tooltip]::after,
    .btn-close::after {
        display: none;
    }
}

/* ─── Shared bottom CTA strip ──────────────────────────────────────────
   Dark, full-bleed CTA section used at the foot of public landing pages
   (/brands, /communities, /referral-partners). Inner buttons are styled
   per-page so they pick up each page's hero-button scoping. */
.bottom-cta-section {
    padding: var(--section-pad-y-sm) 0;
    background: linear-gradient(135deg, var(--surface-dark) 0%, var(--surface-charcoal) 100%);
}

.bottom-cta-card {
    max-width: 900px;
    margin: 0 auto;
    text-align: center;
    color: var(--text-inverse);
    padding: 0 1rem;
}

.bottom-cta-heading {
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 3.5vw, 2.5rem);
    font-weight: 600;
    color: var(--text-inverse);
    margin-bottom: 0.75rem;
    letter-spacing: -0.01em;
    font-optical-sizing: auto;
}

.bottom-cta-sub {
    color: var(--text-on-dark);
    font-size: 1.0625rem;
    margin-bottom: 1.75rem;
}

.bottom-cta-actions {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
}

@media (max-width: 576px) {
    .bottom-cta-actions {
        flex-direction: column;
        width: 100%;
    }
}

/* =====================================================================
   Detail page lightbox overlay
   Injected into document.body by Detail.razor.js — cannot use Blazor CSS
   isolation (scoped selectors won't match dynamically-created elements).
   ===================================================================== */

.detail-lightbox-overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    background: rgba(0, 0, 0, 0.92);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.25s ease;
}

.detail-lightbox-overlay.lb-visible {
    opacity: 1;
}

/* Main image */
.lb-image {
    display: block;
    max-width: calc(100vw - 160px);
    max-height: calc(100vh - 80px);
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: 4px;
    user-select: none;
}

/* Caption — "n / total" */
.lb-caption {
    position: absolute;
    bottom: 1.25rem;
    left: 50%;
    transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.75);
    font-size: 0.875rem;
    font-weight: 500;
    white-space: nowrap;
    pointer-events: none;
}

/* Shared button base */
.lb-btn {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 9999px;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
    z-index: 9001;
}

.lb-btn:focus-visible {
    outline: 2px solid #FF385C;
    outline-offset: 2px;
}

/* Close button — top-right */
.lb-btn-close {
    top: 1rem;
    right: 1rem;
    width: 44px;
    height: 44px;
    background: rgba(255, 255, 255, 0.15);
    color: #ffffff;
    font-size: 1.125rem;
}

.lb-btn-close:hover {
    background: rgba(255, 255, 255, 0.28);
    transform: scale(1.08);
}

/* Prev / Next — vertically centered sides */
.lb-btn-prev,
.lb-btn-next {
    top: 50%;
    transform: translateY(-50%);
    width: 52px;
    height: 52px;
    background: rgba(255, 255, 255, 0.15);
    color: #ffffff;
    font-size: 1.25rem;
}

.lb-btn-prev { left: 1.25rem; }
.lb-btn-next { right: 1.25rem; }

.lb-btn-prev:hover,
.lb-btn-next:hover {
    background: rgba(255, 255, 255, 0.28);
    transform: translateY(-50%) scale(1.06);
}

/* Mobile: full-width image, smaller nav buttons */
@media (max-width: 768px) {
    .lb-image {
        max-width: calc(100vw - 24px);
        max-height: calc(100svh - 120px);
    }

    .lb-btn-prev { left: 0.5rem; }
    .lb-btn-next { right: 0.5rem; }

    .lb-btn-prev,
    .lb-btn-next {
        width: 40px;
        height: 40px;
        font-size: 1rem;
    }
}

/* ---------------------------------------------------------------------------
   Motion foundation (2026 UI/UX overhaul)
   --------------------------------------------------------------------------- */

/* Cross-component hover elevation. Apply to cards/tiles. */
.hover-lift {
    transition:
        transform var(--motion-base) var(--ease-standard),
        box-shadow var(--motion-base) var(--ease-standard);
}

.hover-lift:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lift);
}

/* Global guard: collapse ALL motion when the user opts out. Covers every
   surface (public and authenticated); components may still self-guard for
   effects that need a non-animated fallback state (e.g. Reveal, SkeletonBlock). */
@media (prefers-reduced-motion: reduce) {
    body *,
    body *::before,
    body *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Contact page: the public hoastie square travels into #contact-hoastie-card.
   contact-hoastie.js owns the flight. These rules only hold the settled states. */
html.contact-hoastie-fly #contact-hoastie-card {
    opacity: 0;
    pointer-events: none;
}

html.contact-hoastie-fly .chat-float-button,
html.contact-hoastie-returning .chat-float-button,
html:has(#contact-hoastie-card) .chat-float-button,
.chat-float-button[data-hoastie-parked] {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}

#hoastie-flight-host {
    position: fixed;
    inset: 0;
    z-index: 1090;
    overflow: visible;
    pointer-events: none;
}

#hoastie-flight-host .contact-hoastie-flyer,
#hoastie-flight-host .contact-hoastie-flyer-avatar {
    position: absolute;
}

html:has(#contact-hoastie-card) .chat-modal-container,
html:has(#contact-hoastie-card) .chat-backdrop {
    display: none;
}

.contact-hoastie-flyer,
.contact-hoastie-flyer-avatar {
    position: fixed;
    z-index: 1090;
    margin: 0;
    box-sizing: border-box;
    pointer-events: none;
}

.contact-hoastie-flyer {
    background: linear-gradient(135deg, var(--surface-color) 0%, var(--surface-subtle) 100%);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-xl);
}

.contact-hoastie-flyer-avatar {
    z-index: 1091;
    display: flex;
}
