
:root{
  /* Chart series. Remapped from the old light-page palette (red/blue/green/amber/purple) to
     famoe.ly tokens, and validated for color-vision-deficiency separation against the cosmic
     surface: the worst adjacent pair (act<->exp) is dE 51.4 deutan against a target of 12.
     That pair matters most — the violet-over-teal gap IS this page's thesis, so if the two
     collapsed under CVD the chart would say nothing. Expected also stays DASHED against
     actual's solid, so identity never rests on hue alone. */
  --s-rec:#ff8a3d;    /* songs we called */
  --s-exp:#a78bfa;    /* expected hit rate — dashed */
  --s-act:#2de2c6;    /* actual hit rate */
  --s-churn:#ffd166;  /* board turnover + per-night step (same metric, so one color) */
  --s-drift:#ff5ed2;  /* drift from the genesis pick */
}

/* The hero, matched to the Tape Measure's: same clamp, same weight, same lift off the
 * background. This page used to open with a left-aligned 29px h1 and a floated "moe." wordmark,
 * built before the cosmic shell existed and retrofitted afterwards -- it read as a different
 * site wearing the same background. */
h1{font-family:var(--display);font-weight:700;font-size:clamp(34px,6vw,52px);letter-spacing:-.02em;
  margin:0 0 14px;color:#f6f2ff;
  text-shadow:0 1px 2px rgba(8,5,15,.6),0 3px 30px rgba(8,5,15,.5),0 6px 48px rgba(120,80,200,.3)}
h1 .dot{color:var(--flare);text-shadow:0 0 22px rgba(255,138,61,.9)}
/* The blurb takes the shared 560px measure with no override. It briefly had one, at 760px, to
   accommodate a 110-word blurb; the copy got shorter instead, which is the right way round. */
/* Body-level muted note. The standing description moved into the hero and the fold; what is left
 * using this is the "no scored shows yet" chart fallback. */
.sub{color:var(--muted);font-size:13px;max-width:900px;line-height:1.6}
.sub b{color:var(--ink);font-weight:600}
.chart-wrap{position:relative;width:100%;max-width:1100px;margin:18px 0 4px}
.chart{width:100%;height:auto;display:block}

/* SVG furniture — the old grays were tuned for a white page and vanish on navy */
.grid{stroke:rgba(255,255,255,.07);stroke-width:1}
.grid.ideal{stroke:rgba(255,255,255,.16);stroke-width:1;stroke-dasharray:4 4}
.axis{stroke:rgba(255,255,255,.20);stroke-width:1}.tick{stroke:rgba(255,255,255,.15);stroke-width:1}
.yl{font-size:10px;fill:var(--faint)}.xl{font-size:9px;fill:var(--faint)}
.ideal-lab{font-size:9px;fill:var(--faint)}
.ln-rec{fill:none;stroke:var(--s-rec);stroke-width:2}
.ln-exp{fill:none;stroke:var(--s-exp);stroke-width:1.5;stroke-dasharray:5 4}
.ln-act{fill:none;stroke:var(--s-act);stroke-width:2}
/* the hollow dot is filled with the PAGE, not with white — on a dark page that means --night */
.dot-rec{fill:var(--s-rec)}.dot-exp{fill:var(--night);stroke:var(--s-exp);stroke-width:1.5}
.dot-act{fill:var(--s-act)}
.future{fill:#fff;opacity:.04}
.leak{stroke:rgba(255,255,255,.35);stroke-width:1;stroke-dasharray:2 3}
.leaklab{font-size:9px;fill:var(--faint)}
.hz{fill:transparent;cursor:crosshair}
.hair{stroke:rgba(255,255,255,.45);stroke-width:1;stroke-dasharray:2 2;opacity:0;pointer-events:none;transition:opacity .1s}
.hair.on{opacity:.7}

/* tooltips were ALREADY dark on the light page, so they get re-contrasted (glass panel +
   border), not inverted — a near-black tooltip on a near-black page reads as a smudge. */
.tip{position:absolute;pointer-events:none;opacity:0;transition:opacity .12s;z-index:6;
min-width:158px;background:rgba(18,12,32,.97);border:1px solid var(--glass-brd);color:var(--ink);
border-radius:10px;padding:8px 11px;backdrop-filter:blur(8px);
box-shadow:0 16px 40px -14px rgba(0,0,0,.9)}
.tip.on{opacity:1}
.tt-date{font-family:var(--display);font-weight:700;font-size:11px;letter-spacing:.4px;
padding-bottom:4px;margin-bottom:3px;border-bottom:1px solid var(--glass-brd);color:var(--ink)}
.tt-row{display:flex;justify-content:space-between;align-items:baseline;gap:16px;margin-top:4px}
.tt-row .k{font-size:10px;color:var(--muted)}
.tt-row .v{font-size:14px;font-weight:700;color:var(--ink);font-family:var(--display)}
.tt-sub{font-size:9.5px;color:var(--faint);margin-top:1px}
.tt-head{font-size:12.5px;font-weight:700;color:var(--ink);margin-top:7px;padding-top:6px;
border-top:1px solid var(--glass-brd);font-family:var(--display)}
.tt-sq{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:6px;vertical-align:middle}
.tt-sq.sq-rec{background:var(--s-rec)}.tt-sq.sq-cal{background:var(--s-exp)}
.tt-sq.sq-exp{background:var(--s-exp)}.tt-sq.sq-act{background:var(--s-act)}

.runcard{max-width:1000px;margin:6px 0;font-size:12.5px;color:var(--muted);
background:rgba(255,255,255,.04);border:1px solid var(--glass-brd);border-left:3px solid var(--s-rec);
padding:9px 13px;border-radius:0 8px 8px 0;line-height:1.55}
.runcard-rec{border-left-color:var(--s-rec)}.runcard-bet{border-left-color:var(--s-exp)}
.runcard b{color:var(--ink)}
.legend{margin:10px 0 2px;max-width:1000px}
.lg-keys{display:flex;flex-wrap:wrap;gap:16px;font-size:11px;color:var(--muted);margin-bottom:7px}
.lg-k{display:inline-flex;align-items:center;gap:6px}
.sw{display:inline-block;width:16px;height:3px;border-radius:2px}
.sw-rec{background:var(--s-rec)}
.sw-exp{height:0;border-top:2px dashed var(--s-exp);background:none}
.sw-act{background:var(--s-act)}
.sw-fut{width:14px;height:12px;border-radius:2px;background:#fff;opacity:.07}
.lg-def{display:grid;grid-template-columns:auto 1fr;gap:3px 12px;margin:0;max-width:820px;
font-size:10.5px;color:var(--muted);line-height:1.45}
.lg-def dt{font-weight:700;color:var(--ink);white-space:nowrap}.lg-def dd{margin:0}
.dt-note{font-weight:400;color:var(--faint);font-size:9px}
.lg-def .hr-e{color:var(--s-exp)}.lg-def .hr-a{color:var(--s-act)}.lg-def .hr-c{color:var(--s-rec)}

.scroller{overflow-x:auto;border-top:1px solid var(--glass-brd);padding-top:14px;margin-top:12px}
.cols{display:flex;gap:14px;align-items:flex-start}
.col{flex:0 0 250px;background:rgba(255,255,255,.03);border:1px solid var(--glass-brd);
border-radius:12px;padding:10px 12px}
/* the frontier — first night we don't have a setlist for. The scroller opens here, so say why:
   without a cue, landing mid-scroll just reads as a bug. */
.col-frontier{border-left:2px solid var(--amber);background:rgba(255,209,102,.05)}
.chd{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline;font-size:11px;margin-bottom:5px}
.dt{font-family:var(--display);font-weight:700;font-size:13px;color:var(--ink)}
/* archive.org tape search for this night. margin-left:auto parks it at the right edge of the
   header row; align-self overrides .chd's baseline alignment, which would hang an icon-only
   box off the text baseline. */
.arc{margin-left:auto;align-self:center;display:inline-flex;align-items:center;gap:3px;
justify-content:center;min-height:22px;padding:2px 6px;border-radius:7px;
border:1px solid transparent;text-decoration:none;flex:none;
transition:color .18s,background .18s,border-color .18s,opacity .18s}
.arc:focus-visible{outline:none}
.arc-i{width:15px;height:15px;display:block;fill:currentColor;flex:none}
.arc-n{font-family:var(--display);font-size:10px;font-weight:700;line-height:1}
/* tapes are up — say so, and say how many. This is the state worth clicking. */
.arc.has{color:var(--amber);background:rgba(255,209,102,.08);border-color:rgba(255,209,102,.22)}
.arc.has:hover,.arc.has:focus-visible{color:#ffe19a;background:rgba(255,209,102,.17);
border-color:rgba(255,209,102,.5)}
/* played, but nobody has posted a tape yet. Recessive, not absent: it stays a live search,
   because tapes routinely land weeks or months late — and when one does, this flips to .has. */
.arc.none{color:var(--faint);opacity:.55}
.arc.none:hover,.arc.none:focus-visible{color:var(--amber);opacity:1;
background:rgba(255,209,102,.10);border-color:rgba(255,209,102,.35)}
/* Staleness badge. Hidden until JS decides the build is old -- a static page cannot know its own
   age at build time, only the reader's browser can. Pushover alerts can be missed; a page that
   says out loud that it is three weeks stale cannot be. */
.stale{display:none;margin:14px 0 0;padding:10px 14px;border-radius:10px;
background:rgba(255,90,60,.10);border:1px solid rgba(255,90,60,.38);
color:var(--ink);font-size:12.5px;line-height:1.5;max-width:1000px}
.stale.on{display:block}
.stale b{color:var(--ember)}
.vn{flex:0 0 100%;color:var(--faint);font-size:10px;line-height:1.3}
.s-played{color:var(--s-act);font-weight:700}.s-up{color:var(--faint)}
.s-await{color:var(--flare);font-weight:700}

.spark-wrap{position:relative;margin:2px 0 3px}
.spark{width:100%;height:auto;display:block;overflow:visible}
.sp-base{stroke:rgba(255,255,255,.10);stroke-width:1}
.sp-drift-fill{fill:var(--s-drift);opacity:.16}
.sp-drift{fill:none;stroke:var(--s-drift);stroke-width:1.75;stroke-linejoin:round;stroke-linecap:round}
.sp-drift-dot{fill:var(--s-drift)}
.sp-endlab{font-size:9px;font-weight:700;fill:var(--s-drift)}
.sp-step{fill:none;stroke:var(--s-churn);stroke-width:1.25;stroke-linejoin:round;stroke-linecap:round}
.shair{stroke:rgba(255,255,255,.45);stroke-width:1;stroke-dasharray:2 2;opacity:0}.shair.on{opacity:.6}
.sz{fill:transparent;cursor:crosshair}
.spark-none{font-size:9.5px;color:var(--faint);font-style:italic;padding:8px 0 10px}
.spark-cap{font-size:9.5px;color:var(--faint);margin:0 0 6px}.spark-cap b{color:var(--s-drift)}
.spark-key{display:flex;flex-wrap:wrap;align-items:center;gap:8px 18px;margin:12px 0 2px;
font-size:11px;color:var(--muted);max-width:1000px}
.spark-key .lg-k i{color:var(--faint);font-style:normal;font-size:10px}
.spark-key-note{color:var(--faint);font-size:10px}
.sw-drift{width:16px;height:10px;border-radius:2px;background:var(--s-drift);opacity:.6}
.sw-step{width:16px;height:0;border-top:2px solid var(--s-churn);background:none;border-radius:0}
.sptip{position:fixed;pointer-events:none;opacity:0;transition:opacity .1s;z-index:20;
min-width:150px;background:rgba(18,12,32,.97);border:1px solid var(--glass-brd);color:var(--ink);
border-radius:10px;padding:7px 10px;backdrop-filter:blur(8px);
box-shadow:0 16px 40px -14px rgba(0,0,0,.9)}
.sptip.on{opacity:1}
.tt-sq.sq-drift{background:var(--s-drift)}.tt-sq.sq-step{background:var(--s-churn)}

.board-head{font-family:var(--display);font-size:13.5px;font-weight:600;color:var(--ink);
margin:22px 0 2px;max-width:1000px}
.board-sub{font-family:var(--body);font-weight:400;color:var(--muted);font-size:11px}
.board-wrap{margin:2px 0 4px}
.ln-board{fill:none;stroke:var(--s-churn);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.dot-board{fill:var(--s-churn)}.board-band{fill:var(--s-churn);opacity:.12}
.board-avg{stroke:var(--s-churn);stroke-width:1;stroke-dasharray:4 4;opacity:.5}
.board-avglab{font-size:9px;fill:var(--s-churn);opacity:.9}
.bz{fill:transparent;cursor:crosshair}

.hitrate{margin:3px 0 8px}
.hr-row{display:flex;align-items:center;gap:7px;margin-bottom:3px}
.hr-track{position:relative;flex:1;height:8px;background:rgba(255,255,255,.08);border-radius:3px;overflow:hidden}
.hr-fill{position:absolute;top:0;left:0;height:100%;border-radius:3px}
.hr-red{background:var(--s-rec)}.hr-exp{background:var(--s-exp)}.hr-act{background:var(--s-act)}
.hr-lab{font-size:9.5px;white-space:nowrap;width:72px;text-align:right;color:var(--muted)}
.hr-c{color:var(--s-rec);font-weight:700}.hr-e{color:var(--s-exp);font-weight:700}
.hr-a{color:var(--s-act);font-weight:700}
.hr-off .hr-track{background:rgba(255,255,255,.04)}
.hr-off .hr-lab{color:var(--faint);font-weight:400}
.hr-cap{font-size:8.5px;color:var(--faint);margin-top:4px;line-height:1.35}

table.pt{width:100%;border-collapse:collapse}
.pt th{font-size:9px;text-transform:uppercase;letter-spacing:.08em;color:var(--faint);text-align:left;padding:3px 2px}
.pt td{font-size:11px;padding:3px 2px;border-bottom:1px solid rgba(255,255,255,.06);color:var(--ink)}
.rk{color:var(--faint);width:16px;text-align:right}
.sg{font-weight:700;text-transform:uppercase;font-size:10px}
.cb{white-space:nowrap}
.bar{display:inline-block;width:44px;height:7px;background:rgba(255,255,255,.08);
border-radius:3px;overflow:hidden;vertical-align:middle}
.fill{display:block;height:100%;background:var(--s-rec)}
.cf{font-size:9px;color:var(--muted);margin-left:3px}
.dl{text-align:right;font-size:10px}
.up{color:var(--ok)}.dn{color:var(--bad)}.new{color:var(--s-exp);font-weight:700}
.hc{text-align:center}.hit{color:var(--s-act);font-weight:700}.no{color:rgba(255,255,255,.18)}
.missed{font-size:10px;color:var(--flare);margin-top:5px;border-top:1px dashed var(--glass-brd);padding-top:4px}

/* .foot-note is styled by the SHARED sheet. It used to be redefined here -- at 10px against the
   family's 11px, with different margins -- which meant the Scorecard's fine print and the
   Songbook's rendered differently despite being the same thing in the same slot. That is the exact
   drift this refactor exists to delete, so the local copy is gone. If the fine print needs to
   change, change it in assets/style.css and it changes everywhere. */

/* h1 sizing is a clamp now, so it handles narrow on its own -- no override needed. */
