/* ---------- Reusable check icon (SVG mask) ---------- */
/* Source: /static/icons/check.svg. Inherits color from
   currentColor so it adapts to surrounding text color
   (green badges, white buttons, etc.). */
.icon-check,
.icon-cross {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    background-color: currentColor;
    flex-shrink: 0;
}
.icon-check {
    -webkit-mask: url("/static/icons/check.svg") no-repeat center /
        contain;
    mask: url("/static/icons/check.svg") no-repeat center / contain;
}
.icon-cross {
    -webkit-mask: url("/static/icons/cross.svg") no-repeat center /
        contain;
    mask: url("/static/icons/cross.svg") no-repeat center / contain;
}

/* ---------- Local fonts (served from /static/fonts) ---------- */
@font-face {
    font-family: "Inter";
    src: url("/static/fonts/Inter-roman-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Happy Headline";
    src: url("/static/fonts/Happy-Headline.woff2") format("woff2");
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "JetBrains Mono";
    src: url("/static/fonts/JetBrainsMono-Regular.woff2")
        format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
/* Lora italic, used for chapter intro epigraphs.
   Two subsets: latin covers ASCII + Latin-1 Supplement,
   latin-ext adds extended Latin diacritics and currency
   symbols. Variable weight 400–700 from one file each. */
@font-face {
    font-family: "Lora";
    src: url("/static/fonts/lora/lora-italic-latin.woff2")
        format("woff2");
    font-style: italic;
    font-weight: 400 700;
    font-display: swap;
    unicode-range:
        U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
        U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC,
        U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Lora";
    src: url("/static/fonts/lora/lora-italic-latin-ext.woff2")
        format("woff2");
    font-style: italic;
    font-weight: 400 700;
    font-display: swap;
    unicode-range:
        U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
        U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
        U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
        U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* ---------- Theme tokens ---------- */
:root {
    /* GitHub Primer (light) */
    --color-background: #ffffff;
    --color-surface: #f6f8fa;
    --color-primary: #0969da;
    --color-primary-muted: #0550ae;
    --color-primary-rgb: 9, 105, 218;
    --color-text: #1f2328;
    --color-text-muted: #59636e;
    --color-border: #d1d9e0;
    --color-input-bg: #ffffff;
    --color-input-border: #d1d9e0;
    --color-success: #1a7f37;
    --color-warning: #9a6700;
    --color-error: #d1242f;
    /* Brand pink, used for the headline color and for high-emphasis
       destructive actions (e.g. the admin "Remove participant"
       button) so the page reads with a single accent palette
       instead of competing reds. */
    --color-brand: #fc218a;
    --color-brand-muted: #d11a73;
    --logo-filter: invert(0%);
    /* Syntax highlight palette, shared by chapter prose code
       blocks and the in-page CodeMirror editor. */
    --syn-keyword: #cf222e;
    --syn-type: #953800;
    --syn-string: #0a3069;
    --syn-number: #0550ae;
    --syn-definition: #8250df;
    --syn-macro: #116329;
    --syn-comment: #6e7781;
    --syn-punctuation: #57606a;
    --syn-invalid: #cf222e;
    --syn-bg: #f6f8fa;
    --syn-fg: #1f2328;
    --syn-cursor: #1f2328;
    --syn-selection-bg: #b4d5fe;
    --syn-gutter-bg: #f6f8fa;
    --syn-gutter-fg: #59636e;
    --syn-active-line: #eaeef2;
}

html[data-theme="dark"] {
    /* GitHub Primer (dark) */
    --color-background: #0d1117;
    --color-surface: #151b23;
    --color-primary: #4493f8;
    --color-primary-muted: #1f6feb;
    --color-primary-rgb: 68, 147, 248;
    --color-text: #f0f6fc;
    --color-text-muted: #9198a1;
    --color-border: #3d444d;
    --color-input-bg: #0d1117;
    --color-input-border: #3d444d;
    --color-success: #3fb950;
    --color-warning: #d29922;
    --color-error: #f85149;
    --color-brand: #fc218a;
    --color-brand-muted: #ff4ca0;
    --logo-filter: invert(100%);
    --syn-keyword: #cba6f7;
    --syn-type: #f9e2af;
    --syn-string: #a6e3a1;
    --syn-number: #fab387;
    --syn-definition: #89b4fa;
    --syn-macro: #f5c2e7;
    --syn-comment: #6c7086;
    --syn-punctuation: #94a3b8;
    --syn-invalid: #f38ba8;
    --syn-bg: #1e1e2e;
    --syn-fg: #cdd6f4;
    --syn-cursor: #cdd6f4;
    /* Selection bg has to stay readable against every syntax
       token color (yellows, greens, reds), so we pick a
       saturated blue instead of a muted surface tone. */
    --syn-selection-bg: #3c5a80;
    --syn-gutter-bg: #1e1e2e;
    --syn-gutter-fg: #6c7086;
    --syn-active-line: #2a2b3c;
}

/* ---------- Reset ---------- */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family:
        "Inter",
        -apple-system,
        BlinkMacSystemFont,
        "Segoe UI",
        Roboto,
        "Helvetica Neue",
        sans-serif;
    background-color: var(--color-background);
    color: var(--color-text);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

h1,
.header h1,
.exercise-title {
    font-family:
        "Happy Headline",
        "Inter",
        -apple-system,
        BlinkMacSystemFont,
        sans-serif;
    letter-spacing: -0.01em;
}

h2,
h3,
h4,
h5,
h6 {
    /* Sub-headlines stay in the body face so they read as section
       labels rather than competing with the page title. */
    font-family: inherit;
    letter-spacing: -0.005em;
}

code,
pre,
kbd,
samp,
.cm-editor,
.cm-content,
.code-block {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
}

/* Editor preferences from `/settings`. The settings page
   writes `data-editor-font-size`, `data-editor-ligatures`,
   and `data-editor-active-line` on `<html>` and persists
   them to localStorage; `base.html` re-applies them before
   paint so every page picks them up at load. The base size
   (`0.9rem`) used to live as an inline style on each
   editor's root in `static/js/inline-editor.js`; it now
   lives here so the user override actually wins. */
.cm-editor {
    font-size: 0.9rem;
}
html[data-editor-font-size="small"] .cm-editor {
    font-size: 0.78rem;
}
html[data-editor-font-size="large"] .cm-editor {
    font-size: 1.05rem;
}
/* Programming ligatures (JetBrains Mono ships them on by
   default). Some readers prefer to see the raw glyphs so
   `==`, `!=`, `->`, `=>` etc. read as their literal tokens;
   disable across every monospaced surface so the editor,
   inline code, and read-only viewers stay consistent. */
html[data-editor-ligatures="off"] code,
html[data-editor-ligatures="off"] pre,
html[data-editor-ligatures="off"] kbd,
html[data-editor-ligatures="off"] samp,
html[data-editor-ligatures="off"] .cm-editor,
html[data-editor-ligatures="off"] .cm-content,
html[data-editor-ligatures="off"] .code-block,
html[data-editor-ligatures="off"] .rust-editor {
    font-variant-ligatures: none;
    font-feature-settings:
        "liga" 0,
        "calt" 0,
        "clig" 0,
        "dlig" 0;
}
/* The active-line + active-gutter highlight is on by
   default (via `highlightActiveLine` / `Gutter` in
   `static/js/inline-editor.js`). Some folks find the
   extra band distracting; this knob hides the background
   without touching the editor's extension list. */
html[data-editor-active-line="off"] .cm-activeLine,
html[data-editor-active-line="off"] .cm-activeLineGutter {
    background-color: transparent !important;
}

/* CodeMirror selection. We pin this in static CSS (rather than
   via EditorView.theme) so it always reflects the current
   --syn-selection-bg, even after a theme toggle. */
.cm-editor .cm-selectionBackground,
.cm-editor.cm-focused .cm-selectionBackground,
.cm-editor .cm-content ::selection {
    background-color: var(--syn-selection-bg) !important;
}

/* ---------- Layout ---------- */
.container {
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    padding: 1.5rem 1.5rem 4rem;
    flex: 1 0 auto;
}

.header {
    text-align: center;
    margin-bottom: 3rem;
}
.header h1 {
    font-size: 2.5rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--color-text);
    margin-bottom: 0.5rem;
}
.header p {
    font-size: 1.05rem;
    color: var(--color-text-muted);
}

/* ---------- Cards / forms / buttons (used by other pages) ---------- */
.card {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    padding: 1.5rem;
    margin-bottom: 1.25rem;
}
.form-group {
    margin-bottom: 1.25rem;
}
.form-group label {
    display: block;
    margin-bottom: 0.4rem;
    font-weight: 600;
    color: var(--color-text);
}
.form-control {
    width: 100%;
    padding: 0.7rem 1rem;
    background-color: var(--color-input-bg);
    border: 1px solid var(--color-input-border);
    border-radius: 6px;
    color: var(--color-text);
    font-size: 1rem;
}
.form-control:focus {
    outline: none;
    border-color: var(--color-primary);
}
.form-control::placeholder {
    color: var(--color-text-muted);
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    height: 2.25rem;
    padding: 0 0.95rem;
    background-color: var(--color-primary);
    color: #fff;
    text-decoration: none;
    border: 1px solid var(--color-primary);
    border-radius: 6px;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    box-sizing: border-box;
}
.btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}
/* Post-autosubmit success state: keeps the button visible as a
   confirmation indicator without looking like a generic
   disabled primary action. The Run → Submit handler in
   `static/js/inline-editor.js` adds/removes this class. */
.btn.is-submitted,
.btn.is-submitted:disabled {
    opacity: 1;
    background-color: var(--color-success, #2e7d32);
    border-color: var(--color-success, #2e7d32);
    color: #fff;
    cursor: default;
}
.btn:hover {
    background-color: var(--color-primary-muted);
}
.btn-secondary {
    background-color: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
}
.btn-secondary:hover {
    background-color: var(--color-background);
    border-color: var(--color-text-muted);
    color: var(--color-text);
}
.btn-success {
    background-color: var(--color-success);
    border-color: var(--color-success);
    color: #fff;
}
.btn-success:hover {
    /* Slight darken on hover; falls back to filter so we don't
       need a separate token per theme. */
    filter: brightness(0.92);
}

.exercise-list {
    display: grid;
}
.exercise-item {
    display: flex;
    align-items: center;
    padding: 1rem;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 6px;
}
.exercise-item:hover {
    border-color: var(--color-primary);
}
.exercise-status {
    font-size: 1.25rem;
    margin-right: 1rem;
}
.exercise-name {
    font-weight: 500;
    color: var(--color-text);
    font-family: "SF Mono", Monaco, monospace;
}
.status-completed {
    color: var(--color-success);
}
.status-perfected {
    color: var(--color-warning);
}
.status-pending {
    color: var(--color-text-muted);
}

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}
.stat-card {
    text-align: center;
    padding: 1rem;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
}
.stat-number {
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--color-primary);
    display: block;
}
.stat-label {
    color: var(--color-text-muted);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* ---------- Admin / team page layout rhythm ----------
   Both `/admin` and the per-team pages add `.admin-page` to
   the outer container so they share the same column width,
   vertical padding, and section spacing. The rules live here
   (rather than in either page's scoped `<style>` block) so
   the two views can't drift visually. */
.admin-page {
    max-width: 60rem;
    padding-top: 1rem;
    padding-bottom: 5rem;
}
.admin-hero {
    margin: 3rem 0 4rem;
}
.admin-title {
    font-size: 2.4rem;
}
.admin-section {
    margin-bottom: 5rem;
}
.admin-section:last-of-type {
    margin-bottom: 0;
}

.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.92rem;
}
.admin-table th {
    text-align: left;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    padding: 0.6rem 0.5rem;
    border-bottom: 1px solid var(--color-border);
    background: transparent;
}
.admin-table td {
    padding: 0.7rem 0.5rem;
    border-bottom: 1px solid var(--color-border);
    vertical-align: middle;
    color: var(--color-text);
}
.admin-cell-name {
    font-weight: 500;
    color: var(--color-text);
}
.admin-cell-muted {
    color: var(--color-text-muted);
}
.admin-progress-done {
    color: var(--color-success);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.admin-progress-total {
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}
.admin-progress-complete {
    color: var(--color-warning);
    margin-left: 0.5rem;
    font-size: 0.85rem;
}
.admin-col-actions {
    text-align: right;
    white-space: nowrap;
}
.admin-col-actions .btn {
    margin-left: 0.4rem;
}

/* ---------- Inline forms / inputs shared by admin + team pages ----------
   Inputs match the button height (2.25rem default, 1.85rem for the
   `tiny` variant used inside tables) so rows of controls line up
   cleanly. The styling is intentionally understated: a single thin
   border, the page surface as background, and a soft primary ring on
   focus rather than a heavy outline. */
.admin-input {
    box-sizing: border-box;
    height: 2.25rem;
    padding: 0 0.65rem;
    font-family: inherit;
    font-size: 0.9rem;
    line-height: 1;
    color: var(--color-text);
    background: var(--color-input-bg);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    transition:
        border-color 120ms ease,
        box-shadow 120ms ease;
}
.admin-input:hover {
    border-color: var(--color-text-muted);
}
.admin-input:focus,
.admin-input:focus-visible {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px
        color-mix(in srgb, var(--color-primary) 18%, transparent);
}
.admin-input::placeholder {
    color: var(--color-text-muted);
    opacity: 0.75;
}
.admin-input-tiny {
    height: 1.85rem;
    font-size: 0.82rem;
    padding: 0 0.55rem;
}
.admin-input-mono {
    font-family: "JetBrains Mono", "SF Mono", Monaco, monospace;
    font-size: 0.8rem;
}
select.admin-input {
    padding-right: 1.75rem;
    appearance: none;
    /* Inline SVG caret so the dropdown reads consistently across
       themes without pulling in an icon font. */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%2359636e' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M1 1.5l5 5 5-5'/></svg>");
    background-repeat: no-repeat;
    background-position: right 0.55rem center;
    background-size: 0.7rem auto;
}
html[data-theme="dark"] select.admin-input {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%239198a1' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M1 1.5l5 5 5-5'/></svg>");
}

.admin-inline-form {
    display: inline-flex;
    gap: 0.4rem;
    align-items: center;
}

/* ---------- Tiny / danger button variants ---------- */
.btn.admin-btn-tiny {
    height: 1.85rem;
    padding: 0 0.7rem;
    font-size: 0.78rem;
    font-weight: 600;
}
.btn.admin-btn-danger {
    background-color: var(--color-brand);
    border-color: var(--color-brand);
    color: #fff;
}
.btn.admin-btn-danger:hover {
    background-color: var(--color-brand-muted);
    border-color: var(--color-brand-muted);
}

.code-block {
    background-color: #1e1e2e;
    color: #cdd6f4;
    border: 1px solid #313244;
    border-radius: 12px;
    padding: 1rem;
    margin: 1rem 0;
    overflow-x: auto;
    font-family: "SF Mono", Monaco, monospace;
    font-size: 0.875rem;
    line-height: 1.5;
}

/* ---------- Top bar / brand (kept for non-exercise pages) ---------- */
.nav {
    /* Per-page in-content nav blocks are superseded by the
       global fixed top bar below. Keep the rule for backwards
       compatibility, but hide the markup wherever it appears. */
    display: none !important;
}

/* ---------- Global sticky top bar ---------- */
.topbar {
    position: sticky;
    top: 0;
    z-index: 900;
    height: 3rem;
    background: var(--color-background);
    /* The hairline scroll-progress bar (`.topbar-progress-bar`)
       sits at the bottom edge of the topbar and acts as the
       visual separator from the page content, so the topbar
       itself doesn't draw a border. */
    display: flex;
    align-items: center;
    padding: 0 1.5rem;
}
.topbar-inner {
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.875rem;
}
.topbar-home {
    color: var(--color-text-muted);
    text-decoration: none;
    padding: 0.25rem 0.4rem;
    border-radius: 4px;
}
.topbar-home:hover {
    color: var(--color-text);
}
.topbar-crumb-sep {
    color: var(--color-text-muted);
    opacity: 0.6;
}
.topbar-crumb-static {
    color: var(--color-text-muted);
}
.topbar-crumb-current {
    font-family: "JetBrains Mono", "SF Mono", Monaco, monospace;
    font-size: 0.85rem;
    color: var(--color-text);
}
.topbar-progress {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-left: 0.6rem;
    padding: 0.25rem 0.65rem;
    border-radius: 6px;
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text-muted);
    font-size: 0.8rem;
    line-height: 1.2;
    white-space: nowrap;
}
.topbar-progress-label {
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-size: 0.66rem;
    font-weight: 600;
}
.topbar-progress-count {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}
.topbar-progress-count strong {
    color: var(--color-primary, #0969da);
    font-weight: 600;
}
/* Hairline scroll-progress bar pinned to the bottom edge of
   the sticky topbar. The fill's `width` is driven by the
   inline scroll handler at the bottom of `<body>`; the
   track itself doubles as the topbar's bottom border. */
.topbar-progress-bar {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    pointer-events: none;
    background: var(--color-border);
}
.topbar-progress-bar-fill {
    display: block;
    height: 100%;
    /* `width` is set inline by the scroll handler; default
       to 0 so the bar starts empty before JS runs. No
       transition: the fill should track the scroll gesture
       in real time, not lag behind it. */
    width: 0;
    background: var(--color-primary);
}
html[data-theme="dark"] .topbar-progress-bar-fill {
    /* Brand pink reads better against the dark surface than
       the muted dark-theme blue, and matches the accent
       used elsewhere (headline, destructive admin actions). */
    background: var(--color-brand);
    box-shadow: 0 0 6px
        color-mix(in srgb, var(--color-brand) 55%, transparent);
}
.topbar-spacer {
    flex: 1;
}

/* ---------- Chapter picker (dropdown / mobile sheet) ---------- */
.chapter-picker {
    position: relative;
    display: inline-flex;
}
.chapter-picker-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    padding: 0.2rem 0.4rem 0.2rem 0.5rem;
    color: var(--color-text);
    cursor: pointer;
    font: inherit;
}
.chapter-picker-btn:hover,
.chapter-picker-btn[aria-expanded="true"] {
    background: color-mix(
        in srgb,
        var(--color-text) 8%,
        transparent
    );
    border-color: var(--color-border);
}
.chapter-picker-label {
    font-size: 0.875rem;
    font-weight: 500;
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
    line-height: 1.2;
}
.chapter-picker-label .chapter-picker-num {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--color-primary, #0969da);
    font-variant-numeric: tabular-nums;
}
.chapter-picker-chevron {
    color: var(--color-text-muted);
    transition: transform 0.15s ease;
}
.chapter-picker-btn[aria-expanded="true"] .chapter-picker-chevron {
    transform: rotate(180deg);
}
.chapter-picker-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 950;
    min-width: 320px;
    max-width: min(420px, calc(100vw - 1rem));
    max-height: min(70vh, 28rem);
    overflow-y: auto;
    background: var(--color-background);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.25);
    padding: 0.35rem;
}
.chapter-picker-menu[hidden] {
    display: none;
}
.chapter-picker-sheet-header {
    /* Hidden on desktop; appears only in the mobile sheet. */
    display: none;
}
.chapter-picker-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.chapter-picker-item {
    display: grid;
    grid-template-columns: 2.25rem 1fr auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.6rem;
    border-radius: 6px;
    color: var(--color-text);
    text-decoration: none;
    font-size: 0.875rem;
    line-height: 1.25;
}
.chapter-picker-item:hover {
    background: color-mix(
        in srgb,
        var(--color-text) 8%,
        transparent
    );
}
.chapter-picker-item.is-current {
    background: color-mix(
        in srgb,
        var(--color-primary) 12%,
        transparent
    );
    color: var(--color-text);
}
.chapter-picker-num {
    font-family: "JetBrains Mono", "SF Mono", Monaco, monospace;
    font-size: 0.75rem;
    color: var(--color-text-muted);
    text-align: right;
}
.chapter-picker-item.is-current .chapter-picker-num {
    color: var(--color-primary);
    font-weight: 600;
}
.chapter-picker-title {
    color: inherit;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.chapter-picker-status {
    color: var(--color-text-muted);
    font-size: 0.8rem;
    min-width: 0.8rem;
    text-align: right;
}

/* Mobile: turn the popover into a bottom sheet so taps are
   easy and the list isn't clipped by the viewport. */
@media (max-width: 640px) {
    .chapter-picker-menu {
        position: fixed;
        inset: auto 0 0 0;
        top: auto;
        left: 0;
        right: 0;
        width: 100%;
        max-width: 100%;
        max-height: 80vh;
        border-radius: 14px 14px 0 0;
        padding: 0.5rem 0.5rem 1rem;
        box-shadow: 0 -16px 40px rgba(0, 0, 0, 0.35);
        /* Sit above the (also-overlay) cheatsheet backdrop
           isn't necessary; this is its own layer. */
    }
    .chapter-picker-menu::before {
        /* Dim the page behind the sheet without an extra DOM
           node: we paint a fixed pseudo-backdrop. */
        content: "";
        position: fixed;
        inset: 0;
        background: color-mix(in srgb, black 45%, transparent);
        z-index: -1;
    }
    .chapter-picker-sheet-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0.5rem 0.4rem 0.6rem;
        font-weight: 600;
        color: var(--color-text);
        font-size: 0.95rem;
        border-bottom: 1px solid var(--color-border);
        margin-bottom: 0.4rem;
    }
    .chapter-picker-sheet-close {
        background: transparent;
        border: none;
        color: var(--color-text-muted);
        font-size: 1.5rem;
        line-height: 1;
        padding: 0.25rem 0.5rem;
        cursor: pointer;
    }
    .chapter-picker-item {
        padding: 0.7rem 0.6rem;
        font-size: 0.95rem;
    }
}
.topbar-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.6rem;
    border-radius: 6px;
    font-size: 0.875rem;
    color: var(--color-text-muted);
    text-decoration: none;
    background: transparent;
    border: none;
    cursor: pointer;
    font-family: inherit;
}
.topbar-link:hover {
    color: var(--color-text);
    background: color-mix(
        in srgb,
        var(--color-text) 8%,
        transparent
    );
}
.topbar-link.is-active {
    color: var(--color-text);
    background: color-mix(
        in srgb,
        var(--color-primary) 14%,
        transparent
    );
}
.topbar-link.is-active:hover {
    background: color-mix(
        in srgb,
        var(--color-primary) 20%,
        transparent
    );
}
.topbar-link svg {
    width: 0.95rem;
    height: 0.95rem;
}

/* ---------- Old in-page nav (admin/dashboard) ---------- */
.nav-brand {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--color-text);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
}
.nav-links {
    display: flex;
    gap: 1rem;
    align-items: center;
}
.nav-link {
    color: var(--color-text-muted);
    text-decoration: none;
    font-size: 0.95rem;
}
.nav-link:hover {
    color: var(--color-text);
}

.brand-logo {
    height: 28px;
    display: block;
    filter: var(--logo-filter);
}

/* ---------- Theme toggle (lives inside the top bar) ---------- */
.theme-toggle {
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 6px;
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 0.25rem;
}
.theme-toggle:hover {
    border-color: var(--color-text-muted);
}
.theme-toggle svg {
    width: 0.95rem;
    height: 0.95rem;
}
.theme-toggle .icon-sun {
    display: none;
}
.theme-toggle .icon-moon {
    display: inline-block;
}
html[data-theme="dark"] .theme-toggle .icon-sun {
    display: inline-block;
}
html[data-theme="dark"] .theme-toggle .icon-moon {
    display: none;
}

/* ---------- Code-container helpers (admin/dashboard) ---------- */
.code-container {
    position: relative;
}
.copy-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 4px;
    padding: 4px 8px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--color-text);
    font-size: 0.8rem;
}
.copy-btn:hover {
    border-color: var(--color-text-muted);
}
.copy-btn svg {
    width: 14px;
    height: 14px;
}

/* ---------- Prose code-block copy chrome ----------
   Wraps any `<pre>` that should get a hover-reveal copy
   button. Used by `templates/exercise.html` (chapter
   prose) and `templates/settings.html` (CLI commands).
   The JS lives in those files; the look is shared here. */
.prose-code-wrap {
    position: relative;
}
.prose-copy-btn {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 2;
    background: var(--color-surface);
    color: var(--color-text-muted);
    border: 1px solid var(--color-border);
    border-radius: 3px;
    padding: 0.25rem 0.4rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    opacity: 0;
    transition:
        opacity 0.15s ease,
        color 0.15s ease;
}
.prose-code-wrap:hover .prose-copy-btn,
.prose-code-wrap:focus-within .prose-copy-btn,
.prose-copy-btn:focus-visible {
    opacity: 0.85;
}
.prose-copy-btn:hover {
    opacity: 1;
}
.prose-copy-btn svg {
    width: 14px;
    height: 14px;
}

/* ---------- Footer ---------- */
.site-footer {
    border-top: 1px solid var(--color-border);
    padding: 2.5rem 1.5rem 1.5rem;
    background: var(--color-surface);
    color: var(--color-text-muted);
    font-size: 0.9rem;
}
.site-footer-inner {
    max-width: 1100px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 2.5rem;
    align-items: start;
}
@media (max-width: 720px) {
    .site-footer-inner {
        grid-template-columns: 1fr;
        gap: 2rem;
    }
}
.site-footer-brand .brand-logo {
    height: 26px;
    margin-bottom: 0.75rem;
}
.site-footer-brand p {
    margin: 0;
    line-height: 1.55;
}
.site-footer-brand .site-footer-version {
    margin-top: 0.6rem;
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}
.site-footer-col h3 {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--color-text);
    margin: 0 0 0.85rem;
}
.site-footer-col ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.site-footer a {
    color: var(--color-text-muted);
    text-decoration: none;
}
.site-footer a:hover {
    color: var(--color-text);
    text-decoration: underline;
}

@media (max-width: 768px) {
    .container {
        padding: 1rem 1rem 3rem;
    }
    .header h1 {
        font-size: 1.75rem;
    }
    .stats {
        grid-template-columns: 1fr;
    }
    .admin-table {
        font-size: 0.875rem;
    }
    .topbar {
        padding: 0 0.75rem;
    }
    .topbar-link span:not(.sr-only) {
        /* Drop the labels on phones, keep just the icons. */
        display: none;
    }
}

/* ---------- Shared "book" page chrome ----------
   Used by the dashboard, the admin dashboard, and the
   per-team page. Anything specific to one of those pages
   (TOC, CTA, stats grid, table) lives in the page's own
   <style> block; the shared eyebrow + big title + container
   width all live here so the three pages read as one site. */
.book-dashboard {
    max-width: 60rem;
}
.book-hero {
    text-align: center;
    margin: 4rem 0 3.5rem;
}
.book-eyebrow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.85rem;
    margin-bottom: 1.25rem;
}
.book-eyebrow-rule {
    flex: 0 0 4rem;
    height: 1px;
    background-color: var(--color-border);
}
.book-eyebrow-text {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}
.book-title {
    margin: 0 0 0.85rem;
    font-size: 3rem;
    line-height: 1.1;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--color-brand);
}
.book-byline {
    margin: 0;
    font-size: 1rem;
    color: var(--color-text-muted);
    font-style: italic;
}
@media (max-width: 600px) {
    .book-title {
        font-size: 2.2rem;
    }
    .book-hero {
        margin: 2.5rem 0 2.5rem;
    }
    .book-eyebrow-rule {
        flex-basis: 2rem;
    }
}

/* ---------- Section eyebrow ----------
   Small uppercase label with an underline, used as the
   heading of every section on the dashboard, admin, and
   team pages ("Roster", "Recent submissions", "Participants",
   etc.). Lives here so the three pages stay in lockstep. */
.section-eyebrow {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    margin-bottom: 1.25rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--color-border);
}
.section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.25rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--color-border);
    flex-wrap: wrap;
}
.section-head .section-eyebrow,
.exercise-section-head .section-eyebrow {
    margin: 0;
    padding: 0;
    border: 0;
}
.section-meta {
    font-size: 0.85rem;
    color: var(--color-text-muted);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* ---------- Submission card ----------
   Shared markup is in `templates/partials/submission_card.html`,
   included by both `admin.html` and `team.html`. The
   read-only CodeMirror viewer mounts inside `.rust-editor`
   (see `static/js/readonly-rust-editor.js`). */
/* Submissions feed list, shared by `/admin` and the
   per-team pages. Cards themselves are styled below. */
.submission-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 3rem;
}

.submission-card {
    margin: 0;
    padding: 0;
}
.submission-card-head {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin-bottom: 0.6rem;
    flex-wrap: wrap;
}
.submission-card-who {
    font-weight: 600;
    color: var(--color-text);
}
.submission-card-sep {
    color: var(--color-text-muted);
}
.submission-card-exercise {
    font-family: "JetBrains Mono", "SF Mono", Monaco, monospace;
    color: var(--color-primary);
    font-size: 0.92rem;
}
.submission-card-time {
    margin-left: auto;
    color: var(--color-text-muted);
    font-size: 0.85rem;
}
/* The .rust-editor element starts as a styled <pre>-like
   box so the source is readable even if CodeMirror fails
   to load (network blocked or a local chunk missing). Once the
   read-only viewer mounts and adds a `.cm-editor` child,
   we drop our padding/border so the editor's own chrome
   isn't double-wrapped. */
.rust-editor {
    display: block;
    white-space: pre;
    overflow-x: auto;
    max-height: 32rem;
    font-family: "JetBrains Mono", "SF Mono", Monaco, monospace;
    font-size: 0.85rem;
    background: var(--syn-bg, var(--color-surface));
    color: var(--syn-fg, var(--color-text));
    border: 1px solid var(--color-border);
    border-radius: 12px;
    padding: 0.85rem 1rem;
}
.rust-editor:has(.cm-editor) {
    padding: 0;
    background: transparent;
    border: none;
}

/* ---------- Status badges ----------
   Used by the submission feed (admin + team) for the
   pass / perfect / fail glyph at the start of each row. */
.status-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    font-weight: 700;
    font-size: 0.85rem;
    color: #fff;
    flex-shrink: 0;
}
.status-badge-pass {
    background: transparent;
    color: var(--color-success);
    font-size: 1.4rem;
}
.status-badge-perfect {
    background: #f1c40f;
    color: #4a3a00;
}
.status-badge-fail {
    background: transparent;
    color: var(--color-error);
    font-size: 1.4rem;
}

/* ---------- Shared chapter list ---------- */
/* Rendered by `templates/partials/chapter_list.html` on both
   the homepage and every exercise page. One set of styles,
   two consumers. */
.chapter-list {
    margin: 3rem auto 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 0 2rem;
    max-width: 60rem;
}
@media (min-width: 720px) {
    .chapter-list {
        grid-template-columns: 1fr 1fr;
        grid-auto-flow: column;
        grid-template-rows: repeat(var(--chapter-rows, 10), auto);
    }
}
.chapter-row {
    display: grid;
    grid-template-columns: 2.25rem 1fr auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.65rem 0.75rem;
    border-top: 1px solid var(--color-border);
    color: var(--color-primary, #0969da);
    text-decoration: none;
    font-size: 0.95rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    transition: background-color 120ms;
}
.chapter-row:last-child {
    border-bottom: 1px solid var(--color-border);
}
.chapter-row:hover,
.chapter-row:focus-visible {
    background-color: var(--color-background);
}
.chapter-row .chapter-num {
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    font-weight: 500;
}
.chapter-row .chapter-title {
    font-weight: 500;
}
.chapter-row .chapter-mark {
    width: 0.85rem;
    height: 0.85rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: transparent;
    border: 1px solid var(--color-border);
    font-size: 0.95rem;
    line-height: 1;
    color: transparent;
}
.chapter-row.attempted {
    background-color: rgba(125, 125, 125, 0.06);
}
.chapter-row.attempted .chapter-mark {
    background: var(--color-text-muted);
    border-color: var(--color-text-muted);
    opacity: 0.45;
}
.chapter-row.completed {
    background-color: rgba(46, 125, 50, 0.07);
}
.chapter-row.completed .chapter-mark {
    background: transparent;
    border: none;
    color: var(--color-success, #2e7d32);
    opacity: 1;
}
.chapter-row.completed .chapter-mark::before {
    content: "";
    display: inline-block;
    width: 1em;
    height: 1em;
    background-color: currentColor;
    -webkit-mask: url("/static/icons/check.svg") no-repeat center /
        contain;
    mask: url("/static/icons/check.svg") no-repeat center / contain;
}
.chapter-row.perfected {
    background-color: rgba(241, 196, 15, 0.1);
}
.chapter-row.perfected .chapter-mark {
    background: #f1c40f;
    border-color: #f1c40f;
}
.chapter-row.completed:hover,
.chapter-row.completed:focus-visible {
    background-color: rgba(46, 125, 50, 0.13);
}
.chapter-row.perfected:hover,
.chapter-row.perfected:focus-visible {
    background-color: rgba(241, 196, 15, 0.18);
}
.chapter-row.current {
    background-color: var(--color-background);
    color: var(--color-text);
    font-weight: 700;
    box-shadow: inset 3px 0 0 var(--color-primary, #0969da);
}
.chapter-row.current .chapter-num {
    color: var(--color-text);
    font-weight: 700;
}
.chapter-row.current.completed {
    background-color: rgba(46, 125, 50, 0.12);
}
.chapter-row.current.perfected {
    background-color: rgba(241, 196, 15, 0.18);
}
.chapter-row.quiz .chapter-title {
    font-style: italic;
}

/* ---------- Next-chapter CTA ---------- */
/* Rendered by `templates/partials/next_chapter_cta.html` at
   the bottom of exercise pages and the quick tour. Exercise
   pages add `.is-locked` to hide it until the chapter is
   completed (revealed by the run-success hook in
   `exercise.html`); the tour leaves it always visible. */
.next-chapter-cta {
    margin: 3rem auto 0;
    max-width: 32rem;
    text-align: center;
}
.next-chapter-cta.is-locked {
    display: none;
}
.next-chapter-btn {
    display: inline-grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    column-gap: 1rem;
    row-gap: 0.15rem;
    align-items: center;
    text-align: left;
    text-decoration: none;
    padding: 1rem 1.5rem;
    min-height: auto;
    height: auto;
    font-size: 1rem;
}
.next-chapter-btn:hover,
.next-chapter-btn:focus-visible {
    text-decoration: none;
}
.next-chapter-eyebrow {
    grid-column: 1;
    grid-row: 1;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    font-weight: 600;
    opacity: 0.8;
}
.next-chapter-title {
    grid-column: 1;
    grid-row: 2;
    display: inline-flex;
    align-items: baseline;
    gap: 0.55rem;
    font-size: 1.1rem;
    font-weight: 600;
    line-height: 1.2;
}
.next-chapter-num {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
    font-size: 0.95rem;
    font-weight: 600;
    opacity: 0.85;
    font-variant-numeric: tabular-nums;
}
.next-chapter-arrow {
    grid-column: 2;
    grid-row: 1 / span 2;
    font-size: 1.4rem;
    line-height: 1;
    transition: transform 0.15s ease;
}
.next-chapter-btn:hover .next-chapter-arrow,
.next-chapter-btn:focus-visible .next-chapter-arrow {
    transform: translateX(0.2rem);
}

/* ---------- Quiz block (inline on quiz chapters) ---------- */
/* Rendered by `Quiz::render_html` in src/exercises.rs and
   wired up by `static/js/quiz.js`. Lives inside the chapter
   flow alongside prose and code sections, so it inherits the
   page's max-width and surface colours by default. */
.quiz-section {
    margin: 2rem 0 3rem;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}
.quiz-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem 0.9rem;
    border: 1px solid var(--color-border);
    border-radius: 8px;
    background: var(--color-surface, transparent);
    font-size: 0.85rem;
    color: var(--color-text-muted);
}
.quiz-meta strong {
    color: var(--color-text);
    font-variant-numeric: tabular-nums;
}
.quiz-meta-score[hidden] {
    display: none;
}
.quiz-questions {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}
.quiz-card {
    border: 1px solid var(--color-border);
    border-radius: 12px;
    background: var(--color-surface, transparent);
    padding: 1.25rem 1.4rem 1.1rem;
    transition:
        border-color 150ms ease,
        background-color 150ms ease;
}
.quiz-card.is-answered.is-correct {
    border-color: var(--color-success, #2e7d32);
    background: color-mix(
        in srgb,
        var(--color-success, #2e7d32) 6%,
        var(--color-surface, transparent)
    );
}
.quiz-card.is-answered.is-wrong {
    border-color: var(--color-error, #c0392b);
    background: color-mix(
        in srgb,
        var(--color-error, #c0392b) 6%,
        var(--color-surface, transparent)
    );
}
.quiz-card-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    margin-bottom: 0.75rem;
}
.quiz-card-num {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}
.quiz-card-num-total {
    font-weight: 500;
    opacity: 0.7;
    margin-left: 0.35rem;
}
.quiz-card-status {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.quiz-card.is-correct .quiz-card-status {
    color: var(--color-success, #2e7d32);
}
.quiz-card.is-wrong .quiz-card-status {
    color: var(--color-error, #c0392b);
}
.quiz-prompt {
    font-size: 1.05rem;
    line-height: 1.55;
    color: var(--color-text);
}
.quiz-prompt > :first-child {
    margin-top: 0;
}
.quiz-prompt > :last-child {
    margin-bottom: 0;
}
.quiz-prompt code {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
    font-size: 0.92em;
    padding: 0.05em 0.35em;
    border-radius: 4px;
    background: var(--color-background);
    border: 1px solid var(--color-border);
}
.quiz-prompt pre {
    margin: 0.75rem 0 0;
    padding: 0.85rem 1rem;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    overflow-x: auto;
    font-size: 0.85rem;
}
.quiz-prompt pre code {
    padding: 0;
    background: transparent;
    border: 0;
}
.quiz-hint {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    margin: 0.85rem 0 0;
    font-size: 0.88rem;
    color: var(--color-text-muted);
}
.quiz-hint-tag {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-primary, #0969da);
    padding: 0.1rem 0.45rem;
    border: 1px solid
        color-mix(
            in srgb,
            var(--color-primary, #0969da) 40%,
            transparent
        );
    border-radius: 999px;
    flex-shrink: 0;
}
.quiz-hint code {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
    font-size: 0.9em;
}
.quiz-answers {
    list-style: none;
    margin: 1rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    /* Drives the A/B/C/D markers via `counter-increment`
       below, so the server doesn't have to emit them. */
    counter-reset: quiz-answer;
}
.quiz-answer-wrap {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    counter-increment: quiz-answer;
}
.quiz-answer {
    appearance: none;
    display: grid;
    grid-template-columns: 2rem 1fr;
    align-items: baseline;
    gap: 0.75rem;
    width: 100%;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--color-border);
    border-radius: 8px;
    background: var(--color-background);
    color: var(--color-text);
    text-align: left;
    font: inherit;
    font-size: 0.95rem;
    line-height: 1.45;
    cursor: pointer;
    transition:
        border-color 120ms ease,
        background-color 120ms ease,
        color 120ms ease;
}
.quiz-answer:hover:not(:disabled),
.quiz-answer:focus-visible:not(:disabled) {
    border-color: var(--color-primary, #0969da);
    background: color-mix(
        in srgb,
        var(--color-primary, #0969da) 6%,
        var(--color-background)
    );
}
.quiz-answer:disabled {
    cursor: default;
}
.quiz-answer-marker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 999px;
    border: 1px solid var(--color-border);
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}
.quiz-answer-marker::before {
    content: counter(quiz-answer, upper-alpha);
}
.quiz-answer-text code {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
    font-size: 0.9em;
    padding: 0.05em 0.3em;
    border-radius: 3px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
}
/* Reveal state: every answer in an answered card picks up
   a verdict colour. The chosen one gets a bold ring; all
   correct answers get the green check; all wrong choices
   get the red mark. */
.quiz-card.is-answered .quiz-answer {
    opacity: 0.65;
}
.quiz-card.is-answered .quiz-answer.is-correct {
    opacity: 1;
    border-color: var(--color-success, #2e7d32);
    background: color-mix(
        in srgb,
        var(--color-success, #2e7d32) 10%,
        var(--color-background)
    );
}
.quiz-card.is-answered .quiz-answer.is-correct .quiz-answer-marker {
    background: var(--color-success, #2e7d32);
    border-color: var(--color-success, #2e7d32);
    color: #fff;
}
.quiz-card.is-answered .quiz-answer.is-wrong-pick {
    opacity: 1;
    border-color: var(--color-error, #c0392b);
    background: color-mix(
        in srgb,
        var(--color-error, #c0392b) 10%,
        var(--color-background)
    );
}
.quiz-card.is-answered
    .quiz-answer.is-wrong-pick
    .quiz-answer-marker {
    background: var(--color-error, #c0392b);
    border-color: var(--color-error, #c0392b);
    color: #fff;
}
.quiz-card.is-answered .quiz-answer.is-chosen {
    box-shadow: 0 0 0 2px
        color-mix(
            in srgb,
            var(--color-primary, #0969da) 35%,
            transparent
        );
}
.quiz-explanation {
    margin: 0 0 0 2.75rem;
    padding: 0.65rem 0.85rem;
    border-left: 3px solid var(--color-border);
    background: var(--color-background);
    color: var(--color-text-muted);
    font-size: 0.88rem;
    line-height: 1.55;
    border-radius: 0 6px 6px 0;
}
.quiz-explanation[hidden] {
    display: none;
}
.quiz-explanation code {
    font-family:
        "JetBrains Mono", "SF Mono", Monaco, Menlo, Consolas,
        monospace;
    font-size: 0.9em;
    padding: 0.05em 0.3em;
    border-radius: 3px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
}
.quiz-answer-wrap.is-correct .quiz-explanation {
    border-left-color: var(--color-success, #2e7d32);
    color: var(--color-text);
}
.quiz-answer-wrap.is-wrong-pick .quiz-explanation {
    border-left-color: var(--color-error, #c0392b);
    color: var(--color-text);
}
.quiz-footer {
    margin-top: 0.5rem;
    padding: 1.25rem 1.4rem;
    border: 1px solid var(--color-border);
    border-radius: 12px;
    background: var(--color-surface, transparent);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    text-align: center;
}
.quiz-footer[hidden] {
    display: none;
}
.quiz-footer-headline {
    margin: 0;
    font-size: 1.05rem;
    color: var(--color-text);
}
.quiz-footer-headline strong {
    font-variant-numeric: tabular-nums;
}
.quiz-reset {
    font-size: 0.9rem;
}
@media (max-width: 600px) {
    .quiz-card {
        padding: 1rem 1.1rem;
    }
    .quiz-explanation {
        margin-left: 0;
    }
    .quiz-answer {
        grid-template-columns: 1.6rem 1fr;
        gap: 0.55rem;
        padding: 0.65rem 0.75rem;
    }
}

/* ---------- Cheatsheet modal ---------- */
.cheatsheet-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding: 2.5rem 1rem 1rem;
    background: color-mix(in srgb, black 55%, transparent);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}
.cheatsheet-modal[data-open="true"] {
    display: flex;
}
.cheatsheet-modal-dialog {
    position: relative;
    width: min(1280px, 100%);
    max-height: calc(100vh - 3.5rem);
    display: flex;
    flex-direction: column;
    background: var(--color-background);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    box-shadow: 0 30px 80px rgba(0, 0, 0, 0.45);
    overflow: hidden;
}
.cheatsheet-modal-header {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem 1rem;
    border-bottom: 1px solid var(--color-border);
    background: var(--color-surface);
    flex-shrink: 0;
}
.cheatsheet-modal-header h2 {
    margin: 0;
    font-size: 1rem;
}
.cheatsheet-modal-hint {
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--color-text-muted);
}
.cheatsheet-modal-hint kbd {
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 0.72rem;
    background: color-mix(in srgb, currentColor 12%, transparent);
    border: 1px solid
        color-mix(in srgb, currentColor 25%, transparent);
    border-radius: 4px;
    padding: 1px 5px;
}
.cheatsheet-modal-close {
    background: transparent;
    border: 1px solid var(--color-border);
    color: inherit;
    border-radius: 6px;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
}
.cheatsheet-modal-close:hover {
    background: color-mix(in srgb, currentColor 8%, transparent);
}
.cheatsheet-modal-body {
    overflow-y: auto;
    padding: 0.75rem 1.25rem 1.25rem;
    background: var(--color-background);
}
/* Multi-column flow: sections snake across columns and the
   page becomes much denser. CSS columns honour `break-inside:
   avoid` so a single section (heading + table) stays
   together. */
.cheatsheet-modal-body {
    column-width: 380px;
    column-gap: 1.25rem;
}
.cheatsheet-modal-body > h1 {
    column-span: all;
    margin: 0 0 0.4rem;
    font-size: 1.15rem;
}
/* Only the intro paragraph (immediately after the h1) spans
   all columns. In-section paragraphs (e.g. the prose around
   the "What does my closure receive?" table) must stay in
   column flow, otherwise each one forces a span-all break
   and strands the surrounding sections in empty columns. */
.cheatsheet-modal-body > h1 + p {
    column-span: all;
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
    color: var(--color-text-muted);
}
.cheatsheet-modal-body > p {
    margin: 0 0 0.6rem;
    font-size: 0.78rem;
    line-height: 1.45;
    break-inside: avoid;
    /* Keep paragraphs glued to the heading or paragraph
       above so a section never splits across columns. */
    break-before: avoid;
}
.cheatsheet-modal-body > h2 {
    font-size: 0.9rem;
    font-weight: 600;
    margin: 0 0 0.3rem;
    padding-bottom: 0.2rem;
    border-bottom: 1px solid var(--color-border);
    color: var(--color-text);
    break-after: avoid;
}
/* h3 is used for sub-sections (e.g. "What does my closure
   receive?"). Style smaller than h2 and keep it attached to
   the following paragraph/table. */
.cheatsheet-modal-body > h3 {
    font-size: 0.82rem;
    font-weight: 600;
    margin: 0.4rem 0 0.25rem;
    color: var(--color-text);
    break-after: avoid;
    break-inside: avoid;
}
.cheatsheet-modal-body > h2,
.cheatsheet-modal-body > h3,
.cheatsheet-modal-body > table {
    break-inside: avoid;
}
/* Tables follow either an h2/h3 or an intro paragraph; pin
   them to whatever comes before so they don't detach. */
.cheatsheet-modal-body > table {
    break-before: avoid;
}
.cheatsheet-modal-body > table {
    width: 100%;
    border-collapse: collapse;
    margin: 0 0 1rem;
    font-size: 0.78rem;
    table-layout: fixed;
}
.cheatsheet-modal-body > table th,
.cheatsheet-modal-body > table td {
    border: none;
    border-bottom: 1px solid var(--color-border);
    padding: 0.25rem 0.45rem;
    text-align: left;
    vertical-align: top;
    background: transparent;
}
.cheatsheet-modal-body > table th {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
    background: transparent;
}
.cheatsheet-modal-body > table th:first-child,
.cheatsheet-modal-body > table td:first-child {
    width: 45%;
    font-family: "JetBrains Mono", "SF Mono", Monaco, monospace;
    font-size: 0.75rem;
    white-space: normal;
    word-break: break-word;
}
.cheatsheet-modal-body > table td code,
.cheatsheet-modal-body > table th code {
    font-size: inherit;
    padding: 0 2px;
    background: color-mix(
        in srgb,
        var(--color-text) 6%,
        transparent
    );
    border-radius: 3px;
}
.cheatsheet-modal-body > table td:first-child code {
    background: transparent;
    padding: 0;
}
.cheatsheet-modal-body .cheatsheet-loading {
    column-span: all;
    color: var(--color-text-muted);
    font-style: italic;
}
@media (max-width: 640px) {
    .cheatsheet-modal {
        padding: 0.5rem 0.5rem 0.5rem;
    }
    .cheatsheet-modal-dialog {
        max-height: calc(100vh - 1rem);
    }
    .cheatsheet-modal-body {
        column-width: auto;
        columns: 1;
    }
}
