/* Financial Rebellion league. Same palette, type and screen-vs-paper contrast
   as the one-off Stock Picker's Battleship, because it is the same game. */
:root{
  --canvas:#EFEAD4; --panel:#FAF7E9;
  --ink:#2D2D2D; --ink-muted:#6F675A; --ink-faint:#948B79;
  --rule:#D6CDAF; --rule-soft:#E3DCC2;
  --orange:#E4481A; --mustard:#E7B34D; --teal:#83B6B6;
  --btn-ink:#FAF7E9; --pos:#1F7A5A; --neg:#C23B12; --accent-text:#BC3810;
  --screen:#171614; --screen-2:#211F1C; --screen-ink:#EFEAD4; --screen-mut:#7E7768;
  --screen-rule:rgba(239,234,212,.11); --screen-edge:#3A3936;
  --display:"Saira",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --body:"DM Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --mono:"DM Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --canvas:#1E1D1B; --panel:#2A2926;
    --ink:#EFEAD4; --ink-muted:#A79F8E; --ink-faint:#7E7768;
    --rule:#403E39; --rule-soft:#35332F;
    --btn-ink:#1E1D1B; --pos:#83B6B6; --neg:#F2683F; --accent-text:#F2683F;
    --screen:#131210; --screen-2:#1C1A18; --screen-edge:#4A4844;
  }
}
:root[data-theme="dark"]{
  --canvas:#1E1D1B; --panel:#2A2926;
  --ink:#EFEAD4; --ink-muted:#A79F8E; --ink-faint:#7E7768;
  --rule:#403E39; --rule-soft:#35332F;
  --btn-ink:#1E1D1B; --pos:#83B6B6; --neg:#F2683F; --accent-text:#F2683F;
  --screen:#131210; --screen-2:#1C1A18; --screen-edge:#4A4844;
}

*{box-sizing:border-box}
/* An author rule that sets display beats the hidden attribute outright, so
   without this every el.hidden = true on a flex/grid element does nothing. */
[hidden]{display:none!important}
body{margin:0;background:var(--canvas);color:var(--ink);font-family:var(--body);font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
h1,h2,h3{font-family:var(--display);margin:0;text-wrap:balance;line-height:1.02;letter-spacing:-.015em}
p{margin:0}
button{font:inherit;color:inherit}
a{color:var(--accent-text)}

.wrap{max-width:1000px;margin:0 auto;padding:clamp(20px,4vw,40px) clamp(16px,4vw,32px) 64px}

header.top{display:flex;align-items:center;justify-content:space-between;gap:16px;padding-bottom:16px;border-bottom:2px solid var(--ink);margin-bottom:clamp(22px,4vw,36px)}
.fr-logo{display:block;width:clamp(140px,20vw,186px);height:auto;color:var(--ink)}
.kicker{font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-faint);text-align:right}
.kicker a{color:inherit;text-decoration:none;border-bottom:1px solid var(--rule)}
.kicker a:hover{color:var(--accent-text)}

.hero{margin-bottom:clamp(20px,3.5vw,30px)}
.hero h1{font-size:clamp(32px,7vw,62px);font-weight:800;text-transform:uppercase;letter-spacing:-.03em;margin-bottom:6px}
.hero .league{display:block;font-size:.42em;letter-spacing:.16em;color:var(--accent-text);margin-bottom:4px}
.thesis{font-size:clamp(17px,2.3vw,21px);max-width:56ch;color:var(--ink);margin-top:12px}
.rules{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;background:var(--rule);border:1px solid var(--rule);margin-top:22px}
@media (max-width:640px){.rules{grid-template-columns:1fr}}
.rule-box{background:var(--panel);padding:14px 16px}
.rule-box b{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text);margin-bottom:5px}
.rule-box span{font-size:14.5px;color:var(--ink-muted)}

.weekbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px 18px;border:2px solid var(--ink);background:var(--panel);padding:11px 15px;margin-bottom:20px}
.weekbar .wk{font-family:var(--display);font-weight:800;text-transform:uppercase;font-size:17px;letter-spacing:.02em}
.weekbar .meta{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint)}
.weekbar .meta b{color:var(--ink);font-variant-numeric:tabular-nums}
.weekbar .spacer{flex:1}

.bar{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap;margin:28px 0 14px}
.bar h2{font-size:clamp(19px,2.6vw,25px);font-weight:700;text-transform:uppercase}
.bar .sub{color:var(--ink-muted);font-size:14.5px;margin-top:4px}
.counter{text-align:right;line-height:1;flex-shrink:0}
.counter b{display:block;font-family:var(--display);font-size:clamp(38px,6vw,52px);font-weight:800;font-variant-numeric:tabular-nums}
.counter span{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-faint)}

.body{display:grid;grid-template-columns:minmax(0,1fr) minmax(230px,300px);gap:18px;align-items:start}
@media (max-width:760px){.body{grid-template-columns:1fr}}
.screen{background:var(--screen);border:2px solid var(--screen-edge);padding:clamp(8px,1.6vw,14px);
  background-image:linear-gradient(var(--screen-rule) 1px,transparent 1px),linear-gradient(90deg,var(--screen-rule) 1px,transparent 1px);
  background-size:34px 34px}
.grid{display:grid;grid-template-columns:repeat(10,1fr);gap:clamp(2px,.5vw,4px)}
.cell{aspect-ratio:1;border:1px solid var(--screen-rule);background:var(--screen-2);display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:clamp(5px,1.2vw,10px);letter-spacing:.02em;color:transparent;cursor:crosshair;padding:0;
  transition:background .18s,border-color .18s,color .18s,transform .18s}
.cell:hover:not(.done){background:#332F28;border-color:var(--mustard)}
.cell:focus-visible{outline:2px solid var(--orange);outline-offset:1px}
.cell.done{cursor:default}
.cell.hit{background:var(--mustard);border-color:var(--mustard);color:#2D2D2D}
.cell.hit.kept{background:var(--orange);border-color:var(--orange);color:#FAF7E9}
.cell.hit.dropped{background:#232020;border-color:#3A3430;color:var(--screen-mut)}
.cell.pop{transform:scale(1.12);z-index:2}
.screen.spent .cell:not(.hit){opacity:.55}

.readout{margin-top:10px;border:2px solid var(--rule);background:var(--panel);padding:10px 13px;
  font-family:var(--mono);font-size:13px;color:var(--ink-muted);min-height:41px;display:flex;align-items:center;gap:9px}
.readout b{font-family:var(--display);font-weight:800;font-size:15px;letter-spacing:.04em;color:var(--ink)}
.readout .n{font-variant-numeric:tabular-nums;margin-left:auto;font-size:15px;font-weight:500}

.side{border:2px solid var(--ink);background:var(--panel);padding:14px 15px 16px}
.side h3{font-size:12px;letter-spacing:.13em;text-transform:uppercase;font-weight:700;color:var(--ink-muted);margin-bottom:10px}
.side ol{list-style:none;margin:0;padding:0}
.side ol li{display:flex;justify-content:space-between;gap:10px;padding:6px 0;border-bottom:1px solid var(--rule-soft);font-size:13px}
.side ol li:last-child{border-bottom:0}
.side ol li span{color:var(--ink-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side ol li b{font-family:var(--mono);font-size:12.5px;flex-shrink:0}
.empty{color:var(--ink-faint);font-size:13.5px;font-style:italic}
.pos{color:var(--pos)}.neg{color:var(--neg)}

/* ---------- the cut ---------- */
.stage{margin-top:22px;border:2px solid var(--ink);background:var(--panel);padding:clamp(18px,3vw,28px)}
.kick{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--accent-text);margin-bottom:10px}
.stage h3{font-size:clamp(22px,3.4vw,32px);font-weight:800;text-transform:uppercase;margin-bottom:10px}
.stage p.lede{font-size:clamp(15.5px,1.9vw,18px);color:var(--ink-muted);max-width:60ch}

.picks{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:18px 0 14px}
/* min-width:0 is load-bearing. A grid item defaults to min-width:auto, so the
   card refuses to shrink below its own content and pushes the whole page
   sideways -- 17px of horizontal overflow at 320px, and nowhere else. */
.pick{background:var(--panel);padding:11px 13px;display:flex;align-items:center;gap:11px;text-align:left;border:0;cursor:pointer;width:100%;min-width:0;
  transition:background .14s}
.pick:hover{background:var(--rule-soft)}
.pick:focus-visible{outline:3px solid var(--accent-text);outline-offset:-3px}
.pick .tick{font-family:var(--display);font-weight:800;font-size:15px;letter-spacing:.02em;min-width:52px}
.pick .who{min-width:0;flex:1}
.pick .who b{display:block;font-family:var(--body);font-weight:500;font-size:13.5px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pick .who span{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pick .mark{font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;padding:3px 0;flex-shrink:0;color:var(--ink-faint)}
/* The chip used to be a bare word, and on the cut screen that word was a verb
   pointing the wrong way. It is a checkbox now: the box carries the state, the
   word stays put. An empty box on an unchosen row cannot be read as a command. */
.pick .mark{display:inline-flex;align-items:center;gap:6px;font-style:normal}
.pick .mark .word{font-style:normal}
.pick .mark .box{width:10px;height:10px;flex-shrink:0;border:1.5px solid currentColor;opacity:.5;position:relative}
.pick[aria-pressed="true"] .mark .box{opacity:1;background:#FAF7E9;border-color:#FAF7E9}
.pick[aria-pressed="true"] .mark .box::after{content:"";position:absolute;left:2.5px;top:-0.5px;width:3px;height:6.5px;border:solid var(--orange);border-width:0 1.6px 1.6px 0;transform:rotate(45deg)}
.pick[aria-pressed="true"]{background:var(--orange);color:#FAF7E9}
/* One cell of the cut grid: the keep/cut toggle, and a way out to go read
   about the company. The link is a sibling of the button, never inside it. */
.pickrow{display:flex;align-items:stretch;background:var(--panel);min-width:0}
.pickrow .pick{flex:1;min-width:0}
.research{flex:0 0 auto;display:flex;align-items:center;gap:3px;padding:0 10px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-faint);text-decoration:none;border-left:1px solid var(--rule);white-space:nowrap}
.research:hover{color:var(--accent-text);background:var(--rule-soft)}
.research:focus-visible{outline:3px solid var(--accent-text);outline-offset:-3px}
/* The toggle owns the cell colour, so a kept row must not leave the link
   sitting on the old background looking like a seam. */
.pickrow:has(.pick[aria-pressed="true"]){background:var(--orange)}
.pickrow:has(.pick[aria-pressed="true"]) .research{color:#FAF7E9;border-left-color:rgba(250,247,233,.35)}
.pickrow:has(.pick[aria-pressed="true"]) .research:hover{background:rgba(0,0,0,.14);color:#FAF7E9}
@media (max-width:380px){.research{padding:0 7px;font-size:9px}}

.pick[aria-pressed="true"]:hover{background:#C93E15}
.pick[aria-pressed="true"] .who span,.pick[aria-pressed="true"] .mark{color:rgba(250,247,233,.92)}

.tally{display:flex;align-items:baseline;gap:10px;font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:16px}
.tally b{font-family:var(--display);font-size:26px;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums}

.btn{border:2px solid var(--ink);background:var(--ink);color:var(--btn-ink);padding:12px 22px;cursor:pointer;
  font-family:var(--display);font-weight:700;font-size:13px;letter-spacing:.09em;text-transform:uppercase;transition:transform .1s,background .16s;text-decoration:none;display:inline-block}
.btn:hover{background:#BC3810;border-color:#BC3810;color:#FAF7E9}
.btn:active{transform:translateY(1px)}
.btn:focus-visible{outline:3px solid var(--accent-text);outline-offset:2px}
.btn[disabled]{opacity:.4;cursor:not-allowed}
.btn[disabled]:hover{background:var(--ink);border-color:var(--ink);color:var(--btn-ink)}
.btn.ghost{background:transparent;color:var(--ink)}
.btn.ghost:hover{background:var(--ink);color:var(--btn-ink)}

/* ---------- lock ---------- */
.lockform{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px;align-items:flex-start}
.lockform input{font:inherit;font-size:15px;padding:11px 13px;border:2px solid var(--ink);background:var(--canvas);color:var(--ink);min-width:0}
.lockform input:focus-visible{outline:3px solid var(--accent-text);outline-offset:1px}
.lockform .email{flex:2 1 250px}
.lockform .name{flex:1 1 140px}
.terms{border:2px solid var(--rule);background:var(--canvas);padding:11px 14px;margin-top:14px;font-size:14px;color:var(--ink-muted);max-width:62ch}
.terms b{color:var(--ink)}
.err{color:var(--neg);font-size:14px;margin-top:10px;font-weight:500}

.share{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap}
.share input{font:inherit;font-family:var(--mono);font-size:13px;padding:10px 12px;border:2px solid var(--rule);background:var(--canvas);color:var(--ink-muted);flex:1 1 260px;min-width:0}

/* ---------- leaderboard ---------- */
.tables{display:grid;grid-template-columns:1fr 1fr;gap:18px;align-items:start;margin-top:22px}
@media (max-width:760px){.tables{grid-template-columns:1fr}}
.tbl{border:2px solid var(--ink);background:var(--panel)}
.tbl h3{font-size:12px;letter-spacing:.13em;text-transform:uppercase;font-weight:700;padding:12px 15px;border-bottom:2px solid var(--ink)}
.tbl h3 span{display:block;font-family:var(--body);font-weight:400;letter-spacing:0;text-transform:none;font-size:13px;color:var(--ink-muted);margin-top:3px}
.tbl table{border-collapse:collapse;width:100%;font-size:14.5px}
.tbl td{padding:8px 15px;border-bottom:1px solid var(--rule-soft)}
.tbl tr:last-child td{border-bottom:0}
.tbl .r{font-family:var(--mono);font-size:12.5px;color:var(--ink-faint);width:1%;white-space:nowrap}
.tbl .v{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}
.tbl .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:1px;width:100%}
.tbl .played{color:var(--ink-faint);font-size:12px}
.tbl tr.index td{background:var(--mustard);color:#2D2D2D;font-weight:700}
.tbl tr.index .r,.tbl tr.index .played{color:#5A4A22}
.tbl tr.me td{box-shadow:inset 3px 0 0 var(--orange)}
.tbl tr.gap td{color:var(--ink-faint);font-family:var(--mono);padding:4px 15px}

.scoreline{display:grid;grid-template-columns:repeat(auto-fit,minmax(145px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:16px 0}
.scorebox{background:var(--panel);padding:14px 15px}
.scorebox b{display:block;font-family:var(--display);font-size:30px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1.05}
.scorebox span{font-family:var(--mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-faint)}
.punch{font-size:clamp(16px,2vw,19px);max-width:62ch;margin-top:12px}
.punch em{font-style:normal;background:var(--mustard);color:#2D2D2D;padding:0 4px}

.turned{margin-top:8px}
.turned .grid{gap:clamp(2px,.5vw,4px)}
.turned .cell{cursor:default}
.t-mega{background:var(--orange)!important;border-color:var(--orange)!important;color:#FAF7E9!important}
.t-up{background:rgba(131,182,182,.30)!important;border-color:rgba(131,182,182,.55)!important;color:var(--screen-ink)!important}
.t-flat{background:#2A2724!important;border-color:#3A3430!important;color:var(--screen-mut)!important}
.t-down{background:#3A211B!important;border-color:#553027!important;color:#E3B0A0!important}
.cell.mine{box-shadow:0 0 0 2px var(--screen-ink);z-index:2}
.key{margin-top:14px;display:flex;flex-wrap:wrap;gap:7px 18px}
.key i{width:14px;height:14px;flex-shrink:0;border:1px solid rgba(0,0,0,.2);display:inline-block;vertical-align:-2px;margin-right:7px}
.key span{font-size:12.5px;color:var(--ink-muted)}

footer.foot{margin-top:40px;padding-top:18px;border-top:1px solid var(--rule);display:flex;flex-direction:column;gap:9px}
footer.foot p{color:var(--ink-faint);font-size:13px;max-width:76ch}
footer.foot b{color:var(--ink-muted)}

.cell,.btn,.pick{touch-action:manipulation;-webkit-tap-highlight-color:transparent}
@media (max-width:820px){ .cell{font-size:8px} }
@media (max-width:700px){
  .kicker{display:none}
  header.top{padding-bottom:12px;margin-bottom:18px}
  .hero h1{font-size:clamp(28px,8.2vw,40px)}
  .thesis{font-size:16px;line-height:1.35}
  .rules{display:block;gap:0;border:1px solid var(--rule);margin-top:12px}
  .rule-box{padding:6px 11px;border-bottom:1px solid var(--rule-soft)}
  .rule-box:last-child{border-bottom:0}
  .rule-box b{display:inline;margin-bottom:0;margin-right:6px}
  .rule-box span{font-size:12.5px;line-height:1.3}
  .bar{margin:18px 0 10px}
  .screen{padding:6px}
  .grid{gap:2px}
  .side{padding:12px 13px 14px}
  .stage{padding:18px 15px}
  .scorebox b{font-size:26px}
}
@media (max-width:430px){
  .wrap{padding-left:11px;padding-right:11px}
  /* Five characters cannot be legible in a 25px tile, so colour carries the
     board and the readout underneath says the name in full. */
  .cell{font-size:0}
  .readout{font-size:12.5px;padding:9px 11px}
  .picks{grid-template-columns:minmax(0,1fr)}
  .pick{padding:10px 11px;gap:9px}
  .pick .tick{min-width:46px;font-size:14px}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* ---------- leaderboard rows that carry information ----------
   A column of strangers' names says nothing, and while the league is seeded
   with simulated players it says less than nothing. Every row shows what it
   actually held, and anything that is not a person choosing on purpose is
   labelled as such. */
.tbl .nm{white-space:normal;line-height:1.3}
.tbl .held{display:block;font-family:var(--mono);font-size:11px;letter-spacing:.02em;color:var(--ink-faint);margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbl tr.index .held{color:#5A4A22}
.tbl .played{color:var(--ink-faint);font-size:11.5px;font-family:var(--mono);margin-left:6px}
.tag{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  border:1px solid var(--rule);padding:1px 5px;margin-left:6px;color:var(--ink-faint);white-space:nowrap}
.tag.dice{border-color:var(--accent-text);color:var(--accent-text)}
.tbl tr.index .tag{border-color:#5A4A22;color:#5A4A22}

/* the mid-week holdings table sits inside a stage, so it needs its own rhythm */
#live .tbl td{padding:7px 15px}
#live .tbl .r{font-family:var(--display);font-weight:800;font-size:13px;color:var(--ink);letter-spacing:.03em}

/* ---------- glossary ----------
   Every term explains itself. Underline is dotted rather than solid so it does
   not read as a link that takes you somewhere; nothing here navigates. */
/* text-transform is inherited, but the UA sheet sets it to none on <button>,
   so a linked term inside an uppercase label came out lowercase: "provisional
   PLACE". font:inherit does not cover it. */
.term{background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;cursor:help;
  border-bottom:1px dotted var(--accent-text);line-height:inherit;text-align:inherit;
  text-transform:inherit;letter-spacing:inherit}
.term:hover{color:var(--accent-text)}
.term:focus-visible{outline:2px solid var(--accent-text);outline-offset:2px}
.tbl .term,.readout .term{border-bottom-color:currentColor;opacity:.95}

.term-pop{position:absolute;z-index:60;background:var(--panel);border:2px solid var(--ink);
  padding:13px 15px 14px;box-shadow:0 10px 30px rgba(0,0,0,.18)}
.term-pop b{display:block;font-family:var(--display);font-weight:800;font-size:15px;
  text-transform:uppercase;letter-spacing:.02em;margin-bottom:6px}
.term-pop p{font-size:13.5px;line-height:1.45}
.term-pop .what{color:var(--ink)}
.term-pop .why{color:var(--ink-muted);margin-top:8px;padding-top:8px;border-top:1px solid var(--rule-soft)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .term-pop{box-shadow:0 10px 30px rgba(0,0,0,.5)}}
@media (max-width:430px){.term-pop{padding:11px 13px 12px}.term-pop p{font-size:13px}}

/* a button that reads as a link, for "not you?" and other inline escapes */
.linkish{background:none;border:0;padding:0;font:inherit;color:var(--accent-text);
  text-decoration:underline;cursor:pointer}
.linkish:focus-visible{outline:2px solid var(--accent-text);outline-offset:2px}

/* ---------- group house rules ---------- */
.rules-form{display:grid;gap:2px;background:var(--rule);border:1px solid var(--rule);margin-bottom:16px}
.rule-row{background:var(--panel);padding:11px 14px;display:flex;align-items:center;gap:12px;
  justify-content:space-between;min-width:0}
.rule-row span{display:block;min-width:0}
.rule-row b{display:block;font-weight:500;font-size:14.5px}
.rule-row i{display:block;font-style:normal;font-size:12.5px;color:var(--ink-faint);margin-top:2px}
.rule-row input[type=text],.rule-row input[type=number]{font:inherit;font-size:15px;padding:8px 10px;
  border:2px solid var(--rule);background:var(--canvas);color:var(--ink);width:150px;flex-shrink:0;min-width:0}
.rule-row input[type=checkbox]{width:20px;height:20px;flex-shrink:0;accent-color:var(--orange)}
.rule-row input:focus-visible{outline:2px solid var(--accent-text);outline-offset:1px}
@media (max-width:430px){
  .rule-row{flex-wrap:wrap;gap:8px}
  .rule-row input[type=text],.rule-row input[type=number]{width:100%}
}

/* ===== how it works, for somebody who has never seen this =====
   Numbered, because a number says "there is an end to this" in a way three
   headings side by side do not. */
.steps{list-style:none;counter-reset:step;display:grid;grid-template-columns:repeat(3,1fr);
  gap:2px;background:var(--rule);border:1px solid var(--rule);margin:22px 0 0;padding:0}
@media (max-width:700px){.steps{grid-template-columns:1fr}}
.steps li{counter-increment:step;background:var(--panel);padding:16px 18px 18px;min-width:0}
.steps li::before{content:counter(step);display:block;font-family:var(--display);font-size:13px;
  font-weight:800;color:var(--btn-ink);background:var(--accent-text);width:24px;height:24px;
  line-height:24px;text-align:center;margin-bottom:10px}
.steps b{display:block;font-family:var(--display);font-size:18px;font-weight:800;
  text-transform:uppercase;letter-spacing:-.01em;line-height:1.08;margin-bottom:6px}
.steps span{font-size:14.5px;color:var(--ink-muted);line-height:1.5}
.plain{margin-top:16px;font-size:15.5px;line-height:1.55;color:var(--ink-muted);max-width:64ch}
.plain b{color:var(--ink)}

/* ===== between rounds, at the top of the page =====
   When it is the first thing you see it has to look like the headline, not
   like a notice somebody left at the bottom. */
#closed{border-width:2px;margin-bottom:clamp(20px,3.5vw,30px)}
#closed h3{font-size:clamp(24px,4.4vw,38px);font-weight:800;text-transform:uppercase;
  letter-spacing:-.02em;line-height:1.02;margin-bottom:10px}
#closed .lede{font-size:clamp(16px,2.1vw,18.5px)}
/* The explanation of the game is background once you cannot play it. */
.hero.is-background{border-top:1px solid var(--rule);padding-top:clamp(18px,3vw,26px)}
.hero.is-background .thesis{font-size:clamp(16px,2vw,18px);color:var(--ink-muted)}

/* ===== the between-rounds doors ===== */
.doors{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px;background:var(--rule);
  border:1px solid var(--rule);margin-top:20px}
@media (max-width:820px){.doors{grid-template-columns:1fr}}
.door{background:var(--panel);padding:18px 18px 20px;min-width:0;display:flex;flex-direction:column}
.door h4{font-family:var(--display);font-size:19px;font-weight:800;text-transform:uppercase;
  letter-spacing:-.01em;margin:0 0 8px;line-height:1.06}
.door p{font-size:14.5px;color:var(--ink-muted);line-height:1.5;margin-bottom:14px}
.door .btn{align-self:flex-start;margin-top:auto}
.door .lockform{margin-top:auto}
.door .terms{margin-top:10px}

/* ===== the group roster =====
   A table answers "where do I stand". This answers "who is even here, and did
   Priya play this week", which is a different question and the one somebody
   asks before they go and chase their brother-in-law. */
.roster{border:2px solid var(--ink);background:var(--panel);padding:clamp(14px,2.4vw,20px);margin-top:22px}
.roster-head{display:flex;align-items:baseline;justify-content:space-between;gap:14px;flex-wrap:wrap}
.roster-head .kick{margin:0}
.roster-count{font-family:var(--mono);font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-faint);margin:0}
.roster-table{width:100%;border-collapse:collapse;margin-top:12px;font-size:15px}
.roster-table td{padding:9px 6px;border-bottom:1px solid var(--rule-soft);vertical-align:middle}
.roster-table td:first-child{padding-left:0}
.roster-table td:last-child{padding-right:0;text-align:right;white-space:nowrap}
.roster-table tr:last-child td{border-bottom:0}
.roster-table .nm{font-weight:700}
.roster-table tr.me .nm{color:var(--accent-text)}
.roster-table .sub{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-faint);margin-top:3px}
.roster-table .val{font-family:var(--mono);font-weight:700;font-variant-numeric:tabular-nums}
.roster-table .val.pos{color:var(--pos)}
.roster-table .val.neg{color:var(--neg)}
.roster-table .val.none{color:var(--ink-faint);font-weight:400}
.pill{display:inline-block;font-family:var(--mono);font-size:9.5px;letter-spacing:.11em;
  text-transform:uppercase;padding:3px 7px;border:1px solid var(--rule);color:var(--ink-muted)}
.pill.locked{border-color:var(--pos);color:var(--pos)}
.pill.dice{border-color:var(--mustard);color:var(--accent-text)}
.pill.waiting{border-color:var(--rule);color:var(--ink-faint)}
.pill.owner{border-color:var(--ink);color:var(--ink)}
.roster-note{margin-top:12px;font-size:13.5px;color:var(--ink-muted)}
@media (max-width:520px){
  .roster-table td:nth-child(2){display:none}
}

/* ===== a group season, and its end =====
   The finish line has to be visible from week one. "Week 3 of 8" is the reason
   somebody plays week 6; a season nobody can see the end of is just a habit,
   and habits lapse quietly. */
.season-bar{display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  border:2px solid var(--ink);background:var(--panel);padding:12px 16px;margin-top:22px}
.season-bar .kick{margin:0 0 3px}
.season-bar b{font-family:var(--display);font-size:19px;font-weight:800;text-transform:uppercase;letter-spacing:.01em}
.season-track{display:flex;gap:3px;flex:1;min-width:120px;justify-content:flex-end;flex-wrap:wrap}
.season-track i{width:16px;height:16px;border:1px solid var(--rule);background:var(--panel)}
.season-track i.done{background:var(--orange);border-color:var(--orange)}
.season-track i.now{background:var(--mustard);border-color:var(--mustard)}
.finished{border:2px solid var(--orange);background:var(--panel);padding:clamp(16px,2.6vw,22px);margin-top:18px}
.finished h3{font-size:clamp(20px,3vw,28px);font-weight:800;text-transform:uppercase;margin-bottom:8px}
.finished .lede{margin-bottom:16px}

/* ===== the record =====
   What replaced the public season table. It is deliberately NOT a table: the
   whole point is that there is no ranking here to be behind on. */
.tables.one{grid-template-columns:minmax(0,1fr)}
.record{border:2px solid var(--ink);background:var(--panel);padding:clamp(16px,2.6vw,24px);margin-top:22px}
.record h3{font-size:clamp(19px,2.6vw,25px);font-weight:800;text-transform:uppercase;margin-bottom:14px}
.rec-nums{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;background:var(--rule);border:1px solid var(--rule)}
@media (max-width:620px){.rec-nums{grid-template-columns:1fr}}
.rec-nums > div{background:var(--screen);padding:16px 14px;min-width:0}
.rec-nums b{display:block;font-family:var(--display);font-size:clamp(28px,4.4vw,38px);font-weight:800;
  line-height:1;font-variant-numeric:tabular-nums;color:var(--screen-ink)}
.rec-nums span{display:block;margin-top:8px;font-family:var(--mono);font-size:10.5px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--screen-mut);line-height:1.5}
.rec-note{margin-top:14px;font-size:14.5px;color:var(--ink-muted);max-width:70ch}

/* ===== the console's job table ===== */
.jobs{width:100%;border-collapse:collapse;margin-top:14px;font-size:14px}
.jobs td{padding:9px 8px;border-bottom:1px solid var(--rule-soft);vertical-align:top}
.jobs td:first-child{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--accent-text);white-space:nowrap;padding-left:0}
.jobs td:nth-child(2){color:var(--ink-muted)}
.jobs td:nth-child(3){font-family:var(--mono);font-size:12px;color:var(--ink-faint);white-space:nowrap}
.jobs td:last-child{text-align:right;padding-right:0;white-space:nowrap}
.jobs .btn{padding:6px 12px;font-size:11px}
@media (max-width:600px){
  .jobs td{display:block;border:0;padding:2px 0}
  .jobs tr{display:block;padding:10px 0;border-bottom:1px solid var(--rule-soft)}
  .jobs td:last-child{text-align:left;padding-top:8px}
}

/* ===== the streak =====
   Mustard, not orange: orange is the deadline colour on this page and the two
   must not compete. It is a reward, so it sits on the panel rather than
   shouting from the dark band. */
.streak{display:inline-flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  margin-top:10px;padding:8px 14px;background:var(--panel);border:2px solid var(--mustard)}
.streak b{font-family:var(--display);font-size:26px;font-weight:800;line-height:1;
  font-variant-numeric:tabular-nums;color:var(--accent-text)}
.streak span{font-family:var(--mono);font-size:11.5px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink)}
.streak em{font-family:var(--mono);font-size:11.5px;letter-spacing:.11em;text-transform:uppercase;
  font-style:normal;color:var(--ink-faint);padding-left:9px;border-left:1px solid var(--rule)}

/* ===== the running clock =====
   Dark ground on purpose: it is the same screen the board is played on, so the
   deadline reads as instrumentation rather than as another card. Digits are
   tabular or the whole block shudders once a second as the glyph widths change. */
.clock{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px 28px;align-items:center;
  background:var(--screen);border:2px solid var(--screen-edge);color:var(--screen-ink);
  padding:clamp(12px,2vw,18px) clamp(14px,2.4vw,22px);margin-bottom:20px}
@media (max-width:640px){.clock{grid-template-columns:1fr;gap:10px}}
.clock-kick{font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--mustard);display:flex;align-items:center;gap:7px}
.clock-kick::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}
.clock-time{display:block;font-family:var(--display);font-weight:800;
  font-size:clamp(38px,8.5vw,72px);line-height:.94;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;margin:4px 0 2px}
.clock-when{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--screen-mut)}
.clock-note{font-size:14.5px;line-height:1.5;color:var(--screen-mut);max-width:46ch}
.clock-note b{color:var(--screen-ink)}
/* Under a day it is worth noticing; under an hour it is worth acting on. */
.clock.is-warm .clock-kick{color:var(--mustard)}
.clock.is-hot .clock-kick,.clock.is-hot .clock-time{color:var(--orange)}
.clock.is-hot .clock-kick::before{animation:clockpulse 1s steps(1,end) infinite}
.clock.is-over .clock-time{color:var(--screen-mut)}
@keyframes clockpulse{0%,49%{opacity:1}50%,100%{opacity:.15}}
@media (prefers-reduced-motion:reduce){
  .clock.is-hot .clock-kick::before{animation:none;opacity:1}
}

/* ===== subnav ===== */
/* The row that replaced header.top on the three pages carrying the band. Keeping
   the links matters: without them anyone landing on the game page first is stranded. */
.subnav{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px;font-family:var(--mono);
  font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-faint);
  padding-bottom:12px;border-bottom:2px solid var(--ink);margin-bottom:clamp(20px,3.5vw,30px)}
.subnav a{color:inherit;text-decoration:none;border-bottom:1px solid var(--rule)}
.subnav a:hover{color:var(--accent-text)}
.subnav span{margin-left:auto;text-align:right}
/* the band supplies the top of the page, so the wrap must not add its own */
.bh-band + .wrap{padding-top:clamp(16px,2.5vw,26px)}
@media (max-width:430px){
  .subnav span{margin-left:0;width:100%;text-align:left}
}

/* ===== setting a group up =====
   Five screens and a rail. The rail is the only place the whole group is
   visible at once while it is being built, so it is not decoration: on a
   phone it moves ABOVE the steps, because that is the summary somebody
   scrolls back up to check. */
.setup{display:grid;grid-template-columns:minmax(0,1fr) minmax(220px,280px);gap:20px;align-items:start;
  margin-top:clamp(16px,3vw,26px)}
.setup-main{min-width:0}

.setup-steps{display:flex;list-style:none;margin:0 0 18px;padding:0;gap:2px;background:var(--rule);
  border:1px solid var(--rule);overflow:hidden}
.setup-steps li{flex:1;min-width:0;background:var(--panel)}
.setup-steps button{width:100%;border:0;background:none;padding:9px 6px 8px;cursor:pointer;display:block;text-align:center;
  color:var(--ink-faint)}
.setup-steps button[disabled]{cursor:default;opacity:.55}
.setup-steps button b{display:block;font-family:var(--display);font-size:15px;font-weight:800;line-height:1}
.setup-steps button span{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.11em;
  text-transform:uppercase;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.setup-steps li.done button{color:var(--ink-muted)}
.setup-steps li.now{background:var(--ink)}
.setup-steps li.now button{color:var(--btn-ink);opacity:1}
.setup-steps button:focus-visible{outline:3px solid var(--accent-text);outline-offset:-3px}

.step{border:2px solid var(--ink);background:var(--panel);padding:clamp(18px,3vw,28px)}
.step h2{font-size:clamp(22px,3.4vw,32px);font-weight:800;text-transform:uppercase;margin-bottom:10px}
.step .lede{font-size:clamp(15px,1.8vw,17.5px);color:var(--ink-muted);max-width:58ch}
.step .lede.small{font-size:14px;margin-bottom:8px}
.sub-label{font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink-faint);margin:20px 0 9px}

.field{display:block;margin-top:16px}
.field > span{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-faint);margin-bottom:7px}
.field > span i{font-style:normal;text-transform:none;letter-spacing:0;font-family:var(--body);font-size:12px}
.field input{font:inherit;width:100%;font-size:17px;padding:12px 14px;border:2px solid var(--ink);
  background:var(--canvas);color:var(--ink)}
.field.slim{max-width:170px}
.field input:focus-visible{outline:3px solid var(--accent-text);outline-offset:1px}
/* One row per person. The remove button sits INSIDE the row's border rather
   than beside it, so a column of boxes still reads as one list. */
.person{display:flex;align-items:stretch;gap:0;border:2px solid var(--ink);background:var(--canvas);
  margin-bottom:8px}
.person input{font:inherit;font-size:16px;flex:1;min-width:0;padding:11px 13px;border:0;
  background:transparent;color:var(--ink)}
.person input:focus-visible{outline:3px solid var(--accent-text);outline-offset:-3px}
.person .drop{border:0;border-left:2px solid var(--rule);background:transparent;color:var(--ink-faint);
  cursor:pointer;font-size:19px;line-height:1;width:42px;flex:none}
.person .drop:hover{background:var(--ink);color:var(--canvas)}
.person .drop:focus-visible{outline:3px solid var(--accent-text);outline-offset:-3px}

.add-person{display:inline-flex;align-items:center;gap:8px;border:2px dashed var(--rule);
  background:transparent;color:var(--ink-muted);cursor:pointer;font:inherit;font-size:14.5px;
  padding:9px 14px;margin-top:2px}
.add-person span{font-size:17px;line-height:1;color:var(--orange)}
.add-person:hover{border-color:var(--ink);border-style:solid;color:var(--ink)}
.add-person:focus-visible{outline:3px solid var(--accent-text);outline-offset:1px}

.suggests{display:flex;flex-wrap:wrap;gap:7px;margin-top:12px}
.suggest{border:1px solid var(--rule);background:transparent;color:var(--ink-muted);cursor:pointer;
  font-size:13px;padding:5px 10px}
.suggest:hover{border-color:var(--ink);color:var(--ink)}

.chips{display:flex;flex-wrap:wrap;gap:2px;background:var(--rule);border:1px solid var(--rule)}
.chip{flex:1 1 110px;min-width:0;background:var(--panel);border:0;cursor:pointer;padding:11px 12px;text-align:left;
  font-family:var(--display);font-weight:700;font-size:15px;color:var(--ink)}
.chip i{display:block;font-style:normal;font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-faint);margin-top:3px}
.chip:hover{background:var(--rule-soft)}
.chip.on{background:var(--ink);color:var(--btn-ink)}
.chip.on i{color:rgba(250,247,233,.72)}
.chip:focus-visible{outline:3px solid var(--accent-text);outline-offset:-3px}

.starts{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:2px;
  background:var(--rule);border:1px solid var(--rule)}
.start{background:var(--panel);border:0;cursor:pointer;padding:11px 13px;text-align:left;min-width:0;color:var(--ink)}
.start b{display:block;font-family:var(--display);font-weight:800;font-size:15px;letter-spacing:.01em}
.start span{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-faint);margin-top:3px;line-height:1.5}
.start:hover{background:var(--rule-soft)}
.start.on{background:var(--orange);color:#FAF7E9}
.start.on span{color:rgba(250,247,233,.82)}
.start:focus-visible{outline:3px solid var(--accent-text);outline-offset:-3px}

/* The line that turns settings into a season somebody can picture. */
.derived{margin-top:16px;border-left:3px solid var(--orange);padding:2px 0 2px 12px;
  font-size:14.5px;color:var(--ink-muted);max-width:64ch}
.invite-count{margin-top:10px;font-size:13.5px;color:var(--ink-muted)}
/* On /groups/ the rows live in a real form with a submit under them, rather
   than in a wizard step whose Next button lives outside the panel. */
#invite-send{margin-top:12px}

/* ===== a group, as two columns =====
   The door on the left (name, link, invitations, house rules) and the table on
   the right (season, roster, this week). Stacked, a group with a roster and two
   tables was 2,462px on a 812px screen. */
.gcol{min-width:0}
/* A promise that has to be next to the send button, without five lines of it.
   Dallin, 2026-08-24: "some things could just be a button instead of a full
   explanation." */
.terms.mini{padding:8px 12px;font-size:13px}
.terms.mini summary{cursor:pointer;list-style:none}
.terms.mini summary::-webkit-details-marker{display:none}
.terms.mini summary::after{content:" \2192";color:var(--accent-text)}
.terms.mini[open] summary::after{content:" \2193"}
.terms.mini p{margin-top:7px;font-size:12.5px;line-height:1.45}
.invite-note{font-size:13.5px;margin-bottom:9px}

/* Once there is a group on the page, the pitch for having one is furniture,
   and with exactly one group the list above it is the same group twice. */
@media (min-width:1000px){
  .has-group .groupspage .hero{margin-bottom:10px}
  .has-group .groupspage .hero h1{font-size:clamp(24px,2.6vw,31px)}
  .has-group .groupspage .hero .thesis{display:none}
  .one-group #mine .bar{display:none}
  .one-group #mine{margin-bottom:0}
  .has-group #group{padding:14px 16px 16px}
  .has-group #group h3{font-size:clamp(20px,2.3vw,26px)}
  .has-group .groupcols{margin-top:12px;gap:clamp(16px,1.8vw,24px)}
  .has-group .share{margin-top:12px!important}
  .has-group .makebar{margin-top:12px}
  /* the last 160px, all measured off the invite column */
  .has-group .person input{padding:9px 12px;font-size:15px}
  .has-group .person .drop{padding:0 11px}
  .has-group .add-person{padding:7px 12px;font-size:12.5px}
  .has-group .invite-count{margin-top:8px;font-size:12.5px}
  .has-group #invite-send{margin-top:10px;padding:10px 18px;font-size:12px}
  .has-group .terms.mini{margin-top:9px;padding:7px 11px;font-size:12.5px}
  .has-group .invite-note{margin-bottom:8px;font-size:13px}
  .has-group #group-rules{font-size:14px}
  .has-group .share input{padding:9px 12px;font-size:13px}
  .has-group .share .btn{padding:10px 16px;font-size:12px}
  .has-group .roster-table td{padding:5px 12px}
  .has-group .tbl h3{padding:9px 13px}
  .has-group .tbl td{padding:5px 13px}
  .has-group .season-bar{padding:10px 14px}
  .one-group #mine-rows td{padding:5px 12px;font-size:13px}
  .has-group .groupspage .hero h1{font-size:clamp(22px,2.2vw,26px)}
  .has-group .groupspage .hero{margin-bottom:7px}
  .has-group .roster-head{padding:9px 13px}
  .has-group .roster-note{font-size:12.5px;margin-top:7px;padding:0 13px 11px}
  .has-group .tbl .empty{font-size:12.5px}
  .has-group .makebar .btn{padding:10px 16px;font-size:12px}
  .has-group .tbl h3 span{font-size:12px}
}

/* Email invites, folded away until wanted. The link above it is the invite. */
.invitebox{margin-top:14px}
.invitebox > summary{list-style:none;display:inline-block;cursor:pointer}
.invitebox > summary::-webkit-details-marker{display:none}
.invitebox[open]{border:2px solid var(--rule);background:var(--panel);padding:12px 14px}
.invitebox[open] > summary{margin-bottom:11px}

/* Start one / join one: two buttons, not two panels. */
.makebar{display:flex;flex-wrap:wrap;align-items:flex-start;gap:12px;margin-top:18px}
.joinbox summary{list-style:none;display:inline-block}
.joinbox summary::-webkit-details-marker{display:none}
.joinbox[open]{flex:1 1 340px;border:2px solid var(--rule);background:var(--panel);padding:12px 14px}
.joinbox[open] summary{margin-bottom:10px}
.joinbox .lockform{margin-top:0}
@media (min-width:1000px){
  .wrap.groupspage{max-width:1220px}
  .groupcols{display:grid;grid-template-columns:0.92fr 1.08fr;
    gap:clamp(18px,2.2vw,30px);align-items:start;margin-top:16px}
  .gcol > :first-child{margin-top:0!important}
  #group{padding:16px 18px 18px}
  #group .tables{margin-top:0!important;grid-template-columns:repeat(2,minmax(0,1fr))}
  #group .roster{margin-top:0}
  #group .season-bar{margin-top:0}
  #group .pending{margin-top:0}
  .gactions{margin-top:16px!important}
}
@media (max-width:999px){
  .groupcols{display:flex;flex-direction:column;gap:0}
}
.invite-count.over{color:var(--neg)}

.review{margin-top:16px;display:grid;grid-template-columns:auto minmax(0,1fr);gap:1px 16px;
  border-top:1px solid var(--rule)}
.review dt{font-family:var(--mono);font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-faint);padding:10px 0 10px;border-bottom:1px solid var(--rule-soft);white-space:nowrap}
.review dd{margin:0;padding:10px 0;border-bottom:1px solid var(--rule-soft);font-size:15px;min-width:0;
  overflow-wrap:anywhere}

.setup-nav{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:18px}
.setup-nav .err{margin:0;width:100%}

.rail{border:2px solid var(--ink);background:var(--panel);padding:14px 16px 16px;position:sticky;top:16px}
.rail .kick{margin-bottom:10px}
.rail dl{margin:0;display:grid;grid-template-columns:1fr;gap:0}
.rail dt{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-faint);margin-top:10px}
.rail dt:first-child{margin-top:0}
.rail dd{margin:2px 0 0;font-size:13.5px;line-height:1.4;overflow-wrap:anywhere}
.rail dd i{color:var(--ink-faint)}

@media (max-width:820px){
  .setup{grid-template-columns:minmax(0,1fr)}
  /* Summary first on a phone: it is the thing you scroll up to check. */
  /* After the form, not before it: on a phone the summary of an empty setup
     was the first thing you saw, above the question it summarises. */
  .rail{order:2;position:static}
  .rail dl{grid-template-columns:repeat(2,minmax(0,1fr));gap:0 14px}
  .setup-steps button span{display:none}
  .setup-steps button b{font-size:14px}
}

/* ===== a group that has not started yet =====
   Above the tables, for the same reason the between-rounds panel is above the
   hero on the play page: being shown an empty table and only then told why is
   the wrong order, and it reads as "nobody turned up". */
.pending{border:2px solid var(--ink);background:var(--panel);padding:clamp(16px,2.6vw,22px);margin-top:22px}
.pending h3{font-size:clamp(20px,3vw,28px);font-weight:800;text-transform:uppercase;margin-bottom:8px}
.pending h3 span{color:var(--accent-text)}
.pending .lede{color:var(--ink-muted);font-size:15.5px;max-width:64ch}

/* ===== the site header =====
   Dallin, 2026-08-24: "It needs to have the normal Financial Rebellion header."
   This is the same brand bar every other FR interactive tool opens with -- the
   lockup on the left, linked home, and the nav on the right. It sits OUTSIDE
   .wrap because the band does too, so it carries its own matching max-width or
   the logo and the board below it do not line up. */
.brandbar{max-width:1140px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;
  gap:14px 22px;flex-wrap:wrap;padding:clamp(14px,2vw,20px) clamp(16px,4vw,32px) clamp(10px,1.6vw,14px)}
.brandhome{display:block;line-height:0}
.brandhome:focus-visible{outline:3px solid var(--accent-text);outline-offset:4px}
.brandbar .fr-logo{width:clamp(122px,14vw,152px)}
.topnav{display:flex;align-items:center;gap:6px 20px;flex-wrap:wrap;font-family:var(--display);
  font-size:11.5px;font-weight:700;letter-spacing:.15em;text-transform:uppercase}
.topnav a{color:var(--ink-muted);text-decoration:none;border-bottom:2px solid transparent;padding-bottom:2px}
.topnav a:hover{color:var(--accent-text);border-bottom-color:var(--accent-text)}
.topnav a:focus-visible{outline:2px solid var(--accent-text);outline-offset:3px}
/* The page you are already on is named, not offered. */
.topnav .here{color:var(--ink);border-bottom:2px solid var(--orange);padding-bottom:2px}
.topnav .cta{color:var(--accent-text)}
@media (max-width:640px){
  .brandbar{padding-bottom:8px;gap:10px}
  .brandbar .fr-logo{width:112px}
  .topnav{width:100%;gap:5px 16px;font-size:10px;letter-spacing:.12em}
}

/* ===== the band, slimmed =====
   The full 250px masthead put the board 1067px down the page. It keeps every
   moving part; it loses its own copy of the lockup, because the brand bar
   above it is now carrying that, and two FR lockups 60px apart read as a
   mistake. BATTLESHIP is still centred in a --lw box exactly as measured, so
   the geometry in project_fr_battleship_header is untouched -- only the box's
   width is re-derived now that nothing sits above the line. */
/* THE LOCKUP STAYS IN THE BAND. Dallin, 2026-08-24: "battleship animation
   always needs to show financial rebellion above it. needs to read like
   financial rebellion battleship." So the band is short but it is the whole
   lockup, and --lw goes back to the measured 1.965 cap from
   project_fr_battleship_header rather than the wordmark-only override. */
.bh-band.is-slim{--bh:clamp(112px,11vw,146px)}
.bh-band.is-slim .bh-mid{gap:clamp(4px,calc(var(--bh) * .05),11px)}
/* The wordmark is proportionally wider in a short band, so the radial mask that
   keeps the radar off it has to widen with it or a stray blip tag lands on the T. */
.bh-band.is-slim .bh-core{width:min(82%,880px)}
/* Todd, 2026-08-25: "that is hard to read up here underneath battleship".
   Measured at 1440x900 it was 10.5px against an 80px wordmark, a 7.6:1 ratio
   that reads as a caption on a photograph rather than the line that says what
   the game is. The band is 124px tall and was spending .085 of it on the only
   sentence in the header, so the room came out of the band's own slack and
   nothing below it moved. */
.bh-band.is-slim .bh-sub{font-size:min(clamp(11px,1.05vw,14px),calc(var(--bh) * .115))}
/* The phone band is its own composition, not the desktop one scaled down.
   The subline is 43 characters: at 390px it runs the full width of the band and
   lands across both ships, and no amount of shrinking fixes that. Drop it, and
   push the contacts out to the corners so the wordmark owns the middle. */
@media (max-width:560px){
  .bh-band.is-slim{--bh:clamp(104px,27vw,132px)}
  .bh-band.is-slim .bh-sub{display:none}
  .bh-band.is-slim .bh-contact{min-width:0;width:22%}
  .bh-band.is-slim .bh-contact.bh-a{left:9%;top:82%}
  .bh-band.is-slim .bh-contact.bh-b{left:91%;top:18%}
}

/* ===== the play console =====
   The board on the left and everything you read or press on the right. The
   point of the whole layout: you can see the board and the instructions at
   the same time, which the stacked version could not do at any height.

   The board is capped by VIEWPORT HEIGHT, not by column width. Sized off the
   column it grows with the window and marches straight back off the bottom of
   the screen, which is how it got to 640px tall on a 900px page. */
.wrap.play{max-width:1140px}
.console{display:grid;grid-template-columns:minmax(0,auto) minmax(310px,440px);
  gap:clamp(14px,2vw,24px);align-items:start;justify-content:center;
  --board:clamp(280px,min(46vw,100%),600px)}
/* The rail runs long during the cut. Pinning the board means you are still
   looking at what you hit while you scroll the list of what to drop -- which is
   the whole point of putting them side by side. */
.boardcol{width:var(--board);max-width:100%;min-width:0;position:sticky;top:14px}
/* THE SAME MIN-CONTENT FLOOR THE LEADERBOARD HIT. A cell whose ticker sets its
   own min-width stops the board shrinking: ten of "CMCSA" at 10px is a 336px
   floor, so asking for a 221px board silently got a 336px one and the page
   scrolled. Clip the text and scale it off --board, which is the only thing
   that knows how big a cell is going to be. */
/* "I need things to be read easily." The cell font was capped at 10px, so
   growing the board bought nothing: a 600px board still printed CMCSA at ten
   pixels. min-width:0 and overflow:hidden stay, because a grid CELL is what
   holds a whole column at its min-content width. */
.console .cell{min-width:0;overflow:hidden;font-size:min(15px,calc(var(--board) / 34))}
/* NOT .rail. The group wizard already owns that name, with a border, a sticky
   position and an order:-1 under 900px -- which silently put this whole rail
   ABOVE the board on every phone. */
.playrail{display:flex;flex-direction:column;gap:14px;min-width:0}
/* The standfirst is a hook, not a briefing: at 21px over two lines it cost 110px
   of the fold to say what the line under THE BOARD says again anyway. */
.wrap.play .hero{margin-bottom:14px}
.wrap.play .hero .thesis{font-size:clamp(16px,1.55vw,18px);max-width:82ch;margin-top:0}
.wrap.play .hero.is-background .thesis{font-size:clamp(16px,2vw,18px)}

/* ===== the instrument strip ===== */
/* A BOX, NOT A STRIP. Dallin, 2026-08-25: "the clock can be pretty small. not a
   strip, just a small banner or box."

   It was a full-width dark bar 96px tall carrying a 50px countdown, which made
   the deadline the loudest object on a page whose subject is a hundred tiles.
   It shrinks to its own contents and sits at the top left. Everything it used
   to spend on height goes to the board. */
.status{border:2px solid var(--screen-edge);background:var(--screen);color:var(--screen-ink);
  margin-bottom:clamp(12px,1.5vw,16px);width:fit-content;max-width:100%}
/* Both children start hidden, and an empty strip is a 4px dark scar across the page. */
.status:not(:has(> *:not([hidden]))){display:none}
.status .weekbar{border:0;background:none;margin:0;padding:9px 16px 0;gap:5px 16px}
.status .weekbar .wk{font-family:var(--mono);font-weight:400;font-size:11px;letter-spacing:.15em;color:var(--screen-mut)}
.status .weekbar .meta{color:var(--screen-mut)}
.status .weekbar .meta b{color:var(--screen-ink)}
/* The countdown is six inches below in 50px digits. Saying it twice, once as
   "1D 7H", reads as two different deadlines. */
.status #wkcountdown{display:none}
.status .clock{border:0;margin:0;padding:2px 14px 10px;gap:4px 18px}
.status .clock-time{font-size:clamp(24px,2.4vw,30px);margin:1px 0 0}
/* The note explains the dice ONCE. At 46ch it was setting the width of the
   whole box, which is what made it a strip in the first place. */
.status .clock-note{font-size:13px;max-width:52ch}
@media (max-width:640px){.status .clock{grid-template-columns:1fr}}

/* A flex row wraps, and in a 400px board column it did: the shots counter
   dropped onto its own line and shoved the board 110px down the page, which is
   exactly the fold this layout exists to protect. Grid, two tracks, no wrap. */
.console .bar{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;
  gap:14px;margin:0 0 9px}
.console .bar h2{font-size:clamp(18px,2.2vw,22px)}
.console .bar .sub{font-size:13px;max-width:none;margin-top:2px}
.console .counter b{font-size:clamp(28px,3.4vw,36px)}
.console .readout{margin-top:8px}
/* Every panel in the rail is the same box, so the rail reads as one column
   rather than as four unrelated cards. */
.playrail .stage{margin-top:0;padding:15px 16px 17px}
.playrail .stage h3{font-size:clamp(19px,2.3vw,23px);margin-bottom:8px}
.playrail .stage p.lede{font-size:14.5px;max-width:none}
.playrail .terms{font-size:13px;padding:9px 12px;max-width:none}
.playrail .lockform{margin-top:14px}
@media (max-width:900px){
  .console{grid-template-columns:minmax(0,1fr);--board:min(100%,calc(100vh - 300px))}
  .boardcol{width:100%;position:static}
}
@media (max-width:560px){
  .wrap.play .hero .thesis{font-size:16px;line-height:1.4}
  .status .clock{padding:2px 14px 12px}
  .status .clock-time{font-size:clamp(30px,10vw,40px)}
  .console .bar .sub{font-size:14px}
}

/* ===== how it works, in the rail ===== */
.howto{border:2px solid var(--ink);background:var(--panel);padding:14px 16px 16px}
.howto .kick{margin-bottom:11px}
/* Past step one the how-to stops being a briefing and becomes a position
   marker: three labels across, the live one lit, and the rail gets its height
   back for the decision you are actually making. */
.howto.compact{padding:11px 14px}
.howto.compact .kick{display:none}
.howto.compact .steps{grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.howto.compact .steps li{padding:0 0 0 25px}
.howto.compact .steps li::before{width:18px;height:18px;line-height:18px;font-size:11px;
  background:var(--rule);color:var(--ink-faint)}
.howto.compact .steps li.now::before{background:var(--accent-text);color:var(--btn-ink)}
.howto.compact .steps li:not(.now) b{color:var(--ink-faint)}
.howto.compact .steps b{font-size:12px;line-height:1.15;margin:0}
.howto.compact .steps span{display:none}
/* Three cards side by side need 330px of height in a 390px rail. Stacked, with
   the number beside the line instead of above it, they need 150. */
.playrail .steps{grid-template-columns:minmax(0,1fr);gap:11px;background:none;border:0;margin:0}
.playrail .steps li{background:none;padding:0 0 0 32px;position:relative}
.playrail .steps li::before{position:absolute;left:0;top:0;margin:0;width:22px;height:22px;line-height:22px;font-size:12px}
.playrail .steps b{font-size:16px;margin-bottom:3px}
.playrail .steps span{font-size:13.5px;line-height:1.42}

/* ===== the cut, one row per company =====
   It used to be an auto-fill grid at 215px, which gave four columns on a wide
   page and left the company name about 30px to live in: the name vanished and
   the sector ran straight through the CUT chip. One column, one row each, and
   the name gets the room. */
.playrail .picks{grid-template-columns:minmax(0,1fr);margin:14px 0 12px}
.pickrow{display:grid;grid-template-columns:minmax(0,1fr) auto}
.pick{gap:10px;padding:10px 12px}
.pick .tick{min-width:46px;font-size:14.5px}
.pick .who b{font-size:13.5px}
.research{padding:0 11px;white-space:nowrap;font-size:9px}

/* ===== a list of holdings ===== */
/* Ticker and name were pushed to opposite ends of the row by space-between, so
   on a wide row they read as two unrelated columns and on a narrow one they
   touched. Dallin, 2026-08-24: "I want a space in between the ticker and the
   name." One gap, both left. */
/* Scoped to the HOLDINGS lists only. The leaderboard head-to-head uses the same
   .side shell for name-versus-score, where space-between is right and a 56px
   first column would be nonsense. */
#log li,.side.kept li{display:grid;grid-template-columns:56px minmax(0,1fr);gap:0 12px}
#log li span,.side.kept li span{text-align:left}
.side.kept{border:0;padding:0;background:none;margin:14px 0 0}
.side.kept li{padding:7px 0}

/* ===== a labelled field ===== */
/* The name box said "Name for the board", which Dallin read as "name my
   board" -- a fair reading, since the group wizard really does name things.
   It is the name other players see, and now it says so above the box. */
/* .field is the group wizard’s, and it is display:block there. Scope every one
   of these to the lock form or the wizard fields all become flex children. */
.lockform .field{display:flex;flex-direction:column;gap:5px;margin-top:0;min-width:0;flex:1 1 200px}
/* .lockform .email carries flex:2 1 250px for the old unlabelled row. Inside a
   column-direction label that basis becomes a 250px-TALL email box. */
.lockform .field > input{flex:none}
/* In the rail there is no room for three things across, and a form that wraps
   mid-field reads as broken. */
.playrail .lockform{flex-direction:column;align-items:stretch;gap:12px}
/* Same trap one level up: flex:1 1 200px in a COLUMN is a 200px-tall field. */
.playrail .lockform .field{flex:none}
.playrail .lockform .btn{align-self:flex-start}
.lockform .field > span{font-size:10px;letter-spacing:.13em;color:var(--ink-faint);margin-bottom:0}
.lockform .field input{width:100%;font-size:15px;padding:11px 13px}
/* NOT here. .lockform .field:has(.email) and .playrail .lockform .field have
   the same specificity, so whichever is written last wins -- and this one won,
   which made the email box 230px TALL in the column layout the rail uses on a
   phone. It only belongs where the form is a row. */


/* ===== the leaderboard as a dashboard =====
   Three reads, three columns: where you and everyone else landed, the ranked
   table, and the hundred tiles turned over. Stacked they were 3,167px. */
.boardhero h1{font-size:clamp(24px,2.7vw,31px)}
.boardhero .thesis{font-size:clamp(14px,1.3vw,15px);max-width:none;margin-top:5px}
.colnote{margin-top:7px;font-size:11.5px;line-height:1.4;color:var(--ink-faint)}
.colhead{font-family:var(--display);font-size:13px;font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;margin-bottom:9px}
.colhead span{display:block;font-family:var(--body);font-weight:400;letter-spacing:0;
  text-transform:none;font-size:12.5px;color:var(--ink-muted);margin-top:3px}
.h2hkick{margin-top:16px}
.bcol{display:flex;flex-direction:column;gap:14px;min-width:0}
.bcol > *{margin-top:0}
.turned{margin-top:0}

@media (min-width:1100px){
  .wrap.board{max-width:1220px}
  /* col3 is sized so the hundred tiles land at their natural width instead of
     being capped, and the width that frees up goes to the two columns whose
     text was wrapping. */
  .boardcols{display:grid;grid-template-columns:1fr 1.3fr 0.86fr;
    gap:clamp(16px,1.8vw,24px);align-items:start}
  .board .weekbar{padding:7px 13px;gap:5px 13px;margin-bottom:12px}
  .board .weekbar .btn{padding:7px 14px;font-size:11.5px}
  .boardhero{margin-bottom:4px}
  .board .weekbar .wk{font-size:15px}
  .board .stage{padding:13px 15px 14px}
  .board .stage h3{font-size:clamp(18px,2vw,22px);margin-bottom:6px}
  /* Your week is four numbers. Four across in one band beats two rows of two:
     it is the same information in half the height. */
  .board .scoreline{grid-template-columns:repeat(4,minmax(0,1fr));margin:10px 0 0}
  .board .scorebox{padding:8px 9px}
  .board .scorebox b{font-size:18px}
  .board .scorebox span{font-size:8.5px;letter-spacing:.09em;line-height:1.3}
  .board .punch{font-size:13.5px;max-width:none;margin-top:9px}
  .board .record{padding:13px 15px 14px;margin-top:0}
  .board .record h3{font-size:18px;margin-bottom:10px}
  .board .rec-nums > div{padding:9px 10px}
  .board .rec-nums b{font-size:21px}
  .board .rec-nums span{margin-top:4px;font-size:9px;line-height:1.35}
  .board .rec-note{margin-top:10px;font-size:12.5px}
  .board .tbl h3{padding:9px 13px;font-size:11.5px}
  .board .tbl table{font-size:13px}
  .board .tbl td{padding:3.5px 12px}
  .board .tbl .held{font-size:10px}
  .board .readout{margin-top:7px;min-height:30px;padding:6px 10px;font-size:11.5px}
  .board .key{margin-top:8px;gap:4px 13px}
  .board .key span{font-size:11px}
  .board .tbl h3{padding:8px 13px}
  /* A cell whose ticker sets its min-content width stops the whole column
     shrinking: ten of "CMCSA" at 10px is a 400px floor no grid template can
     beat. Let the text be clipped and the hundred fits its column. */
  .board .turned .screen{padding:8px;max-width:100%}
  .board .turned .cell{min-width:0;overflow:hidden;font-size:9px}
  .board .tbl .held{font-size:9.5px;margin-top:1px}
  .board .tbl .nm{line-height:1.25}
}
@media (max-width:1099px){
  .boardcols{display:flex;flex-direction:column;gap:18px}
}

/* ===== the locked-in panel ===== */
.settleline{margin-top:12px}
.sharelede{margin-top:16px}
/* It sat straight under the range note with nothing between them, so two
   unrelated thoughts read as one paragraph. */
.grouplede{margin-top:16px;padding-top:14px;border-top:1px solid var(--rule)}
.donecta{margin-top:12px}
.livetbl{margin-top:14px}
#live .punch,#range .punch{margin-top:12px}
#live{margin-top:0}

/* ===== NO SCROLLING ON DESKTOP =====
   Dallin, 2026-08-24: "wherever there is scrolling on desktop needs to be
   better. If there are ways to contain it without scrolling please always do
   it." Measured at 1440x812 before: the FIRE stage overflowed by 273px, the
   cut by 828 and step three by 1792. Every number below was cut to a budget,
   not chosen.

   The two rules that make it work:
   1. The board is sized off the VIEWPORT HEIGHT, and everything above and
      below it is a fixed, known cost. --board is 100vh minus that cost.
   2. The rail takes ALL the leftover width, so a ten-row list can be two
      columns instead of ten rows. That is what kept the cut on one screen.

   Below 700px tall the budget stops being achievable and the page scrolls
   like anything else, which is the honest failure mode. */
@media (min-width:901px){
  /* 26px of band gap plus 64px of tail is 90px of nothing on every page. */
  .bh-band + .wrap{padding-top:16px}
  .wrap{padding-bottom:20px}
  .wrap.play{padding-top:14px;padding-bottom:18px}
  /* the group wizard, same budget */
  .setup-steps{margin-bottom:14px}
  .setup-steps button{padding:7px 6px 6px}
  .step{padding:16px 18px 18px}
  .field{margin-top:13px}
  .console{grid-template-columns:minmax(0,auto) minmax(330px,1fr);gap:20px;
    /* 487, not 475: the readout can take a second line on a long company name
       and a webfont swap reflows the bar. 12px of slack is cheaper than a
       scrollbar that appears only sometimes. */
    /* 20px of slack on purpose: a webfont swap reflows the rail and the
       measurements flap by up to 30px at the exact boundary. */
    /* THE BOARD IS OFF THE HEIGHT BUDGET. Dallin, 2026-08-25: "also it can
       scroll, just want to keep things a bit more compact." That settles the
       trade-off this file has been carrying since Aug 24: a square grid sized
       by 100vh minus a fixed chrome cost is 230px on a 1366x768 laptop, which
       is most laptops, and no amount of column width can help because height
       always loses. Sized by the space it actually has now, with a floor that
       keeps a ticker legible and a cap that keeps the rail above its 330px
       minimum on the narrowest desktop this tier covers. */
    --board:clamp(300px,40vw,600px)}

  /* chrome, trimmed to a budget */
  .brandbar{padding-top:11px;padding-bottom:7px}
  .bh-band.is-slim{--bh:clamp(104px,9.4vw,124px)}
  /* Small box, top left. It was a full-width instrument 96px tall; it is the
     deadline, not the game. width:fit-content plus a ceiling on the note is
     what stops it stretching back into a strip. */
  .status{margin-bottom:12px;display:grid;grid-template-columns:auto minmax(0,1fr);
    column-gap:18px;align-items:center;padding:7px 14px 8px;width:fit-content;max-width:100%}
  .status .clock{display:contents}
  .status .clock-face{grid-column:1;grid-row:1/3;align-self:center}
  .status .weekbar{grid-column:2;grid-row:1;padding:0;gap:3px 14px}
  .status .clock-note{grid-column:2;grid-row:2;font-size:12.5px;max-width:44ch;margin-top:1px}
  .status .clock-time{font-size:clamp(22px,2.1vw,28px);margin:0}
  .console .bar{margin:0 0 8px}
  .console .bar .sub{font-size:14px}
  .console .readout{margin-top:7px;min-height:36px;padding:8px 12px}

  /* A wide rail is the whole trick: ten of anything fits in two columns. */
  .console{align-items:stretch}
  .playrail{height:100%}
  #yourten{flex:1}
  /* Three columns was a way of buying HEIGHT back when the page could not
     scroll. It cost about twenty characters a line, which is a column of
     ragged two-word rows. The page scrolls now, so the steps read across the
     rail one under another: "I need things to be read easily." */
  .playrail .steps{grid-template-columns:minmax(0,1fr);gap:14px}
  .playrail .steps span{font-size:15px;line-height:1.5;max-width:62ch}
  .howto{padding:12px 15px 14px}
  #yourten ol{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 20px}
  #yourten{padding:11px 15px 13px}
  .playrail .picks{grid-template-columns:repeat(2,minmax(0,1fr));margin:12px 0 10px}
  .playrail .stage{padding:13px 15px 15px}
  .playrail .stage p.lede{font-size:13px;line-height:1.45;max-width:none}
  .playrail .stage h3{font-size:clamp(18px,2.1vw,21px);margin-bottom:6px}
  .side.kept{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 20px;margin-top:9px}
  .playrail .lockform{flex-direction:row;flex-wrap:wrap;align-items:flex-end;gap:9px;margin-top:10px}
  .playrail .lockform .field{flex:1 1 190px}
  .playrail .lockform .field:has(.email){flex:1.6 1 210px}
  .playrail .lockform .btn{align-self:flex-end}
  .playrail .terms{font-size:12px;line-height:1.4;padding:8px 11px;margin-top:8px}

  /* What you locked, what it could do, and what to do next are three reads.
     Two of them fit beside the first instead of under it. */
  .donecols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    column-gap:clamp(20px,2.4vw,32px);align-items:start}
  #stage-done{padding:13px 17px 15px}
  #stage-done h3{font-size:clamp(20px,2.4vw,26px)}
  #stage-done .lede{font-size:13.5px;max-width:none}
  #stage-done .side.kept{grid-template-columns:repeat(2,minmax(0,1fr))}
  #stage-done .scorebox b{font-size:23px}
  #stage-done .punch{font-size:13px}
  #stage-done .livetbl table{font-size:12.5px}
  /* Ten rows have to fit a screen, so every row is measured: 8px of padding
     and a 13.5px name is 66px a row, which is 660px of list. This is 40. */
  .pick{padding:6px 10px;gap:9px}
  .pick .tick{min-width:42px;font-size:13.5px}
  .pick .who b{font-size:12.5px;line-height:1.2}
  .pick .who span{font-size:9px}
  .pick .mark{font-size:9px;padding:2px 0;gap:5px}
  .pick .mark .box{width:9px;height:9px}
  .research{padding:0 9px;font-size:8.5px}
  /* The count and the button were two stacked rows saying one thing. */
  .stagefoot{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap}
  .playrail .tally{font-size:11px;margin:0}
  .playrail .tally b{font-size:20px}
  .playrail .btn{padding:10px 18px;font-size:12px}
  .playrail .side.kept li{padding:5px 0;font-size:12.5px}
  .playrail .backline{margin-top:7px;font-size:12.5px}
}

/* A 1366x768 laptop is not a rounding error, it is most of them. Everything
   here is the same layout with the chrome squeezed by a measured 63px, which
   is what the cut needed to stay on one screen at that height. */
@media (min-width:901px) and (max-height:860px){
  .brandbar{padding-top:9px;padding-bottom:6px}
  .brandbar .fr-logo{width:clamp(112px,12vw,132px)}
  .bh-band.is-slim{--bh:clamp(92px,12.4vh,112px)}
  .status{padding:7px 15px 8px;margin-bottom:11px}
  .status .clock-time{font-size:clamp(21px,2.8vh,26px)}
  .status .clock-note{font-size:12.5px}
  .status .weekbar .wk,.status .weekbar .meta{font-size:10.5px}
  .wrap.play{padding-top:11px;padding-bottom:14px}
  .playrail .stage{padding:11px 13px 13px}
  .playrail .stage p.lede{font-size:12px;line-height:1.4}
  .playrail .stage h3{font-size:19px}
  .pick{padding:5px 10px}
  .playrail .terms{font-size:11.5px;padding:7px 10px;margin-top:7px}
  #stage-done{padding:11px 15px 13px}
  #stage-done .scorebox b{font-size:20px}
  #stage-done .lede{font-size:12.5px}
  footer.foot.tight{margin-top:10px;padding-top:7px}
  footer.foot.tight p{font-size:10.5px;line-height:1.38}
  /* the leaderboard and the wizard, same budget */
  .boardhero h1{font-size:clamp(22px,2.4vw,27px)}
  .board .stage,.board .record{padding:11px 13px 12px}
  .board .tbl td{padding:3px 12px}
  .board .punch{font-size:12.5px}
  .board .rec-nums b{font-size:19px}
  .board .rec-note{font-size:11.5px;margin-top:8px}
  .colnote{font-size:11px;margin-top:6px}
  .setup-steps{margin-bottom:11px}
  .setup-steps button{padding:6px 6px 5px}
  .field{margin-top:11px}
  .stage p.lede{font-size:14px}
  .step{padding:12px 15px 14px}
  .step h2{font-size:clamp(19px,2.4vw,24px);margin-bottom:7px}
  .step .lede{font-size:13.5px;line-height:1.42}
  .suggests{margin-top:8px}
  .suggests button{padding:6px 10px;font-size:12.5px}

  .field input{font-size:15px;padding:10px 12px}
  .field > span{margin-bottom:4px}
  /* 12 more pixels of slack for the board: at this height the rail is what
     drives the console and the board can afford it. */
  /* a short viewport no longer squeezes the board: the page may scroll. */
  .console{--board:clamp(300px,40vw,600px)}
  .setup-steps button b{font-size:13px}
  .setup-steps button span{font-size:9px}
  .wrap{padding-bottom:14px}
  .board .tbl h3{padding:6px 12px}
  .board .key{margin-top:6px}
  .board .readout{min-height:28px;margin-top:6px}
  .colhead{margin-bottom:7px}
  .colhead span{font-size:11.5px}
}

/* The small print is small print. Two paragraphs and a rule cost 129px of a
   812px screen to say what one block of 12px says. */
footer.foot.tight{margin-top:13px;padding-top:9px;gap:0}
footer.foot.tight p{font-size:11px;line-height:1.42;max-width:none;color:var(--ink-faint)}
.backline{margin-top:10px}
.stagefoot{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-top:4px}

/* ===== the FR site bar: verbatim contract with learn.../courses ===== */
.sitebar{--tan:#EFEAD4;--black:#2D2D2D;--cream:#FAF7E9;--orange:#E4481A;
  position:sticky;top:0;z-index:50;background:#EFEAD4;border-bottom:3px solid #2D2D2D;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:17px 26px;}
.sitebar .sb-logo{display:block;line-height:0;color:#2D2D2D}
.sitebar .sb-logo .fr-logo{height:36px;width:auto;display:block;color:#2D2D2D}
.sitebar .sb-nav{display:flex;align-items:center;gap:28px;}
.sitebar .sb-nav a{text-decoration:none;color:#2D2D2D;font-family:"DM Sans",system-ui,sans-serif;font-weight:600;font-size:16px;}
.sitebar .sb-nav a:hover{color:#E4481A;}
@media (max-width:560px){html,body{overflow-x:clip;max-width:100%}.sitebar{flex-wrap:wrap;gap:10px 14px;padding:12px 16px}.sitebar .sb-nav{gap:15px}.sitebar .sb-nav a{font-size:14px}}
/* The site bar is sticky and 73px tall, so anything else sticky starts below it. */
.boardcol{top:88px}
.rail{top:90px}

/* Battleship's own three pages, a small row under the band. */
.gamenav{display:flex;justify-content:center;flex-wrap:wrap;gap:6px 26px;margin:12px auto 18px;padding:0 16px;
  font-family:var(--display);font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase}
.gamenav a{color:var(--ink-muted);text-decoration:none;border-bottom:2px solid transparent;padding-bottom:3px}
.gamenav a:hover{color:var(--accent-text);border-bottom-color:var(--accent-text)}
.gamenav .here{color:var(--ink);border-bottom:2px solid var(--orange);padding-bottom:3px}

/* ===== the how-to-play video popup ===== */
.introbtn{margin-left:10px;display:inline-flex;align-items:center;gap:7px;border:2px solid var(--ink);background:var(--panel);
  color:var(--ink);font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;padding:4px 10px 4px 8px;cursor:pointer;
  box-shadow:2px 2px 0 var(--orange);vertical-align:middle}
.introbtn:hover{background:var(--rule-soft)}
.introbtn i{width:0;height:0;border-left:8px solid var(--orange);border-top:5px solid transparent;border-bottom:5px solid transparent}
.intro{position:fixed;inset:0;z-index:9000;display:grid;place-items:center;padding:16px;background:rgba(23,22,20,.78);
  animation:fx-fadein .2s ease-out both}
.intro[hidden]{display:none}
body.intro-open{overflow:hidden}
.intro-panel{position:relative;width:min(980px,100%);max-height:calc(100vh - 32px);overflow:auto;background:var(--panel);
  border:3px solid #2D2D2D;box-shadow:8px 8px 0 var(--orange);padding:18px 20px 16px}
.intro-panel .kick{margin-bottom:2px}
.intro-panel h3{font-size:clamp(20px,2.4vw,28px);margin:0 36px 12px 0}
.intro-video{position:relative;background:#171614;border:2px solid #2D2D2D;line-height:0}
.intro-sound{position:absolute;top:12px;right:12px;display:inline-flex;align-items:center;gap:8px;border:2px solid #2D2D2D;
  background:#E4481A;color:#FAF7E9;font-family:var(--display);font-weight:800;font-size:13px;letter-spacing:.1em;text-transform:uppercase;
  padding:9px 14px;cursor:pointer;box-shadow:3px 3px 0 #2D2D2D;line-height:1;animation:fx-ready 1.6s ease-in-out infinite}
.intro-sound[hidden]{display:none}
.intro-sound svg{flex:none}
.intro-video video{width:100%;height:auto;aspect-ratio:16/10;display:block;background:#171614}
.intro-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 18px;margin-top:14px}
.intro-note{margin:0;font-size:14.5px;color:var(--ink-muted);flex:1 1 320px}
.intro-go.is-ready,#intro-go.is-ready{animation:fx-ready 1.6s ease-in-out infinite}
.intro-x{position:absolute;top:8px;right:10px;border:0;background:none;font-size:30px;line-height:1;color:var(--ink-faint);cursor:pointer;padding:2px 8px}
.intro-x:hover{color:var(--ink)}
@media (max-width:560px){ .intro-panel{padding:14px 14px 12px} .intro-foot .btn{width:100%} }

/* ===== last week, on the play page ===== */
.lastweek{position:relative;display:flex;flex-wrap:wrap;align-items:center;gap:12px 24px;border:2px solid var(--ink);
  background:var(--panel);padding:14px 44px 14px 18px;margin:0 0 14px;box-shadow:4px 4px 0 var(--orange)}
.lastweek .lw-main{flex:1 1 360px;min-width:0}
.lastweek .kick{margin-bottom:4px}
.lastweek h3{font-size:clamp(18px,2vw,22px);line-height:1.15;margin:0 0 4px}
.lastweek .lw-line{margin:0;font-size:14.5px;color:var(--ink-muted)}
.lastweek .lw-line b{font-family:var(--display);font-weight:800;color:var(--ink)}
.lastweek .lw-line b.pos{color:var(--pos)} .lastweek .lw-line b.neg{color:var(--neg)}
.lastweek .lw-actions{display:flex;gap:8px;flex-wrap:wrap}
.lastweek .lw-actions .btn{padding:10px 16px;font-size:12px}
.lastweek .lw-x{position:absolute;top:6px;right:8px;border:0;background:none;font-size:22px;line-height:1;color:var(--ink-faint);cursor:pointer;padding:4px 6px}
.lastweek .lw-x:hover{color:var(--ink)}
.sharerow{margin:12px 0 0}
.sharerow .btn{padding:9px 16px;font-size:12px}

/* The Interactive link is a desktop extra. On a phone it wrapped the nav onto a
   second line. */
@media (max-width:560px){ .topnav .more{display:none} }

/* ===== the small clock on the between-rounds panel ===== */
.closedclock{display:inline-flex;align-items:baseline;gap:10px;margin:2px 0 16px;padding:7px 14px;
  background:var(--screen);color:var(--screen-ink);border:2px solid var(--screen-edge)}
.closedclock span{font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--mustard)}
.closedclock b{font-family:var(--display);font-weight:800;font-size:18px;font-variant-numeric:tabular-nums}

/* ===== the pick rows, compact =====
   In the two-column rail the name column was about 0px wide, so JPMorgan read
   "J". Ticker and KEEP share the top line, the name runs full width under it
   in small type, and hovering a row shows the full name and sector. */
.playrail .picks .pick{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"tick mark" "who who";
  row-gap:1px;column-gap:8px;align-items:center}
.playrail .picks .pick .tick{grid-area:tick;min-width:0}
.playrail .picks .pick .mark{grid-area:mark}
.playrail .picks .pick .who{grid-area:who;min-width:0}
.playrail .picks .pick .who b{font-size:12px;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.playrail .picks .pick .who span{display:none}

/* ===== where your five count (locked screen) =====
   The rows arrive with motion, but that is decoration on a resting state that
   is fully visible: the reduced-motion rule leaves a plain list. */
.counts{margin:14px 0 4px}
.counts .kick{margin-bottom:8px}
.countlist{list-style:none;margin:0;padding:0;border:2px solid var(--ink);background:var(--panel)}
.countlist li{position:relative;display:grid;grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:12px;padding:10px 14px;border-bottom:1px solid var(--rule-soft);
  animation:fx-in .45s cubic-bezier(.2,.9,.3,1.1) calc(.9s + var(--i,0) * .15s) both}
.countlist li:last-child{border-bottom:0}
.countlist .tick{width:22px;height:22px;border-radius:50%;background:var(--pos);position:relative}
.countlist .tick::after{content:"";position:absolute;left:7.5px;top:4px;width:5px;height:10px;border:solid var(--panel);border-width:0 2.2px 2.2px 0;transform:rotate(45deg)}
.countlist li.on .tick{animation:fx-pop .5s cubic-bezier(.2,1.6,.4,1) calc(1.05s + var(--i,0) * .15s) both}
.countlist li.off .tick{background:transparent;border:2px dashed var(--ink-faint)}
.countlist li.off .tick::after{display:none}
.countlist .what{min-width:0}
.countlist .what b{display:block;font-family:var(--display);font-weight:800;font-size:15px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.countlist .what em{display:block;font-style:normal;font-size:13px;color:var(--ink-muted);line-height:1.35}
.countlist li.off .what b{color:var(--ink-muted)}
.countlist .go{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent-text);text-decoration:none;white-space:nowrap}
.countlist .go:hover{text-decoration:underline}
.countlist .sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ===== motion (fx-) — driven by src/fx.js =====
   Dallin, 2026-09-23: "make it look cooler... animations of when they pick the
   stocks... things to make it pop." Every class here is added and removed by
   fx.js. None of them changes a resting state: take every fx- class off the
   page and it looks exactly as it did before, which is also what the global
   reduced-motion rule leaves behind. */

.screen{position:relative}
.fx-layer{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:3}
.fx-layer i,.fx-layer div{pointer-events:none}

/* An unfired tile answers the cursor like a target in the sights. */
.console .cell:not(.done):hover{box-shadow:inset 0 0 0 1px var(--mustard),0 0 14px rgba(231,179,77,.35)}

/* ---- boot: the board comes up from the centre, like the header's radar ---- */
.screen.fx-boot .cell{animation:fx-boot .5s cubic-bezier(.2,.9,.3,1.2) var(--fx-d,0ms) both}
@keyframes fx-boot{from{opacity:0;transform:scale(.4);background:rgba(131,182,182,.55);border-color:#83B6B6}
  60%{opacity:1;background:rgba(131,182,182,.25)}to{opacity:1;transform:none}}

/* A slow sonar sweep turning over the board while there is still something to
   fire at. It goes when the ten are spent. */
.fx-sweep{position:absolute;left:50%;top:50%;width:150%;aspect-ratio:1;translate:-50% -50%;border-radius:50%;
  background:conic-gradient(from 0deg,transparent 0 300deg,rgba(131,182,182,.05) 320deg,rgba(131,182,182,.22) 358deg,transparent 360deg);
  animation:fx-spin 6s linear infinite;mix-blend-mode:screen;transition:opacity .8s}
.fx-sweep.is-off,.screen.spent .fx-sweep{opacity:0}
@keyframes fx-spin{to{rotate:360deg}}

/* ---- the shot ---- */
.fx-aim{position:absolute;width:var(--s);height:var(--s);translate:-50% -50%;
  --b:2px solid #E4481A;
  background:
    linear-gradient(#E4481A,#E4481A) left top/10px 2px no-repeat,linear-gradient(#E4481A,#E4481A) left top/2px 10px no-repeat,
    linear-gradient(#E4481A,#E4481A) right top/10px 2px no-repeat,linear-gradient(#E4481A,#E4481A) right top/2px 10px no-repeat,
    linear-gradient(#E4481A,#E4481A) left bottom/10px 2px no-repeat,linear-gradient(#E4481A,#E4481A) left bottom/2px 10px no-repeat,
    linear-gradient(#E4481A,#E4481A) right bottom/10px 2px no-repeat,linear-gradient(#E4481A,#E4481A) right bottom/2px 10px no-repeat;
  animation:fx-aim .28s cubic-bezier(.3,1.4,.5,1) both}
@keyframes fx-aim{from{scale:2.4;opacity:0;rotate:45deg}to{scale:1.25;opacity:1;rotate:0deg}}

.fx-flash{position:absolute;width:var(--s);height:var(--s);translate:-50% -50%;border-radius:50%;
  background:radial-gradient(circle,#FFF8DC 0,rgba(231,179,77,.85) 35%,transparent 70%);animation:fx-flash .42s ease-out both}
@keyframes fx-flash{from{scale:.6;opacity:1}to{scale:3.2;opacity:0}}

.fx-ring{position:absolute;width:var(--s);height:var(--s);translate:-50% -50%;border-radius:50%;
  border:3px solid #E7B34D;animation:fx-ring .7s cubic-bezier(.1,.7,.3,1) both}
.fx-ring.is-keep{border-color:#E4481A;border-width:4px}
@keyframes fx-ring{from{scale:.5;opacity:1}to{scale:4.2;opacity:0;border-width:1px}}

.fx-spark{position:absolute;width:7px;height:7px;margin:-3.5px 0 0 -3.5px;border-radius:1px;background:var(--c);
  box-shadow:0 0 6px var(--c);animation:fx-spark .6s cubic-bezier(.1,.8,.3,1) both}
@keyframes fx-spark{from{transform:translate(0,0) scale(1.3)}to{transform:translate(var(--dx),var(--dy)) scale(0);opacity:.2}}

/* The tile flips to show what was under it, landing hot and cooling. */
.cell.fx-reveal{animation:fx-reveal .62s cubic-bezier(.2,.9,.3,1.25) both;z-index:4;position:relative}
@keyframes fx-reveal{
  0%{transform:perspective(300px) rotateX(-90deg) scale(1.3);background:#FFF8DC;color:transparent}
  45%{transform:perspective(300px) rotateX(12deg) scale(1.22);background:#FFE7A8;box-shadow:0 0 22px 6px rgba(231,179,77,.8)}
  100%{transform:none;box-shadow:0 0 0 0 rgba(231,179,77,0)}}

.cell.fx-ripple{animation:fx-ripple .55s ease-out var(--fx-rd,0ms) both}
@keyframes fx-ripple{0%{}35%{border-color:#83B6B6;background:rgba(131,182,182,.22);transform:scale(.9)}100%{}}

.screen.fx-shake{animation:fx-shake .32s cubic-bezier(.3,.7,.4,1)}
@keyframes fx-shake{0%{translate:0 0}20%{translate:-3px 2px}40%{translate:3px -2px}60%{translate:-2px 1px}80%{translate:1px -1px}100%{translate:0 0}}

/* ---- the counter, the readout, your ten ---- */
.fx-tick{display:inline-block;animation:fx-tick .45s cubic-bezier(.2,1.5,.4,1)}
.counter b.fx-tick{display:block}
@keyframes fx-tick{0%{transform:translateY(-35%) scale(1.35);color:#E4481A}100%{transform:none}}
.counter.fx-low b{color:var(--accent-text);animation:fx-hot 1.1s ease-in-out infinite}
@keyframes fx-hot{50%{text-shadow:0 0 14px rgba(228,72,26,.55)}}

.readout.fx-read{animation:fx-read .5s ease-out}
.readout.fx-read b{animation:fx-type .45s steps(6,end) both}
@keyframes fx-read{0%{border-color:#E7B34D;box-shadow:0 0 0 3px rgba(231,179,77,.35)}100%{}}
@keyframes fx-type{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}

#log li.fx-new{animation:fx-slide .45s cubic-bezier(.2,.9,.3,1.2) both}
@keyframes fx-slide{from{opacity:0;transform:translateX(-18px);background:rgba(231,179,77,.45)}to{opacity:1;transform:none}}

/* ---- ten fired ---- */
.screen.spent.fx-spent .cell:not(.hit){animation:fx-dim .6s ease-out var(--fx-d,0ms) both}
@keyframes fx-dim{from{opacity:1}to{opacity:.55}}
.screen.fx-spent .cell.hit:not(.kept):not(.dropped){animation:fx-glow 2.4s ease-in-out infinite}
@keyframes fx-glow{50%{box-shadow:0 0 12px 2px rgba(231,179,77,.55)}}

.fx-banner{position:absolute;left:0;right:0;top:50%;translate:0 -50%;padding:14px 10px;text-align:center;
  background:linear-gradient(90deg,transparent,rgba(23,22,20,.94) 12%,rgba(23,22,20,.94) 88%,transparent);
  border-top:2px solid #E4481A;border-bottom:2px solid #E4481A;animation:fx-banner 2s cubic-bezier(.2,.9,.3,1) both}
.fx-banner b{display:block;font-family:"Saira Condensed",var(--display);font-weight:900;text-transform:uppercase;
  font-size:clamp(28px,calc(var(--board,400px) / 9),64px);line-height:1;letter-spacing:.02em;color:#FAF7E9}
.fx-banner span{display:block;margin-top:6px;font-family:var(--mono);font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:#E7B34D}
@keyframes fx-banner{0%{clip-path:inset(0 50% 0 50%);opacity:1}18%{clip-path:inset(0 0 0 0)}80%{clip-path:inset(0 0 0 0);opacity:1}100%{clip-path:inset(0 0 0 0);opacity:0;translate:0 -70%}}

/* ---- keeping five ---- */
.pickrow.fx-kept{animation:fx-kept .42s cubic-bezier(.2,1.4,.4,1)}
@keyframes fx-kept{0%{transform:scale(.97)}50%{transform:scale(1.025);box-shadow:0 0 0 3px rgba(228,72,26,.3)}100%{transform:none}}
.pickrow.fx-unkept{animation:fx-unkept .3s ease-out}
@keyframes fx-unkept{40%{transform:translateX(-5px)}75%{transform:translateX(3px)}}
.pick[aria-pressed="true"] .mark .box::after{animation:fx-check .3s cubic-bezier(.2,1.5,.4,1) both}
@keyframes fx-check{from{scale:0}to{scale:1}}

.cell.fx-keep{animation:fx-keep .6s cubic-bezier(.2,1.5,.4,1);z-index:4;position:relative}
@keyframes fx-keep{0%{transform:scale(.8)}45%{transform:scale(1.28);box-shadow:0 0 20px 6px rgba(228,72,26,.7)}100%{transform:none}}
.cell.fx-drop{animation:fx-drop .5s ease-out}
@keyframes fx-drop{0%{transform:scale(1.05)}40%{transform:scale(.82) rotate(-4deg)}100%{transform:none}}

.tally b.fx-tick{display:inline-block}
.tally.fx-full b{color:var(--accent-text)}
.stagefoot .btn:not([disabled]){animation:fx-ready 1.6s ease-in-out infinite}
@keyframes fx-ready{0%,100%{box-shadow:0 0 0 0 rgba(228,72,26,.55)}60%{box-shadow:0 0 0 9px rgba(228,72,26,0)}}

/* ---- locked in ---- */
.fx-lock{position:fixed;inset:0;z-index:9999;pointer-events:none;overflow:hidden;display:grid;place-items:center;
  background:radial-gradient(ellipse at 50% 45%,rgba(23,22,20,.78),rgba(23,22,20,.55) 60%,rgba(23,22,20,.3));
  animation:fx-fadein .2s ease-out both;transition:opacity .6s}
.fx-lock.is-out{opacity:0}
@keyframes fx-fadein{from{opacity:0}}
.fx-lock-ring{position:absolute;left:50%;top:42%;width:120px;aspect-ratio:1;translate:-50% -50%;border-radius:50%;
  border:3px solid #83B6B6;animation:fx-lockring 1.4s cubic-bezier(.1,.7,.3,1) .18s both}
.fx-lock-ring.is-2{border-color:#E4481A;animation-delay:.36s}
@keyframes fx-lockring{from{scale:.2;opacity:1}to{scale:9;opacity:0}}
.fx-stamp{position:relative;text-align:center;translate:0 -6vh}
.fx-stamp b{display:block;font-family:"Saira Condensed",var(--display);font-weight:900;text-transform:uppercase;
  font-size:clamp(64px,13vw,168px);line-height:.9;color:#E4481A;letter-spacing:.01em;
  -webkit-text-stroke:2px #FAF7E9;text-shadow:0 6px 0 rgba(0,0,0,.35),0 0 40px rgba(228,72,26,.5);
  animation:fx-stamp .5s cubic-bezier(.3,1.6,.5,1) both}
@keyframes fx-stamp{0%{transform:scale(3.2) rotate(-14deg);opacity:0;filter:blur(6px)}70%{transform:scale(.94) rotate(-5deg);opacity:1;filter:none}100%{transform:rotate(-5deg)}}
.fx-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:22px;padding:0 16px}
.fx-chips span{font-family:var(--display);font-weight:800;font-size:clamp(15px,2vw,20px);letter-spacing:.04em;
  color:#2D2D2D;background:#E7B34D;padding:6px 14px;border:2px solid #FAF7E9;box-shadow:0 4px 0 rgba(0,0,0,.3);
  animation:fx-chip .5s cubic-bezier(.2,1.5,.4,1) calc(.45s + var(--i) * .09s) both}
@keyframes fx-chip{from{transform:translateY(60px) scale(.5);opacity:0}to{transform:none;opacity:1}}
.fx-confetti{position:absolute;width:9px;height:14px;background:var(--c);border-radius:1px;
  animation-name:fx-confetti;animation-timing-function:cubic-bezier(.15,.6,.4,1);animation-fill-mode:both}
.fx-confetti.is-round{width:9px;height:9px;border-radius:50%}
@keyframes fx-confetti{
  0%{transform:translate(0,0) rotate(0deg) scale(.4);opacity:1}
  35%{transform:translate(var(--dx),var(--dy)) rotate(calc(var(--r) * .4)) scale(1);opacity:1}
  100%{transform:translate(calc(var(--dx) * 1.2),calc(var(--dy) + var(--fall))) rotate(var(--r)) scale(1);opacity:0}}

.fx-dest{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:8px 14px;margin-top:18px;padding:0 16px;min-height:28px}
.fx-dest em{font-style:normal;font-family:var(--mono);font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:#E7B34D;animation:fx-in .3s ease-out both}
.fx-dest span{display:inline-flex;align-items:center;gap:7px;font-family:var(--display);font-weight:800;font-size:clamp(14px,1.6vw,18px);
  color:#FAF7E9;letter-spacing:.03em;animation:fx-chip .45s cubic-bezier(.2,1.5,.4,1) calc(.15s + var(--i) * .18s) both}
.fx-dest span i{width:18px;height:18px;border-radius:50%;background:#1F7A5A;position:relative;flex-shrink:0}
.fx-dest span i::after{content:"";position:absolute;left:6px;top:3px;width:4px;height:8px;border:solid #FAF7E9;border-width:0 2px 2px 0;transform:rotate(45deg)}

/* ---- arriving lists and numbers ---- */
.fx-in{animation:fx-in .45s cubic-bezier(.2,.9,.3,1.1) calc(var(--fx-i,0) * var(--fx-step,60ms)) both}
@keyframes fx-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.fx-pop{display:inline-block;animation:fx-pop .55s cubic-bezier(.2,1.6,.4,1) calc(.15s + var(--fx-i,0) * .1s) both}
.scorebox b.fx-pop{display:block}
@keyframes fx-pop{from{transform:scale(.3);opacity:0}to{transform:none;opacity:1}}
.streak b.fx-pop{display:inline-block}

/* ---- the leaderboard: the board literally turns over ---- */
.turned .cell.fx-turn{animation:fx-turn .6s cubic-bezier(.3,1.3,.5,1) var(--fx-d,0ms) both}
.turned .cell.fx-turn.t-mega{animation:fx-turn .6s cubic-bezier(.3,1.3,.5,1) var(--fx-d,0ms) both,fx-glint 1.6s ease-in-out calc(var(--fx-d,0ms) + .7s) 2}
@keyframes fx-turn{from{transform:perspective(300px) rotateY(180deg);background:var(--screen-2);color:transparent;border-color:var(--screen-rule)}
  50%{transform:perspective(300px) rotateY(90deg);background:var(--screen-2);color:transparent;border-color:var(--screen-rule)}to{transform:none}}
@keyframes fx-glint{50%{box-shadow:0 0 16px 4px rgba(231,179,77,.8)}}
.tbl tr.fx-in{animation-duration:.4s}

/* ===== battleship header (bh-) — generated, see src/header.html ===== */
.bh-band{--bh:250px;
  --bh-ground:var(--canvas);
  --bh-line:color-mix(in srgb,var(--ink) 20%,transparent);
  --bh-sweep:var(--orange);
  --bh-blip:var(--neg);
  --bh-ink:var(--ink);
  --bh-mut:var(--ink-muted);
  --bh-vig:color-mix(in srgb,var(--ink) 13%,transparent);
  position:relative;height:var(--bh);overflow:hidden;isolation:isolate;
  background:var(--bh-ground);color:var(--bh-ink)}

/* dark page: sonar. Both states are declared so the un-stamped system default
   resolves too, not just an explicit toggle. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .bh-band{
    --bh-line:color-mix(in srgb,var(--teal) 26%,transparent);
    --bh-sweep:var(--teal);
    --bh-blip:var(--teal);
    --bh-mut:var(--teal);
    --bh-vig:rgba(0,0,0,.42);
  }
}
:root[data-theme="dark"] .bh-band{
  --bh-line:color-mix(in srgb,var(--teal) 26%,transparent);
  --bh-sweep:var(--teal);
  --bh-blip:var(--teal);
  --bh-mut:var(--teal);
  --bh-vig:rgba(0,0,0,.42);
}

.bh-sprite{position:absolute;width:0;height:0;overflow:hidden}

/* the grid and the arm fade out behind the type instead of cutting through it */
.bh-grid{position:absolute;inset:0;
  -webkit-mask-image:radial-gradient(55% 96% at 50% 50%,transparent 0%,rgba(0,0,0,.18) 54%,#000 96%);
  mask-image:radial-gradient(55% 96% at 50% 50%,transparent 0%,rgba(0,0,0,.18) 54%,#000 96%)}
.bh-rings{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);height:420%;aspect-ratio:1;border-radius:50%;
  background:repeating-radial-gradient(circle,transparent 0 9%,var(--bh-line) 9% calc(9% + 1.5px))}
.bh-cross{position:absolute;inset:0;background:
  linear-gradient(90deg,transparent calc(50% - .75px),var(--bh-line) 50%,transparent calc(50% + .75px)),
  linear-gradient(0deg,transparent calc(50% - .75px),var(--bh-line) 50%,transparent calc(50% + .75px))}
.bh-sweep{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);height:420%;aspect-ratio:1;border-radius:50%;
  background:conic-gradient(from 0deg,
    color-mix(in srgb,var(--bh-sweep) 26%,transparent) 0deg,
    color-mix(in srgb,var(--bh-sweep) 13%,transparent) 15deg,
    color-mix(in srgb,var(--bh-sweep) 5%,transparent) 36deg,
    transparent 66deg,transparent 360deg);
  animation:bh-spin 5s linear infinite}
@keyframes bh-spin{from{transform:translate(-50%,-50%) rotate(0deg)}to{transform:translate(-50%,-50%) rotate(360deg)}}
.bh-arm{position:absolute;left:50%;top:50%;height:2px;width:75%;transform-origin:0 50%;
  background:linear-gradient(90deg,var(--bh-sweep),color-mix(in srgb,var(--bh-sweep) 0%,transparent));
  animation:bh-arm 5s linear infinite}
@keyframes bh-arm{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}

/* --d is written by the script from each element's real angle off centre, and the
   delay is NEGATIVE so everything is already mid-sweep on load. A positive delay
   holds an element at its base style for its whole first cycle, which read as
   "the contact never appears". */
.bh-blip{position:absolute;z-index:4;width:clamp(5px,.65vw,8px);aspect-ratio:1;border-radius:50%;
  background:var(--bh-blip);opacity:0;transform:translate(-50%,-50%);
  animation:bh-blip 5s linear calc(var(--d,0s) - 5s) infinite}
@keyframes bh-blip{0%{opacity:1;box-shadow:0 0 13px 3px color-mix(in srgb,var(--bh-blip) 60%,transparent)}
  5%{opacity:1}55%{opacity:.5;box-shadow:none}100%{opacity:.32;box-shadow:none}}
.bh-tag{position:absolute;z-index:4;font-family:var(--mono);font-size:clamp(9.5px,.9vw,12px);letter-spacing:.1em;
  color:var(--bh-blip);opacity:0;white-space:nowrap;transform:translateY(-50%);margin-left:11px;
  animation:bh-tag 5s linear calc(var(--d,0s) - 5s) infinite}
.bh-tag.bh-flip{transform:translate(-100%,-50%);margin-left:-11px}
@keyframes bh-tag{0%{opacity:1}45%{opacity:.68}100%{opacity:.38}}
.bh-contact{position:absolute;z-index:3;height:auto;color:var(--bh-sweep);opacity:0;transform:translate(-50%,-50%);
  animation:bh-contact 5s linear calc(var(--d,0s) - 5s) infinite}
.bh-contact.bh-a{left:16%;top:75%;width:19%;min-width:104px}
.bh-contact.bh-b{left:84%;top:26%;width:16%;min-width:92px;transform:translate(-50%,-50%) scaleX(-1)}
.bh-contact svg{display:block;width:100%;height:auto}
@keyframes bh-contact{0%{opacity:.66}35%{opacity:.4}100%{opacity:.26}}

.bh-core{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:5;
  width:min(68%,720px);height:175%;pointer-events:none;
  background:radial-gradient(closest-side,color-mix(in srgb,var(--bh-ground) 88%,transparent) 30%,color-mix(in srgb,var(--bh-ground) 45%,transparent) 62%,transparent 100%)}

.bh-mid{position:absolute;inset:0;z-index:6;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(6px,calc(var(--bh) * 0.05),20px);text-align:center;padding:0 14px}
/* 1.965 is 72% of the band divided by the block's own aspect, so the lockup can
   never outgrow a short band. Recompute it if the face changes. */
.bh-lock{--lw:min(clamp(240px,40vw,600px),calc(var(--bh) * 1.965));
  width:var(--lw);display:flex;flex-direction:column;color:var(--bh-ink)}
.bh-lock .bh-lockup{display:block;width:100%;height:auto;opacity:0;
  animation:bh-rise .9s ease-out .28s both}
@keyframes bh-rise{from{opacity:0;filter:blur(7px);transform:translateY(6px)}to{opacity:1;filter:none;transform:none}}
.bh-lock .bh-l3{display:block;width:100%;height:auto;opacity:0;
  padding-left:calc(var(--lw) * 0.0588);padding-right:calc(var(--lw) * 0.0588);
  animation:bh-rise .9s ease-out .5s both}
.bh-mid .bh-sub{font-family:var(--mono);letter-spacing:.15em;text-transform:uppercase;color:var(--bh-mut);
  font-size:min(clamp(9px,.95vw,12.5px),calc(var(--bh) * 0.058));opacity:0;margin:0;
  animation:bh-rise .9s ease-out .76s both}
.bh-vig{position:absolute;inset:0;pointer-events:none;z-index:7;
  background:radial-gradient(115% 150% at 50% 50%,transparent 46%,var(--bh-vig) 100%)}

/* The lockup, the line and the contacts all rest at opacity 0 and are brought up by
   an animation with fill:both. Anything that kills animation-NAME (a page-wide
   *{animation:none!important} under reduced motion, which the standalone board has)
   therefore erases them. Set the resting state explicitly, do not rely on the fill. */
@media (prefers-reduced-motion:reduce){
  .bh-band,.bh-band *{animation-duration:1ms!important;animation-iteration-count:1!important;animation-delay:0ms!important}
  .bh-lockup,.bh-l3,.bh-sub{opacity:1!important;filter:none!important}
  .bh-blip,.bh-tag{opacity:.5!important}
  .bh-contact{opacity:.4!important}
}
