
/* SilaLingo Base Styles - project-owned chrome, tokens and compatibility */

/* ========================================
   CSS CUSTOM PROPERTIES (Design Tokens)
   ======================================== */
:root {
    /* Kinnaree Mascot Palette */
    --color-gold: #F59E0B;
    --color-gold-dark: #D97706;
    --color-gold-light: #FCD34D;
    --color-gold-fade: #FEF3C7;

    --color-emerald: #059669;
    --color-emerald-dark: #047857;
    --color-emerald-light: #34D399;
    --color-emerald-fade: #D1FAE5;

    --color-teal: #0D9488;
    --color-teal-dark: #0F766E;
    --color-teal-light: #5EEAD4;
    --color-teal-fade: #CCFBF1;

    --color-coral: #FB7185;
    --color-coral-dark: #E11D48;
    --color-coral-light: #FECDD3;
    --color-coral-fade: #FFF1F2;

    /* Semantic mapping */
    --color-primary: var(--color-emerald);
    --color-primary-dark: var(--color-emerald-dark);
    --color-primary-light: var(--color-emerald-light);
    --color-cta: var(--color-gold);
    --color-cta-dark: var(--color-gold-dark);
    --color-cta-light: var(--color-gold-light);
    --color-secondary: var(--color-teal);
    --color-secondary-dark: var(--color-teal-dark);
    --color-primary-deep: #065f46;

    /* Mastery level colors - emerald gradient */
    --mastery-0: #9CA3AF;
    --mastery-1: #6EE7B7;
    --mastery-2: #34D399;
    --mastery-3: #10B981;
    --mastery-4: #059669;
    --mastery-5: #047857;
    --mastery-6: #065F46;
    --mastery-7: #064E3B;

    /* Typography */
    --font-family-latin: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-family-thai: 'Sarabun', sans-serif;
    --font-family-thai-cursive: 'Mali', 'Sarabun', sans-serif;
    --font-family-romanization: 'Charis SIL', 'Noto Sans', 'Inter', sans-serif;

    /* Spacing */
    --spacing-1: 0.25rem;
    --spacing-2: 0.5rem;
    --spacing-3: 0.75rem;
    --spacing-4: 1rem;
    --spacing-5: 1.25rem;
    --spacing-6: 1.5rem;
    --spacing-8: 2rem;
    --spacing-10: 2.5rem;
    --spacing-12: 3rem;

    /* Shadows - warmer tint */
    --shadow-sm: 0 1px 2px 0 rgba(217, 119, 6, 0.05);
    --shadow-md: 0 4px 6px -1px rgba(217, 119, 6, 0.08), 0 2px 4px -1px rgba(217, 119, 6, 0.04);
    --shadow-lg: 0 10px 15px -3px rgba(217, 119, 6, 0.1), 0 4px 6px -2px rgba(217, 119, 6, 0.05);
    --shadow-xl: 0 20px 25px -5px rgba(217, 119, 6, 0.12), 0 10px 10px -5px rgba(217, 119, 6, 0.04);

    /* Border Radius */
    --radius-sm: 0.25rem;
    --radius-md: 0.5rem;
    --radius-lg: 0.75rem;
    --radius-xl: 1rem;
    --radius-2xl: 1.25rem;
    --radius-full: 9999px;

    /* Transitions */
    --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-base: 200ms cubic-bezier(0.4, 0, 0.2, 1);

    /* Font Sizes */
    --font-size-xs: 0.75rem;
    --font-size-sm: 0.875rem;
    --font-size-base: 1rem;
    --font-size-lg: 1.125rem;
    --font-size-xl: 1.25rem;
    --font-size-2xl: 1.5rem;
    --font-size-3xl: 1.875rem;

    /* Neutrals */
    --color-white: #ffffff;
    --color-bg: #FFFBF7;
    --color-bg-warm: #FFF7ED;
    --color-gray-50: #fafaf9;
    --color-gray-100: #f5f5f4;
    --color-gray-200: #e7e5e4;
    --color-gray-300: #d6d3d1;
    --color-gray-400: #a8a29e;
    --color-gray-500: #78716c;
    --color-gray-600: #57534e;
    --color-gray-700: #44403c;
    --color-gray-800: #292524;
    --color-gray-900: #1c1917;

    --color-success: #10B981;
    --color-warning: #F59E0B;
    --color-error: #FB7185;

    /* ========================================
       SEMANTIC THEME TOKENS
       Light values below reproduce the legacy appearance exactly;
       html[data-theme="dark"] overrides them (see docs/THEMES.md).
       ======================================== */
    color-scheme: light;

    /* Surfaces */
    --surface-canvas: #FFFBF7;
    --surface: #ffffff;
    --surface-raised: #f8fafc;
    --surface-hover: #f1f5f9;
    --surface-active: #e2e8f0;
    --tooltip-bg: #0f172a;
    --tooltip-ink: #ffffff;

    /* Borders */
    --border: #e2e8f0;
    --border-strong: #cbd5e1;
    --border-input: #ced4da;
    --border-table: #dee2e6;

    /* Ink */
    --ink: #0f172a;
    --ink-alt: #212529;
    --ink-muted: #475569;
    --ink-faint: #64748b;
    --ink-subtle: #94a3b8;
    --ink-on-light: #1f2937;
    --ink-on-accent: #ffffff;
    --ink-on-danger: #3B0A12;
    --chip-contrast-bg: #0f172a;
    --chip-contrast-ink: #ffffff;
    --ink-label: #334155;

    /* Effects & control tracks */
    --wash-hover: rgba(0, 0, 0, 0.035);
    --overlay-backdrop: rgba(15, 23, 42, 0.55);
    --switch-track: #cbd5e1;
    --switch-track-border: #94a3b8;

    /* Focus */
    --focus-outline: #10b981;
    --focus-ring: rgba(16, 185, 129, 0.2);

    /* Status washes (tinted backgrounds + readable ink) */
    --success-accent: #059669;
    --success-ink: #047857;
    --success-ink-deep: #065f46;
    --success-bg: #ecfdf5;
    --success-bg-strong: #d1fae5;
    --success-border: #a7f3d0;
    --warning-accent: #d97706;
    --warning-ink: #92400e;
    --warning-ink-on-solid: #1f2937;
    --warning-bg: #fffbeb;
    --warning-border: #fde68a;
    --danger-accent: #e11d48;
    --danger-ink: #9f1239;
    --danger-ink-alt: #be123c;
    --danger-bg: #fff1f2;
    --danger-border: #fecdd3;
    --danger-border-strong: #fda4af;
    --info-accent: #0284c7;
    --info-accent-alt: #0f766e;
    --info-bg: #f0f9ff;
    --info-border: #99f6e4;
    --streak: #b45309;

    /* Elevation */
    --shadow-card: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
    --badge-ring: #ffffff;
    --shadow-card-hover: 0 1px 2px rgb(15 23 42 / 6%), 0 12px 24px -16px rgb(15 23 42 / 30%);
    --ink-choice: #1e293b;

    /* One-off colors used by kit/page CSS outside the palette */
    --ink-bs-muted: #868e96;
    --chip-ok-bg: #eef6ef;
    --chip-ok-ink: #3f6212;
    --progress-ring: #0f9d76;
    --heat-l1: #A7F3D0;
    --heat-l2: #34D399;
    --heat-l3: #059669;
    --heat-l4: #064E3B;

    /* Alphabet class identity (band, heading ink, tile border) */
    --alphabet-mid-surface: #EEF4FB;
    --alphabet-mid-ink: #3D5A80;
    --alphabet-mid-border: #A8BDD9;
    --alphabet-high-surface: #EAF7EF;
    --alphabet-high-ink: #2F6B49;
    --alphabet-high-border: #A8D9B8;
    --alphabet-low-surface: #F8F2E9;
    --alphabet-low-ink: #805A3D;
    --alphabet-low-border: #D9B8A0;
}

/* ========================================
   DARK THEME - "Evergreen Slate" (docs/THEMES.md)
   ======================================== */
html[data-theme="dark"] {
    color-scheme: dark;

    /* Brand ramps - brighten for dark surfaces, keep the hues */
    --color-gold: #FCD34D;
    --color-gold-dark: #F59E0B;
    --color-gold-light: #FDE68A;
    --color-gold-fade: #2A2210;

    --color-emerald: #34D399;
    --color-emerald-dark: #6EE7B7;
    --color-emerald-light: #6EE7B7;
    --color-emerald-fade: #1B3A2B;

    --color-teal: #5EEAD4;
    --color-teal-dark: #99F6E4;
    --color-teal-light: #5EEAD4;
    --color-teal-fade: #13262B;

    --color-coral: #FB7185;
    --color-coral-dark: #FDA4AF;
    --color-coral-light: #FDA4AF;
    --color-coral-fade: #311A1F;

    --color-primary-deep: #A7F3D0;

    /* Mastery - dim to bright as level rises (inverted for dark surfaces) */
    --mastery-0: #74867A;
    --mastery-1: #1F6B4A;
    --mastery-2: #238B5E;
    --mastery-3: #28A86F;
    --mastery-4: #34D399;
    --mastery-5: #6EE7B7;
    --mastery-6: #A7F3D0;
    --mastery-7: #D1FAE5;

    /* Neutral scale - roles reversed (gray-50 = surface, gray-900 = text) */
    --color-bg: #101713;
    --color-bg-warm: #141E18;
    --color-gray-50: #18221C;
    --color-gray-100: #223027;
    --color-gray-200: #2E4034;
    --color-gray-300: #3A4B40;
    --color-gray-400: #809286;
    --color-gray-500: #93A598;
    --color-gray-600: #B0BDB3;
    --color-gray-700: #CBD8CE;
    --color-gray-800: #E4EAE5;
    --color-gray-900: #F5F7F2;

    --color-success: #34D399;
    --color-warning: #FCD34D;
    --color-error: #FB7185;

    /* Semantic theme tokens */
    --surface-canvas: #101713;
    --surface: #18221C;
    --surface-raised: #223027;
    --surface-hover: #26342C;
    --surface-active: #2E4034;
    --tooltip-bg: #223027;
    --tooltip-ink: #F5F7F2;

    --border: #3A4B40;
    --border-strong: #4E6155;
    --border-input: #3A4B40;
    --border-table: #33453A;

    --ink: #F5F7F2;
    --ink-alt: #F5F7F2;
    --ink-muted: #B0BDB3;
    --ink-faint: #93A598;
    --ink-subtle: #84988B;
    --ink-on-light: #F5F7F2;
    --ink-on-accent: #062A1D;
    --ink-on-danger: #3B0A12;
    --chip-contrast-bg: #2E4034;
    --chip-contrast-ink: #F5F7F2;
    --ink-label: #CBD8CE;

    --wash-hover: rgba(255, 255, 255, 0.05);
    --overlay-backdrop: rgba(0, 0, 0, 0.6);
    --switch-track: #3A4B40;
    --switch-track-border: #4E6155;

    --focus-outline: #34D399;
    --focus-ring: rgba(52, 211, 153, 0.28);

    --success-accent: #34D399;
    --success-ink: #6EE7B7;
    --success-ink-deep: #A7F3D0;
    --success-bg: #142A20;
    --success-bg-strong: #1B3A2B;
    --success-border: #25533D;
    --warning-accent: #FCD34D;
    --warning-ink: #FDE68A;
    --warning-ink-on-solid: #1f2937;
    --warning-bg: #2A2210;
    --warning-border: #4D3D17;
    --danger-accent: #FB7185;
    --danger-ink: #FDA4AF;
    --danger-ink-alt: #FB7185;
    --danger-bg: #311A1F;
    --danger-border: #54272F;
    --danger-border-strong: #6E3440;
    --info-accent: #5EEAD4;
    --info-accent-alt: #5EEAD4;
    --info-bg: #13262B;
    --info-border: #1E444B;
    --streak: #FBBF24;

    /* Elevation - deeper neutral shadows on dark surfaces */
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.35), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.25);
    --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.45), 0 10px 10px -5px rgba(0, 0, 0, 0.25);
    --shadow-card: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.4);
    --badge-ring: #18221C;
    --shadow-card-hover: 0 1px 2px rgb(0 0 0 / 30%), 0 12px 24px -16px rgb(0 0 0 / 60%);
    --ink-choice: #E2EAE4;

    /* Alphabet class identity - tinted bands, lifted inks for dark surfaces */
    --alphabet-mid-surface: #14202B;
    --alphabet-mid-ink: #A8C4E8;
    --alphabet-mid-border: #2F4A63;
    --alphabet-high-surface: #142A20;
    --alphabet-high-ink: #8FD9B0;
    --alphabet-high-border: #2E5B45;
    --alphabet-low-surface: #2A2210;
    --alphabet-low-ink: #E0B890;
    --alphabet-low-border: #5A4433;

    /* ========================================
       TAILWIND PALETTE BRIDGE (Evergreen Slate)
       The kit bundle declares its palette as --tw-color-* variables on
       :root (prefix(tw) namespaces theme variables too). Re-pointing them
       here re-themes every tw: utility and @apply component at once.
       Light never declares them, so the light theme keeps Tailwind's
       defaults untouched. Neutral stops follow the surface ramp (50 =
       recessed, 900 = ink); accent stops keep their hue and lift toward
       the dark-legible end of the scale.
       ======================================== */
    --tw-color-white: #18221C;
    --tw-color-slate-50: #223027;
    --tw-color-slate-100: #26342C;
    --tw-color-slate-200: #3A4B40;
    --tw-color-slate-300: #4E6155;
    --tw-color-slate-400: #809286;
    --tw-color-slate-500: #93A598;
    --tw-color-slate-600: #B0BDB3;
    --tw-color-slate-700: #CBD8CE;
    --tw-color-slate-800: #E2EAE4;
    --tw-color-slate-900: #F5F7F2;
    --tw-color-slate-950: #0B100D;
    --tw-color-gray-50: #223027;
    --tw-color-gray-100: #26342C;
    --tw-color-gray-200: #3A4B40;
    --tw-color-gray-300: #4E6155;
    --tw-color-gray-400: #809286;
    --tw-color-gray-500: #93A598;
    --tw-color-gray-600: #B0BDB3;
    --tw-color-gray-700: #CBD8CE;
    --tw-color-gray-900: #F5F7F2;
    --tw-color-emerald-50: #142A20;
    --tw-color-emerald-100: #1A3B2B;
    --tw-color-emerald-200: #2C5A43;
    --tw-color-emerald-300: #6EE7B7;
    --tw-color-emerald-400: #34D399;
    --tw-color-emerald-500: #34D399;
    --tw-color-emerald-600: #34D399;
    --tw-color-emerald-700: #6EE7B7;
    --tw-color-emerald-800: #A7F3D0;
    --tw-color-emerald-900: #A7F3D0;
    --tw-color-amber-50: #2A2210;
    --tw-color-amber-100: #3A2D12;
    --tw-color-amber-200: #D9A437;
    --tw-color-amber-400: #FCD34D;
    --tw-color-amber-500: #FCD34D;
    --tw-color-amber-600: #FCD34D;
    --tw-color-amber-700: #FCD34D;
    --tw-color-amber-800: #FCD34D;
    --tw-color-rose-50: #311A1F;
    --tw-color-rose-100: #3A1F26;
    --tw-color-rose-200: #5A2E37;
    --tw-color-rose-300: #FDA4AF;
    --tw-color-rose-400: #FB7185;
    --tw-color-rose-500: #FB7185;
    --tw-color-rose-600: #FB7185;
    --tw-color-rose-700: #FDA4AF;
    --tw-color-rose-800: #FDA4AF;
    --tw-color-red-100: #311A1F;
    --tw-color-red-600: #FB7185;
    --tw-color-red-700: #FDA4AF;
    --tw-color-red-800: #FECACA;
    --tw-color-sky-50: #13262B;
    --tw-color-sky-100: #18343C;
    --tw-color-sky-200: #3E7A8C;
    --tw-color-sky-500: #38BDF8;
    --tw-color-sky-600: #38BDF8;
    --tw-color-sky-700: #38BDF8;
    --tw-color-sky-800: #7DD3FC;
    --tw-color-sky-900: #BAE6FD;
    --tw-color-teal-700: #5EEAD4;
    --tw-color-teal-900: #5EEAD4;
    --tw-color-orange-600: #FDBA74;
    --tw-color-cyan-50: #122A2E;
    --tw-color-indigo-50: #1E2033;
    --tw-color-indigo-100: #262847;
    --tw-color-indigo-500: #818CF8;
    --tw-color-indigo-600: #818CF8;
    --tw-color-indigo-700: #A5B4FC;
    --tw-color-indigo-800: #A5B4FC;

    /* One-off colors used by kit/page CSS outside the palette */
    --ink-bs-muted: #93A598;
    --chip-ok-bg: #142A20;
    --chip-ok-ink: #A7F3D0;
    --progress-ring: #34D399;
    --heat-l1: #1F6B4A;
    --heat-l2: #28A86F;
    --heat-l3: #34D399;
    --heat-l4: #A7F3D0;
}

/* ========================================
   GLOBAL STYLES & PRESENTATION COMPATIBILITY
   ======================================== */

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

html {
    height: auto;
}

body {
    margin: 0;
    min-height: 100dvh;
}

body {
    font-family: var(--font-family-latin);
    background-color: var(--color-bg);
    color: var(--color-gray-800);
    display: flex;
    flex-direction: column;
}

/* Thai font â€” set per user preference via data-thai-font on <body> */
body[data-thai-font="sarabun"] { --font-family-thai: 'Sarabun', sans-serif; }
body[data-thai-font="noto"]    { --font-family-thai: 'Noto Sans Thai', sans-serif; }
body[data-thai-font="prompt"] { --font-family-thai: 'Prompt', sans-serif; }
body[data-thai-font="mali"]    { --font-family-thai: 'Mali', sans-serif; }

/* Romanization text uses a font with strong IPA / combining mark support */
.romanization {
    font-family: var(--font-family-romanization);
}

/* Thai text styling */
.thai-text,
[lang="th"] {
    font-family: var(--font-family-thai);
}

.thai-cursive {
    font-family: var(--font-family-thai-cursive);
}



/* ========================================
   LINKS - Remove Bootstrap Blue
   ======================================== */
a {
    color: var(--color-teal);
    text-decoration: none;
    transition: color var(--transition-fast);
}

a:hover {
    color: var(--color-teal-dark);
    text-decoration: none;
}

a:not([href]):not([class]),
a:not([href]):not([class]):hover {
    color: inherit;
    text-decoration: none;
}

/* ========================================
   BOOTSTRAP COLOR UTILITIES
   ======================================== */

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

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

/* CTA Buttons - Gold */
.ui-btn-primary {
    background-color: var(--color-cta);
    border-color: var(--color-cta);
    color: #fff;
}

.ui-btn-primary:hover {
    background-color: var(--color-cta-dark);
    border-color: var(--color-cta-dark);
    color: #fff;
}

.ui-btn-primary:focus,
.ui-btn-primary:active {
    color: #fff !important;
    background-color: var(--color-cta-dark) !important;
    border-color: var(--color-cta-dark) !important;
    box-shadow: 0 0 0 0.25rem rgba(245, 158, 11, 0.35) !important;
}

.ui-btn-outline-primary {
    color: var(--color-cta);
    border-color: var(--color-cta);
}

.ui-btn-outline-primary:hover {
    background-color: var(--color-cta);
    border-color: var(--color-cta);
    color: #fff;
}

/* Success - Emerald */
.text-success {
    color: var(--color-success) !important;
}

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

/* Danger - Coral */
.text-danger {
    color: var(--color-error) !important;
}

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

/* Warning - Gold */
.text-warning {
    color: var(--color-warning) !important;
}

.bg-warning {
    /* Respect Bootstrap's --bs-bg-opacity (e.g. .bg-opacity-10) while keeping
       the project gold hue. Defaults to solid when no opacity utility is set. */
    background-color: rgba(
        245,
        158,
        11,
        var(--bs-bg-opacity, 1)
    ) !important;
}

/* Info - Teal */
.text-info {
    color: var(--color-teal) !important;
}

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

/* Secondary */
.text-secondary {
    color: var(--color-gray-500) !important;
}

/* ========================================
   SITE SHELL - NAVBAR
   ======================================== */

/* The frame is plain CSS on purpose: every page loads base.css, while only the
   migrated pages load the Tailwind bundle, so the shell cannot depend on it.
   Class names mirror the Tailwind kit's vocabulary (nav-pill, nav-stat, ...) so
   a later page-level component can reuse them without a second language. */

.site-nav {
    position: sticky;
    top: 0;
    z-index: 1030;
    background-color: var(--surface);
    border-bottom: 1px solid var(--border);
}

.site-nav__inner {
    max-width: 1140px;
    margin: 0 auto;
    padding: 0 16px;
    height: 64px;
    display: flex;
    align-items: center;
    gap: 18px;
}

.site-nav__brand {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    text-decoration: none;
}

.site-nav__brand:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 3px;
    border-radius: 8px;
}

/* Make the picture/img a solid block so flexbox centering is exact and
   no inline line-box gap pushes the logo off-center. */
.site-nav__brand picture,
.site-nav__brand picture img {
    display: block;
}

.site-nav__logo {
    height: 40px;
    width: auto;
}

.site-nav__burger {
    display: none;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 10px;
    background-color: var(--surface);
    color: var(--ink-muted);
    cursor: pointer;
}

.site-nav__burger span {
    display: block;
    width: 16px;
    height: 2px;
    margin: 3px auto;
    border-radius: 2px;
    background-color: currentColor;
}

.site-nav__burger:hover {
    background-color: var(--surface-hover);
    border-color: var(--border-strong);
    color: var(--ink);
}

.site-nav__burger:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 2px;
}

.site-nav__body {
    display: none;
}

/* Desktop: the body is always open â€” the collapse only applies below 992px.
   The doubled selector has to outrank Bootstrap's `.collapse:not(.show)`. */
@media (min-width: 992px) {
    .site-nav__body,
    .site-nav__body.collapse:not(.show) {
        display: flex;
        align-items: center;
        gap: 18px;
        flex: 1 1 auto;
        min-width: 0;
    }
}

.site-nav__links {
    display: flex;
    align-items: center;
    gap: 2px;
    min-width: 0;
}

.site-nav__right {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

.nav-link {
    font-weight: 500;
    color: var(--color-gray-600);
    text-decoration: none;
}

.nav-link:hover,
.nav-link.active {
    color: var(--color-emerald);
    text-decoration: none;
}

/* --- Nav pills: every top-level destination is one control --------------- */

.site-nav .nav-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 36px;
    padding: 0 12px;
    border: 0;
    border-radius: 10px;
    background-color: transparent;
    color: var(--ink-muted);
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.site-nav .nav-pill:hover,
.site-nav .nav-pill:focus-visible {
    background-color: var(--surface-hover);
    color: var(--ink);
    text-decoration: none;
}

.site-nav .nav-pill:active {
    background-color: var(--surface-active);
    color: var(--ink);
}

.site-nav .nav-pill:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 2px;
}

.nav-caret {
    flex: 0 0 auto;
    opacity: 0.7;
}

.nav-pill[aria-expanded="true"] .nav-caret,
.lang-pill[aria-expanded="true"] .nav-caret {
    transform: rotate(180deg);
}

/* --- Progress stats: one grouped capsule, not three loose badges --------- */

.nav-stats {
    display: inline-flex;
    align-items: center;
    height: 30px;
    flex: 0 0 auto;
    border: 1px solid var(--border);
    border-radius: 999px;
    background-color: var(--surface-raised);
}

.nav-stat {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 100%;
    padding: 0 10px;
    color: var(--ink-muted);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
}

.nav-stat + .nav-stat {
    border-left: 1px solid var(--border);
}

/* XP reads as one green unit: the label inherits the number's ink, so a
   coloured glyph never sits next to a grey word with the same meaning. */
.nav-stat b {
    color: var(--success-ink);
    font-weight: 600;
}

.nav-stat--xp {
    color: var(--success-ink);
}

.nav-stat--streak b {
    color: var(--streak);
}

.nav-prem {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 30px;
    padding: 0 12px;
    flex: 0 0 auto;
    border: 1px solid var(--success-bg-strong);
    border-radius: 999px;
    background-color: var(--success-bg);
    color: var(--success-ink);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.nav-prem:hover,
.nav-prem:focus-visible {
    background-color: var(--success-bg-strong);
    color: var(--success-ink-deep);
    text-decoration: none;
}

.nav-prem:active {
    background-color: var(--success-border);
    color: var(--success-ink-deep);
}

.nav-prem:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 2px;
}

/* --- Bell ---------------------------------------------------------------- */

.nav-bell {
    position: relative;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 999px;
    background-color: var(--surface);
    color: var(--ink-muted);
    font-size: 15px;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.nav-bell:hover {
    background-color: var(--surface-hover);
    border-color: var(--border-strong);
    color: var(--ink);
}

.nav-bell:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 2px;
}

.nav-bell__badge {
    position: absolute;
    top: -3px;
    right: -3px;
    display: grid;
    place-items: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background-color: var(--danger-accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    box-shadow: 0 0 0 2px var(--badge-ring);
}

/* --- User toggle --------------------------------------------------------- */

.nav-user {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 36px;
    max-width: 230px;
    padding: 0 10px 0 4px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background-color: var(--surface);
    color: var(--ink-label);
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.nav-user:hover {
    background-color: var(--surface-hover);
    border-color: var(--border-strong);
}

.nav-user:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 2px;
}

.nav-user__name {
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-user__avatar {
    flex: 0 0 auto;
    border-radius: 999px;
}

.nav-user__badge {
    display: inline-grid;
    place-items: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background-color: var(--danger-accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
}

.nav-ava {
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    flex: 0 0 auto;
    border-radius: 999px;
    background-color: var(--success-bg-strong);
    color: var(--success-ink);
    font-size: 12px;
}

.nav-ava--lg {
    width: 36px;
    height: 36px;
    font-size: 15px;
}

/* --- Menus: static/js/ui/disclosure.js positions and opens them ----------- */

.dropdown {
    position: relative;
}

.dropdown-menu {
    position: absolute;
    z-index: 1000;
    display: none;
    min-width: 10rem;
    margin: 0;
    padding: 0.5rem 0;
    color: var(--ink-alt);
    text-align: left;
    list-style: none;
    background-color: var(--surface);
    background-clip: padding-box;
    border: 1px solid var(--border);
    border-radius: 0.75rem;
}

.dropdown-menu.show {
    display: block;
}

.dropdown-menu-end {
    right: 0;
    left: auto;
}

.dropdown-divider {
    height: 0;
    margin: 0.5rem 0;
    overflow: hidden;
    border-top: 1px solid var(--border);
}

.dropdown-item {
    display: block;
    width: 100%;
    padding: 0.375rem 1rem;
    clear: both;
    font-weight: 400;
    color: var(--ink-alt);
    text-align: inherit;
    text-decoration: none;
    white-space: nowrap;
    background-color: transparent;
    border: 0;
}

.dropdown-menu.ui-menu:not(.ui-drop-up) {
    top: 100%;
}

.dropdown-menu.ui-drop-up {
    top: auto;
    bottom: calc(100% + 8px);
}

.dropdown-menu.ui-align-end {
    right: 0;
    left: auto;
}

/* The desktop profile menu can exceed the viewport; keep every item reachable. */
@media (min-width: 992px) {
    .site-nav__right .dropdown-menu.ui-menu {
        max-height: calc(100dvh - 4rem);
        overflow-y: auto;
        overscroll-behavior: contain;
    }
}

/* Disclosure animation without Bootstrap's Collapse class. */
.ui-collapsing {
    overflow: hidden;
    transition: height 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
    .ui-collapsing {
        transition: none;
    }
}

/* --- Dialogs: static/js/ui/dialog.js owns the native <dialog> lifecycle ---- */

dialog.ui-dialog {
    /* Bootstrap's .modal owns these variables; the outer element is a native
       <dialog> now, so restate them here for the inner modal-* chrome. */
    --bs-modal-zindex: 1055;
    --bs-modal-width: 500px;
    --bs-modal-padding: 1rem;
    --bs-modal-margin: 0.5rem;
    --bs-modal-color: ;
    --bs-modal-bg: var(--bs-body-bg, var(--surface));
    --bs-modal-border-color: var(--bs-border-color-translucent, rgba(0, 0, 0, 0.175));
    --bs-modal-border-width: var(--bs-border-width, 1px);
    --bs-modal-border-radius: var(--bs-border-radius-lg, 0.5rem);
    --bs-modal-box-shadow: var(--bs-box-shadow-sm, 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075));
    --bs-modal-inner-border-radius: calc(var(--bs-border-radius-lg, 0.5rem) - var(--bs-border-width, 1px));
    --bs-modal-header-padding-x: 1rem;
    --bs-modal-header-padding-y: 1rem;
    --bs-modal-header-padding: 1rem 1rem;
    --bs-modal-header-border-color: var(--bs-border-color, var(--border-table));
    --bs-modal-header-border-width: var(--bs-border-width, 1px);
    --bs-modal-title-line-height: 1.5;
    --bs-modal-footer-gap: 0.5rem;
    --bs-modal-footer-bg: ;
    --bs-modal-footer-border-color: var(--bs-border-color, var(--border-table));
    --bs-modal-footer-border-width: var(--bs-border-width, 1px);
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    overflow: visible;
}

dialog.ui-dialog[open] {
    display: flex;
    align-items: center;
    justify-content: center;
}

dialog.ui-dialog::backdrop {
    background: var(--overlay-backdrop);
}

/* A short, settled entrance: the dialog is usable immediately, the animation
   only softens the first paint. No exit animation: the native close is instant
   and a delayed unmount would make the dialog feel slower than it is. */
@keyframes ui-dialog-panel-in {
    from {
        opacity: 0;
        transform: translateY(8px) scale(0.985);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

@keyframes ui-dialog-backdrop-in {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@media (prefers-reduced-motion: no-preference) {
    dialog.ui-dialog[open] > .modal-dialog {
        animation: ui-dialog-panel-in 170ms cubic-bezier(0.16, 1, 0.3, 1);
    }

    dialog.ui-dialog[open]::backdrop {
        animation: ui-dialog-backdrop-in 170ms ease-out;
    }
}

/* The peek/modal reuses the word page's header typography, where the transliteration
   is display-sized. Inside a dialog it is a reading aid: match the vocabulary
   card size instead of competing with the Thai word. */
#wordModal .word-romanization .romanization {
    font-size: 13.5px;
}

.ui-dialog > .modal-dialog {
    width: 100%;
    max-width: min(500px, calc(100vw - 2rem));
    max-height: calc(100dvh - 2rem);
    margin: 0;
    pointer-events: auto;
}

.ui-dialog > .modal-dialog.modal-dialog-centered {
    min-height: 0;
}

.ui-dialog > .modal-dialog.modal-sm {
    max-width: min(300px, calc(100vw - 2rem));
}

/* Admin consoles (scripts, redemptions) are wider than a standard dialog. */
.ui-dialog > .modal-dialog.admin-modal-dialog {
    max-width: min(52rem, calc(100vw - 2rem));
}

/* The Bootstrap modal chrome that normally paints `.modal-content` is gone;
   every dialog that still uses the shared `.modal-*` shell needs the themed
   surface, or the page shows through the dialog. Admin dialogs additionally
   carry `.admin-modal`, which stays as the explicit admin-console override. */
.ui-dialog > .modal-dialog > .modal-content,
.ui-dialog > .modal-dialog > form > .modal-content {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    color: var(--ink);
    border: 1px solid var(--border);
    border-radius: 0.75rem;
    box-shadow: 0 1.5rem 4rem rgba(15, 23, 42, 0.22);
}

html[data-theme="dark"] .ui-dialog > .modal-dialog > .modal-content,
html[data-theme="dark"] .ui-dialog > .modal-dialog > form > .modal-content {
    box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.45);
}

.admin-modal {
    background: var(--surface);
    color: var(--ink);
}

.ui-dialog .modal-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--border);
}

.ui-dialog .modal-title {
    margin: 0;
    color: var(--ink);
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.4;
}

.ui-dialog .modal-body {
    padding: 1.25rem;
}

.ui-dialog .modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: 1rem 1.25rem;
    border-top: 1px solid var(--border);
}

/* The script console is intentionally dark in light mode; the Tailwind
   slate-900 utility is inverted in dark mode, so restate the surfaces. */
html[data-theme="dark"] .admin-script-output {
    background-color: var(--surface-canvas);
    color: var(--ink);
}

.ui-dialog > .modal-dialog.modal-lg {
    max-width: min(800px, calc(100vw - 2rem));
}

.ui-dialog > .modal-dialog.modal-xl {
    max-width: min(1140px, calc(100vw - 2rem));
}

.ui-dialog > .modal-dialog > .modal-content,
.ui-dialog > .modal-dialog > form > .modal-content {
    max-height: calc(100dvh - 2rem);
    overflow: hidden;
}

/* Some Bootstrap forms wrapped the content instead of sitting inside it. */
.ui-dialog > .modal-dialog > form {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    width: 100%;
    max-height: calc(100dvh - 2rem);
    margin: 0;
}

.ui-dialog .modal-body {
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.ui-dialog .modal-header,
.ui-dialog .modal-footer {
    flex: 0 0 auto;
}

.ui-dialog .modal-dialog-scrollable {
    height: auto;
}

.ui-dialog .modal-dialog-scrollable > .modal-content {
    max-height: calc(100dvh - 2rem);
}

.ui-dialog__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex: 0 0 auto;
    margin-left: auto;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--ink-faint);
    font-size: 16px;
    line-height: 1;
}

.ui-dialog__close:hover,
.ui-dialog__close:focus-visible {
    background: var(--surface-hover);
    color: var(--ink);
}

.ui-dialog__close:focus-visible {
    outline: 2px solid var(--ink-subtle);
    outline-offset: 2px;
}

body.ui-dialog-open {
    overflow: hidden;
}

.site-nav .dropdown-menu,
.site-footer .dropdown-menu {
    min-width: 246px;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 18px 40px -20px rgba(15, 23, 42, 0.35);
    /* Popper writes `margin: 0` and a transform inline, so the menu hangs
       flush from its trigger by design; only the height is ours to clamp.
       A staff menu has twenty rows: never let it run past the viewport. */
    max-height: calc(100dvh - 76px);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.site-nav .dropdown-item,
.site-footer .dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 36px;
    padding: 0 10px;
    border-radius: 8px;
    color: var(--ink-label);
    font-size: 13px;
    line-height: 1.25;
    white-space: normal;
}

.site-nav .dropdown-item i.bi,
.site-footer .dropdown-item i.bi {
    width: 16px;
    flex: 0 0 auto;
    color: var(--ink-subtle);
    font-size: 14px;
    text-align: center;
}

.site-nav .dropdown-item:hover,
.site-nav .dropdown-item:focus,
.site-footer .dropdown-item:hover,
.site-footer .dropdown-item:focus {
    background-color: var(--surface-hover);
    color: var(--ink);
}

/* The footer's language list marks the current language with weight and a
   slate wash, not a colour: an emerald row inside a neutral menu reads as a
   hover state that never goes away. */
.site-footer .dropdown-item.active,
.site-footer .dropdown-item:active {
    background-color: var(--surface-hover);
    color: var(--ink);
    font-weight: 600;
}

.nav-gem {
    margin-left: auto;
    color: var(--color-primary) !important;
}

.nav-item--danger {
    color: var(--danger-ink-alt) !important;
}

.nav-item--danger:hover,
.nav-item--danger:focus {
    background-color: var(--danger-bg) !important;
    color: var(--danger-ink) !important;
}

.nav-item--danger i.bi {
    color: inherit !important;
}

/* --- Menu internals ------------------------------------------------------ */

.nav-menu__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
}

.nav-menu__head h6 {
    margin: 0;
    color: var(--ink);
    font-size: 13px;
    font-weight: 600;
}

.nav-menu__action {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ink-faint);
    font-size: 12px;
    cursor: pointer;
}

.nav-menu__action:hover {
    color: var(--ink);
    text-decoration: underline;
}

.nav-menu__foot {
    padding: 10px 12px;
    border-top: 1px solid var(--border);
    text-align: center;
}

.nav-menu__link {
    color: var(--success-ink);
    font-size: 12px;
    font-weight: 500;
    text-decoration: none;
}

.nav-menu__link:hover {
    color: var(--success-ink-deep);
    text-decoration: underline;
}

.nav-empty {
    padding: 20px 12px;
    color: var(--ink-subtle);
    font-size: 12px;
    text-align: center;
}

.nav-empty i {
    display: block;
    margin-bottom: 6px;
    font-size: 20px;
}

.nav-empty p {
    margin: 0;
}

.nav-menu__head--user {
    justify-content: flex-start;
    margin-bottom: 4px;
    padding: 8px 10px 10px;
    border-bottom-color: var(--surface-hover);
}

.nav-menu__id {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

.nav-menu__id b {
    overflow: hidden;
    color: var(--ink);
    font-size: 13px;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-menu__id small {
    overflow: hidden;
    color: var(--ink-subtle);
    font-size: 11px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-prem-line {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 6px 4px;
    padding: 6px 8px;
    border-radius: 8px;
    background-color: var(--success-bg);
    color: var(--success-ink);
    font-size: 12px;
    font-weight: 600;
}

.nav-menu__badge {
    display: inline-grid;
    place-items: center;
    min-width: 16px;
    height: 16px;
    margin-left: auto;
    padding: 0 4px;
    border-radius: 999px;
    background-color: var(--danger-accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
}

.nav-menu__form {
    margin: 0;
}

.nav-menu__form button.dropdown-item {
    width: 100%;
    border: 0;
    background: transparent;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

/* --- Signed-out CTA ------------------------------------------------------ */

.nav-signup {
    display: inline-flex;
    align-items: center;
    height: 32px;
    padding: 0 14px;
    flex: 0 0 auto;
    border-radius: 999px;
    background-color: var(--color-primary);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    transition: background-color 0.15s ease;
}

.nav-signup:hover,
.nav-signup:focus-visible {
    background-color: var(--color-primary-dark);
    color: #fff;
    text-decoration: none;
}

.nav-signup:active {
    background-color: var(--color-primary-deep);
}

.nav-signup:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 2px;
}

/* Below 992px the body becomes the sheet: one column, menus inline. */
@media (max-width: 991.98px) {
    .site-nav__inner {
        height: auto;
        padding: 12px 16px;
        flex-wrap: wrap;
        gap: 12px;
    }

    .site-nav__burger {
        display: block;
        margin-left: auto;
    }

    .site-nav__body.collapse:not(.show) {
        display: none;
    }

    .site-nav__body {
        flex: 1 0 100%;
        min-width: 0;
    }

    .site-nav__body.show {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 6px;
        margin-top: 4px;
        padding-top: 12px;
        border-top: 1px solid var(--border);
        /* The sheet can be taller than the viewport: let it scroll. */
        max-height: calc(100dvh - 88px);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }

    .site-nav__links {
        flex-direction: column;
        align-items: center;
        gap: 2px;
    }

    .site-nav .site-nav__links .nav-pill {
        width: 100%;
        height: 40px;
        justify-content: center;
    }

    .site-nav__links .dropdown {
        width: 100%;
    }

    /* Menus open inline inside the sheet: Popper skips positioning when the
       computed position is static, so this also keeps it from jumping. */
    .site-nav__links .dropdown-menu {
        position: static !important;
        width: auto;
        margin: 4px 8px 8px;
        padding: 6px;
        border: 1px solid var(--border);
        border-radius: 12px;
        box-shadow: 0 14px 28px -24px rgba(15, 23, 42, 0.45);
        background-color: var(--surface);
    }

    .site-nav__right {
        flex-wrap: wrap;
        justify-content: center;
        gap: 8px;
        margin-top: 6px;
        padding-top: 12px;
        border-top: 1px solid var(--border);
    }

    .site-nav__right .dropdown {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
    }

    .site-nav__right .dropdown:has(.dropdown-menu.show) {
        flex: 1 0 100%;
    }

    .site-nav__right .dropdown-menu {
        position: static !important;
        flex: 1 0 100%;
        width: 100%;
        min-width: 0;
        max-height: none;
        margin: 6px 0 2px;
        overflow: visible;
        border: 1px solid var(--border);
        border-radius: 12px;
        background-color: var(--surface);
        box-shadow: 0 14px 28px -24px rgba(15, 23, 42, 0.45);
    }

    .nav-stats {
        max-width: 100%;
    }

    /* The footer trigger sits at the very bottom of long lists. An absolutely
       positioned menu can fall outside the visual viewport when the page
       reflows underneath it, so anchor this one to the viewport instead of
       the footer and keep it above the trigger row. */
    .site-footer .dropdown-menu.ui-menu {
        position: fixed !important;
        top: auto !important;
        right: 16px !important;
        bottom: calc(96px + env(safe-area-inset-bottom)) !important;
        left: 16px !important;
        width: auto;
        min-width: 0;
        max-height: min(60dvh, 320px);
        margin: 0;
        overflow-y: auto;
        z-index: 1080;
    }
}

.dropdown-item:hover,
.dropdown-item:focus {
    background-color: var(--surface-hover);
    color: var(--ink-on-light);
}

/* ========================================
   SITE SHELL - FOOTER
   ======================================== */

.site-footer {
    margin-top: auto;
    background-color: var(--surface);
    border-top: 1px solid var(--border);
    color: var(--ink-faint);
    font-size: 13px;
}

.site-footer__inner {
    max-width: 1140px;
    margin: 0 auto;
    padding: 26px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

.site-footer__copy {
    margin: 0;
}

.site-footer__brand-link {
    color: var(--success-ink);
    font-weight: 500;
    text-decoration: none;
}

.site-footer__brand-link:hover,
.site-footer__brand-link:focus-visible {
    color: var(--success-ink-deep);
    text-decoration: underline;
}

/* Links plus the language pill share one row. The trigger leads with a flag so
   the option is recognisable by icon even when the surrounding page is in a
   language the visitor cannot read. */
.site-footer__links {
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
}

.site-footer__links a {
    color: var(--ink-faint);
    text-decoration: none;
    transition: color 0.15s ease;
}

.site-footer__links a:hover,
.site-footer__links a:focus-visible,
.site-footer__links a:active {
    color: var(--ink);
    text-decoration: none;
}

.lang-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 30px;
    padding: 0 12px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background-color: var(--surface);
    color: var(--ink-muted);
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.lang-pill:hover {
    background-color: var(--surface-hover);
    border-color: var(--border-strong);
    color: var(--ink);
}

.lang-pill:focus-visible {
    outline: 2px solid var(--ink-subtle);
    outline-offset: 2px;
}

/* Open state is a state, not a hover â€” but it stays neutral too: a tinted pill
   under a menu that is already open is the one place the emerald wash had no
   state to communicate. */
.lang-pill[aria-expanded="true"] {
    border-color: var(--ink-subtle);
    background-color: var(--surface-hover);
    color: var(--ink);
}

.footer-lang-flag {
    display: inline-block;
    flex: 0 0 auto;
    vertical-align: -2px;
    width: 24px;
    height: 16px;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
}

@media (max-width: 767.98px) {
    .site-footer__inner {
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
        padding: 20px 16px;
    }

    .site-footer__links {
        gap: 14px 18px;
    }
}

/* ========================================
   MASTERY COLORS
   ======================================== */










/* ========================================
   FORM CHECKS & SWITCHES
   ======================================== */

.ui-check-input:focus {
    border-color: var(--color-primary);
    outline: 0;
    box-shadow: 0 0 0 0.25rem rgba(13, 148, 136, 0.25);
}

.ui-check-input:checked {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
}

.ui-check-input[type="checkbox"] {
    border-radius: 0.25em;
}

/* Add-to-list modal checkboxes are styled by the Tailwind component layer
   (.vocab-list-row / .vocab-list-checkbox in assets/css/tailwind/input.css).
   .list-checkbox itself is now only a hook: static/js/reviews/ItemDetailModal.js
   reads the reader's checked lists from it. */

/* Custom switch styling â€“ clean white circle knob, no checkmark */
.ui-switch {
    padding-left: 0;
}

.ui-switch .ui-check-input {
    width: 2.8em;
    height: 1.5em;
    margin-left: 0;
    background-image: none !important;
    border-radius: 2em;
    position: relative;
    cursor: pointer;
    background-color: var(--switch-track);
    border-color: var(--switch-track-border);
    margin-top: 0;
    appearance: none;
    -webkit-appearance: none;
    transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
}

.ui-switch .ui-check-input::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0.2em;
    width: 1.1em;
    height: 1.1em;
    background: #fff;
    border-radius: 50%;
    transform: translateY(-50%);
    transition: transform 0.2s ease-in-out;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}

.ui-switch .ui-check-input:checked {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
}

.ui-switch .ui-check-input:checked::after {
    transform: translateY(-50%) translateX(1.3em);
}

/* Navbar premium badge */
.navbar-premium-badge {
    cursor: default;
    pointer-events: none;
}

/* ========================================
   KINNAREE ACCENT UTILITIES
   ======================================== */

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

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



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

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

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









/* Warm card tint */


/* ========================================
   BOOTSTRAP CHECKED STATE FIX
   Prevent blue/red defaults on checked, active, and focused outline buttons
   ======================================== */

.ui-btn-check:checked + .ui-btn-outline-primary,
.ui-btn-check:active + .ui-btn-outline-primary,
.ui-btn-check:focus + .ui-btn-outline-primary,
.ui-btn-check:focus-visible + .ui-btn-outline-primary,
.ui-btn-outline-primary:active,
.ui-btn-outline-primary.active,
.ui-btn-outline-primary:focus,
.ui-btn-outline-primary.focus,
.ui-btn-outline-primary:focus-visible,
.ui-btn-outline-primary:active:focus,
.ui-btn-outline-primary:active:focus-visible,
.ui-btn-outline-primary:not(:disabled):not(.disabled):active,
.ui-btn-outline-primary:not(:disabled):not(.disabled).active,
.ui-btn-outline-primary.dropdown-toggle.show {
    background-color: var(--color-cta);
    border-color: var(--color-cta);
    color: #fff;
    box-shadow: 0 0 0 0.25rem rgba(245, 158, 11, 0.35) !important;
}

.ui-btn-outline-primary:focus-visible {
    outline: 0;
}

.empty-state-img {
    max-height: 120px;
}

/* ========================================
   MESSAGE TOASTS (showToast in main.js, _messages.html)
   ======================================== */

/* Soft card with a semantic edge stripe: white surface + slate hairline so it
   sits with the page cards, a 3px stripe and a tinted glyph disc carrying the
   meaning. No coloured header bar. Written as plain CSS on purpose â€” toasts are
   global chrome rendered by base.html on every page, and most pages never load
   the Tailwind bundle. Values match the Tailwind palette. */

.sg-toast-container {
    position: fixed;
    bottom: 1rem;
    right: 1rem;
    z-index: 1090;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: calc(100vw - 2rem);
}

/* A toast hosted inside an open <dialog> lives in the top layer. Lift it above
   the dialog footer so its confirmation never covers Close / primary actions. */
dialog.ui-dialog .sg-toast-container {
    bottom: 5.5rem;
}


.sg-toast {
    --sg-toast-accent: var(--ink-faint);
    --sg-toast-tint: var(--surface-hover);
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    width: 21.5rem;
    max-width: 100%;
    padding: 0.75rem 0.875rem 0.875rem;
    box-sizing: border-box;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--sg-toast-accent);
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.12), 0 2px 6px rgba(15, 23, 42, 0.06);
    animation: sg-toast-in 0.18s ease-out;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.sg-toast--success { --sg-toast-accent: var(--color-primary); --sg-toast-tint: var(--success-bg); }
.sg-toast--error   { --sg-toast-accent: var(--danger-accent); --sg-toast-tint: var(--danger-bg); }
.sg-toast--warning { --sg-toast-accent: var(--warning-accent); --sg-toast-tint: var(--warning-bg); }
.sg-toast--info    { --sg-toast-accent: var(--info-accent); --sg-toast-tint: #f0f9ff; }

.sg-toast--leaving {
    opacity: 0;
    transform: translateY(4px);
}

.sg-toast__icon {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 1.875rem;
    height: 1.875rem;
    border-radius: 999px;
    background: var(--sg-toast-tint);
    color: var(--sg-toast-accent);
    font-size: 0.9375rem;
}

.sg-toast__body {
    flex: 1 1 auto;
    min-width: 0;
}

.sg-toast__title {
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--ink);
}

.sg-toast__message {
    margin-top: 2px;
    font-size: 0.78125rem;
    line-height: 1.4;
    color: var(--ink-muted);
    overflow-wrap: anywhere;
}

.sg-toast__close {
    flex: 0 0 auto;
    padding: 2px;
    border: 0;
    background: none;
    color: var(--ink-subtle);
    font-size: 0.9375rem;
    line-height: 1;
    cursor: pointer;
    border-radius: 6px;
}

.sg-toast__close:hover {
    color: var(--ink-muted);
}

.sg-toast__close:focus-visible {
    outline: 2px solid var(--ink-subtle);
    outline-offset: 1px;
}

@keyframes sg-toast-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Dismiss countdown: a hairline that drains left-to-right over the toast's
   lifetime, so the auto-dismiss is predictable instead of a surprise. The
   duration is set by JS (scheduleToastDismiss) to match the timer exactly; a
   paused animation on hover is what makes the pause legible. */
.sg-toast__progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: var(--surface-hover);
}

.sg-toast__progress-bar {
    height: 100%;
    background: var(--sg-toast-accent);
    border-radius: 0 999px 999px 0;
    transform-origin: left center;
    animation-name: sg-toast-progress;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
    animation-duration: 3000ms;
}

@keyframes sg-toast-progress {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}

@media (prefers-reduced-motion: reduce) {
    .sg-toast {
        animation: none;
        transition: none;
    }

    .sg-toast__progress {
        display: none;
    }
}

/* ========================================
   HTMX LOADING FEEDBACK
   ======================================== */

/* htmx adds .htmx-request to the element driving the request â€” dim it for a
   consistent "working" state. Indicator elements (.htmx-indicator) must not
   be dimmed. */

.htmx-request:not(.htmx-indicator) {
    opacity: 0.65;
    transition: opacity 0.15s ease;
}

/* Hide indicators until their request runs. htmx 2 no longer injects these
   rules (htmx 1 did), so without them an .htmx-indicator element is visible
   permanently â€” a spinner that never stops. Both forms are needed: htmx puts
   .htmx-request on the requesting element and on the indicator itself. */

.htmx-indicator {
    opacity: 0;
    transition: opacity 0.2s ease-in;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
    opacity: 1;
}

/* Reusable inline spinner: give an element class="htmx-spinner htmx-indicator"
   and point an hx-indicator at it (or its parent form) â€” htmx toggles the
   .htmx-indicator visibility, this styles the spinner itself. */

.htmx-spinner {
    display: inline-block;
    width: 1.25rem;
    height: 1.25rem;
    border: 3px solid rgba(0, 0, 0, 0.15);
    border-top-color: var(--bs-primary);
    border-radius: 50%;
    animation: htmx-spin 0.8s linear infinite;
    vertical-align: middle;
}

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

/* Small preview chip for selected tags on the word create page (HTMX picker) */
.tag-preview-chip {
    font-size: 0.7em;
}

/* ========================================
   PREMIUM UPSELL MODAL
   ----------------------------------------
   The paywall dialog is included from base.html on every page, so it cannot
   depend on the Tailwind bundle (most pages do not load it, and loading it
   globally would override the --radius-* and --color-gray-* tokens this file
   owns). These plain-CSS pills mirror .action-primary / .action-quiet in
   assets/css/tailwind/input.css, as .review-btn-* already does â€” keep the
   values in sync rather than linking the bundle here.
   ======================================== */

.upsell-content {
    border: 1px solid var(--color-gray-200);
    border-radius: 1rem;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, .1), 0 8px 10px -6px rgba(0, 0, 0, .1);
}

.upsell-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 9999px;
    background-color: var(--success-bg);
    color: var(--color-emerald);
    font-size: 1.5rem;
}

.upsell-title {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--ink);
    margin-bottom: .5rem;
}

.upsell-text {
    font-size: .875rem;
    line-height: 1.5;
    color: var(--ink-faint);
    margin-bottom: 1.25rem;
}

.upsell-actions {
    display: grid;
    gap: .5rem;
}

.upsell-cta,
.upsell-dismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .375rem;
    width: 100%;
    padding: .625rem 1.25rem;
    border-radius: 9999px;
    font-size: .875rem;
    font-weight: 600;
    line-height: 1.25rem;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.upsell-cta {
    border: 0;
    background-color: var(--color-emerald);
    color: #fff;
}

.upsell-cta:hover,
.upsell-cta:focus {
    background-color: var(--color-emerald-dark);
    color: #fff;
}

/* A quiet pill's hover is the same neutral slate wash the rest of the app uses:
   the accent colour is reserved for state, not for the pointer. */
.upsell-dismiss {
    border: 1px solid var(--border);
    background-color: var(--surface);
    color: var(--ink-muted);
    font-weight: 500;
}

.upsell-dismiss:hover,
.upsell-dismiss:focus {
    border-color: var(--border-strong);
    background-color: var(--surface-hover);
    color: var(--ink-label);
}

.upsell-cta:focus-visible,
.upsell-dismiss:focus-visible {
    outline: 2px solid var(--color-emerald);
    outline-offset: 2px;
}

.upsell-foot {
    margin-top: .75rem;
    margin-bottom: 0;
    font-size: .75rem;
    color: var(--ink-subtle);
}

.upsell-foot .bi {
    color: var(--color-emerald);
}

/* ========================================
   ACHIEVEMENT TOAST
   ======================================== */

.achievement-toast-container {
    position: fixed;
    top: 80px;
    right: 16px;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    gap: 12px;
    pointer-events: none;
    max-width: 380px;
    width: calc(100vw - 32px);
}

.achievement-toast-container .achievement-toast {
    pointer-events: auto;
}

.achievement-toast {
    position: relative;
    border-radius: 16px;
    padding: 16px 18px;
    color: #fff;
    overflow: hidden;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15);
    animation: achievement-slide-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    transform-origin: top right;
    border: 1px solid rgba(255, 255, 255, 0.15);
}

.achievement-toast.hiding {
    animation: achievement-slide-out 0.35s cubic-bezier(0.55, 0, 1, 0.45) forwards;
}

/* Tier gradients */
.achievement-toast--bronze {
    background: linear-gradient(135deg, #8B5A2B 0%, #CD7F32 50%, #D4A574 100%);
}
.achievement-toast--silver {
    background: linear-gradient(135deg, #6B7280 0%, #9CA3AF 50%, #C0C0C0 100%);
}
.achievement-toast--gold {
    background: linear-gradient(135deg, #B45309 0%, #F59E0B 50%, #FCD34D 100%);
}
.achievement-toast--platinum {
    background: linear-gradient(135deg, #0F766E 0%, #14B8A6 50%, #5EEAD4 100%);
}

/* Shine overlay */
.achievement-toast::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 50%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.15), transparent);
    animation: achievement-shine 2.5s ease-in-out infinite;
    pointer-events: none;
}

.achievement-toast__content {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: flex-start;
    gap: 14px;
}

.achievement-toast__icon {
    font-size: 2.25rem;
    line-height: 1;
    flex-shrink: 0;
    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));
}

.achievement-toast__body {
    flex: 1;
    min-width: 0;
}

.achievement-toast__header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 2px;
}

.achievement-toast__name {
    font-weight: 700;
    font-size: 1rem;
    line-height: 1.3;
    text-shadow: 0 1px 2px rgba(0,0,0,0.25);
}

.achievement-toast__tier {
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.25);
    flex-shrink: 0;
}

.achievement-toast__xp {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.8rem;
    font-weight: 600;
    margin-top: 4px;
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.15);
}

.achievement-toast__description {
    font-size: 0.8rem;
    opacity: 0.9;
    margin-top: 6px;
    line-height: 1.4;
    text-shadow: 0 1px 1px rgba(0,0,0,0.15);
}

.achievement-toast__close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: none;
    background: rgba(0, 0, 0, 0.2);
    color: rgba(255, 255, 255, 0.8);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    line-height: 1;
    padding: 0;
    transition: background 0.2s ease, color 0.2s ease;
    z-index: 2;
}

.achievement-toast__close:hover {
    background: rgba(0, 0, 0, 0.35);
    color: #fff;
}

.achievement-toast__progress {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: rgba(0, 0, 0, 0.15);
    border-radius: 0 0 16px 16px;
    overflow: hidden;
}

.achievement-toast__progress-bar {
    height: 100%;
    background: rgba(255, 255, 255, 0.6);
    border-radius: 0 0 16px 16px;
    transform-origin: left;
    animation: achievement-progress 5s linear forwards;
}

@keyframes achievement-slide-in {
    from {
        opacity: 0;
        transform: translateX(120%) scale(0.9);
    }
    to {
        opacity: 1;
        transform: translateX(0) scale(1);
    }
}

@keyframes achievement-slide-out {
    from {
        opacity: 1;
        transform: translateX(0) scale(1);
    }
    to {
        opacity: 0;
        transform: translateX(120%) scale(0.9);
    }
}

@keyframes achievement-shine {
    0% { left: -100%; }
    40% { left: 150%; }
    100% { left: 150%; }
}

@keyframes achievement-progress {
    from { transform: scaleX(1); }
    to { transform: scaleX(0); }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce){
    .achievement-toast {
        animation: none;
        opacity: 1;
        transform: none;
    }
    .achievement-toast.hiding {
        animation: none;
        opacity: 0;
    }
    .achievement-toast::before {
        animation: none;
        display: none;
    }
    .achievement-toast__progress-bar {
        animation: none;
    }
}

/* Mobile */
@media (max-width: 576px){
    .achievement-toast-container {
        top: 70px;
        right: 12px;
        left: 12px;
        width: auto;
        max-width: none;
    }
    .achievement-toast {
        padding: 14px 16px;
    }
    .achievement-toast__icon {
        font-size: 1.75rem;
    }
}

/* ========================================
   MIGRATION COMPONENTS (P6.1)
   Local replacements for the few Bootstrap components still used by residual
   templates. Names are project-owned so the Bootstrap stylesheet can go away.
   ======================================== */

.ui-card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    word-wrap: break-word;
    background-color: var(--surface);
    background-clip: border-box;
    border: 0;
    border-radius: 0.75rem;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.075);
}

.ui-card-body {
    flex: 1 1 auto;
    padding: 1rem;
}

.ui-card-header,
.ui-card-footer {
    padding: 0.75rem 1rem;
    background-color: var(--surface-raised);
}

.ui-card-header {
    border-bottom: 1px solid var(--border);
    border-radius: 0.75rem 0.75rem 0 0;
}

.ui-card-footer {
    border-top: 1px solid var(--border);
    border-radius: 0 0 0.75rem 0.75rem;
}

.ui-badge {
    display: inline-block;
    padding: 0.35em 0.65em;
    font-size: 0.75em;
    font-weight: 700;
    line-height: 1;
    color: #fff;
    text-align: center;
    white-space: nowrap;
    vertical-align: baseline;
    border-radius: 0.375rem;
}

.ui-badge--primary { background-color: var(--color-primary); }
.ui-badge--secondary { background-color: var(--color-secondary); }
.ui-badge--success { background-color: var(--color-success, #10b981); }
.ui-badge--danger { background-color: var(--color-coral); color: var(--ink-on-danger); }
.ui-badge--warning { background-color: var(--color-cta); color: var(--warning-ink-on-solid); }
.ui-badge--info { background-color: var(--color-secondary); }
.ui-badge--light { background-color: var(--surface-raised); color: var(--ink-on-light); border: 1px solid var(--border); }
.ui-badge--white { background-color: var(--surface); color: var(--ink-on-light); border: 1px solid var(--border); }
.ui-badge--soft { background-color: var(--surface-hover); color: var(--ink-muted); }

/* Compact count pill that stays an intentional contrast chip in every theme:
   navy/white in light, raised surface/ink in dark (never a white island). */
.chip-contrast {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    background-color: var(--chip-contrast-bg);
    color: var(--chip-contrast-ink);
}

.ui-alert {
    position: relative;
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
    border: 1px solid transparent;
    border-radius: 0.75rem;
}

.ui-alert--info {
    color: var(--info-accent-alt);
    background-color: var(--color-teal-fade);
    border-color: var(--info-border);
}

.ui-alert--success {
    color: var(--success-ink);
    background-color: var(--color-emerald-fade);
    border-color: var(--success-border);
}

.ui-alert--warning {
    color: var(--warning-ink);
    background-color: var(--color-gold-fade);
    border-color: var(--warning-border);
}

.ui-alert--danger {
    color: var(--danger-ink);
    background-color: var(--color-coral-fade);
    border-color: var(--danger-border);
}

.ui-table {
    width: 100%;
    margin-bottom: 1rem;
    color: var(--ink-alt);
    vertical-align: top;
    border-color: var(--border-table);
    border-collapse: collapse;
}

.ui-table > :not(caption) > * > * {
    padding: 0.5rem;
    border-bottom: 1px solid var(--border-table);
}

.ui-table--sm > :not(caption) > * > * { padding: 0.25rem; }
.ui-table--hover > tbody > tr:hover > * { background-color: var(--wash-hover); }
.ui-table-wrap { overflow-x: auto; }

.ui-select {
    box-sizing: border-box;
    display: block;
    width: 100%;
    height: 2.5rem;
    padding: 0.5rem 2.25rem 0.5rem 0.75rem;
    font-size: 0.875rem;
    line-height: 1.25rem;
    color: var(--ink);
    background-color: var(--surface);
    /* The chevron is an SVG data-URI and cannot consume a custom property;
       html[data-theme="dark"] .ui-select at the end of this file re-states it. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2364748b' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
    background-position: right 0.7rem center;
    background-size: 1rem 1rem;
    background-repeat: no-repeat;
    border: 1px solid var(--border);
    border-radius: 0.75rem;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    appearance: none;
}

.ui-select:focus {
    border-color: var(--color-primary);
    outline: 0;
    box-shadow: 0 0 0 0.2rem var(--focus-ring);
}

.ui-check {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 1.5rem;
    padding-left: 0;
    margin-bottom: 0;
}

.ui-check-input {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
    accent-color: var(--color-primary);
}

.ui-check-label { cursor: pointer; }

/* ========================================
   UI PRIMITIVES (P6.1)
   Structural rules that previously came from Bootstrap. Project pages keep
   their existing visual overrides; these rules supply the layout and control
   chrome the framework used to provide.
   ======================================== */

.ui-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    padding: 0.5rem 0.9rem;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--ink);
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-color: var(--surface);
    border: 1px solid transparent;
    border-radius: 0.5rem;
    transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
        border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.ui-btn:disabled,
.ui-btn.disabled {
    opacity: 0.65;
    pointer-events: none;
}

.ui-btn-sm {
    padding: 0.25rem 0.55rem;
    font-size: 0.8125rem;
    border-radius: 0.4rem;
}

.ui-btn-lg {
    padding: 0.7rem 1.2rem;
    font-size: 1rem;
    border-radius: 0.6rem;
}

.ui-btn-primary,
.ui-btn-success {
    color: #fff;
    background-color: var(--color-success);
    border-color: var(--color-success);
}

.ui-btn-primary {
    background-color: var(--color-cta);
    border-color: var(--color-cta);
}

.ui-btn-primary:hover { background-color: var(--color-cta-dark); border-color: var(--color-cta-dark); }
.ui-btn-success:hover { background-color: var(--color-primary); border-color: var(--color-primary); }

.ui-btn-secondary {
    color: #fff;
    background-color: var(--color-secondary);
    border-color: var(--color-secondary);
}

.ui-btn-danger {
    color: #fff;
    background-color: var(--color-coral);
    border-color: var(--color-coral);
}

.ui-btn-warning {
    color: var(--warning-ink-on-solid);
    background-color: var(--color-cta);
    border-color: var(--color-cta);
}

.ui-btn-info {
    color: var(--ink);
    background-color: var(--color-teal-fade);
    border-color: var(--info-border);
}

.ui-btn-light {
    color: var(--ink);
    background-color: var(--surface-raised);
    border-color: var(--border);
}

.ui-btn-outline-secondary {
    color: var(--ink-muted);
    background-color: var(--surface);
    border-color: var(--border-strong);
}

.ui-btn-outline-secondary:hover {
    color: var(--ink);
    background-color: var(--surface-raised);
    border-color: var(--ink-subtle);
}

.ui-btn-outline-danger {
    color: var(--danger-ink-alt);
    background-color: var(--surface);
    border-color: var(--danger-border-strong);
}

.ui-btn-outline-danger:hover {
    color: #fff;
    background-color: var(--danger-ink-alt);
    border-color: var(--danger-ink-alt);
}

.ui-btn-group {
    position: relative;
    display: inline-flex;
    vertical-align: middle;
}

.ui-btn-group > .ui-btn:not(:first-child) {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    margin-left: -1px;
}

.ui-btn-group > .ui-btn:not(:last-child) {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

/* Bootstrap's visually-hidden checkbox pattern, now project-owned. */
.ui-btn-check {
    position: absolute;
    clip: rect(0, 0, 0, 0);
    pointer-events: none;
}

.ui-row {
    --ui-gutter-x: 1.5rem;
    --ui-gutter-y: 0;
    display: flex;
    flex-wrap: wrap;
    margin-top: calc(-1 * var(--ui-gutter-y));
    margin-right: calc(-0.5 * var(--ui-gutter-x));
    margin-left: calc(-0.5 * var(--ui-gutter-x));
}

.ui-row > * {
    flex-shrink: 0;
    width: 100%;
    max-width: 100%;
    padding-right: calc(var(--ui-gutter-x) * 0.5);
    padding-left: calc(var(--ui-gutter-x) * 0.5);
    margin-top: var(--ui-gutter-y);
}

.ui-g-0 { --ui-gutter-x: 0; --ui-gutter-y: 0; }
.ui-g-1 { --ui-gutter-x: 0.25rem; --ui-gutter-y: 0.25rem; }
.ui-g-2 { --ui-gutter-x: 0.5rem; --ui-gutter-y: 0.5rem; }
.ui-g-3 { --ui-gutter-x: 1rem; --ui-gutter-y: 1rem; }
.ui-g-4 { --ui-gutter-x: 1.5rem; --ui-gutter-y: 1.5rem; }
.ui-g-5 { --ui-gutter-x: 3rem; --ui-gutter-y: 3rem; }

.ui-col,
.ui-col-1, .ui-col-2, .ui-col-3, .ui-col-4, .ui-col-6, .ui-col-8, .ui-col-12 { flex: 0 0 auto; }
.ui-col { flex: 1 0 0%; }
.ui-col-1 { width: 8.33333333%; }
.ui-col-2 { width: 16.66666667%; }
.ui-col-3 { width: 25%; }
.ui-col-4 { width: 33.33333333%; }
.ui-col-6 { width: 50%; }
.ui-col-8 { width: 66.66666667%; }
.ui-col-12 { width: 100%; }

/* `.ui-col` is `flex: 1 0 0%`, so width alone cannot cap a row-cols grid: a
   0-basis column would shrink all 8 cards onto one line. Reset the basis with
   the width, exactly as Bootstrap's `.row-cols-*` did. */
.ui-row-cols-1 > * { flex: 0 0 auto; width: 100%; }
.ui-row-cols-2 > * { flex: 0 0 auto; width: 50%; }

@media (min-width: 576px) {
    .ui-col-sm-6 { width: 50%; }
    .ui-row-cols-sm-2 > * { flex: 0 0 auto; width: 50%; }
}

@media (min-width: 768px) {
    .ui-col-md-1 { width: 8.33333333%; }
    .ui-col-md-2 { width: 16.66666667%; }
    .ui-col-md-3 { width: 25%; }
    .ui-col-md-4 { width: 33.33333333%; }
    .ui-col-md-6 { width: 50%; }
    .ui-col-md-8 { width: 66.66666667%; }
    .ui-col-md-10 { width: 83.33333333%; }
    .ui-col-md-12 { width: 100%; }
    .ui-row-cols-md-3 > * { flex: 0 0 auto; width: 33.33333333%; }
}

@media (min-width: 992px) {
    .ui-col-lg-3 { width: 25%; }
    .ui-col-lg-4 { width: 33.33333333%; }
    .ui-col-lg-5 { width: 41.66666667%; }
    .ui-col-lg-6 { width: 50%; }
    .ui-col-lg-7 { width: 58.33333333%; }
    .ui-col-lg-8 { width: 66.66666667%; }
    .ui-row-cols-lg-4 > * { flex: 0 0 auto; width: 25%; }
}

.ui-control {
    display: block;
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 1rem;
    line-height: 1.5;
    color: var(--ink);
    background-color: var(--surface);
    border: 1px solid var(--border-input);
    border-radius: 0.375rem;
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.ui-control:focus {
    border-color: var(--color-primary);
    outline: 0;
    box-shadow: 0 0 0 0.2rem var(--focus-ring);
}

.ui-label {
    display: inline-block;
    margin-bottom: 0.5rem;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--ink-label);
}

.ui-field-error {
    display: block;
    margin-top: 0.35rem;
    font-size: 0.875rem;
    color: var(--danger-ink-alt);
}

.ui-badge--pill {
    border-radius: 50rem;
}

/* ========================================
   RESIDUAL PRESENTATION UTILITIES (P6.1)
   These names are still present in a few older templates but no longer depend
   on the Bootstrap stylesheet. They are pure presentation helpers; semantic
   components above use project-owned classes.
   ======================================== */

.container,
.container-md,
.container-lg {
    width: 100%;
    max-width: 1320px;
    margin-right: auto;
    margin-left: auto;
    padding-right: 0.75rem;
    padding-left: 0.75rem;
}

.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

.small { font-size: 0.875em; }
.lead { font-size: 1.25rem; font-weight: 300; }
.text-center { text-align: center !important; }
.text-end { text-align: right !important; }
.text-start { text-align: left !important; }
.text-uppercase { text-transform: uppercase !important; }
.text-decoration-none { text-decoration: none !important; }
.text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.text-secondary { color: var(--ink-faint) !important; }
.align-middle { vertical-align: middle !important; }
.align-items-center { align-items: center !important; }
.align-items-start { align-items: flex-start !important; }
.align-items-baseline { align-items: baseline !important; }
.align-items-end { align-items: flex-end !important; }
.justify-content-center { justify-content: center !important; }
.justify-content-between { justify-content: space-between !important; }
.justify-content-end { justify-content: flex-end !important; }
.flex-fill { flex: 1 1 auto !important; min-width: 0; }
.flex-wrap { flex-wrap: wrap !important; }
.flex-column { flex-direction: column !important; }
.d-grid { display: grid !important; }
.mx-auto { margin-left: auto !important; margin-right: auto !important; }
.flex-row { flex-direction: row !important; }
.flex-grow-1 { flex-grow: 1 !important; }
.flex-shrink-0 { flex-shrink: 0 !important; }
.d-grid { display: grid !important; }
.position-relative { position: relative !important; }
.h-100 { height: 100% !important; }
.w-100 { width: 100% !important; }
.border { border: 1px solid var(--border) !important; }
.rounded { border-radius: 0.375rem !important; }
.rounded-4 { border-radius: 1rem !important; }
.shadow { box-shadow: 0 0.5rem 1rem rgba(15, 23, 42, 0.15) !important; }
.shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(15, 23, 42, 0.075) !important; }
.bg-light { background-color: var(--surface-raised) !important; }
.opacity-50 { opacity: 0.5 !important; }
.font-monospace { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace !important; }

.fs-1 { font-size: calc(1.375rem + 1.5vw) !important; }
.fs-2 { font-size: calc(1.325rem + 0.9vw) !important; }
.fs-3 { font-size: calc(1.3rem + 0.6vw) !important; }
.fs-4 { font-size: calc(1.275rem + 0.3vw) !important; }
.fs-5 { font-size: 1.25rem !important; }
.fs-6 { font-size: 1rem !important; }
.display-1 { font-size: calc(1.625rem + 4.5vw); font-weight: 300; line-height: 1.2; }
.display-2 { font-size: calc(1.575rem + 3.9vw); font-weight: 300; line-height: 1.2; }
.display-3 { font-size: calc(1.525rem + 3.3vw); font-weight: 300; line-height: 1.2; }
.display-4 { font-size: calc(1.475rem + 2.7vw); font-weight: 300; line-height: 1.2; }
.display-5 { font-size: calc(1.425rem + 2.1vw); font-weight: 300; line-height: 1.2; }
.display-6 { font-size: calc(1.375rem + 1.5vw); font-weight: 300; line-height: 1.2; }
.h1, h1 { font-size: calc(1.375rem + 1.5vw); font-weight: 600; line-height: 1.2; }
.h2, h2 { font-size: calc(1.325rem + 0.9vw); font-weight: 600; line-height: 1.2; }
.h3, h3 { font-size: calc(1.3rem + 0.6vw); font-weight: 600; line-height: 1.2; }
.h4, h4 { font-size: calc(1.275rem + 0.3vw); font-weight: 600; line-height: 1.2; }
.h5, h5 { font-size: 1.25rem; font-weight: 600; line-height: 1.2; }
.h6, h6 { font-size: 1rem; font-weight: 600; line-height: 1.2; }

.p-0 { padding: 0 !important; }
.p-1 { padding: 0.25rem !important; }
.p-2 { padding: 0.5rem !important; }
.p-3 { padding: 1rem !important; }
.p-4 { padding: 1.5rem !important; }
.p-5 { padding: 3rem !important; }
.px-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; }
.px-3 { padding-left: 1rem !important; padding-right: 1rem !important; }
.px-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; }
.py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; }
.py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; }
.py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; }
.py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; }
.py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; }
.pt-4 { padding-top: 1.5rem !important; }
.pb-4 { padding-bottom: 1.5rem !important; }

@media (min-width: 768px) {
    .p-md-4 { padding: 1.5rem !important; }
    .p-md-5 { padding: 3rem !important; }
    .mb-md-0 { margin-bottom: 0 !important; }
    .flex-md-row { flex-direction: row !important; }
}

/* Tables remain plain semantic tables; this supplies the Bootstrap rhythm. */
.table {
    width: 100%;
    margin-bottom: 1rem;
    color: var(--ink-alt);
    vertical-align: top;
    border-color: var(--border-table);
    border-collapse: collapse;
}
.table > :not(caption) > * > * {
    padding: 0.5rem;
    border-bottom: 1px solid var(--border-table);
}
.table-light > :not(caption) > * > * { background-color: var(--surface-raised); }
.table-light > tr > th,
.table-light > tr > td { background-color: var(--surface-raised); }
.table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.spinner-border {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    vertical-align: -0.125em;
    border: 0.25em solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: ui-spinner-border 0.75s linear infinite;
}
.spinner-border-sm { width: 1rem; height: 1rem; border-width: 0.2em; }
@keyframes ui-spinner-border { to { transform: rotate(360deg); } }

.fade { transition: opacity 0.15s linear; }
.fade:not(.show) { opacity: 0; }
.collapse:not(.show) { display: none; }

.nav { display: flex; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; }
.nav-item { display: list-item; }
.nav-link { display: block; padding: 0.5rem 1rem; color: var(--color-primary); text-decoration: none; }
.nav-pills { display: flex; flex-wrap: wrap; gap: 0.25rem; padding-left: 0; margin-bottom: 0; list-style: none; }
.nav-pills .nav-link {
    display: block;
    padding: 0.5rem 1rem;
    color: var(--color-primary);
    text-decoration: none;
    background: transparent;
    border: 0;
    border-radius: 0.375rem;
    cursor: pointer;
    font: inherit;
}
.nav-pills .nav-link:hover { background-color: var(--surface-hover); }
.nav-pills .nav-link.active { color: var(--ink-on-accent); background-color: var(--color-primary); }
.tab-content > .tab-pane { display: none; }
.tab-content > .active { display: block; }

.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    padding: 0;
    margin: 0 0 1rem;
    list-style: none;
}
.breadcrumb-item + .breadcrumb-item::before {
    content: "/";
    padding: 0 0.5rem;
    color: var(--ink-faint);
}
.breadcrumb-item.active { color: var(--ink-faint); }

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    margin-top: 0;
    margin-bottom: 0.5rem;
}

p {
    margin-top: 0;
    margin-bottom: 1rem;
}

.dropdown-toggle::after {
    display: inline-block;
    margin-left: 0.35em;
    vertical-align: 0.2em;
    content: "";
    border-top: 0.3em solid;
    border-right: 0.3em solid transparent;
    border-bottom: 0;
    border-left: 0.3em solid transparent;
}

/* Legacy Bootstrap modal markup still emitted inside the review item detail
   dialog. Native dialogs use <dialog class="ui-dialog"> and are unaffected. */
.modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1055;
    overflow-x: hidden;
    overflow-y: auto;
    outline: 0;
}

.modal.show {
    display: block;
}

/* ========================================
   DARK THEME - COMPONENT OVERRIDES
   What tokens cannot reach: dark ink on bright accent fills, and the
   select chevron (an SVG data-URI cannot consume a custom property).
   See docs/THEMES.md.
   ======================================== */
html[data-theme="dark"] .ui-select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23B0BDB3' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
}

/* Bright accent fills carry the theme's dark accent-ink in dark mode. */
html[data-theme="dark"] .ui-btn-primary,
html[data-theme="dark"] .ui-btn-primary:hover,
html[data-theme="dark"] .ui-btn-primary:focus,
html[data-theme="dark"] .ui-btn-primary:active,
html[data-theme="dark"] .ui-btn-success,
html[data-theme="dark"] .ui-btn-success:hover,
html[data-theme="dark"] .ui-btn-secondary,
html[data-theme="dark"] .ui-btn-secondary:hover,
html[data-theme="dark"] .upsell-cta,
html[data-theme="dark"] .upsell-cta:hover,
html[data-theme="dark"] .upsell-cta:focus,
html[data-theme="dark"] .nav-signup,
html[data-theme="dark"] .nav-signup:hover,
html[data-theme="dark"] .nav-signup:focus-visible,
html[data-theme="dark"] .ui-badge--primary,
html[data-theme="dark"] .ui-badge--secondary,
html[data-theme="dark"] .ui-badge--success,
html[data-theme="dark"] .ui-badge--info,
html[data-theme="dark"] .ui-btn-outline-primary:hover,
html[data-theme="dark"] .ui-btn-check:checked + .ui-btn-outline-primary,
html[data-theme="dark"] .ui-btn-check:checked + .ui-btn-outline-secondary,
html[data-theme="dark"] .ui-btn-check:checked + .ui-btn-outline-success,
html[data-theme="dark"] .ui-btn-check:checked + .ui-btn-outline-danger {
    color: var(--ink-on-accent);
}

html[data-theme="dark"] .ui-btn-primary:focus,
html[data-theme="dark"] .ui-btn-primary:active {
    color: var(--ink-on-accent) !important;
}

/* Badges pinned on the coral accent keep a readable dark ink. */
html[data-theme="dark"] .nav-bell__badge,
html[data-theme="dark"] .nav-user__badge,
html[data-theme="dark"] .nav-menu__badge {
    color: var(--ink-on-danger);
}

html[data-theme="dark"] .ui-btn-outline-danger:hover {
    color: var(--ink-on-danger);
}

/* Stroke-order animations draw dark ink; the page inverts their SVG and keeps
   the canvas on the page surface instead of a white block. */
html[data-theme="dark"] .stroke-order-mini {
    background: var(--surface-raised);
    border-color: var(--border);
}

html[data-theme="dark"] .stroke-replay-sm {
    background: var(--surface);
    color: var(--ink-muted);
}

/* ========================================
   THEME PREFERENCE CONTROLS
   Light/dark/system: the segmented group on Settings and the compact
   three-button group in the profile dropdown. Both are plain form submits â€”
   the page reload re-renders data-theme and the selected state.
   ======================================== */

/* The navbar renders both wordmark assets; CSS picks one. The dark wordmark
   is the same mascot with an ivory wordmark, so it stays legible on dark.
   Selectors are scoped through .site-nav__brand so they outrank the base
   `.site-nav__brand picture { display: block }` rule. */
.site-nav__brand picture.site-nav__logo-set--dark {
    display: none;
}

html[data-theme="dark"] .site-nav__brand picture.site-nav__logo-set--light {
    display: none;
}

html[data-theme="dark"] .site-nav__brand picture.site-nav__logo-set--dark {
    display: block;
}

.theme-choice-group {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    background-color: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: 999px;
}

.theme-choice {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    border: 0;
    border-radius: 999px;
    background-color: transparent;
    color: var(--ink-muted);
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.2;
    padding: 0.4rem 0.75rem;
    cursor: pointer;
}

.theme-choice:hover {
    color: var(--ink);
    background-color: var(--wash-hover);
}

.theme-choice__icon {
    flex: none;
    width: 15px;
    height: 15px;
}

.theme-choice:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 2px;
}

.theme-choice.is-active,
.theme-choice.is-active:hover {
    background-color: var(--color-primary);
    color: var(--ink-on-accent);
}

/* Compact variant inside the profile dropdown. */
.nav-theme {
    padding: 0.35rem 0.75rem 0.5rem;
}

.nav-theme__head {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin-bottom: 0.35rem;
    color: var(--ink-faint);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.nav-theme__choices {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.25rem;
    padding: 0.2rem;
    background-color: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: 0.55rem;
}

.nav-theme__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 0.4rem;
    background-color: transparent;
    color: var(--ink-faint);
    font-size: 0.95rem;
    padding: 0.4rem 0;
    cursor: pointer;
}

.nav-theme__btn svg {
    width: 16px;
    height: 16px;
}

.nav-theme__btn:hover {
    background-color: var(--surface-hover);
    color: var(--ink);
}

.nav-theme__btn:focus-visible {
    outline: 2px solid var(--focus-outline);
    outline-offset: 1px;
}

.nav-theme__btn.is-active,
.nav-theme__btn.is-active:hover {
    background-color: var(--color-primary);
    color: var(--ink-on-accent);
}

/* Error pages (404/500) reuse the kit's Tailwind classes; without these the
   dark canvas keeps the light-only emerald-700 and slate-500 inks. */
html[data-theme="dark"] .error-code {
    color: var(--color-primary);
}

html[data-theme="dark"] .error-copy {
    color: var(--ink-muted);
}

/* Course rail meta sits on a tinted active row; slate-400 falls to 3.57:1. */
html[data-theme="dark"] .course-rail__meta {
    color: var(--ink-muted);
}

html[data-theme="dark"] .badge-progress__label {
    color: var(--color-gray-500);
}
