/* Dark theme, protan-safe accents: blue and amber only, neutrals elsewhere. */
:root {
  --bg: #14171c;
  --surface: #1e232c;
  --line: #313947;
  --ink: #f2f4f8;
  --ink-2: #a9b1be;
  --ink-3: #6c7686;
  /* UI accents (text and controls). */
  --blue: #648fff;
  --amber: #ffb000;
  /* Chart series, validated for the dark surface. */
  --series-blue: #3987e5;
  --series-amber: #c28300;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.5;
}

.wrap {
  max-width: 640px;
  margin: 0 auto;
  padding: 24px 16px 48px;
}

/* Beats the display rules on the panels this is applied to, which are later in
   the file and equally specific. */
.hidden {
  display: none !important;
}

/* Header. */
.site-header {
  text-align: center;
  margin-bottom: 24px;
}

.site-header h1 {
  margin: 0;
  font-size: 2.5rem;
  letter-spacing: 0.04em;
}

.tagline {
  margin: 4px 0 0;
  color: var(--ink-2);
}

/* Mode switch. */
.mode-switch {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.mode-blurb {
  margin: 8px 0 24px;
  text-align: center;
  color: var(--ink-2);
  font-size: 0.875rem;
}

.mode-tab {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: 999px;
  padding: 8px 16px;
  font: inherit;
  cursor: pointer;
}

.mode-tab.is-active {
  background: var(--blue);
  border-color: var(--blue);
  color: #10131a;
  font-weight: 700;
}

.mode-tab:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
}

/* Stage and pad. */
.stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.pad-ring {
  --progress: 0;
  width: min(70vw, 260px);
  aspect-ratio: 1;
  border-radius: 50%;
  padding: 8px;
  background: conic-gradient(
    var(--blue) calc(var(--progress) * 1%),
    var(--line) 0
  );
}

.pad {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: none;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font: inherit;
  touch-action: manipulation;
}

.pad:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 4px;
}

.pad-state {
  font-size: 2rem;
  font-weight: 700;
}

.pad-detail {
  color: var(--ink-2);
  font-size: 0.875rem;
}

.notice {
  min-height: 1.5em;
  margin: 0;
  color: var(--amber);
  text-align: center;
}

/* Results. */
.results {
  margin-top: 24px;
  background: var(--surface);
  border-radius: 16px;
  padding: 24px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.score-hero {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 16px;
}

.score-value {
  margin: 0;
  font-size: 4rem;
  font-weight: 800;
  color: var(--amber);
  line-height: 1;
}

.score-grade {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
  border: 2px solid var(--line);
  border-radius: 8px;
  padding: 4px 12px;
}

.verdict {
  margin: 0;
  text-align: center;
  color: var(--ink-2);
}

.best-banner {
  margin: 0;
  text-align: center;
  color: var(--amber);
  font-weight: 700;
}

.roll-results {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

/* Sub-score meters. */
.meters {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.meter-row {
  display: grid;
  grid-template-columns: 96px 1fr 32px;
  align-items: center;
  gap: 8px;
}

.meter-label {
  color: var(--ink-2);
  font-size: 0.875rem;
}

.meter {
  display: block;
  height: 8px;
  border-radius: 4px;
  background: var(--line);
  overflow: hidden;
}

.meter-fill {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--blue);
}

.meter-value {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Live readouts. */
.live-readouts {
  display: flex;
  justify-content: center;
  gap: 48px;
}

.live-readout {
  text-align: center;
}

.live-readout-label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0;
  color: var(--ink-2);
  font-size: 0.875rem;
}

.live-readout-value {
  margin: 0;
  font-size: 3rem;
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

/* Rudiment drills. */
/* The exercise picker is a well of its own: there are three dozen rudiments
   in the library, and left to grow the list pushed the exercise, the capture
   pad, and the feedback off the bottom of the page. It scrolls itself instead,
   recessed to the page background so the cards read as sitting inside it. */
.drill-side {
  max-height: clamp(240px, 45vh, 400px);
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px;
}

.drill-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

.drill-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px;
  font: inherit;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}

.drill-card:hover {
  border-color: var(--ink-3);
}

.drill-card.is-active {
  border-color: var(--blue);
  box-shadow: inset 0 0 0 1px var(--blue);
}

.drill-card:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
}

.drill-card-name {
  font-weight: 700;
  font-size: 0.875rem;
  line-height: 1.3;
}

.drill-card-meta {
  color: var(--ink-3);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  /* Long stickings (a seventeen stroke roll is 33 characters) wrap inside
     the card instead of pushing it out of the grid. */
  max-width: 100%;
  overflow-wrap: anywhere;
}

.drill-card-best {
  color: var(--amber);
  font-size: 0.75rem;
  font-weight: 700;
}

.drill-main {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

@media (min-width: 640px) {
  .drill-cards {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* On wide screens the test picker becomes a left pane and the main area
   holds the exercise, the capture, and the feedback. */
@media (min-width: 880px) {
  body[data-mode="drill"] .wrap {
    max-width: 1000px;
  }

  #drill-panel {
    display: grid;
    grid-template-columns: 240px minmax(0, 1fr);
    gap: 8px 24px;
    align-items: start;
  }

  /* As a left pane the well takes the height it can and keeps scrolling
     itself, so the exercise beside it never moves. */
  .drill-side {
    position: sticky;
    top: 16px;
    max-height: calc(100vh - 32px);
  }

  .drill-side .drill-cards {
    grid-template-columns: 1fr;
  }
}

.drill-blurb {
  margin: 8px 0 0;
  text-align: center;
  color: var(--ink-3);
  font-size: 0.875rem;
}

/* Engraving is recolored to the page ink after render, so it sits directly
   on the dark surface like the rest of the UI. */
.drill-sheet {
  margin: 16px 0 0;
  overflow-x: auto;
}

.drill-results-name {
  margin: 0;
  text-align: center;
  font-size: 1.125rem;
}

.drill-sticking {
  margin: 0;
  text-align: center;
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: 0.32em;
  text-indent: 0.32em;
}

.drill-instruction {
  margin: 8px 0 0;
  text-align: center;
  color: var(--ink-2);
}

.drill-reps {
  list-style: none;
  display: flex;
  justify-content: center;
  gap: 8px;
  margin: 16px 0 0;
  padding: 0;
}

.drill-rep {
  width: 24px;
  height: 8px;
  border-radius: 4px;
  background: var(--line);
}

.drill-rep.is-done {
  background: var(--blue);
}

.drill-attempts {
  margin: 4px 0 0;
  color: var(--ink-3);
  font-size: 0.75rem;
}

.drill-last {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.drill-last-charts {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

#drill-rep-timing,
#drill-rep-volume {
  display: block;
  width: 100%;
  height: 150px;
}

@media (min-width: 640px) {
  .drill-last-charts {
    flex-direction: row;
  }

  .drill-last-charts > figure {
    flex: 1;
    min-width: 0;
  }
}

.chart-title {
  margin: 0 0 8px;
  color: var(--ink-2);
  font-size: 0.875rem;
}

.drill-feedback {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.drill-feedback-title {
  margin: 0 0 8px;
  font-size: 1rem;
}

.drill-notes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  color: var(--ink-2);
  font-size: 0.875rem;
}

.drill-note {
  display: flex;
  gap: 8px;
}

.drill-note::before {
  content: "";
  flex: none;
  width: 4px;
  border-radius: 2px;
  background: var(--ink-3);
}

.drill-note.is-good::before {
  background: var(--blue);
}

.drill-note.is-work::before {
  background: var(--amber);
}

.drill-tempo {
  margin: 0;
  text-align: center;
  color: var(--ink-2);
  font-size: 0.875rem;
}

.drill-compare {
  margin: 0;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  color: var(--ink);
}

.drill-coach {
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.coach-blurb {
  margin: 0 0 8px;
  color: var(--ink-3);
  font-size: 0.875rem;
}

.coach-buttons {
  display: flex;
  gap: 8px;
  margin: 0;
}

.coach-output {
  max-height: 420px;
  overflow-y: auto;
  user-select: all;

  margin-top: 16px;
  white-space: pre-wrap;
  background: var(--bg);
  border-radius: 8px;
  padding: 16px;
  color: var(--ink-2);
  font-size: 0.875rem;
  line-height: 1.6;
}

.drill-again {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  border-radius: 999px;
  padding: 8px 24px;
  font: inherit;
  cursor: pointer;
}

.drill-again:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
}

#drill-timing-canvas,
#drill-volume-canvas,
#drill-tone-canvas {
  display: block;
  width: 100%;
  height: 200px;
}

@media (min-width: 640px) {
  .drill-feedback {
    flex-direction: row;
  }

  .drill-feedback > div {
    flex: 1;
  }
}

/* Bubble Pop. */
.metro {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 40px;
}

.metro-light {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--amber);
  opacity: 0.08;
  will-change: opacity;
}

.metro-bpm {
  font-weight: 700;
  font-size: 1.375rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.metro-bpm-bump {
  color: var(--amber);
  animation: bpm-bump 1.2s ease-out;
}

@keyframes bpm-bump {
  0% {
    transform: scale(2);
  }
  100% {
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .metro-bpm-bump {
    animation: none;
  }
}

.bubble-diffs {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.bubble-hud {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px 24px;
  flex-wrap: wrap;
}

.bubble-lives {
  margin: 0;
}

#bubble-canvas {
  display: block;
  width: 100%;
  height: 68vh;
  min-height: 380px;
}

/* The game takes the whole screen. */
body[data-mode="bubble"] .wrap {
  max-width: none;
  padding-top: 16px;
}

body[data-mode="bubble"] .site-header,
body[data-mode="bubble"] .howto {
  display: none;
}

/* Hit timeline. */
.timeline {
  margin: 0;
  position: relative;
}

#timeline-canvas {
  display: block;
  width: 100%;
  height: 140px;
}

#live-canvas {
  display: block;
  width: 100%;
  height: 220px;
}

.timeline-tooltip {
  position: absolute;
  transform: translate(-50%, -100%);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 4px 8px;
  font-size: 0.75rem;
  white-space: nowrap;
  pointer-events: none;
}

.timeline-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 16px;
  margin-top: 8px;
  color: var(--ink-2);
  font-size: 0.75rem;
}

.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.swatch {
  width: 12px;
  height: 12px;
  border-radius: 2px;
}

.swatch-envelope {
  background: var(--series-blue);
}

.swatch-hit {
  background: var(--series-amber);
}

.swatch-grid {
  background: transparent;
  border: 1px dashed var(--ink-3);
}

.swatch-wave {
  background: var(--ink-3);
}

.swatch-flux {
  background: var(--ink-2);
}

/* The debug recorder: the record button up top and the
   waveform-and-hits panel it feeds. */
.debug-record-line {
  margin: 0 0 8px;
  text-align: right;
}

.debug-record {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink-3);
  border-radius: 999px;
  padding: 2px 12px;
  font: inherit;
  font-size: 0.75rem;
  cursor: pointer;
}

.debug-record:hover {
  color: var(--amber);
  border-color: var(--amber);
}

.debug-record.is-recording {
  color: var(--amber);
  border-color: var(--amber);
}

.debug-panel {
  margin-top: 16px;
}

#debug-canvas {
  display: block;
  width: 100%;
  height: 180px;
}

/* Stats. */
.stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 24px;
  margin: 0;
}

.stat {
  text-align: center;
}

.stat dt {
  color: var(--ink-3);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.stat dd {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* How it works. */
.howto {
  max-width: 640px;
  margin: 32px auto 0;
  color: var(--ink-2);
}

.howto h2 {
  color: var(--ink);
  font-size: 1.25rem;
}

.howto strong {
  color: var(--ink);
}

/* Footer. */
.site-footer {
  margin-top: 32px;
  text-align: center;
  color: var(--ink-3);
  font-size: 0.875rem;
}

.site-footer a {
  color: var(--blue);
}

.storage-line {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}

.storage-reset {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink-3);
  border-radius: 999px;
  padding: 2px 12px;
  font: inherit;
  font-size: 0.75rem;
  cursor: pointer;
}

.storage-reset:hover {
  color: var(--amber);
  border-color: var(--amber);
}

@media (min-width: 768px) {
  .wrap {
    padding: 48px 24px 64px;
  }

  .results {
    padding: 32px 24px;
  }
}
