/* ---------- Guide pages (own-sheet-music.html) ---------------------------- */
/* Every section is linked from the table of contents and from support replies,
   so its heading must land below the sticky header rather than under it. */
.sf-guide h2[id] { scroll-margin-top: 96px; }
.sf-guide .sf-faq-nav { margin-top: var(--sf-s-6); }

/* ---------- Free browser tools (tuner.html, metronome.html) --------------- */
/* Both widgets are one card with a readout on top and controls underneath.
   State is carried by classes only — style-src has no 'unsafe-inline', so
   nothing here may be set from a style attribute. The one exception is the
   needle angle, which JS writes as the custom property --sf-needle-deg (a
   CSSOM property write, which the CSP does not cover). */

.sf-tool {
  margin-top: var(--sf-s-7);
  padding: var(--sf-s-6);
  border: 1px solid var(--sf-outline-variant);
  border-radius: var(--sf-r-2xl);
  background: var(--sf-surface);
  box-shadow: var(--sf-elev-1);
}
.sf-tool [hidden] { display: none !important; }

.sf-tool__readout {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--sf-s-2);
  text-align: center;
}
.sf-tool__note {
  font-family: var(--sf-font-display);
  font-size: clamp(44px, 12vw, 72px); line-height: 1;
  color: var(--sf-on-surface);
}
.sf-tool__figure {
  font-family: var(--sf-font-mono); font-size: 15px;
  color: var(--sf-on-surface-variant);
  min-height: 1.4em;
}
.sf-tool__status {
  margin-top: var(--sf-s-4);
  text-align: center; font-size: 14px;
  color: var(--sf-on-surface-variant);
  min-height: 1.4em;
}

/* The dial. ±50 cents across ±45 degrees of needle travel. */
.sf-dial { display: block; width: min(320px, 100%); height: auto; margin: 0 auto; }
.sf-dial__arc { fill: none; stroke: var(--sf-outline-variant); stroke-width: 2; }
.sf-dial__tick { stroke: var(--sf-outline); stroke-width: 2; }
.sf-dial__tick--major { stroke: var(--sf-on-surface-variant); stroke-width: 3; }
.sf-dial__label { fill: var(--sf-on-surface-variant); font: 600 10px var(--sf-font-ui); }
.sf-dial__needle {
  transform: rotate(var(--sf-needle-deg, 0deg));
  transform-origin: 100px 100px;
  transition: transform 90ms linear;
}
.sf-dial__needle line { stroke: var(--sf-on-surface); stroke-width: 3; stroke-linecap: round; }
.sf-dial__pivot { fill: var(--sf-on-surface); }
/* In tune is the app's own "correct" colour, and the only place this page
   uses it — a tuner that says nothing when you arrive is no use. */
.is-in-tune .sf-dial__needle line,
.is-in-tune .sf-dial__pivot { stroke: var(--sf-correct); fill: var(--sf-correct); }
.is-in-tune .sf-tool__note { color: var(--sf-correct); }

@media (prefers-reduced-motion: reduce) {
  .sf-dial__needle { transition: none; }
}

/* Controls shared by both tools. */
.sf-tool__controls {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: var(--sf-s-4);
  margin-top: var(--sf-s-6);
  padding-top: var(--sf-s-5);
  border-top: 1px solid var(--sf-outline-variant);
}
.sf-tool__control { display: flex; flex-direction: column; gap: var(--sf-s-2); }
.sf-tool__control label {
  font: 600 12px/1.3 var(--sf-font-ui);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--sf-on-surface-variant);
}
.sf-tool__control input[type="number"],
.sf-tool__control select {
  min-height: 44px;
  padding: 8px 12px;
  border: 1px solid var(--sf-outline-variant);
  border-radius: var(--sf-r-md);
  background: var(--sf-bg);
  color: var(--sf-on-surface);
  font: 500 15px var(--sf-font-ui);
}
.sf-tool__control input[type="number"]:focus-visible,
.sf-tool__control select:focus-visible {
  outline: 2px solid var(--sf-primary); outline-offset: 2px;
}
.sf-tool__actions { display: flex; flex-wrap: wrap; gap: var(--sf-s-3); margin-top: var(--sf-s-5); justify-content: center; }

/* Tuner: the strings of the chosen tuning. */
.sf-strings {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--sf-s-2);
  margin: var(--sf-s-5) 0 0; padding: 0;
  list-style: none;
}
.sf-string {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 66px;
  padding: var(--sf-s-2) var(--sf-s-3);
  border: 1px solid var(--sf-outline-variant);
  border-radius: var(--sf-r-lg);
  color: var(--sf-on-surface-variant);
}
.sf-string__name { font: 600 16px var(--sf-font-ui); color: var(--sf-on-surface); }
.sf-string__hz { font: 400 11px var(--sf-font-mono); }
.sf-string.is-near {
  border-color: var(--sf-primary);
  background: var(--sf-primary-container);
  color: var(--sf-on-primary-container);
}
.sf-string.is-near .sf-string__name { color: var(--sf-on-primary-container); }

/* Metronome: tempo readout and beat lights. */
.sf-bpm {
  font-family: var(--sf-font-display);
  font-size: clamp(52px, 14vw, 84px); line-height: 1;
  text-align: center; color: var(--sf-on-surface);
}
.sf-bpm__unit {
  display: block; margin-top: var(--sf-s-2);
  font: 600 12px/1 var(--sf-font-ui);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--sf-on-surface-variant);
}
.sf-tempo-row {
  display: flex; align-items: center; justify-content: center;
  gap: var(--sf-s-3);
  margin-top: var(--sf-s-5);
}
.sf-tempo-row input[type="range"] { flex: 1 1 220px; max-width: 420px; min-height: 44px; accent-color: var(--sf-primary); }
.sf-beats {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--sf-s-3);
  margin: var(--sf-s-6) 0 0; padding: 0;
  list-style: none;
}
.sf-beat {
  width: 20px; height: 20px;
  border: 2px solid var(--sf-outline);
  border-radius: 50%;
  transition: background-color var(--sf-dur-1) var(--sf-ease-out),
              border-color var(--sf-dur-1) var(--sf-ease-out);
}
.sf-beat--accent { width: 26px; height: 26px; }
.sf-beat.is-on { background: var(--sf-primary); border-color: var(--sf-primary); }
.sf-beat--accent.is-on { background: var(--sf-tertiary); border-color: var(--sf-tertiary); }

/* ---------- Tuner: the warning box and the diagnostic line ---------------- */
/* Both ship hidden and are revealed by tuner.js. [hidden] needs saying twice
   as loudly as the UA sheet says it, because these carry a border and padding.

   The warning is brass, not red: hues 25 and 145 belong to the practice
   feedback system (see README, "The palette"), and a page that borrows them
   for "your microphone is off" teaches the wrong colour. */
.sf-tool__alert[hidden],
.sf-tool__diag[hidden] { display: none !important; }

.sf-tool__alert {
  margin-top: var(--sf-s-4);
  padding: var(--sf-s-3) var(--sf-s-4);
  border: 1px solid color-mix(in oklch, var(--sf-tertiary) 45%, transparent);
  background: color-mix(in oklch, var(--sf-tertiary) 12%, transparent);
  border-radius: var(--sf-r-lg);
  color: var(--sf-on-surface);
  font-size: 14px; line-height: 1.55;
  text-wrap: pretty;
}

/* Deliberately plain and monospaced: it is meant to be read once, and pasted
   into a bug report. */
.sf-tool__diag {
  margin-top: var(--sf-s-2);
  font-family: var(--sf-font-mono);
  font-size: 12px; line-height: 1.5;
  color: var(--sf-on-surface-variant);
  word-break: break-word;
}
