/* ============================================================================
   GOLDEN SEAM TUNER — a VINTAGE RADIO-DIAL guitar tuner.
   Warm lit dial + a sliding red pointer (like tuning an old radio). The instant
   the note is right, the whole dial FLOODS GREEN and the pointer locks — a big,
   unmissable "you got it, stop tuning" signal. Skin only; engine hooks preserved.
   ============================================================================ */
/* TYPE — two families, each with a job.
   Instrument Serif carries identity and the note itself: the hero glyph, set large enough that its
   stroke contrast is never a legibility risk (at 64-88px the thin strokes are still several pixels).
   IBM Plex Mono carries every MEASUREMENT — cents, hertz, engraved legends, controls. Mono is not a
   style choice here: its figures are tabular, so a live readout counting 12 -> 8 -> 4 does not shift
   width and make the numbers dance while someone is turning a peg. Meaning is mapped to typeface.
   NOTE: ♭ ♯ ¢ ✓ are outside both subsets (they were outside Fraunces too — unchanged behaviour), so
   the fallback chain below is load-bearing, not decoration. */
@font-face{ font-family:"Instrument Serif"; font-style:normal; font-weight:400; font-display:swap; src:url("./fonts/instrument-serif-400.woff2") format("woff2"); }
@font-face{ font-family:"Instrument Serif"; font-style:italic; font-weight:400; font-display:swap; src:url("./fonts/instrument-serif-italic.woff2") format("woff2"); }
@font-face{ font-family:"Plex Mono"; font-style:normal; font-weight:400; font-display:swap; src:url("./fonts/plex-mono-400.woff2") format("woff2"); }
@font-face{ font-family:"Plex Mono"; font-style:normal; font-weight:600; font-display:swap; src:url("./fonts/plex-mono-600.woff2") format("woff2"); }
/* Fraunces is the washi skin's face. Self-hosted like the two above: the Google Fonts
   <link> this replaced was silently blocked by our own CSP (style-src 'self') — the skin
   fell back to Georgia and nobody saw an error. Same subsets caveat as the note above. */
@font-face{ font-family:"Fraunces"; font-style:normal; font-weight:400; font-display:swap; src:url("./fonts/fraunces-400.woff2") format("woff2"); }
@font-face{ font-family:"Fraunces"; font-style:normal; font-weight:500; font-display:swap; src:url("./fonts/fraunces-500.woff2") format("woff2"); }
@font-face{ font-family:"Fraunces"; font-style:normal; font-weight:600; font-display:swap; src:url("./fonts/fraunces-600.woff2") format("woff2"); }

:root{
  /* ── MATERIALS ─────────────────────────────────────────────────────────────
     The chassis used to sit in a narrow mid-brown band — shell, type and dial
     all at similar values, which reads muddy and costs contrast exactly where a
     tuner cannot afford it. It is now dark lacquered rosewood, so the lit dial
     and the readout are the brightest things on the panel by a wide margin. */
  --shell-hi:#4b3524; --shell:#2a1c11; --shell-dk:#120b06;
  --gold-hi:#f7e9c0; --gold:#cfa955; --gold-dk:#8a6a2c; --gold-deep:#43331a;
  --dial-hi:#fdf4dc; --dial:#f1dcac; --dial-dk:#d9b878;
  --cream:#f6ecd4; --amber:#efc987; --amber-dk:#b98c3f;
  --ink:#241a0f; --ink-soft:#5c4526; --dim:#9c8256;
  --red:#e25d3c; --red-dk:#a3301a;  /* was #e0522f: 4.26:1 on --shell, under WCAG AA for the error line.
                                       Same hue and saturation, 3% lighter: 4.61:1 (gs-8mu gate). */
  --green:#31c26a; --green-hi:#93f2bb; --green-dk:#178f4c;
  --display:"Instrument Serif",Georgia,"Times New Roman",serif;
  --label:"Instrument Serif",Georgia,serif;
  --mono:"Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  /* ── TYPE SCALE ────────────────────────────────────────────────────────────
     Sizes used to be ad-hoc (19/12/66/15/14/22/17/12.5/13/24…) with no ratio
     between them. This is a ~1.25 scale, fluid so the phone gets the same
     hierarchy as the desktop instead of a shrunk copy. --t-note sits off-scale
     on purpose: it is the readout, the one thing read from across a room. */
  --t-micro:12.5px;                          /* sub-brand, helper line          */
  --t-legend:clamp(13px,3.4vw,14px);         /* engraved panel legends          */
  --t-body:16px;
  --t-btn:clamp(17px,4.4vw,18px);            /* primary action                  */
  --t-mark:clamp(21px,5.4vw,24px);           /* wordmark                        */
  --t-lock:clamp(21px,5.6vw,24px);           /* "In tune" badge — pairs w/ mark */
  /* THE readout. Raised from clamp(64px,18vw,88px): at three feet on a music stand the note
     name is the ONE element a student can act on, and it was sharing the stage with a cents
     number they cannot act on. The space comes from .tstext below, which shrank to match —
     nobody reading an exact deviation is standing three feet away. */
  --t-note:clamp(76px,22vw,108px);           /* THE readout                     */
  /* engraved-legend tracking; small caps type needs air, the readout needs none */
  --track-legend:.15em; --track-mark:.005em;

  /* ── SPACE SCALE ───────────────────────────────────────────────────────────
     4px base. Every margin/padding below snaps to these so the vertical rhythm
     is deliberate rather than a pile of one-off values. */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:22px; --s6:30px; --s7:40px;

  /* ── THE ROOM (theme-dependent) ────────────────────────────────────────────
     The chassis is a physical object: rosewood and gold do not invert. What the
     colour scheme changes is the ROOM it sits in and the light falling on it. */
  --room:radial-gradient(125% 95% at 50% -12%, #2e2114 0%, transparent 58%),
         linear-gradient(180deg,#161009,#080502 85%);
  --cab-shadow:0 40px 80px -20px rgba(0,0,0,.85), 0 2px 0 rgba(255,231,184,.05);
  --legend-idle:#c9ae7c;                     /* legend on the dark chassis      */
  /* gs-4ib: lifted #b0925f -> #b79b6c. Measured on rendered pixels, the guidance line sat at
     6.30:1 and the trust line at 3.85:1 against the chassis; both are functional text and the
     target is 7:1. This is the minimum lift that clears it with hue and saturation untouched,
     so the warm bronze is unchanged to the eye. */
  --helper:#b79b6c;                          /* italic helper line              */
}

/* DAYLIGHT. Same instrument, different room: parchment wall, softer contact
   shadow, and a touch more warmth in the rim light. Previously the app had no
   light mode at all — it rendered identically dark, which reads as broken on a
   phone set to light. */
@media (prefers-color-scheme:light){
  :root{
    --room:radial-gradient(125% 95% at 50% -12%, #fdf7e8 0%, transparent 62%),
           linear-gradient(180deg,#f5ebd6,#e2d0ac 88%);
    --cab-shadow:0 30px 58px -22px rgba(56,38,20,.42), 0 3px 10px rgba(56,38,20,.16);
    --legend-idle:#d2b98c;
    --helper:#bd9969;   /* gs-4ib: lifted from #a9814b for the same 7:1 reason as the dark token */
  }
}
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;height:100%}
body{
  min-height:100dvh; display:grid; place-items:center;
  padding:var(--s7) var(--s4) calc(var(--s7) + env(safe-area-inset-bottom)); gap:var(--s7);
  font:var(--t-body)/1.5 var(--label); color:var(--ink); -webkit-font-smoothing:antialiased;
  background:var(--room); background-attachment:fixed;
}
.cab{ position:relative; width:min(430px,95vw); }

/* ── the radio chassis (was .face) ─────────────────────────────────────── */
.face{
  position:relative; z-index:1; border-radius:26px;
  padding:var(--s6) var(--s5) var(--s5);
  background:
    linear-gradient(158deg, rgba(255,244,214,.09), transparent 24%),
    linear-gradient(180deg,var(--shell-hi) 0%,var(--shell) 44%,var(--shell-dk) 100%);
  /* the gold reads as a LINE around the object, never a fill across it */
  box-shadow:
    var(--cab-shadow),
    inset 0 1px 0 rgba(255,240,200,.22),
    inset 0 0 0 1px rgba(0,0,0,.72),
    inset 0 0 0 2px rgba(207,169,85,.52);
  transition:box-shadow .5s ease;
}
.screw{position:absolute;width:9px;height:9px;border-radius:50%;
  background:radial-gradient(circle at 34% 30%,#e8d7a6,#7d6132 62%,#2c2110);box-shadow:0 1px 2px rgba(0,0,0,.7)}
.screw.tl{top:12px;left:12px}.screw.tr{top:12px;right:12px}.screw.bl{bottom:12px;left:12px}.screw.br{bottom:12px;right:12px}

.head{display:flex;align-items:flex-start;justify-content:space-between;margin:0 var(--s1) var(--s5)}
/* Instrument Serif ships ONE weight (400). Asking for 600 anywhere on --display would make the
   browser synthesise a bold by smearing the outline — which looks exactly like a cheap fake, and on
   a high-contrast serif it is unmistakable. So the display face never carries a weight above 400;
   where the old design used weight for emphasis, this one uses size, colour and tracking instead. */
.mark .name{font-family:var(--display);font-weight:400;font-size:var(--t-mark);
  line-height:1.05;letter-spacing:var(--track-mark);
  background:linear-gradient(180deg,var(--gold-hi),#dcb96c 55%,#a9843c);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.subbrand{font-family:var(--mono);font-size:10.5px;color:var(--helper);margin-top:var(--s2);
  letter-spacing:.19em;text-transform:uppercase}
/* pilot lamp (was #tlamp — engine lights it via .face state classes) */
.tlamp{width:12px;height:12px;border-radius:50%;margin-top:3px;flex:none;
  background:radial-gradient(circle at 36% 30%,#5a4a2e,#241708 70%);box-shadow:inset 0 0 3px rgba(0,0,0,.7);transition:.4s}
.face.live .tlamp{background:radial-gradient(circle at 36% 30%,#ffe6a8,#c98f2a 60%,#7c5f26);box-shadow:0 0 12px 2px rgba(233,182,80,.6),inset 0 0 3px rgba(255,255,255,.5)}

/* THE READOUT. The slot keeps a fixed height in every state so nothing jumps
   when a note arrives. Idle is a deliberately UNLIT readout — before, the
   engine's placeholder em-dash sat at full 66px in mid-brown and read as a
   stray line floating in dead space. */
.note{font-family:var(--display);font-weight:400;font-size:var(--t-note);line-height:.82;text-align:center;color:#7d6742;
  margin:0 0 var(--s2);letter-spacing:-.005em;display:flex;align-items:baseline;justify-content:center;gap:2px;
  min-height:calc(var(--t-note) * .82);
  transition:color .35s,text-shadow .35s,opacity .35s}
.note .acc{font-size:.42em;font-weight:400;transform:translateY(-.5em);color:var(--gold);opacity:.94}
/* The octave is part of the PITCH NAME ("B0"), not a reading off a scale — so it stays in the
   display face with the note letter. It was briefly set in mono on the theory that a digit is a
   measurement; seen at size that was wrong twice over: Plex Mono's default zero is SLASHED (the
   subset carries no 'zero' feature to turn it off), so "B0" rendered as B-with-a-crossed-nought,
   and a machine digit next to a musical letter broke the one word it belongs to. */
.note .oct{font-family:var(--display);font-size:.30em;color:var(--gold);transform:translateY(-.16em);margin-left:.16em}
.face.live .note{color:#fbf3df;text-shadow:0 2px 26px rgba(0,0,0,.55)}
/* unlit: the placeholder dash shrinks to a quiet panel mark instead of shouting
   at hero size, while the slot it reserves stays exactly the same. */
.face:not(.live) .note .lead{font-size:.34em;opacity:.5;color:var(--legend-idle)}

/* ── WHICH STRING ───────────────────────────────────────────────────────────
   "6th string" — the thing a beginner can actually act on. A note name is
   useless to someone who cannot map it to a peg, and the pitch letter alone
   leaves them guessing which of six they are holding.

   It sits ABOVE the note and stays deliberately quiet: it is context for the
   reading, not the reading. Reserves its line height even when empty (Auto and
   Chromatic have no string positions) so the note never jumps up and down as
   the label appears and disappears. */
/* gs-4ib: was --gold at opacity .62, measured 3.10:1 against the chassis. This element exists
   because a beginner cannot map a note name to a peg — the string number is the ONE thing they
   can act on — so dimming it below legibility worked against its own purpose. --gold-hi at full
   opacity measures 9.87:1. The idle dim below is untouched: that state carries no claim. */
.whichstring{font-family:var(--mono);font-size:calc(var(--t-legend) * .82);
  letter-spacing:.15em;text-transform:uppercase;text-align:center;
  color:var(--gold-hi);min-height:1.15em;line-height:1.15;
  margin:0 0 calc(var(--s1) * .5);transition:opacity .3s}
.face:not(.live) .whichstring{opacity:.3}

/* ── THE SNAP GUARD ─────────────────────────────────────────────────────────
   Shown alongside the reading, never instead of it. A pitch stranded between
   two open strings has no confident answer to "which string is this?", and a
   confident "tighten" there is exactly how a student winds a low E up toward A
   until it breaks. Amber, not red: this is "stop and check", not "error". */
.caution{font-family:var(--mono);font-size:calc(var(--t-legend) * .8);
  letter-spacing:.04em;text-align:center;line-height:1.3;color:#f2cd86;
  background:rgba(120,84,20,.3);box-shadow:inset 0 0 0 1px rgba(233,182,80,.34);
  border-radius:7px;padding:5px 11px;margin:var(--s2) auto 0;max-width:34ch;
  text-wrap:balance}
.caution[hidden]{display:none}

/* ── THE RADIO DIAL ────────────────────────────────────────────────────── */
.dialwrap{position:relative;margin:6px 2px 0;border-radius:14px;overflow:hidden;
  box-shadow:0 0 0 2px #2c2110, 0 0 0 5px var(--gold), 0 0 0 6.5px var(--gold-deep), 0 8px 20px rgba(0,0,0,.6)}
.dial{position:relative;height:150px;
  background:
    radial-gradient(80% 120% at 50% 118%, rgba(255,251,238,.96), rgba(255,231,180,.52) 30%, rgba(236,204,140,.16) 60%, transparent 78%),
    linear-gradient(180deg,var(--dial-hi),var(--dial) 52%,var(--dial-dk));
  transition:background .5s ease, box-shadow .5s ease;
}
.dial::after{content:"";position:absolute;inset:0;pointer-events:none;opacity:.35;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
.dial::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(158deg, rgba(255,255,255,.35) 0%, rgba(255,255,255,.05) 18%, transparent 38%)}

.zone{position:absolute;top:8px;bottom:26px;left:50%;width:12%;transform:translateX(-50%);border-radius:6px;
  background:rgba(60,150,80,.10);box-shadow:inset 0 0 0 1px rgba(40,110,60,.25);transition:.4s}

/* ── THE STRUCTURAL LOCK BRACKET ────────────────────────────────────────────
   In tune was signalled by a thin needle changing colour. A 3px stroke going
   green is invisible at three feet, invisible in peripheral vision — which is
   where it lives, because the student is looking at their hands — and invisible
   to a colour-blind player. The tick and the words help but are small.

   So the signal becomes a SHAPE. Two engraved marks sit either side of centre;
   when the pitch locks, the pointer swells into a solid block that fills the
   space between them. A structural change survives distance, a coloured stage
   wash, greyscale, and the corner of an eye — none of which a hue change does.
   The colour still changes too; it is simply no longer carrying the message
   alone. Top and bottom edges stay open so this reads as engraved gate marks
   rather than a box drawn around the pointer. */
.bracket{position:absolute;top:2px;bottom:20px;left:50%;width:13%;
  transform:translateX(-50%);pointer-events:none;border-radius:5px;
  border:2px solid transparent;border-top:none;border-bottom:none;
  transition:border-color .28s, box-shadow .28s}
.face.live .bracket{border-left-color:rgba(180,150,90,.34);border-right-color:rgba(180,150,90,.34)}
.face.tune-good .bracket{border-left-color:rgba(150,255,190,.95);border-right-color:rgba(150,255,190,.95);
  box-shadow:0 0 18px rgba(120,240,160,.4), inset 0 0 14px rgba(120,240,160,.2)}

.scale{position:absolute;inset:0;pointer-events:none}
.tick{position:absolute;bottom:26px;width:1.5px;background:rgba(92,69,38,.62);transform:translateX(-50%)}
.tick.maj{width:2px;background:rgba(36,26,15,.88)}
.tick.ctr{width:3px;background:var(--ink);box-shadow:0 0 0 .5px rgba(36,26,15,.5)}
/* Engraved scale markings on the dial face (♭ · 0 · ♯) — instrument engraving, not a digital
   readout, and the same slashed-zero problem applies to the centre mark. Display face. */
.lbl{position:absolute;bottom:6px;transform:translateX(-50%);font-family:var(--display);font-weight:400;
  font-size:calc(var(--t-legend) * 1.15);color:var(--ink-soft)}
.lbl.sym{font-size:calc(var(--t-legend) * 1.35)}

/* the SLIDING POINTER — vintage radio hairline (engine sets .left) */
.pointer{position:absolute;top:4px;bottom:22px;left:50%;width:3px;transform:translateX(-50%);pointer-events:none;
  background:linear-gradient(180deg,#ef6a3f,var(--red) 40%,var(--red-dk));border-radius:2px;
  box-shadow:0 0 10px 1px rgba(216,69,42,.7);
  transition:left .18s cubic-bezier(.22,1,.36,1), background .35s, box-shadow .35s, width .35s}
.pointer::before{content:"";position:absolute;top:-9px;left:50%;transform:translateX(-50%);
  width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:12px solid var(--red);
  filter:drop-shadow(0 0 4px rgba(216,69,42,.7));transition:border-top-color .35s}
.pointer::after{content:"";position:absolute;bottom:-7px;left:50%;transform:translateX(-50%);
  width:14px;height:14px;border-radius:50%;background:radial-gradient(circle at 38% 30%,#ffd9c8,var(--red) 60%,var(--red-dk));
  box-shadow:0 1px 3px rgba(0,0,0,.4);transition:background .35s}
.face:not(.live) .pointer{opacity:.5}

/* status row (tlamp already in header; here: word + lock badge) */
.tune-status{position:relative;z-index:2;display:flex;align-items:center;justify-content:center;gap:var(--s3);
  margin-top:var(--s4);min-height:30px}
/* CONTRAST FIX: this was --ink-soft (#5a4426) on the #42301a chassis — about
   1.3:1, effectively invisible, which is why "PLAY A STRING" vanished into the
   panel. It also carries the live cents readout ("12¢ flat ▲"), so it has to be
   legible at a glance while tuning. */
/* This line carries the live cents reading ("12¢ flat · tighten"), so it is mono and tabular: the
   number must not change width as it counts down, or it jitters while someone is turning the peg. */
/* Shrunk from .94 to .84 to pay for the larger note name. This is the deliberate trade from the
   3-feet review: the exact deviation is for someone leaning in to set intonation, and shrinking
   it costs that user nothing, while the note name it funds is the only thing a beginner across
   the room can use. */
.tstext{font-family:var(--mono);font-weight:400;font-size:calc(var(--t-legend) * .84);
  letter-spacing:var(--track-legend);text-transform:uppercase;
  color:var(--legend-idle);transition:.35s;font-feature-settings:"tnum";font-variant-numeric:tabular-nums}
.face.live .tstext{color:var(--cream)}
.lock{display:none;align-items:center;gap:var(--s2);animation:pop .4s cubic-bezier(.2,1.3,.4,1) both}
.lock .check{display:grid;place-items:center;width:26px;height:26px;border-radius:50%;background:var(--green);color:#06301a;font-size:15px;
  box-shadow:0 0 18px rgba(80,220,130,.75)}
.lock .locktxt{font-family:var(--display);font-weight:400;font-size:var(--t-lock);letter-spacing:.01em;color:var(--green-hi)}
@keyframes pop{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}

/* ── CLOSE (amber) ──────────────────────────────────────────────────────── */
.face.tune-close .pointer{background:linear-gradient(180deg,#ffd27a,var(--amber) 40%,var(--amber-dk));box-shadow:0 0 12px 2px rgba(233,182,80,.7)}
.face.tune-close .pointer::before{border-top-color:var(--amber-dk)}
.face.tune-close .pointer::after{background:radial-gradient(circle at 38% 30%,#fff0cf,var(--amber) 60%,var(--amber-dk))}
.face.tune-close .tstext{color:var(--amber-dk)}

/* ══ THE BIG IN-TUNE STATE — floods green, locks, shouts "In tune" ═══════════ */
.face.tune-good .dial{
  background:
    radial-gradient(85% 130% at 50% 118%, rgba(190,255,210,.98), rgba(96,224,150,.6) 32%, rgba(47,191,99,.22) 62%, transparent 82%),
    linear-gradient(180deg,#7ee0a2,#41c778 55%,#2ba85f);
  box-shadow:inset 0 0 40px rgba(20,120,60,.35);
}
.face.tune-good .zone{background:rgba(255,255,255,.22);box-shadow:inset 0 0 0 1px rgba(255,255,255,.5),0 0 22px rgba(120,240,160,.6)}
/* THE SHAPE CHANGE. The hairline becomes a solid block filling the bracket — this is the
   in-tune signal that does not depend on colour. Width is in % so it tracks the bracket's 13%
   at every viewport; the 4px inset leaves the engraved gate marks visible either side rather
   than covering them. `left` still animates from the engine, so the block arrives at centre
   rather than appearing there. */
.face.tune-good .pointer{width:calc(13% - 4px);opacity:1;border-radius:4px;
  background:linear-gradient(180deg,#d6ffe6,var(--green-hi) 35%,var(--green));
  box-shadow:0 0 20px 4px rgba(120,240,160,.9), inset 0 1px 0 rgba(255,255,255,.55)}
.face.tune-good .pointer::before{border-top-color:#eafff1;filter:drop-shadow(0 0 8px rgba(120,240,160,1))}
.face.tune-good .pointer::after{background:radial-gradient(circle at 38% 30%,#eafff1,var(--green-hi) 55%,var(--green-dk))}
.face.tune-good .tlamp{background:radial-gradient(circle at 36% 30%,#d6ffe6,#35c46a 58%,#1c7a42);box-shadow:0 0 18px 4px rgba(80,220,130,.85),inset 0 0 3px rgba(255,255,255,.6)}
.face.tune-good .note{color:#eafff1;text-shadow:0 0 26px rgba(90,230,140,.7)}
.face.tune-good .tstext{display:none}
.face.tune-good .lock{display:inline-flex}
.face.tune-good{box-shadow:0 34px 70px -18px rgba(0,0,0,.75),0 0 40px -4px rgba(60,200,110,.5),
  inset 0 1px 0 rgba(255,240,200,.22),inset 0 0 0 1px rgba(0,0,0,.72),inset 0 0 0 2px rgba(120,220,150,.62)}

/* ── controls ──────────────────────────────────────────────────────────── */
.go{display:block;width:100%;margin:var(--s5) 0 0;padding:var(--s4);cursor:pointer;appearance:none;border:0;border-radius:14px;
  font-family:var(--mono);font-weight:600;font-size:calc(var(--t-btn) * .86);color:#241a0f;min-height:52px;
  letter-spacing:.13em;text-transform:uppercase;
  background:linear-gradient(180deg,#faecc0,#e6c67c 46%,#c49f52);
  box-shadow:0 1px 0 rgba(255,250,228,.75) inset,0 -2px 7px rgba(80,56,16,.32) inset,0 3px 0 var(--gold-dk),0 10px 20px rgba(0,0,0,.42);transition:.12s}
.go:active{transform:translateY(2px);box-shadow:0 1px 0 rgba(255,250,228,.75) inset,0 1px 0 var(--gold-dk)}
/* Stop is deliberately quiet — it is the "I am done" exit, not an invitation mid-tune — but it
   still clears text contrast; the old --dim on near-black was decorative rather than readable. */
.go.stop{background:linear-gradient(180deg,#33251a,#1b1109);color:#cbb187;
  box-shadow:0 2px 0 #0d0805,inset 0 1px 0 rgba(255,240,200,.10),inset 0 0 0 1px rgba(207,169,85,.22)}
.go:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
/* Helper line and the A4 control used to sit in one wrapping flex row, so on a
   phone they broke into a ragged two-line stack with uneven gaps. Now the
   helper owns its line and the control is centred beneath it at every width. */
.subrow{display:flex;flex-direction:column;align-items:center;gap:var(--s3);margin-top:var(--s4)}
/* no ch-based cap here: at this size 34ch measured narrower than the panel and
   forced a mid-phrase break ("slide / to center"). The panel is the measure. */
.status{font-family:var(--label);font-style:italic;font-size:calc(var(--t-micro) * 1.12);color:var(--helper);margin:0;text-align:center;
  text-wrap:balance;line-height:1.5}
.status.err{color:var(--red);font-style:normal;font-family:var(--mono);font-size:var(--t-micro);letter-spacing:.02em}
/* SCREEN-READER ONLY (gs-05h). Takes no space and paints nothing, but STAYS in the
   accessibility tree — display:none and visibility:hidden would remove it and the live
   region would never announce. The 1px+clip technique is the only one that does both. */
.a11y-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
/* TRUST LINE (gs-rv0). Quieter than the helper it sits under — it is a standing fact, not
   guidance, and it must never compete with the reading. Deliberately has no hidden state and
   no dismiss: a promise you can close is a promise you can miss. */
/* No opacity here. I shipped this at opacity:.72 for visual quietness and it dropped the line
   to 3.85:1 — a promise about privacy that a low-vision reader cannot read is not a promise.
   Quietness now comes from size and letter-spacing alone (gs-4ib). */
.privacy{font-family:var(--mono);font-size:calc(var(--t-micro) * .82);letter-spacing:.04em;
  color:var(--helper);margin:0;text-align:center}
/* the one-time silent-switch note, same slot, gold so it reads as reassurance not error */
.silentnote{font-family:var(--mono);font-size:calc(var(--t-micro) * .82);letter-spacing:.04em;
  color:var(--gold-hi);margin:0;text-align:center;text-wrap:balance}
.silentnote[hidden]{display:none}
.gear{appearance:none;cursor:pointer;border:0;border-radius:10px;padding:var(--s2) var(--s4);font-family:var(--mono);
  font-size:11.5px;letter-spacing:.11em;text-transform:uppercase;min-height:44px;
  color:var(--gold-hi);background:linear-gradient(180deg,rgba(207,169,85,.20),rgba(207,169,85,.06));
  box-shadow:inset 0 0 0 1px rgba(207,169,85,.38);transition:background .2s,box-shadow .2s}
.gear:hover{background:linear-gradient(180deg,rgba(207,169,85,.30),rgba(207,169,85,.12));box-shadow:inset 0 0 0 1px rgba(207,169,85,.6)}
.gear:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
#a4tag{font-weight:600;font-variant-numeric:tabular-nums;color:#fbf3df}

/* ── the peg strip: whole-guitar sweep ─────────────────────────────────── */
/* One peg per string of the chosen tuning, low to high. Unlit = still to do, lit gold = the string
   being played, green = confirmed in tune. The point is to answer "which strings are left?" without
   the player having to remember. */
.strings{display:flex;justify-content:center;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s4)}
.strings[hidden]{display:none}
/* Pegs are real buttons — tapping one PLAYS that string, so they need a touch target and an
   affordance. 44px is the Apple/WCAG-2.5.5 minimum, and it matters more than usual here: you tap
   these one-handed while the other hand holds the neck, and a missed tap sounds the wrong string. */
.peg{display:grid;place-items:center;min-width:44px;min-height:44px;padding:var(--s1) var(--s2);
  border:0;border-radius:8px;cursor:pointer;appearance:none;
  font-family:var(--mono);font-weight:600;font-size:calc(var(--t-legend) * .94);line-height:1.5;letter-spacing:.03em;
  color:var(--legend-idle);background:rgba(0,0,0,.26);
  box-shadow:inset 0 0 0 1px rgba(207,169,85,.20);
  transition:color .3s,background .3s,box-shadow .3s,transform .1s}
.peg:hover{color:var(--gold-hi);box-shadow:inset 0 0 0 1px rgba(207,169,85,.45)}
.peg:active{transform:translateY(1px)}
.peg:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
/* SOUNDING — this peg is ringing right now. Brass glow, distinct from the green of "in tune". */
.peg.sounding{color:#fff8e6;background:rgba(207,169,85,.32);
  box-shadow:inset 0 0 0 1px rgba(247,233,192,.85),0 0 18px rgba(224,180,86,.55)}
.peghint{flex-basis:100%;text-align:center;margin-top:var(--s2);
  font-family:var(--label);font-style:italic;font-size:calc(var(--t-micro) * 1.08);color:var(--helper)}
.peg.active{color:var(--gold-hi);background:rgba(207,169,85,.18);box-shadow:inset 0 0 0 1px rgba(207,169,85,.6)}
.peg.done{color:#eafff1;background:rgba(47,191,99,.28);box-shadow:inset 0 0 0 1px rgba(120,240,160,.65)}
.peg.done.active{box-shadow:inset 0 0 0 1px rgba(120,240,160,.9),0 0 14px rgba(80,220,130,.55)}
/* whole instrument confirmed — a quiet, earned glow rather than another alarm */
.strings.all-done .peg{background:rgba(47,191,99,.34);box-shadow:inset 0 0 0 1px rgba(120,240,160,.8)}

/* the two panel controls sit on one line under the helper text */
.ctrls{display:flex;align-items:center;justify-content:center;gap:var(--s2);flex-wrap:wrap}

/* ── tuning picker list ────────────────────────────────────────────────── */
.tunelist{display:grid;gap:var(--s2);max-height:56vh;overflow-y:auto;padding:2px}
.tune-opt{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);width:100%;
  appearance:none;cursor:pointer;border:0;border-radius:11px;padding:var(--s3) var(--s4);text-align:left;
  min-height:48px;color:var(--cream);background:rgba(0,0,0,.3);
  box-shadow:inset 0 0 0 1px rgba(207,169,85,.26);transition:background .18s,box-shadow .18s}
.tune-opt:hover{background:rgba(207,169,85,.13)}
.tune-opt .tname{font-family:var(--display);font-weight:400;font-size:calc(var(--t-body) * 1.12);letter-spacing:.005em}
.tune-opt .tpegs{font-family:var(--mono);font-size:10.5px;color:var(--helper);
  letter-spacing:.12em;white-space:nowrap}
.tune-opt.on{background:rgba(207,169,85,.20);box-shadow:inset 0 0 0 2px var(--gold)}
.tune-opt.on .tpegs{color:var(--gold-hi)}
.tune-opt:focus-visible{outline:2px solid var(--gold);outline-offset:2px}

/* ── settings sheet (reference-pitch dial) ─────────────────────────────── */
.settings{position:fixed;inset:0;z-index:20;display:grid;place-items:center;padding:20px}
.settings[hidden]{display:none}
.settings .backdrop{position:absolute;inset:0;background:rgba(12,8,4,.72);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.settings .sheet{position:relative;width:min(420px,94vw);padding:var(--s6) var(--s5) var(--s5);border-radius:22px;text-align:center;
  background:linear-gradient(180deg,var(--shell-hi),var(--shell) 58%,var(--shell-dk));
  box-shadow:var(--cab-shadow),inset 0 0 0 1px rgba(0,0,0,.72),inset 0 0 0 2px rgba(207,169,85,.46)}
.settings .sheet-title{font-family:var(--mono);font-size:11.5px;letter-spacing:.19em;text-transform:uppercase;color:var(--amber);
  margin:0 0 var(--s4)}
.dial-sheet, .settings .dial{height:96px;border-radius:14px;overflow:hidden;cursor:ew-resize;touch-action:none;position:relative;
  background:linear-gradient(180deg,var(--dial-hi),var(--dial-dk));box-shadow:inset 0 2px 8px rgba(80,54,18,.38),inset 0 0 0 2px var(--gold-deep)}
.settings .dial .glow{position:absolute;top:0;bottom:0;width:120px;transform:translateX(-50%);pointer-events:none;
  background:radial-gradient(closest-side,rgba(216,69,42,.5),transparent 72%);mix-blend-mode:multiply}
.settings .dial .scale{position:absolute;inset:0;pointer-events:none}
.settings .dial .tick{position:absolute;bottom:0;width:1px;background:#6e5121;transform:translateX(-50%)}
.settings .dial .num{position:absolute;bottom:20px;transform:translateX(-50%);font-family:var(--mono);font-size:12px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.settings .dial .needle{position:absolute;top:2px;bottom:2px;width:2px;transform:translateX(-50%);pointer-events:none;
  background:linear-gradient(180deg,#ef6a3f,var(--red-dk));box-shadow:0 0 6px rgba(216,69,42,.8)}
.settings .dial .lug{position:absolute;top:-1px;left:50%;transform:translateX(-50%);width:0;height:0;
  border-left:6px solid transparent;border-right:6px solid transparent;border-top:9px solid var(--red)}
.settings .dial .glassr{position:absolute;inset:0;pointer-events:none;background:linear-gradient(120deg,rgba(255,255,255,.35),transparent 40%)}
.a4read{margin-top:var(--s4);font:var(--t-mark)/1.2 var(--mono);font-weight:600;letter-spacing:.04em;color:var(--gold-hi);font-variant-numeric:tabular-nums}
.a4read .a{color:var(--gold);font-family:var(--display);font-weight:400} .a4read small{color:var(--helper);font-size:var(--t-micro);font-style:italic;font-family:var(--label);letter-spacing:0}
#a4val{font-variant-numeric:tabular-nums}
/* B8: "Reset to A = 440 Hz" after a double-tap — quiet helper text, gone after 3 s */
.a4note{margin:var(--s2) 0 0;font-family:var(--label);font-style:italic;font-size:calc(var(--t-micro) * 1.08);color:var(--helper)}
.a4note[hidden]{display:none}
.settings .done{appearance:none;margin-top:var(--s5);padding:var(--s3) var(--s6);border-radius:14px;cursor:pointer;min-height:48px;
  font-family:var(--mono);font-weight:600;font-size:calc(var(--t-btn) * .86);letter-spacing:.13em;text-transform:uppercase;color:#241a0f;border:0;
  background:linear-gradient(180deg,#faecc0,#e6c67c 46%,#c49f52);box-shadow:0 3px 0 var(--gold-dk),inset 0 1px 0 rgba(255,255,255,.55)}
.settings .done:active{transform:translateY(2px);box-shadow:0 1px 0 #7c5f26}

/* ── ?debug overlay + embed mode ───────────────────────────────────────── */
.debug-overlay{position:fixed;top:8px;left:8px;z-index:99;margin:0;padding:6px 9px;font:11px/1.55 ui-monospace,Menlo,monospace;
  color:#d6e4d6;background:rgba(10,8,4,.86);border:1px solid rgba(200,180,120,.3);border-radius:6px;white-space:pre;pointer-events:none;max-width:calc(100vw - 16px);overflow:hidden}
html[data-embed="tuner"] body{padding:40px 12px 18px;gap:0}
/* Embedded, the HOST page is the room — paint none of our own, so the faceplate floats on the
   host's surface instead of sitting in a second box (Rotem 08-13: "remove the BOX around the
   tuner"). Transparency only exists in embed mode; the standalone app keeps its room. */
html[data-embed="tuner"], html[data-embed="tuner"] body{background:transparent}
/* Transparency only survives when embedder and embedded agree on color-scheme — a mismatch
   makes Chrome paint an opaque white canvas behind the document (the exact white box this
   rule chain exists to remove). The freezone host declares color-scheme:dark. */
html[data-embed="tuner"]{color-scheme:dark}

/* ── VERY NARROW PHONES (iPhone SE and friends) ─────────────────────────────
   Six 44px pegs plus gaps cannot fit one row at 320px, so the strip wraps — it already did at the
   old 42px. Raising the targets to the 44px minimum added 14px of height on top of that and pushed
   the bottom control past the fold, so the space is taken back from the GAPS, never from the
   targets: what you have to hit stays 44px. */
@media (max-width:360px){
  /* Six 44px pegs cannot share a row at this width, and the natural break is 5+1 — one orphaned
     string that reads as a mistake. Capping the strip at three pegs makes it break 3+3, which
     looks like a decision and mirrors how the strings sit in pairs on the neck anyway.
     (Width-scoped, not height-scoped: wrapping is a width problem.) */
  .strings{max-width:calc(44px * 3 + var(--s1) * 2);margin-left:auto;margin-right:auto}
  .strings{gap:var(--s1);margin-top:var(--s2)}
  .peghint{margin-top:0}
  .go{margin-top:var(--s3)}
  .subrow{margin-top:var(--s2)}
}

/* ── COMPACT PORTRAIT: ordinary phones up to 760px tall (audit 2026-10-13, B7) ──────────────
   Listening in Standard — six pegs, their caption, the in-tune badge and the one-time silent-switch
   note all on screen — the Tuning and A4 buttons sat 76-83px BELOW the fold on the SE 2/3
   (375x667) and on an iPhone 15 in Safari (390x664, the height left between Safari's bars):
   the bottoms measured 743 and 747. The space comes out of padding, gaps and 24px of dial height;
   the pointer keeps its full travel and every touch target stays 44px. 390x844 and taller are
   untouched (they have the room). Must stay BEFORE the short tier below, which tightens further.
   Gate: test/short-portrait.test.js + the B7 checks in e2e/audit-20261013.spec.js. */
@media (orientation:portrait) and (max-height:760px){
  body{padding:var(--s4) var(--s4) calc(var(--s4) + env(safe-area-inset-bottom));gap:var(--s5)}
  .face{padding:var(--s4) var(--s5) var(--s4)}
  .head{margin-bottom:var(--s3)}
  .dial{height:126px}
  .tune-status{margin-top:var(--s2)}
  .strings{margin-top:var(--s2)}
  .go{margin-top:var(--s3)}
  .subrow{margin-top:var(--s3);gap:var(--s2)}
}

/* ── SHORT PORTRAIT: the original iPhone SE / 5s (320x568) ──────────────────
   Measured on production: "Tap to tune" sat at y=581 in a 568px viewport — the control that starts
   the app was below the fold. The shortfall is only 13px, so it comes out of the outer padding and
   a little dial height; the pointer keeps its full travel and every touch target stays 44px.

   Bounded at 620px on purpose: it catches 568 (the 2016 SE) and leaves 667 to the compact tier
   above. CORRECTED 2026-10-13 (audit B7): this comment used to say the 375x667 SE "already fits
   with ~105px to spare" — that was measured on the idle screen in Auto, with no peg strip; while
   listening in Standard the Tuning and A4 buttons were below the fold there. 320x480 is not
   supported: it needs 101px, which would mean gutting the dial and the peg strip for an
   iPhone-4-era viewport. */
@media (orientation:portrait) and (max-height:620px){
  body{padding:var(--s4) var(--s4) calc(var(--s4) + env(safe-area-inset-bottom));gap:var(--s5)}
  .face{padding:var(--s5) var(--s5) var(--s4)}
  .head{margin-bottom:var(--s3)}
  .note{margin-bottom:var(--s1)}
  .dial{height:126px}
  .strings{margin-top:var(--s3)}
  .go{margin-top:var(--s3)}
}

/* ── LANDSCAPE: a phone on its side ─────────────────────────────────────────
   How a guitarist actually props a phone while both hands are on the instrument. The portrait
   stack is 646px tall, so at 844x390 the "Tap to tune" button landed at y=580 — below the fold,
   under a large empty gap and half a dial. Unusable without scrolling.

   Here the instrument turns sideways instead of getting squashed: identity + readout + action in a
   left column, the dial and its indicators on the right, where the extra width actually is.
   max-height guards it to phone-sized landscape — a desktop monitor is landscape too, and the
   portrait stack is right there. */
@media (orientation:landscape) and (max-height:560px){
  /* A6 (audit 2026-10-13): this was clamp(40px,10vh,56px) — a 40px note, ~40% of portrait, in the
     posture a phone sits on a music stand. The note name is the one thing read from three feet, so
     it is the LAST thing to shrink; the room comes from moving the helper row (below) to a full-width
     line at the bottom, where the right column had dead space. */
  :root{ --t-note:clamp(64px,19vh,84px); }
  body{padding:var(--s3) var(--s4) calc(var(--s3) + env(safe-area-inset-bottom));gap:var(--s4)}
  .cab{width:min(760px,96vw)}

  .face{
    display:grid;
    grid-template-columns:minmax(150px,.85fr) minmax(300px,1.15fr);
    /* `which` (the string label) rides directly above the note in the left column, and `caut`
       (the snap guard) sits under the status line in the right column with the rest of the
       guidance. Both need explicit areas: an element with no area gets auto-placed, which in a
       fixed template means it lands in an arbitrary cell and shoves the instrument apart. */
    grid-template-areas:
      "mark   dial"
      "which  dial"
      "note   status"
      "note   caut"
      "go     pegs"
      "sub    sub";
    align-items:center; column-gap:var(--s5);
    padding:var(--s4) var(--s5);
  }
  .head{grid-area:mark;margin:0 0 var(--s1)}
  .whichstring{grid-area:which;margin:0;text-align:left}
  .note{grid-area:note;margin:0;min-height:0}
  .dialwrap{grid-area:dial;margin:0}
  .tune-status{grid-area:status;margin-top:var(--s2)}
  .caution{grid-area:caut;margin:var(--s1) 0 0}
  .strings{grid-area:pegs;margin-top:var(--s2)}
  .go{grid-area:go;margin:var(--s3) 0 0}
  /* the helper, the trust line and the two panel buttons share ONE full-width line (wrapping only
     when the one-time silent note or an error needs it) instead of a 100px stack in the left column */
  .subrow{grid-area:sub;margin-top:var(--s3);flex-direction:row;flex-wrap:wrap;justify-content:center;
    column-gap:var(--s4);row-gap:var(--s1)}

  .dial{height:104px}                 /* the pointer still has full width to travel */
  /* Pegs keep the full 44px target in landscape too. Making the sideways layout fit is not a
     reason to hand someone a 34px button while they are holding a guitar — the room is found by
     tightening the gaps and the dial, not the things you have to hit. */
  .peg{min-height:44px;min-width:44px}
  .strings{gap:var(--s1)}
}

@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* ── intonation compare (chromatic mode only) ──────────────────────────────
   Capture the 12th-fret harmonic, then fret the 12th: the app subtracts and names the saddle
   direction. The two readings never coexist on screen otherwise, and the difference that matters
   (3-12¢) is the same size as the ±5¢ in-tune band — so this is the one number a person cannot
   reliably eyeball across two plucks. */
.intn{display:flex;flex-direction:column;align-items:center;gap:var(--s2);margin-top:var(--s4)}
.intn[hidden]{display:none}
.intn-out{margin:0;min-height:1.4em;font-family:var(--label);font-style:italic;
  font-size:calc(var(--t-micro) * 1.08);color:var(--helper);text-align:center;text-wrap:balance}
.intn-out.good{font-style:normal;letter-spacing:.06em;text-transform:uppercase;color:var(--green-hi)}
.intn-out.sharp,.intn-out.flat{font-style:normal;letter-spacing:.06em;text-transform:uppercase;color:var(--amber)}
.intn-out.different-note{color:var(--red)}

/* ══ WASHI — a light skin, written against the REAL markup ═══════════════════
   First attempt targeted .chassis/.panel/.shell — class names I assumed. The app uses
   .cab (cabinet), .face (the lacquered panel), .dial/.scale, .go and .gear for controls.
   Read from the live DOM, not guessed, which is why the background turned to paper and
   the chassis stayed black. Opt-in via ?skin=washi; the standalone app is untouched. */
/* Two palettes, one structure: every structural rule below matches [data-skin^="washi"]
   so "washi" (rice paper) and "washi-dark" (the Practice Room's EVENING) share the same
   flattening; only the --w-* palette differs. Rotem 08-17: switching the page to evening
   left the tuner white — the dark variant did not exist. */
:root[data-skin="washi"]{
  --shell-hi:#eae1cd; --shell:#e0d6c0; --shell-dk:#d3c7ab;
  --gold-hi:#a04324; --gold:#a04324; --gold-dk:#7d3319; --gold-deep:#cfc3a6;
  --dial-hi:#f4efe4; --dial:#eae1cd; --dial-dk:#ded2b8;
  --cream:#f2ece0; --amber:#a04324; --amber-dk:#7d3319;
  --ink:#1c1712; --ink-soft:#4a4131; --dim:#635a48;
  --red:#a04324; --red-dk:#7d3319;
  /* The vintage skin's tan bled in here exactly as it did on moon — but rice is LIGHT PAPER, so
     #bd9969 measured 2.04:1 on the sheet and the guidance and trust lines were unreadable, not
     merely off-palette. Set to rice's OWN existing accent (4.86:1): this fixes the defect without
     deciding the open question of whether rice keeps the terracotta or moves to the deeper
     antique golds the system specifies for light papers. That call is Rotem's. */
  --helper:#a04324;
  --green:#3f6b3b; --green-hi:#2f5c2c; --green-dk:#345a31;
  --display:'Fraunces',Georgia,serif; --label:'Fraunces',Georgia,serif;
  --mono:'Fraunces',Georgia,serif;
  /* washi-scoped structure palette */
  --w-paper:#e0d6c0; --w-sheet:#eae1cd; --w-dial:#f4efe4; --w-border:#bfb191;
  /* rice is UNCHANGED here: it still carries the overruled terracotta. --w-seal-text only
     exists so the shared [data-skin^=washi] rules resolve; moving rice to its own golds
     (#8a6a12 marks / #7d5f10 text, per the README) is a separate call of Rotem's. */
  --w-ink:#1c1712; --w-dim:#635a48; --w-seal:#a04324; --w-seal-text:#a04324; --w-onink:#eae1cd; --w-tick:#4a4131;
}
:root[data-skin="washi-dark"]{
  --shell-hi:#282926; --shell:#20211f; --shell-dk:#1a1b19;
  /* THE ACCENT IS GOLD. Rotem, 2026-08-19: "no I liked that better than the red." A 3-round
     team review recommended terracotta; he overruled it. This skin shipped 08-17, one day
     before the ruling, and carried the overruled colour until 08-19. Two values, per
     WASHI_DESIGN_SYSTEM/README.md: marks are specified against the 3:1 bar, TEXT against 4.5. */
  --gold-hi:#d4a017; --gold:#c9a227; --gold-dk:#a8871f; --gold-deep:#3a3b37;
  --dial-hi:#2c2d2a; --dial:#282926; --dial-dk:#232421;
  --cream:#efe9da; --amber:#c9a227; --amber-dk:#a8871f;
  --ink:#efe9da; --ink-soft:#c8c2b4; --dim:#a49d8e;
  /* NOT part of the accent ruling. .status.err uses this, and an error painted in the accent
     colour is an error nobody sees. Lifted off the overruled #d4714f only because that measured
     4.37:1 on the sheet — under the bar — not because the hue was wrong. */
  --red:#dd7f5c; --red-dk:#c46a49;
  /* the vintage skin's tan (#bd9969) bled through here until 08-19, putting a second accent on
     the face; the system's rule is one lamp, one colour. */
  --helper:#d4a017;
  --green:#7fae6f; --green-hi:#8fbe7f; --green-dk:#6a9a5c;
  --display:'Fraunces',Georgia,serif; --label:'Fraunces',Georgia,serif;
  --mono:'Fraunces',Georgia,serif;
  --w-paper:#20211f; --w-sheet:#282926; --w-dial:#2c2d2a; --w-border:#3f403c;
  --w-ink:#efe9da; --w-dim:#a49d8e; --w-seal:#c9a227; --w-seal-text:#d4a017; --w-onink:#20211f; --w-tick:#c8c2b4;
}
/* the page is paper; the lacquered face becomes a drawn sheet on it */
:root[data-skin^="washi"] body{ background-image:none !important; background-color:var(--w-paper) !important; }
:root[data-skin^="washi"] .face{
  background-image:none !important; background-color:var(--w-sheet) !important;
  border:1px solid var(--w-border) !important; border-radius:3px !important; box-shadow:none !important;
}
:root[data-skin^="washi"] .cab{ box-shadow:none !important; filter:none !important; }
:root[data-skin^="washi"] .cab::before,:root[data-skin^="washi"] .cab::after,
:root[data-skin^="washi"] .face::before,:root[data-skin^="washi"] .face::after{ display:none !important; }
/* the lit dial: paper with graphite ticks, no brass bezel */
:root[data-skin^="washi"] .dial,:root[data-skin^="washi"] .dialwrap,:root[data-skin^="washi"] .scale{
  background-image:none !important; background-color:var(--w-dial) !important;
  border:1.5px solid var(--w-border) !important; box-shadow:none !important; border-radius:2px !important;
}
:root[data-skin^="washi"] .tick{ background:var(--w-tick) !important; }
/* controls become drawn marks; the primary action is the one ink-filled thing */
:root[data-skin^="washi"] .gear{
  background-image:none !important; background-color:transparent !important;
  border:1.5px solid var(--w-border) !important; border-radius:2px !important;
  color:var(--w-ink) !important; box-shadow:none !important;
  font-family:'Fraunces',Georgia,serif !important;
}
:root[data-skin^="washi"] .gear:hover{ border-color:var(--w-seal) !important; color:var(--w-seal-text) !important; }
:root[data-skin^="washi"] .go{
  background-image:none !important; background-color:var(--w-ink) !important; color:var(--w-onink) !important;
  border:1.5px solid var(--w-ink) !important; border-radius:2px !important; box-shadow:none !important;
  font-family:'Fraunces',Georgia,serif !important; letter-spacing:.02em !important;
}
:root[data-skin^="washi"] .go:hover{ background-color:var(--w-seal) !important; border-color:var(--w-seal) !important; }
/* type + the note read as ink */
:root[data-skin^="washi"] .mark .name,:root[data-skin^="washi"] .subbrand,
:root[data-skin^="washi"] .note,:root[data-skin^="washi"] .lbl,
:root[data-skin^="washi"] .whichstring,:root[data-skin^="washi"] .tstext{
  font-family:'Fraunces',Georgia,serif !important; color:var(--w-ink) !important; text-shadow:none !important;
}
:root[data-skin^="washi"] .subbrand,:root[data-skin^="washi"] .whichstring{ color:var(--w-dim) !important; }
:root[data-skin^="washi"] .needle{ background:var(--w-seal) !important; box-shadow:none !important; }
:root[data-skin^="washi"] *{ text-shadow:none !important; }

/* ══ WASHI — PENCIL PASS (2026-08-18, Rotem: "same pencil vibe") ═══════════════════
   The first washi pass repainted surfaces; the radio-dial CHROME survived (bezel rings,
   gloss overlays, gold pointer + lamp, green flood, glow). Everything below is drawn: a
   paper dial with graphite ticks, a single ink needle, the in-tune state as a SHAPE + one
   seal — no light effects. Corner screws + tone lamp go; the ink underline stays. */
:root[data-skin^="washi"] .dialwrap{box-shadow:none !important;border:1.5px solid var(--w-border) !important;border-radius:3px !important;}
:root[data-skin^="washi"] .dial{background:var(--w-dial) !important;background-image:none !important;box-shadow:none !important;}
:root[data-skin^="washi"] .dial::before,:root[data-skin^="washi"] .dial::after{display:none !important;}
:root[data-skin^="washi"] .zone{background:transparent !important;box-shadow:none !important;
  border-left:1px dashed rgba(26,21,16,.28);border-right:1px dashed rgba(26,21,16,.28);border-radius:0 !important;}
:root[data-skin^="washi"] .bracket{border-color:transparent !important;box-shadow:none !important;}
:root[data-skin^="washi"] .face.live .bracket{border-left-color:rgba(26,21,16,.35) !important;border-right-color:rgba(26,21,16,.35) !important;}
:root[data-skin^="washi"] .tick{background:var(--w-tick) !important;box-shadow:none !important;opacity:.85;}
:root[data-skin^="washi"] .tick.maj{background:var(--w-ink) !important;}
:root[data-skin^="washi"] .tick.ctr{background:var(--w-ink) !important;width:2.5px !important;box-shadow:none !important;}
/* the needle: one ink line; close = seal; in tune = a seal BLOCK between the gate marks (shape, not glow) */
:root[data-skin^="washi"] .pointer{background:var(--w-ink) !important;box-shadow:none !important;width:2.5px !important;border-radius:0 !important;}
:root[data-skin^="washi"] .pointer::before{border-top-color:var(--w-ink) !important;filter:none !important;}
:root[data-skin^="washi"] .pointer::after{background:var(--w-ink) !important;box-shadow:none !important;}
:root[data-skin^="washi"] .face.tune-close .pointer{background:var(--w-seal) !important;box-shadow:none !important;}
:root[data-skin^="washi"] .face.tune-close .pointer::before{border-top-color:var(--w-seal) !important;}
:root[data-skin^="washi"] .face.tune-good .dial{background:var(--w-dial) !important;background-image:none !important;box-shadow:none !important;}
:root[data-skin^="washi"] .face.tune-good .zone{background:rgba(160,67,36,.08) !important;box-shadow:none !important;border-color:var(--w-seal) !important;}
:root[data-skin^="washi"] .face.tune-good .bracket{border-left-color:var(--w-seal) !important;border-right-color:var(--w-seal) !important;box-shadow:none !important;}
:root[data-skin^="washi"] .face.tune-good .pointer{background:var(--w-seal) !important;box-shadow:none !important;border-radius:2px !important;}
:root[data-skin^="washi"] .face.tune-good .pointer::before{border-top-color:var(--w-seal) !important;filter:none !important;}
:root[data-skin^="washi"] .face.tune-good .pointer::after{background:var(--w-seal) !important;}
:root[data-skin^="washi"] .face.tune-good .note{color:var(--w-seal) !important;text-shadow:none !important;}
:root[data-skin^="washi"] .face.tune-good .tlamp,:root[data-skin^="washi"] .tlamp{display:none !important;}
/* chrome details that read "radio": corner screws, lamp, gloss */
:root[data-skin^="washi"] .screw,:root[data-skin^="washi"] .face > .screw,:root[data-skin^="washi"] [class*="screw"]{display:none !important;}
:root[data-skin^="washi"] .face{border-radius:3px !important;}
/* the mark + labels: ink, no gold */
:root[data-skin^="washi"] .mark .name{color:var(--w-ink) !important;font-weight:400 !important;}
:root[data-skin^="washi"] .subbrand{color:var(--w-dim) !important;letter-spacing:.14em !important;}
:root[data-skin^="washi"] .lock,:root[data-skin^="washi"] .lock .locktxt{color:var(--w-seal) !important;text-shadow:none !important;}
:root[data-skin^="washi"] .lock *{filter:none !important;box-shadow:none !important;}
/* settings / a4 dial sheet in the same paper */
:root[data-skin^="washi"] .dial-sheet,:root[data-skin^="washi"] .settings .dial{background:var(--w-dial) !important;background-image:none !important;box-shadow:none !important;border:1.5px solid var(--w-border) !important;border-radius:3px !important;}
:root[data-skin^="washi"] .settings .dial .tick{background:var(--w-tick) !important;}
:root[data-skin^="washi"] .a4read,:root[data-skin^="washi"] .a4read .a{color:var(--w-ink) !important;text-shadow:none !important;}
:root[data-skin^="washi"] #a4tag{color:var(--w-seal-text) !important;}
:root[data-skin^="washi"] .tune-opt .tname{color:var(--w-ink) !important;}
:root[data-skin^="washi"] .helper,:root[data-skin^="washi"] .tstext{color:var(--w-dim) !important;}
:root[data-skin^="washi"] .whichstring{color:var(--w-dim) !important;font-style:italic;}

/* gs-mse — OLED burn-in fade. A tuner is the worst case: lit, static, pointed at the same pixels
   for a whole practice session. After 60 s of silence the face dims; the first frame of signal
   removes .dozing and it is instantly back (the transition is deliberately asymmetric — 1.2 s to
   fade down so it is never distracting, 0 s to come back so it is never in the way). Honoured
   under reduced-motion too: dimming is a brightness change, not motion, and the blanket
   prefers-reduced-motion rule kills only the transition, not the effect. */
.face{transition:filter 1.2s ease-out,opacity 1.2s ease-out}
.face.dozing{filter:brightness(.42) saturate(.85);opacity:.9}
.face:not(.dozing){transition:filter 0s,opacity 0s}

/* gs-5zg — 'by Rotem Sivan' wordmark, idle only. It is a signature, not an advert: it sits under
   the brand mark on the idle screen and disappears the moment the tuner is listening, so nothing
   competes with the note. Sized and coloured as helper text; underline only on hover/focus so it
   reads as part of the faceplate rather than a web link. */
.byline{font-family:var(--label);font-style:italic;
  font-size:calc(var(--t-micro) * 1.02);letter-spacing:.01em;color:var(--helper);
  text-decoration:none;opacity:.92;
  /* B9 (audit 2026-10-13): the only link in the app was a 73x19 px target. The tappable box is now
     44px tall (and at least 44 wide); the negative margins hand the extra 25px back, so the text
     sits exactly where it did and the header does not grow. */
  display:inline-flex;align-items:center;min-height:44px;min-width:44px;
  margin:calc(var(--s1) - 12.5px) 0 -12.5px}
.byline:hover,.byline:focus-visible{color:var(--gold);text-decoration:underline}
.face.live .byline{display:none}

/* gs-r9p — mic-denied recovery panel. Sits in the flow where the Tap-to-tune button is, so the
   player's eye is already there. Numbered steps because the fix is a sequence in another app, and
   a big real button because "Try again" is the whole point of the panel. */
.micoff{display:grid;gap:var(--s3);padding:var(--s4);border-radius:12px;
  background:rgba(20,14,8,.55);border:1px solid var(--gold-dk);text-align:left;
  /* A4 (audit 2026-10-13): was max-width:34ch, so the panel sat narrow against the left edge with
     dead space to its right. It now spans the face like the dial and the button it replaces. */
  width:100%}
.micoff[hidden]{display:none}
.micoff-title{margin:0;font-family:var(--display);font-weight:400;
  font-size:calc(var(--t-body) * 1.15);color:var(--gold-hi);letter-spacing:.01em}
/* A4 (audit 2026-10-13): the steps were var(--ink-soft) — dark ink made for the LIT DIAL — on this
   near-black glass: 1.95-2.07:1 on rendered pixels, the one screen a stuck player has to read.
   --cream is the face's own live-text colour (test/mic-panel-contrast.test.js gates >= 4.5:1). */
.micsteps{margin:0;padding-left:1.15em;display:grid;gap:var(--s1);
  font-family:var(--label);font-size:calc(var(--t-micro) * 1.12);color:var(--cream);line-height:1.45}
.micwhy{font-family:var(--mono);font-size:calc(var(--t-micro) * .82);color:var(--helper)}
.micwhy summary{cursor:pointer;letter-spacing:.04em}
.micwhy p{margin:var(--s2) 0 0;line-height:1.5}
