/* ═══════════════════════════════════════════════════════
   FIFTHS POSITION EXPLORER — v21
   Visual: v3 prototype  |  Engine: v20
   ═══════════════════════════════════════════════════════ */

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
:root{
  /* LICHEN ON WALNUT v4 — body is cool lichen-stone (not beige/cowboy); framing
     rails (header + pedal strip) are warm walnut wood; accents stay aged brass.
     Warm-on-cool contrast: bronze inlay on mossy stone. */
  --bg:#c8cdb0; --surf2:#b8bea0; --surf3:#a4aa8a;
  --border:#4a3018; --border2:#2a1608;
  --wood-dark:rgba(42,22,8,0.97); --wood-mid:#4a3018;
  --gold:#9a6420; --gold2:#6a4010; --gold3:#c8902c; --gold-dim:rgba(154,100,32,0.10);
  /* --gold (#9a6420) is only 3.04:1 on the sage bg — fails WCAG 4.5:1 as TEXT.
     --gold-ink is the legibility-safe brass for gold text on light backgrounds
     (~4.6:1 on sage). Can't just darken --gold globally — it's also used on
     dark/walnut backgrounds where it must stay light. Use --gold-ink for
     read-text on light; keep --gold/--gold3 for fills, lines, accents. */
  --gold-ink:#7a4a12;
  --amber:#c4581c; --green:#546234; --ivory:#f0e2be;
  --text:#1a0c04; --dim:#3a2a18; --dim2:#5a4828;
  --ink-rail:#f0e2be; /* text color on --wood-dark rails (ivory, ~13:1) */
  --vellum:#d6dcbe;   /* Sage-tinted vellum for patent drawings — lighter than --bg
                         so cards lift off the lichen page, same color family */
  --shadow-warm:rgba(26,12,4,0.18); --highlight-warm:rgba(255,240,208,0.35);

  /* ── R4 Q5 type recipes (10 canonical, with tracking constants) ──
     Spec: docs/claude-design-2026-04-25/R4 Composition Pass.html §Q5.
     Italic rule: Playfair italic is reserved for names + the player's
     voice (chord romans, tune titles, modes, cartouche subs, notes).
     Never on engineering captions, button labels, or system values.
     Size→tracking inversion: smaller Space Mono = tighter tracking
     (≥10px=2.4 / 9px=2.0 / ≤8.5px=1.6 / ≥22px=0.5–0). */
  --tracking-plate-title:   6.0px;
  --tracking-plate-tab:     2.4px;
  --tracking-fig-banner:    3.0px;
  --tracking-eng-label:     2.4px;
  --tracking-eng-meta:      1.6px;
  --tracking-cartouche-sub: 0.5px;
  --tracking-chord-letter:  0.5px;
  --tracking-chord-roman:   0;
  --tracking-tune-name:     0;
  --tracking-note-quote:    0;

  /* R6.40b — easing tokens per Design handoff
     docs/claude-design-2026-05-11/SEE-HEAR-VOCABULARY.md. Three named
     curves cover every motion in the studio. Use these by name; do not
     invent new ones. */
  --ease-swing: cubic-bezier(0.3, 0.7, 0.4, 1);   /* pendulum, seesaw — gravity-like */
  --ease-thumb: cubic-bezier(0.2, 0.8, 0.2, 1);   /* slider thumbs, fold raises, picker selections */
  --ease-decay: cubic-bezier(0.4, 0, 0.2, 1);     /* wavefronts, heatmap fades, chord-card swaps */

  /* R6.40b — vellum2 token used in d.4 SHAPE inactive-tile fretboard
     bg vs. active-tile vellum lift. Tints below --vellum so the active
     tile reads as raised when the bg lifts. */
  --vellum2: #cad1b0;

  /* R6.40-B.3 — additional tokens for the mode-row degree heatmap.
     vellum3 = "natural-tone" chip (slightly darker than --vellum body
     so the chip reads as inset). rose = flat accidentals (muted, not
     hot pink). slate = sharp accidentals (cool gray-blue, the only
     non-warm hue in the palette — sharps are rare, the cool reads as
     a punctuation mark). Used per-row in 7-chip parallel scan glyph. */
  --vellum3: #c4cba6;
  --shadow-ink: #b3b896;   /* r6p88 Map Cabinet — the ONE drawn offset-shadow, solid (never blurred); spent only under an open chart sheet */
  --ivory: #f3ead0;        /* r6p88 — the active drawer face brightens to this */
  --rose:    #a85070;
  --slate:   #5e7080;
}

/* ── BETA BANNER ─────────────────────────────────────────────────
   Plate-A vellum strip pinned to the foot. Footnote register —
   sits below the canvas as a thin annotation, not a chrome bar.
   R4 Phase 1 restyle (was inline v1 wood/brass with pulse). */
#beta-banner{
  position:fixed; bottom:0; left:0; right:0; z-index:500;
  display:flex; align-items:center; justify-content:space-between;
  gap:18px; padding:7px 22px;
  background:var(--vellum); border-top:1px solid var(--gold2);
  flex-wrap:wrap;
}
#beta-banner .bb-msg{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--text); opacity:0.85; letter-spacing:0;
}
/* R6.16 — right-side version stamp in Space Mono workshop register.
   Patent-drawing footer per Design #15: "BETA · MMXXVI · v <build>".
   The CTA + ✕ live inside the same stamp cluster, same vocabulary. */
#beta-banner .bb-stamp{
  display:inline-flex; align-items:center; gap:6px;
  font-family:'Space Mono',monospace; font-size:9.5px;
  letter-spacing:1.6px; text-transform:uppercase; color:var(--dim2);
}
#beta-banner .bb-cta-link{
  font-family:'Space Mono',monospace; font-size:9.5px;
  letter-spacing:1.6px; text-transform:uppercase;
  color:var(--gold); text-decoration:none;
  border-bottom:1px solid transparent;
  padding:1px 0;
  transition:color 120ms ease, border-color 120ms ease;
}
#beta-banner .bb-cta-link:hover{
  color:var(--text); border-bottom-color:var(--gold);
}
#beta-banner .bb-stamp-sep{ color:var(--gold); opacity:0.55; padding:0 1px; }
#beta-banner .bb-stamp-tag{ color:var(--gold); }
#beta-banner .bb-stamp-year,
#beta-banner .bb-stamp-ver{ color:var(--dim2); }
#beta-banner .bb-dismiss{
  background:none; border:none; cursor:pointer;
  color:var(--dim2); font-size:13px; line-height:1; padding:0 2px;
  transition:color .12s;
  margin-left:8px;
}
#beta-banner .bb-dismiss:hover{ color:var(--gold); }
/* push app content up so banner doesn't cover bottom of screen */
#app{ padding-bottom:44px; }

/* ── R6.25 — Mobile landing ──────────────────────────────────────
   Replaces R6.23's banner-on-broken-app with a curated standalone
   teaser. Hidden by default; shown only on (hover: none) and
   (pointer: coarse) — touch-primary devices. When this lands, #app
   gets display:none in the same media query so the user never sees
   the broken full layout. Plain voice, no Patent Drawing jargon —
   just the brand, a tagline, the dial (which plays a piano chord
   on tap), and a beta-signup mailto.

   R6.25.2 — Now framed as a Patent Drawing PLATE: vellum panel with
   double brass border (FLW double-line register, same vocabulary
   as the chord cards on PL. I and FIG cartouches everywhere). The
   mobile user lands on a single plate that reads as part of the
   workshop register, not a generic landing page. */
#mobile-landing{
  display:none; /* shown only on touch-primary, see media query below */
  position:fixed; inset:0; z-index:900;
  background:var(--bg);
  flex-direction:column; align-items:center; justify-content:flex-start;
  padding:18px 14px;
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
}
/* The PLATE — vellum panel, double brass border (1.5px outer, 1px
   inset). Patent Drawing register. This is the surface; everything
   inside is on the plate. */
#mobile-landing::before{
  content:'';
  position:absolute;
  inset:18px 14px;
  pointer-events:none;
  background:var(--vellum);
  border:1.5px solid var(--gold2);
  z-index:-1;
}
#mobile-landing::after{
  content:'';
  position:absolute;
  inset:24px 20px;
  pointer-events:none;
  border:1px solid var(--gold2);
  opacity:0.45;
  z-index:-1;
}
#mobile-landing > *{ position:relative; z-index:1; }
/* R6.25.6 — tighter padding so the whole thing fits one phone screen
   (the longer postcard from R6.25.4 was pushing content off the bottom). */
#mobile-landing{ padding:32px 22px 24px; }
#mobile-landing .ml-brand{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-weight:700;
  font-size:36px;
  color:var(--text);
  line-height:1;
  margin:0 0 6px;
}
#mobile-landing .ml-tag{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:15px;
  color:var(--text);
  opacity:0.75;
  text-align:center;
  line-height:1.3;
  margin:0 0 22px;
  max-width:300px;
}
/* R6.25.9 — Dial framed as a Patent Drawing exhibit. Same vocabulary as
   FIG. d on PL. I sidebar (Space Mono small-caps FIG label + brass
   hairline). No breathe animation — the real tool's dial doesn't
   breathe, so the postcard shouldn't either. Postcard honesty. */
#mobile-landing .ml-dial-wrap{
  width:min(82vw, 320px);
  aspect-ratio:1/1;
  margin:0 0 8px;
  position:relative;
}
#mobile-landing .ml-dial{
  width:100%; height:100%;
  display:block;
  touch-action:manipulation;
}
#mobile-landing .ml-fig{
  font-family:'Space Mono', monospace;
  font-size:10.5px;
  letter-spacing:2.6px;
  color:var(--gold);
  opacity:0.92;
  text-align:center;
  text-transform:uppercase;
  margin:0 auto 22px;
  padding-top:7px;
  border-top:1px solid var(--gold2);
  width:62%;
  font-weight:600;
}
/* R6.25.1 — dial uses the tool's .ps-dial / .kd-note primitives
   (styled in styles.css around line 6240+). Includes the existing
   .kd-arc-group rule that handles the 600ms easeOutExpo transform
   transition — the arc swing feels identical to the tool's. */
/* R6.25.8 — Fretboard CSS removed (the SVG was dropped from index.html
   per Scott's postcard-discipline note). The dial breathes a bit
   wider now that the fretboard isn't claiming vertical space. */
/* R6.25.6 — Single-line invitation between the fretboard and the
   email. Glance, don't read. Italic Playfair, dim, sized small. */
#mobile-landing .ml-invite{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:14px;
  line-height:1.3;
  color:var(--text);
  opacity:0.65;
  text-align:center;
  margin:0 0 12px;
}
#mobile-landing .ml-send{
  font-family:'Space Mono', monospace;
  font-size:11px;
  letter-spacing:1.4px;
  color:var(--gold);
  text-decoration:none;
  border-bottom:1px solid var(--gold);
  padding:2px 0;
  margin:0 0 10px;
  transition:color 120ms, border-color 120ms;
}
#mobile-landing .ml-send:last-of-type{ margin-bottom:0; }
#mobile-landing .ml-send:hover,
#mobile-landing .ml-send:active{
  color:var(--text);
}
#mobile-landing .ml-warn{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:13px;
  color:var(--text);
  opacity:0.55;
  text-align:center;
  margin:0;
}
/* Mobile-landing gate. Touch + narrow viewport only. The (max-width: 599px)
   clause lets "Request Desktop Site" on a phone bypass the gate: that
   browser override widens the CSS viewport to ~980px, the rule no longer
   matches, and the full desktop app renders. 599px matches _isMobile() in
   src/render.js so CSS + JS agree on the mobile threshold. */
@media (hover: none) and (pointer: coarse) and (max-width: 599px){
  #mobile-landing{ display:flex; }
  #app{ display:none !important; }
  #beta-banner{ display:none !important; }
}

/* ── PLATE A TYPE RECIPES ────────────────────────────────────────
   Canonical primitives from HANDOFF-Plate-A.md, refined per R4 Q5.
   Use these classes instead of inline font declarations anywhere a
   Plate A surface needs title, sub, engineering label, FIG banner,
   or letterpress button. */
.plate-title { font-family:'Playfair Display',serif; font-weight:700; font-size:38px; letter-spacing:var(--tracking-plate-title); color:var(--text); line-height:1; }
.plate-sub   { font-family:'Playfair Display',serif; font-style:italic; font-size:14px; color:var(--gold-ink); letter-spacing:var(--tracking-cartouche-sub); }
.eng-label   { font-family:'Space Mono',monospace; font-size:10px; letter-spacing:var(--tracking-eng-label); text-transform:uppercase; color:var(--dim2); }
.fig-banner  { display:flex; align-items:center; gap:10px; font-family:'Space Mono',monospace; color:var(--gold); font-size:10px; letter-spacing:var(--tracking-fig-banner); text-transform:uppercase; }
.fig-rule    { width:14px; height:1px; background:var(--gold); opacity:0.6; }
.letterpress-btn { background:transparent; border:1px solid var(--gold2); border-radius:1px; padding:6px 14px; font-family:'Space Mono',monospace; font-size:10px; letter-spacing:var(--tracking-eng-label); text-transform:uppercase; color:var(--text); opacity:0.85; cursor:pointer; transition:opacity .15s, background .15s, color .15s; }
.letterpress-btn:hover { opacity:1; }
.letterpress-btn.on { background:var(--gold); color:var(--ivory); border-color:var(--gold); opacity:1; }
/* Brass focus ring instead of browser-default blue. Keep accessibility
   without breaking the Plate-A palette. Uses --gold3 (the warmer brass)
   so it reads as the same vocabulary as the sidebar-twin pulse. */
.letterpress-btn:focus { outline:none; }
.letterpress-btn:focus-visible { outline:1.5px solid var(--gold3); outline-offset:2px; }

/* ── PLATE A CHORD PICKER ─────────────────────────────────────────
   R3 Q1 — vellum slip lifts above the editing chip; chip stays a chip.
   Spec: docs/claude-design-2026-04-25/R3 Step-5 Details.html §Q1.
   Inherits the existing pad mutation path (padShowReplacePicker in
   src/app.js); replaces the dark dropdown that lived there before. */
.plate-picker{
  position:fixed; z-index:900; width:340px;
  background:var(--vellum); border:1px solid var(--gold2);
  padding:14px;
  box-shadow:0 14px 40px rgba(26,12,4,0.25);
  font-family:'Space Mono',monospace;
  opacity:0; transform:translateY(8px);
  transition:opacity 120ms cubic-bezier(0.2,0.8,0.2,1), transform 120ms cubic-bezier(0.2,0.8,0.2,1);
}
.plate-picker.open{ opacity:1; transform:translateY(0); }
.plate-picker.closing{ opacity:0; transform:translateY(8px); transition-duration:80ms; }
/* Plate-A inner double-rule — same primitive every other Card uses */
.plate-picker::before{
  content:""; position:absolute; inset:5px;
  border:1px solid var(--gold2); opacity:0.35; pointer-events:none;
}
@media (prefers-reduced-motion:reduce){
  .plate-picker, .plate-picker.closing{ transition-duration:0ms; }
}
.plate-picker-hdr{
  display:flex; align-items:baseline; justify-content:space-between; gap:10px;
  padding-bottom:4px;
}
.plate-picker-hdr .ppk-eng{
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:2.4px;
  text-transform:uppercase; color:var(--dim2);
}
.plate-picker-hdr .ppk-name{
  font-family:'Playfair Display',serif; font-style:italic; font-size:18px;
  color:var(--text);
}
.plate-picker-sub{
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:2px;
  text-transform:uppercase; color:var(--gold); opacity:0.85;
  padding-bottom:10px; border-bottom:1px solid var(--gold2);
}
/* R4 Q7 (a) — type-it-in row inside the chord picker. Toggle button
   sits flush-right under the sub-line; tapping reveals a single-line
   text-input that accepts "I IV V I" / "D G A D" / mixed grammar.
   Visual register: walnut-on-vellum like the rest of the picker;
   input gets a thin gold underline for the writing-line cue. */
.plate-picker-typeit{
  margin-top:8px; padding-top:6px;
  display:flex; flex-direction:column; gap:6px;
}
.plate-picker-typeit-toggle{
  align-self:flex-end;
  background:transparent; border:none; padding:2px 0;
  font-family:'Space Mono',monospace; font-size:10px;
  letter-spacing:var(--tracking-eng-label,2.4px);
  text-transform:uppercase; color:var(--gold);
  cursor:pointer; opacity:0.85;
  transition:opacity 120ms;
}
.plate-picker-typeit-toggle:hover{ opacity:1; }
.plate-picker-typeit-toggle:focus{ outline:none; }
.plate-picker-typeit-toggle:focus-visible{ outline:1.5px solid var(--gold3); outline-offset:2px; }
.plate-picker-typeit-toggle.is-on{
  color:var(--gold3); opacity:1;
  background:var(--gold-dim); padding:2px 6px; border-radius:1px;
}
.plate-picker-typeit-input{
  width:100%; box-sizing:border-box;
  background:transparent;
  border:none; border-bottom:1px solid var(--gold2);
  padding:6px 2px;
  font-family:'Space Mono',monospace; font-size:13px;
  letter-spacing:0.5px; color:var(--text);
  outline:none;
  transition:border-color 120ms;
}
.plate-picker-typeit-input::placeholder{ color:var(--dim2); opacity:0.7; }
.plate-picker-typeit-input:focus{ border-bottom-color:var(--gold); }
.plate-picker-section-lbl{
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:2.4px;
  text-transform:uppercase; color:var(--dim2);
  margin-top:10px; margin-bottom:5px;
}
.plate-picker-roots{
  display:grid; grid-template-columns:repeat(7, 1fr); gap:4px;
}
.plate-picker-root{
  background:transparent; border:1px solid var(--gold2);
  padding:6px 0; font-family:'Space Mono',monospace; font-size:12px;
  letter-spacing:1px; color:var(--text);
  cursor:pointer; border-radius:1px;
  transition:background 80ms, color 80ms, border-color 80ms;
  position:relative;
}
.plate-picker-root.chromatic{ color:var(--dim2); background:rgba(154,100,32,0.04); }
.plate-picker-root:hover{ background:var(--gold-dim); }
.plate-picker-root.active{
  background:var(--ivory); border-color:var(--gold); color:var(--text);
}
.plate-picker-root.active::before{
  content:""; position:absolute; left:-1px; right:-1px; top:-1px; height:2px;
  background:var(--gold3);
}
.plate-picker-quals{
  display:grid; grid-template-columns:repeat(6, 1fr); gap:4px;
}
.plate-picker-qual{
  background:transparent; border:1px solid var(--gold2);
  padding:6px 0; font-family:'Space Mono',monospace; font-size:11px;
  letter-spacing:1px; color:var(--text); cursor:pointer; border-radius:1px;
  transition:background 80ms, color 80ms, border-color 80ms;
}
.plate-picker-qual:hover{ background:var(--gold-dim); }
.plate-picker-qual.active{
  background:var(--ivory); border-color:var(--gold); color:var(--text);
}
.plate-picker-qual.unsupported{
  opacity:0.32; cursor:not-allowed; color:var(--dim2);
}
.plate-picker-qual.unsupported:hover{ background:transparent; }
.plate-picker-ftr{
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:1.6px;
  color:var(--dim2); margin-top:10px; padding-top:8px;
  border-top:1px solid var(--gold2);
  text-transform:uppercase;
}
.plate-picker-hint{
  font-family:'Space Mono',monospace; font-size:9px; letter-spacing:1.4px;
  color:var(--dim2); margin-top:4px; text-transform:uppercase;
}
/* Brass-edged tail pointing at the chip below; flips when picker is below.
   z-index over the picker's ::before inner double-rule so it isn't masked. */
.plate-picker-tail{
  position:absolute; bottom:-9px; width:16px; height:16px;
  background:var(--vellum);
  border-right:1px solid var(--gold2); border-bottom:1px solid var(--gold2);
  transform:rotate(45deg);
  z-index:1;
}
.plate-picker.below .plate-picker-tail{
  bottom:auto; top:-9px;
  border-right:none; border-bottom:none;
  border-left:1px solid var(--gold2); border-top:1px solid var(--gold2);
}

/* ── PLATE A EDITABLE PROGRESSION STRIP (R2 Sketch B + R3 §Q1, §Q3) ─
   Lives below #prog-cards on PL. I. Each chip is the chord picker's
   anchor. Drag-to-reorder + lock states ship in 5.3 / 5.4. */
.plate-prog-strip-wrap{
  /* R5.32: bottom-clearance for the fixed pedal-strip footer.
     R5.35: moved the clearance from THIS element's margin-bottom
     onto .play-main's padding-bottom — when it lived here, the
     130px was a pseudo-element pushing total .play-main content
     past its overflow:hidden container, clipping the PL. I chord
     cards' top header (Scott's report). Padding-bottom on the
     parent reserves the space within the container instead. */
  margin:14px auto 8px; max-width:920px; padding:0 14px;
}
/* R5.35 — chord-card top-clip fix. .play-main has overflow:hidden;
   without padding-bottom the fixed pedal-strip ate the chord-strip's
   visual space and pushed cards up off the top of the container.
   r6p96 (2026-06-03) — trimmed 120→40. #app already reserves 100px
   padding-bottom for the fixed bottom bar, so 120 here was DOUBLE
   clearance that biased the space-evenly content upward and dumped a
   big void below the chord chips (Scott's "5× more below"). 40px keeps
   a safe buffer above the bar while letting content sit balanced. */
.play-main{ padding-bottom:40px; }
.plate-prog-banner{
  justify-content:center !important; margin:0 auto 4px;
  position:relative;
}
/* R5.8 lock-all button + R5.21 visual-weight ease. Scott's homecoming
   eyeball: "still seeing the lock all and the tiny font about commit."
   The button was both too prominent (full bordered chip in the banner)
   and the hint copy underneath was too small to read. Now: lock-all is
   a transparent icon-only button with text on hover; hint copy is
   bigger (8px → 9.5px) and centered under the FIG banner so it reads
   as caption, not noise. The padlock icon does the heavy lifting. */
.plate-prog-lockall{
  display:inline-flex; align-items:center; gap:5px;
  padding:3px 6px;
  background:transparent; border:1px solid transparent;
  border-radius:1px; cursor:pointer;
  color:var(--gold2);
  font-family:'Space Mono',monospace; font-size:10px;
  letter-spacing:1.4px; text-transform:uppercase;
  margin-left:12px;
  opacity:0.65;
  transition:opacity 120ms, color 120ms, border-color 120ms, background 120ms;
}
.plate-prog-lockall:hover,
.plate-prog-lockall:focus-visible{
  opacity:1; color:var(--gold);
  border-color:var(--gold-dim);
  background:rgba(232,199,106,0.06);
}
.plate-prog-lockall:focus{ outline:none; }
.plate-prog-lockall:focus-visible{ outline:1.5px solid var(--gold3); outline-offset:2px; }
.plate-prog-lockall.all-locked{
  opacity:1; color:var(--gold); border-color:var(--gold-dim);
  background:rgba(232,199,106,0.10);
}
.plate-prog-lockall svg{ vertical-align:middle; }

/* R5.9 — practice-tempo half-speed button. Inline pip in the
   TEMPO cell. Tap halves BPM, tap again restores. Brass border,
   tiny — sized so it doesn't visually compete with the BPM number. */
.ps-half-btn{
  display:inline-flex; align-items:center; justify-content:center;
  width:18px; height:18px; padding:0;
  background:transparent; border:1px solid var(--gold2);
  border-radius:1px; cursor:pointer;
  font-family:'Playfair Display',serif;
  font-size:13px; line-height:1; color:var(--text);
  margin-left:6px; vertical-align:middle;
  transition:background 80ms, color 80ms, border-color 80ms;
}
.ps-half-btn:hover{
  background:var(--gold-dim); border-color:var(--gold);
}
.ps-half-btn:focus{ outline:none; }
.ps-half-btn:focus-visible{ outline:1.5px solid var(--gold3); outline-offset:1px; }
.ps-half-btn.is-on{
  background:var(--gold-dim); border-color:var(--gold); color:var(--gold);
}

/* ──────────────────────────────────────────────────────────────
   R5.11 — FLW BLOWOUT
   Cantilever + cabinet metaphor. The pedal-strip cell is the
   anchored foundation stone. The blowout extends UP from it as
   a cantilever — bigger, more material weight, but visually
   tethered to its source. Indirect light halo (Wright clerestory)
   softens the edges so it doesn't read as a hard modal pop.
   Procession in 240ms, fold-out in 200ms. Compression-and-release.
   ────────────────────────────────────────────────────────────── */
.ps-blowout{
  position:fixed; z-index:700;
  width:280px;
  background:var(--vellum);
  border:1px solid var(--gold);
  border-radius:1px;
  padding:12px 14px;
  font-family:'Space Mono',monospace;
  /* Indirect light halo — soft brass glow extending out from the
     blowout, no hard outer line. Lower z-index light source. */
  box-shadow:
    0 0 0 4px rgba(232,199,106,0.08),   /* clerestory halo */
    0 0 24px 6px rgba(232,199,106,0.05),/* far falloff */
    0 8px 28px rgba(26,12,4,0.20);      /* drop shadow grounding */
  opacity:0;
  transform-origin:center bottom;
  transition:
    opacity 240ms cubic-bezier(0.2, 0.8, 0.2, 1),
    transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.ps-blowout.open{
  opacity:1;
  transform:translateX(-50%) translateY(0) scale(1) !important;
}
.ps-blowout-fig{
  display:flex; align-items:center; gap:10px;
  font-family:'Space Mono',monospace; font-size:10px;
  letter-spacing:var(--tracking-fig-banner,3px);
  text-transform:uppercase; color:var(--gold);
  padding-bottom:8px;
  border-bottom:1px solid var(--gold-dim);
  margin-bottom:8px;
}
.ps-blowout-fig-glyph{ flex:0 0 auto; }
.ps-blowout-fig-rule{
  flex:1; height:1px; background:var(--gold-dim); opacity:0.6;
}
.ps-blowout-fig-cap{
  flex:0 0 auto; color:var(--dim2);
  letter-spacing:var(--tracking-eng-meta,1.6px);
  text-transform:none; font-style:italic;
  font-family:'Playfair Display',serif; font-size:11px;
}
.ps-blowout-body{
  display:flex; align-items:center; justify-content:center;
  padding:4px 0;
}
.ps-blowout-dial{
  width:220px; height:220px;
  display:block;
}
.ps-blowout-bk{
  cursor:pointer;
  transition:opacity 120ms;
}
.ps-blowout-bk circle{
  transition:fill 120ms, stroke-width 120ms;
}
.ps-blowout-bk:hover circle{
  fill:var(--gold-dim);
  stroke-width:1.4;
}
.ps-blowout-bk:focus{ outline:none; }
.ps-blowout-bk:focus-visible circle{
  stroke:var(--gold3); stroke-width:2;
}
.ps-blowout-bk.is-active circle{
  fill:var(--gold-dim);
}
.ps-blowout-hint{
  font-family:'Space Mono',monospace;
  font-size:8.5px; letter-spacing:var(--tracking-eng-meta,1.6px);
  color:var(--dim2); text-transform:uppercase;
  text-align:center;
  border-top:1px solid var(--gold-dim);
  padding-top:6px; margin-top:4px;
}
@media (prefers-reduced-motion: reduce){
  .ps-blowout{ transition:opacity 100ms ease, transform 100ms ease; }
}

/* R6.4 — POSITION + CAPO blowouts.
   Mirror the FIG. b / FIG. c cartouches on PL. I (4-col fret grid).
   Buttons in workshop register: vellum + brass border + Playfair italic
   for the active state; matches the cartouche button vocabulary
   (.ps-ladder .pl-pos / .ps-clamp-menu button) so picker and cartouche
   read as the same apparatus. */
.ps-blowout-pos,
.ps-blowout-capo{
  width:220px;
}

/* R6.40-A.7 — TUNING blowout cantilever per Claude Design rev. 4.
   Wider blowout (4-col card grid). Each card carries a silhouette
   + name + tuning row + scale length. Active state = ivory bg +
   1.5px gold border + gold silhouette + gold name; inactive = vellum2
   bg + 1px gold2 border + dim silhouette + dim2 name. Replaces the
   legacy openPedalAt('instrument') popover — last popover debt. */
.ps-blowout-tuning{
  width:520px;
}

/* R6.40-A.4 — TIMBRE cartouche tile grid per Claude Design rev. 4.
   Three voice tiles in a 3-column row inside the cartouche body.
   Each tile carries an envelope sparkline so the user reads attack +
   decay character before tapping. Active state lifts vellum2 → ivory
   bg, gold2 → gold border, and thickens the sparkline stroke. */
.ps-timbre-grid{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:6px;
  padding:2px 0;
}
.ps-timbre-tile{
  display:flex; flex-direction:column; align-items:stretch;
  gap:4px;
  padding:6px 8px 8px;
  background:var(--vellum2);
  border:1px solid var(--gold2);
  border-radius:1px;
  cursor:pointer;
  font-family:'Space Mono',monospace;
  text-align:left;
  transition:background .12s, border-color .12s;
}
.ps-timbre-tile:hover{
  background:var(--vellum);
  border-color:var(--gold);
}
.ps-timbre-tile:focus{ outline:none; }
.ps-timbre-tile:focus-visible{
  outline:1.5px solid var(--gold); outline-offset:2px;
}
.ps-timbre-tile.is-active{
  background:var(--ivory);
  border:1.5px solid var(--gold);
  padding:5.5px 7.5px 7.5px;   /* compensate for thicker border */
}
.ps-tt-head{
  display:flex; align-items:baseline; justify-content:space-between;
}
.ps-tt-name{
  font-family:'Space Mono',monospace;
  font-size:9px; letter-spacing:1.8px;
  color:var(--dim2);
  font-weight:700;
  text-transform:uppercase;
}
.ps-timbre-tile.is-active .ps-tt-name{ color:var(--gold); }
.ps-tt-spark{ display:block; }
.ps-timbre-tile.is-active .ps-tt-curve{
  stroke:var(--gold);
  stroke-width:1.6;
}
.ps-tt-sub{
  font-family:'Space Mono',monospace;
  font-size:8px; letter-spacing:1.4px;
  color:var(--dim2);
  text-transform:uppercase;
}
.ps-blowout-tuning-grid{
  display:grid;
  grid-template-columns:repeat(4, 1fr);
  gap:8px;
  padding:4px 0;
  width:100%;
}
.ps-blowout-tcard{
  display:flex; flex-direction:column; align-items:stretch;
  gap:4px;
  padding:8px 10px 10px;
  background:var(--vellum2);
  border:1px solid var(--gold2);
  border-radius:1px;
  cursor:pointer;
  transition:background .12s, border-color .12s, transform .12s;
  font-family:'Space Mono',monospace;
  text-align:left;
}
.ps-blowout-tcard:hover{
  background:var(--vellum);
  border-color:var(--gold);
}
.ps-blowout-tcard:focus{ outline:none; }
.ps-blowout-tcard:focus-visible{
  outline:1.5px solid var(--gold); outline-offset:2px;
}
.ps-blowout-tcard.is-active{
  background:var(--ivory);
  border:1.5px solid var(--gold);
  padding:7.5px 9.5px 9.5px;   /* compensate for thicker border, no layout shift */
}
.ps-bt-silhouette{
  display:flex; align-items:center; justify-content:flex-start;
  height:28px;
}
.ps-bt-silhouette svg{ display:block; }
.ps-bt-name{
  font-family:'Space Mono',monospace;
  font-size:8.5px; letter-spacing:1.6px;
  color:var(--dim2);
  text-transform:uppercase;
  font-weight:700;
  line-height:1.15;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.ps-blowout-tcard.is-active .ps-bt-name{ color:var(--gold); }
.ps-bt-meta{
  display:flex; align-items:baseline; justify-content:space-between;
  padding-top:4px;
  border-top:1px solid rgba(106,64,16,0.22);
}
.ps-bt-tuning{
  font-family:'Space Mono',monospace;
  font-size:9.5px; letter-spacing:1.8px;
  color:var(--text);
  font-weight:700;
  text-transform:uppercase;
}
.ps-bt-scale{
  font-family:'Space Mono',monospace;
  font-size:8px; letter-spacing:1.4px;
  color:var(--dim2);
}
.ps-blowout-pos-grid,
.ps-blowout-capo-grid{
  display:grid;
  grid-template-columns:repeat(4, 1fr);
  gap:5px;
  padding:4px 0;
}
.ps-blowout-pb{
  padding:9px 0;
  text-align:center;
  background:var(--vellum);
  border:1px solid var(--gold2);
  border-radius:1px;
  color:var(--text);
  font-family:'Space Mono',monospace;
  font-size:12px;
  letter-spacing:1.2px;
  cursor:pointer;
  transition:color .12s, background .12s, border-color .12s;
}
.ps-blowout-pb:hover{
  color:var(--gold);
  border-color:var(--gold);
  background:rgba(154,100,32,0.06);
}
.ps-blowout-pb:focus{ outline:none; }
.ps-blowout-pb:focus-visible{
  outline:1.5px solid var(--gold); outline-offset:2px;
}
.ps-blowout-pb.is-active{
  color:var(--gold);
  border-color:var(--gold);
  background:var(--gold-dim);
  font-weight:700;
}

/* ──────────────────────────────────────────────────────────────
   R5.12 — CONSTELLATION LIGHT (Wright indirect-light pedagogy)
   Soft brass illumination on every element that shares the
   playing chord's identity. NOT a pulse / flash — it's lighting.
   The class is added when chord plays, replaced when next chord
   changes. The eye sees the light move through the room.
   Smooth fade on add/remove (not snap) so chord transitions
   feel like light shifting rather than switches flipping.
   ────────────────────────────────────────────────────────────── */
.cc-halo{
  /* Inner glow: brass light filtering through. Layered shadows for
     soft radial falloff (clerestory / indirect — no hard edge).
     R5.13 — bumped intensity ~2× across all three layers + background
     so halo reads at a glance from across the screen. Still soft, no
     hard edge; but Scott couldn't tell from a screenshot whether the
     light was firing — now you can.
     R6.18 — also gets a 1.5px brass top edge per Claude Design 2026-
     05-08 punch-list #4. The chip on the strip carries a 3px gold3
     top bar when current; the chord card mirrors that with half the
     weight (1.5px) — semantic link without adding a playhead. The
     ::before pseudo lives at top:0 with a small negative inset so it
     sits flush over the existing 0.5px border. */
  box-shadow:
    inset 0 0 0 1.5px rgba(232,199,106,0.85),
    inset 0 0 16px 3px rgba(232,199,106,0.32),
    0 0 22px 4px rgba(232,199,106,0.22);
  background:rgba(232,199,106,0.10);
  transition:
    box-shadow 380ms ease-out,
    background 380ms ease-out;
}
#v2-shapes-cards > div{ position:relative; } /* anchor for .cc-halo::before */
#v2-shapes-cards > div.cc-halo::before{
  content:'';
  position:absolute;
  top:-0.5px; left:-0.5px; right:-0.5px;
  height:1.5px;
  background:var(--gold);
  z-index:2;
  pointer-events:none;
}
/* Light fades in when class is added; fading out happens via
   the transition rules above when the class is removed. */
.cc-halo,
.plate-prog-chip.current{
  /* Both sources of light — strip chip and constellation halo —
     share the same materials so they read as one light system. */
}
@media (prefers-reduced-motion: reduce){
  .cc-halo{ transition:none; }
}
/* R5.21 — edit hint readable. Bumped 9px→10.5px, tightened tracking
   1.6→1.4 so the three actions read as a quick scan, not a buried
   apologetic whisper. Color stays dim so it doesn't compete with the
   chips themselves. Hides on PL. II / III via CSS in the lens-block
   below (read-only context there). */
.plate-prog-hint{
  font-family:'Space Mono',monospace; font-size:10.5px; letter-spacing:1.4px;
  color:var(--dim); opacity:0.85; text-align:center;
  text-transform:uppercase; margin-bottom:10px;
}
.plate-prog-strip{
  display:flex; flex-wrap:wrap; gap:4px;
  justify-content:center; align-items:stretch;
  padding:6px 0;
}
.plate-prog-chip{
  min-width:42px; height:48px;
  padding:2px 4px;
  display:inline-flex; flex-direction:column;
  align-items:center; justify-content:center;
  background:transparent; border:1px solid var(--gold2);
  border-radius:1px; cursor:pointer; user-select:none;
  position:relative;
  font-family:'Space Mono',monospace;
  transition:background 80ms, border-color 80ms;
}
.plate-prog-chip:hover{ background:var(--gold-dim); }
.plate-prog-chip:focus-visible{
  outline:2px solid var(--gold);
  outline-offset:1px;
}
/* R6.31 — Cowork real-fix #4. Was: Roman + chord-name stacked at near-
   equal weight, both reading as labels. Now: Roman is the function
   (Playfair italic, the figure's "what it does"); chord-name is the
   spelling underneath at half size, dimmed (Space Mono caps, "what it's
   called"). One hierarchy taught at a glance. */
.plate-prog-chip-roman{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:17px; font-weight:600; letter-spacing:0;
  color:var(--text); line-height:1; white-space:nowrap;
}
.plate-prog-chip-name{
  font-family:'Space Mono',monospace; font-weight:600;
  font-size:11px; letter-spacing:0.6px;
  color:var(--text); opacity:0.85; line-height:1; margin-top:3px;
  white-space:nowrap;
}
/* r6p76 — the chip keeps name (roman) + note (letter); the LOCK lives on the
   card, not the chip (Scott: "just name and note … the lock lives on the card").
   Locked status still shows via the chip's gold top-bar (.current.locked::before). */
.plate-prog-chip-lock{ display:none !important; }
/* Currently-playing chip — gold-dim fill + 3px gold3 top bar. Same
   "now" vocabulary the active plate-tab and Rail-S use. */
.plate-prog-chip.current{
  background:var(--gold-dim); border-color:var(--gold);
}
.plate-prog-chip.current::before{
  content:""; position:absolute; left:-1px; right:-1px; top:-1px; height:3px;
  background:var(--gold3);
}
/* + chord append button — dashed brass at end of strip. */
.plate-prog-add{
  width:48px; height:44px;
  background:transparent; border:1px dashed var(--gold2);
  color:var(--dim2); cursor:pointer;
  font-family:'Space Mono',monospace; font-size:18px; line-height:1;
  padding:0; border-radius:1px;
  transition:background 80ms, color 80ms, border-color 80ms;
}
.plate-prog-add:hover{ background:var(--gold-dim); color:var(--gold); border-color:var(--gold); }

/* r6p97 — blank-canvas PASTE-FIRST entry (the armed-transcriber path). The
   paste field is the headline; "+" drops to a one-at-a-time alternate below.
   Skin-aware (works in paper + blueprint) via the shared tokens. */
.plate-prog-paste{
  display:flex; flex-direction:column; align-items:center; gap:10px;
  width:100%; max-width:430px; margin:0 auto;
}
.plate-prog-paste-lbl{
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:2.2px;
  text-transform:uppercase; color:var(--gold2); opacity:0.85;
}
.plate-prog-paste-input{
  width:100%; box-sizing:border-box;
  background:transparent; border:1px solid var(--gold2); border-radius:2px;
  color:var(--text, #1f1d17);
  font-family:'Space Mono',monospace; font-size:15px; letter-spacing:0.5px;
  text-align:center; padding:11px 14px;
  transition:border-color 120ms, box-shadow 120ms;
}
.plate-prog-paste-input::placeholder{
  color:var(--dim2); opacity:0.55; font-size:13px; letter-spacing:1px;
}
.plate-prog-paste-input:focus{
  outline:none; border-color:var(--gold);
  box-shadow:inset 0 0 0 1px var(--gold-dim, rgba(154,100,32,0.22));
}
.plate-prog-paste-alt{
  font-family:'Space Mono',monospace; font-size:9.5px; letter-spacing:1.5px;
  text-transform:uppercase; color:var(--dim2); opacity:0.7;
  display:flex; align-items:center; gap:8px; margin-top:2px;
}
.plate-prog-paste-alt .plate-prog-add{
  width:30px; height:26px; font-size:14px;
}
/* r6p97 — empty blank-canvas composition: faint ghost chart-slots (feedforward
   — "your charts appear here") above the paste field, centered as one block in
   the canvas so the paste field reads as "start here", not a bottom afterthought. */
.play-main.blank-paste{ position:relative; }
.play-main.blank-paste .plate-prog-empty{
  position:absolute; top:44%; left:50%;
  transform:translate(-50%, -50%); z-index:4;
}
.plate-prog-empty{
  display:flex; flex-direction:column; align-items:center; gap:24px;
}
.plate-prog-ghosts{
  display:flex; gap:14px; opacity:0.5;
}
.ppg-slot{
  width:74px; height:106px;
  border:1px dashed var(--gold2); border-radius:2px;
  /* faint string-line hint so it reads as a CHART slot, not a blank box */
  background:repeating-linear-gradient(
    to bottom,
    transparent 0, transparent 19px,
    var(--gold-dim, rgba(154,100,32,0.10)) 19px, var(--gold-dim, rgba(154,100,32,0.10)) 20px
  );
}

/* R5.7 — chip-strip pattern-reveal. The strip is no longer a flat
   inventory list; it now SHOWS the tune's structural form (AABB)
   when the loaded song carries parts data. Section labels in
   Playfair italic gold mark the A part / B part. A brass-rule
   divider sits between sections. Phrase bar-lines (thin brass
   ticks) appear every 4 chips inside each section, mirroring the
   8-bar phrase = 2 × 4 grouping that fiddle tunes (and most folk
   forms) follow. The strip becomes a structural map; the tune's
   bones become legible without counting. */
.plate-prog-strip{ align-items:flex-start; }

/* R5.13 — AABB phrase-stacked sections.
   Each section (A, B, C, …) is now a vertical block:
   - Section label (Playfair italic gold) sits at the upper-left
   - Phrase rows stack vertically inside (phrase 1 above phrase 2)
   - Columns align across phrases so reading down a column compares
     bar 1 of phrase 1 to bar 1 of phrase 2, etc.
   Most fiddle tunes divide each 8-bar section into two 4-bar
   phrases; the stacked rendering reveals their parallel structure
   and the cadence divergence at bar 4. For sections that don't
   divide cleanly by 4, fall back to a single row inside that
   section (R5.7 behavior preserved). */
.plate-prog-section{
  display:flex; flex-direction:row; align-items:stretch;
  gap:6px;
  position:relative;
  padding:8px 6px;
}
/* Brass hairline separator between sections */
.plate-prog-section + .plate-prog-section{
  border-left:1px solid var(--gold-dim);
  padding-left:12px; margin-left:6px;
}
.plate-prog-section-lbl{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:18px; line-height:1;
  color:var(--gold-ink);   /* was --gold = 3.04:1 on sage */
  letter-spacing:0.5px;
  display:flex; align-items:center; justify-content:center;
  width:24px; flex-shrink:0;
  pointer-events:none;
}
.plate-prog-section-rows{
  display:flex; flex-direction:column; gap:4px; flex:1;
}
.plate-prog-phrase-row{
  display:flex; gap:4px; flex-wrap:nowrap;
  align-items:stretch;
}
.plate-prog-phrase-row > .plate-prog-chip{
  flex:1 1 auto; min-width:42px;   /* floor width fits the widest common roman (bVII); grows if room */
}
/* Brass-rule divider between sections — vertical ink line in the
   Patent Drawing register. Hairline + half-opacity so it reads as
   structural notation, not noise. */
.plate-prog-section-div{
  display:inline-block;
  width:1px; align-self:stretch;
  margin:14px 8px 0;
  background:var(--gold2);
  opacity:0.55;
}
/* Phrase bar-line — thin brass tick between every 4 chips inside
   a section. Marks the mid-section phrase boundary (the 4-bar
   half-phrase break that's structurally there in every folk tune
   even when it isn't notated). Hairline, dim — present but not loud. */
.plate-prog-bar{
  display:inline-block;
  width:1px; align-self:stretch;
  margin:18px 3px 4px;
  background:var(--gold-dim);
  opacity:0.6;
}

/* R5.20 — Strip is now visible on every plate as constant context.
   On PL. II / PL. III the strip reads as a context ribbon, not an
   editable surface: hide the lock-all button and the edit-hint, and
   shrink chip width slightly so it sits below the fretboard without
   competing for attention. PL. I keeps the full editable affordance
   set (lock-all + hint + draggable chips). */
body[data-plate-lens="II"] .plate-prog-lockall,
body[data-plate-lens="III"] .plate-prog-lockall,
body[data-plate-lens="II"] .plate-prog-hint,
body[data-plate-lens="III"] .plate-prog-hint{
  display:none !important;
}
body[data-plate-lens="II"] .plate-prog-strip-wrap,
body[data-plate-lens="III"] .plate-prog-strip-wrap{
  margin-top:6px;
  padding-top:4px;
  border-top:1px solid var(--gold-dim);
  opacity:0.95;
}
/* r6p67c v1.7c — legacy chip strip RESTORED on PL. I. The deduped
   card grid above is look-at-only; the chip strip below carries every
   beat with the existing per-chip voicing/lock controls Scott's been
   using all along. Same primitive as PL. II Rhythm, so the two plates
   feel like the same territory. */
/* R5.66 — Scott "still showing the old style" with screenshot. R5.65 hid
   the ribbon and kept #play-prog-dots, but on PL. II #play-prog-dots
   renders as compact basic chips (just Roman numerals, no chord names,
   no brass borders) — that IS the "old style" Scott was pointing at.
   The ribbon (.plate-prog-strip-wrap) has the nicer chips with both
   Roman + chord-name + brass borders + section breaks. Final direction:
   on PL. II, hide #play-prog-dots and SHOW the ribbon. (Terminology
   irrelevant — the visible result is what matters: cleaner chips, no
   duplicate strip.) */
body[data-plate-lens="II"] #play-prog-dots{
  display:none !important;
}
/* Slightly tighter chips on PL. II / III so the strip reads as
   reference context, not the main act. */
body[data-plate-lens="II"] .plate-prog-chip,
body[data-plate-lens="III"] .plate-prog-chip{
  min-width:34px;
  padding:4px 6px;
}
/* r6p85 punch-list #12 — uniform fixed-width cells. Was: flex:1 1 auto +
   content-basis min-width, so a wide roman like "bVII" (~45px) ballooned
   past the "I"/"V" cells (~34px) AND flex-grow gave different widths per
   row — a ragged grid. Mirror the lens-I treatment (fixed width, name
   centred) at the tighter II/III scale: every cell identical regardless
   of chord-name length. 48px clears the widest common roman (bVII). */
body[data-plate-lens="II"] .plate-prog-phrase-row > .plate-prog-chip,
body[data-plate-lens="III"] .plate-prog-phrase-row > .plate-prog-chip{
  flex:0 0 auto; width:48px; min-width:48px; max-width:48px;
}

/* ── R3 Q3 — drag affordances ─────────────────────────────────────
   Source slot becomes a dashed ghost during drag (so the player can
   see where they came from); the clone follows the cursor as a
   lifted brass-bordered card; a 2px brass insertion line marks the
   drop point. */
.plate-prog-chip.pps-ghost-source{
  border-style:dashed !important;
  background:transparent !important;
  color:transparent;
  opacity:0.5;
}
.plate-prog-chip.pps-ghost-source::before{ display:none; }
.plate-prog-chip.pps-ghost-source > *{ visibility:hidden; }
.pps-drag-clone{
  position:fixed !important; pointer-events:none; z-index:1000;
  width:48px; height:44px;
  background:var(--ivory) !important; border:1px solid var(--gold) !important;
  box-shadow:0 16px 36px rgba(26,12,4,0.3);
  transform:scale(1.05) rotate(2deg);
  transition:opacity 80ms, transform 80ms;
}
.pps-insert-line{
  position:fixed; width:2px; background:var(--gold);
  pointer-events:none; z-index:999;
  transition:opacity 60ms, left 40ms;
  opacity:0;
}

/* ── R3 Q2 — lock affordance + locked state + commit flash ───────
   Mouse path: 8×8 brass padlock fades in at the chip's bottom-right
   on hover; click toggles lock. Locked chips keep the padlock filled
   and show a 2px gold3 top bar (same vocabulary as the picker's
   active root). Touch path: 500ms long-press → _padToggleLock fires
   in src/app.js. Keyboard path: L on the focused chip. All three
   trigger the .flash animation (200ms gold-bar pulse) on commit. */
.plate-prog-chip{ position:relative; }
.plate-prog-chip-lock{
  position:absolute; bottom:1px; right:2px;
  display:inline-flex; align-items:center; justify-content:center;
  width:15px; height:18px;
  color:var(--gold); background:transparent; border:none; padding:0;
  /* FB-F5/F8 (iteration 4): default opacity bumped 0 → 0.45 so the
     unlocked padlock is permanently visible. Was hover-only, which
     broke discoverability on touch devices (no hover state) and
     buried the lock affordance from sight on desktop too — Scott's
     "one-point font" friction from the Clocks attempt. 0.45 keeps the
     unlocked state visually quieter than the chord name so it doesn't
     compete; hover + .locked states bump to full 1.0 to signal active
     intent. */
  opacity:0.45; cursor:pointer;
  transition:opacity 60ms;
}
.plate-prog-chip:hover .plate-prog-chip-lock,
.plate-prog-chip:focus-visible .plate-prog-chip-lock{ opacity:1; }
.plate-prog-chip.locked .plate-prog-chip-lock{ opacity:1; color:var(--gold3); }
.plate-prog-chip.locked::before{
  content:""; position:absolute; left:-1px; right:-1px; top:-1px; height:2px;
  background:var(--gold3); pointer-events:none;
}
/* When a locked chip is also currently playing, the 3px ::before from
   .current wins (declared earlier — higher specificity from class
   chaining). The locked 2px stays underneath; no separate stack. */
.plate-prog-chip.current.locked::before{ height:3px; }

@keyframes plate-prog-chip-flash{
  0%   { box-shadow:inset 0 2px 0 0 var(--gold3); }
  20%  { box-shadow:inset 0 4px 0 0 var(--gold3); }
  100% { box-shadow:inset 0 2px 0 0 var(--gold3); }
}
.plate-prog-chip.flash{
  animation:plate-prog-chip-flash 200ms ease-out;
}

/* Stronger landing cue for the just-dropped chip — scale bump + brass
   outline + gold-bar so the moved chip is visually distinct even when
   neighbors are identical. Distinct from .flash (lock-toggle vocabulary)
   because drop-into-identical-neighbors needs more than the inset bar. */
@keyframes plate-prog-chip-just-dropped{
  0%   { transform:scale(1.0); box-shadow:0 0 0 0 var(--gold3), inset 0 2px 0 0 var(--gold3); background:transparent; }
  25%  { transform:scale(1.08); box-shadow:0 0 0 2px var(--gold3), inset 0 4px 0 0 var(--gold3); background:var(--gold-dim); }
  60%  { transform:scale(1.02); box-shadow:0 0 0 1px var(--gold2), inset 0 2px 0 0 var(--gold3); background:var(--gold-dim); }
  100% { transform:scale(1.0); box-shadow:0 0 0 0 transparent, inset 0 2px 0 0 var(--gold3); background:transparent; }
}
.plate-prog-chip.just-dropped{
  animation:plate-prog-chip-just-dropped 600ms cubic-bezier(0.2, 0.8, 0.2, 1);
  z-index:2; /* sit above neighbors during the scale bump */
}

/* ── R3 Q4/Q5/Q6 — SAVE / SHARE CARD (5.5 + 5.6) ─────────────────
   One vellum slip with two faces. Front = Save, Back = Share, Y-axis
   flip joins them. Anchored bottom-right of plate at 28px / 72px,
   tilted -0.4° per R2 Sketch B. */
.save-card{
  /* 2026-05-15 — bottom offset bumped 28→120 so the card sits clear of
     the 66px bottom strip (was overlapping TEMPO / SWING cells, hard
     to read with controls bleeding into the card's lower fields). */
  position:fixed; right:72px; bottom:120px;
  width:360px;
  z-index:1100;
  perspective:1200px;
  transform:rotate(-0.4deg) translateY(8px);
  filter:drop-shadow(0 14px 40px rgba(26,12,4,0.25));
  opacity:0;
  transition:opacity 200ms, transform 200ms;
}
.save-card.open{
  opacity:1; transform:rotate(-0.4deg) translateY(0);
}
.save-card.closing{ opacity:0; transition:opacity 180ms; }
@media (prefers-reduced-motion:reduce){
  .save-card, .save-card.open, .save-card.closing{ transition-duration:0ms; }
}
.save-card-inner{
  position:relative; width:100%; min-height:240px;
  transform-style:preserve-3d;
  transition:transform 460ms cubic-bezier(0.4,0,0.2,1);
}
.save-card.flipped .save-card-inner{ transform:rotateY(180deg); }
.save-card-face{
  /* R5.50b — added bottom:0 so the vellum face fills the full save-card
     inner height (min:240). Face was top:0 only, so its background only
     covered its content size (~140h); below that the save-card outer
     was transparent and the fixed pedal strip + beta banner showed
     through, breaking the popover illusion. */
  position:absolute; top:0; left:0; right:0; bottom:0;
  background:var(--vellum);
  border:1px solid var(--gold2);
  padding:18px;
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
  font-family:'Space Mono',monospace;
}
.save-card-face::before{
  content:""; position:absolute; inset:5px;
  border:1px solid var(--gold2); opacity:0.35; pointer-events:none;
}
.save-card-back{ transform:rotateY(180deg); }
.save-card-title{ margin:8px 0 14px; }
.save-card-h1{
  display:block;
  font-family:'Playfair Display',serif;
  font-style:italic; font-size:18px;
  color:var(--text); letter-spacing:0.5px;
}
.save-card-sub{
  display:block;
  font-family:'Space Mono',monospace;
  font-size:9px; letter-spacing:1.4px;
  color:var(--gold); text-transform:uppercase; margin-top:3px;
}
.save-card-field{ display:block; margin-bottom:10px; }
.save-card-field .eng-label{ display:block; margin-bottom:4px; }
.save-card-field input{
  width:100%; padding:8px 10px;
  background:rgba(240,226,190,0.25);
  border:1px solid var(--gold2); border-radius:1px;
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--text);
  transition:border-color 80ms, background 80ms;
}
.save-card-field input:focus{
  outline:none; border-color:var(--gold);
  background:var(--ivory);
}
.save-card-actions{
  display:flex; gap:6px; margin-top:14px;
}
.save-card-actions .letterpress-btn{ flex:1; }
.save-card-checkbox{
  display:flex; align-items:center; gap:8px;
  margin-top:12px;
  font-family:'Space Mono',monospace; font-size:9px; letter-spacing:1.4px;
  color:var(--dim2); text-transform:uppercase;
  cursor:pointer;
}
.save-card-checkbox input{
  width:14px; height:14px; accent-color:var(--gold);
}
/* Hinge tab on the right edge — matches R3 Sketch B exact values
   (32×120, vertical-rl, Space Mono 9px/2px). */
.save-card-flip-tab{
  position:absolute; right:-32px; top:50%; transform:translateY(-50%);
  width:32px; height:120px;
  background:var(--vellum); border:1px solid var(--gold2);
  border-left:none;
  writing-mode:vertical-rl;
  font-family:'Space Mono',monospace; font-size:9px; letter-spacing:2px;
  text-transform:uppercase; color:var(--gold);
  cursor:pointer; padding:0;
  display:flex; align-items:center; justify-content:center;
  transition:background 80ms;
}
.save-card-flip-tab:hover{ background:var(--gold-dim); }
.save-card-flip-tab.back{
  right:auto; left:-32px;
  border:1px solid var(--gold2); border-right:none;
  writing-mode:vertical-lr;
  transform:translateY(-50%) rotate(180deg);
}

/* Rail-N Save button "just saved" gold pulse */
@keyframes rn-just-saved{
  0%   { background:var(--gold); color:var(--ivory); border-color:var(--gold); box-shadow:0 0 0 0 rgba(154,100,32,0.6); }
  40%  { background:var(--gold); color:var(--ivory); border-color:var(--gold); box-shadow:0 0 0 8px rgba(154,100,32,0); }
  100% { /* default — handled by removing class */ }
}
.app-header .letterpress-btn.rn-just-saved{
  animation:rn-just-saved 1600ms ease-out;
  background:var(--gold); color:var(--ivory); border-color:var(--gold);
}

/* ── R3 Q5 — RECEIPT SLIP (Step 5.7) ────────────────────────────
   Pinned to top-right of the plate at +0.4° tilt (mirror of the
   sender's Save slip's −0.4°). Plate fades to 60% behind so the
   slip reads as the active surface for these 5 seconds. */
.receipt-slip{
  position:fixed; right:48px; top:88px;
  width:340px;
  background:var(--vellum);
  border:1px solid var(--gold2);
  padding:18px;
  z-index:1100;
  font-family:'Space Mono',monospace;
  filter:drop-shadow(0 14px 40px rgba(26,12,4,0.25));
  opacity:0; transform:rotate(0.4deg) translateY(-8px);
  transition:opacity 240ms, transform 240ms;
}
.receipt-slip.open{ opacity:1; transform:rotate(0.4deg) translateY(0); }
.receipt-slip.closing{ opacity:0; transition:opacity 200ms; }
.receipt-slip::before{
  content:""; position:absolute; inset:5px;
  border:1px solid var(--gold2); opacity:0.35; pointer-events:none;
}
.receipt-slip-sender{
  margin-top:8px;
  font-family:'Playfair Display',serif; font-size:14px; color:var(--text);
}
.receipt-slip-sender em{ font-style:italic; color:var(--gold); font-weight:400; }
.receipt-slip-when{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.4px; color:var(--dim2); text-transform:uppercase;
}
.receipt-slip-tune{
  margin-top:4px;
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:18px; color:var(--text);
}
.receipt-slip-note{
  margin-top:10px;
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--dim); line-height:1.4;
}
.receipt-slip-actions{
  display:flex; gap:6px; margin-top:14px;
}
.receipt-slip-actions .letterpress-btn{ flex:1; }

body.receipt-slip-open #app{ opacity:0.6; transition:opacity 200ms; }
@media (prefers-reduced-motion:reduce){
  .receipt-slip, .receipt-slip.open, .receipt-slip.closing,
  body.receipt-slip-open #app{ transition-duration:0ms; }
}

/* ── R3 §Q7 — bench row context menu (R3 polish 5/5) ─────────────
   Right-click on a bench row → small vellum slip near the cursor.
   Same patent-drawing discipline as Plate A cards: 1px gold2 outer +
   ::before inner double-rule at 5px inset. */
.bench-row-menu{
  position:fixed; z-index:1200; min-width:180px;
  background:var(--vellum); border:1px solid var(--gold2);
  padding:6px 0;
  filter:drop-shadow(0 14px 40px rgba(26,12,4,0.25));
  font-family:'Space Mono',monospace;
}
.bench-row-menu::before{
  content:""; position:absolute; inset:5px;
  border:1px solid var(--gold2); opacity:0.35; pointer-events:none;
}
.bench-row-menu-item{
  display:block; width:100%; text-align:left;
  background:transparent; border:none;
  padding:7px 18px; cursor:pointer;
  font-family:'Space Mono',monospace; font-size:11px;
  letter-spacing:0.6px; text-transform:uppercase;
  color:var(--text);
}
.bench-row-menu-item:hover,
.bench-row-menu-item:focus-visible{
  background:var(--gold-dim); color:var(--gold); outline:none;
}
.bench-row-menu-item.danger:hover,
.bench-row-menu-item.danger:focus-visible{
  background:rgba(154,100,32,0.15); color:#9a3a1a;
}

/* Auto-dismiss toast — vellum slip top-center for "Link copied" etc. */
.lib-toast{
  position:fixed; top:24px; left:50%;
  transform:translateX(-50%) translateY(-12px);
  background:var(--vellum); border:1px solid var(--gold2);
  padding:8px 14px; z-index:1300;
  font-family:'Space Mono',monospace; font-size:11px;
  letter-spacing:0.6px; text-transform:uppercase;
  color:var(--text);
  filter:drop-shadow(0 10px 30px rgba(26,12,4,0.2));
  opacity:0; transition:opacity 200ms, transform 200ms;
}
.lib-toast.open{ opacity:1; transform:translateX(-50%) translateY(0); }
.lib-toast.closing{ opacity:0; transition:opacity 200ms; }

/* ── R3 Q7 — LIBRARY DRAWER TABS (Step 5.8) ────────────────────────
   Three tabs above the existing two-column body. Active = ivory fill +
   3px gold3 top bar (matches plate-tab + chord-card primary signifier
   already used on the plate). */
.lib-tabs{
  display:flex; gap:0;
  border-bottom:1px solid var(--gold2);
  background:var(--vellum);
  flex-shrink:0;
}
.lib-tab{
  position:relative;
  flex:1;
  background:transparent;
  border:none;
  border-right:1px solid var(--gold2);
  padding:11px 16px;
  cursor:pointer;
  /* R6.14 — same selection vocabulary as act-tabs at top of plate
     (PL. I Shapes / PL. II Rhythm / PL. III Sound) and FIG. d picker
     primitive on PL. I sidebar. Inactive: Space Mono caps unfilled.
     Active: italic Playfair + 1.5px brass underline. Per Claude Design
     2026-05-08 punch-list #12: "Same act-tab vocabulary as PL. I/II/III
     at top." One selection vocabulary across the chassis is the win. */
  font-family:'Space Mono',monospace;
  font-size:10px; letter-spacing:2.4px; text-transform:uppercase;
  color:var(--dim2);
  transition:background 80ms, color 80ms;
}
.lib-tab:last-child{ border-right:none; }
.lib-tab:hover{ background:rgba(154,100,32,0.04); color:var(--gold); }
.lib-tab.on{
  /* Italic Playfair takes over from Space Mono caps when active —
     same italic-as-state-marker pattern as act-tabs. No fill, no top
     bar; the brass underline carries the weight. */
  background:transparent;
  color:var(--text);
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:14px;
  text-transform:none;
  letter-spacing:0;
  font-weight:500;
}
.lib-tab.on::before{
  content:""; position:absolute; left:14px; right:14px; bottom:0; height:1.5px;
  background:var(--gold);
}
.lib-tab-name{ font-weight:inherit; }
.lib-tab-count{
  margin-left:8px;
  font-family:'Space Mono',monospace; font-size:9px;
  color:var(--gold); letter-spacing:1px;
  font-style:normal;
  text-transform:uppercase;
}
.lib-tab.on .lib-tab-count{ color:var(--gold); opacity:0.75; }

/* Pane visibility */
.lib-pane{ display:none; }
.lib-pane.on{ display:flex; }
.lib-pane-library.on{ display:flex; flex:1; min-height:0; }
.lib-pane-bench, .lib-pane-received{
  flex-direction:column; padding:18px 22px;
  overflow-y:auto;
}

/* Bench row primitive (R3 Q7) — 4-chip thumbnail + title + sub +
   plate roman + date. Ivory hover/focus surface, brass border. */
.bench-rows{ display:flex; flex-direction:column; gap:8px; }
.bench-row{
  display:flex; align-items:center; gap:14px;
  padding:10px 14px;
  background:transparent; border:1px solid transparent;
  cursor:pointer;
  transition:background 80ms, border-color 80ms;
}
.bench-row:hover, .bench-row:focus-visible{
  background:var(--gold-dim); border-color:var(--gold);
  outline:none;
}
.bench-row-chips{
  display:flex; gap:2px; flex-shrink:0;
  padding:4px 0;
}
.bench-row-chip{
  position:relative;
  width:22px; height:26px;
  display:inline-flex; align-items:center; justify-content:center;
  background:transparent; border:1px solid var(--gold2);
  font-family:'Space Mono',monospace; font-size:9px; letter-spacing:0.5px;
  color:var(--text);
}
.bench-row-chip.locked::before{
  content:""; position:absolute; left:-1px; right:-1px; top:-1px; height:2px;
  background:var(--gold3);
}
.bench-row-chip-empty{
  font-family:'Space Mono',monospace; font-size:9px; color:var(--dim2);
}
.bench-row-mid{ flex:1; min-width:0; }
.bench-row-title{
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:15px; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.bench-row-sub{
  margin-top:2px;
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:12px; color:var(--dim);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.bench-row-tag{
  display:inline-block; padding:1px 6px; margin-right:6px;
  background:var(--gold-dim); color:var(--gold);
  font-family:'Space Mono',monospace; font-style:normal;
  font-size:8px; letter-spacing:1.2px; text-transform:uppercase;
  border:1px solid var(--gold2);
}
.bench-row-end{
  display:flex; flex-direction:column; align-items:flex-end;
  gap:2px; flex-shrink:0;
}
.bench-row-plate{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.6px; color:var(--dim2); text-transform:uppercase;
}
.bench-row-date{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:0.8px; color:var(--dim2);
}
/* R6.32 — Received-row delete button. Bench rows have a right-click /
   long-press menu (rename · duplicate · share · delete); Received
   rows don't, and pre-R6.32 had no remove path at all. Visible ✕
   stays low-contrast until hover — present but doesn't compete with
   the row's load-on-click affordance. */
.bench-row-del{
  margin-top:2px;
  width:18px; height:18px;
  border:none; background:transparent; cursor:pointer;
  font-size:11px; line-height:1; color:var(--dim2);
  opacity:0.55; transition:opacity 120ms, color 120ms;
  padding:0; border-radius:50%;
}
.bench-row-del:hover, .bench-row-del:focus-visible{
  opacity:1; color:var(--ink);
  outline:none;
}

.lib-empty{
  padding:38px 22px; text-align:center;
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--dim);
}

/* ════════════════════════════════════════════════════════════════
   MARGIN FRAME — R2 invention, "the whole page is one patent drawing"
   Ref: docs/claude-design-2026-04-24/R2 Topology Memo.html §4.
   Four typed margins surround a bordered plate area:
     · 40px top + 40px bottom  (Rail-N inside top, Rail-S inside bottom)
     · 36px left + 36px right  (Rail-W vertical text left, Rail-E right)
     · Inner content gets a 1px gold2 hairline at 5px inset (the double-rule
       every plate already wears).
   ════════════════════════════════════════════════════════════════ */
#app{ padding:40px 36px; }
#app::before{
  content:"";
  position:absolute;
  inset:40px 36px;
  border:1px solid var(--gold2);
  opacity:0.35;
  pointer-events:none;
  z-index:0;
}
.rail-w, .rail-e{
  position:absolute;
  top:96px;       /* 40px outer + 56px Rail-N */
  bottom:104px;   /* 40px outer + 64px Rail-S */
  width:36px;
  font-family:'Space Mono',monospace;
  font-size:9px;
  letter-spacing:3px;
  text-transform:uppercase;
  color:var(--dim2);
  opacity:0.75;
  pointer-events:none;
  display:flex;
  align-items:flex-start;
  justify-content:center;
  padding-top:40px;
  z-index:1;
  white-space:nowrap;
}
.rail-w{ left:0; writing-mode:vertical-rl; transform:rotate(180deg); }
.rail-e{ right:0; writing-mode:vertical-rl; }
/* R4 Q1 (a) — rail-E retired. Its PAT. PEND. signature now lives
   inside .plate-right-rail's foot stamp; the outer-margin vertical
   text was a decorative duplicate. Element kept in DOM for any JS
   that still looks it up; just not rendered. */
.rail-e{ display:none; }
/* R2.5 Q5 — margin annotation crossfade on lens switch. The text is the
   caption to the figure; captions arrive after the figure, so we fade out
   then fade in around the brass-flash anchor. */
.rail-w{ transition:opacity 100ms ease-out; }
.rail-w.lens-fading{ opacity:0; }
@media (prefers-reduced-motion: reduce) {
  .rail-w{ transition:none; }
}

/* Pedal-strip moves inside the Margin frame. Step 1 keeps existing cell
   structure; Rail-S refactor (Task #4) restyles cells per R2.5 Q6 spec. */
#pedal-strip{ left:36px !important; right:36px !important; bottom:40px !important; }

/* ─── RAIL-N ────────────────────────────────────────────────────
   Step 1b — the global top rail. Logo · tune title · plate-tabs ·
   actions. R2 §2: "the plate-tabs in their current center-top position
   into the rail proper saves vertical space and puts them in the zone
   players expect tabs to be." Single flex-row; tabs absorbed at center.
   Inner height ~64px (R2 spec was 56px; we're 64 to keep the shipped
   plate-tab glyphs as the per-lens signatures). */
.app-header.rail-n{
  height:auto; min-height:64px;
  display:flex; align-items:center; justify-content:flex-start;
  padding:0 18px; gap:14px;
  border-bottom:1px solid var(--gold2);
  position:relative;
}
.rn-brand{
  display:flex; align-items:center; gap:3px;
  flex-shrink:0;
  text-decoration:none; line-height:1;
  /* R5.93 — now a real link to bare URL. Cursor + hover-fade signal it. */
  cursor:pointer; color:inherit;
  transition:opacity .15s;
}
.rn-brand:hover{ opacity:0.78; }
.rn-brand:focus{ outline:none; }
.rn-brand:focus-visible{ outline:1.5px solid var(--gold); outline-offset:3px; }
.rn-brand-mark{ width:30px; height:30px; flex-shrink:0; }
.rn-brand-name{
  font-family:'Playfair Display',serif;
  font-size:22px; letter-spacing:4px;
  color:var(--gold-ink); opacity:1;   /* was --gold @0.95 = 3.04:1 on sage; --gold-ink passes 4.5:1 */
  margin-left:3px; line-height:1;
}
/* R4.8d — header is now a 3-column equal-grow layout: tune (left,
   flex:1) · tabs (center, natural size) · actions (right, flex:1
   right-justified). Tune and actions grow equally so the tabs sit
   geometrically centered. Per Scott's pet-peeve fix 2026-05-01. */
.rn-tune{
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:flex-start; justify-content:center;
  gap:1px; padding-left:8px;
}
.rn-tune .rn-title{
  font-family:'Playfair Display',serif;
  font-size:20px; line-height:1.2; letter-spacing:0.4px;
  color:var(--gold-ink);   /* was --gold = 3.04:1 on sage; --gold-ink passes 4.5:1 */
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  max-width:100%;
  display:inline-flex; align-items:center; gap:8px;
}
/* r6p53 — reset-to-original button rendered as a small brass glyph
   inline with the "(edited)" tune title. The title doubles as the
   state indicator (text) and reset control (button) — fewer elements
   doing the same job (FLW organic unity) + reset mapped directly to
   the surface that shows the edit (Norman direct mapping). Hidden
   when no edit lineage exists. */
.rn-tune .np-reset-btn{
  font-family:'Space Mono', monospace;
  font-size:16px; line-height:1;
  color:var(--gold);
  background:transparent;
  border:1px solid var(--gold2, #6a4010);
  border-radius:50%;
  width:24px; height:24px;
  padding:0;
  cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center;
  flex-shrink:0;
  transition:background .15s, color .15s, border-color .15s;
}
.rn-tune .np-reset-btn:hover{
  background:var(--gold);
  color:var(--ivory);
  border-color:var(--gold);
}
.rn-tune .np-reset-btn:focus-visible{
  outline:2px solid var(--gold); outline-offset:2px;
}
.rn-tune .rn-meta{
  font-family:'DM Sans',sans-serif; font-size:11px;
  color:var(--dim); letter-spacing:0.3px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  max-width:100%;
}
.rn-tabs{ flex:0 0 auto; display:flex; align-items:center; }
.rn-actions{
  flex:1 1 0;
  display:flex; align-items:center; justify-content:flex-end; gap:6px;
}

/* Compact plate-tabs for Rail-N. The shipped glyphs stay (they are
   each lens's signature primitive — see commit eaee6fb), but padding
   and label sizes drop one step so the tabs fit a 64px rail without
   eating the brand's vertical breathing room. */
.app-header .plate-tabs{ margin:0; align-self:center; }
.app-header .plate-tab{ padding:6px 16px 5px; min-width:100px; gap:3px; }
.app-header .plate-tab-glyph{ width:42px; height:24px; }
.app-header .plate-tab-num{ font-size:8.5px; letter-spacing:2.2px; }
.app-header .plate-tab-label{ font-size:13px; }
.app-header .plate-tab.on{ box-shadow:inset 0 3px 0 var(--gold3); } /* R2.5 Q5 anchor */
/* Brass-bar transition — gentle fade on add/remove. Duration short enough
   to read as decisive, long enough that the lens switch feels performed. */
.app-header .plate-tab{ transition:box-shadow 120ms ease-out, background-color .15s, color .15s; }
@media (prefers-reduced-motion: reduce) {
  .app-header .plate-tab{ transition:none; }
}

/* Narrow-viewport graceful collapse: the Margin still reads as a frame
   but the side rails get out of the way of cramped layouts. */
@media (max-width: 720px){
  #app{ padding:24px 18px; }
  #app::before{ inset:24px 18px; }
  .rail-w, .rail-e{ display:none; }
  #pedal-strip{ left:18px !important; right:18px !important; bottom:24px !important; }
}

@keyframes fadeUp  {from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}
@keyframes pulse   {0%,100%{opacity:.5}50%{opacity:1}}
@keyframes glow    {0%,100%{box-shadow:0 0 16px rgba(232,199,106,.1)}50%{box-shadow:0 0 32px rgba(232,199,106,.25)}}
@keyframes tick    {0%{transform:scale(1)}50%{transform:scale(1.35)}100%{transform:scale(1)}}

html,body{height:100%;overflow:hidden;}
body{background-color:var(--bg);color:var(--text);font-family:'DM Sans',sans-serif;display:flex;flex-direction:column;}
button{cursor:pointer;font-family:'DM Sans',sans-serif;}
::-webkit-scrollbar{width:3px;height:3px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:var(--border2);border-radius:2px;}

/* ── SCREENS ── */
.screen{flex-direction:column;height:100%;overflow:hidden;background-color:var(--bg);}
#app{display:none;position:fixed;inset:0;z-index:1;flex-direction:column;}

/* ════════════════════════════════════════════════════════
   SPLASH — Netflix home
════════════════════════════════════════════════════════ */
.bg-neck{position:absolute;inset:0;overflow:hidden;opacity:.04;pointer-events:none;}
.bg-neck-inner{position:absolute;left:50%;transform:translateX(-50%);width:340px;top:0;bottom:0;}
.bg-fret{position:absolute;left:0;right:0;height:1px;background:var(--gold);}
.bg-string{position:absolute;top:0;bottom:0;width:1px;background:#888;}

.splash-title{font-family:'Playfair Display',serif;font-weight:700;font-size:clamp(52px,10vw,80px);color:var(--text);letter-spacing:10px;line-height:1;margin-bottom:4px;}
.splash-sub{font-family:'Playfair Display',serif;font-style:italic;font-size:clamp(13px,2vw,16px);color:var(--gold);letter-spacing:2px;margin-bottom:26px;}
.splash-pill{padding:7px 16px;border:1px solid var(--border);border-radius:24px;background:var(--surf);color:var(--dim);font-family:'Space Mono',monospace;font-size:14px;letter-spacing:1px;cursor:pointer;transition:all .17s;white-space:nowrap;user-select:none;}
.splash-pill:hover{border-color:var(--border2);color:var(--text);background:var(--surf2);}
.splash-pill.active{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
/* ── CHOOSER: Song cards ── */
.chooser-song-card{
  padding:12px 16px;border:1px solid rgba(61,170,112,0.2);border-radius:8px;
  background:rgba(61,170,112,0.04);cursor:pointer;transition:all .18s;
  min-width:130px;max-width:220px;
}
.chooser-song-card:hover{border-color:rgba(61,170,112,0.6);background:rgba(61,170,112,0.08);transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,0.3);}
.chooser-song-card.active{border-color:rgba(61,170,112,0.9);background:rgba(61,170,112,0.10);}
.csong-title{font-family:'Space Mono',monospace;font-size:14px;color:rgba(61,170,112,0.9);letter-spacing:1px;margin-bottom:4px;}
.csong-meta{font-family:'DM Sans',sans-serif;font-size:14px;color:var(--text);margin-bottom:2px;}
.csong-key{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim);letter-spacing:1px;}

/* ── CHOOSER: featured tiles ── */
.chooser-feat-tile{
  padding:14px 18px;border:1px solid rgba(201,168,76,0.28);border-radius:8px;
  background:rgba(201,168,76,0.05);cursor:pointer;transition:all .18s;
  min-width:150px;max-width:260px;
}
.chooser-feat-tile:hover{border-color:rgba(201,168,76,0.65);background:rgba(201,168,76,0.09);transform:translateY(-2px);box-shadow:0 8px 28px rgba(0,0,0,0.35);}
.chooser-feat-tile.active{border-color:var(--gold);background:rgba(201,168,76,0.12);box-shadow:0 0 20px rgba(201,168,76,0.15);}
.cfeat-name{font-family:'Playfair Display',serif;font-size:16px;color:var(--gold);margin-bottom:5px;line-height:1.2;}
.cfeat-chords{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim);letter-spacing:0.5px;margin-bottom:6px;line-height:1.5;}
.cfeat-lock{font-size:14px;color:rgba(201,168,76,0.45);letter-spacing:1px;font-family:'Space Mono',monospace;}


/* ════════════════════════════════════════════════════════
   APP CHROME
════════════════════════════════════════════════════════ */
#app{overflow:hidden;background:var(--bg);padding-bottom:100px;}
.app-header{display:flex;align-items:center;padding:8px 14px;border-bottom:1px solid var(--gold2);
  background:transparent;flex-shrink:0;gap:10px;color:var(--text);}
.logo{font-family:'Playfair Display',serif;font-size:20px;color:var(--gold);letter-spacing:5px;
  cursor:pointer;flex-shrink:0;line-height:1;opacity:0.9;transition:opacity .15s;}
.logo:hover{opacity:1;}
.logo span{display:none;}
.header-instruments{display:flex;gap:1px;flex:1;min-width:0;overflow:hidden;}
.inst-btn{padding:5px 8px;border:1px solid transparent;background:transparent;color:var(--dim);
  font-size:14px;font-family:'DM Sans',sans-serif;letter-spacing:.5px;border-radius:3px;transition:all .14s;text-transform:uppercase;white-space:nowrap;flex-shrink:1;min-width:0;}
.inst-btn:hover{color:var(--text);border-color:var(--border);}
.inst-btn.on{border-color:var(--border2);color:var(--text);background:var(--surf2);}
.pedal-reverb.on,.pedal-delay.on{border-color:rgba(61,170,112,0.6);color:#3daa70;background:rgba(61,170,112,0.10);}
/* ── PEDALBOARD — colored enclosures like real pedals ──────── */
.pb-pedal{
  border:1.5px solid rgba(255,255,255,0.10);border-radius:16px;
  padding:24px 22px 22px;text-align:center;position:relative;
  box-shadow:0 6px 24px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.04) inset;
  display:flex;flex-direction:column;align-items:center;gap:6px;
}
.pb-pedal:hover{border-color:rgba(255,255,255,0.16);}
/* Per-pedal powder-coat colors — the color IS the pedal.
   Bright enough to read from across the room, like 29 Pedals. */
.pb-c-gold{
  background:linear-gradient(170deg,#4e3f1e 0%,#382c12 100%);
  border-color:rgba(232,199,106,0.40);
}
.pb-c-teal{
  background:linear-gradient(170deg,#1a4e56 0%,#123e44 100%);
  border-color:rgba(78,200,200,0.35);
}
.pb-c-green{
  background:linear-gradient(170deg,#1e4e2e 0%,#143a20 100%);
  border-color:rgba(80,190,120,0.32);
}
.pb-c-orange{
  background:linear-gradient(170deg,#4e3810 0%,#3a2808 100%);
  border-color:rgba(240,160,48,0.35);
}
.pb-c-navy{
  background:linear-gradient(170deg,#1e305e 0%,#162248 100%);
  border-color:rgba(100,150,230,0.32);
}
.pb-c-brown{
  background:linear-gradient(170deg,#463422 0%,#342414 100%);
  border-color:rgba(190,150,100,0.32);
}
.pb-c-steel{
  background:linear-gradient(170deg,#383842 0%,#2a2a34 100%);
  border-color:rgba(180,180,205,0.28);
}
.pb-c-red{
  background:linear-gradient(170deg,#522420 0%,#3e1814 100%);
  border-color:rgba(220,90,70,0.36);
}
.pb-c-muted{
  background:linear-gradient(170deg,#383060 0%,#2a2248 100%);
  border-color:rgba(160,140,210,0.28);
}
.pb-c-charcoal{
  background:linear-gradient(170deg,#2a2820 0%,#1e1c16 100%);
  border-color:rgba(232,199,106,0.25);
}

/* Decorative ::after bottom-edge gradients (faux "light-catch") removed
   in the discipline audit — they encoded no information. */
.pb-board{display:flex;gap:28px;flex-wrap:wrap;align-items:flex-end;justify-content:center;padding:8px 0 28px;position:relative;}
/* ── PEDAL DEPTH — no filter, no transforms, no stacking contexts ──
   Side faces are plain dark divs. No filter:, no perspective:, no z-index.
   These properties create stacking contexts and break melody display.      */
.pb-pedal,.sk{position:relative;overflow:clip;}
.pb-side-r{
  position:absolute;top:5px;right:-7px;
  width:8px;height:calc(100% - 5px);
  background:rgba(0,0,0,0.55);
  border-radius:0 5px 5px 0;
  pointer-events:none;
}
.pb-side-b{
  position:absolute;bottom:-7px;left:5px;
  width:calc(100% - 5px);height:8px;
  background:rgba(0,0,0,0.65);
  border-radius:0 0 5px 0;
  pointer-events:none;
}
.pb-footswitch{
  box-shadow:0 5px 0 rgba(0,0,0,0.7),0 7px 12px rgba(0,0,0,0.5),
    inset 0 2px 3px rgba(255,255,255,0.07),inset 0 -2px 4px rgba(0,0,0,0.5);
  transition:box-shadow 0.08s,transform 0.08s;
}
.pb-footswitch:active{
  box-shadow:0 2px 0 rgba(0,0,0,0.7),0 3px 5px rgba(0,0,0,0.5),
    inset 0 2px 6px rgba(0,0,0,0.6);
  transform:translateY(3px);
}
.pb-btn,.pb-knob{
  box-shadow:0 2px 0 rgba(0,0,0,0.45),inset 0 1px 0 rgba(255,255,255,0.07);
  transition:box-shadow 0.08s,transform 0.08s;
}
.pb-btn:active,.pb-knob:active{
  box-shadow:inset 0 2px 4px rgba(0,0,0,0.5);
  transform:translateY(1px);
}
.pb-btn.on,.pb-knob.on{
  box-shadow:0 1px 0 rgba(0,0,0,0.4),inset 0 2px 4px rgba(0,0,0,0.4);
}
.pb-jacks{display:flex;justify-content:space-between;padding:0 6px;margin-top:6px;}
.pb-jack-slot{display:flex;flex-direction:column;align-items:center;gap:2px;}
.pb-jack{
  width:11px;height:11px;border-radius:50%;
  background:radial-gradient(circle at 38% 32%,#aaa,#444);
  border:1px solid #555;
  box-shadow:inset 0 1px 3px rgba(0,0,0,0.8),0 1px 2px rgba(255,255,255,0.08);
  position:relative;display:inline-block;
}
.pb-jack::after{
  content:'';position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);
  width:4px;height:4px;border-radius:50%;background:#111;
}
.pb-jack-lbl{font-size:8px;letter-spacing:1px;color:rgba(200,195,220,0.4);
  font-family:'DM Sans',sans-serif;text-transform:uppercase;}

.pb-board .pb-pedal{flex:0 1 auto;min-width:140px;max-width:320px;}
.pb-wide{flex:1 1 280px !important;min-width:240px !important;max-width:400px !important;}
.pb-narrow{min-width:120px !important;max-width:200px !important;}
.pb-shelf{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:0 4px;}
.pb-shelf-lbl{font-size:12px;letter-spacing:5px;color:var(--dim2);text-transform:uppercase;font-family:'DM Sans',sans-serif;white-space:nowrap;}
/* Pedal name — Playfair, muted gold, generous spacing below */
.pb-label{font-size:16px;letter-spacing:4px;text-transform:uppercase;font-family:'Playfair Display',serif;margin-bottom:16px;font-weight:700;color:var(--gold3);}
/* Controls container — wider gaps for breathing room */
.pb-pedal .pb-controls{gap:8px;width:100%;}
.pb-pedal .pb-btn{font-family:'DM Sans',sans-serif;font-size:14px;padding:10px 16px;border-radius:8px;
  background:rgba(0,0,0,0.40);border:1.5px solid rgba(255,255,255,0.10);
  box-shadow:0 2px 6px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.05);
  color:rgba(200,195,220,0.8);transition:all 0.12s;width:100%;}
.pb-pedal .pb-btn:hover{background:rgba(0,0,0,0.35);border-color:rgba(255,255,255,0.18);}
.pb-pedal .pb-btn.on{background:rgba(0,0,0,0.50);border-color:rgba(232,199,106,0.45);color:var(--gold);
  box-shadow:0 2px 6px rgba(0,0,0,0.4), inset 0 1px 0 rgba(232,199,106,0.08);}
.pb-pedal .pb-knob{font-family:'DM Sans',sans-serif;font-size:14px;padding:7px 14px;
  background:rgba(0,0,0,0.40);border:1.5px solid rgba(255,255,255,0.10);border-radius:6px;
  box-shadow:0 2px 4px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.04);
  color:rgba(200,195,220,0.8);transition:all 0.12s;}
.pb-pedal .pb-knob.on{border-color:rgba(232,199,106,0.4);color:var(--gold);background:rgba(232,199,106,0.08);}
.pb-pedal .pb-knob-lbl{font-family:'DM Sans',sans-serif;font-size:14px;color:var(--dim);}
.pb-pedal .pb-knob-val{font-family:'Space Mono',monospace;font-size:14px;color:var(--gold);}
.pb-pedal .pb-param{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim);}
.pb-pedal .pb-eq-lbl{font-family:'DM Sans',sans-serif;font-size:14px;color:var(--dim);}
.pb-pedal .pb-eq-val{font-family:'Space Mono',monospace;font-size:14px;color:var(--gold);}
/* Footswitch — push to bottom, generous space above */
.pb-footswitch{margin:auto auto 0;margin-top:20px;}
.pb-c-gold  .pb-label{color:rgba(232,199,106,0.85);}
.pb-c-teal  .pb-label{color:rgba(120,220,220,0.75);}
.pb-c-green .pb-label{color:rgba(120,210,150,0.75);}
.pb-c-orange .pb-label{color:rgba(250,180,80,0.80);}
.pb-c-navy  .pb-label{color:rgba(140,170,230,0.75);}
.pb-c-brown .pb-label{color:rgba(210,175,120,0.80);}
.pb-c-steel .pb-label{color:rgba(200,200,220,0.70);}
.pb-c-red   .pb-label{color:rgba(230,120,100,0.80);}
.pb-c-muted .pb-label{color:rgba(180,160,230,0.70);}
.pb-c-charcoal .pb-label{color:rgba(232,199,106,0.70);}
.pb-bpm-display{color:#e8c76a;min-width:52px;text-align:center;cursor:text;border:1px solid rgba(232,199,106,0.20);padding:6px 10px;outline:none;font-size:26px;font-family:'Space Mono',monospace;background:rgba(0,0,0,0.5);border-radius:4px;box-shadow:inset 0 1px 4px rgba(0,0,0,0.4);}
.pb-controls{display:flex;flex-direction:column;gap:8px;}
.pb-btn{background:rgba(0,0,0,0.35);border:1px solid rgba(255,255,255,0.08);border-radius:6px;padding:8px 14px;color:rgba(200,195,220,0.75);font-size:16px;font-family:'Space Mono',monospace;cursor:pointer;display:flex;align-items:center;gap:8px;transition:all 0.15s;box-shadow:0 1px 3px rgba(0,0,0,0.3);}
.pb-btn:hover{border-color:rgba(255,255,255,0.15);color:var(--text);background:rgba(0,0,0,0.4);}
.pb-btn.on{border-color:rgba(232,199,106,0.40);color:var(--text);background:rgba(232,199,106,0.08);box-shadow:0 1px 3px rgba(0,0,0,0.3),0 0 6px rgba(232,199,106,0.06);}
.pb-led{width:8px;height:8px;border-radius:50%;opacity:0.12;flex-shrink:0;transition:all 0.2s;box-shadow:inset 0 1px 1px rgba(0,0,0,0.4);}
.pb-btn.on .pb-led{opacity:1;box-shadow:0 0 10px 2px currentColor;}
.pb-stomp{display:flex;flex-direction:column;align-items:center;gap:4px;}
.pb-param{font-size:14px;color:rgba(200,195,220,0.70);font-family:'Space Mono',monospace;letter-spacing:0.5px;}
/* ── FOOTSWITCH — chrome dome, the hero of every pedal ──────── */
.pb-footswitch{
  width:56px;height:56px;border-radius:50%;
  background:radial-gradient(circle at 38% 35%, #4a4860, #2a283e 45%, #1c1a30 100%);
  border:2px solid rgba(255,255,255,0.12);cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  transition:all 0.12s;
  box-shadow:
    0 6px 16px rgba(0,0,0,0.7),
    0 2px 4px rgba(0,0,0,0.4),
    inset 0 2px 6px rgba(255,255,255,0.08),
    inset 0 -3px 8px rgba(0,0,0,0.5);
  margin:10px auto 0;
}
.pb-footswitch:hover{
  border-color:rgba(255,255,255,0.20);
  box-shadow:0 6px 18px rgba(0,0,0,0.8),0 2px 4px rgba(0,0,0,0.4),inset 0 2px 6px rgba(255,255,255,0.10),inset 0 -3px 8px rgba(0,0,0,0.5);
}
.pb-footswitch:active{transform:translateY(2px);box-shadow:0 2px 6px rgba(0,0,0,0.8),inset 0 2px 8px rgba(0,0,0,0.6);}
.pb-footswitch.on{
  border-color:rgba(61,170,112,0.5);
  background:radial-gradient(circle at 38% 35%, #2e4a3c, #1c3028 45%, #142420 100%);
}
.pb-fs-led{width:11px;height:11px;border-radius:50%;background:#1a1a1a;transition:all 0.25s;box-shadow:inset 0 1px 2px rgba(0,0,0,0.6);}
.pb-footswitch.on .pb-fs-led{background:radial-gradient(circle,#5dff8a,#3daa70 60%,#2a7a50);box-shadow:0 0 16px rgba(61,170,112,0.9),0 0 6px rgba(93,255,138,0.5);}
/* EQ */
.pb-eq-ch{text-align:center;}
.pb-eq-lbl{font-size:14px;color:rgba(200,195,220,0.70);font-family:'Space Mono',monospace;margin-top:4px;letter-spacing:1px;}
.pb-eq-val{font-size:14px;color:var(--gold);font-family:'Space Mono',monospace;}
/* Knob toggle buttons — tactile selectors, big enough to tap */
.pb-knob{background:rgba(0,0,0,0.4);border:1px solid rgba(255,255,255,0.08);border-radius:5px;padding:5px 10px;color:rgba(200,195,220,0.75);font-size:14px;font-family:'Space Mono',monospace;cursor:pointer;transition:all 0.12s;letter-spacing:0.5px;box-shadow:0 1px 2px rgba(0,0,0,0.3);}
.pb-knob:hover{border-color:rgba(255,255,255,0.15);color:var(--text);}
.pb-knob.on{border-color:rgba(232,199,106,0.45);color:var(--gold);background:rgba(232,199,106,0.10);box-shadow:0 1px 2px rgba(0,0,0,0.3),0 0 4px rgba(232,199,106,0.08);}
.pb-knob-lbl{font-size:14px;color:rgba(200,195,220,0.70);font-family:'Space Mono',monospace;letter-spacing:0.5px;min-width:24px;}
.pb-knob-val{font-size:14px;color:var(--gold);font-family:'Space Mono',monospace;min-width:28px;text-align:right;}
/* Sliders — full-width tracks with gold thumb */
.pb-slider-row{display:flex;align-items:center;gap:4px;padding:2px 0;width:100%;}
.pb-slider-row .pb-knob-lbl{flex:0 0 auto;white-space:nowrap;font-size:11px;letter-spacing:0.5px;}
.pb-slider-row .pb-knob-val{flex:0 0 auto;min-width:26px;text-align:right;font-size:11px;}
/* Stacked slider: label+value on top, full-width track below */
.pb-slider-stack{display:flex;flex-direction:column;gap:3px;padding:2px 0;width:100%;}
.pb-slider-header{display:flex;justify-content:space-between;align-items:baseline;width:100%;}
.pb-slider-header .pb-knob-lbl{font-size:10px;letter-spacing:0.8px;text-transform:uppercase;color:var(--dim);font-family:'DM Sans',sans-serif;}
.pb-slider-header .pb-knob-val{font-size:11px;color:var(--gold);font-family:'Space Mono',monospace;}
.pb-slider-stack .pb-slider{width:100%;flex:none;}
.pb-slider{-webkit-appearance:none;appearance:none;width:100%;flex:1;height:6px;background:rgba(255,255,255,0.08);border-radius:3px;outline:none;cursor:pointer;border:none;box-shadow:inset 0 1px 2px rgba(0,0,0,0.3);}
.pb-slider::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;background:radial-gradient(circle at 38% 35%,#f4de80,#c9a840 70%);border-radius:50%;cursor:pointer;border:1px solid rgba(0,0,0,0.3);box-shadow:0 2px 6px rgba(0,0,0,0.5),0 0 10px rgba(232,199,106,0.15);}
.pb-slider::-moz-range-thumb{width:18px;height:18px;background:radial-gradient(circle at 38% 35%,#f4de80,#c9a840 70%);border-radius:50%;cursor:pointer;border:1px solid rgba(0,0,0,0.3);}
/* EQ vertical sliders — taller, more prominent */
.eq-slider{-webkit-appearance:none;appearance:none;width:8px;height:90px;background:rgba(255,255,255,0.08);border-radius:4px;outline:none;writing-mode:vertical-lr;direction:rtl;cursor:pointer;border:none;box-shadow:inset 1px 0 2px rgba(0,0,0,0.3);}
.eq-slider::-webkit-slider-thumb{-webkit-appearance:none;width:20px;height:8px;background:linear-gradient(180deg,#f4de80,#c9a840);border-radius:3px;cursor:pointer;border:1px solid rgba(0,0,0,0.3);box-shadow:0 1px 4px rgba(0,0,0,0.5);}
.eq-slider::-moz-range-thumb{width:20px;height:8px;background:linear-gradient(180deg,#f4de80,#c9a840);border-radius:3px;cursor:pointer;border:1px solid rgba(0,0,0,0.3);}
.eq-slider::-webkit-slider-runnable-track{background:transparent;}
.eq-slider::-moz-range-track{background:transparent;}

/* ── PER-PEDAL VISUAL PERSONALITY ─────────────────────────────
   Each pedal has its own character. Like real pedals in a shop —
   you can tell the Reverb from the Delay from across the room.
   Controls FILL the enclosure. No swimming pools.
   ─────────────────────────────────────────────────────────────── */

/* VOICE — warm amp-head channel strip. Big chunky voice selectors. */
[data-pedal="voice"]{
  border-radius:12px;
  box-shadow:0 4px 14px rgba(0,0,0,0.6), 0 1px 0 rgba(232,199,106,0.06) inset;
}
[data-pedal="voice"] .pb-label::after{
  /* Waveform hint — "this controls your sound" */
  content:'∿';display:block;font-size:18px;color:var(--dim2);margin:-6px 0 4px;letter-spacing:8px;
}
[data-pedal="voice"] .pb-btn{
  border-radius:6px;
  font-size:16px;
  padding:10px 16px;
  font-family:'DM Sans',sans-serif;
}
[data-pedal="voice"] .pb-led{width:10px;height:10px;}
[data-pedal="voice"] .pb-controls{gap:3px;}

/* PATTERN — 3-way toggle. Rhythm selector. */
[data-pedal="pattern"]{
  border-radius:8px;
  display:flex;flex-direction:column;justify-content:center;
}
[data-pedal="pattern"] .pb-label::after{
  content:'♩ ♪ ♩ ♪';display:block;font-size:12px;color:var(--dim2);margin:-6px 0 4px;letter-spacing:3px;opacity:0.45;
}
[data-pedal="pattern"] .pb-btn{
  font-size:16px;
  padding:14px 18px;
  border-radius:8px;
  letter-spacing:1.5px;
  justify-content:center;
  font-family:'DM Sans',sans-serif;
  width:100%;
}
[data-pedal="pattern"] .pb-led{width:10px;height:10px;}
[data-pedal="pattern"] .pb-controls{gap:4px;}
[data-pedal="pattern"] .pb-btn.on{border-color:rgba(100,150,230,0.45);color:rgba(140,180,240,0.95);background:rgba(90,140,220,0.12);box-shadow:0 1px 3px rgba(0,0,0,0.3),0 0 6px rgba(90,140,220,0.08);}
[data-pedal="pattern"] .pb-btn.on .pb-led{box-shadow:0 0 10px 2px rgba(100,160,240,0.8);}

/* MIX — utility junction box, compact but readable */
[data-pedal="mix"]{
  border-radius:6px;
}
[data-pedal="mix"] .pb-label::after{
  content:'⇌ see · hear';display:block;font-size:10px;color:var(--dim2);margin:-6px 0 6px;letter-spacing:1px;opacity:0.5;
}
[data-pedal="mix"] .pb-knob{
  font-size:14px;
  padding:6px 12px;
}
[data-pedal="mix"] .pb-knob-lbl{
  font-size:14px;
  letter-spacing:2px;
  margin-bottom:2px;
  display:block;
  text-align:center;
}

/* REVERB — oceanic depth. Teal glow. Sliders are the star. */
[data-pedal="reverb"]{
  border-radius:12px;
  box-shadow:0 4px 18px rgba(0,0,0,0.6), 0 0 24px rgba(78,200,200,0.05) inset;
}
[data-pedal="reverb"] .pb-label::after{
  /* Expanding arcs — "this adds space" */
  content:')  ))  )))';display:block;font-size:11px;color:var(--dim2);margin:-6px 0 6px;letter-spacing:1px;opacity:0.6;
}
[data-pedal="reverb"] .pb-knob{
  border-color:rgba(78,200,200,0.15);
  font-size:14px;
  padding:5px 12px;
}
[data-pedal="reverb"] .pb-knob.on{
  border-color:rgba(78,200,200,0.5);
  color:rgba(120,220,220,0.9);
  background:rgba(78,200,200,0.10);
  box-shadow:0 0 6px rgba(78,200,200,0.12);
}
[data-pedal="reverb"] .pb-slider::-webkit-slider-thumb{
  background:radial-gradient(circle at 38% 35%,#8eeee0,#4eb4b4 70%);
  box-shadow:0 2px 6px rgba(0,0,0,0.5),0 0 10px rgba(78,200,200,0.3);
}
[data-pedal="reverb"] .pb-knob-val{color:rgba(120,220,220,0.8);}
[data-pedal="reverb"] .pb-knob-lbl{color:rgba(120,220,220,0.70);}
[data-pedal="reverb"] .pb-footswitch.on{
  border-color:rgba(78,200,200,0.5);
  background:radial-gradient(circle at 38% 35%, #1e3a3e, #103030 45%, #0a2424 100%);
}
[data-pedal="reverb"] .pb-footswitch.on .pb-fs-led{
  background:radial-gradient(circle,#8eeee0,#4eb4b4 60%,#2a8080);
  box-shadow:0 0 16px rgba(78,200,200,0.9),0 0 6px rgba(142,238,224,0.5);
}

/* DELAY — vintage tape echo. Warm green. Time buttons like tape speed labels. */
[data-pedal="delay"]{
  border-radius:10px;
  box-shadow:0 4px 16px rgba(0,0,0,0.6), 0 0 20px rgba(80,190,120,0.04) inset;
}
[data-pedal="delay"] .pb-label::after{
  /* Fading echoes — "this repeats and fades" */
  content:'● ● ◐ ○ ○';display:block;font-size:10px;color:var(--dim2);margin:-6px 0 6px;letter-spacing:4px;opacity:0.6;
}
[data-pedal="delay"] .pb-knob{
  border-color:rgba(80,190,120,0.15);
  font-size:14px;
  padding:5px 11px;
}
[data-pedal="delay"] .pb-knob.on{
  border-color:rgba(80,190,120,0.5);
  color:rgba(110,210,150,0.9);
  background:rgba(80,190,120,0.10);
  box-shadow:0 0 6px rgba(80,190,120,0.12);
}
[data-pedal="delay"] .pb-slider::-webkit-slider-thumb{
  background:radial-gradient(circle at 38% 35%,#a0e8b8,#50aa70 70%);
  box-shadow:0 2px 6px rgba(0,0,0,0.5),0 0 10px rgba(80,190,120,0.3);
}
[data-pedal="delay"] .pb-knob-val{color:rgba(110,210,150,0.8);}
[data-pedal="delay"] .pb-knob-lbl{color:rgba(110,210,150,0.70);}
[data-pedal="delay"] .pb-param{color:rgba(110,210,150,0.60);}
[data-pedal="delay"] .pb-footswitch.on{
  border-color:rgba(80,190,120,0.5);
  background:radial-gradient(circle at 38% 35%, #1e3a28, #103020 45%, #0a2418 100%);
}
[data-pedal="delay"] .pb-footswitch.on .pb-fs-led{
  background:radial-gradient(circle,#a0e8b8,#50aa70 60%,#308050);
  box-shadow:0 0 16px rgba(80,190,120,0.9),0 0 6px rgba(160,232,184,0.5);
}

/* EQ — industrial graphic EQ. Orange faders, functional beauty. */
[data-pedal="eq"]{
  border-radius:8px;
}
[data-pedal="eq"] .pb-label::after{
  content:'⎸ ⎹ ⎸';display:block;font-size:14px;color:var(--dim2);margin:-6px 0 6px;letter-spacing:6px;opacity:0.4;
}
[data-pedal="eq"] .eq-slider::-webkit-slider-thumb{
  background:linear-gradient(180deg,#f8c860,#e09030);
  box-shadow:0 1px 4px rgba(0,0,0,0.5),0 0 6px rgba(240,160,48,0.2);
}
[data-pedal="eq"] .pb-eq-lbl{color:rgba(250,180,80,0.5);}
[data-pedal="eq"] .pb-eq-val{color:rgba(250,180,80,0.85);}

/* TEMPO — clockwork precision. BPM display is the hero. Red accents. */
[data-pedal="tempo"]{
  border-radius:10px;
  box-shadow:0 4px 16px rgba(0,0,0,0.6), 0 0 14px rgba(210,80,60,0.04) inset;
}
[data-pedal="tempo"] .pb-label::after{
  /* Pulse marks — "this sets the heartbeat" */
  content:'|  ·  ·  ·  |  ·  ·  ·';display:block;font-size:12px;color:var(--dim2);margin:-6px 0 6px;letter-spacing:1px;opacity:0.5;
}
[data-pedal="tempo"] .pb-bpm-display{
  font-size:22px;
  padding:6px 12px;
  border-color:rgba(210,80,60,0.30);
  box-shadow:inset 0 1px 6px rgba(0,0,0,0.5), 0 0 8px rgba(210,80,60,0.08);
  color:rgba(230,110,90,0.95);
}
[data-pedal="tempo"] .pb-knob{
  border-color:rgba(210,80,60,0.12);
  font-size:14px;
  padding:5px 11px;
}
[data-pedal="tempo"] .pb-knob.on{
  border-color:rgba(210,80,60,0.45);
  color:rgba(230,110,90,0.9);
  background:rgba(210,80,60,0.10);
}
[data-pedal="tempo"] .pb-footswitch.on{
  border-color:rgba(210,80,60,0.5);
  background:radial-gradient(circle at 38% 35%, #3a1e1c, #301410 45%, #240e0a 100%);
}
[data-pedal="tempo"] .pb-footswitch.on .pb-fs-led{
  background:radial-gradient(circle,#ff7860,#d04030 60%,#a02820);
  box-shadow:0 0 16px rgba(210,80,60,0.9),0 0 6px rgba(255,120,96,0.5);
}

/* BASS — woody warmth. Big chunky style buttons. Organic grain. */
[data-pedal="bass"]{
  border-radius:10px;
}
[data-pedal="bass"] .pb-label::after{
  content:'♩   ♩   ♩   ♩';display:block;font-size:14px;color:var(--dim2);margin:-6px 0 4px;opacity:0.35;letter-spacing:2px;
}
[data-pedal="bass"] .pb-knob{
  font-size:14px;
  padding:8px 14px;
  border-color:rgba(180,140,90,0.15);
}
[data-pedal="bass"] .pb-knob.on{
  border-color:rgba(180,140,90,0.5);
  color:rgba(210,175,120,0.9);
  background:rgba(180,140,90,0.10);
}
[data-pedal="bass"] .pb-slider::-webkit-slider-thumb{
  background:radial-gradient(circle at 38% 35%,#e8c888,#b08850 70%);
}
[data-pedal="bass"] .pb-knob-lbl{color:rgba(210,175,120,0.70);}
[data-pedal="bass"] .pb-footswitch.on{
  border-color:rgba(180,140,90,0.5);
  background:radial-gradient(circle at 38% 35%, #302818, #241c10 45%, #1a1408 100%);
}
[data-pedal="bass"] .pb-footswitch.on .pb-fs-led{
  background:radial-gradient(circle,#e8c888,#b08850 60%,#806030);
  box-shadow:0 0 16px rgba(180,140,90,0.8),0 0 6px rgba(232,200,136,0.4);
}

/* DRUMS — brushed metal. Big mode buttons. Percussive. */
[data-pedal="drums"]{
  border-radius:8px;
}
[data-pedal="drums"] .pb-label::after{
  /* Hit marks — "this is percussion" */
  content:'×  ·  ×  ·';display:block;font-size:12px;color:var(--dim2);margin:-6px 0 4px;letter-spacing:4px;opacity:0.5;
}
[data-pedal="drums"] .pb-knob{
  font-size:14px;
  padding:7px 12px;
  border-color:rgba(170,170,195,0.12);
}
[data-pedal="drums"] .pb-knob.on{
  border-color:rgba(170,170,195,0.45);
  color:rgba(200,200,220,0.9);
  background:rgba(170,170,195,0.08);
}
[data-pedal="drums"] .pb-slider::-webkit-slider-thumb{
  background:radial-gradient(circle at 38% 35%,#d0d0e0,#9090a8 70%);
}
[data-pedal="drums"] .pb-knob-lbl{color:rgba(190,190,210,0.70);}
[data-pedal="drums"] .pb-footswitch.on{
  border-color:rgba(170,170,195,0.4);
  background:radial-gradient(circle at 38% 35%, #2a2a32, #1e1e24 45%, #161618 100%);
}
[data-pedal="drums"] .pb-footswitch.on .pb-fs-led{
  background:radial-gradient(circle,#e0e0f0,#9090a8 60%,#606070);
  box-shadow:0 0 14px rgba(170,170,195,0.7),0 0 5px rgba(224,224,240,0.4);
}

/* ── 3D NATIVE — depth is always present ──────────────────── */
.pb-board{
  transform-style:preserve-3d;
}
.pb-pedal{
  transform-style:preserve-3d;
  transform:translateZ(0);
}
.pb-label{transform:translateZ(1px);}
.pb-footswitch{transform:translateZ(4px);}

/* ── VISUAL HIERARCHY — three tiers, all WCAG AA ──────────────
   Font roles:
     Playfair Display = musical identity (Roman numerals, chord names, pedal names)
     DM Sans = readable interface (buttons, labels, controls, status)
     Space Mono = data readouts (BPM, fret numbers, tab, knob values)
   Color tiers (all AA on --bg AND --surf2):
     --text (15:1) = PRIMARY — things you act on
     --dim  (7:1)  = SECONDARY — context you glance at
     --dim2 (5:1)  = TERTIARY — structure that organizes
     --gold (12:1) = accent hero — sparingly, one per view
     --gold3 (7:1) = muted gold — receding accent
   ─────────────────────────────────────────────────────────── */

/* PRIMARY — 16px, DM Sans, full brightness. Things you ACT on. */
.pb-btn{font-size:16px; font-family:'DM Sans',sans-serif;}
.strum-btn{font-size:16px !important; font-family:'DM Sans',sans-serif !important;}
.card-hear{font-size:14px; font-family:'DM Sans',sans-serif; color:var(--dim);}
.picker-title{font-size:16px; font-family:'DM Sans',sans-serif;}

/* SECONDARY — 14px, DM Sans, --dim. Context you GLANCE at. */
.pb-knob{font-size:14px; font-family:'DM Sans',sans-serif;}
.pb-param{font-size:14px;}
.pb-eq-val{font-size:14px;}
.pb-knob-val{font-size:14px;}
.cs-lbl{font-size:14px; font-family:'DM Sans',sans-serif;}
.ctab{font-size:14px;} /* stays Space Mono — it's tab data */
.tweak-btn{font-size:14px; font-family:'DM Sans',sans-serif;}
.tweak-lbl{font-size:14px; font-family:'DM Sans',sans-serif;}
.settings-label{font-size:14px; font-family:'DM Sans',sans-serif;}
.sh-label{font-size:14px; font-family:'DM Sans',sans-serif;}
.sh-btn{font-size:14px; font-family:'DM Sans',sans-serif;}
#inst-desc{font-size:14px; font-family:'DM Sans',sans-serif;}
.attr-origin{font-size:14px; font-family:'DM Sans',sans-serif;}
.attr-badge-pill{font-size:14px; font-family:'DM Sans',sans-serif;}
.attr-note{font-size:14px !important;}

/* TERTIARY — structure that ORGANIZES. DM Sans, --dim2. */
.pb-shelf-lbl{font-size:12px; font-family:'DM Sans',sans-serif; color:var(--dim2);}
.pb-eq-lbl{font-size:14px; font-family:'DM Sans',sans-serif;}
.pb-knob-lbl{font-size:14px; font-family:'DM Sans',sans-serif;}
.fspan{font-size:14px; font-family:'DM Sans',sans-serif; color:var(--dim2);}
.share-locked-strip{font-size:14px; font-family:'DM Sans',sans-serif;}

/* PEDAL NAMES — Playfair, gold-muted. Musical identity that recedes. */
.pb-label{font-size:16px; font-family:'Playfair Display',serif; color:var(--gold3);}

/* Instrument context description — make readable */
#inst-desc { color: rgba(232,199,106,0.5); min-height: 14px; font-size:14px; }
.logo span { display: none; }

/* ── Tuning variant buttons: visually attached to inst button ── */
#tune-row{
  display:flex;gap:0;margin:0;padding:0;
  border-left:1px solid var(--border);
  margin-left:2px;
  flex-shrink:0;
}
.tune-btn{
  padding:5px 7px;border:none;border-right:1px solid var(--border);
  background:transparent;color:var(--dim);
  font-family:'Space Mono',monospace;font-size:14px;letter-spacing:.5px;
  cursor:pointer;transition:all .14s;white-space:nowrap;
  text-transform:uppercase;
}
.tune-btn:hover{color:var(--text);background:var(--surf2);}
.tune-btn.on{color:var(--gold);background:rgba(232,199,106,0.08);}

/* ── Font size toggle ── */
.font-size-btn{
  padding:4px 8px;border:1px solid var(--border);background:transparent;
  color:var(--dim);font-family:'Space Mono',monospace;font-size:14px;
  letter-spacing:1px;cursor:pointer;border-radius:3px;transition:all .15s;
  flex-shrink:0;
}
.font-size-btn:hover{border-color:var(--border2);color:var(--text);}
.font-size-btn.on{border-color:var(--gold);color:var(--gold);background:rgba(232,199,106,0.08);}

/* ── Large text mode — 25% bump above base ── */
/* A+ font size — scale root font-size, everything inherits */
/* A+ toggle: zoom scales everything — inline styles, px values, all of it */
html.large-text #app { zoom: 1.15; }
html.large-text #screen-landing { zoom: 1.15; }
.header-right{display:flex;gap:3px;flex-shrink:0;margin-left:6px;}

/* Tuning sub-buttons — sit inline after their instrument button */
.tune-btn{
  font-size:11px !important;padding:4px 7px !important;
  border-left:1px solid rgba(255,255,255,0.06) !important;
  opacity:0.65;letter-spacing:0.5px;
}
.tune-btn.on{ opacity:1; }
.tune-btn:first-child{ border-left:none !important; margin-left:2px; }

/* Font size toggle */
.font-size-btn{
  padding:3px 7px;border:1px solid var(--border);background:transparent;
  color:var(--dim);font-family:'Space Mono',monospace;font-size:14px;
  border-radius:3px;cursor:pointer;transition:all .15s;flex-shrink:0;
  letter-spacing:1px;
}
.font-size-btn.on{ border-color:var(--gold);color:var(--gold);background:var(--gold-dim); }

/* Large font mode — REMOVED: font-lg class is unused. large-text class handles A+ toggle. */
.mode-btn{padding:5px 11px;border:1px solid var(--gold);background:var(--gold-dim);color:var(--gold);
  font-size:14px;letter-spacing:2px;border-radius:3px;transition:all .14s;text-transform:uppercase;}
.mode-btn:hover{background:rgba(201,168,76,0.18);border-color:var(--gold2);}
.mode-btn.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
.lib-header-btn{padding:5px 10px;border:1px solid var(--border);background:transparent;color:var(--dim);
  font-size:14px;letter-spacing:1px;border-radius:3px;transition:all .14s;text-transform:uppercase;}
.lib-header-btn:hover{border-color:var(--border2);color:var(--text);}

/* ── ATTRIBUTION BANNER ── */
.attr-banner-strip{
  background:linear-gradient(90deg,rgba(232,199,106,.09),rgba(232,199,106,.03));
  border-bottom:1px solid rgba(232,199,106,.15);
  padding:10px 20px;flex-shrink:0;
}
.attr-badge-pill{
  font-size:11px;letter-spacing:2px;padding:3px 9px;border-radius:4px;
  font-family:'DM Sans',sans-serif;font-weight:700;text-transform:uppercase;
  background:rgba(232,199,106,.15);color:var(--gold);
}
.attr-name{font-family:'DM Sans',sans-serif;font-size:15px;font-weight:600;color:#fff;}
.attr-note{
  flex:1;font-family:'DM Sans',sans-serif;font-size:14px;
  color:var(--dim);font-style:italic;white-space:pre-wrap;
  line-height:1.5;padding-top:6px;display:block;
}
.attr-origin{font-size:12px;color:var(--dim2);letter-spacing:1px;margin-top:4px;font-family:'Space Mono',monospace;}
.attr-save-btn{background:transparent;border:1px solid var(--border);border-radius:4px;padding:3px 10px;
  color:var(--dim);font-family:'Space Mono',monospace;font-size:14px;letter-spacing:1px;cursor:pointer;transition:all .14s;}
.attr-save-btn:hover{border-color:var(--gold);color:var(--gold);}
/* R4 Q5 italic rule: teacher hints / player voice → Playfair italic, not Space Mono italic. */
.share-locked-strip{text-align:center;font-size:14px;color:var(--dim2);letter-spacing:0;
  font-family:'Playfair Display',serif;font-style:italic;padding:6px;border-bottom:1px solid var(--border);flex-shrink:0;}

/* ── PANELS ── */
.v3-pane{display:none;flex:1;overflow:hidden;}
.v3-pane.active{display:flex;}

/* ════════════════════════════════════════════════════════
   PLAY / CHARTS
════════════════════════════════════════════════════════ */

/* Sidebar */
/* ════════════════════════════════════════════════════════
   LIBRARY — centered two-column modal
════════════════════════════════════════════════════════ */
/* ── PLATE C · Library drawer ────────────────────────────────
   Formerly a dark modal with gray surfaces and white text. Now
   a vellum plate matching the rest of the Plate A vocabulary:
   hairline brass double-rule, Playfair italic names, Space Mono
   caps for engineering labels, no rounded corners on cards
   (plates aren't rounded). */
.picker-overlay{
  display:none; position:fixed; inset:0;
  background:rgba(26,12,4,0.72);
  /* R5.47 — was z-index:200, which sat BELOW the pedal-strip (z:600)
     and beta-banner (z:500). Scrim was technically full-viewport but
     those two punched through in full color, making the library look
     "attached to the bottom" with row-3 tune cards clipped at the
     pedal-strip's top edge. Bumping scrim above both so dimming
     covers the entire viewport when library is open. Drawer panel
     follows below at +1. */
  z-index:700;
  backdrop-filter:blur(6px);
}
.picker-overlay.open{ display:block; }

.picker-panel{
  position:fixed; top:50%; left:50%;
  transform:translate(-50%,-50%) scale(.96);
  width:min(1020px, 96vw); height:min(84vh, 760px);
  background:var(--vellum);
  border:1px solid var(--gold2);
  box-shadow:0 24px 60px rgba(26,12,4,0.45),
             0 0 0 1px rgba(240,226,190,0.5) inset;
  z-index:701; display:flex; flex-direction:column;
  opacity:0; pointer-events:none;
  transition:opacity .22s ease, transform .22s ease, height .22s ease, width .22s ease;
  overflow:hidden;
}
/* r6p43-modal-fit-build (Scott 2026-05-17): "can we better fit the
   modal to the info?" BROWSE/IMPORT need the full panel for tune
   lists / ABC textareas; BUILD is a small key+mode+tempo form. The
   per-door class set by libSetDoor collapses the panel + lets the
   door-panel content size itself (flex:0 0 auto + overflow:visible
   override of the browse-mode flex:1 + scroll). */
.picker-panel.lib-door-mode-build{
  height:auto;
  max-height:min(84vh, 760px);
  width:min(720px, 96vw);
}
.picker-panel.lib-door-mode-build .lib-door-panel{
  flex:0 0 auto;
  min-height:auto;
  overflow:visible;
}
/* Inner double-brass rule — the plate's page edge */
.picker-panel::before{
  content:""; position:absolute; inset:5px; pointer-events:none;
  border:1px solid var(--gold2); opacity:0.35;
}
.picker-panel.open{
  opacity:1; pointer-events:all;
  transform:translate(-50%,-50%) scale(1);
}

/* Top cartouche — title + plate sigil */
.lib-hd{
  display:flex; align-items:baseline; justify-content:space-between;
  padding:18px 26px 14px; gap:18px;
  border-bottom:1px solid var(--gold2); flex-shrink:0;
  position:relative;
}
.lib-hd-left{ display:flex; align-items:baseline; gap:12px; min-width:0; }
.lib-hd-left .plate-title{ color:var(--text); }
.lib-hd-left .plate-sub{
  font-family:'Playfair Display',serif; font-style:italic;
  color:var(--gold); white-space:nowrap;
}
.lib-hd-right{
  display:flex; align-items:center; gap:14px; flex-shrink:0;
}
.lib-hd-right .eng-label{
  font-size:9px; letter-spacing:2.4px; opacity:0.9;
}

.picker-close{
  background:transparent; border:1px solid var(--gold2); border-radius:1px;
  color:var(--dim); font-size:14px; line-height:1;
  cursor:pointer; padding:4px 9px; transition:all .12s;
  font-family:'Space Mono',monospace;
}
.picker-close:hover{
  color:var(--gold); border-color:var(--gold); background:var(--gold-dim);
}

/* Two-column inner layout */
.lib-modal-inner{
  display:flex; flex:1; min-height:0;
}

/* ── Left rail — Your bench + Sections nav ── */
.lib-rail{
  width:240px; flex-shrink:0;
  border-right:1px solid var(--gold2);
  display:flex; flex-direction:column;
  background:linear-gradient(180deg, rgba(184,190,160,0.18) 0%, rgba(184,190,160,0) 100%);
}
.lib-rail-hd{
  padding:16px 18px 10px; flex-shrink:0;
}
.lib-rail-hd .fig-banner{
  font-size:9.5px; letter-spacing:2.4px; gap:8px;
}
.lib-rail-title{ color:var(--gold); }

/* Bench list */
.lib-bench-list{
  flex:1; overflow-y:auto; padding:2px 0 8px;
  scrollbar-width:thin; scrollbar-color:var(--gold2) transparent;
}
.lib-bench-empty{
  padding:14px 18px 18px; font-family:'Playfair Display',serif;
  font-style:italic; font-size:13px; color:var(--dim2); line-height:1.5;
}
.lib-bench-row{
  display:flex; align-items:center; gap:8px;
  padding:8px 16px 8px 18px; cursor:pointer;
  transition:background .12s, border-left-color .12s;
  border-left:2px solid transparent;
}
.lib-bench-row:hover{
  background:rgba(154,100,32,0.06); border-left-color:var(--gold2);
}
.lib-bench-row.active{
  background:var(--gold-dim); border-left-color:var(--gold);
}
.lib-bench-name{
  flex:1; font-family:'Playfair Display',serif; font-size:14px;
  font-style:italic; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.lib-bench-date{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.2px; color:var(--dim2); flex-shrink:0;
  text-transform:uppercase;
}
.lib-bench-del{
  background:none; border:none; color:var(--dim2); cursor:pointer;
  padding:2px 4px; font-size:12px; opacity:0; transition:opacity .12s, color .12s;
  flex-shrink:0;
}
.lib-bench-row:hover .lib-bench-del{ opacity:1; }
.lib-bench-del:hover{ color:var(--amber); }

/* Section nav in rail */
.lib-nav{ padding:10px 0 14px; border-top:1px solid var(--gold2); flex-shrink:0; }
.lib-nav-hd{
  padding:12px 18px 8px; font-size:9.5px; letter-spacing:2.4px; gap:8px;
}
.lib-nav-hd > span:last-child{ color:var(--gold); }
.lib-nav-btn{
  display:flex; align-items:center; gap:10px; width:100%;
  padding:8px 18px; background:transparent; border:none;
  font-family:'Space Mono',monospace; font-size:11px; font-weight:400;
  letter-spacing:2px; text-transform:uppercase;
  color:var(--dim); cursor:pointer; transition:all .12s;
  text-align:left; border-left:2px solid transparent;
}
.lib-nav-btn:hover{
  color:var(--text); background:rgba(154,100,32,0.04);
}
.lib-nav-btn.on{
  color:var(--gold); border-left-color:var(--gold);
  background:var(--gold-dim);
}
.lib-nav-icon{ font-size:14px; opacity:0.7; }
.lib-nav-btn.on .lib-nav-icon{ opacity:1; }
.lib-nav-btn:focus{ outline:none; }
.lib-nav-btn:focus-visible{ outline:1.5px solid var(--gold); outline-offset:-3px; }

/* ── Right content pane ── */
.lib-content{
  flex:1; display:flex; flex-direction:column; min-width:0;
  /* 2026-05-14 — without min-height:0, the implicit min-height:auto on
     this flex item let it grow beyond .picker-panel's bounds, so
     .picker-body's overflow:auto couldn't engage. Library tunes that
     exceed the drawer's 84vh height became unscrollable. */
  min-height:0;
}

/* Search bar */
.lib-search-wrap{
  display:flex; gap:10px; padding:14px 22px 12px;
  border-bottom:1px solid var(--gold2); flex-shrink:0;
}
.lib-search-input{
  flex:1; background:transparent;
  border:1px solid var(--gold2); border-radius:1px;
  padding:8px 12px; color:var(--text);
  font-family:'Playfair Display',serif; font-style:italic; font-size:14px;
  outline:none; transition:border-color .12s;
}
.lib-search-input:focus{ border-color:var(--gold); }
.lib-search-input::placeholder{ color:var(--dim2); font-style:italic; }
.lib-search-btn,.lib-search-back{
  padding:6px 14px; background:transparent; border:1px solid var(--gold2);
  border-radius:1px; color:var(--text);
  font-family:'Space Mono',monospace; font-size:10px; font-weight:400;
  letter-spacing:2.4px; text-transform:uppercase;
  cursor:pointer; transition:all .12s; white-space:nowrap;
}
.lib-search-btn:hover,.lib-search-back:hover{
  color:var(--gold); border-color:var(--gold); background:var(--gold-dim);
}

/* Content scroll area */
.picker-body{
  flex:1; overflow-y:auto; padding:0 0 20px;
  scrollbar-width:thin; scrollbar-color:var(--gold2) transparent;
}

/* Section header — FIG-banner style */
.pk-section-hd{
  display:flex; align-items:baseline; gap:12px;
  padding:18px 22px 10px;
  font-family:'Space Mono',monospace; font-size:10px;
  letter-spacing:3px; text-transform:uppercase;
  color:var(--gold);
  border-bottom:1px solid rgba(106,64,16,0.25);
  margin:0 22px 12px; padding:18px 0 10px;
}
.pk-section-sub{
  flex:1; font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--dim2);
  letter-spacing:0; text-transform:none; font-weight:400;
}

/* Status / empty states */
.lib-search-status{
  padding:48px 22px; text-align:center;
  color:var(--dim); font-family:'Playfair Display',serif;
  font-style:italic; font-size:15px;
}

/* ── Tune card grid ── */
.tune-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(190px, 1fr));
  gap:12px; padding:0 22px 20px;
}
/* R6.14 — Tune cards as index cards on the desk. Per Claude Design
   2026-05-08 punch-list #11: "Each tune is an index card on the desk.
   Deterministic micro-rotation (-1.5° to +1.5° hashed off the tune
   key), brass FIG. tab peeking top-right of each card, hover lifts
   4px / 240ms ease with 0 2px 0 rgba(0,0,0,0.18) walnut shadow."
   FLW lens: every surface should look like the thing it is. This is
   a card catalog. The cards stop being flat boxes and become the
   thing they are. Rotation is set inline via library.js (CSS var
   --tune-rot) so it's deterministic per tune title — same card
   always tilts the same way. */
.tune-card{
  background:var(--vellum); border:1px solid var(--gold2); border-radius:0;
  padding:14px 14px 12px; cursor:pointer;
  transition:transform 240ms cubic-bezier(0.2,0.8,0.2,1),
             box-shadow 240ms cubic-bezier(0.2,0.8,0.2,1),
             border-color .14s, background .14s;
  text-align:left; display:flex; flex-direction:column; gap:5px;
  position:relative; min-height:110px;
  transform:rotate(var(--tune-rot, 0deg));
  box-shadow:0 1px 0 rgba(26,12,4,0.06);
}
/* Brass FIG. tab — small clipped index-card tab peeking top-right.
   Pseudo-element so no markup change required. The tab is part of
   the card silhouette, not an annotation. */
.tune-card::after{
  content:'';
  position:absolute;
  top:-7px; right:14px;
  width:22px; height:9px;
  background:var(--gold);
  opacity:0.65;
  clip-path:polygon(0 0, 100% 0, 90% 100%, 10% 100%);
  transition:opacity 180ms ease, height 180ms ease;
  pointer-events:none;
}
.tune-card:hover{
  border-color:var(--gold); background:var(--ivory);
  transform:rotate(var(--tune-rot, 0deg)) translateY(-4px);
  box-shadow:0 2px 0 rgba(0,0,0,0.18), 0 6px 12px rgba(26,12,4,0.10);
  z-index:2;
}
.tune-card:hover::after{ opacity:0.95; height:11px; }
.tune-card.active{
  border-color:var(--gold); background:var(--ivory);
  transform:rotate(var(--tune-rot, 0deg)) translateY(-2px);
  box-shadow:0 1px 0 rgba(0,0,0,0.18), 0 4px 8px rgba(26,12,4,0.10);
  z-index:1;
}
.tune-card.active::after{ opacity:1; height:12px; }
.tune-card.active::before{
  content:""; position:absolute; top:-1px; left:-1px; right:-1px;
  height:3px; background:var(--gold);
}
.tune-card.add-card{
  border-style:dashed; border-color:var(--gold2);
  justify-content:center; align-items:center; min-height:110px;
}
.tune-card.add-card:hover{
  border-color:var(--gold); background:rgba(154,100,32,0.04);
}
/* R6.31 — Plate A typography pass on library card content. The deck-of-
   tilted-cards aesthetic stays (R6.14); typography stops fighting it.
   Genre stays Space Mono fig-register caps (already Plate A).
   Title moves to Playfair italic — every Plate A title voice (sidebar
   FIG. caps, chord-card spelling row, splash tiles) is italic. The bold
   non-italic was the holdout that read as a different hierarchy. Tighter
   leading + slightly smaller so longer titles fit on one line. */
.tc-genre{
  font-family:'Space Mono',monospace; font-size:9px; font-weight:700;
  letter-spacing:2.4px; text-transform:uppercase;
  color:var(--gold); line-height:1;
}
.tc-title{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:18px; font-weight:600;
  color:var(--text); line-height:1.15;
  letter-spacing:0.2px;
}
.tc-feel{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:12.5px; color:var(--dim); line-height:1.35; flex:1;
}
.tc-key{
  font-family:'Space Mono',monospace; font-size:9.5px; color:var(--dim2);
  letter-spacing:1.6px; text-transform:uppercase; margin-top:2px;
}
.tc-melody-dot{
  position:absolute; top:10px; right:10px;
  width:8px; height:8px; border-radius:50%;
  background:var(--gold);
  box-shadow:0 0 0 1px var(--vellum);
}
.add-card-plus{ font-size:22px; color:var(--gold2); line-height:1; }
.add-card-label{
  font-family:'Space Mono',monospace; font-size:10px;
  color:var(--dim2); letter-spacing:2px; text-transform:uppercase;
  margin-top:6px;
}
.tune-card:focus{ outline:none; }
.tune-card:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }

/* ── Progressions grid ── */
.prog-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(170px, 1fr));
  gap:10px; padding:0 22px 20px;
}
.pk-prog{
  padding:12px 14px; background:transparent;
  border:1px solid var(--gold2); border-radius:0;
  cursor:pointer; transition:border-color .14s, background .14s;
  text-align:left; position:relative;
}
.pk-prog:hover{
  border-color:var(--gold); background:rgba(154,100,32,0.05);
}
.pk-prog.active{
  border-color:var(--gold); background:var(--gold-dim);
}
.pk-prog.active::before{
  content:""; position:absolute; top:-1px; left:-1px; right:-1px;
  height:3px; background:var(--gold);
}
.pk-prog-feel{
  font-family:'Playfair Display',serif; font-size:15px; font-weight:700;
  color:var(--text); margin-bottom:3px; line-height:1.2;
}
.pk-prog-theory{
  font-family:'Space Mono',monospace; font-size:10px;
  color:var(--dim); letter-spacing:1.2px; text-transform:uppercase;
}
.pk-teacher-lock{
  font-family:'Space Mono',monospace; font-size:8.5px;
  color:var(--gold); letter-spacing:2.4px; text-transform:uppercase;
  margin-bottom:4px;
}
.pk-prog:focus{ outline:none; }
.pk-prog:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }

/* R5.20 — Progression small-multiples stack. Each progression is a row;
   chord cells align by scale-degree column (I, ii, iii, IV, V, vi, vii).
   Read down a column to compare what role each degree plays across the
   catalog. Tufte data-ink: alignment is the comparison. */
.pk-prog-stack{
  display:flex; flex-direction:column;
  gap:0;
  padding:0 22px 20px;
}
.pk-prog-stack-head,
.pk-prog-row{
  display:grid;
  grid-template-columns:160px 1fr;
  align-items:stretch;
  gap:10px;
}
.pk-prog-stack-head{
  padding:6px 8px 8px;
  border-bottom:1px solid var(--gold-dim);
  margin-bottom:4px;
}
.pk-prog-row{
  padding:6px 8px;
  border:1px solid transparent;
  border-bottom:1px solid var(--gold-dim);
  background:transparent;
  cursor:pointer; transition:background .12s, border-color .12s;
  text-align:left;
  font:inherit;
  position:relative;
}
.pk-prog-row:hover{
  background:rgba(154,100,32,0.06);
  border-color:var(--gold2);
}
.pk-prog-row.active{
  background:var(--gold-dim);
  border-color:var(--gold);
}
.pk-prog-row.active::before{
  content:""; position:absolute; top:-1px; left:-1px;
  width:3px; bottom:-1px; background:var(--gold);
}
.pk-prog-row-label{
  display:flex; flex-direction:column; gap:2px;
  align-self:center;
  min-width:0;
}
.pk-prog-row-feel{
  font-family:'Playfair Display',serif; font-size:14px; font-weight:700;
  color:var(--text); line-height:1.15;
}
.pk-prog-row-sub{
  font-family:'Space Mono',monospace; font-size:9px;
  color:var(--dim); letter-spacing:1.2px; text-transform:uppercase;
}
.pk-prog-row-badge{
  font-family:'Space Mono',monospace; font-size:8px;
  letter-spacing:2px; text-transform:uppercase;
  color:var(--gold); margin-bottom:2px; line-height:1;
}
.pk-prog-row-cells{
  display:grid;
  grid-template-columns:repeat(7, 1fr);
  gap:4px;
}
.pk-prog-cell{
  display:flex; align-items:center; justify-content:center;
  padding:6px 4px;
  font-family:'Space Mono',monospace; font-size:11px;
  border-radius:1px;
  position:relative;
  min-height:30px;
}
.pk-prog-cell-hd{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; font-weight:700;
  color:var(--gold); letter-spacing:0.5px;
  border:none; padding:2px 0;
}
.pk-prog-cell-filled{
  background:rgba(154,100,32,0.08);
  border:1px solid var(--gold-dim);
  color:var(--text);
  font-weight:700; letter-spacing:0.5px;
}
.pk-prog-row.active .pk-prog-cell-filled{
  background:rgba(232,199,106,0.18);
  border-color:var(--gold);
}
.pk-prog-cell-empty{
  background:transparent;
  border:1px dashed rgba(154,100,32,0.18);
}
/* Sequence indicator — tiny step-numbers when a degree is revisited.
   E.g. 12-Bar Blues hits the I degree at steps 1,2,3,4,7,8 — the cell
   shows the chord (I7) plus a small "1·2·3·4·7·8" subscript. */
.pk-prog-cell-seq{
  position:absolute; bottom:1px; right:3px;
  font-family:'Space Mono',monospace; font-size:7px;
  letter-spacing:0.5px; color:var(--gold);
  opacity:0.85;
}
.pk-prog-row:focus{ outline:none; }
.pk-prog-row:focus-visible{ outline:1.5px solid var(--gold); outline-offset:1px; }

/* legacy compat */
.pk-row{display:flex;gap:10px;padding:0 18px 4px;overflow-x:auto;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;}
.pk-row::-webkit-scrollbar{display:none;}
.pk-song,.pk-teacher-card{
  flex-shrink:0;padding:12px 14px;background:var(--surf);
  border:1px solid var(--border);border-radius:10px;cursor:pointer;
  transition:all .18s;text-align:left;min-width:150px;
}
.pk-song:hover,.pk-teacher-card:hover{border-color:rgba(232,199,106,.5);background:rgba(232,199,106,.06);}
.pk-song.active,.pk-teacher-card.active{border-color:var(--gold);background:rgba(232,199,106,.1);}
.pk-song-name,.pk-teacher-feel{font-size:14px;color:#fff;font-family:'DM Sans',sans-serif;font-weight:600;margin-bottom:3px;}
.pk-song-meta,.pk-teacher-theory{font-size:11px;color:var(--dim);font-family:'Space Mono',monospace;}
.pk-teacher-lock{font-size:10px;color:rgba(232,199,106,.5);letter-spacing:1.5px;margin-bottom:3px;}
.pk-bench-item{display:flex;align-items:center;gap:10px;padding:10px 18px;
  border-bottom:1px solid var(--border);cursor:pointer;transition:background .15s;}
.pk-bench-item:hover{background:rgba(255,255,255,.04);}
.pk-bench-name{flex:1;font-size:14px;color:#fff;font-family:'DM Sans',sans-serif;}
.pk-bench-meta{font-size:12px;color:var(--dim);font-family:'Space Mono',monospace;}
/* old filter tabs kept for compat but hidden */
.lib-filter-tabs{display:none;}
.lib-filter-tab{display:none;}
.pk-teacher-lock{font-size:14px;color:rgba(232,199,106,.5);margin-bottom:6px;font-family:'Space Mono',monospace;letter-spacing:2px;}
.pk-teacher-feel{font-size:16px;color:var(--gold);font-family:'DM Sans',sans-serif;font-weight:700;margin-bottom:4px;line-height:1.2;}
.pk-teacher-theory{font-size:14px;color:var(--dim);font-family:'Space Mono',monospace;letter-spacing:1px;}
.pk-bench-item{
  display:flex;align-items:center;gap:10px;
  padding:10px 20px;border-bottom:1px solid var(--border);
  cursor:pointer;transition:background .15s;
}
.pk-bench-item:hover{background:rgba(255,255,255,.04);}
.pk-bench-name{flex:1;font-size:14px;color:#fff;font-family:'DM Sans',sans-serif;}
.pk-bench-meta{font-size:14px;color:var(--dim);font-family:'Space Mono',monospace;}
.np-pick-btn{
  height:100%;padding:0 18px;
  border:none;border-right:1px solid var(--border);
  background:rgba(232,199,106,.08);
  color:var(--gold);font-size:14px;letter-spacing:2px;text-transform:uppercase;
  font-family:'Space Mono',monospace;cursor:pointer;
  transition:all .15s;white-space:nowrap;flex-shrink:0;
}
.np-pick-btn:hover{background:rgba(232,199,106,.18);}
.np-save-btn{
  height:100%;padding:0 14px;
  border:none;border-right:1px solid var(--border);
  background:transparent;
  color:var(--dim2);font-size:14px;letter-spacing:2px;text-transform:uppercase;
  font-family:'Space Mono',monospace;cursor:pointer;
  transition:all .15s;white-space:nowrap;flex-shrink:0;
}
.np-save-btn:hover{color:var(--gold);background:rgba(232,199,106,.06);}
/* Save toast — appears after saving, points to bench */
#save-toast{
  position:fixed;top:52px;left:50%;transform:translateX(-50%);
  background:#1a1828;border:1px solid rgba(232,199,106,0.3);border-radius:6px;
  padding:10px 18px;font-family:'Space Mono',monospace;font-size:14px;
  color:var(--gold);letter-spacing:1px;z-index:800;
  opacity:0;pointer-events:none;transition:opacity .2s;white-space:nowrap;
  box-shadow:0 4px 20px rgba(0,0,0,0.5);
}
#save-toast.visible{opacity:1;}
.play-sidebar{width:76px;border-right:1px solid var(--border);display:none;flex-direction:column;
  padding:8px 5px;gap:10px;overflow-y:auto;flex-shrink:0;background:var(--surf3);scrollbar-width:none;}
.play-sidebar::-webkit-scrollbar{display:none;}
.sb-sec{display:flex;flex-direction:column;gap:3px;align-items:center;}
.sb-lbl{font-size:10px;letter-spacing:2px;color:var(--dim2);text-transform:uppercase;text-align:center;font-family:'DM Sans',sans-serif;}

/* Key + Position circles — 2-column wrapping grid */
.key-btns-sidebar{display:flex;flex-wrap:wrap;gap:3px;justify-content:center;width:100%;}
.key-btns-sidebar .circ{width:30px;height:30px;border-radius:50%;border:1px solid var(--border);background:transparent;
  color:var(--dim);font-size:11px;font-family:'Space Mono',monospace;transition:all .14s;display:flex;align-items:center;justify-content:center;cursor:pointer;}
.key-btns-sidebar .circ:hover{border-color:var(--border2);color:var(--text);}
.key-btns-sidebar .circ.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}

/* Capo — wrapping row */
.capo-btns{display:flex;flex-wrap:wrap;gap:3px;justify-content:center;width:100%;}
.capo-btn{padding:2px 4px;border:1px solid var(--border);background:transparent;color:var(--dim);
  font-size:11px;border-radius:3px;text-align:center;transition:all .14s;min-width:24px;}
.capo-btn:hover{border-color:var(--border2);}
.capo-btn.on{border-color:var(--amber);color:var(--amber);background:rgba(240,160,48,.07);}

/* Main */
.play-main{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0;}

/* Now-playing bar (replaces prog strip) */
.now-playing-bar{display:flex;align-items:center;gap:10px;padding:0 0 0 0;border-bottom:1px solid var(--border);background:rgba(13,12,22,.85);flex-shrink:0;height:36px;}

.np-home-btn{height:100%;padding:0 16px;border:none;border-right:1px solid var(--border);background:rgba(201,168,76,0.08);color:var(--gold);font-family:'Space Mono',monospace;font-size:14px;letter-spacing:2px;cursor:pointer;transition:all .15s;flex-shrink:0;white-space:nowrap;}
.np-home-btn:hover{background:rgba(201,168,76,0.16);color:var(--gold2);}
.np-divider{width:1px;height:16px;background:var(--border2);flex-shrink:0;margin:0 6px;}
.np-label{font-size:14px;letter-spacing:3px;color:var(--dim);text-transform:uppercase;flex-shrink:0;}
.np-prog{font-family:'Space Mono',monospace;font-size:14px;color:var(--gold);letter-spacing:1px;}
.np-sep{color:var(--dim2);}
.np-key{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim);letter-spacing:1px;}

/* Pills (songs + progressions rendered by v20 render.js with class 'pill') */
.pill{padding:4px 11px;border:1px solid var(--border);border-radius:20px;background:transparent;
  color:var(--dim);font-size:14px;transition:all .14s;white-space:nowrap;letter-spacing:1px;flex-shrink:0;cursor:pointer;}
.pill:hover{border-color:var(--border2);color:var(--text);}
.pill.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}

/* Controls strip */
.controls-strip{display:flex;align-items:center;gap:4px;padding:2px 14px;border-bottom:1px solid rgba(255,255,255,0.04);
  overflow-x:auto;flex-shrink:0;scrollbar-width:thin;scrollbar-color:var(--border2) transparent;background:transparent;}
.controls-strip::-webkit-scrollbar{height:2px;}
.cs-lbl{font-size:12px;letter-spacing:2px;color:var(--dim2);text-transform:uppercase;white-space:nowrap;flex-shrink:0;font-family:'DM Sans',sans-serif;}
.cs-sep{width:1px;height:14px;background:var(--border);flex-shrink:0;margin:0 2px;margin-left:auto;}
.ctl-btn{padding:2px 7px;border:none;background:transparent;color:var(--dim2);
  font-size:13px;border-radius:3px;transition:color .14s;white-space:nowrap;letter-spacing:1px;text-transform:uppercase;flex-shrink:0;cursor:pointer;}
.ctl-btn:hover{color:var(--dim);}
.ctl-btn.on{color:var(--gold);}
/* Tweak panel — friendly labeled groups */
.tweak-group{display:flex;flex-direction:column;gap:4px;padding:6px 10px;}
.tweak-lbl{font-size:14px;letter-spacing:1.5px;color:var(--dim);text-transform:uppercase;white-space:nowrap;font-family:'Space Mono',monospace;}
.tweak-btns{display:flex;gap:3px;}
.tweak-btn{padding:4px 9px;border:1px solid var(--border);background:transparent;color:var(--dim);font-family:'Space Mono',monospace;font-size:14px;border-radius:4px;cursor:pointer;transition:all .14s;white-space:nowrap;}
.tweak-btn:hover{border-color:var(--border2);color:var(--text);}
.tweak-btn.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
.tweak-sep{width:1px;background:var(--border);flex-shrink:0;margin:6px 0;}


/* Position buttons (rendered by renderPosBtns with class pos-btn) */
.pos-strip-inline{display:flex;gap:3px;flex-wrap:nowrap;}
.pos-btn{padding:3px 5px;border:1px solid var(--border);background:transparent;color:var(--dim);
  font-size:14px;border-radius:3px;transition:all .14s;cursor:pointer;flex-shrink:0;}
.pos-btn:hover{border-color:var(--border2);color:var(--text);}
.pos-btn.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
.pf{pointer-events:none;}

/* Reasoning bar */
.reasoning-bar{padding:7px 14px;font-size:14px;font-family:'DM Sans',sans-serif;color:rgba(232,199,106,0.65);letter-spacing:.5px;
  border-bottom:1px solid var(--border);flex-shrink:0;min-height:30px;font-family:'Space Mono',monospace;
  transition:color .2s,border-color .2s;line-height:1.5;background:rgba(232,199,106,0.03);}

/* ── STATUS STRIP — the OLED readout ── */
.status-strip{
  display:flex;align-items:center;gap:0;padding:5px 14px;
  background:#0d0c1a;border-bottom:1px solid #1e1c2e;
  flex-shrink:0;flex-wrap:wrap;
  font-family:'Space Mono',monospace;font-size:12px;letter-spacing:0.5px;
  min-height:26px;
}
/* Key label — make it unmistakably the key not a chord name */
#ss-key{
  font-size:14px;font-weight:700;color:var(--gold);
  padding:0 6px 0 0;
  border-right:1px solid #2a2840;margin-right:4px;
}
#ss-pos{
  color:var(--gold);font-weight:600;
}

/* ── CONTROL SURFACE SWITCHES — unmistakable on/off ── */
.ctrl-surface{display:flex;flex-wrap:wrap;gap:0;border-bottom:1px solid var(--border);background:#0d0c1a;}
.ctrl-section{display:flex;flex-direction:column;gap:4px;padding:7px 10px;border-right:1px solid #1e1c2e;}
.ctrl-section:last-child{border-right:none;}
.ctrl-section-lbl{font-size:14px;letter-spacing:2px;color:#2e2b3e;text-transform:uppercase;
  font-family:'Space Mono',monospace;margin-bottom:1px;white-space:nowrap;}
.ctrl-switch{display:flex;border:1px solid #2a2640;border-radius:3px;overflow:hidden;background:#0d0c1a;}
.ctrl-switch button{
  padding:3px 9px;border:none;
  background:transparent;
  color:#3a3458;  /* inactive: clearly off, dim */
  font-family:'Space Mono',monospace;font-size:14px;cursor:pointer;
  transition:all .12s;white-space:nowrap;border-right:1px solid #1e1c2e;
}
.ctrl-switch button:last-child{border-right:none;}
.ctrl-switch button:hover{color:#8a80b0;background:#1a1828;}
/* Active: unmistakably on — filled, bright, no ambiguity */
.ctrl-switch button.on{
  background:rgba(232,199,106,0.15);
  color:var(--gold);
  font-weight:700;
  box-shadow:inset 0 0 0 1px rgba(232,199,106,0.35);
}
.ctrl-divider{width:1px;background:#1a1828;flex-shrink:0;margin:4px 0;}

/* Subtabs */
/* ── Unified five-item nav ── */
.unified-nav{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;align-items:center;background:var(--bg);justify-content:center;}
.unav-btn{flex:0 1 160px;padding:10px 20px;border:none;background:transparent;color:rgba(255,255,255,0.35);font-size:12px;letter-spacing:1px;text-transform:uppercase;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;font-family:'DM Sans',sans-serif;transition:color .15s,opacity .15s;}
.unav-btn:hover{color:var(--text);}
.unav-btn.on{color:var(--gold);border-bottom:2px solid var(--gold);background:rgba(232,199,106,0.04);}

.subtabs-row{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;align-items:center;}
.subtab{flex:1;padding:8px 4px;border:none;background:transparent;color:rgba(255,255,255,0.35);font-size:14px;
  letter-spacing:2px;text-transform:uppercase;border-bottom:2px solid transparent;transition:all .14s;cursor:pointer;}
.subtab:hover{color:var(--text);}
.subtab.on{color:var(--gold);border-bottom:2px solid var(--gold);background:rgba(232,199,106,0.04);}

/* ══ RECORDER TRANSPORT ══════════════════════════════════════════
   Tascam-inspired. The circle IS the interface.
   Big. Isolated. Below the tabs. Above the content.
   State speaks for itself — no labels needed after first use.
════════════════════════════════════════════════════════════════ */
/* Roman numeral tooltip — appears on hover over I–IV–V display */
.roman-tooltip{
  position:relative;display:inline-block;cursor:help;
}
.roman-tooltip::after{
  content:attr(data-tip);
  position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);
  background:#0d0c1a;border:1px solid #2a2640;border-radius:4px;
  color:#8a80b0;font-family:'Space Mono',monospace;font-size:14px;
  letter-spacing:0.5px;line-height:1.6;
  padding:6px 10px;white-space:nowrap;
  opacity:0;pointer-events:none;transition:opacity .15s;
  z-index:100;
}
.roman-tooltip:hover::after{opacity:1;}

/* Secondary controls — appear after first note */
.rec-transport-secondary{
  display:flex;gap:8px;align-items:center;flex-wrap:wrap;justify-content:center;
  padding:0 16px;
}
.rec-sec-btn{
  padding:4px 12px;border:1px solid #2a2640;border-radius:3px;
  background:transparent;color:#6860a0;
  font-family:'Space Mono',monospace;font-size:14px;letter-spacing:1px;
  cursor:pointer;transition:all .14s;
}
.rec-sec-btn:hover{border-color:#8a80b0;color:var(--text);}
.rec-sec-save{border-color:rgba(61,170,112,0.4);color:rgba(61,170,112,0.8);}
.rec-sec-save:hover{border-color:rgba(61,170,112,1);color:rgba(61,170,112,1);}
.rec-sec-clear{color:#4a3a3a;}
.rec-sec-clear:hover{border-color:#c03030;color:#c03030;}

/* ── CONTROL SURFACE PANEL ── Grouped, not a flat list */
.ctrl-surface{display:flex;flex-wrap:wrap;gap:0;border-bottom:1px solid var(--border);background:#0d0c1a;}
.ctrl-section{display:flex;flex-direction:column;gap:5px;padding:8px 12px;border-right:1px solid var(--border);min-width:0;}
.ctrl-section:last-child{border-right:none;}
.ctrl-section-lbl{font-size:14px;letter-spacing:2px;color:var(--dim2);text-transform:uppercase;font-family:'Space Mono',monospace;margin-bottom:2px;white-space:nowrap;}
.ctrl-switch-row{display:flex;gap:3px;align-items:center;}
/* Toggle switch — looks like a real switch, not a text button */
.ctrl-switch{
  display:flex;border:1px solid var(--border);border-radius:3px;overflow:hidden;
}
.ctrl-switch button{
  padding:3px 8px;border:none;background:transparent;color:var(--dim);
  font-family:'Space Mono',monospace;font-size:14px;cursor:pointer;transition:all .12s;
  white-space:nowrap;
}
.ctrl-switch button:hover{color:var(--text);background:rgba(255,255,255,0.04);}
.ctrl-switch button.on{background:var(--gold-dim);color:var(--gold);}
.ctrl-switch button.on-amber{background:rgba(200,150,58,0.12);color:var(--amber);}
.ctrl-divider{width:1px;background:var(--border);flex-shrink:0;margin:6px 0;}
.sub-panel{flex:1;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;min-height:0;justify-content:flex-start;padding-top:12px;}

/* ── SLOW MODE TAB BUTTON ── */
.slow-mode-tab{display:none;} /* legacy — no longer in subtab row */
.pad-slow-toggle{
  padding:3px 8px;border:1px solid #2a2640;border-radius:3px;background:transparent;
  color:#3a3450;font-size:14px;letter-spacing:2px;text-transform:uppercase;
  cursor:pointer;font-family:'Space Mono',monospace;transition:all .14s;flex-shrink:0;
  margin-left:4px;
}
.pad-slow-toggle:hover{color:#8a80b0;border-color:#3a3458;}
.pad-slow-toggle.on{color:var(--amber);border-color:var(--amber);background:rgba(240,160,48,0.08);}

/* ── SLOW MODE PANEL ── chord-by-chord builder */
.slow-chord{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-width:64px;padding:8px 10px;border-radius:6px;cursor:pointer;
  font-family:'Space Mono',monospace;transition:all .15s;
}
.slow-chord.locked{
  background:#12101e;border:1px solid #2a2640;
  color:var(--gold);
}
.slow-chord.locked:hover{border-color:var(--gold);background:#1a1828;}
.slow-chord.active{
  background:#0d0c1a;border:1px solid #3a3450;
  border-style:dashed;flex-direction:column;min-width:100%;
}
.slow-chord-name{font-size:14px;color:var(--gold);letter-spacing:1px;}
.slow-chord-type{font-size:14px;color:var(--dim);margin-left:3px;}
.slow-chord-lock{font-size:14px;color:#2a2640;margin-top:2px;}
.slow-root-grid{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px;}
.slow-root-btn{
  display:flex;flex-direction:column;align-items:center;
  padding:6px 10px;border:1px solid #2a2640;border-radius:4px;
  background:transparent;color:var(--dim);font-family:'Space Mono',monospace;
  font-size:14px;cursor:pointer;transition:all .12s;gap:2px;
}
.slow-root-btn:hover{border-color:#c8a850;color:var(--gold);}
.slow-root-btn.on{border-color:var(--gold);color:var(--gold);background:#1a1828;}
.slow-root-note{font-size:14px;color:var(--dim2);letter-spacing:1px;}
.slow-quality-row{display:flex;gap:4px;flex-wrap:wrap;}
.slow-qual-btn{
  padding:4px 10px;border:1px solid #2a2640;border-radius:3px;
  background:transparent;color:var(--dim);font-family:'Space Mono',monospace;
  font-size:14px;cursor:pointer;transition:all .12s;
}
.slow-qual-btn:hover{border-color:var(--gold);color:var(--gold);}
.slow-action-btn{
  padding:5px 14px;border:1px solid #2a2640;border-radius:4px;
  background:transparent;color:var(--dim);font-family:'Space Mono',monospace;
  font-size:14px;cursor:pointer;transition:all .12s;letter-spacing:1px;
}
.slow-action-btn:hover{border-color:#8a80b0;color:var(--text);}
.slow-action-btn.primary{border-color:var(--gold);color:var(--gold);}
.slow-action-btn.primary:hover{background:rgba(232,199,106,0.08);}
.slow-hint{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim2);letter-spacing:1px;}

/* ── SWIPE PICKER ── drum-roll wheel columns */
.sp-col{
  overflow-y:scroll;scroll-snap-type:y mandatory;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
}
.sp-col::-webkit-scrollbar{display:none;}
.sp-item{
  height:40px;display:flex;align-items:center;justify-content:center;
  scroll-snap-align:center;font-family:'Space Mono',monospace;
  font-size:16px;letter-spacing:1px;color:#3a3450;cursor:pointer;
  transition:color .1s;
}
.sp-item.sp-center{color:var(--gold);font-size:14px;}
.sp-item:hover{color:#8a80b0;}
.prog-scroll{padding:4px 12px 4px;overflow-x:visible;flex:1;display:flex;flex-direction:column;justify-content:flex-start;align-items:center;}
.prog-row{display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start;justify-content:center;width:100%;}

/* Chart cards (v20 renders these with class prog-card) */
.prog-col{display:flex;flex-direction:column;align-items:center;gap:8px;overflow:visible;}
.prog-card{background:var(--surf2);border:1px solid var(--border);border-radius:14px;padding:10px 14px;
  /* 2026-05-15 — width was clamp(160px,20vw,260px) which forced 260px at
     ≥1300vw, overflowing the grid cell when the row's container is
     narrower than 4×260+gaps (e.g. 15" MBA at 1440 viewport leaves ~857
     for the prog-card-row; auto-fit grid gives ~190px cells; cards at
     260px each spilled rightward, visually overlapping). width:100% lets
     the card fill its grid cell; max-width:260px still caps wide layouts;
     min-width:120px keeps the diagram readable at narrow viewports. */
  text-align:center;cursor:pointer;transition:all .2s;min-width:120px;max-width:260px;width:100%;overflow:visible;}
.prog-card:hover{border-color:var(--border2);box-shadow:0 12px 32px rgba(0,0,0,.5);}
.prog-card:not(.persp-on):hover{transform:translateY(-3px);}
.prog-card.card-active{border-color:var(--gold);box-shadow:0 0 0 1px var(--gold),0 12px 32px rgba(0,0,0,.5);}
/* 2026-05-15 — Voicing-change flash. Fired by _voicingChangedFlash in
   app.js after setStrPref or toggleParam(rootInBass) reshuffles voicings.
   Brass glow + slight scale, 800ms. Tells the user "this card's voicing
   just changed" so the picker click feels responsive even when the dot
   delta is subtle (e.g., bass note moves one string). */
@keyframes pcCardVoicingFlash {
  0%   { box-shadow:0 0 0 0 rgba(232,199,106,0); transform:scale(1); }
  20%  { box-shadow:0 0 18px 6px rgba(232,199,106,0.55); transform:scale(1.04); }
  100% { box-shadow:0 0 0 0 rgba(232,199,106,0); transform:scale(1); }
}
.prog-card.pc-card-voicing-flash{ animation: pcCardVoicingFlash 800ms ease-out; }
.card-roman{font-family:'Playfair Display',serif;font-size:28px;color:var(--gold);letter-spacing:3px;line-height:1;margin-bottom:2px;text-align:center;}
.cname{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim);letter-spacing:2px;margin-bottom:4px;line-height:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;text-align:center;}
.ctab{font-size:14px;color:var(--dim);letter-spacing:2px;margin-bottom:4px;font-family:'Space Mono',monospace;}
.fspan{font-size:14px;color:var(--dim2);letter-spacing:1px;margin-bottom:8px;}
.card-hear{font-size:14px;color:var(--dim2);letter-spacing:2px;padding:6px 0 2px;text-align:center;font-family:'Space Mono',monospace;}
.card-alt-nav{display:flex;align-items:center;justify-content:center;gap:8px;padding:4px 0 2px;margin-top:2px;}
.card-alt-btn{background:transparent;border:1px solid rgba(232,199,106,0.25);border-radius:4px;color:var(--dim);font-size:12px;padding:2px 7px;cursor:pointer;line-height:1.6;transition:all .12s;}
.card-alt-btn:hover{color:var(--gold);border-color:rgba(232,199,106,0.6);}
.card-alt-count{font-family:'Space Mono',monospace;font-size:11px;color:var(--dim2);letter-spacing:1px;min-width:44px;text-align:center;}

/* ── ADD CHORD "+" card ─────────────────────────────── */
.prog-add-card{
  border-style:dashed !important;border-color:var(--border2) !important;
  background:transparent !important;
  transition:all 0.2s;
}
.prog-add-card:hover{
  border-color:var(--gold) !important;background:var(--gold-dim) !important;
}
.prog-add-plus{
  font-family:'Playfair Display',serif;font-size:36px;color:var(--dim);
  line-height:1;margin-bottom:4px;transition:color 0.2s;
}
.prog-add-card:hover .prog-add-plus{color:var(--gold);}

.prog-add-picker{
  position:absolute;top:100%;left:50%;transform:translateX(-50%);
  z-index:100;margin-top:6px;
  background:var(--surf);border:1px solid var(--border2);border-radius:10px;
  padding:8px;display:flex;flex-wrap:wrap;gap:4px;
  width:220px;box-shadow:0 12px 32px rgba(0,0,0,0.6);
}
.prog-add-opt{
  flex:1 1 48%;padding:8px 6px;border:1px solid var(--border);border-radius:6px;
  background:var(--surf2);cursor:pointer;text-align:center;transition:all 0.15s;
}
.prog-add-opt:hover{border-color:var(--gold);background:var(--gold-dim);}
.prog-add-opt-roman{
  display:block;font-family:'Playfair Display',serif;font-size:16px;color:var(--gold);line-height:1.2;
}
.prog-add-opt-name{
  display:block;font-family:'Space Mono',monospace;font-size:14px;color:var(--dim);letter-spacing:1px;
}
.strum-btn{padding:7px 18px;border:1px solid rgba(232,199,106,.4);background:rgba(232,199,106,.04);color:rgba(232,199,106,.7);
  font-size:14px;border-radius:4px;transition:all .14s;letter-spacing:1px;cursor:pointer;font-family:'Space Mono',monospace;}
.strum-btn:hover{background:var(--gold-dim);color:var(--gold);border-color:var(--gold);}
.strum-btn.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
/* Strum button inside chord cards must not overflow the card frame */


/* Align SEE THE SHAPES dashboard with Play Along / Solo —
   those tabs have a 33px collapsed pad bar above their dashboard;
   this keeps the dashboard at the same vertical anchor on all three tabs */
/* dashboard sits inside fretboard region — padding-top on the region provides spacing */

/* Legend (role colours) */
.legend{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;opacity:0.7;transition:opacity 0.2s;}
.legend:hover{opacity:1;}
.leg{display:flex;align-items:center;gap:4px;font-size:14px;color:var(--dim2);letter-spacing:1px;}
.leg-interactive{cursor:pointer;padding:2px 4px;border-radius:4px;transition:background 0.12s;}
.leg-interactive:hover{background:rgba(232,199,106,0.08);}
.leg-interactive:active{background:rgba(232,199,106,0.15);}
.leg-dot{width:10px;height:10px;border-radius:50%;}

/* ── BACKING TRACK / PLAY ── */
/* sub-play-panel removed — Play and Solo now match Charts structure */

/* Desktop: solo and play panels centre their content vertically */
@media (hover:hover) and (pointer:fine) {
  #sub-scale { justify-content: flex-start; }
}
.play-chord-header{display:flex;align-items:center;justify-content:space-between;padding:6px 0 4px;gap:8px;}
.play-side-stat{text-align:center;min-width:44px;}
.play-big-num{font-family:'Playfair Display',serif;font-size:clamp(28px,5vw,48px);color:var(--gold);line-height:1;}
.play-stat-lbl{font-size:14px;letter-spacing:3px;color:var(--dim);text-transform:uppercase;}
.play-roman-big{font-family:'Playfair Display',serif;font-size:clamp(22px,3.5vw,36px);color:var(--dim);text-align:center;flex:1;letter-spacing:2px;}

/* Dashboard: three tiles grouped */
.play-dashboard{display:flex;justify-content:center;align-items:stretch;gap:0;padding:1px 0;}
.dash-tile{background:var(--surf2);border:1px solid var(--border);padding:5px 16px;text-align:center;min-width:90px;width:90px;}
.dash-tile:first-child{border-radius:8px 0 0 8px;}
.dash-tile:last-child{border-radius:0 8px 8px 0;}
.dash-tile-mid{border-left:none;border-right:none;min-width:100px;width:100px;background:var(--surf3);}
.dash-num{font-family:'Playfair Display',serif;font-size:clamp(20px,3vw,32px);color:var(--gold);line-height:1;}
.dash-roman{font-family:'Playfair Display',serif;font-size:clamp(20px,3vw,32px);color:var(--dim);line-height:1;letter-spacing:1px;}
.dash-lbl{font-size:14px;letter-spacing:3px;color:var(--dim);text-transform:uppercase;margin-top:2px;}

/* Scale pills overlaid on neck */
.neck-scale-pill{padding:3px 9px;border:1px solid rgba(255,255,255,0.12);border-radius:20px;background:rgba(0,0,0,0.55);color:rgba(255,255,255,0.3);font-family:'Space Mono',monospace;font-size:14px;letter-spacing:1px;cursor:pointer;transition:all .14s;backdrop-filter:blur(4px);}
.neck-scale-pill:hover{border-color:rgba(255,255,255,0.3);color:rgba(255,255,255,0.7);}
.neck-scale-pill.on{border-color:var(--gold);color:var(--gold);background:rgba(201,168,76,0.12);}
.neck-scale-pill.penta.on{border-color:rgba(61,170,112,1);color:rgba(61,170,112,1);background:rgba(61,170,112,0.12);}
.neck-scale-pill.minor.on{border-color:rgba(72,128,208,1);color:rgba(72,128,208,1);background:rgba(72,128,208,0.12);}
.neck-scale-pill.major.on{border-color:rgba(192,64,160,1);color:rgba(192,64,160,1);background:rgba(192,64,160,0.12);}
.neck-scale-pill.mixo.on{border-color:rgba(232,199,106,1);color:rgba(232,199,106,1);background:rgba(232,199,106,0.10);}
.neck-scale-pill.dorian.on{border-color:rgba(200,130,58,1);color:rgba(200,130,58,1);background:rgba(200,130,58,0.11);}
.neck-scale-pill.natmin.on{border-color:rgba(140,100,200,1);color:rgba(140,100,200,1);background:rgba(140,100,200,0.11);}

/* Beat dots */
.play-meta-row{display:flex;gap:10px;align-items:center;justify-content:center;padding:4px 0;}
.beat-dot{width:15px;height:15px;border-radius:50%;background:var(--border2);transition:background .08s;}
.beat-dot.tick{background:var(--amber);animation:tick .15s ease;}
.beat-dot.accent{background:var(--gold);animation:tick .15s ease;}

/* SEE / HEAR row */
.sh-row{display:flex;gap:16px;align-items:center;justify-content:center;margin:4px 0;}
.sh-group{display:flex;align-items:center;gap:7px;}
.sh-label{font-size:14px;letter-spacing:2px;color:var(--text);text-transform:uppercase;white-space:nowrap;
  background:var(--surf2);border:1px solid var(--border2);padding:2px 7px;border-radius:3px;}
.sh-btns{display:flex;gap:3px;}
.sh-btn{padding:3px 9px;border:1px solid var(--border);background:transparent;color:var(--dim);
  font-size:14px;border-radius:3px;transition:all .14s;letter-spacing:1px;text-transform:uppercase;}
.sh-btn:hover{border-color:var(--border2);}
.sh-btn.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}

/* Playback */
.playback-row{display:flex;align-items:center;gap:8px;padding:4px 0;flex-wrap:wrap;justify-content:center;flex-shrink:0;}
/* Play button — printed ink card. Paper fiber texture + inner rim ink for
   material depth. No cast shadow — sits flat on the page. */
.play-main-btn{
  color: var(--ivory) !important;
  font-size: 20px !important;
  font-family: 'DM Sans',sans-serif !important;
  font-weight: 600 !important;
  padding: 14px 64px !important;
  letter-spacing: 2px !important;
  border: 1px solid var(--border2) !important;
  border-radius: 3px !important;
  background-color: var(--gold) !important;
  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='0.85' numOctaves='2' stitchTiles='stitch' seed='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.22'/%3E%3C/svg%3E") !important;
  box-shadow:
    inset 0 0 14px rgba(26,12,4,0.22),
    inset 0 1px 0 rgba(240,226,190,0.14) !important;
  animation: none !important;
  transition: transform 0.12s ease, background-color 0.12s ease !important;
}
.play-main-btn:hover{
  background-color: var(--gold3) !important;
}
.play-main-btn:active,
.play-main-btn.playing{
  background-color: var(--gold2) !important;
  box-shadow:
    inset 0 2px 6px rgba(26,12,4,0.35),
    inset 0 1px 0 rgba(240,226,190,0.08) !important;
}

/* Thin divider between transport controls and record button */
.transport-rec-divider {
  width: 1px;
  height: 20px;
  background: #2a2640;
  flex-shrink: 0;
  margin: 0 4px;
}

/* ════════════════════════════════════════════════════════
   POSITION MAP (hidden pane kept for v20 compat)
════════════════════════════════════════════════════════ */
.section-label{font-size:14px;letter-spacing:4px;color:var(--dim);text-transform:uppercase;margin-bottom:6px;}
.circ-row{display:flex;flex-wrap:wrap;gap:4px;}
.circ{width:34px;height:34px;border-radius:50%;border:1px solid var(--border);background:transparent;
  color:var(--dim);font-size:14px;font-family:'Space Mono',monospace;transition:all .14s;display:flex;align-items:center;justify-content:center;cursor:pointer;}
.circ:hover{border-color:var(--border2);color:var(--text);}
.circ.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
.pos-strip{display:flex;flex-wrap:wrap;gap:4px;}

/* ════════════════════════════════════════════════════════
   IMPORT SHEET (ABC paste / TheSession search) — R6.31 Plate A
════════════════════════════════════════════════════════ */
/* R6.31 — Plate A migration. The import modal was the last dark-on-dark
   surface (#0e0d1e + #2a2640 + Space Mono everywhere) that read like a
   different app. Now: parchment substrate, walnut text, brass rules,
   FIG.-banner header — same vocabulary as the sidebar cartouches.
   Markup change in src/import.js wires class names; this stylesheet
   carries the typography. */
.imp-overlay{
  position:fixed; top:0; left:0; right:0; bottom:0;
  z-index:9100;
  background:rgba(26,12,4,0.55);
  display:none; align-items:center; justify-content:center;
  font-family:'Playfair Display',serif;
}
.imp-box{
  width:92%; max-width:520px;
  background:var(--vellum);
  border:1px solid var(--gold2);
  box-shadow:inset 0 0 0 1px rgba(240,226,190,0.6),
             0 8px 28px rgba(26,12,4,0.45);
  display:flex; flex-direction:column;
  max-height:88vh; overflow:hidden;
  border-radius:0; /* Patent Drawing — no soft corners */
  padding:18px 22px 16px;
}
.imp-head{
  display:flex; align-items:center; justify-content:space-between;
  flex-shrink:0; padding-bottom:6px;
}
.imp-fig{ font-size:10px; letter-spacing:2.4px; }
.imp-close{
  background:transparent; border:0; padding:2px 6px; cursor:pointer;
  font-family:'Space Mono',monospace; font-size:14px;
  color:var(--dim2); line-height:1;
}
.imp-close:hover{ color:var(--gold); }
.imp-gloss{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--dim); line-height:1.35;
  padding-bottom:10px; margin-bottom:10px;
  border-bottom:1px solid rgba(106,64,16,0.25);
}
.imp-tabs{
  display:flex; gap:0; flex-shrink:0;
  margin-bottom:14px;
}
.imp-tab{
  background:transparent; border:0;
  border-bottom:1px solid var(--gold2);
  padding:6px 14px 8px;
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--dim);
  cursor:pointer; letter-spacing:0.3px;
  transition:color .15s, border-color .15s;
}
.imp-tab:hover{ color:var(--gold); }
.imp-tab.on{
  color:var(--text);
  border-bottom:2px solid var(--gold);
}
.imp-tab:focus{ outline:none; }
.imp-tab:focus-visible{ outline:1px solid var(--gold); outline-offset:1px; }
.imp-body{
  flex:1; overflow-y:auto;
  scrollbar-width:thin;
  scrollbar-color:var(--gold-dim) transparent;
}
.imp-panel{ padding:4px 0 12px; }
.imp-instruction{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:12px; color:var(--dim); line-height:1.4;
  margin-bottom:10px;
}
.imp-dropzone{
  border:1px dashed var(--gold2);
  padding:36px 20px; text-align:center; cursor:pointer;
  background:rgba(240,226,190,0.4);
  transition:border-color .2s, background .2s;
  border-radius:0;
}
.imp-dropzone:hover,
.imp-dropzone.is-over{
  border-color:var(--gold); background:rgba(240,226,190,0.7);
}
.imp-dropzone-glyph{
  font-size:30px; color:var(--gold); opacity:0.7;
  margin-bottom:10px; line-height:1;
}
.imp-dropzone-line{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--text);
}
.imp-dropzone-hint{
  font-family:'Space Mono',monospace; font-size:9px;
  color:var(--dim2); letter-spacing:2px; text-transform:uppercase;
  margin-top:6px;
}
.imp-textarea{
  width:100%; height:160px; box-sizing:border-box;
  background:rgba(240,226,190,0.4);
  border:1px solid var(--gold2);
  color:var(--text);
  font-family:'Space Mono',monospace; font-size:11px; line-height:1.5;
  padding:10px; resize:vertical; border-radius:0;
  outline:none;
}
.imp-textarea:focus{ border-color:var(--gold); background:rgba(240,226,190,0.7); }
.imp-search-row{
  display:flex; gap:8px; margin-bottom:12px;
}
.imp-search-input{
  flex:1; min-width:0;
  background:rgba(240,226,190,0.4);
  border:1px solid var(--gold2);
  color:var(--text);
  font-family:'Playfair Display',serif; font-size:14px;
  padding:8px 10px; border-radius:0; outline:none;
}
.imp-search-input:focus{ border-color:var(--gold); }
.imp-search-input::placeholder{ font-style:italic; color:var(--dim2); }
.imp-search-results{ display:flex; flex-direction:column; gap:6px; }
.imp-action-btn{
  display:flex; align-items:center; justify-content:center; width:100%;
  padding:9px 14px;
  border:1px solid var(--gold2); background:transparent;
  color:var(--text); margin-top:10px;
  font-family:'Space Mono',monospace; font-size:11px;
  letter-spacing:2.4px; text-transform:uppercase;
  border-radius:0; cursor:pointer;
  transition:background .15s, border-color .15s, color .15s;
}
.imp-action-btn:hover{
  border-color:var(--gold); background:var(--gold-dim); color:var(--gold);
}
.imp-action-btn.imp-action-inline{ width:auto; margin-top:0; padding:8px 16px; }
.imp-attribution{
  flex-shrink:0;
  margin-top:6px; padding:8px 10px;
  background:rgba(240,226,190,0.4);
  border:1px solid var(--gold2);
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:12px; color:var(--dim);
}
.imp-status{
  flex-shrink:0;
  padding-top:8px; min-height:18px;
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.6px; color:var(--gold); text-transform:uppercase;
}
.imp-tune-row{
  display:flex; align-items:center; gap:8px; padding:8px 10px;
  background:rgba(240,226,190,0.4);
  border:1px solid var(--gold2); border-radius:0; cursor:pointer;
  transition:border-color .15s, background .15s;
  font-family:'Playfair Display',serif; color:var(--text);
}
.imp-tune-row:hover{ border-color:var(--gold); background:rgba(240,226,190,0.7); }

/* ════════════════════════════════════════════════════════
   LIBRARY DRAWER
════════════════════════════════════════════════════════ */

/* ── Scale Explorer ── */
.sx-scale-btn{padding:4px 12px;border:1px solid var(--border);background:transparent;color:var(--dim);font-family:'Space Mono',monospace;font-size:14px;border-radius:20px;cursor:pointer;transition:all .15s;letter-spacing:1px;}
.sx-scale-btn:hover{border-color:var(--border2);color:var(--text);}
.sx-scale-btn.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
.sx-scale-btn.on#sx-penta{border-color:rgba(61,170,112,0.8);color:rgba(61,170,112,1);background:rgba(61,170,112,0.08);}
.sx-scale-btn.on#sx-minor{border-color:rgba(72,128,208,0.8);color:rgba(72,128,208,1);background:rgba(72,128,208,0.08);}
.sx-scale-btn.on#sx-major{border-color:rgba(192,64,160,0.8);color:rgba(192,64,160,1);background:rgba(192,64,160,0.08);}

/* ── Solo tab: chord glow pulse animation ── */
@keyframes sxGlowPulse {
  0%,100% { opacity:1; box-shadow:0 0 14px rgba(232,199,106,0.7), 0 0 4px rgba(232,199,106,0.4); }
  50%      { opacity:0.75; box-shadow:0 0 22px rgba(232,199,106,0.95), 0 0 8px rgba(232,199,106,0.6); }
}
/* Solo tab scale picker — compact pills */
.sx-scale-btn { padding:5px 14px; line-height:1; text-align:center; font-size:14px; }
#sub-scale .sx-scale-btn { border-radius:20px; }
#sub-scale .sx-scale-btn.on#sx-penta { border-color:rgba(61,170,112,0.8); background:rgba(61,170,112,0.07); color:rgba(61,170,112,1); }
#sub-scale .sx-scale-btn.on#sx-minor { border-color:rgba(72,128,208,0.8); background:rgba(72,128,208,0.07); color:rgba(72,128,208,1); }
#sub-scale .sx-scale-btn.on#sx-major { border-color:rgba(192,64,160,0.8); background:rgba(192,64,160,0.07); color:rgba(192,64,160,1); }

/* Solo scale picker: centre-align to match fretboard axis */
/* Solo scale picker: centre to match fretboard visual axis */
#sx-scale-strip { justify-content: center !important; }

/* ════════════════════════════════════════════════════════
   MOBILE — first-pass responsive
════════════════════════════════════════════════════════ */
@media (max-width:600px) {
  /* Header: compact */
  .app-header{padding:5px 8px;gap:4px;}
  .logo{font-size:15px;letter-spacing:3px;margin-right:3px;}
  .logo span{display:none;}
  .mode-btn{padding:4px 8px;font-size:10px;letter-spacing:1px;}
  .header-instruments{gap:0;}
  .inst-btn{padding:4px 6px;font-size:10px;}

  /* Sidebar: hide on mobile, show toggle */
  .play-sidebar{width:46px;padding:7px 3px;gap:10px;}
  .sb-lbl{font-size:10px;letter-spacing:1px;}
  .key-btns-sidebar .circ{width:30px;height:30px;font-size:10px;}

  /* Controls strip: scroll horizontally */
  .controls-strip{padding:2px 8px;gap:3px;}
  .cs-lbl{font-size:10px;}

  /* Now playing bar */
  .now-playing-bar{height:32px;}
  .np-home-btn{padding:0 10px;font-size:10px;}
  .np-label{display:none;}

  /* Sub panels */
  .sub-play-panel{padding:0 8px 0;}
  .sh-row{gap:10px;}
  .sh-label{font-size:10px;padding:2px 5px;}

  /* Beat dots */
  .beat-dot{width:11px;height:11px;}
  .play-meta-row{gap:8px;}

  /* Reasoning bar */
  .reasoning-bar{font-size:10px;padding:5px 10px;}

  /* Build mode: stack panels */
  #mode-build .v3-pane.active{flex-direction:column;}
  .build-right{width:100%;border-right:none;border-top:1px solid var(--border);}
  .build-left{border-right:none;}

  /* Prog cards: smaller */
  .prog-card{min-width:160px;max-width:220px;padding:10px 12px;}
  .cname{font-size:24px;}

  /* Play button */
  .play-main-btn{padding:8px 24px !important;font-size:11px !important;}

  /* Subtabs */
  .subtab{font-size:10px;letter-spacing:1px;padding:7px 2px;}
}


/* ══ INTERACTIVE SPLASH TILES ════════════════════════════════════ */

.spl-tiles-wrap {
  margin: 28px auto 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.spl-tiles {
  display: flex;
  align-items: center;
  gap: 10px;
  user-select: none;
  position: relative;
}

.spl-tile {
  width: 72px;
  height: 72px;
  border: 1px solid rgba(154,100,32,0.45);
  border-radius: 4px;
  background: rgba(255,250,230,0.55);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  cursor: grab;
  transition: border-color .18s, background .18s, transform .15s, box-shadow .18s;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  position: relative;
  box-shadow: 0 1px 3px rgba(26,12,4,.10);
}

.spl-tile:hover {
  background: rgba(255,250,230,0.90);
  border-color: var(--gold);
  cursor: grab;
}

/* Cycle arrow — appears on hover, invisible otherwise */
.spl-tile::after {
  content: '↕';
  position: absolute;
  top: 4px;
  right: 5px;
  font-size: 8px;
  color: var(--gold);
  opacity: 0;
  transition: opacity .18s;
  line-height: 1;
  pointer-events: none;
}

.spl-tile:hover::after {
  opacity: 0.55;
}

.spl-tile.tapped {
  transform: scale(.93);
  border-color: var(--gold);
  background: rgba(154,100,32,.18);
}

.spl-tile.dragging {
  opacity: .3;
  transform: scale(.9);
  cursor: grabbing;
}

.spl-tile.drag-over {
  border-color: var(--gold);
  background: rgba(154,100,32,.22);
  box-shadow: 0 0 16px rgba(154,100,32,.35);
  transform: scale(1.06);
}

.spl-tile.lit {
  border-color: var(--gold);
  background: rgba(154,100,32,.14);
  box-shadow: 0 0 20px rgba(154,100,32,.3);
}

.spl-cname {
  font-family: 'Playfair Display', serif;
  font-size: 22px;
  color: var(--gold);
  line-height: 1;
  letter-spacing: .5px;
}

.spl-roman {
  font-family: 'Space Mono', monospace;
  font-size: 9px;
  letter-spacing: 2px;
  color: var(--dim);
  line-height: 1;
}

/* Minor chords: same paper base, green ink — major is brass, minor is sage */
.spl-tile.minor {
  border-color: rgba(61,130,90,0.55) !important;
  background: rgba(255,250,230,0.55) !important;
}
.spl-tile.minor .spl-cname {
  color: rgba(30,90,70,0.95);
}
.spl-tile.minor .spl-roman {
  color: rgba(40,110,80,0.75);
}
.spl-tile.minor:hover {
  border-color: rgba(61,130,90,0.9) !important;
  background: rgba(255,250,230,0.90) !important;
}
.spl-tile.minor::after {
  color: rgba(40,110,80,0.8) !important;
}

.spl-arr {
  color: var(--dim2);
  font-size: 16px;
  flex-shrink: 0;
  transition: color .2s;
  pointer-events: none;
}

/* Desktop: tiles respond to hover */
@media (hover: hover) {
  .spl-tile { cursor: grab; }
  .spl-tile:active { cursor: grabbing; }
}
.spl-action-row {
  display: flex;
  align-items: center;
  gap: 14px;
  justify-content: center;
  margin-top: 96px;
  flex-wrap: wrap;
}

.spl-play-btn,
.spl-make-btn {
  padding: 18px 56px;
  background: var(--gold);
  border: none;
  border-radius: 10px;
  color: #0a0604;
  font-family: 'DM Sans', sans-serif;
  font-size: 16px;
  letter-spacing: 1px;
  cursor: pointer;
  transition: all .2s;
  font-weight: 700;
}

.spl-play-btn:hover,
.spl-make-btn:hover {
  background: #e8c76a;
}

.spl-play-btn:active,
.spl-make-btn:active { transform: scale(.97); }

/* ── R6.33 Build a jam (Blank Canvas) tile + panel ── */
.spl-jam-cta-row {
  display: flex;
  justify-content: center;
  margin-top: 16px;
}
.spl-jam-cta {
  background: transparent;
  border: 1px solid rgba(154,100,32,0.45);
  border-radius: 6px;
  padding: 10px 22px;
  font-family: 'Space Mono', monospace;
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold);
  cursor: pointer;
  transition: all .18s;
}
.spl-jam-cta:hover {
  background: rgba(255,250,230,0.55);
  border-color: var(--gold);
  color: #7d4f17;
}
.spl-jam-cta[aria-expanded="true"] {
  background: rgba(154,100,32,0.10);
  border-color: var(--gold);
}
.spl-jam-panel {
  margin: 14px auto 0;
  max-width: 460px;
  padding: 14px 18px 16px;
  border: 1px solid rgba(154,100,32,0.35);
  border-radius: 6px;
  background: rgba(255,250,230,0.55);
  display: flex;
  flex-direction: column;
  gap: 10px;
  animation: fadeUp .25s ease both;
}
.spl-jam-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.spl-jam-lbl {
  font-family: 'Space Mono', monospace;
  font-size: 9px;
  letter-spacing: 2px;
  color: var(--dim2);
  width: 56px;
  text-transform: uppercase;
  flex-shrink: 0;
}
.spl-jam-keys {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  flex: 1;
}
.spl-jam-key {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--dim);
  font-family: 'Space Mono', monospace;
  font-size: 8px;
  cursor: pointer;
  transition: all .14s;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.spl-jam-key:hover { border-color: var(--gold); color: var(--gold); }
.spl-jam-key.on {
  background: var(--gold);
  color: #0a0604;
  border-color: var(--gold);
}
.spl-jam-modes {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  flex: 1;
}
.spl-jam-mode {
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--dim);
  font-family: 'Space Mono', monospace;
  font-size: 9px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 5px 9px;
  border-radius: 3px;
  cursor: pointer;
  transition: all .14s;
}
.spl-jam-mode:hover { border-color: var(--gold); color: var(--gold); }
.spl-jam-mode.on {
  background: var(--gold);
  color: #0a0604;
  border-color: var(--gold);
}
.spl-jam-tempo {
  display: flex;
  align-items: center;
  gap: 6px;
}
.spl-jam-tempo-input {
  width: 56px;
  background: rgba(255,250,230,0.85);
  border: 1px solid var(--border2);
  border-radius: 3px;
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-size: 16px;
  text-align: center;
  color: var(--text);
  padding: 4px 0;
  -moz-appearance: textfield;
}
.spl-jam-tempo-input::-webkit-outer-spin-button,
.spl-jam-tempo-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.spl-jam-tempo-step {
  width: 24px;
  height: 24px;
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--gold);
  font-family: 'Space Mono', monospace;
  font-size: 12px;
  border-radius: 3px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: all .14s;
}
.spl-jam-tempo-step:hover { border-color: var(--gold); background: rgba(154,100,32,0.10); }
.spl-jam-tempo-unit {
  font-family: 'Space Mono', monospace;
  font-size: 9px;
  letter-spacing: 2px;
  color: var(--dim2);
}
.spl-jam-go-row {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}
.spl-jam-go {
  background: var(--gold);
  border: none;
  border-radius: 6px;
  padding: 10px 28px;
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #0a0604;
  cursor: pointer;
  transition: all .2s;
}
.spl-jam-go:hover { background: #e8c76a; }
.spl-jam-go:active { transform: scale(.97); }

/* Ghost tile while dragging */
.spl-drag-ghost {
  position: fixed;
  pointer-events: none;
  z-index: 9999;
  opacity: .85;
  width: 72px;
  height: 72px;
  border: 1.5px solid var(--gold);
  border-radius: 12px;
  background: rgba(232,199,106,.15);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  box-shadow: 0 12px 36px rgba(0,0,0,.5);
  transform: scale(1.08) rotate(2deg);
  backdrop-filter: blur(4px);
}

/* Desktop: tiles respond to hover */
@media (hover: hover) {
  .spl-tile:hover .spl-cname { color: #e8c76a; }
  .spl-tile { cursor: pointer; }
}

/* ── Key selector ── */
.spl-key-row {
  display: flex;
  gap: 6px;
  justify-content: center;
  flex-wrap: wrap;
  margin: 20px auto 0;
  max-width: 420px;
}

.spl-key-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--dim);
  font-family: 'Space Mono', monospace;
  font-size: 8px;
  letter-spacing: 0;
  cursor: pointer;
  transition: all .14s;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  flex-shrink: 0;
}

.spl-key-btn:hover {
  border-color: var(--gold);
  color: var(--text);
}

.spl-key-btn.on {
  border-color: var(--gold);
  background: var(--gold-dim);
  color: var(--gold);
  font-weight: 700;
}

/* ── Tile remove button ── */
.spl-rm {
  position: absolute;
  top: 3px;
  left: 4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--dim2);
  font-size: 11px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  line-height: 1;
  opacity: 0;
  transition: opacity .14s, color .14s;
  z-index: 5;
}

.spl-tile:hover .spl-rm {
  opacity: 1;
}

.spl-rm:hover {
  color: #e06060;
  background: rgba(224,96,96,.12);
}

/* ── Add tile button ── */
.spl-add-btn {
  width: 44px;
  height: 72px;
  border: 1.5px dashed var(--border2);
  border-radius: 12px;
  background: transparent;
  color: var(--dim);
  font-size: 20px;
  cursor: pointer;
  transition: all .18s;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-left: 4px;
}

.spl-add-btn:hover {
  border-color: var(--gold);
  color: var(--gold);
  background: var(--gold-dim);
}

/* Tiles wrap scrolls on narrow screens */
.spl-tiles-wrap {
  margin: 14px auto 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  max-width: 100vw;
}

.spl-tiles {
  display: flex;
  align-items: center;
  gap: 8px;
  user-select: none;
  position: relative;
  overflow-x: auto;
  padding: 8px 4px;
  max-width: calc(100vw - 32px);
  scrollbar-width: none;
}
.spl-tiles::-webkit-scrollbar { display: none; }

/* ── Splash sound toggle — inline in action row ── */
.spl-sound-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--border2);
  background: transparent;
  font-size: 15px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0.5;
  transition: opacity .2s, border-color .2s, background .2s;
  flex-shrink: 0;
}
.spl-sound-btn:hover {
  opacity: 1;
  border-color: var(--gold);
  background: var(--gold-dim);
}
.spl-sound-btn.on {
  opacity: 1;
  border-color: var(--gold);
}

.spl-reset-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--border2);
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0.5;
  transition: opacity .2s, border-color .2s, background .2s;
  flex-shrink: 0;
}
.spl-reset-btn:hover {
  opacity: 1;
  border-color: var(--gold);
  background: var(--gold-dim);
}
.spl-reset-btn:active {
  transform: rotate(-30deg);
  transition: transform .15s;
}

/* F-hole decorations — desktop only, far edges */
.spl-fhole {
  position: absolute;
  width: 28px;
  height: 110px;
  opacity: 0.09;
  pointer-events: none;
  top: 50%;
  transform: translateY(-50%);
  display: none; /* hidden on mobile */
}
@media (min-width: 700px) {
  .spl-fhole { display: block; }
  .spl-fhole-l { left: clamp(20px, 5vw, 60px); }
  .spl-fhole-r { right: clamp(20px, 5vw, 60px); }
}

/* F-hole size */
.spl-fhole {
  width: 30px;
  height: 124px;
}

/* Anchor line */
.spl-anchor {
  font-family: 'Space Mono', monospace;
  font-size: 9px;
  letter-spacing: 1.5px;
  color: rgba(201,168,76,0.45);
  text-transform: lowercase;
  margin-top: 6px;
}

/* Tiles: warm wood grain undertone */
.spl-tile {
  background:
    repeating-linear-gradient(
      91deg,
      transparent 0px, transparent 2px,
      rgba(160,100,30,0.025) 2px, rgba(160,100,30,0.025) 5px
    ),
    var(--surf2) !important;
}

/* SVG sound button — replace emoji version */
.spl-sound-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid rgba(201,168,76,0.25);
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0.5;
  transition: opacity .2s, border-color .2s, background .2s;
  flex-shrink: 0;
}
.spl-sound-btn:hover {
  opacity: 1;
  border-color: var(--gold);
  background: var(--gold-dim);
}
.spl-sound-btn.on {
  opacity: 0.85;
  border-color: rgba(201,168,76,0.5);
}

/* Hide waves by default (muted state), show slash */
.spl-sound-wave1,
.spl-sound-wave2 { display: none; }
.spl-sound-slash  { display: block; }

/* On touch devices × is always visible — hover doesn't exist */
@media (hover: none) {
  .spl-rm { opacity: 0.5; }
  .spl-tile:active .spl-rm { opacity: 1; }
}

/* ── Collapsible key selector ── */
.spl-key-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 14px auto 0;
}

.spl-key-current {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  border: 1px solid rgba(201,168,76,0.3);
  border-radius: 20px;
  background: transparent;
  color: var(--gold);
  font-family: 'Space Mono', monospace;
  font-size: 11px;
  letter-spacing: 1px;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.spl-key-current:hover {
  border-color: var(--gold);
  background: var(--gold-dim);
}
#spl-key-chevron {
  transition: transform .2s;
  flex-shrink: 0;
}

/* key row now flex-wrap when open */
.spl-key-row {
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  max-width: 360px;
}

/* ── F-hole size update ── */
.spl-fhole {
  width: 32px;
  height: 130px;
}

/* ── Perspective chord card view ─────────────────────────────── */
#prog-cards .prog-col svg {
  transition: transform .3s ease, filter .3s ease;
  transform-origin: center 85%;
}
#prog-cards .prog-col svg.persp-on {
  transform: perspective(500px) rotateX(16deg);
  transform-origin: center 85%;
  filter: drop-shadow(0 8px 14px rgba(0,0,0,0.7)) drop-shadow(0 3px 5px rgba(0,0,0,0.5));
}
#prog-cards .prog-card.persp-on {
  box-shadow: 0 12px 32px rgba(0,0,0,0.5);
}
/* 3D un-orphaned onto the live PIANOLA cards — lay the grips back like sheet
   music on a stand (player's-eye). Gentle 13deg; transition so the toggle
   feels mechanical. */
.pia-card { transition: transform .3s ease, box-shadow .3s ease; }
/* Perspective belongs to the SCENE, not each card. Baking perspective() into
   every card's own transform gave each one its own vanishing point, so they
   splayed/fanned (Scott: "drawing dimension 101 error"). Fix: one shared
   vanishing point on the parent row + just the tilt on each card → the whole
   row lays back together like charts on a stand. Generous distance = gentle,
   near-parallel recline. !important on the tilt because the active card's
   scale-pop otherwise wins and stands it upright. */
.pia-row-cards:has(.pia-card.persp-on){
  perspective: 700px;
  perspective-origin: 50% 60%;
}
.pia-card.persp-on {
  transform: rotateX(16deg) !important;
  transform-origin: center bottom;
  box-shadow: 0 14px 30px rgba(0,0,0,0.45);
}
/* Box (position window) only acts on the big fretboard, which Shapes (PL.I)
   doesn't show — hide that row there so the View menu only offers live
   controls (lens: no inert toggles; Norman). Fingering + 3D remain live on
   Shapes via the cards. */
body[data-plate-lens="I"] #hdr-view-menu #posbox-toggle { display: none; }

/* ── Perspective fretboard wrappers (Play Along + Solo) ──────────── */
.strip-hear-btn { font-family:'DM Sans',sans-serif;font-size:12px;padding:2px 7px;border-radius:4px;border:1px solid transparent;background:transparent;cursor:pointer;color:var(--dim2);transition:all .15s; }
.strip-hear-btn.on { color:var(--gold);border-color:rgba(232,199,106,0.3);background:rgba(232,199,106,0.07); }
.strip-hear-btn:hover:not(.on) { color:var(--dim); }
#strip-zone-hear button { font-family:'DM Sans',sans-serif;font-size:12px;padding:2px 7px;border-radius:4px;border:1px solid transparent;background:transparent;cursor:pointer;color:var(--dim2);transition:all .15s; }
#strip-zone-hear button.on { color:var(--gold);border-color:rgba(232,199,106,0.3);background:rgba(232,199,106,0.07); }
#strip-zone-hear button:hover:not(.on) { color:var(--dim); }
  flex-shrink: 0;
  transition: transform .3s ease, filter .3s ease;
  transform-origin: center bottom;
  overflow: hidden;
  min-height: 120px;
  user-select: none;
  -webkit-user-select: none;
}
/* Very short viewports: settings panel hides, fretboard gets smaller */
@media (max-height: 580px) {
  #play-neck-wrap, #sx-neck-wrap {
    min-height: 80px;
  }
  .settings-panel {
    max-height: 0 !important;
    overflow: hidden !important;
    padding: 0 !important;
    opacity: 0;
  }
}
@media (max-height: 480px) {
  .play-dashboard, .sx-dashboard { display: none !important; }
  .beat-gear-row { display: none !important; }
}
#play-neck-wrap.persp-neck-on,
#sx-neck-wrap.persp-neck-on {
  transform: perspective(700px) rotateX(16deg);
  transform-origin: center bottom;
  filter: drop-shadow(0 16px 24px rgba(0,0,0,0.8)) drop-shadow(0 6px 8px rgba(0,0,0,0.5));
}

/* ── Pedalboard 3D — looking down at your board ────────────────── */
#sounds-panel.persp-board-on {
  perspective: 1000px;
  perspective-origin: center 30%;
}
#sounds-panel.persp-board-on .pb-board {
  transform: rotateX(8deg);
  transform-origin: center bottom;
  transition: transform 0.3s ease;
  transform-style: preserve-3d;
}
#sounds-panel.persp-board-on .pb-pedal {
  transform: translateZ(4px);
  box-shadow: 0 6px 16px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,255,255,0.04);
  transition: transform 0.2s, box-shadow 0.2s;
  /* Force crisp text rasterization in 3D context */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
/* Force all text/controls inside pedals to render on their own GPU layer — eliminates subpixel blur */
#sounds-panel.persp-board-on .pb-label,
#sounds-panel.persp-board-on .pb-btn,
#sounds-panel.persp-board-on .pb-knob,
#sounds-panel.persp-board-on .pb-knob-lbl,
#sounds-panel.persp-board-on .pb-knob-val,
#sounds-panel.persp-board-on .pb-param,
#sounds-panel.persp-board-on .pb-bpm-display,
#sounds-panel.persp-board-on .pb-eq-lbl,
#sounds-panel.persp-board-on .pb-eq-val {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
#sounds-panel.persp-board-on .pb-pedal:hover {
  transform: translateZ(8px);
  box-shadow: 0 8px 20px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,255,255,0.06);
}
#sounds-panel.persp-board-on .pb-footswitch {
  transform: translateZ(6px);
  box-shadow: 0 4px 10px rgba(0,0,0,0.8), inset 0 2px 3px rgba(255,255,255,0.06), inset 0 -2px 4px rgba(0,0,0,0.5);
}
#sounds-panel.persp-board-on .pb-footswitch:active {
  transform: translateZ(2px) translateY(1px);
}
/* Back shelf tilts slightly more — farther away */
#sounds-panel.persp-board-on .pb-board:first-of-type {
  transform: rotateX(10deg);
}

/* ── Beat dot strip: directly under fretboard ────────────────────── */
.neck-beat-strip {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 16px 0 14px;
  gap: 0;
}
/* Mobile: hide the strip, show gear-row dots instead */
@media (max-width: 599px) {
  .neck-beat-strip       { display: none !important; }
  .beat-dot-mobile-only  { display: flex !important; }
}
/* Desktop: show strip, hide gear-row mobile dots */
@media (min-width: 600px) {
  .beat-dot-mobile-only  { display: none !important; }
}

/* ── Desktop vertical rhythm: consistent gap between beat strip and controls ── */
/* A fixed breathing gap replaces the old margin:auto which created a large void */
@media (min-width: 600px) {
  #sub-play  .settings-panel,
  #sub-scale .settings-panel {
    margin-top: clamp(8px, 2vh, 20px);
  }
}

/* ── CONTEXTUAL RECORDER — Improvise tab only ──────────────────────
   Not HAL. Not a red eye staring at you.
   Small, at the bottom, in context. Appears because it belongs here.
─────────────────────────────────────────────────────────────────── */
.improv-recorder{
  display:none;align-items:center;gap:10px;
  padding:8px 14px;border-top:1px solid #1e1c2e;
  flex-shrink:0;flex-wrap:wrap;
  padding-bottom:calc(8px + env(safe-area-inset-bottom, 0px));
  margin-bottom:44px; /* clear the beta banner height */
}
.improv-recorder.rec-active{
  display:flex;
}
.improv-rec-dot{
  width:24px;height:24px;border-radius:50%;
  border:1.5px solid #3a2a0a;
  background:radial-gradient(circle at 38% 35%, #1e1500, #0e0a00);
  cursor:pointer;outline:none;flex-shrink:0;
  transition:all .2s;
  box-shadow:0 1px 4px rgba(0,0,0,0.5);
}
.improv-rec-dot:hover{border-color:#7a5a10;}
.improv-rec-dot.armed{border-color:#c9a840;box-shadow:0 0 0 3px rgba(201,168,64,0.12);}
.improv-rec-dot.recording{border-color:#f0a030;animation:rec-outer-pulse .9s ease-in-out infinite;}
.improv-rec-label{
  font-family:'Space Mono',monospace;font-size:14px;
  letter-spacing:2px;color:#2a1e08;text-transform:uppercase;
  transition:color .2s;
}
.improv-rec-dot.armed + .improv-rec-label{color:#c9a840;}
.improv-rec-dot.recording + .improv-rec-label{color:#f0a030;}
.improv-rec-hint{
  font-family:'Space Mono',monospace;font-size:14px;
  letter-spacing:1px;color:#3a2828;flex:1;
}

/* Slow mode — one-tap root grid, inline quality changer */
.slow-root-grid{display:flex;flex-wrap:wrap;gap:5px;padding:8px 14px;}
.slow-root-btn{
  display:flex;flex-direction:column;align-items:center;
  padding:6px 10px;border:1px solid var(--border2);border-radius:4px;
  background:transparent;cursor:pointer;transition:all .12s;gap:2px;
  min-width:44px;
}
.slow-root-btn:hover{border-color:var(--gold);background:#1a1828;}
.slow-root-btn:active{background:#2a2440;transform:scale(0.96);}
.slow-root-roman{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim);letter-spacing:1px;}
.slow-root-note{font-family:'Space Mono',monospace;font-size:14px;color:var(--dim2);letter-spacing:1px;}
.slow-root-btn:hover .slow-root-roman{color:var(--gold);}
.slow-root-btn:hover .slow-root-note{color:var(--dim);}

.slow-chord.last{border-color:var(--border2);}
.slow-qual-row-inline{display:flex;gap:3px;margin-top:5px;flex-wrap:wrap;}
.slow-qual-inline{
  padding:2px 7px;border:1px solid var(--border2);border-radius:3px;
  background:transparent;color:var(--dim);font-family:'Space Mono',monospace;
  font-size:14px;cursor:pointer;transition:all .12s;letter-spacing:1px;
}
.slow-qual-inline:hover{border-color:var(--gold);color:var(--gold);}
.slow-qual-inline.on{border-color:var(--gold);color:var(--gold);background:var(--gold-dim);}
.slow-qual-inline.on{border-color:var(--gold);color:var(--gold);background:rgba(232,199,106,0.08);}

/* ── PEDAL CENTERING FIX — everything centered like real pedals ── */

/* ── TIER 3 BAR — secondary actions, recessed from tabs ──────────── */
.t3-bar{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;
  background:rgba(10,9,20,0.5);}
.t3-seg{flex:1;padding:5px 8px;border:none;background:transparent;
  font-family:'DM Sans',sans-serif;font-size:12px;color:var(--dim2);
  cursor:pointer;text-align:center;transition:all .15s;letter-spacing:0.5px;}
.t3-seg:hover{color:var(--dim);background:rgba(232,199,106,0.03);}
.t3-seg.on{color:var(--gold);background:rgba(232,199,106,0.06);
  box-shadow:inset 0 -2px 0 rgba(232,199,106,0.4);}
.t3-icon{opacity:0.5;margin-right:3px;}
.t3-seg.on .t3-icon{opacity:1;}
.t3-divider{width:1px;background:var(--border);margin:4px 0;flex-shrink:0;}
.t3-voice-seg{flex:0.7;}

.t3-panel{flex-shrink:0;border-bottom:1px solid var(--border);
  background:rgba(10,9,20,0.6);animation:fadeUp .15s ease both;}

/* ── PER-PEDAL PERSONALITY — unique shapes ──────────────────── */
[data-pedal="instrument"]{border-radius:12px;padding:18px 20px 14px;}
[data-pedal="voice"]{border-radius:20px;padding:20px 18px 16px;}
[data-pedal="pattern"]{border-radius:4px;padding:16px 14px 14px;}
[data-pedal="mix"]{border-radius:6px 6px 14px 14px;padding:14px 12px 12px;}
[data-pedal="reverb"]{border-radius:24px;padding:22px 20px 18px;}
[data-pedal="delay"]{border-radius:14px;padding:20px 18px 16px;}
[data-pedal="eq"]{border-radius:3px;padding:16px 20px 14px;}
[data-pedal="tempo"]{border-radius:8px;padding:20px 22px 16px;}
[data-pedal="bass"]{border-radius:22px 22px 16px 16px;padding:20px 16px 16px;}
[data-pedal="drums"]{border-radius:3px;padding:16px 14px 14px;border-width:2px;}


/* ── Three visual tiers ─────────────────────────────────────── */
/* T1: full weight — fretboard, dashboard, play button */
/* T2: 72% — active tab, content in progress */
/* T3: 35%, hover→100% — secondary controls, status strip */
.tier3{opacity:0.35;transition:opacity .15s;}
.tier3:hover{opacity:1;}
/* ── RAIL-S — the bottom glance ─────────────────────────────────
   R2.5 Q6: nine cells (Transport · Course · Key · Chord · Position ·
   Tempo · Swing · Capo · FX), content-sized widths (lead + trail get
   min-width), brass hairline dividers, baseline-aligned values, three
   state grammars (changed / playing / summonable).

   Carrying #pedal-strip + .ps-cell selectors so existing JS handlers
   keep working through the migration. Step 1c restyles structure;
   step 1d wires the state grammars; step 6 (later arc) deletes the
   pedalboard category entirely.
   Spec: docs/claude-design-2026-04-24/R2.5 Follow-up.html §Q6. */
#pedal-strip{
  background:var(--vellum);
  border-top:1px solid var(--gold2);
  box-shadow:inset 0 1px 0 rgba(240,226,190,0.6);
  color:var(--text);
}
#pedal-strip-bar{
  display:flex; align-items:stretch;
  /* R5.43 — Scott's call: "spread the controls along the bottom why be
     pressed left?" Cells were content-sized (flex:0 0 auto) clumping at
     the left edge. Now: distribute across full width via space-between,
     each cell flex:1 to grow. */
  justify-content:space-between;
  min-height:30px;                 /* R4.6 Q-G floor — was 62px */
  padding:0;
  width:100%;
}
#pedal-strip-bar > .ps-cell{
  flex:1 1 0 !important;
}
#pedal-strip-bar > .ps-div{
  flex:0 0 auto;
}

/* R4.6 Q-G — row 2 of the pedal strip carries the recorder
   transport. ⏺ Rec next to ▶ Playback (visible once a take
   exists), phrase scrubber container (populated by recorder.js
   when a take is captured), metronome readout. Row 2 height is
   40px per R4.6 Q-G; total strip = ~70px (row 1 30 + row 2 40).
   Same wood-walnut bench register as row 1 — it's the same bench. */
/* R4.8e — recorder row only meaningful on the Melody plate (the only
   plate where the player is actually playing notes that get captured).
   Hidden elsewhere per Scott's "don't be misleading" call.
   The recorder JS state machine (recorder.js) keeps working unchanged;
   when the player switches to the Melody plate the row reappears with
   whatever take state is active.
   r6p41-outer-chrome — was data-plate-lens="III"; the rename PR #219
   moved Melody to PL. IV (PL. III is now Color). The recorder belonged
   on PL. IV after Wave 2c; this rule still pointed at PL. III. */
.ps-row2{
  display:none;
  align-items:center;
  gap:10px; padding:6px 14px;
  min-height:40px;
  border-top:1px solid rgba(154,100,32,0.18);
  background:rgba(214,220,190,0.55);
  font-family:'Space Mono',monospace;
}
body[data-plate-lens="IV"] .ps-row2{ display:flex; }
.ps-row2-btn{
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 10px;
  background:transparent; border:1px solid var(--gold2); border-radius:1px;
  color:var(--text); cursor:pointer;
  font-family:'Space Mono',monospace;
  transition:background 120ms, color 120ms, border-color 120ms;
}
.ps-row2-btn:hover{ background:var(--gold-dim); border-color:var(--gold); }
.ps-row2-btn:focus{ outline:none; }
.ps-row2-btn:focus-visible{ outline:1.5px solid var(--gold3); outline-offset:2px; }
.ps-row2-btn .ps-row2-glyph{
  font-size:14px; line-height:1; color:var(--gold);
}
.ps-row2-btn .ps-row2-lbl{
  font-size:9px; letter-spacing:var(--tracking-eng-label); text-transform:uppercase;
}
/* Rec button states — armed (gold) / recording (amber) */
#ps-rec-btn.is-armed     { border-color:var(--gold);  background:var(--gold-dim); }
#ps-rec-btn.is-armed   .ps-row2-glyph{ color:var(--gold3); }
#ps-rec-btn.is-recording { border-color:var(--amber); background:rgba(196,88,28,0.10); }
#ps-rec-btn.is-recording .ps-row2-glyph{ color:var(--amber); }
@keyframes ps-rec-pulse {
  0%, 100% { opacity:1; }
  50%      { opacity:0.5; }
}
#ps-rec-btn.is-recording .ps-row2-glyph{ animation: ps-rec-pulse 800ms ease-in-out infinite; }

.ps-row2-scrubber{
  flex:1 1 auto; min-width:0;
  height:24px;
  display:flex; align-items:center;
  border:1px solid rgba(154,100,32,0.20);
  background:rgba(240,226,190,0.30);
  border-radius:1px;
  overflow:hidden;
  font-family:'Space Mono',monospace; font-size:9px; color:var(--dim2);
}
.ps-row2-scrubber:empty::before{
  content: 'PHRASE SCRUBBER · ARM TO RECORD';
  letter-spacing:var(--tracking-eng-meta); padding:0 10px;
  text-transform:uppercase; opacity:0.5;
}
.ps-row2-take-indicator{
  display:inline-flex; align-items:center; gap:6px;
  padding:3px 8px;
  border:1px solid var(--gold2); border-radius:1px;
  background:rgba(154,100,32,0.05);
  font-size:9px; letter-spacing:var(--tracking-eng-label);
  color:var(--gold); text-transform:uppercase;
}
.ps-row2-actions{
  display:inline-flex; gap:4px; align-items:center;
}
.ps-row2-act{
  width:22px; height:22px; padding:0;
  background:transparent; border:1px solid var(--gold2); border-radius:1px;
  color:var(--text); cursor:pointer; font-size:11px; line-height:1;
  display:inline-flex; align-items:center; justify-content:center;
}
.ps-row2-act:hover{ background:var(--gold-dim); color:var(--gold); }
.ps-row2-act-save:hover{ color:var(--gold3); border-color:var(--gold); }
.ps-row2-divider{
  width:1px; height:24px; background:rgba(154,100,32,0.25);
  margin:0 4px;
}
.ps-row2-meta{
  display:inline-flex; flex-direction:column; gap:1px;
  font-family:'Space Mono',monospace;
}
.ps-row2-meta-lbl{
  font-size:8.5px; letter-spacing:var(--tracking-eng-meta);
  color:var(--dim2); text-transform:uppercase;
}
.ps-row2-meta-val{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:11px; color:var(--text);
}

/* R4 Q6 — collapse-on-PL.I/II spec. Row 2 stays compact when no
   take exists; on PL. III Melody it stays expanded once a take
   is captured (handled via JS — body class set by _setPlateTab).
   For now the scrubber empty-state is universal; per-plate
   collapse is a Phase 8 audit-cleanup polish. */
.ps-cell{
  flex:0 0 auto;                   /* content-sized — was flex:1 1 0 */
  padding:10px 14px;               /* R2.5 Q6: 14 L/R · 10 T/B */
  position:relative; min-width:0; background:transparent;
  display:flex; flex-direction:column; justify-content:center; gap:2px;
  transition:background .15s;
}
.ps-cell.tapable{ cursor:pointer; }
.ps-cell.tapable:hover{ background:rgba(154,100,32,0.04); }
/* R4 Q1 (a) — when a pedal cell raises the rail, the cell itself
   gets a 3px gold3 top bar (same primitive the chord cards use
   for "active") so the player sees the cell→rail link. Cleared on
   close. Same vocabulary as the brass-bar transition R2.5 Q5. */
.ps-cell.is-rail-active{
  box-shadow:inset 0 3px 0 var(--gold3);
}
/* Lead (Transport) and trail (FX) get a guaranteed footprint so the
   rail's anchors don't collapse on narrow content. */
.ps-cell.lead{  min-width:78px; }
.ps-cell.trail{ min-width:108px; }
/* Hot cell (Chord · in hand) keeps brass tint but loses the 1.6× flex
   inflation — content-sized now, like the others. */
.ps-cell.hot{ background:rgba(154,100,32,0.05); padding:10px 18px; }
.ps-cell.hot.tapable:hover{ background:rgba(154,100,32,0.10); }
.ps-cell.dim{ opacity:0.55; }
.ps-div{ width:1px; align-self:stretch; background:var(--gold2); opacity:0.18; }
/* R6.16 — Three-act pedal-strip spacers per Claude Design 2026-05-08
   punch-list #7. Intra-group dividers stay quiet (opacity:0.18 above);
   inter-group dividers get the .ps-div-major class for the brighter
   articulation: gear (TRANSPORT) │ gear (COURSE · TIMBRE) │ state
   (KEY · CHORD · POSITION · TEMPO · SWING · CAPO) │ output (EFFECTS).
   Patent Drawing: dividers articulate function without changing the
   weight of the cells themselves. */
.ps-div.ps-div-major{ opacity:0.55; }

/* R5.30 / R5.31 — Brass hinge pin. 4×4 brass dot at the trailing edge
   of every tappable chassis cell, vertically centered. R5.31 fix:
   was right:-2px which overlapped the .ps-div divider (1px brass
   sibling) and got clipped on its right side; now right:0 places the
   dot fully inside the cell flush with its right edge. No divider
   conflict, reads as "this cell has a brass pin at its trailing edge."
   Last cell (FX, .trail) skips the pin since there's no divider after. */
.ps-cell.tapable::after{
  content:""; position:absolute;
  top:50%; right:0;
  width:4px; height:4px;
  margin-top:-2px;
  background:var(--gold);
  border-radius:50%;
  opacity:0.5;
  transition:opacity 160ms ease, transform 160ms ease;
  pointer-events:none;
}
.ps-cell.tapable:hover::after{ opacity:1; transform:scale(1.15); }
.ps-cell.is-rail-active::after{ opacity:1; box-shadow:0 0 0 1px rgba(0,0,0,0.35); }
.ps-cell.trail::after{ display:none; }

/* R6.16 — State-canonical signifier per Claude Design 2026-05-08 punch-
   list #8: "4×4px brass dot under the labels of CHORD, POSITION, KEY
   (the cells read elsewhere in the app). 0.55 opacity. Signifier, not
   symbol." (Norman.) The right-edge brass-hinge dot (::after above)
   reads "this cell can open something." This new bottom-center brass
   square reads "this cell's value lives somewhere else too" — the
   state-canonical link to FIG. a/b/c on PL. I sidebar (Key/Position/
   Capo) and FIG. d Voicings (CHORD). Square (not circle) so it doesn't
   echo the round hinge dot. */
#ps-cell-key::before,
#ps-cell-chord::before,
#ps-cell-position::before{
  content:""; position:absolute;
  bottom:5px; left:50%;
  width:4px; height:4px;
  margin-left:-2px;
  background:var(--gold);
  opacity:0.55;
  pointer-events:none;
}
@media (prefers-reduced-motion: reduce){
  .ps-cell.tapable::after{ transition:none; }
}

/* ── Three state grammars (R2.5 Q6 architectural rules) ─────────
   1. changed — gold3 top bar + gold-dim fill, 800ms (200ms on Chord
      because chord changes are frequent and the flash mustn't cumulate)
   2. playing — amber dot pulses on Tempo cell on the downbeat; visible
      affordance, not seizure-inducing
   3. summonable — value-line in --gold instead of --text; the colour
      IS the affordance, no border or chrome
   JS hooks (apply/remove these classes on real events) ship in 1d. */
.ps-cell.state-changed{
  box-shadow:inset 0 2px 0 var(--gold3);
  background:var(--gold-dim);
}
.ps-cell.state-changed.tapable:hover{ background:rgba(154,100,32,0.15); }
.ps-cell.state-playing::after{
  content:""; position:absolute; left:10px; bottom:6px;
  width:6px; height:6px; border-radius:50%;
  background:var(--amber);
  animation:rs-pulse-beat var(--rs-beat-period, 750ms) ease-in-out infinite;
  pointer-events:none;
}
@keyframes rs-pulse-beat {
  0%   { opacity:0.25; transform:scale(0.85); }
  18%  { opacity:1;    transform:scale(1.15); } /* 60ms in @ 750ms */
  60%  { opacity:0.35; transform:scale(0.95); } /* 140ms out */
  100% { opacity:0.25; transform:scale(0.85); }
}
.ps-cell.state-summonable .ps-val{ color:var(--gold); }
.ps-lbl-row{ display:flex; align-items:center; gap:6px; margin-bottom:4px; }
/* R6.40-C.3 — Chassis cell glyph per Claude Design rev. 4. 16×16
   brass-on-dark inline glyph that sits before each cell's label.
   Each glyph is instrument-anatomy (tuning pegs, side-dots, capo
   bar) or engineering-anatomy (metronome, wavefront, seesaw) —
   never generic. Parallel recognition vs sequential read. */
.ps-glyph{
  display:inline-flex; align-items:center; justify-content:center;
  flex:0 0 auto;
  width:16px; height:16px;
  opacity:0.85;
}
.ps-glyph svg{ display:block; }
.ps-cell:hover .ps-glyph{ opacity:1; }
.ps-cell.hot .ps-lbl-row{ margin-bottom:6px; }
.ps-lbl{
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:2.4px;
  text-transform:uppercase; color:var(--dim2); white-space:nowrap;
}
/* Step 1f — drop the dotted leader line. At 62 px Rail height the dots
   read as chart-junk noise; they also align with letter-spaced values
   below them and create a visual fault line that bisects strings like
   "GDAE". Per R2.5 Q6 + Tufte data-ink discipline, kept hidden but the
   element itself remains for any JS that may still reference it. */
.ps-leader{ display:none; }
.ps-val{
  font-family:'Playfair Display',serif; font-style:italic; font-weight:700; font-size:20px; line-height:1;
  color:var(--text); display:flex; align-items:baseline; gap:6px;
  white-space:nowrap; overflow:hidden;
}
/* R6.31 — .ps-val.mono override neutralized per Design's prescription.
   Was forcing Course / Position / Tempo / Swing / Capo into Space Mono;
   the chassis seam read as half-Plate-A. Now: every cell speaks
   Playfair italic by default (Tempo + Position are numbers; Playfair
   handles them gracefully and the Patent Drawing register reads as one
   instrument, not two typefaces stitched together). The .mono class is
   left in markup for compat — its only effect now is the legacy
   letter-spacing reset. */
.ps-val.mono{ letter-spacing:0; }
#ps-course-val{ letter-spacing:0 !important; }
/* Hot cell keeps brass tint + Chord-cell role colour, but its value
   shrinks to match siblings — R2.5 Q6 baseline alignment beats the
   hero treatment from Phase 7a. */
.ps-cell.hot .ps-val{ color:var(--gold); font-size:20px; }
.ps-cell.dim .ps-val{ color:var(--dim2); }
.ps-sub{
  font-family:'Space Mono',monospace; font-style:normal; font-size:11px; letter-spacing:1.6px;
  color:var(--dim2); font-weight:400; text-transform:uppercase; white-space:nowrap;
}
/* A.7 — TUNING cell now carries TWO pieces of info inline (tuning string +
   instrument name) where other cells carry one short word + unit. Give it
   ~1.7× width of sibling cells so the sub renders at the SAME register as
   DEG (chord) and BPM (tempo) — Space Mono caps 11px 1.6 letter-spacing —
   without truncating. Width pulls from the under-used short cells (KEY/CAPO/SWING). */
#pedal-strip-bar > #ps-cell-course{ flex:1.7 1 0 !important; }
#ps-cell-course .ps-val{ overflow:visible; }
.ps-half-btn{ font-style:normal; }
/* Step 1f — .ps-tip dropped from rendering. R2.5 Q6 architectural rule
   #2: "the sub line is a live caption, not static help. The pedal-strip's
   old behavior of permanent help text is replaced by a sub that actually
   reports something." The live caption now lives in .ps-sub (inline with
   the value), populated by updatePedalStrip per cell. */
.ps-tip{ display:none; }
.ps-drone-pip{
  display:inline-block; width:10px; height:10px; border-radius:50%;
  border:1px solid var(--gold2); background:transparent;
}
.ps-drone-pip.on{ background:var(--amber); border-color:var(--amber); }
/* Legacy FX overflow menu — kept hidden. Step 2 ships the new
   #fx-panel as the primary entry point; this element is retained
   solely for any code path that still references it during the
   migration and gets removed in step 6. */
#ps-fx-menu{ display:none !important; }

/* ── FX▾ PANEL — R2 Step 2 / R2.5 Q7 ──────────────────────────────
   Rises from Rail-S as a 2×2 grid of effect cards. Covers Rail-S
   ("the player has decided not to glance"), does NOT cover the plate
   ("the plate is always the subject"). 240 px tall. Slides up over
   180 ms with cubic-bezier(0.2, 0.8, 0.2, 1). Sits in the same inset
   as the Rail-S itself (36 px from each side; 40 px from bottom of
   the viewport — same as the Margin frame). */
#fx-panel{
  position:fixed;
  left:36px; right:36px; bottom:40px;
  /* Height accommodates: 30 header + 212 grid (2×~99 cards + 14 gap)
     + 30 more-row + 18+16 padding = ~320. Responsive on short
     viewports so the panel never eats the plate. */
  height:min(320px, calc(100vh - 200px));
  padding:18px 22px 16px;
  z-index:700;
  background:var(--vellum);
  border:1px solid var(--gold2);
  box-shadow:inset 0 0 0 1px rgba(240,226,190,0.6),
             0 -6px 18px rgba(26,12,4,0.22);
  transform:translateY(110%);  /* hidden — slides up from below */
  transition:transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
  display:flex; flex-direction:column;
  pointer-events:none; visibility:hidden;
}
#fx-panel.open{ transform:translateY(0); pointer-events:auto; visibility:visible; }
@media (prefers-reduced-motion: reduce) {
  #fx-panel{ transition:none; }
}

#fx-panel-head{
  display:flex; align-items:baseline; justify-content:space-between;
  padding-bottom:10px; margin-bottom:12px;
  border-bottom:1px solid rgba(106,64,16,0.25);
}
#fx-panel-head .fig-banner{ font-size:9px; letter-spacing:2.4px; }
#fx-panel-close{
  background:transparent; border:0; padding:2px 6px; cursor:pointer;
  font-family:'Space Mono',monospace; font-size:11px; letter-spacing:2px;
  color:var(--dim2); text-transform:uppercase;
}
#fx-panel-close:hover{ color:var(--gold); }

.fx-grid{
  flex:1;
  display:grid;
  grid-template-columns:1fr 1fr; grid-template-rows:1fr 1fr;
  gap:14px;
  margin-bottom:10px;
}
.fx-card{
  border:1px solid var(--gold2);
  border-radius:0;                 /* square corners — Plate A discipline */
  background:rgba(240,226,190,0.4);
  padding:12px 16px;
  display:flex; flex-direction:column;
  gap:6px; cursor:pointer;
  transition:background .15s, border-color .15s, box-shadow .15s;
  font:inherit;
  text-align:left;
}
.fx-card:hover{
  background:rgba(240,226,190,0.65);
  border-color:var(--gold);
}
.fx-card:focus-visible{
  outline:none;
  box-shadow:inset 0 3px 0 var(--gold3),
             0 0 0 1px var(--gold);
}
.fx-card-head{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:10px;
}
.fx-card-title{
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:18px; color:var(--text); letter-spacing:0.3px;
}
.fx-card-val{
  font-family:'Space Mono',monospace;
  font-size:10px; letter-spacing:1.6px;
  color:var(--gold); text-transform:uppercase; white-space:nowrap;
}
/* Phase 7b · FX cards — val pill cycles preset on tap. Outer card
   click still opens popover; helper stops propagation. */
.fx-card-val.fx-cycle{
  cursor:pointer;
  padding:2px 6px; margin:-2px -6px;
  border-radius:2px;
  transition:background .12s, color .12s;
}
.fx-card-val.fx-cycle:hover{ background:var(--gold-dim); color:var(--gold3); }
.fx-card-val.fx-cycle:focus{ outline:none; }
.fx-card-val.fx-cycle:focus-visible{ outline:1px solid var(--gold); outline-offset:1px; }
.fx-card-fig{
  flex:1;
  display:flex; align-items:center; justify-content:center;
  min-height:52px;
}
.fx-card-fig svg{ display:block; max-width:100%; height:auto; }
.fx-card-cap{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:12px; color:var(--dim); line-height:1.35;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

#fx-more{
  display:flex; align-items:center; gap:8px;
  padding-top:10px;
  border-top:1px solid rgba(106,64,16,0.18);
}
.fx-more-lbl{
  font-family:'Space Mono',monospace; font-size:8.5px;
  letter-spacing:2.2px; color:var(--dim2); text-transform:uppercase;
  margin-right:4px;
}
.fx-more-btn{
  background:transparent; border:0; padding:3px 9px; cursor:pointer;
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--text); letter-spacing:0.3px;
  border-left:1px solid rgba(106,64,16,0.25);
  transition:color .12s;
}
.fx-more-btn:first-of-type{ border-left:none; padding-left:0; }
.fx-more-btn:hover{ color:var(--gold); }
#ps-fx-menu.open{ display:block; }
#ps-fx-menu .ps-fx-hd{
  font-family:'Space Mono',monospace; font-size:9px; letter-spacing:2.4px;
  text-transform:uppercase; color:var(--gold2); padding-bottom:6px; margin-bottom:8px;
  border-bottom:1px solid var(--gold2);
}
#ps-fx-menu .ps-fx-btn{
  display:block; width:100%; text-align:left;
  background:transparent; border:0; padding:6px 4px;
  font-family:'Playfair Display',serif; font-size:14px; color:var(--text);
  cursor:pointer; transition:color .1s, background .1s;
}
#ps-fx-menu .ps-fx-btn:hover{ color:var(--gold); background:rgba(154,100,32,0.06); }
/* Narrow viewport: reduce per-cell padding and hide dim cells first */
@media (max-width: 860px){
  #pedal-strip-bar{ min-height:82px; }
  .ps-cell{ padding:8px 10px 10px; }
  .ps-cell.hot{ padding:8px 14px 10px; }
  .ps-val{ font-size:18px; }
  .ps-cell.hot .ps-val{ font-size:28px; }
}

/* ── PLATE A · fretboard frame (Phase 5) ───────────────────────
   Wraps #play-neck-wrap as a patent-drawing plate: 1px brass
   hairline, FIG. I banner above with live context caption, "Scale 1:1"
   right-aligned. Frame sits inline-block so it hugs the fretboard's
   natural width — the chrome rail stays outside, left. */
.plate-fb-frame{
  display:inline-block;
  /* R5.63 — frame border bumped 1px→2px and color gold2→walnut so the
     "box" reads as prominently as the highlighted fret label. The 1px
     gold-2 hairline was so faint Scott couldn't tell what the position
     window was; the bracket above tried to fill that role and read
     as disconnected. Now: the frame IS the box, no bracket needed. */
  border:2px solid #4a2410;
  padding:10px 14px 8px;
  background:
    /* 2-3% paper grain — tiny SVG feTurbulence, tiled */
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='4'/><feColorMatrix values='0 0 0 0 0.3  0 0 0 0 0.22  0 0 0 0 0.1  0 0 0 0.055 0'/></filter><rect width='120' height='120' filter='url(%23g)'/></svg>"),
    linear-gradient(180deg, rgba(214,220,190,0.18) 0%, rgba(214,220,190,0) 55%);
  /* Soft inner shadow at frame edge — reads as raised/elevated, not etched */
  box-shadow:
    inset 0 0 14px rgba(26,12,4,0.22),
    inset 0 1px 0 rgba(240,226,190,0.08);
  position:relative;
}
.plate-fb-frame .pff-head{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:16px; margin-bottom:8px;
}
.plate-fb-frame .pff-head .fig-banner{
  font-size:10px; letter-spacing:2.4px; flex:0 1 auto; min-width:0;
}
.plate-fb-frame .pff-context{
  color:var(--dim2); letter-spacing:2px; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis;
}
.plate-fb-frame .pff-scale{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:2px; color:var(--dim2); text-transform:uppercase;
  white-space:nowrap; flex:0 0 auto;
  /* Hidden until Phase 3d ships rail-expansion choreography
     (canvas pulses 720↔680↔620 for pedal/FX). Until then this
     is permanently "SCALE 1:1" — static text = chart junk per
     CLAUDE.md liveness rule. Un-hide when _plCanvasW state
     actually varies and the label has something live to say. */
  display:none !important;
}
.plate-fb-frame #play-neck-wrap{ display:block; }

/* Embodied fretboard — patent-drawing context around the neck.
   The neck itself (#play-neck-wrap) stays solid + authoritative;
   its extremities fade into the instrument. Pegs on the left
   hint at the headstock; body + soundhole on the right hint at
   where the neck joins the resonator. Both rendered in brass
   hairline at low opacity. No interaction — pure context. */
.pff-neck-wrap{
  display:flex; align-items:stretch;
}
.pff-pegs, .pff-body{
  flex:0 0 34px; position:relative;
  display:flex; align-items:center; justify-content:center;
  pointer-events:none;
}
.pff-pegs svg, .pff-body svg{
  width:100%; height:100%; max-height:160px; display:block;
}
.pff-pegs{ margin-right:-6px; }
.pff-body{ margin-left:-6px; }

/* View ▾ overflow — expert toggles (Ghosts · 3D · Box).
   Riff on var-a-plate.jsx's FIG. d View rail — spec had five
   toggles in a vertical rail; we have three (Modes+Shapes are
   absorbed by the PL. I/II/III tabs) and they're expert-mode,
   not load-bearing, so they live behind an overflow button
   matching the pedal strip's FX ▾ pattern for consistency.
   Scope: the three toggles keep their existing onclick handlers
   + existing class hooks (trails-toggle, #perspective-toggle-2,
   #posbox-toggle) — this is a relocation + reskin of handles,
   not a rewrite of behavior. */
.plate-fb-frame .pff-head{ position:relative; }
.pff-view-btn{
  position:relative; padding:4px 10px; font-size:9px;
  letter-spacing:2.2px; line-height:1; flex-shrink:0;
  display:inline-flex; align-items:center; gap:6px;
}
/* R4.6 Q-H — Teacher mode T-toggle. 20×20 square, sits in
   .rn-actions cluster after SHARE. Different shape from the
   letterpress action chips because it's a *state*, not an action.
   Off: hollow with walnut T on lichen. On: filled brass with
   ivory T. Tooltip: "Teacher mode — author lessons, lock fields."
   Hover ring: 1px outer at --gold3 per R4.6 Q-H. */
.teacher-toggle{
  width:24px; height:24px; padding:0;
  background:transparent;
  border:1px solid var(--gold2); border-radius:1px;
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:13px; line-height:1; color:var(--text);
  cursor:pointer; transition:background 120ms, border-color 120ms, color 120ms;
  display:inline-flex; align-items:center; justify-content:center;
  flex-shrink:0;
}
.teacher-toggle:hover{ outline:1px solid var(--gold3); outline-offset:1px; }
.teacher-toggle:focus{ outline:none; }
.teacher-toggle:focus-visible{ outline:1.5px solid var(--gold3); outline-offset:2px; }
.teacher-toggle.is-on{
  background:var(--gold); border-color:var(--gold); color:var(--ivory);
}

/* R4.6 Q-H on-state — thin brass rule below header carrying
   FIG. T — TEACHER MODE. Same vocabulary as the outer-left FIG
   annotation. Hidden by default; .teacher-mode-on on body reveals. */
.fig-t-rule{
  display:none;
  align-items:center; gap:10px;
  padding:4px 36px;
  border-bottom:1px solid var(--gold);
  background:rgba(154,100,32,0.04);
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:var(--tracking-fig-banner); color:var(--gold);
  text-transform:uppercase;
}
body.teacher-mode-on .fig-t-rule{ display:flex; }
.fig-t-rule .fig-t-rule-rule{
  flex:1; height:1px; background:var(--gold); opacity:0.4;
}
.fig-t-rule .fig-t-rule-lbl{
  color:var(--gold3); letter-spacing:var(--tracking-eng-label);
}

/* R4 Q3 — ⤢ expand button. Hidden pending FOLLOWUP-6 design call
   (kill, keep with frost, or grow canvas). The supporting JS in
   render.js (frost overlay, _plExpanded state, setFretWindowExpanded)
   stays dormant — easy to un-hide once design replies. */
.pff-expand-btn{
  /* R5.32 — re-hidden per Scott's clarification. R5.30 surfaced this
     under a misread of "unhide everything"; the directive was actually
     "unhide stuff that works" — and the Expand toggle is incomplete
     (the toggleFretWindowExpanded handler exists but the visual
     transition between 7-fret window and full neck doesn't land
     reliably yet). Better to keep hidden than show a button that
     does something visually broken. Restored display:none !important. */
  display:none !important;
  position:relative; padding:4px 10px; font-size:9px;
  letter-spacing:2.2px; line-height:1; flex-shrink:0;
  align-items:center; gap:4px;
  margin-right:6px;
}
.pff-expand-btn.on{
  background:var(--gold); color:var(--ivory); border-color:var(--gold);
}

/* R4 Q3 — expand = orientation, not detail. The visual register
   shift happens via SVG-rendered frost overlays in buildPlayGrid:
   semi-transparent vellum rects cover the frets *outside* the
   active box, fading the surrounding context. The box itself is
   uncovered → stays at full strength → reads as the focal area
   without any per-element opacity manipulation. CSS only handles
   the brass color override on landmark fret labels (5 / 7 / 9 /
   12, marked with font-weight=700) so they read as orientation
   anchors when expand is on. */
#play-grid-svg.pl-expanded text[font-weight="700"]{
  fill:var(--gold3);
}
.pff-view-dot{
  display:none; width:5px; height:5px; border-radius:50%;
  background:var(--gold);
}
.pff-view-btn.has-active .pff-view-dot{ display:inline-block; }
.pff-view-menu{
  display:none; position:absolute; top:calc(100% + 6px); right:0;
  z-index:40; min-width:180px;
  background:var(--vellum); border:1px solid var(--gold2);
  box-shadow:0 4px 14px rgba(26,12,4,0.2), inset 0 0 0 1px rgba(240,226,190,0.55);
  padding:8px 6px;
}
.pff-view-menu.open{ display:block; }
.pff-view-hd{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:2.4px; text-transform:uppercase; color:var(--gold2);
  padding:2px 10px 6px; border-bottom:1px solid var(--gold2);
  margin-bottom:4px;
}
.pff-view-toggle{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:12px; width:100%;
  padding:6px 10px; background:transparent; border:1px solid transparent;
  border-radius:1px; cursor:pointer;
  transition:border-color .12s, background .12s, color .12s;
  text-align:left;
}
.pff-view-toggle:hover{
  border-color:var(--gold2); background:rgba(154,100,32,0.05);
}
.pff-view-toggle.on{
  border-color:var(--gold); background:var(--gold-dim); color:var(--gold);
}
.pff-view-toggle .pff-view-label{
  font-family:'Playfair Display',serif; font-size:15px; line-height:1;
  color:var(--text);
}
.pff-view-toggle.on .pff-view-label{ color:var(--gold); font-weight:700; }
.pff-view-toggle .pff-view-hint{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.4px; text-transform:uppercase; color:var(--dim2);
}
.pff-view-toggle:focus{ outline:none; }
.pff-view-toggle:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }

/* r6p98-viewmenu — the global header View ▾. The wrap anchors the absolutely-
   positioned .pff-view-menu under the button; the button matches the other
   header letterpress chips and carries the brass has-active dot (lit when any
   of Fingering/3D/Box is on, synced by _syncViewBtnDot). */
.hdr-view-wrap{ position:relative; display:inline-flex; align-items:center; }
#hdr-view-btn{ display:inline-flex; align-items:center; }
#hdr-view-btn .pff-view-dot{ margin-right:5px; }
#hdr-view-btn.has-active .pff-view-dot{ display:inline-block; }

/* ── Fingering toggle (direct header button) ───────────────
   Quick-grab "ways of seeing" button beside the develop switch. When
   on, it reads active in the gold register (mirrors .pff-view-toggle.on). */
.letterpress-btn.trails-toggle.on{
  border-color:var(--gold); background:var(--gold-dim); color:var(--gold);
}

/* ── PLATE A · PL. II Rhythm ruler ──────────────────────────
   Shown only when body[data-plate-lens="II"]. A horizontal
   brass-tick ruler above the fretboard that pulses with the
   transport's beatTick. Swing offset visible as a horizontal
   nudge on offbeat ticks (the swing amount becomes ink).
   Live data-ink, reusing _metroBeat / PS.timeSig / _swingAmount. */
.plate-rhythm-ruler{
  display:none;
  align-items:center; justify-content:center;
  gap:0; padding:6px 14px 8px;
  margin-bottom:4px;
  border-bottom:1px dashed var(--gold2);
}
body[data-plate-lens="II"] .plate-rhythm-ruler{ display:flex; }
.plate-rhythm-ruler .prr-tick{
  display:flex; flex-direction:column; align-items:center; gap:4px;
  position:relative; transition:transform .15s ease-out;
}
.plate-rhythm-ruler .prr-glyph{
  font-family:'Space Mono',monospace; font-size:10px;
  color:var(--dim2); letter-spacing:1px; line-height:1;
  opacity:0.65; transition:color .08s, opacity .08s;
}
.plate-rhythm-ruler .prr-mark{
  width:10px; height:10px; border-radius:50%;
  border:1px solid var(--gold2); background:transparent;
  transition:background .08s, border-color .08s, box-shadow .08s;
}
.plate-rhythm-ruler .prr-tick.accent .prr-mark{
  background:var(--gold); border-color:var(--gold);
  box-shadow:0 0 0 3px rgba(154,100,32,0.18);
}
.plate-rhythm-ruler .prr-tick.accent .prr-glyph{ color:var(--gold); opacity:1; }
.plate-rhythm-ruler .prr-tick.tick .prr-mark{
  background:var(--gold2); border-color:var(--gold2);
  box-shadow:0 0 0 2px rgba(154,100,32,0.1);
}
.plate-rhythm-ruler .prr-tick.tick .prr-glyph{ color:var(--text); opacity:1; }
.plate-rhythm-ruler .prr-gap{
  width:40px; height:1px; background:var(--gold2);
  opacity:0.3; align-self:center;
}
.plate-rhythm-ruler .prr-label{
  font-family:'Space Mono',monospace; font-size:8.5px;
  letter-spacing:1.6px; color:var(--dim2);
  text-transform:uppercase; line-height:1;
}

/* ── r6p91 — THE BEAT RULER as a CABLE RUN (Scott: the same wire as the Shapes
   carriage, with the squeak). _syncRhythmRuler relocates the orphaned ruler into the
   band below the fretboard and stretches a continuous WIRE (.prr-cable, dressed
   identically to the Shapes .pia-cable — hairline + mounting brackets + one drawn
   offset-shadow, standing proud of the wall) across the beat stations. A gold PLAYHEAD
   carriage rides the wire to the current beat (beatTick); the wire squeaks on the
   bar's downbeat (the long slide back). Rhythm and Shapes are now one family. ── */
/* r6p91c (Scott's sketch: @————{ ◦ ◦ ◦ ◦ }————@) — ONE continuous wire full-width with
   round eyelet terminals; a central windowed PANEL; the ball is the SOLE object riding
   the wire, glimpsed through whichever window it's passing; empty windows show only the
   bare wire. */
body[data-plate-lens="II"] .plate-rhythm-ruler{
  display:flex !important;            /* revive (overrides the old benched state) */
  position:relative; align-items:center; justify-content:center;
  margin:20px auto 2px;
  padding:14px 30px;
  border-bottom:none;
  box-sizing:border-box;
  /* width is set to the fretboard width by _syncRhythmRuler so the wire system spans
     the same as Shapes; the beats cluster centre, the wire runs out to the terminals. */
}
body[data-plate-lens="II"] .plate-rhythm-ruler .prr-gap{ opacity:0; }
body[data-plate-lens="II"] .plate-rhythm-ruler .prr-label{ display:none; }
/* THE WIRE — one continuous hairline run (full width; left/width/top set by
   _syncRhythmRuler), with @ ROUND EYELET terminals at each end (the wire ties off) and
   one drawn offset-shadow so it stands proud. */
.plate-rhythm-ruler .prr-cable{
  position:absolute; height:0; z-index:1;
  border-top:1.25px solid var(--gold2,#6a4010); opacity:0.7;
  filter:drop-shadow(2px 2px 0 var(--shadow-ink,#b3b896));
}
/* r6p95-sib — END BRACKETS (match Shapes; Scott: the little brackets read more fun + keep
   the FIXED ends square so the round travellers clearly read as the movers). */
.plate-rhythm-ruler .prr-cable::before,
.plate-rhythm-ruler .prr-cable::after{
  content:""; position:absolute; top:-4px; width:6px; height:8px;
  border-radius:1.5px; box-sizing:border-box;
  border:1px solid var(--gold2,#6a4010); background:var(--vellum2,#dcd9b8);
}
.plate-rhythm-ruler .prr-cable::before{ left:-5px; }
.plate-rhythm-ruler .prr-cable::after{ right:-5px; }
/* NO station dots — an empty window shows only the bare wire (Scott). Keep the mark in
   the layout but INVISIBLE so the playhead can still measure each beat's position. */
body[data-plate-lens="II"] .plate-rhythm-ruler .prr-mark{ visibility:hidden; }
/* the beat NUMBERS sit above the windows, above the panel */
body[data-plate-lens="II"] .plate-rhythm-ruler .prr-tick{ z-index:4; }
/* r6p95-sym — lift the beat NUMBERS clear of the panel's top edge (Scott: they sat over the box, hard to read) */
body[data-plate-lens="II"] .plate-rhythm-ruler .prr-glyph{ position:relative; transform:translateY(-9px); }
/* THE PANEL — the central { } faceplate with N windows cut at the beats. Opaque vellum
   with transparent slot-openings (gradient + position set by _syncRhythmRuler); a framed
   bracket + inset recess so you read THROUGH it to the wire+ball behind + offset-shadow. */
.plate-rhythm-ruler .prr-panel{
  position:absolute; height:26px; z-index:3; pointer-events:none;
  border:1.25px solid var(--gold2,#6a4010); border-radius:3px;
  box-shadow:inset 0 2px 3px rgba(106,64,16,0.28);
  filter:drop-shadow(2px 2px 0 var(--shadow-ink,#b3b896));
}
/* THE BALL — the sole object on the wire; rides BEHIND the panel (z-index below it),
   glimpsed through whichever window it's passing. Present only while playing. */
.plate-rhythm-ruler .prr-playhead{
  position:absolute; left:0; top:50%; transform:translate(-50%,-50%);
  width:13px; height:13px; border-radius:50%;
  border:1.5px solid var(--gold,#9a6420);
  background:radial-gradient(circle at 40% 35%, var(--gold3,#c8902c), var(--gold,#9a6420) 70%);
  box-shadow:none;                    /* r6p91d — asleep in its seat: no glow at rest */
  z-index:2; pointer-events:none; opacity:0;
  transition:left .14s cubic-bezier(.34,1.1,.5,1), top .14s ease, opacity .25s ease;
}
/* r6p91d — THE BALL'S LIFE. It LIVES in the left eyelet (visible, parked, asleep);
   _prrBallEnter rolls it out across the count-in to land on beat 1; it runs the
   windows; _prrBallHome rolls it back to the seat on stop. So it comes out to play
   and goes home to rest — the eyelet is its seat, the count-in is its entrance. */
body[data-plate-lens="II"] .plate-rhythm-ruler .prr-playhead{ opacity:1; }   /* visible, parked in the eyelet */
body[data-playing="1"][data-plate-lens="II"] .plate-rhythm-ruler .prr-playhead{
  box-shadow:0 0 6px rgba(200,144,44,0.55);   /* wakes for the music */
}

/* ── r6p92 — COUNT-IN PIP-GATE (lens panel, Julin-led: a count-in is a pulse + an
   arrival, not a blocking number). A small vellum chip at the top of the fretboard
   frame; N brass pips EMPTY one per beat, the last clearing on the downbeat — the
   fretboard (the chord you're about to play) stays fully visible behind it. On Rhythm
   the ball's roll-out resolves on the same downbeat. Replaces the off-brand walnut box. */
.ci-gate{
  margin-top:8px; display:flex; align-items:center; gap:9px;
  padding:4px 11px;
  background:var(--vellum,#efe7cf);
  border:1px solid var(--gold2,#6a4010); border-radius:3px;
  box-shadow:2px 2px 0 var(--shadow-ink,#b3b896);
}
.ci-label{
  font-family:'Space Mono',monospace; font-size:8px; font-weight:700;
  letter-spacing:1.8px; text-transform:uppercase; color:var(--gold-ink,#7a4a12);
  white-space:nowrap;
}
.ci-pips{ display:flex; align-items:center; gap:6px; }
.ci-pip{
  width:10px; height:10px; border-radius:50%; box-sizing:border-box;
  border:1.25px solid var(--gold2,#6a4010);
  background:radial-gradient(circle at 40% 35%, var(--gold3,#c8902c), var(--gold,#9a6420) 70%);
  transition:background .14s ease, opacity .14s ease, transform .12s cubic-bezier(.34,1.4,.5,1);
}
.ci-pip.spent{ background:transparent; opacity:0.4; }   /* emptied — a hollow ring left behind */
.ci-pip.firing{ transform:scale(1.4); }                  /* the clack as it clears */

/* ── r6p93 — THE COLOR RIBBON (the tune in harmonic colour). Circle of fifths unrolled,
   HOME dead-centre, the colour chord (the b7/bVII you HANG on) glowing at the flat edge;
   stations spaced by real fifths-distance. The traveller rides to the sounding chord and
   DWELLS on the colour. Same wire/eyelet vocabulary as the other lenses. Lens III only;
   placed in the band by _syncColorRibbon. ── */
.plate-color-ribbon{ display:none; }
body[data-plate-lens="III"] .plate-color-ribbon{
  display:block; position:relative; margin:22px auto 2px; height:60px; box-sizing:border-box;
}
/* the wire — same cable run as the others: hairline + offset-shadow + eyelet terminals */
.plate-color-ribbon .pcr-wire{
  position:absolute; top:30px; height:0; z-index:1;
  border-top:1.25px solid var(--gold2,#6a4010); opacity:0.6;
  filter:drop-shadow(2px 2px 0 var(--shadow-ink,#b3b896));
}
/* r6p95-sib — END BRACKETS, matching Shapes + Rhythm (square fixed ends; the round sphere is the mover) */
.plate-color-ribbon .pcr-wire::before,
.plate-color-ribbon .pcr-wire::after{
  content:""; position:absolute; top:-4px; width:6px; height:8px; border-radius:1.5px;
  box-sizing:border-box; border:1px solid var(--gold2,#6a4010); background:var(--vellum2,#dcd9b8);
}
.plate-color-ribbon .pcr-wire::before{ left:-5px; }
.plate-color-ribbon .pcr-wire::after{ right:-5px; }
/* a station = a chord plotted at its fifths-distance (left set by _syncColorRibbon) */
.plate-color-ribbon .pcr-station{ position:absolute; top:0; width:0; z-index:2; }
.plate-color-ribbon .pcr-roman{
  position:absolute; left:0; top:-2px; transform:translateX(-50%); white-space:nowrap;
  font-family:'Playfair Display',serif; font-style:italic; font-size:17px; color:var(--gold-ink,#7a4a12);
}
/* r6p95-roman — the home dock is double-framed (sits taller); lift its numeral a touch more
   so the thin italic "I" clears the frame and doesn't get swallowed (Scott). */
.plate-color-ribbon .pcr-station.is-home .pcr-roman{ top:-5px; }
/* r6p93d — a station is a real SEATED DOCK with DIMENSION (Scott: "figure out how you'd
   build it" — a little box the ball physically sits in). Recessed interior (inset
   shadow) + a bottom lip (inset highlight) + a drawn offset-shadow so it stands proud
   of the wall. An empty dock reads as an empty slot; the ball nests INTO it. */
.plate-color-ribbon .pcr-mark{
  position:absolute; left:0; top:30px; transform:translate(-50%,-50%);
  width:21px; height:18px; border-radius:3px; box-sizing:border-box;
  background:var(--vellum,#efe7cf);
  border:1px solid var(--gold2,#6a4010);
  box-shadow:
    inset 0 2px 3px rgba(106,64,16,0.30),       /* the recess — a real slot carved in */
    inset 0 -1px 0 rgba(255,255,255,0.5),         /* the lower lip catches light */
    1.5px 1.5px 0 var(--shadow-ink,#b3b896);      /* the dock stands proud of the wall */
}
.plate-color-ribbon .pcr-root{
  position:absolute; left:0; top:46px; transform:translateX(-50%); white-space:nowrap;
  font-family:'Space Mono',monospace; font-size:10.5px; letter-spacing:1px; font-weight:700;
  text-transform:uppercase; color:var(--gold-ink,#7a4a12);
}
/* HOME — the tonic dock: a deeper, DOUBLE-FRAMED seat (keeps the recess + lip), so it
   reads as home base even when the ball has left it. */
.plate-color-ribbon .pcr-station.is-home .pcr-mark{
  box-shadow:
    inset 0 2px 3px rgba(106,64,16,0.34),
    inset 0 -1px 0 rgba(255,255,255,0.5),
    0 0 0 2px var(--vellum,#efe7cf), 0 0 0 3px var(--gold2,#6a4010),   /* the outer home frame */
    1.5px 1.5px 0 var(--shadow-ink,#b3b896);
}
/* the COLOUR dock (the b7 you hang on) — a seat that GLOWS, marking WHERE the colour
   lives on the map. Even empty it glows; it's a location, not a second ball. */
.plate-color-ribbon .pcr-station.is-color .pcr-mark{
  border-color:var(--gold,#9a6420);
  box-shadow:
    inset 0 2px 3px rgba(106,64,16,0.30),
    inset 0 -1px 0 rgba(255,255,255,0.5),
    1.5px 1.5px 0 var(--shadow-ink,#b3b896),
    0 0 8px rgba(200,144,44,0.6);                  /* the colour glow */
}
.plate-color-ribbon .pcr-station.is-color .pcr-roman{ color:var(--gold,#9a6420); }
/* the traveller — the ONE raised SPHERE; it casts a small drop-shadow so it reads as
   sitting ABOVE the wall, nested into whichever dock it's in. Rides to the sounding
   chord (slower, dwelling glide than the beat ball). */
.plate-color-ribbon .pcr-traveler{
  position:absolute; left:0; top:30px; transform:translate(-50%,-50%);
  width:14px; height:14px; border-radius:50%; z-index:3; pointer-events:none;
  background:radial-gradient(circle at 37% 31%, #e8c573 0%, var(--gold,#9a6420) 58%, #6a4010 100%);
  box-shadow:0 2px 2.5px rgba(58,36,18,0.5); opacity:0;
  transition:left .34s cubic-bezier(.34,1.05,.5,1), box-shadow .3s ease, opacity .3s ease;
}
body[data-plate-lens="III"] .plate-color-ribbon .pcr-traveler{ opacity:1; }   /* parked at home at rest */
/* HANGING ON THE SEVEN — the traveller glows while it sits in the colour dock */
.plate-color-ribbon.on-color .pcr-traveler{ box-shadow:0 2px 2.5px rgba(58,36,18,0.5), 0 0 12px rgba(200,144,44,0.9); }
/* Rhythm caption in the FIG header — only visible on PL. II */
.pff-rhythm-caption{
  display:none;
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:2px; color:var(--gold); text-transform:uppercase;
  white-space:nowrap;
}
body[data-plate-lens="II"] .pff-rhythm-caption{ display:inline; }
/* Hide Scale 1:1 on PL. II (frame reads differently there) */
body[data-plate-lens="II"] .pff-scale{ display:none; }

/* ── PLATE A · sidebar metaphors (Phase 4) ─────────────────────
   Three live cartouches on the left: key dial (circle of fifths),
   position ladder, capo clamp. Width 150px per var-a-plate.jsx.
   Sync functions in src/v2-modes.js: _buildKeyDial (one-time paint),
   _syncKeyDial / _syncPositionLadder / _syncCapoClamp (called from
   updatePedalStrip). Follow-up commit adds I/IV/V brass arcs +
   rotation-on-key-change (Craft ambition §1). */
.plate-sidebar{
  /* R4 Q2 — sidebar widens 150→180 to fix the PL. III FIG. a Mode-strip
     clip (Addendum §A) and to mirror the new .plate-right-rail at 180.
     R5.23 — on PL. II the sidebar grows to 260px so the rhythm cartouches
     (pendulum / telegraph / pattern / swing seesaw / bass / drums) get the
     room they earned in R5.19 (visual weight) + R5.22 (delight pass).
     Fretboard region (flex:1) shrinks to compensate — exactly Scott's call:
     "shrink the fretboards and have on the rythem tab more space for these
     diagrams to be cool and hands on." */
  width:180px; flex-shrink:0;
  /* r6p96 (2026-06-03, lens panel) — flex-start is the base / OPEN-drawer default:
     a tall EXPANDED drawer (.is-open) must anchor to the top so its head never
     clips. The CLOSED rail instead CENTERS in the upper stage — see the
     `.plate-sidebar:not(.is-open)` rule just below. (Earlier this session
     flex-start was the closed behaviour too; Scott flagged the rail floated high
     while the exhibit centred lower — "not settled" — so the closed rail now
     pairs with the figure it controls.) */
  align-self:flex-start;
  display:flex; flex-direction:column;
  gap:10px; padding:10px 12px 12px;
  background:linear-gradient(180deg, rgba(214,220,190,0.22) 0%, rgba(214,220,190,0) 60%);
  /* R5.30 — was overflow:hidden, which clipped PL. III's lower sections
     (Voice cartouche / Harmony stack / R5.25 Position+Capo) on
     short-viewport screens. For beta: never hide content from testers
     because of screen size. overflow-y:auto only paints a scrollbar
     when content overflows — PL. I never shows one, PL. II rarely,
     PL. III on shorter screens does. Smaller scrollbar styling below. */
  overflow-y:auto;
  overflow-x:hidden;
  transition:width 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
  scrollbar-width:thin;
  scrollbar-color:var(--gold-dim) transparent;
  /* r6p96 (2026-06-03) — removed the R5.46 bottom-fade mask. It was a
     "more below" scroll hint, but with the task-#23 fit-to-viewport scaling
     the whole app to fit the screen, the sidebar no longer overflows in
     normal use — so the fade could only MISFIRE, dissolving the drawer's
     last item + its bottom border into the background ("fading into space",
     Scott). The thin styled scrollbar remains as the cue on genuine overflow. */
}
/* r6p96 (2026-06-03, lens panel) — CLOSED rail centres in the UPPER STAGE
   (canvas-top → pinned chip strip), the same field the exhibit centres in, so
   the action rail reads as PAIRED with the figure it controls (Left = action),
   not hung from the top edge. align-self:center + margin-bottom pulls the
   centring datum UP off the chip zone and adds a small optical nudge (the eye
   reads true-centre as low — the picture-hanging rule): cy = canvasCentre −
   margin/2, so 250px lands the rail's centre on the fretboard's centre on
   PL. II / III. The centre is INDEPENDENT of chip-strip height (it's a function
   of the row height + margin only), so it stays put when a progression wraps to
   two rows — no jump when you riffle the tabs. Scoped to :not(.is-open) so a
   tall expanded drawer keeps its flex-start top-anchor (above). Lens panel
   unanimous: FLW datum/pairing · Tufte fixed-frame · Norman/Resnick stable map. */
.plate-sidebar:not(.is-open){
  align-self:center;
  margin-bottom:250px;
}
.plate-sidebar::-webkit-scrollbar{ width:6px; }
.plate-sidebar::-webkit-scrollbar-track{ background:transparent; }
.plate-sidebar::-webkit-scrollbar-thumb{
  background:var(--gold-dim); border-radius:3px;
}
.plate-sidebar::-webkit-scrollbar-thumb:hover{ background:var(--gold2); }
body[data-plate-lens="II"] .plate-sidebar{
  width:260px;
  /* R6.19 — gap 24→8 (was R5.23). PL. II carries 5 cartouches; the
     R5.23 generous gap (4 × 24 = 96px just in spacing) was the main
     reason BASS clipped its header below the sidebar fold. Tighter
     vertical gap, same horizontal breathing room — the diagrams
     stay workshop-scale per R5.23 intent, but the strip reads as a
     stack instead of needing scroll. */
  gap:8px;
}
/* R6.41-B.4 — PL. II PATTERN + SWING go edge-to-edge per Claude Design
   rev. 5 G4. Old max-width:240px cap centered the SVGs in a narrow well;
   new spec is full inner width of the cartouche (14px sides come from the
   .ps-sec body padding, no further inset). The diagrammatic primitives —
   stairstep pattern, seesaw plank — strengthen at full width: the
   metaphor reads as a literal measure, not a precious thumbnail. Bass +
   drums were already edge-to-edge (width:100%) and stay that way. */
body[data-plate-lens="II"] .ps-pattern-notation,
body[data-plate-lens="II"] .ps-swing-visual,
body[data-plate-lens="II"] .ps-en-bass-svg,
body[data-plate-lens="II"] .ps-en-drum-svg{
  width:100%; max-width:none;
}
/* R6.41-B.4 — PL. II TEMPO recompose per Claude Design rev. 4.
   Three elements previously sat on three different visual baselines
   (TAP knob top, pendulum top, voice strip bottom) so the cartouche
   read as "stapled." New composition: ONE shared horizontal beat-clock
   axis under a diagrammatic row. ROW 1 above the clock: TAP tile left
   (telegraph + BPM number + 4/4 inside one vellum cell) and pendulum
   centered to its right. ROW 2: the beat-clock ruler, spanning the full
   inner width — long ticks + 1·2·3·4 numerals at downbeats, short ticks
   at and-beats between, pulse on active downbeat during play. The
   clock IS the divider between diagrammatic (above) and interactive
   (below). ROW 3: voice strip (off · woodblock · rim · click) as
   segmented-row primitive. Total: TAP/pendulum/clock/voice all hang
   from the same horizontal axis. Cartouche reads as one machine. */
body[data-plate-lens="II"] .ps-tempo-wrap{
  width:100%;
  display:flex; flex-direction:column;
  align-items:center;          /* r6p43 — pendulum centred in the cartouche */
  gap:14px;
  margin-left:0;
}
/* r6p43-tempo-recompose — pendulum is the centerpiece, sized large so
   it doesn't read as a sidebar after-thought. Wraps the SVG so the
   parent flex-column can centre it without affecting the SVG's intrinsic
   width. */
body[data-plate-lens="II"] .ps-tempo-pendulum-wrap{
  display:flex;
  align-items:center;
  justify-content:center;
  width:100%;
}
body[data-plate-lens="II"] .ps-tempo-pendulum-wrap .ps-pendulum{
  display:block;
}
/* Control row — compact telegraph (TAP) + BPM readout + time-sig in a
   single horizontal strip, centred under the pendulum. Replaces the
   stale .ps-tempo-tap-tile + .ps-tempo-diag layout that referenced
   non-existent wrappers. */
body[data-plate-lens="II"] .ps-tempo-control-row{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:18px;
  width:100%;
}
/* r6p43-tempo-bell — bell-button affordance. Hover lifts the dome
   slightly (filter brightness) so the button feels alive. Tap
   compresses the dome (.is-pressed flips for 120ms via _telegraphFlash
   reusing the same handler). */
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-bell{
  display:block;
  cursor:pointer;
  outline:none;
  filter:drop-shadow(0 2px 0 rgba(0,0,0,0.18));
  transition:filter .15s ease;
  flex:0 0 56px;
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-bell:hover{
  filter:drop-shadow(0 2px 0 rgba(0,0,0,0.18)) brightness(1.08);
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-bell:focus-visible{
  outline:2px solid var(--gold); outline-offset:2px; border-radius:50%;
}
/* Press feedback — dome compresses inward (top-down view) on tap.
   transform-origin is the dome centre so it scales evenly. */
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-bell.pressed .ps-bell-dome{
  transform:scale(0.92);
  transform-origin:28px 28px;
  transition:transform 80ms cubic-bezier(0.3, 0.7, 0.4, 1);
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-bell-dome{
  transition:transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
  transform-origin:28px 28px;
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-readout{
  display:flex; align-items:baseline; justify-content:center; gap:4px;
  /* Fixed-width so BPM weight ("80" vs "116" vs "208") doesn't push
     the bell or the sig pill left/right. Min-width covers the widest
     three-digit BPM at 32px Playfair plus the " bpm" unit. */
  min-width:118px;
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-bpm{
  font-family:'Playfair Display', serif;
  font-weight:700;
  font-size:32px;                /* was 22px in the old tap-tile rule */
  color:var(--text);
  line-height:1;
  letter-spacing:0.5px;
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-unit{
  font-family:'Space Mono', monospace;
  font-style:italic;
  font-size:12px;
  letter-spacing:0.5px;
  color:var(--dim2);
  text-transform:lowercase;
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-sig{
  font-family:'Space Mono', monospace;
  font-size:11px;
  letter-spacing:1.4px;
  color:var(--dim2);
  cursor:pointer;
  padding:3px 6px;
  border:1px solid var(--gold2);
  border-radius:1px;
  transition:color .15s, border-color .15s;
}
body[data-plate-lens="II"] .ps-tempo-control-row .ps-tempo-sig:hover{
  color:var(--gold);
  border-color:var(--gold);
}
body[data-plate-lens="II"] .ps-tempo-diag{
  display:flex; align-items:flex-start; justify-content:flex-start;
  gap:14px;
}
body[data-plate-lens="II"] .ps-tempo-tap-tile{
  flex:0 0 auto;
  display:flex; flex-direction:column; align-items:center;
  gap:2px;
  padding:6px 8px 8px;
  background:var(--vellum2, #cad1b0);
  border:1px solid var(--gold-dim);
  border-radius:2px;
  width:96px;
}
body[data-plate-lens="II"] .ps-tempo-tap-tile .ps-telegraph{
  width:80px; height:43px; display:block;
}
body[data-plate-lens="II"] .ps-tempo-tap-tile .ps-tempo-readout{
  display:flex; align-items:baseline; gap:4px;
  margin-top:2px;
}
body[data-plate-lens="II"] .ps-tempo-tap-tile .ps-tempo-bpm{
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:22px; color:var(--text); line-height:1;
}
body[data-plate-lens="II"] .ps-tempo-tap-tile .ps-tempo-unit{
  font-family:'Space Mono',monospace; font-style:italic;
  font-size:11px; letter-spacing:0.5px;
  color:var(--dim2); text-transform:lowercase;
}
body[data-plate-lens="II"] .ps-tempo-tap-tile .ps-tempo-sig{
  font-family:'Space Mono',monospace; font-style:normal;
  font-size:8px; letter-spacing:1.4px;
  color:var(--dim2); margin-top:0; padding:0;
}
body[data-plate-lens="II"] .ps-tempo-diag .ps-pendulum{
  flex:1 1 auto; min-width:0;
  width:auto; height:92px;
  align-self:flex-start;
}
body[data-plate-lens="II"] .ps-tempo-beat-clock{
  display:block;
  width:100%; height:18px;
}
body[data-plate-lens="II"] .ps-tempo-mvoice{
  align-self:center;
}
body[data-plate-lens="II"] .ps-pattern-wrap,
body[data-plate-lens="II"] .ps-swing-wrap,
body[data-plate-lens="II"] .ps-ensemble-wrap{
  width:100%;
}

/* ── PLATE RIGHT RAIL ────────────────────────────────────────────
   R4 Q1 (a) — replaces the decorative rail-E. At rest: patent stamp
   + live-state cartouche (tune name, K/P/C summary, current chord,
   transport state). When a pedal is tapped: re-renders with that
   pedal's detail panel (Phase 3 wires the swap; Phase 2 just stands
   the container up at 180px with at-rest content). */
.plate-right-rail{
  width:180px; flex-shrink:0;
  display:flex; flex-direction:column;
  gap:18px; padding:14px 12px 16px;
  background:linear-gradient(180deg, rgba(214,220,190,0.18) 0%, rgba(214,220,190,0) 65%);
  overflow:hidden;
  font-family:'Space Mono',monospace;
  /* R4.7 Q-A — width pulses 180↔240↔300 by state. Shared 240ms
     cubic-bezier(0.2, 0.8, 0.2, 1) with the rest of the figure's
     choreographed motion (R4.5). Phase 3d will add the canvas /
     chord-card / fretboard reflow on top. */
  transition: width 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
/* R4.8 Scott's "let them reflow" reframe (2026-05-01) — the rail
   honors the pedal's natural footprint instead of forcing pedals
   into a fixed width. Each pedal skin defines its own min-width
   in content/skins/board.js (currently uniform 300, but the rail
   accommodates whatever the truth turns out to be per pedal).

   Two states stay numeric on purpose:
     - rest (180): the at-rest stamp + cartouche, designed for 180
     - fx-chooser (180): the 5-card stack, designed for 156 inner
   Two states reflow:
     - pedal-active: width follows the pedal's intrinsic footprint
     - fx-detail: width follows the FX card's intrinsic footprint
   Sane bounds keep the rail from collapsing or eating the canvas. */
.plate-right-rail.is-pedal-active,
.plate-right-rail.is-fx-detail-active {
  width: max-content;
  min-width: 280px;
  max-width: min(420px, 38vw);
}
.plate-right-rail.is-fx-chooser-active{ width:180px; } /* chooser stays 180; designed for the stack */
@media (prefers-reduced-motion: reduce) {
  .plate-right-rail{ transition:none; }
}

/* R4.8 — let pedal skins keep their natural padding + min-width.
   Earlier override (min-width:0 !important; max-width:100%) was
   compressing pedals into the old 240 cage. Now the rail accommodates;
   skins render at their truth. */
.plate-right-rail .pb-pedal{
  border-radius:1px;
}

/* R4.5 mitigations — Phase 3d rail-expansion choreography.
   When the rail expands from 180 → 240 (pedal active) or
   180 → 300 (fx detail), the canvas auto-shrinks via flex
   distribution (sidebar 180 + canvas-1fr + rail variable).
   PL. I chord cards have inline min-width:160 so the flex
   row doesn't overflow at the narrower canvas widths — the
   body.rail-* classes override:
       rail-pedal      canvas ~680 → cards 152 (was 160)
       rail-fx-detail  canvas ~620 → cards 138
   Per R4.5 mitigation #3: "cards narrow proportionally; row
   stays one row, no reflow." Transition uses the shared 240ms
   cubic-bezier to ride alongside the rail-width animation.
   Fretboard SVG re-renders via _setRailState → setFretCanvasWidth
   (R4.5 mitigation #2: condense, don't shift). */
/* R4.8b — chord cards stay one row (R4.5 mitigation #3 — condense,
   don't reflow). flex:1 + min-width:0 lets them split whatever canvas
   width is available without ever wrapping. Parent gets flex-wrap:
   nowrap to enforce. Floor of 0 means cards can shrink as far as the
   inner chart needs; the chord-chart SVG inside has its own intrinsic
   sizing that prevents collapse to nothing. */
#v2-shapes-cards{
  flex-wrap: nowrap !important;
}
#v2-shapes-cards > div{
  flex: 1 1 0;
  min-width: 0;
  transition: min-width 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
/* R6.16 — Chord cards step back to vellum2 register per Claude Design
   2026-05-08 punch-list #3: "Card bg → vellum2. Borders 0.5px gold2 @
   0.4. Mini-fretboard ink to 0.7. Cards become a reference frieze; the
   dial wins focal hierarchy back. (FLW: restraint over size.)" The
   chord-card inline cssText (set in v2RenderShapesOverlay) carries the
   pre-Plate-A dark walnut bg + heavy border. Overriding with !important
   here keeps the JS path unchanged but pulls the surface into the
   workshop register so PL. I reads as dial-focal + cards-as-frieze. */
#v2-shapes-cards > div{
  background:rgba(184,190,160,0.45) !important;
  border:0.5px solid rgba(106,64,16,0.40) !important;
  border-radius:0 !important;
  box-shadow:none !important;
}
#v2-shapes-cards > div svg{
  opacity:0.7;
  transition:opacity 240ms ease;
}
#v2-shapes-cards > div:hover{
  background:rgba(214,220,190,0.85) !important;
  border-color:rgba(106,64,16,0.6) !important;
}
#v2-shapes-cards > div:hover svg{ opacity:1; }
#v2-shapes-cards > div[data-active="1"]{
  background:var(--ivory) !important;
  border-color:var(--gold) !important;
}
#v2-shapes-cards > div[data-active="1"] svg{ opacity:1; }
@media (prefers-reduced-motion: reduce){
  #v2-shapes-cards > div{ transition:none; }
}

/* R4.7 Q-B — FX chooser in the rail. Vertical 5-card stack at
   180px; existing #fx-panel content lifts into .fx-rail-chooser
   inside the rail's .prr-detail. Cards collapse from the 2x2 grid
   to a single column; figures slim down to fit 156px (180 - 24
   padding). */
.plate-right-rail .fx-rail-chooser{
  display:flex; flex-direction:column; gap:10px;
}
.plate-right-rail .fx-rail-grid{
  display:flex; flex-direction:column; gap:8px;
}
.plate-right-rail .fx-rail-grid .fx-card{
  width:100%; min-width:0; max-width:100%;
  padding:8px 10px; text-align:left;
  background:var(--vellum); border:1px solid var(--gold2); border-radius:1px;
  cursor:pointer; transition:border-color 120ms, background 120ms, box-shadow 240ms;
  position:relative;
  display:flex; flex-direction:column; gap:4px;
  font-family:'Space Mono',monospace;
}
.plate-right-rail .fx-rail-grid .fx-card:hover{
  border-color:var(--gold);
}
/* R4.7 Q-B — breadcrumb glow on the just-closed card. 1.5px
   --gold3 outline at 2400ms, no fill (so the chooser stays
   readable). Same brass vocabulary as the Q-C sidebar pulse. */
@keyframes fx-breadcrumb-fade {
  0%   { box-shadow: 0 0 0 1.5px var(--gold3); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.plate-right-rail .fx-rail-grid .fx-card.is-fx-breadcrumb{
  animation: fx-breadcrumb-fade 2400ms ease-out;
}
.plate-right-rail .fx-rail-grid .fx-card-head{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:8px;
}
.plate-right-rail .fx-rail-grid .fx-card-title{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--text); letter-spacing:0;
}
.plate-right-rail .fx-rail-grid .fx-card-val{
  font-size:9px; letter-spacing:var(--tracking-eng-meta);
  color:var(--gold); text-transform:uppercase;
  padding:2px 6px; border:1px solid var(--gold-dim);
  border-radius:1px; cursor:pointer;
}
.plate-right-rail .fx-rail-grid .fx-card-val:hover{
  background:var(--gold-dim); border-color:var(--gold);
}
.plate-right-rail .fx-rail-grid .fx-card-fig{
  display:flex; justify-content:center; padding:2px 0;
  opacity:0.85;
}
.plate-right-rail .fx-rail-grid .fx-card-fig svg{
  max-width:100%; height:auto;
}
.plate-right-rail .fx-rail-grid .fx-card-cap{
  font-size:8.5px; letter-spacing:var(--tracking-eng-meta);
  color:var(--dim2); text-transform:uppercase; line-height:1.4;
}
.plate-right-rail .fx-rail-more{
  display:flex; flex-wrap:wrap; gap:4px;
  padding-top:8px; border-top:1px solid var(--gold-dim);
}
.plate-right-rail .fx-rail-more .fx-more-lbl{
  font-size:8.5px; letter-spacing:var(--tracking-eng-meta);
  color:var(--dim2); text-transform:uppercase;
  flex-basis:100%;
}
.plate-right-rail .fx-rail-more .fx-more-btn{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:11px; color:var(--text);
  background:transparent; border:1px solid var(--gold-dim);
  border-radius:1px; padding:3px 8px; cursor:pointer;
  transition:border-color 120ms;
}
.plate-right-rail .fx-rail-more .fx-more-btn:hover{
  border-color:var(--gold); color:var(--gold);
}

/* R4.7 Q-B — FX detail. Rail expands to 300; existing pedal skin
   renders inside .fx-rail-detail with a "← FX" back affordance at
   the top so player returns to the chooser, not just closes. */
.plate-right-rail .fx-rail-detail{
  display:flex; flex-direction:column; gap:8px;
}
/* R4.8 — Voicings algorithm panel mount. The t3-voicing-panel's
   children get moved here when the FX > Voicings card opens; the
   panel's existing button styles (ctrl-section, ctrl-switch, ptog-*
   buttons) keep working unchanged. Just neutralizes the dark v1
   ctrl-surface background so the controls live on vellum. */
.plate-right-rail .voicings-rail-mount{
  display:flex; flex-direction:column; gap:14px;
  padding:8px 4px;
}
.plate-right-rail .voicings-rail-mount .ctrl-surface{
  background:transparent !important; border:none !important;
  padding:0 !important; flex-direction:column !important;
  align-items:stretch !important;
}
.plate-right-rail .voicings-rail-mount .ctrl-divider{ display:none !important; }
.plate-right-rail .voicings-rail-mount .ctrl-section{
  display:flex !important; flex-direction:column !important;
  gap:6px !important; padding:0 !important;
  border-right:none !important; min-width:0;
}
.plate-right-rail .voicings-rail-mount .ctrl-section-lbl{
  font-family:'Space Mono',monospace !important; font-size:9px !important;
  letter-spacing:var(--tracking-eng-label,2.4px) !important;
  color:var(--gold) !important; text-transform:uppercase !important;
  margin-bottom:0 !important; white-space:normal !important;
}
.plate-right-rail .voicings-rail-mount .ctrl-switch{
  display:flex !important; gap:4px !important; flex-wrap:wrap !important;
  background:transparent !important; border:none !important;
  border-radius:0 !important; overflow:visible !important;
}
.plate-right-rail .voicings-rail-mount .ctrl-switch-row,
.plate-right-rail .hcv-engine-mount .ctrl-switch-row,
.plate-right-rail .hcv-engine-mount .ctrl-switch{
  display:flex !important; gap:4px !important; flex-wrap:wrap !important;
  background:transparent !important;
}
.plate-right-rail .voicings-rail-mount .ctrl-switch button,
.plate-right-rail .hcv-engine-mount .ctrl-switch button{
  flex:1 1 auto !important; min-width:0 !important;
  background:var(--vellum) !important;
  border:1px solid var(--gold2) !important;
  border-radius:1px !important; padding:6px 8px !important;
  font-family:'Playfair Display',serif !important; font-style:italic !important;
  font-size:11px !important; color:var(--text) !important; cursor:pointer !important;
  transition:background 120ms, border-color 120ms, color 120ms !important;
  text-transform:none !important; letter-spacing:0 !important;
}
.plate-right-rail .voicings-rail-mount .ctrl-switch button:hover,
.plate-right-rail .hcv-engine-mount .ctrl-switch button:hover{
  background:var(--gold-dim) !important;
  border-color:var(--gold) !important;
  color:var(--text) !important;
}
.plate-right-rail .voicings-rail-mount .ctrl-switch button.on,
.plate-right-rail .hcv-engine-mount .ctrl-switch button.on{
  background:var(--gold-dim) !important;
  border-color:var(--gold) !important;
  color:var(--gold) !important;
}
.plate-right-rail .fx-voi-cap{
  font-family:'Space Mono',monospace; font-size:8.5px;
  letter-spacing:var(--tracking-eng-meta,1.6px);
  color:var(--dim2); text-transform:uppercase;
  padding:0 4px 6px; border-bottom:1px solid var(--gold-dim);
  margin-bottom:4px;
}
.plate-right-rail .fx-rail-back{
  background:transparent; border:1px solid var(--gold2);
  border-radius:1px; padding:4px 10px;
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:var(--tracking-eng-label); color:var(--text);
  text-transform:uppercase; cursor:pointer;
  align-self:flex-start;
  transition:background 120ms, color 120ms;
}
.plate-right-rail .fx-rail-back:hover{
  background:var(--gold-dim); color:var(--gold);
}
.plate-right-rail .prr-fig{ font-size:9.5px; letter-spacing:var(--tracking-eng-label); gap:8px; color:var(--gold); }
.plate-right-rail .prr-stamp{
  margin-top:auto; padding-top:14px;
  border-top:1px solid var(--gold2);
  font-size:8.5px; letter-spacing:var(--tracking-eng-meta);
  color:var(--dim2); text-transform:uppercase;
  text-align:center; line-height:1.55;
}
.plate-right-rail .prr-stamp .prr-build{ color:var(--gold); }
.plate-right-rail .prr-state{ display:flex; flex-direction:column; gap:6px; }
.plate-right-rail .prr-state .prr-tune{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--text); letter-spacing:var(--tracking-tune-name);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.plate-right-rail .prr-state .prr-row{
  font-size:9px; letter-spacing:var(--tracking-eng-meta);
  color:var(--dim2); text-transform:uppercase;
}
.plate-right-rail .prr-state .prr-chord{
  font-family:'Space Mono',monospace; font-weight:700;
  font-size:14px; letter-spacing:var(--tracking-chord-letter);
  color:var(--text);
}
.plate-right-rail .prr-state .prr-transport{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:11px; color:var(--gold); letter-spacing:0;
}

/* R4 Q1 (a) — content swap: when a pedal/cell is tapped, .prr-detail
   replaces the at-rest content (which Scott's clarification reduced
   to just the patent stamp); .prr-stamp stays anchored at the foot
   through both states. */
.plate-right-rail .prr-detail{
  display:flex; flex-direction:column; gap:14px;
}
.plate-right-rail .prr-detail-head{
  display:flex; align-items:center; justify-content:space-between;
  gap:8px;
}
.plate-right-rail .prr-detail-head .prr-fig{ flex:1; min-width:0; }
.plate-right-rail .prr-close{
  background:transparent; border:none; cursor:pointer;
  color:var(--dim2); font-size:14px; line-height:1; padding:2px 6px;
  border-radius:1px; transition:color .12s, background .12s;
}
.plate-right-rail .prr-close:hover{ color:var(--gold); background:var(--gold-dim); }
.plate-right-rail .prr-detail-body{ display:flex; flex-direction:column; gap:10px; }

/* R4.6 Q-A bonus — patent stamp dims when the rail is occupied by
   detail content, so it reads as the substrate the popover sits on,
   not as competing content. Returns to opacity 1 when rail empties.
   :has() selector keeps the dim purely a function of the DOM state
   that _renderRightRail / _clearRightRail already manage. */
.plate-right-rail .prr-stamp{ transition: opacity 240ms ease-out; }
.plate-right-rail:has(.prr-detail) .prr-stamp{ opacity:0.55; }

/* R4.6 Q-C — sidebar twin glow keyframe pulse. 800ms total with
   200/400/200 envelope, --gold3 brass (warmer than the resting
   --gold), 2px ring. Same vocabulary as the chord-card "active"
   pulse. R4's literal "200ms 1px" was below saccade threshold. */
@keyframes prr-glow-pulse {
  0%   { box-shadow: 0 0 0 0 transparent; }
  25%  { box-shadow: 0 0 0 2px var(--gold3); } /* fade-in 0–200ms (25% of 800ms) */
  75%  { box-shadow: 0 0 0 2px var(--gold3); } /* hold 200–600ms (50% of 800ms) */
  100% { box-shadow: 0 0 0 0 transparent;   } /* fade-out 600–800ms (25% of 800ms) */
}
.ps-sec.prr-glow{
  border-radius:1px;
  animation: prr-glow-pulse 800ms ease-in-out;
}

/* R6.37 — Fold primitive. .ps-sec carrying [data-fold] becomes a
   condensed/expand exhibit. At rest (closed): one-line brass header
   showing FIG. label + name + live state + chevron. Tap header →
   expands to full body. Mutual exclusion within .plate-sidebar — only
   one open at a time. Honors the Swiss-army-chassis blade pattern
   (memory: project_swiss_army_chassis.md). Solves the below-the-fold
   pile-up problem when multiple substantive exhibits stack on a
   sidebar. Cartouches WITHOUT [data-fold] keep their original
   always-visible behavior — opt-in only. */
.ps-sec[data-fold] {
  /* Trim down sidebar's flex gap when collapsed so headers stack
     tightly. The full padding/gap kicks back in via the body. */
  padding:0;
  overflow:hidden;
  /* R6.37b — keep open-state from being compressed by .plate-sidebar's
     max-height. The sidebar is display:flex; flex-direction:column with
     max-height:calc(100vh - 195px); without flex-shrink:0 the section
     shrinks to header height (overflow:hidden then clips the body, so
     the expand visually does nothing). Closed-state body is display:none
     and takes 0 space, so flex-shrink:0 is safe in both states. */
  flex-shrink:0;
}
.ps-sec[data-fold="closed"] .ps-sec-body { display:none; }
.ps-sec[data-fold="open"]   .ps-sec-body { display:block; }
.ps-sec-header{
  display:flex;
  align-items:baseline;
  gap:10px;
  padding:8px 12px 7px;
  cursor:pointer;
  user-select:none;
  background:transparent;
  border:none;
  border-bottom:1px solid rgba(154,100,32,0.18);
  width:100%;
  text-align:left;
  font-family:inherit;
  transition:background .15s, border-color .15s;
}
.ps-sec-header:hover{ background:rgba(154,100,32,0.06); }
.ps-sec-header:focus-visible{
  outline:2px solid var(--gold);
  outline-offset:-2px;
}
.ps-sec[data-fold="open"] .ps-sec-header{
  border-bottom-color:rgba(154,100,32,0.42);
}
.ps-sec-fig{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2px;
  color:var(--gold);
  text-transform:uppercase;
  flex:0 0 auto;
}
.ps-sec-name{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--gold);
  text-transform:uppercase;
  /* r6p85i (#9) — shrink-with-ellipsis safety net so a long title (e.g.
     "Position distance") can never overflow its box and overprint the
     right-aligned state label. Only triggers if genuinely out of room. */
  flex:0 1 auto;
  min-width:0;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
/* R6.40-A.6 — closed-fold header sub-gloss block per Claude Design rev. 4.
   Each fold cartouche header now carries a Playfair italic sub-gloss line
   under the FIG. label that names the axis in human terms (e.g.
   "chord shape family" under FIG. d.4 SHAPE). The block is a column-flex
   inside the row-flex header so glyph + value + caret remain on the
   right edge unchanged. Sub-gloss is the load-bearing addition for the
   closed-fold-header pass — Patent register, "axis at a glance." */
.ps-sec-fig-block{
  display:flex;
  flex-direction:column;
  gap:1px;
  flex:0 1 auto;
  min-width:0;
}
.ps-sec-fig-row{
  display:flex;
  align-items:baseline;
  gap:8px;
  min-width:0;   /* r6p85i (#9) — allow .ps-sec-name to ellipsize, not overflow */
}
.ps-sec-sub{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:10.5px;
  color:var(--dim2);
  opacity:0.82;
  letter-spacing:0;
  line-height:1.15;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
/* When the rail narrows below ~280px, the sub-gloss drops out first
   (per Design's truncation rule). Triggers at the breakpoint where
   sidebar columns compress; the FIG label + name + glyph + value
   must remain readable. */
@media (max-width: 320px){
  .ps-sec-sub{ display:none; }
}
/* E — A.6 slice 2: .ps-sec-fig-block inside .fig-banner (non-fold cartouches).
   The .fig-banner's align-items:center would vertically center the block; switch
   to flex-start so the sub-gloss drops below the FIG label row naturally. */
.fig-banner:has(.ps-sec-fig-block){
  align-items:flex-start;
}
/* Active italic-name above BASS + DRUMS segmented rows (Extension C).
   Playfair italic 14px 700 matches word-value class per G3 a.
   2026-05-14 — hidden. Both BASS and DRUMS are fold cartouches whose
   closed-fold headers already carry the active-value field; the italic
   here duplicates it when the fold is open (Patent register data-ink
   violation: one display per state). SWING is non-fold and legitimately
   needs its italic — its rules live elsewhere. */
.ps-bass-active-name,
.ps-drums-active-name{
  display:none;
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:14px;
  font-weight:700;
  color:var(--text);
  line-height:1.2;
  letter-spacing:0;
  align-self:center;
  margin-bottom:3px;
}
/* Reverb closed-fold header glyph slot. */
.ps-reverb-state-glyph{
  display:inline-flex;
  align-items:center;
  flex:0 0 auto;
  margin-right:4px;
  vertical-align:middle;
}
.ps-sec-state{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:11.5px;
  color:var(--dim2, #7a6450);
  flex:1 1 auto;
  text-align:right;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
  letter-spacing:0;
  opacity:0.85;
}
.ps-sec-chev{
  /* R6.40-A.6 — caret refined per Design rev. 4: 13px gold (was 10px
     dim2). The caret is the fold affordance — at the closed-fold
     header it's the only signifier that this strip is interactive,
     so bumping size + color earns its role on the unified anatomy. */
  font-family:'Space Mono', monospace;
  font-size:13px;
  color:var(--gold);
  transition:transform 0.22s ease;
  flex:0 0 auto;
  line-height:1;
}
.ps-sec[data-fold="open"] .ps-sec-chev{ transform:rotate(180deg); }
.ps-sec[data-fold] .ps-sec-body{
  padding:10px 12px 14px;
}

/* R4.6 Q-B + Q-D — K/P/C cell affordance, plate-aware:
   - PL. I: cell is tappable; the 800ms glow pulse on the sidebar
     twin is the discoverability instrument — taught by doing.
   - PL. II/III: cells are pure read-only display; cursor:default
     prevents the "looks tappable" tease. R4 Q4's hover-arrow
     proposal isn't shipped yet — its direction was geometrically
     ambiguous after Scott's right-rail clarification (sidebar
     lives up-left, not up-right) and R4.6 Q-D suggested the better
     instrument is the lens header itself (PL. I plate-tab hover →
     "shapes (key · pos · capo)"). Flagged for R5 alongside the
     brand mark — design call, not Code's. */
body:not([data-plate-lens="I"]) .ps-cell.tapable#ps-cell-key,
body:not([data-plate-lens="I"]) .ps-cell.tapable#ps-cell-position,
body:not([data-plate-lens="I"]) .ps-cell.tapable#ps-cell-capo{
  cursor:default;
}
.plate-sidebar .ps-sec{ display:flex; flex-direction:column; gap:10px; }
.plate-sidebar .ps-fig{ font-size:9.5px; letter-spacing:2.4px; gap:8px; }
.plate-sidebar .ps-fig-cap{ color:var(--gold); }

/* ── R6.37/R6.38 — REVERB EXHIBIT (Arc 4 Cluster 1) ────────────────
   The Patent diagram you play with. Wavefront SVG is the canvas;
   sliders modulate ring opacity / extent / thickness; presets morph
   the room outline. Ivory + brass palette; no fill colors that fight
   Plate A. Mounted on PL. III sidebar via fold primitive. */
.ps-reverb-sec[data-fold="open"] .ps-sec-body { padding-bottom:18px; }
.rvc-wave{
  display:block;
  width:100%;
  height:auto;
  max-height:140px;
  margin:6px 0 10px 0;
}
.rvc-presets{
  display:flex;
  gap:6px;
  margin:6px 0 14px 0;
}
.rvc-preset{
  flex:1 1 0;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:3px;
  padding:6px 4px 5px;
  background:rgba(184,190,160,0.40);
  border:0.5px solid rgba(106,64,16,0.32);
  border-right-width:0;
  cursor:pointer;
  color:var(--dim2, #7a6450);
  transition:background .15s, color .15s;
  position:relative;
}
.rvc-preset:first-child{ border-top-left-radius:1px; border-bottom-left-radius:1px; }
.rvc-preset:last-child{ border-right-width:0.5px; border-top-right-radius:1px; border-bottom-right-radius:1px; }
.rvc-preset:hover{
  background:rgba(214,220,190,0.80);
  color:var(--gold);
}
.rvc-preset.on{
  background:var(--ivory, #f4ecd2);
  color:var(--gold);
  border-color:rgba(106,64,16,0.55);
  z-index:1;
}
.rvc-preset.on::after{
  content:'';
  position:absolute;
  left:6px; right:6px; bottom:0;
  height:1.5px;
  background:var(--gold);
}
.rvc-preset-lbl{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:10.5px;
  line-height:1;
  letter-spacing:0;
}

.rvc-slider-stack{
  display:flex;
  flex-direction:column;
  gap:6px;
  margin-top:4px;
}
.rvc-slider-row{
  display:grid;
  grid-template-columns: 70px 1fr 50px;
  align-items:center;
  gap:8px;
}
.rvc-slider-lbl{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:2px;
  color:var(--gold);
  text-transform:uppercase;
}
.rvc-slider-val{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:0.5px;
  color:var(--gold);
  text-align:right;
}
.rvc-slider{
  appearance:none;
  -webkit-appearance:none;
  background:transparent;
  height:2px;
  border:none;
  border-top:1px solid rgba(154,100,32,0.55);
  margin:6px 0 2px;
}
.rvc-slider::-webkit-slider-thumb{
  appearance:none;
  -webkit-appearance:none;
  background:var(--gold);
  border:1px solid rgba(42,22,8,0.5);
  border-radius:1px;
  width:10px;
  height:14px;
  cursor:pointer;
  box-shadow:none;
}
.rvc-slider::-moz-range-thumb{
  background:var(--gold);
  border:1px solid rgba(42,22,8,0.5);
  border-radius:1px;
  width:10px;
  height:14px;
  cursor:pointer;
}

/* ── FIG. d — VOICINGS cartouche (R6.11 · 2026-05-08) ─────────────
   Permanent fourth exhibit on PL. I sidebar. K · P · C · V as the
   spine of "how the tune sits in the hand." Replaces the R5.98
   navy-band Voicings panel.

   The id="t3-voicing-panel" lives on this cartouche so the existing
   R5.98 _openHotcellVoicingsInRail() child-move keeps working on
   PL. II/III via the CHORD pedal-cell tap.

   Picker primitive (active=ivory+1.5px brass underline, inactive=
   vellum2+0.5px gold2 border) is the canonical selection vocabulary
   for the chassis — same vocabulary as act-tabs at top, Library
   tabs (R6.13+ #12), OFF/WOODBLOCK row on PL. II (R6.13+ #14). */

/* R6.40h — all five d.1–d.5 fold exhibits are live; legacy button rows
   are now redundant visually. Keep the panel in DOM (syncParamToggles
   finds ptog-vl/ptog-low/ptog-bal/ptog-high by ID), but hide everything
   the user would see. toggleTier3('voicing') is never called. */
.ps-voicings-sec{ gap:6px; background:transparent; border-bottom:none; animation:none; flex-shrink:1; }
.ps-voicings-sec .ps-fig{ display:none; }
.ps-voicings-sec .fig-d-rows{ display:none; }
.fig-d-marker{
  margin-left:auto;
  font-family:'Space Mono', monospace;
  font-size:10px;
  color:var(--gold);
  opacity:0.85;
  letter-spacing:0;
}
.fig-d-gloss{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:10.5px;
  line-height:1.2;
  color:var(--text);
  opacity:0.6;
  margin-top:-4px;
}
.fig-d-rows{
  display:flex;
  flex-direction:column;
  gap:0;
  margin-top:2px;
}
.fig-d-row{
  display:flex;
  flex-direction:column;
  gap:0;
  padding:2px 0 3px 0;
  border-top:1px solid rgba(154,100,32,0.30); /* brass hairline @ 0.3 */
}
.fig-d-row:first-child{ border-top:none; padding-top:2px; }
.fig-d-row-lbl{ display:flex; flex-direction:column; gap:0; line-height:1; }
.fig-d-row-name{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:2px;
  color:var(--gold);
  text-transform:uppercase;
  line-height:1.05;
}
.fig-d-row-helper{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:9px;
  line-height:1;
  color:var(--text);
  opacity:0.55;
  margin-top:0;
}

/* Picker primitive — replaces the legacy .ctrl-switch dark-band
   look. Active = ivory fill + 1.5px brass underline (not border).
   Inactive = vellum2 fill + 0.5px gold2 border @ 0.4. The same
   primitive will land on act-tabs / Library tabs / OFF-WOODBLOCK
   row in R6.13+ via punch-list items #12 + #14. */
.fig-d-picker{
  display:flex;
  flex-direction:row;
  flex-wrap:nowrap;
  gap:0;
  background:transparent;
  border:none;
  border-radius:0;
  overflow:visible;
}
.fig-d-picker button{
  flex:1 1 0;
  min-width:0;
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:10.5px;
  line-height:1.1;
  padding:3px 4px 4px 4px;
  background:rgba(184,190,160,0.55); /* vellum2 ≈ surf2 @ 0.55 */
  color:var(--text);
  border:0.5px solid rgba(106,64,16,0.40); /* gold2 @ 0.4 */
  border-right-width:0;
  cursor:pointer;
  text-align:center;
  position:relative;
  letter-spacing:0;
  transition:background .15s, color .15s;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.fig-d-picker button:last-child{ border-right-width:0.5px; }
.fig-d-picker button:hover{
  background:rgba(214,220,190,0.85);
  color:var(--gold);
}
.fig-d-picker button.on{
  background:var(--ivory);
  color:var(--text);
  font-style:italic;
  border-color:rgba(106,64,16,0.55);
  z-index:1;
}
.fig-d-picker button.on::after{
  content:'';
  position:absolute;
  left:6px; right:6px; bottom:0;
  height:1.5px;
  background:var(--gold);
}

/* Rail-mount overrides: when FIG. d's children get moved into
   .hcv-engine-mount on PL. II/III via R5.98 _openHotcellVoicings
   InRail(), neutralize the legacy .ctrl-switch overrides at
   line ~4646 that would otherwise repaint the buttons. */
.plate-right-rail .hcv-engine-mount .fig-d-picker{
  background:transparent !important;
  border:none !important;
}
.plate-right-rail .hcv-engine-mount .fig-d-picker button{
  background:rgba(184,190,160,0.55) !important;
  border:0.5px solid rgba(106,64,16,0.40) !important;
  border-right-width:0 !important;
  font-family:'Playfair Display', serif !important;
  font-style:italic !important;
  font-size:11.5px !important;
  color:var(--text) !important;
}
.plate-right-rail .hcv-engine-mount .fig-d-picker button:last-child{
  border-right-width:0.5px !important;
}
.plate-right-rail .hcv-engine-mount .fig-d-picker button.on{
  background:var(--ivory) !important;
  border-color:rgba(106,64,16,0.55) !important;
  color:var(--text) !important;
}

/* R6.11 — FIG. c Capo compressed for the four-cartouche spine.
   Per Design (D): "FIG. d displaces Capo to a single-row compact
   cell." Tighter section gap + smaller pill so all four feel
   equal-weight inside --rail-l: 180px. */
.plate-sidebar .ps-clamp-sec{ gap:6px; }
.plate-sidebar .ps-clamp-sec .ps-clamp-row{ align-items:center; gap:8px; }
/* Lens-specific sidebar sections: show only on the matching plate.
   Body starts with data-plate-lens="I" so PL. I sections show by
   default; the fallback rule that previously forced I to display
   always was the bug — other plates couldn't hide I sections. */
/* R5.25 — switched from `[data-lens="X"]` (exact match) to `[data-lens~="X"]`
   (whitespace-separated word match) so a section can declare visibility on
   multiple plates with `data-lens="I III"`. Position ladder + Capo clamp
   now appear on both PL. I (Shapes) and PL. III (Sound) — Scott's
   homecoming question "how to change capo or position on the melody tab"
   gets a real answer without duplicating DOM. */
.plate-sidebar .ps-sec[data-lens]{ display:none; }
body[data-plate-lens="I"]   .plate-sidebar .ps-sec[data-lens~="I"]  { display:flex; }
body[data-plate-lens="II"]  .plate-sidebar .ps-sec[data-lens~="II"] { display:flex; }
body[data-plate-lens="III"] .plate-sidebar .ps-sec[data-lens~="III"]{ display:flex; }

/* R5.25 — Shared utility sections (Position + Capo) hide their FIG banner
   on plates other than PL. I. On PL. I they're FIG. b/c — part of the
   patent-figure sequence. On PL. III they're just compact utility
   controls below the modal/harmony figures. Tighter top-margin on PL. III
   so they tuck under the Harmony stack rather than competing for figure
   space. */
body[data-plate-lens="III"] .ps-shared-utility .fig-banner{
  display:none;
}
body[data-plate-lens="III"] .ps-shared-utility{
  margin-top:8px;
  padding-top:10px;
  border-top:1px solid var(--gold-dim);
  opacity:0.92;
  /* Flex order pushes Position + Capo AFTER Scale/Voice/Harmony on
     PL. III. They live earlier in the DOM (under PL. I's lens-I block),
     but visually they belong at the bottom on Sound — a quiet utility
     foot below the modal/harmony figures. */
  order:10;
}
body[data-plate-lens="III"] .ps-shared-utility + .ps-shared-utility{
  border-top:none; padding-top:0; margin-top:6px;
}

/* Scale selector strip (v2-scale-strip) is now vestigial — modes
   live in the PL. III sidebar Mode cartouche. Strip buttons still
   exist for scale state sync (via data-scale) but are never shown. */
#v2-scale-strip{ display:none !important; }

/* Progression cards hide on PL. III Melody — when improvising,
   the scale is the focus; chord cards would compete. Current
   chord still visible via the pedal strip's Chord · in hand cell.
   !important beats the element's inline display:flex. */
body[data-plate-lens="III"] #play-prog-dots{ display:none !important; }

/* r6p91 — REVIVED. The ruler was hidden here because it sat ABOVE the fretboard
   (two beat displays, Scott). It's now relocated by _syncRhythmRuler into the naked
   band BELOW the fretboard — its proper home — and dressed as the rail-and-traveler
   (rhymes with the Shapes carriage). The placement problem that benched it is gone.
   Shown + styled in the r6p91 block further down. */

/* ── 7b: PL. I Shapes is card-focal ────────────────────────
   On Shapes, the chord cards ARE the content — each card is its
   own micro-fretboard. The big fretboard becomes redundant. Per
   Scott: "if you choose a song you see the charts, just them no
   fretboard." Bigger cards in a grid, centered; big fretboard
   hidden so the cards own the space.
   On PL. II (Rhythm) and PL. III (Melody) the fretboard stays —
   that's where playing / improvising happens. */
body[data-plate-lens="I"] .plate-fb-frame{ display:none; }

body[data-plate-lens="I"] .prog-card-row{
  display:grid;
  /* R5.45 — was minmax(340px, 1fr) which fit only 2 cols → 2 rows for 4
     chords → ~600px tall in a ~190px canvas (#sub-play). Cards bled
     above and below the visible plate; only chord-name labels showed,
     fingering diagrams were clipped. Smaller minmax fits 4 cards in a
     single row at default canvas widths; tunes with >4 unique chords
     wrap to a second row that the row-level overflow-clip can handle.
     R5.46 — width:100% forces grid to parent's width (was sizing to
     content and bleeding past viewport on narrower screens). Now
     auto-fit correctly drops columns when parent is too narrow. */
  width:100%;
  grid-template-columns:repeat(auto-fit, minmax(140px, 1fr));
  gap:14px; padding:8px 24px 12px;
  max-width:1500px; margin:0 auto;
  justify-content:center;
  align-content:start;
  /* Constrain to canvas — cards can no longer bleed past parent bounds.
     min-height:0 lets a flex/grid child shrink below content size.
     R5.46 — overflow:hidden→auto. At narrower viewports (e.g. 1024w),
     4 cards don't fit one row → grid wraps → wrapped row was clipped
     by overflow:hidden, so the V chord card was invisible. overflow:
     auto lets the wrapped rows scroll within the canvas — visible at
     any viewport, any chord count. */
  min-height:0;
  max-height:100%;
  overflow-y:auto;
  overflow-x:hidden;
}
body[data-plate-lens="I"] .prog-card{
  /* R5.46 — was min-width:340px (paired with R5.42's grid minmax(340,1fr)).
     R5.45 changed grid to minmax(160,1fr) for the 4-cards-in-1-row layout
     but left this min-width behind. At narrower viewports the 340px
     min-width forced cards bigger than their grid cell, blowing the row
     out horizontally and clipping cards 3 + 4 (incl. the V chord) off
     the right edge of the canvas. min-width:0 lets grid control sizing. */
  min-width:0;
  padding:16px 22px; gap:8px;
  display:flex; flex-direction:column;
  position:relative;
  /* A.9 — sage card bg, ivory paper inside the fretboard SVG. Was --ivory
     (#f0e2be) which matched the paper inside the SVG (same #f0e2be) —
     paper-on-paper = no contrast, two-tone look. The big fretboard sits
     on --bg sage (#c8cdb0) with ivory paper inside it (`<rect fill="#f0e2be">`
     in plUpdateDots) — sage-on-ivory is the contrast that makes paper
     read as MATERIAL. Switching card bg to --vellum (sage-tinted, between
     --bg and --vellum2) gives the same effect at the chord-card scale. */
  background:var(--vellum);
  border:1px solid var(--text);
  border-radius:0;
  box-shadow:none;
}
body[data-plate-lens="I"] .prog-card::before{ display:none; }
body[data-plate-lens="I"] .prog-card:hover{
  border-color:var(--text);
  background:color-mix(in srgb, var(--ivory) 92%, var(--gold));
}
body[data-plate-lens="I"] .prog-card.active{
  background:var(--ivory);
  border-color:var(--text);
  box-shadow:inset 0 3px 0 var(--gold);
}
body[data-plate-lens="I"] .prog-card .pc-head{
  margin-bottom:4px;
  display:flex; justify-content:space-between; align-items:baseline;
}
body[data-plate-lens="I"] .prog-card .pc-roman{
  font-family:'Playfair Display',serif; font-style:italic; font-weight:700;
  font-size:42px; line-height:1; color:var(--text);
}
body[data-plate-lens="I"] .prog-card .pc-name{
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:30px; line-height:1; color:var(--text);
}
body[data-plate-lens="I"] .prog-card .pc-mini{
  /* A.7d — was max-height:100px which crunched the fretboard. Bumped to 150
     so the diagram has room to breathe; dots inside (r=14 in viewBox 280)
     render ~25px displayed. */
  max-height:150px; width:100%; height:auto; flex:1 1 auto;
  display:block;
}

/* A.10 — paper-as-material frame around the mini fretboard SVG.
   Lifts the .plate-fb-frame recipe (walnut border + grain + inner-shadow
   vignette + gradient highlight) used by the big PL. II/III fretboard so
   the chord card's fretboard area reads as a DISTINCT PAPER PIECE laid
   on the sage card — not just a paper-toned rect floating in a card.
   Same recipe, scaled-down padding. */
body[data-plate-lens="I"] .prog-card .pc-mini-frame{
  margin-top:4px;
  padding:6px 8px 4px;
  border:2px solid #4a2410;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='4'/><feColorMatrix values='0 0 0 0 0.3  0 0 0 0 0.22  0 0 0 0 0.1  0 0 0 0.055 0'/></filter><rect width='120' height='120' filter='url(%23g)'/></svg>"),
    linear-gradient(180deg, rgba(214,220,190,0.18) 0%, rgba(214,220,190,0) 55%),
    var(--ivory);
  box-shadow:
    inset 0 0 14px rgba(26,12,4,0.22),
    inset 0 1px 0 rgba(240,226,190,0.08);
  position:relative;
}
body[data-plate-lens="I"] .prog-card .pc-mini text{ opacity:1 !important; }
body[data-plate-lens="I"] .prog-card .pc-spelling{
  display:flex; justify-content:space-between; align-items:baseline;
  padding:12px 2px 0;
  margin-top:8px;
  border-top:1px solid var(--text);
  font-family:'Space Mono',monospace;
  letter-spacing:1.5px;
}
body[data-plate-lens="I"] .prog-card .pc-notes{
  color:var(--text); font-weight:700; font-size:14px;
  display:inline-flex; gap:6px; align-items:baseline;
}
body[data-plate-lens="I"] .prog-card .pc-notes .pc-note{
  cursor:pointer; padding:2px 6px; border-radius:0;
  border:1px solid transparent;
  transition:background .12s, border-color .12s, color .12s;
  color:var(--text); font-weight:700; letter-spacing:1.5px;
}
body[data-plate-lens="I"] .prog-card .pc-notes .pc-note:hover,
body[data-plate-lens="I"] .prog-card .pc-notes .pc-note:focus-visible{
  background:var(--text); color:var(--ivory);
  border-color:var(--text);
  outline:none;
}
body[data-plate-lens="I"] .prog-card .pc-notes .pc-sep{
  color:var(--text); opacity:0.35; padding:0 1px;
}
body[data-plate-lens="I"] .prog-card .pc-quality{
  color:var(--text); opacity:0.82;
  font-size:11px; letter-spacing:2.4px; text-transform:uppercase; font-weight:700;
}

/* Dots + open rings — subtle brass halo on hover (visible on ivory) */
body[data-plate-lens="I"] .prog-card .pc-mini .pc-hit{
  transition:filter .15s;
}
body[data-plate-lens="I"] .prog-card .pc-mini .pc-hit:hover{
  filter:drop-shadow(0 0 3px rgba(154,100,32,0.7)) drop-shadow(0 0 6px rgba(154,100,32,0.35));
}
/* Cross-highlight flash — brass glow expanding from the dot.
   On ivory/walnut diagrams, drop-shadow in brass reads loud. */
@keyframes pc-flash-pulse{
  0%   { filter:none; }
  25%  { filter:drop-shadow(0 0 10px rgba(200,144,44,0.95)) drop-shadow(0 0 18px rgba(200,144,44,0.55)); }
  100% { filter:none; }
}
body[data-plate-lens="I"] .prog-card .pc-mini .pc-hit.pc-flash{
  animation:pc-flash-pulse 0.75s ease-out;
}
/* Live playback flash on the NEW chord cards (.pia-card) — the fingering glows
   as it's struck. Not lens-gated: the cards can show across tabs, and the flash
   only fires from the playback scheduler on the sounding card. */
.pia-card .pc-mini .pc-hit.pc-flash{ animation:pc-flash-pulse 0.75s ease-out; }
/* The SOUNDING chord card glows while it plays (chord-level light). */
.pia-card{ transition:box-shadow 140ms ease; }
.pia-card.pia-sounding{ box-shadow:0 0 0 1.5px var(--gold), 0 0 16px rgba(200,144,44,0.5); }
body[data-plate-lens="I"] .prog-card .pc-notes .pc-note.pc-flash{
  animation:pc-flash-pulse 0.75s ease-out;
  background:var(--gold);
  border-color:var(--gold);
  color:var(--ivory);
}

/* Card-level hover affordance — subtle tap-this cue. The whole card
   is still clickable (strums the chord); this visual just signals it. */
body[data-plate-lens="I"] .prog-card{ cursor:pointer; }
/* Hide spelling row on non-PL.I lenses (strip context) */
body:not([data-plate-lens="I"]) .prog-card .pc-spelling{ display:none; }
/* R6.48 — Patent Drawing alt-nav footer: bare ◀ 1/N ▶, no button chrome */
.pc-alts{display:flex;align-items:center;justify-content:center;gap:6px;border-top:1px solid var(--border2);padding:3px 0 2px;margin-top:2px;}
.pc-alt-prev,.pc-alt-next{background:none;border:none;padding:2px 6px;cursor:pointer;color:var(--dim2);font-size:10px;line-height:1;transition:color .1s;}
.pc-alt-prev:hover,.pc-alt-next:hover{color:var(--gold);}
.pc-alt-count{font-family:'Space Mono',monospace;font-size:9px;color:var(--dim2);letter-spacing:.5px;min-width:22px;text-align:center;}

/* Remove the peg-overlay on the left of the fretboard. The four
   circles read as "what are these?" instead of "tuning pegs."
   Body silhouette on the right stays — it's clearly an
   instrument shape, reads as body. Per Scott's observation. */
.pff-pegs{ display:none !important; }

/* Kill the below-fretboard beat-dots+BPM strip across all plates.
   On PL. I it was floating in empty space (fretboard hides).
   On PL. II it was hidden already. On PL. III it was visible
   mid-screen as "• • • •  − 112 +" — orphaned UI. The pedal strip's
   Tempo cell already carries BPM; the Transport cell carries bar
   progress. No need for a mid-screen strip. */
#play-beat-strip{ display:none !important; }

/* ── PL. III Melody — Mode cartouche (sidebar, Patent Drawing) ──
   r6p44-mode-chart-analog: engineered scale-comparison table, ink on
   vellum. Same Tufte small-multiples (9 modes × 7 degrees, the
   staircase of flatting reads as data) — re-cast in the studio's
   default 1D register, not a cabinet. Cart has NO frame: rows sit on
   the same vellum as everything else. Per-row borders + border-radius
   are stripped (those were the web-app vocabulary). Adjacent rows are
   separated by a single hairline rule (data-ink). The active row is
   marked Patent-style: a brass tick in the left margin + brass
   hairlines above and below. No fills, no bevels, no 3D. Same family
   as FIG. a Key-wheel (concentric strokes on vellum) and the pendulum
   (line-work mechanism on the page). */
.ps-mode-cart{
  width:100%;
  display:flex; flex-direction:column; gap:8px;
  padding:6px 0 2px;
}
.ps-mode-pills{
  display:flex; flex-direction:column; gap:0;
  margin-top:4px;
}
.ps-mode-pills .pmp{
  /* Engineered table row. No border, no radius, no card — just an
     engraved row on the vellum. Padding gives the row breath; the
     hairline rule below ties adjacent rows together. */
  position:relative;
  display:flex; flex-direction:column; align-items:stretch;
  gap:5px; padding:7px 4px 7px 12px;
  border:none; border-radius:0;
  background:transparent; color:var(--text);
  cursor:pointer;
  transition:background .15s ease;
  text-align:left;
  font:inherit;
}
.ps-mode-pills .pmp + .pmp{
  /* Hairline rule between every pair of rows — Tufte data-ink. */
  border-top:1px solid var(--gold-dim);
}
.ps-mode-pills .pmp:hover:not(.active){
  /* Pre-press preview: a barely-there vellum tint, not a fill. */
  background:rgba(232,199,106,0.05);
}
.ps-mode-pills .pmp.active{
  /* Active row marked engineered-style: brass left-margin tick (left
     border) + brass hairline rules above and below. No fill, no bevel,
     no relief. Same register as FIG. labels and the harmony tier rules. */
  background:transparent;
  border-radius:0;
  border-top:1px solid var(--gold);
  border-bottom:1px solid var(--gold);
  border-left:2px solid var(--gold);
  padding-left:10px; /* compensate for the 2px brass tick so content
                        doesn't shift left/right on activation */
}
.ps-mode-pills .pmp.active + .pmp{
  /* Row immediately below the active row: suppress its gold-dim top
     hairline since the active row's brass bottom hairline already
     provides separation. (The active row itself keeps its own brass
     top — that's its identifying mark.) */
  border-top-color:transparent;
}
.ps-mode-pills .pmp:focus-visible{
  outline:2px solid var(--gold); outline-offset:1px;
}
.ps-mode-pills .pmp-head{
  display:flex; align-items:center; justify-content:space-between;
  gap:8px; width:100%;
}
.ps-mode-pills .pmp-name{
  font-family:'Space Mono',monospace;
  font-size:11px; letter-spacing:1.4px;
  text-transform:uppercase; color:var(--dim);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  flex:1 1 auto; min-width:0;
}
/* r6p44-mode-chart-analog — audition glyph in Patent Drawing register:
   flat brass ▸, no dome, no border, no fill. Just the ink. Progress
   on .is-playing is a single brass hairline filling L→R underneath
   the row's text-baseline (engineered meter, not a stud). */
.ps-mode-pills .pmp-audition{
  flex:0 0 auto;
  display:inline-flex; align-items:center; justify-content:center;
  position:relative;            /* anchors the ::before progress fill */
  width:16px; height:16px;
  padding:0; margin:0;
  border:0; border-radius:0;
  background:transparent; color:var(--gold);
  font:inherit; cursor:pointer;
  transition:color .15s, opacity .15s;
}
/* Progress meter — single brass hairline at the row baseline,
   fills L→R over the audition duration. Engineered meter, not a stud
   indicator. Inline --audition-duration drives the transition. */
.ps-mode-pills .pmp-audition::before{
  content:'';
  position:absolute; left:0; bottom:-1px;
  height:1px; width:0;
  background:var(--gold);
  pointer-events:none;
}
.ps-mode-pills .pmp-audition.is-playing::before{
  width:100%;
  transition:width var(--audition-duration, 1100ms) linear;
}
.ps-mode-pills .pmp-audition:hover:not(.is-disabled){
  color:var(--gold3);
}
.ps-mode-pills .pmp-audition:focus-visible{
  outline:1px solid var(--gold); outline-offset:1px;
}
.ps-mode-pills .pmp-audition.is-disabled{
  opacity:0.30; cursor:not-allowed; color:var(--dim2);
}
.ps-mode-pills .pmp-audition-glyph{
  position:relative;
  font-size:11px; line-height:1;
  font-family:'Space Mono',monospace;
  font-variant-numeric:tabular-nums;
  display:inline-block;
  transform:translateY(-0.5px);
  color:inherit;
}
.ps-mode-pills .pmp.active .pmp-name{
  font-weight:700;
  color:var(--text);
}
.ps-mode-pills .pmp-formula{
  display:grid; grid-template-columns:repeat(7, minmax(0, 1fr)); gap:3px;
  /* R5.21 — explicit padding so tiles have shoulder-room and the
     7-column grid reads as a real columnar layout, not a fly-speck row.
     R5.33 — gap 5→3 to give tiles more width when "♭3" / "♭7" content
     would otherwise push past the sidebar edge.
     R6.13 — minmax(0, 1fr) replaces 1fr to enforce strict equal-width
     columns (1fr alone allows content to expand the column when min-
     content is wider). Per Claude Design 2026-05-08 punch-list #5:
     "every degree column on a fixed monospace grid across all 9 rows."
     The columns are the comparison axis — once they align rigorously,
     "one note flattens per row" is seen, not read (Tufte small-
     multiples need alignment to comparison axis). */
  padding:2px 1px 1px;
  width:100%;
  box-sizing:border-box;
}
.ps-mode-pills .pmf-tile{
  /* R5.21 — bumped 12px→15px Space Mono for the degree numerals.
     R5.33 — pulled to 13px so 2-char content (♭3, ♭7) fits inside the
     tile cell on a 180px sidebar without pushing the grid wider than
     the pill (Scott's "modes running off the right side" report).
     min-width:0 + overflow:hidden enforces the 1fr cell width.
     R6.13 — naturals solid (opacity 1.0), flats fade (.alt below at
     0.85). Per Claude Design 2026-05-08 punch-list #6: "The cascading
     shape of the flatting becomes visible at glance" — Resnick lens,
     shape of data is the data. Pre-R6.13 flipped this: flats popped
     in brass, naturals lived at 0.7 — the eye saw bright accents
     rather than the modal-cascade pattern. Now the naturals carry
     the row, flats step back, and the staircase of flatting from
     LYDIAN → LOCRIAN reads as a shape. */
  font-family:'Space Mono',monospace;
  font-size:13px; text-align:center; line-height:1.15;
  color:var(--text); opacity:1;
  font-weight:600;
  letter-spacing:0.2px;
  padding:1px 0;
  min-width:0;
  overflow:hidden;
  font-variant-numeric:tabular-nums; /* lock digit advance for clean ruler */
}
.ps-mode-pills .pmf-tile.alt{
  /* Flat accidentals fade to 0.85 — same color as naturals (no gold
     pop), so the symbol ♭ does the work of distinguishing without
     stealing the eye. */
  opacity:0.85;
}
.ps-mode-pills .pmf-tile.off{
  opacity:0.28;
}
.ps-mode-pills .pmp.active .pmf-tile{ opacity:1; }
.ps-mode-pills .pmp.active .pmf-tile.alt{ opacity:0.85; }
.ps-mode-pills .pmp.active .pmf-tile.off{ opacity:0.3; }

/* r6p44-mode-chart-analog — heatmap chips become ink dots on vellum.
   Patent Drawing register: filled / open / dashed circles, no
   colour-block rectangles. Tufte data-ink: just enough size to scan
   the staircase pattern by colour across the 9-row column. Natural =
   brass-dim filled, flat = rose filled, sharp = slate filled, off =
   open dashed ring. Sized to read at the production sidebar width
   without screaming. */
.ps-mode-pills .pmp-heatmap{
  display:grid; grid-template-columns:repeat(7, minmax(0, 1fr));
  gap:3px; padding:0 1px;
  margin-top:4px;
  justify-items:center; align-items:center;
}
.ps-mode-pills .pmh-chip{
  width:8px; height:8px;
  background:var(--gold-dim);
  border:1px solid var(--gold2);
  border-radius:50%;
  opacity:0.85;
}
.ps-mode-pills .pmh-chip.flat{
  background:var(--rose);
  border-color:rgba(120,40,60,0.7);
  opacity:1;
}
.ps-mode-pills .pmh-chip.sharp{
  background:var(--slate);
  border-color:rgba(50,68,86,0.7);
  opacity:1;
}
.ps-mode-pills .pmh-chip.off{
  background:transparent;
  border:1px dashed rgba(106,64,16,0.45);
  opacity:0.7;
}
.ps-mode-pills .pmp.active .pmh-chip{ opacity:1; }
.ps-mode-pills .pmp.active .pmh-chip.off{ opacity:0.7; }

/* r6p44-mode-chart-analog (Julin lock) — active-chord fire on the
   active row. Patent Drawing register: tile gets a flat brass fill +
   ivory ink, chip-dot grows + brass-ring. No radial foil, no inset
   bevel — just brass-on-ivory as if a stamp was pressed on the row.
   PR #276 wiring unchanged. */
.ps-mode-pills .pmf-tile.pmf-fire{
  background:var(--gold);
  color:var(--ivory);
  font-weight:700;
  border-radius:1px;
  animation:pmf-fire-enter 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes pmf-fire-enter{
  0%   { transform:scale(1.35); }
  100% { transform:scale(1);    }
}
.ps-mode-pills .pmh-chip.pmh-fire{
  background:var(--gold);
  border-color:var(--gold2);
  box-shadow:0 0 0 1px var(--gold);
  animation:pmh-fire-enter 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes pmh-fire-enter{
  0%   { transform:scale(1.45); }
  100% { transform:scale(1);    }
}

/* R5.6 — FIG. c HARMONY small-multiples stack. Universal music-
   theory progressions ordered by harmonic vocabulary growth.
   Walking down the stack, the eye sees chord count expanding,
   the V appearing in different roles, modal markers (♭VII)
   clustering, minor-key entries grouped. Same breathing-room
   principles as the mode wheel: pattern needs air to be visible. */
.ps-harmony-cart{
  display:flex; flex-direction:column; gap:6px;
  margin-top:4px;
}
.ps-harmony-stack{
  display:flex; flex-direction:column; gap:4px;
}
/* R5.92 — tier section headers (1 chord / 2 chords / 3 chords /
   4 chords / Minor). Label sits left in patent-drawing small-caps;
   hairline brass rule extends to the right edge — same register as
   FIG banners but at sub-FIG scale. Makes the data tiers in
   HARMONY_PATTERNS visible to the eye instead of buried in the
   ordering. */
.ps-harmony-tier-hd{
  display:flex; align-items:center; gap:8px;
  padding-top:6px; padding-bottom:0;
  margin-top:2px;
}
.ps-harmony-tier-hd:first-child{ margin-top:0; padding-top:0; }
.ps-harmony-tier-lbl{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.6px; text-transform:uppercase;
  color:var(--dim2); flex:0 0 auto;
}
.ps-harmony-tier-rule{
  flex:1 1 auto; height:1px;
  background:var(--gold-dim);
}
.ps-harmony-row{
  display:flex; flex-wrap:wrap; align-items:center;
  gap:5px; padding:8px 10px;
  border:1px solid var(--gold2); border-radius:1px;
  background:transparent; color:var(--text);
  cursor:pointer; text-align:left;
  font:inherit;
  transition:background .15s, border-color .15s;
}
.ps-harmony-row:hover{
  background:color-mix(in srgb, var(--gold) 6%, transparent);
  border-color:var(--gold);
}
.ps-harmony-row:focus{ outline:none; }
.ps-harmony-row:focus-visible{ outline:2px solid var(--gold); outline-offset:1px; }
.ps-harmony-row .phr-tile{
  display:inline-block;
  font-family:'Space Mono',monospace;
  font-size:12px; line-height:1.1;
  letter-spacing:0.6px;
  padding:3px 7px;
  border:1px solid var(--gold-dim);
  border-radius:1px;
  color:var(--text);
  background:rgba(232,199,106,0.06);
}
.ps-harmony-row.is-minor .phr-tile{
  font-style:italic;
  color:var(--text);
  background:rgba(140,100,200,0.06);
  border-color:rgba(140,100,200,0.3);
}
.ps-harmony-cap{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.6px; text-transform:uppercase;
  color:var(--dim2); opacity:0.85;
  padding-top:2px;
}
/* Tile pulse — fires per note as the scale-run plays. Each degree
   number flashes brass in sync with its audible note: see + hear =
   "OOOOH I get it." */
@keyframes pmfTilePulse {
  0%, 100% { color: inherit; text-shadow: none; opacity: inherit; }
  20%      { color: var(--gold); text-shadow: 0 0 6px rgba(232,199,106,0.95); opacity: 1; }
}
.ps-mode-pills .pmf-tile.pmf-pulse{ animation: pmfTilePulse 520ms ease-out; }

/* 2026-05-15 — Scale-dot flash on mode-audition. Each note that plays
   in playScaleRun also flashes the corresponding fretboard dot — the
   user hears AND sees where the note lives on the neck. Dot scales up
   to 1.6× with a brass glow, then returns. 520ms total to match the
   tile-pulse cadence. */
@keyframes pmfFbFlash {
  0%, 100% { transform: scale(1); box-shadow: none; }
  20%      { transform: scale(1.6); box-shadow: 0 0 12px rgba(232,199,106,0.95); }
}
#play-scale-layer .pmf-fb-flash { animation: pmfFbFlash 520ms ease-out; }
.ps-mode-desc{
  font-family:'DM Sans','Inter',sans-serif; font-size:11px;
  line-height:1.4; color:var(--text); opacity:0.78;
  font-style:italic;
  padding:0 4px;
  min-height:30px;
}

/* R6.41-D · modes tier 2 — persistent status row inside FIG. A SCALE
   per Claude Design rev. 5 (G1 iii). Strip sits inside the cartouche
   body, separated from the value row above by a 1px walnut divider;
   subtle gold-dim background so it reads as a fixed receipt the engine
   keeps current. Stays visible as the user scrolls / interacts. */
.ps-bass-walks-row{
  display:flex; align-items:center; justify-content:space-between;
  border-top:1px solid rgba(106,64,16,0.22);
  background:rgba(154,100,32,0.06);
  padding:5px 14px 6px;
  margin-top:6px;
  font-family:'Space Mono',monospace;
  font-size:8.5px;
  line-height:1;
}
.ps-bass-walks-lbl{
  text-transform:uppercase;
  letter-spacing:2px;
  color:var(--gold);
  font-weight:700;
}
.ps-bass-walks-formula{
  letter-spacing:1px;
  color:var(--dim2);
  font-weight:400;
  white-space:nowrap;
}
/* Disabled state — no song loaded → no bass to walk. Single dim label,
   no formula chip. Anatomy unchanged so the strip doesn't reflow. */
.ps-bass-walks-row.is-idle{ opacity:0.55; }
.ps-bass-walks-row.is-idle .ps-bass-walks-lbl{
  color:var(--dim2); font-weight:400;
}
.ps-bass-walks-row.is-idle .ps-bass-walks-formula{ visibility:hidden; }

/* R6.41 modes tier 3 · shift register strip per Claude Design rev. 5/6 (G2/G4).
   Third strip below BASS WALKS in the FIG. A SCALE cartouche. Reads
   "N NOTE(S) OFF FROM MAJOR" + altered-degree names. Background tints
   from gold-dim (0.04) when N=0 toward rose-dim (0.08) as N grows;
   Lydian (single sharp degree) gets slate-dim instead. Persists in
   closed-fold header. Synced by _syncModeShiftRow() in src/v2-modes.js. */
.ps-mode-shift-row{
  display:flex; align-items:center; justify-content:space-between;
  border-top:1px solid rgba(106,64,16,0.18);
  background:rgba(154,100,32,0.04);
  padding:5px 14px 6px;
  font-family:'Space Mono',monospace;
  font-size:8.5px;
  line-height:1;
  transition:background 220ms ease;
}
.ps-mode-shift-lbl{
  text-transform:uppercase;
  letter-spacing:2px;
  color:var(--dim2);
  font-weight:700;
  transition:color 220ms ease;
}
.ps-mode-shift-formula{
  letter-spacing:1px;
  color:var(--dim2);
  font-weight:400;
  white-space:nowrap;
  transition:color 220ms ease;
}
/* N > 0 — altered-from-major. Rose-dim fill, rose text on both sides. */
.ps-mode-shift-row.is-shift-rose{
  background:rgba(168,80,112,0.08);
}
.ps-mode-shift-row.is-shift-rose .ps-mode-shift-lbl,
.ps-mode-shift-row.is-shift-rose .ps-mode-shift-formula{
  color:var(--rose);
}
/* Lydian — single sharp degree gets slate fill, slate text (per Design:
   "Lydian uses ♯ + slate fill not rose"). */
.ps-mode-shift-row.is-shift-slate{
  background:rgba(94,112,128,0.10);
}
.ps-mode-shift-row.is-shift-slate .ps-mode-shift-lbl,
.ps-mode-shift-row.is-shift-slate .ps-mode-shift-formula{
  color:var(--slate);
}
/* Idle — no song / no mode. Same dim2 baseline, no fill bump. */
.ps-mode-shift-row.is-idle{ opacity:0.55; }
@media (prefers-reduced-motion: reduce){
  .ps-mode-shift-row,
  .ps-mode-shift-lbl,
  .ps-mode-shift-formula{ transition:none; }
}

/* R6.41-D · modes tier 2 — chord-card pulse per Claude Design rev. 5 (G1 ii).
   Fires once on mode-switch as a causal arrow: that knob you turned →
   these cards. 1.6px brass underline at the bass-string y-position +
   6.5px brass ring around the bass-note dot. Linear timing, 200ms hold
   + 200ms tail = 400ms total. --gold3 (brighter than idle gold) so the
   pulse reads as a transient signal, not steady-state ink.

   Implementation: an absolutely-positioned ::after on .pc-mini-frame
   draws the underline; the ring lives as a thin colored box-shadow
   ring on the entire frame (drawing onto each SVG dot would require
   re-rendering, which we explicitly avoid — the frame-level ring is
   the legible substitute and reads as "this card just got tapped").
   Bass string in mandolin diagrams sits at the BOTTOM of the frame
   (sy(0) in miniChordDiagram), so the underline sits near the frame's
   bottom edge — ~9% above the bottom matches the bass-string y for
   the SVG viewBox 280×148. */
.prog-card .pc-mini-frame::after{
  content:'';
  position:absolute;
  left:6%; right:6%; bottom:14%;
  height:1.6px; background:transparent;
  pointer-events:none;
  border-radius:1px;
}
.prog-card.is-mode-pulse .pc-mini-frame::after{
  background:var(--gold3);
  box-shadow:0 0 6px rgba(200,144,44,0.55);
  animation:pcBassPulse 400ms linear forwards;
}
.prog-card.is-mode-pulse .pc-mini-frame{
  box-shadow:
    inset 0 0 0 6.5px rgba(200,144,44,0.0),
    inset 0 0 14px rgba(26,12,4,0.22),
    inset 0 1px 0 rgba(240,226,190,0.08);
  animation:pcBassRing 400ms linear forwards;
}
@keyframes pcBassPulse{
  0%   { opacity:0; }
  50%  { opacity:1; }      /* 200ms hold */
  100% { opacity:0; }      /* 200ms tail */
}
@keyframes pcBassRing{
  0%   { box-shadow:
           inset 0 0 0 0px rgba(200,144,44,0),
           inset 0 0 14px rgba(26,12,4,0.22),
           inset 0 1px 0 rgba(240,226,190,0.08); }
  50%  { box-shadow:
           inset 0 0 0 6.5px rgba(200,144,44,0.75),
           inset 0 0 14px rgba(26,12,4,0.22),
           inset 0 1px 0 rgba(240,226,190,0.08); }
  100% { box-shadow:
           inset 0 0 0 0px rgba(200,144,44,0),
           inset 0 0 14px rgba(26,12,4,0.22),
           inset 0 1px 0 rgba(240,226,190,0.08); }
}
@media (prefers-reduced-motion: reduce){
  .prog-card.is-mode-pulse .pc-mini-frame::after{
    animation:none; opacity:1;
  }
  .prog-card.is-mode-pulse .pc-mini-frame{
    animation:none;
    box-shadow:
      inset 0 0 0 6.5px rgba(200,144,44,0.55),
      inset 0 0 14px rgba(26,12,4,0.22),
      inset 0 1px 0 rgba(240,226,190,0.08);
  }
}

/* R6.41 modes tier 3 — chord-card re-palette cross-fade per Design rev. 5/6 G2.
   Fires alongside the gold bass-pulse on mode-commit, but the channel is
   rose (the altered-degree color, same as the FIG. A SCALE shift register).
   Two layers: (1) 220ms voicing-dot cross-fade — SVG fingering groups dip
   opacity then return, reading as "dots swapped"; (2) 280ms rose halo
   around the mini-frame as the receipt of the palette shift. Distinct
   from the gold bass-pulse (which lives on ::after as a bottom underline
   + ring) so the two cues can coexist on the same card without stepping
   on each other. Halo composes via outline since not all .pc-mini-frame
   instances guarantee position:relative. */
.prog-card.is-mode-pulse-rose .pc-mini g.pc-hit{
  animation:pcModePulseRose 220ms ease-in-out forwards;
}
.prog-card.is-mode-pulse-rose .pc-mini-frame{
  animation:pcModeHaloRose 280ms ease-out forwards;
}
@keyframes pcModePulseRose{
  0%   { opacity:1; }
  50%  { opacity:0.35; }
  100% { opacity:1; }
}
@keyframes pcModeHaloRose{
  0%   { outline:0 solid rgba(168,80,112,0); outline-offset:-2px; }
  40%  { outline:1.5px solid rgba(168,80,112,0.55); outline-offset:-2px; }
  100% { outline:0 solid rgba(168,80,112,0); outline-offset:-2px; }
}
@media (prefers-reduced-motion: reduce){
  .prog-card.is-mode-pulse-rose .pc-mini g.pc-hit{
    animation:none; opacity:1;
  }
  .prog-card.is-mode-pulse-rose .pc-mini-frame{
    animation:none;
    outline:1.5px solid rgba(168,80,112,0.55); outline-offset:-2px;
  }
}

/* ── PL. II Rhythm cartouches ───────────────────
   Three cartouches matching the FIG. a/b/c structure of PL. I:
   Tempo (pendulum + BPM), Pattern (mini-notation + name),
   Swing (eighth-note offset visual). */
.ps-tempo-wrap{
  /* 2026-05-15 — centre the pendulum+TAP gadget in the cartouche
     (was margin-left:-12px which left the wrap flush-left with ~248px
     void on the right). */
  display:flex; flex-direction:column; align-items:center; gap:4px;
  margin:0 auto; width:150px;
}
.ps-pendulum{ display:block; }
/* R5.13 — Telegraph-key tap-tempo. Walnut base + brass lever; finger
   presses the knob (left end), arm pivots ~−14° around the right post
   for 120ms, springs back. The whole gadget is a patent-drawing in
   miniature: contact post, pivot, mounting screws, spring coil hint. */
.ps-telegraph{ display:block; cursor:pointer; outline:none; }
.ps-telegraph:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; border-radius:2px; }
.ps-telegraph:hover #ps-telegraph-arm{ filter:brightness(1.12); }
#ps-telegraph-arm{
  transition:transform 80ms cubic-bezier(0.4, 0.0, 0.2, 1);
  transform:rotate(0deg);
}
.ps-telegraph.pressed #ps-telegraph-arm{
  transform:rotate(-14deg);
  transition:transform 60ms cubic-bezier(0.4, 0.0, 0.6, 1);
}
@media (prefers-reduced-motion: reduce){
  #ps-telegraph-arm{ transition:none !important; }
  .ps-telegraph.pressed #ps-telegraph-arm{ transform:rotate(-8deg) !important; transition:none !important; }
}

/* R5.13 — pendulum was event-driven; R5.19 fixed the gravity bug.
   R6.15 — pendulum now always breathes at the active BPM cycle. Per
   Claude Design 2026-05-08 punch-list #13 (Resnick: "representations
   should think with you. Today the pendulum is decoration; one
   transform makes it instrument"). The diagram becomes a metronome
   you can see — the rhythm is visible before you press play. Was
   ±20° gated on body.is-playing; now ±8° always-on, period set by
   _syncPendulumSwing() to 120/BPM seconds (= 2 beats per cycle, same
   as a mechanical metronome). 4 keyframes for the natural arc.
   Reduced-motion users still get a static pendulum at rest. */
/* R6.45 — animation removed; transform driven by RAF loop in v2-modes.js
   (_pendulumRafTick). transform-origin stays; no keyframes needed. */
#ps-pendulum-arm{
  transform-origin:55px 10px;
  transform:rotate(0deg);
}
@media (prefers-reduced-motion: reduce){
  #ps-pendulum-arm{ transform:rotate(0deg) !important; }
}
.ps-tempo-readout{
  display:flex; align-items:baseline; gap:6px;
}
.ps-tempo-bpm{
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:26px; color:var(--text); line-height:1;
}
.ps-tempo-unit{
  font-family:'Space Mono',monospace; font-size:10px;
  letter-spacing:1.8px; color:var(--dim2); text-transform:uppercase;
}
.ps-tempo-sig{
  font-family:'Space Mono',monospace; font-size:9.5px;
  letter-spacing:2.2px; color:var(--gold); text-transform:uppercase;
  margin-top:2px;
}

/* Phase 7b · Tempo edit affordances. The three new tap targets earn
   their interactivity without new chrome — pendulum SVG, BPM number,
   and time-sig text are existing elements that gain cursors + focus
   states. Hover/focus reveals; rest state is unchanged. */
.ps-pendulum{ cursor:pointer; }
.ps-pendulum:focus{ outline:none; }
.ps-pendulum:focus-visible #ps-pendulum-bob{ stroke:var(--gold); stroke-width:1.5; }
.ps-pendulum:hover #ps-pendulum-bob{ filter:brightness(1.15); }
.ps-pendulum:active #ps-pendulum-bob{ r:8; opacity:1; }

.ps-tempo-bpm{
  cursor:text; padding:0 3px; border-radius:1px;
  transition:background 80ms, box-shadow 80ms;
}
.ps-tempo-bpm:hover{ background:rgba(154,100,32,0.06); }
.ps-tempo-bpm:focus{
  outline:none; background:var(--ivory);
  box-shadow:inset 0 -1px 0 0 var(--gold);
}

.ps-tempo-sig{ cursor:pointer; padding:1px 4px; border-radius:1px; }
.ps-tempo-sig:hover{ background:var(--gold-dim); }
.ps-tempo-sig:focus-visible{ outline:1px solid var(--gold); outline-offset:1px; }

/* Phase 7b · Pattern + Swing edit. Tap targets on existing live
   elements — same affordance pattern as Tempo: cursor + hover bg,
   no chrome at rest. Pattern notation SVG previews the pattern
   sound on tap; pattern name cycles styles; swing label cycles
   preset levels. */
.ps-pattern-notation{ cursor:pointer; }
.ps-pattern-notation:focus{ outline:none; }
.ps-pattern-notation:focus-visible{ outline:1px solid var(--gold); outline-offset:2px; }
.ps-pattern-notation:hover #ps-pattern-hits rect{ filter:brightness(1.15); }

.ps-pattern-name,
.ps-swing-label,
.ps-val-cycle{
  cursor:pointer; padding:1px 6px; border-radius:1px;
  transition:background 80ms;
}
.ps-pattern-name:hover,
.ps-swing-label:hover,
.ps-val-cycle:hover{ background:var(--gold-dim); }
.ps-pattern-name:focus-visible,
.ps-swing-label:focus-visible,
.ps-val-cycle:focus-visible{ outline:1px solid var(--gold); outline-offset:1px; }
.ps-val-cycle:focus{ outline:none; }

/* ══════════════════════════════════════════════════════════════════
   R5.41 · STATIC 1/3 + 2/3 LAYOUT — replaces R5.36 dynamic widening
   ══════════════════════════════════════════════════════════════════
   Scott's call after using R5.36 in anger: "the left bar on each tab
   is super glitchy I'm not even able to open timbre because it
   glitches between them and it's hard to click rhythm and when it
   forces open it's cut off and tinted what if we did 1/3 2/3
   division for the exhibit ???"

   R5.36 made each cartouche an engaged-on-hover stage card; siblings
   collapsed to bare FIG banners. In practice: hover races between
   cartouches, the engaged one cut off the canvas, content disappeared.

   R5.41: kill the dynamic engagement entirely. Sidebar stays at a
   permanent generous width (~33% of the plate). Every cartouche shows
   its full content all the time. No hover-promote, no sibling-collapse,
   no transform scaling, no max-height transitions. The exhibit just
   IS — at rest, full-size, every visit.

   The "engagement" idea isn't dead — it lives on in the layout-edit
   playground (R5.38, currently held) and in any future click-to-focus
   pattern. But ambient hover-promote was the wrong vehicle.
   ════════════════════════════════════════════════════════════════ */

/* Cartouche base — quiet vellum card. No transitions, no transforms,
   no max-height. What you see is what you get. */
.plate-sidebar .ps-sec{
  background:var(--vellum);
  border:1px solid var(--gold-dim);
  border-radius:2px;
  padding:12px 10px;
  margin:0 -2px;
  box-shadow:0 1px 2px rgba(58, 36, 18, 0.08);
}

/* Sidebar at static 33% of viewport width — overrides earlier 180px /
   260px values per plate. Padding-bottom = pedal strip clearance so
   the bottom cartouche (e.g., Capo on PL. III) doesn't bleed into
   the fixed-position TRANSPORT cell below (Bug #12 from R5.40 audit).
   PL. III has a 2-row pedal strip (~140px); PL. I/II have 1-row (~70px).

   R5.45 — added max-height. Padding-bottom is INSIDE the box; it doesn't
   stop the box from extending past pedal-strip top. The fixed pedal
   strip (#pedal-strip; position:fixed; bottom:40px; height:107px) sits
   147px above the viewport bottom. Without max-height, the sidebar's
   outer box extends down to its parent's bottom (~y=620 at 720vh) which
   is 47px past the pedal-strip top (y=573). The bottom slice of the
   sidebar is then occluded by the strip's z-index:600, so overflow:auto
   thinks it has more visible space than it actually does. The calc
   uses the play-pane top (~110px) + the strip clearance (147px + 8px
   buffer) so the box terminates exactly at the strip's top edge. */
.plate-sidebar{
  width:33% !important;
  min-width:280px;
  max-width:480px;
  /* R5.46 — padding-bottom dropped 90→16. R5.45's max-height already
     terminates the sidebar box at the pedal-strip top edge, so the 90px
     "pedal-strip clearance" was double-counting and stealing 74px from
     visible cartouche space (which was the difference between POSITION
     showing as "label only" vs. fully-content-visible on PL. I). PL. III
     keeps its own padding-bottom override below for the 2-row pedal-strip
     case.
     R6.17 — buffer 265→195 to give the sidebar 70px more vertical room
     so PL. I FIG. d (5 sub-figs) and PL. III modes (9 rows) both fit
     without scroll at 1440×900. The original 265 was conservative
     (header 60 + strip 107 + 98 buffer); 195 keeps a 28px buffer above
     the pedal-strip top — still terminates before the strip's z-index
     occludes it. */
  padding-bottom:12px;
  max-height:calc(100vh - 195px);
}
body[data-plate-lens="II"] .plate-sidebar{ width:33% !important; }
/* A.3 — PL. III shows a second pedal-strip row (recorder transport, ~40px)
   under row 1. The 195px constant in the base max-height calc was tuned for
   row-1-only; without compensation here the sidebar tail (PENTA MINOR row)
   bleeds visually behind / through the bottom bar. Drop max-height by 40px
   on PL. III so the sidebar terminates above row 1 even when row 2 exists. */
body[data-plate-lens="III"] .plate-sidebar{
  padding-bottom:150px;
  /* A.3 — the base 195px in the parent calc covered header(~95) + row1(~65)
     + ~35 slack. PL. III adds row2 (~40px), so we need to subtract that PLUS
     reclaim the slack that was already eating into row1's top edge.
     Net: -90 from the base 195. Empirically verified: sidebar.bottom drops
     from 756 → ~628, row1.top = 728 → 100px buffer between sidebar tail
     and bottom bar. PENTA MINOR row no longer bleeds into TUNING / TIMBRE. */
  max-height:calc(100vh - 285px);
}

/* ── Rail mode — Unified Plate Skeleton Stage 2 (PL. I first).
   At rest the sidebar collapses to a 64px rail of value-badges; tapping a
   badge opens the full cartouche drawer (.is-open), which auto-closes on an
   outside click. Reuses the existing width transition + cartouche rendering.
   Scoped to PL. I so Rhythm/Color keep their current sidebar untouched.
   Overrides the base `.plate-sidebar{width:33%!important;max-width:480px}`
   via higher specificity + !important. ── */
.ps-rail{ display:none; }                       /* hidden unless rail mode + rest */
/* r6p85 — rail mode covers PL. I + II + III (the three live plates).
   :not([data-plate-lens="IV"]) excludes only the parked Melody plate. */
/* r6p88 MAP CABINET (Design Plate CAB-a, supersedes r6p87) — the rail is a
   shallow chart-chest: 88px carcass holding flush 44px drawer-faces. Faces
   recede by TONE not Z (orthographic, no depth). Pushing a face unrolls that
   drawer's chart RIGHTWARD onto the plate (gap 0, from its own row). */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar:not(.is-open){
  width:198px !important;           /* r6p88i — 172 carcass + 26 left-inset margin. MUST hold rail+margin or the rail's right frame clips (bug). Instrument panel anchoring the left. */
  min-width:198px !important;
  max-width:198px !important;
  padding:0;
  overflow:visible;                /* the unrolled sheet escapes the column onto the plate */
  background:transparent;
  /* r6p90d — glide the 600→198 collapse on CLOSE so the plate cards slide back
     instead of POPPING (the jump that made the close read as a glitch). Scoped to
     :not(.is-open) so it fires only on close — OPEN keeps its instant reserve. */
  transition:width .30s ease, min-width .30s ease, max-width .30s ease;
}
/* r6p88c — drop the chest down to share the chord-board EYE-LINE (was top-pinned
   181px above the boards). The sidebar column is tall; nudging the rail down
   centers the cabinet against the board band so tools + song read as a pair. */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar{ justify-content:flex-start; }
/* r6p88h — inset the chest from the left wall: it was jammed at x:62, hanging in
   the margin outside the plate frame ("pressed up against the left", Scott). A
   left margin gives it breathing room so it floats in its corner, not glued to
   the edge — matching Design's mockup. margin-top keeps it on the board eye-line. */
body[data-rail="on"]:not([data-plate-lens="IV"]) .ps-rail{ margin-top:118px; margin-left:26px; }
/* r6p88 MAP CABINET — OPEN: the sidebar reserves 96 (chest) + ~330 (chart) so the
   workspace shifts and the sheet sits beside the board; the CHEST itself (the
   .ps-rail carcass) stays 96px. The faces STAY visible. */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open{
  width:600px !important;             /* r6p88m — full cabinet (204) + 360 chart + dowel/shadow, no overlap */
  min-width:600px !important;
  max-width:600px !important;
  overflow:visible !important;
  padding:0;
}
/* THE CARCASS lives on .ps-rail — a DOUBLE-CASED chest (Design): an outer gold2
   frame + an inner ruled liner with a gap between (the drawers sit in a bordered
   well), a darker vellum2 ground, and an engraved plate header. The finished oak
   case. (::before draws the header band; the inner liner is a 2nd inset ring.) */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar .ps-rail{
  width:172px; box-sizing:border-box;   /* r6p88i — wider so labels fit with margin */
  padding:26px 9px 11px;           /* top pad clears the header band; the inner liner sits at ~5px */
  background:var(--vellum2);
  border:1.5px solid var(--gold2);
  border-radius:3px;
  /* r6p88i double-case: a second ruled liner inset 4px inside the outer frame,
     so the drawers read as sitting in a bordered well (Design's finished case).
     Drawn with a hard inset ring (offset 0, two stacked spreads) + the lift. */
  box-shadow:
    inset 0 0 0 4px var(--vellum2),                      /* the gap between frame + liner */
    inset 0 0 0 5px rgba(106,64,16,0.45),                /* the inner liner rule */
    0 1px 2px rgba(58,36,18,0.12);                       /* the chest sits on the page */
}
/* engraved plate header on the carcass: "PL. I · SHAPES" etc., struck at the top */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar .ps-rail::before{
  content:attr(data-chest-label);
  position:absolute; top:7px; left:0; right:0;
  text-align:center;
  /* r6p90e (Scott) — was 6.5px mouse-type ("1pt, hard to read"). Bumped to a legible
     9.5px (matches the drawer labels below) so the chest header reads as a proper
     engraved LABEL — plain words, no box (a box made it look like another teeny
     drawer). Says what the chest is, big enough to read. */
  font-family:'Space Mono', monospace; font-size:9.5px; letter-spacing:1.8px;
  text-transform:uppercase; color:var(--gold-ink); opacity:1;
}
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar .ps-rail{ position:relative; }
/* rest state: cartouches hidden; show ONLY the active lens's rail (each rail is
   data-lens scoped, so PL. I's badges don't leak onto PL. II and vice-versa) */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar:not(.is-open) .ps-sec{ display:none !important; }
body[data-rail="on"][data-plate-lens="I"]   .plate-sidebar:not(.is-open) .ps-rail[data-lens~="I"],
body[data-rail="on"][data-plate-lens="II"]  .plate-sidebar:not(.is-open) .ps-rail[data-lens~="II"],
body[data-rail="on"][data-plate-lens="III"] .plate-sidebar:not(.is-open) .ps-rail[data-lens~="III"]{
  display:flex; flex-direction:column; gap:6px; align-items:stretch;   /* r6p88 — 6px channel between faces */
}
/* r6p88 — OPEN: the faces STAY in the chest (a chart-chest reads as drawers open
   or shut). Keep the active lens's rail shown. */
body[data-rail="on"][data-plate-lens="I"]   .plate-sidebar.is-open .ps-rail[data-lens~="I"],
body[data-rail="on"][data-plate-lens="II"]  .plate-sidebar.is-open .ps-rail[data-lens~="II"],
body[data-rail="on"][data-plate-lens="III"] .plate-sidebar.is-open .ps-rail[data-lens~="III"]{
  display:flex; flex-direction:column; gap:6px; align-items:stretch;
  /* r6p88m — THE CABINET NEVER CHANGES SIZE (Scott: "real drawers don't compact
     when you open them"). Stale rule pinned it to 88px on open, crushing the
     172px faces to 53px = the smush. Locked to 172 (= closed width); the chart
     is position:absolute, so the reserved sidebar width holds it, NOT a shrunk rail. */
  width:172px; flex:0 0 172px;
}
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open .ps-sec{ display:none !important; }
/* the matched cartouche becomes the unrolling CHART: a fixed-width sheet that
   grows from 0 width at the cabinet wall (gap 0) rightward onto the plate,
   top-anchored to the pushed drawer's row (--chart-top). The roll-dowel + bail
   ride the leading edge (::before/::after). One drawn offset-shadow beneath. */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open .ps-sec{
  position:absolute;
  left:204px;                         /* r6p88m — past the FULL cabinet (26 margin + 172 carcass = 198) + 6px gap, so the chart sits to the RIGHT of the now-full-size drawers, never covering their labels. Close enough to read as emerging from the drawer. */
  top:var(--chart-top, 8px);
  width:0;                            /* unrolls to 360 via .chart-out */
  padding-left:0; padding-right:0;    /* r6p90d — collapse the sheet's own padding on CLOSE so it rolls fully to NOTHING (killed the ~24px padding nub that made it pause at three-quarters then flick off). */
  max-height:calc(100% - var(--chart-top, 8px) - 6px);
  overflow:hidden;
  box-sizing:border-box;
  z-index:2;
  border:1.5px solid var(--gold2);
  border-left:2px solid var(--gold2);  /* the spool seam at the wall */
  border-radius:0 3px 3px 0;
  background:var(--paper, #efe6c8);
  box-shadow:4px 4px 0 var(--shadow-ink);   /* r6p88r — Design's exact .chart-sheet shadow: 4px 4px 0 #b3b896 (was 5px 6px) */
  /* r6p90d — CLOSE motion lives on the BASE (fires when .chart-out is removed): a
     smooth ease-IN that accelerates fully shut over .30s — no overshoot, no slow-stop
     crawl. Padding collapses with the width so the sheet reaches true zero. The OPEN
     overshoot curve lives on .chart-out below, so each DIRECTION has its own curve
     (was one shared overshoot, which front-loaded the close → the glitchy pause). */
  transition:width .30s cubic-bezier(.4,0,1,1), padding .30s cubic-bezier(.4,0,1,1);
}
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open.chart-out .ps-sec{
  width:360px;                        /* r6p88h — bolt-width grown 300→360 so the SHAPE 3-tile row + other charts breathe (was mushed after the plate grew). Fixed, not per-tool (Plate IV). */
  padding-left:10px; padding-right:10px;   /* r6p90d — restore the sheet's content padding when open */
  overflow:visible;                   /* r6p88j — once unrolled, let the roll-dowel + bail ESCAPE the right edge (overflow:hidden was clipping them). The unroll-clip stays via the base rule during animation; the inner body scrolls if a chart is tall. */
  /* OPEN: roll out + shudder — the overshoot lives HERE so CLOSE (base) can be a clean ease-in */
  transition:width .46s cubic-bezier(.34,1.56,.5,1), padding .46s cubic-bezier(.34,1.56,.5,1);
}
/* if a chart is taller than its window, the BODY scrolls (not the .ps-sec, which
   must stay overflow:visible so the dowel shows). */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open.chart-out .ps-sec > *{
  max-height:calc(100vh - var(--chart-top, 8px) - 120px); overflow-y:auto; overflow-x:visible;
}
/* r6p88r — THE ROLLER, copied from DESIGN'S ACTUAL HTML (.dowel computed style):
   8px wide, a SYMMETRIC flat light gradient (dark edge → vellum → cream highlight
   at center → vellum → dark edge), NO border-radius, NO border, NO shadow. Simple
   and flat — the symmetric gradient alone reads as a round rod catching light.
   (I'd overbuilt it w/ rounded caps + cast shadow + curl; Design's is plainer.) */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open .ps-sec::after{
  content:""; position:absolute; top:0; bottom:0; right:-8px; width:8px;
  background:linear-gradient(90deg, #6a4010 0%, #d6dcbe 38%, #efe6c8 50%, #d6dcbe 62%, #6a4010 100%);
  opacity:0; transition:opacity .16s ease .26s;
  z-index:3;
}
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open .ps-sec .ps-sec-body{ position:relative; }
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open.chart-out .ps-sec::after{ opacity:1; }
/* r6p88r — the BAIL RING, from DESIGN'S ACTUAL .bail: a 13px HOLLOW ring,
   1px solid gold2, no fill, no shadow. A plain pull-ring, nothing chunky. */
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open .ps-sec::before{
  content:""; position:absolute; top:50%; right:-10px; transform:translateY(-50%);
  width:13px; height:13px; border-radius:50%;
  border:1px solid var(--gold2, #6a4010);
  background:var(--paper, #efe6c8);   /* sits on the page, ring reads hollow against it */
  opacity:0; transition:opacity .16s ease .30s; z-index:4;
}
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar.is-open.chart-out .ps-sec::before{ opacity:1; }
/* reduced-motion: instant full sheet, no half-roll */
@media (prefers-reduced-motion: reduce){
  body[data-rail="on"] .plate-sidebar.is-open .ps-sec{ transition:none; }
  body[data-rail="on"] .plate-sidebar.is-open .ps-sec::after,
  body[data-rail="on"] .plate-sidebar.is-open .ps-sec::before{ transition:none; }
}
/* r6p88p — OPEN-DRAWER SIGNIFIER (Design, Scott: "it's the BUTTON that tells you
   which is open + click-here-to-close, not a highlight"). The open drawer is NOT
   ivory-flooded; it just gets a slightly HEAVIER FRAME (depressed look) and its
   ring-pull FILLS with a gold dot (the latch engaged). The pull does double duty:
   status + close-affordance, like a real push-latch button. */
body[data-rail="on"] .ps-rail-badge.is-active{
  border-color:var(--gold);
  box-shadow:inset 0 0 0 1px var(--gold);   /* a heavier frame = "this one is pressed/open" */
  transform:translateX(1px);                /* +1px nudge in the pull direction (press) */
}
/* PL. I tools */
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="key"]  #ps-key-cart { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="pos"]  #ps-pos-cart { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="capo"] #ps-capo-cart{ display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="voice"] #t3-voicing-panel,
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="voice"] #ps-shape-sec,
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="voice"] #ps-position-sec,
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="voice"] #ps-bass-sec,
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="voice"] #ps-register-sec{ display:flex !important; }
/* PL. I grip facets (r6p85g reconcile) — each voicing facet opens individually
   from its own Shapes-rail badge. Unique keys (vbass ≠ PL. II 'bass'). */
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="shape"]    #ps-shape-sec    { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="roam"]     #ps-position-sec { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="vbass"]    #ps-bass-sec     { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="register"] #ps-register-sec { display:flex !important; }
/* PL. II tools (r6p85) */
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="tempo"]   #ps-tempo-cart  { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="pattern"] #ps-pattern-cart{ display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="bass"]    #ps-bass-cart   { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="drums"]   #ps-drums-cart  { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="delay"]   #ps-delay-cart  { display:flex !important; }
/* PL. III tools (r6p85) — Key reuses #ps-key-cart (Color-home wheel); timbre/
   reverb are fold cartouches, expanded by _railTo when opened as a drawer. */
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="key"]    #ps-key-cart   { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="scale"]  #ps-mode-sec   { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="timbre"] #ps-timbre-sec { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="reverb"] #ps-reverb-sec { display:flex !important; }
body[data-rail="on"] .plate-sidebar.is-open[data-open-cart="mixer"]  #ps-mixer-sec  { display:flex !important; }

/* ── r6p88 DRAWER FACE (Plate CAB-a Fig.1) — a shallow inlaid chart-drawer ──
   44px flush face (= min touch target), engraved label struck on a ruled
   baseline, a countersunk ring-pull (a drilled hole reads as recess, never a
   protruding knob), plate-index initial answering it. Patent line, lit by line. */
/* r6p88e — a WIDE drawer face uses its whole width: ring-pull as a real LEFT
   handle (vertically centered, like a drawer pull), the label filling the rest
   centered, the FIG letter in the top-right corner. No more pile-up + collision
   in the top-left; the space inside each drawer is now USED. */
.ps-rail-badge{
  -webkit-appearance:none; appearance:none;
  position:relative;
  height:46px;
  box-sizing:border-box;
  margin:0 7px;                        /* inlaid: carcass shows as a 7px channel each side */
  padding:0 8px 0 28px;                /* r6p88j — tighter so ROOT IN BASS fits one line; left pad clears the handle */
  cursor:pointer;
  background:var(--vellum);            /* face lighter than the vellum2 carcass */
  border:1px solid var(--gold2);
  border-radius:1px;                   /* ruled corners, barely rounded */
  display:flex; flex-direction:column; align-items:flex-start; justify-content:center;
  /* +1px X nudge (pull direction) is the press; no Z dip (Design struck fake-Z) */
  transition:transform .09s cubic-bezier(.2,.7,.3,1), filter .12s ease, background .12s ease, box-shadow .12s ease;
}
.ps-rail-badge:hover{ filter:brightness(1.03); }
.ps-rail-badge:active{ transform:translateX(1px); filter:brightness(0.945); }   /* push-latch press: +1px in-plane nudge, no Z-dip */
/* r6p88j — kill the browser's blue focus ring (broke the patent aesthetic — Scott).
   Keep keyboard focus VISIBLE but in-register: a soft gold inset, not Windows-blue. */
.ps-rail-badge:focus{ outline:none; }
.ps-rail-badge:focus-visible{ outline:none; box-shadow:inset 0 0 0 1.5px var(--gold,#9a6420); }
/* the engraved tool label: struck on a ruled baseline, filling the face width
   (the handle's to its left, the FIG letter top-right — nothing collides). */
.ps-rail-badge .rb-cap{
  font-family:'Space Mono', monospace; font-size:9.5px; letter-spacing:1.5px; font-weight:700;
  text-transform:uppercase; color:var(--gold-ink);   /* r6p88l — restored readable size (labels are short now: SHAPE/ROAM/ROOT/REGISTER, no mush) */
  text-align:left;                     /* left-aligned (like Design): label grows from the handle outward */
  padding-bottom:3px;
  border-bottom:0.75px solid rgba(106,64,16,0.40);  /* the register rule (ledger baseline) */
  line-height:1.15;
  white-space:nowrap;                  /* r6p88k — never wrap; ROOT IN BASS stays one line (no mush) */
  /* SHORT rule under the label text only (Design), not full width. */
  display:inline-block; width:auto; align-self:flex-start; max-width:100%;
}
/* r6p88h — the FIG index letter pairs with the HANDLE on the left (above the
   ring-pull), out of the label's way entirely — no more right-corner collision.
   A small engraved index, like a drawer's catalog number by its pull. */
.ps-rail-badge .rb-fig{
  position:absolute; top:4px; left:7px; z-index:2;
  font-family:'Playfair Display', serif; font-style:italic; font-size:11px; color:var(--gold);
  line-height:1;
}
/* the ring-pull: a countersunk drilled recess, now a real LEFT HANDLE —
   vertically centered on the face, clear of the label (a drawer pull lives at
   the drawer's edge, not piled on the name). */
.ps-rail-badge::before{
  content:""; position:absolute; top:50%; left:9px; transform:translateY(-50%);
  width:13px; height:13px; border-radius:50%;
  border:1px solid var(--gold2);
  box-shadow:inset 0 0 0 2px var(--vellum2), inset 0 1px 1.5px rgba(106,64,16,0.30);  /* double-ring + drilled-recess shading */
}
/* r6p88p — the OPEN drawer's ring-pull FILLS with a gold dot (the latch engaged =
   "push here to close"); closed drawers keep the hollow ring (pull-to-open). */
.ps-rail-badge.is-active::before{
  left:9px;
  background:radial-gradient(circle at 40% 35%, var(--gold3,#c8902c), var(--gold,#9a6420) 70%);
  box-shadow:inset 0 0 0 2px var(--vellum2), 0 0 0 1px var(--gold2);   /* keep the double-ring bezel, filled center */
  border-color:var(--gold);
}
/* retired chrome: old value/chevron/glyph + the boxed close-× (knob/push is the close) */
.ps-rail-badge .rb-val, .ps-rail-badge .rb-chev, .ps-rail-badge .rb-glyph{ display:none; }
.ps-rail-close{ display:none !important; }
body[data-rail="on"]:not([data-plate-lens="IV"]) .plate-sidebar{ position:relative; }
/* r6p85 — living rail: a badge pulses on the beat so the collapsed rail IS the
   performance view (the metronome ticks, the pattern hits) — driven from beatTick. */
.ps-rail-badge.rb-firing .rb-glyph{
  filter:drop-shadow(0 0 5px rgba(200,144,44,0.85)) drop-shadow(0 0 9px rgba(200,144,44,0.45));
  transform:scale(1.14);
}

/* r6p83 — FX retired (the last right-rail surface). Delay lives under timing
   (PL. II Rhythm cartouche); EQ + Mix → the deferred Mixer cartouche. Hide the
   FX bottom-cell + right panel; code stays for the Mixer migration. */
#ps-cell-fx, #ps-fx-menu, #fx-panel { display: none !important; }

/* Right rail retires to 0 except when actively showing pedal/FX
   content. Scott's call: "if nothing is on the right why take up
   10 percent over there?" The empty 180–300px column was 26% of
   horizontal real estate for nothing — Tufte data-ink violation.
   Now: width:0, no padding, no flex-basis. Reclaimed for canvas.
   Reappears with width:300px when a pedal popover or FX detail
   actually mounts content into it. */
.plate-right-rail{
  width:0 !important;
  min-width:0 !important;
  padding:0 !important;
  flex:0 0 0 !important;
  overflow:visible;
}
.plate-right-rail.is-pedal-active,
.plate-right-rail.is-fx-detail-active,
.plate-right-rail.is-fx-chooser-active{
  width:340px !important;
  flex:0 0 340px !important;
  padding:14px 20px 16px 20px !important;
}
/* R5.63 — popover right edge clipping fix. Pedal skins declare
   min-width:300px on their outer card; the rail at 300px with 12px
   horizontal padding only gave the card 276px of content area, so the
   card overflowed by ~24px and the right border + "WORKS" suffix on
   the FIFTHS STUDIO WORKS header got clipped off-screen. Bump rail to
   340px so the 300px skin card fits cleanly inside 20px-each-side
   gutter. Total horizontal cost vs prior 300px state: +40px. Chord
   cards on PL. I narrow by 10px each (4 cards) — acceptable trade
   given the popover is a transient state, not the resting layout. */

/* PL. I chord-card grid — even distribution. Scott's call:
   "PLEASE fix how the chord cards load they are tucked up and need
   to scroll then the cards below are floating in luxury." Cards
   were vertically tucked to the top with overflow:hidden cropping;
   bottom rows had loose empty space. Now: justify-content:center
   on the column flex so cards distribute through the available
   vertical space evenly, no clipping on top, no orphan space below. */
/* R5.43 — Scott's call: "why is the fretboard suddenly super wide?"
   R5.41 collapsed the right rail to width:0, giving the canvas 67%
   uninterrupted. Result: the fretboard pushed to the absolute right
   edge with no breathing room. Add right padding to .play-main so
   the figure has a margin to live in. Same for left so the figure
   doesn't go edge-to-edge on the sidebar side either.
   R5.49 — Scott's call: "why the extra space on the right but none
   on the left?" R5.43 set 60r / 8l which is visibly asymmetric. Now
   30 / 30 — same total breathing room (60px), centered. Distributes
   content evenly via justify-content:space-evenly so the fretboard
   and chord-chip strip don't stick to the top of the canvas. */
.play-main{
  padding-right:30px;
  padding-left:30px;
  /* 2026-06-03 — reverted to space-evenly (the known-good baseline) after a
     center+gap attempt made things worse: the exhibit + chooser are nested
     inside #sub-play, so the visible chip gap lives INSIDE that container, not
     in this flex layout — outer changes couldn't touch it. The welded-trio
     fix needs a structural pass on #sub-play, not a play-main tweak (task #23). */
  justify-content:space-evenly;
}

/* R5.44 — fretboard window clips out-of-bounds dots. Scott's screenshot
   2 (PL. II in Bb): chord dots float OUTSIDE the right edge of the
   fretboard frame because chord-shape position exceeds the visible
   fret window. Until the render layer learns to suppress out-of-window
   chords, clip overflow at the wrapper so loose dots don't appear in
   the canvas at large. */
#play-neck-wrap{ overflow:hidden; }
.plate-fb-frame{ overflow:hidden; }

/* R5.44 — harmony list (PL. III) bleeding into TRANSPORT cell. After
   R5.42 removed Position+Capo from PL. III sidebar, the Harmony stack
   grew taller; on shorter viewports the last few rows hang past the
   sidebar bottom and visually overlap the fixed pedal strip's
   TRANSPORT cell. Bump PL. III sidebar padding-bottom so harmony
   always clears the rec-row + pedal strip stack (~180px on PL. III).
   r6p96 — scoped to .is-open only: the CLOSED PL. III rail is now a short
   tool-badge list that centres in the upper stage (see .plate-sidebar
   :not(.is-open)); the 200px bottom pad would skew that centring. It still
   applies when a tool drawer is EXPANDED (.is-open) and can run tall. */
body[data-plate-lens="III"] .plate-sidebar.is-open{ padding-bottom:200px; }

/* R5.43 — Box-view investigation deferred. Scott flagged: Box-on vs
   Box-off look indistinguishable when the fretboard is already narrow-
   windowed. Real fix needs the render.js code that draws the position
   bracket — adding render-side classes (.fb-out-of-box / .fb-position-
   bracket) so CSS can dim the outside area when Box is on. Holding
   that fix for a follow-up batch since it touches render code, not
   just CSS, and Scott may prefer to retire Box entirely. */

/* R5.43 — metronome SOUND picker inline in Tempo cartouche. Three
   tile-buttons (Woodblock · Rim · Click) styled as a small radio
   group with the active one brass-tinted. Lives right under the
   TAP key + 4/4 readout so the player can change the click sound
   without diving to the pedal popover. setMetroVoice toggles the
   .on class via existing pedal-popover sync code. */
.ps-tempo-mvoice{
  display:flex;
  gap:4px;
  justify-content:center;
  margin-top:8px;
  flex-wrap:wrap;
}
/* R6.15 — Per Claude Design 2026-05-08 punch-list #14: "OFF /
   WOODBLOCK / RIM / CLICK — underline, not fill. Active = 1.5px brass
   underline; inactive = unfilled Space Mono caps. Same vocabulary as
   everything else once Library tabs land." Pre-R6.15 the active state
   was a gold-dim fill + brass border — read as an HTML radio bar, not
   the workshop. Now: drop the box entirely, brass underline carries
   the active signal. The studio gets one more selection vocabulary
   row aligned to the chassis primitive. */
.ps-tmv-btn{
  font-family:'Space Mono',monospace;
  font-size:9px;
  font-weight:700;
  letter-spacing:1.4px;
  text-transform:uppercase;
  color:var(--dim);
  background:transparent;
  border:none;
  border-bottom:1.5px solid transparent;
  border-radius:0;
  padding:4px 8px 4px;
  cursor:pointer;
  transition:color 120ms ease, border-color 120ms ease;
}
.ps-tmv-btn:hover{ color:var(--gold); }
.ps-tmv-btn.on{
  color:var(--text);
  border-bottom-color:var(--gold);
}

/* ────────────────────────────────────────────────────────────
   DELAY cartouche (r6p48 — FIG. e on PL. II Rhythm)
   Tape-echo register; pulse train + return-bus geometry.
   Mechanism is the diagram; FEEDBACK is the return bus.
   ──────────────────────────────────────────────────────────── */
.ps-delay-wrap{
  padding:6px 8px 4px;
  transition:opacity 200ms ease;
}
.ps-delay-wrap[data-delay-on="false"]{ opacity:0.55; }
.ps-delay-svg{
  display:block;
  margin:2px auto 8px;
  width:100%;
  max-width:320px;
  height:auto;
}
/* Return-bus segments. Inactive = hairline ghost; active = brass solid.
   Hover lifts opacity but doesn't change weight. _syncDelayDiagram sets
   the stroke-width per segment based on current feedback % (25/50/75/90). */
.dl-cart-fb-group path{
  transition:stroke-width 160ms ease, opacity 160ms ease;
}
.dl-cart-fb-group path:hover{ opacity:0.9; }
.dl-cart-fb-group path:focus-visible{
  outline:1px dashed var(--gold);
  outline-offset:2px;
}
/* State line in fig-banner — small caps, sits beside FIG. label. */
.ps-sec-fig-state{
  display:inline-block;
  margin-left:8px;
  font-family:'Space Mono',monospace;
  font-size:9px;
  font-weight:700;
  letter-spacing:1.4px;
  text-transform:uppercase;
  color:var(--dim);
  vertical-align:baseline;
}
.ps-delay-wrap[data-delay-on="true"] ~ * .ps-sec-fig-state,
#ps-delay-cart .ps-sec-fig-state[data-on="true"]{ color:var(--text); }
/* Time + Type segmented rows inherit .ps-tempo-mvoice + .ps-tmv-btn. */

/* r6p48b — single-tier .pat-stamp-pop CSS removed. The 2026-05-22
   "all inventions get equal weight" reversal of the 2026-05-21 two-
   tier lock means every patent stamp now opens a full canvas-takeover
   deep view via _openDeepView(); no more floating popover variant. */

/* R5.42 — chord cards fit without scroll. Scott's call: "the chords
   are still needing to scroll." Earlier global #v2-shapes-cards had
   flex-wrap:nowrap !important (single horizontal row that overflowed);
   PL. I needs a grid that fills available canvas without scroll. Now:
   3-column CSS grid auto-sizing so 4-5 cards distribute as 2 rows of
   2-3 each. Cards shrink to fit; no scroll. */
body[data-plate-lens="I"] #v2-shapes-cards{
  display:grid !important;
  grid-template-columns:repeat(3, minmax(0, 1fr));
  grid-auto-rows:minmax(0, 1fr);
  align-content:stretch;
  justify-content:stretch;
  gap:12px;
  padding:8px 4px;
  height:100%;
  min-height:0;
  flex-wrap:initial !important;
}
body[data-plate-lens="I"] #v2-shapes-cards > div{
  flex:none;
  min-width:0;
  min-height:0;
  overflow:hidden;
}
body[data-plate-lens="I"] .play-main{
  overflow:hidden;
  align-items:stretch;
  justify-content:flex-start;
}

/* Active mode pill — formula tiles slightly bigger (was inside the
   engaged-state in R5.36; now applies always since the pill is
   always at full visibility). */
.plate-sidebar .pmp.active .pmf-tile{
  font-size:16px;
  transition:font-size 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

@media (prefers-reduced-motion: reduce){
  .plate-sidebar .ps-sec{
    transition:none !important; transform:none !important;
  }
  .plate-sidebar .ps-sec svg{ transform:none !important; }
}

/* ── R2 Step 3 · PL. II Ensemble cartouche (Bass + Drums collapsed) ──
   R6.19 — tightened gap + zero padding so PL. II's 5-cartouche stack
   (Tempo/Pattern/Swing/Bass/Drums) fits in the parent-flex-constrained
   sidebar (~683px at 1440×900) without BASS clipping its header
   below the fold. */
.ps-ensemble-wrap{
  display:flex; flex-direction:column; align-items:stretch; gap:4px;
  padding:0;
}
.ps-ensemble-name{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--text); line-height:1;
  text-align:center;
}
/* Each section: italic name + horizontal hit-row, peer typography to
   Pattern/Swing cartouches above. Brass label = "tap to add", walnut
   label = "active". */
.ps-en-section{
  display:flex; align-items:center; gap:8px;
  padding:0;
}
/* R6.31 — segmented controls + volume slider. Cartouche stacks vertically:
   patent diagram on top (display only), segmented row in the middle,
   thin volume slider at the bottom. One affordance per cell, Norman
   compliant — Scott's "designer himself forgets which click does what"
   problem solved. */
.ps-en-section .ps-en-diagram{
  width:100%; max-width:160px; cursor:default;
  pointer-events:none; /* SVG no longer the cycle target */
}
.ps-en-segs{
  display:flex; flex-wrap:wrap; gap:2px; width:100%;
  margin-top:6px;
}
.ps-en-seg{
  flex:1 1 auto; min-width:0;
  background:transparent; border:1px solid var(--gold2);
  border-radius:1px; padding:3px 4px;
  font-family:'Space Mono',monospace; font-size:8.5px;
  letter-spacing:1.2px; text-transform:uppercase;
  color:var(--dim2); cursor:pointer; line-height:1;
  white-space:nowrap; text-overflow:ellipsis; overflow:hidden;
  transition:background 80ms, color 80ms, border-color 80ms;
}
.ps-en-seg:hover{ background:var(--gold-dim); color:var(--gold); border-color:var(--gold); }
.ps-en-seg.on{
  background:var(--gold-dim); color:var(--text);
  border-color:var(--gold);
  box-shadow:inset 0 1.5px 0 var(--gold);
}
.ps-en-seg:focus{ outline:none; }
.ps-en-seg:focus-visible{ outline:1px solid var(--gold); outline-offset:1px; }
.ps-en-vol-row{
  display:flex; align-items:center; gap:6px; width:100%;
  margin-top:5px;
}
.ps-en-vol-lbl{
  font-family:'Space Mono',monospace; font-size:8px;
  letter-spacing:1.6px; text-transform:uppercase; color:var(--dim2);
  flex:0 0 auto;
}
input[type="range"].ps-en-vol{
  flex:1 1 auto; -webkit-appearance:none; appearance:none;
  height:14px; background:transparent;
  cursor:pointer;
}
input[type="range"].ps-en-vol::-webkit-slider-runnable-track{
  height:1px; background:var(--gold2); border:0;
}
input[type="range"].ps-en-vol::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:10px; height:10px; border-radius:50%;
  background:var(--gold); border:1px solid var(--gold3);
  margin-top:-5px;
  cursor:grab;
}
input[type="range"].ps-en-vol::-moz-range-track{
  height:1px; background:var(--gold2); border:0;
}
input[type="range"].ps-en-vol::-moz-range-thumb{
  width:10px; height:10px; border-radius:50%;
  background:var(--gold); border:1px solid var(--gold3);
  cursor:grab;
}

/* ── GLOBAL SLOT (IA palace) — the one reveal target at the top of the sidebar.
   Hidden until a spine cell opens it; shows only the item matching data-open. */
.ps-global-slot{ display:none; }
.ps-global-slot[data-open]:not([data-open=""]){
  display:block; margin-bottom:12px; padding:11px 13px;
  border:1px solid var(--gold2); border-radius:4px;
  background:rgba(154,100,32,0.05);
}
.ps-gslot-item{ display:none; }
.ps-global-slot[data-open="tempo"]    .ps-gslot-item[data-glob="tempo"],
.ps-global-slot[data-open="key"]      .ps-gslot-item[data-glob="key"],
.ps-global-slot[data-open="position"] .ps-gslot-item[data-glob="position"],
.ps-global-slot[data-open="capo"]     .ps-gslot-item[data-glob="capo"],
.ps-global-slot[data-open="levels"]   .ps-gslot-item[data-glob="levels"]{ display:block; }

/* ── Compact GLOBAL TEMPO (tray) — beat dot + bpm + tap. Value/exhibit split:
   the full Maelzel pendulum stays on Rhythm; this is the irreducible "how fast"
   that travels to every plate, with a live pulse so the beat is felt. */
.ps-gtray-head{ display:flex; align-items:baseline; gap:8px; margin-bottom:6px; }
.ps-gtray-lbl{
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:2px;
  text-transform:uppercase; color:var(--gold-ink);
}
.ps-gtray-sub{ font-family:'DM Sans',sans-serif; font-size:9px; color:var(--dim2); letter-spacing:0.5px; }
.ps-gtempo-row{ display:flex; align-items:center; gap:10px; }
.ps-gtempo-beat{
  width:13px; height:13px; border-radius:50%; flex:0 0 auto;
  border:1.5px solid var(--gold2); background:transparent;
  transition:background 90ms ease, transform 90ms ease, box-shadow 90ms ease;
}
.ps-gtempo-beat.tick{ background:var(--gold); transform:scale(1.18); box-shadow:0 0 6px rgba(154,100,32,0.5); }
.ps-gtempo-beat.accent{ background:var(--gold3); transform:scale(1.35); box-shadow:0 0 9px rgba(200,144,44,0.7); }
.ps-gtempo-nudge{
  width:22px; height:22px; flex:0 0 auto; border:1px solid var(--gold2);
  border-radius:3px; background:transparent; color:var(--gold-ink);
  font-family:'Space Mono',monospace; font-size:14px; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center; padding:0;
}
.ps-gtempo-nudge:hover{ background:rgba(154,100,32,0.1); }
.ps-gtempo-readout{ display:flex; align-items:baseline; gap:3px; }
.ps-gtempo-bpm{
  font-family:'Playfair Display',serif; font-style:italic; font-size:19px;
  color:var(--text); min-width:30px; text-align:center; cursor:text;
  outline:none; border-radius:2px;
}
.ps-gtempo-bpm:focus{ background:rgba(154,100,32,0.12); }
.ps-gtempo-unit{ font-family:'Space Mono',monospace; font-size:9px; letter-spacing:1px; color:var(--dim2); }
.ps-gtempo-tap{
  margin-left:auto; padding:4px 12px; border:1px solid var(--gold2);
  border-radius:3px; background:transparent; color:var(--gold-ink);
  font-family:'Space Mono',monospace; font-size:10px; letter-spacing:1.5px;
  text-transform:uppercase; cursor:pointer;
}
.ps-gtempo-tap:hover{ background:rgba(154,100,32,0.1); }

/* ── MIXER channel strip (FIG. d, PL. III) — vertical brass faders in a
   console row. Per-voice levels + a set-off master. Native range inputs
   (free drag / keyboard / a11y), turned vertical via writing-mode so top = max. */
.ps-mixer-strip{
  display:flex; align-items:flex-end; justify-content:center; gap:12px;
  padding:12px 4px 6px;
}
.ps-mixer-ch{ display:flex; flex-direction:column; align-items:center; gap:7px; }
.ps-mixer-lbl{
  font-family:'Space Mono',monospace; font-size:9px; letter-spacing:1.5px;
  text-transform:uppercase; color:var(--gold-ink);
}
.ps-mixer-val{
  font-family:'Playfair Display',serif; font-style:italic; font-size:12px;
  color:var(--text); min-height:15px; line-height:1;
}
input[type="range"].ps-mixer-fader{
  -webkit-appearance:none; appearance:none;
  writing-mode:vertical-lr; direction:rtl;   /* vertical; top = max */
  width:14px; height:100px; background:transparent; cursor:pointer; margin:0;
}
input[type="range"].ps-mixer-fader::-webkit-slider-runnable-track{
  width:3px; background:var(--gold2); opacity:0.5; border-radius:2px;
}
input[type="range"].ps-mixer-fader::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:18px; height:11px; border-radius:2px;
  background:var(--gold); border:1px solid var(--gold2);
}
input[type="range"].ps-mixer-fader::-moz-range-track{ width:3px; background:var(--gold2); opacity:0.5; border-radius:2px; }
input[type="range"].ps-mixer-fader::-moz-range-thumb{
  width:18px; height:11px; border-radius:2px;
  background:var(--gold); border:1px solid var(--gold2);
}
/* master set off with a brass divider + brighter knob */
.ps-mixer-div{ width:1px; align-self:stretch; background:var(--gold2); opacity:0.5; margin:16px 2px 22px; }
.ps-mixer-master input.ps-mixer-fader::-webkit-slider-thumb{ background:var(--gold3); }
.ps-mixer-master input.ps-mixer-fader::-moz-range-thumb{ background:var(--gold3); }
.ps-mixer-master .ps-mixer-lbl{ color:var(--text); }

/* R6.31 — drum imagery animates during play (parity with bass). The
   group of drum-hit glyphs gently breathes when the engine is on; the
   bass dots already pulse via _syncEnsembleSidebar opacity. */
@keyframes psDrumBreathe {
  0%   { opacity: 0.85; }
  50%  { opacity: 1.0; }
  100% { opacity: 0.85; }
}
.ps-en-drum-svg.playing #ps-ensemble-drum-hits{
  animation: psDrumBreathe 1.6s ease-in-out infinite;
}
.ps-en-bass-svg.playing #ps-en-bass-string{
  animation: psDrumBreathe 1.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce){
  .ps-en-drum-svg.playing #ps-ensemble-drum-hits,
  .ps-en-bass-svg.playing #ps-en-bass-string{ animation:none !important; }
}
/* Section now stacks: diagram → segments → vol. Override the row layout
   inherited above. */
#ps-bass-cart .ps-en-section,
#ps-drums-cart .ps-en-section{
  flex-direction:column; align-items:stretch; gap:0;
}
.ps-en-name{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:15px; line-height:1;
  min-width:48px; flex:0 0 auto;
  cursor:pointer; padding:1px 4px; border-radius:1px;
  color:var(--gold);
  transition: color 120ms, background 80ms;
}
.ps-en-name.on{ color:var(--text); }
.ps-en-name:hover{ background:var(--gold-dim); }
.ps-en-name:focus{ outline:none; }
.ps-en-name:focus-visible{ outline:1px solid var(--gold); outline-offset:1px; }
.ps-en-row-grid{
  display:block; flex:1 1 auto; max-width:140px;
  cursor:pointer;
}
.ps-en-row-grid:focus{ outline:none; }
.ps-en-row-grid:focus-visible{ outline:1px solid var(--gold); outline-offset:2px; }
.ps-en-row-grid:hover rect{ filter:brightness(1.15); }

/* R5.22 — ensemble delight pass.
   Bass = thick brass string with hit dots (taller SVG, 0..30 viewBox).
   Drums = 3-row patent-drawing kit (Kick/Snare/Hat × 8 eighth notes,
   taller SVG, 0..56 viewBox). Both sections grow vertically — the
   ensemble cartouche is now a real exhibit, not a tucked-away strip. */
/* R6.31 — SVGs are now display-only legends (segmented controls below
   own the affordance). Cursor + focus-ring removed; hover-brightness
   gone since the user no longer "interacts" with the diagram. */
.ps-en-bass-svg,
.ps-en-drum-svg{
  display:block; flex:1 1 auto; max-width:160px;
  outline:none;
}
/* Bass hit dots transition smoothly when style cycles (boom-chuck →
   walking ascends; etc.). Same 240ms canonical curve as everywhere. */
.ps-en-bass-svg circle{
  transition:cy 240ms cubic-bezier(0.2, 0.8, 0.2, 1),
             r  240ms cubic-bezier(0.2, 0.8, 0.2, 1),
             opacity 240ms ease-out;
}
@media (prefers-reduced-motion: reduce){
  .ps-en-bass-svg circle{ transition:none !important; }
}
.ps-en-section{
  align-items:flex-start;
}

/* Liveness pulse — applied to a hit-rect or pattern note for ~240ms
   on each beat-tick when transport is playing. Brass glow over the
   existing fill, fades back via animation. The active beat is the
   data-ink in motion: paper = static, playing = colour. */
@keyframes psRhythmPulse {
  0%   { filter: none; }
  10%  { filter: brightness(1.55) drop-shadow(0 0 3px rgba(154,100,32,0.85)); }
  100% { filter: none; }
}
.ps-rhythm-pulse{ animation: psRhythmPulse 240ms ease-out; }

/* ── r6p41-drums · FIG. e DRUMS 16-cell K·S·H rhythm-grid substrate
   (Claude Design rev. 6 G2). Edge-to-edge per G4 lock.
   Accent by SIZE (not color) — color is spoken for (rose/role).
   State classes on .ps-drums-substrate wrapper: is-none / is-march /
   is-backbeat / is-shuffle. Hit cells fade on state switch. ── */
.ps-drums-substrate{
  width:100%; display:block; position:relative;
  transition: opacity 220ms ease;
}
/* OFF (is-none) — the empty grid recedes; no hatch, no idle text. */
.ps-drums-substrate.is-none{
  opacity:0.42;
}
.ps-drums-grid{
  display:block; width:100%; overflow:visible;
}
/* Hit circles: transition opacity for state fade (180ms out / 220ms in).
   JS staggers via a CSS custom property --hit-delay set inline. */
.ps-drums-hit{
  transition: opacity 180ms ease-out var(--hit-delay, 0ms),
              r       180ms ease-out var(--hit-delay, 0ms);
}
.ps-drums-hit.is-entering{
  transition: opacity 220ms ease-in  var(--hit-delay, 0ms),
              r       220ms ease-in  var(--hit-delay, 0ms);
}
/* IDLE state: diagonal hatch covers the grid area */
.ps-drums-hatch{
  display:none;
}
.ps-drums-substrate.is-none .ps-drums-hatch{
  display:block;
}
/* Reduce-motion: hard swap — no fade */
@media (prefers-reduced-motion: reduce){
  .ps-drums-hit,
  .ps-drums-hit.is-entering{
    transition:none !important;
  }
}

/* ── R2 Step 4 · PL. III TIMBRE rule + Voice cartouche (subordinate
   to Mode per R2.5 Q2). Hairline rule with centred caption above
   FIG. b Voice. Italic voice name one step smaller than Mode = visual
   statement of subordination. ADSR figure compressed for sidebar. ── */
.ps-mode-rule{
  display:flex; align-items:center; gap:8px;
  margin:8px 0 4px; padding:0 6px;
  height:14px;
}
.ps-mode-rule-l, .ps-mode-rule-r{
  flex:1; height:1px; background:var(--gold2); opacity:0.5;
}
.ps-mode-rule-c{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:2px; color:var(--dim2); text-transform:uppercase;
  white-space:nowrap;
}
.ps-voice-cart{
  display:flex; flex-direction:column; align-items:stretch; gap:6px;
  padding:0 4px 4px;
}
.ps-voice-name{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--text); line-height:1.1;
  text-align:left;
  cursor:pointer;
  padding:2px 4px; margin:-2px -4px;
  border-radius:2px;
  transition:background .12s;
}
.ps-voice-name:hover{ background:var(--gold-dim); }
.ps-voice-name:focus{ outline:none; }
.ps-voice-name:focus-visible{ outline:1px solid var(--gold); outline-offset:1px; }
.ps-voice-adsr{ width:100%; max-width:200px; cursor:pointer; }
.ps-voice-adsr:focus{ outline:none; }
.ps-voice-adsr:focus-visible{ outline:1px solid var(--gold); outline-offset:2px; }
.ps-voice-adsr:hover #ps-voice-adsr-curve{ filter:brightness(1.15); stroke-width:1.3; }
.ps-voice-cap{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:11px; color:var(--dim); line-height:1.35;
}
.ps-voice-btn{
  align-self:flex-start;
  background:transparent; border:0; padding:3px 6px 3px 0;
  cursor:pointer;
  font-family:'Space Mono',monospace; font-size:8.5px;
  letter-spacing:1.6px; color:var(--gold); text-transform:uppercase;
  transition:color .12s;
}
.ps-voice-btn:hover{ color:var(--gold3); }

.ps-pattern-wrap{
  display:flex; flex-direction:column; align-items:stretch; gap:8px;
  padding:2px 0;
}
/* R6.41-B.4 — edge-to-edge per rev. 5 G4. Was max-width:160px which
   centered the staff in a narrow well; the cartouche frame is the
   unit of meaning, not the diagram thumbnail. */
.ps-pattern-notation{ display:block; width:100%; }
.ps-pattern-name{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:15px; color:var(--text); line-height:1;
  align-self:center;
}

.ps-swing-wrap{
  display:flex; flex-direction:column; align-items:stretch; gap:6px;
}
/* R6.41-B.4 — edge-to-edge per rev. 5 G4. Plank ends at 8%/92% of
   cartouche width when the SVG fills the frame. */
.ps-swing-visual{
  display:block; width:100%;
  cursor:pointer; outline:none;
}
.ps-swing-visual:focus-visible{
  outline:1.5px solid var(--gold); outline-offset:2px; border-radius:2px;
}
.ps-swing-visual:hover #ps-swing-plank{ filter:brightness(1.1); }
/* R5.14 — seesaw plank tilts via inline transform set by
   _syncSwingSeesaw(). Transition makes the swing-cycle feel like a
   physical lever responding, not a snap. Same 240ms curve as the
   FX rail expansion (the codebase's canonical "single motion" ease). */
/* R6.46 — beat-driven tip uses --ease-swing (pendulum/seesaw token) */
#ps-swing-plank{
  transition:transform 160ms var(--ease-swing);
}
@media (prefers-reduced-motion: reduce){
  #ps-swing-plank{ transition:none !important; }
}
/* Legacy ruleset (R5.13 dot-shift visual) — kept as a no-op guard in case
   any old DOM still uses .ps-sw-note before the next reload. */
.ps-sw-note{ transition:transform .2s ease-out, fill .15s; }
/* R6.41-SWING-REFIT — fallback cy transition for the C ball in case
   the inline style is cleared. The JS sets a full inline transition
   (cy + r + fill + opacity) during normal operation; this is just a
   safety net. */
@media (prefers-reduced-motion: reduce){
  #ps-sw-beat-and{ transition:none !important; }
}
.ps-swing-label{
  /* R5.34 — was Space Mono caps 9px while pattern + ensemble names
     are Playfair italic 15px. Inconsistency Scott called out: "the
     thing you click is in one font and then in the other figure it's
     a different font. it's kind of foo bar." Unifying as the common
     primary-cycle label across all PL. II cartouches. */
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:15px; color:var(--text); line-height:1;
  text-transform:none; letter-spacing:0;
  align-self:center;
}

/* Integration: drop the dashed rule under the beat ruler; part of the frame. */
.plate-rhythm-ruler{ border-bottom:none; padding:8px 14px 6px; }

/* On PL. II, the above-fretboard beat ruler is primary — hide the
   redundant below-fretboard beat-dots strip to reduce chrome. */
body[data-plate-lens="II"] #play-beat-strip{ display:none; }

/* Shapes signature: on PL. I, prog card mini-diagrams shine full;
   on PL. II/III they dim slightly as a supporting role so the
   lens-specific content (ruler / scale dots) reads as primary. */
body[data-plate-lens="II"] .prog-card .pc-mini,
body[data-plate-lens="III"] .prog-card .pc-mini{
  opacity:0.45; transition:opacity .15s;
}
body[data-plate-lens="II"] .prog-card:hover .pc-mini,
body[data-plate-lens="III"] .prog-card:hover .pc-mini{
  opacity:1;
}

/* Key dial */
/* R6.31 — variable cartouche heights on PL. I sidebar. KEY (FIG. a)
   is the densest figure and the primary tool, so it scales up; CAPO
   (FIG. c) compresses to a single row (binary state — capo is either
   off or at fret N — doesn't need vertical space); VOICINGS (FIG. d)
   takes the height it needs (5 segmented rows). When total exceeds the
   viewport, the sidebar's overflow-y:auto absorbs the spill. The
   alternative (uniform heights) made the densest figure tiny and the
   sparsest (CAPO OFF) loud — wrong inversion. */
.ps-dial-wrap{
  /* R6.31 — Scott's call ("FIG. A KEY chart sized up"). R6.17's 130px
     cap solved cluster fit but the dial ended up tiny while chord cards
     on the right were 60pt — the most-data figure on the plate read as
     the smallest. CAPO compresses to one row (load 8 below), VOICINGS
     takes the height it needs, KEY scales up to 200px. Sidebar scrolls
     past the fold if cumulative height exceeds viewport (parent
     overflow-y:auto already in .plate-sidebar). 200px reads like an
     instrument dial again — the activity is tuning, the dial is the
     primary tool. */
  width:100%; max-width:200px;
  aspect-ratio:1/1;
  position:relative;
  margin:0 auto;
}
.ps-dial{ display:block; width:100%; height:100%; transform-origin:50% 50%; }

/* R5.29 — Killed the idle "breathing" animation per Scott's homecoming
   feedback ("the literally breathing wheel of fifths needs to go").
   The R4 §C baseline B liveness intent was right (dial should feel
   alive, not inert), but the constant ±2% scale read as nervous, not
   alive. R5.26's accidental-count tags + the existing chord-pulse on
   playback already make the dial feel live with intent. The breathing
   was decorative motion without function — the kind of thing the
   liveness rule (CLAUDE.md, "no static, no nervous") cuts.
   Keeping the .is-breathing class hook in JS for now (no-op) so the
   _setDialBreathing call sites don't need editing in this commit. */
.ps-dial.is-breathing { animation: none; }

/* Chord pulse — 200ms gold flash on the dial note matching the
   chord under the playhead. Same vocabulary as the chord-card
   active-bar flash: --gold3 fill, ~10% scale-up at peak. Re-
   triggered cleanly on each chord change via class toggle in JS. */
@keyframes ps-dial-note-pulse {
  0%   { transform: scale(1.0); }
  50%  { transform: scale(1.10); }
  100% { transform: scale(1.0); }
}
.ps-dial .kd-note.is-pulsing {
  animation: ps-dial-note-pulse 200ms ease-out;
  transform-origin: center;
  transform-box: fill-box;
}
.ps-dial .kd-note.is-pulsing .kd-bg{ opacity:0.9; fill:var(--gold3); }
.ps-dial .kd-note.is-pulsing .kd-txt{ fill:var(--ivory); }
@media (prefers-reduced-motion: reduce){
  .ps-dial .kd-note.is-pulsing { animation: none; }
}
.ps-dial .kd-note{ cursor:pointer; }
.ps-dial .kd-note .kd-bg{ fill:var(--gold); opacity:0; transition:opacity .15s, r .2s; }
.ps-dial .kd-note.active .kd-bg{ opacity:0.95; }
.ps-dial .kd-note .kd-txt{
  font-family:'Space Mono',monospace; font-size:10px; font-weight:700;
  fill:var(--dim); transition:fill .15s, font-size .2s;
  -webkit-user-select:none; user-select:none;
}
.ps-dial .kd-note.active .kd-txt{
  /* R5.26 — bolder active-key visual: bigger letter + ivory fill on the
     brass disc. The letter pops out of the dial as the locus of the
     player's attention. */
  fill:var(--ivory); font-size:12px;
}
.ps-dial .kd-note:hover:not(.active) .kd-txt{ fill:var(--text); }
/* R5.26 — accidental count tag (e.g. "2♯" beside D, "1♭" beside F).
   Sits radially outside the key letter, tiny Space Mono caption.
   Reads as the key signature attached to each key — clockwise gradient
   reveals the circle-of-fifths mechanism. C has no tag (the zero-
   accidental anchor — visually clean is correct). */
.ps-dial .kd-note .kd-acc{
  /* R5.33 — bumped 6.5px → 8.5px font and gold2→gold fill at higher
     opacity. Multiple Scott reports said the accidental count tags
     were not visible on prod after deploys; root cause was likely the
     6.5px font being sub-pixel-faint at the rendered dial scale. */
  font-family:'Space Mono',monospace;
  font-size:8.5px; letter-spacing:0.3px;
  font-weight:700;
  fill:var(--gold); opacity:0.92;
  -webkit-user-select:none; user-select:none;
  pointer-events:none;
  transition:fill .15s, opacity .15s;
}
.ps-dial .kd-note.active .kd-acc{ fill:var(--gold3); opacity:1; }
.ps-dial .kd-note:hover:not(.active) .kd-acc{ opacity:1; }
/* Phase 4 polish — IV·I·V brass arc + vi relative-minor dot.
   Fixed geometry centered on "top" (position 0); rotated as a group
   by _syncKeyDial. Notes stay in fixed positions so the circle of
   fifths is a stable reference; only the functional highlight moves.
   Rotation animation: 600 ms easeOutExpo — the signature moment. */
/* R5.92 — class-based selector so the rule survives tour-modal
   clones (which strip IDs). Was #ps-dial-arc-group; if both ID and
   class are present this still resolves correctly. */
.kd-arc-group{
  transform-origin:75px 75px;
  transition:transform 600ms cubic-bezier(0.19, 1, 0.22, 1);
}
/* 2026-05-21 — Autowind rotor (sidebar). Settle-on-change: snappy
   ease-out with a touch of overshoot so it reads as a mechanical part
   landing, not a UI animation. Real autowind rotor only moves when
   wrist moves; sits at rest otherwise. */
.kd-rotor-group{
  transform-origin:75px 75px;
  transition:transform 320ms cubic-bezier(0.34, 1.32, 0.4, 1);
}
/* Focus polish — kill the browser's default blue outline on mouse click
   but keep a brass focus ring for keyboard tab-through (a11y). */
.ps-dial .kd-note:focus{ outline:none; }
.ps-dial .kd-note:focus-visible .kd-bg{ opacity:1; fill:transparent; stroke:var(--gold); stroke-width:1.5; }
.ps-ladder .pl-pos:focus{ outline:none; }
.ps-ladder .pl-pos:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }
.ps-clamp-pill:focus{ outline:none; }
.ps-clamp-pill:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }
.ps-clamp-menu button:focus{ outline:none; }
.ps-clamp-menu button:focus-visible{ outline:1.5px solid var(--gold); outline-offset:1px; }

/* Position ladder — 4-col grid, 8 frets.
   R6.17 — tighter padding so FIG. b takes less vertical room and the
   K · P · C · V spine reads at glance with FIG. d's 5 sub-figs visible
   without scroll. Was padding:7px 0 (40px-tall buttons); now 4px 0
   (~30px-tall) — still tap-target sized at 30px tall for desktop. */
.ps-ladder{
  /* 2026-05-15 — was display:grid with 4 columns for the legacy
     .pl-pos button ladder. After PR #218 swapped the button row for
     the POSITION side-dot strip (one fixed-width child), the grid's
     unused columns 2-4 still ate horizontal space, pinning the strip
     flush-left in the cartouche with a ~113px void on the right.
     Flex + centre justification is the right shape for the single-
     child case; falls back gracefully if more children are added. */
  display:flex; justify-content:center; gap:3px;
}
.ps-ladder .pl-pos{
  padding:4px 0; text-align:center; cursor:pointer;
  background:transparent; color:var(--dim);
  border:1px solid var(--gold2);
  font-family:'Space Mono',monospace; font-size:11px; letter-spacing:1px;
  transition:color .12s, background .12s, border-color .12s;
}
.ps-ladder .pl-pos:hover{
  color:var(--text);
  border-color:var(--gold);
  background:rgba(154,100,32,0.06);
}
.ps-ladder .pl-pos.active{
  color:var(--gold); background:var(--gold-dim);
  border-color:var(--gold);
}

/* ── POSITION mini-fretboard substrate (r6p42-position-fretboard) ──────────
   2026-05-15 — Scott reframe: "I didnt read that as hte side of the neck.
   keep it simple. we use the fretboard to show eg close or roam too."
   Replaces the R6.42 dark-mahogany side-dot strip with the SAME vellum-
   board vocabulary as CAPO substrate (FIG. c immediately below) so PL. I
   reads one fretboard metaphor across both anchor mechanisms, not two
   parallel languages (side-view + front-view). Brass anchor bracket sits
   BEHIND the active fret wire — same brass palette as the capo bar, so
   anchor reads as a physical touchpoint on the same neck.

   Geometry: 300×84 frame (matches CAPO), 12-fret window (so position 12
   octave-anchor lands at the right edge), vellum2 board fill, GDAE
   string letters at left margin, Arabic fret numbers below at tappable
   positions only (1·2·3·4·5·7·9·12). Active fret-number swaps to brass
   + bold inside _positionStripSyncActive. */
.ps-pos-substrate{
  display:block; width:100%; max-width:300px;
  /* Centre within the cartouche body — same auto-margin recipe as CAPO
     substrate (max-width on a wider sidebar; without auto margin the
     SVG hugs the left edge). */
  margin:4px auto 2px;
  outline:none;
  border-radius:2px;
  transition: box-shadow 160ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1));
}
.ps-pos-substrate:focus-visible,
.ps-pos-substrate:focus-within{
  box-shadow:0 0 0 1.5px var(--gold3);
}
.ps-pos-substrate svg{
  display:block; width:100%; height:auto;
  user-select:none; -webkit-user-select:none;
}
.ps-pos-box-rect{
  /* Position box (hand-span) — smooth x + width transitions for the
     240ms slide animation when STATE.anchor changes. Distinct from
     CAPO's single-fret bar: this is an AREA on the neck (the hand's
     natural reach), not a touchpoint. Subtle amber-tinted fill so the
     inlay dots + fret wires inside the box still read through. */
  transition: x 240ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1)),
              width 240ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1));
  filter:drop-shadow(0 0.5px 0 rgba(58,34,8,0.2));
}
.ps-pos-fret-num{
  font-family:'Space Mono',monospace;
  transition: fill 180ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1)),
              font-weight 180ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1));
}
.ps-pos-hit:hover{
  fill:rgba(154,100,32,0.06);
}

/* Capo clamp */
.ps-clamp-sec{ position:relative; }
.ps-clamp-row{
  display:flex; align-items:center; gap:10px;
  font-family:'Space Mono',monospace; font-size:10px; color:var(--dim);
}
.ps-clamp-pill{
  padding:4px 10px; border:1px solid var(--gold2); border-radius:1px;
  letter-spacing:2px; background:transparent; color:var(--text);
  font-family:'Space Mono',monospace; font-size:10px;
  cursor:pointer; transition:border-color .12s, background .12s;
}
.ps-clamp-pill:hover{ border-color:var(--gold); background:rgba(154,100,32,0.06); }
.ps-clamp-pill.on{ border-color:var(--gold); color:var(--gold); background:var(--gold-dim); }
.ps-clamp-status{ color:var(--dim2); letter-spacing:1.4px; text-transform:uppercase; font-size:9px; }
.ps-clamp-menu{
  display:none; position:absolute; left:0; top:100%; margin-top:4px; z-index:20;
  background:var(--vellum); border:1px solid var(--gold2);
  box-shadow:0 4px 12px rgba(26,12,4,0.18), inset 0 0 0 1px rgba(240,226,190,0.55);
  padding:6px; grid-template-columns:repeat(4, 1fr); gap:3px;
  min-width:150px;
}
.ps-clamp-menu.open{ display:grid; }
.ps-clamp-menu button{
  padding:5px 0; background:transparent; border:1px solid var(--gold2);
  font-family:'Space Mono',monospace; font-size:10px; color:var(--dim);
  cursor:pointer; border-radius:1px;
}
.ps-clamp-menu button:hover{ color:var(--gold); border-color:var(--gold); background:rgba(154,100,32,0.06); }

/* C.2 (r6p41) — CAPO mini-fretboard substrate. Replaces the legacy
   pill+dropdown UI on the always-visible PL. I FIG. c CAPO cartouche.
   The capo is a physical object; the substrate draws it that way
   (Patent register). Brass bar + thumbscrew on an 8-fret neck slice.
   Bar color reuses --amber from C.5; thumbscrew uses --gold3 (brass). */
.ps-capo-substrate{
  display:block; width:100%; max-width:300px;
  /* 2026-05-15 — centre within the cartouche body. The substrate has
     max-width 300px on a ~380px sidebar; auto margins centre it
     (previously flush-left with ~68px void on the right). */
  margin:4px auto 2px;
  outline:none;
  border-radius:2px;
  /* Keyboard focus halo — gold ring on tab focus only. */
  transition: box-shadow 160ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1));
}
.ps-capo-substrate:focus-visible{
  box-shadow:0 0 0 1.5px var(--gold3);
}
.ps-capo-substrate svg{
  display:block; width:100%; height:auto;
  user-select:none; -webkit-user-select:none;
  touch-action:none;
}
.ps-capo-neck{
  fill:var(--vellum2);
}
.ps-capo-bar{
  /* Smooth attribute transitions handled inline (per-property); base
     filter for subtle felt-on-wood drop shadow. */
  filter:drop-shadow(0 0.5px 0 rgba(58,34,8,0.35));
}
.ps-capo-bar-live{
  cursor:grab;
}
.ps-capo-bar-live:active,
#ps-capo-bar-g:active .ps-capo-bar-live{
  cursor:grabbing;
}
.ps-capo-bar-ghost{
  opacity:0.5;
  pointer-events:none;
}
.ps-capo-thumbscrew{
  /* Brass cap; outlined for definition against the bar at small sizes. */
}
.ps-capo-thumbscrew-slot{
  pointer-events:none;
}
.ps-capo-fret-num{
  font-family:'Space Mono',monospace;
  transition: fill 180ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1)),
              font-weight 180ms var(--ease-thumb, cubic-bezier(0.2, 0.8, 0.2, 1));
}
.ps-capo-state-lbl{
  font-family:'Space Mono',monospace; font-size:9.5px;
  letter-spacing:1.4px; text-transform:uppercase;
  color:var(--gold);
  margin-top:2px;
}
.ps-capo-hit:hover{
  fill:rgba(154,100,32,0.06);
}

/* ── PL. II FIG. C BASS substrate — beat-grid (sibling of DRUMS) ──────
   2026-06-02 — replaces the 2-string fretboard slice. Beat columns from
   the time signature; dot height = rough register/contour. State classes
   (.is-off / .is-walking / .is-boom-chuck / .is-pulse) on the wrapper;
   OFF recedes the empty grid (no hatch, no idle text). */
.ps-bass-substrate{
  display:block; width:100%;
  margin:2px 0 2px;
  outline:none;
  transition: opacity 220ms ease;
}
.ps-bass-substrate svg{
  display:block; width:100%; height:auto;
  user-select:none; -webkit-user-select:none;
}
.ps-bass-grid{ overflow:visible; }
/* OFF — the empty grid recedes; nothing played on it yet. */
.ps-bass-substrate.is-off{
  opacity:0.42;
}
/* Beat dots fade on state switch. */
.ps-bass-substrate .ps-bass-hit{
  transition: opacity 200ms ease;
}
@media (prefers-reduced-motion: reduce){
  .ps-bass-substrate,
  .ps-bass-substrate .ps-bass-hit{
    transition: none !important;
  }
}
/* Closed-fold header — A.6 anatomy. Glyph slot + italic value name. */
.ps-bass-head-glyph{
  display:inline-flex; align-items:center;
  margin-left:6px;
  vertical-align:middle;
  flex:0 0 auto;
}
.ps-bass-head-glyph svg{
  display:block;
}
.ps-bass-head-value{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:14px; font-weight:700;
  color:var(--text);
  align-self:center;
  margin-left:auto; padding-left:6px;
  letter-spacing:0;
}
.ps-bass-head-value.is-off{
  color:var(--dim2);
  font-weight:400;
}

/* Kill the header KEY/POS chip — redundant now that the sidebar
   carries dial + ladder + clamp. */
#v2-kp-chip{ display:none !important; }

/* ── PLATE A · FIG tabs (three lenses) ─────────────────────
   The three-view framework from var-a-plate.jsx lines 82-113.
   One surface, three lenses: PL. I Shapes · PL. II Rhythm ·
   PL. III Melody. Each tab has two lines — Space Mono caps
   "PL. <roman>" over Playfair italic label. Active = brass
   background, ivory text. Vellum container with brass hairline
   border between cells. v2 killed this; we're restoring it. */
/* ── WELCOME POSTCARD retired R5.68 ─────────────────────────────
   Tour (src/tour.js) replaces it as the canonical first-visit
   orientation. CSS removed; markup removed from index.html;
   showWelcomePostcard / dismissWelcomePostcard reduced to no-op
   stubs in src/app.js for backwards compat. */

.plate-tabs{
  display:flex; align-self:center;
  margin:10px auto 8px;
  border:1px solid var(--gold2);
  background:var(--vellum);
}

/* R5.28 — plate-tab discoverability preview. Hidden by default, shown
   when any tab is hovered. Position absolute below the tab row, anchors
   horizontally to the hovered tab's center via inline `left` set in JS.
   Patent-Drawing register: vellum frame, brass border, FIG-style caption
   header, walnut text rows. Stays open on hover-out for ~120ms via the
   transition's overlap with the JS hide timer. */
.rn-tabs{ position:relative; }
.plate-tab-preview{
  position:absolute; top:100%; left:50%;
  transform:translateX(-50%) translateY(-4px);
  margin-top:6px;
  background:var(--vellum); border:1px solid var(--gold2);
  border-radius:1px;
  padding:8px 12px 9px;
  min-width:200px; max-width:300px;
  pointer-events:none;
  opacity:0; visibility:hidden;
  transition:opacity 140ms ease-out, transform 140ms ease-out, visibility 0s linear 140ms;
  z-index:50;
  box-shadow:0 6px 18px rgba(58, 36, 18, 0.10);
}
.plate-tab-preview.is-visible{
  opacity:1; visibility:visible;
  transform:translateX(-50%) translateY(0);
  transition:opacity 140ms ease-out, transform 140ms ease-out, visibility 0s;
}
.plate-tab-preview .ptp-cap{
  font-family:'Space Mono',monospace; font-size:8.5px;
  letter-spacing:2.4px; text-transform:uppercase;
  color:var(--gold); margin-bottom:6px;
  border-bottom:1px solid var(--gold-dim); padding-bottom:4px;
}
.plate-tab-preview .ptp-rows{
  display:grid; grid-template-columns:auto 1fr;
  gap:3px 14px;
  font-family:'Playfair Display',serif;
  font-size:13px; color:var(--text);
}
.plate-tab-preview .ptp-row-lbl{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.6px; text-transform:uppercase;
  color:var(--dim); align-self:center;
}
.plate-tab-preview .ptp-row-val{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--text);
  align-self:center; line-height:1.15;
}
@media (prefers-reduced-motion: reduce){
  .plate-tab-preview{ transition:opacity 0s, visibility 0s linear 0.001s; }
  .plate-tab-preview.is-visible{ transition:opacity 0s, visibility 0s; }
}
.plate-tab{
  display:flex; flex-direction:column; align-items:center; gap:4px;
  padding:10px 22px 8px;
  min-width:108px;
  background:transparent; border:none; cursor:pointer;
  color:var(--gold); position:relative;
  transition:color .15s, background .15s, border-color .15s;
}
.plate-tab + .plate-tab{ border-left:1px solid var(--gold2); }
.plate-tab:hover:not(.on){
  background:color-mix(in srgb, var(--gold) 7%, transparent);
  color:var(--text);
}
.plate-tab.on{
  background:var(--ivory);
  color:var(--text);
  box-shadow:inset 0 3px 0 var(--gold);
}
.plate-tab-glyph{
  width:44px; height:26px;
  display:block;
  color:inherit;
  transition:color .15s;
}
.plate-tab-num{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:2.4px; text-transform:uppercase;
  color:var(--gold-ink);   /* contrast: was inherited gold 3.52:1 on the header */
  opacity:0.9;
}
.plate-tab.on .plate-tab-num{ opacity:0.9; }
.plate-tab-label{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:15px; line-height:1; letter-spacing:0.3px;
  color:var(--gold-ink);   /* contrast */
}
.plate-tab:focus{ outline:none; }
.plate-tab:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }

/* ── PLATE A · progression chord cards (FIG. IV) ─────────────
   Below the Play button: the real primitive from welcome.jsx
   callout 4 + var-a-plate mini-schematic — each chord is a
   small card with italic roman, Space Mono 700 chord name, and
   "BAR N" engineering label. Active card gets 3 px brass top
   bar matching the voicing-card / tune-card pattern. Tap to
   jump the transport (playGoTo). Phrase-boundary grouping uses
   the song form data already computed in render.js: a brass
   hairline drawn between cards at the AABB phrase break turns
   the tune's form into visible ink. (Craft §2.)
   Supersedes the prog-dot placeholder (commit c92f694). */
.prog-card-row{
  display:flex; flex-wrap:wrap; align-items:stretch;
  gap:5px; justify-content:center;
}
.prog-card{
  display:flex; flex-direction:column; gap:4px;
  min-width:84px; padding:4px 8px 4px;
  background:transparent;
  border:1px solid var(--gold2); border-radius:0;
  cursor:pointer; position:relative;
  transition:border-color .12s, background .12s;
  user-select:none;
}
.prog-card:hover{
  border-color:var(--gold); background:rgba(154,100,32,0.06);
}
.prog-card.active{
  border-color:var(--gold); background:var(--gold-dim);
}
.prog-card.active::before{
  content:""; position:absolute; top:-1px; left:-1px; right:-1px;
  height:2px; background:var(--gold);
}
.prog-card .pc-head{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:8px;
}
.prog-card .pc-roman{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:14px; color:var(--dim); line-height:1;
}
.prog-card.active .pc-roman{ color:var(--gold); font-weight:700; }
.prog-card .pc-name{
  font-family:'Space Mono',monospace; font-weight:700;
  font-size:10.5px; color:var(--text); letter-spacing:0.3px;
  line-height:1;
}
/* Mini chord diagram — dots are colored by interval role (root,
   3rd, 5th, etc.) and labeled with note names inside. Fill is
   set inline per-dot by miniChordDiagram; CSS only modulates
   opacity for active/inactive cards. */
.prog-card .pc-mini{
  display:block; width:100%; height:auto;
}
/* Sharp at rest — dots always full opacity. Scott: "the chord charts
   should look sharp all the time, not only on hover." */
.prog-card .pc-mini-dot{ opacity:1; }
/* PL. II / III: diagrams render alongside other primary primitives
   (pendulum, mode pills). Keep them readable at rest, lift on hover. */
body[data-plate-lens="II"] .prog-card .pc-mini,
body[data-plate-lens="III"] .prog-card .pc-mini{
  opacity:0.85;
}
body[data-plate-lens="II"] .prog-card:hover .pc-mini,
body[data-plate-lens="III"] .prog-card:hover .pc-mini{
  opacity:1;
}
/* Phrase boundary — thin brass hairline between cards.
   Song form (AABB) becomes visible ink (Craft §2). */
.prog-phrase-rule{
  align-self:stretch; width:1px; background:var(--gold2);
  opacity:0.4; margin:0 5px;
}
.prog-card:focus{ outline:none; }
.prog-card:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }

/* ── PL. II Rhythm · prog timeline tile ──────────────────────
   On PL. II the progression row switches from "chord vocabulary"
   (wide diagramed cards) to "bar-by-bar timeline" (thin tiles,
   one per bar). Shapes-lens content is chord shapes; Rhythm-lens
   content is time. Different lens, different treatment. */
.prog-bar{
  display:flex; align-items:center; justify-content:center;
  min-width:36px; padding:6px 8px;
  background:transparent;
  border:1px solid var(--gold2); border-radius:0;
  cursor:pointer; position:relative;
  transition:border-color .12s, background .12s;
  user-select:none;
}
.prog-bar:hover{ border-color:var(--gold); background:rgba(154,100,32,0.06); }
.prog-bar.active{ border-color:var(--gold); background:var(--gold-dim); }
.prog-bar.active::before{
  content:""; position:absolute; top:-1px; left:-1px; right:-1px;
  height:2px; background:var(--gold);
}
.prog-bar .pb-roman{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:13px; color:var(--dim); line-height:1;
}
.prog-bar.active .pb-roman{ color:var(--gold); font-weight:700; }
.prog-bar:focus{ outline:none; }
.prog-bar:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }

/* ── PLATE A · Phase 7b · hot-cell voicings popover ────────────
   R5.1 (2026-05-02) — popover stops floating; content moves into
   the right rail via _openHotcellVoicingsInRail. The element stays
   in the DOM as the children-source/children-restore home, but is
   never visible (display:none) since children render via rail mount.
   Old position:fixed / .open class behavior retired. */
#hotcell-voicings-popover{ display:none; }
.hotcell-voicings-rail-mount{
  display:flex; flex-direction:column;
  background:var(--vellum); padding:0;
  max-height:62vh; overflow-y:auto; overflow-x:hidden;
}
.plate-right-rail .hcv-rail-wrap{
  display:flex; flex-direction:column; gap:8px;
}
/* R5.98 — "Tune the engine ▾" collapsible toggle and mount.
   Sits below the voicings cards. Collapsed by default — most users
   pick a voicing and don't need the engine settings. The toggle is
   a horizontal divider with text and a chevron, low visual weight,
   so it doesn't compete with the picker above. */
.hcv-engine-toggle{
  display:flex; align-items:baseline; gap:10px;
  width:100%;
  padding:10px 12px;
  margin-top:14px;
  background:transparent;
  border:none;
  border-top:1px solid var(--gold2);
  border-bottom:1px solid transparent;
  cursor:pointer;
  text-align:left;
  font-family:'Space Mono',monospace;
  color:var(--dim2);
  transition:background .15s, color .15s;
}
.hcv-engine-toggle:hover{
  background:rgba(232,199,106,0.06);
  color:var(--gold);
}
.hcv-engine-toggle:focus{ outline:none; }
.hcv-engine-toggle:focus-visible{
  outline:1.5px solid var(--gold); outline-offset:-2px;
}
.hcv-engine-glyph{
  display:inline-block;
  font-size:10px; line-height:1;
  color:var(--gold);
  transition:transform .2s ease;
  flex:0 0 auto;
}
.hcv-engine-toggle.is-open .hcv-engine-glyph{
  transform:rotate(90deg);
}
.hcv-engine-lbl{
  font-size:10px; letter-spacing:2px; text-transform:uppercase;
  color:var(--gold);
  flex:0 0 auto;
}
.hcv-engine-sub{
  flex:1; text-align:right;
  font-size:9px; letter-spacing:1.4px; text-transform:lowercase;
  color:var(--dim2);
  font-style:italic;
}
.hcv-engine-mount{
  padding:8px 4px 14px;
  border-bottom:1px solid var(--gold2);
}
.hcv-engine-mount[hidden]{ display:none; }
/* The t3-voicing-panel children come over with their original
   .ctrl-section / .ctrl-switch / .ctrl-divider markup. Slim the
   spacing for the rail context (was designed for a wider panel). */
.hcv-engine-mount .ctrl-section{
  padding:6px 4px;
}
.hcv-engine-mount .ctrl-section-lbl{
  font-size:9px; letter-spacing:1.4px;
  margin-bottom:4px;
}
.hcv-engine-mount .ctrl-divider{
  display:none; /* the section padding alone separates them in the rail */
}
/* R5.98 — task-group sub-headers separating Scott's three-task
   decomposition: Task 2 (how they play together — voice-leading,
   root in bass) and Task 3 (player's physical preference — roam,
   shape, strings). One panel, two clearly-labeled rooms inside. */
.hcv-engine-mount .hcv-task-group{
  display:flex; flex-direction:column;
  margin-bottom:14px;
}
.hcv-engine-mount .hcv-task-group:last-child{
  margin-bottom:0;
}
.hcv-engine-mount .hcv-task-hd{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:13px;
  color:var(--gold);
  padding:4px 4px 6px;
  border-bottom:1px solid var(--gold-dim);
  margin-bottom:6px;
}
/* When the popover children live in the rail, narrow the layout to
   fit. Voicings cards stack vertically (the rail is taller than wide). */
.plate-right-rail .hcv-body{
  display:flex !important; flex-direction:column !important;
  gap:10px !important;
}
.plate-right-rail .hcv-voicing{
  width:100% !important; max-width:100% !important;
}
#hotcell-voicings-popover .hcv-head{
  display:flex; flex-direction:column; align-items:stretch;
  gap:6px; margin-bottom:12px; padding-bottom:10px;
  border-bottom:1px solid var(--gold2);
}
#hotcell-voicings-popover .hcv-head .fig-banner{
  font-size:10px; letter-spacing:2.8px; gap:8px; flex:0 0 auto;
}
#hotcell-voicings-popover .hcv-hdr-lbl{ color:var(--gold); }
/* R5.91 — name + function badge centered between ◀ ▶ nav buttons.
   Counter sits on its own line below as plain prose. */
#hotcell-voicings-popover .hcv-chord-row{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:14px;
}
#hotcell-voicings-popover .hcv-chord-name{
  flex:1; text-align:center; display:flex; align-items:baseline;
  justify-content:center; gap:8px;
}
#hotcell-voicings-popover .hcv-nav{
  background:transparent; border:1px solid var(--gold2); border-radius:2px;
  color:var(--gold); font-size:12px; line-height:1;
  padding:5px 9px; cursor:pointer; transition:all .12s;
  font-family:'Space Mono',monospace;
  flex:0 0 auto;
}
#hotcell-voicings-popover .hcv-nav:hover{
  background:var(--gold-dim); border-color:var(--gold);
}
#hotcell-voicings-popover .hcv-nav:focus{ outline:none; }
#hotcell-voicings-popover .hcv-nav:focus-visible{
  outline:1.5px solid var(--gold); outline-offset:2px;
}
/* R5.91 — counter restyled from coded mono-uppercase ("1 / 4 · 11×")
   to plain prose ("Chord 1 of 4 · played 11 times in this song").
   No uppercase, no letter-spacing, italic serif to read as caption. */
#hotcell-voicings-popover .hcv-chord-idx{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:11px; color:var(--dim2); text-align:center;
  letter-spacing:0; text-transform:none; line-height:1.3;
}
#hotcell-voicings-popover #hcv-name{
  font-family:'Playfair Display',serif; font-weight:700;
  font-size:28px; color:var(--text); line-height:1;
}
/* R5.91 — roman demoted to supporting badge after the chord name,
   wrapped in parens via JS: "D (I)". Smaller, gold, italic. */
#hotcell-voicings-popover #hcv-roman{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:15px; color:var(--gold); line-height:1;
  letter-spacing:0.5px;
}
#hotcell-voicings-popover .hcv-close{
  flex:0 0 auto; background:transparent; border:0;
  color:var(--dim2); font-size:22px; line-height:1;
  cursor:pointer; padding:0 4px; transition:color .1s;
}
#hotcell-voicings-popover .hcv-close:hover{ color:var(--gold); }
#hotcell-voicings-popover .hcv-body{
  display:flex; gap:14px; flex-wrap:wrap; justify-content:center;
}
.hcv-voicing{
  flex:0 0 auto; width:180px;
  border:1px solid var(--gold2); padding:10px 10px 12px;
  background:transparent; cursor:pointer;
  transition:border-color .12s, background .12s;
  position:relative;
}
.hcv-voicing:hover{ border-color:var(--gold); background:rgba(154,100,32,0.06); }
.hcv-voicing.primary{
  background:var(--gold-dim);
  border-color:var(--gold);
}
/* Brass top bar on primary — the spec's "this is the one" signal.
   Matches Plate A chord-card pattern in HANDOFF §10. */
.hcv-voicing.primary::before{
  content:""; position:absolute; top:-1px; left:-1px; right:-1px;
  height:3px; background:var(--gold);
}
.hcv-voicing .hcv-v-label{
  font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:2.2px; text-transform:uppercase;
  color:var(--dim2); margin-bottom:6px;
}
.hcv-voicing.primary .hcv-v-label{ color:var(--gold); font-weight:700; }
.hcv-voicing svg{ display:block; width:100%; }
.hcv-voicing .hcv-v-tab{
  margin-top:6px; font-family:'Space Mono',monospace; font-size:11px;
  letter-spacing:1.2px; color:var(--dim); text-align:center;
}
.hcv-voicing .hcv-v-range{
  margin-top:3px; font-family:'Space Mono',monospace; font-size:9px;
  letter-spacing:1.6px; color:var(--dim2); text-transform:uppercase;
  text-align:center;
}
.hcv-voicing:focus{ outline:none; }
.hcv-voicing:focus-visible{ outline:1.5px solid var(--gold); outline-offset:2px; }

/* ══════════════════════════════════════════════════════
   THREE-TIER VISUAL WEIGHT SYSTEM — Panel consensus
   T1 = 100% (fretboard, dashboard, play)
   T2 = 72%  (active nav, transport, mode pills)
   T3 = 35% → hover 100% (all chrome, settings, strip)
   ══════════════════════════════════════════════════════ */

/* NAV — inactive tabs very dim, active bright */
.unified-nav { background:rgba(13,12,26,0.9); }
.unified-nav .unav-btn {
  opacity: 0.35;
  transition: opacity .15s, color .15s;
}
.unified-nav .unav-btn.on  { opacity: 1; }
.unified-nav .unav-btn:hover { opacity: 0.72; }

/* TRANSPORT ◀ ▶ — Tier 2 */
.play-step-btn { opacity: 0.72; transition: opacity .15s; }
.play-step-btn:hover { opacity: 1; }

/* STATUS STRIP — Tier 3, hover to reveal */

/* Left cluster (load-bearing: Piano · Arpeggio · tempo) always full */
#strip-zone-voice { opacity: 1; }

/* LEGEND, BEAT DOTS — Tier 3.
   A.11 — #play-prog-dots removed from this group. It's the CHORD CARDS
   container, which is 1/3 of the tool (PL. I Shapes' main feature), not
   secondary chrome. Was accidentally getting the 0.35 "whisper" treatment
   alongside legend/beat-strip; now full opacity. */
.legend, .neck-beat-strip, #play-beat-strip,
.beat-gear-row { opacity: 0.35; transition: opacity .15s; }
.legend:hover, .neck-beat-strip:hover { opacity: 1; }

/* DISPLAY TOGGLES (GHOSTS 3D A+) — Tier 3 */
.trails-toggle, #perspective-toggle-2, .font-size-btn {
  opacity: 0.35 !important; transition: opacity .15s;
}
.trails-toggle:hover, #perspective-toggle-2:hover, .font-size-btn:hover {
  opacity: 1 !important;
}

/* SAVE / SHARE — Tier 3 */
#undo-btn, button[onclick="saveToLibrary()"] {
  opacity: 0.35; transition: opacity .15s;
}
#undo-btn:hover, button[onclick="saveToLibrary()"]:hover { opacity: 1; }

/* DASHBOARD — Tier 1, always full */
.play-dashboard { opacity: 1 !important; }

/* RHYTHM INLINE CONTROLS — Tier 1, load-bearing */
#rhythm-inline-controls { opacity: 1; }

/* FRETBOARD — never dimmed */
#play-neck-wrap, #sx-neck-wrap { opacity: 1 !important; }

/* ── Melody tab: tighten transport and mode bar ─────────── */
.sx-player-row { padding: 2px 0; flex-shrink: 0; }
.sx-stepper { gap: 6px; }
.neck-beat-strip { padding: 2px 0 1px; }
#sx-scale-strip, #play-beat-strip { padding: 0; }

/* ── V2: Fretboard-First Architecture ──────────────────────────── */

/* Tab row hidden — JS compat preserved, fretboard takes the space */
.unified-nav { display: none !important; }

/* Dashboard tiles hidden — key/pos now in header */
.play-dashboard { display: none !important; }

/* sub-play is now the permanent default view */
#sub-play  { display: flex !important; flex-direction: column; flex: 1; }
#sub-charts { display: none !important; }
#sub-scale  { display: none !important; }

/* When scale mode is active, override above */
#sub-play.v2-scale-mode  { display: none !important; }
#sub-scale.v2-scale-active { display: flex !important; flex-direction: column; flex: 1; }

/* Fretboard fills everything between header and footer */
#pane-progressions {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding: 10px 26px 12px 26px;
  position: relative;            /* positioning context for .plate-frame */
}

/* ── Plate frame — the locked double-hairline brass rule (DESIGN-LOG).
   r6p73 Stage 1 of the Unified Plate Skeleton: gives the plate its walls.
   Overlay only (pointer-events:none, absolute) so it never touches the
   pane's flex layout. Content is held off the frame by the pane padding
   above. Encloses the plate content (rail + canvas + progression);
   the header sits above the pane and the pedalboard below, both outside
   the frame, per the content-vs-chrome split (OQ-3). ── */
.plate-frame {
  position: absolute;
  inset: 20px 16px 20px 16px;   /* floats evenly — top and bottom match, clear of the PLAY bar */
  border: 1px solid rgba(106, 64, 16, 0.60);   /* --gold2, outer rule */
  pointer-events: none;
  z-index: 6;
}
.plate-frame::after {
  content: '';
  position: absolute;
  inset: 4px;
  border: 1px solid rgba(106, 64, 16, 0.30);   /* --gold2, inner rule */
}

/* Key·Position chip in header — dashboard-readable at a glance */
.v2-kp-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: 'Space Mono', monospace;
  font-size: 14px;
  color: var(--dim);
  cursor: pointer;
  padding: 4px 12px;
  border: 1px solid rgba(232,199,106,0.25);
  border-radius: 20px;
  transition: all 0.15s;
  white-space: nowrap;
  flex-shrink: 0;
  background: rgba(232,199,106,0.04);
}
.v2-kp-chip:hover { color: var(--gold); border-color: var(--gold); background: rgba(232,199,106,0.08); }
.v2-kp-chip .v2-kp-key { color: var(--gold); font-weight: 700; font-size: 16px; }

/* Chrome rail buttons — shared style for all 5 (Modes / Shapes / Ghosts / 3D / Box).
   State colors live here so .on / .active / .scale-active classes show current status. */
.chrome-rail-btn {
  background: transparent;
  border: 1px solid var(--gold2);
  color: var(--text);
  font-family: 'Space Mono', monospace;
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  padding: 6px 10px;
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.15s;
  min-width: 80px;
  text-align: center;
  line-height: 1;
}
.chrome-rail-btn:hover {
  background: var(--gold-dim);
  border-color: var(--gold);
}
.chrome-rail-btn.on,
.chrome-rail-btn.active,
.chrome-rail-btn.scale-active {
  background: var(--gold);
  color: var(--ivory);
  border-color: var(--border2);
}

/* Fretboard-body responsive — bound the horizontal extent so wide screens
   don't strand the fretboard in empty lichen, and narrow screens don't clip
   the left rail off-viewport. Sidebar (Plate A Phase 4) now anchors the left
   edge, so the cap can be generous without stranding. */
#fretboard-body {
  max-width: 1600px;
  margin: 0 auto;
  width: 100%;
  padding: 4px 14px 0;
  box-sizing: border-box;
}
@media (max-width: 900px) {
  /* Narrow screen: rail becomes a horizontal row above the fretboard */
  #fretboard-body { flex-direction: column; align-items: center; gap: 10px; }
  #fretboard-rail { flex-direction: row; gap: 8px; width: 100%; justify-content: center; }
  #fretboard-rail > div { flex-direction: row; gap: 4px; padding: 4px 8px; }
  .chrome-rail-btn { min-width: 64px; padding: 5px 8px; font-size: 10px; letter-spacing: 1.5px; }
}

/* Legacy rules retained for non-rail uses; rail version wins via class specificity */
#v2-mode-toggle.scale-active { color: var(--ivory); border-color: var(--border2); }

/* Shapes overlay — REPLACES fretboard when open */
#v2-shapes-overlay {
  display: none;
  flex-direction: row;
  gap: 10px;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap;
  padding: 12px;
  min-height: 200px;
}
#v2-shapes-overlay.open { display: flex; }
/* When shapes open, hide the fretboard layers */
#v2-shapes-overlay.open ~ #play-grid-svg,
#v2-shapes-overlay.open ~ #play-trails,
#v2-shapes-overlay.open ~ #play-scale-layer,
#v2-shapes-overlay.open ~ #play-dots-layer,
#v2-shapes-overlay.open ~ #melody-dot-layer,
#v2-shapes-overlay.open ~ #count-in-overlay { display: none !important; }

/* Shapes toggle legacy rule — kept so any non-rail usage still compiles */
#v2-shapes-toggle.active { color: var(--ivory); border-color: var(--border2); }

/* Scale mode strip — embedded at bottom of fretboard zone in scale mode */
#v2-scale-strip {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  justify-content: center;
  flex-wrap: wrap;
  border-top: 1px solid var(--border);
  background: rgba(14,12,24,0.6);
}

/* ── V2: Additional overrides ─────────────────────────────────────── */

/* Sidebar hidden — key/pos now in header chip + pedal strip */
.play-sidebar { display: none !important; }

/* Legends hidden — fretboard dots are self-labeling (R/3/5/b7) */
.legend { display: none !important; }

/* Fretboard region: vertically centered in the available space */
#fretboard-region {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 0;
}

/* r6p96 — PL. I cards CENTER in the region, like PL. II / III.
 * (Was flex-start under r6p72a, to stop the tall chord-card head
 * from overflowing ABOVE the viewport edge. That concern is moot
 * since r6p96-fit: the fit-to-screen zoom now shrinks the whole
 * canvas to fit, so nothing overflows the top.) Centering the
 * exhibit lets the chip strip pin to one baseline across all three
 * plates (see #sub-play below) — the "welded trio, pinned chips"
 * composition the five lenses landed on (Tufte: small multiples,
 * fixed frame; FLW: the chips are the ground line; Julin: the
 * chart stays on the stand; Norman/Resnick: stable spatial map). */
body[data-plate-lens="I"] #fretboard-region {
  justify-content: center;
}

/* r6p72a — PL. I reclaims most of play-main's 120 px bottom
 * padding so the action stage has the height it needs for the
 * 380-px-tall chord cards. The 120 was clearance under a wider
 * pedal-strip era; with the current single-row bottom toolbar
 * (~100 px) sitting OUTSIDE play-main, 40 px is sufficient
 * breathing room. Net: claims 80 px back for the cards stage. */
body[data-plate-lens="I"] .play-main {
  padding-bottom: 40px;
}

/* r6p96 — PL. I action stage FILLS the space above the chip strip,
 * exactly like PL. II / III (was flex:0 0 auto under r6p72a, which
 * sized #sub-play to the cards and let play-main center the whole
 * [cards + chips] unit — so the chips floated to a different
 * baseline than the other two plates). Filling here pins the chip
 * strip to one baseline on every plate: the exhibit centers in the
 * filled region above, the chips sit at the bottom, identical
 * across Shapes / Rhythm / Color. Nothing jumps when you riffle
 * the tabs. */
body[data-plate-lens="I"] #sub-play {
  flex: 1 1 auto;
}
body[data-plate-lens="I"] .plate-prog-strip-wrap {
  flex: 0 0 auto;
  margin-top: 0;
  padding-top: 0;
}

/* r6p72a — chord set = action stage + chord chips as ONE
 * composition. Scott's call: "the chord chips are a component
 * of the chord charts · they should sit just below at a
 * comfortable spacing · thin space above and below the
 * cards/chips set · same goes for the other tabs." Applies
 * universally across PL. I / II / III: hide the disconnecting
 * chrome (PROGRESSION banner + TAP A CHORD hint) so the chips
 * sit immediately under their action surface as one visual
 * block. lock-all migrates into the active card chrome in
 * r6p72b — per-card lock already exists. */
.plate-prog-banner,
.plate-prog-hint{
  display: none !important;
}
.plate-prog-strip-wrap{
  margin: 0 auto !important;
  padding-top: 12px !important;
  border-top: 0 !important;
}

/* ── r6p78 STAGE GRID — the governing system (replaces the per-element tweaks).
   Heuristics (Scott's "golden mean / what centers with what"):
   • The STAGE is play-main — the frame interior MINUS the rail. Everything
     centers on the stage axis, not the frame center (the rail offsets it).
   • The progression is a cohesive centered GROUP on that same axis as the
     cards above — they share a centre line. No edge-stretch, so the "+" stays
     inside the group (adjacent to section B) and never floats to the margin.
   • One module: chip width = card ÷ 3 (240→80). Gaps on an 8px scale.
   ──────────────────────────────────────────────────────────────────────── */
body[data-plate-lens="I"] .plate-prog-strip-wrap{
  width: auto; max-width: none !important;
  margin: 0 auto !important;       /* centred on the stage axis, same as the cards */
  padding: 16px 0 0;
}
body[data-plate-lens="I"] #plate-prog-strip{ justify-content: center; gap: 40px; }   /* 40 = 5×8 */
body[data-plate-lens="I"] .plate-prog-section{ flex: 0 0 auto; max-width: none; }      /* content width — no stretch */
body[data-plate-lens="I"] .plate-prog-section-rows{ flex: 0 0 auto; width: auto; }
body[data-plate-lens="I"] .plate-prog-phrase-row{ justify-content: center; gap: 8px; }
body[data-plate-lens="I"] .plate-prog-phrase-row > .plate-prog-chip{
  flex: 0 0 auto; width: 56px; min-width: 56px; max-width: 56px;   /* = card ÷ 3 (168/3), uniform */
}


/* play-neck-wrap fills available space */
#play-neck-wrap {
  flex-shrink: 1;
  transition: width 0.15s ease;
}

/* ── V2: Popover basics — JS handles positioning ── */
#pedal-popover {
  overflow-y: auto !important;
}
#kp-picker {
  overflow-y: auto !important;
}

/* ══════════════════════════════════════════════════════════════════
   R-tour-kill — Spotlight chooser (replaces src/tour.js)
   ════════════════════════════════════════════════════════════════ */

.spotlight-modal{
  position:fixed; inset:0;
  z-index:8500;
  display:flex; align-items:center; justify-content:center;
  background:rgba(28,16,8,0.72);
  opacity:0; pointer-events:none;
  /* r6p43-catalog-x-close: slower fade so the eye can follow the
     modal-close → spotlight-ring-on hand-off. Scott: "the modals
     disappear before you have to for your eye to see oh the catalog
     closed and now it's showing me where it is." */
  transition:opacity 280ms ease;
}
.spotlight-modal.spotlight-visible{
  opacity:1; pointer-events:auto;
}
.spotlight-inner{
  background:var(--vellum);
  border:1px solid var(--gold2);
  border-radius:2px;
  width:min(520px, calc(100vw - 40px));
  max-height:calc(100vh - 80px);
  display:flex; flex-direction:column;
  overflow:hidden;
  box-shadow:0 8px 32px rgba(28,16,8,0.55);
}
.spotlight-hdr{
  padding:18px 20px 10px 20px;
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:17px;
  color:var(--gold);
  border-bottom:1px solid var(--gold2);
  flex-shrink:0;
  /* 2026-05-15 — close ✕ button rides the right edge. Was Esc-only;
     Scott: "why no close button?" */
  display:flex; align-items:center; justify-content:space-between;
  gap:12px;
}
.spotlight-close{
  background:transparent;
  border:1px solid var(--gold2);
  color:var(--gold);
  width:26px; height:26px;
  border-radius:50%;
  font-family:'Space Mono', monospace;
  font-size:13px;
  line-height:1;
  cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center;
  padding:0;
  transition:background .15s, color .15s, border-color .15s;
}
.spotlight-close:hover{ background:var(--gold); color:var(--vellum, #efe6cf); }
.spotlight-close:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.spotlight-body{
  overflow-y:auto;
  flex:1 1 auto;
  padding:8px 0 8px 0;
}
.spotlight-body::-webkit-scrollbar{ width:6px; }
.spotlight-body::-webkit-scrollbar-track{ background:transparent; }
.spotlight-body::-webkit-scrollbar-thumb{ background:var(--gold2); border-radius:3px; }
/* r6p43-catalog-tiered — Two-tier accordion. Scott 2026-05-17:
   "looking at it is like looking at a menu and you get overwhelmed...
   with glyphs even tiered?" Tier 1 is the group card (Global · Shapes
   · Rhythm · Color · Workshop); Tier 2 expands inline on click. Brass
   anatomy glyphs on every item — chassis-row miniatures where they
   exist, simple Patent-register shapes elsewhere. */
.sp-card{
  border-bottom:1px solid rgba(154,100,32,0.18);
}
.sp-card:last-child{ border-bottom:none; }
.sp-card-head{
  display:flex;
  align-items:center;
  gap:10px;
  width:100%;
  background:none;
  border:none;
  cursor:pointer;
  padding:12px 20px;
  text-align:left;
  transition:background 120ms;
  font-family:inherit;
  color:inherit;
}
.sp-card-head:hover{ background:rgba(180,140,60,0.06); }
.sp-card-head:focus-visible{
  outline:2px solid var(--gold);
  outline-offset:-3px;
}
.sp-card-title{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:18px;
  color:var(--ink);
  letter-spacing:0.1px;
  flex-shrink:0;
}
.sp-card-plate{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--gold2);
  flex-shrink:0;
  padding:2px 6px;
  border:1px solid var(--gold2);
  border-radius:1px;
  opacity:0.7;
}
.sp-card-preview{
  display:flex;
  gap:4px;
  flex:1 1 auto;
  align-items:center;
  margin-left:6px;
  min-width:0;
}
.sp-preview-glyph{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:18px;
  height:18px;
  opacity:0.7;
  transition:opacity .15s ease;
}
.sp-card-head:hover .sp-preview-glyph{ opacity:1; }
.sp-card.sp-open .sp-card-preview{ opacity:0.35; }
.sp-card-count{
  font-family:'Space Mono', monospace;
  font-size:10.5px;
  color:var(--dim2);
  letter-spacing:0.5px;
  flex-shrink:0;
  min-width:18px;
  text-align:right;
}
.sp-card-caret{
  font-size:13px;
  color:var(--gold);
  flex-shrink:0;
  transition:transform .2s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.sp-card.sp-open .sp-card-caret{ transform:rotate(180deg); }
.sp-card-body{
  max-height:0;
  overflow:hidden;
  transition:max-height .3s cubic-bezier(0.2, 0.8, 0.2, 1);
  background:rgba(248,242,210,0.35);
}
.sp-card.sp-open .sp-card-body{
  max-height:600px;
}
.sp-row{
  display:flex;
  align-items:flex-start;
  gap:12px;
  width:100%;
  background:none;
  border:none;
  cursor:pointer;
  padding:10px 20px 10px 28px;
  text-align:left;
  transition:background 120ms;
  font-family:inherit;
  color:inherit;
}
.sp-row:hover{ background:rgba(180,140,60,0.10); }
.sp-row:focus-visible{
  outline:1px solid var(--gold2);
  outline-offset:-2px;
}
.sp-row-glyph{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:22px;
  height:22px;
  flex-shrink:0;
  margin-top:2px;
}
.sp-row-text{
  display:flex;
  flex-direction:column;
  gap:2px;
  min-width:0;
  flex:1 1 auto;
}
.sp-row-primary{
  font-family:'Playfair Display', serif;
  font-size:14px;
  color:var(--ink);
  display:inline;
}
.sp-row-secondary{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.2px;
  text-transform:uppercase;
  color:var(--dim2);
  margin-left:8px;
}
.sp-row-gloss{
  font-family:'Space Mono', monospace;
  font-size:10px;
  color:var(--dim2);
  line-height:1.4;
  margin-top:2px;
  white-space:normal;
}
.spotlight-ftr{
  padding:8px 20px 12px 20px;
  font-family:'Space Mono',monospace;
  font-size:9px;
  letter-spacing:0.1em;
  text-transform:uppercase;
  color:var(--dim2);
  border-top:1px solid var(--gold2);
  flex-shrink:0;
}
.spotlight-ring{
  border:2px solid var(--gold);
  border-radius:4px;
  box-shadow:0 0 0 4px rgba(180,140,60,0.22);
  opacity:0;
  transition:opacity 200ms;
}
.spotlight-ring.spotlight-ring-on{ opacity:1; }
.spotlight-gloss-card{
  background:var(--vellum);
  border:1px solid var(--gold2);
  border-radius:2px;
  padding:7px 10px 7px 12px;
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:13px;
  color:var(--ink);
  max-width:260px;
  box-shadow:0 4px 12px rgba(28,16,8,0.35);
  opacity:0;
  /* r6p43-catalog-x-close: slower fade so the hand-off from modal
     close → spotlight ring on is perceptible. */
  transition:opacity 280ms ease;
  /* Layout: text on the left, close button on the right */
  display:flex;
  align-items:flex-start;
  gap:8px;
}
.spotlight-gloss-card.spotlight-ring-on{ opacity:1; }
.spotlight-gloss-text{
  flex:1 1 auto;
  min-width:0;
}
.spotlight-gloss-close{
  flex:0 0 auto;
  background:transparent;
  border:1px solid var(--gold2);
  color:var(--gold);
  width:20px; height:20px;
  border-radius:50%;
  font-family:'Space Mono', monospace;
  font-style:normal;
  font-size:11px;
  line-height:1;
  cursor:pointer;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  padding:0;
  margin-top:-1px;
  transition:background .15s, color .15s, border-color .15s;
}
.spotlight-gloss-close:hover{
  background:var(--gold);
  color:var(--vellum);
}
.spotlight-gloss-close:focus-visible{
  outline:2px solid var(--gold);
  outline-offset:2px;
}

/* ════════════════════════════════════════════════════════════════
   R6.40d — FIG. d.3 BASS BEHAVIOR substrate
   ════════════════════════════════════════════════════════════════ */
.bass-exhibit{
  display:flex; flex-direction:column; gap:10px;
  padding:10px 12px 12px;
}
/* C.1 — d.3 BASS BEHAVIOR is now picker-only (Claude Design rev. 3 reframe).
   Two-cell row, dot indicator + main label + sub-label per cell. The old
   .bass-rows / .bass-row / .bass-cell letter-grid styles below are dead code
   left in place for now — will be GC'd in a later cleanup pass. */
.bass-picker-exhibit{
  display:flex; flex-direction:column; gap:8px;
  padding:6px 0 0;
}
.bass-picker-row{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:6px;
  padding:0;
}
.bass-picker-cell{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:3px;
  padding:10px 8px 8px;
  border:1px solid var(--gold2);
  background:var(--vellum2);
  border-radius:1px;
  cursor:pointer;
  transition:border-color 120ms var(--ease-thumb), background 120ms var(--ease-thumb);
  font-family:inherit;
}
.bass-picker-cell:hover{
  background:var(--vellum);
}
.bass-picker-cell.on{
  border-color:var(--gold);
  border-width:1.5px;
  background:var(--ivory);
  margin:-0.5px;
}
.bass-cell-glyph-svg{
  display:block;
  margin-bottom:3px;
  opacity:0.55;
  transition:opacity 120ms var(--ease-thumb);
}
.bass-picker-cell.on .bass-cell-glyph-svg{
  opacity:1;
}
.bass-picker-label{
  font-family:'Space Mono',monospace;
  font-size:10.5px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--dim2);
  line-height:1.2;
  white-space:nowrap;
}
.bass-picker-cell.on .bass-picker-label{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:700;
  font-size:14px;
  letter-spacing:0;
  text-transform:none;
  color:var(--text);
}
.bass-picker-sub{
  font-family:'Space Mono',monospace;
  font-size:8.5px;
  letter-spacing:1.2px;
  text-transform:uppercase;
  color:var(--dim2);
  opacity:0.7;
}
.bass-picker-cell.on .bass-picker-sub{
  color:var(--gold);
  opacity:1;
}

.bass-rows{
  display:flex; flex-direction:column; gap:6px;
}
.bass-row{
  display:grid;
  grid-template-columns:1fr auto;
  grid-template-rows:auto auto;
  gap:4px 10px;
  padding:7px 10px;
  border:1px solid var(--gold2);
  background:var(--vellum2);
  border-radius:1px;
  cursor:pointer;
  transition:border-color 120ms var(--ease-thumb), background 120ms var(--ease-thumb);
  grid-template-areas: "deg lbl" "cells lbl";
}
.bass-row:hover{
  border-color:var(--gold2);
  background:var(--vellum);
}
.bass-row.on{
  border-color:var(--gold);
  border-width:1.5px;
  background:var(--vellum);
  margin:-0.5px;
}
.bass-degree-row{
  grid-area:deg;
  display:grid;
  grid-template-columns:repeat(var(--bass-cols,4),1fr);
  gap:4px;
}
.bass-degree{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:11px;
  color:var(--dim2);
  letter-spacing:0.5px;
  text-align:center;
}
.bass-cells{
  grid-area:cells;
  display:grid;
  grid-template-columns:repeat(var(--bass-cols,4),1fr);
  gap:4px;
}
.bass-cell{
  font-family:'Space Mono',monospace;
  font-weight:700;
  font-size:13px;
  color:var(--dim);
  background:var(--vellum2);
  border:1px solid var(--gold2);
  border-radius:1px;
  padding:4px 0;
  text-align:center;
  transition:border-color 120ms, background 80ms, box-shadow 120ms;
  opacity:0.75;
}
.bass-row.on .bass-cell{
  color:var(--text);
  background:var(--vellum);
  opacity:1;
}
.bass-cell.bass-cell-diff{
  background:rgba(154,100,32,0.10);
  border-color:var(--gold2);
}
.bass-cell.bass-cell-playing{
  box-shadow:0 2px 0 0 var(--gold) inset;
}
.bass-setting-label{
  grid-area:lbl;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:3px;
  min-width:68px;
}
.bass-dot{
  display:inline-block;
  width:6px; height:6px;
  border-radius:50%;
  border:1px solid var(--gold2);
  background:transparent;
  transition:background 120ms, border-color 120ms;
}
.bass-row.on .bass-dot{
  background:var(--gold);
  border-color:var(--gold);
}
.bass-label{
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--dim2);
  text-align:center;
  line-height:1.2;
  white-space:nowrap;
}
.bass-row.on .bass-label{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:11px;
  letter-spacing:0;
  text-transform:none;
  color:var(--text);
}
.bass-label-gloss{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:9px;
  color:var(--dim2);
  text-align:center;
  line-height:1.3;
  white-space:normal;
  max-width:68px;
  opacity:0.75;
}
.bass-row.on .bass-label-gloss{
  color:var(--dim);
  opacity:1;
}
.bass-foot-row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:8px;
  margin-top:2px;
}
.bass-gloss{
  font-family:'Space Mono',monospace;
  font-size:9px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--dim2);
}
.bass-preview-btn{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:5px;
  border:1px solid var(--gold2);
  border-radius:1px;
  background:transparent;
  padding:5px 10px;
  cursor:pointer;
  min-height:28px;
  overflow:hidden;
  flex-shrink:0;
}
.bass-preview-btn:hover{ background:var(--gold-dim); }
.bass-preview-triangle{
  font-size:9px;
  color:var(--gold);
  line-height:1;
}
.bass-preview-label{
  font-family:'Space Mono',monospace;
  font-size:9.5px;
  letter-spacing:2.4px;
  text-transform:uppercase;
  color:var(--gold);
}
.bass-preview-bar{
  position:absolute;
  inset:0;
  width:0%;
  background:var(--gold);
  opacity:0.18;
  pointer-events:none;
}
/* r6p54e (P1-5) — header readout structure aligned with d.4 SHAPE +
   d.2 POSITION DISTANCE siblings. .ps-bass-state was 9px / 1.4px /
   0.85 opacity carrying "● DRONE" as one text run; siblings used
   separate glyph + label spans at 10px / 2.4px (label) + 14px-tall
   SVG (glyph). Now matched. .ps-bass-state itself is retained hidden
   for any out-of-flow callers and no longer styles the visible header. */
.ps-bass-state-row{
  flex:1 1 auto;
  display:flex;
  align-items:center;
  justify-content:flex-end;
  gap:6px;
  height:18px;
  overflow:hidden;
}
.ps-bass-state-glyph{
  display:inline-flex;
  align-items:center;
}
.ps-bass-state-glyph svg{
  height:10px;
  width:auto;
  display:block;
}
.ps-bass-state-lbl{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--gold);
  text-transform:uppercase;
  line-height:1;
}
.ps-bass-state{
  font-family:'Space Mono',monospace;
  font-size:9px;
  letter-spacing:1.4px;
  color:var(--gold);
  opacity:0.85;
}

/* ════════════════════════════════════════════════════════════════
   R6.40e — FIG. d.5 REGISTER exhibit
   ════════════════════════════════════════════════════════════════
   Heatmap fretboard + three preset taps (LOW / EVEN / HIGH) +
   ▸ PREVIEW button. Pattern mirrors d.3 BASS BEHAVIOR. */
.register-exhibit{
  display:flex;
  flex-direction:column;
  gap:10px;
  padding:10px 12px 12px;
}
.register-fb-wrap{
  overflow-x:auto;
  overflow-y:hidden;
}
.register-dot{
  transition: fill 240ms var(--ease-decay), opacity 240ms var(--ease-decay), r 240ms var(--ease-decay);
}
.register-dot-halo{
  filter: drop-shadow(0 0 4px rgba(200,144,44,0.6));
}
.register-presets{
  display:flex;
  flex-direction:row;
  gap:6px;
  justify-content:space-between;
}
.register-preset{
  flex:1;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:3px;
  padding:6px 4px;
  background:transparent;
  border:1px solid var(--gold2);
  border-radius:1px;
  cursor:pointer;
  font-family:'Space Mono',monospace;
}
.register-preset.on{
  border-color:var(--gold);
  border-width:1.5px;
  background:var(--gold-dim);
}
.register-preset-dot{
  width:8px;
  height:8px;
  border-radius:50%;
  border:1px solid var(--gold2);
  display:block;
}
.register-preset.on .register-preset-dot{
  background:var(--gold);
  border-color:var(--gold);
}
.register-preset-lbl{
  font-size:9px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--dim2);
}
.register-preset.on .register-preset-lbl{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:11px;
  letter-spacing:0;
  color:var(--gold);
}
.register-preset-sub{
  font-size:8.5px;
  letter-spacing:0.8px;
  color:var(--gold);
  opacity:0.7;
}
.register-foot-row{
  display:flex;
  flex-direction:row;
  align-items:center;
  justify-content:space-between;
  gap:8px;
}
.register-gloss{
  font-family:'Space Mono',monospace;
  font-size:8.5px;
  letter-spacing:0.8px;
  color:var(--dim2);
  opacity:0.7;
  flex:1;
}
.register-preview-btn{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:5px;
  padding:4px 10px 4px 8px;
  background:transparent;
  border:1px solid var(--gold2);
  border-radius:1px;
  cursor:pointer;
  font-family:'Space Mono',monospace;
  font-size:9px;
  letter-spacing:1.4px;
  color:var(--gold);
  overflow:hidden;
  white-space:nowrap;
}
.register-preview-btn:hover{ background:var(--gold-dim); }
.register-preview-tri{
  font-size:9px;
  color:var(--gold);
  line-height:1;
}
.register-preview-lbl{
  font-size:9px;
  letter-spacing:1.4px;
  text-transform:uppercase;
  color:var(--gold);
}
.register-preview-bar{
  position:absolute;
  inset:0;
  width:0%;
  background:var(--gold);
  opacity:0.18;
  pointer-events:none;
}
.ps-register-state-row{
  display:flex;
  align-items:center;
  gap:5px;
  margin-left:auto;
  margin-right:4px;
  min-width:0;
  overflow:hidden;
}
.ps-register-state-glyph{
  flex-shrink:0;
}
.ps-register-state-lbl{
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:1.4px;
  text-transform:uppercase;
  color:var(--gold);
  white-space:nowrap;
}

/* ════════════════════════════════════════════════════════════════
   R6.39 — Library three-door toggle (BROWSE / BUILD / IMPORT)
   ════════════════════════════════════════════════════════════════
   Mirrors the .tour-mode-toggle vocabulary from R6.38d so the
   segmented-control register stays consistent across surfaces. Doors
   sit between the Library header (.lib-hd) and the existing
   Library/Bench/Received tabs (which now live inside the BROWSE door
   panel). Cue line below names the door's verb in plain language. */
.lib-door-toggle{
  display:flex;
  flex-direction:row;
  flex-wrap:nowrap;
  gap:0;
  margin:6px 18px 0 18px;
  background:transparent;
  border:none;
}
.lib-door-btn{
  flex:0 0 auto;
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:12px;
  line-height:1.1;
  padding:6px 14px 7px 14px;
  background:rgba(184,190,160,0.45);
  color:var(--dim2, #7a6450);
  border:0.5px solid rgba(106,64,16,0.32);
  border-right-width:0;
  cursor:pointer;
  text-align:center;
  position:relative;
  letter-spacing:0;
  transition:background .15s, color .15s;
  white-space:nowrap;
}
.lib-door-btn:first-child{ border-top-left-radius:1px; border-bottom-left-radius:1px; }
.lib-door-btn:last-child{ border-right-width:0.5px; border-top-right-radius:1px; border-bottom-right-radius:1px; }
.lib-door-btn:hover{
  background:rgba(214,220,190,0.75);
  color:var(--gold);
}
.lib-door-btn.is-active{
  background:var(--ivory, #f4ecd2);
  color:var(--text);
  font-style:italic;
  border-color:rgba(106,64,16,0.50);
  z-index:1;
}
.lib-door-btn.is-active::after{
  content:'';
  position:absolute;
  left:6px; right:6px; bottom:0;
  height:1.5px;
  background:var(--gold);
}
.lib-door-cue{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:11px;
  line-height:1.3;
  color:var(--dim2, #7a6450);
  opacity:0.85;
  margin:4px 18px 10px 18px;
  min-height:14px;
}
.lib-door-cue:empty{ display:none; }

.lib-door-panel{
  /* 2026-05-15 — scrollable body region. The library's .picker-panel is
     a fixed-height flex column (height:min(84vh, 760px), overflow:hidden);
     header + door-toggle + door-cue eat ~105px from the top, leaving the
     door panel to fill whatever's left. Without flex:1 + min-height:0 +
     overflow-y:auto, the door content (28 tunes + a fold-stack + import
     body) grows to its natural size and just gets clipped at the panel's
     bottom edge — tunes past the fold are invisible AND unreachable. */
  flex:1 1 0;
  min-height:0;
  overflow-y:auto;
}
.lib-door-panel[hidden]{ display:none !important; }

/* ── BUILD door — key/mode/tempo configurator ──────────────────
   Mirror of the splash .spl-jam-* configurator (same shapes, same
   handlers' visual language) but with library-scoped IDs (lib-build-*)
   so the two host containers don't collide. Padding wraps to give the
   row layout breathing room inside the drawer (drawer is narrower than
   the splash). */
.lib-door-panel-build{
  padding:14px 22px 22px 22px;
}
.lib-build-row{
  display:flex;
  align-items:center;
  gap:10px;
  flex-wrap:wrap;
  margin-bottom:14px;
}
.lib-build-lbl{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:2px;
  color:var(--dim2, #7a6450);
  width:56px;
  text-transform:uppercase;
  flex-shrink:0;
}
.lib-build-keys, .lib-build-modes{
  display:flex;
  gap:4px;
  flex-wrap:wrap;
  flex:1;
}
.lib-build-key{
  width:26px;
  height:26px;
  border-radius:50%;
  border:1px solid rgba(106,64,16,0.32);
  background:transparent;
  color:var(--dim2, #7a6450);
  font-family:'Space Mono', monospace;
  font-size:8px;
  cursor:pointer;
  transition:all .14s;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:0;
}
.lib-build-key:hover{ border-color:var(--gold); color:var(--gold); }
.lib-build-key.on{
  background:var(--gold);
  color:#0a0604;
  border-color:var(--gold);
}
.lib-build-mode{
  border:1px solid rgba(106,64,16,0.32);
  background:transparent;
  color:var(--dim2, #7a6450);
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.5px;
  text-transform:uppercase;
  padding:5px 9px;
  border-radius:3px;
  cursor:pointer;
  transition:all .14s;
}
.lib-build-mode:hover{ border-color:var(--gold); color:var(--gold); }
.lib-build-mode.on{
  background:var(--gold);
  color:#0a0604;
  border-color:var(--gold);
}
.lib-build-tempo{
  display:flex;
  align-items:center;
  gap:6px;
}
.lib-build-tempo-input{
  width:56px;
  background:rgba(255,250,230,0.85);
  border:1px solid rgba(106,64,16,0.32);
  border-radius:3px;
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:16px;
  text-align:center;
  color:var(--text);
  padding:4px 0;
  -moz-appearance:textfield;
}
.lib-build-tempo-input::-webkit-outer-spin-button,
.lib-build-tempo-input::-webkit-inner-spin-button{
  -webkit-appearance:none;
  margin:0;
}
.lib-build-tempo-step{
  width:24px;
  height:24px;
  border:1px solid rgba(106,64,16,0.32);
  background:transparent;
  color:var(--gold);
  font-family:'Space Mono', monospace;
  font-size:14px;
  border-radius:3px;
  cursor:pointer;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  padding:0;
  line-height:1;
}
.lib-build-tempo-step:hover{ background:rgba(232,199,106,0.15); }
.lib-build-tempo-unit{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.5px;
  color:var(--dim2, #7a6450);
}
.lib-build-go-row{
  display:flex;
  justify-content:flex-end;
  margin-top:6px;
}
.lib-build-go{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:14px;
  padding:6px 18px;
  background:var(--gold);
  color:#0a0604;
  border:1px solid var(--gold);
  border-radius:2px;
  cursor:pointer;
  transition:background .15s;
}
.lib-build-go:hover{ background:var(--gold3, #b87a1a); }

/* ── IMPORT door — body mounted lazily by mountImportPanel() ────
   The import body renders into .lib-door-panel-import; its internal
   styles (.imp-tabs, .imp-panel, .imp-dropzone, .imp-textarea, etc.)
   already exist from the pre-R6.39 modal version and are reused as-is.
   Just give the host container some padding so the body doesn't kiss
   the drawer edge. */
.lib-door-panel-import{
  padding:14px 22px 22px 22px;
}

/* ════════════════════════════════════════════════════════════════
   R6.40b — FIG. d.4 SHAPE substrate
   ════════════════════════════════════════════════════════════════
   Per Design handoff docs/claude-design-2026-05-11/d.4-SHAPE.md.
   Three archetype fretboards (ANY/BARRE/CHOP) tile the body of the
   #ps-shape-sec fold cartouche. Active state = frame around the shape
   (border + label color + bg lift), not paint on the shape itself.
   Closed-fold header carries a 22×16 miniature glyph + active label.
   Chop tile auto-degrades on non-mandolin instruments (.is-locked). */

/* HEADER — closed-fold state row */
.ps-shape-state-row{
  flex:1 1 auto;
  display:flex;
  align-items:center;
  justify-content:flex-end;
  gap:6px;
  height:18px;
  overflow:hidden;
}
.ps-shape-state-svg{
  display:inline-flex;
  align-items:center;
}
.ps-shape-state-svg svg{
  height:16px;
  width:auto;
  display:block;
}
.ps-shape-state-lbl{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--gold);
  text-transform:uppercase;
  line-height:1;
}

.ps-shape-sec[data-fold="open"] .ps-sec-body{ padding:6px 10px 14px; }

/* TILES ROW — three side-by-side, equal width per Design */
.ps-shape-tiles{
  display:flex;
  flex-direction:row;
  gap:6px;
  margin:4px 0 8px 0;
}

/* TILE — Design spec: ~110x150, label/fretboard/fret-indicator/dot */
.ps-shape-tile{
  flex:1 1 0;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:flex-start;
  gap:5px;
  padding:8px 4px 7px;
  background:transparent;
  border:1px solid var(--gold-dim);
  border-radius:1px;
  cursor:pointer;
  transition:border-color .18s var(--ease-thumb), background .18s var(--ease-thumb);
  position:relative;
}
/* Inactive tile fretboard background vs. active tile vellum lift —
   Design spec: bg lifts var(--vellum2) → var(--vellum) on active. */
.ps-shape-tile-fb{
  display:block;
  background:var(--vellum2);
  border:0.5px solid rgba(106,64,16,0.20);
  border-radius:1px;
  padding:2px;
  line-height:0;
  transition:background .18s var(--ease-thumb);
}
.ps-shape-tile-fb svg{
  display:block;
  /* r6p85i (#9) — scale the fretboard down to fit its (flex:1 1 0) tile so
     three tiles never overflow/clip the drawer; preserves aspect ratio. */
  max-width:100%;
  height:auto;
}
.ps-shape-tile-lbl{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--dim2, #5a4828);
  text-transform:uppercase;
  line-height:1;
  transition:color .18s var(--ease-thumb);
}
.ps-shape-tile-fret{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.6px;
  color:var(--dim2, #5a4828);
  text-transform:lowercase;
  line-height:1;
  margin-top:1px;
}
.ps-shape-tile-dot{
  display:inline-block;
  width:6px;
  height:6px;
  border-radius:50%;
  background:transparent;
  border:1px solid var(--gold2);
  margin-top:3px;
  transition:background .18s var(--ease-thumb), border-color .18s var(--ease-thumb);
}

/* HOVER / FOCUS on inactive — border to gold2 1.5px, label to text */
.ps-shape-tile:hover:not(.on):not(.is-locked),
.ps-shape-tile:focus-visible:not(.on):not(.is-locked){
  border-color:var(--gold2);
  border-width:1.5px;
  padding:7.5px 3.5px 6.5px; /* counter the +0.5px border to avoid layout shift */
}
.ps-shape-tile:hover:not(.on):not(.is-locked) .ps-shape-tile-lbl,
.ps-shape-tile:focus-visible:not(.on):not(.is-locked) .ps-shape-tile-lbl{
  color:var(--text);
}

/* ACTIVE — Design spec: 1.5px gold border, label gold, fretboard bg
   lifts to vellum, filled gold dot. */
.ps-shape-tile.on{
  border-color:var(--gold);
  border-width:1.5px;
  padding:7.5px 3.5px 6.5px; /* avoid layout shift vs. inactive 1px border */
}
.ps-shape-tile.on .ps-shape-tile-lbl{ color:var(--gold); }
.ps-shape-tile.on .ps-shape-tile-fb{ background:var(--vellum); }
.ps-shape-tile.on .ps-shape-tile-dot{
  background:var(--gold);
  border-color:var(--gold);
}

/* CHOP DISABLED — Design spec: fretboard opacity 0.35, label
   "MANDOLIN FAMILY" var(--dim2), dot replaced with brass × glyph,
   not clickable. Label text swap is JS-side. */
.ps-shape-tile.is-locked{
  cursor:default;
}
.ps-shape-tile.is-locked .ps-shape-tile-fb{
  opacity:0.35;
}
.ps-shape-tile.is-locked .ps-shape-tile-lbl{
  color:var(--dim2);
}
.ps-shape-tile.is-locked:hover{
  /* No hover affordance when locked */
  border-color:var(--gold-dim);
  border-width:1px;
  padding:8px 4px 7px;
}
.ps-shape-tile.is-locked .ps-shape-tile-dot{
  /* Hide the dot; the JS could swap it for ✕ in the future, for now
     the disabled visual carries via opacity + label change. */
  background:transparent;
  border-color:transparent;
  position:relative;
}
.ps-shape-tile.is-locked .ps-shape-tile-dot::after{
  content:'×';
  position:absolute;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  font-family:'Space Mono', monospace;
  font-size:11px;
  color:var(--gold2);
  opacity:0.6;
  line-height:1;
}

/* GLOSS — Design spec: bottom of fold body, plain declarative */
.ps-shape-gloss{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:11px;
  line-height:1.4;
  color:var(--dim2, #5a4828);
  opacity:0.85;
  text-align:center;
  margin:8px 0 0 0;
}

/* ════════════════════════════════════════════════════════════════
   R6.40c — FIG. d.2 POSITION DISTANCE substrate
   ════════════════════════════════════════════════════════════════
   Per Design handoff docs/claude-design-2026-05-11/d.2-POSITION-DISTANCE.md.
   Single 13-fret fretboard with brass window rectangle drawn over it
   at anchor ± N. Anchor marked below with brass triangle + label.
   Three preset taps: RIGHT HERE / NEAR / LOOSE. Closed-fold header
   carries miniature brass-bracket glyph + active label. */

/* HEADER — closed-fold state row (mirrors .ps-shape-state-row) */
.ps-position-state-row{
  flex:1 1 auto;
  display:flex;
  align-items:center;
  justify-content:flex-end;
  gap:6px;
  height:18px;
  overflow:hidden;
}
.ps-position-state-glyph{
  display:inline-flex;
  align-items:center;
}
.ps-position-state-glyph svg{
  height:14px;
  width:auto;
  display:block;
}
.ps-position-state-lbl{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--gold);
  text-transform:uppercase;
  line-height:1;
}

.ps-position-sec[data-fold="open"] .ps-sec-body{ padding:8px 10px 14px; }

/* FRETBOARD wrapper */
.ps-position-fb-wrap{
  display:flex;
  justify-content:center;
  margin:2px 0 6px 0;
}
.ps-position-fb{
  width:100%;
  max-width:360px;
  position:relative;
}
.ps-position-fb svg{
  display:block;
  width:100%;
  height:auto;
}
/* Window rect + anchor triangle transitions per Design spec — 240ms
   ease-thumb for width changes, 180ms for anchor slides. SVG attrs
   transition via CSS by targeting the inline attributes. */
#ps-position-window-rect{
  transition:x 240ms var(--ease-thumb), width 240ms var(--ease-thumb);
}
#ps-position-anchor-tri{
  transition:d 180ms var(--ease-thumb);
}
/* Anchor label sits centered below the SVG. */
.ps-position-anchor-lbl{
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.5px;
  color:var(--dim2, #5a4828);
  text-align:center;
  margin-top:2px;
  text-transform:lowercase;
}

/* PRESETS — three buttons in a row, two-line stack each */
.ps-position-presets{
  display:flex;
  flex-direction:row;
  justify-content:space-around;
  align-items:flex-start;
  gap:8px;
  margin-top:10px;
  padding:8px 4px 4px 4px;
  border-top:1px solid rgba(106,64,16,0.18);
}
.ps-position-preset{
  flex:1 1 0;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:3px;
  padding:4px 6px;
  background:transparent;
  border:none;
  cursor:pointer;
  transition:opacity .18s var(--ease-thumb);
}
.ps-position-preset-dot{
  display:inline-block;
  width:6px;
  height:6px;
  border-radius:50%;
  background:transparent;
  border:1px solid var(--gold2);
  transition:background .18s var(--ease-thumb), border-color .18s var(--ease-thumb);
}
.ps-position-preset-lbl{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2px;
  color:var(--dim2, #5a4828);
  text-transform:uppercase;
  line-height:1.05;
  transition:color .18s var(--ease-thumb), font-family .18s var(--ease-thumb);
}
.ps-position-preset-sub{
  font-family:'Space Mono', monospace;
  font-size:9.5px;
  color:var(--gold);
  opacity:0.7;
  line-height:1;
  letter-spacing:0.2px;
}
.ps-position-preset:hover:not(.on) .ps-position-preset-lbl{
  color:var(--text);
}
.ps-position-preset.on .ps-position-preset-dot{
  background:var(--gold);
  border-color:var(--gold);
}
.ps-position-preset.on .ps-position-preset-lbl{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:12px;
  letter-spacing:0;
  color:var(--text);
  text-transform:none;
}

/* ────── r6p41-melody — PL. IV MELODY plate per Design rev. 6 G3 ──────
   Plate-IV sidebar: cascade rule for data-lens~="IV" matches the
   existing I/II/III pattern. CONTOUR substrate is full-width in the
   play-main area, hidden on every other plate.
   The 3 sidebar fold cartouches (TARGETS / SUBDIVISION / ORNAMENT)
   reuse the .ps-sec[data-fold] / .ps-sec-header / .ps-sec-body
   primitives — no special-case CSS needed for the fold mechanic.
   The substrate-specific rules below govern the CONTOUR canvas + the
   per-overlay body content (toggle pill + audition button). */

/* Cascade: PL. IV sidebar shows IV-tagged cartouches. */
body[data-plate-lens="IV"] .plate-sidebar .ps-sec[data-lens~="IV"]{ display:flex; }

/* CONTOUR substrate visibility — only shown on PL. IV, full-width.
   Hidden by default so it doesn't paint over the fretboard on PL. I/II/III. */
.plate-contour-wrap{
  display:none;
  width:100%;
  margin:0 0 6px 0;
  padding:8px 10px 12px;
  background:rgba(214,220,190,0.18);
  border:1px solid var(--gold-dim);
  border-radius:6px;
}
body[data-plate-lens="IV"] .plate-contour-wrap{
  display:block;
}
/* On PL. IV, the fretboard region collapses — CONTOUR is the looking
   mode (per per-plate-one-looking-mode lock). The fretboard remains
   present (chord cards still draw, transport still works) but the big
   fretboard SVG is suppressed to keep the visual register clean. */
body[data-plate-lens="IV"] .pff-neck-wrap{
  display:none;
}
body[data-plate-lens="IV"] #play-beat-strip{
  display:none;
}

/* CONTOUR fig banner — Playfair italic gloss + Patent register, same
   anatomy as the non-fold cartouche FIG. banners on other plates. */
.plate-contour-fig-banner{
  display:flex;
  align-items:baseline;
  gap:10px;
  padding:2px 4px 8px;
  border-bottom:1px solid var(--gold-dim);
  margin-bottom:8px;
}
.plate-contour-fig{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--gold);
  text-transform:uppercase;
}
.plate-contour-fig-rule{
  flex:0 0 18px;
  height:1px;
  background:var(--gold-dim);
}
.plate-contour-fig-cap{
  font-family:'Space Mono', monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--gold);
  text-transform:uppercase;
}
.plate-contour-fig-sub{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:11.5px;
  color:var(--dim2);
  opacity:0.85;
  flex:1 1 auto;
  line-height:1.2;
}
.plate-contour-play{
  background:transparent;
  border:1px solid var(--gold2);
  color:var(--gold);
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.8px;
  text-transform:uppercase;
  padding:5px 10px;
  border-radius:3px;
  cursor:pointer;
  display:inline-flex;
  align-items:center;
  gap:6px;
  transition:background .15s, border-color .15s, color .15s;
}
.plate-contour-play:hover{
  background:rgba(154,100,32,0.08);
  border-color:var(--gold);
  color:var(--gold);
}
.plate-contour-play-glyph{
  font-size:11px;
  line-height:1;
}

/* CONTOUR substrate canvas — vellum bg, vellum2 inner staff band. */
.plate-contour-substrate{
  width:100%;
  height:auto;
  display:block;
}
.plate-contour-substrate .ps-contour-svg{
  display:block;
  width:100%;
  height:auto;
  max-height:240px;
}
/* Idle state — hatch + IDLE label visible only when no melody loaded.
   When a melody loads, the substrate adds .has-melody and the idle
   layer drops out. */
.plate-contour-wrap.has-melody .ps-contour-idle-bg,
.plate-contour-wrap.has-melody .ps-contour-idle-lbl{
  display:none;
}
.plate-contour-wrap.no-melody .ps-contour-bars,
.plate-contour-wrap.no-melody .ps-contour-tails,
.plate-contour-wrap.no-melody .ps-contour-curve,
.plate-contour-wrap.no-melody .ps-contour-notes,
.plate-contour-wrap.no-melody .ps-contour-targets,
.plate-contour-wrap.no-melody .ps-contour-subdivision,
.plate-contour-wrap.no-melody .ps-contour-ornaments{
  display:none;
}

/* PL. IV sidebar — per-overlay body anatomy.
   Each TARGETS / SUBDIVISION / ORNAMENT cartouche body carries one
   sentence of gloss + a SHOW/HIDE toggle + an audible-test button.
   Compact two-row layout so the body fits inside the existing fold
   primitive without forcing a wider sidebar. */
.ps-melody-body{
  display:flex;
  flex-direction:column;
  gap:8px;
  padding:6px 0;
}
.ps-melody-gloss{
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:11px;
  line-height:1.45;
  color:var(--dim2);
  opacity:0.9;
}
.ps-melody-row{
  display:flex;
  align-items:center;
  gap:8px;
  flex-wrap:wrap;
}
.ps-melody-toggle{
  flex:0 0 auto;
  display:inline-flex;
  align-items:center;
  gap:6px;
  background:transparent;
  border:1px solid var(--gold2);
  color:var(--gold);
  font-family:'Space Mono', monospace;
  font-size:9.5px;
  letter-spacing:1.8px;
  text-transform:uppercase;
  padding:5px 9px;
  border-radius:3px;
  cursor:pointer;
  transition:background .15s, border-color .15s;
}
.ps-melody-toggle:hover{
  background:rgba(154,100,32,0.08);
  border-color:var(--gold);
}
.ps-melody-toggle[aria-pressed="true"]{
  background:rgba(232,199,106,0.12);
  border-color:var(--gold);
}
.ps-melody-toggle-dot{
  width:7px;
  height:7px;
  border-radius:50%;
  background:var(--gold2);
  transition:background .15s;
}
.ps-melody-toggle[aria-pressed="true"] .ps-melody-toggle-dot{
  background:var(--gold);
}
.ps-melody-audition{
  flex:1 1 auto;
  background:transparent;
  border:1px solid var(--gold-dim);
  color:var(--gold);
  font-family:'Space Mono', monospace;
  font-size:9px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  padding:5px 8px;
  border-radius:3px;
  cursor:pointer;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  transition:background .15s, border-color .15s;
}
.ps-melody-audition:hover{
  background:rgba(154,100,32,0.08);
  border-color:var(--gold);
}
.ps-melody-aud-glyph{
  font-size:11px;
  line-height:1;
}
.ps-melody-aud-lbl{
  line-height:1;
}

/* Closed-fold header — overlay state glyph + ON/OFF state pill.
   Matches the REVERB closed-fold pattern: mini glyph + state text. */
.ps-targets-state-glyph,
.ps-subdivision-state-glyph,
.ps-ornament-state-glyph{
  display:inline-flex;
  align-items:center;
  flex:0 0 auto;
  margin-right:4px;
  vertical-align:middle;
}

/* Reduced motion — overlays appear instantly per Design G3 lock. */
@media (prefers-reduced-motion: reduce){
  .ps-contour-targets,
  .ps-contour-subdivision,
  .ps-contour-ornaments{
    transition:none !important;
  }
}
/* End r6p41-melody PL. IV ─────────────────────────────────────── */

/* ── 2026-05-15 — Welcome card lens-driven redesign.
   Splash-screen feel + hang-on-the-fridge aesthetic + Patent register:
   - Vellum + double brass border (Patent PLATE primitive — same recipe
     as #mobile-landing's outer plate)
   - Italic Playfair brand (anchored, presence, not generic-modal)
   - HONEST decorative instrument silhouette (Octave Mandolin) +
     FIG. caption with brass hairline — same FIG. ƒ pattern the rest
     of the studio uses, but explicitly aria-hidden so it doesn't lie
     about interactivity
   - Two CTAs: Browse / Pick at random
   - Wider card (560px) for splash presence; generous padding ── */
.welcome-card-overlay{
  position:fixed; inset:0; z-index:550;
  display:flex; align-items:center; justify-content:center;
  background:rgba(10,6,4,0.42);
  font-family:'Playfair Display',serif;
  animation:welcomeCardFadeIn .26s ease both;
}
@keyframes welcomeCardFadeIn{ from{opacity:0;} to{opacity:1;} }
.welcome-card{
  background:var(--vellum, #efe6cf);
  border:1.5px solid var(--gold2, #6a4010);
  box-shadow:0 18px 48px rgba(0,0,0,0.38);
  border-radius:2px;
  padding:48px 56px 40px;
  max-width:560px; width:calc(100% - 40px);
  text-align:center;
  position:relative;
}
.welcome-card::before{
  /* Inner brass hairline — Patent PLATE double-border. */
  content:""; position:absolute; inset:7px;
  border:1px solid var(--gold2, #6a4010);
  opacity:0.45;
  pointer-events:none;
}
.welcome-card-brand{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:700;
  font-size:clamp(48px, 6vw, 64px);
  color:var(--text, #1a0c04);
  line-height:1;
  letter-spacing:0.5px;
  margin:0 0 8px;
}
.welcome-card-tag{
  font-family:'Playfair Display',serif; font-style:italic;
  font-size:clamp(15px, 1.55vw, 17px);
  color:var(--text, #1a0c04); opacity:0.72;
  letter-spacing:0.3px; line-height:1.4;
  margin:0 auto 28px;
  max-width:380px;
}
/* 2026-05-15 v2 — Family-portrait row. Seven fifths-tuned instruments
   in a flex row, each a silhouette SVG + tiny brass label. Brass
   hairline rules top + bottom frame the row as a Patent plate. The
   row literally answers the tagline's "instruments tuned in fifths"
   by showing the family. No FIG. caption — the row IS the figure. */
.welcome-card-family{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap:8px;
  margin:0 auto 24px;
  padding:14px 4px;
  border-top:1px solid var(--gold2, #6a4010);
  border-bottom:1px solid var(--gold2, #6a4010);
  max-width:480px;
}
.welcome-card-family .wcf-cell{
  display:flex; flex-direction:column; align-items:center; gap:5px;
  flex:1 1 0;
  min-width:0;
  /* r6p97-frontdoor — click an instrument to HEAR its open fifths. Turns the
     row from a false affordance (looked clickable, did nothing) into a real
     one (Norman). */
  cursor:pointer;
  transition:transform .15s ease, color .15s ease;
  -webkit-tap-highlight-color:transparent;
}
/* Honest hover signifier — the ink DARKENS, nothing else. No glow, and no
   lift (Scott: the lift reads out of character for these patent-drawing
   silhouettes). The sound is the payoff, on CLICK only — sweeping is silent. */
.welcome-card-family .wcf-cell:focus-visible{ outline:none; }
.welcome-card-family .wcf-cell:hover .wcf-silhouette,
.welcome-card-family .wcf-cell:focus-visible .wcf-silhouette,
.welcome-card-family .wcf-cell:hover .wcf-label,
.welcome-card-family .wcf-cell:focus-visible .wcf-label{
  color:var(--gold2, #6a4010);
  opacity:1;
}
.welcome-card-family .wcf-silhouette{
  display:block;
  width:54px; height:24px;
  color:var(--gold, #9a6420);
}
.welcome-card-family .wcf-label{
  font-family:'Space Mono', monospace;
  font-size:8px;
  letter-spacing:1.2px;
  color:var(--gold, #9a6420);
  opacity:0.85;
  text-align:center;
  text-transform:uppercase;
  line-height:1.2;
  white-space:nowrap;
}
/* r6p43 — Tug-handle apparatus. Single brass pull-handle (the
   affordance) + title field (the result). Replaces the cylinder-and-
   lever combo per Scott 2026-05-17: spinning cylinders read as slot-
   machine, two parts read as two actions. The handle is unambiguous
   ("pull"); the title is the answer ("here's your tune"). */
.welcome-card-apparatus{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:14px;
  position:relative;
  width:100%;
  max-width:520px;
}
/* r6p43-welcome-card-v2 — Music-box cabinet. One brass-framed gadget:
   cylinder window in the middle, crank on the right. The crank IS the
   affordance (Norman: crank-shape says turn); cylinder + pointer ▼
   show the result (Tufte: the data is the picked tune). Single tap on
   the cabinet rotates the crank 360° and slides the strip onto a
   random tune. */
.wc-cabinet{
  /* Brass-framed cabinet. Walnut interior backdrop, brass hairline
     border, 4 corner bolts. Crank docked at right; cylinder window
     centred-left. */
  position:relative;
  width:380px;
  height:96px;
  display:grid;
  grid-template-columns: 1fr 72px;
  align-items:center;
  gap:0;
  padding:14px 18px 14px 22px;
  background:
    linear-gradient(180deg, rgba(74,52,34,0.06) 0%, rgba(74,52,34,0.12) 100%),
    radial-gradient(ellipse at 50% 30%, rgba(154,100,32,0.10), transparent 60%);
  border:1.2px solid var(--gold, #9a6420);
  border-radius:3px;
  box-shadow:
    inset 0 0 0 1px rgba(255,235,200,0.18),
    inset 0 2px 4px rgba(74,52,34,0.10),
    0 1px 0 rgba(0,0,0,0.06);
  cursor:pointer;   /* r6p97-frontdoor — a push-button is clicked, not grabbed */
  outline:none;
  user-select:none;
  -webkit-tap-highlight-color:transparent;
}
.wc-cabinet:focus-visible{
  outline:2px solid var(--gold, #9a6420);
  outline-offset:3px;
}
.wc-cabinet-bolt{
  position:absolute;
  width:5px;
  height:5px;
  border-radius:50%;
  background:radial-gradient(circle at 35% 35%,
    rgba(255,235,200,0.7) 0%,
    var(--gold, #9a6420) 45%,
    var(--gold2, #6a4010) 100%);
  box-shadow:0 0 0 0.5px rgba(74,52,34,0.4);
}
.wc-cabinet-bolt-tl{ top:6px; left:6px; }
.wc-cabinet-bolt-tr{ top:6px; right:6px; }
.wc-cabinet-bolt-bl{ bottom:6px; left:6px; }
.wc-cabinet-bolt-br{ bottom:6px; right:6px; }
.wc-cabinet-pointer{
  /* Fixed pointer above the strip — marks the active cell row. The
     strip slides past this fixed mark. */
  position:absolute;
  top:0;
  left:calc(50% - 36px);  /* offset for crank in the grid */
  transform:translate(-50%, -55%);
  font-size:11px;
  line-height:1;
  color:var(--gold, #9a6420);
  text-shadow:0 1px 0 rgba(255,235,200,0.5);
  pointer-events:none;
  z-index:2;
}
.wc-cabinet-window{
  /* Cylinder viewport — the visible portion of the rolling strip.
     Edge fade-mask so titles dissolve at top/bottom rather than
     clipping hard. Single-cell visible height keeps the eye on one
     tune at a time. */
  position:relative;
  width:100%;
  height:36px;
  overflow:hidden;
  background:
    linear-gradient(180deg, rgba(74,52,34,0.18) 0%, rgba(74,52,34,0.04) 50%, rgba(74,52,34,0.18) 100%);
  border-top:0.6px solid rgba(74,52,34,0.35);
  border-bottom:0.6px solid rgba(74,52,34,0.35);
  border-radius:1px;
  -webkit-mask-image:linear-gradient(180deg, transparent 0%, #000 28%, #000 72%, transparent 100%);
          mask-image:linear-gradient(180deg, transparent 0%, #000 28%, #000 72%, transparent 100%);
}
.wc-cabinet-strip{
  /* Strip of tune-title cells. JS sets translateY to slide cells
     past the window. Each cell is 36px tall; window is 36px so one
     cell is centred at a time. */
  display:flex;
  flex-direction:column;
  will-change:transform;
}
.wc-cabinet-strip-cell{
  height:36px;
  display:flex;
  align-items:center;
  justify-content:center;
  font-family:'Playfair Display', serif;
  font-style:italic;
  font-size:18px;
  line-height:1;
  color:var(--text, #1f1d17);
  letter-spacing:0.2px;
  white-space:nowrap;
  padding:0 8px;
}
.wc-cabinet-strip-cell.is-landed{
  /* Landed-cell brass pulse — eye registers "this one" before card
     dismisses. Patent register: brass colour, slightly larger weight. */
  color:var(--gold, #9a6420);
  text-shadow:0 0 12px rgba(154,100,32,0.45);
  animation:wcLandPulse 900ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes wcLandPulse{
  0%   { transform:scale(1);    }
  35%  { transform:scale(1.06); }
  100% { transform:scale(1);    }
}
.wc-cabinet-crank{
  /* r6p97-frontdoor — brass PUSH-BUTTON in the cabinet's right column. The
     SVG (bezel) is static; the cap (#wc-press-cap) depresses INTO it on
     press — the one depth direction flat UI renders convincingly. */
  display:block;
  margin-left:6px;
  filter:drop-shadow(0 1px 1.5px rgba(74,52,34,0.28));
}
.wc-press-cap{
  /* The cap that sinks into the bezel on press. 2D translate only — no 3D. */
  transform-origin:50% 50%;
  transition:transform .2s cubic-bezier(0.2, 0.8, 0.2, 1);
  will-change:transform;
}
/* r6p97-frontdoor — NO hover effect on the button. Lens panel (Norman/Tufte/
   FLW): the cap's form + cursor:pointer IS the signifier; a real mechanical
   button doesn't react to a hovering hand, and a glow would be dishonest
   decoration. The only motion is the actual press. */
/* r6p97-frontdoor — front-door clarity restored. The "act here" signal is
   the cylinder's analog auto-spin (attract mode), not instruction text
   (Scott: didn't want a literal "tap to spin" caption). Two PEER doors —
   browse the library · build a jam — restore the Build entry the r6p43
   redesign dropped (Build second: it's the more advanced move). */
.wc-doors{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:12px;
  margin-top:2px;
}
.wc-doors-sep{
  font-family:'Space Mono', monospace;
  font-size:10px;
  color:var(--gold2, #6a4010);
  opacity:0.4;
  user-select:none;
}
.wc-door{
  font-family:'Space Mono', monospace;
  font-size:10.5px;       /* peer weight, up from the old 9.5px escape-hatch */
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--gold2, #6a4010);
  opacity:0.78;
  text-decoration:none;
  cursor:pointer;
  transition:opacity .15s ease, color .15s ease;
  user-select:none;
}
.wc-door:hover,
.wc-door:focus-visible{
  opacity:1;
  color:var(--gold, #9a6420);
  outline:none;
}
/* #wc-or-browse keeps its id (JS hook) but now styles as a .wc-door peer;
   neutralise the old standalone margin so it sits flush in the row. */
.wc-or-browse{ margin-top:0; }

/* 2026-05-14 — Reverb OFF state: hide wavefront rings + dim room outline.
   Geometrically distinct from Room/Hall/Cathedral per Patent Drawing
   "active state must be visually distinct" lock. */
.rvc-wave.is-off #rvc-rings { opacity:0; transition:opacity 220ms ease; }
.rvc-wave.is-off #rvc-room  { opacity:0.20; }
.rvc-wave.is-off #rvc-source { opacity:0.55; }

/* ============================================================== */
/* r6p47 slice 2 — Paternoster mode picker (Color plate's signature
   4th-wall-break mechanism). The pill list is the chain inventory
   — all 9 modes always visible — framed top + bottom by brass
   sprockets with engraved teeth, central axles, and spokes. Above
   the chain, per-section stacked slots show each tune section's
   current mode with formula row aligned in columns so comparison
   reads at a glance (Major's 4 sits directly above Lydian's ♯4).
   Mechanism-as-pedagogy per feedback_mechanism_as_pedagogy.md —
   the sprockets are drawn honestly so a curious viewer can see how
   the chain rides them. */

/* Sprockets — top + bottom of the chain. Inline SVG in index.html;
   CSS just controls placement + spacing. */
.psm-sprocket{
  display:block;
  margin:0 auto;
}
.psm-sprocket-top{ margin-bottom:4px; }
.psm-sprocket-bottom{ margin-top:4px; }

/* Per-section stacked slots. One row per section. Each row shows
   section letter + mode name + formula chips. Stacked vertically
   so the formula columns align for direct comparison. */
.ps-mode-section-slots{
  display:flex;
  flex-direction:column;
  gap:4px;
  /* r6p52 — was margin:6px 6px 10px (with 6px horizontal margin). The
     mode-pill container below has no horizontal margin, so slots ran
     6px narrower on each side, breaking cross-list digit-column
     alignment. Dropped horizontal margin so slots span the same width
     as pills. padding-left:8px matches the .ps-mode-pills container
     padding (which reserves room for the brass chain ::before pattern
     down the left edge) — both lists now indent identically so row
     content starts at the same x. */
  margin:6px 0 10px 0;
  padding-left:8px;
  font-family:'Playfair Display', serif;
}
.ps-mode-section-slots[data-hidden="1"]{ display:none; }
.ps-mode-section-slot{
  display:grid;
  /* r6p52 — name column was `auto`, so longer names ("MIXOLYDIAN") pushed
     the formula right, breaking column alignment across A/B rows when the
     two sections had different mode names. Fixed 110px column holds the
     longest catalog mode name and keeps the formula's x-position stable.
     Right padding bumped 8→10 to match the .pmp pill row below so both
     containers have identical content widths (cross-list digit-column
     alignment). */
  grid-template-columns:18px 110px 1fr;
  align-items:center;
  gap:8px;
  padding:5px 10px 5px 14px;
  background:rgba(154,100,32,0.05);
  border:1px solid var(--gold2, #6a4010);
  border-radius:1px;
  position:relative;
  cursor:pointer;
}
/* The brass selector caret — a small engraved triangle ⊳ on the
   left edge of the SELECTED slot. Vintage cash register row pointer
   vocabulary: "this is the slot I'm editing; pull from the chain
   below." Mechanism-as-pedagogy — the eye reads "this points at
   the row, the chain mode commits here." Default invisible; only
   appears on .is-selected. Single-section tunes don't show one
   (rendered via aria attribute on the slots container). */
.ps-mode-section-slot::before{
  content:'';
  position:absolute;
  left:2px;
  top:50%;
  transform:translateY(-50%);
  width:0;
  height:0;
  border-top:5px solid transparent;
  border-bottom:5px solid transparent;
  border-left:7px solid transparent; /* triangle ⊳ pointing right */
  opacity:0;
  transition:opacity 180ms ease, border-left-color 180ms ease;
  pointer-events:none;
}
.ps-mode-section-slots[data-multi="1"] .ps-mode-section-slot.is-selected::before{
  opacity:1;
  border-left-color:var(--gold, #9a6420);
}
.ps-mode-section-slot.is-live{
  background:rgba(154,100,32,0.12);
}
.ps-mode-section-slot.is-selected{
  /* Brass embossed left edge to amplify the caret pointer. */
  box-shadow:inset 2px 0 0 0 var(--gold, #9a6420);
}

/* Single-section variant — for tunes with one harmonic frame
   (Autumn Leaves, Blue Bossa, etc.). Drops the section-letter
   column (no "A" when there's no "B" to compare to), uses a
   slightly larger slot, and centers the mode name + formula
   so the slot reads as "the tune's mode" confidently rather
   than as half of a missing pair. No caret either — there's
   nothing to choose between, so the single slot is implicitly
   always the editing target. */
.ps-mode-section-slot.is-single{
  grid-template-columns:auto 1fr;
  padding:8px 12px 8px 14px;
  background:rgba(154,100,32,0.08);
  box-shadow:inset 2px 0 0 0 var(--gold, #9a6420);
}
.ps-mode-section-slot.is-single .psms-name{
  font-size:14px;
  min-width:90px;
}
.ps-mode-section-slot.is-single .psms-formula{
  font-size:12px;
}
/* Suppress the caret pseudo-element on the single variant — the
   slot is implicitly always selected, no pointer needed. */
.ps-mode-section-slot.is-single::before{
  display:none;
}
.ps-mode-section-slot .psms-letter{
  font-style:italic;
  font-weight:700;
  font-size:14px;
  color:var(--gold3, #c8902c);
  text-align:center;
}
.ps-mode-section-slot .psms-name{
  font-style:italic;
  font-weight:700;
  font-size:13px;
  color:var(--text, #1a0c04);
  min-width:70px;
}
.ps-mode-section-slot .psms-formula{
  display:grid;
  /* r6p52 — grid setup must match the .pmp-formula r6p47 override at
     line 10895 (repeat(7,1fr) + gap:2px + padding:2px 1px 1px) so digit
     columns line up vertically through both the section-slot list and
     the chain inventory below. */
  grid-template-columns:repeat(7, 1fr);
  gap:2px;
  padding:2px 1px 1px;
  font-family:'Space Mono', monospace;
  font-size:11px;
  font-weight:700;
}
.ps-mode-section-slot .psms-deg{
  text-align:center;
  color:var(--text, #1a0c04);
  opacity:0.78;
  /* r6p52 — relative anchor for the .pmf-acc accidental that hangs left */
  position:relative;
}
/* r6p52 — accidental positioning: ♭/♯ floats absolutely to the left of the
   centered digit, so the digit always sits at the column center regardless
   of whether the row has a natural ("3") or an accidental ("♭3"). Both the
   chain-inventory pills (.pmf-tile) and the per-section slots (.psms-deg)
   share the .pmf-acc child — same alignment behavior in both layouts. */
.ps-mode-section-slot .psms-deg .pmf-acc,
.ps-mode-pills .pmf-tile .pmf-acc{
  position:absolute;
  right:60%;
  top:0;
  font-size:0.85em;
  line-height:inherit;
  pointer-events:none;
}
.ps-mode-pills .pmf-tile{
  position:relative;
}
.ps-mode-section-slot .psms-deg.alt{
  color:var(--gold, #9a6420);
  opacity:1;
}
.ps-mode-section-slot .psms-deg.off{
  color:var(--gold2, #6a4010);
  opacity:0.4;
}
.ps-mode-section-slot.is-live::after{
  content:'●';
  position:absolute;
  right:8px;
  top:50%;
  transform:translateY(-50%);
  color:var(--gold, #9a6420);
  font-size:9px;
}

/* Chain inventory — the pill list lives between the sprockets and
   IS the body of the chain. Modes currently parked in section slots
   are "lifted off" the chain (.is-parked → visibility:hidden so the
   cabinet stays the same size with visible gaps where cars are
   parked). When the user reassigns a section's mode, the smooth
   opacity transition makes the swap read mechanically: one car
   coming back to the chain, another lifting off. */
.ps-mode-pills .pmp{
  transition:opacity 380ms cubic-bezier(0.4, 0, 0.2, 1),
             visibility 380ms step-end,
             transform 380ms cubic-bezier(0.4, 0, 0.2, 1);
}
.ps-mode-pills .pmp.is-parked{
  visibility:hidden;
  opacity:0;
  transform:translateY(-12px);
  pointer-events:none;
  transition:opacity 380ms cubic-bezier(0.4, 0, 0.2, 1),
             visibility 0s linear 380ms,
             transform 380ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* When a parked pill becomes UN-parked (its slot got reassigned to
   a different mode), it returns to the chain with a small drop-in
   animation — translateY from above into resting position. */
.ps-mode-pills .pmp.active{
  /* No more order:-1 elevation — with the parked-out-of-chain model,
     no in-chain mode should be elevated. The section slots above
     are where the "elevated" modes live. */
}
.ps-mode-pills .pmp.reel-arrived{
  animation:reel-arrival 460ms ease-out;
}
@keyframes reel-arrival{
  0%   { box-shadow:0 0 0 0 rgba(154,100,32,0.0); }
  35%  { box-shadow:0 0 10px 2px rgba(154,100,32,0.55); }
  100% { box-shadow:0 0 0 0 rgba(154,100,32,0.0); }
}

/* The vertical chain itself — visible as a brass guide running
   down the left edge of the pill list, between the sprocket
   hubs. Alternating link pattern (small ovals) communicates
   "this is a chain, not just a rail." Mechanism-as-pedagogy:
   eye reads "modes hang from a chain that runs between two
   sprockets." */
.ps-mode-pills{
  position:relative;
  padding-left:8px;
}
.ps-mode-pills::before{
  content:'';
  position:absolute;
  left:1px;
  top:0;
  bottom:0;
  width:3px;
  background-image:
    repeating-linear-gradient(
      to bottom,
      var(--gold2, #6a4010) 0px,
      var(--gold2, #6a4010) 4px,
      transparent 4px,
      transparent 9px
    );
  opacity:0.55;
  pointer-events:none;
}
.ps-mode-pills.reel-spinning::before{
  opacity:0.85;
  transition:opacity 320ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ============================================================== */
/* r6p47 paternoster pill restyle — compact chain-car layout.
   The chain pill list was originally a dense pill with heatmap
   chips + audition button + formula tiles. Post-paternoster
   re-framing (section slots above carry the formula comparison
   axis), the chain pill is reframed as a chain-car: compact row
   with section-slot-matching layout. Heatmap chips hidden by
   default. Audition ▸ visible only on hover/focus. */
.ps-mode-pills .pmp{
  /* Override the original .pmp grid with a chain-car layout.
     r6p52 — head column was `auto`, which let the mode-name width
     drive how wide the head ran ("Mixolydian" > "Major") and shrank
     the formula column accordingly. That made formula columns
     misalign across rows ("3" in Major sat at a different x than
     "♭3" in Dorian). Fixed 134px head column holds the longest
     catalog mode name + audition glyph AND lines up the formula's
     left edge with the section-slot's formula above — the slot has
     a leading 18px letter column ("A"/"B") + 110px name with 8px
     gaps (14 + 18 + 8 + 110 + 8 = 158); pills need the same
     formula start (14 + 134 + 10 = 158) so digit columns align
     vertically through both the section-pair and the chain
     inventory. Per Scott's standing column-axis rule. */
  display:grid !important;
  grid-template-columns:134px 1fr !important;
  align-items:center !important;
  gap:10px !important;
  padding:5px 10px 5px 14px !important;
  background:rgba(154,100,32,0.04) !important;
  border:1px solid var(--gold2, #6a4010) !important;
  border-radius:1px !important;
  margin:0 0 3px 0 !important;
  height:auto !important;
  min-height:24px !important;
  cursor:pointer;
}
.ps-mode-pills .pmp:hover:not(.is-parked){
  background:rgba(154,100,32,0.10) !important;
  border-color:var(--gold, #9a6420) !important;
}
.ps-mode-pills .pmp.active{
  /* Active chain-car gets a brass embossed left edge — same
     vocabulary as the section slot's selected state. */
  background:rgba(154,100,32,0.10) !important;
  box-shadow:inset 2px 0 0 0 var(--gold, #9a6420) !important;
}
.ps-mode-pills .pmp-head{
  display:flex !important;
  align-items:center !important;
  gap:4px !important;
}
.ps-mode-pills .pmp-name{
  font-family:'Playfair Display', serif !important;
  font-style:italic !important;
  font-weight:700 !important;
  font-size:13px !important;
  color:var(--text, #1a0c04) !important;
  text-transform:capitalize !important;
  letter-spacing:0 !important;
  min-width:0 !important;
}
.ps-mode-pills .pmp-formula{
  display:grid !important;
  grid-template-columns:repeat(7, 1fr) !important;
  gap:2px !important;
  font-family:'Space Mono', monospace !important;
  font-size:11px !important;
  font-weight:700 !important;
  flex:none !important;
  width:auto !important;
}
.ps-mode-pills .pmf-tile{
  text-align:center !important;
  background:none !important;
  color:var(--text, #1a0c04) !important;
  opacity:0.78 !important;
  padding:0 !important;
  border:none !important;
  min-width:0 !important;
  border-radius:0 !important;
}
.ps-mode-pills .pmf-tile.alt{
  color:var(--gold, #9a6420) !important;
  opacity:1 !important;
}
.ps-mode-pills .pmf-tile.off{
  color:var(--gold2, #6a4010) !important;
  opacity:0.4 !important;
}
.ps-mode-pills .pmp-heatmap{
  /* Hidden in paternoster mode — the color-coded heatmap was a
     pre-paternoster surface. Comparison axis now lives in the
     section slots above. */
  display:none !important;
}
.ps-mode-pills .pmp-audition{
  opacity:0 !important;
  transition:opacity 160ms ease !important;
  position:absolute !important;
  right:6px !important;
  top:50% !important;
  transform:translateY(-50%) !important;
  margin:0 !important;
  padding:0 !important;
  border:none !important;
  background:none !important;
  cursor:pointer;
}
.ps-mode-pills .pmp{
  position:relative;
}
.ps-mode-pills .pmp:hover .pmp-audition,
.ps-mode-pills .pmp:focus-within .pmp-audition,
.ps-mode-pills .pmp-audition:focus{
  opacity:1 !important;
}
.ps-mode-pills .pmp-audition.is-disabled{
  display:none !important;
}

/* Sprocket rotation — the driver gear visibly turns when a section
   changes. r6p52 — was one-shot @keyframes via .is-spinning toggle
   that snapped the gear back to 0° on class removal (the "jump"
   Scott flagged 2026-05-22). Now: inline transform set by
   _v2RotateSprocketsOnSwap accumulates 120° per call; CSS transition
   smooths the change. CSS targets the inner .psm-spinner-{top,bot}
   wrapper rather than the outer positioning <g> — the outer SVG
   transform="translate(...)" attribute would otherwise conflict
   with CSS transform on the same element (Chrome quirk that
   silently strips the rotate part). transform-origin:center under
   fill-box keeps the rotation in place since the gear geometry is
   centered at the wrapper's origin. */
.psm-spinner-top,
.psm-spinner-bot{
  transform-origin:center;
  transform-box:fill-box;
  transition:transform 420ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── 2026-05-21 — TWO-TIER PATENT-DRAWING SCAFFOLDING ──────────────────
   Two reusable primitives, used by cartouches that depict gravity-defying
   mechanisms (SWING anchor escapement; TEMPO Maelzel metronome). Other
   cartouches stay single-tier. Spec: docs/2026-05-21-swing-two-tier-proposal.md

   .pat-stamp  — tiny brass affordance in the fig-banner. Reads as a
                 patent stamp (PAT. date · inventor · location). Click → deep view.
   .deep-view  — full right-canvas overlay. Replaces the fretboard area
                 with a Patent Drawing + exposition + working controls.
                 Left sidebar stays interactive (Left=action stays honest).
   ─────────────────────────────────────────────────────────────────── */
.pat-stamp{
  display:inline-flex;
  align-items:center;
  margin-left:auto;
  padding:2px 6px;
  border:0;
  background:transparent;
  font-family:'Space Mono',monospace;
  font-size:8.5px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--gold3);
  cursor:pointer;
  white-space:nowrap;
  border-bottom:1px dotted transparent;
  transition:color 180ms ease, border-color 180ms ease;
}
.pat-stamp:hover{
  color:var(--gold);
  border-bottom-color:var(--gold2);
}
.pat-stamp:focus-visible{
  outline:1px solid var(--gold);
  outline-offset:2px;
}
.pat-stamp .pat-dot{
  display:inline-block;
  width:4px; height:4px;
  border-radius:50%;
  background:var(--gold);
  margin-right:6px;
  flex:0 0 auto;
}

/* 2026-05-21 — Deep view as a MODAL: full-viewport backdrop dim + a
   centered vellum panel holding the Patent Drawing + exposition.
   First pass was overlay-on-play-main (locked to bottom on split
   layouts); second was full-viewport (Scott: too aggressive — should
   be a modal); this is the modal. Backdrop dims everything else so
   the panel reads as the focus. */
.deep-view{
  position:fixed;
  inset:0;
  z-index:600;
  background:rgba(20, 12, 4, 0.55);
  opacity:0;
  pointer-events:none;
  transition:opacity 320ms ease;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:32px;
}
.deep-view[data-open="true"]{
  opacity:1;
  pointer-events:auto;
}
.deep-view-shell{
  background:var(--vellum, #ece4cf);
  width:100%;
  max-width:920px;
  max-height:90vh;
  overflow-y:auto;
  padding:28px 36px 36px;
  border:1px solid var(--gold2);
  border-radius:2px;
  box-shadow:0 24px 64px -12px rgba(20, 12, 4, 0.45),
             0 8px 16px -4px rgba(20, 12, 4, 0.25);
}
.dv-back{
  display:inline-flex;
  align-items:center;
  gap:8px;
  background:transparent;
  border:1px solid var(--gold2);
  color:var(--gold);
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:2px;
  text-transform:uppercase;
  padding:6px 12px;
  cursor:pointer;
  margin-bottom:28px;
  transition:background 180ms ease;
}
.dv-back:hover{ background:rgba(200,144,44,0.08); }
.dv-back:focus-visible{ outline:1px solid var(--gold); outline-offset:2px; }
.dv-head{ margin-bottom:16px; text-align:center; }
.dv-title{
  font-family:'Playfair Display',serif;
  font-weight:700;
  font-size:28px;
  letter-spacing:4px;
  text-transform:uppercase;
  color:var(--text);
  line-height:1.05;
  margin:0;
}
.dv-sub{
  display:block;
  margin-top:10px;
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--gold3);
}
.dv-mechanism{
  margin:4px 0 16px;
  background:transparent;
  display:block;
  text-align:center;
}
.dv-mechanism svg{
  display:block;
  max-width:100%;
  max-height:340px;
  height:auto;
  width:auto;
  margin:0 auto;
}
.dv-body{
  font-family:'Playfair Display',serif;
  font-size:15.5px;
  line-height:1.55;
  color:var(--text);
  max-width:60ch;
  margin:0 auto 16px;
  text-align:center;
}
.dv-body strong{ font-weight:700; color:var(--gold); font-style:normal; }
.dv-listen{
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--gold3);
  margin-bottom:16px;
  text-align:center;
}
.dv-listen a{
  color:var(--gold);
  text-decoration:none;
  border-bottom:1px solid var(--gold2);
}
.dv-listen a:hover{ color:var(--gold2); }
/* 2026-05-21 — Patent record link slot. Each deep view can register one
   or more patents; renders as a centered "PATENT(S) · <link> · <link>"
   line so the mechanism honors the actual primary source. */
.dv-patents{
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--gold3);
  margin-bottom:10px;
  text-align:center;
}
.dv-patents a{
  color:var(--gold);
  text-decoration:none;
  border-bottom:1px solid var(--gold2);
  margin:0 4px;
}
.dv-patents a:hover{ color:var(--gold2); }
.dv-controls{
  margin-top:16px;
  padding-top:16px;
  border-top:1px solid var(--gold2);
  text-align:center;
}
.dv-controls .ps-tempo-mvoice{
  justify-content:center;
}
/* 2026-05-21 — modal footer line naming the current sidebar setting.
   Modal is read-only learning; this line connects "what I'm watching"
   to "what I have set in the tool." Patent register, italic Playfair. */
.dv-state-label{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-size:14px;
  line-height:1.5;
  color:var(--text);
  opacity:0.78;
  margin:0;
}
.dv-state-label strong{
  font-family:'Space Mono',monospace;
  font-style:normal;
  font-size:12px;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--gold);
  opacity:1;
}

/* 2026-05-21 — Sidebar + deep-view escapements animate via RAF
   (driven by _escapementAnimateStart in src/v2-modes.js) so the
   pendulum's leg durations are ASYMMETRIC at swing > 0 — long swing
   one way, short the other. That asymmetric motion is the visible
   swing. Static fallback for reduce-motion users; pallet widths
   still encode the swing % independent of motion. */
.ps-swing-visual #ps-esc-anchor,
.ps-swing-visual #ps-esc-pendulum{
  transform-box: view-box;
  transform-origin: 60px 6px;
}
.ps-swing-visual #ps-esc-wheel{
  transform-box: view-box;
  transform-origin: 60px 38px;
  transition: transform 140ms cubic-bezier(0.32, 0.72, 0, 1);
}
.deep-view #dv-esc-anchor,
.deep-view #dv-esc-pendulum{
  transform-box: view-box;
  transform-origin: 320px 100px;
}
.deep-view #dv-esc-wheel{
  transform-box: view-box;
  transform-origin: 320px 250px;
  transition: transform 140ms cubic-bezier(0.32, 0.72, 0, 1);
}
/* Deep view play button — prominent enough to invite the "hear AND see" loop */
.dv-play-btn{
  display:inline-flex;
  align-items:center;
  gap:10px;
  background:transparent;
  border:1px solid var(--gold);
  color:var(--gold);
  font-family:'Space Mono',monospace;
  font-size:12px;
  letter-spacing:2px;
  text-transform:uppercase;
  padding:10px 20px;
  cursor:pointer;
  margin-bottom:16px;
  transition:background 180ms ease, color 180ms ease;
}
.dv-play-btn:hover{ background:rgba(200,144,44,0.10); }
.dv-play-btn:focus-visible{ outline:1px solid var(--gold); outline-offset:2px; }
.dv-play-btn .dv-play-icon{ font-size:14px; line-height:1; }
.dv-play-btn[data-playing="true"]{ background:var(--gold); color:var(--vellum); }

/* ═══════════════════════════════════════════════════════════════════════
 * PL. I · FORM-STACKED CHORD SURFACE  (R6.51 v1.1)
 * ═══════════════════════════════════════════════════════════════════════
 * Tool-surface variation of the Pianola IDEAS. The chord cards are the
 * thing the jam-along player reads at music-stand distance, so they
 * stay BIG; sections stack as rows (form-stacking); repeats compress
 * (×N badge); long tunes fit viewport (no scroll). Patent-Drawing
 * chrome (FIG. D header, spool gutters, tracker frame, pneumatic
 * stack) does NOT live here — that's the v1.2 deep-view modal, the
 * museum exhibit alongside METRONOME / KEY / SCALE / DELAY. The TOOL
 * is a variation; the MODAL is true-to-form.
 * See src/v2-modes.js → _renderPianolaInline */
#pianola-inline-host{
  display:block;
  width:100%;
}
#pianola-inline-host.pia-mounted{
  display:block;
  width:100%;
  margin:4px 0 10px;
}

/* Section row stack */
.pia-mounted .pia-rows{
  display:flex;
  flex-direction:column;
  gap:6px;
  width:100%;
  min-width:0;
}

/* Section row — two resolutions: active (full chord cards) vs queued
 * (compact chip strip). Gutter is thin + quiet so the cards get the
 * real estate they need at music-stand distance. */
.pia-mounted .pia-row{
  display:grid;
  grid-template-columns:44px 1fr;
  position:relative;
  background:transparent;
}
.pia-mounted .pia-row.queued{opacity:0.78;}
.pia-mounted .pia-row + .pia-row{
  border-top:1px solid rgba(106,64,16,0.22);
  padding-top:4px;
}

.pia-mounted .pia-row-gutter{
  display:flex;
  align-items:center;
  justify-content:center;
  padding:4px 6px;
  flex:0 0 36px;
}
.pia-mounted .pia-row-letter{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:900;
  color:var(--gold,#9a6420);
  font-size:30px;
  line-height:1;
}
.pia-mounted .pia-row.queued .pia-row-letter{
  color:var(--dim2,#5a4828);
  opacity:0.7;
}
/* Chartjunk (mode pill, ×N badge, L⁵ tag) removed in v1.5 — chip strip
 * below handles section structure via _padRenderPlateStrip dividers.
 * .pia-mode-pill / .pia-repeat-badge / .pia-row-tag classes no longer
 * emitted by _piaSectionRow. */

/* Active row's chord-card slot — pass-through, no padding chrome that
 * would shrink the cards. */
.pia-mounted .pia-row.active .pia-row-cards{
  padding:0;
  min-width:0;
}
.pia-mounted .pia-row.active .pia-row-cards #play-prog-dots{
  width:100%;
}
/* Queued row's chip strip */
.pia-mounted .pia-row.queued .pia-row-cards.pia-chips{
  padding:4px 0;
  display:flex;
  flex-wrap:wrap;
  gap:3px;
  align-items:center;
  min-height:22px;
}
.pia-mounted .pia-chip{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-width:26px;
  height:18px;
  padding:0 5px;
  background:rgba(10,5,0,0.85);
  border:0.5px solid var(--gold2,#6a4010);
  border-radius:9px;
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:700;
  font-size:10px;
  color:var(--ivory,#f0e2be);
}

/* Form ribbon + PAT. 1904 stub removed in v1.5 — chartjunk (chip strip
 * below already shows section sequence via dividers; PAT.1904 deep
 * view will live on PL. II where playback-as-time happens). */

/* (ADD FORM affordance CSS removed r6p65d — affordance was vaporware;
 * see _renderPianolaInline for the JS-side removal note.) */

/* r6p65e DOCK MAGNIFICATION — chips themselves grow/shrink based on
 * distance from the active chord. macOS Dock magnifier metaphor: chips
 * at base size, the "lens peak" (active) renders as a full chord card,
 * immediate neighbours render medium, far chips stay small. As the song
 * advances the peak migrates and sizes interpolate smoothly. ALL chords
 * in the active section visible at once (Don Julin: shows the whole
 * shape; Tufte: data-dense; Norman: direct mapping; FLW: the row IS the
 * progression IS the timeline IS the indicator). */
body[data-plate-lens="I"].pianola-active .prog-card-row{
  display:flex;
  flex-wrap:nowrap;
  gap:6px;
  align-items:center;
  justify-content:center;
  padding:8px 12px 12px;
  overflow-x:auto;
  overflow-y:hidden;
  /* Override the default grid sizing — we want flex with per-chip width */
  grid-template-columns:none;
}

/* Base — every Pianola card is flex item with smooth size transitions */
body[data-plate-lens="I"].pianola-active .prog-card{
  flex:0 0 auto;
  overflow:hidden;
  transition:
    width 280ms cubic-bezier(.32,.8,.42,1),
    height 280ms cubic-bezier(.32,.8,.42,1),
    padding 280ms cubic-bezier(.32,.8,.42,1),
    opacity 280ms cubic-bezier(.32,.8,.42,1),
    transform 280ms cubic-bezier(.32,.8,.42,1);
  min-width:0;
  position:relative;
}

/* UNIFORM CARDS, v1.5 — every chord card the same size. Active chord
 * highlighted via standard .prog-card.active brass border (existing
 * styling). No size graduation, no magnification, no popped-up card.
 * Two surfaces: rows of cards above (shape decisions), chip strip
 * below (sequence + editing). The Pianola-as-mechanism moves to
 * PL. II Rhythm where playback-as-time actually happens. */
body[data-plate-lens="I"].pianola-active .prog-card-row{
  display:flex;
  flex-wrap:nowrap;
  gap:6px;
  justify-content:center;
  padding:8px 12px;
  overflow-x:auto;
  overflow-y:hidden;
  grid-template-columns:none;
}
body[data-plate-lens="I"].pianola-active .prog-card{
  width:128px;
  height:172px;
  padding:8px 10px;
  flex:0 0 auto;
  position:relative;
  transition:border-color 220ms ease, box-shadow 220ms ease;
}
body[data-plate-lens="I"].pianola-active .prog-card .pc-spelling,
body[data-plate-lens="I"].pianola-active .prog-card .pc-alts{
  display:none;
}
body[data-plate-lens="I"].pianola-active .prog-card .pc-head{
  margin-bottom:4px;
  display:flex;
  flex-direction:row;
  align-items:baseline;
  justify-content:space-between;
}
body[data-plate-lens="I"].pianola-active .prog-card .pc-roman{
  font-size:22px;
  color:var(--gold,#9a6420);
}
body[data-plate-lens="I"].pianola-active .prog-card .pc-name{
  font-size:11px;
  color:var(--dim,#3a2a18);
}
body[data-plate-lens="I"].pianola-active .prog-card .pc-mini-frame{
  transform:scale(0.82);
  transform-origin:top center;
}
/* Active highlight — brass border + warm glow, no size change. */
body[data-plate-lens="I"].pianola-active .prog-card.active,
body[data-plate-lens="I"].pianola-active .prog-card[data-dist="0"]{
  border-color:var(--gold,#9a6420);
  box-shadow:0 0 0 1px var(--gold,#9a6420), 0 4px 12px rgba(154,100,32,0.20);
  z-index:2;
}

/* Queued section row — parallel chip strip with full chord cards
 * (Roman + name + mini fretboard) at the SAME base size as the
 * active row's compact chips. AABB reads as two stacked rows of
 * cords (Scott r6p65h walk: "literally two rows of cords... see
 * the shapes"). */
.pia-mounted .pia-row.queued .pia-row-cards.pia-queued-strip{
  display:flex;
  flex-wrap:nowrap;
  gap:6px;
  align-items:center;
  justify-content:center;
  padding:8px 12px;
  overflow-x:auto;
  overflow-y:hidden;
}
.pia-mounted .pia-row.queued .pia-queued-card{
  /* Match the active row's uniform card size (v1.5) so both rows
   * read as parallel chip strips of identical dimensions. */
  width:128px;
  height:172px;
  padding:8px 10px;
  flex:0 0 auto;
  position:relative;
  opacity:0.78;
}
.pia-mounted .pia-row.queued .pia-queued-card .pc-head{
  margin-bottom:4px;
  display:flex;
  flex-direction:row;
  align-items:baseline;
  justify-content:space-between;
}
.pia-mounted .pia-row.queued .pia-queued-card .pc-roman{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:700;
  font-size:20px;
  color:var(--gold,#9a6420);
}
.pia-mounted .pia-row.queued .pia-queued-card .pc-name{
  font-family:'Space Mono',monospace;
  font-size:10.5px;
  letter-spacing:0.8px;
  color:var(--dim,#3a2a18);
}
.pia-mounted .pia-row.queued .pia-queued-card .pc-mini-frame{
  transform:scale(0.78);
  transform-origin:top center;
}

/* (Chip-strip-hide rule from r6p65c removed in v1.5c — the chip strip
 * carries the add/delete affordances people need on all PL.I states,
 * not just editing. Hide-when-not-editing was a holdover from when
 * the form-stacked rows duplicated the chip strip's structural job.
 * With v1.5b's deduped 3-card rows, the chip strip is no longer
 * redundant — it's the only place to add/delete chord slots.) */

/* Hide the chord-card surface (#pianola-inline-host) on PL. II Rhythm
 * + PL. III Color — those plates show the fretboard, not chord cards.
 * Scott's call r6p65l walk: "we only see the chord cards on the
 * shapes." Cards live exclusively on PL. I. */
body[data-plate-lens="II"] #pianola-inline-host,
body[data-plate-lens="III"] #pianola-inline-host{
  display:none !important;
}

/* ═══════════════════════════════════════════════════════════════════════
 * PL. I SHAPES · v2.4 SCALE-DEGREE ROW + 3-FULL + PEEK
 * ═══════════════════════════════════════════════════════════════════════
 * Ported from docs/2026-05-28-pianola-v2p3-mockup.html (Scott approved).
 *
 * Per-section row of UNIQUE chord cards, sorted left→right by SCALE
 * DEGREE (I → IV → V → bVII for D mix Over the Waterfall — not
 * progression order). Eye scans L→R = walking up the scale.
 *
 * Window: 3 cards visible at full canonical size + 4th (and beyond) as
 * peripheral peek(s). Lens vote 5-0 (Tufte/Norman/Julin/FLW/Patent)
 * for capping at 3 to preserve fretboard readability. As active hops
 * to a chord outside the visible window, the window slides one
 * position so active enters at the edge.
 *
 *   ACTIVE     = brass border + paper bg + full chrome (spelling +
 *                ◀ N/M ▶ voicing flip + LOCK)
 *   INACTIVE   = same canonical fretboard + 64px spacer for height
 *                match with active
 *   PEEK       = compact 130px wide / 60px fretboard / opacity 0.72;
 *                signals "more vocabulary lives here" without
 *                competing with the readable three. Fretboards only
 *                shrink HERE (Scott's rule: fretboards stay canonical
 *                across all tabs unless the whole card is shrunken).
 *
 * Legacy chord chips strip (.plate-prog-strip-wrap) stays mounted
 * below — same primitive as PL. II Rhythm + PL. III Color for plate
 * continuity. */

body[data-plate-lens="I"].pianola-active .pia-shapes{
  display:flex;
  flex-direction:column;
  gap:14px;
  width:100%;
  max-width:none;
}

/* ── GRID ───────────────────────────────────────────────────────── */
.pia-shapes .pia-grid{
  display:flex;
  flex-direction:column;
  gap:12px;
}
.pia-shapes .pia-row{
  display:flex;
  align-items:flex-start;
  gap:14px;
}
.pia-shapes .pia-row-letter{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:900;
  font-size:30px;
  color:var(--gold,#9a6420);
  width:36px;
  flex:0 0 36px;
  text-align:center;
  align-self:center;
}
.pia-shapes .pia-row-cards{
  display:flex;
  flex:1 1 auto;
  align-items:flex-start;
  gap:12px;
  flex-wrap:nowrap;
  scrollbar-width:thin;
  scroll-behavior:smooth;
}
/* r6p72a2 — at 1-6 unique chords, cards fit the stage at 200-280
 * wide; centered with breathing room. At 7+ they'd overflow, so
 * anchor left and enable horizontal scroll; active card scrolled
 * into view by JS on render. Same affordance per card across
 * counts — cards never shrink below the 200-px 3-ft floor. */
.pia-shapes .pia-row-cards[data-count="1"],
.pia-shapes .pia-row-cards[data-count="2"],
.pia-shapes .pia-row-cards[data-count="3"],
.pia-shapes .pia-row-cards[data-count="4"],
.pia-shapes .pia-row-cards[data-count="5"],
.pia-shapes .pia-row-cards[data-count="6"]{
  justify-content:center;
  overflow:visible;
}
.pia-shapes .pia-row-cards{
  justify-content:flex-start;
  overflow-x:auto;
  overflow-y:visible;
  padding-bottom:8px;
}

/* ── CARD ───────────────────────────────────────────────────────── */
/* Chord card — the PL. I instance of the Fifths universal
 * action-stage item primitive (docs/2026-05-29-rail-collapse-tri-plate.md
 * §13). Same card height treatment applies on PL. II beat tiles
 * and PL. III color cells when they land.
 * Total height: 380 px (fits the 421-px stage budget at 1920 with
 * 41 px region padding). Active and inactive ALWAYS the same height
 * — active chrome (50) replaces inactive spacer (50) one-for-one.
 * Width: 200–280 responsive flex. */
.pia-shapes .pia-card{
  background:var(--vellum2,#dde3c5);
  border:1px solid rgba(106,64,16,0.55);
  padding:8px 10px;
  /* r6p85m — COMPACT GRIP: a small label over the fretboard, nothing else.
     No chrome, no spacer → every card is identical and short (label + board).
     The selected chord's controls live in one shared strip below the row. */
  display:flex;
  flex-direction:column;
  align-items:stretch;
  gap:4px;
  position:relative;
  cursor:pointer;
  /* r6p72a4 — fixed 240 px so every card is the exact same size
   * regardless of count. Scott walkthrough: comparing Reba (2
   * cards at 280) and Ode (5 cards at 210) showed Ode chord
   * glyphs visibly smaller and less prominent — Reba "grand,"
   * Ode "compact." Now both render at 240, the chord-chart
   * glyph is identical across all tunes, overflow scrolls. */
  /* r6p85n — fixed GRAND width, uniform across ALL tunes regardless of chord
     count — "no song penalized by its length" (a long tune SCROLLS, it doesn't
     get shrunk cards). r6p88f — grown 168→210 to USE the plate's wasted vertical
     whitespace: bigger boards = more readable charts, which is what the space is
     FOR (Scott). The LOCK'S INTENT is preserved — still uniform across every
     song, long tunes still scroll; this raises the grand size, it doesn't size-
     to-fit-count (the thing the rule forbids). Lens read: a max-size cap was
     never the rule; uniformity was. */
  flex:0 0 210px;
  width:210px;
  opacity:0.94;
  transition:background 220ms ease,
             border-color 220ms ease,
             box-shadow 220ms ease,
             opacity 220ms ease,
             flex-basis 320ms ease;
}
.pia-shapes .pia-card:hover{ opacity:1; }

/* Active: brass border + paper bg highlight */
/* r6p88b — the ACTIVE (under-study) card gets its OWN signifier, distinct from
   the cabinet's flat inset brown-frame drawer language. The cards' vocabulary is
   shadow/glow/motion (the sounding card already glows + moves), so the active
   card READS AS RAISED + LIT: a gold ring, a lift, a soft halo. "This is THE
   live chord," not "this card is in a box." (Norman: one meaning, one signifier.)
   Lens-driven fix for "how would anyone know which card is highlighted?" */
.pia-shapes .pia-card.active{ opacity:1; position:relative; z-index:3; }
/* the RAISED + LIT signifier applies only at REST — in PLAY the focus recedes
   (the neutralizer below) so the sounding card is the sole cue. Scoping the
   whole emphasis to :not(play) keeps it from fighting the play-mode rules. */
body:not([data-playing="1"]) .pia-shapes .pia-card.active{
  background:#faf3dd;                                   /* warmer than siblings' paper */
  border:1.5px solid var(--gold,#9a6420);
  box-shadow:0 0 0 2px var(--gold,#9a6420), 0 7px 20px rgba(154,100,32,0.26);
  transform:translateY(-4px) scale(1.025);
  transition:transform .2s ease, box-shadow .2s ease;
}

/* ── REST vs PLAY (docs/2026-05-30-global-vs-lens-IA.md). Rest = workbench
   (chrome = tools, the focused card is brass-bordered). Play = performance:
   chrome recedes, no card is "focused", only the SOUNDING card glows and moves
   with the music. The transition breathes (.3s fade). */
.pia-shapes .pia-active-control{ transition:opacity .3s ease; }
body[data-playing="1"] .pia-shapes .pia-active-control{ opacity:0; pointer-events:none; }
/* No focus in play — neutralize the active card's emphasis and suppress the
   static render-time playing-now underline; .pia-sounding is the live cue.
   EXCLUDE the sounding card so its glow survives (it's a box-shadow too). */
body[data-playing="1"] .pia-shapes .pia-card.active:not(.pia-sounding){
  background:transparent; border-color:transparent; box-shadow:none;
  transform:none;   /* r6p88b — drop the rest-state lift in play (focus recedes) */
}
body[data-playing="1"] .pia-shapes .pia-card.playing-now::after{ display:none; }
/* The sounding card's glow must read clearly in play (after the neutralize so
   it wins on equal specificity). */
body[data-playing="1"] .pia-shapes .pia-card.pia-sounding{
  background:var(--paper,#efe6c8);
  box-shadow:0 0 0 1.5px var(--gold), 0 0 18px rgba(200,144,44,0.6);
}

/* ── REST vs PLAY on RHYTHM + COLOR. Unlike Shapes (where you WATCH in play, so
   the edit chrome hides), the Rhythm/Color sidebar controls are LIVE INSTRUMENTS
   you ride while performing — swing, bass/drum style, metronome, mode, reverb.
   So they STAY. The only pure chrome is the patent stamps; those recede. The
   play-mode signature on these tabs is the FIRING (pendulum/pattern/mode pills
   pulsing), which is already there. docs/2026-05-30-global-vs-lens-IA.md. */
.plate-sidebar .pat-stamp{ transition:opacity .3s ease; }
body[data-playing="1"] .plate-sidebar .pat-stamp{ opacity:0; pointer-events:none; }

/* On Color + Rhythm the fretboard caption is just "FIG. III" / "FIG. II" — the
   key/scale/pattern/swing/bpm are all shown elsewhere (bottom bar, wheel,
   cartouches), so the context + rhythm-caption + their rule are dropped. Hide
   the dangling rule + any stale context. (Scott 2026-05-30: "same on rhythm".)
   The live beat RULER (.plate-rhythm-ruler) is untouched — that's the firing. */
body[data-plate-lens="III"] .pff-head .fig-rule,
body[data-plate-lens="II"]  .pff-head .fig-rule,
body[data-plate-lens="II"]  .pff-context{ display:none; }

/* ── r6p88s/r6p89 — THE TETHER. A 1px dashed #9a6420 line dropping from the active
   card's bottom-centre to the CABLE just below it — the card's attachment to the
   rail the carriage rides (the dot moved to the carriage's hollow pulley, which now
   terminates the line on the cable). Shortened from 36px (it used to reach a full-
   width band) to ~14px (card → cable). REST-ONLY: in play the focus recedes
   (REST/PLAY rule), so the study tether goes with it. */
body:not([data-playing="1"]) .pia-shapes .pia-card.active::before{
  content:"";
  position:absolute;
  left:50%;
  transform:translateX(-50%);
  top:100%;
  width:1px;
  height:14px;
  pointer-events:none;
  z-index:4;
  background:linear-gradient(var(--gold,#9a6420) 50%, transparent 50%) center top / 1px 4px repeat-y;
}

/* Playing-now: brass underline pulse (independent of active focus) */
.pia-shapes .pia-card.playing-now::after{
  content:"";
  position:absolute;
  left:8px;
  right:8px;
  bottom:-5px;
  height:3px;
  background:var(--gold,#9a6420);
  border-radius:1.5px;
  box-shadow:0 0 6px rgba(154,100,32,0.45);
  animation:pia-playing-pulse 1.2s ease-in-out infinite;
}
@keyframes pia-playing-pulse{
  0%, 100%{ opacity:1; }
  50%{ opacity:0.55; }
}

/* r6p72a2 — peek class is now a NO-OP: every chord card gets the
 * same affordance regardless of count. Scott's call after the
 * Reba vs Ode walkthrough: "same affordance regardless of # of
 * chords." Peek made the horizon cards look diminished against
 * the focal middle; for many-chord tunes that meant the user
 * was looking at second-class chord cards. Now: cards uniformly
 * size (200–280) and the row scrolls horizontally for overflow
 * (9+ unique chords). Active card scrolled into view by JS on
 * tune load + chord change. */
.pia-shapes .pia-card.peek{
  /* inherit base .pia-card sizing — same affordance */
}

/* r6p85m — compact top label: roman + name on one baseline-aligned row above
   the fretboard. Small (no 44px bar / border / negative margins). */
.pia-shapes .pia-card-head{
  display:flex;
  flex-direction:row;
  align-items:baseline;
  justify-content:flex-start;
  gap:6px;
}
.pia-shapes .pia-card-roman{
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:700;
  font-size:22px;
  color:var(--gold-ink,#7a4a12);   /* contrast: gold 3.99:1 on card → gold-ink */
  line-height:1;
  flex:0 0 auto;
}
.pia-shapes .pia-card-name{
  font-family:'Space Mono',monospace;
  font-size:13px;
  letter-spacing:0.6px;
  color:var(--dim,#3a2a18);
  font-weight:700;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
/* r6p89 — THE NOTES, TOP-RIGHT (Scott): the active chord's literal pitches sit at
   the right end of the head, opposite its degree·key on the left ("I·D" … "D·F♯·A").
   margin-left:auto pushes it to the right edge (same pattern as .pia-card-fretstart).
   Only the active card renders it (see _piaBuildCard), so the row stays uniform. */
.pia-shapes .pia-card-spelling{
  margin-left:auto;
  font-family:'Playfair Display',serif;
  font-style:italic;
  font-weight:600;
  font-size:15px;
  letter-spacing:0.6px;
  color:var(--gold-ink,#7a4a12);
  line-height:1;
  white-space:nowrap;
  flex:0 0 auto;
}
/* r6p72a — STARTS · FR. X tag (or OPEN). Patent register small
 * caps in gold. Sits right-aligned in the head so readers know
 * which fret window the diagram opens at, without counting from
 * the side labels. Reference: docs/2026-05-29-rail-collapse-tri-plate.md §13. */
.pia-shapes .pia-card-fretstart{
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--gold-ink,#7a4a12);   /* contrast */
  font-weight:700;
  opacity:0.78;
  white-space:nowrap;
  margin-left:auto;
  align-self:center;
}

/* Vertical chord-chart fretboard viewer — taller than wide.
 * SVG viewBox 134×280 from miniChordDiagramV; container sizes the
 * width and lets height auto-scale.
 * r6p72a — max-width raised 140 → 200 so the SVG actually scales
 * with the wider responsive cards (200–280px), and max-height cap
 * keeps card total height in viewport bounds (3-ft legibility
 * trade — slightly wasted horizontal padding at max card width
 * is the cost of preserving the chord-chart aspect ratio without
 * touching the viewBox internals). */
.pia-shapes .pia-card-board{
  flex:0 0 auto;
  display:flex;
  align-items:center;
  justify-content:center;
}
.pia-shapes .pia-card-board svg{
  width:100%;
  max-width:100%;
  max-height:none;   /* tall neck board renders full height */
  height:auto;
  display:block;
}

/* r6p85l — the 70px inactive spacer is GONE. With the side-rail the active
   card's chrome adds WIDTH not height, so all cards already share the board's
   height; no spacer (and no blank bottom) needed. */

/* ── ACTIVE CARD CHROME (spelling + voicing flip + LOCK) — r6p85l: stacked in
   the side rail (was a centered bottom bar). Left-aligned, no top border. ── */
.pia-shapes .pia-card-spelling{
  font-family:'Space Mono',monospace;
  font-size:12px;
  letter-spacing:0.6px;
  color:var(--dim,#3a2a18);
  font-weight:700;
  text-align:left;
  line-height:1.5;
  margin-top:2px;
}
.pia-shapes .pia-card-actions{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:8px;
  margin-top:auto;          /* push nav + lock to the bottom of the rail */
}
.pia-shapes .pia-card-altnav{
  display:flex;
  align-items:center;
  gap:4px;
}
.pia-shapes .pia-altnav-btn{
  background:transparent;
  border:1px solid var(--gold2,#6a4010);
  color:var(--gold-ink,#7a4a12);   /* contrast */
  padding:2px 8px;
  font-size:12px;
  line-height:1.4;
  cursor:pointer;
  border-radius:1px;
  transition:background 120ms ease;
}
.pia-shapes .pia-altnav-btn:hover{
  background:rgba(154,100,32,0.10);
}
.pia-shapes .pia-altnav-label{
  font-family:'Space Mono',monospace;
  font-size:10px;
  letter-spacing:0.8px;
  color:var(--gold-ink,#7a4a12);   /* contrast */
  font-weight:700;
  min-width:30px;
  text-align:center;
}
.pia-shapes .pia-altnav-label.single{
  color:var(--gold2,#6a4010);
  opacity:0.65;
}
/* Lock icon button — padlock SVG only (matches chord-chip lock).
 * Compact icon-only target; brass border + paper bg unlocked,
 * filled brass when locked. */
.pia-shapes .pia-card-lock{
  background:transparent;
  border:1px solid var(--gold2,#6a4010);
  color:var(--gold,#9a6420);
  padding:3px 6px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  cursor:pointer;
  transition:background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.pia-shapes .pia-card-lock svg{ display:block; }
.pia-shapes .pia-card-lock:hover{
  background:rgba(154,100,32,0.10);
}
.pia-shapes .pia-card-lock.is-locked{
  background:var(--gold,#9a6420);
  color:var(--ivory,#f0e2be);
  border-color:var(--gold,#9a6420);
}

/* r6p85m — the ONE shared control for the selected chord, centered below the
   card row: identity · notes · voicing flip · lock. Replaces per-card chrome,
   so the cards stay uniform compact grips (no reserved blank). */
/* r6p88d — FINGERING is a full-width BAND (Design's structure): a filled vellum
   bar spanning the plate, caption + spelling LEFT, page-nav + lock RIGHT. The
   active chord's notes read as a shelf under the board row, not a floating
   cluster on a hairline. (Matches Design's edge-to-edge band layout.) */
.pia-shapes .pia-active-control{
  display:flex;
  flex-direction:row;
  align-items:center;
  justify-content:flex-start;
  gap:18px;
  /* r6p88g — the band belongs to the chord cards, so it HUGS their span, not the
     whole plate (Scott: "the bar should never be that much wider than the set of
     chord cards"). Width matches ~4 grand cards (4×210 + gaps ≈ 900) and centers
     under the row; controls stay right via margin-left:auto on .pia-ac-right. */
  width:min(912px, 100%);
  margin:16px auto 0;
  box-sizing:border-box;
  padding:11px 22px;
  background:var(--paper,#efe6c8);
  border:1px solid var(--gold2,#6a4010);
  border-radius:3px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.25);
}
/* the nav + lock cluster sits at the far right of the band */
.pia-shapes .pia-ac-right{
  margin-left:auto;
  display:flex; align-items:center; gap:16px;
}
.pia-shapes .pia-ac-caption{
  font-family:'Space Mono',monospace;
  font-size:10px;
  font-weight:700;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--gold-ink,#7a4a12);
  line-height:1;
}
/* r6p88d — the spelling is the band's HERO (Design): a large Playfair serif
   display of the active chord's notes, not small mono. Gives the band weight. */
.pia-shapes .pia-ac-spelling{
  font-family:'Playfair Display',serif;
  font-size:21px;
  font-style:italic;
  letter-spacing:1px;
  color:var(--text,#1a0c04);
  font-weight:600;
  line-height:1;
}

/* ════════════════════════════════════════════════════════════════════════════
   r6p89 — THE VOICING CARRIAGE (lens panel + Scott's beam-and-pulley)
   The full-width FINGERING band (.pia-active-control, above — now unused) is
   replaced by a carriage that hangs from a cable strung under the card row and
   TRAVELS to whichever chord is active, so the changer is always under its chord.
   Drawn in patent register: hairline cable, hollow pulley-wheel, one offset-shadow.
   _piaPlaceCarriage() sets left/top/width and glides the travel on `left`.
   ════════════════════════════════════════════════════════════════════════════ */
.pia-shapes .pia-grid{ position:relative; padding-bottom:88px; }
/* THE CABLE — the rail between the first and last card centres (the "beam"), with a
   small anchor-ring tied off at each end. left/top/width set by _piaPlaceCarriage. */
.pia-shapes .pia-cable{
  position:absolute; height:0; z-index:1;
  border-top:1.25px solid var(--gold2,#6a4010); opacity:0.7;
  transition:opacity .3s ease;
  /* r6p89b (Scott) — the wire stands proud of the wall, so it casts the SAME drawn
     offset-shadow as the carriage. One light source (upper-left), one shadow. */
  filter:drop-shadow(2px 2px 0 var(--shadow-ink,#b3b896));
}
/* r6p89b — END BRACKETS (Scott: "how is it attached to the wall? standing up from
   it?"). The cable ties off to a small mounting block bolted to the plate at each
   end — a filled bracket (not a hollow ring), which reads as a post holding the wire
   proud of the surface. The parent's drop-shadow gives each bracket the same offset
   shadow, so the whole rig sits on one consistent plane above the page. */
.pia-shapes .pia-cable::before,
.pia-shapes .pia-cable::after{
  content:""; position:absolute; top:-4px; width:6px; height:8px;
  border-radius:1.5px; border:1px solid var(--gold2,#6a4010);
  background:var(--vellum2,#dcd9b8); box-sizing:border-box;
}
.pia-shapes .pia-cable::before{ left:-5px; }
.pia-shapes .pia-cable::after{ right:-5px; }
/* THE CARRIAGE — pulley (rides the cable) + hanger + body (the verbs). Centred under
   the active card via `left`; the `left` transition IS the travel (zip-and-settle). */
.pia-shapes .pia-carriage{
  position:absolute; z-index:3;
  display:flex; flex-direction:column; align-items:center;
  transition:left .52s cubic-bezier(.34,1.32,.5,1), opacity .3s ease;
  /* r6p89b — ONE drawn offset-shadow for the whole assembly (pulley + hanger +
     body), matching the cable. A single silhouette shadow reads as one rig standing
     proud of the wall, lit from the same upper-left source. */
  filter:drop-shadow(2px 2px 0 var(--shadow-ink,#b3b896));
}
.pia-shapes .pia-carriage-pulley{
  width:14px; height:14px; border-radius:50%; box-sizing:border-box;
  border:1.5px solid var(--gold2,#6a4010);
  background:var(--paper,#efe6c8);
  box-shadow:inset 0 0 0 3px var(--paper,#efe6c8);   /* hollow centre → reads as a wheel */
  margin-top:-7px;                                   /* seat the wheel ON the cable line */
}
.pia-shapes .pia-carriage-hanger{
  width:1px; height:13px; background:var(--gold2,#6a4010); opacity:0.55;
}
.pia-shapes .pia-carriage-body{
  display:flex; align-items:center; gap:14px;
  padding:5px 11px;
  background:var(--paper,#efe6c8);
  border:1px solid var(--gold2,#6a4010); border-radius:2px;
  /* shadow now comes from the parent .pia-carriage filter (one unified silhouette) */
}
/* r6p97 — in play, the carriage does NOT vanish (Scott: a physical slider
   wouldn't disappear in real life). It stays on its cable and RIDES to the
   sounding card (an alive playhead, like the Rhythm ruler's beat carriage,
   driven by _piaRideCarriageTo). Made INERT during performance — an indicator,
   not a control — and its voicing-nav controls quiet down so it reads as a
   playhead, not an editor. The cable stays visible (the carriage rides it). */
body[data-playing="1"] .pia-shapes .pia-carriage{ pointer-events:none; }
/* In play, only the KNOB (pulley) rides the cable as a bare playhead; the
   voicing-control box + its hanger tuck away (you don't edit while performing,
   and the box's "1/3" index isn't playhead info). The slider's bead stays
   present and tracks the music — it doesn't vanish. */
body[data-playing="1"] .pia-shapes .pia-carriage-hanger,
body[data-playing="1"] .pia-shapes .pia-carriage-body{ opacity:0; }
@media (prefers-reduced-motion: reduce){
  .pia-shapes .pia-carriage{ transition:opacity .3s ease; }
}


/* ════════════════════════════════════════════════════════════════════
   r6p96 — BLUEPRINT SKIN (the "develop" switch flips paper <-> blueprint)
   Pass 1: token remap (dark ground, luminous line, light ink) + the
   readability-critical surfaces (page, fretboard frame, sidebar/cards).
   Cartouche-SVG holdouts (hardcoded hex) get converted in follow passes.
   ════════════════════════════════════════════════════════════════════ */
html[data-skin="blueprint"]{
  --bg:#0d1620; --surf2:#142231; --surf3:#1b2c3c;
  --text:#ece3cf; --dim:#b9cdd9; --dim2:#90aaba;
  --border:#3a5567; --border2:#27414f;
  --vellum:#142231; --vellum2:#18293a; --vellum3:#1c2f42; --ivory:#1b2d40;
  --paper:#16263a; /* carriage / pulley body + any --paper surface -> dark sheet */
  --wood-dark:#0a121b; --wood-mid:#13212e;
  --gold:#e8c76a; --gold2:#caa84e; --gold3:#f0d27a; --gold-ink:#e8c76a;
  --amber:#ff9a4d; --green:#58d39a;
  --shadow-warm:rgba(0,0,0,0.45); --highlight-warm:rgba(169,207,224,0.12);
  --shadow-ink:#0a121b; --ink-rail:#ece3cf;
}
html[data-skin="blueprint"] body{ background:#0d1620; }
/* faint blueprint grid on the page ground */
html[data-skin="blueprint"] #app,
html[data-skin="blueprint"] .play-main{
  background-image:
    linear-gradient(rgba(123,160,181,0.045) 1px,transparent 1px),
    linear-gradient(90deg,rgba(123,160,181,0.045) 1px,transparent 1px);
  background-size:30px 30px;
}
/* fretboard frame -> dark sheet, luminous edge (no warm grain/gradient) */
html[data-skin="blueprint"] .plate-fb-frame{
  border-color:rgba(169,207,224,0.5);
  background:#142231;
  box-shadow:inset 0 0 0 1px rgba(13,22,32,0.6), 0 8px 26px rgba(0,0,0,0.4);
}
/* chord cards (pia) -> dark sheets */
html[data-skin="blueprint"] .pia-shapes .pia-card{
  background:#16263a; border-color:rgba(169,207,224,0.35);
}
html[data-skin="blueprint"] body:not([data-playing="1"]) .pia-shapes .pia-card.active{
  background:#1c3046; border-color:var(--gold);
  box-shadow:0 0 0 2px var(--gold), 0 0 16px rgba(232,199,106,0.25);
}
/* The plate sidebar's warm PAPER gradient (rgba(214,220,190,.22)) reads as a
   stray pale "shadow" rectangle on the dark ground — invisible on paper, but
   on blueprint it shows, especially once a drawer opens and the sidebar
   expands to ~600px (Scott: "the shadow when you open a drawer in dark mode").
   Drop it to transparent; the rail boxes + the exhibit panel carry their own
   dark sheets. */
html[data-skin="blueprint"] .plate-sidebar{ background:transparent; }
/* r6p98-logo — the brand mark's strokes are baked PAPER inks (near-black
   #1a0c04 paddle/nut/tuners + bronze #9a6420 axis) that go invisible on the
   dark sheet (Scott: "look at logo in dark mode"). Flip the structural ink to
   the luminous blueprint draughting line (the same #a9cfe0 the fb-frame edge
   uses) and the dashed axis to blueprint gold, so the headstock reads as an
   actual blueprint of itself. Presentation-attribute strokes are CSS-overridable
   so no JS re-render is needed. */
html[data-skin="blueprint"] .rn-brand-mark .bm-ink{ stroke:#a9cfe0; }
html[data-skin="blueprint"] .rn-brand-mark .bm-axis{ stroke:#e8c76a; }
/* the develop switch */
.skin-switch{ display:inline-flex; align-items:center; gap:7px; }
.skin-switch .skin-switch-glyph{
  width:13px; height:11px; border-radius:1.5px; flex:0 0 auto;
  border:1px solid currentColor; position:relative; transition:all .25s ease;
  background:
    repeating-linear-gradient(0deg, currentColor 0 1px, transparent 1px 3px);
  opacity:0.8;
}
/* r6p97-frontdoor — glyph previews the TARGET (matches the target label):
   when in PAPER you can develop INTO blueprint, so the swatch shows the
   blueprint reproduction; when in blueprint the default striped (paper)
   swatch shows. Was keyed on [data-skin="blueprint"] (current state). */
html[data-skin="paper"] .skin-switch .skin-switch-glyph{
  background:#1b3a5c; border-color:#7ba0b5;
  box-shadow:inset 0 0 0 1px rgba(123,160,181,0.5);
}
.skin-switch .skin-switch-lbl{ font-size:9px; letter-spacing:1.6px; }

/* r6p96 BLUEPRINT — text-colour stragglers the token remap didn't reach
   (caught by the SVG-aware legibility audit): bottom-bar labels, chip note
   name, library doors/nav. Light ink on the dark ground. */
html[data-skin="blueprint"] .ps-lbl,
html[data-skin="blueprint"] .ps-sub,
html[data-skin="blueprint"] #ps-chord-sub{ color:#b9cdd9 !important; }
html[data-skin="blueprint"] .plate-prog-chip-name{ color:#ece3cf; opacity:1; }
html[data-skin="blueprint"] .lib-door,
html[data-skin="blueprint"] .lib-door-build,
html[data-skin="blueprint"] .lib-door-import,
html[data-skin="blueprint"] .lib-nav-btn,
html[data-skin="blueprint"] .lib-nav-icon{ color:#ece3cf !important; }

/* r6p96 BLUEPRINT — Library doors (Build/Import): their translucent light-sage
   bg + dim text failed only in the open-Library state. Dark translucent panel +
   light ink. (The other audit "fails" — chip-name, ps-lbl — were false positives:
   the contrast walker read semi-transparent backgrounds as opaque.) */
html[data-skin="blueprint"] #lib-door-build,
html[data-skin="blueprint"] #lib-door-import,
html[data-skin="blueprint"] [class*="lib-door"]{
  background:rgba(20,34,49,0.7) !important;
  color:#ece3cf !important;
  border-color:rgba(169,207,224,0.4) !important;
}
html[data-skin="blueprint"] #lib-nav-tunes,
html[data-skin="blueprint"] #lib-nav-melody,
html[data-skin="blueprint"] #lib-nav-progressions,
html[data-skin="blueprint"] .lib-nav-icon{ color:#ece3cf !important; }
