/* wallmarkets Design System - WORLD-CLASS Color Palette
   Inspired by: Linear, Vercel, Stripe, Notion, Discord
   ============================================================================ */

/* ============================================================================
   🌞 LIGHT MODE - Clean, Professional, High Contrast
   Inspired by: Stripe's clarity + Linear's elegance
   ============================================================================ */

:root {
    /* ═══════════════════════════════════════════════════════════════════════
       BRAND COLORS - Vibrant Purple (Stripe-inspired)
       Authored as HSL channels so alpha tints (bg-brand/20) compute cleanly
       HSL channels keep alpha tints and brand swaps consistent.
       ═══════════════════════════════════════════════════════════════════════ */
    --brand-h: 244;
    --brand-s: 100%;
    --brand-l: 68%;
    --brand-primary: hsl(var(--brand-h) var(--brand-s) var(--brand-l));
    /* Brand as SMALL TEXT on a light surface. --brand-primary is tuned as a
       FILL (white-on-brand buttons are fine at any of these lightnesses), but
       as 11-13px text it measures 4.30:1 on the --theme-card-bg (#F6F7F9) used
       by marketing sections — under WCAG 1.4.3's 4.5:1 for normal text. It
       passes on pure white (4.61) which is why it looked fine in isolation; the
       card background is what tips it. Two points darker clears both: 4.76 on
       card, 5.10 on white. Do NOT use this for fills — it is a text token. */
    /* 66% was solved against white and the plain card (#F6F7F9). On a brand
       TINT — .pc-toc-h-tag and .wm-section-nav-item-active sit on
       --tint-brand-10, i.e. the brand itself at 10% — it lands on exactly
       4.50:1, meeting AA with no margin at all. One more point clears it to
       4.70 and is imperceptible; darkening only ever helps the other callers,
       which are all brand text on light surfaces. */
    --brand-l-text: 65%;   /* light theme: DARKER than --brand-l (68%) */
    --brand-text: hsl(var(--brand-h) var(--brand-s) var(--brand-l-text));
    /* Brand as a FILLED SURFACE carrying white text (bg-brand + text-white:
       PWA install CTA, onboarding banners, the shared button macro — 18 sites).
       The claim above that "white-on-brand buttons are fine at any of these
       lightnesses" holds in the light theme (4.61:1) but NOT in the dark one,
       where --brand-l rises to 74% to serve brand text/borders on dark chrome
       and white-on-fill drops to 2.86:1. Like --brand-l-text, this lightness
       has to move per theme; unlike it, it moves DOWN in dark. Note the dark
       theme also shifts --brand-h 244 → 232, so the usable band has to be
       solved against THAT hue, not this one. Do NOT use this for brand text or
       borders — it is a fill. */
    --brand-l-fill: 68%;   /* light: same as --brand-l — white reads 4.62:1 */
    --brand-fill: hsl(var(--brand-h) var(--brand-s) var(--brand-l-fill));
    --brand-primary-hover: #5046E5;
    --brand-primary-active: #4338CA;
    --brand-primary-light: #EEF2FF;
    --brand-primary-lighter: #F5F7FF;
    --brand-primary-border: #C7D2FE;
    --brand-primary-glow: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.15);

    /* B2B channels — aliased to the brand: the portal is the SAME product,
       so tailwind's text-b2b-… and bg-b2b-… utilities render brand-colored.
       (The emerald .b2b-theme override is gone — 2026-07-06 audit.)
       NB: do not write the glob for those utilities with a literal asterisk
       followed by a slash in here — that sequence CLOSES this comment, and
       the rest of the sentence is then parsed as CSS. It used to. */
    --b2b-h: var(--brand-h);
    --b2b-s: var(--brand-s);
    --b2b-l: var(--brand-l);

    /* ═══════════════════════════════════════════════════════════════════════
       SEMANTIC COLORS - Carefully tuned for accessibility (WCAG AA+)
       ═══════════════════════════════════════════════════════════════════════ */

    /* Success - Fresh Emerald */
    --success: #10B981;
    --success-hover: #059669;
    --success-active: #047857;
    --success-light: #ECFDF5;
    --success-lighter: #F0FDF9;
    --success-border: #A7F3D0;
    --success-text: #065F46;

    /* Danger - Vibrant Rose */
    --danger: #F43F5E;
    --danger-hover: #E11D48;
    --danger-active: #BE123C;
    --danger-light: #FFF1F2;
    --danger-lighter: #FFF5F6;
    --danger-border: #FECDD3;
    --danger-text: #9F1239;
    --danger-bg: var(--danger-lighter);  /* subtle danger surface (danger-zone, danger nav hover). Themeable in ONE place — 4 call-sites (form_v2/detail_v2/index_v2) previously relied on an rgba() fallback literal. Auto-darkens via --danger-lighter. */

    /* Warning - Warm Amber */
    --warning: #F59E0B;
    --warning-hover: #D97706;
    --warning-active: #B45309;
    --warning-light: #FFFBEB;
    --warning-lighter: #FEFCE8;
    --warning-border: #FDE68A;
    --warning-text: #92400E;
    /* Rating stars. They used --warning (#F59E0B), which is 2.15:1 on white —
       under WCAG 1.4.11's 3:1 for graphics that carry meaning. --warning-text
       is the wrong repair here: it is a brown tuned for body copy and turns
       gold stars to mud. sf_stars only renders a visible numeric rating when a
       count is passed, so where it is not the stars ARE the rating and the
       floor applies. One step deeper clears it (3.18:1) and still reads gold. */
    /* #B45309, not #D97706: the filled stars are a meaning-bearing graphic
       (the visible "4.2 of 5") and #D97706 measured 2.97:1 on white — just
       under WCAG 1.4.11's 3:1. #B45309 is ~4.7:1 and still reads as amber. */
    --rating-star: #B45309;

    /* Info - Clear Sky Blue */
    --info: #3B82F6;
    --info-hover: #2563EB;
    --info-active: #1D4ED8;
    --info-light: #EFF6FF;
    --info-lighter: #F0F9FF;
    --info-border: #BFDBFE;
    --info-text: #1E40AF;

    /* ═══════════════════════════════════════════════════════════════════════
       NEUTRAL PALETTE - Refined Gray Scale (Notion-inspired)
       ═══════════════════════════════════════════════════════════════════════ */
    --white: #FFFFFF;
    --gray-25: #FCFCFD;
    --gray-50: #F9FAFB;
    --gray-100: #F3F4F6;
    --gray-200: #E5E7EB;
    --gray-300: #D1D5DB;
    --gray-400: #9CA3AF;
    --gray-500: #6B7280;
    --gray-600: #4B5563;
    --gray-700: #374151;
    --gray-800: #1F2937;
    --gray-900: #111827;
    --gray-950: #030712;

    /* ═══════════════════════════════════════════════════════════════════════
       ACCENT COLORS - For highlights and special elements
       ═══════════════════════════════════════════════════════════════════════ */
    --accent-purple: #8B5CF6;
    --accent-pink: #EC4899;
    --accent-cyan: #06B6D4;
    --accent-orange: #F97316;
    --accent-lime: #84CC16;

    /* ═══════════════════════════════════════════════════════════════════════
       TYPOGRAPHY
       ═══════════════════════════════════════════════════════════════════════ */
    /* Operational / Linear-style fonts for dashboard, storefront, all customer flows.
       Fancy display fonts (Space Grotesk / Plus Jakarta) are ONLY for landing + footer marketing surfaces.
       See tailwind.config.js fontFamily + prior cleanup + user rule. */
    /* Dashboard typography roles. Change these once for every workspace. */
    --wm-type-page: 1.375rem;    /* 22px: page title */
    --wm-type-section: 0.875rem; /* 14px: section title, distinguished by weight */
    --wm-type-body: 0.875rem;    /* 14px: values, controls, prose */
    --wm-type-label: 0.75rem;    /* 12px: supporting metadata and help text */
    --wm-type-metric: 2rem;      /* 32px: standalone summary values */
    --wm-type-metric-fit: clamp(1rem, 13cqi, 1.625rem); /* Metrics inside narrow tiles */
    --wm-type-display: 3rem;    /* 48px: one primary dashboard metric */
    --wm-type-icon: 1.25rem;    /* 20px: glyphs, not text */
    --wm-type-icon-lg: 2rem;
    --wm-leading-title: 1.25;
    --wm-leading-text: 1.5;
    --wm-weight-regular: 400;
    --wm-weight-medium: 500;
    --wm-weight-strong: 600;

    --font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-family-heading: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-family-mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace;

    /* Type scale base = 16px (1rem) — matches Tailwind defaults + WCAG sane.
       --font-size-xxs (11px) is the legitimately-tiny tier so templates stop
       reaching for arbitrary `text-[10px]`/`text-[11px]` literals. */
    --font-size-xxs:  0.6875rem;  /* 11px */
    --font-size-xs:   0.75rem;    /* 12px */
    --font-size-sm:   0.875rem;   /* 14px */
    --font-size-base: 1rem;       /* 16px (was 14px — caused two parallel scales) */
    --font-size-lg:   1.125rem;   /* 18px */
    --font-size-xl:   1.25rem;    /* 20px */
    --font-size-2xl:  1.5rem;     /* 24px */
    --font-size-3xl:  1.875rem;   /* 30px */
    --font-size-4xl:  2.25rem;    /* 36px */
    --font-size-5xl:  3rem;       /* 48px */
    --font-size-6xl:  3.75rem;    /* 60px */

    /* ═══════════════════════════════════════════════════════════════════════
       SPACING - 4px Base Grid
       ═══════════════════════════════════════════════════════════════════════ */
    --space-0: 0;
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-7: 1.75rem;   /* completes the 4px grid — was missing; pages using it (careers, investors, docs) had their margins/padding collapse to 0 */
    --space-8: 2rem;
    --space-10: 2.5rem;
    --space-12: 3rem;
    --space-14: 3.5rem;   /* completes the 4px grid — was missing; section gaps that used it collapsed, cramming sections together */
    --space-16: 4rem;
    --space-20: 5rem;
    --space-24: 6rem;

    /* ═══════════════════════════════════════════════════════════════════════
       BORDER RADIUS - Smooth, Modern Curves
       ═══════════════════════════════════════════════════════════════════════ */
    --radius-none: 0;
    --radius-sm: 0.25rem;
    /* One control height for every toolbar. Each v2 family used to derive
       height from `padding: 7px 14px` + its own font-size, which is how a
       40px "…" trigger ended up beside 34px buttons in the same row
       (user-reported). Buttons, selects, icon-triggers and date inputs in
       page chrome all sit on --control-h; compact table-row controls use
       --control-h-sm. */
    --control-h: 36px;
    --control-h-sm: 32px;

    /* The mobile topbar lives INSIDE <main> (the scroll container), sticky at
       top:0 z-20. Any other sticky bar in main that also says top:0 pins
       BEHIND it — the delivery form's action bar lost 69 of its 107px that
       way. Sticky bars offset by this under the mobile shell (<768px); the
       topbar pins its own height to it so the two cannot drift apart. */
    --wm-mobile-topbar-h: 69px;

    /* THE card. Two "systems" (wm-card, frm-card) turned out to be one
       definition duplicated across files — identical trio, separate blocks,
       free to drift. Every card primitive consumes THESE, so there is one
       source of truth and N names; a card that strays fails
       test_ui_contract_invariants with its selector printed. */
    --card-bg: var(--theme-card-bg);
    --card-border: 1px solid var(--border-subtle);
    --card-radius: var(--radius-lg);
    --radius-md: 0.375rem;
    --radius-lg: 0.5rem;
    --radius-xl: 0.75rem;
    --radius-2xl: 1rem;
    --radius-3xl: 1.5rem;
    --radius-full: 9999px;

    /* ═══════════════════════════════════════════════════════════════════════
       SHADOWS - Two-part composition
       Tight key shadow + diffuse ambient shadow on slate-tinted alpha so
       elevation reads "lit from above" without feeling neutral-grey.
       ═══════════════════════════════════════════════════════════════════════ */
    --shadow-xs: 0 1px 1px 0 rgba(15, 23, 42, 0.04);
    --shadow-sm: 0 1px 2px 0 rgba(15, 23, 42, 0.04), 0 1px 1px -1px rgba(15, 23, 42, 0.06);
    --shadow-md: 0 1px 3px 0 rgba(15, 23, 42, 0.05), 0 4px 8px -2px rgba(15, 23, 42, 0.08);
    --shadow-lg: 0 4px 8px -2px rgba(15, 23, 42, 0.06), 0 12px 24px -4px rgba(15, 23, 42, 0.10);
    --shadow-xl: 0 8px 16px -4px rgba(15, 23, 42, 0.08), 0 24px 48px -12px rgba(15, 23, 42, 0.16);
    --shadow-float-strong: 0 12px 24px -6px rgba(15, 23, 42, 0.10), 0 40px 80px -20px rgba(15, 23, 42, 0.20);
    --shadow-inner: inset 0 1px 2px 0 rgba(15, 23, 42, 0.06);

    /* Semantic elevation aliases */
    --shadow-card: var(--shadow-md);
    --shadow-popover: var(--shadow-lg);
    --shadow-modal: var(--shadow-xl);
    --shadow-floating: var(--shadow-float-strong);

    /* Colored shadows for buttons — kept subtle for hover focus */
    --shadow-brand: 0 1px 2px 0 rgba(15, 23, 42, 0.04), 0 4px 14px rgba(99, 91, 255, 0.18);
    --shadow-success: 0 1px 2px 0 rgba(15, 23, 42, 0.04), 0 4px 14px rgba(16, 185, 129, 0.18);
    --shadow-danger: 0 1px 2px 0 rgba(15, 23, 42, 0.04), 0 4px 14px rgba(244, 63, 94, 0.18);

    /* ═══════════════════════════════════════════════════════════════════════
       TRANSITIONS - Smooth, Responsive
       ═══════════════════════════════════════════════════════════════════════ */
    /* Named easing curves (emil-design-eng): built-in CSS easings are too weak
       for UI. Strong ease-out gives instant feedback; ease-in-out for on-screen
       morphing. Use these for new component transitions. */
    --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
    --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

    /* --transition-fast is the micro-interaction token (hover/press/focus, 317
       uses). Upgraded from Material ease-in-out → strong ease-out so feedback
       feels instant (ease-in-out starts slow exactly when the user is watching).
       base/normal/slow keep ease-in-out — they animate larger/morphing surfaces. */
    --transition-fast: 120ms cubic-bezier(0.23, 1, 0.32, 1);
    --transition-base: 150ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-bounce: 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);

    /* ═══════════════════════════════════════════════════════════════════════
       GRADIENTS - Premium Feel
       ═══════════════════════════════════════════════════════════════════════ */
    --gradient-brand: linear-gradient(135deg, #635BFF 0%, #8B5CF6 100%);
    --gradient-brand-subtle: linear-gradient(135deg, #EEF2FF 0%, #F5F3FF 100%);
    --gradient-success: linear-gradient(135deg, #10B981 0%, #34D399 100%);
    --gradient-danger: linear-gradient(135deg, #F43F5E 0%, #FB7185 100%);
    --gradient-sunset: linear-gradient(135deg, #F97316 0%, #EC4899 100%);
    --gradient-ocean: linear-gradient(135deg, #3B82F6 0%, #06B6D4 100%);
    --gradient-aurora: linear-gradient(135deg, #8B5CF6 0%, #06B6D4 100%);

    /* Mesh gradients for hero sections */
    --gradient-mesh-light: radial-gradient(at 40% 20%, rgba(99, 91, 255, 0.08) 0px, transparent 50%),
                           radial-gradient(at 80% 0%, rgba(139, 92, 246, 0.06) 0px, transparent 50%),
                           radial-gradient(at 0% 50%, rgba(59, 130, 246, 0.06) 0px, transparent 50%);

    /* ═══════════════════════════════════════════════════════════════════════
       LAYOUT
       ═══════════════════════════════════════════════════════════════════════ */
    --sidebar-width: 240px;
    --navbar-height: 64px;
    --height-footer: 80px;
    --border-width-1: 1px;
    --border-width-2: 2px;
    --max-width-content: 1280px;
    --min-touch-target: 44px;  /* WCAG 2.5.5 minimum tap target */

    /* ═══════════════════════════════════════════════════════════════════════
       SEMANTIC BORDER TOKENS — pick by intent, not literal color
       ═══════════════════════════════════════════════════════════════════════ */
    --border-divider: hsl(var(--brand-h) 8% 92%);    /* row dividers, table tbody */
    --border-subtle: hsl(var(--brand-h) 8% 88%);     /* card edges, inputs at rest */
    --border-strong: hsl(var(--brand-h) 8% 80%);     /* dividers, emphasis edges */
    /* The BOUNDARY OF AN INTERACTIVE CONTROL — inputs, selects, checkboxes,
     * radios, steppers. Separate from --border-strong because the two have
     * different requirements and cannot share a value:
     *
     *   - a divider is decoration; WCAG imposes no ratio on it;
     *   - a control's boundary is "visual information required to identify a
     *     user interface component" — WCAG 1.4.11 requires 3:1.
     *
     * --border-strong served both and met neither: measured on the rendered
     * checkout form, its border was 1.66:1 in light and 2.06:1 in dark, and the
     * control's FILL is identical to the card behind it (1.00:1), so the border
     * was the only thing identifying where the field was. Worst case is an
     * unchecked checkbox, which is nothing BUT its border.
     *
     * 3.26:1 against the worst-case surface in each theme (white card in light,
     * --theme-card-bg in dark). Raising --border-strong instead would have
     * dragged every divider in the app up to a control's ratio, which is how a
     * form-control requirement becomes a heavy-looking table. */
    --border-control: hsl(var(--brand-h) 8% 58%);
    --border-accent: hsl(var(--brand-h) var(--brand-s) var(--brand-l));  /* focus rings */

    /* ═══════════════════════════════════════════════════════════════════════
       CANONICAL TINT UTILITIES — replace ad-hoc rgba() across the codebase
       (consume via var(--tint-...) or via Tailwind's bg-brand/N path)
       ═══════════════════════════════════════════════════════════════════════ */
    --tint-brand-05: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.05);
    --tint-brand-10: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.10);
    --tint-brand-15: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.15);
    --tint-brand-25: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.25);
    --tint-success-10: hsla(160, 84%, 39%, 0.10);
    --tint-success-15: hsla(160, 84%, 39%, 0.15);
    --tint-danger-10: hsla(351, 89%, 60%, 0.10);
    --tint-danger-15: hsla(351, 89%, 60%, 0.15);

    /* ═══════════════════════════════════════════════════════════════════════
       COMPONENT SIZES
       ═══════════════════════════════════════════════════════════════════════ */
    --size-icon-sm: 1rem;
    --size-icon-md: 1.5rem;
    --size-icon-lg: 2rem;
    --size-icon-xl: 2.5rem;
    --size-icon-3xl: 3rem;
    --size-avatar-sm: 1.5rem;
    --size-avatar-md: 2rem;
    --size-avatar-lg: 2.5rem;
    --size-avatar-xl: 3rem;
    --size-avatar-2xl: 4rem;
    --size-avatar-3xl: 7.5rem;

    /* ═══════════════════════════════════════════════════════════════════════
       EXTENDED COLOR PALETTE - Blue scale (used by components)
       ═══════════════════════════════════════════════════════════════════════ */
    --blue-50: #eff6ff;
    --blue-100: #dbeafe;
    --blue-200: #bfdbfe;
    --blue-300: #93c5fd;
    --blue-400: #60a5fa;
    --blue-500: #3b82f6;
    --blue-600: #2563eb;
    --blue-700: #1d4ed8;

    --emerald-50: #ecfdf5;
    --emerald-100: #d1fae5;
    --emerald-500: #10b981;
    --emerald-600: #059669;

    --red-50: #fef2f2;
    --red-100: #fee2e2;
    --red-500: #ef4444;
    --red-600: #dc2626;

    --amber-100: #fef3c7;
    --amber-500: #f59e0b;

    --yellow-100: #fef9c3;

    /* Neutral alias */
    --neutral-50: var(--gray-50);

    /* Extended blue scale */
    --blue-800: #1e40af;

    /* ═══════════════════════════════════════════════════════════════════════
       Z-INDEX SCALE
       ═══════════════════════════════════════════════════════════════════════ */
    --z-base: 0;
    --z-behind: -1;
    --z-default: 1;
    --z-dropdown: 1000;
    --z-sticky: 1020;
    --z-fixed: 1030;
    --z-modal-backdrop: 1040;
    --z-modal: 1050;
    --z-offcanvas: 1060;
    --z-popover: 1070;
    --z-tooltip: 1080;
    --z-toast: 1090;
    --z-loader: 9999;

    /* ═══════════════════════════════════════════════════════════════════════
       🌞 LIGHT MODE THEME TOKENS
       ═══════════════════════════════════════════════════════════════════════ */
    --theme-bg: #F6F7F9;          /* canvas — cool-gray, sits BELOW white cards so panels float (mirrors dark: page #0F0F14 < card #1A1A21). Was #FFFFFF, which == card and read as one flat sheet. */
    --theme-bg-secondary: #F9FAFB;
    --theme-bg-tertiary: #F3F4F6;
    --theme-bg-elevated: #FFFFFF;
    --theme-bg-sunken: #F3F4F6;

    --theme-text: #111827;
    --theme-text-secondary: #4B5563;
    /* #6B7280 (gray-500) sat ON the AA boundary and tipped over depending on the
       surface — measured from rendered pixels: 4.83:1 on a white card, 4.51:1 on
       the canvas, 4.47:1 on a card, and 4.39-4.40:1 on bg-tertiary and a
       brand-tinted storefront. So the unit prices and department counts on
       /@demoshop were failing while the same colour passed on /market/wishlist by
       0.01 — invisible unless you measure the exact surface.
       #5F6675 gives 5.24-5.76:1 across all five, matching the 5.06-5.59 band the
       dark tertiary was corrected to in the same round, and still a clear step
       below secondary #4B5563 (6.87-7.56) so the hierarchy holds. */
    --theme-text-tertiary: #5F6675;
    --theme-text-inverted: #FFFFFF;

    --theme-border: #E5E7EB;
    --theme-border-light: #F3F4F6;
    --theme-border-strong: #D1D5DB;

    --theme-shadow: rgba(0, 0, 0, 0.08);
    --theme-card-bg: #FFFFFF;
    --theme-input-bg: #FFFFFF;
    /* Every one of this token's 13 consumers is a form control — inputs, selects,
     * date fields, search boxes, copyfields, input prefixes. Not one is a divider.
     * So it is a control boundary by definition and inherits the 3:1 that WCAG
     * 1.4.11 requires; #D1D5DB measured 1.47:1 against a white card.
     *
     * Aliased rather than replaced at 13 call sites: the sites are all correct
     * already, the VALUE was wrong. This also means anything written against
     * --theme-input-border in future is right by construction, which matters —
     * the .wm-* family, then .sf-input, then .auth-input were each fixed in turn
     * while the others kept the old value. Three rounds of the same bug. */
    --theme-input-border: var(--border-control);
    --theme-input-focus: #635BFF;
    --theme-hover: rgba(0, 0, 0, 0.04);
    --theme-active: rgba(0, 0, 0, 0.06);

    /* Selection */
    --theme-selection-bg: rgba(99, 91, 255, 0.15);
    --theme-selection-text: #111827;

    /* Scrollbar */
    --theme-scrollbar-track: #F3F4F6;
    --theme-scrollbar-thumb: #D1D5DB;
    --theme-scrollbar-thumb-hover: #9CA3AF;

    /* Auth brand panel — intentionally dark in both themes */
    --auth-brand-bg: #0b0d12;
    --auth-brand-text: #fff;
    --auth-brand-text-muted: rgba(255,255,255,0.62);
    --auth-brand-text-subtle: rgba(255,255,255,0.5);
    --auth-brand-dot: rgba(255,255,255,0.35);
}

/* ============================================================================
   🌙 DARK MODE - Rich, Immersive, Easy on Eyes
   Inspired by: Linear's dark mode + Discord's depth + Vercel's elegance
   ============================================================================ */

[data-theme="dark"],
.dark {
    color-scheme: dark;

    /* ═══════════════════════════════════════════════════════════════════════
       BRAND COLORS - Slightly brighter for dark backgrounds
       Override only the H/S/L channels — the alpha tints below use them.
       ═══════════════════════════════════════════════════════════════════════ */
    --brand-h: 232;
    --brand-s: 89%;
    --brand-l: 74%;
    /* Dark theme moves brand text the OTHER WAY. --brand-l-text was defined once
       (66%, darker) for the light theme and inherited here, which is backwards
       against a dark backdrop: it measured 4.19:1 on the darkest hero-gradient
       stop rgb(26,26,33) — under 4.5. Matching --brand-l gives 6.06. A single
       "text" lightness cannot serve both themes; it has to invert with them. */
    --brand-l-text: 74%;
    /* Fill moves the other way from text here — see --brand-l-fill above.
       At hsl(232 89% L) only 59–64% satisfies both floors at once: white on the
       fill needs >=4.5:1 (fails above 64%) and the fill itself needs >=3:1
       against the darkest card #1A1A21 so the button still reads as a shape
       (fails below 59%). 62% sits mid-band — 4.98:1 and 3.47:1. */
    --brand-l-fill: 62%;
    --brand-fill: hsl(var(--brand-h) var(--brand-s) var(--brand-l-fill));
    --brand-primary: hsl(var(--brand-h) var(--brand-s) var(--brand-l));
    --brand-primary-hover: #A5B4FC;
    --brand-primary-active: #C7D2FE;
    --brand-primary-light: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.15);
    --brand-primary-lighter: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.08);
    --brand-primary-border: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.3);
    --brand-primary-glow: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.2);

    /* B2B channels stay aliased to the brand in dark mode too. */
    --b2b-h: var(--brand-h);
    --b2b-s: var(--brand-s);
    --b2b-l: var(--brand-l);

    /* ═══════════════════════════════════════════════════════════════════════
       SEMANTIC COLORS - Adjusted for dark mode visibility
       ═══════════════════════════════════════════════════════════════════════ */

    /* Success - Brighter Emerald */
    --success: #34D399;
    --success-hover: #6EE7B7;
    --success-active: #A7F3D0;
    --success-light: rgba(52, 211, 153, 0.15);
    --success-lighter: rgba(52, 211, 153, 0.08);
    --success-border: rgba(52, 211, 153, 0.3);
    --success-text: #6EE7B7;

    /* Danger - Softer Rose */
    --danger: #FB7185;
    --danger-hover: #FDA4AF;
    --danger-active: #FECDD3;
    --danger-light: rgba(251, 113, 133, 0.15);
    --danger-lighter: rgba(251, 113, 133, 0.08);
    --danger-border: rgba(251, 113, 133, 0.3);
    --danger-text: #FDA4AF;

    /* Warning - Warm Gold */
    --warning: #FBBF24;
    --warning-hover: #FCD34D;
    --warning-active: #FDE68A;
    --warning-light: rgba(251, 191, 36, 0.15);
    --warning-lighter: rgba(251, 191, 36, 0.08);
    --warning-border: rgba(251, 191, 36, 0.3);
    --warning-text: #FCD34D;
    /* Dark mode inverts it: on a near-black card the light amber is already
       10.4:1, so the star keeps its brightness here. */
    --rating-star: #FBBF24;

    /* Info - Bright Blue */
    --info: #60A5FA;
    --info-hover: #93C5FD;
    --info-active: #BFDBFE;
    --info-light: rgba(96, 165, 250, 0.15);
    --info-lighter: rgba(96, 165, 250, 0.08);
    --info-border: rgba(96, 165, 250, 0.3);
    --info-text: #93C5FD;

    /* ═══════════════════════════════════════════════════════════════════════
       DARK NEUTRAL PALETTE - Rich, Layered Depth (Linear-inspired)
       Key: Multiple subtle gray layers create depth without being flat
       ═══════════════════════════════════════════════════════════════════════ */
    --gray-950: #0A0A0F;  /* Deepest - for overlays */
    --gray-900: #0F0F14;  /* Main background */
    --gray-850: #141419;  /* Elevated surfaces */
    --gray-800: #1A1A21;  /* Cards, sidebars */
    --gray-750: #21212A;  /* Hover states */
    --gray-700: #2A2A35;  /* Active states */
    --gray-600: #3D3D4A;  /* Borders */
    --gray-500: #52525E;  /* Muted text */
    --gray-400: #71717A;  /* Secondary text */
    --gray-300: #A1A1AA;  /* Primary text */
    --gray-200: #D4D4D8;  /* Headings */
    --gray-100: #E4E4E7;  /* Bright text */
    --gray-50: #FAFAFA;   /* White text */

    --neutral-50: var(--gray-50);

    /* ═══════════════════════════════════════════════════════════════════════
       ACCENT COLORS - Vibrant on dark
       ═══════════════════════════════════════════════════════════════════════ */
    --accent-purple: #A78BFA;
    --accent-pink: #F472B6;
    --accent-cyan: #22D3EE;
    --accent-orange: #FB923C;
    --accent-lime: #A3E635;

    /* ═══════════════════════════════════════════════════════════════════════
       SHADOWS - Two-part, deeper for dark mode
       ═══════════════════════════════════════════════════════════════════════ */
    --shadow-xs: 0 1px 1px 0 rgba(0, 0, 0, 0.20);
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.24), 0 1px 1px -1px rgba(0, 0, 0, 0.18);
    --shadow-md: 0 1px 3px 0 rgba(0, 0, 0, 0.28), 0 4px 8px -2px rgba(0, 0, 0, 0.22);
    --shadow-lg: 0 4px 8px -2px rgba(0, 0, 0, 0.30), 0 12px 24px -4px rgba(0, 0, 0, 0.30);
    --shadow-xl: 0 8px 16px -4px rgba(0, 0, 0, 0.32), 0 24px 48px -12px rgba(0, 0, 0, 0.40);
    --shadow-float-strong: 0 12px 24px -6px rgba(0, 0, 0, 0.36), 0 40px 80px -20px rgba(0, 0, 0, 0.55);
    --shadow-inner: inset 0 1px 2px 0 rgba(0, 0, 0, 0.30);

    /* Semantic elevation aliases (mirror light mode) */
    --shadow-card: var(--shadow-md);
    --shadow-popover: var(--shadow-lg);
    --shadow-modal: var(--shadow-xl);
    --shadow-floating: var(--shadow-float-strong);

    /* Subtle colored shadows for dark mode */
    --shadow-brand: 0 2px 10px rgba(129, 140, 248, 0.20);
    --shadow-success: 0 2px 10px rgba(52, 211, 153, 0.20);
    --shadow-danger: 0 2px 10px rgba(251, 113, 133, 0.20);

    /* ═══════════════════════════════════════════════════════════════════════
       GRADIENTS - Rich, vibrant for dark mode
       ═══════════════════════════════════════════════════════════════════════ */
    --gradient-brand: linear-gradient(135deg, #818CF8 0%, #A78BFA 100%);
    --gradient-brand-subtle: linear-gradient(135deg, rgba(129, 140, 248, 0.15) 0%, rgba(167, 139, 250, 0.15) 100%);
    --gradient-success: linear-gradient(135deg, #34D399 0%, #6EE7B7 100%);
    --gradient-danger: linear-gradient(135deg, #FB7185 0%, #FDA4AF 100%);
    --gradient-sunset: linear-gradient(135deg, #FB923C 0%, #F472B6 100%);
    --gradient-ocean: linear-gradient(135deg, #60A5FA 0%, #22D3EE 100%);
    --gradient-aurora: linear-gradient(135deg, #A78BFA 0%, #22D3EE 100%);

    /* Dark mesh gradient */
    --gradient-mesh-light: radial-gradient(at 40% 20%, rgba(129, 140, 248, 0.12) 0px, transparent 50%),
                           radial-gradient(at 80% 0%, rgba(167, 139, 250, 0.1) 0px, transparent 50%),
                           radial-gradient(at 0% 50%, rgba(96, 165, 250, 0.08) 0px, transparent 50%);

    /* ═══════════════════════════════════════════════════════════════════════
       🌙 DARK MODE THEME TOKENS
       ═══════════════════════════════════════════════════════════════════════ */
    --theme-bg: #0F0F14;
    --theme-bg-secondary: #141419;
    --theme-bg-tertiary: #1A1A21;
    --theme-bg-elevated: #26262F;   /* a real step ABOVE the card (#1A1A21) — raised overlays/menus + the active view-tab. Was == card (a dead token). */
    --theme-bg-sunken: #0A0A0F;

    --theme-text: #FAFAFA;
    --theme-text-secondary: #A1A1AA;
    /* #71717A (zinc-500) was 3.58:1 on cards — below WCAG AA 4.5:1 for normal
       text. #8A8A93 is 5.06:1 on card / 5.59:1 on canvas, still a clear step
       below secondary #A1A1AA so the hierarchy holds (mirrors the light-theme
       tertiary bump to #6B7280 from the r10 UX round). */
    --theme-text-tertiary: #8A8A93;
    --theme-text-inverted: #0F0F14;

    --theme-border: #2A2A35;
    --theme-border-light: #21212A;
    --theme-border-strong: #3D3D4A;

    /* Semantic border + tint overrides for dark mode */
    --border-divider: hsl(var(--brand-h) 8% 22%);
    --border-subtle: hsl(var(--brand-h) 8% 26%);
    --border-strong: hsl(var(--brand-h) 8% 32%);
    /* 3.26:1 against --theme-card-bg (#1A1A21) — the lightest surface a control
     * sits on, so the worst case in this theme. See the light-theme definition
     * for why this is not --border-strong. */
    --border-control: hsl(var(--brand-h) 8% 44%);
    --border-accent: hsl(var(--brand-h) var(--brand-s) var(--brand-l));
    --tint-brand-05: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.07);
    --tint-brand-10: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.12);
    --tint-brand-15: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.18);
    --tint-brand-25: hsl(var(--brand-h) var(--brand-s) var(--brand-l) / 0.30);

    --theme-shadow: rgba(0, 0, 0, 0.4);
    --theme-card-bg: #1A1A21;
    --theme-input-bg: #141419;
    /* 1.22:1 against --theme-card-bg before this — see the light-theme note. */
    --theme-input-border: var(--border-control);
    --theme-input-focus: #818CF8;
    --theme-hover: rgba(255, 255, 255, 0.04);
    --theme-active: rgba(255, 255, 255, 0.08);

    /* Selection */
    --theme-selection-bg: rgba(129, 140, 248, 0.3);
    --theme-selection-text: #FAFAFA;

    /* Scrollbar */
    --theme-scrollbar-track: #141419;
    --theme-scrollbar-thumb: #2A2A35;
    --theme-scrollbar-thumb-hover: #3D3D4A;

    /* Auth brand panel — same values as light (panel is always dark) */
    --auth-brand-bg: #0b0d12;
    --auth-brand-text: #fff;
    --auth-brand-text-muted: rgba(255,255,255,0.62);
    --auth-brand-text-subtle: rgba(255,255,255,0.5);
    --auth-brand-dot: rgba(255,255,255,0.35);
}

/* ============================================================================
   GLOBAL STYLES - Applied to both modes
   ============================================================================ */

/* Smooth color transitions when switching themes */
*,
*::before,
*::after {
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.15s ease;
}

/* Disable transitions for elements that shouldn't animate */
.no-transition,
.no-transition *,
[data-no-transition],
[data-no-transition] * {
    transition: none;
}

/* Custom scrollbar styling */
::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: var(--theme-scrollbar-track);
}

::-webkit-scrollbar-thumb {
    background: var(--theme-scrollbar-thumb);
    border-radius: var(--radius-full);
}

::-webkit-scrollbar-thumb:hover {
    background: var(--theme-scrollbar-thumb-hover);
}

/* Text selection */
::selection {
    background: var(--theme-selection-bg);
    color: var(--theme-selection-text);
}

/* Focus ring styling */
:focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
}

/* ─── Reduced motion (global) ──────────────────────────────────────────────
   Honor the OS "reduce motion" preference app-wide — WCAG 2.3.3 + baseline-ui
   "SHOULD respect prefers-reduced-motion". Loaded on every page via
   design-variables.css, so one rule covers all 42 motion-bearing stylesheets.
   Uses 0.01ms (not 0) so JS transitionend/animationend handlers still fire and
   nothing that waits on them breaks. Only activates for users who opted in. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ─── Forced colors / Windows High Contrast (global) ───────────────────────
   forced-colors strips custom backgrounds and box-shadow. Keep focus rings
   and surface edges visible with system colours so structure and keyboard
   affordances survive (WCAG 1.4.11 / 2.4.7). Minimal: borders + focus only. */
@media (forced-colors: active) {
    :focus-visible,
    .skip-to-content:focus,
    main#main-content:focus-visible {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }

    /* Hairline edges when shadow is forced off */
    .wm-card,
    .wm-card-bordered,
    .wm-card-elevated,
    .wm-index-surface,
    .wm-form-surface {
        border: 1px solid CanvasText;
    }

    .wm-btn-primary,
    .frm-btn-pri {
        border: 1px solid ButtonText;
    }
}

/* ─── Typography wrapping (global) ─────────────────────────────────────────
   baseline-ui: "MUST use text-balance for headings and text-pretty for body".
   Applied via cascade (one rule, every page) instead of editing every template.
   Pure progressive enhancement — browsers without text-wrap ignore it; balance
   self-limits to short blocks (headings) and pretty only fixes orphan lines. */
h1, h2, h3, .frm-title, .sm-title {
    text-wrap: balance;
}
p, .frm-subtitle, .sm-sub {
    text-wrap: pretty;
}

/* ─── Font smoothing (global) ──────────────────────────────────────────────
   make-interfaces-feel-better / baseline-ui: crisper text on macOS/WebKit.
   Already applied on the v2 page wrappers (.dash-v2/.frm-v2/…); promoting it to
   <body> makes the shell + every non-v2 page consistent instead of patchy. */
body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}


/* ── Progressive disclosure ────────────────────────────────────────────────
   Collapsible content — tab panels, accordion bodies, carousel slides — is
   hidden only when JavaScript is available to reopen it. `.js` is set on
   <html> by the render-blocking theme-toggle script, so this applies before
   first paint and there is no flash of expanded content.

   Without JS the rule never matches and every panel stays readable, which is
   what Alpine's x-show used to give us for free: the directive simply never
   ran. Hard-coding display:none in the markup would have hidden that content
   permanently for anyone whose JS failed to load. */
.js .js-collapsed {
    display: none;
}


/* Reveal motion for panels the components show/hide directly.

   These used to be Alpine `x-show` + `x-collapse`, which animated the open.
   x-collapse hooks x-show, and x-show cannot carry a per-item key under the
   CSP Alpine build, so the panels toggle `display` instead. This restores the
   sense of a reveal without reintroducing a directive: a short fade-and-rise
   on the frame the panel appears. Collapse stays instant, which is the half
   users notice least. */
@media (prefers-reduced-motion: no-preference) {
    .js [data-toggle-panel]:not(.js-collapsed),
    .js [data-tab-panel]:not(.js-collapsed) {
        animation: wm-panel-reveal 180ms ease-out;
    }
}

@keyframes wm-panel-reveal {
    from {
        opacity: 0;
        transform: translateY(-4px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}


/* ── Flash toasts ──────────────────────────────────────────────────────────
   Placement: the container is anchored top-4 for the desktop top-right stack.
   On a phone that lands on top of the sticky app bar (measured 61px on both
   the authenticated shell and the storefront header), so the first toast
   covered the logo and the menu button. Push it clear below on small screens;
   desktop is untouched. Marketing pages have no sticky bar and simply get a
   slightly lower toast, which is harmless. */
@media (max-width: 639px) {
    #wm-flash-toasts {
        top: calc(env(safe-area-inset-top, 0px) + 4.75rem);
    }
}

/* Severity: tint the hairline border to match the icon.

   Severity was carried by the icon alone, so if the icon font fails to load —
   blocked CDN, corporate proxy, offline first paint — a success and a failure
   render identically. The border already exists in the design; colouring it
   costs no new geometry and keeps the signal when the glyph is missing.

   A left accent rail would be the obvious move and is explicitly banned by the
   design system (see STRIPE_UI_TEARDOWN "no-border-left-rail rule"), so this
   tints the full hairline instead — which is the Linear convention anyway. */
#wm-flash-toasts [data-toast-severity='success'] {
    border-color: var(--success-border);
}
#wm-flash-toasts [data-toast-severity='warning'] {
    border-color: var(--warning-border);
}
#wm-flash-toasts [data-toast-severity='danger'],
#wm-flash-toasts [data-toast-severity='error'] {
    border-color: var(--danger-border);
}
#wm-flash-toasts [data-toast-severity='info'] {
    border-color: var(--info-border);
}


/* ── Touch target floor for standalone CTAs ────────────────────────────────
   The r10 audit set a 44px tap floor and .wm-icon-btn already honours it via
   a (pointer: coarse) rule. Auditing the same way on real data found three
   standalone controls still under it on touch: the dashboard quick actions
   (38px), the B2B onboarding CTAs (35px) and the skip link (43px). All are
   primary actions, not inline text links, so WCAG 2.5.8's inline exception
   does not cover them.

   Scoped to coarse pointers exactly like the existing rule, so desktop
   density is unchanged — only the hit box grows, and these are all
   inline-flex/centred so the label stays put. Selectors are qualified to
   match the component sheets' specificity. */
@media (pointer: coarse) {
    .dash-v2 .dv-qa .dv-qa-btn,
    .dash-v2 .dv-banner .dv-qa-btn,
    .dtl-v2 .dtl-btn-pri,
    .dtl-v2 .dtl-btn-sec,
    .skip-to-content {
        min-height: var(--min-touch-target, 44px);
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   Brand fill: route Tailwind's `bg-brand` at the fill lightness channel.

   The compiled utility resolves --brand-l at runtime:
     .bg-brand{background-color:hsl(var(--brand-h) var(--brand-s) var(--brand-l)
                                    /var(--tw-bg-opacity,1))}
   so re-pointing it needs no Tailwind rebuild — only a selector that outranks
   a bare class. `:root .bg-brand` is (0,2,0) vs (0,1,0), so it wins no matter
   which stylesheet loads first, which matters because the dist bundle and this
   file are linked independently.

   In the light theme --brand-l-fill == --brand-l, so this is a no-op there and
   nothing about the existing look changes. In dark it drops 74% → 66%, taking
   white-on-brand CTAs from 2.86:1 to 4.79:1. The alpha slot is preserved, so
   `bg-brand/10`-style tints (separate classes) are untouched, as are text and
   border brand utilities, which legitimately want the lighter 74%. */
:root .bg-brand {
    background-color: hsl(var(--brand-h) var(--brand-s) var(--brand-l-fill)
                          / var(--tw-bg-opacity, 1));
}


/* ─────────────────────────────────────────────────────────────────────────
   Section-nav active item: brand text on a brand tint.

   `.wm-section-nav-item-active` applies `bg-brand/10 text-brand
   dark:text-brand-light` from the compiled Tailwind layer. That pairs the FILL
   lightness with a 10% tint of itself: 4.05:1 in light and 4.19:1 in dark, both
   under AA for 14px text. Re-pointed at the text channel here rather than in
   the Tailwind source, which would need a rebuild — `:root` (0,2,0) outranks
   the bare utility class whichever sheet loads first, exactly as for .bg-brand.

   Dark needs a genuinely lighter value, not the text channel: the nav's active
   background is a light-blue tint, so --brand-primary-hover (#A5B4FC) is what
   clears it at 6.29:1. */
:root .wm-section-nav-item-active,
:root .wm-section-nav-item.active {
    color: var(--brand-text);
}

:root[data-theme="dark"] .wm-section-nav-item-active,
:root[data-theme="dark"] .wm-section-nav-item.active {
    color: var(--brand-primary-hover);
}


/* ─────────────────────────────────────────────────────────────────────────
   Brand as TEXT: route Tailwind's `text-brand` at the text lightness channel.

   The mirror image of the `.bg-brand` rule above. The compiled utility is

     .text-brand{color:hsl(var(--brand-h) var(--brand-s) var(--brand-l)
                           /var(--tw-text-opacity,1))}

   i.e. the FILL lightness used as text — the same defect that was fixed 145
   times in hand-written CSS, reached here through the utility layer instead.
   At light-theme 68% it measures 4.61:1 on pure white, which is why it looked
   fine, but the app's canvas is #F6F7F9 and its brand tints are darker still:

     text-brand on canvas #F6F7F9      4.30:1   (/docs/ "Contact Support")
     text-brand on brand tint #F7F7FF  4.33:1   (/social/* wm-btn-brand-soft)
     text-brand on #F9FAFB             4.42:1   (/business/welcome, .wm-text-action)

   --brand-l-text (65%) clears 4.5:1 against every surface the app paints:
   5.36 on white, 5.00 on the canvas, 4.87 on the darkest neutral #F3F4F6.

   Scoped to the light theme with :not([data-theme="dark"]), which matters more
   than it looks. In dark --brand-l-text IS --brand-l, so the declaration would
   compute the same value — but not the same CASCADE. Tailwind's darkMode is
   'class', so `dark:text-brand-light` compiles to `.dark .dark\:text-brand-light`
   at (0,2,0); `:root .text-brand` is also (0,2,0), and this file is linked
   AFTER dist/css/tailwind.css, so an unscoped rule would win on order and
   repaint every dark-mode brand link at the wrong lightness. The :not() keeps
   it out of dark entirely.

   The alpha slot is preserved, so `text-brand/N` variants keep working. The
   two @apply components that bake text-brand into their own class — and so are
   not reached by the utility selector — are listed alongside it. Deliberately
   NOT listed: .wm-progress-brand, the checkbox/radio accents and the other
   places `text-brand` supplies a FILL rather than text, which legitimately
   want the fill lightness. */
:root:not([data-theme="dark"]) .text-brand,
:root:not([data-theme="dark"]) .wm-btn-brand-soft,
:root:not([data-theme="dark"]) .wm-text-action,
:root:not([data-theme="dark"]) .wm-table-action-link {
    color: hsl(var(--brand-h) var(--brand-s) var(--brand-l-text)
               / var(--tw-text-opacity, 1));
}
