/* Fret Naught -- one stylesheet, no framework, no build step. */

:root {
  color-scheme: light dark;

  --bg:        #f6f5f2;
  --surface:   #ffffff;
  --surface-2: #eeece7;
  --line:      #d9d6cf;
  --line-soft: #e6e3dc;
  --text:      #24231f;
  --muted:     #6b6961;
  --faint:     #9a978e;

  --root:      #c0562a;   /* chord/scale root */
  --tone:      #2f7d68;   /* other members */
  --root-ink:  #ffffff;
  --tone-ink:  #ffffff;

  --danger:    #a8322c;
  --ok:        #2f7d68;

  /* CAGED: the colours of the usual diagrams, so a chart and this neck read
     the same. Ink is whatever reads on top of each. */
  --cg-c: #d9423b;  --cg-c-ink: #ffffff;
  --cg-a: #2d5fd3;  --cg-a-ink: #ffffff;
  --cg-g: #1fa3c0;  --cg-g-ink: #0d2a31;
  --cg-e: #2a9448;  --cg-e-ink: #ffffff;
  --cg-d: #e3aa12;  --cg-d-ink: #2b2104;
  --cg-plain: #2e2d29; --cg-plain-ink: #ffffff;

  --radius: 9px;
  --gap: 1rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #15161a;
    --surface:   #1d1f24;
    --surface-2: #24262c;
    --line:      #33363e;
    --line-soft: #2a2d34;
    --text:      #e7e7e4;
    --muted:     #9b9a94;
    --faint:     #6e6d68;

    --root:      #d8814d;
    --tone:      #4fae90;
    --root-ink:  #16171a;
    --tone-ink:  #12201c;

    --danger:    #e0716b;
    --ok:        #4fae90;

    --cg-c: #ec6b63;  --cg-c-ink: #1a0a09;
    --cg-a: #6f93f0;  --cg-a-ink: #0b1430;
    --cg-g: #4cc3dc;  --cg-g-ink: #0b2429;
    --cg-e: #5cc27a;  --cg-e-ink: #0c2213;
    --cg-d: #f0c445;  --cg-d-ink: #2b2104;
    --cg-plain: #d9d8d3; --cg-plain-ink: #16171a;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}

/* ---------- top bar ---------- */

.topbar {
  display: flex;
  align-items: center;
  gap: var(--gap);
  padding: .7rem 1.1rem;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
  flex-wrap: wrap;
}

.brand { font-weight: 600; letter-spacing: .01em; }

.tabs { display: flex; gap: .35rem; }

.tab {
  font: inherit;
  padding: .35rem .8rem;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.tab:hover { color: var(--text); }
.tab[aria-current="page"] {
  background: var(--surface-2);
  border-color: var(--line);
  color: var(--text);
}

.status { margin-left: auto; font-size: .8rem; color: var(--muted); }
/* The instrument is app-wide, so it lives in the bar, beside the stamp. */
.instrument-switch { margin-left: auto; }
.instrument-switch + .status { margin-left: 0; }
.status::before {
  content: "";
  display: inline-block;
  width: .5rem; height: .5rem;
  border-radius: 50%;
  margin-right: .4rem;
  background: var(--faint);
  vertical-align: middle;
}
.status.ok::before  { background: var(--ok); }
.status.bad::before { background: var(--danger); }

/* ---------- layout ---------- */

main { max-width: 1180px; margin: 0 auto; padding: 1.2rem 1.1rem 4rem; }

/* A utility class, and the one place !important is the right tool: it has to
   beat whatever display the element already had. Without it `.hidden` only
   worked on the three selectors that spelled it out, so every other element
   toggling the class stayed on screen -- empty, but there. */
.hidden { display: none !important; }
.view.hidden { display: none; }

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: .7rem;
  align-items: flex-end;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .9rem 1rem;
}

.field { display: flex; flex-direction: column; gap: .25rem; min-width: 7rem; }
/* 14rem fitted four controls; the Scale/Mode split makes five, so the
   basis has to come down or the fret inputs wrap onto their own line. */
.field.grow { flex: 1 1 10.5rem; }
.field.narrow { min-width: 5.5rem; max-width: 6.5rem; }
.field > span { font-size: .74rem; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
/* In a row that mixes titled fields with plain buttons and chips, the title
   used to be part of the field's height, so centring the row centred the
   title+control block and the control sat low. Here the title floats above
   its control and takes no height: every control in the row shares one
   centre line, and the row reserves room on top for the titles. */
.lift-labels { row-gap: 1.7rem; }
.lift-labels .field { position: relative; }
.lift-labels .field > span { position: absolute; bottom: calc(100% + .22rem); left: 0; white-space: nowrap; }
.timer-bar.lift-labels, .metro-bar.lift-labels { padding-top: 1.75rem; }
.toggles.lift-labels { margin-top: 1.5rem; }
/* A control that is still usable but is not driving the current view. This was
   styled only for .field
   for a long while, so every .check and .chips row that toggled it stayed at
   full strength -- the same trap .hidden fell into. It is a utility now. */
.inactive { opacity: .42; }
/* A control that has nothing to do right now (subdivision in 7/8). */
.segmented.inactive { pointer-events: none; }

select, input[type="number"] {
  font: inherit;
  padding: .45rem .55rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  width: 100%;
}

.toggles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .7rem;
  margin: .9rem 0 .2rem;
}

.segmented { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.segmented button {
  font: inherit;
  font-size: .88rem;
  padding: .32rem .8rem;
  border: 0;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
}
.segmented button + button { border-left: 1px solid var(--line); }
.segmented button.on { background: var(--surface-2); color: var(--text); font-weight: 500; }

.ghost {
  font: inherit; font-size: .88rem;
  padding: .32rem .8rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
}
.ghost:hover { color: var(--text); }

.hint { margin: 0; font-size: .82rem; color: var(--muted); }

.toggle-label {
  font-size: .74rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted);
}

.chip.toggle.off {
  opacity: .45;
  background: transparent;
  border-style: dashed;
}
.chip.toggle.off .deg { color: var(--faint); }

.chip.preset { font-size: .82rem; background: transparent; }

.grip-chip { flex-direction: column; align-items: center; gap: 0; min-width: 3.1rem; padding: .25rem .4rem; }
.grip-chip .grip-fret { font-size: 1.05rem; font-weight: 600; line-height: 1.2; }
.grip-chip .deg { font-size: .66rem; letter-spacing: .02em; }
.grip-chip:disabled { opacity: .55; }
.preset-row { margin-top: .55rem; }
.error { min-height: 1.3rem; margin: .5rem 0 0; color: var(--danger); font-size: .9rem; }

.scale-title { font-size: 1.45rem; font-weight: 600; margin: 1rem 0 .1rem; }
.scale-sub { margin: 0 0 .9rem; color: var(--muted); font-size: .92rem; }

/* ---------- fretboard ---------- */

.board-wrap {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .6rem .3rem;
  overflow-x: auto;
}
.board-wrap svg { display: block; }

.fb-string   { stroke: var(--line); stroke-width: 1.4; }
.fb-string.on { stroke: var(--root); stroke-width: 3.2; }

/* ---- circle of fifths ---- */
.cof-wrap {
  display: flex; justify-content: center;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: .4rem; margin-top: .6rem;
}
.cof { max-width: 100%; height: auto; }
/* Each slot gets its own hue (set per cell as --h); the rings share it, the
   inner rings a little deeper, so a slot reads as one column. */
.cof-major .cof-fill { fill: hsl(var(--h) 70% 86%); }
.cof-minor .cof-fill { fill: hsl(var(--h) 45% 76%); }
.cof-dim .cof-fill   { fill: hsl(var(--h) 25% 64%); }
.cof-fill { stroke: var(--surface); stroke-width: 1.2; }
.cof-cell.clickable { cursor: pointer; }
.cof-cell.clickable:hover .cof-fill { filter: brightness(1.05) saturate(1.15); }
/* Outside the selected key the circle steps back, so the key's block reads. */
.cof-cell:not(.in-key) { opacity: .62; }
.cof-borders { pointer-events: none; }
/* The key's chords: thin white lines between them, equal on every side. */
.cof-sep { fill: none; stroke: #ffffff; stroke-width: 2; stroke-linejoin: round; opacity: .9; }
.cof-family { fill: none; stroke: #26251f; stroke-width: 4; stroke-linejoin: round; }
/* Home (the mode's I or i): a solid box inset in the cell, always shown.
   The chord picked for the neck: a dashed box nearer the edge. */
.cof-home { fill: none; stroke: var(--root); stroke-width: 2.4; stroke-linejoin: round; }
.cof-focus { fill: none; stroke: var(--root); stroke-width: 2.6; stroke-dasharray: 7 4; stroke-linejoin: round; }
.cof-name { font-weight: 700; text-anchor: middle; fill: #1d1c18; pointer-events: none; }
.cof-notes { text-anchor: middle; fill: #3a3934; pointer-events: none; }
.cof-numeral { font-weight: 700; text-anchor: middle; fill: #7a2f12; pointer-events: none; }
.cof-mode { font-style: italic; text-anchor: middle; fill: #2d2c27; pointer-events: none; }
/* Label sizes are set by circlefifths.js, which fits them to each cell. */
/* The giveaway chord: its numeral filled, like a tag. */
.cof-give-pill { fill: var(--root); pointer-events: none; }
.cof-numeral.give { fill: #ffffff; }
#cf-chords .chip.giveaway .num { background: var(--root); color: #ffffff; border-radius: 999px; padding: 0 .4em; }
#cf-chords .chip.giveaway.on .num { background: #ffffff; color: var(--root); }
.cof-hub { fill: var(--surface); stroke: var(--line); }
.cof-hub-text { font-size: 14px; font-weight: 700; text-anchor: middle; fill: var(--text); }
.cof-staff { stroke: var(--muted); stroke-width: 1; }
.cof-acc { font-size: 14px; text-anchor: middle; fill: var(--text); }
.cof-sig-label { font-size: 10px; letter-spacing: .06em; text-anchor: middle; fill: var(--muted); font-weight: 600; }
.cof-sig-hit { fill: transparent; }
.cof-sig.clickable { cursor: pointer; }
.cof-sig.clickable:hover .cof-staff { stroke: var(--text); }
.cof-summary { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-top: var(--gap); }
.cof-summary .scale-title { margin: 0; }
.cof-panels { margin-top: .6rem; }
/* Order | Home | (empty): the Home chips stay centred under the circle and
   the Order switch sits in the space to their left. */
.cof-home-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: 1rem; margin: .9rem 0 .2rem; }
.cof-home-row .toggles { margin: 0; flex-wrap: nowrap; }
.cof-order { justify-self: end; }
.cof-home-group { grid-column: 2; }
@media (max-width: 1180px) {
  .cof-home-row { display: flex; flex-wrap: wrap; justify-content: center; row-gap: .5rem; }
  .cof-home-row .toggles { flex-wrap: wrap; justify-content: center; }
}
#cf-home .chip { display: inline-flex; flex-direction: column; align-items: center; line-height: 1.15; min-width: 4.7rem; }
#cf-home .chip .deg { font-size: .68rem; color: var(--muted); margin-top: .1rem; }
#cf-home .chip.on .deg { color: inherit; opacity: .85; }
.cof-giveaway { text-align: center; margin-top: .1rem; }
.chip.cf-chord .num { font-size: .72rem; color: var(--muted); font-weight: 700; margin-right: .15rem; }
.chip.cf-chord.on .num { color: inherit; }
.cof-showing { font-size: 1.02rem; }
@media (prefers-color-scheme: dark) {
  .cof-major .cof-fill { fill: hsl(var(--h) 40% 34%); }
  .cof-minor .cof-fill { fill: hsl(var(--h) 30% 27%); }
  .cof-dim .cof-fill   { fill: hsl(var(--h) 18% 21%); }
  .cof-name { fill: #f1f0ec; }
  .cof-notes, .cof-mode { fill: #d6d4cd; }
  .cof-numeral { fill: #f0a77e; }
  .cof-family { stroke: #f1f0ec; }
  .cof-sep { stroke: #f1f0ec; opacity: .55; }
}

/* ---- the pitch ring ---- */
.ring-wrap {
  display: flex; justify-content: center;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: .6rem; margin-top: var(--gap);
}
.pitch-ring { max-width: 100%; height: auto; }
.pr-track { fill: none; stroke: var(--line); stroke-width: 2; }
.pr-spoke { stroke: var(--root); stroke-width: 2; opacity: .5; }
.pr-dot { fill: var(--surface-2); stroke: var(--line); stroke-width: 1.5; }
.pr-node.clickable { cursor: pointer; }
.pr-node.clickable:hover .pr-dot { stroke: var(--muted); }
.pr-node.ref .pr-dot, .pr-node.start .pr-dot { fill: var(--root); stroke: var(--root); }
.pr-node.ref .pr-name, .pr-node.start .pr-name { fill: var(--root-ink); }
.pr-node.good .pr-dot { fill: var(--ok); stroke: var(--ok); }
.pr-node.good .pr-name { fill: #fff; }
.pr-node.bad .pr-dot { fill: var(--danger); stroke: var(--danger); }
.pr-node.bad .pr-name { fill: #fff; }
.pr-name { font-size: 15px; font-weight: 600; text-anchor: middle; fill: var(--text); pointer-events: none; }
.pr-name.small { font-size: 11.5px; }
.pr-num { font-size: 13px; font-weight: 600; text-anchor: middle; fill: var(--muted); pointer-events: none; }
.pr-rel { font-size: 12px; font-weight: 600; text-anchor: middle; fill: var(--text); pointer-events: none; }
.pr-int { font-size: 11.5px; text-anchor: middle; fill: var(--tone); font-weight: 600; pointer-events: none; }
.pr-hub { font-size: 14px; text-anchor: middle; fill: var(--muted); }

/* ---- the neck game ---- */
.fb-extra { pointer-events: none; }
.fb-extra-label, .kb-extra-label { font-size: 11px; font-weight: 600; text-anchor: middle; }
.kb-extra { pointer-events: none; }
.game-wrong .fb-extra-dot, .game-wrong .kb-extra-dot { fill: var(--danger); }
.game-wrong .fb-extra-label, .game-wrong .kb-extra-label { fill: #fff; }
.game-hint .fb-extra-dot, .game-hint .kb-extra-dot {
  fill: none; stroke: var(--root); stroke-width: 2; stroke-dasharray: 3 3; opacity: .9;
}
.game-found .fb-extra-dot, .game-found .kb-extra-dot { fill: var(--tone); }
.game-found .fb-extra-label, .game-found .kb-extra-label { fill: var(--tone-ink); }
/* Naming (guitar sprint): the lit place, and the answer shown after a skip. */
.game-target .fb-extra-dot, .game-target .kb-extra-dot {
  fill: var(--root); stroke: var(--surface); stroke-width: 2;
}
.game-skipped .fb-extra-dot, .game-skipped .kb-extra-dot { fill: var(--muted); }
.game-skipped .fb-extra-label, .game-skipped .kb-extra-label { fill: #fff; }

/* The answer pad: one octave shaped like piano keys. Its colours are fixed,
   not themed, like the keyboard's own keys (a themed key renders as a
   negative in dark mode). */
.note-pad { position: relative; width: min(420px, 100%); height: 118px; margin: .9rem auto .2rem; }
.pad-key {
  position: absolute; top: 0; box-sizing: border-box; padding: 0 0 .45rem;
  display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
  font: inherit; font-weight: 700; cursor: pointer; border-radius: 0 0 7px 7px;
  transition: background-color .12s, transform .06s;
}
.pad-key:active { transform: translateY(1px); }
.pad-key.white {
  width: calc(100% / 7 - 3px); height: 118px; margin-left: 1.5px;
  background: #f7f6f2; color: #1d1c18; border: 1px solid #b9b7af; font-size: 1.05rem;
}
.pad-key.black {
  width: 12%; height: 72px; z-index: 2; padding-bottom: .35rem;
  background: #26251f; color: #f1f0ec; border: 1px solid #111; font-size: .8rem; line-height: 1.2;
}
.pad-key.white:hover { background: #ecebe5; }
.pad-key.black:hover { background: #3a3931; }
.pad-key:focus-visible { outline: 2px solid var(--root); outline-offset: 2px; }
.pad-key.right { background: var(--ok) !important; color: #fff !important; }
.pad-key.wrong { background: var(--danger) !important; color: #fff !important; }
.game-stats { display: flex; gap: 1.2rem; justify-content: center; flex-wrap: wrap;
  font-size: .9rem; color: var(--muted); margin-top: .3rem; }
.game-stats strong { color: var(--text); font-size: 1.05rem; }
.game-flash { min-height: 1.3em; font-weight: 600; }
.game-flash.good { color: var(--ok); }
.game-flash.bad { color: var(--danger); }
.fb-fret     { stroke: var(--line-soft); stroke-width: 1.2; }
.fb-nut      { stroke: var(--text); stroke-width: 4; stroke-linecap: round; }
.fb-inlay    { fill: var(--line); }
.fb-fretnum  { fill: var(--faint); font-size: 11px; text-anchor: middle; }
.fb-open     { fill: var(--muted); font-size: 11px; text-anchor: end; }

.fb-dot            { fill: var(--tone); stroke: none; }
.fb-dot.is-root    { fill: var(--root); }
.fb-dot.is-open    { fill: none; stroke: var(--tone); stroke-width: 2; }
.fb-dot.is-open.is-root { stroke: var(--root); }

.fb-ghost          { fill: transparent; stroke: var(--line); stroke-width: 1; stroke-dasharray: 2 2; }
.fb-ghost:hover    { stroke: var(--muted); fill: var(--surface-2); }
.fb-ghost-label    { fill: var(--faint); font-size: 10px; text-anchor: middle; pointer-events: none; }
.fb-pos.clickable  { cursor: pointer; }

.fb-label          { fill: var(--tone-ink); font-size: 11px; font-weight: 600; text-anchor: middle; }

/* ---- CAGED overlay ---- */
.cg-band  { opacity: .11; }
.cg-tag   { font-size: 11px; font-weight: 700; text-anchor: middle; }
.cg-line  { fill: none; stroke-width: 3; stroke-linejoin: round; stroke-linecap: round; opacity: .9; }
.cg-plain { fill: var(--cg-plain); }
.fb-label.cg-plain-ink { fill: var(--cg-plain-ink); }
.cg-dim   { opacity: .16; }
.cg-band.cg-C, .cg-dot.cg-C { fill: var(--cg-c); }  .cg-line.cg-C { stroke: var(--cg-c); }  .cg-tag.cg-C { fill: var(--cg-c); }  .cg-ink.cg-C { fill: var(--cg-c-ink); }
.cg-band.cg-A, .cg-dot.cg-A { fill: var(--cg-a); }  .cg-line.cg-A { stroke: var(--cg-a); }  .cg-tag.cg-A { fill: var(--cg-a); }  .cg-ink.cg-A { fill: var(--cg-a-ink); }
.cg-band.cg-G, .cg-dot.cg-G { fill: var(--cg-g); }  .cg-line.cg-G { stroke: var(--cg-g); }  .cg-tag.cg-G { fill: var(--cg-g); }  .cg-ink.cg-G { fill: var(--cg-g-ink); }
.cg-band.cg-E, .cg-dot.cg-E { fill: var(--cg-e); }  .cg-line.cg-E { stroke: var(--cg-e); }  .cg-tag.cg-E { fill: var(--cg-e); }  .cg-ink.cg-E { fill: var(--cg-e-ink); }
.cg-band.cg-D, .cg-dot.cg-D { fill: var(--cg-d); }  .cg-line.cg-D { stroke: var(--cg-d); }  .cg-tag.cg-D { fill: var(--cg-d); }  .cg-ink.cg-D { fill: var(--cg-d-ink); }
/* The letter chips above the neck, in the same colours. */
.chip.cg-chip.on { color: #fff; }
.chip.cg-chip.cg-C.on { background: var(--cg-c); border-color: var(--cg-c); color: var(--cg-c-ink); }
.chip.cg-chip.cg-A.on { background: var(--cg-a); border-color: var(--cg-a); color: var(--cg-a-ink); }
.chip.cg-chip.cg-G.on { background: var(--cg-g); border-color: var(--cg-g); color: var(--cg-g-ink); }
.chip.cg-chip.cg-E.on { background: var(--cg-e); border-color: var(--cg-e); color: var(--cg-e-ink); }
.chip.cg-chip.cg-D.on { background: var(--cg-d); border-color: var(--cg-d); color: var(--cg-d-ink); }
.fb-label.is-root  { fill: var(--root-ink); }
.fb-label.on-open        { fill: var(--tone); }
.fb-label.on-open.is-root { fill: var(--root); }

/* ---------- panels ---------- */

.panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--gap);
  margin-top: var(--gap);
}

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .85rem 1rem 1rem;
}
.panel.hidden { display: none; }
.panel h3 {
  margin: 0 0 .6rem;
  font-size: .76rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.panel-hint { margin: .6rem 0 0; font-size: .78rem; color: var(--faint); }

.chips { display: flex; flex-wrap: wrap; gap: .4rem; }

.chip {
  font: inherit;
  font-size: .9rem;
  padding: .3rem .6rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  cursor: default;
  display: inline-flex;
  align-items: baseline;
  gap: .35rem;
}
button.chip { cursor: pointer; }
button.chip:hover { border-color: var(--muted); }
.chip .deg { font-size: .76rem; color: var(--muted); }
.chip.is-root { border-color: var(--root); }
.chip.is-root .deg { color: var(--root); }
.chip.on { background: var(--root); color: var(--root-ink); border-color: var(--root); }
.chip.on .deg { color: var(--root-ink); opacity: .8; }

.chords { width: 100%; border-collapse: collapse; font-size: .93rem; }
.chords td { padding: .3rem .2rem; border-bottom: 1px solid var(--line-soft); }
.chords tr:last-child td { border-bottom: 0; }
.chords .numeral { font-weight: 600; width: 4.5rem; }
.chords .sym { width: 5rem; }
.chords .tones { color: var(--muted); font-size: .85rem; }

.readings { list-style: none; margin: 0; padding: 0; }
.readings li { padding: .3rem 0; border-bottom: 1px solid var(--line-soft); font-size: .93rem; }
.readings li:last-child { border-bottom: 0; }
.readings .best { font-weight: 600; }
.readings .kind { color: var(--muted); font-size: .8rem; margin-left: .4rem; }
/* The inversion belongs to the reading above it, so it sits on its own line
   underneath rather than running on after the chord name. */
.readings .inv { display: block; color: var(--muted); font-size: .78rem; margin-top: .1rem; }

@media (max-width: 640px) {
  main { padding: .9rem .7rem 3rem; }
  .field, .field.grow { flex: 1 1 100%; min-width: 0; }
  .field.narrow { flex: 0 0 6rem; }
}

/* --- mode siblings: one set of notes, every tonic it can be read from --- */
.toggles.siblings { align-items: flex-start; }
#ex-siblings .chip { display: inline-flex; flex-direction: column; align-items: center; line-height: 1.15; }
#ex-siblings .chip .deg { font-size: .68rem; color: var(--muted); margin-top: .1rem; }
#ex-siblings .chip.on .deg { color: inherit; opacity: .85; }

/* --- key context in the chord builder --- */
.controls.subtle { margin-top: .6rem; padding: .6rem .9rem; background: transparent; border-style: dashed; }
.controls.subtle .hint { flex: 1 1 14rem; align-self: center; }
.chip.out { border-style: dashed; opacity: .7; }
.chip.out .deg { color: var(--danger); }
/* The fits table is three columns of short text; squeezed into one grid
   column every row wraps onto three lines, so it takes the whole row. */
#ch-key-panel { grid-column: 1 / -1; }
#ch-key-panel .chords { width: 100%; }
#ch-key-panel .chords .numeral { width: 5rem; }
#ch-key-panel .chords .sym { width: 7rem; }
#ch-fits tr.complete .numeral, #ch-fits tr.complete .sym { font-weight: 600; }
#ch-fits tr.complete .tones { color: var(--ok); }

/* --- chord diagrams --- */
#ch-voicings-panel { grid-column: 1 / -1; }
.toggles.compact { margin: .2rem 0 .6rem; gap: .5rem; }
.boxes { display: flex; flex-wrap: wrap; gap: .5rem; align-items: flex-start; }
.box {
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface-2); padding: .35rem .3rem .2rem;
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
  cursor: pointer;
}
.box:hover { border-color: var(--muted); }
.box.on { border-color: var(--root); box-shadow: 0 0 0 1px var(--root) inset; }
.box .grip { font-size: .68rem; color: var(--muted); letter-spacing: .01em; }
.box .gaps { font-size: .62rem; color: var(--danger); }
.cb-string { stroke: var(--line); stroke-width: 1; }
.cb-fret   { stroke: var(--line-soft); stroke-width: 1; }
.cb-nut    { stroke: var(--text); stroke-width: 3; }
.cb-dot    { fill: var(--tone); }
.cb-dot.is-root { fill: var(--root); }
.cb-barre  { fill: var(--tone); }
.cb-open   { fill: none; stroke: var(--muted); stroke-width: 1.2; }
.cb-mute   { fill: var(--muted); font-size: 10px; text-anchor: middle; }
.cb-pos    { fill: var(--muted); font-size: 9px; text-anchor: middle; }
.cb-deg    { fill: var(--faint); font-size: 8px; text-anchor: middle; }
.fb-mark { fill: none; stroke: var(--root); stroke-width: 2; opacity: .85; }

/* ---------- practice ---------- */
/* Everything here is sized to be read from a few feet away, with a guitar in
   your hands and the laptop on a table. That is the whole design brief. */

.timer-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: .7rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: .7rem 1rem; margin-top: .4rem;
}
.clock {
  font-size: 2.1rem; font-weight: 600; font-variant-numeric: tabular-nums;
  min-width: 4.4rem; letter-spacing: .01em;
}
.clock.done { color: var(--danger); }
.ghost.primary { background: var(--surface-2); color: var(--text); font-weight: 500; }
.check { display: inline-flex; align-items: center; gap: .4rem; font-size: .85rem; color: var(--muted); }
.check input { accent-color: var(--root); }
.panel .check { display: flex; margin-bottom: .3rem; }

.stage {
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  padding: 1.6rem 1rem 1.1rem; margin-top: var(--gap); text-align: center;
}
.prompt-label {
  margin: 0; font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted);
}
.prompt {
  margin: .2rem 0 .5rem; font-size: 4.4rem; font-weight: 600; line-height: 1.05;
  letter-spacing: -.01em;
}
.answer { margin: .4rem 0 .8rem; }
.answer.hidden { display: none; }
.answer-row {
  display: flex; flex-wrap: wrap; justify-content: center; gap: .9rem;
  font-size: 2rem; font-weight: 600;
}
.answer-row.small { font-size: 1.25rem; gap: .6rem; }
.answer-note-name, .answer-pos {
  display: inline-flex; flex-direction: column; align-items: center; line-height: 1.1;
}
.answer-note-name .deg, .answer-pos .deg {
  font-size: .7rem; font-weight: 400; color: var(--muted); margin-top: .15rem;
}
.answer-note { margin: .5rem 0 0; font-size: .82rem; color: var(--faint); }
.answer .box { display: inline-flex; margin: .8rem auto 0; }
.stage-actions { display: flex; justify-content: center; gap: .6rem; margin-top: .4rem; }
.stage-actions .ghost { font-size: 1rem; padding: .5rem 1.4rem; }
#pr-count { margin-top: .6rem; font-size: .78rem; }
#pr-board-wrap { margin-top: var(--gap); }

@media (max-width: 560px) {
  .prompt { font-size: 3.2rem; }
  .clock { font-size: 1.7rem; }
}

/* --- chord rows open their voicings ---
   The row being clickable has to be visible before it is clicked, so the
   symbol carries a dotted underline the way a link would, and the row gets a
   chevron column that fills in on hover. */
.chords tr.clickable { cursor: pointer; }
/* Both the numeral and the symbol carry the affordance. Only underlining the
   symbol made the row look like the symbol was the only live part of it. */
.chords tr.clickable .sym,
.chords tr.clickable .numeral { text-decoration: underline dotted var(--line); text-underline-offset: 3px; }
.chords tr.clickable:hover { background: var(--panel-hover, rgba(127,127,127,.09)); }
.chords tr.clickable:hover .sym,
.chords tr.clickable:hover .numeral { color: var(--root); text-decoration-color: var(--root); }
.chords tr.clickable td:last-child::after {
  content: "\203A";
  float: right;
  padding-left: .6rem;
  color: var(--line);
  transition: color .12s ease;
}
.chords tr.clickable:hover td:last-child::after,
.chords tr.on td:last-child::after { color: var(--root); }
.chords tr.on { background: var(--panel-hover, rgba(127,127,127,.09)); }
.chords tr.on .numeral, .chords tr.on .sym { color: var(--root); font-weight: 600; }
/* Out of the .panels grid entirely, not spanning it. Inside the grid, the
   panel appearing changed how many auto-fit tracks the container made, so the
   Notes/Triads/Sevenths panels jumped narrower the moment a chord was
   clicked. A block-level sibling below the grid cannot touch their widths. */
#ex-voicings-panel { margin-top: var(--gap); }
.box .inv { font-size: .62rem; color: var(--muted); letter-spacing: .02em; }
.box .strings { font-size: .62rem; color: var(--faint); letter-spacing: .02em; }
/* The named shape, and the reason the card is where it is in the list. */
.box .form {
  font-size: .64rem; font-weight: 600; letter-spacing: .02em;
  color: var(--tone);
}
.box.on .form { color: var(--root); }
.box.on .inv { color: var(--root); }

/* ---------- metronome ---------- */

.metro-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: .7rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: .7rem 1rem; margin-top: .6rem;
}
.metro-go { min-width: 7.2rem; }
.metro-go.running { background: var(--root); color: var(--root-ink); border-color: var(--root); }
.metro-go.running:hover { color: var(--root-ink); }

/* The tempo slider takes the slack so the row stays on one line at desktop
   width and the fixed controls keep their size. */
.metro-slider { flex: 1 1 8rem; min-width: 7rem; accent-color: var(--root); }

.beats { display: inline-flex; gap: .42rem; align-items: center; }
.beat {
  width: .74rem; height: .74rem; border-radius: 50%;
  border: 1.5px solid var(--line); background: transparent;
  transition: background-color .06s linear, border-color .06s linear;
}
.beat.one { border-color: var(--muted); }
/* The first beat of each accent group (the 4 of 6/8 grouped 3+3). */
.beat.group { border-color: var(--muted); border-width: 2px; }
.beats .beat.group { margin-left: .3rem; }
/* No transition on the way in: the light has to arrive with the click, and a
   fade makes it read as late even when the timing is exact. */
.beat.lit { background: var(--tone); border-color: var(--tone); transition: none; }
.beat.one.lit { background: var(--root); border-color: var(--root); }

.metro-advance { gap: .35rem; }
.inline-num {
  width: 3.2rem; padding: .18rem .3rem; text-align: center;
  font: inherit; font-size: .9rem;
  border-radius: var(--radius); border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text);
}
#pr-metro-hint { flex-basis: 100%; }

@media (max-width: 720px) {
  .metro-slider { flex-basis: 100%; }
}

/* ---------- keyboard ---------- */

/* A piano is black and white in both themes. These are the one place in the
   stylesheet that does NOT follow the surface tokens: theming the keys is
   what broke the first version, where --text is near-white in dark mode and
   every black key rendered white. Keys are the instrument, not the chrome. */
:root {
  --key-white:      #f4f2ee;
  --key-white-edge: #b4b0a8;
  --key-black:      #23242a;
  --key-black-edge: #0e0f12;
}
@media (prefers-color-scheme: dark) {
  :root {
    --key-white:      #e8e6e1;
    --key-white-edge: #6f6d68;
    --key-black:      #17181c;
    --key-black-edge: #000000;
  }
}

.kb-white { fill: var(--key-white); stroke: var(--key-white-edge); stroke-width: 1.1; }
.kb-black { fill: var(--key-black); stroke: var(--key-black-edge); stroke-width: 1; }

/* The wash: the key tinted, not replaced. Low enough that a black key still
   reads as black and a white key still reads as white. */
.kb-wash          { fill: var(--tone); opacity: .22; pointer-events: none; }
.kb-wash.is-root  { fill: var(--root); opacity: .28; }

/* The dot, exactly as the fretboard marks a note. */
.kb-dot         { fill: var(--tone); stroke: none; }
.kb-dot.is-root { fill: var(--root); }
.kb-dot.marked  { stroke: var(--key-white); stroke-width: 2.5; stroke-dasharray: 3 2; }

.kb-label {
  font-size: 11px;
  font-weight: 600;
  text-anchor: middle;
  pointer-events: none;
  fill: var(--tone-ink);
}
.kb-label.is-root { fill: var(--root-ink); }
.kb-label.big { font-size: 15px; }
.kb-octave.big { font-size: 14px; }

.kb-octave { fill: var(--faint); font-size: 10px; text-anchor: middle; }
.kb-key.clickable { cursor: pointer; }
.kb-key.clickable:hover .kb-white { fill: #ffffff; }
.kb-key.clickable:hover .kb-black { fill: #34363e; }

/* Inversions on a keyboard: a small board each, listed not ranked. */
.kbvoicings { display: flex; flex-wrap: wrap; gap: .9rem; margin-top: .6rem; }
.kbv {
  display: flex; flex-direction: column; align-items: center; gap: .15rem;
  padding: .5rem .55rem .45rem;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface-2); cursor: pointer;
}
.kbv:hover { border-color: var(--muted); }
.kbv.on { border-color: var(--root); }
.kbv svg { width: 260px; height: auto; }
.kbv-label { font-size: .82rem; font-weight: 500; }
.kbv-reach { font-size: .7rem; color: var(--muted); }

/* ---------- progression player ---------- */

input[type="text"] {
  font: inherit;
  padding: .45rem .55rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  width: 100%;
}

.prog-next { margin-top: -.2rem; font-size: 1rem; }
.prompt.counting { opacity: .45; }

/* The chart. Four bars to a line, like a lead sheet, so the twelve-bar blues
   reads as the three lines everyone already knows by shape. */
.strip {
  display: grid;
  grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr));
  gap: .4rem;
  max-width: 36rem;
  margin: .9rem auto 0;
}
.strip .bar {
  font: inherit;
  display: flex; flex-direction: column; align-items: center; gap: 0;
  padding: .35rem .25rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.strip .bar .num { font-size: .66rem; color: var(--muted); letter-spacing: .02em; }
.strip .bar .sym { font-weight: 600; font-size: .98rem; }
.strip .bar:hover { border-color: var(--muted); }
/* Where you are: filled, so it is found by peripheral vision alone. */
.strip .bar.on { background: var(--root); border-color: var(--root); color: var(--root-ink); }
.strip .bar.on .num { color: var(--root-ink); opacity: .8; }
/* Where you are going: outlined, a bar's warning before the change. */
.strip .bar.next { border-style: dashed; border-color: var(--tone); }

.prog-grips { margin-top: var(--gap); justify-content: center; }
.prog-box { min-width: 9.5rem; }
.prog-box .prog-head { display: flex; align-items: baseline; gap: .45rem; justify-content: center; }
.prog-box .prog-head .sym { font-weight: 600; font-size: 1.05rem; }
.prog-box .prog-head .num { font-size: .72rem; color: var(--muted); }
.prog-box.next { border-style: dashed; border-color: var(--tone); }
.prog-box .cycle { display: flex; align-items: center; justify-content: center; gap: .4rem; font-size: .72rem; color: var(--muted); }
.prog-box .cycle .ghost { padding: .05rem .5rem; font-size: 1rem; line-height: 1.2; }
/* Piano voicings in the player. Every box draws the same stretch of keys, so
   they are sized alike and read as one keyboard seen several times. */
.prog-box.keys svg { width: 245px; max-width: 100%; height: auto; display: block; }
.answer .kbv { display: inline-flex; margin: .8rem auto 0; cursor: default; }
.answer .kbv:hover { border-color: var(--line); }
