/* ==========================================================================
   KozerJob — Design System
   Built to the KozerJob Brand Guidelines v1 (August 2026).

   DESIGN INTENT
   The people using the candidate side of this product are outdoors, on cheap
   Android phones, in strong Mauritian sunlight, often with one hand free. So
   this system optimises for legibility over decoration: high contrast, large
   type, generous tap targets, and no glass or blur effects on the surfaces
   that carry essential text.

   The recruiter and employer side is the opposite problem — dense tabular
   information that needs hierarchy — so it gets a tighter scale, a real data
   table, and a persistent shell.

   Three colours carry the brand: Ink for text and structure, Lagoon Teal for
   links/CTAs/tags, and Mango Gold reserved for small accents — the logo mark
   and icon tiles — never a button, a link, or a large field. White is the
   ground almost everywhere; Warm Sand is reserved for card surfaces.

   STRUCTURE
     1. Tokens          — colour, type, space, radius, elevation, motion
     2. Reset and base
     3. Layout
     4. Components
     5. Utilities
     6. Motion and accessibility preferences
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
    /* --- Palette: Sand (neutrals — white ground, Warm Sand cards, Ink text)
       One ramp spans the brand kit's three neutral references: sand-0 is the
       page ground (white), sand-50 is Warm Sand (#F7F6F3, card surfaces),
       sand-600 is Slate Gray (#6B6B70, secondary text) and sand-950 is Ink
       (#1B1B1F, headline/body text and the "Kozer" half of the wordmark). The
       light steps lean warm (matching Warm Sand's hue); the dark steps lean
       toward Ink's slightly cool cast, exactly as the two brand anchors do. */
    --sand-0:   #ffffff;
    --sand-25:  #fdfdfc;
    --sand-50:  #f7f6f3;
    --sand-100: #efeeea;
    --sand-200: #e2e0d9;
    --sand-300: #c9c7be;
    --sand-400: #a3a099;
    --sand-500: #86837c;
    --sand-600: #6b6b70;
    --sand-700: #4f4e53;
    --sand-800: #37363a;
    --sand-900: #232226;
    --sand-950: #1b1b1f;

    /* --- Palette: Teal (Lagoon Teal — links, CTAs, tags) ------------------
       #00B4A6 is the brand's literal swatch, kept at teal-400 for dark-mode
       text/accent (it measures 6.6:1 against Ink there) and for decorative,
       non-text use in light mode (hero glow, card accent stripe). Small text
       and filled buttons in LIGHT mode use teal-600 instead: #00B4A6 itself
       only reaches 2.6:1 against white, well under the 4.5:1 WCAG AA floor
       this file holds everything else to (see the --text-muted note below);
       teal-600 reaches 5.2:1 while still reading unmistakably as the brand
       teal. */
    --teal-50:  #e6faf8;
    --teal-100: #b8f0ea;
    --teal-200: #7fe0d6;
    --teal-300: #33cbbd;
    --teal-400: #00b4a6;
    --teal-500: #009e92;
    --teal-600: #007a71;
    --teal-700: #00665e;
    --teal-800: #044d47;
    --teal-900: #0a3d38;

    /* --- Palette: Gold (Mango Gold — small accents only, never a large
       field, never a button or text colour) --------------------------------
       Used for the logo mark and small icon-tile fills only. */
    --gold-400: #f7c14d;
    --gold-500: #f2a900;
    --gold-600: #cf8f00;

    /* --- Palette: Status -------------------------------------------------
       Each has a text-safe and a surface variant so a badge never relies on
       colour alone at a contrast that fails against its own background. */
    --success-surface: #e3f5ed;
    --success-border:  #a6dcc6;
    --success-text:    #0d6b48;
    --success-solid:   #14805a;

    --warning-surface: #fdf1dc;
    --warning-border:  #f0cf94;
    --warning-text:    #8a5209;
    --warning-solid:   #b45309;

    --danger-surface:  #fdeae9;
    --danger-border:   #f3b7b3;
    --danger-text:     #9c2822;
    --danger-solid:    #c0322b;

    --info-surface:    #e7f1f9;
    --info-border:     #b3d3ea;
    --info-text:       #1d4d7a;
    --info-solid:      #2563a3;

    /* --- Semantic surfaces (light theme is the default) -------------------
       White is the ground almost everywhere (--bg-page); Warm Sand is
       reserved for card surfaces (--bg-surface), per the brand kit. */
    --bg-page:     var(--sand-0);
    --bg-surface:  var(--sand-50);
    --bg-raised:   var(--sand-0);
    --bg-sunken:   var(--sand-100);
    --bg-inverse:  var(--sand-950);
    --bg-field:    var(--sand-0);
    --bg-hover:    var(--sand-100);

    --text-strong:  var(--sand-950);
    --text-default: var(--sand-700);
    /* sand-600, not a lighter step. Measured against the darkest surface
       muted text ever sits on (--bg-sunken), sand-600 (Slate Gray, the brand
       kit's own secondary-text colour) measures 4.9:1 there and 5.3:1 on
       white — clearing the 4.5:1 WCAG 2.1 AA floor for body text while still
       reading as clearly secondary. */
    --text-muted:   var(--sand-600);
    --text-inverse: var(--sand-0);
    --text-link:    var(--teal-600);

    --border-subtle: var(--sand-200);
    --border-default: var(--sand-300);
    --border-strong: var(--sand-400);

    --accent:        var(--teal-600);
    --accent-hover:  var(--teal-700);
    --accent-text:   #ffffff;
    --accent-subtle: var(--teal-50);

    /* Ink — the "structural fill" used by brand-mark, secondary buttons, the
       hero icon tile, chat's own-message bubble and similar tiles. Paired
       with --brand-text (not a hardcoded white) so it can invert cleanly in
       dark mode, where a near-black fill would vanish into the page. */
    --brand:         var(--sand-950);
    --brand-hover:   var(--sand-800);
    --brand-text:    #ffffff;

    --focus-ring: var(--teal-600);

    /* --- Type --------------------------------------------------------------
       Poppins (headlines, subheads, body) and IBM Plex Mono (labels, meta,
       data) per the brand kit, self-hosted as subsetted woff2 under this
       origin — see the @font-face block below. That keeps every font request
       same-origin, satisfying the existing font-src 'self' CSP without
       loosening it, and avoids the extra-DNS-hop cost a third-party font host
       would add on the slow connections this product targets. The system
       stack stays as the fallback chain, not removed, so text still renders
       correctly for the one paint before the woff2 arrives. */
    --font-sans: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
                 'Helvetica Neue', 'Noto Sans', Arial, sans-serif;
    --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

    /* Fluid scale. Candidate-facing text sits at the larger end on purpose. */
    --text-2xs: 0.6875rem;   /* 11px — table meta only */
    --text-xs:  0.75rem;     /* 12px */
    --text-sm:  0.8125rem;   /* 13px */
    --text-base: 0.9375rem;  /* 15px */
    --text-md:  1rem;        /* 16px — body on candidate pages */
    --text-lg:  clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
    --text-xl:  clamp(1.1875rem, 1.1rem + 0.5vw, 1.375rem);
    --text-2xl: clamp(1.375rem, 1.25rem + 0.8vw, 1.75rem);
    --text-3xl: clamp(1.625rem, 1.4rem + 1.4vw, 2.25rem);
    --text-4xl: clamp(2rem, 1.6rem + 2.2vw, 3rem);

    --leading-tight: 1.18;
    --leading-snug:  1.35;
    --leading-normal: 1.55;
    --leading-relaxed: 1.7;

    --tracking-tight: -0.02em;
    --tracking-normal: 0;
    --tracking-wide: 0.04em;

    /* --- Space (4px base) ------------------------------------------------ */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-10: 2.5rem;
    --space-12: 3rem;
    --space-16: 4rem;
    --space-20: 5rem;

    /* --- Radius ---------------------------------------------------------- */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 14px;
    --radius-xl: 20px;
    --radius-full: 9999px;

    /* --- Elevation -------------------------------------------------------
       Two-layer shadows: a tight contact shadow plus a soft ambient one. */
    --shadow-xs: 0 1px 2px rgb(16 20 26 / 0.06);
    --shadow-sm: 0 1px 2px rgb(16 20 26 / 0.06), 0 2px 6px rgb(16 20 26 / 0.05);
    --shadow-md: 0 2px 4px rgb(16 20 26 / 0.06), 0 6px 16px rgb(16 20 26 / 0.08);
    --shadow-lg: 0 4px 8px rgb(16 20 26 / 0.07), 0 16px 32px rgb(16 20 26 / 0.10);
    --shadow-focus: 0 0 0 3px rgb(0 122 113 / 0.35);

    /* Decorative glow behind the landing hero. Deliberately faint — this is
       ambience, not a graphic element anyone needs to resolve. */
    --hero-glow: radial-gradient(circle, rgb(0 180 166 / 0.16) 0%, transparent 70%);

    /* --- Motion ---------------------------------------------------------- */
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --duration-fast: 120ms;
    --duration-base: 200ms;
    --duration-slow: 320ms;

    /* --- Layout ----------------------------------------------------------- */
    --container-narrow: 34rem;
    --container-base: 46rem;
    --container-wide: 72rem;
    --container-full: 90rem;
    --sidebar-width: 15rem;
    --appbar-height: 3.75rem;

    --z-base: 1;
    --z-sticky: 100;
    --z-appbar: 200;
    --z-drawer: 300;
    --z-overlay: 400;
    --z-toast: 500;

    color-scheme: light dark;
}

/* --- Dark theme ----------------------------------------------------------
   Applied from the OS preference, and overridable with data-theme on <html>
   so an explicit user choice always wins. */

@media (prefers-color-scheme: dark) {
    :root:not([data-theme='light']) {
        --bg-page:    #141317;
        --bg-surface: #1c1b20;
        --bg-raised:  #232228;
        --bg-sunken:  #100f13;
        --bg-inverse: var(--sand-950);
        --bg-field:   #100f13;
        --bg-hover:   #29282e;

        --text-strong:  #f5f4f1;
        --text-default: #d3d1cb;
        --text-muted:   #9d9b9f;
        --text-link:    var(--teal-400);

        --border-subtle: #29282e;
        --border-default: #37363c;
        --border-strong: #4c4b52;

        --accent:       var(--teal-400);
        --accent-hover: var(--teal-300);
        --accent-text:  #06201d;
        --accent-subtle: #0f2b28;

        /* Ink can't be the "structural fill" once the page itself is
           near-black — a near-black tile would vanish. It lightens to a
           sand tint here instead, with --brand-text flipping to Ink so the
           label text on it stays readable. */
        --brand:       var(--sand-100);
        --brand-hover: var(--sand-200);
        --brand-text:  var(--sand-950);

        --focus-ring: var(--teal-400);

        --success-surface: #11291f; --success-border: #1f5942; --success-text: #6ee7b7;
        --warning-surface: #2c1f0c; --warning-border: #6b4a13; --warning-text: #fcd34d;
        --danger-surface:  #2c1413; --danger-border:  #6d2723; --danger-text:  #fca5a1;
        --info-surface:    #10222f; --info-border:    #1f4a6b; --info-text:    #93c5e8;

        --shadow-xs: 0 1px 2px rgb(0 0 0 / 0.4);
        --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4), 0 2px 6px rgb(0 0 0 / 0.3);
        --shadow-md: 0 2px 4px rgb(0 0 0 / 0.4), 0 6px 16px rgb(0 0 0 / 0.35);
        --shadow-lg: 0 4px 8px rgb(0 0 0 / 0.45), 0 16px 32px rgb(0 0 0 / 0.4);

        --hero-glow: radial-gradient(circle, rgb(0 180 166 / 0.22) 0%, transparent 70%);
    }
}

:root[data-theme='dark'] {
    --bg-page:    #141317;
    --bg-surface: #1c1b20;
    --bg-raised:  #232228;
    --bg-sunken:  #100f13;
    --bg-inverse: var(--sand-950);
    --bg-field:   #100f13;
    --bg-hover:   #29282e;

    --text-strong:  #f5f4f1;
    --text-default: #d3d1cb;
    --text-muted:   #9d9b9f;
    --text-link:    var(--teal-400);

    --border-subtle: #29282e;
    --border-default: #37363c;
    --border-strong: #4c4b52;

    --accent:       var(--teal-400);
    --accent-hover: var(--teal-300);
    --accent-text:  #06201d;
    --accent-subtle: #0f2b28;

    --brand:       var(--sand-100);
    --brand-hover: var(--sand-200);
    --brand-text:  var(--sand-950);
    --focus-ring: var(--teal-400);

    --success-surface: #11291f; --success-border: #1f5942; --success-text: #6ee7b7;
    --warning-surface: #2c1f0c; --warning-border: #6b4a13; --warning-text: #fcd34d;
    --danger-surface:  #2c1413; --danger-border:  #6d2723; --danger-text:  #fca5a1;
    --info-surface:    #10222f; --info-border:    #1f4a6b; --info-text:    #93c5e8;

    --hero-glow: radial-gradient(circle, rgb(0 180 166 / 0.22) 0%, transparent 70%);
}

/* --- Fonts -----------------------------------------------------------------
   Self-hosted, subsetted to Latin + Latin Extended (covers Kreol and French
   accents), so every request stays same-origin under the existing font-src
   'self' CSP. Two weights (Poppins Regular and ExtraBold) are preloaded from
   <head> on every page — see js/theme.js's neighbouring <link> tags — since
   those cover the wordmark, headlines and body copy on first paint. */
@font-face {
    font-family: 'Poppins';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/assets/fonts/poppins-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Poppins';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/assets/fonts/poppins-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Poppins';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/assets/fonts/poppins-600-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Poppins';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/assets/fonts/poppins-600-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Poppins';
    font-style: normal;
    font-weight: 800;
    font-display: swap;
    src: url('/assets/fonts/poppins-800-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Poppins';
    font-style: normal;
    font-weight: 800;
    font-display: swap;
    src: url('/assets/fonts/poppins-800-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/assets/fonts/ibm-plex-mono-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/assets/fonts/ibm-plex-mono-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/assets/fonts/ibm-plex-mono-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/assets/fonts/ibm-plex-mono-500-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ==========================================================================
   2. RESET AND BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
    -webkit-text-size-adjust: 100%;
    -moz-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Anchors and focus targets clear the sticky app bar. */
    scroll-padding-top: calc(var(--appbar-height) + var(--space-4));
}

body {
    margin: 0;
    min-height: 100svh;
    font-family: var(--font-sans);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    color: var(--text-default);
    background-color: var(--bg-page);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    /* Nothing in this app scrolls sideways; a stray wide element should be
       contained rather than shifting the whole page on a phone. */
    overflow-x: hidden;
}

img, svg, video, canvas, audio, iframe, embed, object {
    display: block;
    max-width: 100%;
}
img, video { height: auto; }

input, button, textarea, select { font: inherit; color: inherit; }

/* Poppins ExtraBold for h1 (the brand kit's headline weight), SemiBold for
   the rest — matching "Headlines & wordmark" vs "Subheads" in the type
   system. */
h1, h2, h3, h4, h5, h6 {
    color: var(--text-strong);
    font-weight: 600;
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-tight);
    text-wrap: balance;
}

h1 { font-size: var(--text-3xl); font-weight: 800; }
h2 { font-size: var(--text-2xl); font-weight: 700; }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }
h5, h6 { font-size: var(--text-md); }

p { text-wrap: pretty; }

a {
    color: var(--text-link);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}
a:hover { color: var(--accent-hover); }

strong, b { font-weight: 600; color: var(--text-strong); }

hr {
    border: 0;
    border-top: 1px solid var(--border-subtle);
    margin-block: var(--space-6);
}

:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}
/* Only suppress the ring for pointer users; keyboard focus is never hidden. */
:focus:not(:focus-visible) { outline: none; }

::selection {
    background: var(--teal-100);
    color: var(--sand-950);
}

[hidden] { display: none !important; }

/* Visible only to assistive technology. */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: var(--z-toast);
    padding: var(--space-2) var(--space-4);
    background: var(--bg-surface);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    transform: translateY(-200%);
    transition: transform var(--duration-fast) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

/* ==========================================================================
   3. LAYOUT
   ========================================================================== */

.container {
    width: 100%;
    max-width: var(--container-base);
    margin-inline: auto;
    padding-inline: var(--space-4);
}
.container--narrow { max-width: var(--container-narrow); }
.container--wide   { max-width: var(--container-wide); }
.container--full   { max-width: var(--container-full); }

@media (min-width: 640px) {
    .container { padding-inline: var(--space-6); }
}

/* Vertically centred single-panel page (login, confirmation, landing). */
.page-centred {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100svh;
    padding-block: var(--space-8);
}

.stack       { display: flex; flex-direction: column; gap: var(--space-4); }
.stack--sm   { gap: var(--space-2); }
.stack--lg   { gap: var(--space-6); }
.stack--xl   { gap: var(--space-8); }

.row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.row--between { justify-content: space-between; }
.row--end     { justify-content: flex-end; }
.row--centre  { justify-content: center; }
.row--top     { align-items: flex-start; }
.row--tight   { gap: var(--space-2); }
.row--nowrap  { flex-wrap: nowrap; }

/* Auto-fitting grid: no breakpoint needed, columns collapse when they must. */
.grid {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
}
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr)); }
.grid--fixed-2 { grid-template-columns: 1fr; }

@media (min-width: 640px) {
    .grid--fixed-2 { grid-template-columns: 1fr 1fr; }
}

.section { padding-block: var(--space-10); }
.divider { height: 1px; background: var(--border-subtle); margin-block: var(--space-5); }

/* --- Application shell (employer and admin) ------------------------------ */

.app-bar {
    position: sticky;
    top: 0;
    z-index: var(--z-appbar);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    min-height: var(--appbar-height);
    padding: var(--space-2) var(--space-4);
    padding-top: max(var(--space-2), env(safe-area-inset-top));
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-subtle);
}

.app-bar__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    color: var(--text-strong);
    text-decoration: none;
    font-weight: 700;
    letter-spacing: var(--tracking-tight);
}

/* The logo mark itself (assets/logo.svg) is already gold-filled flat art —
   this just sizes it, no background tile needed. */
.brand-mark {
    display: block;
    width: 2rem;
    height: 2rem;
    flex-shrink: 0;
}

.console {
    display: grid;
    grid-template-columns: 1fr;
    min-height: 100svh;
}

@media (min-width: 1024px) {
    .console { grid-template-columns: var(--sidebar-width) 1fr; }
}

.console__sidebar {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    z-index: var(--z-drawer);
    width: min(var(--sidebar-width), 82vw);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4);
    background: var(--bg-inverse);
    color: var(--sand-300);
    transform: translateX(-102%);
    transition: transform var(--duration-base) var(--ease-out);
    overflow-y: auto;
    overscroll-behavior: contain;
}
.console__sidebar[data-open='true'] { transform: translateX(0); }

@media (min-width: 1024px) {
    .console__sidebar { position: sticky; top: 0; height: 100svh; transform: none; width: auto; }
}

.console__brand {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-2) var(--space-5);
    color: var(--sand-0);
    font-weight: 700;
    text-decoration: none;
    letter-spacing: var(--tracking-tight);
}

.console__nav { display: flex; flex-direction: column; gap: 2px; }

.console__link {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    min-height: 2.75rem;
    border-radius: var(--radius-md);
    /* .console__link--danger is a <button>, unlike its <a> siblings, so this
       needs an explicit reset — otherwise the UA default button chrome shows
       through as a grey box against the dark sidebar. */
    background: transparent;
    border: 0;
    width: 100%;
    color: var(--sand-300);
    font-size: var(--text-base);
    font-weight: 550;
    text-align: left;
    cursor: pointer;
    text-decoration: none;
    transition: background var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out);
}
.console__link:hover { background: rgb(255 255 255 / 0.08); color: var(--sand-0); }
.console__link[aria-current='page'] {
    background: rgb(255 255 255 / 0.14);
    color: var(--sand-0);
    box-shadow: inset 3px 0 0 var(--accent);
}
/* Fixed light-red tint rather than the theme-dependent --danger-text: this
   sidebar is always a dark surface (--bg-inverse doesn't flip with the page
   theme), so the sign-out link needs a colour that reads on dark regardless
   of which theme the rest of the page is in. */
.console__link--danger { color: #f7a8a0; margin-top: auto; }
.console__link--danger:hover { background: rgb(192 50 43 / 0.2); color: #fbc9c4; }

/* Sits between the nav and sign-out, so appearance is a persistent, easy-to-
   find setting rather than buried in a per-page corner. */
.console__utility {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    margin-top: var(--space-2);
    border-top: 1px solid rgb(255 255 255 / 0.08);
    border-bottom: 1px solid rgb(255 255 255 / 0.08);
}
.console__utility-label {
    font-size: var(--text-sm);
    font-weight: 550;
    color: var(--sand-300);
}
.console__utility .theme-toggle {
    background: rgb(255 255 255 / 0.06);
    border-color: rgb(255 255 255 / 0.12);
    color: var(--sand-300);
}
.console__utility .theme-toggle:hover { background: rgb(255 255 255 / 0.14); color: var(--sand-0); }

.console__icon { flex-shrink: 0; width: 1.25rem; text-align: center; }

.console__main {
    min-width: 0;
    padding: var(--space-5) var(--space-4) var(--space-16);
}
@media (min-width: 768px) {
    .console__main { padding: var(--space-8) var(--space-8) var(--space-16); }
}

.console__scrim {
    position: fixed;
    inset: 0;
    z-index: calc(var(--z-drawer) - 1);
    background: rgb(16 20 26 / 0.5);
    backdrop-filter: blur(2px);
}
@media (min-width: 1024px) { .console__scrim { display: none; } }

.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-6);
}
.page-head__title { font-size: var(--text-2xl); }
.page-head__sub { color: var(--text-muted); font-size: var(--text-base); margin-top: var(--space-1); }

/* ==========================================================================
   4. COMPONENTS
   ========================================================================== */

/* --- Button --------------------------------------------------------------
   Minimum height is 44px, the smallest reliably tappable target. The old
   buttons were 32-36px on mobile, which produces mis-taps on a phone held in
   one hand. */

.btn {
    --btn-bg: var(--bg-surface);
    --btn-fg: var(--text-strong);
    --btn-border: var(--border-default);

    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 2.75rem;
    padding: var(--space-3) var(--space-5);
    border: 1px solid var(--btn-border);
    border-radius: var(--radius-md);
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-size: var(--text-base);
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: background var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

.btn:hover:not(:disabled) { background: var(--bg-hover); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled='true'] { opacity: 0.5; cursor: not-allowed; }

.btn--primary {
    --btn-bg: var(--accent);
    --btn-fg: var(--accent-text);
    --btn-border: transparent;
    box-shadow: var(--shadow-sm);
}
.btn--primary:hover:not(:disabled) { --btn-bg: var(--accent-hover); }

.btn--brand {
    --btn-bg: var(--brand);
    --btn-fg: var(--brand-text);
    --btn-border: transparent;
}
.btn--brand:hover:not(:disabled) { --btn-bg: var(--brand-hover); }

.btn--secondary { --btn-bg: var(--bg-surface); --btn-fg: var(--text-strong); }

.btn--ghost {
    --btn-bg: transparent;
    --btn-fg: var(--text-default);
    --btn-border: transparent;
}
.btn--ghost:hover:not(:disabled) { --btn-bg: var(--bg-hover); }

.btn--danger {
    --btn-bg: var(--danger-solid);
    --btn-fg: #ffffff;
    --btn-border: transparent;
}
.btn--danger:hover:not(:disabled) { --btn-bg: var(--danger-text); }

.btn--danger-quiet {
    --btn-bg: transparent;
    --btn-fg: var(--danger-text);
    --btn-border: var(--danger-border);
}
.btn--danger-quiet:hover:not(:disabled) { --btn-bg: var(--danger-surface); }

.btn--success {
    --btn-bg: var(--success-solid);
    --btn-fg: #ffffff;
    --btn-border: transparent;
}
.btn--success:hover:not(:disabled) { --btn-bg: var(--success-text); }

.btn--sm { min-height: 2.25rem; padding: var(--space-2) var(--space-3); font-size: var(--text-sm); }
.btn--lg { min-height: 3.25rem; padding: var(--space-4) var(--space-6); font-size: var(--text-lg); }
.btn--block { display: flex; width: 100%; }

/* Loading state. The label is hidden rather than replaced so the button keeps
   its width and the layout does not jump. */
.btn[data-loading] { color: transparent !important; pointer-events: none; }
.btn[data-loading]::after {
    content: '';
    position: absolute;
    width: 1.125rem;
    height: 1.125rem;
    border: 2px solid currentColor;
    border-radius: 50%;
    border-top-color: transparent;
    color: var(--btn-fg);
    animation: kj-spin 0.7s linear infinite;
}

.btn-group { display: flex; flex-wrap: wrap; gap: var(--space-3); }
@media (max-width: 480px) {
    .btn-group--stack { flex-direction: column; }
    .btn-group--stack > .btn { width: 100%; }
}

/* --- Card ---------------------------------------------------------------- */

.card {
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    box-shadow: var(--shadow-xs);
}
.card--flush { padding: 0; overflow: hidden; }
.card--raised { box-shadow: var(--shadow-md); }
.card--accent { border-color: var(--accent); border-left-width: 3px; }
.card--quiet { background: var(--bg-sunken); box-shadow: none; }

@media (min-width: 640px) { .card { padding: var(--space-6); } }

.card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}
.card__title { font-size: var(--text-lg); }
.card__body { display: flex; flex-direction: column; gap: var(--space-4); }
.card__foot {
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border-subtle);
}

/* --- Forms --------------------------------------------------------------- */

.field { display: flex; flex-direction: column; gap: var(--space-2); }
.field + .field { margin-top: var(--space-4); }

.label {
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--text-strong);
}
.label__optional { font-weight: 400; color: var(--text-muted); font-size: var(--text-sm); }
.label__required { color: var(--danger-text); }

.input, .select, .textarea {
    width: 100%;
    min-height: 2.875rem;
    padding: var(--space-3);
    background: var(--bg-field);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    color: var(--text-strong);
    /* 16px minimum: iOS Safari zooms the viewport on focus for anything
       smaller, which then leaves the page scrolled sideways. */
    font-size: max(1rem, var(--text-md));
    transition: border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

.input::placeholder, .textarea::placeholder { color: var(--text-muted); opacity: 1; }

/* Compact variant for controls that sit inside a table cell, where the
   full-height field would blow the row out. */
.select--sm {
    min-height: 2.25rem;
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-sm);
}

.input:focus, .select:focus, .textarea:focus {
    outline: none;
    border-color: var(--focus-ring);
    box-shadow: var(--shadow-focus);
}

.input[aria-invalid='true'], .select[aria-invalid='true'], .textarea[aria-invalid='true'] {
    border-color: var(--danger-solid);
}

.textarea { min-height: 7rem; resize: vertical; line-height: var(--leading-normal); }

.select {
    appearance: none;
    padding-inline-end: var(--space-8);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%2355606e' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-3) center;
}

.hint { font-size: var(--text-sm); color: var(--text-muted); }

/* Inline validation and error messages. */
.notice {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-sunken);
    color: var(--text-default);
    font-size: var(--text-base);
}
.notice--error   { background: var(--danger-surface);  border-color: var(--danger-border);  color: var(--danger-text); }
.notice--success { background: var(--success-surface); border-color: var(--success-border); color: var(--success-text); }
.notice--warning { background: var(--warning-surface); border-color: var(--warning-border); color: var(--warning-text); }
.notice--info    { background: var(--info-surface);    border-color: var(--info-border);    color: var(--info-text); }

/* Large numeric entry for the SMS code. */
.otp-input {
    text-align: center;
    font-size: var(--text-3xl);
    font-weight: 700;
    letter-spacing: 0.4em;
    text-indent: 0.4em;
    font-variant-numeric: tabular-nums;
    padding-block: var(--space-4);
}

/* --- Badge --------------------------------------------------------------- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.1875rem var(--space-2);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    font-weight: 650;
    line-height: 1.4;
    white-space: nowrap;
}
.badge--neutral { background: var(--bg-sunken);       border-color: var(--border-subtle);  color: var(--text-default); }
.badge--success { background: var(--success-surface); border-color: var(--success-border); color: var(--success-text); }
.badge--warning { background: var(--warning-surface); border-color: var(--warning-border); color: var(--warning-text); }
.badge--danger  { background: var(--danger-surface);  border-color: var(--danger-border);  color: var(--danger-text); }
.badge--info    { background: var(--info-surface);    border-color: var(--info-border);    color: var(--info-text); }
.badge--accent  { background: var(--accent-subtle);   border-color: var(--teal-200);       color: var(--teal-700); }

/* --- Chip / filter ------------------------------------------------------- */

.chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2.25rem;
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-full);
    background: var(--bg-surface);
    color: var(--text-default);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: all var(--duration-fast) var(--ease-out);
}
.chip:hover { border-color: var(--border-strong); background: var(--bg-hover); }
.chip[aria-pressed='true'] {
    background: var(--brand);
    border-color: var(--brand);
    color: var(--brand-text);
}

.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* --- Quote card -----------------------------------------------------------
   A testimonial. Left border in the accent teal (echoes .card--accent) so a
   grid of these reads as one family from a glance. The quote mark sits in
   its own stacking layer behind the text — decorative, so aria-hidden. */

.quote {
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-lg);
    padding: var(--space-6) var(--space-5) var(--space-5);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    position: relative;
}

.quote__mark {
    position: absolute;
    top: var(--space-3);
    right: var(--space-4);
    font-family: var(--font-mono);
    font-size: 2.75rem;
    line-height: 1;
    color: var(--accent-subtle);
    user-select: none;
}

.quote__text {
    font-size: var(--text-base);
    line-height: 1.65;
    color: var(--text-default);
}

.quote__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border-subtle);
}

.quote__who { display: flex; flex-direction: column; gap: 0.125rem; }
.quote__name { font-weight: 650; font-size: var(--text-sm); color: var(--text-strong); }
.quote__meta { font-size: var(--text-xs); color: var(--text-muted); }

.quote__lang {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--accent);
    background: var(--accent-subtle);
    border-radius: var(--radius-sm);
    padding: 0.1875rem var(--space-2);
    flex-shrink: 0;
}

.quote-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    gap: var(--space-5);
}

/* --- Job card -------------------------------------------------------------
   A whole listing is one link, so the tap target is the card rather than a
   small "view" control — this board is used on a phone, often one-handed.
   Built on the same surface tokens as .card; the chevron mirrors .choice on
   the landing page so the two read as the same gesture. */

.job-card {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    box-shadow: var(--shadow-xs);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--duration-fast) var(--ease-out),
                background var(--duration-fast) var(--ease-out);
}
.job-card:hover {
    border-color: var(--accent);
    background: var(--bg-hover);
}
.job-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.job-card__main { flex: 1; min-width: 0; }
.job-card__role {
    font-size: var(--text-lg);
    font-weight: 650;
    color: var(--text-strong);
    margin-bottom: var(--space-1);
}
.job-card__meta { font-size: var(--text-sm); color: var(--text-muted); }
.job-card__pay {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--accent);
    margin-top: var(--space-1);
}
.job-card__chevron {
    flex-shrink: 0;
    font-size: var(--text-lg);
    color: var(--text-muted);
}
.job-card:hover .job-card__chevron { color: var(--accent); }

.job-list { display: flex; flex-direction: column; gap: var(--space-3); }

/* Filter bar: chips scroll sideways on a narrow screen rather than wrapping
   into a tall stack that pushes the listings below the fold. */
.job-filters {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding-bottom: var(--space-5);
    border-bottom: 1px solid var(--border-subtle);
}
.job-filters__chips {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    padding-bottom: var(--space-1);
    scrollbar-width: thin;
}
.job-filters__chips .chip { flex-shrink: 0; }

/* --- Theme toggle ---------------------------------------------------------
   A single icon button that flips between light and dark. `aria-pressed`
   carries both the accessible state and the visual one: no JS class toggling
   or innerHTML swap needed, the two icons are always in the DOM and CSS shows
   whichever matches the current state. */

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-full);
    background: var(--bg-surface);
    color: var(--text-default);
    cursor: pointer;
    transition: background var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}
.theme-toggle:hover { border-color: var(--border-strong); background: var(--bg-hover); color: var(--text-strong); }
.theme-toggle:active { transform: scale(0.92); }

.theme-toggle svg { width: 1.125rem; height: 1.125rem; }
.theme-toggle__moon { display: none; }
.theme-toggle[aria-pressed='true'] .theme-toggle__sun { display: none; }
.theme-toggle[aria-pressed='true'] .theme-toggle__moon { display: block; }

/* --- Utility bar -----------------------------------------------------------
   The header pattern shared by every candidate-facing page: a way back on
   the left, language and appearance controls grouped on the right. Replaces
   what used to be a bare, unstyled row of floating buttons. */

/* Public site header ------------------------------------------------------
   Used on the marketing/public pages (home, jobs, about, FAQ, contact, terms,
   privacy) so they read as one site rather than a set of standalone landing
   pages. The candidate *flow* pages — register, record, chat, upload-cv,
   profile — deliberately keep the leaner `.util-bar` below instead: someone
   mid-way through building a profile should not be offered five ways to
   navigate away from it.

   No hamburger. Four short labels fit a 375px screen, and the drawer would
   cost a focus trap, an escape handler and aria wiring for very little. On
   narrow screens the nav simply drops to its own row (order/flex-basis
   below) — no JavaScript involved, so it survives a failed script load. */
.site-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-bottom: var(--space-8);
}

.site-head__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 800;
    font-size: var(--text-lg);
    color: var(--text-strong);
    text-decoration: none;
    letter-spacing: -0.02em;
}
.site-head__brand:hover { color: var(--text-strong); }
.site-head__brand .brand-mark { width: 1.75rem; height: 1.75rem; }

.site-head__controls {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-inline-start: auto;
}

.site-nav {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    /* Own row on mobile, inline on desktop. */
    order: 3;
    flex-basis: 100%;
    overflow-x: auto;
    scrollbar-width: none;
    padding-block: var(--space-1);
}
.site-nav::-webkit-scrollbar { display: none; }

.site-nav a {
    color: var(--text-default);
    text-decoration: none;
    font-size: var(--text-sm);
    font-weight: 600;
    white-space: nowrap;
    padding-block: var(--space-1);
    border-bottom: 2px solid transparent;
}
.site-nav a:hover { color: var(--text-strong); }

/* The current page, marked with aria-current in the markup so the styling
   and the accessibility tree agree rather than being set independently. */
.site-nav a[aria-current='page'] {
    color: var(--text-strong);
    border-bottom-color: var(--accent);
}

@media (min-width: 640px) {
    .site-nav {
        order: 0;
        flex-basis: auto;
        margin-inline-start: var(--space-6);
    }
    .site-head__controls { margin-inline-start: auto; }
}

/* FAQ accordion. Built on native <details>/<summary> so it is keyboard
   operable, findable by the browser's own in-page search, and functional
   with scripting disabled — none of which a div-and-JS accordion gives you
   without deliberate work. */
.faq-item {
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-4) var(--space-5);
}

.faq-item > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    cursor: pointer;
    font-weight: 600;
    color: var(--text-strong);
    list-style: none;
    /* Comfortably past the 44px touch target minimum on a phone. */
    min-height: 1.75rem;
}
.faq-item > summary::-webkit-details-marker { display: none; }

.faq-item > summary::after {
    content: '+';
    flex-shrink: 0;
    font-size: var(--text-lg);
    font-weight: 400;
    color: var(--text-muted);
    line-height: 1;
}
.faq-item[open] > summary::after { content: '\2212'; }

.faq-item > p {
    margin-top: var(--space-3);
    font-size: var(--text-sm);
    color: var(--text-muted);
    line-height: var(--leading-normal);
}

.util-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-6);
}

.util-bar__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-default);
    font-size: var(--text-sm);
    font-weight: 600;
    text-decoration: none;
}
.util-bar__brand:hover { color: var(--text-strong); }

.util-bar__controls {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* For pages with nothing to put on the left (a bare sign-in screen, an error
   page) — the controls cluster alone, pinned right. */
.util-bar--end { justify-content: flex-end; }

/* Segmented control, used for the language switcher. */
.segmented {
    display: inline-flex;
    padding: 3px;
    gap: 2px;
    background: var(--bg-sunken);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-full);
}
.segmented__option {
    /* 36px. Not the 44px of a primary button — a segmented control that tall
       dominates a header — but comfortably above the 24px WCAG 2.5.8 floor,
       and the language switcher is a control this audience uses often. */
    min-height: 2.25rem;
    min-width: 2.75rem;
    padding: var(--space-1) var(--space-3);
    border: 0;
    border-radius: var(--radius-full);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: var(--tracking-wide);
    cursor: pointer;
    transition: all var(--duration-fast) var(--ease-out);
}
.segmented__option:hover { color: var(--text-strong); }
.segmented__option[aria-pressed='true'] {
    background: var(--bg-surface);
    color: var(--text-strong);
    box-shadow: var(--shadow-xs);
}

/* --- Data table ----------------------------------------------------------
   Below 900px each row becomes a stacked card, with the column name supplied
   from `data-label`. A nine-column table cannot be read on a phone, and
   horizontal scrolling hides the action buttons at the far right. */

.table-wrap {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-base);
}

.table th {
    padding: var(--space-3) var(--space-4);
    text-align: left;
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-muted);
    background: var(--bg-sunken);
    border-bottom: 1px solid var(--border-subtle);
    white-space: nowrap;
}
.table th:first-child { border-start-start-radius: var(--radius-md); }
.table th:last-child  { border-start-end-radius: var(--radius-md); }

.table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
    vertical-align: middle;
}

.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background var(--duration-fast) var(--ease-out); }
.table tbody tr:hover { background: var(--bg-hover); }

.table__primary { font-weight: 650; color: var(--text-strong); }
/* A cell whose primary text is itself the control that opens the row's
   detail. A real <button>, not a styled link, because it performs an action
   rather than navigating; the global :focus-visible rule supplies the ring. */
.table__link {
    font: inherit;
    font-weight: 650;
    color: var(--text-strong);
    background: none;
    border: 0;
    padding: 0;
    text-align: left;
    cursor: pointer;
}
.table__link:hover { text-decoration: underline; }
.table__meta { font-size: var(--text-sm); color: var(--text-muted); }
.table__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.table__empty { padding: var(--space-12) var(--space-4); text-align: center; color: var(--text-muted); }

@media (max-width: 900px) {
    .table--responsive thead { display: none; }
    .table--responsive, .table--responsive tbody, .table--responsive tr, .table--responsive td {
        display: block;
        width: 100%;
    }
    .table--responsive tr {
        margin-bottom: var(--space-3);
        border: 1px solid var(--border-subtle);
        border-radius: var(--radius-md);
        background: var(--bg-surface);
        padding: var(--space-2);
    }
    .table--responsive td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--space-4);
        padding: var(--space-2) var(--space-3);
        border-bottom: 1px solid var(--border-subtle);
        text-align: right;
    }
    .table--responsive td:last-child { border-bottom: 0; }
    .table--responsive td::before {
        content: attr(data-label);
        flex-shrink: 0;
        font-size: var(--text-xs);
        font-weight: 700;
        letter-spacing: var(--tracking-wide);
        text-transform: uppercase;
        color: var(--text-muted);
        text-align: left;
    }
    .table--responsive td:empty { display: none; }
    .table--responsive .table__actions { justify-content: flex-end; }
}

/* --- Statistic ----------------------------------------------------------- */

.stat {
    padding: var(--space-5);
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
}
.stat__value {
    font-size: var(--text-3xl);
    font-weight: 750;
    line-height: 1.1;
    color: var(--text-strong);
    letter-spacing: var(--tracking-tight);
    font-variant-numeric: tabular-nums;
}
.stat__label {
    margin-top: var(--space-1);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
}
.stat__value--warning { color: var(--warning-text); }
.stat__value--success { color: var(--success-text); }

/* Confidence / match score meter. Colour is paired with the number itself, so
   the meaning survives for someone who cannot distinguish the hues. */
.score {
    display: inline-flex;
    align-items: baseline;
    gap: 1px;
    padding: 0.125rem var(--space-2);
    border-radius: var(--radius-sm);
    font-weight: 700;
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
    background: var(--bg-sunken);
    color: var(--text-default);
}
.score--high { background: var(--success-surface); color: var(--success-text); }
.score--mid  { background: var(--warning-surface); color: var(--warning-text); }
.score--low  { background: var(--danger-surface);  color: var(--danger-text); }
.score__unit { font-size: var(--text-2xs); font-weight: 600; opacity: 0.75; }

/* --- Empty state --------------------------------------------------------- */

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-12) var(--space-4);
    text-align: center;
    color: var(--text-muted);
}
.empty__icon { font-size: 2rem; opacity: 0.6; }
.empty__title { font-size: var(--text-lg); color: var(--text-strong); }

/* --- Dialog --------------------------------------------------------------
   Uses the native <dialog> element: it gives focus trapping, Escape handling
   and inertness of the page behind for free, all of which the previous
   div-with-a-class overlay lacked. */

dialog.dialog {
    width: min(34rem, calc(100vw - 2rem));
    max-height: min(85svh, 48rem);
    /* The `* { margin: 0 }` reset above also strips the UA stylesheet's
       `margin: auto` on <dialog>, which is what centres a modal in its
       viewport — without this every dialog in the console opens pinned to the
       top-left corner. */
    margin: auto;
    padding: 0;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--bg-surface);
    color: var(--text-default);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}
dialog.dialog--wide { width: min(52rem, calc(100vw - 2rem)); }

dialog.dialog::backdrop {
    background: rgb(16 20 26 / 0.55);
    backdrop-filter: blur(2px);
}

.dialog__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-5);
    border-bottom: 1px solid var(--border-subtle);
}
.dialog__title { font-size: var(--text-lg); }
.dialog__sub { font-size: var(--text-sm); color: var(--text-muted); margin-top: var(--space-1); }
.dialog__body {
    padding: var(--space-5);
    overflow-y: auto;
    max-height: min(60svh, 34rem);
}
.dialog__foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--border-subtle);
    background: var(--bg-sunken);
}
.dialog__close {
    display: grid;
    place-items: center;
    width: 2rem; height: 2rem;
    flex-shrink: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-lg);
    cursor: pointer;
}
.dialog__close:hover { background: var(--bg-hover); color: var(--text-strong); }

@media (max-width: 480px) {
    .dialog__foot { flex-direction: column-reverse; }
    .dialog__foot > .btn { width: 100%; }
}

/* --- Toast --------------------------------------------------------------- */

.toast-stack {
    position: fixed;
    z-index: var(--z-toast);
    left: 50%;
    transform: translateX(-50%);
    bottom: max(var(--space-4), env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    width: min(28rem, calc(100vw - 2rem));
    pointer-events: none;
}
@media (min-width: 640px) {
    .toast-stack { left: auto; right: var(--space-6); transform: none; bottom: var(--space-6); }
}

.toast {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-surface);
    box-shadow: var(--shadow-lg);
    font-size: var(--text-base);
    pointer-events: auto;
    animation: kj-toast-in var(--duration-base) var(--ease-out);
}
.toast--leaving { animation: kj-toast-out var(--duration-base) var(--ease-in-out) forwards; }

.toast__icon {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 1.25rem; height: 1.25rem;
    border-radius: 50%;
    font-size: var(--text-xs);
    font-weight: 800;
    background: var(--info-surface);
    color: var(--info-text);
}
.toast--success { border-color: var(--success-border); }
.toast--success .toast__icon { background: var(--success-solid); color: #fff; }
.toast--error { border-color: var(--danger-border); }
.toast--error .toast__icon { background: var(--danger-solid); color: #fff; }
.toast__body { color: var(--text-strong); }

/* --- Progress and loading ------------------------------------------------ */

.progress {
    height: 0.5rem;
    border-radius: var(--radius-full);
    background: var(--bg-sunken);
    overflow: hidden;
}
.progress__bar {
    height: 100%;
    width: 0;
    border-radius: inherit;
    background: var(--accent);
    transition: width var(--duration-slow) var(--ease-out);
}
/* Width steps for admin.js's paintBars(): CSP's script-src being strict is
   the point, but style-src 'self' with no unsafe-inline means a per-render
   computed width can never be set via element.style either -- it isn't
   presentable as a static hash. Ten fixed steps, picked by rounding to the
   nearest 10%, keep the chart CSP-compliant with no exceptions. Precision
   loss is a non-issue here: this is a comparative frequency chart, and the
   exact count is already shown as text next to each bar. */
.progress__bar--0   { width: 0; }
.progress__bar--10  { width: 10%; }
.progress__bar--20  { width: 20%; }
.progress__bar--30  { width: 30%; }
.progress__bar--40  { width: 40%; }
.progress__bar--50  { width: 50%; }
.progress__bar--60  { width: 60%; }
.progress__bar--70  { width: 70%; }
.progress__bar--80  { width: 80%; }
.progress__bar--90  { width: 90%; }
.progress__bar--100 { width: 100%; }

/* --- Admin activity feed row ---------------------------------------------- */
/* Was an inline style object (a constant, not data-driven -- it never needed
   to be inline in the first place) in admin.js's paintActivity(). Moved here
   for the same style-src reason as the bars above. */
.activity-row {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--border-subtle);
}

/* --- Match reasons list ---------------------------------------------------- */
/* Same story: a constant indent in admin-jobs.js's match-reasons list. */
.reasons-list { padding-inline-start: 1.1rem; }

.spinner {
    display: inline-block;
    width: 1.5rem; height: 1.5rem;
    border: 2px solid var(--border-default);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: kj-spin 0.7s linear infinite;
}
.spinner--lg { width: 2.5rem; height: 2.5rem; border-width: 3px; }

.skeleton {
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--border-subtle) 37%, var(--bg-sunken) 63%);
    background-size: 400% 100%;
    animation: kj-shimmer 1.4s ease-in-out infinite;
}
.skeleton--text { height: 0.875rem; }
.skeleton--pill { height: 1.25rem; width: 4rem; border-radius: var(--radius-full); }

.loading-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    padding: var(--space-12) var(--space-4);
    text-align: center;
}

/* --- Steps --------------------------------------------------------------- */

.steps { display: flex; align-items: center; gap: var(--space-2); }
.steps__dot {
    flex: 1;
    height: 0.25rem;
    border-radius: var(--radius-full);
    background: var(--border-subtle);
    transition: background var(--duration-base) var(--ease-out);
}
.steps__dot[data-state='done']    { background: var(--success-solid); }
.steps__dot[data-state='current'] { background: var(--accent); }

.step-meta {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-3);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
}

.numbered {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
}
.numbered__index {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 1.75rem; height: 1.75rem;
    border-radius: 50%;
    background: var(--brand);
    color: var(--brand-text);
    font-size: var(--text-sm);
    font-weight: 700;
}

/* --- Prompt list (recording guidance) ------------------------------------ */

.prompt-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4);
    background: var(--bg-sunken);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    list-style: none;
}
.prompt-list__label {
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-muted);
}
.prompt-list li { display: flex; gap: var(--space-3); font-size: var(--text-base); }

/* --- Recorder ------------------------------------------------------------ */

.record-btn {
    display: grid;
    place-items: center;
    width: 7rem; height: 7rem;
    margin-inline: auto;
    border: 0;
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-text);
    font-size: 2.5rem;
    cursor: pointer;
    box-shadow: var(--shadow-md);
    transition: transform var(--duration-fast) var(--ease-out),
                background var(--duration-fast) var(--ease-out);
}
.record-btn:hover:not(:disabled) { background: var(--accent-hover); }
.record-btn:active:not(:disabled) { transform: scale(0.96); }
.record-btn[data-recording='true'] {
    background: var(--danger-solid);
    animation: kj-pulse 2s var(--ease-in-out) infinite;
}

.timer {
    font-size: var(--text-2xl);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-strong);
    letter-spacing: var(--tracking-tight);
}
.timer[data-state='warning'] { color: var(--warning-text); }
.timer[data-state='danger']  { color: var(--danger-text); }

.waveform {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 4px;
    height: 2.5rem;
}
.waveform__bar {
    width: 4px;
    height: 30%;
    border-radius: var(--radius-full);
    background: var(--accent);
    opacity: 0.4;
}
.waveform[data-active='true'] .waveform__bar {
    animation: kj-wave 1s var(--ease-in-out) infinite;
    opacity: 1;
}
.waveform[data-active='true'] .waveform__bar:nth-child(2) { animation-delay: 0.12s; }
.waveform[data-active='true'] .waveform__bar:nth-child(3) { animation-delay: 0.24s; }
.waveform[data-active='true'] .waveform__bar:nth-child(4) { animation-delay: 0.36s; }
.waveform[data-active='true'] .waveform__bar:nth-child(5) { animation-delay: 0.48s; }

/* --- Chat ---------------------------------------------------------------- */

.chat {
    display: flex;
    flex-direction: column;
    /* svh, not vh: on mobile Safari `100vh` is taller than the visible area,
       which pushed the message input under the browser chrome. */
    height: 100svh;
    max-width: var(--container-narrow);
    margin-inline: auto;
    background: var(--bg-surface);
    border-inline: 1px solid var(--border-subtle);
}

.chat__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-shrink: 0;
    padding: var(--space-3) var(--space-4);
    padding-top: max(var(--space-3), env(safe-area-inset-top));
    border-bottom: 1px solid var(--border-subtle);
    background: var(--bg-surface);
}

.chat__identity { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.chat__name { font-size: var(--text-base); font-weight: 700; color: var(--text-strong); }
.chat__status {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-xs);
    color: var(--success-text);
    font-weight: 600;
}
.chat__status::before {
    content: '';
    width: 0.5rem; height: 0.5rem;
    border-radius: 50%;
    background: var(--success-solid);
}

.avatar {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 2.5rem; height: 2.5rem;
    border-radius: 50%;
    background: var(--brand);
    color: var(--brand-text);
    font-size: var(--text-lg);
}

.chat__log {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.bubble {
    max-width: 85%;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-lg);
    font-size: var(--text-md);
    line-height: var(--leading-snug);
    /* Long unbroken strings (a URL, a pasted token) must wrap rather than
       widen the container and force the page to scroll sideways. */
    overflow-wrap: anywhere;
    animation: kj-bubble-in var(--duration-base) var(--ease-out);
}
.bubble--bot {
    align-self: flex-start;
    background: var(--bg-sunken);
    border: 1px solid var(--border-subtle);
    color: var(--text-strong);
    border-bottom-left-radius: var(--radius-sm);
}
.bubble--user {
    align-self: flex-end;
    background: var(--brand);
    color: var(--brand-text);
    border-bottom-right-radius: var(--radius-sm);
}

.typing { display: flex; gap: 4px; align-items: center; padding-block: var(--space-1); }
.typing__dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--text-muted);
    animation: kj-typing 1.4s var(--ease-in-out) infinite both;
}
.typing__dot:nth-child(2) { animation-delay: 0.16s; }
.typing__dot:nth-child(3) { animation-delay: 0.32s; }

.chat__composer {
    flex-shrink: 0;
    display: flex;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
    border-top: 1px solid var(--border-subtle);
    background: var(--bg-surface);
}
.chat__composer .input { border-radius: var(--radius-full); }

.chat__send {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 2.875rem; height: 2.875rem;
    border: 0;
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-text);
    cursor: pointer;
    transition: background var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}
.chat__send:hover:not(:disabled) { background: var(--accent-hover); }
.chat__send:active:not(:disabled) { transform: scale(0.94); }
.chat__send:disabled { opacity: 0.45; cursor: not-allowed; }

.chat__actions {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-4);
    padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
    border-top: 1px solid var(--border-subtle);
    background: var(--bg-sunken);
}

.chat__overlay {
    position: absolute;
    inset: 0;
    z-index: var(--z-overlay);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    padding: var(--space-6);
    text-align: center;
    background: var(--bg-surface);
}

/* A form is too long to centre-and-fit like the spinner overlays above, so
   this variant scrolls its own content and left-aligns instead. */
.chat__overlay--scroll {
    justify-content: flex-start;
    align-items: stretch;
    text-align: left;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* --- Landing hero -------------------------------------------------------- */

/* Wraps the hero page. `isolation: isolate` gives the glow its own stacking
   context so the explicit z-index below is reliable without depending on
   paint-order edge cases between positioned and in-flow siblings. */
.hero-scene {
    position: relative;
    isolation: isolate;
    overflow: hidden;
}
.hero-scene::before {
    content: '';
    position: absolute;
    z-index: 0;
    top: -12rem;
    left: 50%;
    width: 44rem;
    height: 44rem;
    transform: translateX(-50%);
    background: var(--hero-glow);
    pointer-events: none;
}
.hero-scene > .container { position: relative; z-index: 1; }

.hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-6);
    text-align: center;
}
.hero__title {
    font-size: var(--text-4xl);
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--text-strong);
}
.hero__lede {
    font-size: var(--text-lg);
    color: var(--text-muted);
    max-width: 32ch;
}
.hero__mark {
    display: grid;
    place-items: center;
    width: 5.5rem; height: 5.5rem;
    border-radius: var(--radius-xl);
    background: var(--brand);
    color: var(--brand-text);
    font-size: 2.75rem;
    box-shadow: var(--shadow-md);
    animation: kj-float 6s var(--ease-in-out) infinite;
}

/* Quiet footer nav — a hairline row of secondary links (employer / about /
   privacy). Underlined-by-default reads as a wall of citations when several
   sit together; removing the permanent underline and restoring it on
   hover/focus keeps the affordance without the visual noise. */
.footer-nav {
    color: var(--text-muted);
}
.footer-nav a {
    color: var(--text-muted);
    text-decoration: none;
}
.footer-nav a:hover, .footer-nav a:focus-visible {
    color: var(--text-link);
    text-decoration: underline;
}

/* CV upload dropzone ------------------------------------------------------ */
.dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    text-align: center;
    padding: var(--space-8) var(--space-4);
    border: 2px dashed var(--border-default);
    border-radius: var(--radius-lg);
    background: var(--bg-sunken);
    cursor: pointer;
    transition: border-color var(--duration-base) var(--ease-out), background var(--duration-base) var(--ease-out);
}
.dropzone:hover, .dropzone:focus-visible { border-color: var(--accent); background: var(--accent-subtle); }
.dropzone--active { border-color: var(--accent); background: var(--accent-subtle); }
.dropzone__icon { color: var(--accent); }
.dropzone__icon .icon { width: 2rem; height: 2rem; }
.dropzone__hint { font-weight: 600; color: var(--text-strong); }
.dropzone__types { color: var(--text-muted); }

.choice {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    width: 100%;
    padding: var(--space-4);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    background: var(--bg-surface);
    color: var(--text-strong);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}
.choice:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.choice__icon {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 2.75rem; height: 2.75rem;
    border-radius: var(--radius-md);
    background: var(--accent-subtle);
    font-size: var(--text-xl);
}
.choice__title { font-weight: 700; color: var(--text-strong); }
.choice__sub { font-size: var(--text-sm); color: var(--text-muted); }
.choice__chevron { margin-inline-start: auto; color: var(--text-muted); flex-shrink: 0; }

/* --- In-app browser interstitial ----------------------------------------- */

.iab-block {
    position: fixed;
    inset: 0;
    z-index: var(--z-toast);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-6);
    background: var(--bg-page);
}

/* --- Success mark -------------------------------------------------------- */

.success-mark {
    display: grid;
    place-items: center;
    width: 5rem; height: 5rem;
    margin-inline: auto;
    border-radius: 50%;
    background: var(--success-surface);
    color: var(--success-text);
    font-size: 2.5rem;
    animation: kj-pop var(--duration-slow) var(--ease-out) both;
}

/* --- Definition list (profile detail) ------------------------------------ */

.detail-grid {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
}
.detail__term {
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: var(--space-1);
}
.detail__value { color: var(--text-strong); overflow-wrap: anywhere; }

.transcript {
    padding: var(--space-4);
    background: var(--bg-sunken);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    max-height: 24rem;
    overflow-y: auto;
    font-size: var(--text-base);
    line-height: var(--leading-relaxed);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.transcript-turn {
    padding: var(--space-3);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-2);
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    white-space: normal;
}
.transcript-turn--bot { background: var(--info-surface); border-color: var(--info-border); }
.transcript-turn__who {
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    color: var(--text-muted);
    margin-bottom: var(--space-1);
}

/* ==========================================================================
   5. UTILITIES
   A deliberately small set. Anything used more than a few times becomes a
   component instead, so the markup stays readable.
   ========================================================================== */

.text-xs   { font-size: var(--text-xs); }
.text-sm   { font-size: var(--text-sm); }
.text-lg   { font-size: var(--text-lg); }
.text-xl   { font-size: var(--text-xl); }
.text-2xl  { font-size: var(--text-2xl); }

.text-muted   { color: var(--text-muted); }
.text-strong  { color: var(--text-strong); }
.text-danger  { color: var(--danger-text); }
.text-success { color: var(--success-text); }
.text-accent  { color: var(--accent); }

/* --- Icons -----------------------------------------------------------------
   References into assets/icons.svg. Sized in em so an icon scales with
   whatever type-scale class or component sets font-size on its container —
   the same way the emoji glyphs they replace used to. No fill is set in the
   sprite's shapes themselves; it inherits currentColor from here so a single
   symbol can be teal in one spot and ink in another. */
.icon {
    display: inline-block;
    flex-shrink: 0;
    width: 1em;
    height: 1em;
    fill: currentColor;
    vertical-align: -0.125em;
}
.prompt-list .icon {
    width: 0.5em;
    height: 0.5em;
    margin-top: 0.45em;
    color: var(--accent);
}

.font-semibold { font-weight: 600; }
.font-bold     { font-weight: 700; }
.font-mono     { font-family: var(--font-mono); letter-spacing: 0.05em; }

/* Raw JSON, e.g. an activity_logs.metadata blob in the admin activity log's
   detail dialog -- nowhere else in the app displays anything like it. */
.code-block {
    margin: 0;
    padding: var(--space-3);
    background: var(--bg-sunken);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 16rem;
    overflow-y: auto;
}

.text-centre { text-align: center; }
.text-end    { text-align: right; }

.mt-auto { margin-top: auto; }
.mt-2 { margin-top: var(--space-2); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-6 { margin-bottom: var(--space-6); }

.flex-1 { flex: 1; min-width: 0; }
.w-full { width: 100%; }
.relative { position: relative; }

/* `style-src 'self'` blocks inline style attributes, so widths that used to be
   written inline in the markup live here instead. */
.w-limit-xs { width: 100%; max-width: 20rem; }
.w-limit-sm { width: 100%; max-width: 28rem; }

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 767px) { .hide-mobile { display: none !important; } }
@media (min-width: 1024px) { .hide-desktop { display: none !important; } }

/* ==========================================================================
   6. MOTION AND PREFERENCES
   ========================================================================== */

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

@keyframes kj-shimmer {
    0%   { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

@keyframes kj-pulse {
    0%, 100% { box-shadow: var(--shadow-md), 0 0 0 0 rgb(192 50 43 / 0.45); }
    50%      { box-shadow: var(--shadow-md), 0 0 0 14px rgb(192 50 43 / 0); }
}

@keyframes kj-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-8px); }
}

@keyframes kj-wave {
    0%, 100% { height: 25%; }
    50%      { height: 100%; }
}

@keyframes kj-typing {
    0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
    40%           { transform: scale(1);   opacity: 1; }
}

@keyframes kj-bubble-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

@keyframes kj-toast-in {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
}

@keyframes kj-toast-out {
    to { opacity: 0; transform: translateY(8px); }
}

@keyframes kj-pop {
    from { opacity: 0; transform: scale(0.7); }
    to   { opacity: 1; transform: scale(1); }
}

@keyframes kj-fade-up {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}

.enter { animation: kj-fade-up var(--duration-slow) var(--ease-out) both; }
.enter-delay-1 { animation-delay: 60ms; }
.enter-delay-2 { animation-delay: 120ms; }
.enter-delay-3 { animation-delay: 180ms; }

/* Respect the OS setting. Motion is decoration here; removing it costs
   nothing and prevents nausea for people with vestibular disorders. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Honour a user's forced-colours (high contrast) mode rather than fighting
   it: keep borders explicit so components remain distinguishable. */
@media (forced-colors: active) {
    .btn, .card, .input, .select, .textarea, .badge, .chip { border: 1px solid; }
    .btn[data-loading]::after { border-color: currentColor; border-top-color: transparent; }
}

@media print {
    .app-bar, .console__sidebar, .toast-stack, .btn, .chat__composer { display: none !important; }
    body { background: #fff; color: #000; }
    .card { border: 1px solid #999; box-shadow: none; }
}
