/* Midi2Score front end.
   One responsive artifact: an editorial spread on a desktop, a viewport-sized
   shell with a bottom dock on a phone, switching at 900px.
   Design source: the accepted mocks in the design track's shared directory.
   Donors, per the taste corpus: worksinprogress (layout, hairlines), cursor
   (colour, type), gumroad's offset-stack-button (the control construction). */

:root{
  --paper:#F7F8FA; --paper-2:#EDF1F6; --paper-3:#DFE6EF;
  --surface:#FFFFFF;
  --ink:#141821; --ink-muted:rgba(20,24,33,.66); --ink-soft:rgba(20,24,33,.78);
  --ink-faint:rgba(20,24,33,.44);
  --rule:rgba(20,24,33,.1); --rule-strong:rgba(20,24,33,.22);
  --accent:#0C62CF; --accent-deep:#004CB7; --accent-fg:#141821;
  --accent-fill:#2093FE; --accent-fill-hover:#0083ED; --accent-fill-hit:#0073DB;
  --accent-wash:rgba(12,98,207,.08);
  --tonal:rgba(207,213,221,.7); --tonal-hover:rgba(207,213,221,.85); --tonal-hit:rgba(207,213,221,1);
  --tonal-soft:rgba(207,213,221,.3);
  --shadow-1:0 1px 2px rgba(20,24,33,.06);
  --shadow-2:0 6px 11px rgba(20,24,33,.11);
  --font-ui:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-serif:"Spectral","Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  --font-mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,monospace;
  --text-xs:.75rem; --text-sm:.875rem; --text-base:1rem; --text-md:1.167rem;
  --text-lg:1.333rem; --text-xl:1.833rem; --text-2xl:2.2rem;
  --text-display:clamp(2.2rem,5.4vw,2.667rem);
  --leading-tight:1.15; --leading-snug:1.35; --leading-normal:1.6; --leading-relaxed:1.7;
  --tracking-display:-.02em; --tracking-heading:-.012em; --tracking-ui:0;
  --tracking-caps:.06em; --tracking-body:0;
  --radius-sm:6px; --radius-md:10px; --radius-lg:14px; --radius-pill:999px;
  --plate:0px;
  --focus-w:2px;
  --weight-regular:400; --weight-medium:500; --weight-semibold:600;
  --space-1:.25rem; --space-2:.5rem; --space-3:.75rem; --space-4:1rem; --space-5:1.5rem;
  --space-6:2rem; --space-7:3rem; --space-8:4rem; --space-9:5.5rem;
  --weight-regular:400; --weight-medium:500;
  --duration-fast:150ms; --duration-base:420ms;
  --ease-standard:cubic-bezier(.4,0,.2,1); --ease-entrance:cubic-bezier(.16,1,.3,1);
  --container:1160px; --rail:19.5rem;
  --safe-bot:env(safe-area-inset-bottom,0px);
  /* Without this the native select on the Key field, the scrollbars and the
     focus rings keep following the phone even when a theme has been chosen:
     an explicit Light on a dark phone renders a dark dropdown on a light page. */
  color-scheme:light dark;
}
:root[data-theme="light"]{color-scheme:light}
:root[data-theme="dark"]{color-scheme:dark}
/* Three states, and the order matters: the phone's preference applies
   unless Light was chosen explicitly, and an explicit Dark wins outright.
   A bare media query cannot be beaten by an attribute, which is why the
   `:not()` guard is here rather than relying on source order. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --paper:#0E1116; --paper-2:#161B22; --paper-3:#1F2630;
    --surface:#242427;
    --ink:#E6EAF1; --ink-muted:rgba(230,234,241,.64); --ink-soft:rgba(230,234,241,.8);
    --ink-faint:rgba(230,234,241,.44);
    --rule:rgba(230,234,241,.1); --rule-strong:rgba(230,234,241,.22);
    --accent:#4FA3FF; --accent-deep:#66BAFF; --accent-fg:#0E1116;
    --accent-fill:#2093FE; --accent-fill-hover:#36A3FF; --accent-fill-hit:#0073DB;
    --accent-wash:rgba(79,163,255,.1);
    --tonal:rgba(89,89,89,.7); --tonal-hover:rgba(89,89,89,.85); --tonal-hit:rgba(89,89,89,1);
    --tonal-soft:rgba(89,89,89,.3);
    --shadow-1:0 1px 2px rgba(230,234,241,.06);
    --shadow-2:0 6px 11px rgba(230,234,241,.11);
  }
}
:root[data-theme="dark"]{
    --paper:#0E1116; --paper-2:#161B22; --paper-3:#1F2630;
    --surface:#242427;
    --ink:#E6EAF1; --ink-muted:rgba(230,234,241,.64); --ink-soft:rgba(230,234,241,.8);
    --ink-faint:rgba(230,234,241,.44);
    --rule:rgba(230,234,241,.1); --rule-strong:rgba(230,234,241,.22);
    --accent:#4FA3FF; --accent-deep:#66BAFF; --accent-fg:#0E1116;
    --accent-fill:#2093FE; --accent-fill-hover:#36A3FF; --accent-fill-hit:#0073DB;
    --accent-wash:rgba(79,163,255,.1);
    --tonal:rgba(89,89,89,.7); --tonal-hover:rgba(89,89,89,.85); --tonal-hit:rgba(89,89,89,1);
    --tonal-soft:rgba(89,89,89,.3);
    --shadow-1:0 1px 2px rgba(230,234,241,.06);
    --shadow-2:0 6px 11px rgba(230,234,241,.11);
  }

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--font-serif); font-size:var(--text-base); font-weight:var(--weight-regular);
  line-height:var(--leading-normal); letter-spacing:var(--tracking-ui);
  -webkit-font-smoothing:antialiased;
}
a{color:inherit; text-decoration:none}
button{font:inherit; color:inherit}
.wrap{max-width:var(--container); margin-inline:auto; padding-inline:var(--space-5)}
@media(min-width:900px){ .wrap{padding-inline:var(--space-6)} }
.kicker{font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-muted)}

/* double rule: the title-page device, under the masthead and over the dock */
.rule2{border-top:2px solid var(--rule-strong); position:relative; height:5px}
.rule2::after{content:""; position:absolute; inset:3px 0 auto 0; border-top:1px solid var(--rule)}

.masthead .wrap{display:flex; align-items:baseline; justify-content:space-between;
  gap:var(--space-4); padding-block:var(--space-4)}
.wordmark{font-size:var(--text-lg); letter-spacing:var(--tracking-heading); font-weight:var(--weight-medium)}
/* `min-width:0` on both, so the one item with variable text — the account chip —
   can be squeezed rather than pushing Sign out off the right of a narrow phone.
   A username is now chosen by whoever signs up and can be 32 characters. */
.mast-nav{display:flex; align-items:baseline; gap:var(--space-4); min-width:0}
.mast-nav a{font-family:var(--font-mono); font-size:var(--text-sm); color:var(--ink-muted);
  border-bottom:1px solid transparent;
  transition:color var(--duration-fast) var(--ease-standard),
             border-color var(--duration-fast) var(--ease-standard)}
.mast-nav a:hover{color:var(--ink); border-bottom-color:var(--rule-strong)}
.mast-nav a.here{color:var(--ink)}
.mast-nav .flag{color:var(--accent)}
.mast-nav form{display:contents}
/* Sign out never wraps to two lines to make room for a long username: the chip
   is the elastic item in this bar and takes all of the squeeze. */
.mast-nav .btn{white-space:nowrap; flex:0 0 auto}

/* The account's project is a label, so it gets the corpus's bordered chip. Sign
   out is an action, so it gets the button family at its smallest size — the
   plate is what tells the eye which of the two is pressable. */
.chip{
  font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink);
  border:1px solid var(--rule-strong); border-radius:var(--radius-sm);
  padding:var(--space-1) var(--space-2); white-space:nowrap;
  min-width:0; overflow:hidden; text-overflow:ellipsis;
  transition:border-color var(--duration-fast) var(--ease-standard);
}
.chip:hover{border-color:var(--ink)}
/* The chip holds the username, and the project name after it when that is a
   second fact rather than the same word. The middot is the separator the corpus
   uses inside a line of mono. */
.chip .proj::before{content:"·"; margin-inline:var(--space-2); color:var(--ink-soft)}
.btn.mini{
  min-height:0; padding:var(--space-1) var(--space-3);
  font-size:var(--text-xs); text-transform:uppercase; letter-spacing:var(--tracking-caps);
  box-shadow:2px 2px 0 0 var(--ink);
}
.btn.mini:active{transform:translate(2px,2px); box-shadow:0 0 0 0 var(--ink)}
@media (prefers-reduced-motion:reduce){
  .btn.mini:active{transform:none; box-shadow:2px 2px 0 0 var(--ink)}
}
/* the sign-in screen has one column and nothing to navigate to */
.cols.one{grid-template-columns:1fr}
.cols.one > .main{padding-right:0; max-width:26rem}

/* A form is not a ledger: the label sits above its field and the field is full
   width, per the corpus's input rules. The ledger layout the cue screen uses
   would squeeze both of these into the value column. */
.signin{border:1px solid var(--rule-strong); background:var(--paper-2); padding:var(--space-5)}
.signin .row + .row{margin-top:var(--space-4)}
.signin label{
  display:block; margin-bottom:var(--space-2);
  font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-soft);
}
.signin .tin{width:100%; font-size:var(--text-lg); min-height:var(--space-7)}
.signin .action{margin-top:var(--space-5)}

.titleband .wrap{padding-block:var(--space-7) var(--space-6); border-bottom:1px solid var(--rule)}
h1{font-size:var(--text-display); font-weight:300; line-height:var(--leading-tight);
  letter-spacing:var(--tracking-display); margin:var(--space-2) 0 var(--space-3)}
.dek{font-size:var(--text-md); color:var(--ink-muted); max-width:36em; margin:0; font-weight:300}
.later{
  border:1px solid var(--rule-strong); background:var(--paper-2);
  padding:var(--space-3) var(--space-4); margin-top:var(--space-4);
  font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-muted);
  line-height:var(--leading-relaxed);
}

.cols{display:grid; grid-template-columns:1fr var(--rail); gap:0}
.cols > *{min-width:0}
.cols > .main{padding-block:var(--space-6) var(--space-9); padding-right:var(--space-7)}
.cols > .rail{border-left:1px solid var(--rule); padding:var(--space-6) 0 var(--space-9) var(--space-6)}

/* ── the bounce, and the empty state that precedes it ── */
.bounce{
  border:1px solid var(--rule-strong); background:var(--paper-2);
  padding:var(--space-4) var(--space-5); margin-bottom:var(--space-6);
  transition:border-color var(--duration-fast) var(--ease-standard);
}
.bounce:hover{border-color:var(--ink-faint)}
.bounce-file{display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between; gap:var(--space-3)}
.bounce-file .name{font-family:var(--font-mono); font-size:var(--text-sm); word-break:break-all}
.bounce-file .swap{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft);
  border-bottom:1px solid var(--rule); white-space:nowrap; cursor:pointer; background:none; border-top:0;
  border-left:0; border-right:0; padding:0}
.bounce-file .swap:hover{color:var(--ink); border-bottom-color:var(--rule-strong)}
.readout{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--space-4);
  border-top:1px solid var(--rule); margin-top:var(--space-4); padding-top:var(--space-4)}
.readout div{min-width:0}
.readout .v{font-family:var(--font-mono); font-size:var(--text-md); display:block; letter-spacing:-.01em}
.readout .l{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft); display:block; margin-top:2px}

.drop{
  border:1px dashed var(--rule-strong); background:var(--paper-2);
  padding:var(--space-8) var(--space-5); text-align:center; cursor:pointer; display:block; width:100%;
  transition:border-color var(--duration-fast) var(--ease-standard),
             background-color var(--duration-fast) var(--ease-standard);
}
.drop:hover, .drop.over{border-color:var(--accent); background:var(--accent-wash)}
.drop .big{font-size:var(--text-lg); font-weight:300; display:block; letter-spacing:var(--tracking-heading)}
.drop .small{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft);
  display:block; margin-top:var(--space-2)}
.drop:focus-visible{outline:2px solid var(--accent); outline-offset:3px}

/* ── fields ── */
.field{border-top:1px solid var(--rule); padding-block:var(--space-5)}
.field:last-of-type{border-bottom:1px solid var(--rule)}
.field-top{display:flex; align-items:baseline; justify-content:space-between; gap:var(--space-4); margin-bottom:var(--space-3)}
.field-label{font-size:var(--text-md); font-weight:var(--weight-regular); margin:0; letter-spacing:var(--tracking-heading)}
.prov{font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-soft); white-space:nowrap}
.prov.yours{color:var(--accent)}
.value{font-size:var(--text-xl); font-weight:300; letter-spacing:var(--tracking-heading);
  display:flex; align-items:baseline; gap:var(--space-3); flex-wrap:wrap}
.value .qualify{font-family:var(--font-mono); font-size:var(--text-sm); color:var(--ink-muted)}
.note{font-size:var(--text-sm); color:var(--ink-muted); margin:var(--space-3) 0 0; max-width:44em; font-weight:300}
.note.flagged{color:var(--ink); border-left:2px solid var(--accent); padding-left:var(--space-3)}

.tin{
  font-family:var(--font-serif); font-size:var(--text-xl); font-weight:300;
  background:var(--paper); color:var(--ink); border:1px solid var(--rule-strong);
  border-radius:var(--radius-sm); padding:var(--space-2) var(--space-3); min-width:0; width:100%;
  letter-spacing:var(--tracking-heading);
}
.tin:focus-visible{outline:2px solid var(--accent); outline-offset:2px; border-color:var(--accent)}
@media(max-width:900px){
  .field .tin{width:auto; max-width:11rem; text-align:right; font-size:var(--text-lg)}
  .field select.tin{max-width:12.5rem; font-size:var(--text-sm); text-align:left}
  .signin{padding:var(--space-4)}
  .signin .action{display:none}
}
select.tin{font-family:var(--font-mono); font-size:var(--text-md)}

/* desks: two real tap targets flanking the count */
.desks{display:flex; flex-wrap:wrap; gap:var(--space-4); margin-top:var(--space-1)}
.desk{border:1px solid var(--rule-strong); background:var(--paper);
  display:flex; align-items:stretch; min-width:13.5rem; flex:1 1 13.5rem}
.desk .who{padding:var(--space-3) var(--space-4); font-size:var(--text-md); font-weight:300; flex:1;
  display:flex; align-items:center}
.spin{display:flex; align-items:stretch; border-left:1px solid var(--rule-strong)}
.spin-b{min-width:2.75rem; background:none; border:0; cursor:pointer;
  font-family:var(--font-mono); font-size:var(--text-md); color:var(--ink-soft);
  transition:background-color var(--duration-fast) var(--ease-standard),
             color var(--duration-fast) var(--ease-standard)}
.spin-b:hover{color:var(--ink); background:var(--paper-3)}
.spin-b:active{background:var(--paper-3)}
.spin-b:focus-visible{outline:2px solid var(--accent); outline-offset:-3px}
.spin-n{display:flex; align-items:center; justify-content:center; min-width:2.75rem;
  font-family:var(--font-mono); font-size:var(--text-lg); font-variant-numeric:tabular-nums;
  background:var(--accent-wash); color:var(--accent); border-inline:1px solid var(--rule)}

/* The one thing the cue form has to say about itself: a typed name or a tapped
   desk count lives in this form until Engrave posts it. True on both skins and
   on both devices, so it is stated on all of them. */
.unsaved{font-size:var(--text-sm); color:var(--ink-muted); font-weight:300;
  margin:var(--space-5) 0 0}

.action{margin-top:var(--space-7); display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-4)}
.action .after{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-muted); line-height:1.6}
/* `a` is bare by default here, so the two places a sentence carries a link —
   the note beside a button, and the dock's note under one — have to say so. */
.action .after a, .dock-note a{color:var(--ink); border-bottom:1px solid var(--rule-strong)}

/* ── buttons: one construction, two fills.
   A zero-blur offset plate models displacement rather than a light source, so the
   control reads identically on paper, in dark mode and at any size; pressing lands
   the face on its plate. From the corpus `offset-stack-button`, moved from hover to
   :active because this is a touch surface. ── */
.btn{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  min-height:3.25rem; padding:var(--space-3) var(--space-5); gap:var(--space-2);
  font-family:var(--font-mono); font-size:var(--text-sm); letter-spacing:var(--tracking-ui);
  line-height:var(--leading-snug); text-align:center;
  background:var(--accent); color:var(--accent-fg);
  border:1px solid var(--ink); border-radius:var(--radius-sm);
  box-shadow:var(--plate) var(--plate) 0 0 var(--ink);
  cursor:pointer;
  transition:transform var(--duration-fast) var(--ease-standard),
             box-shadow var(--duration-fast) var(--ease-standard),
             background-color var(--duration-fast) var(--ease-standard);
}
.btn:hover{background:var(--accent-deep)}
.btn:active{transform:translate(var(--plate),var(--plate)); box-shadow:0 0 0 0 var(--ink)}
.btn:focus-visible{outline:2px solid var(--accent); outline-offset:3px}
.btn.ghost{background:var(--paper); color:var(--ink)}
.btn.ghost:hover{background:var(--paper-3)}
.btn[disabled]{opacity:.5; cursor:not-allowed}
@media (prefers-reduced-motion:reduce){
  .btn{transition:background-color var(--duration-fast) var(--ease-standard)}
  .btn:active{transform:none; box-shadow:var(--plate) var(--plate) 0 0 var(--ink); background:var(--accent-deep)}
  .btn.ghost:active{background:var(--paper-3)}
}

/* ── delivered ── */
.collect{border:1px solid var(--rule-strong); background:var(--paper-2);
  padding:var(--space-5); display:flex; flex-wrap:wrap; align-items:center;
  justify-content:space-between; gap:var(--space-4); margin-bottom:var(--space-6)}
.collect .what{min-width:0}
.collect .file{font-family:var(--font-mono); font-size:var(--text-md); display:block; word-break:break-all}
.collect .meta{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft); display:block; margin-top:var(--space-1)}
.summary{font-size:var(--text-md); font-weight:300; max-width:40em; margin:0 0 var(--space-7)}
.summary b{font-weight:var(--weight-regular)}

.family{font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-muted);
  padding-block:var(--space-4) var(--space-2); border-bottom:1px solid var(--rule-strong)}
.stave{display:grid; grid-template-columns:1fr auto; align-items:baseline; gap:var(--space-4);
  border-bottom:1px solid var(--rule); padding-block:var(--space-3)}
.stave .name{font-size:var(--text-md); font-weight:300; letter-spacing:var(--tracking-ui)}
.stave .from{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft); display:block; margin-top:1px}
.stave .n{font-family:var(--font-mono); font-size:var(--text-md); font-variant-numeric:tabular-nums}
.stave.marked{border-left:2px solid var(--accent); padding-left:var(--space-3);
  margin-left:calc(-1 * var(--space-3) - 2px)}
.stave.marked .n{color:var(--accent)}

.meters{display:flex; overflow-x:auto; border:1px solid var(--rule-strong); margin-top:var(--space-6)}
.meters div{font-family:var(--font-mono); font-size:var(--text-sm); padding:var(--space-3) var(--space-4);
  border-right:1px solid var(--rule); white-space:nowrap; flex:0 0 auto}
.meters div:last-child{border-right:0}
.meters div span{display:block; font-size:var(--text-xs); color:var(--ink-soft)}
.meters div.marked{color:var(--accent); background:var(--accent-wash)}
.meters div.marked span{color:var(--accent)}

/* ── decisions, on the delivered cue and in the queue ── */
.look{margin-top:var(--space-8)}
.look > h2{font-size:var(--text-lg); font-weight:var(--weight-regular);
  letter-spacing:var(--tracking-heading); margin:0 0 var(--space-2)}
.look > .sub{font-size:var(--text-sm); color:var(--ink-muted); margin:0 0 var(--space-5);
  font-weight:300; max-width:40em}
.item{border-top:1px solid var(--rule-strong); padding-block:var(--space-5)}
.item:last-child{border-bottom:1px solid var(--rule-strong)}
.item .claim{font-size:var(--text-md); font-weight:300; margin:0 0 var(--space-2); letter-spacing:var(--tracking-ui)}
.item .claim strong{font-weight:var(--weight-medium); color:var(--accent)}
.item .why{font-size:var(--text-sm); color:var(--ink-muted); margin:0; max-width:44em; font-weight:300}
.item .ev{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft);
  display:block; margin-top:var(--space-2)}
.choices{display:flex; flex-wrap:wrap; gap:var(--space-3); margin-top:var(--space-4)}
.choices form{display:contents}

.cue-band{font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-muted);
  padding-block:var(--space-5) var(--space-2); border-bottom:1px solid var(--rule-strong);
  display:flex; justify-content:space-between; gap:var(--space-4)}
.cue-band:first-child{padding-top:0}
.pager{display:none; align-items:center; justify-content:space-between;
  border-bottom:1px solid var(--rule-strong); padding-block:var(--space-3) var(--space-2)}
.pager .where{font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-muted)}
.pager .step{display:flex; gap:var(--space-4)}
.pager .step button{background:none; border:0; cursor:pointer; padding:0 var(--space-1);
  font-family:var(--font-mono); font-size:var(--text-md); color:var(--ink-soft);
  transition:color var(--duration-fast) var(--ease-standard)}
.pager .step button:hover{color:var(--ink)}
.consequence{display:none; margin:auto 0 0; padding-top:var(--space-4);
  border-top:1px solid var(--rule); font-family:var(--font-mono); font-size:var(--text-xs);
  color:var(--ink-soft); line-height:var(--leading-relaxed)}
.closing{margin-top:var(--space-7)}
.closing p{font-size:var(--text-md); font-weight:300; max-width:40em; margin:0}
.closing p em{font-style:italic}

/* ── rail ── */
.rail h2{font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-muted); font-weight:var(--weight-regular);
  margin:0 0 var(--space-4)}
.rail h2 + .rail-sub{font-size:var(--text-sm); color:var(--ink-muted);
  margin:calc(-1 * var(--space-3)) 0 var(--space-4); font-weight:300}
.style-row{border-top:1px solid var(--rule); padding-block:var(--space-3)}
.style-row:last-of-type{border-bottom:1px solid var(--rule)}
.style-row .what{font-size:var(--text-base); font-weight:300; display:block; letter-spacing:var(--tracking-ui)}
.style-row .src{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft);
  display:block; margin-top:2px}
.rail-foot{font-size:var(--text-sm); color:var(--ink-muted); margin-top:var(--space-4); font-weight:300}
.rail-block{margin-top:var(--space-7)}
/* Starting a project is one field and one button, sitting on the row under the
   list it adds to rather than behind a screen of its own. */
.newproj{display:flex; gap:var(--space-2); margin-top:var(--space-4); align-items:stretch}
.newproj .tin{flex:1; min-width:0}
.rail a.lnk{border-bottom:1px solid var(--rule)}
.rail a.lnk:hover{border-bottom-color:var(--rule-strong)}

.foot{border-top:1px solid var(--rule); padding-block:var(--space-5) var(--space-7)}
.foot p{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft); margin:0}

.err{border-left:2px solid var(--accent); background:var(--accent-wash);
  padding:var(--space-3) var(--space-4); margin-bottom:var(--space-5)}
.err b{font-weight:var(--weight-medium); color:var(--accent)}
.err p{margin:var(--space-1) 0 0; font-size:var(--text-sm); color:var(--ink-muted); font-weight:300}

/* ── the dock: mobile only ── */
.dock{display:none}
.dock-action{display:flex; flex-direction:column; align-items:stretch; gap:var(--space-2);
  padding:var(--space-4) var(--space-4) var(--space-3)}
.dock-action.pair{flex-direction:row; gap:var(--space-3); padding:var(--space-4)}
.dock-action.pair .btn{flex:1 1 50%; white-space:normal}
.dock-note{font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft); text-align:center}
.tabs{display:grid; grid-template-columns:repeat(3,1fr); border-top:1px solid var(--rule);
  background:var(--paper-2)}
.tabs.four{grid-template-columns:repeat(4,1fr)}
.tab{font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); color:var(--ink-soft);
  background:none; border:0; border-top:2px solid transparent; margin-top:-1px;
  min-height:3.5rem; padding:var(--space-3) var(--space-1) calc(var(--space-3) + var(--safe-bot));
  text-align:center; cursor:pointer;
  transition:color var(--duration-fast) var(--ease-standard),
             border-color var(--duration-fast) var(--ease-standard)}
.tabs.four .tab{letter-spacing:.07em}
.tab.on{color:var(--ink); border-top-color:var(--accent); background:var(--paper)}
.tab:focus-visible{outline:2px solid var(--accent); outline-offset:-3px}
.tab .flag{color:var(--accent)}

/* ── mobile app shell: the page fits the viewport, only the stage moves ── */
@media(max-width:900px){
  html{height:100%}
  body{height:100dvh; overflow:hidden; display:flex; flex-direction:column}
  .wrap{padding-inline:var(--space-4)}
  .masthead .wrap{padding-block:var(--space-3)}
  /* The mark steps down on the phone and nothing else about it changes: same
     serif, same weight, same colour. 18.7px between the 21.3 the owner called
     too big here and the 17 he called too small. */
  .wordmark{font-size:var(--text-md)}
  .titleband .wrap{padding-block:var(--space-2) var(--space-3); border-bottom:1px solid var(--rule)}
  h1{font-size:var(--text-2xl); margin:2px 0 var(--space-1)}
  .dek{display:none}
  .dek.facts{display:block; font-size:var(--text-sm)}
  .wide{display:none}
  .later{margin-top:var(--space-3); padding:var(--space-2) var(--space-3)}
  .stage{flex:1; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
    display:flex; flex-direction:column}
  /* `.stage` is a flex column and `.wrap` centres itself with auto inline
     margins, which opts it out of stretching: it then shrink-to-fits, and on a
     cue with a long meter row that reaches the 1160px cap and carries every card
     off the right of the phone. Measured on a 19-meter cue at 456px: the wrap
     was 1160px wide. `ios.css` has always carried this rule; the paper skin is a
     real device too, and it is the one `/paper` hands you. */
  .stage > .wrap{flex:1; display:flex; flex-direction:column; min-height:0;
    width:100%; max-width:100%; margin-inline:0}
  .cols{flex:1; display:flex; flex-direction:column}
  .mast-nav{gap:var(--space-3)}
  .cols > .main{padding:var(--space-4) 0}
  .cols > .rail{border-left:0; padding:var(--space-4) 0}
  .panel{display:none}
  .panel.on{display:block}
  .panel[data-panel="open"].on{display:flex; flex-direction:column; flex:1}
  .consequence{display:block}
  .action{display:none}
  .foot{display:none}
  .dock{display:block; background:var(--paper); flex:0 0 auto;
    box-shadow:0 -10px 28px rgba(35,33,28,.055)}
  .bounce{padding:var(--space-3); margin-bottom:var(--space-3)}
  .readout{gap:var(--space-2); margin-top:var(--space-2); padding-top:var(--space-2)}
  .readout .v{font-size:var(--text-base)}
  .drop{padding:var(--space-7) var(--space-4)}
  /* `minmax(0,auto)`, not `auto`: the value column is capped at what is left of
     the row. A bare `auto` sizes to the control's own max-content, so the Key
     select — its text plus the field inset — hung over the card's right edge. */
  .field{display:grid; grid-template-columns:1fr minmax(0,auto); align-items:baseline;
    gap:var(--space-3); padding-block:var(--space-2)}
  .field-top{display:block; margin:0}
  .field-label{font-size:var(--text-base)}
  .prov{display:block; margin-top:1px}
  .value{font-size:var(--text-lg); justify-content:flex-end}
  .field > .note{display:none}
  .field.block{display:block}
  .field.block > .note{display:block; margin-top:var(--space-3)}
  .desks{gap:var(--space-2)}
  .desk{min-width:0; flex:1 1 100%; min-height:var(--space-7)}
  .desk .who{padding:var(--space-2) var(--space-3); font-size:var(--text-base)}
  .collect{display:block; padding:var(--space-3) var(--space-4); margin-bottom:var(--space-4)}
  .collect .btn{display:none}
  .summary{font-size:var(--text-base); margin-bottom:var(--space-3); line-height:var(--leading-snug)}
  .meters{margin-top:var(--space-3)}
  .meters div{padding:var(--space-2) var(--space-3)}
  .family{padding-block:var(--space-3) var(--space-1)}
  .stave{padding-block:var(--space-2)}
  .stave .name, .stave .n{font-size:var(--text-base)}
  .look{margin-top:0}
  .look > h2{font-size:var(--text-md)}
  .look > .sub{margin-bottom:var(--space-3); font-size:var(--text-xs)}
  .item{padding-block:var(--space-3); border-bottom:0}
  .item .why{line-height:var(--leading-snug)}
  .item .ev{margin-top:var(--space-1)}
  .choices{gap:var(--space-2); margin-top:var(--space-3)}
  .choices .btn{flex:1 1 100%}
  .style-row, .settled{padding-block:var(--space-2)}
  .rail h2{margin-bottom:var(--space-2)}
  .rail-foot{font-size:var(--text-xs); margin-top:var(--space-3)}
  .rail-block{margin-top:var(--space-5)}
  .cue-band{display:none}
  .pager{display:flex}
  .queue-item{display:none}
  .queue-item .choices{display:none}
  .queue-item.now{display:block}
  .closing{display:none}
}
@media(min-width:901px){ .rule2.dockrule{display:none} }

@media (prefers-reduced-motion:no-preference){
  @keyframes panel-in{from{opacity:0; transform:translateY(6px)} to{opacity:1; transform:none}}
  @media(max-width:900px){ .flash{animation:panel-in var(--duration-base) var(--ease-entrance) both} }
}
/* ════ the desktop, from 2026-08-10 ═══════════════════════════════════════════

   The desktop's information architecture. It shipped behind the skin cookie for
   one day so the owner could look at it before Cecilia did; on 2026-08-10 he
   approved it and it moved here, which is what makes it the desktop rather than
   a preview of one. The cookie is back to meaning only what it always meant —
   which phone skin you get — and `ios.css` is a phone stylesheet again.

   What it does NOT do is restyle. The desktop's visual debt was never the
   problem — the paper spread's donors stand (worksinprogress for the layout and
   the hairlines, cursor for colour and type, gumroad for the button plate) and
   not a colour or a typeface moves below. The debt was architectural: above
   901px `.panel{display:none}` never applies, so every panel already rendered at
   once and the four `.tabs` bars every screen builds showed zero pixels inside
   the hidden dock. The desktop had the phone's consolidation before the phone
   did. What it did not have was a navigation: four visible controls, two of them
   pointing at the same page, and `/score` and `/project` with no inbound link
   anywhere in the app.

   So this block adds one nav and takes three duplicate lists away.
   `handoff/facts.md` records what it is and why.

   Three elements are now emitted on every page and belong only up here — the
   nav, the appearance control and the decisions pointer. Each is hidden below
   901px, and `ios.css` puts the last two back for the phone in its own shapes: a
   44px glyph and a grouped-card row. The paper phone gets neither, which is
   correct — it never had them, and it is the one surface that still answers
   decisions inline. */
.desknav{display:none}
@media(max-width:900px){
  .theme{display:none}
  .pointer{display:none}
}

@media(min-width:901px){

  /* ── the navigation ──
     Cue, Score, Review, Project: the order the work goes in, which is the claim
     worth carrying over from the phone. A bar under the masthead, not a dock —
     a dock is a thumb idiom and the pointer already starts at the top — and not
     a left sidebar, which the corpus bans and which would put a second rail
     against the one this page already has.

     Sticky rather than fixed. `7c79da8` had to undo fixed chrome on the phone
     because it means reserving the height by hand and the scroll container
     silently discards the reserve. `position:sticky` reserves its own space, and
     up here `body` is not viewport-locked, so none of that applies. Retreating
     to in-flow is deleting two properties.

     Donor: worksinprogress's sticky-context-subnav, which `app.css` already
     names as its layout and hairline donor — reuse, not a new import. */
  .desknav{display:block; position:sticky; top:0; z-index:2;
    background:var(--paper); border-bottom:1px solid var(--rule)}
  .desknav .wrap{display:flex; gap:var(--space-6)}
  .desknav a{
    font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
    letter-spacing:var(--tracking-caps); color:var(--ink-muted);
    padding-block:var(--space-3); border-bottom:2px solid transparent; margin-bottom:-1px;
    transition:color var(--duration-fast) var(--ease-standard),
               border-color var(--duration-fast) var(--ease-standard);
  }
  .desknav a:hover{color:var(--ink)}
  /* The same device as the phone's tab, rotated: the accent rule marks where you
     are, and it sits on the bar's own hairline rather than beside it. */
  .desknav a.on{color:var(--ink); border-bottom-color:var(--accent)}
  .desknav a:focus-visible{outline:2px solid var(--accent); outline-offset:-4px}
  .desknav .flag{color:var(--accent)}

  /* ── appearance ──
     Same three states, same cookie, same URL as the phone's glyph. A word rather
     than an icon, because the desktop masthead is text links in mono and an icon
     there would be the only one on the page. It takes the bordered-chip
     construction the project label beside it already uses, and the accent only
     once a choice has been stored — so the masthead still shows at a glance
     whether anything is overridden. */
  .theme{
    font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
    letter-spacing:var(--tracking-caps); color:var(--ink-muted);
    border:1px solid var(--rule); border-radius:var(--radius-sm);
    padding:var(--space-1) var(--space-2); white-space:nowrap;
    transition:color var(--duration-fast) var(--ease-standard),
               border-color var(--duration-fast) var(--ease-standard);
  }
  .theme::before{display:none}
  .theme:hover{color:var(--ink); border-color:var(--ink)}
  .theme[data-state="light"], .theme[data-state="dark"]{
    color:var(--accent); border-color:var(--accent)}

  /* ── the cue form ──
     The house-style rows stay beside the form: on a phone there is no room next
     to a form, but here they are 312px holding the answer to a question the form
     is asking at that moment — will my keyswitches be dropped, will the parts
     come back transposed — while she decides what to type. Adjacency is the
     whole value, which is why this is one of the three things the phone stacks
     and the desktop keeps side by side.
     The cue list is not that. It is Project's, and this was copy two of three. */
  [data-here="new"] .rail-block.cues{display:none}

  /* ── the delivered cue ──
     "What was left out" stays in the rail for the same reason: the main column
     says 38 tracks came in and 11 staves went out, and the rail is the answer to
     the question that raises. Moving it 1700px down the page to match the phone
     would break the only adjacency on the screen doing argumentative work.

     The decisions do leave, and not for symmetry. Answering one here writes a row
     into the project's house style and hands you back a screen that never says
     so; the consequence line lives on Review. The place that shows the
     consequence should be the only place that takes the action. */
  [data-here="cue"] .look{display:none}
  .pointer{
    display:flex; align-items:center; justify-content:space-between; gap:var(--space-4);
    margin-top:var(--space-8); padding-block:var(--space-4);
    border-top:1px solid var(--rule-strong); border-bottom:1px solid var(--rule-strong);
    font-size:var(--text-md); font-weight:300; letter-spacing:var(--tracking-heading);
  }
  .pointer .go{
    font-family:var(--font-mono); font-size:var(--text-xs); text-transform:uppercase;
    letter-spacing:var(--tracking-caps); color:var(--accent);
    transition:color var(--duration-fast) var(--ease-standard);
  }
  .pointer .go::after{content:" \203A"}
  .pointer:hover .go{color:var(--accent-deep)}

  /* ── review ──
     One column. Its rail held copy two of the settled rows — which is where the
     two-answers bug lived — and copy three of the cue list, and both belong to
     Project. With those gone the rail is empty, so a queue stops pretending to
     be a spread.

     `.cue-band` has been in `app.css` since the first build with nothing
     emitting it. It groups the queue by the cue that raised each question, which
     the payload has always carried and only the phone's pager ever read. */
  [data-here="review"] .rail{display:none}
  [data-here="review"] .cols{grid-template-columns:1fr}
  [data-here="review"] .cols > .main{padding-right:0; max-width:46rem}
  /* The count is the feedback for having answered, so the screen that takes the
     answer is the screen that shows it. `.closing` stays: it argues about the
     future of the queue, which is a different claim from the running total. */
  [data-here="review"] .consequence{display:block; margin-top:var(--space-7)}

  /* ── project ──
     It was a 416px strip in a 1440px window: `.cols.one > .main` is capped at
     26rem for the sign-in form and this screen inherited it, which nobody saw
     because nothing linked here. It is now the widest screen in the app, which
     is right for the one page that is pure reference — settled and account down
     the left, every cue down the right, both at the full measure. */
  [data-here="project"] .cols.one > .main{max-width:none; padding-right:0}
  [data-here="project"] .main > .rail{
    display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:var(--space-8); align-content:start}
  [data-here="project"] .main > .rail > .rail-block.cues{
    grid-column:2; grid-row:1 / span 99; margin-top:0}
}

/* ═══════════════════════════════════════════════════════════════════════════
   SCORE INK — the MuseScore-derived design language.            2026-08-21
   Proposal build. Everything below supersedes the paper spread's control
   treatments; nothing above is deleted, so this whole block is the diff.

   Sources, all measured rather than eyeballed:
   · MuseScore Studio 4 shipped themes — `MuseScore/sandbox/web_sandbox/configs/
     {light,dark}.cfg`: accent, chrome greys, stroke, button colour, font colours,
     `border_width: 0`, `navigation_control_border_width: 2.0`, and the
     normal/hover/hit opacity triples.
   · MuseScore Studio 4 `FlatButton.qml` — `backgroundRadius: 3`, margins 12/16.
   · MuseScore Studio 4 `uiconfiguration.cpp` — the type ratio, one body size in:
     BODY ×1, BODY_LARGE ×1.167, TAB ×1.333, HEADER ×1.833, TITLE ×2.667.
   · Noteflight — elevation `rgba(93,93,93,.11) 0 6px 11px 0`, pill radius 23px.
   · Flat.io — radius 8/10/24px, elevation offsets 4px/8px.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── 1. Surfaces stop being outlined and start being layered ──────────────
   MuseScore ships `border_width: 0`: no control in it is drawn with a stroke.
   Separation is surface value plus elevation. The paper spread did the opposite
   — a 1px hairline on every card, field, button and row — and that, with the
   offset plate below, is most of what reads as dated. */
.bounce, .collect, .drop, .readout, .meters, .tin, .spin, .btn, .chip,
.mast-nav .btn, .item, .cue-band{border-color:transparent}

.bounce, .collect{
  background:var(--surface); border:0; border-radius:var(--radius-lg);
  box-shadow:var(--shadow-1); padding:var(--space-5);
}
.readout{border-top:0; margin-top:var(--space-4); padding-top:var(--space-4);
  border-top:1px solid var(--rule)}

/* The drop target keeps a dashed edge — it is the one control whose whole job is
   to say "put something here", and MuseScore's own import target does the same. */
.drop{background:var(--tonal-soft); border:1.5px dashed var(--rule-strong);
  border-radius:var(--radius-lg); box-shadow:none}
.drop:hover, .drop.over{border-color:var(--accent); background:var(--accent-wash)}

/* ── 2. Buttons: three levels, no plate ───────────────────────────────────
   The old construction was a zero-blur offset plate (`3px 3px 0 0 ink`) from the
   corpus's `offset-stack-button`. It models displacement rather than light, which
   is exactly the retro read. MuseScore's model instead: a filled accent for the
   primary action, a neutral tonal chip for everything else, and opacity for
   state — `button_opacity_normal .7 / hover .5 / hit 1.0`. The hover direction is
   inverted here (state goes UP on hover, not down); on a pointer surface a hover
   that recedes reads as a disabled control. */
.btn{
  min-height:2.75rem; padding:var(--space-3) var(--space-5);
  font-family:var(--font-ui); font-size:var(--text-sm);
  font-weight:var(--weight-semibold); letter-spacing:0;
  background:var(--accent-fill); color:var(--accent-fg);
  border:0; border-radius:var(--radius-md);
  box-shadow:var(--shadow-1);
  transition:background-color var(--duration-fast) var(--ease-standard),
             box-shadow var(--duration-fast) var(--ease-standard),
             transform var(--duration-fast) var(--ease-standard);
}
.btn:hover{background:var(--accent-fill-hover); box-shadow:var(--shadow-2)}
.btn:active{transform:translateY(1px); box-shadow:var(--shadow-1);
  background:var(--accent-fill-hit)}
.btn:focus-visible{outline:var(--focus-w) solid var(--accent); outline-offset:2px}

/* Secondary — MuseScore's default button is a neutral chip, not an outline. */
.btn.ghost{background:var(--tonal); color:var(--ink); box-shadow:none}
.btn.ghost:hover{background:var(--tonal-hover); box-shadow:var(--shadow-1)}
.btn.ghost:active{background:var(--tonal-hit); transform:translateY(1px)}
.btn[disabled]{opacity:.3; cursor:not-allowed}   /* item_opacity_disabled: 0.3 */

/* Mini is a SIZE variant, not a corner variant. `--radius-sm` was chosen for
   its 2rem design height, but the only place it renders with a fill is the
   new-project row, where `.newproj{align-items:stretch}` pulls it to the
   field's 58px — and 6px on a 58px box reads square, which is what the owner
   saw (2026-08-21). Every other filled control on the desktop is
   `--radius-md`; this is the one that was not. Measured, `/project` at 1440:
   field 10px/58, Start 6px/58 -> 10px/58. */
.btn.mini{min-height:2rem; padding:var(--space-2) var(--space-4);
  font-size:var(--text-xs); border-radius:var(--radius-md); box-shadow:none}
.btn.mini:active{transform:translateY(1px); box-shadow:none}
.mast-nav .btn{background:var(--tonal); color:var(--ink); box-shadow:none;
  border-radius:var(--radius-pill); padding:var(--space-2) var(--space-4)}
.mast-nav .btn:hover{background:var(--tonal-hover)}

@media (prefers-reduced-motion:reduce){
  .btn:active, .btn.ghost:active, .btn.mini:active{transform:none}
}

/* ── 3. Fields ────────────────────────────────────────────────────────────
   `text_field_color: #FFFFFF` on `background_primary_color: #F5F5F6` — the field
   is lighter than its page and carries no stroke. The focus ring is MuseScore's
   own `navigation_control_border_width: 2.0`. */
.tin{
  background:var(--surface); border:0; border-radius:var(--radius-md);
  box-shadow:inset 0 0 0 1px var(--rule);
  font-family:var(--font-ui); padding:var(--space-3) var(--space-5);
}
.tin:hover{box-shadow:inset 0 0 0 1px var(--rule-strong)}
.tin:focus-visible, .tin:focus{
  outline:0; box-shadow:inset 0 0 0 var(--focus-w) var(--accent)}

.spin{background:var(--tonal-soft); border:0; border-radius:var(--radius-md);
  overflow:hidden}
.spin-b{background:transparent; border:0; border-radius:0; color:var(--ink-soft);
  font-family:var(--font-ui); font-size:var(--text-md)}
.spin-b:hover{background:var(--tonal-hover); color:var(--ink)}
.spin-b:focus-visible{outline:var(--focus-w) solid var(--accent); outline-offset:-2px}
.spin-n{background:transparent; color:var(--accent); border-inline:0;
  font-weight:var(--weight-semibold)}

/* ── 4. Type: MuseScore's ratio, and sans for everything that is chrome ───
   Its UI is one platform sans at five sizes off a single body size. The mono
   survives only where the text is data — a filename, a stat, a key, an evidence
   line — and the serif survives only on the page title, which is the one piece
   of this product's own identity worth keeping (see redesign.md, override 3). */
body, .btn, .tin, .tab, .desknav a, .field-label, .prov, .family, .kicker,
.rail h2, .chip, .dock-note, .style-row .src, .drop .big, .drop .small,
.summary, .dek, .item .why, .rail-foot, .closing, .consequence{
  font-family:var(--font-ui);
}
.wordmark, .titleband h1, h1{font-family:var(--font-serif)}
.readout .v, .bounce-file .name, .collect .file, .collect .meta, .stave .n,
.item .ev, .style-row .src.tech, .foot{font-family:var(--font-mono)}

.kicker, .family, .prov, .rail h2{
  font-size:var(--text-xs); font-weight:var(--weight-semibold);
  letter-spacing:.06em; text-transform:uppercase; color:var(--ink-muted);
}
.field-label{font-size:var(--text-md); font-weight:var(--weight-medium)}
.summary, .stave .name, .value{font-weight:var(--weight-regular)}
h1, .titleband h1{letter-spacing:var(--tracking-display); font-weight:var(--weight-regular)}

/* ── 5. Rows and lists ────────────────────────────────────────────────────
   Hairlines drop to a value that separates without drawing; the row itself
   becomes the hit target, with a tonal hover, which is how MuseScore's own
   lists behave. */
.stave, .style-row{border-bottom:1px solid var(--rule); border-radius:var(--radius-sm)}
.stave{padding-inline:var(--space-3); margin-inline:calc(-1 * var(--space-3))}
.stave:hover, .style-row:hover{background:var(--tonal-soft)}
.stave.marked{border-left:0; box-shadow:inset 2px 0 0 0 var(--accent)}
.family{border-bottom:1px solid var(--rule-strong)}

.meters{border:0; border-radius:var(--radius-md); background:var(--tonal-soft);
  padding:var(--space-1); gap:var(--space-1)}
.meters div{border-radius:var(--radius-sm); border-inline:0}
.meters div.marked{background:var(--accent-wash); color:var(--accent)}

/* ── 6. Decisions ─────────────────────────────────────────────────────────
   Each question becomes a card, because a decision is an object you act on and
   the old rule-separated stack read as prose. */
.item{background:var(--surface); border-radius:var(--radius-lg);
  box-shadow:var(--shadow-1); padding:var(--space-5); border-bottom:0;
  margin-bottom:var(--space-4)}
.item .ev{background:var(--tonal-soft); border-radius:var(--radius-sm);
  padding:var(--space-2) var(--space-3); display:inline-block}
.cue-band{border-radius:var(--radius-sm)}

/* ── 7. Navigation ────────────────────────────────────────────────────────
   The tab marker moves from a hard 2px top border to a pill, which is the shape
   MuseScore uses for a selected item and the shape Noteflight uses for a control
   (23px, i.e. fully rounded at control height). */
.chip{border:0; border-radius:var(--radius-pill); background:var(--tonal);
  padding:var(--space-2) var(--space-4)}
.chip:hover{background:var(--tonal-hover)}
.err{border-left:0; border-radius:var(--radius-md); background:var(--accent-wash);
  padding:var(--space-4); box-shadow:inset 2px 0 0 0 var(--accent)}

/* ── 8. Desktop: the nav, and the column Review was not using ─────────────── */
@media(min-width:901px){
  .desknav a{border-bottom:0; border-radius:var(--radius-pill);
    padding:var(--space-2) var(--space-4); font-family:var(--font-ui);
    font-size:var(--text-sm); font-weight:var(--weight-medium);
    text-transform:none; letter-spacing:0; color:var(--ink-muted)}
  .desknav a:hover{background:var(--tonal-soft); color:var(--ink)}
  .desknav a.on{background:var(--accent-wash); color:var(--accent);
    border-bottom:0; font-weight:var(--weight-semibold)}
  .desknav a:focus-visible{outline:var(--focus-w) solid var(--accent); outline-offset:2px}

  .cols > .rail{border-left:0; padding-left:var(--space-7)}

  /* Layout upgrade 1. Review's rail was hidden on purpose: it used to carry a
     second copy of the settled rows, and a duplicate is worse than a gap
     (app.css line ~601). The gap is real all the same — 736px of content in a
     1096px container leaves 360px doing nothing on the widest screen the app
     has. So the column comes back carrying something that exists nowhere else:
     an index of which cues still have questions, which is navigation rather
     than a repeat. */
  [data-here="review"] .rail{display:block}
  /* the queue screen goes back to a spread, so the grid has to as well */
  [data-here="review"] .cols{grid-template-columns:1fr var(--rail)}
  [data-here="review"] .cols > .main{padding-right:var(--space-7); max-width:46rem}
  .qindex{margin-top:var(--space-3)}
  .qindex a{display:flex; justify-content:space-between; align-items:baseline;
    gap:var(--space-3); padding:var(--space-3); border-radius:var(--radius-sm);
    border-bottom:1px solid var(--rule); color:var(--ink)}
  .qindex a:hover{background:var(--tonal-soft)}
  .qindex .n{font-family:var(--font-mono); font-size:var(--text-xs);
    color:var(--accent); font-weight:var(--weight-semibold)}
  .qindex .none{color:var(--ink-muted); font-size:var(--text-sm);
    padding:var(--space-3)}

  /* Layout upgrade 2. Four equal numbers said nothing about which one wants the
     reader. The value the engine only guessed is the one that does. */
  .readout div.confirm .v{color:var(--accent)}
  .readout div.confirm .l{color:var(--accent); font-weight:var(--weight-semibold)}

  /* Layout upgrade 4. Which cue was I last in? Answerable without reading four
     timestamps. */
  .rail-block.cues .style-row:first-of-type{box-shadow:inset 2px 0 0 0 var(--accent);
    border-radius:var(--radius-sm); padding-left:var(--space-3)}
}

/* ── 9. Phone: the same language at the phone's scale ─────────────────────── */
@media(max-width:900px){
  .bounce, .collect, .item{border-radius:var(--radius-md); padding:var(--space-4)}
  .btn{border-radius:var(--radius-md); min-height:2.75rem}
  .dock{box-shadow:0 -6px 11px rgba(93,93,93,.11)}
  .tab{border-top:0; border-radius:var(--radius-sm); font-family:var(--font-ui);
    letter-spacing:0; text-transform:none}
  .tab.on{background:var(--accent-wash); color:var(--accent);
    border-top-color:transparent; font-weight:var(--weight-semibold)}
  .tabs{gap:var(--space-1); padding:var(--space-1)}
}

/* ── 10. Specificity corrections ──────────────────────────────────────────
   Three controls sit inside `.mast-nav a` (0,1,1), which outranks the plain
   class selectors above, and the Key field is a `select` reached by a
   type-qualified rule. Named individually rather than fought with `!important`. */
.mast-nav a, .mast-nav .chip, .mast-nav .theme, .mast-nav a.chip .acct,
.mast-nav a.chip .proj{font-family:var(--font-ui); letter-spacing:0;
  text-transform:none}
select.tin, .value select, .tin select{font-family:var(--font-ui)}

/* ── 11. One header ───────────────────────────────────────────────  2026-08-21
   The bar carried four elements in four idioms: a serif wordmark, a bordered
   mono chip, a tonal pill, and a mini button on an offset plate — and the phone
   skin overrode three of them again, so the two renderings shared almost
   nothing. The owner, shown both: "the name is too small on one and too big on
   the other ... I need a complete pass to bring congruency."

   The shape lock is the fix. Nothing in this bar is a container any more except
   the one control that has to be tappable, so what separates the four elements
   is size and colour rather than four different plates. Three sizes: the mark,
   then the two utilities, then a glyph. The loudest thing in the bar is the
   product's name, which is what a masthead is for — it was the sign-out link. */

/* The mark. Serif on every surface: it is the one element that should look the
   same everywhere, and the phone skin had swapped it for the system sans, which
   is most of what made the two headers read as two products. Only the size
   steps, and it steps between the two the owner rejected — 21.3px "too big" on
   the phone, 17px "too small" — landing on 18.7px there and keeping 21.3 for the
   desktop bar, which is 27px taller and carries it. */
.wordmark{font-weight:var(--weight-medium); color:var(--ink)}

/* Who you are. A label, not a plate: the border and the uppercase mono were
   doing the work that its position in the bar already does, and the pill
   competed with the appearance control beside it for the same attention. */
.mast-nav .chip{
  border:0; border-radius:0; padding:0; background:none;
  font-size:var(--text-sm); color:var(--ink-muted); font-weight:var(--weight-regular);
}
.mast-nav .chip:hover{color:var(--ink); border-color:transparent}
.chip .acct{font-weight:var(--weight-medium); color:var(--ink)}

/* Sign out. Text, at the account's size and colour — the owner picked the phone
   skin's plain-text treatment over the plated one, and this is that treatment
   with the accent taken off. Signing out is not the accent-coloured thing to do
   on a page whose accent means "this is the action"; it goes quiet and comes up
   on hover. */
.mast-nav .btn.mini{
  min-height:0; padding:0; background:none; border:0; box-shadow:none;
  font-family:var(--font-ui); font-size:var(--text-sm); font-weight:var(--weight-regular);
  text-transform:none; letter-spacing:var(--tracking-ui); color:var(--ink-muted);
  transition:color var(--duration-fast) var(--ease-standard);
}
.mast-nav .btn.mini:hover{color:var(--ink); background:none; box-shadow:none}
.mast-nav .btn.mini:active{transform:none; box-shadow:none; opacity:.6}

/* Appearance: one control on both surfaces, and a glyph rather than a word. It
   used to be a 79x38 labelled pill on the desktop and a 44px filled circle on
   the phone — "the light/dark button there is way too big", and it was: the
   heaviest object in a bar whose subject is the score. The fill goes, the glyph
   stays 18px, and the 2rem box keeps it a real target; the phone widens that box
   to 44px without making it look any bigger, which is `ios.css`'s only
   remaining job in this bar.

   The three states are the phone's own: half circle for "following the device",
   sun, moon — and the accent only appears once a choice is stored, so the bar
   says at a glance whether anything is overridden. Masks live here rather than
   in the skin now that both surfaces draw them. */
.mast-nav .theme{
  display:inline-flex; align-items:center; justify-content:center;
  width:var(--space-6); height:var(--space-6); padding:0; border:0;
  border-radius:var(--radius-pill);
  background:none; color:var(--ink-soft);
  transition:background-color var(--duration-fast) var(--ease-standard),
             color var(--duration-fast) var(--ease-standard);
}
.mast-nav .theme:hover{background:var(--tonal-soft); color:var(--ink)}
.mast-nav .theme[data-state="light"], .mast-nav .theme[data-state="dark"]{color:var(--accent)}
.mast-nav .theme .lab{display:none}
.mast-nav .theme::before{
  content:""; width:1.125rem; height:1.125rem; background:currentColor; display:block;
  -webkit-mask:var(--g) center/contain no-repeat; mask:var(--g) center/contain no-repeat;
}
.mast-nav .theme[data-state="system"]::before{--g:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm8,16.37a86.4,86.4,0,0,1,16,3V212.67a86.4,86.4,0,0,1-16,3Zm32,9.26a87.81,87.81,0,0,1,16,10.54V195.83a87.81,87.81,0,0,1-16,10.54ZM40,128a88.11,88.11,0,0,1,80-87.63V215.63A88.11,88.11,0,0,1,40,128Zm160,50.54V77.46a87.82,87.82,0,0,1,0,101.08Z'/%3E%3C/svg%3E")}
.mast-nav .theme[data-state="light"]::before{--g:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M120,40V16a8,8,0,0,1,16,0V40a8,8,0,0,1-16,0Zm72,88a64,64,0,1,1-64-64A64.07,64.07,0,0,1,192,128Zm-16,0a48,48,0,1,0-48,48A48.05,48.05,0,0,0,176,128ZM58.34,69.66A8,8,0,0,0,69.66,58.34l-16-16A8,8,0,0,0,42.34,53.66Zm0,116.68-16,16a8,8,0,0,0,11.32,11.32l16-16a8,8,0,0,0-11.32-11.32ZM192,72a8,8,0,0,0,5.66-2.34l16-16a8,8,0,0,0-11.32-11.32l-16,16A8,8,0,0,0,192,72Zm5.66,114.34a8,8,0,0,0-11.32,11.32l16,16a8,8,0,0,0,11.32-11.32ZM48,128a8,8,0,0,0-8-8H16a8,8,0,0,0,0,16H40A8,8,0,0,0,48,128Zm80,80a8,8,0,0,0-8,8v24a8,8,0,0,0,16,0V216A8,8,0,0,0,128,208Zm112-88H216a8,8,0,0,0,0,16h24a8,8,0,0,0,0-16Z'/%3E%3C/svg%3E")}
.mast-nav .theme[data-state="dark"]::before{--g:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M233.54,142.23a8,8,0,0,0-8-2,88.08,88.08,0,0,1-109.8-109.8,8,8,0,0,0-10-10,104.84,104.84,0,0,0-52.91,37A104,104,0,0,0,136,224a103.09,103.09,0,0,0,62.52-20.88,104.84,104.84,0,0,0,37-52.91A8,8,0,0,0,233.54,142.23ZM188.9,190.34A88,88,0,0,1,65.66,67.11a89,89,0,0,1,31.4-26A106,106,0,0,0,96,56,104.11,104.11,0,0,0,200,160a106,106,0,0,0,14.92-1.06A89,89,0,0,1,188.9,190.34Z'/%3E%3C/svg%3E")}
.mast-nav a.here{color:var(--accent); font-weight:var(--weight-semibold)}

/* Layout upgrade 5: on the desktop the consequence line moved into the rail, so
   the main column stops ending in three muted paragraphs at one weight. The
   phone keeps it inline — it has no rail to move it to. */
@media(min-width:901px){ .consequence.wide-hide{display:none} }

/* Two labels the group in §4 missed, both type-qualified elsewhere. */
.cue-band{font-family:var(--font-ui); font-weight:var(--weight-semibold);
  letter-spacing:.06em; border-bottom:0}
.facts, .dek.facts, .look > .sub{font-family:var(--font-ui)}
.look > h2{font-size:var(--text-lg); font-weight:var(--weight-medium)}
