/* ============================================================
   PONZI EMPORIUM — design system
   Recreated in-stack from design_handoff_ponzi_emporium (README +
   brand-guidelines). "A ledger, not an app": sharp corners, hairline ink
   borders, aged paper, one hard offset shadow (primary buttons only),
   monospace numbers, a closed 9-colour palette.
   Prototype support.js is intentionally NOT ported.
   ============================================================ */

:root {
  /* Core palette */
  --paper:        #F7F3E8;  /* app background */
  --certificate:  #FFFDF6;  /* cards, rows, inputs */
  --ink:          #1C2B24;  /* text, all borders, dark surfaces */
  --money-green:  #157A4A;  /* wins, your picks, active, primary button */
  --green-deep:   #0E5734;  /* primary button border, pressed green */
  --void-red:     #C63B2F;  /* busts, rank drops — verdict only */
  --faded-ink:    #7A857D;  /* secondary text, metadata, inactive tabs */
  --ledger-line:  #B9B29C;  /* dotted row rules, muted borders */
  --green-wash:   #EAF3EC;  /* your-row highlight, selected pick, callout */

  /* Support neutrals */
  --desk:         #E7E1D2;  /* desk bg; disabled button fill */
  --divider:      #EDE7D6;  /* empty track; grid cell dividers */
  --rail-empty:   #DCD5C2;  /* unfilled progress rail */
  --nudge-off:    #D8D1BC;  /* disabled nudge arrow */
  --consensus:    #C7C0AC;  /* the side you didn't pick */
  --on-ink-muted: #9FB0A6;  /* muted text on ink surfaces */
  --disabled-txt: #9AA39B;  /* disabled text; losing score; grip lines */
  --hair-on-ink:  rgba(247,243,232,0.22);

  /* §96 — gold. The first accent added since this stylesheet was written: green
     means a win and ink means the app, so a shared money arrangement had nowhere
     to live in the closed palette. #C9A227 and lighter golds go yellow on --paper. */
  --gold:         #B8892B;  /* rules, bars, the active segment */
  --gold-text:    #8C6B1F;  /* gold text on cream — the readable weight */
  --gold-on-ink:  #E7C67E;  /* the headline figure on the ink card */
  --gold-dim:     #D8B978;  /* its label */
  --gold-wash:    #F7EFDD;  /* the entry band, and members' rows on the Ledger */
  --gold-hatch:   #F1E4C6;  /* the light stripe past the line */
  --sand:         #F4EFE2;  /* quiet explanatory panels */

  /* §100 — a ranker row frozen by its own kickoff. The lock is carried by the
     TAN, not by the pick colour: two passes darkened the picked side instead and
     were reverted (Ryan, 2026-09-09: "I don't want the green to be darker, I want
     the tan bar to be darker"). The first tan was #F2EEE1, a few percent off an
     unlocked row, and disappeared in a scroll of sixteen — the row has to read as
     a FILLED bar among white ones, so don't lighten these back toward the sheet. */
  --lock-row:      #DCD2B8;  /* the frozen row's ground */
  --lock-slot:     #CFC4A8;  /* its rank slot, and the LOCKED chip's fill */
  --lock-ink:      #3E4A43;  /* its rank numeral, and the chip's text */
  --lock-line:     #A79E85;  /* its borders, and the chip's */
  --lock-pick:     #E4EDE6;  /* the committed pick — a paler --green-wash */
  --lock-pick-bd:  #7FA98F;
  --lock-pick-fg:  #2F5C42;
  --lock-off:      #E0D7C0;  /* the side not taken */
  --lock-off-fg:   #7C7663;

  --font-display: 'Playfair Display', Georgia, serif;
  --font-body:    'Barlow', system-ui, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, monospace;

  --shadow-btn:   3px 3px 0 var(--ink);
  --shadow-lift:  6px 8px 0 rgba(28,43,36,0.22);
}

/* ---- Reset ---- */
* { margin: 0; padding: 0; box-sizing: border-box; }
img { max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
a { color: inherit; text-decoration: none; }

body.emporium {
  background: var(--desk);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* ============================================================
   App chrome — centered mobile column
   ============================================================ */
.em-app {
  max-width: 430px;
  margin: 0 auto;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border-left: 1px solid var(--ink);
  border-right: 1px solid var(--ink);
}
/* §83 — pin the shell to the viewport so .em-screen is the element that actually
   scrolls. The shell is min-height, so .em-screen's overflow-y never engages and
   the WINDOW scrolls: Sortable measures its autoscroll zones from the scroll
   container's edges, which put the top zone in the window's top 64px — behind the
   sticky app header and the .em-screen-head band. A row dragged upwards slid under
   the band with no pan (down worked: the bottom zone is only clipped by the tab
   bar). With the shell pinned, the top zone sits just below the band, in reach.
   Scoped to the ranker — it is the only screen with a drag, and this changes a
   screen's scroll model. */
.em-app--pane { height: 100dvh; }

/* In-app header (kept from the design; no fake status bar) */
.em-header {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px;
  padding: 11px 16px;
  background: var(--certificate);
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  position: sticky; top: 0; z-index: 20;
  /* The header is STICKY at top:0, so it pins to the viewport edge — under the
     status bar once viewport-fit=cover is on. Padding on .em-app can't help:
     that padding scrolls away and the header still sticks to the raw edge. So
     the inset lives here, and the ink band reads as the column continuing up
     behind the clock. */
  padding-top: calc(11px + env(safe-area-inset-top));
}
.em-wordmark { justify-self: start; font-family: var(--font-display); font-weight: 900; font-size: 17px; letter-spacing: -0.01em; white-space: nowrap; }
.em-context { justify-self: center; font-family: var(--font-mono); font-size: 9px; text-transform: uppercase; letter-spacing: 0.16em; color: var(--faded-ink); white-space: nowrap; }

/* §108f — the game switcher. The kicker becomes a button for a member who is in
   a contest; everyone else keeps the plain .em-context line above, so the whole
   of this section is dormant for the rest of the pool. */
/* #B9B29C in §108f — which is --ledger-line, so it is named, not repeated. */
.em-gameswitch { border: 1px solid var(--ledger-line); border-radius: 2px; padding: 4px 8px;
  background: none; color: var(--ink); cursor: pointer; line-height: 1;
  /* The header is a 1fr/auto/1fr grid and the wordmark will not shrink, so an
     over-wide centre pushes Sign out off the screen rather than wrapping. Cap it
     and ellipsize: a clipped game name is recoverable, a lost Sign out is not. */
  max-width: 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  /* Tighter tracking than `.em-context`'s 0.16em, and deliberately so: at mono
     9px `SUPER CONTEST` plus the caret came to 123px in a 121px button, so the
     ellipsis ate the caret and the control stopped reading as a dropdown. The
     2px was all it needed, and 0.12em buys about five. */
  letter-spacing: 0.12em; }
.em-header > .em-gameswitch { justify-self: center; }
.em-gameswitch .car { margin-left: 5px; color: var(--faded-ink); font-size: 8px; }
.em-gameswitch[aria-expanded="true"] { border-color: var(--ink); }

/* Drops from under the header. Fixed, not absolute: .em-app is the scroll
   container's parent and an absolute sheet would scroll away from the button
   that opened it. Width is the app shell's, so it lines up on a wide screen. */
/* `top` is set from the header's measured bottom when the sheet opens — see
   base_emporium.html. The value here is only a sane start before that runs. */
.em-gamesheet { position: fixed; top: calc(48px + env(safe-area-inset-top));
  left: 0; right: 0; margin: 0 auto; width: 100%; max-width: 430px; z-index: 19;
  background: var(--certificate); border-bottom: 1px solid var(--ink);
  box-shadow: 0 6px 14px rgba(28, 43, 36, .16); }
.em-gs-row { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px;
  padding: 11px 16px; border-bottom: 1px dotted var(--ledger-line);
  text-decoration: none; }
.em-gs-row:last-child { border-bottom: none; }
.em-gs-row .nm { font-family: var(--font-body); font-weight: 600; font-size: 14px;
  color: var(--ink); }
.em-gs-row .st { grid-column: 1 / -1; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink); }
.em-gs-row .here { font-family: var(--font-mono); font-size: 9px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--money-green);
  align-self: center; }
/* The 3px bar sits inside the row's own padding so the dotted rule above it
   still runs the full width — the bar marks the row, not the list. */
.em-gs-row.is-here { background: var(--green-wash);
  box-shadow: inset 3px 0 0 var(--money-green); }
/* Sign-out lives at the top-right of the wordmark line, on every screen. */
.em-signout { justify-self: end; margin: 0; }
.em-signout button { font-family: var(--font-body); font-weight: 600; font-size: 10px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--faded-ink);
  border: 1px solid var(--ledger-line); padding: 5px 9px; white-space: nowrap; }
.em-signout button:hover { border-color: var(--ink); color: var(--ink); }

/* Simulation / tester bars (kept from the app, restyled) */
.em-sim-bar { background: var(--ink); color: var(--paper); font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; padding: 6px 18px;
  display: flex; justify-content: space-between; align-items: center; }
.em-sim-bar a { color: #7FCFA0; }

/* Staff tester tools — jump the (fake) clock to a phase, or reset to live. */
.em-tester { background: var(--desk); border-bottom: 1px solid var(--ink);
  padding: 6px 10px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  font-family: var(--font-mono); font-size: 10px; }
.em-tester .lbl { color: var(--faded-ink); letter-spacing: 0.12em; text-transform: uppercase; }
.em-tester a { color: var(--ink); border: 1px solid var(--ledger-line); padding: 2px 6px; }
.em-tester a.reset { color: var(--void-red); border-color: var(--void-red); }
.em-tester .sep { color: var(--ledger-line); }

.em-screen { flex: 1; padding: 12px; overflow-y: auto; animation: em-scrIn 0.3s ease; }
/* §55a — the fixed white header band: a filed-document plate that stays on screen
   (on the Full Grid it keeps the title + lens control in reach). Sticky at top:48px,
   the app header's height. Hidden on screens that don't fill the block. */
.em-screen-head { background: var(--certificate); border-bottom: 1px solid var(--ink);
  padding: 20px 20px 12px; z-index: 10;
  /* 48px is the header's height; it grows by the top inset, so this offset has
     to grow with it or the band tucks underneath the header. */
  position: sticky; top: calc(48px + env(safe-area-inset-top)); }
.em-screen-head:empty { display: none; }
@keyframes em-scrIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* Bottom tab bar — HOME · PICKS · LIVE · BOARD · LEDGER */
/* The home indicator sat ON the tab labels: the shell reserved no bottom safe
   area at all. The ink ground extends into the inset, so the indicator gets a
   dark band of its own instead of overlapping the tabs. */
.em-tabbar { display: flex; border-top: 2px solid var(--ink); background: var(--ink);
  position: sticky; bottom: 0; z-index: 21;
  padding-bottom: env(safe-area-inset-bottom); }
.em-tab { flex: 1; text-align: center; padding: 14px 0 13px; font-family: var(--font-mono);
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--on-ink-muted); background: transparent;
  border-right: 1px solid var(--hair-on-ink);
  display: flex; align-items: center; justify-content: center; gap: 5px; }
.em-tab:last-child { border-right: none; }
.em-tab.is-active { background: var(--money-green); color: var(--paper); font-weight: 600; }
/* live dot — visible on the green fill as well as the ink ground */
.em-tab .em-tab-dot { width: 6px; height: 6px; border-radius: 50%;
  background: var(--money-green); flex-shrink: 0; }
.em-tab.is-active .em-tab-dot { background: var(--paper); }

/* Navigation loading indicator — shown (after a short delay, so fast pages don't
   flash it) when a slow destination is clicked, notably the Board's Full Grid;
   cleared by the fresh page load. */
.em-navload { position: fixed; inset: 0; z-index: 60; display: none;
  align-items: center; justify-content: center; background: rgba(28, 43, 36, 0.10); }
.em-navload.on { display: flex; }
.em-navload .spin { width: 30px; height: 30px; border: 3px solid var(--ledger-line);
  border-top-color: var(--money-green); border-radius: 50%; animation: em-navspin 0.7s linear infinite; }
@keyframes em-navspin { to { transform: rotate(360deg); } }

/* ============================================================
   Type helpers
   ============================================================ */
.em-serif { font-family: var(--font-display); }
.em-mono  { font-family: var(--font-mono); }
.em-h1 { font-family: var(--font-display); font-weight: 900; font-size: 36px; line-height: 0.98; }
/* §54a — Home hero headline is 21px (Ryan-confirmed), sized to sit on one line so
   the joke stays the frame, not the wall. Separate rule so the shared 36px .em-h1
   (Standings' rank readout) is untouched. nowrap dropped: at 21px it's one line on
   375px+ but would overflow a 320px screen, so it wraps gracefully there instead. */
/* §77 — the member's name, not the (unchanging) tagline, is the hero headline. */
.em-hero-title { font-family: var(--font-display); font-weight: 900; font-size: 16px;
  line-height: 1.15; }
.em-h2 { font-family: var(--font-display); font-weight: 900; font-size: 28px; line-height: 1.02; }
.em-card-title { font-family: var(--font-display); font-weight: 700; font-size: 22px; line-height: 1.1; }
.em-kicker { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--money-green); }
.em-label { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.16em; color: var(--faded-ink); }
.em-field-label { font-family: var(--font-body); font-weight: 700; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.12em; }
.em-body { font-family: var(--font-body); font-size: 15px; line-height: 1.5; color: var(--faded-ink); }
.em-body strong { color: var(--ink); font-weight: 600; }
.em-num { font-family: var(--font-mono); }
.em-green { color: var(--money-green); }
.em-red { color: var(--void-red); }
.em-muted { color: var(--faded-ink); }

/* ============================================================
   Buttons — one green button per screen
   ============================================================ */
.em-btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-body); font-weight: 700; font-size: 15px;
  text-transform: uppercase; letter-spacing: 0.07em;
  padding: 14px 24px; min-height: 44px;
  border: 1px solid var(--ink); background: transparent; color: var(--ink);
}
.em-btn--primary { background: var(--money-green); color: var(--paper);
  border-color: var(--green-deep); box-shadow: var(--shadow-btn); }
.em-btn--primary:hover { background: var(--green-deep); }
.em-btn--primary:active { box-shadow: 1px 1px 0 var(--ink); transform: translate(2px, 2px); }
.em-btn--block { width: 100%; }
.em-btn:disabled, .em-btn--disabled {
  background: var(--desk); border-color: var(--ledger-line); color: var(--disabled-txt);
  box-shadow: none; cursor: not-allowed; transform: none;
}

/* ============================================================
   Cards & certificate
   ============================================================ */
.em-card { background: var(--certificate); border: 1px solid var(--ink); padding: 20px; position: relative; }
.em-card--compact { padding: 16px 18px; }
.em-cert { background: var(--certificate); border: 1px solid var(--ink);
  outline: 1px solid var(--ink); outline-offset: 4px; padding: 26px; position: relative; }

/* dotted key/value line */
.em-line { display: flex; justify-content: space-between; align-items: baseline;
  padding: 10px 0; border-bottom: 1px dotted var(--ledger-line); font-size: 15px; }
.em-line:last-child { border-bottom: none; }
.em-line .val { font-family: var(--font-mono); font-weight: 600; }
.em-line .val--green { color: var(--money-green); }
.em-line .val--red { color: var(--void-red); }

/* ============================================================
   Stamps — rubber-stamp status, never filled pills
   ============================================================ */
/* The `hidden` attribute must actually hide: an explicit `display` (e.g. the
   inline-block below) overrides the UA `[hidden]{display:none}`, which is why the
   ranker's server-hidden "Picks In" stamp still showed on an empty board. */
[hidden] { display: none !important; }
.em-stamp { display: inline-block; font-family: var(--font-mono); font-weight: 600;
  font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 3px 9px; border: 1px solid currentColor; background: transparent; }
.em-stamp--green { color: var(--money-green); border-width: 2px; }
.em-stamp--ink { color: var(--faded-ink); }
.em-stamp--red { color: var(--void-red); border-width: 2px; }
.em-stamp--rot { transform: rotate(6deg); }
.em-stamp--corner { position: absolute; top: -12px; right: 12px; background: var(--certificate); }

/* ============================================================
   Progress rail / bar
   ============================================================ */
.em-progress { height: 5px; background: var(--ledger-line); overflow: hidden; }
.em-progress > span { display: block; height: 100%; background: var(--money-green); }

/* segmented 16-game rail */
.em-rail { display: flex; gap: 2px; }
.em-rail > i { flex: 1; height: 5px; background: var(--rail-empty); }
.em-rail > i.on { background: var(--money-green); }

/* ============================================================
   Home
   ============================================================ */
.em-week-card { background: var(--green-wash); border: 1px solid var(--ink);
  padding: 16px 18px; position: relative; }
.em-week-card .row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 10px; }

.em-nav-row { display: flex; align-items: center; gap: 14px; background: var(--certificate);
  border: 1px solid var(--ink); padding: 16px 18px; }
.em-nav-row .idx { font-family: var(--font-mono); font-size: 12px; color: var(--faded-ink); }
.em-nav-row .body { flex: 1; }
/* §54c — title and description are blocks with a 2px gap; the old <br> pulled in
   the body's 1.55 line-height (~20px) and loosened each nav row. */
.em-nav-row .body .t { display: block; font-family: var(--font-display); font-weight: 700; font-size: 18px; }
.em-nav-row .body .d { display: block; margin-top: 2px; font-family: var(--font-body); font-size: 13px; color: var(--faded-ink); }
.em-nav-row .aff { font-family: var(--font-mono); color: var(--faded-ink); }
.em-nav-row .aff-stat { font-family: var(--font-mono); font-size: 11px; line-height: 1.5;
  text-align: right; color: var(--ink); white-space: nowrap; }
.em-nav-row .aff-stat .k { color: var(--faded-ink); }

/* Home hero — headline, member name, kickoff countdown, rule + footnote */
.em-hero-ast { color: var(--void-red); font-weight: 700; }
/* §54b — the member's own name: green with a 3px green rule (green = "yours"),
   so it reads as who-you-are rather than a subtitle to the headline joke. */
.em-hero-name { display: flex; align-items: center; gap: 9px; margin-top: 16px;
  font-family: var(--font-body); font-weight: 700; font-size: 26px; color: var(--money-green); }
.em-hero-name::before { content: ''; width: 3px; height: 26px;
  background: var(--money-green); flex-shrink: 0; }
.em-hero-count { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 22px; }
.em-hero-count .lbl { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--faded-ink); line-height: 1.35; }
.em-hero-count .val { font-family: var(--font-mono); font-size: 25px; font-weight: 600; color: var(--ink); white-space: nowrap; }
.em-hero-rule { border-bottom: 1px solid var(--ink); margin-top: 18px; }
/* §54d — legal-parody small print sits at the bottom of the contrast ladder. */
.em-hero-foot { font-family: var(--font-mono); font-size: 10px; line-height: 1.55; color: var(--ledger-line); margin-top: 22px; }

.em-stack > * + * { margin-top: 12px; }

/* Circular team logo token — the one rounded thing in the system */
.em-logo { border-radius: 50%; object-fit: cover; background: var(--divider); }

/* ============================================================
   Segmented control (This Week / Season, All Picks lenses)
   ============================================================ */
.em-seg { display: flex; gap: 6px; }
.em-seg > a { flex: 1; text-align: center; padding: 9px 0; font-family: var(--font-mono);
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em;
  border: 1px solid var(--ink); background: var(--certificate); color: var(--faded-ink); }
.em-seg > a.is-active { background: var(--money-green); border-color: var(--green-deep); color: var(--paper); }

/* ============================================================
   Standings — the Ledger
   ============================================================ */
/* §56a — the ink band is a masthead: it breaks out of the screen's 8px padding to
   run edge-to-edge (same negative-margin pattern as .em-rk-foot / .em-lv-impact). */
.em-standing { background: var(--ink); color: var(--paper); padding: 18px 20px 16px;
  margin-left: -8px; margin-right: -8px; }
.em-standing .top { display: flex; justify-content: space-between; }
.em-standing .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--on-ink-muted); }
.em-standing .rank { font-family: var(--font-mono); font-weight: 600; font-size: 36px; letter-spacing: -0.02em;
  line-height: 1; color: var(--paper);
  /* §84 — a position and a total, not one number: a hairline rule with 14px of
     air either side. The rank digits need .no, or the bare text node becomes an
     anonymous flex item and the baseline shifts. */
  display: flex; align-items: baseline; gap: 14px; }
.em-standing .rank .sep { align-self: stretch; width: 1px; background: #3B4B42; flex-shrink: 0; }
/* §105 — the points and the ceiling stack in one cell. The row keeps
   align-items:baseline, so `42 pts` still registers with the 36px rank and the
   ceiling hangs below it. Points go 15px -> 20px: there is vertical room now
   that something sits under them. */
.em-standing .rank .ptscol { display: flex; flex-direction: column; gap: 2px; }
.em-standing .rank .pts { font-family: var(--font-mono); font-size: 20px; font-weight: 400;
  color: var(--on-ink-muted); line-height: 1; }
.em-standing .rank .poss { font-family: var(--font-mono); font-size: 11px; font-weight: 400;
  color: #8A9A90; white-space: nowrap; line-height: 1; }
.em-standing .stat-val { font-family: var(--font-mono); font-size: 15px; text-align: right; }
.em-standing .boxes { display: flex; gap: 8px; margin-top: 14px; }
/* §68 — the two bounded values (Behind, Won) get tracks sized to their labels;
   the two sentence values (To Climb, Cushion) keep the room. */
.em-standing .box { flex: 1; min-width: 0; border: 1px solid var(--hair-on-ink); padding: 9px 8px; }
.em-standing .box--fixed { flex: 0 0 52px; }
.em-standing .box .k { font-family: var(--font-mono); font-size: 8px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--on-ink-muted); white-space: nowrap; }
.em-standing .box .v { font-family: var(--font-mono); font-size: 14px; margin-top: 3px; white-space: nowrap; }
.em-standing .box--won { flex: 0 0 56px; border-color: var(--money-green); }
.em-standing .box--won .v { color: #7FCFA0; }

/* §57 — the column labels float on --paper above the box as annotations, not a
   header row; the bordered box begins at the first real ledger entry. .em-board-head
   keeps .em-board .row's grid, and its 13px inline padding = the box's 1px border +
   the row's 12px, so each label sits over its column. Sort <button>s move with it. */
.em-board-wrap { margin-top: 14px; }
/* §105 — a fifth track for Poss (0px on the season board, which keeps its own
   four columns). `minmax(0, 1fr)` on the member track is REQUIRED, not tidying:
   with a bare `1fr` a long display name refuses to shrink below its content
   width and pushes the new 40px column off the right edge of a 430px column.
   With it, long names ellipsis as they already do. */
.em-board-head { display: grid; align-items: center;
  grid-template-columns: 54px minmax(0, 1fr) var(--pts, 46px) var(--last, 52px) var(--poss, 0px);
  padding: 0 13px 8px; }
.em-board-head span, .em-board-head button { font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink); }
.em-board-head span.num, .em-board-head button { text-align: right; }
.em-board-head button.is-active { color: var(--money-green); }
.em-board-head button .ar { opacity: 0.5; }
.em-board-head button.is-active .ar { opacity: 1; }
.em-board { border: 1px solid var(--ink); background: var(--certificate); }
.em-board .row { display: grid; align-items: center;
  grid-template-columns: 54px minmax(0, 1fr) var(--pts, 46px) var(--last, 52px) var(--poss, 0px);
  padding: 10px 12px 9px; }
.em-board .row .num { text-align: right; }
.em-board .row { border-bottom: 1px dotted var(--ledger-line); }
.em-board .row:last-child { border-bottom: none; }
.em-board .row.is-you { background: var(--green-wash); }
.em-board .rank { font-family: var(--font-mono); font-weight: 600; font-size: 14px; letter-spacing: -0.02em; color: var(--faded-ink); white-space: nowrap; padding-right: 10px; }
.em-board .row.is-leader .rank { color: var(--money-green); }
.em-board .row.is-you .rank { color: var(--ink); }
.em-board .name { display: flex; flex-direction: column; justify-content: center;
  align-items: flex-start; font-size: 14px; overflow: hidden; }
.em-board .row.is-you .name { font-weight: 700; }
.em-board .name .txt { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* §73 — real name as a quiet 11px second line under the display name. */
.em-board .name .rn { max-width: 100%; margin-top: 1px; font-family: var(--font-body);
  font-weight: 400; font-size: 11px; line-height: 1.2; color: var(--faded-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.em-board .num { font-family: var(--font-mono); font-size: 14px; }
/* The Points column reads big and dark — it's the number that matters. */
.em-board .row .ptsval { font-size: 20px; font-weight: 700; color: var(--ink); line-height: 1; }
/* §105 — 12px #4A574F: below Pts (20px/700) so it reads as secondary, above the
   --faded-ink of Hits so it is not mistaken for metadata. */
.em-board .row .possval { font-family: var(--font-mono); font-size: 12px; color: #4A574F; }
.em-board .row .possval .none { color: var(--faded-ink); }
.em-board .won { color: var(--money-green); font-weight: 600; }
.em-board .sub { grid-column: 2 / -1; display: flex; align-items: baseline; gap: 10px;
  font-family: var(--font-mono); font-size: 11px; color: var(--faded-ink); margin-top: 4px; }
/* Movement sits in a fixed left slot so the arrows and digits line up as a column;
   the gap is always shoved to the right edge (weekly rows carry only the gap).
   Both read a touch bigger + darker than plain metadata — they're the numbers you scan. */
.em-board .sub .gap { margin-left: auto; text-align: right; font-size: 12px;
  font-weight: 600; color: var(--ink); }
/* §58 — the Leader stamp at the start of row 2, pushed against the name's left edge
   (margin-right:auto shoves movement/gap to the right). */
.em-board .sub .sub-stamp { margin-right: auto; font-size: 8px; padding: 2px 5px; }
.em-board .sub .mv { display: inline-grid; grid-template-columns: 12px auto; gap: 4px;
  align-items: baseline; font-size: 12px; font-weight: 700; }
.em-board .sub .mv .ar { text-align: center; }
.em-board .sub .mv--up { color: var(--money-green); }
.em-board .sub .mv--down { color: var(--void-red); }
.em-board .sub .mv--flat { color: var(--faded-ink); }
/* Movement readout in the ink "Your Standing" band (lighter tints for contrast). */
.em-standing .stat-val.mv--up { color: #7FCFA0; }
.em-standing .stat-val.mv--down { color: #E4796F; }
.em-standing .stat-val.mv--flat { color: var(--on-ink-muted); }

/* §73 — the Ledger controls row (Week picker + Show Real Names), shared by both
   views. The toggle is pushed to the right edge; §72c caps this row at 430px on wide
   screens so `margin-left:auto` keeps meaning "beside the picker", not "far right". */
.em-ledger-controls { display: flex; align-items: center; gap: 10px; margin: 0 0 16px; }
.em-realnames { margin-left: auto; }
.em-switch { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.em-switch input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.em-switch .track { width: 30px; height: 16px; flex-shrink: 0; border: 1px solid var(--ink);
  background: var(--certificate); display: inline-flex; align-items: center; padding: 1px;
  justify-content: flex-start; }
.em-switch .knob { width: 12px; height: 12px; background: var(--ledger-line); display: block; }
.em-switch input:checked + .track { background: var(--money-green); justify-content: flex-end; }
.em-switch input:checked + .track .knob { background: var(--paper); }
.em-switch .lbl { width: 70px; text-align: left; font-family: var(--font-mono); font-size: 10px;
  line-height: 1.25; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink); }
.em-switch input:checked ~ .lbl { color: var(--ink); }
.em-switch input:focus-visible + .track { outline: 2px solid var(--money-green); outline-offset: 2px; }
.em-footnote { font-family: var(--font-mono); font-size: 10px; color: var(--faded-ink);
  margin-top: 14px; line-height: 1.5; }

/* ============================================================
   Auth — the Member Portal
   ============================================================ */
.em-auth { max-width: 430px; margin: 0 auto; min-height: 100dvh; background: var(--paper);
  border-left: 1px solid var(--ink); border-right: 1px solid var(--ink);
  /* No tab bar on the auth screens, so nothing else reserves the bottom inset
     and a footer link would sit under the home indicator. */
  padding-bottom: env(safe-area-inset-bottom); }
.em-auth-head { text-align: center; padding: 18px; background: var(--certificate);
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); }
.em-auth-head .wm { font-family: var(--font-display); font-weight: 900; font-size: 17px; }
.em-auth-head .sub { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--faded-ink); margin-top: 4px; }
.em-auth-body { padding: 26px 20px 40px; }
.em-auth-kicker { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--money-green); text-align: center; }
.em-auth-title { font-family: var(--font-display); font-weight: 900; font-size: 31px;
  text-align: center; line-height: 1.02; margin: 6px 0 20px; }

/* Certificate panel (double-rule frame) */
.em-cert-eyebrow { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--money-green); text-align: center; }
/* §53j — the share certificate's countersignature: an actual signature on a rule. */
.em-cert-sign { margin: 18px 0 0; border-top: 1px solid var(--ink); padding-top: 14px; text-align: center; }
.em-cert-sig { font-family: 'Mrs Saint Delafield', cursive; font-size: 40px;
  line-height: 0.78;   /* tight — the script's descenders carry the height */
  color: var(--ink); }
.em-cert-sig-rule { border-top: 1px solid var(--ledger-line); margin: 4px auto 0; width: 74%; }
.em-cert-sig-cap { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); margin-top: 7px; }

/* Fields */
.em-field { margin-bottom: 16px; }
.em-field > label { display: block; font-family: var(--font-body); font-weight: 700;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 7px; }
.em-field input, .em-field select {
  width: 100%; padding: 12px 13px; border: 1px solid var(--ink);
  background: var(--certificate); color: var(--ink);
  font-family: var(--font-body); font-size: 16px; line-height: 24px; }
.em-field input:focus, .em-field select:focus { outline: none;
  border-color: var(--money-green); box-shadow: inset 0 0 0 1px var(--money-green); }
.em-field .hint { font-family: var(--font-mono); font-size: 11px; color: var(--faded-ink); margin-top: 6px; }

/* §76 — the sign-in password field reads DISABLED by default (grey ground, muted
   border/text/label), so it never looks like an empty input the member skipped.
   The email branch adds .pw-live to the wrapper, restoring the live appearance.
   -webkit-text-fill-color forces the colour on iOS, which dims disabled inputs. */
#password-field input {
  background: #E7E1D2; border-color: var(--ledger-line);
  color: #9AA39B; -webkit-text-fill-color: #9AA39B; opacity: 1; }
#password-field input::placeholder { color: #9AA39B; opacity: 1; }
#password-field > label { color: #9AA39B; }
#password-field.pw-live input {
  background: var(--certificate); border-color: var(--ink);
  color: var(--ink); -webkit-text-fill-color: var(--ink); }
#password-field.pw-live input::placeholder { color: var(--ink); }
#password-field.pw-live > label { color: var(--ink); }

/* §80 — Get Code takes the password field's slot in the card once a full phone
   number is entered (the field is removed, not greyed; the footer CTA is hidden). */
.em-getcode { display: block; width: 100%; margin-top: 14px; padding: 15px;
  background: var(--money-green); border: 1px solid #0E5734; box-shadow: 3px 3px 0 var(--ink);
  color: var(--paper); font-family: var(--font-body); font-weight: 700; font-size: 15px;
  text-transform: uppercase; letter-spacing: 0.07em; cursor: pointer; border-radius: 0;
  animation: em-scrIn 0.22s ease; }
.em-getcode:active { box-shadow: 1px 1px 0 var(--ink); transform: translate(2px, 2px); }

.em-error { border: 1px solid var(--void-red); color: var(--void-red);
  padding: 10px 12px; font-size: 13px; margin-bottom: 16px; }
.em-authlink { text-align: center; margin-top: 18px; font-size: 14px; color: var(--faded-ink); }
.em-authlink a { color: var(--money-green); font-weight: 600; }
/* §53a — dotted "OR" divider between the sign-in form and Open an Account. */
.em-or { display: flex; align-items: center; gap: 12px; margin: 20px 0 14px; }
.em-or::before, .em-or::after { content: ''; flex: 1; border-top: 1px dotted var(--ledger-line); }
.em-or span { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-forgot { text-align: right; margin: -6px 0 16px; font-size: 13px; }
.em-forgot a { color: var(--faded-ink); }

/* §53a-i — with the identifier field empty, Get Code is disabled and Open an Account
   is the only live action, so it takes the primary green; the moment the member
   starts typing (declaring they already have an account) it recedes to the outline
   treatment and hands the emphasis to the sign-in primary. Both states keep the
   primary's dimensions — only colour and the offset shadow change. */
.em-auth-signup { background: var(--money-green); color: var(--paper);
  border-color: var(--green-deep); box-shadow: var(--shadow-btn);
  transition: background .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease; }
.em-auth-signup.is-receded { background: transparent; color: var(--ink);
  border-color: var(--ink); box-shadow: none; }

/* §53d-iii — the application must fit one screen: a tighter field gap scoped to the
   registration form so it doesn't pull every other form with it. Kept scrollable as
   a fallback rather than clipped. */
.em-reg-fields { margin-top: 14px; }
.em-reg-form .em-field { margin-bottom: 11px; }
.em-reg-form .em-field:last-child { margin-bottom: 0; }

/* §53c-ii — Account login: the two sign-in-method cards select rather than navigate. */
.em-reg-card { display: block; width: 100%; text-align: left; position: relative;
  background: var(--certificate); border: 1px solid var(--ink); padding: 16px 18px;
  margin-bottom: 12px; cursor: pointer; border-radius: 0;
  transition: border-color .15s ease, box-shadow .15s ease; }
.em-reg-card .t { display: block; font-family: var(--font-display); font-weight: 700;
  font-size: 19px; color: var(--ink); }
.em-reg-card .d { display: block; margin-top: 4px; font-family: var(--font-body);
  font-size: 13px; line-height: 1.45; color: var(--faded-ink); }
.em-reg-card.is-selected { border-color: var(--money-green); box-shadow: 3px 3px 0 var(--money-green); }
.em-reg-card-rec { position: absolute; top: -11px; right: 12px; background: var(--certificate); }
.em-reg-pw { margin-top: 16px; padding-top: 16px; border-top: 1px dotted var(--ledger-line); }

/* ============================================================
   All Picks — The League Board
   ============================================================ */
.em-gamecard { background: var(--certificate); border: 1px solid var(--ink);
  padding: 12px 14px; margin-bottom: 12px; }
/* §37b — the summary is a real <button>; reset it to the card's own layout so it
   looks unchanged, and it (not the whole card) carries the pointer/keyboard focus. */
.em-gamecard .gc-summary { display: block; width: 100%; text-align: left;
  background: none; border: none; padding: 0; cursor: pointer; }
.em-gamecard .gc-head { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.em-gamecard .gc-head .gc-team { font-family: var(--font-mono); font-size: 13px; font-weight: 600; }
/* §109i — Super Contest's game cards head with crests. Scoped to `.crest` so
   Confidence's own cards, which have no image here, are untouched. */
.em-gamecard .gc-head .crest { border-radius: 50%; background: #E7E1D2;
  object-fit: cover; flex-shrink: 0; }
.em-gamecard .gc-head .gc-at { font-family: var(--font-mono); font-size: 11px; color: var(--faded-ink); }
.em-gamecard .gc-head .status { margin-left: auto; font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.12em; color: var(--faded-ink); }
.em-gamecard .gc-logo { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; background: var(--divider); }
/* §27b — your-pick marker: a 3px bar under the picked team's logo */
.em-gamecard .gc-head .gc-team-wrap { display: inline-flex; flex-direction: column; align-items: center; gap: 4px; }
.em-gamecard .gc-head .gc-underline { width: 22px; height: 3px; background: transparent; }
.em-gamecard .gc-head .gc-team-wrap.is-mine .gc-underline { background: var(--ink); }
.em-gamecard .gc-head .gc-team-wrap.is-mine.hit .gc-underline { background: var(--money-green); }
.em-gamecard .gc-head .gc-team-wrap.is-mine.bust .gc-underline { background: var(--void-red); }

/* Consensus bar */
.em-consensus { display: flex; height: 26px; border: 1px solid var(--ink); overflow: hidden; }
.em-consensus > div { display: flex; align-items: center; justify-content: space-between;
  padding: 0 8px; font-family: var(--font-mono); font-size: 10px; font-weight: 600; min-width: 0; }
.em-consensus .filled { background: var(--ink); color: var(--paper); }
.em-consensus .filled.hit { background: var(--money-green); }
.em-consensus .filled.bust { background: var(--void-red); }
.em-consensus .tan { background: var(--consensus); color: var(--ink); }
.em-consensus span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* team logo on the consensus bar — a paper disc so it reads on any bar colour */
.em-consensus img { width: 17px; height: 17px; border-radius: 50%; object-fit: cover;
  background: var(--paper); flex-shrink: 0; }

.em-gc-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; }
.em-gc-meta .left { display: flex; align-items: center; gap: 8px; }
/* §27a — two per-team average-confidence bars (0..top_conf). Each bar shows how
   convinced that side's backers were; your side takes the verdict accent, the other
   stays neutral. (Replaces the earlier single split bar, which just re-encoded the
   pick percentage.) */
.em-gc-conviction { margin-top: 11px; padding-top: 10px; border-top: 1px dotted var(--ledger-line); }
.em-gc-conviction .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--faded-ink); margin-bottom: 8px; }
.em-gc-conviction .conf-row { display: flex; align-items: center; gap: 9px; margin-top: 6px; }
.em-gc-conviction .conf-row .tm { width: 38px; flex-shrink: 0; font-family: var(--font-mono);
  font-size: 11px; font-weight: 600; color: var(--ink); }
.em-gc-conviction .conf-row .track { flex: 1; height: 8px; background: var(--divider);
  border: 1px solid var(--ledger-line); overflow: hidden; }
.em-gc-conviction .conf-row .fill { height: 100%; background: var(--consensus); }
.em-gc-conviction .conf-row .fill.mine { background: var(--ink); }
.em-gc-conviction .conf-row .fill.mine.hit { background: var(--money-green); }
.em-gc-conviction .conf-row .fill.mine.bust { background: var(--void-red); }
.em-gc-conviction .conf-row .v { width: 30px; flex-shrink: 0; text-align: right;
  font-family: var(--font-mono); font-weight: 600; font-size: 13px; color: var(--ink); }
.em-verdict { font-family: var(--font-mono); font-size: 10px; }
.em-verdict.hit { color: var(--money-green); }
.em-verdict.bust { color: var(--void-red); }
.em-verdict.pending { color: var(--faded-ink); }

/* Roll call — collapsed until the card is opened (§27d) or jumped to (§37a: a jump
   chip lands on #game-N, so :target opens it without needing the JS). */
.em-gamecard .em-rollcall { display: none; margin-top: 10px; border-top: 1px dotted var(--ledger-line); padding-top: 8px; }
.em-gamecard.is-open .em-rollcall,
.em-gamecard:target .em-rollcall { display: block; }

/* §75 — By Game rebuilt. Section-rule count (matches the Live Hub headers). */
.em-lv-sec .cnt { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ledger-line); white-space: nowrap; }

/* Live card — the only card whose content changes on screen, so the only one with
   weight: a 2px frame, an offset lift, and a pulsing INK dot (never red — a live
   game hasn't lost anything). */
.em-gamecard.is-live { border-width: 2px; box-shadow: 3px 3px 0 rgba(28, 43, 36, 0.16); }
@keyframes livePulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* §86a — the header is a box score: score + crest at each edge, clock between
   them. The old inline "CAR 24 @ ARI 17" sentence and the right-hand status
   cluster are gone — their two facts are the two lines in the middle now. */
.gc-head2 { display: flex; justify-content: space-between; align-items: center; gap: 14px; margin-bottom: 11px; }
.gc-head2 .mu { display: inline-flex; align-items: center; gap: 9px; min-width: 0; }
.gc-head2 .mu .lg { width: 30px; height: 30px; border-radius: 50%; object-fit: cover;
  background: var(--divider); flex-shrink: 0; }
/* §86b — your pick is a ring on the crest, not a bar under it. box-shadow, not
   border (which would resize the 30px box) and not outline (which ignores the
   50% radius). Ink while unsettled: a green ring on a live pick would claim a
   result that hasn't happened. */
.gc-head2 .mu .lg.mine { box-shadow: 0 0 0 2px var(--ink); }
.gc-head2 .mu .lg.mine.hit { box-shadow: 0 0 0 2px var(--money-green); }
.gc-head2 .mu .lg.mine.bust { box-shadow: 0 0 0 2px var(--void-red); }
.gc-head2 .mu .sc { font-family: var(--font-mono); font-size: 28px; font-weight: 600;
  line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.gc-head2 .mu .ab { font-family: var(--font-mono); font-size: 15px; font-weight: 600; color: var(--ink); }
.gc-head2 .mu .at { font-family: var(--font-mono); font-size: 10px; font-weight: 400; color: var(--ledger-line); }
/* An upcoming matchup sits back until something happens — but the crest carrying
   the member's ring keeps full strength; that ring is their pick (§75). */
.em-gc--upcoming .gc-head2 .mu .lg { opacity: 0.55; }
.em-gc--upcoming .gc-head2 .mu .lg.mine { opacity: 1; }
.em-gc--upcoming .gc-head2 .mu .ab { color: var(--faded-ink); }
.gc-head2 .clk { display: inline-flex; flex-direction: column; align-items: center; gap: 4px; flex-shrink: 0; }
.gc-head2 .clk .l1 { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono);
  font-size: 9px; letter-spacing: 0.1em; color: var(--faded-ink); white-space: nowrap; }
.em-gamecard.is-live .gc-head2 .clk .l1 { color: var(--ink); font-weight: 600; }
.gc-head2 .clk .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ink);
  flex-shrink: 0; animation: livePulse 1.6s ease-in-out infinite; }
.gc-head2 .clk .l2 { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: #B9B29C; }
.gc-head2 .clk .l2.hit { color: var(--money-green); }
.gc-head2 .clk .l2.bust { color: var(--void-red); }
/* .st survives for the no-picks header only, which has no clock stack. */
.gc-head2 .st { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.gc-head2 .st .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink);
  flex-shrink: 0; animation: livePulse 1.6s ease-in-out infinite; }
.gc-head2 .st .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.08em; color: var(--faded-ink); }
.em-gamecard.is-live .gc-head2 .st .lbl { color: var(--ink); font-weight: 600; }

/* Took / Boards / Avg Conf table. */
.gc-tab { border-top: 1px solid var(--ink); }
.gc-tab .th, .gc-tab .tr { display: grid; grid-template-columns: 1fr 66px 74px; gap: 8px; align-items: center; }
.gc-tab .th { padding: 8px 0 7px; border-bottom: 1px dotted var(--ledger-line);
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink); }
.gc-tab .th .n, .gc-tab .tr .n { text-align: right; font-family: var(--font-mono); }
.gc-tab .tr { padding: 9px 8px 9px 0; margin-right: -8px; }
.gc-tab .tr + .tr { border-top: 1px dotted var(--ledger-line); }
.gc-tab .tr .tk { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.gc-tab .tr .tk .ab { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--ink); }
.gc-tab .tr .n { font-size: 14px; color: var(--ink); }
.gc-tab .tr .con { flex-shrink: 0; font-family: var(--font-mono); font-weight: 600; font-size: 8px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink); border: 1px solid var(--ink); padding: 1px 4px; }
/* Your row: sand while unsettled; green/red only once the game is final. */
.gc-tab .tr.mine { background: #EFE9D9; }
.gc-tab .tr.mine .ab, .gc-tab .tr.mine .n { font-weight: 700; }
.gc-tab .tr.mine.hit { background: var(--green-wash); }
.gc-tab .tr.mine.hit .ab, .gc-tab .tr.mine.hit .n { color: var(--money-green); }
.gc-tab .tr.mine.bust { background: #F6E7E4; }
.gc-tab .tr.mine.bust .ab, .gc-tab .tr.mine.bust .n { color: var(--void-red); }

/* Footer — stake badge (left) + roll-call toggle (right), one line. */
.gc-foot { display: flex; justify-content: space-between; align-items: center;
  margin-top: 0; padding-top: 10px; border-top: 1px solid var(--ink); }
.gc-foot .stake { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.gc-foot .stake .badge { font-family: var(--font-mono); font-size: 10px; font-weight: 600; border: 1px solid; padding: 1px 5px; }
.gc-foot .stake .lbl { font-family: var(--font-mono); font-size: 10px; white-space: nowrap; }
/* §102 — the crest of the side you took. 14px and NO larger: the row's height is
   set by that 10px mono type, so a bigger crest lifts the footer and grows all
   sixteen cards in the list for what is a decoration. No ring and no state
   colour either — §86's coloured ring belongs to the crest in the card's box-score
   HEADER, and a second coloured mark 6px from a badge and a word that already
   carry the state makes the line read as though it reports two different things.
   This crest identifies; it does not judge. The .stake row is already
   flex/center/gap:6px, so it needs nothing else to sit on the mono baseline. */
.gc-foot .stake .crest { width: 14px; height: 14px; display: block; flex-shrink: 0;
  border-radius: 50%; object-fit: cover; background: var(--divider); }
.gc-foot .stake--pre { color: var(--faded-ink); }
.gc-foot .stake--live { color: var(--ink); }
.gc-foot .stake--hit { color: var(--money-green); }
.gc-foot .stake--bust { color: var(--void-red); }
.gc-rc { display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0; }
.gc-rc .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--faded-ink); white-space: nowrap; }
.gc-rc .cv { font-family: var(--font-mono); font-size: 12px; line-height: 1; color: var(--faded-ink);
  display: inline-block; transition: transform 0.2s ease; }
.em-gamecard.is-open .gc-rc .cv { transform: rotate(180deg); }
.em-gamecard:not(.is-open) .gc-rc .js-rc-close { display: none; }
.em-gamecard.is-open .gc-rc .js-rc-open { display: none; }
.gc-rc .cv.chev-nudge { animation: chevNudge 1.3s ease-in-out; }
@keyframes chevNudge {
  0%, 100% { transform: rotate(0deg); }
  18% { transform: rotate(180deg); }  36% { transform: rotate(0deg); }
  54% { transform: rotate(180deg); }  72% { transform: rotate(0deg); } }
@media (prefers-reduced-motion: reduce) { .gc-rc .cv.chev-nudge { animation: none; } }

/* Roll call — abbreviations, coloured green/red once settled. */
.em-rollcall .rc-lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--faded-ink); margin-bottom: 6px; }
.em-rc-row { display: grid; grid-template-columns: 1fr 52px 30px; align-items: center; gap: 8px; padding: 5px 4px; }
/* §75 — mark your own roll-call row with the card's neutral sand, NOT green: in a
   panel where green means the pick won, a green "you" band reads as a win on a
   game you lost. Sand marks the row without claiming a result. */
.em-rc-row.is-you { background: #EFE9D9; }
.em-rc-row .nm { font-family: var(--font-body); font-size: 12px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.em-rc-row.is-you .nm { font-weight: 700; }
.em-rc-row .tm { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--faded-ink); }
.em-rc-row .cf { font-family: var(--font-mono); font-size: 11px; text-align: right; color: var(--faded-ink); }
.em-rc-row .tm.agree, .em-rc-row .cf.agree { color: var(--ink); }
.em-rc-row .tm.won, .em-rc-row .cf.won { color: var(--money-green); font-weight: 600; }
.em-rc-row .tm.lost, .em-rc-row .cf.lost { color: var(--void-red); font-weight: 600; }
/* Close from the bottom — a standalone 44px tap target at the foot of the panel. */
.em-rollcall .rc-hide { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; margin-top: 10px; padding: 15px 0 12px; min-height: 44px;
  background: none; border: none; border-top: 1px dotted var(--ledger-line); cursor: pointer; text-align: left; }
.em-rollcall .rc-hide .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-rollcall .rc-hide .cv { font-family: var(--font-mono); font-size: 12px; color: var(--faded-ink); transform: rotate(180deg); }

/* Sealed game — inert card in the Scheduled group; no picks, no chevron (§48). */
.em-gc--sealed { border: 1px dashed var(--ledger-line); background: transparent; }
.em-gc--sealed .gc-srow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.em-gc--sealed .teams { display: flex; align-items: center; gap: 7px; min-width: 0; }
.em-gc--sealed .teams img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; opacity: 0.55; }
.em-gc--sealed .teams .mu { font-family: var(--font-mono); font-size: 13px; font-weight: 600; color: var(--faded-ink); margin-left: 3px; }
.em-gc--sealed .right { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex-shrink: 0; }
.em-gc--sealed .right .chip { font-family: var(--font-mono); font-weight: 600; font-size: 8px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--void-red); border: 1px solid var(--void-red); padding: 2px 6px; }
.em-gc--sealed .right .ko { font-family: var(--font-mono); font-size: 9px; color: var(--ledger-line); white-space: nowrap; }
.em-gc--sealed .gc-rc--inert { margin-top: 9px; padding-top: 9px; border-top: 1px dotted #DCD5C2;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em; text-transform: uppercase; color: #C7C0AC; }

/* §81 — week summary bar. Two figures + a sentence; the ground IS the message —
   sand while running, ink once every game is in. Read as a ledger figure (mono). */
.em-wksum { margin-top: 14px; border: 1px solid var(--ink); background: #F4EFE2; padding: 13px 15px; }
.em-wksum.is-final { background: var(--ink); box-shadow: 3px 3px 0 var(--ledger-line); }
.em-wksum .row { display: flex; justify-content: space-between; align-items: flex-end; gap: 14px; }
.em-wksum .col { display: flex; flex-direction: column; min-width: 0; }
.em-wksum .col.right { align-items: flex-end; text-align: right; }
.em-wksum .k { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-wksum .v { font-family: var(--font-mono); font-weight: 600; font-size: 28px;
  letter-spacing: -0.01em; color: var(--ink); margin-top: 3px; font-variant-numeric: tabular-nums; }
.em-wksum .sub { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase; font-weight: 400; color: var(--faded-ink); margin-top: 3px; }
.em-wksum .sub b { font-weight: 700; color: inherit; }
.em-wksum .note { margin-top: 10px; padding-top: 10px; border-top: 1px dotted var(--ledger-line);
  font-family: var(--font-mono); font-size: 10px; color: var(--faded-ink); }
.em-wksum.is-final .v { color: var(--paper); }
.em-wksum.is-final .k, .em-wksum.is-final .sub { color: #9FB3A6; }

/* By Member table */
.em-mtable { border: 1px solid var(--ink); background: var(--certificate); }
/* §87a — .mrow is the disclosure (and the element the sort reorders); the grid
   moved onto the button inside it so the panel can be its child. */
.em-mtable .mrow-btn, .em-mtable .mhead { display: grid; grid-template-columns: 1fr 44px 64px;
  align-items: center; padding: 11px 14px; }
.em-mtable .mrow-btn { width: 100%; background: none; border: none; font: inherit;
  color: inherit; text-align: left; cursor: pointer; }
.em-mtable .mhead { border-bottom: 1px solid var(--ink); }
/* §57 — when the table is wrapped in .em-mtable-wrap, the column labels float on
   --paper above the box (same treatment as the Ledger's .em-board-head), and the
   certificate box begins at the first member row. The 15px inline padding = the box's
   1px border + the row's 14px, so each label still sits over its column. (The plain,
   unwrapped .em-mtable keeps its boxed header for the reminder tool.) */
.em-mtable-wrap .mhead { display: grid; grid-template-columns: 1fr 44px 64px;
  align-items: center; padding: 0 15px 8px; }
.em-mtable .mhead span, .em-mtable-wrap .mhead span { font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink); }
.em-mtable .mhead span.num, .em-mtable-wrap .mhead span.num, .em-mtable .mrow .num { text-align: right; }
.em-mtable .mrow { border-bottom: 1px dotted var(--ledger-line); font-size: 14px; }
/* §87a moved the row grid onto .mrow-btn so a disclosure panel could be the
   .mrow's other child. Tables whose rows are plain — no button, no panel —
   opt back in here, or they render as unpadded blocks with the columns run
   together (which is what the reminder tool did after §87a). */
.em-mtable--plain .mrow { display: grid; align-items: center; padding: 11px 14px; }
.em-mtable .mrow:last-child { border-bottom: none; }
.em-mtable .mrow.is-you { background: var(--green-wash); font-weight: 700; }
.em-mtable .num { font-family: var(--font-mono); }
.em-mtable .agree-hi { color: var(--money-green); }
/* 4-column variant: Member | Pts | Agree | Weighted */
.em-mtable--wide .mrow-btn, .em-mtable--wide .mhead { grid-template-columns: 1fr 32px 50px 64px; gap: 6px; }

/* §87b — the slate panel: that member's board as team + confidence chips, in
   schedule order (the Full Grid's order). Sealed games arrive from the view as
   pick-less placeholders. */
.em-mtable .mslate { display: none; padding: 4px 14px 14px; }
.em-mtable .mrow.is-open .mslate { display: block; }
.em-mtable .mslate > .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faded-ink); font-weight: 400; margin-bottom: 9px; }
.em-mtable .mslate .chips { display: flex; flex-wrap: wrap; gap: 6px; }
.em-mtable .mslate .chip { display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--ink); background: var(--certificate); padding: 5px 8px; }
.em-mtable .mslate .chip .tm { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--ink); }
.em-mtable .mslate .chip .cf { font-family: var(--font-mono); font-size: 10px; font-weight: 400; color: var(--faded-ink); }
/* Ink while the game is unsettled; green/red only once it finals (§75's rule). */
.em-mtable .mslate .chip.hit { border-color: var(--money-green); }
.em-mtable .mslate .chip.hit .tm { color: var(--money-green); }
.em-mtable .mslate .chip.bust { border-color: var(--void-red); }
.em-mtable .mslate .chip.bust .tm { color: var(--void-red); }
.em-mtable .mslate .chip--sealed { border: 1px dashed var(--rail-empty); background: transparent;
  min-width: 44px; justify-content: center; font-family: var(--font-mono); font-size: 11px;
  font-weight: 400; color: var(--consensus); }
.em-mtable .mslate-hide { width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: 10px; min-height: 44px; margin-top: 10px; padding: 15px 0 12px; background: none; border: none;
  border-top: 1px dotted var(--ledger-line); cursor: pointer; text-align: left; }
.em-mtable .mslate-hide .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em;
  text-transform: uppercase; font-weight: 400; color: var(--faded-ink); white-space: nowrap; }
.em-mtable .mslate-hide .cv { flex-shrink: 0; font-family: var(--font-mono); font-size: 12px;
  line-height: 1; color: var(--faded-ink); transform: rotate(180deg); }
/* §78 — Pts/Agree sort headers (faded caret on the inactive one), and the member's
   own points figure lighter, since it's the reference the Agree column reads against. */
.em-mtable-wrap .mhead span.sortable { cursor: pointer; white-space: nowrap; }
.em-mtable-wrap .mhead span.sortable.is-active { color: var(--ink); }
.em-mtable-wrap .mhead span.sortable .ar { margin-left: 3px; }
.em-mtable-wrap .mhead span.sortable:not(.is-active) .ar { color: var(--ledger-line); }
.em-mtable .mrow .num.pts-own { color: #9AA39B; }

/* By Game: jump-to-game selector + back-to-top (the list gets long) */
.em-jump { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.em-jump-chip { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.03em;
  border: 1px solid var(--ledger-line); padding: 4px 7px; color: var(--faded-ink); white-space: nowrap; }
.em-jump-chip:hover { border-color: var(--money-green); color: var(--money-green); }
#board-top { scroll-margin-top: 60px; }
.em-gamecard { scroll-margin-top: 60px; }
.em-backtotop { display: inline-block; margin-top: 10px; font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--money-green); }

/* ============================================================
   My Picks — the Confidence Ranker ("Set your board")
   ============================================================ */
/* §55a — .em-rk-head now sits inside the fixed .em-screen-head band, which supplies
   the certificate ground, padding and closing rule; the wrapper itself is bare. */
.em-rk-head { }
/* §94 — the header is two lines. It was an eyebrow, a title, a stat line, a rail
   and a caption row (~125px); the state badge, the save button and the picked
   count were three separate things saying one thing between them. Now: title +
   one slot, then one meta line, and the rail only while it still reports
   something (§94c). ~86px complete / ~104px picking — 7 rows in view against 5. */
.em-rk-titlerow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.em-rk-title { font-family: var(--font-display); font-weight: 900; font-size: 27px;
  line-height: 1.02; margin: 0; }

/* §94a — the state/action slot. Five mutually exclusive states in one element:
   the window being open, the board being unsaved and the board being filed are
   never true at the same time, so they share the slot. 36px is deliberately under
   the 44px minimum — it is ~44px wide by 36px tall, it matches the title's cap
   height, and (§94e) this action has no second home on the screen. Raise
   min-height alone if it needs to be 44. */
.em-rk-slot { flex-shrink: 0; min-height: 36px; padding: 0 13px;
  font-family: var(--font-mono); font-weight: 600; font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; white-space: nowrap; background: none; cursor: default; }
/* Open / Tiebreak / Picks In — stated, not offered: 2px, no fill. */
.em-rk-slot.is-open, .em-rk-slot.is-tiebreak, .em-rk-slot.is-in {
  border: 2px solid var(--money-green); color: var(--money-green); }
/* Locked drops to 1px and greys: the window closing is the schedule working, not
   an error and not a loss, so it recedes (same rule as §92). */
.em-rk-slot.is-locked { border: 1px solid var(--ledger-line); color: var(--faded-ink); }
/* §91b — the one tappable state. The pulse only reads because the saved state is
   quiet: outline against pulsing fill is what makes the first edit after a save
   visibly re-arm the button. */
.em-rk-slot.is-save { border: 1px solid var(--green-deep); background: var(--money-green);
  color: var(--paper); cursor: pointer; animation: emSavePulse 1.6s ease-in-out infinite; }
.em-rk-slot.is-save:active { transform: translate(2px, 2px); }
@keyframes emSavePulse {
  0%, 100% { box-shadow: 3px 3px 0 var(--ink); }
  50%      { box-shadow: 3px 3px 0 var(--ink), 0 0 0 4px rgba(21, 122, 74, 0.3); }
}
/* The fill-vs-outline contrast still carries the state without the animation. */
@media (prefers-reduced-motion: reduce) {
  .em-rk-slot.is-save { animation: none; box-shadow: 3px 3px 0 var(--ink); }
}

/* §94b — one meta line replaces the eyebrow, the `16 / 16 picked` stat line and
   the scale caption. Ellipsizes rather than wraps: the row is a fixed cost in a
   header whose whole point is height. */
/* §107 — the week picker's own row, between the title and the meta line. */
.em-rk-weekrow { display: flex; align-items: center; gap: 10px; margin-top: 9px; }
/* §107 — why the Spreads chip is dead, said out loud. Quiet, but above the
   contrast floor: this is information, not decoration. */
.em-rk-weeknote { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--faded-ink); white-space: nowrap; }
/* §107 option 2 — the chip when the week's lines haven't posted. Greyed the way
   §76 greys a disabled field: it reads as unavailable, not as unticked. */
.em-rk-spreads.is-unavailable { border-color: var(--ledger-line); color: var(--disabled-txt);
  cursor: default; }
.em-rk-spreads.is-unavailable .box { border-color: var(--ledger-line); background: var(--desk); }

.em-rk-metarow { display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 7px; }
.em-rk-meta { min-width: 0; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.em-rk-meta b { color: var(--ink); font-weight: 600; }
/* Only rendered when the week on screen is not the week the app header names. */
.em-rk-meta .wk { color: var(--ink); font-weight: 600; }

/* §94d — the Vegas checkbox became a chip on the meta row. 36px to match the slot
   above it; at 22px it failed the touch check. */
.em-rk-spreads { flex-shrink: 0; display: inline-flex; align-items: center; gap: 6px;
  min-height: 36px; padding: 0 9px; border: 1px solid var(--ledger-line);
  background: var(--certificate); color: var(--faded-ink); cursor: pointer; }
.em-rk-spreads .lbl { font-family: var(--font-mono); font-weight: 600; font-size: 9px;
  letter-spacing: 0.12em; text-transform: uppercase; }
.em-rk-spreads .box { width: 11px; height: 11px; flex-shrink: 0; border: 1px solid currentColor;
  display: inline-flex; align-items: center; justify-content: center; }
.em-rk-spreads.is-on { border-color: var(--money-green); color: var(--money-green); }
.em-rk-spreads.is-on .box::after { content: ''; width: 7px; height: 7px; background: var(--money-green); }

/* §94c — rail + count, shown only while the board is incomplete. */
.em-rk-railrow { display: flex; align-items: center; gap: 9px; margin-top: 8px; }
.em-rk-railrow[hidden] { display: none; }
.em-rk-rail { flex: 1; min-width: 0; }
.em-rk-railrow .cnt { flex-shrink: 0; font-family: var(--font-mono); font-weight: 600;
  font-size: 11px; color: var(--faded-ink); }

/* List — a static number ruler beside the sortable cards, so the confidence
   slot numbers stay put while you drag a team into position. */
/* §90 — tight rows: 66px against 90px, gap 6px against 8px. A row cost 98px and
   now costs 72px, which with §94's header is what puts 7 in view against 5. */
.em-rk-ranker { display: flex; gap: 8px; align-items: flex-start; --rk-h: 66px; }
.em-rk-nums { display: flex; flex-direction: column; gap: 6px; flex-shrink: 0; }
.em-rk-numslot { width: 34px; height: var(--rk-h); display: flex; flex-direction: column;
  align-items: center; justify-content: center; background: var(--divider);
  outline: 1px solid var(--ledger-line); outline-offset: -1px; }
.em-rk-num { font-family: var(--font-display); font-weight: 900; font-size: 19px; line-height: 1; color: var(--ink); }

.em-rk-cards { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; position: relative; }
.em-rk-row { height: var(--rk-h); min-width: 0; display: flex; align-items: stretch; gap: 9px;
  background: var(--certificate); border: 1px solid var(--ink); padding: 6px 9px; }
/* §100 — the frozen row. The §89 verdict boxes are deliberately NOT muted below:
   on a settled game the green or the red IS the information, and dimming it would
   take the result off the row to restate what the tan and the padlock already say. */
.em-rk-row.locked { background: var(--lock-row); }
.em-rk-numslot.is-locked { background: var(--lock-slot); }
.em-rk-numslot.is-locked .em-rk-num { color: var(--lock-ink); }
/* Drag-to-reorder feedback (§8). Without these Sortable falls back to leaving the
   dragged row itself in the list, so the team shows twice at the target slot.
   Ghost = an empty white slot with a dashed outline ("lands here"); drag = the
   lifted element under the finger, using the system's one lift shadow. */
.em-rk-row.sortable-ghost { background: #fff; border: 1px dashed var(--money-green); }
.em-rk-row.sortable-ghost > * { visibility: hidden; }
.em-rk-row.sortable-drag { background: var(--certificate); border: 1px solid var(--money-green);
  box-shadow: var(--shadow-lift); opacity: 0.97; }

.game-wrapper-inner { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 4px; }
/* 3-track meta: spread pinned left, No-pick centered, schedule/score pinned right
   (fixed tracks so the schedule line never shifts when the No-pick stamp toggles). */
.em-rk-meta { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px; min-height: 15px; }
.em-rk-time { grid-area: 1 / 3; justify-self: end; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--ink); }
.em-rk-spread { grid-area: 1 / 1; justify-self: start; font-family: var(--font-mono); font-size: 11px; color: var(--ink); }
.is-permanent-score { grid-area: 1 / 3; justify-self: end; font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--ink); }
/* live game clock / "Final" tag, centered between spread and score.
   Named -gamestatus (not -status) so it can't collide with the header (§33 — it
   was silently overriding the old .em-rk-status line, now replaced by §94's
   .em-rk-meta; the name stays distinct so the collision can't come back). */
.em-rk-gamestatus { grid-area: 1 / 2; justify-self: center; font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--faded-ink); white-space: nowrap; }
.em-rk-gamestatus.live { color: var(--money-green); }
.em-rk-nopick { grid-area: 1 / 2; justify-self: center; display: none; font-family: var(--font-mono); font-size: 8px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); border: 1px solid var(--ledger-line); padding: 1px 5px; }
.em-rk-row.rk-unpicked .em-rk-nopick { display: inline-block; }
/* §100 — the LOCKED chip takes the centre track, the slot `No pick` occupies on an
   unpicked row. The two can't collide: updateCounter() only ever sets .rk-unpicked
   on a row that is NOT locked, so an unranked locked game shows the chip and not
   the stamp. Final / the live clock share the track too, and win it — see the
   template for why. */
.em-rk-lockchip { grid-area: 1 / 2; justify-self: center; font-family: var(--font-mono);
  font-size: 8px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--lock-ink);
  background: var(--lock-slot); border: 1px solid var(--lock-line); padding: 1px 5px;
  white-space: nowrap; }

.em-rk-teams { display: flex; gap: 6px; }
/* §99 — away/home read explicitly rather than by position alone. #B9B29C is a
   border tint, used for text only here: the @ carries nothing a member has to
   read, so it deliberately sits below the contrast floor the rest of the type
   holds to, and must not compete with either abbreviation. */
.em-rk-at {
  align-self: center;
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  color: #B9B29C;
}
.team-box-rank { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px;
  padding: 7px 8px; background: var(--certificate); border: 1px solid var(--ledger-line);
  cursor: pointer; text-align: left; }
.team-box-rank img { width: 16px; height: 16px; border-radius: 50%; object-fit: cover; flex-shrink: 0; background: var(--divider); }
.team-box-rank strong { font-family: var(--font-mono); font-size: 12px; font-weight: 500; color: var(--ink); }
/* Neutral (ink) check — it marks who WON, and green must stay reserved for YOUR
   correct pick, so a game you lost carries no green. */
.team-box-rank .rk-check { display: none; margin-left: auto; font-family: var(--font-mono);
  font-size: 16px; font-weight: 700; line-height: 1; color: var(--ink); }
/* your pick (open / in-progress / tie) — green highlights your selection. */
.team-box-rank.selected-rank { background: var(--green-wash); border-color: var(--money-green); }
.team-box-rank.selected-rank strong { font-weight: 700; color: var(--money-green); }
/* the team that WON a finished game — a checkmark only, no colour: green is for
   your correct pick, not for a winner you didn't take. */
.team-box-rank.winner-team strong { font-weight: 700; }
.team-box-rank.winner-team .rk-check { display: block; }
/* your CORRECT pick — the one green box on a settled game, checkmark included. */
.team-box-rank.winning-rank { background: var(--green-wash); border: 2px solid var(--money-green); }
.team-box-rank.winning-rank strong { color: var(--green-deep); font-weight: 700; }
/* your losing pick — bold, red frame, no check */
.team-box-rank.lost-rank { border: 2px solid var(--void-red); background: rgba(198, 59, 47, 0.1); }
.team-box-rank.lost-rank strong { color: var(--void-red); font-weight: 700; }
.team-box-rank.lost-rank .rk-check { display: none; }
/* §100 — the pick is inert (the row also drops the handler, and save_confidence
   rejects a changed pick on a started game server-side, so the appearance is the
   last of three guards rather than the only one). */
.em-rk-row.locked .team-box-rank { cursor: default; }
.em-rk-row.locked .team-box-rank:not(.selected-rank):not(.winning-rank):not(.lost-rank) {
  background: var(--lock-off); border-color: var(--lock-line); }
.em-rk-row.locked .team-box-rank:not(.selected-rank):not(.winning-rank):not(.lost-rank) strong {
  color: var(--lock-off-fg); }
.em-rk-row.locked .team-box-rank.selected-rank {
  background: var(--lock-pick); border-color: var(--lock-pick-bd); }
.em-rk-row.locked .team-box-rank.selected-rank strong { color: var(--lock-pick-fg); }

/* Control column: nudge up / grip / nudge down */
.em-rk-ctrl { width: 30px; flex-shrink: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: space-between; }
.em-rk-nudge { width: 30px; height: 22px; font-family: var(--font-mono); font-size: 12px;
  color: var(--faded-ink); padding: 0; line-height: 1; }
.em-rk-nudge:disabled { color: var(--nudge-off); cursor: default; }
.em-rk-grip { width: 30px; height: 30px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 3px; cursor: grab; touch-action: none; }
.em-rk-grip span { width: 14px; height: 1px; background: var(--disabled-txt); display: block; }
/* §100 — the padlock takes the 30px gutter the nudges vacate, so the row's width
   and grid are untouched. Two nested spans: no icon font, no SVG. 1.5px --ink and
   not 1px --disabled-txt — the first pass was too faint to read at 30px wide
   (Ryan, 2026-09-09: "can you bold this black"). The drawn lock is decoration to a
   screen reader; the span carries role="img" and aria-label="Locked". */
.em-rk-row.locked .em-rk-ctrl { justify-content: center; }
.em-rk-lock { display: block; position: relative; width: 12px; height: 10px;
  border: 1.5px solid var(--ink); border-top: none; }
.em-rk-lock > span { display: block; position: absolute; left: 2px; top: -5.5px;
  width: 6px; height: 5.5px; border: 1.5px solid var(--ink); border-bottom: none;
  border-radius: 3.5px 3.5px 0 0; }

/* MNF tiebreaker */
.em-rk-mnf { border: 1px solid var(--ink); background: var(--certificate); padding: 16px;
  text-align: center; margin-top: 18px; }
.em-rk-mnf .lbl { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--faded-ink); margin-bottom: 4px; }
.em-rk-mnf .sub { font-family: var(--font-body); font-size: 12px; color: var(--faded-ink); margin-bottom: 10px; }
/* §45 — MNF lockup: two team crests flanking the licensed shield. The shield is
   the event mark and dominates (46px vs 34px crests); it is used as supplied and
   never recoloured or cropped. */
.em-tb-lockup { display: flex; align-items: center; justify-content: center; gap: 14px;
  margin: 11px 0 9px; }
.em-tb-lockup .team { width: 34px; height: 34px; border-radius: 50%; object-fit: cover;
  background: var(--divider); flex-shrink: 0; }
.em-mnf-mark { width: 62px; height: 62px; object-fit: contain; flex-shrink: 0; }
.em-rk-mnf input { width: 110px; text-align: center; font-family: var(--font-mono); font-weight: 600;
  font-size: 24px; color: var(--ink); border: 1px solid var(--ledger-line); background: var(--paper);
  padding: 8px 10px; outline: none; }
.em-rk-mnf input:focus { border-color: var(--money-green); box-shadow: inset 0 0 0 1px var(--money-green); }
.em-rk-mnf input:disabled { color: var(--faded-ink); background: var(--desk); }

/* §94e — the sticky save footer is deleted; the §94a slot is the only save. */

/* §101 — the committing action at the foot of the screen, under the tiebreaker.
   Three states off the header slot's own guard. No pulse: §91b's animation is on
   the slot, and two pulsing controls on one screen compete. */
.em-rk-submitwrap { margin-top: 12px; }
.em-rk-submitwrap[hidden] { display: none; }
.em-rk-submit { width: 100%; padding: 14px; font-family: var(--font-mono);
  font-weight: 600; font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase;
  background: var(--desk); color: var(--disabled-txt); border: 1px solid var(--ledger-line);
  box-shadow: none; cursor: not-allowed; }
.em-rk-submit.is-live { background: var(--money-green); color: var(--paper);
  border: 1px solid var(--green-deep); box-shadow: var(--shadow-btn); cursor: pointer; }
/* The shadow stays put, so the button presses INTO it — the same press every other
   offset-shadow button in the app uses. Live state only. */
.em-rk-submit.is-live:active { transform: translate(2px, 2px); }
.em-rk-submit.is-filed { background: none; color: var(--money-green);
  border: 1px solid var(--money-green); box-shadow: none; cursor: default; }
/* A greyed button with no reason beside it is a dead end: the hint names the one
   thing in the way, and is rendered only while the button is disabled. */
.em-rk-submithint { margin-top: 8px; text-align: center; font-family: var(--font-mono);
  font-size: 10px; color: var(--faded-ink); }
.em-rk-submithint[hidden] { display: none; }

/* Fully-locked banner */
.em-rk-lockbanner { border: 1px solid var(--void-red); color: var(--void-red);
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; text-align: center; padding: 8px; margin-bottom: 14px; }

/* ============================================================
   Live Hub — Live Scoreboard + the What-If engine
   ============================================================ */
.em-lv-controls { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 12px 0 14px; }
.em-lv-refresh { font-family: var(--font-body); font-size: 13px; color: var(--faded-ink); }
.em-lv-refresh b { color: var(--ink); font-weight: 600; }
.em-lv-refresh b.paused { color: var(--money-green); }
/* §49 — partial-slate What-If scope note. */
.em-lv-scope { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--faded-ink); border: 1px dashed var(--ledger-line);
  padding: 7px 10px; margin: 0 0 14px; }

/* Compact button (What-If toggle) */
.em-btn--sm { padding: 10px 16px; min-height: 0; font-size: 12px; }

/* Legend (shown when not in What-If mode) */
.em-lv-legend { display: flex; flex-wrap: wrap; gap: 11px 16px; padding: 11px 0;
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); margin-bottom: 18px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-lv-legend .item { display: inline-flex; align-items: center; gap: 7px; }
.em-lv-legend .sw { width: 11px; height: 11px; flex-shrink: 0; }
.em-lv-legend .sw--pick { background: var(--green-wash); border: 1px solid var(--money-green); }
.em-lv-legend .sw--won { background: var(--money-green); }
.em-lv-legend .sw--lost { background: var(--void-red); }
.em-lv-legend .sw--live { border-radius: 50%; background: var(--money-green); }

/* What-If callout (shown in What-If mode) */
.em-lv-callout { background: var(--green-wash); border: 1px solid var(--money-green);
  padding: 11px 14px; margin-bottom: 18px; font-family: var(--font-body); font-size: 13px;
  line-height: 1.45; color: var(--ink); }

/* Section dividers */
.em-lv-sec { display: flex; align-items: center; gap: 10px; margin: 2px 0 12px; }
.em-lv-sec.spaced { margin-top: 26px; }
.em-lv-sec .lbl { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-lv-sec .lbl.live { color: var(--money-green); }
.em-lv-sec .rule { flex: 1; border-top: 1px dotted var(--ledger-line); }

.em-lv-list { display: flex; flex-direction: column; gap: 12px; }
/* §21 — the "Settled" header already says these are done; don't also dim them
   (dimming made a loss read as less visible than a win). Verdict now = a fill. */
.em-lv-list--settled { opacity: 1; }

/* Game card */
.em-lv-card { background: var(--certificate); border: 1px solid var(--ink); padding: 12px 14px; }
.em-lv-cardhead { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.em-lv-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--money-green); flex-shrink: 0; }
/* §69 — the tracking only reads as deliberate on caps; uppercasing here also makes
   FINAL (from the model status) render like the template-built LIVE variants. */
.em-lv-status { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; color: var(--faded-ink); text-transform: uppercase; }
.em-lv-status.live, .em-lv-status.sched { color: var(--ink); }
.em-lv-situation { display: inline-block; font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.05em; color: var(--faded-ink); border: 1px solid var(--ledger-line);
  padding: 2px 7px; margin-bottom: 8px; }
.em-lv-situation.redzone { color: var(--void-red); border-color: var(--void-red); }

/* Score row — the What-If tap target */
.score-row { display: flex; align-items: center; gap: 9px; padding: 7px 8px; width: 100%;
  background: transparent; border: none; text-align: left; }
.what-if-mode-active .score-row.what-if-toggle { cursor: pointer; }
.em-lv-bar { width: 3px; align-self: stretch; min-height: 20px; background: transparent; flex-shrink: 0; }
.team-box { display: flex; align-items: center; gap: 8px; min-width: 0; flex-shrink: 0; }
.team-box img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover;
  background: var(--divider); flex-shrink: 0; }
.team-abbr { font-family: var(--font-mono); font-size: 15px; color: var(--ink); }
/* Possession = a little football, sitting after the pick-number chip (order:1) */
.possession-indicator { order: 1; width: 16px; height: 12px; flex-shrink: 0; font-size: 0;
  background: center / contain no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 14'%3E%3Cpath d='M1.8 7 C3 3.6 6.5 1.6 10 1.6 C13.5 1.6 17 3.6 18.2 7 C17 10.4 13.5 12.4 10 12.4 C6.5 12.4 3 10.4 1.8 7 Z' fill='%237B4A26'/%3E%3Cg stroke='%23F7F3E8' stroke-width='1.1' stroke-linecap='round'%3E%3Cline x1='7.4' y1='7' x2='12.6' y2='7'/%3E%3Cline x1='8.6' y1='5.5' x2='8.6' y2='8.5'/%3E%3Cline x1='10' y1='5.3' x2='10' y2='8.7'/%3E%3Cline x1='11.4' y1='5.5' x2='11.4' y2='8.5'/%3E%3C/g%3E%3C/svg%3E"); }
.confidence-chip { font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  color: var(--faded-ink); border: 1px solid var(--ledger-line); padding: 1px 5px; }
.em-lv-whatif-tag { display: none; font-family: var(--font-mono); font-size: 8px;
  letter-spacing: 0.1em; color: var(--money-green); border: 1px solid var(--money-green); padding: 2px 5px; }
/* Down & distance for the team with the ball — centered in the row's open space */
.em-lv-dd { flex: 1 1 auto; min-width: 0; text-align: center; font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.03em; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.em-lv-dd.redzone { color: var(--void-red); font-weight: 600; }
/* Placeholder shown live when ESPN has no ball situation (post-score, pre-kickoff). */
.em-lv-await { margin-left: auto; min-width: 0; font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.03em; font-style: italic; color: var(--faded-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.score { margin-left: auto; flex-shrink: 0; font-family: var(--font-mono); font-size: 20px; color: var(--ink); font-weight: 400; }
.score.dot { color: var(--consensus); }
.score.winning-score { font-weight: 700; }
.em-lv-divider { height: 1px; background: var(--divider); margin: 0 8px; }
.em-lv-proj { display: none; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em;
  color: var(--faded-ink); padding: 8px 8px 2px; }
.what-if-mode-active .em-lv-proj { display: block; }
.em-lv-proj.gain { color: var(--money-green); }
.em-lv-proj.bust { color: var(--void-red); }

/* Row states — driven by JS class hooks (markUserPicks / what-if selection) */
.score-row.pz-row--picked .em-lv-bar,
.score-row.pz-row--won .em-lv-bar,
.score-row.pz-row--whatif .em-lv-bar { background: var(--money-green); }
.score-row.pz-row--lost .em-lv-bar { background: var(--void-red); }
.score-row.pz-row--won .team-abbr { color: var(--money-green); font-weight: 700; }
.score-row.pz-row--won .confidence-chip { color: var(--money-green); border-color: var(--money-green); }
.score-row.pz-row--lost .team-abbr { color: var(--void-red); }
.score-row.pz-row--lost .confidence-chip { color: var(--void-red); border-color: var(--void-red); }
.score-row.pz-row--picked .confidence-chip { color: var(--money-green); border-color: var(--money-green); }
/* §21 — a settled verdict on YOUR pick row gets a background tint (same idea as
   the grid's correct/wrong cells). Only your pick's row is tinted; the winning
   team is already shown by .winning-score. */
.score-row.pz-row--won  { background: rgba(21,122,74,0.14); }
.score-row.pz-row--lost { background: rgba(198,59,47,0.14); }
/* §21 — What-If is provisional, so outline the row rather than fill it: fill=final,
   outline=in-progress, matching the rest of the system. A projection that busts
   your pick outlines red. Use outline (not border) so selection doesn't shift the row. */
/* §89 — a tied final has no winner, so BOTH rows carry the loss, not just the one
   you staked: this is the only card that shows both teams, and reddening only your
   row would make a tie look like an ordinary final you happened to lose. Weight
   still marks your stake (700 against 500); colour no longer does. Card-level, so
   it holds for a member who never picked the game — the tie is a fact about it. */
.em-lv-card.is-tie .score-row { background: rgba(198,59,47,0.14); }
.em-lv-card.is-tie .em-lv-bar { background: var(--void-red); }
.em-lv-card.is-tie .team-abbr { color: var(--void-red); font-weight: 500; }
.em-lv-card.is-tie .score-row.pz-row--lost .team-abbr { font-weight: 700; }
.em-lv-card.is-tie .confidence-chip { color: var(--void-red); border-color: var(--void-red); }
.score-row.pz-row--whatif { background: transparent; outline: 2px solid var(--money-green); outline-offset: -2px; }
.score-row.pz-row--whatif.is-bust { outline-color: var(--void-red); }
.score-row.pz-row--whatif .em-lv-whatif-tag { display: inline-block; }
.score-row.pz-row--whatif .team-abbr { font-weight: 700; }

/* §70b — Hypothetical Standings sheet: a full-bleed overlay opened from the pinned
   impact bar. Pinned `fixed` to the app column (max-width, centred) rather than the
   spec's `absolute; inset:0`, because this app scrolls the window — absolute would
   size to the whole tall document instead of the viewport. z-index clears the tab
   bar (21) so it's a true overlay. */
.em-hypo-sheet { position: fixed; top: 0; bottom: 0; left: 0; right: 0; margin: 0 auto;
  width: 100%; max-width: 430px; z-index: 30; display: flex; flex-direction: column;
  background: var(--paper); border-left: 1px solid var(--ink); border-right: 1px solid var(--ink);
  animation: em-hypo-in 0.25s ease; }
.em-hypo-sheet[hidden] { display: none; }
@keyframes em-hypo-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
/* Header — same --certificate band + 1px ink rule as .em-screen-head (§70b). */
.em-hypo-head { display: flex; justify-content: space-between; align-items: flex-start;
  padding: 18px 20px 12px; border-bottom: 1px solid var(--ink); background: var(--certificate); }
.em-hypo-kicker { letter-spacing: 0.2em; color: var(--money-green); }
.em-hypo-x { background: none; border: 1px solid var(--ink); padding: 6px 11px; line-height: 1;
  font-family: var(--font-mono); font-size: 13px; color: var(--ink); cursor: pointer; }
.em-hypo-body { flex: 1; overflow-y: auto; padding: 16px 20px 22px; }
.em-hypo-callout { background: var(--green-wash); border: 1px solid var(--money-green);
  padding: 12px 14px; margin-bottom: 18px; font-family: var(--font-body); font-size: 13px;
  line-height: 1.5; color: var(--ink); }
.em-hypo-callout .gain { color: var(--money-green); }
/* Table label on --paper, dotted rule to the right edge (§57 pattern). */
.em-hypo-tlabel { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
.em-hypo-tlabel > span:first-child { font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.16em; text-transform: uppercase; }
.em-hypo-tlabel--wk > span:first-child { color: var(--money-green); }
.em-hypo-tlabel .rule { flex: 1; border-top: 1px dotted var(--ledger-line); }
.em-hypo-body .em-lv-proj-table { margin-bottom: 22px; }
/* §70b — the member's own row runs its rank in money-green inside the sheet. */
.em-hypo-body .em-lv-proj-row.is-you .rk { color: var(--money-green); }

/* §11 — pinned What-If impact bar, so a tap and its consequence are on screen
   together. NOTE: pinned at `bottom: 42px` (the tab bar's height) rather than the
   spec's `bottom: 0`: this app scrolls the window, and the tab bar is itself
   sticky at bottom:0, so bottom:0 here would hide the bar behind it. */
/* §70a — the bar is now a <button> that opens the sheet; reset the button chrome
   (full width, left-aligned, inherited type, no side borders) so it reads as the bar. */
/* §104 — FIXED, not sticky. The bar has to sit over the list with the tap that
   produced it, which is the whole reason §11 made it a bar; sticky was the right
   intent and could never fire here. Two independent reasons, either alone enough:
   the bar is the LAST in-flow child of .em-screen, and a sticky box cannot be
   offset past the bottom edge of its own containing block — `bottom: 42px` had
   nothing left to slide against; and .em-screen's `overflow-y: auto` never
   engages, because the min-height shell means the WINDOW scrolls (the §83 comment
   at the top of this file says so), so the scrollport it resolved against never
   moved. .em-tabbar works by contrast because its containing block is .em-app,
   which runs to the bottom of the document.
   This is .em-hypo-sheet's pattern (below), and the template comment on that
   sheet already named "the impact bar's bottom:42px" as the same environment
   note — it was written beside the element that needed it and never applied.
   The old `width: calc(100% + 24px)` / `margin: 14px -12px 0` pair is DELETED,
   not kept: that is the edge-to-edge trick that cancels .em-screen's 12px padding
   (the pattern line 318 names), and a fixed box is no longer inside that padding,
   so the same two declarations would make the bar 24px wider than the column and
   hang it 12px off each edge.
   z-index 19: under .em-tabbar (21) and well under .em-hypo-sheet (30), so the
   sheet still covers the bar that opened it. */
.em-lv-impact { position: fixed; left: 0; right: 0;
  /* 42px is the tab bar's height, which now grows by the bottom inset — without
     the calc the bar would sit BEHIND the tab bar on every Face ID phone, i.e.
     §104 would regress on exactly the devices the members use. */
  bottom: calc(42px + env(safe-area-inset-bottom)); margin: 0 auto;
  width: 100%; max-width: 430px; z-index: 19;
  background: var(--certificate); border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink); border-left: 0; border-right: 0;
  text-align: left; font: inherit; color: inherit;
  cursor: pointer; -webkit-appearance: none; appearance: none;
  padding: 11px 14px 12px; display: none; }
.what-if-active .em-lv-impact { display: block; }
/* §104 — out of flow means the last game card ends underneath it. 150px = 42 (tab
   bar) + ~96 (the bar at its tallest, over a `full` slate where `See standings`
   renders; ~86 over a `partial` one) + 12 (the screen's own gap). Gated on the
   same class that gates the bar's display, so the floor appears and disappears
   with it and no other screen is touched. */
.what-if-active .em-screen { padding-bottom: 150px; }
.em-lv-impact .top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.em-lv-impact .rt { text-align: right; }
/* §70a — "See standings ▾", under the movement line and right-aligned with it. */
.em-lv-impact .more { display: block; margin-top: 5px; font-family: var(--font-body);
  font-weight: 600; font-size: 10px; color: var(--money-green); }
.em-lv-impact .impact-clear { background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--font-body); font-weight: 600; font-size: 12px; color: var(--money-green); }
.em-lv-impact .k { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-lv-impact .v { font-family: var(--font-display); font-weight: 900; font-size: 28px;
  line-height: 1; color: var(--money-green); }
.em-lv-impact .v small { font-family: var(--font-mono); font-size: 11px; font-weight: 400;
  color: var(--faded-ink); }
.em-lv-impact .moves { font-family: var(--font-mono); font-size: 11px; text-align: right;
  color: var(--ink); white-space: nowrap; }
.em-lv-impact .moves .up { color: var(--money-green); font-weight: 600; }
.em-lv-impact .moves .down { color: var(--void-red); font-weight: 600; }
.em-lv-impact .bot { display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-top: 7px; font-family: var(--font-mono); font-size: 10px; color: var(--faded-ink); }
.em-lv-proj-table { border: 1px solid var(--ink); background: var(--certificate); }
.em-lv-proj-row { display: grid; grid-template-columns: 42px 1fr 54px; align-items: center;
  padding: 9px 14px; border-bottom: 1px dotted var(--ledger-line); }
.em-lv-proj-row:last-child { border-bottom: none; }
.em-lv-proj-row.is-you { background: var(--green-wash); }
.em-lv-proj-row .rk { font-family: var(--font-mono); font-weight: 600; font-size: 13px; letter-spacing: -0.02em; color: var(--faded-ink); }
.em-lv-proj-row.is-you .rk { color: var(--ink); }
.em-lv-proj-row .nm { font-family: var(--font-body); font-size: 14px; color: var(--ink); }
.em-lv-proj-row.is-you .nm { font-weight: 700; }
.em-lv-proj-row .pt { text-align: right; font-family: var(--font-mono); font-size: 14px; color: var(--ink); }
.em-lv-empty { font-family: var(--font-body); font-size: 14px; color: var(--faded-ink); }

/* ============================================================
   The League Board — Full Grid (the picks matrix)
   ============================================================ */
.em-grid-wrap { position: relative; overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
  border: 1px solid var(--ink); background: var(--certificate); }
.em-grid { border-collapse: separate; border-spacing: 0; width: max-content; }
.em-grid th, .em-grid td { border-right: 1px solid var(--divider); border-bottom: 1px dotted var(--ledger-line);
  padding: 7px 8px; text-align: center; min-width: 74px; vertical-align: middle; }
.em-grid thead th { position: sticky; top: 0; z-index: 5; background: var(--paper);
  border-bottom: 1px solid var(--ink); font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--faded-ink); }
.em-grid .gm { display: block; font-family: var(--font-mono); font-size: 9px; font-weight: 600;
  color: var(--ink); margin-bottom: 3px; }
.em-grid .gm-logos { display: flex; justify-content: center; align-items: center; gap: 4px; }
.em-grid .gm-logos img { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; background: var(--divider); }

/* Sticky member + score columns */
/* §64a — the frozen Member/Pts block is chrome, not matrix data: it sits on --paper
   (matching the header rail), so the certificate body is the only stock that reads as
   "picks". §64d — long names (e.g. Caroline+Ellies Mom) wrap to two lines at 11px inside
   the .nm clamp rather than truncating, which in a 61-member league can mis-identify a row. */
.em-grid .col-user { position: sticky; left: 0; z-index: 10; background: var(--paper);
  text-align: left; min-width: 104px; width: 104px; max-width: 104px; border-right: none;
  white-space: normal; word-break: break-word; line-height: 1.15;
  font-family: var(--font-body); font-size: 11px; font-weight: 600; color: var(--ink); }
.em-grid td.col-user .nm { display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.em-grid .col-score { position: sticky; left: 104px; z-index: 10; background: var(--paper);
  min-width: 46px; width: 46px; border-right: 1px solid var(--ink);
  font-family: var(--font-mono); font-weight: 600; color: var(--money-green); }
.em-grid thead .col-user, .em-grid thead .col-score { z-index: 20; background: var(--paper); }
.em-grid .row-you .col-user { box-shadow: inset 3px 0 0 var(--money-green); font-weight: 700; }

/* Pick cells */
.em-grid .cell img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover;
  background: var(--divider); vertical-align: middle; }
.em-grid .cell .cf { font-family: var(--font-mono); font-weight: 600; font-size: 12px; color: var(--faded-ink); margin-left: 4px; }
.em-grid td.correct { background: var(--green-wash); }
.em-grid td.correct .cf { color: var(--money-green); }
.em-grid td.wrong { background: rgba(198, 59, 47, 0.09); }
.em-grid td.wrong .cf { color: var(--void-red); }
/* Live cells (§65) — a single 11px bottom-right corner flag, never a fill, so a
   live game reads as provisional without a settled cell's tint. One slot for all
   three states; only the hue changes. Painted as a background-image so the cell's
   box, 74px track width and borders are untouched and the column doesn't shift
   when a game goes live. */
.em-grid td.cell.live-winning { background-image: linear-gradient(315deg, var(--money-green) 0 11px, transparent 11px); }
.em-grid td.cell.live-losing { background-image: linear-gradient(315deg, var(--void-red) 0 11px, transparent 11px); }
/* live and level — nobody is ahead, so neither colour is right; --faded-ink is the
   same weight class as the two colour flags (a light --ink tint vanishes at 11px). */
.em-grid td.cell.live-tied { background-image: linear-gradient(315deg, var(--faded-ink) 0 11px, transparent 11px); }
/* the confidence number carries the matching colour, ink on a tie */
.em-grid td.live-winning .cf { color: var(--money-green); }
.em-grid td.live-losing .cf { color: var(--void-red); }
.em-grid td.live-tied .cf { color: var(--ink); }
.em-grid .col-tb { background: var(--certificate); border-left: 1px solid var(--ink);
  min-width: 46px; font-family: var(--font-mono); font-size: 12px; }

/* Footer summary rows (sticky left columns only; not sticky-bottom in a window-scroll layout) */
.em-grid tfoot td { background: var(--paper); border-top: 1px solid var(--ink); }
.em-grid tfoot .col-user, .em-grid tfoot .col-score { background: var(--paper); }
.em-grid tfoot .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--faded-ink); text-align: left; }
.em-grid .stat-away { color: var(--faded-ink); border-bottom: 1px dotted var(--ledger-line);
  padding-bottom: 2px; font-family: var(--font-mono); font-size: 11px; }
.em-grid .stat-home { color: var(--ink); padding-top: 2px; font-family: var(--font-mono); font-size: 11px; }

/* sort affordance on the header cells. §64e — a single directional caret (▼ desc /
   ▲ asc) replaces the ambiguous ⇅: the active column is green with a full-opacity
   caret, the inactive one shows its default direction dimmed. Same treatment as the
   Ledger's .em-board-head, so the two boards read identically. */
.em-grid th.sortable { cursor: pointer; }
.em-grid th.sortable:hover { color: var(--money-green); }
.em-grid th.sortable .ar { font-size: 8px; opacity: 0.45; }
.em-grid th.sortable.is-active { color: var(--money-green); }
.em-grid th.sortable.is-active .ar { opacity: 1; }

/* ── §48 The League Board — sealed until kickoff ──────────────────────────── */

/* Eyebrow row: the kicker (left) and the seal stamp/count pushed to the right
   margin (§55b) — a rubber stamp reads as applied to the document, not a label. */
.em-eyebrow-row { display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 8px; }
/* §55c — a quiet grey kicker where the eyebrow already carries a red SEALED stamp,
   so there aren't two accent colours on one line before the title. */
.em-kicker--quiet { color: var(--faded-ink); }

/* State 1 — loud SEALED stamp; State 2 — quiet unsealed count (a status, not an alarm). */
.em-seal-stamp { font-family: var(--font-mono); font-weight: 600; font-size: 10px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--void-red);
  border: 2px solid var(--void-red); padding: 3px 9px; transform: rotate(-4deg);
  flex-shrink: 0; }
.em-seal-count { font-family: var(--font-mono); font-weight: 600; font-size: 9px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink);
  border: 1px solid var(--ledger-line); padding: 3px 8px; white-space: nowrap;
  flex-shrink: 0; }

/* State 1 — the centred sealed panel. */
.em-seal-panel { display: flex; flex-direction: column; align-items: center;
  text-align: center; padding: 34px 24px; }
.em-week-block { width: 64px; height: 64px; border: 2px solid var(--ink);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  margin-bottom: 20px; }
.em-week-block .wk { font-family: var(--font-mono); font-size: 8px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-week-block .no { font-family: var(--font-display); font-weight: 900; font-size: 28px;
  line-height: 1; color: var(--ink); }
.em-seal-title { font-family: var(--font-display); font-weight: 900; font-size: 26px;
  line-height: 1.08; color: var(--ink); margin-bottom: 10px; }
.em-seal-sub { font-family: var(--font-body); font-size: 14px; line-height: 1.5;
  color: var(--faded-ink); max-width: 262px; margin-bottom: 20px; }
.em-seal-status { width: 100%; max-width: 270px; border: 1px solid var(--ink);
  background: var(--certificate); margin-bottom: 20px; }
.em-seal-status .row { display: flex; justify-content: space-between; align-items: baseline;
  padding: 11px 14px; }
.em-seal-status .row + .row { border-top: 1px dotted var(--ledger-line); }
.em-seal-status .k { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-seal-status .v { font-family: var(--font-mono); font-weight: 600; font-size: 13px;
  color: var(--ink); }
.em-seal-status .v.money { color: var(--money-green); }

/* Secondary button — outline, not filled (the member is here early; offer the ranker). */
.em-btn--outline { background: transparent; color: var(--ink); border: 1px solid var(--ink);
  box-shadow: none; }
.em-btn--outline:hover { background: var(--green-wash); }

/* §103 — the SECOND CTA on Home's results phases. Same geometry as the primary
   and it KEEPS the offset shadow: the shadow is what makes it a button, the fill
   is what makes it THE button. Two filled greens stacked read as one action
   repeated, which is how the second card was first built and why it changed.
   Distinct from .em-btn--outline, which is the dialog button and is deliberately
   shadowless — sharing that rule would put a shadow on every confirm dialog. */
.em-btn--secondary { background: none; color: var(--ink); border: 1px solid var(--ink);
  box-shadow: var(--shadow-btn); }
.em-btn--secondary:hover { background: var(--green-wash); }
.em-btn--secondary:active { box-shadow: 1px 1px 0 var(--ink); transform: translate(2px, 2px); }

/* §103b/§103c — the card's corner badge: the board count, or Standings' WK/SZN
   pair on one line once that row is promoted to a card. */
.em-badge-corner { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em;
  color: var(--ink); border: 1px solid var(--ledger-line); padding: 3px 7px;
  white-space: nowrap; }
.em-badge-corner .k { color: var(--faded-ink); letter-spacing: 0.12em; }

/* State 2 — By Game sealed rows: dashed, dimmed, non-interactive. */
.em-sealed-list { margin-top: 6px; }
.em-gc-sealed { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; border: 1px dashed var(--ledger-line); padding: 11px 13px; margin-bottom: 8px; }
.em-gc-sealed .teams { display: flex; align-items: center; gap: 8px; min-width: 0; }
.em-gc-sealed .teams img { width: 22px; height: 22px; border-radius: 50%; object-fit: cover;
  background: var(--divider); opacity: 0.4; flex-shrink: 0; }
.em-gc-sealed .mu { font-family: var(--font-body); font-weight: 600; font-size: 13px;
  color: var(--faded-ink); white-space: nowrap; }
.em-gc-sealed .right { display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  flex-shrink: 0; }
.em-gc-sealed .chip { font-family: var(--font-mono); font-weight: 600; font-size: 8px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--void-red);
  border: 1px solid var(--void-red); padding: 2px 6px; }
.em-gc-sealed .ko { font-family: var(--font-mono); font-size: 9px; color: var(--ledger-line); }

/* State 2 — Full Grid: sealed column headers/cells greyed, one overlay stamp. */
.em-grid th.col-sealed, .em-grid th.col-sealed .gm { color: var(--ledger-line); }
.em-grid th.col-sealed .gm-logos { opacity: 0.4; }
.em-grid td.col-sealed { background: transparent; }
.em-grid .seal-dash { font-family: var(--font-mono); color: var(--consensus); }
.em-grid-seal { position: absolute; top: 46px; bottom: 0; z-index: 1;
  /* §72a — pixels from the run's start/count so each breakpoint uses its own tracks:
     phone = 150px frozen + 74px game cells. */
  left: calc(150px + var(--seal-start, 0) * 74px); width: calc(var(--seal-count, 0) * 74px);
  border-left: 1px dashed var(--ledger-line);
  background: rgba(122, 133, 125, 0.16); overflow: visible; }
/* The stamp tracks the horizontal scroll so it is always on screen. It sticks at
   158px (past the two frozen left columns — col-user 104 + col-score 46 = 150 —
   plus an 8px gap), not 8px: the frozen columns sit above the overlay (z-index
   10-20 vs 1), so a mark stuck at 8px slid underneath them, leaving only its tail
   visible. Sticking past their edge locks the whole stamp in view. */
.em-grid-seal .mark { position: sticky; left: 158px; width: 246px;
  display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 26px 0; }
.em-grid-seal .mark .stamp { font-family: var(--font-mono); font-weight: 600; font-size: 26px;
  letter-spacing: 0.26em; text-transform: uppercase; color: #3F4A43;
  border: 3px solid #3F4A43; padding: 11px 20px 11px 28px;
  transform: rotate(-4deg); white-space: nowrap; }
/* #3F4A43 is --ink read through the grey wash — the stamp and its caption sit on
   the same value, not a palette token. If the wash changes, this changes with it. */
.em-grid-seal .mark .cap { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.08em;
  text-transform: uppercase; color: #3F4A43; }

/* Emporium select (week picker) */
/* §35's week pill. `border-radius: 999px` restored 2026-09-17: the prototype
   carries it on all three of these selects and the original build dropped it, so
   §106's spec describes a pill the Ledger did not actually have. Corrected on the
   shared rule rather than only on the new controls — making the new ones round
   and leaving this one square would give the same component two looks, which is
   the opposite of what reusing it is for. This is the design's one deliberate
   exception to the sharp-corners rule; do not generalise it to other controls. */
.em-select { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
  border: 1px solid var(--ink); background: var(--certificate); color: var(--ink);
  padding: 7px 12px; border-radius: 999px; cursor: pointer; }
/* §106/§107 — the same pill one notch down, for rows it has to share. */
.em-select--sm { font-size: 10px; padding: 5px 9px; flex-shrink: 0; }

/* §106 — kicker + pill in one cell, so the seal chips keep their
   space-between position on the right of .em-eyebrow-row. */
.em-kicker--pick { display: inline-flex; align-items: center; gap: 8px; }
.em-weekform { display: flex; align-items: center; margin: 0; }
/* Visually-hidden label — the select needs an accessible name, and the kicker
   text beside it is not one. */
.em-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ============================================================
   §72 — wide-screen layouts (min-width: 1024px)
   Below 1024 NOTHING changes. The shell holds a constant 1024 width so
   switching tabs never resizes the frame; prose screens keep the 430
   column (centred, with side rails) and the three table screens opt in
   via .em-app--wide (+ a screen class) and release their content.
   ============================================================ */
/* The What-If badge must never wrap (it broke to WHAT-/IF in a narrow card). */
.em-lv-whatif-tag { white-space: nowrap; }
/* Card-level down & distance: only rendered into the wide Live Hub (below). */
.em-lv-dd--head { display: none; }
/* Ledger header cells that only exist in the wide (≥1024) column layout (§72c). */
.em-board-head .wide-h { display: none; }

@media (min-width: 1024px) {
  .em-app { max-width: 1024px; }

  /* Prose screens (Home, ranker): keep the 430 column, centred in the shell
     with the phone frame's ink-rail equivalent down each side. */
  /* `width:100%` is load-bearing, not belt-and-braces. .em-app is a flex column,
     and an auto left/right margin on a flex item disables the default stretch —
     the item then shrink-to-fits its CONTENT and only bumps into max-width if the
     content is wider. .em-screen's content is, so it sat at 430; the head's is not,
     so it sat at whatever its hero text measured (391px on Home) and rode ~20px
     inboard of the column beneath it. Being sticky, it then scrolled over the
     content as a visibly misaligned floating box. */
  .em-app:not(.em-app--wide) .em-screen-head,
  .em-app:not(.em-app--wide) .em-screen { width: 100%; max-width: 430px; margin-left: auto; margin-right: auto; }
  /* Side rails run the whole column, band included, so the two read as one edge. */
  .em-app:not(.em-app--wide) .em-screen-head,
  .em-app:not(.em-app--wide) .em-screen { border-left: 1px solid var(--divider); border-right: 1px solid var(--divider); }

  /* Tab bar: the ink bar spans the shell (anchored to the bottom edge), but the
     tabs cluster centred at their phone size rather than stretching across 1024. */
  .em-tabbar { justify-content: center; }
  .em-tab { flex: 0 0 auto; min-width: 108px; }
  /* Keep the What-If legend/prose to a measure too (it's chrome, not a game card). */
  .em-lv-wide .em-lv-legend { max-width: 560px; }

  /* ---- §72b — Live Hub ---- */
  /* Game lists go multi-column by WIDTH (not count), so cards stay near phone
     measure and the count grows with the display (3 at 1024, more when wider). */
  .em-lv-wide .em-lv-list { display: block; column-width: 300px; column-gap: 14px; }
  .em-lv-wide .em-lv-list .em-lv-card { break-inside: avoid; margin-bottom: 14px; }
  /* Prose keeps a readable measure rather than the full shell. */
  .em-lv-wide .em-lv-controls,
  .em-lv-wide .em-lv-scope,
  .em-lv-wide .em-lv-callout { max-width: 560px; }
  /* Impact bar: its border-top rule spans the shell; its contents cap + centre
     (both rows, including the Clear footer). */
  /* §104 + §72b — the bar is fixed now, so its own 430px cap would stop it
     spanning the wide shell. The 620px content caps below then centre the
     content inside a full-width bar, which is what §72b specified: the
     border-top is the full-width rule, the content is a measure. */
  .em-lv-wide .em-lv-impact { max-width: 1024px; }
  .em-lv-wide .em-lv-impact .top,
  .em-lv-wide .em-lv-impact .bot { max-width: 620px; margin-left: auto; margin-right: auto; }
  /* Down & distance moves onto the card's status line — the team row truncates
     it in the narrow card ("4th & Goal at ARI 2" -> "4th & Goal at ..."). */
  .em-lv-wide .em-lv-cardhead .em-lv-dd--head { display: inline-block; flex: 0 0 auto; }
  .em-lv-wide .score-row .em-lv-dd { display: none; }

  /* ---- §72a — Full Grid ---- */
  /* All 16 games fit at fixed tracks (148 member + 40 pts + 16x48 + 44 MNF = 1000),
     so the two-axis scroll and the frozen columns both go. Widths are fixed (not
     stretched) so the seal overlay lands exactly on its columns. */
  .em-board-wide .em-grid-wrap { overflow-x: visible; }
  /* table-layout:fixed so columns obey these exact widths (content can't push them
     wider) — that's what keeps the total inside 1024 AND the seal overlay aligned to
     its columns. 148 member + 40 pts + 16x46 game + 44 MNF = 968. */
  .em-board-wide .em-grid { table-layout: fixed; width: 968px; }
  .em-board-wide .em-grid td, .em-board-wide .em-grid th { padding: 7px 3px; }
  .em-board-wide .em-grid td.cell,
  .em-board-wide .em-grid thead th:not(.col-user):not(.col-score):not(.col-tb) { width: 46px; min-width: 0; }
  /* Member + Pts stop freezing (nothing scrolls under them anymore). */
  .em-board-wide .em-grid .col-user { position: static; left: auto;
    width: 148px; min-width: 0; max-width: none; padding-left: 8px; }
  .em-board-wide .em-grid .col-score { position: static; left: auto; width: 40px; min-width: 0; }
  .em-board-wide .em-grid .col-tb { width: 44px; min-width: 0; }
  /* Smaller header crests at the tighter cell width. */
  .em-board-wide .em-grid .gm-logos img { width: 14px; height: 14px; }
  /* Seal overlay: frozen block is now 148+40=188, cells 46. Recompute from the run
     indices, and let the stamp centre in the run (nothing to stick past). */
  .em-board-wide .em-grid-seal { left: calc(188px + var(--seal-start, 0) * 46px);
    width: calc(var(--seal-count, 0) * 46px); overflow: hidden; }
  /* Fit the stamp inside the run (its fixed 246px would spill past the grid and add
     a scrollbar); centre it, and scale the stamp down so a short run doesn't clip. */
  .em-board-wide .em-grid-seal .mark { position: static; left: auto; width: 100%; margin: 0; padding: 16px 0; }
  .em-board-wide .em-grid-seal .mark .stamp { font-size: 16px; letter-spacing: 0.14em;
    padding: 7px 10px; max-width: 100%; }

  /* ---- §72a-i — By Game cards go 3-up ---- */
  /* A real grid (not multi-column): the open card spans all three so its roll call
     gets full width, and align-items:start keeps the other rows from stretching. */
  .em-board-wide .em-gamecard-list { display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 12px; align-items: start; }
  .em-board-wide .em-gamecard-list .em-gamecard { margin-bottom: 0; }
  .em-board-wide .em-gamecard-list .em-gamecard.is-open { grid-column: span 3; }
  /* Inside the spanning card, the Avg-Confidence block is two bars, not a table. */
  .em-board-wide .em-gamecard.is-open .em-gc-conviction { max-width: 430px; }
  /* Compact tweaks for the narrower (~318px) card. */
  .em-board-wide .em-gamecard { padding: 11px 13px 12px; }
  .em-board-wide .em-consensus { height: 23px; }
  .em-board-wide .em-gamecard .gc-head { gap: 8px; }
  .em-board-wide .em-gc-meta { flex-wrap: wrap; }

  /* Board chrome + prose keep a measure — tables get the width, controls don't. */
  .em-board-wide .em-seg { max-width: 430px; }
  .em-board-wide .em-mtable-wrap { max-width: 560px; }
  .em-board-wide #board-top, .em-board-wide .em-jump { max-width: 560px; }

  /* ---- §72c — Ledger ---- */
  /* Table gets the width (capped, centred); the chrome and the ink band don't. */
  .em-ledger-wide .em-board-wrap { max-width: 1000px; margin-left: auto; margin-right: auto; }
  .em-ledger-wide .em-seg,
  .em-ledger-wide .em-ledger-controls { max-width: 430px; }
  .em-ledger-wide .em-standing > * { max-width: 620px; margin-left: auto; margin-right: auto; }
  /* The second row (§58) unpacks into real columns, so every row is one line again.
     display:contents lets the .sub's children join the row grid; each is placed
     explicitly so DOM order doesn't matter. Header padding is 1px wider than the rows
     (0 15 vs 0 14) because the head sits outside the box's 1px border. */
  .em-ledger-wide .em-board-head { padding: 0 15px 8px; }
  .em-ledger-wide .em-board-head .wide-h { display: block; }
  .em-ledger-wide .em-board-head .h-gap { text-align: right; }
  /* dense flow so Gap (which follows Pts/Hits in the DOM) backfills its column
     instead of wrapping to a second grid row. */
  .em-ledger-wide .em-board .row { padding: 9px 14px; grid-auto-flow: dense; }
  .em-ledger-wide .em-board .sub { display: contents; }
  .em-ledger-wide .em-board .sub .sub-stamp { margin-right: 0; justify-self: start; white-space: nowrap; }
  .em-ledger-wide .em-board .sub .mv { justify-self: start; }
  .em-ledger-wide .em-board .sub .gap { margin-left: 0; white-space: nowrap; }

  /* This Week: Rank · Member · Leader · Gap · Pts · Hits */
  /* §105 — one more track for Poss (the wide grids are explicit, so the
     narrow --poss variable does not reach them). */
  .em-ledger-wide .em-board-wrap--week .em-board-head,
  .em-ledger-wide .em-board-wrap--week .em-board .row { grid-template-columns: 52px minmax(0, 1fr) 76px 92px 58px 58px 58px; }
  .em-ledger-wide .em-board-wrap--week .h-rank,   .em-ledger-wide .em-board-wrap--week .row .rank { grid-column: 1; }
  .em-ledger-wide .em-board-wrap--week .h-member, .em-ledger-wide .em-board-wrap--week .row .name { grid-column: 2; }
  .em-ledger-wide .em-board-wrap--week .h-leader, .em-ledger-wide .em-board-wrap--week .row .sub-stamp { grid-column: 3; }
  .em-ledger-wide .em-board-wrap--week .h-gap,    .em-ledger-wide .em-board-wrap--week .row .gap { grid-column: 4; }
  /* Placed by [value], the way the season pair below is: the week board's three
     sort headers are BUTTONS, and .h-pts / .h-hits were classes no element ever
     carried. Poss had no rule at all, so .possval fell to auto placement — and
     with grid-auto-flow: dense on .row it backfilled the empty Leader track,
     printing the ceiling under the Leader stamp while the Poss column stood
     empty. Every track on this grid is now named by something that exists. */
  .em-ledger-wide .em-board-wrap--week button[value="pts"],  .em-ledger-wide .em-board-wrap--week .row .ptsval { grid-column: 5; }
  .em-ledger-wide .em-board-wrap--week button[value="hits"], .em-ledger-wide .em-board-wrap--week .row .hitsval { grid-column: 6; }
  .em-ledger-wide .em-board-wrap--week button[value="poss"], .em-ledger-wide .em-board-wrap--week .row .possval { grid-column: 7; }

  /* Season: Rank · Member · Move · Leader · Gap · Points · $ Won */
  .em-ledger-wide .em-board-wrap--season .em-board-head,
  .em-ledger-wide .em-board-wrap--season .em-board .row { grid-template-columns: 52px 1fr 62px 76px 92px 72px 82px; }
  .em-ledger-wide .em-board-wrap--season .h-rank,   .em-ledger-wide .em-board-wrap--season .row .rank { grid-column: 1; }
  .em-ledger-wide .em-board-wrap--season .h-member, .em-ledger-wide .em-board-wrap--season .row .name { grid-column: 2; }
  .em-ledger-wide .em-board-wrap--season .h-move,   .em-ledger-wide .em-board-wrap--season .row .mv { grid-column: 3; }
  .em-ledger-wide .em-board-wrap--season .h-leader, .em-ledger-wide .em-board-wrap--season .row .sub-stamp { grid-column: 4; }
  .em-ledger-wide .em-board-wrap--season .h-gap,    .em-ledger-wide .em-board-wrap--season .row .gap { grid-column: 5; }
  .em-ledger-wide .em-board-wrap--season button[value="pts"], .em-ledger-wide .em-board-wrap--season .row .ptsval { grid-column: 6; }
  .em-ledger-wide .em-board-wrap--season button[value="won"], .em-ledger-wide .em-board-wrap--season .row .won { grid-column: 7; }
}

/* ============================================================
   §74 — side bets (Ledger population control + strip/stake/footer)
   ============================================================ */
/* Chip row — reuses the segmented-control palette; wraps, never scrolls (§74j). */
.em-chiprow { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 11px; }
.em-chip { flex-shrink: 0; white-space: nowrap; font-family: var(--font-mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.06em; padding: 6px 11px; cursor: pointer;
  text-decoration: none; border: 1px solid var(--ink); background: var(--certificate); color: var(--faded-ink); }
.em-chip:first-child { letter-spacing: 0.1em; }
.em-chip.is-active { background: var(--money-green); color: var(--paper); border-color: var(--green-deep); }
/* §74c — stranded: red dashed, opens the fix dialog instead of filtering. */
.em-chip--stranded { background: #FBEDEA; border: 1px dashed var(--void-red); color: var(--void-red); }
/* §95 — a labelled chip, not a bare `+`: beside a filter chip a lone `+` reads as
   "add a filter", and the empty state is the one place a member has never seen a
   side-bet chip to generalise from. Dashed still reads as "make one". */
.em-chip-add { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  gap: 5px; min-height: 30px; padding: 0 10px; cursor: pointer; white-space: nowrap;
  border: 1px dashed var(--faded-ink); background: transparent; color: var(--faded-ink);
  font-family: var(--font-mono); font-weight: 600; font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; line-height: 1; }
.em-chip-add .pl { font-size: 14px; font-weight: 400; line-height: 1; }
.em-chip-add.at-start { margin-left: auto; }   /* only when there are no side bets (§74) */

/* Stake bar — SETTLED OFFLINE is permanent (§74). */
.em-stakebar { display: flex; align-items: flex-start; margin-top: 12px; padding: 9px 11px;
  border: 1px solid var(--ledger-line); background: #F4EFE2; }
.em-stakebar .stakes { font-family: var(--font-mono); font-weight: 600; font-size: 12px; color: var(--ink); }
.em-stakebar .meta { margin-left: auto; text-align: right; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--faded-ink); line-height: 1.5; }

/* Result strip — first block in the scroll area, four states (§74). */
.em-result { padding: 14px 20px 15px; border-bottom: 1px solid var(--ink); }
.em-result .rk { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-result .nm { font-family: var(--font-display); font-weight: 900; font-size: 21px; line-height: 1.05; margin-top: 2px; }
.em-result .sub { font-family: var(--font-body); font-size: 12px; color: var(--faded-ink); margin-top: 4px; }
.em-result--settled { background: var(--green-wash); }
.em-result--settled .nm { color: var(--money-green); }
.em-result--pending, .em-result--tied, .em-result--season { background: #F4EFE2; }
.em-result--pending .nm { color: var(--faded-ink); }
.em-result--tied .nm, .em-result--season .nm { color: var(--ink); }

/* Footer — membership management, one place at the bottom (§74). */
.em-sb-footer { display: flex; align-items: flex-start; gap: 12px;
  border-top: 1px dotted var(--ledger-line); padding-top: 14px; margin-top: 14px; }
.em-sb-footer .note { flex: 1; margin: 0; font-family: var(--font-body); font-size: 12px; color: var(--faded-ink); }
.em-sb-footer .actions { display: flex; flex-direction: column; gap: 6px; flex-shrink: 0; }
.em-sb-btn { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 7px 12px; background: transparent; cursor: pointer; white-space: nowrap; }
.em-sb-btn.add { border: 1px solid var(--ink); color: var(--ink); }
.em-sb-btn.leave { border: 1px solid var(--void-red); color: var(--void-red); }

/* §74 — create/add sheet + Leave/stranded dialogs */
.em-sb-sheet .em-input { width: 100%; padding: 10px 12px; border: 1px solid var(--ink);
  background: var(--certificate); color: var(--ink); font-family: var(--font-body); font-size: 15px; }
.em-sb-namewrap { position: relative; }
.em-sb-namewrap .em-input { padding-right: 58px; }
.em-sb-counter { position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  font-family: var(--font-mono); font-size: 10px; color: var(--faded-ink); pointer-events: none; }
/* §95b — the bet type. A second-level label under the STAKES rule, so the rule
   still heads the block and the dropdown reads as the first field inside it. */
.em-sb-sublabel { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faded-ink); margin: 0 0 6px; }
.em-sb-selectwrap { position: relative; margin-bottom: 8px; }
/* The right padding is part of ONE shorthand on purpose: split into `padding` plus
   a later `padding-right`, the room the chevron needs is the first thing a future
   rule overrides, and the label then runs under the arrow. */
.em-sb-select { width: 100%; padding: 10px 34px 10px 12px; border: 1px solid var(--ink);
  background: var(--certificate); color: var(--ink); font-family: var(--font-body);
  font-size: 15px; appearance: none; -webkit-appearance: none; border-radius: 0; }
/* CSS-drawn, not an inline-SVG data URI — one in a style attribute broke page
   rasterisation in review (2026-08-19). */
.em-sb-chev { position: absolute; right: 13px; top: 50%; width: 9px; height: 9px;
  margin-top: -6px; border-right: 1.5px solid var(--ink); border-bottom: 1.5px solid var(--ink);
  transform: rotate(45deg); pointer-events: none; }
/* One stake field gets the whole row; two share it. Grid rather than flex so the
   single-field case can't leave a half-width input beside dead space. */
.em-sb-stakes { display: grid; grid-template-columns: 1fr; gap: 8px; }
.em-sb-stakes.is-two { grid-template-columns: 1fr 1fr; }
.em-sb-stakes .em-input[hidden] { display: none; }
.em-sb-roster { border: 1px solid var(--ledger-line); }
.em-sb-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; cursor: pointer;
  border-bottom: 1px dotted var(--ledger-line); }
.em-sb-row:last-child { border-bottom: none; }
.em-sb-row .who { display: flex; flex-direction: column; }
.em-sb-row .dn { font-family: var(--font-body); font-size: 14px; color: var(--ink); }
.em-sb-row .rn { font-family: var(--font-body); font-size: 11px; color: var(--faded-ink); margin-top: 1px; }
.em-sb-row .cap { margin-left: auto; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: #9AA39B; }
.em-sb-row.at-cap { cursor: default; }
.em-sb-row.at-cap .dn { color: #9AA39B; }
.em-sb-row.at-cap .rn { color: var(--ledger-line); }
.em-sb-sheetfoot { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 20px; border-top: 1px solid var(--ink); background: var(--certificate); }

/* Bottom-anchored confirm dialogs (§74b/§74c) */
.em-sb-dialog-scrim { position: fixed; inset: 0; z-index: 40; background: rgba(28,43,36,0.55);
  display: flex; align-items: flex-end; justify-content: center; }
.em-sb-dialog-scrim[hidden] { display: none; }
.em-sb-dialog { width: 100%; max-width: 394px; margin: 0 18px 18px; padding: 19px 19px 17px;
  border: 1px solid var(--ink); background: var(--certificate); box-shadow: 5px 5px 0 rgba(28,43,36,0.35); }
.em-sb-dialog .k { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-sb-dialog .k.red { color: var(--void-red); }
.em-sb-dialog-btns { display: flex; gap: 8px; margin-top: 14px; }
.em-sb-dialog-btns > * { flex: 1; }
.em-sb-danger { background: var(--void-red); color: var(--paper); border: 1px solid #96271D; box-shadow: 3px 3px 0 var(--ink); }

/* ============================================================
   §96 — The Collective
   Gold is the third accent. Every figure on this screen is derived from the
   fund's own $ Won column, so nothing here is a stored total.
   ============================================================ */

/* §96c — the entry band on the Ledger. The only way in: above the fund table and
   INSIDE the scroll region, directly over the tinted rows it explains. The whole
   band is the tap target, not the arrow. */
.em-coll-band { width: 100%; display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 11px 13px; margin-bottom: 14px; background: var(--gold-wash); border: 1px solid var(--gold); }
.em-coll-band .lead { flex: 1; min-width: 0; }
.em-coll-band .k { display: block; font-family: var(--font-mono); font-weight: 600; font-size: 10px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--gold-text); }
.em-coll-band .sub { display: block; font-family: var(--font-body); font-size: 12px;
  color: var(--faded-ink); margin-top: 2px; }
.em-coll-band .net { flex-shrink: 0; text-align: right; }
.em-coll-band .net .k { font-weight: 400; font-size: 9px; letter-spacing: 0.12em; }
.em-coll-band .net .v { display: block; font-family: var(--font-mono); font-weight: 600;
  font-size: 17px; color: var(--gold-text); margin-top: 1px; }
.em-coll-band .arrow { flex-shrink: 0; font-family: var(--font-mono); font-size: 14px; color: var(--gold); }

/* §96d — members' rows on the fund table. `you` still wins; the template picks one
   class, so these never fight in source order. */
.em-board .row.is-coll { background: var(--gold-wash); }

/* §96e — the screen. */
.em-coll-back { display: inline-flex; align-items: center; gap: 6px; padding: 0; margin-bottom: 11px;
  font-family: var(--font-mono); font-weight: 600; font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-coll-kicker { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gold-text); }

/* The headline card — net first (the member's own number is what they came for),
   the pot as context beside it. */
.em-coll-head { background: var(--ink); color: var(--paper); padding: 18px 20px 17px; }
.em-coll-head .top { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; }
.em-coll-head .k { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gold-dim); }
.em-coll-head .net { font-family: var(--font-mono); font-weight: 600; font-size: 40px; line-height: 1;
  letter-spacing: -0.02em; color: var(--gold-on-ink); margin-top: 5px; }
.em-coll-head .pot-wrap { text-align: right; }
.em-coll-head .pot-wrap .k { letter-spacing: 0.14em; color: var(--on-ink-muted); }
.em-coll-head .pot { font-family: var(--font-mono); font-weight: 600; font-size: 22px;
  color: var(--paper); margin-top: 4px; }
.em-coll-head .note { font-family: var(--font-body); font-size: 12px; color: var(--on-ink-muted); margin-top: 12px; }

/* §96f — Progress to the line. One bar per member on a SHARED axis: the tick sits in
   the same place on every row, which is what makes clearing it read as crossing a
   threshold. Segments use flex:0 1 <pct> rather than width so a shrink at a rounding
   boundary can't push the hatch past the frame. */
.em-coll-bars { padding: 18px 20px 8px; }
.em-coll-bars .hd { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 11px; }
.em-coll-bars .hd .lbl, .em-coll-bars .hd .cleared { font-family: var(--font-mono); font-size: 9px;
  text-transform: uppercase; }
.em-coll-bars .hd .lbl { letter-spacing: 0.16em; color: var(--faded-ink); }
.em-coll-bars .hd .cleared { letter-spacing: 0.1em; color: var(--gold-text); }
.em-coll-bar { margin-bottom: 11px; }
.em-coll-bar .row { display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; margin-bottom: 4px; }
.em-coll-bar .nm { font-family: var(--font-body); font-size: 13px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.em-coll-bar .fig { flex-shrink: 0; font-family: var(--font-mono); font-weight: 600; font-size: 13px; color: var(--ink); }
/* The figure is text: ink unless clearing the line has earned it the gold. */
.em-coll-bar.is-cleared .fig { color: var(--gold-text); }
.em-coll-bar .track { position: relative; height: 12px; background: var(--divider); }
.em-coll-bar .fill { position: absolute; inset: 0; display: flex; }
.em-coll-bar .solid { min-width: 0; background: var(--gold); }
.em-coll-bar .hatch { min-width: 0;
  background: repeating-linear-gradient(45deg, var(--gold) 0 3px, var(--gold-hatch) 3px 6px); }
/* The line OVERSHOOTS the bar top and bottom — that is what makes it read as a
   threshold rather than the edge of a segment. */
.em-coll-bar .tick { position: absolute; top: -3px; bottom: -3px; width: 1px; background: var(--ink); }
.em-coll-axis { position: relative; height: 12px; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--faded-ink); }
.em-coll-axis .zero { position: absolute; left: 0; }
.em-coll-axis .line { position: absolute; transform: translateX(-50%); white-space: nowrap; color: var(--gold-text); }
.em-coll-axis .max { position: absolute; right: 0; }

/* §96g — the breakdown. A share renders on EVERY row, including members who have
   cleared nothing: they still collect, and that is the whole arrangement. */
.em-coll-list { padding: 14px 20px 4px; }
.em-coll-grid { display: grid; grid-template-columns: 1fr 52px 52px; gap: 8px; }
/* §57 — column labels are annotations: they float on --paper outside the box. */
.em-coll-list .hd { padding: 0 13px 7px; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--faded-ink); }
.em-coll-list .hd .num { text-align: right; }
.em-coll-list .box { border: 1px solid var(--ink); background: var(--certificate); }
.em-coll-list .item { border-bottom: 1px dotted var(--ledger-line); padding: 10px 12px 9px; }
.em-coll-list .item:last-child { border-bottom: none; }
.em-coll-list .who { display: flex; align-items: center; gap: 7px; min-width: 0; }
.em-coll-list .nm { font-family: var(--font-body); font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.em-coll-list .stamp { flex-shrink: 0; font-family: var(--font-mono); font-weight: 600; font-size: 8px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold-text);
  border: 1px solid var(--gold); padding: 2px 5px; }
.em-coll-list .won, .em-coll-list .share { text-align: right; font-family: var(--font-mono);
  font-weight: 600; font-size: 15px; }
.em-coll-list .won { color: var(--ink); }
.em-coll-list .share { color: var(--gold-text); }
.em-coll-list .note { font-family: var(--font-body); font-size: 11px; color: var(--faded-ink); margin-top: 4px; }

/* §96h — placings. The place is the member's place in the FUND, not within the
   collective: that is the number that decides whether they cash. */
.em-coll-places { padding: 16px 20px 4px; }
.em-coll-places .hd { display: flex; justify-content: space-between; align-items: center;
  gap: 10px; margin-bottom: 9px; }
.em-coll-places .hd .lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-coll-seg { display: flex; gap: 5px; flex-shrink: 0; }
.em-coll-seg a { padding: 5px 10px; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; background: none; color: var(--faded-ink); border: 1px solid var(--ledger-line); }
.em-coll-seg a.is-active { background: var(--gold); color: var(--certificate); border-color: var(--gold); }
.em-coll-places .box { border: 1px solid var(--ink); background: var(--certificate); }
.em-coll-place { display: grid; grid-template-columns: 38px 1fr 46px; gap: 8px; align-items: center;
  border-bottom: 1px dotted var(--ledger-line); padding: 10px 12px; }
.em-coll-place:last-child { border-bottom: none; }
.em-coll-place.is-you { background: #F1E6CC; }
.em-coll-place .pl { font-family: var(--font-mono); font-weight: 600; font-size: 14px; color: var(--gold-text); }
.em-coll-place .nm { font-family: var(--font-body); font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.em-coll-place.is-you .nm { font-weight: 700; }
.em-coll-place .pts { text-align: right; font-family: var(--font-mono); font-weight: 600;
  font-size: 15px; color: var(--ink); }

/* The sand panel — the pre-kickoff placings note (§96h) and the rules note (§96i). */
.em-coll-note { border: 1px solid var(--ledger-line); background: var(--sand); padding: 12px 14px;
  font-family: var(--font-body); font-size: 12px; line-height: 1.5; color: var(--faded-ink); }
.em-coll-rules { padding: 16px 20px 28px; }
.em-coll-rules .em-coll-note { line-height: 1.55; color: var(--ink); text-wrap: pretty; }

/* Support address on the signed-out screens. Quiet — it is a safety net, not a
   call to action — but present on every auth screen, because a member who can't
   sign in can't reach anything behind the wall. */
.em-auth-support { text-align: center; padding: 0 20px 30px; }
.em-auth-support .k { display: block; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--faded-ink); margin-bottom: 4px; }
.em-auth-support a { font-family: var(--font-mono); font-size: 12px; color: var(--money-green);
  border-bottom: 1px solid var(--money-green); padding-bottom: 1px; }
/* In-app support line — Home only (see the template comment). Shares the auth
   treatment so the address looks the same wherever a member finds it. */
.em-home-support { text-align: center; padding: 22px 20px 8px; margin-top: 6px;
  border-top: 1px dotted var(--ledger-line); }
.em-home-support .k { display: block; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--faded-ink); margin-bottom: 4px; }
.em-home-support a { font-family: var(--font-mono); font-size: 12px; color: var(--money-green);
  border-bottom: 1px solid var(--money-green); padding-bottom: 1px; }

/* TEMPORARY — §98 mark beside the wordmark, mockup only (?mark=1). Delete with
   the template block once the logo question is settled either way. */
.em-wordmark.has-mark { display: inline-flex; align-items: center; gap: 8px; }
.em-wordmark.has-mark img { display: block; flex-shrink: 0; }

/* ============================================================
   §109b — The Sovereign Selectors: Pick five
   ============================================================ */
/* The status chip is a READOUT, not a button: every tap on this screen has
   already written, so unlike the ranker's slot there is nothing for it to do. */
.em-sc-chip { justify-self: end; font-family: var(--font-mono); font-size: 10px;
  font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 6px 10px; border: 1px solid var(--gold); color: var(--gold-text);
  white-space: nowrap; }
.em-sc-chip.is-in { border: 2px solid var(--money-green); color: var(--money-green); }

.em-sc-count { font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  color: #4A574F; white-space: nowrap; }
.em-sc-count.is-full { color: var(--money-green); }

.em-sc-rows { display: flex; flex-direction: column; gap: 8px; }
.em-sc-row { background: var(--certificate); border: 1px solid var(--ink);
  padding: 10px 12px; }
/* §100's locked treatment, same two colours, so "locked" reads the same in both
   games rather than being two things to learn. */
.em-sc-row.is-locked { background: #DCD2B8; border-color: #A79E85; }
.em-sc-when { display: flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faded-ink); margin-bottom: 8px; }

.em-sc-sides { display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: 8px; }
.em-sc-at { font-family: var(--font-mono); font-size: 10px; color: var(--faded-ink); }
.em-sc-side { display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 8px; width: 100%; padding: 10px; background: var(--certificate);
  border: 1px solid var(--ledger-line); cursor: pointer; text-align: left; }
.em-sc-side .crest { border-radius: 50%; background: #E7E1D2; object-fit: cover; }
.em-sc-side .code { font-family: var(--font-mono); font-size: 13px; font-weight: 500;
  color: var(--ink); }
/* The line is gold because it is the TERMS, not the team — a pick is a team with
   its number, which is also why both sides carry one. */
.em-sc-side .line { font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  color: var(--gold-text); white-space: nowrap; }
.em-sc-side.is-on { background: var(--green-wash); border-color: var(--money-green); }
.em-sc-side.is-on .code { color: #0E5734; font-weight: 700; }
.em-sc-side.is-on .line { color: #0E5734; }

/* §109b — the fifth pick does not raise an error or a toast. Unpicked rows just
   stop taking taps; picked ones stay live so a member can switch or unpick. */
.em-sc-row.is-inert .em-sc-side:disabled { opacity: 0.45; cursor: default; }
.em-sc-row.is-locked .em-sc-side { cursor: default; }

.em-sc-noline { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--gold-text); margin: 8px 0 0; }
/* A tab whose screen is not built yet (§108f note in contests/context_processors):
   visibly present, visibly not a destination. Build scaffolding — by §108h both
   games ship all five, so nothing should still carry this at beta. */
.em-tab.is-soon { color: #5A6B61; opacity: 0.45; cursor: default; }

/* ---- §109e / §109d — Board + Live ---------------------------------- */
/* Three live states and two settled ones. Covering and Won are different
   colours on purpose: a pick that is covering can still lose. */
.em-sc-legend { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 0 12px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-sc-legend span { display: inline-flex; align-items: center; gap: 5px; }
.em-sc-legend .sw { width: 11px; height: 11px; display: inline-block; }
.sw.covering { background: var(--green-wash); border: 1px solid var(--money-green); }
.sw.short    { background: #FBEDEA; border: 1px solid #C63B2F; }
.sw.onnum    { background: #F0E6D0; border: 1px solid var(--gold); }

.em-grouphead { display: flex; align-items: center; gap: 10px; margin: 18px 0 10px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-grouphead .t { color: var(--ink); }
/* §109j — the head says which list you are in: ink for YOUR FIVE, green while a
   group is in play, grey for the rest. Modifier classes rather than a change to
   `.t`, because this bar is Confidence's too and it is not part of this spec. */
.em-grouphead.is-yours .t { color: var(--ink); }
.em-grouphead.is-live .t { color: var(--money-green); }
.em-grouphead.is-quiet .t { color: var(--faded-ink); }
.em-grouphead::after { content: ""; flex: 1; border-top: 1px dotted var(--ledger-line); order: 1; }
.em-grouphead .n { order: 2; }

/* Full Grid: sticky name column, the rest scrolls sideways. */
.em-sc-grid-wrap { overflow-x: auto; }
.em-sc-grid { border-collapse: collapse; }
.em-sc-grid th, .em-sc-grid td { padding: 6px 4px; font-family: var(--font-mono);
  font-size: 10px; text-align: center; border-bottom: 1px dotted var(--ledger-line); }
.em-sc-grid th.nm, .em-sc-grid td.nm { position: sticky; left: 0; z-index: 2;
  background: var(--paper); text-align: left; min-width: 112px; max-width: 112px;
  font-family: var(--font-body); font-size: 12px; }
.em-sc-grid td.pt { font-weight: 600; min-width: 34px; }
.em-sc-grid th.gm { min-width: 44px; line-height: 1.3; }
.em-sc-grid th.gm .st { display: block; color: var(--faded-ink); font-size: 9px; }
.em-sc-grid th.gm.is-live .st { color: var(--money-green); }
/* §109i — the column head is the status, then away crest over home crest, as
   the prototype stacks them (`flex-direction: column; align-items: center`).
   `display: block` says so outright: left inline these two sat side by side
   whenever the column was wide enough, which reads as one matchup turned on its
   side. `.tm` is gone with the codes it carried — Survivor's Board has its own. */
.em-sc-grid th.gm .crest { display: block; margin: 1px auto 0; border-radius: 50%;
  background: #E7E1D2; object-fit: cover; }
.em-sc-grid tr.is-you td { background: var(--green-wash); }
.em-sc-grid tr.is-you td.nm { background: var(--green-wash); font-weight: 700; }
.em-sc-grid .dot { color: #C7C0AC; }
/* §109k — sealed is a FILLED cell, not an empty one. Sized off the 18px crest
   it stands in for, so a column does not change width when its games lock. */
.em-sc-grid .sealed { display: inline-block; width: 18px; height: 18px;
  background: #EFE9D9; border: 1px solid #DDD5C2; vertical-align: middle; }
/* §109i — inline-flex, not inline-block: the chip's only child is now an 18px
   image, and inline layout added the font's descender space under it, which grew
   every row in the grid by a couple of pixels. The fill and border are the
   cell's state and are untouched. */
.em-sc-grid .chip { display: inline-flex; align-items: center;
  justify-content: center; padding: 2px 3px; font-weight: 600; }
.em-sc-grid .chip .crest { display: block; border-radius: 50%;
  background: #E7E1D2; object-fit: cover; }

/* The one state vocabulary, shared by the grid chip, the By Game table row,
   the By Member chip and the Live row — so they cannot drift apart. */
.chip.covering, .em-sc-took tr.covering, .em-sc-mchip.covering,
  .em-sc-lrow.covering { background: var(--green-wash); color: #0E5734; }
.chip.short, .em-sc-took tr.short, .em-sc-mchip.short,
  .em-sc-lrow.short { background: #FBEDEA; color: #C63B2F; }
.chip.on_the_number, .em-sc-took tr.on_the_number, .em-sc-mchip.on_the_number,
  .em-sc-lrow.on_the_number { background: #F0E6D0; color: var(--gold-text); }

.em-sc-took { width: 100%; border-collapse: collapse; margin-top: 4px; }
.em-sc-took th, .em-sc-took td { padding: 7px 6px; font-family: var(--font-mono);
  font-size: 11px; text-align: left; border-bottom: 1px dotted var(--ledger-line); }
.em-sc-took th { font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--faded-ink); }
.em-sc-took .n { text-align: right; }
.em-sc-took .line { color: var(--gold-text); margin-left: 6px; }
/* §109i — the crest replaced the code in this cell, so YOUR side is marked on
   the line instead. Dropping `.code` without moving this rule is how the row you
   took stops looking any different from the one you didn't. */
.em-sc-took tr.is-mine .line { font-weight: 700; }
.em-sc-took .crest { vertical-align: middle; border-radius: 50%;
  background: #E7E1D2; object-fit: cover; }
.em-sc-roll { margin-top: 8px; }
.em-sc-roll summary { font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--money-green);
  cursor: pointer; }
.em-sc-roll .rc { display: flex; justify-content: space-between; padding: 5px 0;
  border-bottom: 1px dotted var(--ledger-line); font-size: 13px; }
/* §109k — the line the roll call opens with, and the open-but-empty one. */
.em-sc-roll .sealed { margin: 5px 0; font-family: var(--font-mono);
  font-size: 10px; color: #7A857D; }
.em-sc-roll .pk { display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-weight: 600; }
/* The space is the crest's own margin and NOT a flex `gap`: `halves` wraps the
   ½ in its own span, so a gap counts it as a third child and prints `−3 ½`,
   splitting the number down the middle. */
.em-sc-roll .pk .crest { margin-right: 6px; border-radius: 50%;
  background: #E7E1D2; object-fit: cover; flex-shrink: 0; }

.em-sc-member { background: var(--certificate); border: 1px solid var(--ink);
  padding: 10px 12px; margin-bottom: 8px; }
.em-sc-member.is-you { background: var(--green-wash); }
.em-sc-member summary { display: grid; grid-template-columns: 1fr auto auto;
  gap: 10px; align-items: center; cursor: pointer; }
.em-sc-member summary .nm { font-weight: 600; }
.em-sc-member summary .cv, .em-sc-member summary .pt {
  font-family: var(--font-mono); font-size: 11px; }
.em-sc-member summary .pt { font-weight: 700; }
.em-sc-mchip { display: flex; justify-content: space-between; align-items: center;
  margin-top: 6px; padding: 6px 8px; font-family: var(--font-mono); font-size: 11px; }
.em-sc-mchip .pk { display: inline-flex; align-items: center; font-weight: 600; }
/* Margin, not `gap` — see the note on `.em-sc-roll .pk .crest`. */
.em-sc-mchip .pk .crest { margin-right: 7px; border-radius: 50%;
  background: #E7E1D2; object-fit: cover; flex-shrink: 0; }

/* Flex, not grid: the row's children are OPTIONAL — the PICK badge only on your
   side, the COVERS badge only when projected — and a fixed column count made
   the score wrap to a second line the moment What-If added a sixth child. */
.em-sc-lrow { display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; margin-bottom: 4px; }
.em-sc-lrow .line { margin-right: auto; }
.em-sc-lrow .crest { border-radius: 50%; background: #E7E1D2; object-fit: cover; }
.em-sc-lrow .line { font-family: var(--font-mono); font-size: 11px; color: var(--gold-text); }
.em-sc-lrow .pick { font-family: var(--font-mono); font-size: 9px; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--money-green);
  border: 1px solid var(--money-green); padding: 1px 5px; }
.em-sc-lrow .score { font-family: var(--font-mono); font-size: 20px; font-weight: 600; }
.em-sc-lrow.is-mine { box-shadow: inset 3px 0 0 var(--money-green); }
.gc-foot .st.none { color: var(--faded-ink); }

/* ---- §109g / §109f — Standings + the Card ------------------------- */
.em-sc-stand .row { display: grid; grid-template-columns: 38px minmax(0,1fr) 64px 40px;
  gap: 8px; align-items: center; padding: 11px 10px;
  border-bottom: 1px dotted var(--ledger-line); text-decoration: none; color: var(--ink); }
.em-sc-stand .row.head { font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--faded-ink);
  border-bottom: 1px solid var(--ink); }
.em-sc-stand .row.is-you { background: var(--green-wash); }
.em-sc-stand .rk { font-family: var(--font-mono); font-size: 11px; }
.em-sc-stand .nm { font-weight: 500; }
.em-sc-stand .row.is-you .nm { font-weight: 700; }
.em-sc-stand .rec, .em-sc-stand .pt { font-family: var(--font-mono); font-size: 12px;
  text-align: right; }
.em-sc-stand .pt { font-weight: 700; }
/* §109f — the only tappable row in the beta says so in its own cell. */
.em-sc-stand .card { margin-left: 8px; font-family: var(--font-mono); font-size: 9px;
  font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--money-green); white-space: nowrap; }
.em-sc-stand .paid { margin-left: 8px; font-family: var(--font-mono); font-size: 9px;
  font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gold-text); border: 1px solid var(--gold); padding: 1px 5px; }

/* §109h's `n of 5` stamp. The system has green/ink/red but no gold one, and the
   gold weight is doing real work here — it is the "not finished yet" state, and
   ink would read as settled. */
.em-stamp--gold { border-color: var(--gold); color: var(--gold-text); }

.em-sc-cardhead { display: flex; align-items: baseline; gap: 12px; }
.em-sc-cardhead .score { font-family: var(--font-display); font-weight: 900;
  font-size: 44px; line-height: 1; color: var(--ink); }
.em-sc-cardhead .rec { font-family: var(--font-mono); font-size: 14px;
  color: var(--faded-ink); }
.em-sc-cardrow { display: grid; grid-template-columns: 26px 1fr 28px;
  gap: 8px 10px; align-items: center; padding: 11px 10px;
  border-bottom: 1px dotted var(--ledger-line); }
.em-sc-cardrow .res { font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  text-align: center; padding: 3px 0; }
.em-sc-cardrow .res.rW { background: var(--money-green); color: var(--paper); }
.em-sc-cardrow .res.rL { border: 1px solid #C63B2F; color: #C63B2F; }
.em-sc-cardrow .res.rP { background: #F0E6D0; color: var(--gold-text); }
.em-sc-cardrow .pick { font-family: var(--font-mono); font-size: 13px; font-weight: 600; }
.em-sc-cardrow .pick .line { color: var(--gold-text); font-weight: 600; }
.em-sc-cardrow .pts { font-family: var(--font-mono); font-size: 13px; font-weight: 700;
  text-align: right; }
.em-sc-cardrow .detail { grid-column: 2 / -1; font-family: var(--font-mono);
  font-size: 10px; color: var(--faded-ink); }

.em-hero-band { display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--ink); }
.em-hero-band .k { font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faded-ink); }
.em-hero-band .v { font-family: var(--font-mono); font-size: 25px; font-weight: 600; }
/* §109c's ½. IBM Plex Mono squeezes U+00BD into one cell, so at 12px beside two
   digits it reads as clipped — Paul saw `+12½` and thought it was cut off. The
   glyph moves to the proportional body face, which draws a wider fraction; the
   digits stay mono so a column of numbers still lines up. */
.frac { font-family: var(--font-body); font-size: 1.08em; margin-left: 0.5px;
  letter-spacing: 0; }
/* §109b, deviating — see the note in super_picks.html. The foot of the Picks
   screen reports that the picks are already written; it is not a button,
   because there is nothing left to press. */
.em-sc-saved { display: flex; align-items: center; justify-content: center;
  gap: 8px; margin-top: 12px; padding: 13px; font-family: var(--font-mono);
  font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  border: 1px solid var(--ledger-line); color: var(--faded-ink); }
.em-sc-saved .mark { color: var(--ledger-line); }
.em-sc-saved.is-in { border: 2px solid var(--money-green); color: var(--money-green); }
.em-sc-saved.is-in .mark { color: var(--money-green); }

/* §109b, deviating — see the note in super_picks.html. The foot of the Picks
   screen REPORTS that the picks are already written; it is not a button,
   because there is nothing left to press. */
.em-sc-saved { display: flex; align-items: center; justify-content: center;
  gap: 8px; margin-top: 12px; padding: 13px; font-family: var(--font-mono);
  font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  border: 1px solid var(--ledger-line); color: var(--faded-ink); }
.em-sc-saved .mark { color: var(--ledger-line); }
.em-sc-saved.is-in { border: 2px solid var(--money-green); color: var(--money-green); }
.em-sc-saved.is-in .mark { color: var(--money-green); }

/* ---- §109d — What-If on Live ------------------------------------- */
/* A projected side gets an ink outline and a COVERS badge. Ink, not green:
   green already means "covering right now", and a hypothesis must not borrow
   the colour that reports fact. */
.em-sc-lrow.is-wi { outline: 2px solid var(--ink); outline-offset: -2px; }
.em-sc-lrow .covers { font-family: var(--font-mono); font-size: 9px;
  font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  background: var(--ink); color: var(--paper); padding: 2px 5px; }

/* Fixed above the tab bar, the same berth §104 gave Confidence's gain bar —
   and for the same reason: the number has to stay on screen beside the taps
   that produced it. */
.em-sc-wi { position: fixed; left: 0; right: 0;
  bottom: calc(42px + env(safe-area-inset-bottom)); margin: 0 auto;
  width: 100%; max-width: 430px; z-index: 19;
  display: grid; grid-template-columns: 1fr auto; gap: 2px 12px;
  padding: 12px 16px; background: var(--certificate);
  border-top: 1px solid var(--ink); box-shadow: 0 -4px 12px rgba(28,43,36,.12); }
.em-sc-wi .l { display: flex; flex-direction: column; }
.em-sc-wi .k { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-sc-wi .v { font-family: var(--font-display); font-weight: 900; font-size: 28px;
  line-height: 1.05; color: var(--money-green); }
.em-sc-wi .d { font-family: var(--font-mono); font-size: 10px; color: var(--faded-ink); }
.em-sc-wi .r { display: flex; flex-direction: column; justify-content: center; gap: 2px; }
.em-sc-wi .r .row { display: flex; align-items: baseline; gap: 6px; justify-content: flex-end; }
.em-sc-wi .r .p { font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  min-width: 46px; text-align: right; }
.em-sc-wi .f { grid-column: 1 / -1; display: flex; align-items: center;
  justify-content: space-between; margin-top: 4px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-sc-wi .f button { font: inherit; color: var(--money-green); background: none;
  border: 1px solid var(--money-green); padding: 3px 9px; cursor: pointer; }
/* The bar is fixed, so the list needs room to scroll clear of it. */
.em-sc-wi:not([hidden]) ~ * { }
body:has(.em-sc-wi:not([hidden])) .em-screen { padding-bottom: 150px; }
/* §109d — the What-If tag marks a tappable side, and only in What-If mode. The
   rows were tappable with no affordance at all before: Paul went looking for a
   button and found nothing, which is exactly the signal that was missing. */
/* No per-row "tappable" badge: Confidence marks only the row you PROJECTED,
   and COVERS already does that here. A badge on every tappable side was noise
   on sixteen games (Paul, 2026-10-17). The mode button and its one line of help
   are the affordance; the cursor does the rest. */
.em-sc-lrow[data-wi-game] { cursor: default; }
body.wi-mode .em-sc-lrow[data-wi-game] { cursor: pointer; }
#wi-toggle.is-on { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* §109d — the hypothetical Standings the What-If bar opens. Sits directly on
   top of the bar so the number and the field it produced stay together. */
.em-sc-witable { position: fixed; left: 0; right: 0;
  bottom: calc(42px + env(safe-area-inset-bottom) + 112px);
  margin: 0 auto; width: 100%; max-width: 430px; z-index: 20;
  max-height: 52vh; overflow-y: auto; background: var(--certificate);
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink);
  box-shadow: 0 -6px 14px rgba(28,43,36,.16); }
.em-sc-witable .hd { display: flex; align-items: center; justify-content: space-between;
  padding: 11px 16px 6px; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faded-ink); }
.em-sc-witable .hd .x { font-size: 18px; line-height: 1; background: none;
  border: none; color: var(--faded-ink); cursor: pointer; padding: 0 2px; }
.em-sc-witable .em-seg { padding: 0 16px 8px; }
.em-sc-witable .rows { padding: 0 6px 10px; }
.em-sc-witable .row { display: grid; grid-template-columns: 40px minmax(0,1fr) 42px 40px;
  gap: 8px; align-items: center; padding: 9px 10px;
  border-bottom: 1px dotted var(--ledger-line); }
.em-sc-witable .row.is-you { background: var(--green-wash); }
.em-sc-witable .rk { font-family: var(--font-mono); font-size: 11px; }
.em-sc-witable .nm { font-size: 13px; }
.em-sc-witable .row.is-you .nm { font-weight: 700; }
/* The Move column is the only reason to open this rather than read Standings,
   so it carries the colour: up is the league's green, down its red. */
.em-sc-witable .mv { font-family: var(--font-mono); font-size: 11px;
  text-align: right; color: var(--faded-ink); }
.em-sc-witable .mv.up { color: var(--money-green); }
.em-sc-witable .mv.dn { color: #C63B2F; }
.em-sc-witable .pt { font-family: var(--font-mono); font-size: 12px; font-weight: 700;
  text-align: right; }
.em-sc-wi .f .open { color: var(--money-green); cursor: pointer; }

/* Where the game has got to, on the card head. Green while the ball is moving,
   the way the Confidence Live Hub reads. */
.em-sc-clock { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faded-ink); margin-bottom: 8px; }
.em-sc-clock.is-live { color: var(--money-green); }

/* ---- §110 — Natural Selection ------------------------------------- */
/* §110h — a used team is greyed, not struck through: the crest replaced the
   text that a line-through had to cross. */
.em-sc-side.is-used { opacity: 0.45; cursor: default; }
.em-sc-side.is-used .crest { filter: grayscale(1); }
.em-sc-side .usedtag { font-family: var(--font-mono); font-size: 10px;
  font-weight: 600; color: #C63B2F; white-space: nowrap; }
/* The line is a GUIDE on this game — won straight up — so it is quiet grey,
   not the Super Contest's gold, where the number IS the contest. */
.em-sc-side .guide { font-family: var(--font-mono); font-size: 10px;
  color: var(--faded-ink); white-space: nowrap; }
.em-sc-chip.is-out { border: 2px solid #C63B2F; color: #C63B2F; }
.em-sv-out { background: #FBEDEA; border: 1px solid #C63B2F; padding: 12px 14px;
  margin-bottom: 12px; }
.em-sv-out .k { font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: #C63B2F; }

/* §110g / §110k — the field, and the standings it becomes. */
.em-sv-row { display: grid; grid-template-columns: auto minmax(0,1fr) auto auto;
  gap: 8px; align-items: center; padding: 10px 12px;
  background: var(--certificate); border: 1px solid var(--ink); margin-bottom: 6px; }
.em-sv-row.is-you { background: var(--green-wash); }
.em-sv-row.is-you .nm { font-weight: 700; }
.em-sv-row.is-out { background: #F7F3E8; }
.em-sv-row.is-out .nm { color: #4A574F; }
.em-sv-row .rk { font-family: var(--font-mono); font-size: 11px; min-width: 34px; }
.em-sv-row .nm { font-size: 14px; }
.em-sv-row .bb { margin-left: 6px; font-family: var(--font-mono); font-size: 9px;
  font-weight: 600; color: var(--gold-text); border: 1px solid var(--gold); padding: 1px 4px; }
.em-sv-row .crest { border-radius: 50%; background: #E7E1D2; object-fit: cover; }
.em-sv-row .cd { font-family: var(--font-mono); font-size: 12px; font-weight: 600; }
.em-sv-row .cd.win { color: var(--money-green); }
.em-sv-row .cd.loss { color: #C63B2F; }
.em-sv-row .rec { font-family: var(--font-mono); font-size: 12px; }
/* §110g — a filed pick that has not locked is a DASHED cell. Blank would read
   as "no pick", which is a different and worse thing to say about someone. */
.em-sv-row .sealed { display: inline-block; width: 34px; height: 18px;
  border: 1px dashed var(--faded-ink); }
.em-sv-row .none { font-family: var(--font-mono); font-size: 10px;
  color: var(--faded-ink); }
.em-sv-row .lasted { font-family: var(--font-mono); font-size: 9px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; padding: 3px 7px;
  border: 1px solid #C63B2F; color: #C63B2F; white-space: nowrap; }
.em-sv-row .lasted.is-alive { background: var(--money-green); border-color: var(--money-green);
  color: var(--paper); }

.em-sv-team { display: grid; grid-template-columns: auto auto 44px minmax(0,1fr);
  gap: 8px; align-items: center; padding: 8px 12px;
  border-bottom: 1px dotted var(--ledger-line); }
.em-sv-team.is-strong .cd { color: var(--money-green); font-weight: 700; }
.em-sv-team .crest { border-radius: 50%; background: #E7E1D2; object-fit: cover; }
.em-sv-team .cd, .em-sv-team .rec { font-family: var(--font-mono); font-size: 12px; }
.em-sv-team .who { font-size: 11px; color: var(--faded-ink); text-align: right; }

.em-sv-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
  margin: 0 0 14px; text-align: center; }
.em-sv-strip span { display: flex; flex-direction: column; gap: 2px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-sv-strip b { font-family: var(--font-display); font-weight: 900; font-size: 22px;
  color: var(--ink); }
.em-sv-strip b.won { color: var(--money-green); }
.em-sv-strip b.lost { color: #C63B2F; }
.em-sv-strip b.gold { color: var(--gold-text); }
/* §110n — Standings' strip is RULED: 1px gaps showing the container through as
   hairlines, which is how the four cells read as one ledger block rather than
   four floating numbers. Scoped, because Live's strip (§110j) shares this class
   and is drawn without them. */
.em-sv-strip.is-ruled { gap: 1px; background: #DDD5C2; }
.em-sv-strip.is-ruled span { background: var(--paper); padding: 8px 4px; }
/* The arithmetic under the pot. Checkable, not asserted — and display only. */
.em-sv-sums { margin: 0 0 14px; font-family: var(--font-mono); font-size: 9px;
  letter-spacing: 0.08em; color: #7A857D; }

.em-sv-lrow { display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  margin-bottom: 4px; }
.em-sv-lrow .crest { border-radius: 50%; background: #E7E1D2; object-fit: cover; }
.em-sv-lrow .code { font-family: var(--font-mono); font-size: 13px; font-weight: 600; }
.em-sv-lrow .who { flex: 1; font-size: 12px; color: var(--faded-ink); }
.em-sv-lrow .who .you { font-weight: 700; color: var(--ink); }
.em-sv-lrow .score { font-family: var(--font-mono); font-size: 20px; font-weight: 600; }
/* The ridden side is tinted by its state, with an inset bar in the same colour. */
.em-sv-lrow.ridden.winning, .em-sv-lrow.ridden.won { background: var(--green-wash);
  box-shadow: inset 3px 0 0 var(--money-green); }
.em-sv-lrow.ridden.losing, .em-sv-lrow.ridden.lost { background: #FBEDEA;
  box-shadow: inset 3px 0 0 #C63B2F; }
.em-sv-lrow.ridden.pending { background: #F3EEDF;
  box-shadow: inset 3px 0 0 var(--ledger-line); }
.em-hero-name.is-out { color: #C63B2F; }

/* §110g — the commissioner's report, redrawn. Two matrices: members down,
   weeks across on Picks; members down, all 32 teams across on Teams left.
   Both scroll in two directions with a sticky name column. */
.em-sv-matrix-wrap { overflow: auto; max-height: 68vh; }
.em-sv-matrix { border-collapse: collapse; }
.em-sv-matrix th, .em-sv-matrix td { padding: 5px 4px; font-family: var(--font-mono);
  font-size: 10px; text-align: center; border-bottom: 1px dotted var(--ledger-line); }
.em-sv-matrix th { position: sticky; top: 0; z-index: 3; background: var(--paper);
  font-size: 9px; letter-spacing: 0.08em; }
.em-sv-matrix th.nm, .em-sv-matrix td.nm { position: sticky; left: 0; z-index: 2;
  background: var(--paper); text-align: left; min-width: 104px; max-width: 104px;
  font-family: var(--font-body); font-size: 12px; }
.em-sv-matrix th.nm { z-index: 4; }
.em-sv-matrix th.wk { min-width: 40px; }
/* The current week's head is green — it is the column you are reading. */
.em-sv-matrix th.wk.is-now { color: var(--money-green); font-weight: 600; }
.em-sv-matrix tr.grp td { background: var(--paper); text-align: left;
  font-size: 9px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--faded-ink); border-bottom: 1px solid var(--ink); padding-top: 12px; }
.em-sv-matrix tr.is-you td.nm { font-weight: 700; }
.em-sv-matrix tr.is-out td.nm { color: #4A574F; background: #EFE9DA; }
.em-sv-matrix tr.is-out td { background: #EFE9DA; }
.em-sv-matrix .bb, .em-sv-matrix .bbtag { margin-left: 4px; font-size: 8px;
  font-weight: 600; color: var(--gold-text); border: 1px solid var(--gold);
  padding: 0 3px; }
/* §110h — the crest in a matrix cell. `display: block` and auto side margins:
   inline layout would add the font's descender space under the image and grow
   every row of a grid that is already 12 weeks or 32 teams wide — the same
   thing that bit Super Contest's Full Grid in 30a. The circle keeps its own
   #E7E1D2 ground so a crest with transparency still reads on a solid cell. */
.em-sv-matrix .crest { display: block; margin: 0 auto; border-radius: 50%;
  background: #E7E1D2; object-fit: cover; }
/* A cell carrying both a crest and the BB tag stops being a single centred
   image, so it lays them out in a row instead. */
.em-sv-matrix td.cell:has(.bbtag) { white-space: nowrap; }
.em-sv-matrix td.cell:has(.bbtag) .crest { display: inline-block;
  vertical-align: middle; margin: 0; }
/* Teams left: the head is the crest over its win–loss record. */
.em-sv-matrix th.tm .crest { margin-bottom: 2px; }

/* A settled cell is the team's crest on a solid fill — the result reads before
   the team does. */
.em-sv-matrix td.cell.win { background: var(--money-green); color: var(--paper); font-weight: 600; }
.em-sv-matrix td.cell.loss { background: #C63B2F; color: var(--paper); font-weight: 600; }
/* §110m — a game in play is NOT a filled cell. It keeps the paper ground with
   an ink hairline and carries §65's 11px corner flag, so a settled result still
   reads as the only solid colour on the grid and "in doubt" never looks decided.
   `linear-gradient` and not a pseudo-element: the cell already uses ::after for
   the band label (§110g), and a second one would fight it. */
.em-sv-matrix td.cell.leading, .em-sv-matrix td.cell.trailing {
  background: #FFFDF6; border: 1px solid var(--ink); }
.em-sv-matrix td.cell.leading {
  background-image: linear-gradient(315deg, var(--money-green) 0 11px, #FFFDF6 11px); }
/* Trailing covers a TIE as well — a tie is a loss (§110b), so there is no grey
   level state on this grid however §65 draws one. */
.em-sv-matrix td.cell.trailing {
  background-image: linear-gradient(315deg, #C63B2F 0 11px, #FFFDF6 11px); }
/* Open since the lock and not yet kicked off. */
.em-sv-matrix td.cell.pending { background: #FFFDF6; border: 1px solid #B9B29C; }
/* §110g — a filed pick that has not locked is DASHED, never blank. */
.em-sv-matrix td.cell.sealed::after { content: ""; display: block; width: 26px;
  height: 14px; margin: 0 auto; border: 1px dashed var(--faded-ink); }
.em-sv-matrix td.cell.band { background: #E4DDCB; }
.em-sv-matrix td.cell.tky { border-left: 2px solid var(--gold); }
.em-sv-matrix td.left, .em-sv-matrix th.left { position: sticky; left: 104px;
  z-index: 2; background: var(--paper); min-width: 72px; text-align: left; }
.em-sv-matrix th.left { z-index: 4; }
.em-sv-matrix td.left .rec { font-weight: 600; font-size: 11px; display: block; }
.em-sv-matrix td.left .st { font-size: 8px; color: var(--faded-ink); }
.em-sv-matrix th.tm { min-width: 34px; }
.em-sv-matrix th.tm .cd, .em-sv-matrix th.tm .rec { display: block; }
.em-sv-matrix th.tm .rec { font-size: 8px; color: var(--faded-ink); }
.em-sv-matrix td.cell.strongteam { background: var(--green-wash); color: #0E5734;
  border: 1px solid var(--money-green); font-weight: 600; }
.em-sv-matrix td.cell.open { background: var(--certificate); border: 1px solid #DDD5C2; }
.em-sv-matrix td.cell.used { background: transparent; }

.em-sv-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
  margin: 0 0 10px; }
.em-sv-stats span { display: flex; flex-direction: column; gap: 2px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-sv-stats b { font-family: var(--font-display); font-weight: 900; font-size: 20px;
  color: var(--ink); }
.em-sv-stats b.won { color: var(--money-green); }
.em-sv-stats b.gold { color: var(--gold-text); }
.em-sv-legend { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 0 10px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faded-ink); }
.em-sv-legend span { display: inline-flex; align-items: center; gap: 5px; }
.em-sv-legend .sw { width: 11px; height: 11px; display: inline-block; }
.em-sv-legend .sw.won { background: var(--money-green); }
.em-sv-legend .sw.lost { background: #C63B2F; }
/* The legend's live swatches carry the same corner flag as the cells. */
.em-sv-legend .sw.leading { background: #FFFDF6; border: 1px solid var(--ink);
  background-image: linear-gradient(315deg, var(--money-green) 0 7px, #FFFDF6 7px); }
.em-sv-legend .sw.trailing { background: #FFFDF6; border: 1px solid var(--ink);
  background-image: linear-gradient(315deg, #C63B2F 0 7px, #FFFDF6 7px); }
.em-sv-legend .sw.sealed { border: 1px dashed var(--faded-ink); }
.em-sv-legend .sw.open { background: var(--certificate); border: 1px solid #DDD5C2; }
/* The band's label sits on its first cell and overflows across the rest. */
.em-sv-matrix td.cell.band { position: relative; }
.em-sv-matrix .bandlbl { position: absolute; left: 6px; top: 50%;
  transform: translateY(-50%); white-space: nowrap; font-size: 9px;
  letter-spacing: 0.1em; text-transform: uppercase; color: #6B6553; }
