/* ============================================================================
   DESIGN TOKENS — the single source of truth for the product's visual language.
   ----------------------------------------------------------------------------
   Theme: "Glacier x Ink" (2026-07). Vanda's husky palette — white screens,
   ink type, cool premium (slate) greys, and one deep glacier-ice action
   colour lifted from a Siberian husky's coat and eyes. Colour is spent only
   where it means something: the tab bar, notification types, achievements,
   and status. The bright ice (#4fa3c7, --color-primary-glint) is the logo's
   eye and appears only as a sparing accent; large surfaces stay clean white.

   Every colour, radius, shadow, and duration in the app lives here. app.css and
   the Blade views reference these as var(--*) and MUST NOT contain hex literals;
   tests/Feature/DesignTokenIntegrityTest.php enforces that.

   To re-skin the entire product: replace the values in this file. Nothing else
   should need to change.

   Loaded before app.css — see app/Modules/Shared/Views/layout.blade.php.
   NOTE: --color-primary is duplicated as brand.theme_color in config/brand.php
   (HTML meta tags can't read CSS custom properties). Keep the two in sync.
   ============================================================================ */

:root {

    /* ── Brand / action — glacier (deep ice) ────────────────────────────────
       Vanda's husky palette. The action colour is a DEEP ice-blue, not the
       bright ice of the logo's eye: #4fa3c7 on white is only ~2.4:1 and fails
       AA for text/controls, so the primary is darkened to a petrol/glacier
       blue that clears 4.5:1 while still reading as cool husky-ice. The bright
       ice (#4fa3c7 / #8fd3f0) survives only as a light glint accent. */
    --color-primary:       #1b6a86;
    --color-primary-hover: #155a72;
    --color-primary-text:  #1b6a86;
    /* Ice tints, lifted HARD toward white so large surfaces read as clean white
       with a whisper of glacier — never as blue cards. These are deliberately
       close to #ffffff; only small elements (avatar disc, active tab) should
       show any colour, and even then faintly. */
    --color-primary-tint:  #eef5f9;   /* avatar bg, active Discover tab, achievements */
    --color-primary-tint2: #f7fbfd;   /* top-match & request cards, bell bg, chips */
    --color-primary-faint: #fbfdff;   /* unread rows, AI-feedback panel */
    --color-primary-border:#d7e7ef;
    --color-primary-track: #dbeaf1;   /* unfilled arc of the match ring */
    --color-primary-glint: #4fa3c7;   /* bright ice — the logo eye, sparing accents */

    /* Brand cover — the charcoal band + husky-ears mark on the profile. Kept as
       dedicated semantic tokens (NOT --color-ink, which flips light in dark
       mode) so the band stays a dark brand surface in both themes. */
    --color-brand-cover:      #15181c;   /* the band */
    --color-brand-cover-mark: #ffffff;   /* the ear strokes */

    /* ── Text ramp ──────────────────────────────────────────────────────────
       DELIBERATELY DARKER THAN THE HANDOFF. The design spec's greys fail WCAG
       AA on white at the sizes they're used (11-13px): muted was 3.83:1,
       muted-2 2.95:1, faint 2.14:1, faint-2 1.72:1 — all below the 4.5:1 floor
       for body text. Every step below is >= 4.5:1 except --color-faint-2, which
       is demoted to NON-TEXT use only (chevrons, decorative strokes) at >= 3:1.

       The ramp is compressed toward the dark end on purpose: white simply
       cannot support four distinguishable greys that all clear 4.5:1, so the
       hierarchy is carried by the darker steps rather than by fading out.
       Do not lighten these back toward the spec values.

       A cool (slate) hue is dialled into the greys — premium/technical on white,
       and in the same family as the glacier accent — without lightening any
       step: every contrast ratio below is preserved.                         */
    --color-ink:     #15181c;   /* headings, primary text          17.6:1 */
    --color-ink-2:   #333a42;   /* body copy                       11.4:1 */
    --color-muted:   #566068;   /* labels, section eyebrows         6.4:1 */
    --color-muted-2: #657079;   /* meta, timestamps, inactive nav   5.1:1 */
    --color-faint:   #717c85;   /* placeholders, disabled text     4.26:1 */
    /* ^ MEASURED 4.26:1 on white, not the 4.5:1 this comment used to claim.
         It is therefore below AA for body text and is reserved for genuine
         placeholder/disabled use, which WCAG 1.4.3 exempts. Anything
         informational — timestamps, status, meta — must use --color-muted-2. */
    --color-faint-2: #97a1aa;   /* NON-TEXT: chevrons, strokes      3.0:1 */

    /* ── Surfaces — white ───────────────────────────────────────────────────
       The greys below are NEUTRAL on purpose. The handoff specified them warm
       (hue ~45deg, 17-27% saturation), inherited from the postcard theme, and
       warm grey on pure white reads as aged paper rather than clear white —
       the surfaces were already #ffffff, it was the chips, borders and
       hairlines tinting the impression. They are also a step lighter than
       spec so less of the screen is grey at all. Keep them neutral. */
    --color-paper:        #ffffff;
    --color-surface:      #ffffff;
    --color-card:         #ffffff;
    --color-card-border:  #e9edf1;   /* cool premium hairline greys */
    --color-hairline:     #eaeef2;   /* row dividers, sticky-bar top border */
    --color-input-border: #dde3e9;   /* inputs, outline chips, secondary buttons */
    --color-chip-bg:      #f2f5f8;   /* inactive chips, settings tiles, composer */
    --color-chip-border:  #e6ebf0;
    --color-scrim:        rgba(26, 29, 27, .42);  /* dims the page behind a sheet */

    /* ── Clay — the "tutor's pen" accent (wax stamp, streak flame) ───────── */
    --color-clay:        #b46118;   /* darkened from #c2691a to clear 4.5:1 */
    --color-clay-hover:  #97500f;
    --color-clay-tint:   #fdeede;
    --color-clay-border: #f0d9c2;
    --color-clay-text:   #8f4c12;

    /* ── Illustration palette ───────────────────────────────────────────────
       Artwork colours for the inline mascot/logo SVGs. Separated from the UI
       tokens above because illustration is the first thing a rebrand replaces:
       swapping these restyles the character without touching any interface
       colour. Not subject to text-contrast rules — decorative, aria-hidden. */
    --illus-fur:      #566068;
    --illus-fur-soft: #d9a08e;
    --illus-eye:      #4fa3c7;
    --illus-ink:      #1b1d22;
    --illus-glint:    #f4f8fb;

    /* ── Status / feedback ──────────────────────────────────────────────── */
    --color-online:      #1b6a86;   /* online = glacier ice, not a separate green */
    --color-online-text: #1b6a86;
    --color-avatar-self: #eef5f9;

    /* ── Initial-avatar palette ─────────────────────────────────────────────
       Six pairs, picked from a learner's name, for when there is no photo.

       A single tint for everyone was tried and lost something worth having:
       with no photo and no colour, a list of learners is a column of identical
       discs, and the eye has nothing to catch on when scanning back to someone
       it has seen before. Colour here is doing recognition work, not decoration.

       Deliberately desaturated and close to white — these sit next to real
       photographs and must not shout over them. Every pair clears 4.5:1, so
       the initial is readable text, not a decorative smudge.

       Six, not twenty-six: enough that neighbours in a list rarely collide,
       few enough that the set still reads as one family. */
    --avatar-1-bg: #e4eff5;  --avatar-1-fg: #1b6a86;   /* glacier */
    --avatar-2-bg: #e4efe9;  --avatar-2-fg: #2b6a56;   /* pine   */
    --avatar-3-bg: #ece6f2;  --avatar-3-fg: #574379;   /* plum   */
    --avatar-4-bg: #f4e9dd;  --avatar-4-fg: #825227;   /* clay   */
    --avatar-5-bg: #f4e5e9;  --avatar-5-fg: #87394c;   /* rose   */
    --avatar-6-bg: #e7ebf0;  --avatar-6-fg: #3b4f63;   /* slate  */
    --color-danger:       #c0492f;   /* sign-out, error toast, unread dot */
    --color-danger-tint:  #fbece7;
    --color-danger-hover: #a13c25;

    /* Text and icons sitting ON a filled brand/danger/clay surface. Named for
       the role, not the colour, so a future theme can make it non-white. */
    --color-on-accent: #ffffff;

    /* Disabled controls. Exempt from the 4.5:1 rule by WCAG 1.4.3, but they
       still have to read as "off" rather than as a broken button. */
    --color-disabled-bg:   #ebebeb;
    --color-disabled-text: #696969;   /* 4.2:1 on the bg above — reads as "off"
                                         without becoming unreadable */

    /* Unfilled toggle track (the "off" position of a switch). */
    --color-toggle-track: #dcdcdc;

    /* Loading skeletons: base fill and the sheen that sweeps across it. */
    --color-skeleton-base:  #ededed;
    --color-skeleton-sheen: #f6f6f6;

    /* CEFR A1/A2 badge family. -text is the on-tint variant, so it is darkened
       enough to stay legible on --color-amber-tint. */
    --color-amber:        #9c671b;
    --color-amber-text:   #7d5214;
    --color-amber-tint:   #f9f0e3;
    --color-amber-border: #e4cbae;

    /* Email-verification banner — folded into the clay note family. */
    --color-warning-tint:   #fdeede;
    --color-warning-border: #f0d9c2;
    --color-warning-text:   #8f4c12;

    /* ── CEFR level badges ──────────────────────────────────────────────────
       Consumed by App\Support\CefrBadge, which emits var() references rather
       than hex so the badge palette re-skins with everything else. Every pair
       below clears 4.5:1 text-on-tint. */
    --cefr-beginner-text:       #7d5214;   /* A1, A2      6.0:1 */
    --cefr-beginner-bg:         #f9f0e3;
    --cefr-beginner-border:     #e4cbae;

    --cefr-intermediate-text:   #1b6a86;   /* B1          5.2:1 */
    --cefr-intermediate-bg:     #e6f1f6;
    --cefr-intermediate-border: #c3d9e4;

    --cefr-advanced-text:       #134f65;   /* B2, C1, C2  7.4:1 */
    --cefr-advanced-bg:         #daeaf1;
    --cefr-advanced-border:     #b3ccd8;

    --cefr-unrated-text:        #5d5d5d;   /* no level    5.9:1 */
    --cefr-unrated-bg:          #f6f6f6;
    --cefr-unrated-border:      #e8e8e8;

    /* ── Chat bubbles ───────────────────────────────────────────────────── */
    --color-bubble-out:      #1b6a86;  /* my message: glacier fill … */
    --color-bubble-out-text: #ffffff;  /* … white text (5.6:1) */
    --color-bubble-in:       #f1f4f7;  /* their message: cool grey, ink text */
    --color-bubble-ink:      #ffffff;  /* legacy alias for outgoing bubble text */

    /* ── Balanced bottom nav — each tab owns a hue ──────────────────────── */
    --color-nav-sessions: #2762ce;  --color-nav-sessions-tint: #e6effb;
    --color-nav-discover: #1b6a86;  --color-nav-discover-tint: #eef5f9;
    --color-nav-profile:  #7c3aed;  --color-nav-profile-tint:  #f3ecfb;

    /* ── Semantic accents (achievements + notification types) ───────────── */
    --acc-streak:   #b46118;  --acc-streak-tint:   #fdeede;  /* flame / streak */
    --acc-message:  #2762ce;  --acc-message-tint:  #e6effb;  /* message / first chat */
    --acc-partners: #7c3aed;  --acc-partners-tint: #f3ecfb;  /* partners milestone */
    --acc-success:  #1b6a86;  --acc-success-tint:  #eef5f9;  /* accepted / positive */
    /* Safety is PURPLE, not pine. The handoff README §5.9 says pine
       shield-check, but the prototype itself renders #7c3aed on #f3ecfb — and
       it has to, or "report reviewed" would be indistinguishable from
       "request accepted", which is also pine with a check. Prototype wins. */
    --acc-safety:   #7c3aed;  --acc-safety-tint:   #f3ecfb;  /* safety / shield */

    /* Legacy postcard callout tokens, remapped rather than removed so nothing
       breaks mid-migration. --color-stitch (the dashed postcard seam) is gone
       entirely: those borders are solid now and use card-border / hairline. */
    --color-callout-tint:   #f2f9fc;
    --color-callout-border: #cfe3ec;

    /* ── Typography ─────────────────────────────────────────────────────── */
    --font-sans:  'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif;
    --font-serif: 'Fraunces', Georgia, serif;

    /* ── Elevation ──────────────────────────────────────────────────────── */
    --shadow-card:       0 1px 2px rgba(22, 22, 21, .05);
    --shadow-card-hover: 0 8px 24px rgba(22, 22, 21, .10);
    --shadow-dropdown:   0 18px 40px rgba(0, 0, 0, .14);
    --shadow-toast:      0 14px 34px rgba(0, 0, 0, .18);
    --shadow-modal:      0 24px 60px rgba(0, 0, 0, .25);
    /* Slate-tinted lift under the level-check certificate. */
    --shadow-cert:       0 16px 40px rgba(43, 74, 82, .14);
    /* The focus ring is an accessibility affordance, so it gets a token rather
       than a literal — it has to change with the theme to stay visible. */
    --shadow-focus:      0 0 0 3px rgba(63, 111, 134, .20);
    /* Upward lift under a bottom sheet. Neutralised: the old value was a warm
       brown-grey left over from the retired postcard theme. */
    --shadow-sheet:      0 -8px 30px rgba(0, 0, 0, .14);

    /* ── Radii ──────────────────────────────────────────────────────────── */
    --radius-pill:    999px;
    --radius-card:    16px;   /* cards, request/session tiles */
    --radius-xl:      18px;   /* level-result frame, top-match wrap */
    --radius-inner:   14px;   /* quiz options, dropdown panels */
    --radius-nav:     14px;   /* nav pills */
    --radius-input:   12px;   /* text inputs */
    --radius-modal:   22px;
    --radius-tile:    11px;   /* icon tiles */
    --radius-tile-sm:  9px;   /* streak day squares */

    /* ── Spacing (4px base) ─────────────────────────────────────────────── */
    --space-1:  4px;  --space-2:  8px;  --space-3: 12px;  --space-4: 16px;
    --space-5: 20px;  --space-6: 24px;  --space-8: 32px;

    /* ── Motion ─────────────────────────────────────────────────────────── */
    --ease-standard: cubic-bezier(.2, .7, .3, 1);
    /* Absorbs the .1s / .12s / 120ms trio that used to be written by hand in 26
       separate rules. The largest change to any of them is 20ms, which is below
       what anyone can perceive — the point is that the value is now governed. */
    --dur-quick: .12s;  /* hover tint, border colour, background swap */
    --dur-fast: .15s;   /* toggle knob, chip select, tab swap */
    --dur-med:  .22s;   /* dropdown collapse, hover */

    --dur-slow: .28s;   /* sheet rise/fall, message entrance, progress fill */

    /* Press feedback. Deliberately asymmetric: going down should feel
       instantaneous, coming back up should feel like the control settling.
       Equal durations in both directions read as a mechanism, not a surface. */
    --dur-press:   .09s;
    --dur-release: .16s;

    /* Motion character for this product: critically damped, NO overshoot.
       --ease-standard is already a decelerate curve with no bounce, and every
       animation below uses it. Bounce was considered and deliberately rejected:
       these fire on screens people open dozens of times a day. */
    --stagger-step: 40ms;   /* gap between siblings in a list reveal */

    /* ── Layout ─────────────────────────────────────────────────────────── */
    --rail-width: 236px;
    /* The reading column every page's body is capped to. Anything that has to
       line up with that column on desktop reads it from here rather than
       repeating the number — the profile masthead is the first such thing. */
    --page-column: 960px;
}

/* ============================================================================
   DARK MODE — "Glacier Night". Same tokens, remapped: cool charcoal surfaces,
   light slate text, and the glacier ice BRIGHTENED so the accent finally glows
   (its whole point on dark). Only colour flips — radii, spacing, type, motion
   are shared with light above. Fills that carry white text (buttons, my-bubble)
   stay deep enough for AA; text/icons on the dark field use the brighter
   --color-primary-text.

   Applied via [data-theme="dark"] on <html>, set synchronously by the theme
   boot script in the layout <head>. That script resolves the user's stored
   preference (auto | light | dark) — "auto" follows the OS. One dark block, no
   duplication, and no flash because the attribute is set before first paint.
   ============================================================================ */
:root[data-theme="dark"] {

        /* Brand / action — glacier, brightened */
        --color-primary:       #1f7a99;   /* fill: white text 5.2:1 */
        --color-primary-hover: #248fb2;
        --color-primary-text:  #74c2e3;   /* text/icon on dark: 7.4:1 */
        --color-primary-tint:  #16242c;   /* avatar disc, active tab */
        --color-primary-tint2: #131d23;
        --color-primary-faint: #101a20;
        --color-primary-border:#2f4d5b;
        --color-primary-track: #263640;
        --color-primary-glint: #5cb6da;   /* the eye — glows on dark */

        /* Brand cover stays a dark band, lifted just off the page so it reads */
        /* Lifted well clear of --color-paper (#14181c). At #1d232a the band sat
           at 1.13:1 against the page — invisible — so the only thing anyone saw
           of the cover in dark mode was the 1px hairline tracing its corners,
           which reads as a stray line rather than the bottom edge of anything.
           #2f3843 puts it at ~1.5:1: present as a surface, still quiet. In
           light mode the band is near-black on white (17.8:1); the dark-mode
           equivalent of "darker than the page" is a lifted surface. */
        --color-brand-cover:      #2f3843;
        --color-brand-cover-mark: #eaf3f8;

        /* Text ramp — light on charcoal */
        --color-ink:     #eef2f6;
        --color-ink-2:   #d3dae1;
        --color-muted:   #a6b0b9;
        --color-muted-2: #939ea8;
        --color-faint:   #838e98;
        --color-faint-2: #6a747d;

        /* Surfaces — cool charcoal, white base becomes near-black */
        --color-paper:        #14181c;
        --color-surface:      #14181c;
        --color-card:         #191e23;
        --color-card-border:  #2a3138;
        --color-hairline:     #242a30;
        --color-input-border: #333b43;
        --color-chip-bg:      #1f252b;
        --color-chip-border:  #2c333a;
        --color-scrim:        rgba(0, 0, 0, .58);  /* deeper: the page behind is already dark */

        /* Clay accent — brightened */
        --color-clay:        #d98a3f;
        --color-clay-hover:  #e59a52;
        --color-clay-tint:   #2a1c10;
        --color-clay-border: #45301b;
        --color-clay-text:   #e2a161;

        /* Illustration */
        --illus-fur:      #8b98a0;
        --illus-fur-soft: #d9a08e;
        --illus-eye:      #5cb6da;
        --illus-ink:      #cfd7de;
        --illus-glint:    #1a1f24;

        /* Status / feedback */
        --color-online:      #4fa3c7;
        --color-online-text: #74c2e3;
        --color-avatar-self: #16242c;

        /* Same six hues, inverted: a deep disc with a light initial. The tints
           above would glow against a dark thread, and the dark inks would
           vanish into it. */
        --avatar-1-bg: #16242c;  --avatar-1-fg: #93cbe0;
        --avatar-2-bg: #17271f;  --avatar-2-fg: #93ccb6;
        --avatar-3-bg: #211b2c;  --avatar-3-fg: #bfaeda;
        --avatar-4-bg: #2b2119;  --avatar-4-fg: #dbb586;
        --avatar-5-bg: #2b1d21;  --avatar-5-fg: #dba7b3;
        --avatar-6-bg: #1d2227;  --avatar-6-fg: #adbfcf;
        --color-danger:       #e5765c;
        --color-danger-tint:  #2a1712;
        --color-danger-hover: #ef8a72;
        --color-on-accent:    #ffffff;

        --color-disabled-bg:   #21272d;
        --color-disabled-text: #7c8790;
        --color-toggle-track:  #333b43;
        --color-skeleton-base:  #1f252b;
        --color-skeleton-sheen: #2a3138;

        /* Amber / warning */
        --color-amber:        #d9a441;
        --color-amber-text:   #e6b866;
        --color-amber-tint:   #2a2010;
        --color-amber-border: #453515;
        --color-warning-tint:   #2a1c10;
        --color-warning-border: #45301b;
        --color-warning-text:   #e2a161;

        /* CEFR badges */
        --cefr-beginner-text:       #e6b866;
        --cefr-beginner-bg:         #2a2010;
        --cefr-beginner-border:     #453515;
        --cefr-intermediate-text:   #74c2e3;
        --cefr-intermediate-bg:     #16242c;
        --cefr-intermediate-border: #2f4d5b;
        --cefr-advanced-text:       #8fd0e8;
        --cefr-advanced-bg:         #132028;
        --cefr-advanced-border:     #294250;
        --cefr-unrated-text:        #a6b0b9;
        --cefr-unrated-bg:          #1f252b;
        --cefr-unrated-border:      #2c333a;

        /* Chat bubbles */
        --color-bubble-out:      #1f7a99;
        --color-bubble-out-text: #ffffff;
        --color-bubble-in:       #232a31;
        --color-bubble-ink:      #ffffff;

        /* Bottom nav — each tab brightened, dark tints */
        --color-nav-sessions: #6f9be8;  --color-nav-sessions-tint: #172234;
        --color-nav-discover: #5cb6da;  --color-nav-discover-tint: #16242c;
        --color-nav-profile:  #b191f0;  --color-nav-profile-tint:  #211a34;

        /* Semantic accents */
        --acc-streak:   #d98a3f;  --acc-streak-tint:   #2a1c10;
        --acc-message:  #6f9be8;  --acc-message-tint:  #172234;
        --acc-partners: #b191f0;  --acc-partners-tint: #211a34;
        --acc-success:  #4fa3c7;  --acc-success-tint:  #16242c;
        --acc-safety:   #b191f0;  --acc-safety-tint:   #211a34;

        --color-callout-tint:   #131d23;
        --color-callout-border: #2f4d5b;

        /* Shadows read as depth against dark — deepen the black */
        --shadow-card:       0 1px 2px rgba(0, 0, 0, .40);
        --shadow-card-hover: 0 8px 24px rgba(0, 0, 0, .55);
        --shadow-dropdown:   0 18px 40px rgba(0, 0, 0, .60);
        --shadow-toast:      0 14px 34px rgba(0, 0, 0, .62);
        --shadow-modal:      0 24px 60px rgba(0, 0, 0, .70);
        --shadow-cert:       0 16px 40px rgba(0, 0, 0, .55);
        --shadow-sheet:      0 -8px 30px rgba(0, 0, 0, .55);
        /* Lifted to the bright ice at a higher alpha: the light-mode ring is a
           deep blue that all but disappears against charcoal. */
        --shadow-focus:      0 0 0 3px rgba(116, 194, 227, .32);
}

/* Typing indicator — three bouncing dots in an incoming chat bubble. */
@keyframes tdot {
    0%, 60%, 100% { opacity: .3; transform: translateY(0); }
    30%           { opacity:  1; transform: translateY(-2px); }
}

@media (prefers-reduced-motion: reduce) {
    /* Motion in this product is functional, never decorative, so reduced-motion
       users still get the state change — just without the movement. */
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}
