/* ==========================================================================
   Prüfungsmeister Design System
   Light: white/near-white surfaces + soft shadows + deep forest green accent
          (UI_UX_GUIDELINES.md §2 target, migrated 2026-08-05).
   Dark : the same brand system on a deep green-black field — forest-green
          primary, cream ink, gold kept to badge/headline accents
          (see body.dark-theme below).
   Philosophy: Apple / Linear / editorial premium. No pure black. Hairline borders,
   near-zero radius, soft low-spread shadows. Accent var names kept for compat.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Self-hosted brand typefaces (no-CDN policy: served from /fonts by server.py).
   Until 2026-08-20 these families were declared in the stacks below but never
   shipped, so every user rendered the fallback system fonts. Variable WOFF2s,
   subset to Latin + Latin-Extended-A (covers German incl. ä ö ü ß ẞ and the
   typographic punctuation/arrows the UI uses). font-display: swap keeps first
   paint instant on weak connections; the layout was designed on metric-similar
   fallbacks, so the swap is not jarring.
   -------------------------------------------------------------------------- */
@font-face {
    font-family: 'Space Grotesk';
    src: url('fonts/SpaceGrotesk.woff2') format('woff2');
    font-weight: 300 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Inter';
    src: url('fonts/Inter.woff2') format('woff2');
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Inter';
    src: url('fonts/Inter-Italic.woff2') format('woff2');
    font-weight: 400 900;
    font-style: italic;
    font-display: swap;
}
@font-face {
    font-family: 'JetBrains Mono';
    src: url('fonts/JetBrainsMono.woff2') format('woff2');
    font-weight: 400 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'EB Garamond';
    src: url('fonts/EBGaramond.woff2') format('woff2');
    font-weight: 400 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'EB Garamond';
    src: url('fonts/EBGaramond-Italic.woff2') format('woff2');
    font-weight: 400 800;
    font-style: italic;
    font-display: swap;
}
/* The same italic serif, cut down to the four letters the landing page
   decorates itself with (.ld-fl-glyph in content/public/landing.html - eight
   spans, four distinct characters).
   Declared last so it wins for those characters, and given a unicode-range so
   a browser fetches it INSTEAD of the 133 KB file above when a page renders
   nothing else in italic serif - which is exactly the landing page's case.
   3.9 KB rather than 133 KB, for identical pixels.

   The range below must list EVERY character that markup renders. It listed
   three at first and the markup uses four; the browser dutifully fetched the
   full 133 KB face for the missing one and the saving silently evaporated.
   tools/build_fonts.py prints the correct range - run it after touching those
   spans and paste what it says.

   The alternative was to drop the italic or fall back to a system serif, and
   both were rejected: styles.css's paper-serif note (search --font-paper)
   records that EB Garamond is self-hosted precisely so this face stops drifting
   between Iowan on Mac, Book Antiqua on Windows and DejaVu on Linux.

   Pages that DO set other italic serif text (the paper correction cards) fetch
   both files, which costs them 3.5 KB. That is the trade, and it is the right
   way round: the landing page is the one every visitor loads. */
@font-face {
    font-family: 'EB Garamond';
    src: url('fonts/EBGaramond-Italic-Deco.woff2') format('woff2');
    font-weight: 400 800;
    font-style: italic;
    font-display: swap;
    unicode-range: U+00DF, U+00E4, U+00F6, U+00FC;
}

:root {
    /* Color Palette — white / near-white with warm-neutral hairlines */
    --bg-main: #FAFAF9;            /* page background — near-white */
    --bg-surface: #FFFFFF;         /* cards / surfaces — white */
    --bg-surface-elevated: #F5F5F4;
    --bg-surface-hover: #F0EFED;
    --bg-card: #FFFFFF;
    --bg-input: #FFFFFF;

    --border-color: #E7E5E1;       /* light warm-neutral hairline */
    --border-color-focus: #0F4C3A;

    /* Text Colors — warm neutrals */
    --text-primary: #202020;       /* warm near-black */
    --text-secondary: #57534A;     /* warm gray */
    --text-muted: #8A857B;

    /* Brand Accents — deep forest green (jeetjalu brand) */
    --accent-indigo: #0F4C3A;      /* primary brand (name kept for compat) */
    --accent-purple: #0F4C3A;      /* was generic green; unified to forest */
    --accent-strong: #0B3A2C;
    --on-accent: #F3EFE6;          /* text/icon colour on filled accent */
    --accent-gradient: linear-gradient(135deg, #0F4C3A 0%, #0B3A2C 100%);
    --accent-gradient-hover: linear-gradient(135deg, #0B3A2C 0%, #082A20 100%);
    /* Landing page final CTA band: a wider dark-to-light spread than the
       buttons' --accent-gradient (whose two stops are close enough to read
       as a flat fill at banner size) - dark top-left to light bottom-right. */
    --cta-band-gradient: linear-gradient(135deg, #0B3A2C 0%, #2E8763 100%);

    /* Feedback Colors */
    --success: #0F4C3A;
    --success-bg: rgba(15, 76, 58, 0.08);
    --warning: #9A6B14;
    --warning-bg: rgba(154, 107, 20, 0.08);
    --error: #A83A28;
    --error-bg: rgba(168, 58, 40, 0.08);
    --info: #0F4C3A;
    --info-bg: rgba(15, 76, 58, 0.07);

    /* Typography — Space Grotesk (display) + Inter (body): modern, engineered,
       Linear/Arc-grade premium. Shared by light and dark themes. */
    --font-heading: 'Space Grotesk', 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --font-body: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, monospace;

    /* Layout Constants — soft liquid-glass corners (2026-08-08 glass
       evolution, user-approved via design preview: original palette kept,
       morphism added). Matches the 6-16px the shipped screens already used
       inline; the old 2-4px "sharp editorial" scale is retired. */
    --sidebar-width: 260px;
    --header-height: 64px;
    --border-radius-sm: 8px;
    --border-radius-md: 10px;
    --border-radius-lg: 12px;
    --border-radius-xl: 16px;

    /* Glassmorphism tokens — light theme. The tint pair lets components
       build accent-tinted highlights without hardcoding rgba() of the brand
       color at call sites (dark theme overrides both). */
    --glass-bg: rgba(255, 255, 255, 0.70);
    --glass-rim: rgba(255, 255, 255, 0.95);   /* 1px light-catch on top edges */
    --glass-blur: 16px;
    --accent-tint: rgba(15, 76, 58, 0.08);    /* forest green wash */
    --accent-tint-border: rgba(15, 76, 58, 0.40);

    /* Transitions & Shadows — soft, low-spread elevation on white surfaces.
       Shadow base #101828 matches design-system.css's --e-* elevation scale
       (one shadow language across both files, cool-neutral per its lineage). */
    --transition-smooth: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.05), 0 3px 10px rgba(16, 24, 40, 0.07);
    --shadow-md: 0 2px 4px rgba(16, 24, 40, 0.05), 0 8px 20px rgba(16, 24, 40, 0.10);
    --shadow-premium: 0 2px 4px rgba(16, 24, 40, 0.05), 0 12px 28px -6px rgba(16, 24, 40, 0.12);
    --shadow-glow: none;
}

/* ==========================================================================
   Base resets & layouts
   ========================================================================== */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body {
    background-color: var(--bg-main);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 15px;
    line-height: 1.6;
    overflow-x: hidden;
    min-height: 100vh;
}

/* Device controls container (Floating tester controls) */
/* Legacy device-frame toolbar — removed. The rules below are dead weight kept for
   any residual markup; safe to delete when nothing else references them. */
#device-controls, .controls-container, .controls-label, .device-btn { display: none !important; }

.__legacy_device_btn_dead {
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-secondary);
    padding: 6px 14px;
    border-radius: 99px;
    font-size: 13px;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.__legacy_device_btn_dead svg {
    width: 14px;
    height: 14px;
}

.__legacy_device_btn_dead:hover {
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.03);
}

.__legacy_device_btn_dead.__active {
    color: #fff;
    background: var(--accent-gradient);
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
}

/* Real viewport — fills the actual window. The old rule constrained everything
   inside a 1440×[100vh-130px] fake "device" centred on a 90px top margin, which
   is why the app felt like it "took whole screen space" without using it. */
#app-viewport {
    width: 100%;
    min-height: 100vh;
    background-color: var(--bg-main);
    /* Faint warm glows give the light glass something to frost over —
       without them translucent cards read as plain grey. Dark theme
       overrides this with its own green-black field (scoped rule below). */
    background-image:
        radial-gradient(680px 400px at 22% -8%, rgba(15, 76, 58, 0.05), transparent 62%),
        radial-gradient(520px 320px at 88% 22%, rgba(154, 107, 20, 0.04), transparent 65%);
    background-attachment: fixed;
    position: relative;
}

/* Scrollbars */
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
::-webkit-scrollbar-track {
    background: transparent;
}
::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.2);
}

/* ==========================================================================
   Layout Shell
   ========================================================================== */
.layout-wrapper {
    display: none;
    width: 100%;
    height: 100%;
}

.layout-wrapper.active {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

#public-content {
    flex: 1;
    width: 100%;
}

#app-layout {
    display: none;
    flex-direction: row;
}

#app-layout.active {
    display: flex;
    min-height: 100vh;
}

/* Public Header (Landing & Login Navbar) */
.public-header {
    height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 40px;
    border-bottom: 1px solid var(--border-color);
    background: rgba(248, 249, 251, 0.95);
    backdrop-filter: blur(20px);
    position: sticky;
    top: 0;
    z-index: 100;
}

.header-logo {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 18px;
    letter-spacing: -0.02em;
}

.logo-icon {
    width: 32px;
    height: 32px;
    background: var(--accent-gradient);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 18px;
    font-weight: 800;
    box-shadow: 0 2px 8px rgba(30, 58, 95, 0.15);
}

.logo-icon.small {
    width: 24px;
    height: 24px;
    font-size: 14px;
    border-radius: 6px;
}

.badge-premium {
    font-size: 9px;
    font-weight: 700;
    background: var(--warning-bg);
    color: var(--warning);
    border: 1px solid rgba(200, 155, 60, 0.15);
    padding: 1px 5px;
    border-radius: 4px;
    vertical-align: middle;
    margin-left: 4px;
    text-transform: uppercase;
}

.public-nav {
    display: flex;
    align-items: center;
    gap: 24px;
}

.public-nav a {
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 14px;
    font-weight: 500;
    transition: var(--transition-smooth);
}

.public-nav a:hover {
    color: var(--text-primary);
}

.btn-login-nav {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    padding: 8px 18px;
    border-radius: var(--border-radius-sm);
    color: var(--text-primary) !important;
}

.btn-login-nav:hover {
    background: var(--bg-surface-hover);
    border-color: var(--text-muted);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

/* App Sidebar (Notion/Linear Inspired) */
.app-sidebar {
    width: var(--sidebar-width);
    border-right: 1px solid var(--border-color);
    background: rgba(255, 255, 255, 0.78);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    display: flex;
    flex-direction: column;
    height: 100%;
    flex-shrink: 0;
    transition: var(--transition-smooth);
}

.sidebar-header {
    height: var(--header-height);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 20px;
    cursor: pointer;
}

.brand-lockup {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
    line-height: 1.2;
}

.logo-text {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 17px;
    letter-spacing: -0.02em;
    color: var(--text-primary);
    white-space: nowrap;
}

.brand-tagline {
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent-indigo);
    white-space: nowrap;
}

.sidebar-user-section {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 10px 16px 20px;
    padding: 10px 12px;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
}

.user-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--accent-gradient);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 13px;
    color: white;
}

.user-info {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.user-name {
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

.user-level-badge {
    font-size: 10px;
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    gap: 4px;
}

.sidebar-nav {
    flex: 1;
    overflow-y: auto;
    padding: 0 12px;
}

.nav-group-title {
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin: 24px 0 8px 12px;
    font-family: var(--font-body);
}

.sidebar-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 12px;
    color: var(--text-secondary);
    text-decoration: none;
    border-radius: var(--border-radius-md);
    /* Reserve the accent-rail space so activating a link never shifts its text */
    border-left: 2px solid transparent;
    font-size: 13.5px;
    font-weight: 500;
    margin-bottom: 1px;
    transition: var(--transition-smooth);
}

.sidebar-link svg {
    width: 16px;
    height: 16px;
    stroke-width: 1.75;
}

.sidebar-link:hover {
    color: var(--text-primary);
    background: var(--bg-surface-elevated);
}

.sidebar-link.active {
    color: var(--accent-indigo);
    background: var(--info-bg);
    border-left-color: var(--accent-indigo);
    font-weight: 600;
}

.sidebar-count {
    margin-left: auto;
    background: var(--warning-bg);
    color: var(--warning);
    font-size: 10.5px;
    font-weight: 600;
    font-family: var(--font-mono);
    padding: 1px 6px;
    border-radius: var(--border-radius-sm);
}

.sidebar-footer {
    padding: 16px 20px;
    border-top: 1px solid var(--border-color);
}

.sidebar-logout {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 13px;
    transition: var(--transition-smooth);
}

.sidebar-logout:hover {
    color: var(--error);
}

.sidebar-logout svg {
    width: 16px;
    height: 16px;
}

/* App Main Body */
.app-main {
    display: flex;
    flex-direction: column;
    flex: 1;
    overflow: hidden;
    height: 100%;
}

.app-header {
    height: var(--header-height);
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 24px;
    background: rgba(255, 255, 255, 0.72);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
}

.mobile-sidebar-toggle {
    display: none;
    background: transparent;
    border: none;
    /* Was hardcoded white - invisible against the light theme's near-white
       header (found in the same mobile audit as the grid !important fix
       above: the hamburger was in the DOM and clickable, just not visible,
       so a phone user had no apparent way to reach the sidebar at all).
       Tokenized so it stays visible in dark mode too. */
    color: var(--text-primary);
    cursor: pointer;
}

.app-header-title h2 {
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 15px;
    letter-spacing: -0.01em;
}

.app-header-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Interface language toggle (Deutsch / English). Sits next to the theme
   toggle in both the public header and the app header. The label shows the
   language you would switch TO, so it reads as an action, not a status. */
.lang-toggle-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-secondary);
    cursor: pointer;
    padding: 5px 9px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1;
    outline: none;
    transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.lang-toggle-btn:hover {
    color: var(--accent-indigo);
    border-color: var(--accent-indigo);
    background: var(--bg-surface-hover);
}
.lang-toggle-btn:focus-visible {
    border-color: var(--border-color-focus);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-indigo) 25%, transparent);
}
.lang-toggle-btn i,
.lang-toggle-btn svg {
    width: 15px;
    height: 15px;
}
.public-nav .lang-toggle-btn {
    margin-left: 12px;
    vertical-align: middle;
}

.streak-indicator {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--warning-bg);
    border: 1px solid var(--border-color);
    padding: 5px 10px;
    border-radius: var(--border-radius-md);
    font-size: 12.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--warning);
}

.xp-badge {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--info-bg);
    border: 1px solid var(--border-color);
    padding: 5px 10px;
    border-radius: var(--border-radius-md);
    font-size: 12.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--accent-indigo);
}

.xp-badge svg {
    width: 14px;
    height: 14px;
    fill: var(--accent-indigo);
}

.app-content-container {
    flex: 1;
    overflow-y: auto;
    padding: 32px;
}

/* A readable measure: content centers instead of stretching edge-to-edge on
   wide screens. Exam mode opts out — the simulator owns its own full-bleed
   layout and must keep exact Goethe-like framing. */
.app-content-container > * {
    max-width: 1180px;
    margin-left: auto;
    margin-right: auto;
}

.exam-mode-active .app-content-container > * {
    max-width: none;
}

/* ==========================================================================
   UI Components (Notion/Linear elements)
   ========================================================================== */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 20px;
    margin-bottom: 24px;
}

.glass-card {
    /* Real light-mode glass (2026-08-08): translucent white over the warm
       backdrop glows, frosted, with a bright light-catch on the top edge.
       Dark theme keeps its own scoped glass treatment further down. */
    background: var(--glass-bg);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    padding: 24px;
    box-shadow: var(--shadow-premium), inset 0 1.5px 0 var(--glass-rim);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    transition: var(--transition-smooth);
}

.glass-card:hover {
    border-color: var(--border-color-focus);
}

/* Legibility beats effect: when blur isn't available, or the user asked for
   reduced transparency, glass falls back to solid surfaces. */
@supports not (backdrop-filter: blur(1px)) {
    .glass-card { background: var(--bg-surface); }
}
@media (prefers-reduced-transparency: reduce) {
    .glass-card {
        background: var(--bg-surface);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
}

.card-title-sec {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 11.5px;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.card-title-sec svg {
    width: 15px;
    height: 15px;
}

/* Buttons */
.btn-primary {
    background: var(--accent-gradient);
    color: var(--on-accent);
    border: none;
    outline: none;
    padding: 10px 20px;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 13.5px;
    letter-spacing: 0.01em;
    border-radius: var(--border-radius-md);
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    transition: var(--transition-smooth);
    box-shadow: var(--shadow-sm);
}

.btn-primary:hover {
    box-shadow: var(--shadow-md);
    background: var(--accent-gradient-hover);
}

.btn-primary:active {
    transform: translateY(1px);
    box-shadow: var(--shadow-sm);
}

.btn-secondary {
    background: var(--bg-surface);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    padding: 10px 20px;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 13.5px;
    letter-spacing: 0.01em;
    border-radius: var(--border-radius-md);
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    transition: var(--transition-smooth);
    box-shadow: none;
}

.btn-secondary:hover {
    background: var(--bg-surface-hover);
    border-color: var(--text-muted);
}

.btn-secondary:active {
    transform: translateY(1px);
}

/* Linear-style items */
.linear-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.linear-item {
    display: flex;
    align-items: center;
    padding: 12px 16px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    transition: var(--transition-smooth);
    cursor: pointer;
}

.linear-item:hover {
    background: var(--bg-surface-elevated);
    border-color: var(--border-color-focus);
}

.linear-icon {
    margin-right: 12px;
    color: var(--accent-indigo);
    display: flex;
    align-items: center;
}

.linear-icon svg {
    width: 18px;
    height: 18px;
}

.linear-content {
    flex: 1;
}

.linear-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 2px;
}

.linear-desc {
    font-size: 11px;
    color: var(--text-muted);
}

.linear-meta {
    display: flex;
    align-items: center;
    gap: 12px;
}

.badge {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.03em;
    padding: 2px 8px;
    border-radius: var(--border-radius-md);
}

.badge-a1 { background: var(--info-bg); color: var(--accent-indigo); border: 1px solid var(--border-color-focus); }
.badge-a2 { background: rgba(154, 107, 20, 0.08); color: var(--warning); border: 1px solid rgba(154, 107, 20, 0.25); }
.badge-b1 { background: rgba(120, 90, 40, 0.08); color: #7A5A28; border: 1px solid rgba(120, 90, 40, 0.22); }
/* Teal rather than another brown: PFLEGE is a different exam body (telc, not
   Goethe) and a different track, so it should not read as 'one past B1'. */
.badge-pflege { background: rgba(13, 110, 108, 0.08); color: #0D6E6C; border: 1px solid rgba(13, 110, 108, 0.25); }

/* Progress Bar */
.prog-container {
    width: 100%;
}

.prog-header {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 6px;
}

.prog-bar-outer {
    height: 6px;
    /* Track uses the hover tone, one step deeper than elevated, so an empty
       bar stays visible even when the bar sits ON an elevated surface. */
    background: var(--bg-surface-hover);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    overflow: hidden;
}

.prog-bar-inner {
    height: 100%;
    background: var(--accent-indigo);
    border-radius: 0;
    width: 0%;
    transition: width 0.8s ease-in-out;
}

/* ==========================================================================
   Page Templates (Public Pages)
   ========================================================================== */

/* 1. Landing Page */
.landing-hero {
    padding: 80px 40px 100px;
    text-align: center;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.hero-glow {
    position: absolute;
    width: 600px;
    height: 400px;
    background: radial-gradient(circle, rgba(30, 58, 95, 0.05) 0%, rgba(0,0,0,0) 70%);
    top: -100px;
    left: 50%;
    transform: translateX(-50%);
    pointer-events: none;
}

.hero-badge {
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    padding: 6px 16px;
    border-radius: var(--border-radius-md);
    font-size: 12px;
    font-weight: 700;
    color: var(--accent-indigo);
    margin-bottom: 24px;
    font-family: var(--font-heading);
    letter-spacing: 0.02em;
}

.landing-hero h1 {
    font-family: var(--font-heading);
    font-size: 54px;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.03em;
    max-width: 800px;
    margin-bottom: 20px;
    color: var(--text-primary);
    background: linear-gradient(180deg, var(--text-primary) 0%, #475569 100%);
    -webkit-background-clip: text;
    background-clip: text;
}

.landing-hero p {
    font-size: 18px;
    color: var(--text-secondary);
    max-width: 600px;
    line-height: 1.6;
    margin-bottom: 36px;
}

.hero-ctas {
    display: flex;
    gap: 16px;
    margin-bottom: 60px;
}

.hero-preview-container {
    width: 100%;
    max-width: 960px;
    border-radius: var(--border-radius-lg);
    border: 1px solid var(--border-color);
    background: var(--bg-surface);
    padding: 6px;
    box-shadow: var(--shadow-premium);
}

.hero-preview-bar {
    display: flex;
    gap: 6px;
    padding: 8px 12px;
}

.circle-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border-color);
}

.hero-preview-img {
    width: 100%;
    border-radius: var(--border-radius-sm);
    border: 1px solid var(--border-color);
}

/* 2. Login Page */
.login-container {
    min-height: calc(100vh - 150px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.login-card {
    width: 100%;
    max-width: 420px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 40px;
    box-shadow: var(--shadow-premium);
}

.login-header {
    text-align: center;
    margin-bottom: 30px;
}

.login-header h2 {
    font-family: var(--font-heading);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin-bottom: 8px;
}

.login-header p {
    color: var(--text-secondary);
    font-size: 14px;
}

.form-group {
    margin-bottom: 20px;
}

.form-group label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.form-input {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    padding: 12px 16px;
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 14px;
    transition: var(--transition-smooth);
}

.form-input:focus {
    outline: none;
    border-color: var(--accent-indigo);
    box-shadow: 0 0 0 2px var(--info-bg);
}

.btn-login-submit {
    width: 100%;
    justify-content: center;
    margin-top: 10px;
}

.oauth-divider {
    display: flex;
    align-items: center;
    margin: 24px 0;
    color: var(--text-muted);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.oauth-divider::before, .oauth-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-color);
}

.oauth-divider span {
    padding: 0 10px;
}

.oauth-buttons {
    display: flex;
    gap: 12px;
}

.btn-oauth {
    flex: 1;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    padding: 10px;
    color: var(--text-primary);
    font-size: 13px;
    font-weight: 500;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.btn-oauth:hover {
    background: var(--bg-surface-hover);
}

.btn-oauth svg {
    width: 16px;
    height: 16px;
}

/* ==========================================================================
   Page Templates (App Dashboard & Features)
   ========================================================================== */

/* 3. Student Dashboard */
.dashboard-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 24px;
}

.stat-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    margin-bottom: 24px;
}

.stat-box {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
    padding: 16px 20px;
    display: flex;
    flex-direction: column;
}

.stat-val {
    font-size: 22px;
    font-weight: 600;
    font-family: var(--font-mono);
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    margin-top: 6px;
}

.stat-lbl {
    font-size: 10.5px;
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.quick-srs-card {
    background: var(--info-bg);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent-indigo);
    border-radius: var(--border-radius-md);
    padding: 24px;
    margin-bottom: 24px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.srs-info h3 {
    font-family: var(--font-heading);
    font-size: 18px;
    margin-bottom: 6px;
}

.srs-info p {
    font-size: 13px;
    color: var(--text-secondary);
}

.sub-skill-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.sub-skill-item {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.sub-skill-label {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
    font-weight: 600;
}

.sub-skill-score {
    color: var(--accent-indigo);
}

/* 4. Grammar Page */
.level-filter-bar {
    display: flex;
    gap: 8px;
    margin-bottom: 24px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 12px;
}

.filter-btn {
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-secondary);
    padding: 6px 16px;
    border-radius: var(--border-radius-md);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.filter-btn:hover {
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.02);
}

.filter-btn.active {
    color: white;
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.1);
}

/* 5. Vocabulary Spaced Repetition (Notion/Quizlet Card Flip) */
.vocab-workspace {
    display: flex;
    flex-direction: column;
    /* stretch, not center: children are full-width rows whose own space-between needs
       the full column width. With align-items:center they shrink to content width and
       the labels collide ("Karte 1 von 30" against "Box 1 / 5"). */
    align-items: stretch;
    max-width: 600px;
    margin: 40px auto;
}

.card-container {
    width: 100%;
    height: 320px;
    perspective: 1000px;
    cursor: pointer;
    margin-bottom: 24px;
}

.flashcard {
    width: 100%;
    height: 100%;
    position: relative;
    transform-style: preserve-3d;
    transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.flashcard.flipped {
    transform: rotateY(180deg);
}

.card-face {
    position: absolute;
    width: 100%;
    height: 100%;
    backface-visibility: hidden;
    border-radius: var(--border-radius-lg);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-premium);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: 40px;
}

.card-front {
    background: var(--bg-surface);
}

.card-back {
    background: var(--bg-surface-elevated);
    transform: rotateY(180deg);
    border-color: rgba(99, 102, 241, 0.2);
}

.card-word {
    font-family: var(--font-heading);
    font-size: 32px;
    font-weight: 700;
    margin-bottom: 8px;
    color: white;
}

.card-type {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--accent-indigo);
    font-weight: 600;
}

.card-meaning {
    font-family: var(--font-heading);
    font-size: 26px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 12px;
    text-align: center;
}

.card-example {
    font-size: 14px;
    color: var(--text-secondary);
    font-style: italic;
    text-align: center;
    max-width: 400px;
    line-height: 1.5;
}

.srs-buttons {
    display: flex;
    gap: 12px;
    width: 100%;
}

.btn-srs {
    flex: 1;
    padding: 14px;
    border-radius: var(--border-radius-md);
    border: none;
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
    transition: var(--transition-smooth);
    color: white;
    text-align: center;
}

.btn-again { background: #ef4444; }
.btn-again:hover { background: #dc2626; box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3); }
.btn-hard { background: #f59e0b; }
.btn-hard:hover { background: #d97706; box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3); }
.btn-good { background: #3b82f6; }
.btn-good:hover { background: #2563eb; box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); }
.btn-easy { background: #10b981; }
.btn-easy:hover { background: #059669; box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); }

/* 6. Reading Page (Split Pane) */
.split-pane {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    height: calc(100vh - 180px);
}

.pane-left, .pane-right {
    overflow-y: auto;
    padding: 20px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
}

.reading-text {
    line-height: 1.8;
    font-size: 15px;
    color: var(--text-primary);
}

/* Dictionary Hover triggers */
.trans-word {
    border-bottom: 1px dashed rgba(255, 255, 255, 0.25);
    cursor: help;
    position: relative;
    display: inline-block;
    transition: var(--transition-smooth);
}

.trans-word:hover {
    color: var(--accent-indigo);
    border-bottom-color: var(--accent-indigo);
    background: rgba(99, 102, 241, 0.05);
}

.word-tooltip {
    visibility: hidden;
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translate(-50%, -8px);
    background: #1e293b;
    border: 1px solid rgba(255,255,255,0.1);
    color: white;
    padding: 6px 12px;
    border-radius: 6px;
    font-size: 11px;
    white-space: nowrap;
    z-index: 1000;
    box-shadow: var(--shadow-premium);
    opacity: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.trans-word:hover .word-tooltip {
    visibility: visible;
    opacity: 1;
    transform: translate(-50%, -12px);
}

.reading-questions {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.question-card {
    padding: 16px;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
}

.question-text {
    font-weight: 600;
    font-size: 14px;
    margin-bottom: 12px;
}

.option-btn {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 12px 16px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    color: var(--text-primary);
    font-size: 13px;
    cursor: pointer;
    text-align: left;
    margin-bottom: 8px;
    transition: var(--transition-smooth);
}

.option-btn:hover {
    background: var(--bg-surface-elevated);
    border-color: rgba(255,255,255,0.08);
}

.option-letter {
    width: 22px;
    height: 22px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.05);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
    margin-right: 12px;
}

.option-btn.selected-correct {
    background: var(--success-bg);
    border-color: var(--success);
}
.option-btn.selected-correct .option-letter {
    background: var(--success);
    color: white;
}

/* "You picked this" during an ungraded exam attempt - deliberately NOT green/
   success-colored, unlike .selected-correct above (which really does mean
   "this is the correct answer", e.g. practice-mode immediate feedback). A
   live mock exam has no grading yet, so marking the chosen option green read
   as "you got it right" mid-exam - misleading in exactly the moment a
   candidate should be uncertain. */
.option-btn.selected-chosen {
    background: var(--bg-surface-elevated);
    border-color: var(--accent-indigo);
    border-width: 2px;
}
.option-btn.selected-chosen .option-letter {
    background: var(--accent-indigo);
    color: white;
}

.option-btn.selected-incorrect {
    background: var(--error-bg);
    border-color: var(--error);
}
.option-btn.selected-incorrect .option-letter {
    background: var(--error);
    color: white;
}

/* 7. Listening Page */
.audio-player-card {
    padding: 24px;
    background: var(--bg-surface-elevated);
    border-radius: var(--border-radius-lg);
    border: 1px solid var(--border-color);
    margin-bottom: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.player-controls {
    display: flex;
    align-items: center;
    gap: 16px;
}

.btn-play-pause {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--accent-indigo);
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.btn-play-pause:hover {
    transform: scale(1.05);
    background: var(--accent-purple);
}

.player-timeline-container {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-secondary);
}

.player-slider {
    flex: 1;
    height: 4px;
    border-radius: 2px;
    background: rgba(255,255,255,0.1);
    position: relative;
    cursor: pointer;
}

.player-progress {
    height: 100%;
    border-radius: 2px;
    background: var(--accent-gradient);
    width: 35%;
}

.player-handle {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: white;
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    left: 35%;
}

.transcript-container {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
    padding: 20px;
    max-height: 240px;
    overflow-y: auto;
}

.transcript-para {
    line-height: 1.8;
    color: var(--text-secondary);
    font-size: 14px;
}

.highlighted-segment {
    background: rgba(99,102,241,0.15);
    color: white;
    padding: 2px 4px;
    border-radius: 4px;
    font-weight: 500;
}

/* 8. Speaking Page */
.voice-assistant-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 40px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    text-align: center;
    margin-bottom: 24px;
}

.voice-visualizer {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    background: rgba(99, 102, 241, 0.05);
    border: 2px dashed rgba(99, 102, 241, 0.2);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 24px;
    position: relative;
}

.voice-visualizer.recording::before {
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 2px solid var(--accent-indigo);
    animation: pulseGlow 1.5s infinite;
}

.mic-btn-large {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    background: var(--accent-gradient);
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    cursor: pointer;
    box-shadow: var(--shadow-glow);
    z-index: 10;
    transition: var(--transition-smooth);
}

.mic-btn-large:hover {
    transform: scale(1.05);
}

@keyframes pulseGlow {
    0% { transform: scale(1); opacity: 0.5; }
    100% { transform: scale(1.4); opacity: 0; }
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

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

/* Screen-reader-only text: visually hidden, still announced by assistive tech. */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   Loading Skeletons — shared shimmer system
   Replaces ~20 previously-duplicated bare-text "Lade X..." loading states
   across app.js and src/levels/*.js with one design-system component.
   Rendered by the renderSkeleton(kind) helper in app.js. A production app
   never leaves the user staring at plain text or frozen stale content while
   a page's data is in flight.
   ========================================================================== */
.skel-block {
    position: relative;
    overflow: hidden;
    background: var(--bg-surface-elevated);
    border-radius: 6px;
}
.skel-block::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.4) 50%, transparent 100%);
    transform: translateX(-100%);
    animation: skelShimmer 1.6s ease-in-out infinite;
}
body.dark-theme .skel-block::after {
    background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.07) 50%, transparent 100%);
}
@keyframes skelShimmer {
    100% { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
    .skel-block::after { animation: none; }
}

.skel-page { padding: 4px 2px; }
.skel-title { height: 26px; width: 240px; margin-bottom: 22px; }
.skel-card { height: 84px; width: 100%; border-radius: var(--border-radius-lg, 12px); margin-bottom: 14px; }
.skel-line { height: 15px; }

.skel-list { padding: 20px 0; }
.skel-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    margin-bottom: 10px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
}
.skel-row .skel-block { flex-shrink: 0; }
.skel-list .skel-row:last-child { margin-bottom: 0; }

/* Bespoke "Dein Plan für heute" card skeleton — matches the real card's
   ring + numbered rows + CTA bar shape, since it's the single most-seen
   loading state in the app (rendered on every dashboard visit). */
.skel-plan-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
.skel-plan-ring { width: 76px; height: 76px; border-radius: 50%; }
.skel-plan-cta { height: 48px; width: 100%; border-radius: 999px; margin-top: 16px; }

.phoneme-panel {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
    margin-top: 20px;
    background: var(--bg-surface-elevated);
    padding: 16px;
    border-radius: var(--border-radius-md);
    width: 100%;
}

.phoneme-score {
    font-size: 13px;
    font-weight: 500;
    padding: 4px 10px;
    border-radius: 6px;
}

.phoneme-good { background: var(--success-bg); color: var(--success); }
.phoneme-warn { background: var(--warning-bg); color: var(--warning); }
.phoneme-bad { background: var(--error-bg); color: var(--error); }

/* 9. Writing Page */
.writing-layout {
    display: grid;
    grid-template-columns: 3fr 2fr;
    gap: 24px;
    height: calc(100vh - 180px);
}

.writing-editor-pane {
    display: flex;
    flex-direction: column;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    /* Never 'hidden': a tall task prompt pushed the footer — and with it the
       "Prüfen & Bewerten" button — outside the pane, where it was clipped with no
       way to scroll to it. The student could write but not submit. */
    overflow-y: auto;
}

.writing-prompt-header {
    padding: 20px;
    border-bottom: 1px solid var(--border-color);
    background: rgba(255,255,255,0.01);
}

.writing-textarea {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    padding: 24px;
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 17px;
    line-height: 1.7;
    resize: none;
}

.writing-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
    padding: 16px 20px;
    border-top: 1px solid var(--border-color);
    background: rgba(0,0,0,0.15);
}

.word-counter {
    font-size: 12px;
    color: var(--text-muted);
}

.corrections-panel {
    display: flex;
    flex-direction: column;
    gap: 12px;
    overflow-y: auto;
    padding: 20px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
}

.correction-card {
    padding: 16px;
    border-left: 3px solid var(--error);
    background: var(--bg-surface-elevated);
    border-radius: 4px var(--border-radius-sm) var(--border-radius-sm) 4px;
}

.correction-wrong {
    text-decoration: line-through;
    color: var(--error);
    font-size: 13px;
    margin-bottom: 4px;
}

.correction-right {
    color: var(--success);
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 8px;
}

.correction-exp {
    font-size: 11px;
    color: var(--text-secondary);
}

/* 10. Mock Test Page */
.mocktest-shell {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 24px;
}

.mocktest-steps {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.mocktest-step-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 13px;
    font-weight: 600;
    border-radius: var(--border-radius-sm);
    transition: var(--transition-smooth);
}

.mocktest-step-link.active {
    background: rgba(255, 255, 255, 0.05);
    color: white;
}

.mocktest-step-link.done {
    color: var(--success);
}

.mocktest-timer-banner {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 20px;
    background: var(--error-bg);
    border: 1px solid rgba(239, 68, 68, 0.2);
    border-radius: var(--border-radius-md);
    margin-bottom: 24px;
    font-family: var(--font-mono);
    font-size: 14px;
    color: var(--error);
    font-weight: 700;
}

/* 11. AI Tutor Page (Chat Interface) */
.tutor-layout {
    display: grid;
    grid-template-columns: 1fr 280px;
    gap: 24px;
    height: calc(100vh - 180px);
}

.chat-workspace {
    display: flex;
    flex-direction: column;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    overflow: hidden;
}

.chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.chat-bubble {
    max-width: 80%;
    padding: 14px 18px;
    border-radius: var(--border-radius-md);
    line-height: 1.5;
    font-size: 13.5px;
}

.bubble-user {
    background: var(--accent-indigo);
    color: white;
    align-self: flex-end;
    border-bottom-right-radius: 4px;
}

.bubble-ai {
    background: var(--bg-surface-elevated);
    color: var(--text-primary);
    align-self: flex-start;
    border-bottom-left-radius: 4px;
    border: 1px solid var(--border-color);
}

.bubble-ai p {
    margin-bottom: 8px;
}

.bubble-ai p:last-child {
    margin-bottom: 0;
}

.bubble-ai code {
    background: rgba(0,0,0,0.2);
    font-family: var(--font-mono);
    padding: 2px 4px;
    border-radius: 4px;
    font-size: 12px;
}

/* Wraps output from renderAiText() (src/core/ai_text_render.js). Without
   this, a rendered bullet/numbered list falls back to the browser default
   40px indent, which reads as broken inside a narrow chat bubble or card. */
.ai-rendered-text p {
    margin: 0 0 8px;
}

.ai-rendered-text p:last-child {
    margin-bottom: 0;
}

.ai-rendered-text ul,
.ai-rendered-text ol {
    margin: 4px 0 8px;
    padding-left: 20px;
}

.ai-rendered-text li {
    margin-bottom: 4px;
}

.ai-rendered-text li:last-child {
    margin-bottom: 0;
}

.chat-input-area {
    padding: 16px;
    border-top: 1px solid var(--border-color);
    display: flex;
    gap: 12px;
    background: rgba(0,0,0,0.1);
}

.chat-textarea {
    flex: 1;
    background: var(--bg-main);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    padding: 12px;
    color: white;
    font-family: var(--font-body);
    font-size: 14px;
    resize: none;
    height: 44px;
    outline: none;
}

.chat-textarea:focus {
    border-color: var(--accent-indigo);
}

.chat-send-btn {
    width: 44px;
    height: 44px;
    border-radius: var(--border-radius-sm);
    background: var(--accent-gradient);
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.chat-send-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
}

.tutor-sidebar {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.tutor-suggest-btn {
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    padding: 10px 14px;
    border-radius: var(--border-radius-sm);
    font-size: 12px;
    text-align: left;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.tutor-suggest-btn:hover {
    border-color: var(--accent-indigo);
    color: white;
}

/* 12. Progress Page */
.analytics-summary {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 24px;
}

.progress-chart-container {
    height: 240px;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
    margin-bottom: 24px;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    padding: 30px 40px;
    position: relative;
}

.bar-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    flex: 1;
}

.bar-pill {
    width: 32px;
    background: var(--accent-gradient);
    border-radius: var(--border-radius-sm) var(--border-radius-sm) 0 0;
    transition: var(--transition-smooth);
}

.bar-label {
    font-size: 11px;
    color: var(--text-secondary);
    font-weight: 500;
}

/* 13. Teacher Dashboard */
.teacher-grid {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.table-container {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    overflow: hidden;
}

.teacher-table {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
}

.teacher-table th {
    background: var(--bg-surface-elevated);
    padding: 14px 20px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-color);
}

.teacher-table td {
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-color);
    font-size: 13px;
}

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

.teacher-table tr:hover td {
    background: var(--bg-surface-hover);
}

.student-pfp {
    display: flex;
    align-items: center;
    gap: 12px;
}

.student-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--bg-surface-hover);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
}

/* 14. Admin Dashboard */
.admin-card {
    border-left: 3px solid var(--accent-indigo);
}

/* 15. Subscription Page */
.pricing-header {
    text-align: center;
    max-width: 600px;
    margin: 20px auto 40px;
}

.pricing-header h2 {
    font-family: var(--font-heading);
    font-size: 32px;
    font-weight: 800;
    margin-bottom: 10px;
}

.pricing-header p {
    color: var(--text-secondary);
    font-size: 15px;
}

.pricing-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    max-width: 1080px;
    margin: 0 auto;
}

.pricing-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 30px;
    display: flex;
    flex-direction: column;
    position: relative;
    box-shadow: var(--shadow-premium);
}

.pricing-card.premium {
    border-color: var(--accent-indigo);
    box-shadow: var(--shadow-glow);
}

/* A "most popular" tag used to sit here. Removed 2026-09-23: nothing measures
   popularity, so it was an unverified claim (CLAUDE.md 6.6). The highlighted
   card is the plan that fits the learner's exam date; its "Empfohlen" badge
   says so. */

.price-title {
    font-family: var(--font-heading);
    font-size: 18px;
    font-weight: 700;
    margin-bottom: 8px;
}

.price-desc {
    font-size: 12px;
    color: var(--text-secondary);
    margin-bottom: 24px;
}

.price-amt {
    font-size: 36px;
    font-weight: 800;
    font-family: var(--font-heading);
    margin-bottom: 24px;
    display: flex;
    align-items: baseline;
}

.price-amt span {
    font-size: 14px;
    font-weight: 500;
    color: var(--text-secondary);
}

.price-features {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 30px;
    flex: 1;
}

.price-features li {
    font-size: 13px;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 8px;
}

.price-features li svg {
    width: 16px;
    height: 16px;
    color: var(--success);
}

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

/* 16. Settings Page */
.settings-workspace {
    max-width: 600px;
}

.settings-section {
    margin-bottom: 32px;
}

.settings-section h3 {
    font-family: var(--font-heading);
    font-size: 16px;
    font-weight: 700;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 8px;
}

.settings-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-bottom: 16px;
}

/* ==========================================================================
   Responsive & Device-specific adjustments
   ========================================================================== */

/* =============================================================================
   RESPONSIVE — real breakpoints, keyed to the actual window, not a fake frame.
   Tablet:  ≤1024px  (portrait iPad and below → sidebar collapses to a top rail)
   Mobile:  ≤640px   (phone → sidebar becomes an off-canvas drawer, single col)
   Scoped horizontal overflow is intentional on wide tables/grids; the BODY
   never scrolls horizontally at any width.
   ============================================================================ */

/* Global protection: prevent any child ever pushing the page sideways. */
html, body { overflow-x: hidden; }
img, video, canvas, svg, iframe { max-width: 100%; height: auto; }

@media (max-width: 1024px) {
    .public-header { padding: 0 20px; }

    #app-layout { flex-direction: column; }

    /* Sidebar becomes a top navigation rail on tablet — same links, horizontal. */
    .app-sidebar {
        width: 100%;
        height: auto;
        border-right: none;
        border-bottom: 1px solid var(--border-color);
    }
    .sidebar-header { padding-inline: 20px; }
    .sidebar-user-section { display: none; }
    .sidebar-nav {
        display: flex;
        overflow-x: auto;
        padding: 8px;
        gap: 8px;
    }
    .nav-group-title { display: none; }
    .sidebar-link {
        margin-bottom: 0;
        white-space: nowrap;
        flex-shrink: 0;
    }
    .sidebar-footer { display: none; }

    /* Two-column layouts collapse to one column. Horizontal scroll never appears
       on the page — only on the inner element that legitimately needs it.
       !important on the column value: several real screens set their own
       per-instance column ratio via an inline style="grid-template-columns:…"
       (e.g. the A1/A2 Schreiben workspace's 1.2fr/1fr, the Progress page's
       1.2fr/1.8fr and 1.6fr/1.4fr HUD rows, the teacher student-detail
       charts) - a plain class rule can never outrank an inline style
       regardless of media query, so without !important those specific
       screens silently stayed two-column and unreadable at phone width
       (found 2026-08-20, founder report "dashboard and stuff messed up on
       mobile" - confirmed via a live-server screenshot audit at 390px).
       Same fix already applied to .exam-content-split/.exam-2col-grid below
       for the same reason. */
    .dashboard-grid,
    .pricing-grid,
    .split-pane,
    .writing-layout,
    .tutor-layout,
    .settings-row {
        grid-template-columns: 1fr !important;
        height: auto;
        overflow: visible;
    }

    /* Same collapse, !important: these two are set inline (grid-template-columns
       computed per-question in mock_exam_section_workspace.js), which otherwise
       always outranks a plain class rule regardless of media query. */
    .exam-content-split,
    .exam-2col-grid {
        grid-template-columns: 1fr !important;
        height: auto;
        overflow: visible;
    }

    /* Mock exam workspace: the 200px fixed sidebar + timed header were never
       given a mobile layout, so at phone width the sidebar squeezed the
       reading/listening/writing panes into unreadable ~2-word-wide columns
       and the header's title/counters/timer collided (found 2026-08-17,
       independent audit of the 10-exam A1 expansion). Same "sidebar becomes
       a horizontal rail" treatment as .app-sidebar above, applied to the
       exam's own step list. */
    .mocktest-shell {
        grid-template-columns: 1fr !important;
        height: auto !important;
        max-height: none !important;
    }
    .mocktest-steps {
        border-right: none !important;
        border-bottom: 1px solid var(--border-color);
        display: flex;
        flex-direction: row !important;
        overflow-x: auto;
        padding: 12px 16px !important;
        gap: 8px;
        align-items: center;
    }
    .mocktest-steps > div:first-child { display: none; } /* "Prüfungsteile" heading - redundant once it's a rail */
    .mocktest-step-link {
        flex-shrink: 0;
        white-space: nowrap;
        margin-bottom: 0 !important;
    }

    .exam-header-row {
        flex-wrap: wrap;
        height: auto !important;
        padding: 10px 16px !important;
        row-gap: 8px;
    }
    .exam-header-title { flex: 1 1 auto; }
    .exam-header-counters { gap: 12px !important; }
    .exam-header-counter-total { display: none; } /* "Modul: x/y" stays; the exam-wide total is one tap away in the review screen */
    .exam-header-controls { margin-left: auto; }

    /* 4-column results row (name / bar / score / pass-fail) has no room for
       four columns at phone width - stack instead of squeezing the progress
       bar to a sliver. */
    .exam-result-row {
        grid-template-columns: 1fr !important;
        gap: 4px !important;
        text-align: left;
    }
    .exam-result-row > div:nth-child(3),
    .exam-result-row > div:nth-child(4) {
        text-align: left !important;
    }

    /* Results report: the BESTANDEN/NICHT BESTANDEN badge is corner-anchored
       with position:absolute for the desktop layout, which collides with the
       "Ergebnisbericht Nr. X" label once the card narrows to phone width
       (found 2026-08-17, same audit as above). Drop it into normal flow,
       stacked above the header, instead of overlaying it. */
    .exam-report-card { padding: 24px 20px !important; }
    .exam-report-badge-wrap {
        position: static !important;
        display: flex;
        justify-content: flex-end;
        margin-bottom: 12px;
    }
}

@media (max-width: 640px) {
    /* Same bug and same fix as .app-header (the logged-in shell): a fixed
       height with a no-wrap row only ever fit the desktop set of nav links
       + login button. .public-nav already wrapped its OWN children here,
       but .public-header itself kept the fixed --header-height with no
       overflow clipping, so the wrapped second line of nav links spilled
       out above/below the header box instead of the box growing to fit it
       (found in the same mobile audit as the logged-in header fix - the
       public/landing header has the identical structural bug). */
    .public-header {
        height: auto;
        min-height: var(--header-height);
        padding: 10px 16px;
        flex-wrap: wrap;
        row-gap: 8px;
    }
    .public-nav    { gap: 12px; flex-wrap: wrap; row-gap: 8px; justify-content: flex-end; }

    .landing-hero h1 { font-size: 28px; }
    .landing-hero p  { font-size: 14px; }
    .hero-ctas {
        flex-direction: column;
        width: 100%;
    }
    .hero-ctas button {
        width: 100%;
        justify-content: center;
    }

    /* On phone the sidebar becomes an off-canvas drawer. The toggle button
       (already in the header markup) reveals it via .active. */
    #app-layout { position: relative; }
    /* Off-canvas drawer driven by transform, not `left`: it composites on the GPU,
       avoids layout thrash, and sidesteps cascade fights over positional offsets. */
    .app-sidebar {
        position: fixed;
        left: 0;
        top: 0;
        width: min(84vw, 320px);
        height: 100vh;
        z-index: 1000;
        box-shadow: 20px 0 50px rgba(0, 0, 0, 0.5);
        transform: translateX(-100%);
        transition: transform var(--d-base, 220ms) var(--ease-out, cubic-bezier(0.16, 1, 0.3, 1));
        /* The desktop sidebar's translucent glass (rgba + blur, base rule
           above) is meant for a permanent side panel sitting beside the
           page. Here it becomes a full-height drawer laid OVER the page, so
           that same translucency let the busy dashboard content behind it
           bleed through - the drawer read as a washed-out double exposure,
           nav links barely legible (found in the same mobile audit as the
           other fixes in this block). An off-canvas drawer needs a solid
           surface. */
        background: var(--bg-surface);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
        will-change: transform;
    }
    .app-sidebar.active,
    body.sidebar-open .app-sidebar { transform: translateX(0); }
    .mobile-sidebar-toggle { display: inline-flex; }

    /* The ≤1024px tablet block above turns .sidebar-nav into a horizontal
       scrolling rail (the sidebar is a top bar there, not a drawer) - but
       that rule still applies here too, since media queries stack rather
       than override each other by width. Without resetting it, the phone
       drawer showed its nav links crammed into one horizontally-scrollable
       row instead of the normal vertical list a slide-out drawer needs
       (found in the same mobile audit as the other fixes in this block).
       .sidebar-user-section and .nav-group-title were hidden for the same
       rail reason and need the same reversal - group titles orient the
       learner in a full drawer, and there's room for the user card again. */
    .sidebar-nav {
        display: flex;
        flex-direction: column;
        overflow-x: visible;
        overflow-y: auto;
        gap: 0;
        padding: 12px 8px;
    }
    .sidebar-link { white-space: normal; }
    .nav-group-title { display: block; }
    .sidebar-user-section { display: flex; }
    .sidebar-footer { display: block; }

    /* Dark backdrop when the drawer is open — click it to dismiss. */
    .app-sidebar-backdrop {
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.35);
        z-index: 999;
        opacity: 0;
        pointer-events: none;
        transition: opacity var(--d-base, 220ms) var(--ease-out, ease);
    }
    body.sidebar-open .app-sidebar-backdrop {
        opacity: 1;
        pointer-events: auto;
    }

    .stat-row { grid-template-columns: 1fr; }
    .card-container { height: 260px; }
    .app-content-container { padding: 16px; }

    /* App header: fixed height + no-wrap actions row worked while the row
       only ever held the theme toggle + streak + XP badge, but
       refreshAiStatusBanner() (app.js) also prepends a "KI-Bewertung AUS"
       pill into .app-header-actions whenever GEMINI_API_KEY is unset - full
       words, not an icon. At 390px that no longer fits in one row, and
       because .app-header has a fixed height with no overflow clipping, the
       overflowing pill just visually floats on top of the page content
       below it instead of pushing the header taller (found in the same
       mobile audit as the grid !important fix above). Let the header grow
       and the actions wrap onto their own row instead - same pattern
       already used for .exam-header-row. */
    .app-header {
        height: auto;
        min-height: var(--header-height);
        padding: 10px 16px;
        flex-wrap: wrap;
        row-gap: 8px;
    }
    .app-header-actions {
        flex-wrap: wrap;
        justify-content: flex-end;
        row-gap: 8px;
    }
    /* The warning text is a dev/founder signal ("AI grading is off"), not
       something a student needs spelled out - the icon plus its native
       title tooltip is enough, and it keeps the wrapped actions row from
       ballooning across two more lines on a phone. refreshAiStatusBanner()
       (app.js) appends the label as a trailing text node after the icon,
       not inside its own element, so zeroing the container's font-size is
       what collapses just that text - the icon keeps its own explicit
       inline px width/height, which isn't font-size-relative. */
    #ai-status-warning { font-size: 0; }

    .greeting-title { font-size: var(--t-xl, 25px); }

    /* Wide tables get horizontal scroll on their own container, not the page. */
    .table-container { overflow-x: auto; }
    .table-container table { min-width: 640px; }
}

/* ==========================================================================
   Mock Exam Focus Mode (Goethe-style computer-based exam simulator)
   ========================================================================== */
/* Premium exam transitions: one subtle fade+rise when a Teil, the review
   screen or the report enters. Deliberately the only animation in exam mode. */
.exam-teil-enter {
    animation: examTeilEnter 0.28s cubic-bezier(0.22, 0.9, 0.36, 1);
}
@keyframes examTeilEnter {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .exam-teil-enter { animation: none; }
}

/* Lesen booklet: the reading material stays pinned and independently
   scrollable while the candidate works through its Aufgaben. */
.lesen-resource-pane {
    position: sticky;
    top: 0;
    align-self: start;
    max-height: calc(100vh - 300px);
    overflow-y: auto;
}
/* The paper redesign (below, .exam-paper-sheet) sets position:relative and
   is combined on the same element (class="lesen-resource-pane exam-paper-sheet").
   Equal specificity + later source order meant .exam-paper-sheet silently won,
   turning "sticky" into "relative" - the reading text (or, for a Zuordnung Teil
   like Anzeigen/Situationen matching, the whole shared ad list) just scrolled
   away with everything else instead of staying pinned while Aufgaben scrolled.
   Reported by a student: on Lesen Teil 3, once you scroll to situation 15+ the
   ads are long gone and you have to scroll back up to re-read them. A compound
   selector always wins over either single-class rule regardless of source
   order, so this can't silently regress again the next time either class's
   rule gets edited. */
.exam-paper-sheet.lesen-resource-pane {
    position: sticky;
}

.exam-mode-active .app-sidebar {
    display: none !important;
}

.exam-mode-active .app-header {
    display: none !important;
}

.exam-mode-active .app-main {
    width: 100% !important;
}

.exam-mode-active .app-content-container {
    padding: 0 !important;
    max-height: 100vh !important;
    overflow-y: hidden !important;
}

.exam-mode-active #app-viewport {
    margin: 0 !important;
    width: 100vw !important;
    max-width: 100vw !important;
    height: 100vh !important;
    min-height: 100vh !important;
    border: none !important;
    border-radius: 0 !important;
}

/* Phones and tablets (<= 1024px): the mobile rule for .mocktest-shell lets it
   grow to its content, so .exam-desk is no longer a height-bound scroll box.
   The exam-mode container above still clipped at 100vh with overflow hidden,
   so on those screens nothing could scroll and the last module's finish
   button sat below the fold, out of reach (2026-09-22). Make the container
   itself the scroll box there. Placed after the rule it overrides because
   both carry !important at equal specificity, so source order decides. */
@media (max-width: 1024px) {
    .exam-mode-active .app-content-container {
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch;
    }
}

/* Modal Backdrop Overlay */
.modal-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(8px);
    display: none;
    justify-content: center;
    align-items: center;
    z-index: 9999;
    animation: fadeIn 0.2s ease-out;
}

/* Modal Content Container */
.modal-content {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 32px;
    width: 90%;
    max-width: 650px;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: 0 20px 40px rgba(0,0,0,0.4);
    animation: slideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

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

/* ==========================================================================
   Dark Theme Overrides & Accessibility Styles
   ========================================================================== */
body.dark-theme {
    /* The same brand system as light mode, re-weighted for a dark room: a deep
       green-black field instead of the old Prussian navy, cream ink, the forest
       green as the primary, and gold kept to the places light mode uses it
       (badge, headline accent, thin rules) rather than filling buttons. */
    --bg-main: #0C1210;
    --bg-surface: #131C18;
    --bg-surface-elevated: #18231F;
    --bg-surface-hover: #1E2A25;
    --bg-card: #131C18;
    --bg-input: #101815;

    --border-color: #24312B;
    --border-color-focus: #2E8B6F;

    --text-primary: #F2EFE6;
    --text-secondary: #A8B3AC;
    --text-muted: #7E8B84;

    /* Brand accent — the forest green, lifted until it carries as TEXT on the
       dark field. --accent-indigo is read as a colour far more often than it is
       poured as a fill (58 `color:` sites vs 21 `background:`), and the button
       fill has its own token below, so this value is tuned for legibility:
       4.7:1 on --bg-surface, where #1E6F54 itself would sit at 3.1:1. */
    --accent-indigo: #329578;
    --accent-purple: #329578;
    --accent-strong: #268464;
    --on-accent: #F2EFE6;          /* cream text on the green primary */
    /* Flat fills, not a gradient: the spec fixes the primary at #1E6F54 and its
       hover at #268464, and a two-stop blend would make the rendered button a
       colour nobody specified. Token shape kept for the call sites. */
    --accent-gradient: linear-gradient(135deg, #1E6F54 0%, #1E6F54 100%);
    --accent-gradient-hover: linear-gradient(135deg, #268464 0%, #268464 100%);
    --cta-band-gradient: linear-gradient(135deg, #131C18 0%, #1E6F54 100%);

    --success: #4ADE9E;
    --success-bg: rgba(74, 222, 158, 0.10);
    /* Warning carries the brand gold in dark mode: it is what the premium badge
       is painted with, which is one of the two places light mode uses gold. */
    --warning: #D9B36C;
    --warning-bg: rgba(217, 179, 108, 0.12);
    --error: #F0857A;
    --error-bg: rgba(240, 133, 122, 0.10);
    --info: #329578;
    --info-bg: rgba(50, 149, 120, 0.12);

    /* Dark depth comes from the scoped .dark-theme glass/glow rules below, not
       from the light theme's soft shadows — pin these so the confirmed dark
       design is unchanged by the light-mode surface migration. */
    --shadow-sm: none;
    --shadow-md: none;
    --shadow-premium: none;
    --shadow-glow: none;

    /* Glassmorphism tokens — green accent tints on the green-black field. */
    --glass-bg: linear-gradient(180deg, rgba(30, 43, 37, 0.62) 0%, rgba(19, 28, 24, 0.54) 100%);
    --glass-rim: rgba(242, 239, 230, 0.10);
    --glass-blur: 14px;
    --accent-tint: rgba(50, 149, 120, 0.13);
    --accent-tint-border: rgba(50, 149, 120, 0.48);
}

/* Make sure form inputs and textareas have clear background and text colors in dark mode */
body.dark-theme input,
body.dark-theme textarea,
body.dark-theme select {
    background-color: var(--bg-input);
    color: var(--text-primary);
    border-color: var(--border-color);
}

/* ==========================================================================
   PREMIUM "WAVY" DARK MODE — atmospheric depth (Arc / Raycast / Linear vibe)
   Light mode stays flat & editorial; dark mode gets luminous gradients, glass
   surfaces and soft glow so nothing reads as flat 2D. All scoped to .dark-theme.
   ========================================================================== */

/* Exam-room backdrop — one smooth green-black field: soft luminous center,
   gently darker edges (vignette). Calm and focused, like the speaking exam room. */
body.dark-theme #app-viewport {
    background-color: var(--bg-main);
    background-image:
        radial-gradient(140% 110% at 50% 22%, #16211C 0%, #101815 46%, #080D0B 100%);
    background-attachment: fixed;
}

/* Glass surfaces — translucent so the backdrop glows through, with a top
   highlight and soft drop shadow for real depth (not flat blocks). */
body.dark-theme .glass-card,
body.dark-theme .stat-box,
body.dark-theme .linear-item,
body.dark-theme .srs-tab-btn,
body.dark-theme .card,
body.dark-theme .table-container {
    background: var(--glass-bg);
    border: 1px solid var(--border-color);
    border-top-color: var(--glass-rim);
    box-shadow: 0 14px 38px -14px rgba(0, 0, 0, 0.62), inset 0 1.5px 0 rgba(255, 255, 255, 0.09);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
}

body.dark-theme .glass-card:hover,
body.dark-theme .linear-item:hover {
    border-color: var(--accent-tint-border);
    box-shadow: 0 16px 40px -14px rgba(0, 0, 0, 0.65), inset 0 1px 0 rgba(255, 255, 255, 0.07);
}

/* Accent card (daily practice) keeps its accent edge but gains glass depth. */
body.dark-theme .quick-srs-card {
    background: linear-gradient(135deg, var(--accent-tint) 0%, rgba(24, 35, 31, 0.58) 60%);
    border: 1px solid var(--accent-tint-border);
    border-left: 3px solid var(--accent-indigo);
    box-shadow: 0 12px 34px -14px rgba(0, 0, 0, 0.55);
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
}

/* Sidebar & header — frosted glass panes. */
body.dark-theme .app-sidebar {
    background: linear-gradient(180deg, rgba(19, 28, 24, 0.92) 0%, rgba(12, 18, 16, 0.92) 100%);
    border-right: 1px solid var(--border-color);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
}

body.dark-theme .app-header,
body.dark-theme .public-header {
    background: rgba(12, 18, 16, 0.55);
    border-bottom: 1px solid var(--border-color);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
}

/* .badge-b1 uses a hardcoded brown (#7A5A28) tuned for a near-white light-mode
   card - unlike .badge-a1/.badge-a2 (which read from theme-aware
   --accent-indigo/--warning), it never adapted to the dark glass card
   background and went near-invisible. Give it its own deeper gold, one step
   warmer and darker than --warning, so B1 stays distinguishable from A2 on the
   dark field exactly as light mode's brown keeps them apart on cream. */
body.dark-theme .badge-b1 {
    background: rgba(194, 149, 86, 0.14);
    color: #C29556;
    border: 1px solid rgba(194, 149, 86, 0.40);
    text-shadow: none;
    box-shadow: none;
}

/* The green primary lifts off the dark field with its own colour, not gold. */
body.dark-theme .btn-primary {
    box-shadow: 0 6px 22px -6px rgba(30, 111, 84, 0.55);
}
body.dark-theme .btn-primary:hover {
    box-shadow: 0 8px 30px -6px rgba(38, 132, 100, 0.70);
}

/* Headings gain a faint luminous lift so serif display type doesn't read flat. */
body.dark-theme .app-header-title h2,
body.dark-theme .glass-card h2,
body.dark-theme .glass-card h3,
body.dark-theme .stat-val,
body.dark-theme .srs-info h3 {
    text-shadow: 0 1px 24px rgba(120, 200, 169, 0.12);
}

/* Progress fill glows in the brand green. */
body.dark-theme .prog-bar-inner {
    box-shadow: 0 0 12px rgba(50, 149, 120, 0.45);
}

/* Accessibility Focus outlines */
body.keyboard-nav-active *:focus-visible {
    outline: 3px solid var(--accent-indigo) !important;
    outline-offset: 2px !important;
}

/* ==========================================================================
   Interactive 3D Flashcards & Vocabulary System
   ========================================================================== */
.vocab-workspace {
    max-width: 800px;
    margin: 0 auto;
    padding: 10px;
}

.srs-deck-bar {
    display: flex;
    gap: 10px;
    margin-bottom: 24px;
    overflow-x: auto;
    padding-bottom: 6px;
}

.srs-tab-btn {
    padding: 10px 18px;
    border-radius: 24px;
    border: 1px solid var(--border-color);
    background: var(--bg-surface);
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    transition: all 0.2s ease;
}

.srs-tab-btn:hover {
    background: var(--bg-surface-hover);
    color: var(--text-primary);
}

.srs-tab-btn.active {
    background: var(--accent-indigo);
    color: #FFFFFF;
    border-color: var(--accent-indigo);
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}

.card-container {
    perspective: 1000px;
    width: 100%;
    max-width: 580px;
    /* Must be >= .flashcard's min-height (360px): an earlier, unrelated
       .card-container rule fixes height at 320px, which .flashcard's
       min-height overrides for itself but not for this container - the
       card then visually overflows 40px past its box, eating the margin
       below and bleeding into the SRS rating row under it. */
    height: 360px;
    margin: 0 auto 24px auto;
    cursor: pointer;
}

.flashcard {
    position: relative;
    width: 100%;
    min-height: 360px;
    border-radius: var(--border-radius-xl);
    transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
    transform-style: preserve-3d;
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.15);
}

.flashcard.flipped {
    transform: rotateY(180deg);
}

.card-face {
    position: absolute;
    width: 100%;
    height: 100%;
    backface-visibility: hidden;
    border-radius: var(--border-radius-xl);
    padding: 28px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    /* Must be stretch: the earlier .card-face rule sets align-items:center, which makes
       the header/footer rows shrink to their content width, so their space-between has
       no room and the labels collide ("Aussprache testen" over "Klicken zum Umdrehen"). */
    align-items: stretch;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    box-sizing: border-box;
}

.card-back {
    transform: rotateY(180deg);
    background: var(--bg-surface-elevated);
}

.article-badge {
    display: inline-block;
    padding: 4px 12px;
    border-radius: 8px;
    font-weight: 700;
    font-size: 14px;
    text-transform: lowercase;
    margin-right: 8px;
}
.article-der { background: rgba(59, 130, 246, 0.2); color: #3B82F6; border: 1px solid rgba(59, 130, 246, 0.3); }
.article-die { background: rgba(239, 68, 68, 0.2); color: #EF4444; border: 1px solid rgba(239, 68, 68, 0.3); }
.article-das { background: rgba(16, 185, 129, 0.2); color: #10B981; border: 1px solid rgba(16, 185, 129, 0.3); }
.article-none { background: rgba(148, 163, 184, 0.2); color: var(--text-secondary); }

.srs-rating-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    max-width: 580px;
    margin: 0 auto;
}

.btn-rating {
    padding: 12px 8px;
    border-radius: var(--border-radius-md);
    border: 1px solid var(--border-color);
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.btn-rating:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.btn-again { background: #FEF2F2; color: #DC2626; border-color: #FCA5A5; }
.btn-hard { background: #FFFBEB; color: #D97706; border-color: #FCD34D; }
.btn-good { background: #EFF6FF; color: #2563EB; border-color: #93C5FD; }
.btn-easy { background: #ECFDF5; color: #059669; border-color: #6EE7B7; }

body.dark-theme .btn-again { background: rgba(220, 38, 38, 0.15); color: #FCA5A5; border-color: rgba(220, 38, 38, 0.3); }
body.dark-theme .btn-hard { background: rgba(217, 119, 6, 0.15); color: #FCD34D; border-color: rgba(217, 119, 6, 0.3); }
body.dark-theme .btn-good { background: rgba(37, 99, 235, 0.15); color: #93C5FD; border-color: rgba(37, 99, 235, 0.3); }
body.dark-theme .btn-easy { background: rgba(5, 150, 105, 0.15); color: #6EE7B7; border-color: rgba(5, 150, 105, 0.3); }

/* ==========================================================================
   DIGITAL GRAMMAR HANDBOOK STYLES
   ========================================================================== */
.handbook-container {
    max-width: 900px;
    margin: 0 auto;
    font-family: var(--font-sans);
    color: var(--text-primary);
    line-height: 1.7;
}

.handbook-header {
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.12), rgba(168, 85, 247, 0.12));
    border: 1px solid rgba(99, 102, 241, 0.25);
    border-radius: var(--border-radius-xl);
    padding: 32px;
    margin-bottom: 28px;
    box-shadow: var(--shadow-md);
}

.handbook-toc-bar {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding: 12px 16px;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    margin-bottom: 24px;
    white-space: nowrap;
}

.handbook-toc-link {
    font-size: 12px;
    font-weight: 600;
    padding: 6px 14px;
    border-radius: var(--border-radius-md);
    background: var(--bg-surface);
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
    cursor: pointer;
    text-decoration: none;
    transition: all 0.2s ease;
}

.handbook-toc-link:hover {
    background: var(--accent-indigo);
    color: white;
    border-color: var(--accent-indigo);
}

.handbook-section {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    padding: 28px;
    margin-bottom: 24px;
    box-shadow: var(--shadow-sm);
}

.handbook-section-title {
    font-family: var(--font-heading);
    font-size: 20px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 10px;
    border-bottom: 2px solid rgba(99, 102, 241, 0.2);
    padding-bottom: 8px;
}

/* Callouts & Info Boxes */
.callout-box {
    padding: 16px 20px;
    border-radius: var(--border-radius-md);
    margin: 16px 0;
    border-left: 4px solid;
    font-size: 14px;
}

.callout-info {
    background: rgba(59, 130, 246, 0.08);
    border-left-color: #3B82F6;
    color: var(--text-primary);
}

.callout-tip {
    background: rgba(16, 185, 129, 0.08);
    border-left-color: #10B981;
    color: var(--text-primary);
}

.callout-warning {
    background: rgba(245, 158, 11, 0.08);
    border-left-color: #F59E0B;
    color: var(--text-primary);
}

.callout-remember {
    background: rgba(139, 92, 246, 0.08);
    border-left-color: #8B5CF6;
    color: var(--text-primary);
}

/* Syntax Formulas & Formula Badges */
.syntax-formula-container {
    background: var(--bg-input);
    border: 1px dashed var(--accent-indigo);
    border-radius: var(--border-radius-md);
    padding: 16px;
    margin: 16px 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    justify-content: center;
}

.formula-part {
    padding: 6px 14px;
    border-radius: 8px;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.3px;
}

.formula-pos1 { background: rgba(59, 130, 246, 0.2); color: #3B82F6; }
.formula-verb { background: rgba(239, 68, 68, 0.2); color: #EF4444; border: 1px solid rgba(239, 68, 68, 0.4); }
.formula-mid { background: rgba(245, 158, 11, 0.2); color: #F59E0B; }
.formula-end { background: rgba(16, 185, 129, 0.2); color: #10B981; border: 1px solid rgba(16, 185, 129, 0.4); }

/* Common Mistakes Comparison Grid */
.mistake-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin: 16px 0;
}

@media (max-width: 640px) {
    .mistake-grid { grid-template-columns: 1fr; }
}

.mistake-card-falsch {
    background: rgba(239, 68, 68, 0.08);
    border: 1px solid rgba(239, 68, 68, 0.3);
    border-radius: var(--border-radius-md);
    padding: 16px;
}

.mistake-card-richtig {
    background: rgba(16, 185, 129, 0.08);
    border: 1px solid rgba(16, 185, 129, 0.3);
    border-radius: var(--border-radius-md);
    padding: 16px;
}

/* Styled Grammar Tables */
.grammar-table-styled {
    width: 100%;
    border-collapse: collapse;
    margin: 16px 0;
    border-radius: var(--border-radius-md);
    overflow: hidden;
    font-size: 14px;
}

.grammar-table-styled th {
    background: var(--accent-indigo);
    color: white;
    padding: 12px 16px;
    text-align: left;
    font-weight: 600;
}

.grammar-table-styled td {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-surface-elevated);
}

.grammar-table-styled tr:nth-child(even) td {
    background: var(--bg-surface);
}

/* Handbuch "Ausführliche Erklärung" raw content (grammar.js renderOverviewTab) -
   authored HTML rendered as-is, unlike the Table tab's own hand-built markup.
   Most A1 topics bake class="grammar-table-styled" onto their own <table> tags,
   so they already look fine; B1's authored content uses bare <table>/<h3>/<h4>
   with no class at all, so every element fell back to unstyled browser defaults -
   a <td> next to a <td> with zero padding/border reads as one run-together word.
   Styling the raw tags directly here fixes every topic on every level at once,
   present or future, without touching a single word of authored content. */
.handbook-content-wrapper h3 {
    font-family: var(--font-heading);
    font-size: 18px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 10px 0;
}

.handbook-content-wrapper h4 {
    font-family: var(--font-heading);
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 20px 0 8px 0;
}

.handbook-content-wrapper p {
    margin: 0 0 12px 0;
    color: var(--text-primary);
}

.handbook-content-wrapper ul {
    margin: 0 0 16px 0;
    padding-left: 20px;
}

.handbook-content-wrapper li {
    margin-bottom: 8px;
    line-height: 1.6;
}

.handbook-content-wrapper strong {
    color: var(--text-primary);
    font-weight: 700;
}

.handbook-content-wrapper table {
    width: 100%;
    border-collapse: collapse;
    margin: 12px 0 20px 0;
    border-radius: var(--border-radius-md);
    overflow: hidden;
    font-size: 14px;
}

.handbook-content-wrapper th {
    background: var(--accent-indigo);
    color: white;
    padding: 12px 16px;
    text-align: left;
    font-weight: 600;
}

.handbook-content-wrapper td {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-surface-elevated);
}

.handbook-content-wrapper tr:nth-child(even) td {
    background: var(--bg-surface);
}

/* Quick Revision Card */
.revision-summary-box {
    background: linear-gradient(135deg, rgba(16, 185, 129, 0.1), rgba(59, 130, 246, 0.1));
    border: 2px solid #10B981;
    border-radius: var(--border-radius-lg);
    padding: 24px;
    margin-top: 24px;
}

/* Daily Mission Score & 3-Task Sequence Hub */
.mission-score-hub {
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.08), rgba(168, 85, 247, 0.05));
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    padding: 28px;
    margin-bottom: 24px;
}

.mission-score-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 24px;
}

.mission-score-badge {
    background: linear-gradient(135deg, var(--accent-indigo), #6366f1);
    color: white;
    padding: 8px 20px;
    border-radius: var(--border-radius-md);
    font-size: 18px;
    font-weight: 800;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
}

.task-flow-sequence {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 24px;
}

.task-flow-item {
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 16px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.task-flow-item:hover {
    border-color: var(--accent-indigo);
    transform: translateY(-2px);
}

.task-flow-arrow {
    text-align: center;
    color: var(--accent-indigo);
    font-size: 18px;
    font-weight: 800;
}

.reward-xp-badge {
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.3);
    color: #f59e0b;
    padding: 10px 18px;
    border-radius: var(--border-radius-md);
    font-weight: 800;
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.exam-readiness-bar-outer {
    background: var(--bg-input);
    border-radius: var(--border-radius-sm);
    height: 10px;
    overflow: hidden;
    margin-top: 8px;
}

.exam-readiness-bar-inner {
    background: linear-gradient(90deg, var(--accent-indigo), #10b981);
    height: 100%;
    border-radius: var(--border-radius-sm);
    transition: width 0.5s ease;
}

/* ==========================================================================
   COURSE SELECTION HUB & LEVEL ACADEMY ARCHITECTURE
   ========================================================================== */
.course-hub-hero {
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.15), rgba(168, 85, 247, 0.15));
    border: 1px solid rgba(99, 102, 241, 0.3);
    border-radius: var(--border-radius-xl);
    padding: 40px 32px;
    margin-bottom: 32px;
    text-align: center;
}

.course-hub-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 24px;
    margin-bottom: 32px;
}

.course-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    padding: 28px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
    box-shadow: var(--shadow-sm);
    position: relative;
    overflow: hidden;
}

.course-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-xl);
    border-color: var(--accent-indigo);
}

.course-card.active-enrolled {
    border: 2px solid var(--accent-indigo);
    background: linear-gradient(180deg, rgba(99, 102, 241, 0.05), var(--bg-surface));
}

.course-card.coming-soon {
    opacity: 0.75;
    background: var(--bg-surface-elevated);
}

.course-card-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 16px;
}

.course-flag-badge {
    font-size: 28px;
    display: inline-block;
}

.level-status-pill {
    padding: 4px 10px;
    border-radius: var(--border-radius-md);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.pill-active { background: rgba(16, 185, 129, 0.2); color: #10B981; border: 1px solid rgba(16, 185, 129, 0.4); }
.pill-locked { background: rgba(245, 158, 11, 0.2); color: #F59E0B; border: 1px solid rgba(245, 158, 11, 0.4); }
.pill-soon { background: rgba(148, 163, 184, 0.2); color: var(--text-secondary); border: 1px solid var(--border-color); }

/* Pinned Level Academy Header Banner */
.level-academy-banner {
    background: linear-gradient(90deg, rgba(99, 102, 241, 0.1), rgba(168, 85, 247, 0.1));
    border-bottom: 1px solid var(--border-color);
    padding: 12px 24px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 24px;
    border-radius: var(--border-radius-md);
}

.btn-switch-course {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border-radius: var(--border-radius-md);
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    cursor: pointer;
    transition: all 0.2s ease;
}

.btn-switch-course:hover {
    background: var(--accent-indigo);
    color: white;
    border-color: var(--accent-indigo);
}

/* ==========================================================================
   IN-APP BETA FEEDBACK WIDGET STYLES
   ========================================================================== */
.beta-feedback-fab, #coach-chat-trigger, #coach-chat-widget-wrapper {
    display: none !important;
}

.beta-feedback-fab:hover {
    transform: translateY(-3px) scale(1.03);
    box-shadow: 0 12px 30px rgba(99, 102, 241, 0.6);
}

.feedback-modal-overlay {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(4px);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.feedback-modal-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    width: 100%;
    max-width: 520px;
    padding: 32px;
    box-shadow: var(--shadow-2xl);
}

.star-rating-selector {
    display: flex;
    gap: 8px;
    justify-content: center;
    margin: 16px 0;
}

.star-btn {
    background: none;
    border: none;
    font-size: 28px;
    cursor: pointer;
    transition: transform 0.15s ease;
    opacity: 0.4;
}

.star-btn.selected, .star-btn:hover {
    opacity: 1;
    transform: scale(1.2);
}

/* ==========================================================================
   FLAGSHIP MOCK EXAM SYSTEM & DIAGNOSTIC REPORT STYLES
   ========================================================================== */
.mock-exam-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 20px;
    margin-bottom: 32px;
}

.exam-modellsatz-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    padding: 24px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    transition: all 0.2s ease;
    box-shadow: var(--shadow-sm);
}

.exam-modellsatz-card:hover {
    border-color: var(--accent-indigo);
    transform: translateY(-3px);
    box-shadow: var(--shadow-lg);
}

.exam-report-hero {
    background: linear-gradient(135deg, rgba(16, 185, 129, 0.12), rgba(59, 130, 246, 0.12));
    border: 2px solid #10B981;
    border-radius: var(--border-radius-xl);
    padding: 36px;
    margin-bottom: 28px;
    text-align: center;
}

.exam-report-hero.failed {
    background: linear-gradient(135deg, rgba(239, 68, 68, 0.12), rgba(245, 158, 11, 0.12));
    border-color: #EF4444;
}

.report-modules-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 28px;
}

@media (max-width: 768px) {
    .report-modules-grid { grid-template-columns: repeat(2, 1fr); }
}

.report-module-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 20px;
    text-align: center;
}

.recommendation-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: rgba(99, 102, 241, 0.1);
    color: var(--accent-indigo);
    border: 1px solid rgba(99, 102, 241, 0.3);
    padding: 8px 16px;
    border-radius: var(--border-radius-md);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    margin: 4px;
    transition: all 0.2s ease;
}

.recommendation-chip:hover {
    background: var(--accent-indigo);
    color: white;
}

/* ==========================================================================
   Story Builder Component Styles (Experimental Input Learning Mode)
   ========================================================================== */

.story-builder-container {
    max-width: 900px;
    margin: 0 auto;
}

.story-controls-header {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 20px;
    margin-bottom: 24px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.story-level-selector {
    display: flex;
    align-items: center;
    gap: 8px;
}

.story-pill-btn {
    padding: 8px 16px;
    border-radius: var(--border-radius-md);
    border: 1px solid var(--border-color);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
    transition: all 0.2s ease;
}

.story-pill-btn.active {
    background: var(--accent-indigo);
    color: white;
    border-color: var(--accent-indigo);
}

.story-step-btn {
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    padding: 8px 14px;
    border-radius: var(--border-radius-md);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
    transition: all 0.2s ease;
}

.story-step-btn:hover {
    background: var(--bg-surface-elevated);
    border-color: var(--border-color-focus);
}

.story-step-btn.active {
    background: var(--accent-indigo);
    color: #ffffff;
    border-color: var(--accent-indigo);
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.25);
}

.story-reader-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    padding: 32px;
    margin-bottom: 28px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}

/* Immersive Story Mode CSS */
.immersive-split-layout {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    align-items: start;
    margin-top: 20px;
}

@media (max-width: 900px) {
    .immersive-split-layout {
        grid-template-columns: 1fr;
    }
}

.immersive-visual-viewport {
    position: sticky;
    top: 20px;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: var(--border-radius-lg);
    overflow: hidden;
    background: #0f172a;
    border: 2px solid rgba(139, 92, 246, 0.3);
    box-shadow: 0 12px 36px rgba(139, 92, 246, 0.2);
}

.immersive-scene-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: opacity 0.5s ease-in-out, transform 0.6s ease-in-out;
}

.immersive-caption-bar {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(to top, rgba(15, 23, 42, 0.95), rgba(15, 23, 42, 0));
    padding: 16px;
    color: #ffffff;
    font-size: 13px;
    font-weight: 600;
    text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}

.immersive-sentence {
    opacity: 0.5;
    font-size: 17px;
    line-height: 1.85;
    transition: opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1), transform 0.35s cubic-bezier(0.4, 0, 0.2, 1), color 0.3s ease, background 0.3s ease;
    cursor: pointer;
    display: inline;
    padding: 4px 8px;
    border-radius: 6px;
    margin-right: 4px;
}

.immersive-sentence:hover {
    opacity: 0.85;
    background: rgba(99, 102, 241, 0.1);
}

.immersive-sentence.active-apple-lyrics {
    opacity: 1.0;
    font-weight: 800;
    color: var(--accent-purple);
    background: rgba(139, 92, 246, 0.18);
    box-shadow: 0 4px 14px rgba(139, 92, 246, 0.2);
    text-shadow: 0 0 16px rgba(139, 92, 246, 0.35);
}

.story-meta-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 24px;
}

.story-meta-tags {
    display: flex;
    align-items: center;
    gap: 8px;
}

.story-tag {
    font-size: 12px;
    font-weight: 700;
    padding: 4px 10px;
    border-radius: var(--border-radius-md);
    background: rgba(99, 102, 241, 0.1);
    color: var(--accent-indigo);
}

.story-view-toggles {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.story-toggle-btn {
    font-size: 12px;
    font-weight: 600;
    padding: 6px 14px;
    border-radius: var(--border-radius-md);
    border: 1px solid var(--border-color);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.2s ease;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.story-toggle-btn.active {
    background: rgba(16, 185, 129, 0.15);
    color: #10B981;
    border-color: rgba(16, 185, 129, 0.4);
}

.story-text-display {
    font-size: 19px;
    line-height: 1.8;
    color: var(--text-primary);
    margin-bottom: 28px;
    font-family: var(--font-body);
}

.target-word-pill {
    background: rgba(236, 72, 153, 0.12);
    color: #EC4899;
    border-bottom: 2px dashed #EC4899;
    padding: 2px 6px;
    border-radius: 4px;
    font-weight: 600;
    cursor: pointer;
    position: relative;
    transition: all 0.2s ease;
}

.target-word-pill:hover {
    background: rgba(236, 72, 153, 0.25);
    transform: translateY(-1px);
}

.story-text-display.hide-hints .target-word-pill {
    background: transparent;
    color: inherit;
    border-bottom: none;
    padding: 0;
    font-weight: inherit;
}

.story-audio-bar {
    display: flex;
    align-items: center;
    gap: 16px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    padding: 14px 20px;
    border-radius: var(--border-radius-lg);
    margin-top: 20px;
}

.story-word-tooltip {
    position: fixed;
    z-index: 1000;
    background: var(--bg-surface);
    border: 1px solid var(--accent-indigo);
    box-shadow: 0 10px 25px rgba(0,0,0,0.3);
    border-radius: var(--border-radius-lg);
    padding: 16px;
    width: 280px;
}

.quiz-question-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 20px;
    margin-bottom: 16px;
}

.quiz-option-btn {
    width: 100%;
    text-align: left;
    padding: 12px 16px;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
    background: var(--bg-elevated);
    color: var(--text-primary);
    font-size: 14px;
    margin-top: 8px;
    cursor: pointer;
    transition: all 0.2s ease;
}

.quiz-option-btn:hover {
    border-color: var(--accent-indigo);
}

.quiz-option-btn.selected-correct {
    background: rgba(16, 185, 129, 0.15);
    border-color: #10B981;
    color: #10B981;
    font-weight: 700;
}

.quiz-option-btn.selected-wrong {
    background: rgba(239, 68, 68, 0.15);
    border-color: #EF4444;
    color: #EF4444;
}

/* ==========================================================================
   AI STUDY COACH ONBOARDING & MISSION LAYOUT STYLES
   ========================================================================== */
.onboarding-wizard-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 70vh;
    padding: 20px;
}

.onboarding-card {
    width: 100%;
    max-width: 560px;
    padding: 36px;
    border-radius: var(--border-radius-xl);
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.08);
    position: relative;
    border: 1px solid var(--border-color);
}

.onboarding-progress-bar {
    width: 100%;
    height: 6px;
    background: var(--border-color);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 12px;
}

.onboarding-progress-inner {
    height: 100%;
    background: var(--accent-indigo);
    border-radius: 3px;
    transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.onboarding-step-indicator {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--text-muted);
    letter-spacing: 0.5px;
    margin-bottom: 24px;
}

.onboarding-content-body h3 {
    font-family: var(--font-heading);
    font-size: 24px;
    font-weight: 800;
    margin-bottom: 8px;
    color: var(--text-primary);
}

.onboarding-step-desc {
    font-size: 14px;
    color: var(--text-secondary);
    margin-bottom: 28px;
    line-height: 1.6;
}

.onboarding-form-group {
    margin-bottom: 24px;
}

.onboarding-form-group label {
    display: block;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    margin-bottom: 8px;
}

.onboarding-options-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
}

.onboarding-options-grid.horizontal {
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}

.onboarding-opt-card {
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 18px;
    cursor: pointer;
    transition: all 0.2s ease;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.onboarding-opt-card:hover {
    border-color: var(--accent-indigo);
    background: var(--bg-surface-hover);
}

.onboarding-opt-card.active {
    border-color: var(--accent-indigo);
    background: rgba(99, 102, 241, 0.05);
    box-shadow: 0 0 0 1px var(--accent-indigo);
}

.onboarding-opt-card strong {
    font-size: 15px;
    color: var(--text-primary);
}

.onboarding-opt-card span {
    font-size: 12px;
    color: var(--text-secondary);
}

.days-checkbox-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
    gap: 10px;
    margin-bottom: 24px;
}

.day-checkbox-label {
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.day-checkbox-label input {
    display: none;
}

.day-checkbox-label span {
    display: block;
    width: 100%;
    text-align: center;
    padding: 12px 6px;
    border-radius: 10px;
    border: 1px solid var(--border-color);
    background: var(--bg-surface-elevated);
    font-weight: 700;
    font-size: 13px;
    color: var(--text-secondary);
    transition: all 0.2s ease;
}

.day-checkbox-label input:checked + span {
    background: var(--accent-indigo);
    color: white;
    border-color: var(--accent-indigo);
}

.onboarding-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 32px;
}

/* Today's Mission & Tabs Layout */
.dashboard-tabs-wrapper {
    display: flex;
    justify-content: center;
    margin-bottom: 28px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 12px;
}

.dashboard-tabs {
    display: flex;
    gap: 8px;
    background: var(--bg-surface-elevated);
    padding: 4px;
    border-radius: 30px;
    border: 1px solid var(--border-color);
}

.dash-tab-btn {
    padding: 8px 20px;
    border-radius: 24px;
    font-size: 13px;
    font-weight: 700;
    border: none;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    transition: all 0.2s ease;
}

.dash-tab-btn:hover {
    color: var(--text-primary);
}

.dash-tab-btn.active {
    background: var(--bg-surface);
    color: var(--accent-indigo);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.mission-layout {
    max-width: 680px;
    margin: 0 auto;
}

.mission-header-card {
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.06), rgba(168, 85, 247, 0.06));
    border: 1px solid rgba(99, 102, 241, 0.15);
    padding: 28px;
    border-radius: var(--border-radius-xl);
    margin-bottom: 24px;
    text-align: center;
}

.mission-main-title {
    font-family: var(--font-heading);
    font-size: 22px;
    font-weight: 800;
    margin-bottom: 8px;
    color: var(--text-primary);
}

.mission-countdown {
    display: inline-block;
    padding: 4px 12px;
    background: rgba(16, 185, 129, 0.12);
    color: #10B981;
    border: 1px solid rgba(16, 185, 129, 0.2);
    border-radius: var(--border-radius-md);
    font-size: 12px;
    font-weight: 700;
    margin-bottom: 12px;
}

.mission-subtext {
    font-size: 14px;
    color: var(--text-secondary);
    margin: 0;
}

.mission-card-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin-bottom: 32px;
}

.mission-item-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 20px;
    display: flex;
    align-items: center;
    gap: 18px;
    cursor: pointer;
    transition: all 0.2s ease;
}

.mission-item-card:hover {
    border-color: var(--accent-indigo);
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.04);
}

.mission-item-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--border-radius-xl);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.vocab-icon { background: rgba(59, 130, 246, 0.1); color: #3B82F6; }
.story-icon { background: rgba(139, 92, 246, 0.1); color: #8B5CF6; }
.listen-icon { background: rgba(16, 185, 129, 0.1); color: #10B981; }

.mission-item-card.completed-task {
    background: rgba(16, 185, 129, 0.03);
    border-color: rgba(16, 185, 129, 0.25);
    opacity: 0.85;
}
.mission-item-card.completed-task .mission-item-icon {
    background: rgba(16, 185, 129, 0.15);
    color: #10B981;
}

.mission-item-details {
    flex-grow: 1;
}

.mission-item-details h4 {
    font-size: 16px;
    font-weight: 700;
    margin: 0 0 4px 0;
    color: var(--text-primary);
}

.mission-item-details p {
    font-size: 13px;
    color: var(--text-secondary);
    margin: 0 0 6px 0;
}

.mission-item-time {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    gap: 4px;
}

.mission-extra-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-top: 1px solid var(--border-color);
    padding-top: 20px;
}

/* ==========================================================================
   COACH INTERVENTION BANNER STYLES
   ========================================================================== */
.coach-intervention-banner {
    background: linear-gradient(135deg, rgba(79, 70, 229, 0.08) 0%, rgba(99, 102, 241, 0.03) 100%);
    border: 1px solid rgba(79, 70, 229, 0.25);
    border-radius: var(--border-radius-lg);
    padding: 18px 24px;
    display: flex;
    align-items: flex-start;
    gap: 16px;
    margin-bottom: 24px;
    box-shadow: 0 4px 16px rgba(79, 70, 229, 0.05);
}

.coach-avatar-small {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: var(--gradient-primary, linear-gradient(135deg, #4F46E5, #6366F1));
    color: #FFFFFF;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.coach-intervention-content {
    flex-grow: 1;
}

.coach-intervention-badge {
    display: inline-block;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--accent-indigo, #4F46E5);
    margin-bottom: 4px;
}

.coach-intervention-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 4px 0;
}

.coach-intervention-text {
    font-size: 13px;
    color: var(--text-secondary);
    margin: 0;
    line-height: 1.5;
}

.coach-intervention-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.btn-primary-sm {
    background: var(--accent-indigo, #4F46E5);
    color: #FFFFFF;
    border: none;
    border-radius: 8px;
    padding: 8px 14px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
}

.btn-primary-sm:hover {
    background: #4338CA;
}

.btn-ghost-sm {
    background: transparent;
    border: none;
    color: var(--text-muted);
    padding: 8px;
    cursor: pointer;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.btn-ghost-sm:hover {
    background: rgba(0, 0, 0, 0.05);
    color: var(--text-primary);
}

/* ==========================================================================
   OUTCOME ANALYTICS & TELEMETRY STYLES
   ========================================================================== */
.analytics-layout {
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.analytics-header-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    padding: 24px 28px;
    box-shadow: var(--shadow-sm);
}

.analytics-header-card h2 {
    font-family: var(--font-heading);
    font-size: 22px;
    font-weight: 800;
    color: var(--text-primary);
    margin: 0 0 4px 0;
    display: flex;
    align-items: center;
    gap: 10px;
}

.analytics-subtitle {
    font-size: 14px;
    color: var(--text-secondary);
    margin: 0;
}

.analytics-metrics-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
}

.analytics-metric-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 20px 24px;
    display: flex;
    align-items: center;
    gap: 16px;
    box-shadow: var(--shadow-sm);
}

.analytics-metric-card.primary-gauge {
    background: linear-gradient(135deg, rgba(79, 70, 229, 0.06), rgba(99, 102, 241, 0.02));
    border-color: rgba(79, 70, 229, 0.2);
}

.analytics-metric-card .metric-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--border-radius-xl);
    background: rgba(79, 70, 229, 0.1);
    color: var(--accent-indigo, #4F46E5);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.metric-data {
    flex-grow: 1;
}

.metric-label {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    display: block;
    margin-bottom: 4px;
}

.metric-value-large {
    font-family: var(--font-heading);
    font-size: 28px;
    font-weight: 900;
    color: var(--accent-indigo, #4F46E5);
    line-height: 1.1;
    margin-bottom: 8px;
}

.metric-value {
    font-family: var(--font-heading);
    font-size: 24px;
    font-weight: 800;
    color: var(--text-primary);
    line-height: 1.2;
}

.metric-value small {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted);
}

.metric-subtext {
    font-size: 12px;
    color: var(--text-muted);
}

.metric-progress-bar {
    height: 6px;
    background: rgba(0, 0, 0, 0.08);
    border-radius: 3px;
    overflow: hidden;
}

.metric-progress-fill {
    height: 100%;
    background: var(--gradient-primary, linear-gradient(135deg, #4F46E5, #6366F1));
    border-radius: 3px;
    transition: width 0.4s ease;
}

.analytics-section-grid {
    display: grid;
    grid-template-columns: 1.3fr 1fr;
    gap: 20px;
}

.analytics-box {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    padding: 24px;
    box-shadow: var(--shadow-sm);
}

.analytics-box h3 {
    font-family: var(--font-heading);
    font-size: 17px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 16px 0;
    display: flex;
    align-items: center;
    gap: 8px;
}

.box-subtext {
    font-size: 13px;
    color: var(--text-muted);
    margin: -10px 0 20px 0;
}

.skill-bars-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.skill-bar-item {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.skill-bar-header {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
}

.skill-bar-track {
    height: 8px;
    background: rgba(0, 0, 0, 0.06);
    border-radius: 4px;
    overflow: hidden;
}

.skill-bar-fill {
    height: 100%;
    border-radius: 4px;
    transition: width 0.4s ease;
}

.lesen-fill { background: #3B82F6; }
.hoeren-fill { background: #8B5CF6; }
.schreiben-fill { background: #EC4899; }
.sprechen-fill { background: #10B981; }
.vocab-fill { background: #F59E0B; }
.grammar-fill { background: #6366F1; }

.activity-bars-container {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    height: 160px;
    padding-top: 20px;
    border-bottom: 1px solid var(--border-color);
}

.activity-bar-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    flex-grow: 1;
    height: 100%;
}

.activity-bar-fill-wrap {
    flex-grow: 1;
    width: 24px;
    background: rgba(0, 0, 0, 0.04);
    border-radius: 6px 6px 0 0;
    display: flex;
    align-items: flex-end;
    overflow: hidden;
}

.activity-bar-fill {
    width: 100%;
    background: var(--accent-indigo, #4F46E5);
    border-radius: 6px 6px 0 0;
    transition: height 0.3s ease;
}

.activity-bar-label {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
}

/* ==========================================================================
   SPRINT 6: AI COACH CHAT ASSISTANT STYLES
   ========================================================================== */
#coach-chat-widget-wrapper {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 1000;
}

#coach-chat-trigger {
    background: var(--gradient-primary, linear-gradient(135deg, #4F46E5, #6366F1));
    color: #FFFFFF;
    border: none;
    border-radius: 30px;
    padding: 12px 20px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 10px 25px rgba(79, 70, 229, 0.35);
    display: flex;
    align-items: center;
    gap: 8px;
    transition: all 0.2s ease;
}

#coach-chat-trigger:hover {
    transform: translateY(-2px);
    box-shadow: 0 14px 30px rgba(79, 70, 229, 0.45);
}

#coach-chat-modal {
    position: fixed;
    bottom: 84px;
    right: 24px;
    width: 380px;
    height: 520px;
    background: var(--bg-surface, #FFFFFF);
    border: 1px solid var(--border-color, #E2E8F0);
    border-radius: var(--border-radius-xl);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
    z-index: 1001;
}

.coach-chat-modal-hidden {
    opacity: 0;
    pointer-events: none;
    transform: translateY(20px) scale(0.95);
}

.coach-chat-modal-visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0) scale(1);
}

.chat-modal-header {
    background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(99, 102, 241, 0.04));
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-color, #E2E8F0);
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.chat-modal-teacher-info {
    display: flex;
    align-items: center;
    gap: 12px;
}

.teacher-avatar {
    font-size: 26px;
    background: rgba(79, 70, 229, 0.1);
    width: 42px;
    height: 42px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.teacher-name {
    font-family: var(--font-heading);
    font-size: 15px;
    font-weight: 800;
    margin: 0;
    color: var(--text-primary);
}

.teacher-role {
    font-size: 11px;
    font-weight: 600;
    color: var(--accent-indigo, #4F46E5);
}

.chat-modal-close {
    background: transparent;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 6px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.chat-modal-close:hover {
    background: rgba(0, 0, 0, 0.05);
    color: var(--text-primary);
}

.chat-modal-body {
    flex-grow: 1;
    padding: 16px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
    background: var(--bg-main, #F8FAFC);
}

.chat-msg {
    display: flex;
    max-width: 85%;
}

.chat-msg.coach-msg {
    align-self: flex-start;
}

.chat-msg.user-msg {
    align-self: flex-end;
}

.chat-msg-bubble {
    padding: 12px 16px;
    border-radius: 16px;
    font-size: 13px;
    line-height: 1.5;
}

.coach-msg .chat-msg-bubble {
    background: var(--bg-surface, #FFFFFF);
    color: var(--text-primary);
    border: 1px solid var(--border-color, #E2E8F0);
    border-top-left-radius: 4px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
}

.user-msg .chat-msg-bubble {
    background: var(--accent-indigo, #4F46E5);
    color: #FFFFFF;
    border-top-right-radius: 4px;
}

.chat-quick-prompts {
    padding: 10px 16px;
    display: flex;
    gap: 8px;
    overflow-x: auto;
    background: var(--bg-surface, #FFFFFF);
    border-top: 1px solid var(--border-color, #E2E8F0);
}

.prompt-chip {
    background: rgba(79, 70, 229, 0.06);
    color: var(--accent-indigo, #4F46E5);
    border: 1px solid rgba(79, 70, 229, 0.15);
    border-radius: 16px;
    padding: 6px 12px;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
    transition: all 0.2s ease;
}

.prompt-chip:hover {
    background: rgba(79, 70, 229, 0.12);
}

.chat-modal-footer {
    padding: 12px 16px;
    background: var(--bg-surface, #FFFFFF);
    border-top: 1px solid var(--border-color, #E2E8F0);
    display: flex;
    gap: 8px;
}

#coach-chat-input {
    flex-grow: 1;
    border: 1px solid var(--border-color, #E2E8F0);
    border-radius: var(--border-radius-md);
    padding: 10px 16px;
    font-size: 13px;
    outline: none;
    transition: border 0.2s ease;
}

#coach-chat-input:focus {
    border-color: var(--accent-indigo, #4F46E5);
}

#coach-chat-send-btn {
    background: var(--accent-indigo, #4F46E5);
    color: #FFFFFF;
    border: none;
    border-radius: 50%;
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.2s ease;
}

#coach-chat-send-btn:hover {
    background: #4338CA;
}

/* ==========================================================================
   SPRINT 7: GOETHE PASSING FORECAST & MILESTONES STYLES
   ========================================================================== */
.forecast-section-card {
    background: var(--bg-surface, #FFFFFF);
    border: 1px solid var(--border-color, #E2E8F0);
    border-radius: var(--border-radius-xl, 16px);
    padding: 24px 28px;
    box-shadow: var(--shadow-sm);
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.forecast-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.forecast-header h3 {
    font-family: var(--font-heading);
    font-size: 20px;
    font-weight: 800;
    margin: 0 0 4px 0;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 8px;
}

.forecast-subtext {
    font-size: 13px;
    color: var(--text-muted);
    margin: 0;
}

.forecast-badge {
    padding: 8px 16px;
    border-radius: var(--border-radius-md);
    font-size: 13px;
    font-weight: 800;
}

.forecast-badge.status-pass {
    background: rgba(16, 185, 129, 0.1);
    color: #059669;
    border: 1px solid rgba(16, 185, 129, 0.3);
}

.forecast-badge.status-warn {
    background: rgba(245, 158, 11, 0.1);
    color: #D97706;
    border: 1px solid rgba(245, 158, 11, 0.3);
}

.forecast-modules-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
}

.forecast-module-card {
    background: var(--bg-main, #F8FAFC);
    border: 1px solid var(--border-color, #E2E8F0);
    border-radius: var(--border-radius-xl);
    padding: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
}

.forecast-module-title {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
}

.forecast-module-val {
    font-family: var(--font-heading);
    font-size: 24px;
    font-weight: 900;
    color: var(--text-primary);
}

.module-status-chip {
    font-size: 10px;
    font-weight: 800;
    padding: 4px 10px;
    border-radius: var(--border-radius-md);
    text-transform: uppercase;
}

.chip-pass {
    background: rgba(16, 185, 129, 0.12);
    color: #059669;
}

.chip-ok {
    background: rgba(59, 130, 246, 0.12);
    color: #2563EB;
}

.chip-warn {
    background: rgba(239, 68, 68, 0.12);
    color: #DC2626;
}

.chip-neutral {
    background: rgba(148, 163, 184, 0.14);
    color: #64748B;
}

.forecast-milestone-bar {
    background: linear-gradient(135deg, rgba(79, 70, 229, 0.06), rgba(99, 102, 241, 0.02));
    border: 1px dashed rgba(79, 70, 229, 0.25);
    border-radius: var(--border-radius-sm);
    padding: 12px 18px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13px;
    color: var(--text-primary);
}

.forecast-milestone-bar i {
    color: var(--accent-indigo, #4F46E5);
}

/* ==========================================================================
   GOETHE B1 LESEN EXAM SIMULATOR STYLES (TASK 1)
   ========================================================================== */
.reading-simulator-container {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.reading-simulator-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
    background: var(--bg-surface-elevated, rgba(255, 255, 255, 0.05));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    border-radius: var(--border-radius-lg, 16px);
    padding: 16px 24px;
}

.reading-teil-tabs {
    display: flex;
    gap: 8px;
    overflow-x: auto;
}

.reading-teil-tab {
    padding: 8px 16px;
    border-radius: 8px;
    background: var(--bg-surface, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    color: var(--text-secondary);
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
    transition: all 0.2s ease;
}

.reading-teil-tab.active {
    background: var(--accent-indigo, #6366f1);
    color: #ffffff;
    border-color: var(--accent-indigo, #6366f1);
}

.reading-timer-badge {
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(239, 68, 68, 0.1);
    border: 1px solid rgba(239, 68, 68, 0.3);
    color: #ef4444;
    padding: 8px 16px;
    border-radius: var(--border-radius-md);
    font-weight: 700;
    font-size: 14px;
}

.reading-simulator-grid {
    display: grid;
    grid-template-columns: 1.1fr 1fr;
    gap: 24px;
    align-items: start;
}

@media (max-width: 900px) {
    .reading-simulator-grid {
        grid-template-columns: 1fr;
    }
}

/* B1 Lesen practice: the passage pane is the screen's ONE paper-bridge
   element (UI_UX_GUIDELINES.md §18) — the authentic Lesetext prints as paper
   while the question cards beside it stay app-world. Fixed paper palette,
   never theme vars. */
.reading-passage-panel {
    background-color: var(--paper-bg);
    background-image:
        radial-gradient(120% 60% at 30% -10%, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 60%),
        repeating-linear-gradient(0deg, rgba(120, 100, 60, 0.013) 0 2px, rgba(0, 0, 0, 0) 2px 5px);
    border: 1px solid #E4DCC9;
    border-radius: 2px;
    padding: 28px;
    position: sticky;
    top: 80px;
    max-height: calc(100vh - 130px);
    overflow-y: auto;
    box-shadow:
        0 1px 2px rgba(74, 60, 30, 0.07),
        2px 3px 0 -1px #F2ECDD,
        2px 3px 0 0 #D9D0BA;
}

.reading-passage-title {
    font-family: var(--font-paper);
    font-size: 21px;
    font-weight: 700;
    margin-bottom: 16px;
    color: var(--paper-ink);
    line-height: 1.35;
}

.reading-passage-body {
    max-width: 68ch;
    font-family: var(--font-paper);
    font-size: 16px;
    line-height: 1.75;
    color: var(--paper-ink);
    white-space: pre-line;
    word-break: break-word;
}

.reading-questions-panel {
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-height: calc(100vh - 130px);
    overflow-y: auto;
    padding-right: 4px;
}

.reading-question-card {
    background: var(--bg-surface-elevated, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    border-radius: var(--border-radius-md, 12px);
    padding: 20px;
    transition: border-color 0.2s ease;
}

.reading-question-card.answered {
    border-color: rgba(99, 102, 241, 0.35);
}

.reading-question-text {
    font-weight: 700;
    font-size: 14.5px;
    margin-bottom: 14px;
    color: var(--text-primary);
    line-height: 1.5;
}

.reading-option-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-radius: 10px;
    border: 1.5px solid var(--border-color, rgba(255, 255, 255, 0.12));
    background: var(--bg-surface, rgba(255, 255, 255, 0.02));
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    text-align: left;
    transition: all 0.18s ease;
    margin-bottom: 8px;
}

.reading-option-btn:hover:not(:disabled) {
    background: rgba(99, 102, 241, 0.08);
    border-color: var(--accent-indigo, #6366f1);
}

.reading-option-btn.selected {
    background: rgba(99, 102, 241, 0.14);
    border-color: var(--accent-indigo, #6366f1);
    color: var(--accent-indigo, #6366f1);
    font-weight: 700;
}

.reading-option-btn.correct-target {
    background: rgba(16, 185, 129, 0.15) !important;
    border-color: #10b981 !important;
    color: #10b981 !important;
    font-weight: 700;
}

.reading-option-btn.wrong-target {
    background: rgba(239, 68, 68, 0.15) !important;
    border-color: #ef4444 !important;
    color: #ef4444 !important;
}

.rf-btn-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.rf-pill-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px;
    border-radius: var(--border-radius-md);
    border: 1.5px solid var(--border-color, rgba(255, 255, 255, 0.12));
    background: var(--bg-surface, rgba(255, 255, 255, 0.02));
    color: var(--text-primary);
    font-weight: 700;
    font-size: 14.5px;
    cursor: pointer;
    transition: all 0.2s ease;
}

.rf-pill-btn:hover:not(:disabled) {
    background: rgba(99, 102, 241, 0.08);
    border-color: var(--accent-indigo, #6366f1);
}

.rf-pill-btn.selected {
    background: var(--accent-indigo, #6366f1);
    color: #ffffff;
    border-color: var(--accent-indigo, #6366f1);
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
}

.rf-pill-btn.correct-target {
    background: #10b981 !important;
    color: #ffffff !important;
    border-color: #10b981 !important;
}

.rf-pill-btn.wrong-target {
    background: #ef4444 !important;
    color: #ffffff !important;
    border-color: #ef4444 !important;
}

.citation-callout-box {
    margin-top: 14px;
    padding: 12px 16px;
    border-radius: 10px;
    background: rgba(99, 102, 241, 0.07);
    border-left: 4px solid var(--accent-indigo, #6366f1);
    display: flex;
    gap: 10px;
    align-items: flex-start;
}

.citation-text {
    font-size: 13px;
    line-height: 1.5;
    color: var(--text-primary);
    font-style: italic;
}

/* ==========================================================================
   GOETHE B1 HÖREN AUDIO PLAYER & SIMULATOR STYLES (TASK 2)
   ========================================================================== */
.listening-simulator-container {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.listening-audio-card {
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(16, 185, 129, 0.05));
    border: 1px solid rgba(99, 102, 241, 0.25);
    border-radius: var(--border-radius-lg, 16px);
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.listening-replay-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(99, 102, 241, 0.15);
    border: 1px solid rgba(99, 102, 241, 0.3);
    color: var(--accent-indigo, #6366f1);
    padding: 6px 14px;
    border-radius: var(--border-radius-md);
    font-size: 13px;
    font-weight: 700;
}

.audio-controls-row {
    display: flex;
    align-items: center;
    gap: 16px;
}

.audio-play-btn {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--accent-indigo, #6366f1);
    color: #ffffff;
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 18px;
    transition: transform 0.2s, background 0.2s;
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
}

.audio-play-btn:hover {
    transform: scale(1.05);
    background: #4f46e5;
}

.audio-progress-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.audio-progress-bar {
    width: 100%;
    height: 8px;
    background: var(--bg-surface, rgba(255, 255, 255, 0.1));
    border-radius: var(--border-radius-sm);
    overflow: hidden;
    cursor: pointer;
}

.audio-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #6366f1, #10b981);
    width: 0%;
    border-radius: var(--border-radius-sm);
    transition: width 0.1s linear;
}

/* ==========================================================================
   GOETHE B1 SCHREIBEN WORKSPACE & AI EVALUATOR STYLES (TASK 3)
   ========================================================================== */
.writing-workspace-container {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.writing-workspace-grid {
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    gap: 24px;
}

@media (max-width: 900px) {
    .writing-workspace-grid {
        grid-template-columns: 1fr;
    }
}

.writing-prompt-panel {
    background: var(--bg-surface-elevated, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    border-radius: var(--border-radius-lg, 16px);
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.writing-editor-panel {
    background: var(--bg-surface-elevated, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    border-radius: var(--border-radius-lg, 16px);
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.writing-editor-textarea {
    width: 100%;
    min-height: 280px;
    background: var(--bg-surface, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.15));
    border-radius: var(--border-radius-md, 12px);
    padding: 16px;
    color: var(--text-primary);
    font-family: inherit;
    font-size: 17px;
    line-height: 1.6;
    resize: vertical;
}

.writing-editor-textarea:focus {
    outline: none;
    border-color: var(--accent-indigo, #6366f1);
    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
}

.writing-counters-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 14px;
    background: var(--bg-surface, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    border-radius: 8px;
    font-size: 14.5px;
    font-weight: 600;
}

.writing-rubric-card {
    background: var(--bg-surface, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    border-radius: 10px;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}






/* ==========================================================================
   TAGESPLAN CARD (A1 daily plan) — the app's hero surface.
   Structure follows the user-approved glass preview (2026-08-08): header +
   progress ring, numbered block rows with a highlighted "next", jewels for
   streak/XP, one full-width pill CTA. Colors come entirely from theme
   tokens, so light renders forest-green-on-white glass and dark renders
   the same forest green on green-black glass with zero per-theme rules here.
   ========================================================================== */
.tp-card {
    max-width: 620px;
    margin: 0 auto;
    padding: 30px 30px 26px;
}

.tp-top {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 18px;
}

.tp-top h2 {
    font-family: var(--font-heading);
    font-size: 23px;
    font-weight: 750;
    letter-spacing: -0.015em;
    margin: 0;
    color: var(--text-primary);
}

.tp-sub {
    margin: 5px 0 0;
    font-size: 13px;
    color: var(--text-secondary);
}
.tp-sub b { color: var(--text-primary); font-weight: 650; }

.tp-ring { position: relative; width: 74px; height: 74px; flex-shrink: 0; }
.tp-ring svg { transform: rotate(-90deg); display: block; }
.tp-ring circle { fill: none; stroke-width: 6; }
.tp-ring .tp-ring-track { stroke: var(--border-color); }
.tp-ring .tp-ring-val {
    stroke: var(--accent-indigo);
    stroke-linecap: round;
    transition: stroke-dashoffset 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.tp-ring-num {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.tp-ring-num b {
    font-family: var(--font-mono);
    font-size: 15px;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
}
.tp-ring-num span {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
}

.tp-blocks { margin-top: 18px; display: flex; flex-direction: column; gap: 9px; }

.tp-blk {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 12px 15px;
    border-radius: var(--border-radius-md);
    font-size: 14.5px;
    background: var(--bg-surface-elevated);
    border: 1px solid transparent;
    color: var(--text-primary);
    transition: var(--transition-smooth);
}
.tp-blk:hover { transform: translateY(-1px); border-color: var(--border-color); }

.tp-blk-st {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    border: 1.5px solid var(--border-color);
    color: var(--text-secondary);
    background: transparent;
}
.tp-blk.done .tp-blk-st { border-color: transparent; background: var(--success-bg); color: var(--success); }
.tp-blk.done .tp-blk-t {
    color: var(--text-muted);
    text-decoration: line-through;
    text-decoration-color: var(--success);
    text-decoration-thickness: 1.5px;
}
.tp-blk.next {
    background: var(--accent-tint);
    border-color: var(--accent-tint-border);
}
.tp-blk.next .tp-blk-st { border-color: var(--accent-indigo); color: var(--accent-indigo); }
.tp-blk.next .tp-blk-t { font-weight: 700; }
.tp-blk-t { flex: 1; }
.tp-blk-m {
    font-size: 11.5px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tp-foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
    flex-wrap: wrap;
}
.tp-mockline { font-size: 12.5px; color: var(--text-secondary); }
.tp-mockline b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.tp-jewels { display: flex; gap: 14px; font-size: 12.5px; color: var(--text-secondary); }
.tp-jewels b { color: var(--warning); font-variant-numeric: tabular-nums; font-weight: 700; }
.tp-jewels .tp-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--warning);
    margin-right: 6px;
    vertical-align: 2px;
}

.tp-cta {
    width: 100%;
    margin-top: 18px;
    padding: 14px 26px;
    border: none;
    border-radius: 999px;
    background: var(--accent-gradient);
    color: var(--on-accent);
    font-family: var(--font-body);
    font-size: 14.5px;
    font-weight: 800;
    letter-spacing: 0.01em;
    cursor: pointer;
    box-shadow: var(--shadow-md);
    transition: var(--transition-smooth);
}
.tp-cta:hover {
    background: var(--accent-gradient-hover);
    transform: translateY(-1px);
    box-shadow: var(--shadow-premium);
}
.tp-cta:focus-visible { outline: 3px solid var(--border-color-focus); outline-offset: 2px; }
body.dark-theme .tp-cta { box-shadow: 0 6px 22px -6px rgba(30, 111, 84, 0.55); }
body.dark-theme .tp-cta:hover { box-shadow: 0 8px 30px -6px rgba(38, 132, 100, 0.70); }

.tp-note { font-size: 12px; color: var(--accent-indigo); margin: 6px 0 0; }
.tp-done-banner {
    text-align: center;
    padding: 16px;
    background: var(--success-bg);
    border: 1px solid var(--success);
    border-radius: var(--border-radius-lg);
    margin-top: 16px;
}
.tp-done-banner p { margin: 0; font-weight: 800; color: var(--success); }
.tp-done-banner .tp-done-sub { font-size: 12px; font-weight: 400; color: var(--text-secondary); margin-top: 4px; }

@media (max-width: 560px) {
    .tp-card { padding: 22px 18px 20px; }
    .tp-ring { width: 62px; height: 62px; }
}

/* ==========================================================================
   LANDING PAGE (landing.js) — public marketing homepage.
   Styled entirely through theme tokens + the glass system, so light shows
   white/forest-green glass and dark shows green-black/forest-green glass with no
   per-theme rules except where glow strength genuinely differs.
   ========================================================================== */
.ld-container { width: min(1080px, 92%); margin: 0 auto; }

.ld-hero {
    position: relative;
    isolation: isolate;
    padding: 72px 0 84px;
    overflow: hidden;
}
/* Ambient green/white/gold wash - the founder-approved keeper from the
   2026-08-21 pass. Two brand-coloured pools that drift very slowly against
   each other, so the hero background feels alive without ever moving fast
   enough to compete with the copy. Static under prefers-reduced-motion. */
.ld-hero-aurora {
    position: absolute;
    inset: -30% -12% auto -12%;
    height: 160%;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(46% 40% at 22% 22%, rgba(15, 76, 58, 0.13), rgba(15, 76, 58, 0) 70%),
        radial-gradient(40% 38% at 82% 14%, rgba(169, 133, 47, 0.14), rgba(169, 133, 47, 0) 72%),
        radial-gradient(60% 45% at 50% 4%, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0) 70%);
    animation: ldAuroraDrift 26s ease-in-out infinite alternate;
}
body.dark-theme .ld-hero-aurora {
    background:
        radial-gradient(46% 40% at 22% 22%, rgba(30, 111, 84, 0.26), rgba(30, 111, 84, 0) 70%),
        radial-gradient(40% 38% at 82% 14%, rgba(217, 179, 108, 0.14), rgba(217, 179, 108, 0) 72%),
        radial-gradient(60% 45% at 50% 4%, rgba(242, 239, 230, 0.07), rgba(242, 239, 230, 0) 70%);
}
@keyframes ldAuroraDrift {
    from { transform: translate3d(-2.5%, 0, 0) scale(1); }
    to   { transform: translate3d(2.5%, 3%, 0) scale(1.06); }
}
.ld-hero-grain {
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: 0.5;
    background-image: repeating-linear-gradient(0deg, rgba(60, 50, 30, 0.016) 0 2px, rgba(0, 0, 0, 0) 2px 5px);
}
.ld-hero-grid {
    width: min(1080px, 92%);
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1.05fr 0.95fr;
    gap: 56px;
    align-items: center;
    text-align: left;
}
.ld-hero-copy h1 {
    font-family: var(--font-heading);
    font-size: clamp(30px, 4.6vw, 46px);
    font-weight: 800;
    letter-spacing: -0.025em;
    line-height: 1.12;
    color: var(--text-primary);
    margin: 14px 0 0;
}
.ld-sub {
    margin: 18px 0 26px;
    font-size: 16px;
    color: var(--text-secondary);
    max-width: 54ch;
    line-height: 1.6;
}
.ld-cta-main { padding: 14px 28px; font-size: 15px; border-radius: 999px; }
.ld-fineprint {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
    margin-top: 22px;
    font-size: 12.5px;
    color: var(--text-muted);
}
.ld-fineprint span { display: inline-flex; align-items: center; gap: 6px; }
.ld-fineprint svg { color: var(--success); flex-shrink: 0; }

/* ---- demo player ---- */
.ld-demo { display: flex; justify-content: center; }
.ld-demo-frame {
    width: min(400px, 100%);
    background: var(--glass-bg);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-xl);
    box-shadow: var(--shadow-premium), inset 0 1.5px 0 var(--glass-rim);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    padding: 18px 18px 12px;
}
body.dark-theme .ld-demo-frame {
    box-shadow: 0 24px 56px rgba(4, 8, 6, 0.55), inset 0 1.5px 0 var(--glass-rim);
}
.ld-demo-stage { position: relative; min-height: 300px; }
.ld-shot {
    position: absolute;
    inset: 0;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.5s ease, transform 0.5s ease;
    pointer-events: none;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ld-shot.ld-shot-active { opacity: 1; transform: translateY(0); }
.ld-shot-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: var(--font-heading);
    font-size: 15px;
    font-weight: 750;
    color: var(--text-primary);
    margin-bottom: 4px;
}
.ld-ring, .ld-timer {
    font-family: var(--font-mono);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--accent-indigo);
    border: 1.5px solid var(--accent-indigo);
    border-radius: 999px;
    padding: 3px 10px;
}
.ld-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: var(--border-radius-md);
    background: var(--bg-surface-elevated);
    border: 1px solid transparent;
    font-size: 13px;
    color: var(--text-primary);
}
.ld-row em { margin-left: auto; font-style: normal; font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ld-row .ld-st {
    width: 21px; height: 21px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 10.5px; font-weight: 700;
    border: 1.5px solid var(--border-color); color: var(--text-secondary);
    flex-shrink: 0;
}
.ld-row.done .ld-st { border-color: transparent; background: var(--success-bg); color: var(--success); }
.ld-row.done { color: var(--text-muted); }
.ld-row.next { background: var(--accent-tint); border-color: var(--accent-tint-border); font-weight: 700; }
.ld-row.next .ld-st { border-color: var(--accent-indigo); color: var(--accent-indigo); }
.ld-pill {
    margin-top: 6px;
    text-align: center;
    padding: 11px;
    border-radius: 999px;
    background: var(--accent-gradient);
    color: var(--on-accent);
    font-size: 13px;
    font-weight: 800;
}
.ld-q { font-size: 17px; font-weight: 750; color: var(--text-primary); margin: 2px 0 6px; }
.ld-opt {
    padding: 10px 13px;
    border-radius: var(--border-radius-md);
    border: 1px solid var(--border-color);
    background: var(--bg-surface-elevated);
    font-size: 13.5px;
    color: var(--text-primary);
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.ld-opt.right { border-color: var(--success); background: var(--success-bg); }
.ld-opt.right b { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--success); }
.ld-opt.sel { border-color: var(--accent-indigo); background: var(--accent-tint); font-weight: 700; }
.ld-expl {
    padding: 10px 13px;
    border-radius: var(--border-radius-md);
    background: var(--info-bg);
    border: 1px solid var(--accent-indigo);
    font-size: 12.5px;
    color: var(--text-primary);
}
.ld-fw-in {
    align-self: flex-end;
    max-width: 85%;
    padding: 10px 14px;
    border-radius: var(--border-radius-lg);
    border-bottom-right-radius: 4px;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    font-size: 13px;
    color: var(--text-secondary);
    /* Not italic, deliberately. This is the ONE element on the landing page that
       rendered italic body text, and a browser downloads a font face the moment
       a single glyph needs it - so this one mock chat line was fetching the
       whole Inter-Italic file for every visitor who ever loaded the page. The
       German quotation marks around the sentence already mark it as quoted
       speech, which is all the italic was doing. */
}
.ld-fw-out {
    align-self: flex-start;
    max-width: 92%;
    padding: 12px 15px;
    border-radius: var(--border-radius-lg);
    border-bottom-left-radius: 4px;
    background: var(--accent-tint);
    border: 1px solid var(--accent-tint-border);
    font-size: 13px;
    color: var(--text-primary);
    line-height: 1.55;
}
.ld-audio {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 15px;
    border-radius: var(--border-radius-md);
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    color: var(--accent-indigo);
    font-weight: 700;
}
.ld-wave { display: flex; align-items: center; gap: 3px; height: 18px; }
.ld-wave i {
    width: 3px;
    border-radius: 2px;
    background: var(--accent-indigo);
    animation: ld-wave 1.1s ease-in-out infinite;
}
.ld-wave i:nth-child(1) { height: 6px; animation-delay: 0s; }
.ld-wave i:nth-child(2) { height: 12px; animation-delay: 0.12s; }
.ld-wave i:nth-child(3) { height: 16px; animation-delay: 0.24s; }
.ld-wave i:nth-child(4) { height: 9px;  animation-delay: 0.36s; }
.ld-wave i:nth-child(5) { height: 14px; animation-delay: 0.48s; }
.ld-wave i:nth-child(6) { height: 7px;  animation-delay: 0.6s; }
.ld-wave i:nth-child(7) { height: 12px; animation-delay: 0.72s; }
.ld-wave i:nth-child(8) { height: 5px;  animation-delay: 0.84s; }
@keyframes ld-wave { 0%, 100% { transform: scaleY(0.6); } 50% { transform: scaleY(1.25); } }

.ld-demo-dots { display: flex; justify-content: center; gap: 8px; padding-top: 12px; }
.ld-demo-dots button {
    width: 8px; height: 8px;
    border-radius: 50%;
    border: none;
    background: var(--border-color);
    cursor: pointer;
    padding: 0;
    transition: var(--transition-smooth);
}
.ld-demo-dots button.on { background: var(--accent-indigo); transform: scale(1.3); }

/* ---- stats ---- */
.ld-stats { padding: 56px 0 8px; }
.ld-stats-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 28px;
    text-align: center;
}
.ld-stat h3 {
    font-family: var(--font-heading);
    font-size: clamp(28px, 3.6vw, 40px);
    font-weight: 800;
    color: var(--accent-indigo);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}
.ld-stat p { font-size: 12.5px; color: var(--text-secondary); margin-top: 4px; line-height: 1.45; }
.ld-stats-note { text-align: center; font-size: 12px; color: var(--text-muted); margin-top: 26px; }

/* Odometer digit roll (initLandingStats in landing.js). Sizes are all in em
   so the reel scales with .ld-stat h3's own responsive clamp() font-size -
   .ld-reel's height must track the digit spans' height exactly, or the
   translateY roll lands mid-digit instead of squarely on the next one. */
.ld-reel {
    display: inline-flex;
    overflow: hidden;
    height: 1em;
    line-height: 1em;
    vertical-align: bottom;
}
.ld-reel-strip {
    display: flex;
    flex-direction: column;
    transform: translateY(0);
    transition: transform 900ms cubic-bezier(0.22, 1, 0.36, 1);
}
.ld-reel-strip span {
    height: 1em;
    line-height: 1em;
    text-align: center;
}
.ld-static {
    display: inline-block;
    /* Must match .ld-reel-strip span's box metrics exactly. h3 inherits
       line-height 1.6, so without this the separator's taller line box sits
       ~0.3em higher than the digits and a comma reads as a mid-height dot. */
    height: 1em;
    line-height: 1em;
    vertical-align: bottom;
}

/* ---- shared section chrome ---- */
.ld-section-head { text-align: center; max-width: 640px; margin: 0 auto 44px; }
.ld-section-head h2 {
    font-family: var(--font-heading);
    font-size: clamp(24px, 3.6vw, 34px);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--text-primary);
}
.ld-section-head p { color: var(--text-secondary); margin-top: 12px; font-size: 15px; }
.ld-eyebrow {
    display: inline-block;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent-indigo);
    margin-bottom: 12px;
}

/* ---- features ---- */
.ld-features { padding: 72px 0; }
.ld-feat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.ld-feat h3 { font-size: 16px; font-weight: 750; color: var(--text-primary); margin-bottom: 6px; }
.ld-feat p { font-size: 13.5px; color: var(--text-secondary); line-height: 1.6; }
.ld-feat-icon {
    width: 46px; height: 46px;
    border-radius: var(--border-radius-md);
    display: flex; align-items: center; justify-content: center;
    background: var(--accent-tint);
    color: var(--accent-indigo);
    margin-bottom: 14px;
}

/* ---- how it works ---- */
.ld-how { padding: 40px 0 72px; }
.ld-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 26px; }
.ld-step { padding-top: 8px; will-change: transform, opacity; }
.ld-step-n {
    font-family: var(--font-heading);
    font-size: 40px;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--accent-indigo);
    opacity: 0.35;
    line-height: 1;
    display: block;
    margin-bottom: 12px;
}
.ld-step h3 { font-size: 16px; font-weight: 750; color: var(--text-primary); margin-bottom: 8px; }
.ld-step p { font-size: 13.5px; color: var(--text-secondary); line-height: 1.6; }

/* ---- honesty block ---- */
.ld-honest { padding: 8px 0 72px; }
.ld-honest-card { padding: 40px; }
.ld-honest-card h2 {
    font-family: var(--font-heading);
    font-size: clamp(22px, 3.2vw, 30px);
    font-weight: 800;
    color: var(--text-primary);
    margin-bottom: 14px;
}
.ld-honest-card > p { font-size: 14.5px; color: var(--text-secondary); line-height: 1.7; max-width: 70ch; }
.ld-honest-card b { color: var(--text-primary); }
.ld-levels { display: flex; flex-direction: column; gap: 10px; margin-top: 22px; }
.ld-level {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 13.5px;
    color: var(--text-secondary);
    padding: 10px 14px;
    border-radius: var(--border-radius-md);
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
}

/* ---- FAQ ---- */
.ld-faq { padding: 8px 0 72px; }
.ld-faq-list { max-width: 720px; margin: 0 auto; display: flex; flex-direction: column; gap: 12px; }
.ld-faq-item {
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    background: var(--bg-surface);
    overflow: hidden;
    transition: var(--transition-smooth);
}
.ld-faq-item.open { border-color: var(--border-color-focus); }
.ld-faq-q {
    width: 100%;
    background: none;
    border: none;
    padding: 18px 22px;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
    cursor: pointer;
    text-align: left;
}
.ld-chev {
    flex-shrink: 0;
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    display: flex; align-items: center; justify-content: center;
    font-weight: 700;
    color: var(--text-secondary);
    transition: var(--transition-smooth);
}
.ld-faq-item.open .ld-chev { transform: rotate(45deg); color: var(--accent-indigo); border-color: var(--accent-indigo); }
.ld-faq-a { max-height: 0; overflow: hidden; transition: max-height 0.35s ease; }
.ld-faq-a > div { padding: 0 22px 20px; font-size: 13.5px; color: var(--text-secondary); line-height: 1.65; }

/* ---- CTA band ---- */
.ld-cta-band { padding: 8px 0 84px; }
.ld-cta-card {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    background: var(--cta-band-gradient);
    color: var(--on-accent);
    border-radius: 24px;
    padding: 56px 32px;
    text-align: center;
    box-shadow: var(--shadow-premium);
}

/* Floating German "stickers" in the green: umlauts, article chips, level
   chips and a tiny Bestanden stamp, drifting slowly behind the copy.
   Faint by design (the copy stays boss), placed toward the card's edges,
   never interactive. Each sticker gets its own duration/delay so the
   ensemble never visibly repeats; alternate + ease-in-out keeps the drift
   soft with no jump at the loop point. */
.ld-cta-floats {
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
}
.ld-fl {
    position: absolute;
    /* linear, not ease-in-out: an eased loop spends most of its time near
       the keyframes, which is exactly what made the drift look frozen. */
    animation: ldFloat var(--fl-dur, 9s) linear var(--fl-delay, 0s) infinite;
    will-change: transform;
}
/* A wandering loop, not a two-point slide. The first version travelled 24px
   over 10-16s with ease-in-out, i.e. roughly 1.5px/second and slowest at
   both ends - which reads as frozen (founder: "it's almost frozen"). This
   traces a closed path ~66px tall and ~40px wide at a steady linear pace,
   so each sticker is always visibly moving and never parks. The path
   returns to its origin, so it loops with `infinite` rather than
   `alternate` - no direction flip, no pause at the turn. */
@keyframes ldFloat {
    0%   { transform: translate3d(0, 0, 0)        rotate(var(--fl-rot, -6deg)); }
    20%  { transform: translate3d(14px, -22px, 0) rotate(var(--fl-rot2, 6deg)); }
    45%  { transform: translate3d(4px, -44px, 0)  rotate(var(--fl-rot, -6deg)); }
    62%  { transform: translate3d(-16px, -32px, 0) rotate(var(--fl-rot2, 6deg)); }
    82%  { transform: translate3d(-10px, -12px, 0) rotate(var(--fl-rot, -6deg)); }
    100% { transform: translate3d(0, 0, 0)        rotate(var(--fl-rot, -6deg)); }
}
/* Tiny umlaut confetti - the same paper serif the exam booklet uses, at
   text scale rather than billboard scale (founder: "too big, I need tiny
   umlauts"). Small enough that they read as scattered marks in the green,
   so opacity can sit a little higher than the earlier oversized version
   without ever competing with the copy. */
.ld-fl-glyph {
    font-family: var(--font-paper, Georgia, serif);
    font-style: italic;
    font-weight: 700;
    font-size: 26px;
    line-height: 1;
    color: rgba(255, 255, 255, 0.20);
}
/* Tiny article chips - "der · die · das" and the three articles on their
   own, like little stickers scattered across the card. */
.ld-fl-chip {
    font-family: var(--font-heading);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    white-space: nowrap;
    color: rgba(255, 255, 255, 0.42);
    background: rgba(255, 255, 255, 0.07);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px;
    padding: 4px 10px;
}
/* Placement: strictly the left and right gutters (outer ~20% each side).
   The copy column occupies roughly the middle 55% at every width, so
   confining decoration to the gutters makes collisions structurally
   impossible rather than tuned-by-eye - an earlier pass put a "ß" across
   "closer." and a "das" chip across the fine print. Sizes vary per position
   so the scatter reads as depth, not a grid. */
.ld-fl-1  { top: 14%; left: 6%;      font-size: 30px; --fl-dur: 8s; --fl-rot: -8deg; --fl-rot2: 4deg; }
.ld-fl-3  { bottom: 20%; left: 11%;  font-size: 22px; --fl-dur: 6.5s; --fl-delay: -3s; --fl-rot: 5deg; --fl-rot2: -7deg; }
.ld-fl-4  { top: 34%; left: 15%;     font-size: 20px; --fl-dur: 9s; --fl-delay: -8s; --fl-rot: -6deg; --fl-rot2: 5deg; }
.ld-fl-6  { bottom: 10%; left: 14%;  font-size: 19px; --fl-dur: 7.5s; --fl-delay: -9s; --fl-rot: -5deg; --fl-rot2: 6deg; }
.ld-fl-7  { top: 62%; left: 8%;      font-size: 23px; --fl-dur: 8.5s; --fl-delay: -4s; --fl-rot: 9deg; --fl-rot2: -3deg; }
.ld-fl-10 { top: 45%; left: 4%;      --fl-dur: 7s; --fl-delay: -7s; --fl-rot: 6deg; --fl-rot2: -4deg; }

.ld-fl-2  { bottom: 14%; right: 7%;  font-size: 28px; --fl-dur: 9.5s; --fl-delay: -6s; --fl-rot: 6deg; --fl-rot2: -5deg; }
.ld-fl-5  { top: 30%; right: 12%;    font-size: 24px; --fl-dur: 6.8s; --fl-delay: -2s; --fl-rot: 7deg; --fl-rot2: -4deg; }
.ld-fl-8  { top: 54%; right: 6%;     font-size: 18px; --fl-dur: 10s; --fl-delay: -11s; --fl-rot: -7deg; --fl-rot2: 4deg; }
.ld-fl-9  { top: 20%; right: 5%;     --fl-dur: 8.2s; --fl-delay: -5s; --fl-rot: -5deg; --fl-rot2: 3deg; }
.ld-fl-11 { bottom: 28%; right: 16%; --fl-dur: 7.2s; --fl-delay: -1s; --fl-rot: -4deg; --fl-rot2: 6deg; }
.ld-fl-12 { bottom: 8%; right: 19%;  --fl-dur: 9.2s; --fl-delay: -10s; --fl-rot: 8deg; --fl-rot2: -5deg; }
@media (max-width: 700px) {
    /* On a narrow card the headline wraps to three lines and fills the upper
       half, so the chips - solid enough to read as foreground - collided
       with it (caught at 390px). Phones keep the umlaut confetti, which is
       faint enough to sit behind text, plus the one full "der · die · das"
       chip parked low where nothing else is. */
    .ld-fl-10, .ld-fl-11, .ld-fl-12 { display: none; }
    .ld-fl-9 { top: auto; bottom: 6%; right: 6%; }
    .ld-fl-4, .ld-fl-8 { display: none; }
}
.ld-cta-card h2 {
    font-family: var(--font-heading);
    font-size: clamp(24px, 3.8vw, 34px);
    font-weight: 800;
    color: var(--on-accent);
    letter-spacing: -0.02em;
}
.ld-cta-card p { margin: 14px auto 28px; max-width: 46ch; opacity: 0.85; font-size: 15px; }
.ld-cta-card .btn-primary {
    /* .btn-primary is display:flex (block-level), so the card's text-align:
       center can't center it like it centers the heading/paragraph text -
       it needs its own auto margins. */
    margin: 0 auto;
    background: var(--bg-surface);
    color: var(--text-primary);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
}
.ld-cta-fine { margin-top: 16px; font-size: 12px; opacity: 0.7; }

/* ---- footer ---- */
.ld-footer { border-top: 1px solid var(--border-color); padding: 28px 0; }
.ld-foot-inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    font-size: 12.5px;
    color: var(--text-muted);
}
.ld-foot-links { display: flex; gap: 20px; }
.ld-foot-links a { color: var(--text-secondary); text-decoration: none; font-weight: 600; }
.ld-foot-links a:hover { color: var(--accent-indigo); }
/* Legal links sit quieter than the product links next to them - present and
   findable, never competing with the call to action. */
.ld-foot-legal a { font-weight: 500; color: var(--text-muted); }

/* ---- legal pages (AGB / Datenschutz / Widerruf / Kontakt) ----
   A long document read once, usually by someone who is worried. Measure kept
   narrow and line-height generous so it is genuinely readable, not a wall. */
.legal-page { max-width: 720px; margin: 0 auto; padding: 48px 24px 80px; }
.legal-header { margin-bottom: 32px; padding-bottom: 24px; border-bottom: 1px solid var(--border-color); }
.legal-header h2 { font-size: 30px; margin: 0 0 6px; }
.legal-header p { margin: 0; color: var(--text-muted); font-size: 14px; }
.legal-body { font-size: 15px; line-height: 1.75; color: var(--text-primary); }
.legal-h { font-size: 17px; font-weight: 700; margin: 30px 0 10px; }
.legal-p { margin: 0 0 14px; color: var(--text-secondary); }
.legal-list { margin: 0 0 16px; padding-left: 20px; color: var(--text-secondary); }
.legal-list li { margin-bottom: 7px; }
.legal-body a { color: var(--accent-indigo); }
.legal-warning {
    margin-bottom: 24px; padding: 14px 16px; border-radius: 8px; font-size: 14px;
    background: rgba(234,179,8,0.10); border: 1px solid rgba(234,179,8,0.45); color: #7a5b00;
}
.legal-warning code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.legal-footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--border-color); font-size: 14px; }
.legal-footer a { color: var(--text-secondary); text-decoration: none; font-weight: 600; }
.legal-footer a:hover { color: var(--accent-indigo); }
@media (max-width: 640px) {
    .legal-page { padding: 32px 18px 64px; }
    .legal-header h2 { font-size: 24px; }
}

/* ---- reveal ---- */
.ld-reveal { opacity: 0; transform: translateY(22px); transition: opacity 0.6s ease, transform 0.6s ease; }
.ld-reveal.in { opacity: 1; transform: translateY(0); }

/* ---- hero: word-by-word split-text reveal (Motion, JS-driven) ----
   Each word is wrapped in a span at render time (initLandingHeroReveal);
   this class just establishes the box the animation runs against. Motion
   sets the initial opacity/transform inline before the first paint, so
   there's no unstyled flash - see initLandingHeroReveal in landing.js. */
.ld-hero-copy h1 .ld-word { display: inline-block; will-change: transform, opacity, filter; }

/* "Goethe-Zertifikat" carries the brand wash inside the type itself: a
   green->gold gradient clipped to the glyphs, shimmering slowly (React Bits
   "GradientText", rebuilt in CSS). background-size 200% gives the position
   animation room to travel; the fallback color underneath means the word
   never disappears if background-clip:text is unsupported. */
.ld-word-shine {
    color: var(--accent-indigo);
    background: linear-gradient(100deg, #0F4C3A 0%, #2E8763 28%, #C9A961 52%, #2E8763 74%, #0F4C3A 100%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: ldShineSweep 6s ease-in-out infinite;
}
body.dark-theme .ld-word-shine {
    background-image: linear-gradient(100deg, #329578 0%, #D9B36C 40%, #F2EFE6 55%, #D9B36C 70%, #329578 100%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
}
@keyframes ldShineSweep {
    0%, 100% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
}

/* Feature cards: cursor-following spotlight (React Bits "SpotlightCard").
   The glow is a pseudo-element radial anchored to --spot-x/--spot-y, which
   initLandingSpotlight() updates on pointermove; only opacity transitions,
   so the hot path is a compositor-only property. The .ld-spot class is
   added by JS on fine-pointer devices only - the base card is untouched on
   touch and under reduced motion. */
.ld-feat.ld-spot {
    position: relative;
    overflow: hidden;
}
.ld-feat.ld-spot::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.35s ease;
    background: radial-gradient(220px circle at var(--spot-x, 50%) var(--spot-y, 50%),
        rgba(15, 76, 58, 0.10), rgba(169, 133, 47, 0.05) 45%, transparent 70%);
}
body.dark-theme .ld-feat.ld-spot::after {
    background: radial-gradient(220px circle at var(--spot-x, 50%) var(--spot-y, 50%),
        rgba(50, 149, 120, 0.14), rgba(217, 179, 108, 0.05) 45%, transparent 70%);
}
.ld-feat.ld-spot:hover::after { opacity: 1; }

/* ---- app preview: restrained mouse-tilt (Motion drives the settle-back
   spring on pointerleave; pointermove sets the transform directly for
   1:1 responsiveness - see initLandingTilt). Disabled entirely for touch
   input and prefers-reduced-motion (JS-gated, not just CSS). ---- */
.ld-demo { perspective: 1200px; }
.ld-demo-frame { will-change: transform; }

/* ---- "built in class, not in a lab": honest facts ticker, alongside
   (not replacing) the existing static per-level status list. Slow,
   continuous, pauses on hover/focus - no fabricated quotes, no avatars,
   no invented names: every chip is a fact already stated on this page. ---- */
.ld-ticker {
    margin-top: 24px;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.ld-ticker-track {
    display: flex;
    gap: 12px;
    width: max-content;
    animation: ldTickerScroll 32s linear infinite;
}
.ld-ticker:hover .ld-ticker-track,
.ld-ticker:focus-within .ld-ticker-track {
    animation-play-state: paused;
}
.ld-ticker-chip {
    flex: 0 0 auto;
    white-space: nowrap;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-secondary);
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 9px 16px;
}
@keyframes ldTickerScroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* ---- pricing: real A1/A2/B1 course cards (no invented monthly/yearly
   toggle - the product has no such billing model to animate honestly). ---- */
.ld-pricing { padding: 8px 0 72px; }
.ld-pricing-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 22px;
    margin-top: 34px;
}
.ld-price-card {
    padding: 30px 26px;
    display: flex;
    flex-direction: column;
    will-change: transform, opacity;
}
.ld-price-card h3 { font-family: var(--font-heading); font-size: 20px; font-weight: 800; margin: 14px 0 6px; }
.ld-price-card p { font-size: 13.5px; color: var(--text-secondary); line-height: 1.6; margin-bottom: 22px; flex: 1; }
/* Holds a real amount now rather than the word "Free", so it is sized like a
   price. Empty when a level is not for sale - see applyLivePricing(). */
.ld-price-free {
    font-size: 26px;
    font-weight: 800;
    color: var(--accent-indigo);
    margin-bottom: 4px;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
    min-height: 32px;
}
/* The card's primary action is now an <a> to the level's own page, not a
   button into the SPA: these are server-rendered URLs, and a real href is what
   a crawler follows and what a reader can open in a new tab. */
.ld-price-cta {
    width: 100%;
    justify-content: center;
    text-decoration: none;
}
.ld-price-alt {
    margin-top: 10px;
    width: 100%;
    background: none;
    border: none;
    padding: 6px 0;
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
    transition: var(--transition-smooth);
}
.ld-price-alt:hover { color: var(--text-primary); }

/* The upgrade price sits on the same line as "Free to start" but reads as the
   secondary fact: free is the offer, the price is the answer to "and then?".
   Filled from /api/public/pricing at runtime - empty until it resolves, so the
   line must look finished without it. */
.ld-price-from { font-weight: 600; color: var(--text-secondary); }
.ld-price-sep { opacity: 0.45; margin: 0 4px; }
.ld-price-note { font-weight: 500; opacity: 0.75; }

/* ---- final CTA: sheen sweep + lift on hover (this button only - the
   hero's primary CTA stays plain, per "prefer restraint": one animated
   moment at the very end of the page, not everywhere). ---- */
.ld-cta-band .ld-cta-main {
    position: relative;
    overflow: hidden;
    transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
.ld-cta-band .ld-cta-main::after {
    content: '';
    position: absolute;
    top: 0; left: -60%;
    width: 40%; height: 100%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.32), transparent);
    transform: skewX(-20deg);
    transition: left 0.65s cubic-bezier(0.16, 1, 0.3, 1);
    pointer-events: none;
}
.ld-cta-band .ld-cta-main:hover {
    transform: translateY(-2px);
    box-shadow: 0 16px 34px -10px rgba(15, 76, 58, 0.45);
}
.ld-cta-band .ld-cta-main:hover::after { left: 130%; }

/* ---- responsive ---- */
@media (max-width: 920px) {
    .ld-hero-grid { grid-template-columns: 1fr; gap: 48px; text-align: center; }
    .ld-hero-copy .ld-sub { margin-left: auto; margin-right: auto; }
    .ld-hero-copy .hero-ctas, .ld-fineprint { justify-content: center; }
    .ld-feat-grid { grid-template-columns: repeat(2, 1fr); }
    .ld-stats-grid { grid-template-columns: repeat(2, 1fr); }
    .ld-steps { grid-template-columns: repeat(2, 1fr); gap: 32px; }
}
@media (max-width: 600px) {
    .ld-feat-grid { grid-template-columns: 1fr; }
    .ld-steps { grid-template-columns: 1fr; }
    .ld-honest-card { padding: 26px 20px; }
    .ld-cta-card { padding: 42px 20px; }
}
@media (prefers-reduced-motion: reduce) {
    .ld-reveal { opacity: 1; transform: none; transition: none; }
    .ld-shot { transition: none; }
    .ld-wave i { animation: none; }
    .ld-ticker-track { animation: none; }
    .ld-cta-band .ld-cta-main { transition: none; }
    .ld-cta-band .ld-cta-main::after { display: none; }
    .ld-hero-aurora { animation: none; }
    .ld-word-shine { animation: none; }
    .ld-fl { animation: none; }
}

/* ---- Per-level Exam Pass pricing (payments) ---- */
.pass-active-banner {
    max-width: 1080px;
    margin: 0 auto 20px;
    padding: 12px 18px;
    border-radius: var(--border-radius-md, 10px);
    background: var(--success-bg, rgba(16,185,129,0.1));
    color: var(--success, #15803D);
    border: 1px solid rgba(16,185,129,0.25);
    font-weight: 600;
    font-size: 14px;
    text-align: center;
}
.pass-note {
    max-width: 1080px;
    margin: 0 auto 20px;
    padding: 12px 18px;
    border-radius: var(--border-radius-md, 10px);
    background: var(--warning-bg, rgba(180,83,9,0.08));
    color: var(--warning, #B4530A);
    border: 1px solid rgba(180,83,9,0.25);
    font-size: 14px;
    text-align: center;
}
/* Exam-date urgency. Deliberately neutral rather than alarming: the banner
   states a fact the learner gave us, and the per-card line answers "does this
   one still cover me". Nothing counts down, nothing flashes - the pressure is
   the real date, and dressing it up would be the dark pattern CLAUDE.md 6.6
   rules out. */
.pass-exam-banner {
    max-width: 1080px;
    margin: 0 auto 20px;
    padding: 12px 18px;
    border-radius: var(--border-radius-md, 10px);
    background: var(--bg-surface-elevated, rgba(47,91,234,0.06));
    color: var(--text-primary);
    border: 1px solid var(--border-color, rgba(47,91,234,0.2));
    font-size: 14px;
    text-align: center;
    line-height: 1.5;
}
.pass-exam-ask { text-align: left; display: flex; flex-wrap: wrap; gap: 10px 16px;
    align-items: center; justify-content: space-between; }
.pass-exam-ask label { flex: 1 1 260px; }
.pass-exam-ask-row { display: flex; gap: 8px; align-items: center; }
.pass-exam-ask input[type="date"] { width: auto; padding: 7px 10px; font-size: 14px; }

.price-fit {
    font-size: 12.5px;
    font-weight: 600;
    margin: 8px 0 2px;
    line-height: 1.35;
}
.price-fit-ok { color: var(--success, #15803D); }
.price-fit-short { color: var(--warning, #B4530A); }

.price-amt span { font-size: 14px; color: var(--text-secondary); font-weight: 500; }
.pass-compare {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    max-width: 1080px;
    margin: 36px auto 0;
}
.pass-col {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg, 14px);
    padding: 22px 24px;
}
.pass-col-premium { border-color: var(--accent-indigo, #2F5BEA); }
.pass-col h4 {
    margin: 0 0 14px;
    font-family: var(--font-heading);
    font-size: 15px;
    color: var(--text-primary);
}
.pass-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.pass-col li {
    position: relative;
    padding-left: 24px;
    font-size: 14px;
    color: var(--text-secondary);
    line-height: 1.5;
}
.pass-col li::before {
    content: '✓';
    position: absolute;
    left: 0;
    color: var(--success, #15803D);
    font-weight: 700;
}
.pass-col-premium li::before { color: var(--accent-indigo, #2F5BEA); }
@media (max-width: 720px) {
    .pass-compare { grid-template-columns: 1fr; }
}

/* ==========================================================================
   EXAM PAPER — printed booklet look for the mock-exam workspace
   --------------------------------------------------------------------------
   Founder request 2026-08-19: the exam should feel like the real printed
   Prüfungstraining book — paper, ink and serif type — not an app screen full
   of words. Scope: ONLY the exam-taking surfaces rendered by
   src/core/mock_exam_workspace.js + mock_exam_section_workspace.js (briefing,
   workspace, review). Practice pages keep the app look.

   Paper is deliberately theme-independent: a printed page is cream with dark
   ink in light AND dark mode (the dark navy chrome around it stays themed),
   so every colour here is hardcoded, not a var(--...) that flips at night.
   No external fonts (index.html rule) — EB Garamond is self-hosted from
   /fonts (see @font-face at the top of this file), so the paper serif now
   renders identically on every OS instead of drifting between Iowan (Mac),
   Book Antiqua (Windows) and DejaVu (Linux). System serifs stay as fallback.
   ========================================================================== */
:root {
    --font-paper: "EB Garamond", "Iowan Old Style", "Palatino Linotype", "Book Antiqua",
                  Palatino, Charter, Cambria, Georgia, "Times New Roman", serif;
    --paper-bg: #FBF7EE;            /* page cream */
    --paper-bg-deep: #F5EFE1;       /* aged edge / bands */
    --paper-white: #FFFDF8;         /* answer boxes, form fields */
    --paper-ink: #262219;           /* printing ink, never pure black */
    --paper-ink-soft: #4C463A;
    --paper-ink-muted: #8A8272;
    --paper-rule: #DCD4C1;          /* hairline rules */
    --paper-rule-strong: #B8AE97;
    --paper-accent: #0F4C3A;        /* brand forest ink — legible on cream in both themes */
    --paper-gold: #A9852F;          /* foil-stamp accent for covers/labels */
    --paper-shadow: 0 1px 1px rgba(74, 60, 30, 0.05),
                    0 10px 28px -10px rgba(74, 60, 30, 0.28);
}

/* Desk backdrop behind the sheets: warm blotter in light mode; in dark mode
   the existing dark vignette already reads as a desk at night, keep it. */
.exam-desk {
    background:
        radial-gradient(120% 90% at 50% 0%, #EFEAE0 0%, #E7E1D3 55%, #DFD8C7 100%);
}
body.dark-theme .exam-desk { background: transparent; }

/* ── The sheet ─────────────────────────────────────────────────────────── */
.exam-paper-sheet {
    position: relative;
    background-color: var(--paper-bg);
    /* faint grain + a soft light falloff so the page doesn't read as flat fill */
    background-image:
        radial-gradient(140% 70% at 30% -10%, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0) 60%),
        repeating-linear-gradient(0deg, rgba(120, 100, 60, 0.014) 0 2px, rgba(0, 0, 0, 0) 2px 5px);
    border: 1px solid #E4DCC9;
    border-radius: 3px;             /* paper is crisp, not an app card */
    box-shadow:
        var(--paper-shadow),
        3px 4px 0 -1px #F2ECDD,     /* the sheet beneath */
        3px 4px 0 0 #D9D0BA;
    padding: 30px 34px 34px;
    color: var(--paper-ink);
    font-family: var(--font-paper);
}
/* No sibling margin here: the section containers space sheets with flex/grid
   gap. An adjacent-sibling margin pushed the second sheet of the text/Aufgaben
   grid 20px lower than the first — the two "pages" no longer sat level. */
@media (max-width: 860px) {
    .exam-paper-sheet { padding: 20px 18px 24px; }
}

/* Inputs/textareas ON paper stay paper even when body.dark-theme repaints
   every input dark (that rule wins on plain inputs; these win here). */
body.dark-theme .exam-paper-sheet input,
body.dark-theme .exam-paper-sheet textarea {
    background-color: var(--paper-white);
    color: var(--paper-ink);
    border-color: var(--paper-rule-strong);
}

/* ── Page furniture ────────────────────────────────────────────────────── */
/* Teil head: kicker + title left, Aufgaben range right, double rule under —
   the classic exam-book section head. */
.paper-page-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    border-bottom: 2px solid var(--paper-ink);
    padding-bottom: 10px;
    position: relative;
    margin-bottom: 6px;
}
.paper-page-head::after {           /* second, thin rule = printed double rule */
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: -4px;
    border-bottom: 1px solid var(--paper-ink);
}
.paper-kicker {
    display: block;
    font-family: var(--font-paper);
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--paper-gold);
    margin-bottom: 4px;
}
.paper-teil-title {
    font-family: var(--font-paper);
    font-size: 23px;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--paper-ink);
    margin: 0;
}
.paper-range {
    font-family: var(--font-paper);
    font-size: 14px;
    font-style: italic;
    color: var(--paper-ink-muted);
    white-space: nowrap;
}

/* Arbeitsanweisung: italic serif on a light band, like the printed books. */
.paper-instruction {
    margin: 14px 0 0;
    padding: 11px 16px;
    background: var(--paper-bg-deep);
    border: 1px solid var(--paper-rule);
    border-left: 3px solid var(--paper-rule-strong);
    font-family: var(--font-paper);
    font-style: italic;
    font-size: 15.5px;
    line-height: 1.65;
    color: var(--paper-ink-soft);
}

/* Inner printed document (reading text, headline list, cloze letter). */
.paper-doc {
    border: 1px solid var(--paper-rule);
    background: var(--paper-white);
    padding: 18px 20px;
}
.paper-doc-label {
    display: flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-paper);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--paper-ink-muted);
    margin-bottom: 12px;
}
.paper-doc-label::after {
    content: '';
    flex: 1;
    border-top: 1px solid var(--paper-rule);
}
.paper-text {
    font-family: var(--font-paper);
    font-size: 17px;
    line-height: 1.8;
    color: var(--paper-ink);
    white-space: pre-wrap;
    /* Ragged-right on purpose: justified text in these narrow panes opened
       rivers of white between words, which reads as MORE noise, not less. */
    text-align: left;
}

/* ── Aufgaben ──────────────────────────────────────────────────────────── */
.paper-question { padding: 18px 0 6px; }
.paper-question + .paper-question { border-top: 1px solid var(--paper-rule); }
.paper-question-head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 12px;
}
.paper-question-no {
    flex: none;
    min-width: 28px;
    height: 28px;
    padding: 0 4px;
    border: 1.5px solid var(--paper-ink);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-paper);
    font-size: 15.5px;
    font-weight: 700;
    color: var(--paper-ink);
    background: var(--paper-white);
}
.paper-question-text {
    font-family: var(--font-paper);
    font-size: 17px;
    font-weight: 400;      /* reading weight — bold paragraphs read as a wall */
    line-height: 1.75;
    color: var(--paper-ink);
    margin: 0;
    padding-top: 2px;
    white-space: pre-wrap;
}

/* Options: answer-sheet rows — a letter box you mark. Deliberately a DIFFERENT
   voice than the question: smaller sans-serif in a softer ink, so the eye
   separates "text to read" (serif) from "choices to mark" (sans) at a glance.
   Class pairs with .option-btn so selectExamChoice()'s querySelectorAll and
   the shared .selected-chosen contract keep working unchanged. */
.paper-option {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    width: 100%;
    padding: 7px 10px;
    margin: 0 0 4px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    cursor: pointer;
    text-align: left;
    font-family: var(--font-body);
    font-size: 14.5px;
    line-height: 1.5;
    color: var(--paper-ink-soft);
    transition: background 0.15s ease, border-color 0.15s ease;
}
.paper-option:hover {
    background: rgba(15, 76, 58, 0.05);
    border-color: var(--paper-rule);
    color: var(--paper-ink);
}
.paper-option .opt-letter {
    flex: none;
    width: 22px;
    height: 22px;
    border: 1.5px solid var(--paper-rule-strong);
    border-radius: 2px;
    background: var(--paper-white);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--paper-ink-soft);
}
.paper-option .opt-text { flex: 1; min-width: 0; padding-top: 3px; }
/* Marked on the answer sheet: filled box, inked border. Deliberately NOT
   green-means-correct — same honesty rule as .option-btn.selected-chosen. */
.paper-option.selected-chosen {
    background: rgba(15, 76, 58, 0.07);
    border-color: var(--paper-accent);
    box-shadow: inset 0 0 0 1px var(--paper-accent);
    color: var(--paper-ink);
    font-weight: 600;
}
.paper-option.selected-chosen .opt-letter {
    background: var(--paper-accent);
    border-color: var(--paper-accent);
    color: #F3EFE6;
}

/* ── Hören: printed track strip ────────────────────────────────────────── */
.paper-audio {
    display: flex;
    align-items: center;
    gap: 14px;
    border: 1px solid var(--paper-rule);
    background: var(--paper-white);
    border-radius: 3px;
    padding: 12px 14px;
}
.paper-note {
    background: var(--paper-bg-deep);
    border: 1px solid var(--paper-rule);
    border-radius: 3px;
    padding: 10px 14px;
    font-family: var(--font-paper);
    font-style: italic;
    font-size: 14.5px;
    line-height: 1.6;
    color: var(--paper-ink-soft);
}
.paper-note strong { color: var(--paper-accent); font-style: normal; }

/* ── Schreiben: ruled writing paper ────────────────────────────────────── */
/* background-attachment: local ⇒ the ruled lines scroll WITH the text. */
.paper-writing-area,
textarea.paper-writing-area {
    background-color: var(--paper-white);
    background-image: repeating-linear-gradient(
        to bottom,
        transparent 0, transparent 29px,
        var(--paper-rule) 29px, var(--paper-rule) 30px);
    background-attachment: local;
    border: 1px solid var(--paper-rule-strong);
    border-radius: 3px;
    font-family: var(--font-paper);
    font-size: 17px;
    line-height: 30px;
    padding: 8px 16px 16px;
    color: var(--paper-ink);
    box-shadow: inset 0 1px 3px rgba(74, 60, 30, 0.06);
}
.paper-meta {
    font-family: var(--font-paper);
    font-style: italic;
    font-size: 14px;
    color: var(--paper-ink-muted);
}
.paper-meta strong { color: var(--paper-ink); font-style: normal; }

/* ── Workspace chrome around the sheets ────────────────────────────────── */
/* Module masthead above the tabs — serif, like a chapter opening. */
.exam-module-masthead {
    font-family: var(--font-paper);
    font-size: 24px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0;
    letter-spacing: 0.01em;
}
.exam-module-masthead .masthead-kicker {
    display: block;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent-indigo);
    margin-bottom: 2px;
}

/* Teil tabs as book register tabs: flat, serif, sitting on a baseline rule;
   the active one is "pulled forward" in paper. Extra class next to
   .reading-teil-tab so the practice pages' pill tabs stay untouched. */
.exam-book-tabs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    border-bottom: 2px solid var(--border-color);
    padding: 0 4px;
}
.exam-book-tab.reading-teil-tab {
    background: transparent;
    border: 1px solid transparent;
    border-bottom: none;
    border-radius: 6px 6px 0 0;
    margin-bottom: -2px;
    padding: 9px 16px 10px;
    font-family: var(--font-paper);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text-secondary);
}
.exam-book-tab.reading-teil-tab:hover { color: var(--text-primary); }
.exam-book-tab.reading-teil-tab.active {
    background: var(--paper-bg);
    border-color: var(--paper-rule-strong);
    border-bottom: 2px solid var(--paper-bg);
    color: var(--paper-ink);
    box-shadow: 0 -3px 10px -4px rgba(74, 60, 30, 0.25);
}
.exam-book-tab .tab-count {
    opacity: 0.65;
    font-size: 11px;
    margin-left: 5px;
    font-style: italic;
}

/* Left rail as the booklet's table of contents. */
.exam-mode-active .mocktest-step-link {
    font-family: var(--font-paper);
    font-size: 14px;
    gap: 12px;
}
.exam-mode-active .mocktest-step-link span:first-child {
    flex: none;
    width: 22px;
    height: 22px;
    border: 1px solid var(--border-color);
    border-radius: 2px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11.5px;
    font-weight: 700;
}
.exam-mode-active .mocktest-step-link.active {
    background: var(--accent-tint);
    color: var(--text-primary);
    font-weight: 700;
}
.exam-mode-active .mocktest-step-link.active span:first-child {
    background: var(--accent-indigo);
    border-color: var(--accent-indigo);
    color: var(--on-accent);
}
.exam-mode-active .mocktest-step-link.done { color: var(--success); }
.exam-mode-active .mocktest-step-link.done span:first-child {
    border-color: var(--success);
    color: var(--success);
}

/* ── Briefing: booklet cover page ──────────────────────────────────────── */
.exam-cover {
    max-width: 720px;
    margin: 0 auto;
}
.exam-cover-frame {                 /* the stamped double frame of a test book */
    border: 1px solid var(--paper-rule-strong);
    outline: 3px double var(--paper-rule-strong);
    outline-offset: 5px;
    margin: 6px;
    padding: 34px 36px 30px;
    text-align: center;
}
.exam-cover-inst {
    font-family: var(--font-paper);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--paper-gold);
}
.exam-cover-title {
    font-family: var(--font-paper);
    font-size: 30px;
    font-weight: 700;
    line-height: 1.25;
    color: var(--paper-ink);
    margin: 14px 0 10px;
}
.exam-cover-sub {
    font-family: var(--font-paper);
    font-style: italic;
    font-size: 14.5px;
    color: var(--paper-ink-soft);
}
.exam-cover-rule {
    width: 90px;
    border: none;
    border-top: 2px solid var(--paper-ink);
    margin: 18px auto;
}
.exam-cover-facts {
    display: flex;
    justify-content: center;
    gap: 26px;
    flex-wrap: wrap;
    font-family: var(--font-paper);
    font-size: 13.5px;
    color: var(--paper-ink-soft);
}
.exam-cover-facts strong { color: var(--paper-ink); }
.exam-cover-modules {
    margin-top: 8px;
    text-align: left;
}
.exam-cover-module-row {
    display: grid;
    grid-template-columns: 150px 1fr;
    gap: 14px;
    padding: 12px 2px;
    border-bottom: 1px solid var(--paper-rule);
    font-family: var(--font-paper);
    font-size: 13.5px;
}
.exam-cover-module-row:last-child { border-bottom: none; }
.exam-cover-module-row .mod-name { font-weight: 700; color: var(--paper-ink); }
.exam-cover-module-row .mod-teile { color: var(--paper-ink-soft); line-height: 1.7; }
@media (max-width: 640px) {
    .exam-cover-frame { padding: 22px 16px; }
    .exam-cover-module-row { grid-template-columns: 1fr; gap: 4px; }
}

/* Options hang under the question text, aligned with it past the number box;
   at phone width the indent goes — every pixel of line length matters there. */
.paper-question-options { padding-left: 40px; }
@media (max-width: 640px) { .paper-question-options { padding-left: 0; } }

/* ── Designer polish pass (founder: "fix everything", 2026-08-19) ─────────── */

/* Exam chrome: the flat navy bar becomes a subtle vertical gradient with a
   gold hairline — institutional, like the edge of a certificate. The JS no
   longer sets background/border inline, so these rules own the look. */
.exam-header {
    background: linear-gradient(180deg, #21395B 0%, #162A4B 100%);
    color: #F5F1E8;
    border-bottom: 1px solid rgba(201, 169, 97, 0.70);
    box-shadow: 0 2px 14px rgba(8, 14, 26, 0.30);
}
.exam-header-kicker { color: #C9A961; }

/* Footer navigation: one quiet rule over the desk, back is a ghost, forward
   is THE action. (Primary styling comes from .btn-primary itself.) */
.exam-footer-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
    border-top: 1px solid var(--border-color);
    padding-top: 18px;
    margin-top: 24px;
}

/* Headline bank (telc Lesen Teil 1 a–j, ads lists): printed rows with letter
   boxes and hairline separators instead of raw text lines. */
.paper-headline-list { display: flex; flex-direction: column; }
.paper-headline-head {
    font-family: var(--font-paper);
    font-size: 17px;
    font-weight: 700;
    color: var(--paper-ink);
    padding-bottom: 8px;
}
.paper-headline-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 9px 2px;
    border-bottom: 1px solid var(--paper-rule);
    font-family: var(--font-paper);
    font-size: 16px;
    line-height: 1.6;
    color: var(--paper-ink);
}
.paper-headline-item:last-child { border-bottom: none; }
.paper-headline-letter {
    flex: none;
    width: 22px;
    height: 22px;
    margin-top: 1px;
    border: 1.5px solid var(--paper-rule-strong);
    border-radius: 2px;
    background: var(--paper-white);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--paper-ink-soft);
}

/* Theme buttons that land ON a paper sheet (Sprechen card selector, deck
   navigation) keep the paper's fixed palette in BOTH themes — dark mode's
   gold/navy pills looked pasted onto the cream page. Scoped with the
   body.dark-theme variants so they outrank the global dark overrides. */
.exam-paper-sheet .btn-secondary,
body.dark-theme .exam-paper-sheet .btn-secondary {
    background: var(--paper-white);
    border: 1px solid var(--paper-rule-strong);
    color: var(--paper-ink-soft);
    box-shadow: none;
}
.exam-paper-sheet .btn-secondary:hover,
body.dark-theme .exam-paper-sheet .btn-secondary:hover {
    background: var(--paper-bg-deep);
    color: var(--paper-ink);
    border-color: var(--paper-rule-strong);
}
.exam-paper-sheet .btn-primary,
body.dark-theme .exam-paper-sheet .btn-primary {
    background: #0F4C3A;
    color: #F3EFE6;
    box-shadow: none;
}
.exam-paper-sheet .btn-primary:hover,
body.dark-theme .exam-paper-sheet .btn-primary:hover {
    background: #0B3A2C;
}

/* ── Hub & report on paper (same premium system as the exam itself) ──────── */

/* Hub masthead — chapter-opening serif over the app background. */
.exam-hub-masthead .masthead-kicker {
    display: block;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent-indigo);
    margin-bottom: 3px;
}
.exam-hub-masthead h2 {
    font-family: var(--font-paper);
    font-size: 26px;
    font-weight: 700;
    margin: 0;
    color: var(--text-primary);
}
.exam-hub-masthead p {
    font-family: var(--font-paper);
    font-style: italic;
    font-size: 13.5px;
    color: var(--text-secondary);
    margin: 4px 0 0;
}

/* One exam on the shelf: a small booklet cover. */
.exam-shelf-card {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 20px;
    margin-bottom: 18px;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.exam-shelf-card:hover {
    transform: translateY(-2px);
    box-shadow:
        0 2px 3px rgba(74, 60, 30, 0.07),
        0 16px 34px -12px rgba(74, 60, 30, 0.34),
        3px 4px 0 -1px #F2ECDD,
        3px 4px 0 0 #D9D0BA;
}
.exam-shelf-kicker {
    font-family: var(--font-paper);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--paper-gold);
    margin-bottom: 5px;
}
.exam-shelf-title {
    font-family: var(--font-paper);
    font-size: 17px;
    font-weight: 700;
    color: var(--paper-ink);
    margin: 0 0 5px;
    line-height: 1.35;
}
.exam-shelf-meta {
    font-family: var(--font-paper);
    font-style: italic;
    font-size: 12.5px;
    color: var(--paper-ink-muted);
}
.exam-shelf-lock {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-paper);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--paper-ink-soft);
    border: 1px solid var(--paper-rule-strong);
    background: var(--paper-bg-deep);
    border-radius: 2px;
    padding: 2px 8px;
    margin-left: 8px;
    vertical-align: 2px;
}

/* Printed exam log (previous attempts). */
.exam-log-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 11px 2px;
    border-bottom: 1px solid var(--paper-rule);
    cursor: pointer;
}
.exam-log-row:last-child { border-bottom: none; }
.exam-log-row:hover { background: rgba(15, 76, 58, 0.04); }
.exam-log-title {
    font-family: var(--font-paper);
    font-size: 13.5px;
    font-weight: 700;
    color: var(--paper-ink);
    line-height: 1.4;
}
.exam-log-scores {
    font-family: var(--font-paper);
    font-style: italic;
    font-size: 11.5px;
    color: var(--paper-ink-muted);
    margin-top: 2px;
}
.exam-log-verdict {
    flex: none;
    font-family: var(--font-paper);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border-radius: 2px;
    padding: 3px 8px;
    border: 1px solid;
}
.exam-log-verdict.pass { color: #0F4C3A; border-color: rgba(15, 76, 58, 0.5); background: rgba(15, 76, 58, 0.07); }
.exam-log-verdict.fail { color: #A83A28; border-color: rgba(168, 58, 40, 0.5); background: rgba(168, 58, 40, 0.07); }

/* Rubber stamp on the report — inked, slightly rotated, like a real Amt. */
.paper-stamp {
    display: inline-block;
    transform: rotate(-7deg);
    border: 3px double currentColor;
    border-radius: 4px;
    padding: 8px 16px;
    font-family: var(--font-paper);
    font-size: 15.5px;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    opacity: 0.9;
    -webkit-mask-image: radial-gradient(140% 120% at 40% 30%, #000 55%, rgba(0,0,0,0.72) 100%);
            mask-image: radial-gradient(140% 120% at 40% 30%, #000 55%, rgba(0,0,0,0.72) 100%);
}
.paper-stamp.pass { color: #0F4C3A; }
.paper-stamp.fail { color: #A83A28; }

/* Report: printed module-score table. */
.paper-result-row {
    display: grid;
    grid-template-columns: 130px 1fr 84px 96px;
    gap: 14px;
    align-items: center;
    padding: 11px 2px;
    border-bottom: 1px solid var(--paper-rule);
}
.paper-result-row:last-child { border-bottom: none; }
.paper-result-name {
    font-family: var(--font-paper);
    font-weight: 700;
    font-size: 15.5px;
    color: var(--paper-ink);
}
.paper-result-bar {
    position: relative;
    height: 7px;
    background: var(--paper-bg-deep);
    border: 1px solid var(--paper-rule);
    border-radius: 4px;
    overflow: hidden;
}
.paper-result-bar > div { height: 100%; border-radius: 4px; }
.paper-result-score {
    font-family: var(--font-paper);
    font-size: 14.5px;
    font-weight: 700;
    text-align: right;
    color: var(--paper-ink);
    white-space: nowrap;
}
.paper-result-verdict {
    font-family: var(--font-paper);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: right;
    white-space: nowrap;
}
@media (max-width: 640px) {
    .paper-result-row { grid-template-columns: 1fr 84px; }
    .paper-result-bar { display: none; }
    .paper-result-verdict { grid-column: 1 / -1; text-align: left; }
}

/* Recommendation chips on paper keep the paper voice in both themes. */
.exam-paper-sheet .recommendation-chip,
body.dark-theme .exam-paper-sheet .recommendation-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--paper-white);
    border: 1px solid var(--paper-rule-strong);
    border-radius: 3px;
    color: #0F4C3A;
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 600;
    padding: 7px 12px;
    cursor: pointer;
    transition: background 0.15s ease;
}
.exam-paper-sheet .recommendation-chip:hover,
body.dark-theme .exam-paper-sheet .recommendation-chip:hover {
    background: rgba(15, 76, 58, 0.07);
}
.exam-paper-sheet .recommendation-chip svg { width: 13px; height: 13px; }

/* Printed correction card (writing feedback). */
.paper-correction {
    padding: 9px 12px;
    border-left: 2px solid #A83A28;
    background: var(--paper-white);
    border-radius: 2px;
    font-family: var(--font-paper);
    font-size: 14px;
    line-height: 1.6;
}
.paper-correction .corr-orig { color: #A83A28; text-decoration: line-through; }
.paper-correction .corr-fix { color: #0F4C3A; font-weight: 700; }
.paper-correction .corr-why { font-size: 11.5px; font-style: italic; color: var(--paper-ink-muted); }

/* Report head reserves stamp space inline (padding-right) on desktop; on the
   phone the stamp is already in normal flow (rule above), so release it. */
@media (max-width: 860px) {
    .exam-report-card .paper-page-head { padding-right: 0 !important; }
}

/* ── §18 bridge: authentic exam material inside app-world practice ────────── */
/* The ONE small paper card a practice/diagnostic screen may carry — reading
   text, Hörtranskript, exam task, model letter. A compact cousin of
   .exam-paper-sheet: same fixed paper palette (never theme vars), lighter
   shadow, no page stack. The frame around it (question UI, buttons, feedback)
   stays app-world; more than one paper element per screen is over the line
   (UI_UX_GUIDELINES.md §18).
   .reading-passage-box (diagnostic Lesen/Hören/Schreiben/Sprechen material)
   was never styled at all — it IS this component. */
.paper-bridge,
.reading-passage-box {
    background-color: var(--paper-bg);
    background-image:
        radial-gradient(120% 60% at 30% -10%, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 60%),
        repeating-linear-gradient(0deg, rgba(120, 100, 60, 0.013) 0 2px, rgba(0, 0, 0, 0) 2px 5px);
    border: 1px solid #E4DCC9;
    border-radius: 2px;
    box-shadow:
        0 1px 2px rgba(74, 60, 30, 0.07),
        2px 3px 0 -1px #F2ECDD,
        2px 3px 0 0 #D9D0BA;
    padding: 16px 20px;
    font-family: var(--font-paper);
    font-size: 17px;
    line-height: 1.75;
    color: var(--paper-ink);
}
.reading-passage-box { white-space: pre-wrap; margin: 8px 0 4px; }
.paper-bridge strong,
.reading-passage-box strong { color: var(--paper-ink); }

/* ---------------------------------------------------------------------------
   Free Einstufungstest (placement.js) — the public, no-signup level check.

   UI_UX_GUIDELINES §19: intro and result are marketing and may persuade; the
   paper between them is work, so it borrows the exam surface's calm — warm
   paper ground, serif resource text, nothing that moves while you read.
   --------------------------------------------------------------------------- */
.pl-wrap {
    max-width: 720px;
    margin: 0 auto;
    padding: 48px 20px 72px;
}
.pl-card {
    /* --card-bg is defined nowhere, so this always fell through to the
       hardcoded #fff: right by accident in light mode, a white card carrying
       cream dark-mode text on the Einstufungstest page. --bg-card is the real
       token and is #FFFFFF in light mode, so light rendering is unchanged. */
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg, 16px);
    padding: 32px;
    margin-bottom: 20px;
}
.pl-eyebrow {
    display: inline-block;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent-indigo);
    margin-bottom: 14px;
}
.pl-title {
    font-family: var(--font-heading);
    font-size: clamp(26px, 4vw, 36px);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--text-primary);
    margin-bottom: 14px;
}
.pl-h3 {
    font-family: var(--font-heading);
    font-size: 18px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 16px;
}
.pl-lead { font-size: 16.5px; line-height: 1.6; color: var(--text-secondary); }
.pl-facts { margin: 20px 0; padding: 0; list-style: none; }
.pl-facts li {
    position: relative;
    padding-left: 24px;
    margin-bottom: 9px;
    font-size: 15px;
    color: var(--text-secondary);
}
.pl-facts li::before {
    content: "";
    position: absolute;
    left: 4px; top: 8px;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--accent-indigo);
}
/* Said quietly on purpose: overclaiming what 18 questions can tell you is the
   one thing that would make this test worth less than nothing. */
.pl-honest {
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--text-muted);
    margin-top: 16px;
}
.pl-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; align-items: center; }
.pl-actions-center { justify-content: center; }
.pl-actions .btn-secondary { text-decoration: none; }

/* Optional "email me this result" capture on the placement result screen
   (placement.js renderPlacementEmailCapture). Reuses .form-input's own look;
   this only adds the row layout. */
.pl-email-row { display: flex; flex-wrap: wrap; gap: 10px; }
.pl-email-row .pl-email-input { flex: 1 1 220px; }
.pl-email-row .btn-secondary { white-space: nowrap; }
.pl-email-error { font-size: 13px; color: var(--danger, #DC2626); margin-top: 10px; }

.pl-progress-head {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 8px;
}
.pl-progress {
    height: 5px;
    border-radius: 3px;
    background: var(--border-color);
    overflow: hidden;
    margin-bottom: 24px;
}
.pl-progress-bar {
    height: 100%;
    background: var(--accent-indigo);
    transition: width 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* The paper. Same warm ground and serif resource text as the exam surface, so
   the practice a visitor meets here looks like the thing they are training for. */
.pl-paper {
    background: var(--paper-bg, #F7F4ED);
    border: 1px solid var(--paper-border, #E2DACA);
    border-radius: var(--border-radius-lg, 16px);
    padding: 30px;
}
.pl-paper-meta {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 14px;
}
.pl-resource {
    font-family: var(--font-paper);
    font-size: 17px;
    line-height: 1.7;
    white-space: pre-wrap;
    color: var(--paper-ink, #23201A);
    padding: 16px 18px;
    background: rgba(255, 255, 255, 0.6);
    border-left: 3px solid var(--accent-indigo);
    border-radius: 6px;
    margin-bottom: 20px;
}
.pl-prompt {
    font-family: var(--font-heading);
    font-size: 19px;
    font-weight: 700;
    line-height: 1.45;
    color: var(--paper-ink, #23201A);
    margin-bottom: 20px;
}
.pl-options { display: flex; flex-direction: column; gap: 10px; }
.pl-option {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    text-align: left;
    padding: 14px 16px;
    font-size: 16px;
    font-family: inherit;
    color: var(--paper-ink, #23201A);
    background: #fff;
    border: 1.5px solid var(--paper-border, #E2DACA);
    border-radius: 10px;
    cursor: pointer;
    transition: border-color 140ms ease, background 140ms ease;
}
.pl-option:hover { border-color: var(--accent-indigo); }
.pl-option:focus-visible { outline: 2px solid var(--accent-indigo); outline-offset: 2px; }
.pl-option-on { border-color: var(--accent-indigo); background: rgba(15, 76, 58, 0.06); }
.pl-option-key {
    flex-shrink: 0;
    width: 26px; height: 26px;
    display: grid;
    place-items: center;
    border-radius: 6px;
    background: var(--paper-border, #E2DACA);
    font-size: 12.5px;
    font-weight: 700;
    color: var(--paper-ink, #23201A);
}
.pl-option-on .pl-option-key { background: var(--accent-indigo); color: #fff; }

.pl-nav { display: flex; gap: 10px; margin-top: 22px; flex-wrap: wrap; }
.pl-nav .btn-primary { margin-left: auto; }

.pl-result-hero { text-align: center; padding: 12px 0 34px; }
.pl-result-hero .pl-lead, .pl-result-hero .pl-honest { max-width: 520px; margin-left: auto; margin-right: auto; }
.pl-level {
    font-family: var(--font-heading);
    font-size: clamp(64px, 13vw, 104px);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.04em;
    color: var(--accent-indigo);
    margin: 4px 0 16px;
}
.pl-bars { display: flex; flex-direction: column; gap: 12px; }
.pl-bar-row { display: flex; align-items: center; gap: 14px; }
.pl-bar-label { width: 30px; font-weight: 700; font-size: 14px; color: var(--text-secondary); }
.pl-bar { flex: 1; height: 10px; border-radius: 5px; background: var(--border-color); overflow: hidden; }
.pl-bar-fill { height: 100%; background: var(--accent-indigo); border-radius: 5px; }
.pl-bar-num { width: 44px; text-align: right; font-size: 13.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.pl-weak { margin-top: 20px; font-size: 15px; line-height: 1.55; color: var(--text-secondary); }

.pl-cta {
    background: var(--accent-gradient, linear-gradient(135deg, #0F4C3A 0%, #0B3A2C 100%));
    color: #F3EFE6;
    border-radius: var(--border-radius-lg, 16px);
    padding: 32px;
    margin-bottom: 20px;
}
.pl-cta .pl-h3 { color: #fff; }
.pl-cta p { font-size: 15.5px; line-height: 1.6; color: rgba(243, 239, 230, 0.86); }
.pl-cta .btn-secondary { background: rgba(255, 255, 255, 0.12); color: #F3EFE6; border-color: rgba(255, 255, 255, 0.3); }

.pl-review { list-style: none; padding: 0; margin: 0; }
.pl-review li { padding: 16px 0; border-top: 1px solid var(--border-color); }
.pl-review li:first-child { border-top: none; }
.pl-review-q { font-size: 15.5px; line-height: 1.5; color: var(--text-primary); margin-bottom: 4px; }
.pl-review-meta { font-size: 12px; color: var(--text-muted); margin-bottom: 8px; }
.pl-review-a { display: flex; flex-wrap: wrap; gap: 8px 18px; font-size: 14px; }
.pl-wrong { color: var(--error, #B4231A); }
.pl-right { color: var(--success, #0F4C3A); font-weight: 600; }

@media (max-width: 640px) {
    .pl-wrap { padding: 28px 16px 56px; }
    .pl-card, .pl-paper, .pl-cta { padding: 22px; }
    .pl-nav .btn-primary { margin-left: 0; width: 100%; }
    .pl-nav .btn-secondary { flex: 1; }
}
.pl-noun {
    font-family: var(--font-paper);
    font-size: 22px;
    font-weight: 600;
    text-align: center;
    color: var(--paper-ink, #23201A);
    margin: -6px 0 18px;
}

/* ==========================================================================
   Policy pages (/agb, /datenschutz, /erstattung, /lieferung, /kontakt)
   Rendered by legal.js. Deliberately plain and high-contrast: these are read
   by customers looking for a refund rule and by payment-risk reviewers, and
   both need to find a specific clause fast, not admire a layout.
   ========================================================================== */
.lg-page { max-width: 780px; margin: 40px auto 80px; padding: 0 20px; }

.lg-nav { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 32px; }
.lg-nav a {
    font-size: 13px; font-weight: 600; text-decoration: none;
    padding: 7px 14px; border-radius: 999px;
    color: var(--text-secondary); border: 1px solid var(--border-color);
    background: var(--bg-surface);
}
.lg-nav a:hover { color: var(--text-primary); border-color: var(--text-secondary); }
.lg-nav a.is-current {
    color: #fff; background: var(--accent-indigo, #4F46E5);
    border-color: var(--accent-indigo, #4F46E5);
}

.lg-doc { color: var(--text-primary); line-height: 1.75; font-size: 15px; }
.lg-doc h1 { font-size: 30px; font-weight: 800; margin: 0 0 6px; letter-spacing: -0.01em; }
.lg-doc h3 { font-size: 17px; font-weight: 700; margin: 34px 0 10px; }
.lg-doc p { margin: 0 0 14px; }
.lg-doc ul { margin: 0 0 16px; padding-left: 22px; }
.lg-doc li { margin-bottom: 8px; }
.lg-doc a { color: var(--accent-indigo, #4F46E5); }
.lg-doc strong { font-weight: 700; }
.lg-updated { font-size: 13px; color: var(--text-secondary); margin-bottom: 28px !important; }

.lg-table { width: 100%; border-collapse: collapse; margin: 8px 0 20px; }
.lg-table th, .lg-table td {
    text-align: left; padding: 11px 12px; font-size: 14px;
    border-bottom: 1px solid var(--border-color); vertical-align: top;
}
.lg-table th { width: 40%; font-weight: 600; color: var(--text-secondary); }

.ld-foot-legal { margin-top: 10px; opacity: 0.85; }

@media (max-width: 600px) {
    .lg-doc h1 { font-size: 24px; }
    .lg-table th { width: 100%; display: block; border-bottom: none; padding-bottom: 0; }
    .lg-table td { width: 100%; display: block; padding-top: 2px; }
}

/* Campaign offer on the pricing screen. The card must show what the offer link
   promised, or the reader who was sent "₹299" reads "₹499" and leaves. */
.pass-offer-banner {
    max-width: 1080px;
    margin: 0 auto 20px;
    padding: 12px 18px;
    border-radius: var(--border-radius-md, 10px);
    background: var(--warning-bg, rgba(180,83,9,0.08));
    color: var(--warning, #9A3412);
    border: 1px solid rgba(180,83,9,0.25);
    font-weight: 600;
    font-size: 14px;
    text-align: center;
}
.pricing-card.on-offer {
    border-color: rgba(180,83,9,0.45);
}
.price-offer-tag {
    display: inline-block;
    margin-bottom: 8px;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--warning-bg, rgba(180,83,9,0.1));
    color: var(--warning, #9A3412);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .02em;
}
.price-was {
    margin-right: 10px;
    font-size: .62em;
    font-weight: 500;
    text-decoration: line-through;
    opacity: .55;
}

/* ==========================================================================
   SZENARIO-ROLLENSPIEL (Gespräch)
   Built on the existing design tokens and on .voice-visualizer / .mic-btn-large,
   which the speaking exam already defines above - the conversation reuses that
   microphone rather than introducing a second one.
   ========================================================================== */

.roleplay-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 18px;
}

.roleplay-card {
    display: flex;
    flex-direction: column;
    padding: 22px;
    gap: 8px;
}

.roleplay-card-icon { font-size: 30px; line-height: 1; }

.roleplay-card-title {
    font-family: var(--font-heading);
    font-size: 17px;
    font-weight: 800;
    color: var(--text-primary);
    margin: 2px 0 0 0;
}

.roleplay-card-situation,
.roleplay-card-goal {
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-secondary);
    margin: 0;
}

.roleplay-card-goal strong { color: var(--text-primary); }

.roleplay-card-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: auto;
    padding-top: 14px;
}

.roleplay-card-turns { font-size: 11.5px; color: var(--text-muted); font-weight: 600; }

.roleplay-free-card { padding: 24px 28px; }

.roleplay-free-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
}

.roleplay-topic-input {
    flex: 1 1 240px;
    min-width: 0;
    padding: 11px 14px;
    font-size: 13.5px;
    font-family: inherit;
    color: var(--text-primary);
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
}

/* --- the conversation itself --- */

.roleplay-stage {
    max-width: 860px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.roleplay-header {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 20px 24px;
}

.roleplay-avatar-wrap { position: relative; width: 58px; height: 58px; flex: 0 0 58px; }

.roleplay-avatar {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26px;
    border-radius: 50%;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
}

.roleplay-avatar-ring {
    position: absolute;
    inset: -5px;
    border-radius: 50%;
    border: 2px solid transparent;
    transition: border-color .25s ease, box-shadow .25s ease;
}

.roleplay-avatar-ring.speaking {
    border-color: var(--accent-indigo);
    box-shadow: 0 0 18px rgba(79, 70, 229, .35);
}

.roleplay-avatar-ring.listening {
    border-color: #10b981;
    box-shadow: 0 0 18px rgba(16, 185, 129, .32);
}

.roleplay-header-text { flex: 1; min-width: 0; }

.roleplay-header-text h2 {
    font-family: var(--font-heading);
    font-size: 19px;
    font-weight: 800;
    margin: 0 0 4px 0;
    color: var(--text-primary);
}

.roleplay-goal { margin: 0; font-size: 12.5px; color: var(--text-secondary); line-height: 1.5; }
.roleplay-goal strong { color: var(--text-primary); }
.roleplay-avatar-state { margin: 4px 0 0 0; font-size: 12px; color: var(--accent-indigo); font-weight: 600; min-height: 16px; }
.roleplay-exit { flex: 0 0 auto; }

.roleplay-progress { display: flex; align-items: center; gap: 12px; padding: 0 4px; }

.roleplay-progress-bar {
    flex: 1;
    height: 6px;
    border-radius: 3px;
    background: var(--bg-surface-elevated);
    overflow: hidden;
}

.roleplay-progress-bar span {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, var(--accent-indigo), #8b5cf6);
    transition: width .35s ease;
}

.roleplay-progress-label { font-size: 11.5px; font-weight: 700; color: var(--text-muted); white-space: nowrap; }

.roleplay-thread {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 20px;
    max-height: 46vh;
    overflow-y: auto;
}

.roleplay-thread-static { max-height: none; box-shadow: none; border: 0; padding: 16px 0 0 0; }

.roleplay-bubble {
    max-width: 78%;
    padding: 11px 15px;
    border-radius: 14px;
    font-size: 14px;
    line-height: 1.6;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.roleplay-bubble.from-ai {
    align-self: flex-start;
    background: var(--bg-surface-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    border-bottom-left-radius: 4px;
}

.roleplay-bubble.from-student {
    align-self: flex-end;
    background: var(--accent-indigo);
    color: #fff;
    border-bottom-right-radius: 4px;
}

.roleplay-thinking { opacity: .55; letter-spacing: 3px; }

.roleplay-input-card { padding: 18px 20px; display: flex; flex-direction: column; gap: 12px; }

.roleplay-mic-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.roleplay-mic-row .voice-visualizer { width: 62px; height: 62px; flex: 0 0 62px; }
.roleplay-mic-row .mic-btn-large { width: 40px; height: 40px; }
.roleplay-mic-side { flex: 1; min-width: 160px; }
.roleplay-mic-status { font-size: 12.5px; color: var(--text-secondary); font-weight: 600; }
.roleplay-mic-notice { margin: 6px 0 0 0; font-size: 11.5px; color: var(--text-muted); line-height: 1.5; }
.roleplay-repeat { flex: 0 0 auto; }

.roleplay-draft {
    width: 100%;
    padding: 12px 14px;
    font-family: inherit;
    font-size: 14px;
    line-height: 1.6;
    resize: vertical;
    color: var(--text-primary);
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
}

.roleplay-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.roleplay-error {
    padding: 12px 16px;
    border-radius: var(--border-radius-sm);
    border: 1px solid rgba(239, 68, 68, .35);
    background: rgba(239, 68, 68, .08);
    color: var(--text-primary);
    font-size: 13px;
    line-height: 1.6;
    margin-bottom: 12px;
}

/* --- the report --- */

.roleplay-report-head { padding: 26px 28px; }
.roleplay-report-head h2 { font-family: var(--font-heading); font-size: 22px; font-weight: 800; margin: 0 0 4px 0; color: var(--text-primary); }
.roleplay-report-sub { margin: 0 0 18px 0; font-size: 13px; color: var(--text-secondary); }

.roleplay-verdicts { display: flex; flex-wrap: wrap; gap: 12px; }

.roleplay-verdict {
    flex: 1 1 150px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px 14px;
    border-radius: var(--border-radius-sm);
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
}

.roleplay-verdict-label { font-size: 11px; text-transform: uppercase; letter-spacing: .6px; color: var(--text-muted); font-weight: 700; }
.roleplay-verdict-value { font-size: 17px; font-weight: 800; color: var(--text-primary); }
.roleplay-verdict-note { margin: 14px 0 0 0; font-size: 13px; line-height: 1.65; color: var(--text-secondary); }

.roleplay-report-block { padding: 22px 26px; }
.roleplay-report-block h3 { font-family: var(--font-heading); font-size: 16px; font-weight: 800; margin: 0 0 14px 0; color: var(--text-primary); }
.roleplay-report-block summary { font-family: var(--font-heading); font-size: 15px; font-weight: 800; cursor: pointer; color: var(--text-primary); }

.roleplay-list { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.roleplay-list li { font-size: 13.5px; line-height: 1.65; color: var(--text-secondary); }
.roleplay-list li strong { color: var(--text-primary); }

.roleplay-mistake { display: flex; gap: 14px; padding: 12px 0; border-top: 1px solid var(--border-color); }
.roleplay-mistake:first-of-type { border-top: 0; padding-top: 0; }

.roleplay-mistake-rank {
    flex: 0 0 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--accent-indigo);
    color: #fff;
    font-size: 12px;
    font-weight: 800;
    display: flex;
    align-items: center;
    justify-content: center;
}

.roleplay-said { margin: 0 0 4px 0; font-size: 13.5px; color: var(--text-secondary); text-decoration: line-through; text-decoration-color: rgba(239, 68, 68, .6); }
.roleplay-correction { margin: 0 0 4px 0; font-size: 14px; font-weight: 700; color: var(--text-primary); }
.roleplay-why { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--text-secondary); }
.roleplay-empty { margin: 0; font-size: 13.5px; color: var(--text-secondary); }

@media (max-width: 640px) {
    .roleplay-header { flex-wrap: wrap; }
    .roleplay-exit { width: 100%; }
    .roleplay-bubble { max-width: 88%; }
    .roleplay-card-foot { flex-direction: column; align-items: stretch; }
}

/* ==========================================================================
   SHAREABLE RESULT CARD (result_card.js)
   The two controls under a result, and the preview of the image they produce.
   Used on two very different surfaces, so the styling here is only the parts
   that are the same on both: the free Einstufungstest result keeps its
   marketing card around them (§19), the Modelltest report keeps its paper.
   ========================================================================== */
.pm-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    justify-content: center;
    margin-top: 16px;
}
.pl-card .pm-card-actions { justify-content: flex-start; margin-top: 20px; }

.pm-card-btn { min-width: 150px; }

/* Empty until a button is pressed — the image is drawn on demand, not for
   every learner who merely reads their score. */
.pm-card-preview:empty { display: none; }
.pm-card-preview {
    margin-top: 18px;
    display: flex;
    justify-content: center;
}
.pm-card-image {
    display: block;
    width: 320px;
    max-width: 100%;
    height: auto;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    box-shadow: 0 2px 4px rgba(16, 24, 40, 0.05), 0 8px 20px rgba(16, 24, 40, 0.10);
}

@media (max-width: 640px) {
    .pm-card-btn { flex: 1 1 100%; min-width: 0; }
}

/* ==========================================================================
   MILESTONE SHARE DIALOG (src/core/milestone_card.js) and TESTIMONIAL PROMPT
   (src/core/testimonial_prompt.js). App world: calm, no motion of their own
   (UI_UX_GUIDELINES.md 19). The share image itself carries its own fixed
   palette; only the dialog around it follows the theme.
   ========================================================================== */
.ms-open { margin-top: 8px; padding: 6px 12px; font-size: 12.5px; }

.ms-card { max-width: 440px; text-align: center; }
.ms-kicker, .tm-kicker { margin: 0 0 4px; font-size: 13px; color: var(--text-secondary); }
.ms-title { margin: 0 0 16px; font-size: 20px; }
.ms-preview { display: flex; justify-content: center; min-height: 120px; align-items: center; }
.ms-image { width: 240px; }
.ms-status { margin: 0; font-size: 14px; color: var(--text-secondary); }
.ms-status--error { color: var(--error); }
.ms-actions { margin-top: 16px; }
.ms-actions .pm-card-btn { justify-content: center; }
.ms-close, .tm-close { width: 100%; justify-content: center; margin-top: 10px; }

.tm-card { max-width: 520px; }
.tm-question { display: block; margin: 0 0 6px; font-size: 20px; font-weight: 600; line-height: 1.3;
    color: var(--text-primary); font-family: var(--font-heading); }
.tm-lead { margin: 0 0 12px; font-size: 14px; color: var(--text-secondary); }
.tm-body { resize: vertical; min-height: 104px; line-height: 1.5; }
.tm-count, .tm-hint { margin: 6px 0 14px; font-size: 12.5px; color: var(--text-muted); }
.tm-count { text-align: right; font-variant-numeric: tabular-nums; }
.tm-label { display: block; margin: 0 0 6px; font-size: 14px; font-weight: 600; color: var(--text-primary); }
.tm-consent { display: flex; gap: 10px; align-items: flex-start; margin: 0 0 14px; font-size: 13.5px;
    line-height: 1.45; color: var(--text-secondary); cursor: pointer; }
.tm-consent input { margin-top: 3px; width: 18px; height: 18px; flex-shrink: 0; }
.tm-error { margin: 0 0 12px; font-size: 13.5px; color: var(--error); }
.tm-submit { width: 100%; justify-content: center; }
.tm-submit:disabled { opacity: 0.6; cursor: not-allowed; }

@media (max-width: 640px) {
    .ms-image { width: 200px; }
    .ms-card, .tm-card { padding: 22px 18px; }
}

/* The testimonial text column on /admin-testimonials: the learner's own line
   breaks, a readable measure, never one endless line. Qualified with
   .au-table td because that rule keeps every other cell on one line. */
.au-table td.at-text { white-space: pre-wrap; overflow-wrap: anywhere; min-width: 280px; width: 420px; }
.at-link { color: var(--accent-indigo); font-weight: 600; }


/* ==========================================================================
   READINESS HEADLINE (dashboard.js)
   The one number at the top of the dashboard: the learner's most recent mock
   exam score, the verdict that came with it, and what would raise it most.
   Quiet on purpose - this sits in the product world (UI_UX_GUIDELINES §19),
   above a learner's daily plan, and its job is to orient, not to shout.
   ========================================================================== */
.rh-card {
    /* Same width and centring as .tp-card below it: the headline and the daily
       plan read as one column, not two cards that happen to be stacked. */
    max-width: 620px;
    margin: 0 auto 20px;
    padding: 22px 26px;
    border-radius: var(--border-radius-lg);
    border: 1px solid var(--border-color);
}
.rh-card[role="button"] { cursor: pointer; }
.rh-card[role="button"]:hover { border-color: var(--accent-indigo); }
.rh-card[role="button"]:focus-visible {
    outline: 2px solid var(--accent-indigo);
    outline-offset: 2px;
}

.rh-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
.rh-eyebrow {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted, var(--text-secondary));
}

.rh-trend { font-size: 12.5px; font-weight: 700; }
.rh-trend-up { color: var(--success, #0F4C3A); }
.rh-trend-down { color: var(--error, #A83A28); }
.rh-trend-flat { color: var(--text-secondary); }

.rh-score-row {
    display: flex;
    align-items: flex-end;
    gap: 22px;
    flex-wrap: wrap;
    margin: 10px 0 4px;
}
.rh-score {
    font-family: var(--font-heading);
    font-size: 46px;
    font-weight: 800;
    line-height: 1;
}
.rh-score-of {
    font-size: 17px;
    font-weight: 700;
    color: var(--text-secondary);
    margin-left: 4px;
}

.rh-bar-wrap { flex: 1; min-width: 200px; padding-bottom: 4px; }
.rh-bar {
    position: relative;
    height: 9px;
    border-radius: 5px;
    background: var(--bg-main);
    border: 1px solid var(--border-color);
}
.rh-bar-fill { position: absolute; inset: 0 auto 0 0; border-radius: 5px; }
/* The 60-point pass mark. A score means nothing to someone who cannot see
   where the line is. */
.rh-bar-mark {
    position: absolute;
    left: 60%;
    top: -4px;
    bottom: -4px;
    width: 2px;
    background: var(--text-primary);
    opacity: 0.5;
}
.rh-bar-note { display: block; margin-top: 6px; font-size: 11.5px; color: var(--text-secondary); }

.rh-verdict {
    margin: 8px 0 2px;
    font-family: var(--font-heading);
    font-size: 16px;
    font-weight: 700;
}
.rh-next { margin: 0 0 2px; font-size: 13.5px; line-height: 1.6; color: var(--text-secondary); }
.rh-estimated {
    margin: 8px 0 0;
    padding-left: 10px;
    border-left: 3px solid var(--warning, #9A6B14);
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--text-secondary);
}
.rh-source { margin: 10px 0 0; font-size: 12px; line-height: 1.55; color: var(--text-muted, var(--text-secondary)); }
.rh-link { color: var(--accent-indigo); font-weight: 600; white-space: nowrap; }

/* --- no mock exam yet: what is still missing, never an invented number --- */
.rh-empty-lead { margin: 8px 0 14px; font-size: 14px; line-height: 1.6; color: var(--text-secondary); }
.rh-checklist { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.rh-checklist li { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--text-secondary); }
.rh-checklist li.done { color: var(--text-primary); }
.rh-check {
    flex: 0 0 20px;
    text-align: center;
    font-weight: 800;
    color: var(--text-muted, var(--text-secondary));
}
.rh-checklist li.done .rh-check { color: var(--success, #0F4C3A); }
.rh-check-label { flex: 1; }
.rh-check-detail { font-variant-numeric: tabular-nums; font-size: 12.5px; }
.rh-empty-cta { align-self: flex-start; }

@media (max-width: 640px) {
    .rh-card { padding: 18px 18px; }
    .rh-score { font-size: 38px; }
    .rh-score-row { gap: 14px; }
}


/* --- exam date, inside the readiness card (dashboard.js) ----------------
   The deadline the readiness number is measured against. 55/100 with three
   months left is a work plan; 55/100 with four days left is a different
   conversation, so the two are read together. */
.rh-exam {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 10px 0 4px;
    padding: 10px 12px;
    border-radius: var(--border-radius);
    background: var(--bg-main);
    border: 1px solid var(--border-color);
    font-size: 13.5px;
}
.rh-exam strong { font-size: 14.5px; color: var(--text-primary); }
.rh-exam-meta { font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); }
/* The final week reads differently because the plan behaves differently:
   Feinschliff drops new material entirely. */
.rh-exam-close { border-left: 3px solid var(--warning, #9A6B14); }

.rh-exam-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.rh-exam-row .form-input { width: auto; padding: 7px 10px; font-size: 13.5px; }

.rh-ask-honest { margin: 0 0 14px; font-size: 12.5px; line-height: 1.6; color: var(--text-secondary); }
.rh-passed-lead {
    margin: 8px 0 6px;
    font-family: var(--font-heading);
    font-size: 17px;
    font-weight: 700;
    color: var(--success, #0F4C3A);
}
.rh-card-passed { border-color: rgba(16, 185, 129, 0.35); }

@media (max-width: 640px) {
    .rh-exam-row { flex-direction: column; align-items: stretch; }
    .rh-exam-row .form-input { width: 100%; }
}


/* --- certificate of completion, on the Mock Test hub -------------------
   Lives on the paper surface with the exam log, so it inherits that world's
   restraint. It is a document, not a prize: no confetti, no gold. */
.cert-sheet { border-left: 3px solid var(--success, #0F4C3A); }
.cert-lead {
    margin: 10px 0 8px;
    font-family: var(--font-paper, inherit);
    font-size: 15px;
    line-height: 1.6;
    color: var(--paper-ink, var(--text-primary));
}
/* The disclaimer travels with the card as well as the PDF: someone deciding
   whether to download it should already know what it is not. */
.cert-note { margin: 0 0 14px; font-size: 13px; line-height: 1.55; }


/* --- Freunde einladen (app.js renderReferralPage) ----------------------
   Plain counters on purpose. A progress bar toward a prize would dress up
   other people's purchases as a game, and these are real friends being asked
   for real money. */
.ref-lead { margin: 0 0 18px; font-size: 14.5px; line-height: 1.65; color: var(--text-secondary); }
.ref-link-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 22px; }
.ref-link-row .form-input { flex: 1; min-width: 240px; font-family: var(--font-mono, monospace); font-size: 13px; }

.ref-stats { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 18px; }
.ref-stat {
    flex: 1;
    min-width: 120px;
    padding: 14px 16px;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    background: var(--bg-main);
}
.ref-stat-num {
    display: block;
    font-family: var(--font-heading);
    font-size: 26px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}
.ref-stat-lbl { display: block; margin-top: 4px; font-size: 12.5px; color: var(--text-secondary); }

/* A reward that has been earned but cannot be paid yet. Said plainly, because
   the alternative is a learner wondering whether it worked. */
.ref-pending {
    margin: 0 0 16px;
    padding: 12px 14px;
    border-left: 3px solid var(--warning, #9A6B14);
    border-radius: var(--border-radius);
    background: var(--bg-main);
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-secondary);
}
.ref-rules { margin: 0; font-size: 12.5px; line-height: 1.65; color: var(--text-muted, var(--text-secondary)); }

@media (max-width: 640px) {
    .ref-link-row { flex-direction: column; align-items: stretch; }
    .ref-stat { min-width: 0; }
}


/* --- seat code redemption, on the Membership page ----------------------
   A consultancy buys seats and hands its candidates a code. Until this field
   existed the endpoint had no caller, so a bought seat could not be activated
   by the person it was bought for. */
.seat-code {
    margin-top: 26px;
    padding: 20px 22px;
    border: 1px dashed var(--border-color);
    border-radius: var(--border-radius-lg);
}
.seat-code h4 { margin: 0 0 6px; font-size: 15px; font-weight: 700; color: var(--text-primary); }
.seat-code p { margin: 0 0 14px; font-size: 13.5px; line-height: 1.6; color: var(--text-secondary); }
.seat-code-row { display: flex; gap: 10px; flex-wrap: wrap; }
.seat-code-row .form-input {
    flex: 1;
    min-width: 220px;
    font-family: var(--font-mono, monospace);
    text-transform: uppercase;
}

@media (max-width: 640px) {
    .seat-code-row { flex-direction: column; align-items: stretch; }
}

/* ============================================================================
   ÜBUNGSZENTRUM — the Practice Center
   ----------------------------------------------------------------------------
   One structural idea, committed to: THE ROW IS THE PROGRESS BAR. Each official
   Teil is a full-width strip whose own background fills from the left as the
   student works through it. There is no ring, no separate bar, no percentage
   floating in a corner — the page is a stack of bars filling up, read top to
   bottom in the order of the real exam day.

   Why rows and not a card grid: the unit is full-width, so the phone layout IS
   the layout. A wide screen only centres it. There is no second layout to get
   wrong, and this is used on phones.

   Skills are told apart by the STROKE of their spine, not by five hues. Five
   colours would fight the one brand green; an icon alone is not an identity.

   Every value below is an existing token. Nothing here defines a colour, so
   nothing here needs a dark-mode override.
   ========================================================================= */

.pc-page {
    max-width: 760px;
    margin: 0 auto;
    padding: var(--s-5) var(--s-4) var(--s-8);
}

.pc-head { margin-bottom: var(--s-7); }

.pc-head h1 {
    font-family: var(--font-heading);
    font-size: var(--t-2xl);
    line-height: var(--lh-tight);
    letter-spacing: var(--tracking-tight);
    color: var(--text-primary);
    margin: 0 0 var(--s-2);
}

.pc-head p {
    font-size: var(--t-sm);
    color: var(--text-secondary);
    margin: 0;
}

/* --- A skill band: the spine plus its Teile. ------------------------------ */
.pc-band {
    /* The spine is a border, so its stroke style is the whole identity. */
    border-left: 2px solid var(--accent-indigo);
    padding-left: var(--s-5);
    margin-bottom: var(--s-7);
}
.pc-band[data-spine="dashed"] { border-left-style: dashed; }
.pc-band[data-spine="double"] { border-left-style: double; border-left-width: 4px; }
.pc-band[data-spine="dotted"] { border-left-style: dotted; }
.pc-band[data-spine="hair"]   { border-left-color: var(--border-color); }

.pc-band-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-3);
    margin-bottom: var(--s-4);
}

.pc-band-head h2 {
    font-family: var(--font-heading);
    font-size: var(--t-lg);
    line-height: var(--lh-snug);
    color: var(--text-primary);
    margin: 0;
}

.pc-band-count {
    font-size: var(--t-xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* --- One Teil. The element IS the bar. ----------------------------------- */
.pc-teil {
    position: relative;
    display: block;
    width: 100%;
    text-align: left;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
    padding: var(--s-4);
    margin-bottom: var(--s-3);
    cursor: pointer;
    overflow: hidden;
    font-family: var(--font-body);
    /* Colour only. A transform here would make every row twitch on touch, and
       the page is meant to lower a student's pulse, not raise it. */
    transition: border-color var(--d-fast) var(--ease-out);
}

.pc-teil:last-child { margin-bottom: 0; }
.pc-teil:hover { border-color: var(--accent-tint-border); }
.pc-teil:focus-visible { outline: none; box-shadow: var(--e-focus); }

/* The fill. Painted behind the text, grown from the left edge by --pc-fill. */
.pc-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--pc-fill, 0%);
    background: var(--accent-tint);
    /* The waterline. The tint alone is deliberately quiet - calm is the point -
       but quiet enough to be unreadable is not calm, it is vague. A single
       hairline at the leading edge is what makes "how far along am I" legible
       at a glance without raising the volume of the whole row. */
    border-right: 1px solid var(--accent-tint-border);
    pointer-events: none;
}
/* Nothing done yet: no fill, and therefore no waterline to draw. */
.pc-teil[data-state="empty"] .pc-fill { border-right: 0; }

/* The one moment of motion on this page: on first load every fill grows from
   nothing to where the student actually stands. Added by JS one frame after
   paint, removed when it ends, so a re-render never replays it. */
.pc-animate .pc-fill {
    animation: pc-fill-in var(--d-deliberate) var(--ease-out) both;
    animation-delay: var(--pc-delay, 0ms);
}
@keyframes pc-fill-in {
    from { width: 0; }
    to   { width: var(--pc-fill, 0%); }
}

/* A row that has earned "Sicher" carries a solid marker on its leading edge.
   One state change, not a colour ramp: the fill already says how much is done,
   so this only ever has to say whether it is trustworthy yet. */
.pc-teil[data-state="secure"]::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--accent-strong);
}

.pc-teil-body { position: relative; }

.pc-teil-name {
    display: block;
    font-size: var(--t-md);
    line-height: var(--lh-snug);
    color: var(--text-primary);
    font-weight: 600;
}
.pc-teil-name .pc-teil-label { font-weight: 400; color: var(--text-secondary); }

.pc-teil-score {
    font-size: var(--t-sm);
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    margin-left: auto;
}
/* Under 60% the figure alone carries the warning. The fill is not recoloured:
   it answers "how much have I done", which a low score does not change. */
.pc-teil-score[data-weak="1"] { color: var(--warning); }

.pc-teil-blurb {
    font-size: var(--t-sm);
    line-height: var(--lh-base);
    color: var(--text-secondary);
    margin: var(--s-2) 0 var(--s-3);
    max-width: var(--measure);
}

.pc-teil-foot {
    display: flex;
    align-items: baseline;
    gap: var(--s-3);
    font-size: var(--t-xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.pc-teil-count { flex: 1 1 auto; min-width: 0; }

/* Room for the arrow, which is pinned out of the flow below. */
.pc-teil-foot { padding-right: var(--s-5); }

/* Pinned to the row's corner rather than sitting in the foot's flex flow. In
   the flow, a long status ("Noch nicht begonnen") pushed it onto a line of its
   own, where a lone arrow reads as a rendering fault. It is decoration here -
   the whole row is the button - so it must never dictate the layout. */
.pc-teil-go {
    position: absolute;
    right: 0;
    bottom: 0;
    color: var(--accent-indigo);
    font-size: var(--t-sm);
    line-height: 1;
}

/* Narrow phones: the numbers wrap under the name rather than squeezing it. */
@media (max-width: 400px) {
    .pc-page { padding: var(--s-4) var(--s-3) var(--s-7); }
    .pc-band { padding-left: var(--s-4); }
    /* The count gives way first; the score never splits. */
    .pc-teil-foot { flex-wrap: wrap; row-gap: var(--s-1); }
}

/* A student who has asked their device for less movement gets a page that has
   already arrived, not one that animates more slowly. */
@media (prefers-reduced-motion: reduce) {
    .pc-animate .pc-fill { animation: none; }
    .pc-teil { transition: none; }
}

/* ==========================================================================
   LIVE SPEAKING PRACTICE (Sprechen -> Gespräch üben)
   src/core/speaking/practice.js and the dashboard card in dashboard.js.
   Deutsche Präzision: ink on paper, 1px hairlines, 2px radius, no shadows,
   no emoji. Scoped under .sp-* so nothing else on the page changes.
   ========================================================================== */
.sp-page,
.sp-card {
    --sp-ink: #1A1A1A;
    --sp-paper: #FAFAF7;
    --sp-line: #D8D6D0;
    --sp-red: #E30613;
    --sp-green: #1E7A46;
    --sp-muted: #6B6963;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    color: var(--sp-ink);
    background: var(--sp-paper);
    border: 1px solid var(--sp-line);
    border-radius: 2px;
    box-shadow: none;
}
.sp-card { padding: 20px 22px; margin-bottom: 24px; }
.sp-page { padding: 28px; max-width: 720px; margin: 0 auto; }
.sp-kicker {
    font-size: 11px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--sp-muted); margin: 0 0 6px 0;
}
.sp-title { font-family: inherit; font-size: 22px; font-weight: 600; line-height: 1.25; margin: 0 0 10px 0; color: var(--sp-ink); }
.sp-text { font-size: 15px; line-height: 1.55; margin: 0 0 14px 0; color: var(--sp-ink); }
.sp-note { font-size: 13px; line-height: 1.5; margin: 0 0 10px 0; color: var(--sp-muted); }
.sp-note--strong { color: var(--sp-ink); font-weight: 600; }
.sp-steps { font-size: 14px; line-height: 1.55; margin: 0 0 16px 0; padding-left: 20px; }
.sp-steps li { margin-bottom: 6px; }
.sp-btn {
    font: inherit; font-size: 15px; font-weight: 600; line-height: 1;
    border: 1px solid var(--sp-ink); border-radius: 2px;
    background: var(--sp-paper); color: var(--sp-ink);
    padding: 13px 22px; cursor: pointer; box-shadow: none; text-shadow: none;
    transition: background 120ms ease, color 120ms ease;
}
.sp-btn:hover { background: #F0EFEA; }
.sp-btn:focus-visible { outline: 2px solid var(--sp-ink); outline-offset: 2px; }
.sp-btn-primary { background: var(--sp-ink); color: var(--sp-paper); }
.sp-btn-primary:hover { background: #000000; color: var(--sp-paper); }
.sp-btn-danger { border-color: var(--sp-red); color: var(--sp-red); }
.sp-btn-danger:hover { background: var(--sp-red); color: var(--sp-paper); }
.sp-btn-start { width: 100%; max-width: 440px; font-size: 20px; padding: 24px 28px; }
.sp-actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-top: 18px; }
.sp-topbar { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.sp-state { display: flex; align-items: center; gap: 10px; font-size: 17px; font-weight: 600; margin: 18px 0 6px 0; }
.sp-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--sp-line); flex: 0 0 auto; }
.sp-dot--listening { background: var(--sp-green); }
.sp-dot--speaking { background: var(--sp-red); }
.sp-clock { font-variant-numeric: tabular-nums; font-size: 13px; color: var(--sp-muted); white-space: nowrap; }
/* Goethe A1 Prüfungssimulation only: which of the one AI voice's two roles
   is speaking right now (Prüfer/in vs Partner/in) - src/core/speaking_exam/practice.js. */
.sp-role-badge {
    display: inline-block; font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--sp-ink); border: 1px solid var(--sp-ink);
    border-radius: 2px; padding: 3px 8px; margin-bottom: 10px;
}
.sp-role-badge:empty { display: none; }
/* The Kandidatenblatt, laid out like the book's: a band on top, the content
   large in the middle, a one-line hint underneath. */
.sp-task-card {
    border: 1px solid var(--sp-ink); border-radius: 2px; padding: 0 0 12px 0; margin-bottom: 14px;
    background: var(--sp-paper); text-align: center;
}
.sp-card-band {
    font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--sp-paper); background: var(--sp-ink); margin: 0 0 14px 0; padding: 6px 12px;
}
.sp-card-word {
    font-family: 'EB Garamond', Georgia, 'Times New Roman', serif; font-style: italic;
    font-size: 34px; line-height: 1.15; font-weight: 500; margin: 6px 12px 10px; color: var(--sp-ink);
}
.sp-card-word--caption { font-size: 22px; margin-top: 4px; }
.sp-card-hint { font-size: 13px; line-height: 1.5; margin: 0 12px; color: var(--sp-muted); }
.sp-card-picture svg { width: 96px; height: 96px; stroke-width: 1.25; color: var(--sp-ink); }
.sp-stichpunkte {
    list-style: none; margin: 0 auto 6px; padding: 0 12px; max-width: 260px;
    font-family: 'EB Garamond', Georgia, 'Times New Roman', serif; font-style: italic; font-size: 24px;
}
.sp-stichpunkte li { padding: 6px 0; border-bottom: 1px solid var(--sp-line); color: var(--sp-ink); }
.sp-stichpunkte li:last-child { border-bottom: none; }
.sp-stichpunkt--done { color: var(--sp-green); }
.sp-stichpunkt--done::after { content: ' \2713'; font-family: inherit; font-style: normal; font-size: 18px; }
.sp-prompt { border: 1px solid var(--sp-line); border-radius: 2px; padding: 14px 16px; margin-top: 16px; }
.sp-prompt .sp-actions { margin-top: 4px; }
.sp-transcript { border-top: 1px solid var(--sp-line); margin-top: 18px; padding-top: 12px; }
.sp-transcript summary { cursor: pointer; font-size: 13px; color: var(--sp-muted); list-style: none; }
.sp-transcript summary::-webkit-details-marker { display: none; }
.sp-transcript summary::before { content: '+ '; }
.sp-transcript[open] summary::before { content: '– '; }
.sp-line {
    display: grid; grid-template-columns: 56px 1fr; gap: 10px;
    font-size: 14px; line-height: 1.55; padding: 7px 0; border-bottom: 1px solid var(--sp-line);
}
.sp-line-who { font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--sp-muted); padding-top: 3px; }
.sp-error { border-left: 2px solid var(--sp-red); padding-left: 12px; }
@media (max-width: 600px) {
    .sp-page { padding: 18px; }
    .sp-btn-start { font-size: 18px; padding: 20px 22px; }
}

/* ---- Free/paid line, 2026-09-23 --------------------------------------------
   The padlock on paid items (.pm-lock), the screen after the free graded answer
   (.us-*), and the locked Tagesplan card. Product world: calm, no motion
   (UI_UX_GUIDELINES.md 19). */
.pm-lock { width: 14px; height: 14px; vertical-align: -2px; color: var(--text-secondary); flex-shrink: 0; }
.pm-lock-badge { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600;
    color: var(--text-secondary); margin-left: 6px; }
.us-card { max-width: 580px; max-height: 92vh; overflow-y: auto; }
.us-kicker { margin: 0 0 4px; font-size: 13px; color: var(--text-secondary); }
.us-score { margin: 0 0 6px; font-size: 26px; font-variant-numeric: tabular-nums; }
.us-sub { margin: 0 0 10px; font-size: 14px; color: var(--text-secondary); }
.us-label { margin: 12px 0 4px; font-size: 14px; font-weight: 600; }
.us-criteria { margin: 0 0 14px; padding-left: 20px; font-size: 14.5px; }
.us-locked { position: relative; border: 1px solid var(--border-color); border-radius: var(--border-radius-md);
    padding: 12px 14px; margin: 0 0 12px; overflow: hidden; }
.us-blur { filter: blur(5px); user-select: none; pointer-events: none; }
.us-line { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; font-size: 14px; }
.us-err { color: #A83A28; font-weight: 600; white-space: nowrap; }
.us-lock-over { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    gap: 8px; font-size: 14.5px; background: rgba(255, 255, 255, 0.35); }
.us-lock-over .pm-lock { width: 18px; height: 18px; color: var(--text-primary); }
.us-date { margin: 0 0 12px; font-size: 15px; font-weight: 600; }
.us-plans-h { margin: 14px 0 8px; font-size: 16px; }
.us-plans { display: grid; gap: 8px; margin-bottom: 12px; }
.us-plan { display: grid; grid-template-columns: auto 1fr auto; grid-template-rows: auto auto; column-gap: 10px;
    align-items: center; padding: 10px 12px; border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md); cursor: pointer; }
.us-plan input { grid-row: 1 / span 2; }
.us-plan.is-selected { border-color: var(--accent-indigo); box-shadow: 0 0 0 1px var(--accent-indigo); }
.us-plan-name { font-weight: 600; }
.us-plan-days { grid-column: 2; font-size: 13px; color: var(--text-secondary); }
.us-plan-price { grid-column: 3; grid-row: 1 / span 2; font-weight: 700; font-variant-numeric: tabular-nums; }
.us-badge { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: 11px;
    font-weight: 600; background: var(--accent-indigo); color: #fff; vertical-align: 1px; }
.us-badge-g { background: transparent; color: var(--text-primary); border: 1px solid var(--border-color); }
.us-price-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 12px; margin: 4px 0 8px; font-size: 20px; }
.us-fee { font-size: 13.5px; color: var(--text-secondary); }
.us-buy { width: 100%; }
.us-paylines { margin: 6px 0 10px; font-size: 12.5px; color: var(--text-secondary); text-align: center; }
.us-close { width: 100%; }
.us-fix { padding: 8px 0; border-bottom: 1px solid var(--border-color); font-size: 14px; }
.us-fix-orig { text-decoration: line-through; color: #A83A28; }
.us-fix-new { color: var(--text-primary); font-weight: 600; }
.mock-section-locked { padding: 28px 20px; text-align: center; border: 1px dashed var(--border-color);
    border-radius: var(--border-radius-md); }
.mock-section-locked .pm-lock { width: 28px; height: 28px; display: block; margin: 0 auto 10px; }

/* ---- Landing, 2026-09-23: goal paths, B1 exam-date plans, payment lines ---- */
.ld-goals { padding: 40px 0 24px; }
.ld-goal-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 18px;
    margin-top: 24px;
}
.ld-goal-card { padding: 24px 22px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.ld-goal-card h3 { font-family: var(--font-heading); font-size: 18px; font-weight: 800; margin: 6px 0 0; }
.ld-goal-card p { font-size: 13.5px; color: var(--text-secondary); line-height: 1.55; margin: 0 0 8px; flex: 1; }
.ld-goal-card .btn-primary { width: 100%; justify-content: center; }
.ld-plans-h { font-family: var(--font-heading); font-size: 22px; font-weight: 800; text-align: center; margin: 36px 0 4px; }
.ld-plans-sub { text-align: center; color: var(--text-secondary); font-size: 14px; margin: 0; }
.ld-plan-grid { margin-top: 20px; }
.ld-price-card-rec { border: 2px solid var(--accent-indigo); }
.ld-paylines { margin: 10px 0 0 !important; flex: 0 !important; font-size: 12px !important; text-align: center; color: var(--text-secondary); }
.ld-results:empty { display: none; }

/* ==========================================================================
   ADMIN USAGE DASHBOARD  (/admin-usage)
   --------------------------------------------------------------------------
   Built on the shipped tokens in this file (UI_UX_GUIDELINES.md), not on the
   reverted "Deutsche Präzision" layer. Section 7 gives cards their hairline +
   soft elevation, section 12 puts numeric columns in --font-mono so digits
   align down a column, and section 4 keeps Space Grotesk for the deliberate
   display numerals. Accent tokens are forest green in light and gold in dark,
   so both themes follow without a second set of rules.
   ========================================================================== */

.au-meta {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 20px;
}

/* --- the four headline numbers ------------------------------------------ */

.au-kpis {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 20px;
}

/* Rides on .stat-box for its surface, hairline, radius and padding - and so
   inherits the dark-theme glass/rim/elevation recipe that .stat-box already
   gets further up this file. Copying that recipe here would be a second place
   for it to drift. This class only adds what a KPI tile needs on top. */
.au-kpi {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 18px 20px;
}

/* Two lines' worth of room whether a label needs one or two, so the four
   figures sit on one baseline instead of stepping down the row. */
.au-kpi__label {
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    min-height: 2.6em;
}

.au-kpi__figure { display: flex; align-items: baseline; gap: 6px; }

.au-kpi__value {
    font-family: var(--font-heading);
    font-size: 34px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}
.au-kpi__value--text { font-size: 20px; letter-spacing: 0; }

.au-kpi__of {
    font-family: var(--font-mono);
    font-size: 15px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.au-kpi__sub { font-size: 12.5px; color: var(--text-secondary); margin-top: auto; }

.au-meter {
    height: 5px;
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    overflow: hidden;
}
.au-meter__fill {
    height: 100%;
    background: var(--accent-gradient);
    border-radius: 999px;
}

/* --- the honest caveat --------------------------------------------------- */

.au-note {
    background: var(--bg-surface-elevated);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent-indigo);
    border-radius: var(--border-radius-lg);
    padding: 14px 18px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-secondary);
    margin-bottom: 20px;
    max-width: 78ch;
}

/* --- roster -------------------------------------------------------------- */

/* .table-container clips with overflow:hidden, so the scroll lives here -
   guidelines section 14: wide content scrolls in its own box, the page body
   never scrolls sideways. */
.au-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.au-table td, .au-table th { white-space: nowrap; }
.au-table tbody tr { transition: var(--transition-smooth); }
.au-table tbody tr:hover { background: var(--bg-surface-hover); }
.au-table tbody tr:last-child td { border-bottom: 0; }

/* Sorting is the whole usability story at 45 rows: it floats the students who
   actually use the app to the top and sinks the dormant accounts. */
.au-sort {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: inherit;
    cursor: pointer;
    transition: var(--transition-smooth);
}
.au-sort:hover { color: var(--text-primary); }
.au-sort:focus-visible { outline: 2px solid var(--border-color-focus); outline-offset: 3px; }
.au-sort__caret { opacity: 0; font-size: 9px; }
.au-sort[aria-sort="ascending"],
.au-sort[aria-sort="descending"] { color: var(--accent-indigo); }
.au-sort[aria-sort="ascending"] .au-sort__caret,
.au-sort[aria-sort="descending"] .au-sort__caret { opacity: 1; }

.au-person__name { font-weight: 600; color: var(--text-primary); display: block; }
.au-person__mail { font-size: 12px; color: var(--text-muted); }
.au-level {
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
}

/* Guidelines section 12: numbers right-aligned and monospaced so a column can
   be read down rather than across. */
.au-num {
    text-align: right;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
}
.au-num--zero { color: var(--text-muted); font-weight: 400; }
.au-sub { display: block; font-family: var(--font-body); font-size: 11.5px; color: var(--text-muted); }
.au-nil { color: var(--text-muted); }

/* A row nobody has touched is information, not clutter - it is most of what
   the founder came to this page to see. */
.au-row--cold .au-person__name { color: var(--text-secondary); font-weight: 500; }

.au-foot { font-size: 12.5px; color: var(--text-muted); margin-top: 14px; line-height: 1.6; }

@media (max-width: 1100px) { .au-kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px)  {
    .au-kpis { grid-template-columns: 1fr; }
    .au-kpi__label { min-height: 0; }
}

/* ==========================================================================
   ADMIN COHORTS  (/admin-cohort)
   --------------------------------------------------------------------------
   The member table, numbers, dates and footnote reuse the .au-* rules above.
   New here: the grant form card, the cohort picker row, the result line, and
   a disabled state for the two buttons - .btn-primary / .btn-secondary have
   none, and guidelines section 8 requires one.
   ========================================================================== */

.ac-card {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-lg);
    box-shadow: var(--shadow-sm);
    padding: 24px;
    margin-bottom: 24px;
}

.ac-card__title {
    font-family: var(--font-heading);
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0 0 16px;
}

.ac-form {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
    gap: 16px;
    align-items: end;
}

.ac-form .form-group,
.ac-toolbar .form-group { margin-bottom: 0; }

.ac-form .btn-primary,
.ac-toolbar .btn-secondary { min-height: 44px; justify-content: center; }

.ac-form .btn-primary:disabled,
.ac-toolbar .btn-secondary:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

/* Ten columns: 12px side padding instead of the table default's 20px, so the
   table fits a laptop screen without a sideways scroll. */
.ac-table th,
.ac-table td { padding-left: 12px; padding-right: 12px; }

.ac-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 16px;
    margin-bottom: 16px;
}
.ac-toolbar .form-group { min-width: 280px; }

/* Text first, colour second (guidelines section 11): every state is a
   sentence, and the tinted band only reinforces it. */
.ac-notice {
    margin: 0 0 16px;
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--text-primary);
}
.ac-card .ac-notice { margin: 16px 0 0; }
.ac-notice:empty { display: none; }
.ac-notice--ok,
.ac-notice--warn,
.ac-notice--error {
    padding: 10px 14px;
    border-radius: var(--border-radius-md);
    border-left: 3px solid var(--border-color);
}
.ac-notice--ok    { background: var(--success-bg); border-left-color: var(--success); }
.ac-notice--warn  { background: var(--warning-bg); border-left-color: var(--warning); }
.ac-notice--error { background: var(--error-bg);   border-left-color: var(--error); }

.ac-help {
    margin: 12px 0 0;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--text-muted);
    max-width: 78ch;
}

@media (max-width: 760px) {
    .ac-form { grid-template-columns: 1fr; }
    .ac-toolbar .form-group { min-width: 0; flex: 1 1 100%; }
}

/* Same-name accounts are flagged, never merged (modules/analytics/usage.py
   flag_duplicates) - warning, not error, because two real people can share a
   name and nothing here can tell which case it is. */
.au-dupe {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 7px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: var(--bg-surface-elevated);
    font-family: var(--font-body);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--warning);
    vertical-align: 1px;
    cursor: help;
}
