@font-face {
    font-family: 'Quicksand';
    src: url('fonts/Quicksand-VariableFont_wght.ttf');
    unicode-range: U+00-52F, U+1E00-1FFF, U+2200-22FF;
}

@font-face {
    font-family: 'Bravura';
    src: url('fonts/Bravura.woff2') format('woff2');
    font-display: block;
}

/* ---------------------------------------------------------------
   Manuscript design tokens.

   Engraved music on cream paper: ink staves, one oxblood accent;
   green, red, and amber are reserved for answer feedback. Pico stays
   underneath — we retheme it by mapping its variables onto ours.
   The mapping is repeated in each theme block, matching the
   specificity of Pico's own scheme selectors so ours win. */

[data-theme=light],
:root:not([data-theme=dark]) {
    --sf-desk: #e9e5dc;
    --sf-paper: #fdfaf3;
    --sf-ink: #24211d;
    --sf-muted: #736c62;
    --sf-accent: #8f2f3a;
    --sf-on-accent: #ffffff;
    --sf-line: #dcd5c8;
    --sf-grid: rgba(143, 47, 58, 0.22);
    --sf-good: #3f8a5f;
    --sf-good-soft: rgba(63, 138, 95, 0.14);
    --sf-bad: #bc4b3c;
    --sf-bad-soft: rgba(188, 75, 60, 0.12);
    --sf-warn: #ad7c2c;
    --sf-cool: #3f6aa8;
    --sf-shadow: 0 1px 2px rgba(37, 42, 51, 0.06),
        0 6px 20px rgba(37, 42, 51, 0.07);

    --pico-background-color: var(--sf-desk);
    --pico-color: var(--sf-ink);
    --pico-muted-color: var(--sf-muted);
    --pico-muted-border-color: var(--sf-line);
    --pico-primary: var(--sf-accent);
    --pico-primary-background: var(--sf-accent);
    --pico-primary-border: var(--sf-accent);
    --pico-primary-hover: color-mix(in srgb, var(--sf-accent) 85%, var(--sf-ink));
    --pico-primary-hover-background: color-mix(in srgb, var(--sf-accent) 85%, var(--sf-ink));
    --pico-primary-hover-border: color-mix(in srgb, var(--sf-accent) 85%, var(--sf-ink));
    --pico-primary-inverse: var(--sf-on-accent);
    --pico-primary-focus: color-mix(in srgb, var(--sf-accent) 40%, transparent);
    --pico-card-background-color: var(--sf-paper);
    --pico-card-border-color: var(--sf-line);
    --pico-card-box-shadow: var(--sf-shadow);
    --pico-form-element-background-color: var(--sf-paper);
    --pico-form-element-border-color: var(--sf-line);
    --pico-form-element-active-border-color: var(--sf-accent);
    --pico-form-element-focus-color: color-mix(in srgb, var(--sf-accent) 40%, transparent);
    --pico-form-element-color: var(--sf-ink);
    --pico-border-radius: 10px;
}

@media only screen and (prefers-color-scheme: dark) {
    :root:not([data-theme=light]) {
        --sf-desk: #16141a;
        --sf-paper: #211e24;
        --sf-ink: #ece6dc;
        --sf-muted: #a39b90;
        --sf-accent: #e3909a;
        --sf-on-accent: #2a1418;
        --sf-line: #38333b;
        --sf-grid: rgba(227, 144, 154, 0.28);
        --sf-good: #6cba8d;
        --sf-good-soft: rgba(108, 186, 141, 0.16);
        --sf-bad: #dd8272;
        --sf-bad-soft: rgba(221, 130, 114, 0.14);
        --sf-warn: #d2a558;
        --sf-cool: #8eaee0;
        --sf-shadow: 0 1px 2px rgba(0, 0, 0, 0.4),
            0 8px 24px rgba(0, 0, 0, 0.35);

        --pico-background-color: var(--sf-desk);
        --pico-color: var(--sf-ink);
        --pico-muted-color: var(--sf-muted);
        --pico-muted-border-color: var(--sf-line);
        --pico-primary: var(--sf-accent);
        --pico-primary-background: var(--sf-accent);
        --pico-primary-border: var(--sf-accent);
        --pico-primary-hover: color-mix(in srgb, var(--sf-accent) 85%, #ffffff);
        --pico-primary-hover-background: color-mix(in srgb, var(--sf-accent) 85%, #ffffff);
        --pico-primary-hover-border: color-mix(in srgb, var(--sf-accent) 85%, #ffffff);
        --pico-primary-inverse: var(--sf-on-accent);
        --pico-primary-focus: color-mix(in srgb, var(--sf-accent) 40%, transparent);
        --pico-card-background-color: var(--sf-paper);
        --pico-card-border-color: var(--sf-line);
        --pico-card-box-shadow: var(--sf-shadow);
        --pico-form-element-background-color: var(--sf-paper);
        --pico-form-element-border-color: var(--sf-line);
        --pico-form-element-active-border-color: var(--sf-accent);
        --pico-form-element-focus-color: color-mix(in srgb, var(--sf-accent) 40%, transparent);
        --pico-form-element-color: var(--sf-ink);
        --pico-border-radius: 10px;
    }
}

[data-theme=dark] {
    --sf-desk: #16141a;
    --sf-paper: #211e24;
    --sf-ink: #ece6dc;
    --sf-muted: #a39b90;
    --sf-accent: #e3909a;
    --sf-on-accent: #2a1418;
    --sf-line: #38333b;
    --sf-grid: rgba(227, 144, 154, 0.28);
    --sf-good: #6cba8d;
    --sf-good-soft: rgba(108, 186, 141, 0.16);
    --sf-bad: #dd8272;
    --sf-bad-soft: rgba(221, 130, 114, 0.14);
    --sf-warn: #d2a558;
    --sf-cool: #8eaee0;
    --sf-shadow: 0 1px 2px rgba(0, 0, 0, 0.4),
        0 8px 24px rgba(0, 0, 0, 0.35);

    --pico-background-color: var(--sf-desk);
    --pico-color: var(--sf-ink);
    --pico-muted-color: var(--sf-muted);
    --pico-muted-border-color: var(--sf-line);
    --pico-primary: var(--sf-accent);
    --pico-primary-background: var(--sf-accent);
    --pico-primary-border: var(--sf-accent);
    --pico-primary-hover: color-mix(in srgb, var(--sf-accent) 85%, #ffffff);
    --pico-primary-hover-background: color-mix(in srgb, var(--sf-accent) 85%, #ffffff);
    --pico-primary-hover-border: color-mix(in srgb, var(--sf-accent) 85%, #ffffff);
    --pico-primary-inverse: var(--sf-on-accent);
    --pico-primary-focus: color-mix(in srgb, var(--sf-accent) 40%, transparent);
    --pico-card-background-color: var(--sf-paper);
    --pico-card-border-color: var(--sf-line);
    --pico-card-box-shadow: var(--sf-shadow);
    --pico-form-element-background-color: var(--sf-paper);
    --pico-form-element-border-color: var(--sf-line);
    --pico-form-element-active-border-color: var(--sf-accent);
    --pico-form-element-focus-color: color-mix(in srgb, var(--sf-accent) 40%, transparent);
    --pico-form-element-color: var(--sf-ink);
    --pico-border-radius: 10px;
}

/* ---------------------------------------------------------------
   Base */

body {
    font-family: 'Quicksand', sans-serif;
    font-weight: 450;
}

h1, h2, h3, h4, h5, h6 {
    color: var(--sf-ink);
    font-weight: 650;
}

article {
    max-width: 650px;
    position: relative;
    border: 1px solid var(--sf-line);
}

/* ---------------------------------------------------------------
   Header */

.brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    text-decoration: none;
}

.logo-mark {
    width: 32px;
    height: 32px;
    flex: none;
    border: 1.5px solid var(--sf-accent);
    border-radius: 8px;
    display: grid;
    place-items: center;
    overflow: hidden;
    color: var(--sf-accent);
    background: var(--sf-paper);
}

.logo-mark .smufl {
    font-size: 17px;
    line-height: 1;
    translate: 0 4px;
}

/* ---------------------------------------------------------------
   Quiz cards */

.quiz-shell {
    text-align: center;
}

/* text-align doesn't center the block-level card itself. */
.quiz-shell article,
.quiz-shell .feedback {
    margin-inline: auto;
}

.quiz-kind {
    font-size: 0.72rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sf-muted);
    font-weight: 650;
    margin-bottom: 1.25rem;
}

.count {
    position: absolute;
    top: 16px;
    right: 16px;
    font-size: 0.75rem;
    font-weight: 650;
    color: var(--sf-accent);
    background: color-mix(in srgb, var(--sf-accent) 12%, transparent);
    border-radius: 99px;
    padding: 2px 10px;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------
   Answer buttons (interval and key quizzes). quiz.js adds
   .green/.red as it grades. */

.answer-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.6rem;
    margin-top: 1rem;
}

button.answer {
    margin: 0;
    background: var(--sf-paper);
    color: var(--sf-ink);
    border: 1px solid var(--sf-line);
    box-shadow: none;
    }

button.answer:hover:not(:disabled) {
    border-color: var(--sf-accent);
}

button.answer.green {
    background: var(--sf-good-soft);
    border-color: var(--sf-good);
    color: var(--sf-good);
    box-shadow: none;
}

button.answer.red {
    background: var(--sf-bad-soft);
    border-color: var(--sf-bad);
    color: var(--sf-bad);
    box-shadow: none;
}

/* Once the quiz resolves the answers disable; keep the verdict
   colors at full strength and fade only the rest. */
button.answer:disabled {
    opacity: 0.45;
}

button.answer.green:disabled,
button.answer.red:disabled {
    opacity: 1;
}

/* Applied to every answer once the quiz resolves. */
button.grey {
    opacity: 0.45;
    box-shadow: none;
}

input.green {
    background: var(--sf-good-soft);
    border-color: var(--sf-good);
    box-shadow: none;
}

input.red {
    background: var(--sf-bad-soft);
    border-color: var(--sf-bad);
    box-shadow: none;
}

/* ---------------------------------------------------------------
   FSRS feedback bar: a colored top rule ranks the four buttons,
   with the scheduled interval underneath. */

.feedback {
    max-width: 650px;
    margin-top: 0.75rem;
    gap: 0.5rem;
}

.feedback button {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    padding: 0.5rem 0.25rem 0.45rem;
    background: var(--sf-paper);
    color: var(--sf-ink);
    border: 1px solid var(--sf-line);
    border-top: 3px solid var(--srs-hue, var(--sf-line));
    box-shadow: none;
    font-weight: 650;
    font-size: 0.95rem;
    line-height: 1.2;
}

.feedback button:hover {
    border-color: var(--srs-hue, var(--sf-accent));
    background: var(--sf-paper);
    color: var(--sf-ink);
}

.feedback button small {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--sf-muted);
    font-variant-numeric: tabular-nums;
}

.srs-again { --srs-hue: var(--sf-bad); }
.srs-hard  { --srs-hue: var(--sf-warn); }
.srs-good  { --srs-hue: var(--sf-good); }
.srs-easy  { --srs-hue: var(--sf-cool); }
.srs-retest { --srs-hue: var(--sf-muted); }

/* ---------------------------------------------------------------
   Loading state: while htmx has a request in flight it flags #quiz
   (our hx-indicator), so dim the outgoing card and float a spinner.
   The delays keep fast swaps from flickering. */

#quiz {
    position: relative;
}

#quiz.htmx-request {
    pointer-events: none;
}

#quiz.htmx-request > * {
    opacity: 0.45;
    transition: opacity 0.15s ease 0.15s;
}

#quiz.htmx-request::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 30px;
    height: 30px;
    margin: -15px;
    border: 3px solid var(--sf-grid);
    border-top-color: var(--sf-accent);
    border-radius: 50%;
    opacity: 0;
    animation: hf-appear 0.15s ease 0.2s forwards,
        hf-spin 0.8s linear infinite;
}

@keyframes hf-appear {
    to { opacity: 1; }
}

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

@media (prefers-reduced-motion: reduce) {
    #quiz.htmx-request::after {
        animation: hf-appear 0.15s ease 0.2s forwards;
        border-color: var(--sf-accent);
    }
}

/* ---------------------------------------------------------------
   Stats page */

.stat-chips {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 0.75rem;
    margin-bottom: 1.5rem;
}

.stat-chip {
    background: var(--sf-paper);
    border: 1px solid var(--sf-line);
    border-radius: 10px;
    padding: 0.75rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}

.stat-chip strong {
    font-size: 1.5rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

.stat-chip strong small {
    font-size: 0.9rem;
    color: var(--sf-muted);
}

.stat-chip span {
    font-size: 0.78rem;
    color: var(--sf-muted);
}

.stats-card h2 {
    font-size: 0.72rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sf-muted);
    font-weight: 650;
    margin-bottom: 1rem;
}

.heatmap-scroll {
    overflow-x: auto;
    padding-bottom: 0.25rem;
}

.heatmap {
    display: grid;
    grid-template-rows: repeat(7, 9px);
    grid-auto-flow: column;
    grid-auto-columns: 9px;
    gap: 2px;
    width: max-content;
}

.hm {
    width: 9px;
    height: 9px;
    border-radius: 2px;
    background: color-mix(in srgb, var(--sf-ink) 7%, transparent);
}

.hm-future { background: transparent; }
.hm-1 { background: color-mix(in srgb, var(--sf-accent) 25%, transparent); }
.hm-2 { background: color-mix(in srgb, var(--sf-accent) 50%, transparent); }
.hm-3 { background: color-mix(in srgb, var(--sf-accent) 75%, transparent); }
.hm-4 { background: var(--sf-accent); }

.heatmap-months {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 11px;
    font-size: 0.6rem;
    color: var(--sf-muted);
    height: 1rem;
    width: max-content;
}

.heatmap-months span {
    overflow: visible;
    white-space: nowrap;
}

.heatmap-legend {
    display: flex;
    align-items: center;
    gap: 3px;
    margin-top: 0.5rem;
    font-size: 0.65rem;
    color: var(--sf-muted);
}

.chart {
    width: 100%;
    height: auto;
}

.chart .gridline {
    stroke: color-mix(in srgb, var(--sf-ink) 8%, transparent);
    stroke-dasharray: 3 3;
}

.chart .axis {
    stroke: var(--sf-line);
}

.chart .tick {
    fill: var(--sf-muted);
    font-size: 9px;
    font-family: inherit;
    font-variant-numeric: tabular-nums;
}

.chart .line {
    fill: none;
    stroke: var(--sf-accent);
    stroke-width: 1.8;
    stroke-linejoin: round;
}

.chart .area {
    fill: color-mix(in srgb, var(--sf-accent) 14%, transparent);
    stroke: none;
}

.chart .bar {
    fill: color-mix(in srgb, var(--sf-accent) 55%, transparent);
}

.chart .bar-lapse {
    fill: color-mix(in srgb, var(--sf-bad) 65%, transparent);
}

.chart .bar-overdue {
    fill: color-mix(in srgb, var(--sf-warn) 75%, transparent);
}

.chart-note {
    font-size: 0.8rem;
    color: var(--sf-muted);
    margin: 0.5rem 0 0;
}

.hard-list {
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.hard-list li {
    list-style: none;
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
}

.hard-glyph {
    font-size: 1.6rem;
    min-width: 3.5rem;
}

.hard-detail {
    font-size: 0.85rem;
    color: var(--sf-muted);
}

.logout-form {
    margin-bottom: 0;
}

/* Off-screen but still read by screen readers; for labels whose
   meaning is visually obvious from the quiz layout. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

[hidden] {
    display: none !important;
}

/* ---------------------------------------------------------------
   Notation. Bravura draws every glyph; its em is four staff spaces,
   and score.py lays out in a 10-unit space, so 40 units per em. */

.smufl {
    font-family: 'Bravura';
    font-weight: normal;
    font-style: normal;
}

.score {
    display: block;
    inline-size: 100%;
    max-inline-size: calc(var(--score-width) * 1.7px);
    margin: 0 auto 0.75rem;
    overflow: visible;
}

.score text {
    font-size: 40px;
    fill: var(--sf-ink);
}

.score line {
    stroke: var(--sf-ink);
    stroke-linecap: butt;
}

.score .staff-line { stroke-width: 1.1; stroke: color-mix(in srgb, var(--sf-ink) 75%, transparent); }
.score .ledger { stroke-width: 1.6; }
.score .barline { stroke-width: 1.4; }
.score .stem { stroke-width: 1.2; }

/* Note states: the drill's cursor, and verdicts. */
.score .current { fill: var(--sf-accent); stroke: var(--sf-accent); }
.score .played { fill: var(--sf-good); stroke: var(--sf-good); }
.score .missed { fill: var(--sf-bad); stroke: var(--sf-bad); }
.score .played.missed { fill: var(--sf-warn); stroke: var(--sf-warn); }
#card.right .score .note { fill: var(--sf-good); }
#card.missed .score .note { fill: var(--sf-bad); }

.answer-name {
    font-size: 1.35rem;
    font-weight: 650;
    letter-spacing: 0.02em;
    margin-bottom: 0.5rem;
}

.verdict {
    font-weight: 600;
    min-block-size: 1.5em;
    margin-bottom: 0.25rem;
}

#card.right .verdict { color: var(--sf-good); }
#card.missed .verdict { color: var(--sf-bad); }

.teaching {
    text-align: left;
    max-inline-size: 46ch;
    margin: 0.75rem auto 1rem;
    padding-inline-start: 1.1rem;
    font-size: 0.92rem;
    color: var(--sf-muted);
}

.teaching li {
    margin-bottom: 0.35rem;
}

.hint {
    font-size: 0.85rem;
    color: var(--sf-muted);
    margin-bottom: 0.75rem;
}

/* The rating quiz.js suggests, which space accepts. */
.feedback button.suggested {
    background: color-mix(in srgb, var(--srs-hue) 14%, var(--sf-paper));
    border-color: var(--srs-hue);
    outline: 2px solid var(--srs-hue);
    outline-offset: 1px;
}

/* ---------------------------------------------------------------
   The on-screen piano. Black keys position themselves from the
   count of white keys to their left (--i), so the markup stays a
   flat list. */

.piano-scroll {
    overflow-x: auto;
    max-inline-size: 650px;
    margin: 1rem auto 0;
    padding-bottom: 0.25rem;
    overscroll-behavior-x: contain;
}

.piano {
    --wk: calc(100% / var(--whites));
    position: relative;
    isolation: isolate;
    display: flex;
    min-inline-size: calc(var(--whites) * 20px);
    block-size: 7.5rem;
    user-select: none;
    touch-action: manipulation;
}

.piano .key {
    all: unset;
    box-sizing: border-box;
    cursor: pointer;
    transition: background-color 0.08s;
}

.piano .white {
    flex: 1;
    display: flex;
    align-items: end;
    justify-content: center;
    padding-bottom: 0.3rem;
    background: var(--sf-paper);
    border: 1px solid var(--sf-line);
    border-inline-start-width: 0;
    border-radius: 0 0 5px 5px;
    font-size: 0.55rem;
    font-weight: 650;
    color: var(--sf-muted);
}

.piano .white:first-child {
    border-inline-start-width: 1px;
}

.piano .black {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: calc(var(--i) * var(--wk) - var(--wk) * 0.3);
    inline-size: calc(var(--wk) * 0.6);
    block-size: 62%;
    z-index: 1;
    background: var(--sf-ink);
    border-radius: 0 0 4px 4px;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme=light]) .piano .black {
        background: #08070a;
        border: 1px solid var(--sf-line);
    }
}

.piano .white.pressed { background: color-mix(in srgb, var(--sf-ink) 12%, var(--sf-paper)); }
.piano .black.pressed { background: color-mix(in srgb, var(--sf-ink) 70%, var(--sf-paper)); }
.piano .white.target { background: color-mix(in srgb, var(--sf-good) 35%, var(--sf-paper)); }
.piano .black.target { background: var(--sf-good); }
.piano .white.wrong { background: color-mix(in srgb, var(--sf-bad) 35%, var(--sf-paper)); }
.piano .black.wrong { background: var(--sf-bad); }

.input-status {
    font-size: 0.78rem;
    color: var(--sf-muted);
    margin-top: 0.4rem;
}

/* ---------------------------------------------------------------
   Drill */

.drill-clefs {
    display: flex;
    justify-content: center;
    gap: 1.25rem;
    margin-bottom: 1rem;
    font-weight: 650;
}

.drill-clefs a[aria-current] {
    text-decoration: underline;
    text-underline-offset: 0.3em;
}

.hard-glyph small {
    font-size: 0.9rem;
    color: var(--sf-muted);
}
