/* Replicas of the app's own components for the tutorial's product windows.
   Every .rep-* class that mirrors an app component is mapped in
   replica_manifest.json to the selector it copies; tests/test_tutorial_replicas_in_sync.py
   fails when the app renames one. Type floor 16px, like the app. */
.rep-window { border:1px solid var(--border-strong); border-radius:12px; background:var(--bg-surface); overflow:hidden; margin:18px 0; }
.rep-chrome { display:flex; align-items:center; gap:10px; padding:8px 14px; background:var(--bg-elevated); border-bottom:1px solid var(--border); font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-muted); }
.rep-chrome::before { content:''; width:10px; height:10px; border-radius:50%; background:var(--accent); opacity:0.7; }
.rep-chrome-title { letter-spacing:0.04em; }
.rep-body { padding:14px; position:relative; }
/* overflow-wrap (Task 17): an as-of line names files; a path is one unbreakable
   token and the window is overflow:hidden, so at 375px it was clipped. */
.rep-asof { font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-muted); margin-top:8px; overflow-wrap:anywhere; }
.rep-badge { display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:16px; padding:2px 8px; border:1px solid var(--amber); color:var(--amber); border-radius:6px; }
.rep-free-pro { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:18px; }
.rep-free, .rep-pro { border:1px solid var(--border); border-radius:12px; padding:14px; }
.rep-pro { border-color:rgba(16,185,129,0.35); }
.rep-free h3, .rep-pro h3 { margin:0 0 8px; font-size:18px; }
.rep-free ul, .rep-pro ul { margin:0; padding-left:18px; font-size:17px; line-height:1.5; }
@media (max-width: 768px) { .rep-free-pro { grid-template-columns:1fr; } .rep-body { padding:10px; } }

/* ─── Task 14: the deal panel (step 16) and the chat pool line (step 8) ─── */
.rep-upgrade-cta { display:inline-flex; align-items:center; justify-content:center; min-height:44px; padding:10px 22px; border-radius:6px; background:var(--accent); color:#0d1117; font-weight:700; font-size:17px; text-decoration:none; border:none; cursor:pointer; }
.rep-upgrade-cta.secondary { background:none; color:var(--text-primary); border:1px solid var(--border-strong); }
.rep-upgrade-lines { margin:10px 0; padding-left:18px; font-size:17px; line-height:1.55; }
.rep-upgrade-fine { font-size:16px; color:var(--text-muted); }
.rep-chat-cap { font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-muted); }

/* ─── Task 15: the board window (step 2) ───
   Tokens are the app's own values where the deck has no token for them
   (main.css :root): --border-card rgba(255,255,255,0.22), --border-subtle
   rgba(255,255,255,0.06), --accent-muted rgba(16,185,129,0.15),
   --accent-green-bg rgba(34,197,94,0.12), --shadow-card-sm. */
/* A marker that sits in the text flow instead of at fixed offsets: no
   overlap at any width, nothing clipped by a card's overflow:hidden. */
/* The sidebar rail beside the board (main.css .sidebar / .sidebar-category /
   .sidebar-league-item): All Sports above the categories, the active
   sport's category open. */
.rep-board { display:grid; grid-template-columns:168px minmax(0,1fr); gap:14px; align-items:start; }
.rep-rail { border-right:1px solid var(--border); padding-right:10px; }
.rep-rail-cat { padding:7px 10px 3px; font-size:16px; font-weight:600; color:var(--text-muted); }
.rep-rail-cat::before { content:'\25B8'; display:inline-block; width:16px; color:var(--text-dim); }
.rep-rail-cat.open::before { content:'\25BE'; }
.rep-sidebar-item { display:flex; align-items:center; gap:4px; padding:6px 12px; border-radius:6px; border-left:3px solid transparent; margin:1px 0; font-size:16px; font-weight:600; color:var(--text-primary); }
.rep-sidebar-item.active { background:rgba(16,185,129,0.15); color:var(--accent); font-weight:700; border-left-color:var(--accent); }
.rep-board-main { min-width:0; }
/* The board search (main.css .board-search / .board-search-input): a pill
   input, mono, with the slash key that focuses it beside it. Drawn as a span,
   not an <input>: a real field in the deck would be focusable but not the
   product. */
.rep-search { display:flex; align-items:center; gap:8px; margin-bottom:10px; }
.rep-search-input { display:inline-flex; align-items:center; min-height:44px; width:220px; max-width:100%; padding:8px 14px; border-radius:999px; border:1px solid var(--border); background:var(--bg-surface); color:var(--text-muted); font-family:'IBM Plex Mono',monospace; font-size:16px; }
/* The block, collapsed (Best Bets spec §6.2): header plus one summary line,
   Plex Mono 16px, single line, ellipsis. Mapped to .bb-summary in Task 27. */
.rep-block-line { padding:10px 14px; margin-bottom:10px; border:1px solid var(--border); border-radius:12px; background:var(--bg-card); }
.rep-block-head { display:flex; align-items:center; gap:10px; }
.rep-block-eyebrow { font-family:'IBM Plex Mono',monospace; font-size:16px; letter-spacing:0.08em; color:var(--text-muted); }
.rep-block-title { font-size:20px; font-weight:500; color:var(--text-primary); }
.rep-block-fold { margin-left:auto; color:var(--text-dim); font-size:16px; }
.rep-block-summary { margin-top:4px; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-primary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* The card (.ob-card), its header (.ob-head + .ob-when), the verdict strip
   (.ob-verdict and its parts), the odds box (.ob-box / .ob-cell) and the
   most-likely strip (.ob-strip / .ob-strip-k / .ob-pct-prob). */
.rep-card { background:var(--bg-elevated); border:1px solid rgba(255,255,255,0.22); border-radius:12px; margin-bottom:10px; overflow:hidden; box-shadow:0 1px 3px rgba(0,0,0,0.4); }
.rep-card-head { display:flex; justify-content:space-between; align-items:center; gap:8px; flex-wrap:wrap; padding:10px 14px; border-bottom:1px solid var(--border); font-size:16px; font-weight:600; color:var(--text-primary); }
.rep-card-at { color:var(--text-muted); font-weight:400; margin:0 2px; }
.rep-card-time { font-size:16px; font-weight:500; opacity:0.68; white-space:nowrap; }
.rep-verdict { display:flex; justify-content:space-between; align-items:center; gap:8px; flex-wrap:wrap; padding:7px 10px; border-top:1px solid var(--border); font-size:17px; color:var(--text-secondary); }
.rep-verdict-play { border-top-color:var(--accent); color:var(--text-primary); }
.rep-verdict-ev { color:var(--accent); font-weight:600; }
.rep-verdict-stake { font-family:'IBM Plex Mono',monospace; }
.rep-verdict-none { color:var(--text-secondary); }
.rep-verdict-go { font-size:16px; color:#0d1117; font-weight:700; white-space:nowrap; display:inline-flex; align-items:center; padding:3px 10px; background:var(--text-primary); border:1px solid var(--text-primary); border-radius:999px; }
.rep-odds-box { border-top:1px solid var(--border); }
.rep-odds-head, .rep-odds-row { display:grid; grid-template-columns:1.4fr 1fr 1fr 1fr; gap:4px; align-items:center; padding:6px 8px 6px 14px; border-bottom:1px solid rgba(255,255,255,0.06); }
.rep-odds-row:last-child { border-bottom:none; }
.rep-odds-head { font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-secondary); text-align:center; }
.rep-odds-head > span:first-child { text-align:left; }
/* Phones show O/U (the full label was the one cell that made the app's table
   scroll sideways, 2026-09-11); the long form stays for screen readers. */
.rep-th-short { display:none; }
.rep-odds-row > span:first-child { font-size:16px; font-weight:600; color:var(--text-primary); overflow-wrap:anywhere; }
.rep-odds-cell { display:flex; flex-direction:column; align-items:center; justify-self:center; gap:1px; min-width:0; max-width:100%; padding:4px 8px; border:1px solid transparent; border-radius:6px; font-family:'IBM Plex Mono',monospace; font-size:16px; line-height:1.25; color:var(--text-primary); text-align:center; }
.rep-odds-cell small { font-size:17px; font-weight:700; }
.rep-odds-cell.is-pick { background:rgba(34,197,94,0.12); border-color:var(--accent); }
.rep-card-strip { padding:8px 14px; border-top:1px solid rgba(255,255,255,0.06); font-size:16px; color:var(--text-primary); }
.rep-strip-k { font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-secondary); margin-right:8px; }
.rep-pct-prob { font-family:'IBM Plex Mono',monospace; font-weight:700; }
.rep-card--quiet .rep-verdict { border-top:none; }
/* Phones (the app's own <=768 rules): the rail becomes a wrapped row of chips
   above the board, cells lose their side padding, the head and strips tuck
   in to 10px. Four columns stay; the probability stays under the price. */
@media (max-width: 767px) {
  .rep-board { grid-template-columns:1fr; gap:10px; }
  .rep-rail { display:flex; flex-wrap:wrap; gap:6px; border-right:none; padding:0 0 10px; border-bottom:1px solid var(--border); }
  /* The app's chips are 44px tall for the thumb; these are not tappable, so
     they take 36px and the strip wraps to three rows at 375 instead of four. */
  .rep-rail-cat, .rep-sidebar-item { flex:0 0 auto; white-space:nowrap; min-height:36px; margin:0; padding:6px 12px; border:1px solid var(--border); border-radius:999px; color:var(--text-primary); display:inline-flex; align-items:center; }
  .rep-rail-cat::before, .rep-rail-cat.open::before { content:none; }
  .rep-sidebar-item.active { border-color:var(--accent); }
  .rep-th-long { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
  .rep-th-short { display:inline; }
  .rep-odds-head { letter-spacing:0.04em; }
  .rep-search-input { width:100%; }
  .rep-odds-head, .rep-odds-row { gap:2px; padding:6px 3px 6px 10px; }
  .rep-odds-row > span:first-child { padding-right:2px; }
  .rep-odds-cell { padding:4px 2px; width:100%; }
  .rep-card-head, .rep-card-strip { padding-left:10px; padding-right:10px; }
}

/* --- Task 16: the takeover's grade line and ceiling (step 5) ---
   slate.css .slate-ts-grade / .slate-ts-grade-k / .is-refusal (the amber
   left border is the app's --accent-amber, #f59e0b, the deck's --amber) and
   .slate-ts-compelled with its key and range parts, values copied. The boxes
   take --bg-elevated where the app uses --bg-surface: inside the window,
   which is already --bg-surface, the app's value would leave them invisible. */
.rep-ts-grade { margin:10px 0 0; padding:10px 12px; border-left:3px solid var(--accent); border-radius:6px; background:var(--bg-elevated); color:var(--text-secondary); font-size:17px; line-height:1.5; }
.rep-ts-grade:first-child { margin-top:0; }
.rep-ts-grade.is-refusal { border-left-color:var(--amber); }
.rep-ts-grade-k { font-size:16px; font-weight:700; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.04em; }
.rep-ts-grade b { color:var(--text-primary); }
.rep-ts-compelled { margin:10px 0 0; padding:10px 12px; border-left:3px solid var(--text-dim); border-radius:6px; background:var(--bg-elevated); color:var(--text-secondary); font-size:17px; line-height:1.5; }
.rep-ts-compelled-k { font-weight:700; color:var(--text-primary); }
.rep-ts-compelled-range { margin-top:6px; font-family:'IBM Plex Mono',monospace; font-size:17px; }
.rep-ts-compelled-range-v { color:var(--text-dim); }
.rep-ts-compelled-range-m { color:var(--text-secondary); margin-left:8px; }
.rep-ts-compelled-range-m b { color:var(--text-primary); }

/* --- Task 17: the takeover's Signal stack, Confidence conviction and Line
   movement cards (step 6). Values copied from static/css/slate.css (.slate-sec
   and its head/title/meta/badge, .slate-sub-h, .slate-lm-wrap, .slate-lm-read
   via .slate-narr-body) and static/css/main.css (.slate-ss-sig and its parts,
   .slate-ss-sig--unavail, .slate-ctx-details summary, .slate-ss-conviction,
   .slate-ss-footnote). App tokens the deck lacks, as values: --text-sm 17px,
   --text-xs 16px, --border-subtle rgba(255,255,255,0.06), --text-faint
   #c6c6cd, --ev-pos #22c55e, --ev-neg #f87171, --slate-blue #60a5fa,
   --accent-amber-bg rgba(245,158,11,0.12). Deck-only (no app target, in the
   test's shared set): .rep-two-windows, the SVG stand-in's parts, .rep-lm-axis and .rep-lm-caption. */
.rep-sec, .rep-lm-card { display:block; background:var(--bg-card); border:1px solid var(--border); border-radius:10px; padding:18px 20px; min-width:0; }
.rep-sec + .rep-sec { margin-top:14px; }
.rep-sec-head { display:flex; align-items:center; flex-wrap:wrap; gap:8px 10px; margin-bottom:12px; }
.rep-sec-h { font-size:16px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.16em; font-weight:700; margin:0; line-height:1.4; }
.rep-sec-meta { margin-left:auto; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-dim); }
/* The header chip: the read module's tone (with = blue, against = amber). */
.rep-lm-chip { font-size:16px; font-weight:700; letter-spacing:0.06em; padding:1px 8px; border-radius:10px; text-transform:uppercase; }
.rep-lm-chip--blue { background:rgba(96,165,250,0.15); color:#60a5fa; }
.rep-lm-chip--amber { background:rgba(245,158,11,0.12); color:var(--amber); }
.rep-sub-h { font-size:16px; font-weight:700; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.12em; margin:12px 0 6px; display:flex; align-items:center; flex-wrap:wrap; }
.rep-sec-head + .rep-sub-h { margin-top:0; }
.rep-ss-count { font-weight:400; text-transform:none; letter-spacing:0; margin-left:6px; color:var(--text-muted); }
/* One signal row (name | bar | favored side or Agrees | probability), the
   explanation on its own full-width line beneath. The app's desktop grid is
   1fr auto 52px auto (name, side, prob, magnitude); the bar takes the
   magnitude cell's place since the deck merges no /signals-fired payload.
   The bar is the flexible track (so the spanning explanation cannot size
   the name column) and the name is sized to its content, wrapping only
   when the row is narrower than name + bar + numbers. */
.rep-signal-row { display:grid; grid-template-columns:minmax(0,max-content) minmax(48px,1fr) auto auto; gap:4px 8px; padding:3px 0; border-bottom:1px solid rgba(255,255,255,0.06); font-size:17px; align-items:baseline; }
.rep-signal-name { color:var(--text-secondary); display:flex; align-items:center; min-width:0; }
.rep-signal-favor { color:var(--text-primary); font-weight:600; text-align:right; }
.rep-signal-favor--even { color:var(--text-muted); font-weight:400; }
.rep-signal-prob { color:var(--text-secondary); font-family:'IBM Plex Mono',monospace; text-align:right; }
.rep-signal-explain { grid-column:1 / -1; font-size:16px; color:var(--text-muted); line-height:1.4; }
.rep-signal-agree { color:#22c55e; }
.rep-signal-disagree { color:#f87171; }
/* 0.7, not the app's 0.55 (main.css .slate-ss-sig--unavail): at 0.55 the 16px
   "Unavailable" line (text-muted over the card) came to 3.4:1, under the
   4.5:1 bar; 0.7 reads 4.9:1 and the row still reads as dark (accessibility
   audit, Task 28). */
/* "+ N signals without data": the app's <summary> (44px tall for the thumb);
   the dark rows follow it, as they do when the disclosure is open. */
.rep-conviction { max-width:720px; }
.rep-ss-footnote { margin-top:4px; font-size:16px; color:#c6c6cd; line-height:1.4; }
/* The chart host and the read beneath it. The app's plot is 180px tall (300
   on phones, for a five-book legend); the stand-in has no legend, so 180. */
.rep-lm-wrap { height:180px; position:relative; }
.rep-lm-svg { display:block; width:100%; height:100%; }
.rep-lm-grid { stroke:rgba(255,255,255,0.08); stroke-width:1; vector-effect:non-scaling-stroke; }
.rep-lm-line { fill:none; stroke-width:2; stroke-linejoin:round; stroke-linecap:round; vector-effect:non-scaling-stroke; }
.rep-lm-axis { display:flex; justify-content:space-between; gap:12px; margin-top:6px; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-dim); }
.rep-lm-read { margin-top:12px; color:var(--text-muted); font-size:16px; line-height:1.7; }
.rep-lm-read p { margin:0; }
/* Narrow containers: the app's <=639px row (the name on its own line, the
   numbers on the next) also applies while the two windows share the width
   (769-1200px), where each is ~460-560px wide. */
@media (max-width: 639px), (min-width: 769px) and (max-width: 1200px) {
  .rep-signal-row { grid-template-columns:minmax(48px,1fr) auto auto; }
  .rep-signal-name { grid-column:1 / -1; }
  .rep-signal-favor { text-align:left; }
}
@media (max-width: 768px) {
  .rep-sec, .rep-lm-card { padding:14px 14px; }
  .rep-lm-read { font-size:17px; line-height:1.6; }
}

/* --- Task 18: the takeover's summary mosaic, the settled outcome line and the
   locked card (step 7). Values copied from static/css/slate.css
   (.slate-takeover-summary, .slate-ts-cell and its -l / -v / -sub parts,
   .accent / .lock / .book, .slate-ts-band and its range / mark; the phone
   rules at <=639px) and static/css/main.css (.ce-locked-card,
   .ce-locked-card.ce-locked-inline, .ce-locked-blur, .ce-locked-badge). App
   tokens the deck lacks, as values: --slate-border-soft rgba(255,255,255,0.04),
   --slate-bg = --bg-base, --slate-text-3 = --text-dim, --slate-text-4 #b0b0ba,
   --slate-green = --accent, --slate-blue #60a5fa, --border-default =
   --border-strong, --text-xs 16px. Deck-only (the test's shared set):
   .rep-outcome (no app surface prints a settled pick's outcome on a
   takeover) and .rep-locked-line (the app styles the blurred lines through
   .ce-locked-blur; the line class itself has no rule). */
.rep-takeover-summary { display:grid; grid-template-columns:repeat(4,1fr); gap:1px; margin-top:10px; background:rgba(255,255,255,0.04); border:1px solid var(--border); border-radius:10px; overflow:hidden; }
.rep-ts-cell { background:var(--bg-base); padding:18px 12px; text-align:center; min-width:0; }
.rep-ts-cell-l { font-size:16px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.14em; font-weight:700; display:flex; align-items:center; justify-content:center; flex-wrap:wrap; }
.rep-ts-cell-v { font-family:'IBM Plex Mono',monospace; font-size:28px; font-weight:800; color:var(--text-primary); margin-top:8px; line-height:1; overflow-wrap:anywhere; }
.rep-ts-cell-v.accent { color:var(--accent); }
.rep-ts-cell-v.lock { color:#60a5fa; }
.rep-ts-cell-v.book { font-family:'IBM Plex Sans',sans-serif; font-size:18px; }
.rep-ts-cell-sub { font-size:16px; color:#b0b0ba; margin-top:6px; font-family:'IBM Plex Mono',monospace; display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:2px 0; overflow-wrap:anywhere; }
.rep-ts-band { margin-top:6px; padding-top:6px; border-top:1px dashed var(--border); }
.rep-ts-band-range { font-size:17px; color:var(--text-dim); letter-spacing:0.01em; }
.rep-ts-band-mark { font-size:16px; color:var(--text-secondary); margin-top:2px; }
.rep-ts-band-mark b { color:var(--text-primary); }
/* The window's parts come and go by the hidden attribute; the class rules
   above set display (the badge, the strip, the section), which would outrank
   the UA's [hidden]{display:none} -- the app's own fix, main.css .ob-card[hidden]. */
#samplePick [hidden] { display:none; }
/* The chrome wraps so the failure badge drops under the label on a phone
   instead of stacking four lines beside it. */
#samplePick .rep-chrome { flex-wrap:wrap; row-gap:6px; }
#samplePick .rep-sec { margin-top:10px; }
#samplePick .rep-ts-grade, #samplePick .rep-ts-compelled { margin-top:10px; }
/* The settled kind's outcome, beneath the stack: the record slide's own
   vocabulary (per $100 staked), mono like the as-of line. */
.rep-outcome { margin-top:10px; padding:8px 12px; border-left:3px solid var(--text-dim); border-radius:6px; background:var(--bg-elevated); font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-secondary); overflow-wrap:anywhere; }
/* The locked card's inline variant (tiers.js lockedCardInlineHtml): dashed
   box, the two placeholder lines blurred, the Pro badge beside them. The
   app's lines are --text-xs; here 16px, the floor. */
.rep-locked-card { position:relative; display:inline-flex; align-items:center; gap:8px; min-width:0; max-width:100%; padding:4px 8px; border:1px dashed var(--border-strong); border-radius:6px; background:var(--bg-elevated); color:var(--text-primary); font:inherit; vertical-align:middle; }
.rep-locked-card.rep-locked-inline { cursor:inherit; }
.rep-locked-blur { display:flex; flex-direction:column; gap:2px; filter:blur(4px); user-select:none; pointer-events:none; font-size:16px; line-height:1.2; color:var(--text-muted); min-width:0; overflow:hidden; }
.rep-locked-line { display:block; white-space:nowrap; }
.rep-locked-badge { font-size:16px; font-weight:600; letter-spacing:0.04em; text-transform:uppercase; color:var(--accent); white-space:nowrap; }
/* Phones (slate.css <=639px): the mosaic becomes a 2x2 grid, the values 22px. */
@media (max-width: 639px) {
  .rep-takeover-summary { grid-template-columns:repeat(2,1fr); }
  .rep-ts-cell { padding:14px 8px; }
  .rep-ts-cell-v { font-size:22px; margin-top:6px; }
  .rep-ts-cell-v.book { font-size:17px; }
  .rep-ts-cell-sub { font-size:16px; }
}

/* --- Task 19: the chat panel and the entry pill (step 8). Values copied from
   static/css/chat.css (.ce-chat-panel, .ce-chat-header, .ce-chat-title,
   .chat-messages, .chat-msg and its user / assistant variants, .chat-table,
   .chat-cite, .chat-sources, .chat-h, .chat-note, .chat-status,
   .chat-composer, .chat-input, .chat-btn / .chat-btn-primary, .ce-chat-fab,
   its two labels and .ce-chat-mark). App tokens the deck lacks, as values:
   --border-default = --border-strong, --bg-raised = --bg-elevated,
   --text-dim (the app's, on --text-primary) = the deck's --text-dim,
   --radius-sm 6px. The panel is fixed and 420px wide in the app; here it
   fills the product window, as the same classes do on the /chat page
   (.chat-conversation). The message list does not scroll: the window grows.
   The pill is static, not fixed: it is shown, not offered. Deck-only (the
   test's shared set): .rep-fab-demo, the row that holds the pill and its
   caption. The rendered answer carries the panel's own class names
   (CEChatThread.renderMarkdown); deck_logic.js repClasses maps each onto
   its rep- twin below. */
.rep-body.rep-chat-panel { padding:0; display:flex; flex-direction:column; background:var(--bg-card); color:var(--text-primary); font-size:16px; }
.rep-chat-header { display:flex; align-items:center; gap:8px; padding:12px 12px 8px; border-bottom:1px solid var(--border-strong); flex-wrap:wrap; }
.rep-chat-title { font-size:18px; font-weight:700; margin:0; flex:1 1 auto; }
.rep-chat-header .rep-chat-cap { font-family:inherit; color:var(--text-dim); }
.rep-chat-messages { padding:12px; display:flex; flex-direction:column; gap:10px; min-height:44px; }
.rep-chat-msg { max-width:92%; padding:10px 12px; border-radius:12px; line-height:1.45; font-size:16px; overflow-wrap:anywhere; }
.rep-chat-msg p { margin:0 0 8px; }
.rep-chat-msg p:last-child { margin-bottom:0; }
.rep-chat-msg ul, .rep-chat-msg ol { margin:0 0 8px; padding-left:20px; }
.rep-chat-msg-user { align-self:flex-end; background:var(--accent); color:#0d1117; }
.rep-chat-msg-assistant { align-self:flex-start; background:var(--bg-elevated); border:1px solid var(--border-strong); position:relative; }
/* Marker 2 sits on the last answer's top-left corner, inside the message
   list's 12px padding, a stable element beside the re-rendered text. */
.rep-chat-note { font-style:italic; color:var(--text-dim); }
/* The table is the app's: collapsed borders, full width, the last column
   right-aligned in tabular figures. At phone width the columns take what
   they need and the message stays inside its bubble (the bubble wraps at
   any character); a wide grid scrolls inside the bubble rather than past it. */
.rep-chat-table { border-collapse:collapse; margin:8px 0; width:100%; font-size:16px; }
.rep-chat-table th, .rep-chat-table td { border:1px solid var(--border-strong); padding:6px 8px; text-align:left; }
.rep-chat-table td:last-child, .rep-chat-table th:last-child { text-align:right; font-variant-numeric:tabular-nums; }
.rep-chat-cite { font-size:16px; text-decoration:none; color:var(--accent); }
.rep-chat-sources { margin:8px 0 0; padding-left:20px; font-size:16px; color:var(--text-dim); }
.rep-chat-sources a { color:var(--accent); }
.rep-chat-h { font-size:16px; }
.rep-chat-status { min-height:20px; padding:0 12px 6px; font-size:16px; color:var(--text-dim); }
.rep-chat-composer { display:flex; gap:8px; padding:10px 12px; border-top:1px solid var(--border-strong); }
/* A span standing in for the textarea (a real field in the deck would be
   focusable but not the product); it shows the app's placeholder. */
.rep-chat-input { flex:1 1 auto; min-height:44px; padding:10px; border-radius:8px; border:1px solid var(--border-strong); background:var(--bg-base); color:var(--text-dim); font-size:16px; font-family:inherit; display:flex; align-items:center; min-width:0; }
.rep-chat-btn { display:inline-flex; align-items:center; justify-content:center; min-height:44px; padding:8px 14px; border-radius:6px; border:1px solid var(--border-strong); background:var(--bg-elevated); color:var(--text-primary); font-size:16px; white-space:nowrap; }
.rep-chat-btn-primary { background:var(--accent); color:#0d1117; border-color:var(--accent); font-weight:600; }
.rep-chat-btn:empty { display:none; }
/* The chrome carries the provenance line; it wraps under the title on a
   phone instead of clipping (the window is overflow:hidden). */
#exchange[data-state="loading"] .rep-chat-messages::before { content:'\2026'; color:var(--text-dim); }
/* The entry pill (chat.css .ce-chat-fab), static here. The app swaps the
   label for "Ask" at <=799px, where the fixed pill would occlude a phone's
   cards; the replica follows the app's rule so a phone shows what the app
   shows there. */
.rep-chat-fab { display:inline-flex; align-items:center; gap:8px; min-height:44px; padding:8px 14px 8px 12px; border-radius:6px; border:1px solid var(--accent); background:var(--bg-card); color:var(--text-primary); font-family:'IBM Plex Sans',system-ui,sans-serif; font-size:17px; font-weight:500; line-height:1.2; white-space:nowrap; box-shadow:0 4px 16px rgba(0,0,0,0.4); }
.rep-chat-mark { flex:0 0 auto; color:var(--accent); }
.rep-chat-fab-label-short { display:none; }
@media (max-width: 799px) {
  .rep-chat-fab-label { display:none; }
  .rep-chat-fab-label-short { display:inline; }
}
/* Phones: the bubbles take the full list width (the app's 92% is of a
   351px panel; the window here is 315px inside) and the outcome table
   keeps its last column -- the net, what each outcome pays -- and its
   headers whole, so the breaks overflow-wrap:anywhere allows land in the
   leg cells, never in the figure the narration points at. */
@media (max-width: 639px) {
  .rep-chat-msg { max-width:100%; }
  .rep-chat-table th, .rep-chat-table td { padding:6px 5px; }
  .rep-chat-table th { overflow-wrap:normal; }
  .rep-chat-table td:last-child, .rep-chat-table th:last-child { white-space:nowrap; }
  .rep-chat-table td:first-child, .rep-chat-table th:first-child { width:1%; }   /* the scenario column takes its min width; the leg cells get the rest */
}
/* --- Task 20: the Edge math card (step 9), the freshness header, the Your
   price card and the line-shopping table (step 10), the bankroll pill, the
   Settings row and the Sizing band (step 11). Values copied from
   static/css/slate.css (.slate-narr-body / .slate-narr-math; .slate-freshness
   and its ::before dot, .odds-format-toggle / .odds-format-btn,
   .my-book-select and its select; .slate-yp and its label / input / number /
   sub / results / cell / k / v / note / open parts; .slate-ls-table, its
   --books variant, tr.best, tr.mine, .slate-ls-price, .slate-ls-mine, the
   <=639px column cut) and static/css/main.css (.ob-verdict-mine; .top-nav-right,
   .top-nav-pill, .top-nav-icon-pill, .bankroll-pill and its sep / input /
   units / note, .top-nav-dropdown and its label). App tokens the deck lacks,
   as values: --slate-text-3 = --text-dim, --slate-text-2 = --text-muted,
   --slate-text = --text-primary, --slate-border rgba(255,255,255,0.08),
   --slate-border-soft rgba(255,255,255,0.04), --slate-green = --accent,
   --slate-red #f87171, --border-default rgba(255,255,255,0.1), --text-sm 17px,
   --text-xs 16px, --radius-sm 6px, --radius-md 8px, --space-xs 4px, --space-md
   12px; the app's 1.0625rem is 17px and its 1rem 16px. Three deliberate
   differences, each because a replica is shown rather than used: the inputs,
   the selects and the toggle are spans, not controls (a real field in the deck
   would be focusable but not the product); the pill's unit label stays visible
   at every width (the app hides it below 1440px for nav room; here it is the
   point) and its confirmation note sits in the flow under the pill instead of
   floating over whatever is beneath; the Settings select is drawn open, so
   its four options can be read. Deck-only (the test's shared set):
   .rep-repaint / .rep-state / .rep-state-k / .rep-state-l (no app surface
   shows two bankrolls at once) and .rep-pill-stack (the note is absolute in
   the app; here it is stacked under the pill) and .rep-risk-select / .rep-risk-option (the select is
   a native control with no rule of its own in static/css). */
.rep-narr-body { color:var(--text-muted); font-size:16px; line-height:1.7; }
.rep-narr-body p { margin:0; }
.rep-narr-body p + p { margin-top:10px; }
.rep-narr-body strong { color:var(--text-primary); }
.rep-narr-math { font-family:'IBM Plex Mono',monospace; background:rgba(255,255,255,0.04); padding:12px 14px; border-radius:6px; font-size:17px; line-height:1.7; margin:10px 0; overflow-wrap:anywhere; }
.rep-narr-math .accent { color:var(--accent); }
/* The freshness header: mono, the green dot the app draws with ::before, the
   format toggle pushed right, the My book select beside it. The app's phone
   rules: the row wraps at <=639px (the toggle loses its auto margin, the
   buttons grow to 44px) and the select takes the full width at <=540px. */
.rep-freshness { font-family:'IBM Plex Mono',monospace; font-size:17px; color:var(--text-dim); padding:6px 1px; margin:0 0 7px; display:flex; align-items:center; gap:6px; line-height:1.3; }
.rep-freshness::before { content:'\25CF'; font-size:16px; color:#22c55e; line-height:1; }
.rep-odds-toggle { margin-left:auto; display:inline-flex; gap:2px; padding:2px; border:1px solid rgba(255,255,255,0.08); border-radius:6px; flex:none; }
.rep-odds-btn { font:inherit; font-size:17px; line-height:1.4; min-height:26px; padding:3px 9px; border-radius:4px; background:transparent; color:var(--text-dim); display:inline-flex; align-items:center; }
.rep-odds-btn.active { background:rgba(255,255,255,0.08); color:var(--text-primary); font-weight:600; }
.rep-mybook { display:inline-flex; align-items:center; gap:6px; flex:none; font-family:'IBM Plex Sans',sans-serif; font-size:16px; color:var(--text-dim); }
.rep-mybook-select { display:inline-flex; align-items:center; gap:8px; font:inherit; font-size:16px; min-height:44px; padding:4px 8px; background:var(--bg-elevated); color:var(--text-primary); border:1px solid rgba(255,255,255,0.08); border-radius:6px; max-width:11rem; }
.rep-mybook-select::after { content:'\25BE'; color:var(--text-dim); }
@media (max-width: 639px) {
  .rep-freshness { flex-wrap:wrap; row-gap:6px; }
  .rep-odds-toggle { margin-left:0; }
  .rep-odds-btn { min-height:44px; padding:3px 14px; }
}
@media (max-width: 540px) {
  .rep-mybook { width:100%; justify-content:flex-end; }
}
/* The strip's My-book chip (app.js renderVerdictStrip): neutral, never green;
   red when the EV at the reader's book is negative. */
.rep-verdict-mine { color:var(--text-secondary); font-weight:500; }
.rep-verdict-mine.neg { color:#f87171; }
/* The Your price card: never green (green means "we recommend this" on every
   other surface); a negative value tints red. The input and the number
   select are spans showing the app's pre-fill and the selected option. */
.rep-yp { display:flex; flex-direction:column; gap:10px; }
.rep-yp-label { display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; font-size:16px; color:var(--text-muted); }
.rep-yp-input { display:inline-flex; align-items:center; font-family:'IBM Plex Mono',monospace; font-size:17px; font-weight:600; min-height:44px; width:9ch; padding:6px 10px; box-sizing:border-box; background:rgba(255,255,255,0.06); color:var(--text-primary); border:1px solid rgba(255,255,255,0.08); border-radius:6px; }
.rep-yp-number { display:inline-flex; align-items:center; gap:8px; font-size:17px; min-height:44px; padding:6px 10px; background:rgba(255,255,255,0.06); color:var(--text-primary); border:1px solid rgba(255,255,255,0.08); border-radius:6px; }
.rep-yp-number::after { content:'\25BE'; color:var(--text-dim); }
.rep-yp-sub, .rep-yp-note { margin:0; font-size:16px; color:var(--text-dim); line-height:1.5; }
.rep-yp-results { display:flex; flex-wrap:wrap; gap:8px 22px; }
.rep-yp-cell { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.rep-yp-k { font-size:16px; color:var(--text-dim); }
.rep-yp-v { font-family:'IBM Plex Mono',monospace; font-size:17px; font-weight:700; color:var(--text-primary); }
.rep-yp-v.neg { color:#f87171; }
.rep-yp-open { font-size:16px; color:var(--text-muted); text-decoration:underline; min-height:44px; display:inline-flex; align-items:center; align-self:flex-start; }
@media (max-width: 540px) {
  .rep-yp-results { flex-direction:column; gap:6px; }
}
/* The line-shopping table: the best row green, the reader's own book bold
   with the "your book" tag after its name. */
.rep-ls-table { width:100%; border-collapse:collapse; }
.rep-ls-table th { font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.12em; font-weight:700; padding:8px 10px; text-align:left; border-bottom:1px solid rgba(255,255,255,0.08); }
.rep-ls-table td { padding:10px; border-bottom:1px solid rgba(255,255,255,0.04); font-size:17px; color:var(--text-primary); }
.rep-ls-table tr.best { background:rgba(16,185,129,0.04); }
.rep-ls-table tr.best td { color:var(--accent); font-weight:700; }
.rep-ls-price { font-family:'IBM Plex Mono',monospace; font-weight:700; }
.rep-ls-table tr.mine td:first-child { font-weight:700; }
.rep-ls-mine { margin-left:6px; font-size:16px; font-weight:500; color:var(--text-dim); text-transform:none; letter-spacing:0; }
@media (max-width: 639px) {
  .rep-ls-table--books .rep-ls-col-implied { display:none; }
  .rep-ls-table--books th, .rep-ls-table--books td { padding:8px 6px; }
  .rep-ls-table--books td { font-size:16px; }
  .rep-ls-table--books th { letter-spacing:0.06em; }
}
/* The top bar's right-hand cluster: the bankroll pill and the Settings pill,
   the dropdown drawn beneath them as the app anchors it (right edge to the
   pill's). The unit label stays visible here at every width (see above). */
.rep-topbar { display:flex; align-items:center; justify-content:flex-end; gap:8px; flex-wrap:wrap; }
.rep-topbar-pill { background:none; border:1px solid var(--border-strong); border-radius:6px; padding:6px 14px; color:var(--text-secondary); font-size:17px; font-weight:500; font-family:'IBM Plex Sans',sans-serif; display:inline-flex; align-items:center; gap:6px; white-space:nowrap; min-height:44px; }
.rep-icon-pill { padding-left:9px; padding-right:9px; }
.rep-icon-pill svg { display:block; }
.rep-bankroll-pill { gap:2px; }
.rep-bankroll-sep { color:var(--text-muted); font-family:'IBM Plex Mono',monospace; font-weight:600; }
.rep-bankroll-input { color:var(--text-primary); font-family:'IBM Plex Mono',monospace; font-size:17px; font-weight:600; width:60px; }
.rep-bankroll-units { color:var(--text-muted); font-family:'IBM Plex Mono',monospace; font-size:17px; font-weight:600; border-left:1px solid rgba(255,255,255,0.1); padding-left:6px; margin-left:4px; }
.rep-bankroll-note { display:inline-block; margin-top:6px; white-space:nowrap; font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:600; color:var(--text-primary); background:var(--bg-surface); border:1px solid var(--border-strong); border-radius:6px; padding:6px 10px; box-shadow:0 8px 24px rgba(0,0,0,0.4); }
.rep-pill-stack { display:flex; flex-direction:column; align-items:flex-end; }
.rep-dropdown { width:260px; max-width:100%; margin:8px 0 0 auto; background:var(--bg-surface); border:1px solid rgba(255,255,255,0.1); border-radius:8px; padding:12px; box-shadow:0 8px 24px rgba(0,0,0,0.4); }
.rep-dropdown-label { font-size:17px; color:var(--text-secondary); display:block; margin-bottom:4px; }
.rep-risk-select { display:block; background:var(--bg-elevated); border:1px solid rgba(255,255,255,0.1); border-radius:6px; overflow:hidden; font-size:17px; }
.rep-risk-option { display:flex; align-items:center; min-height:44px; padding:4px 10px; color:var(--text-primary); border-top:1px solid rgba(255,255,255,0.06); }
.rep-risk-option:first-child { border-top:none; }
.rep-risk-option.selected { background:rgba(16,185,129,0.15); color:var(--accent); font-weight:600; }
/* The repaint panel: the same pick's three stake surfaces at two bankrolls,
   side by side (one column on phones). The Sizing cell and its band are the
   Task 18 replicas. */
.rep-repaint { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:14px; }
.rep-state { border:1px solid var(--border); border-radius:10px; padding:12px; background:var(--bg-card); min-width:0; }
/* No uppercase: the heading quotes the app's unit label, and "1U" is not it. */
.rep-state-k { font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:700; letter-spacing:0.04em; color:var(--text-dim); margin-bottom:8px; display:flex; align-items:center; flex-wrap:wrap; gap:4px 0; }
.rep-state-l { margin-top:10px; margin-bottom:4px; font-size:16px; color:var(--text-dim); }
.rep-state .rep-verdict { border-top:none; padding:0; }
.rep-state .rep-ts-cell { border:1px solid var(--border); border-radius:8px; text-align:left; padding:12px; }
.rep-state .rep-ts-cell-l { justify-content:flex-start; }
@media (max-width: 768px) {
  .rep-repaint { grid-template-columns:1fr; }
}
/* --- Task 21: the Props tab and its same-game slip (step 12), the account's
   four surfaces (step 13), the conviction card with its definition (step 14).
   Values copied from static/css/main.css (.props-header, .props-title,
   .how-pill, .props-sport-pills / .props-sport-pill, .props-sgp-toggle,
   .props-game-card and its header / matchup / count, .props-type-toggle and
   .props-team-toggle with their labels and chevrons, .props-team-body,
   .props-col-header, .props-player-row and its .props-sgp-mode tracks,
   .props-sgp-checkbox, .props-player-name, .props-line, .props-odds-cell,
   .props-shop-badge, .props-proj, .props-ev, .ce-yp-under, .ce-yp-chip,
   .props-sizing-cell, .game-strip-badge and its -bet / -lean tints; the
   .props-sgp-panel family; .ob-actions and .ob-action-watch / -log),
   static/css/slate.css (.slate-sec-info, .slate-sec-def and its -why line)
   and the /me family's own page styles, which are inline in
   routes/me_log_bet.py (.flash--ok, .link-btn, fieldset, legend, label,
   input, button, .row2), routes/me_clv_dashboard.py (.header-band,
   .stat-label, .stat-value, .profile-card, .profile-row),
   routes/me_alerts.py (.alert-row, .dot, .alert-title, .alert-meta,
   .alert-actions) and routes/_me_shared.py (.me-top-nav, .me-bottom-nav and
   its badge): nothing in static/css to map those to, so their rep- classes
   sit in the test's shared set and tests/test_tutorial_replicas_in_sync.py
   pins each one's app selector to its route file instead. App tokens the
   deck lacks, as values: --text-lg 22px, --text-base 18px, --text-sm 17px,
   --text-xs 16px, --border-default rgba(255,255,255,0.1), --border-subtle
   rgba(255,255,255,0.06), --accent-green #22c55e, --accent-green-bg
   rgba(34,197,94,0.12), --accent-amber-bg rgba(245,158,11,0.12), --text-faint
   #c6c6cd, --ev-pos #22c55e, --radius-pill 999px; the routes' 1.125rem is
   18px, 1.0625rem 17px, 1.2rem 19px. Liberties, each because a replica is
   shown rather than used: the pills, buttons, checkboxes, inputs and selects
   are spans (a real control in the deck would be focusable but not the
   product); on phones the app scrolls the props grid sideways inside the
   team body, while here the row wraps to three lines with the column words
   as small labels, so the EV, the chip and the grade the narration points at
   are on screen without a swipe, and at one-line widths the odds, EV and
   grade tracks take 120 / 96 / 100px where the app's 76 / 76 / 56 clip a
   22px price with its shop badge, a two-line chip and a grade word; the
   slip is static at its 340px (fixed,
   bottom-right in the app); the submit button's disabled state is drawn as
   the browser draws it, dimmed; the account's two navs are both drawn (the
   app shows one per width); the conviction card's definition is drawn open.
   Deck-only (the shared set): .rep-props-count-badge (the app's count is an
   inline style), .rep-ev-pos (the app colours the EV inline),
   .rep-me-page, .rep-profile-h / .rep-profile-check (the publish card's
   heading is an inline style and its checkbox a native control). */
.rep-props-header { display:flex; align-items:center; gap:10px 16px; flex-wrap:wrap; padding:8px 16px; border-bottom:1px solid rgba(255,255,255,0.06); }
.rep-props-title { font-size:22px; font-weight:700; color:var(--text-primary); margin:0; }
.rep-how-pill { display:inline-flex; align-items:center; gap:5px; padding:10px 16px; border-radius:999px; border:1px solid rgba(255,255,255,0.1); background:var(--bg-surface); color:var(--text-primary); font-size:18px; font-weight:600; white-space:nowrap; letter-spacing:0.02em; min-height:44px; }
.rep-props-sport-pills { display:flex; align-items:center; gap:2px; }
.rep-props-sport-pill { display:inline-flex; align-items:center; min-height:44px; border-bottom:2px solid transparent; color:var(--text-muted); padding:4px 12px; font-size:18px; font-weight:600; }
.rep-props-sport-pill.active { color:var(--accent); border-bottom-color:var(--accent); }
.rep-props-sgp-toggle { margin-left:auto; display:inline-flex; align-items:center; gap:6px; min-height:44px; padding:6px 14px; border:1px solid var(--accent); border-radius:999px; color:var(--accent); font-size:17px; font-weight:600; white-space:nowrap; }
.rep-props-game-card { margin-top:10px; background:var(--bg-card); border:1px solid rgba(255,255,255,0.1); border-radius:12px; overflow:hidden; }
.rep-props-game-header { display:flex; align-items:center; justify-content:space-between; gap:8px; flex-wrap:wrap; padding:10px 16px; background:var(--bg-surface); border-bottom:1px solid rgba(255,255,255,0.06); }
.rep-props-game-matchup { font-size:18px; font-weight:700; color:var(--text-primary); }
.rep-props-game-count { font-size:17px; color:var(--text-muted); }
.rep-props-type-toggle { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:10px 16px; background:var(--bg-surface); border-bottom:1px solid rgba(255,255,255,0.06); }
.rep-props-type-toggle-label { font-size:18px; font-weight:700; color:var(--text-primary); letter-spacing:0.02em; }
.rep-props-type-toggle-chevron, .rep-props-team-toggle-chevron { color:var(--text-muted); display:inline-block; }
.rep-props-type-toggle-chevron { font-size:18px; }
.rep-props-type-toggle.open .rep-props-type-toggle-chevron, .rep-props-team-toggle.open .rep-props-team-toggle-chevron { transform:rotate(90deg); }
.rep-props-team-toggle { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:7px 16px 7px 28px; background:var(--bg-card); }
.rep-props-team-toggle-label { font-size:18px; font-weight:600; color:var(--text-secondary); }
.rep-props-team-toggle-chevron { font-size:17px; }
.rep-props-count-badge { font-weight:400; color:var(--text-muted); margin-left:8px; }
.rep-props-type-toggle-label .rep-props-count-badge { font-size:17px; }
.rep-props-team-toggle-label .rep-props-count-badge { font-size:16px; margin-left:6px; }
.rep-props-col-header { display:grid; grid-template-columns:1fr 110px 120px 62px 96px 100px; gap:0; padding:5px 16px; font-size:17px; font-weight:700; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.04em; border-bottom:1px solid rgba(255,255,255,0.1); }
.rep-props-col-header > span { text-align:right; }
.rep-props-col-header > span:first-child { text-align:left; }
.rep-props-row { display:grid; grid-template-columns:1fr 110px 120px 62px 96px 100px; gap:0; align-items:center; padding:6px 16px; min-height:44px; font-size:18px; border-bottom:1px solid rgba(255,255,255,0.06); }
.rep-props-row:last-child { border-bottom:none; }
.rep-props-row.rep-props-sgp-mode, .rep-props-col-header.rep-props-sgp-mode { grid-template-columns:44px 1fr 110px 120px 62px 96px 100px; }
.rep-props-sgp-checkbox { display:inline-flex; align-items:center; justify-content:center; width:20px; height:20px; border:1.5px solid rgba(255,255,255,0.1); border-radius:4px; color:transparent; }
.rep-props-sgp-checkbox.checked { background:var(--accent); border-color:var(--accent); color:var(--bg-base); }
.rep-props-player-name { display:flex; align-items:center; font-weight:700; font-size:18px; color:var(--text-primary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; }
.rep-props-line { font-family:'IBM Plex Mono',monospace; font-weight:600; font-size:18px; color:var(--text-primary); text-align:right; }
.rep-props-odds-cell { text-align:right; font-family:'IBM Plex Mono',monospace; font-size:22px; color:var(--text-primary); }
.rep-props-shop-badge { display:inline-block; margin-left:6px; padding:1px 5px; border-radius:6px; background:rgba(59,130,246,0.10); color:#3b82f6; font-family:'IBM Plex Sans',sans-serif; font-size:16px; font-weight:600; vertical-align:middle; white-space:nowrap; }
.rep-props-proj { text-align:right; font-family:'IBM Plex Mono',monospace; color:var(--text-primary); font-size:22px; }
.rep-props-ev { text-align:right; font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:22px; }
.rep-ev-pos { color:#22c55e; }
.rep-yp-under { display:block; margin-top:2px; font-weight:500; text-align:right; }
.rep-yp-chip { display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:600; color:var(--text-secondary); white-space:normal; }
.rep-props-sizing-cell { text-align:center; }
.rep-strip-badge { display:inline-flex; padding:1px 6px; border-radius:999px; font-size:17px; font-weight:700; text-transform:uppercase; letter-spacing:0.03em; }
.rep-strip-badge-bet { background:rgba(34,197,94,0.12); color:#22c55e; }
.rep-strip-badge-lean { background:rgba(245,158,11,0.12); color:#f59e0b; }
/* Phones: the app scrolls the seven tracks sideways inside the team body; here
   the row wraps (the tick beside the name, then line / odds / projection, then
   the EV with its chip and the grade), the column words as labels. The cut is
   767px, not the app's 639: the window is narrower than the app's page, and
   the one-line row needs ~620px of tracks beside the name. */
@media (max-width: 767px) {
  .rep-props-col-header { display:none; }
  .rep-props-row, .rep-props-row.rep-props-sgp-mode { grid-template-columns:44px repeat(3,minmax(0,1fr)); gap:4px 8px; padding:8px 12px; }
  .rep-props-row > .rep-props-sgp-checkbox { grid-column:1; grid-row:1; }
  .rep-props-player-name { grid-column:2 / 5; grid-row:1; white-space:normal; }
  .rep-props-line { grid-column:2; grid-row:2; }
  .rep-props-odds-cell { grid-column:3; grid-row:2; display:flex; flex-direction:column; align-items:flex-start; }
  .rep-props-proj { grid-column:4; grid-row:2; }
  .rep-props-ev { grid-column:2 / 4; grid-row:3; }
  .rep-props-sizing-cell { grid-column:4; grid-row:3; text-align:left; }
  .rep-props-line, .rep-props-odds-cell, .rep-props-proj, .rep-props-ev, .rep-yp-under { text-align:left; }
  .rep-props-shop-badge { margin:2px 0 0; white-space:normal; }
  .rep-props-line::before, .rep-props-odds-cell::before, .rep-props-proj::before, .rep-props-ev::before { display:block; font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:700; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.04em; }
  .rep-props-line::before { content:'Line'; }
  .rep-props-odds-cell::before { content:'Odds'; }
  .rep-props-proj::before { content:'Proj'; }
  .rep-props-ev::before { content:'EV'; }
  .rep-props-team-toggle { padding-left:16px; }
}
/* The slip: the app's floating panel, in the flow at its own width. */
.rep-sgp-slip { width:340px; max-width:100%; flex:0 0 auto; background:var(--bg-card); border:1px solid rgba(255,255,255,0.1); border-radius:12px; box-shadow:0 10px 30px rgba(0,0,0,0.4); display:flex; flex-direction:column; }
.rep-sgp-panel-header { display:flex; align-items:center; gap:8px; padding:12px 16px; background:var(--bg-surface); border-bottom:1px solid rgba(255,255,255,0.06); border-radius:12px 12px 0 0; }
.rep-sgp-panel-title { font-weight:700; color:var(--text-primary); font-size:18px; white-space:nowrap; }
.rep-sgp-leg-count-wrap { font-size:17px; color:var(--text-muted); font-family:'IBM Plex Mono',monospace; white-space:nowrap; }
.rep-sgp-panel-close { margin-left:auto; color:var(--text-muted); font-size:20px; line-height:1; padding:0 4px; }
.rep-sgp-legs { padding:8px 12px; flex:1; min-height:60px; }
.rep-sgp-leg { display:flex; flex-wrap:wrap; align-items:center; gap:2px 8px; padding:8px 10px; margin-bottom:6px; background:var(--bg-surface); border-radius:6px; font-size:17px; }
.rep-sgp-leg-name { font-weight:700; color:var(--text-primary); flex-shrink:0; }
.rep-sgp-leg-detail { order:3; flex-basis:100%; min-width:0; color:var(--text-muted); font-family:'IBM Plex Mono',monospace; font-size:16px; }
.rep-sgp-leg-remove { margin-left:auto; color:#c6c6cd; font-size:18px; line-height:1; padding:0 4px; flex-shrink:0; }
.rep-sgp-actions { display:flex; gap:8px; padding:8px 12px; border-top:1px solid rgba(255,255,255,0.06); }
.rep-sgp-btn { flex:1; display:inline-flex; align-items:center; justify-content:center; min-height:44px; padding:8px 14px; border-radius:6px; font-size:17px; font-weight:600; }
.rep-sgp-btn-primary { background:var(--accent); color:var(--bg-base); }
.rep-sgp-btn-secondary { background:var(--bg-surface); color:var(--text-secondary); border:1px solid rgba(255,255,255,0.1); }
.rep-sgp-result { padding:0 16px 12px; }
.rep-sgp-result-row { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:6px 0; font-size:17px; border-top:1px solid rgba(255,255,255,0.06); color:var(--text-secondary); }
.rep-sgp-result-row:first-child { border-top:none; padding-top:10px; }
.rep-sgp-result-val { font-family:'IBM Plex Mono',monospace; font-weight:700; color:var(--text-primary); }
.rep-sgp-result-corr { color:#22c55e; font-style:italic; font-size:16px; padding:2px 0; border-top:none; }
/* Below 400px the slip is narrower than its 340px, and its header wraps. */
@media (max-width: 399px) {
  .rep-sgp-panel-header { flex-wrap:wrap; row-gap:4px; }
}
/* The account (step 13). The Log a Bet form after a submit: the page's own
   flash, fieldset, labels, inputs and button. */
.rep-logbet { font-family:'IBM Plex Sans',system-ui,sans-serif; color:var(--text-primary); }
.rep-logbet-flash { padding:13px 16px; border-radius:5px; margin:0 0 16px; font-size:18px; line-height:1.5; background:rgba(29,220,122,0.12); color:#22c55e; border:1px solid rgba(29,220,122,0.3); overflow-wrap:anywhere; }
.rep-logbet-flash strong { color:inherit; }
.rep-logbet-link-btn { margin-left:8px; color:inherit; text-decoration:underline; font:inherit; }
.rep-logbet-fieldset { border:1px solid var(--border); padding:14px 16px; margin:13px 0; border-radius:6px; background:var(--bg-card); }
.rep-logbet-legend { font-weight:600; color:var(--text-primary); font-size:18px; margin-bottom:2px; }
.rep-logbet-label { display:block; margin:10px 0 4px; font-weight:500; font-size:17px; color:var(--text-secondary); }
.rep-logbet-input { display:flex; align-items:center; width:100%; min-height:44px; padding:11px; font-size:18px; box-sizing:border-box; border:1px solid var(--border); border-radius:4px; background:var(--bg-base); color:var(--text-primary); }
.rep-logbet-select::after { content:'\25BE'; margin-left:auto; color:var(--text-dim); }
/* Dimmed like a disabled button, at 0.8 rather than the browser's ~0.65: the
   label is text on this slide, not an inactive control, and 0.65 put the
   ink on the green at 3.7:1; 0.8 is 5.1:1 (accessibility audit, Task 28). */
.rep-logbet-submit { display:flex; align-items:center; justify-content:center; width:100%; min-height:44px; margin-top:13px; padding:15px 24px; border-radius:5px; background:var(--accent); color:#0d1117; font-size:18px; font-weight:700; opacity:0.8; }
/* The dashboard's header band and the publish card. */
.rep-me-clv { background:var(--bg-card); border-left:3px solid var(--accent); padding:16px 18px; border-radius:0 5px 5px 0; margin:0 0 12px; display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:10px; }
.rep-stat-label { display:flex; align-items:center; flex-wrap:wrap; font-size:17px; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.04em; }
.rep-stat-value { font-size:19px; font-weight:700; margin-top:2px; color:var(--text-primary); }
.rep-stat-value.good { color:#22c55e; }
.rep-stat-value.bad { color:#f87171; }
.rep-profile-card { background:var(--bg-card); border:1px solid var(--border); border-radius:8px; padding:14px 18px; }
.rep-profile-h { font-size:18px; font-weight:700; margin-bottom:6px; color:var(--text-primary); }
.rep-profile-row { display:flex; align-items:center; gap:8px; min-height:44px; font-size:18px; color:var(--text-primary); }
.rep-profile-check { display:inline-block; width:18px; height:18px; border:1px solid var(--border-strong); border-radius:3px; background:var(--bg-base); flex-shrink:0; }
/* The card's actions row (main.css .ob-actions), beneath its head. */
.rep-ob-actions { display:flex; justify-content:flex-end; align-items:center; gap:8px; padding:10px 14px; }
.rep-ob-action-watch, .rep-ob-action-log { display:inline-flex; align-items:center; justify-content:center; font-size:16px; font-weight:600; line-height:1; padding:5px 9px; border-radius:6px; border:1px solid var(--border); background:var(--bg-surface); color:var(--text-secondary); }
.rep-ob-action-watch { padding:5px 8px; }
.rep-ob-action-watch.on { color:#f59e0b; border-color:#f59e0b; }
@media (max-width: 639px) {
  .rep-ob-action-watch, .rep-ob-action-log { min-height:44px; min-width:44px; }
}
/* /me/alerts: the account's top nav, one alert row, the phone nav with its
   unread badge (static here; fixed to the bottom of the screen in the app). */
.rep-me-page { padding:0 0 10px; }
.rep-me-top-nav { display:flex; flex-wrap:wrap; align-items:center; gap:2px 14px; padding:9px 16px; margin:0 0 14px; background:var(--bg-surface); border-bottom:1px solid rgba(255,255,255,0.1); font-size:17px; }
.rep-me-top-nav > span { display:inline-flex; align-items:center; min-height:44px; padding:6px 2px; color:var(--accent); }
.rep-me-top-nav > span.active { font-weight:700; color:var(--text-primary); }
.rep-me-top-nav > .rep-me-top-nav-slate { font-weight:600; color:#c6c6cd; margin-right:6px; }
.rep-alert-row { display:flex; gap:10px; align-items:flex-start; padding:11px 0; margin:0 14px; border-bottom:1px solid rgba(255,255,255,0.1); }
.rep-alert-row.unread { background:var(--bg-elevated); margin:0; padding:11px 14px; }
.rep-alert-dot { width:9px; height:9px; border-radius:50%; background:var(--accent); flex-shrink:0; margin-top:8px; }
.rep-alert-body { flex:1; min-width:0; }
.rep-alert-title { font-weight:600; font-size:18px; color:var(--text-primary); overflow-wrap:anywhere; }
.rep-alert-meta { color:#c6c6cd; font-size:16px; margin-top:2px; font-family:'IBM Plex Mono',monospace; overflow-wrap:anywhere; }
.rep-alert-actions { display:flex; gap:6px; flex-wrap:wrap; margin-top:6px; }
.rep-alert-actions > span { display:inline-flex; align-items:center; min-height:44px; color:var(--accent); font-size:16px; border:1px solid var(--accent); padding:3px 10px; border-radius:3px; }
/* The conviction card's definition control and block (slate.css
   .slate-sec-info / .slate-sec-def): the control drawn in its pressed state,
   the block open. .rep-conviction-row is the same row as .rep-signal-row. */
.rep-sec-info { position:relative; flex:0 0 auto; width:17px; height:17px; border-radius:50%; border:1.5px solid var(--accent); background:transparent; color:var(--accent); font-size:16px; font-weight:700; font-family:'IBM Plex Mono',monospace; line-height:1; display:inline-flex; align-items:center; justify-content:center; }
.rep-conviction-row { display:grid; grid-template-columns:minmax(0,max-content) minmax(48px,1fr) auto auto; gap:4px 8px; padding:3px 0; border-bottom:1px solid rgba(255,255,255,0.06); font-size:17px; align-items:baseline; }
/* The Task 17 narrow-row rules put .rep-signal-name on its own line at <=639px
   and while two windows share the width (769-1200px); the conviction row
   takes the same three-column template in both bands so the bar keeps its
   track under the name. */
@media (max-width: 639px), (min-width: 769px) and (max-width: 1200px) {
  .rep-conviction-row { grid-template-columns:minmax(48px,1fr) auto auto; }
  .rep-conviction-row .rep-signal-name { grid-column:1 / -1; }
  .rep-conviction-row .rep-signal-favor { text-align:left; }
}

/* ─── Task 27: the Best Bets block (step 3), the cards anatomy (Task 26b) ───
   static/css/slate.css .best-bets and its .bb-* parts (the cards redesign,
   docs/superpowers/specs/2026-09-21-best-bets-cards-design.md s6), values
   copied; the app's tokens as the deck's (--slate-text-3 = --text-dim,
   --slate-text-2 = --text-muted, --slate-text-1 = --text-primary,
   --slate-green = --accent, --slate-green-bright #34d399, --slate-amber =
   --amber, --slate-blue #60a5fa, --bg-raised #27272a, --accent-muted
   rgba(16,185,129,0.15), --slate-border rgba(255,255,255,0.08) = --border,
   --slate-border-soft rgba(255,255,255,0.04), --border-strong, --bg-elevated
   and --slate-bg-card = --bg-card as the deck's own, --radius-lg 12px,
   --radius-sm 6px). The markup is the view module's own with its classes
   re-prefixed and its controls drawn as spans (tests/js/tutorial_best_bets.test.js
   pins the bytes), so the app's hover and focus rules are not copied; the
   spans that stand in for buttons centre their label as a button does. One
   DOM for both layouts, like the app: three columns from 1280px, the tablist
   below it with the Moneyline list shown (data-tab on the block, as slate.js
   sets it). The summary line is in the markup and hidden, as the app hides it
   while the block is open. The slide is 1000px wide, so the deck's three
   columns are narrower than the app's tightest band (1280-1439px), and the
   lead card keeps that band's sizes (mark 48, name 20, chance 36) at every
   three-column width here, as the app's own rule for a block this wide.
   Measured (Task 26b, task27_check.py, Plex Mono loaded): the app's
   columns are 317px at 1280 and a row's widest pair of pills (`-105 BOV`
   + `no +4 at DK`, 224px) is at that width's limit; inside the deck's
   window frame the columns were 296px and those pills ran past the row.
   So step 3's window is flush (.rep-window--flush: no body padding, the
   window's border standing in for the block's) and, from 1280px, 30px
   wider than the slide on each side (inside the slide's 40px gutter),
   which gives the block the app's own 1280-1440 geometry: 326px columns,
   8px to spare on that pair. (The block's closing legend, and this
   replica's one deviation from the app's values for it, went with the
   legend on 2026-09-24: its terms now live behind "How this works".) */
.rep-window--flush .rep-body { padding:0; }
.rep-window--flush .rep-best-bets { border:0; border-radius:0; }
@media (min-width: 1280px) { .rep-window--flush { margin-left:-30px; margin-right:-30px; } }
.rep-best-bets { background:var(--bg-card); border:1px solid var(--border); border-radius:12px; padding:18px 20px 16px; }
.rep-bb-head { display:flex; justify-content:space-between; align-items:flex-start; gap:16px; }
.rep-bb-head-l { min-width:0; }
.rep-bb-eyebrow { font-family:'IBM Plex Mono',monospace; font-size:20px; font-weight:700; letter-spacing:0.08em; color:var(--text-muted); text-transform:uppercase; }
.rep-bb-title { font-size:24px; font-weight:600; color:var(--text-primary); margin:2px 0 4px; line-height:1.2; }
.rep-bb-sub { font-size:17px; color:var(--text-muted); margin:0; line-height:1.4; }
.rep-bb-how { color:#34d399; white-space:nowrap; }
.rep-bb-head-r { display:flex; align-items:center; gap:10px; flex-shrink:0; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-dim); }
.rep-bb-risk, .rep-bb-collapse { display:inline-flex; align-items:center; justify-content:center; box-sizing:border-box; font:inherit; color:inherit; border:1px solid var(--border); border-radius:6px; padding:5px 10px; min-height:32px; }
.rep-bb-collapse { min-width:44px; }
.rep-bb-summary { display:none; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-muted); margin-top:10px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rep-bb-tabs { display:none; }
.rep-bb-cols { display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); column-gap:20px; margin-top:16px; }
.rep-bb-col { min-width:0; }
.rep-bb-col-h { display:flex; align-items:center; gap:10px; font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:500; text-transform:uppercase; letter-spacing:0.06em; color:var(--text-dim); margin:0 0 10px; }
/* The books'-number tag and dot (the app's s6.2). */
.rep-bb-dot { display:inline-block; width:8px; height:8px; border-radius:50%; background:#60a5fa; flex:none; }
.rep-bb-src { display:inline-flex; align-items:center; gap:6px; font-size:16px; font-weight:400; text-transform:none; letter-spacing:0; color:var(--text-dim); border:1px solid var(--border); border-radius:6px; padding:3px 8px; line-height:1; white-space:nowrap; }
.rep-bb-src-dot { display:none; }
/* Marks: a logo in a box (the app's s4.5; every side here has a file). */
.rep-bb-mark { position:relative; display:inline-flex; align-items:center; justify-content:center; flex:none; }
.rep-bb-mark--lg { width:48px; height:48px; }
.rep-bb-mark--md { width:36px; height:36px; }
.rep-bb-logo { width:100%; height:100%; object-fit:contain; filter:drop-shadow(0 1px 1px rgba(0,0,0,0.6)); }
/* The pair side by side on one centre line, away first (the app's, 2026-09-24). */
.rep-bb-mark2 .rep-bb-logo { position:absolute; top:50%; width:64%; height:64%; transform:translateY(-50%); }
.rep-bb-mark2 .rep-bb-logo:first-child { left:-4%; }
.rep-bb-mark2 .rep-bb-logo:last-child { right:-4%; filter:drop-shadow(-2px 0 1px rgba(0,0,0,0.75)); }
/* The lead card (the app's s6.3). */
.rep-bb-lead { display:block; position:relative; overflow:hidden; background:linear-gradient(180deg, var(--bg-elevated) 0%, var(--bg-card) 100%); border:1px solid var(--border-strong); border-radius:12px; padding:16px 16px 14px; color:inherit; }
.rep-bb-lead::before { content:''; position:absolute; top:0; bottom:0; left:0; width:4px; background:var(--accent); }
.rep-bb-lead-top { display:flex; align-items:center; gap:10px; }
.rep-bb-lead-id { min-width:0; flex:1 1 auto; display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.rep-bb-lead-name { display:block; min-width:0; font-size:20px; font-weight:600; line-height:1.15; color:var(--text-primary); }
.rep-bb-pick-team { display:inline; white-space:normal; overflow-wrap:break-word; }
.rep-bb-pick-line { display:inline; white-space:nowrap; }
.rep-bb-pick-line::before { content:'\00a0'; }
.rep-bb-opponent { flex-basis:100%; font-size:16px; color:var(--text-dim); overflow-wrap:break-word; }
.rep-bb-lead-chance { margin-left:auto; text-align:right; flex:none; }
.rep-bb-lead-chance .rep-bb-chance { display:block; font-family:'IBM Plex Mono',monospace; font-size:36px; font-weight:700; line-height:1; letter-spacing:-0.02em; color:var(--text-primary); }
.rep-bb-chance-label { display:block; max-width:78px; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-dim); margin-top:2px; }
/* The meter (the app's s6.3): 22px of room above the track for the label. */
.rep-bb-meter { position:relative; display:block; height:10px; margin:30px 0 14px; background:#27272a; border-radius:999px; }
.rep-bb-meter-fill { position:absolute; top:0; bottom:0; left:0; border-radius:999px; background:linear-gradient(90deg, #0f766e, #10b981 60%, #34d399); }
.rep-bb-meter-tick { position:absolute; top:-3px; bottom:-3px; left:50%; width:2px; background:rgba(255,255,255,0.35); }
.rep-bb-meter-gap { position:absolute; top:0; bottom:0; }
.rep-bb-meter-gap--pay { background:repeating-linear-gradient(135deg, rgba(245,158,11,0.55) 0 3px, transparent 3px 6px); }
.rep-bb-meter-gap--edge { background:repeating-linear-gradient(135deg, rgba(52,211,153,0.85) 0 3px, transparent 3px 6px); }
.rep-bb-meter-mark { position:absolute; top:-6px; width:3px; height:22px; border-radius:2px; background:var(--text-primary); transform:translateX(-50%); }
.rep-bb-meter-label { position:absolute; bottom:26px; left:50%; transform:translateX(-50%); font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-dim); white-space:nowrap; }
.rep-bb-meter-fill, .rep-bb-meter-gap, .rep-bb-meter-mark { border-radius:999px; }
.rep-bb-lead-foot { display:flex; align-items:center; flex-wrap:wrap; gap:8px; }
.rep-bb-pill { display:inline-flex; align-items:center; font-family:'IBM Plex Mono',monospace; font-size:16px; line-height:1; padding:7px 10px; border-radius:6px; border:1px solid var(--border); color:var(--text-muted); white-space:nowrap; }
.rep-bb-pill-note { white-space:pre; } /* keeps the note's leading space in the flex pill, as slate.css */
.rep-bb-pill--best { background:rgba(16,185,129,0.15); border-color:rgba(16,185,129,0.45); color:var(--text-primary); }
.rep-bb-pill--mine { border-color:var(--border-strong); }
.rep-bb-pill--off { border-style:dashed; color:var(--text-dim); }
.rep-bb-evchip { margin-left:auto; display:inline-flex; align-items:center; font-family:'IBM Plex Mono',monospace; font-size:16px; line-height:1; padding:7px 10px; border-radius:6px; white-space:nowrap; }
.rep-bb-evchip--ev { background:var(--bg-elevated); border:1px solid var(--border); color:var(--text-muted); }
.rep-bb-evchip--edge { background:rgba(16,185,129,0.15); border:1px solid rgba(16,185,129,0.45); color:#34d399; font-weight:600; }
/* Rows 2-3 (the app's s6.4): the chance keeps its own column; line 2 wraps
   in steps and never ellipsizes (the pills drop under the text as a unit). */
.rep-bb-rows { list-style:none; margin:8px 0 0; padding:0; }
.rep-bb-row { display:grid; grid-template-columns:22px 36px minmax(0, 1fr) auto; grid-template-rows:auto auto; column-gap:10px; row-gap:4px; align-items:center; padding:10px 8px; border-top:1px solid rgba(255,255,255,0.04); border-radius:6px; color:inherit; }
.rep-bb-rank { grid-row:1 / span 2; align-self:start; line-height:36px; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-dim); text-align:center; }
.rep-bb-row .rep-bb-mark { grid-row:1 / span 2; align-self:start; }
.rep-bb-pick { display:block; min-width:0; font-size:18px; font-weight:500; color:var(--text-primary); }
.rep-bb-prob { grid-column:4; grid-row:1; align-self:start; text-align:right; }
.rep-bb-prob .rep-bb-chance { font-family:'IBM Plex Mono',monospace; font-size:22px; font-weight:600; line-height:1.1; color:var(--text-primary); }
.rep-bb-line2 { grid-column:3 / span 2; grid-row:2; display:flex; flex-wrap:wrap; align-items:center; gap:4px 8px; min-width:0; }
.rep-bb-when { flex:1 1 auto; min-width:0; display:flex; flex-wrap:wrap; align-items:baseline; column-gap:8px; row-gap:2px; font-size:16px; color:var(--text-dim); }
.rep-bb-pills { display:flex; flex-wrap:wrap; justify-content:flex-end; gap:6px; flex:0 1 auto; max-width:100%; margin-left:auto; }
.rep-bb-pills .rep-bb-pill, .rep-bb-pills .rep-bb-evchip { padding:4px 8px; }
@media (max-width: 1279px) {
  .rep-bb-head { flex-wrap:wrap; }
  .rep-bb-head-l { flex:1 1 320px; }
  .rep-bb-tabs { display:flex; gap:4px; margin-top:12px; }
  .rep-bb-tab { flex:1; display:inline-flex; align-items:center; justify-content:center; min-height:44px; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-muted); border:1px solid var(--border); border-radius:6px; }
  .rep-bb-tab[aria-selected="true"] { background:var(--bg-elevated); color:var(--text-primary); box-shadow:inset 0 -2px 0 var(--accent); }
  .rep-bb-src-dot { display:inline; margin-left:6px; color:#60a5fa; }
  .rep-bb-cols { grid-template-columns:minmax(0, 1fr); }
  .rep-bb-col-h .rep-bb-src { display:none; }
  .rep-best-bets[data-tab="moneyline"] .rep-bb-col:not([data-market="moneyline"]) { display:none; }
  .rep-bb-lead-foot .rep-bb-evchip { margin-left:0; }
}
@media (max-width: 639px) {
  .rep-best-bets { padding:14px 16px 12px; }
  .rep-bb-head { flex-direction:column; }
  .rep-bb-head-l { flex:0 1 auto; }
}
@media (max-width: 479px) {
  .rep-bb-head-r { flex-wrap:wrap; }
  .rep-bb-risk { white-space:nowrap; }
}

/* ─── One laptop screen per slide (Bill, 2026-09-24) ───
   The figure runs wider than the 1000px text column, centred, up to 1456px:
   the viewport less the slide's 40px gutters. min(0px, ...) keeps it from
   ever running narrower than the column (under the phone gutter the inner
   term turns positive). */
.s2-fig, .rep-window.s3-wide, .s3-graded, .s5-fig, .s6-fig, .s7-fig, .s9-fig, .s10-fig, .s11-fig, .s12-fig,
.s13-fig, .s14-fig, .s15-fig, #step-15 .record-verdict, .s15-foot, .s16-path, .rep-window.s16-deal, .s16-sign { margin-inline:min(0px, calc(50% - min(728px, 50vw - 40px))); }
/* The disclosure sits at the right end of the window's title bar. */
.s2-fig .rep-chrome, .s3-wide .rep-chrome, .s5-fig .rep-chrome, .s6-fig .rep-chrome, .s10-fig .rep-chrome, .s12-fig .rep-chrome,
.s13-fig .rep-chrome, .s14-fig .rep-chrome { flex-wrap:wrap; row-gap:4px; }
.s2-fig .rep-chrome .rep-asof, .s3-wide .rep-chrome .rep-asof, .s5-fig .rep-chrome .rep-asof, .s6-fig .rep-chrome .rep-asof,
.s10-fig .rep-chrome .rep-asof, .s12-fig .rep-chrome .rep-asof, .s13-fig .rep-chrome .rep-asof, .s14-fig .rep-chrome .rep-asof { margin:0 0 0 auto; }

/* Step 2: the board beside one card up close, one column under 1180px. */
.s2-fig { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.05fr); gap:20px; align-items:start; }
.s2-fig .rep-window, .s2-fig .rep-card--illustrative { margin:0; }
.s2-fig .rep-block-summary { white-space:normal; }
@media (min-width: 768px) {
  .s2-fig .rep-board { grid-template-columns:160px minmax(0,1fr); }
  .s2-fig .rep-rail-cat { padding:3px 10px 1px; line-height:1.3; }
  .s2-fig .rep-sidebar-item { padding:4px 12px; line-height:1.3; }
}
@media (max-width: 1179px) { .s2-fig { grid-template-columns:minmax(0,1fr); } }
/* The close-up is illustrative: a dashed amber border and a label in its
   header (deck-only; no card in the app is an example). */
.rep-card--illustrative { border-style:dashed; border-color:rgba(245,158,11,0.45); }
.rep-illustrative { font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:500; color:var(--amber); padding:1px 8px; border:1px dashed rgba(245,158,11,0.55); border-radius:6px; white-space:nowrap; }
/* The line above a spread or over/under price (main.css .ob-line: bold,
   primary, --text-base), and the legend row under the column heads
   (renderOddsBoxCard's subhead, each word in the colour of the value it
   names) on the odds rows' own grid. Phones hide the row and read one line
   above the table instead (.ob-legend-phone). */
.rep-odds-line { font-size:18px; font-weight:700; }
.rep-odds-sub { display:grid; grid-template-columns:1.4fr 1fr 1fr 1fr; gap:4px; padding:0 8px 8px 14px; border-bottom:1px solid var(--border); font-family:'IBM Plex Mono',monospace; font-size:16px; line-height:1.3; color:var(--text-muted); text-align:center; }
.rep-k-line, .rep-k-price, .rep-k-prob { color:var(--text-primary); white-space:nowrap; }
.rep-k-prob { font-weight:700; }
.rep-legend-phone { display:none; }
@media (max-width: 767px) {
  .rep-odds-sub { display:none; }
  .rep-legend-phone { display:block; font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-muted); text-align:right; padding:6px 10px 2px; line-height:1.3; }
}

/* Step 3: the block at the app's three-column width, and under it the
   illustrative graded pick on one line (wrapping on narrow screens). */
.rep-window.rep-window--flush.s3-wide { margin-top:0; margin-bottom:0; }
.s3-wide .rep-best-bets { padding:16px 20px 12px; }
.s3-graded { display:flex; align-items:center; flex-wrap:wrap; gap:6px 16px; margin-top:8px; padding:5px 16px; border:1px dashed rgba(245,158,11,0.55); border-radius:12px; background:var(--bg-card); }
.s3-graded-k { font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--amber); white-space:nowrap; }
.s3-graded-row { display:flex; align-items:center; flex-wrap:wrap; gap:6px 12px; flex:1 1 auto; min-width:0; }
.s3-graded-row .rep-bb-chance { font-family:'IBM Plex Mono',monospace; font-size:22px; font-weight:600; line-height:1.1; color:var(--text-primary); margin-left:auto; }
.s3-graded-row .rep-bb-evchip { margin-left:0; }
/* Step 3's no-graded-calls panel (Bill, 2026-09-27): hidden until its three recorded lines play,
   then it takes the lists' place (and the graded strip steps aside), keeping the slide one screen. */
.s3-nocall { display:none; margin:14px 0 4px; padding:12px 14px; border:1px solid var(--border); border-radius:8px; }
[data-beats]:is([data-now~="nocall"], [data-now~="gaps"], [data-now~="gapsh"]) .s3-nocall { display:block; }
[data-beats]:is([data-now~="nocall"], [data-now~="gaps"], [data-now~="gapsh"]) :is(.rep-bb-cols, .rep-bb-tabs, .s3-graded) { display:none !important; }
.s3-nocall-h, .s3-nocall-p, .s3-gaps li { font-size:17px; line-height:1.45; color:var(--text-muted); margin:0; }
.s3-nocall-p { margin-top:10px; }
.s3-nocall b { color:var(--text-primary); font-weight:600; }
.s3-nocall-k { font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--amber); white-space:nowrap; margin-left:8px; }
.s3-gaps { list-style:none; margin:4px 0 0; padding:0; }
.s3-gaps li { margin-top:4px; }
/* The grade chip beside a graded pick's name (slate.css .slate-grade-chip,
   placed by .bb-pick .slate-grade-chip; actionable is --slate-green, the
   deck's --accent). */
.rep-grade-chip { display:inline-flex; margin-left:8px; vertical-align:middle; font-size:16px; font-weight:800; letter-spacing:0.04em; line-height:1.25; white-space:nowrap; }
.rep-grade-chip--actionable { color:var(--accent); }
/* The edge-grade chip (slate.css .slate-grade-tag, CESlateGradeChip.edgeGradeTagHTML): steps 5 and 7. */
.rep-grade-tag { display:inline-flex; align-items:center; vertical-align:1px; font-family:var(--font-mono); font-size:16px; font-weight:700; letter-spacing:0.06em; line-height:1; padding:3px 8px; border-radius:4px; border:1px solid transparent; }
.rep-grade-tag--a { background:rgba(34,197,94,0.12); color:#22c55e; border-color:rgba(34,197,94,0.35); }
.rep-grade-tag--b { background:rgba(16,185,129,0.08); color:#10b981; border-color:rgba(16,185,129,0.28); }
.rep-grade-tag--lean { background:rgba(245,158,11,0.12); color:#f59e0b; border-color:rgba(245,158,11,0.35); }
.rep-grade-tag--defer { background:rgba(245,158,11,0.12); color:#f59e0b; border-color:rgba(245,158,11,0.35); }
.rep-grade-tag--suspect { background:rgba(239,68,68,0.12); color:#f87171; border-color:rgba(239,68,68,0.35); }

/* Step 5: the two panels above the takeover's grade line, as wide as 2 and 3. */
.s5-fig .rep-window { margin:18px 0 0; }

/* Step 6: two takeover windows for one game (tests/fixtures/tutorial/
   rams_broncos_2026-09-24.json), one column under 1180px. The Signal stack
   table is main.css .slate-ss-table and its parts, with the app's values
   (--text-sm 17px, --text-xs 16px, --text-faint #c6c6cd, --border-subtle
   rgba(255,255,255,0.06)); the detail rows set in two columns, without the
   app's explanation line or the deck's bar. */
.s6-fig { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:start; }
.s6-fig .rep-window { margin:0; }
.s6-fig .rep-body { padding:10px; }
.s6-fig .rep-sec, .s6-fig .rep-lm-card { padding:12px 16px; }
.s6-fig .rep-sub-h { margin:10px 0 4px; }
.s6-fig .rep-lm-wrap { height:130px; }
.rep-ss-scroll { overflow-x:auto; }
.rep-ss-table { width:100%; border-collapse:collapse; font-size:17px; }
.rep-ss-table th { text-align:right; font-size:16px; font-weight:700; color:var(--text-muted); padding:3px 6px; border-bottom:1px solid rgba(255,255,255,0.06); white-space:normal; overflow-wrap:break-word; vertical-align:bottom; }
.rep-ss-table th:first-child { text-align:left; }
.rep-ss-table td { padding:4px 6px; text-align:right; color:var(--text-secondary); font-family:'IBM Plex Mono',monospace; border-bottom:1px solid rgba(255,255,255,0.06); }
.rep-ss-table td:first-child { text-align:left; font-family:inherit; }
.rep-ss-table td.rep-ss-pick { font-weight:700; color:var(--text-primary); }
.rep-ss-table td.rep-ss-wt { color:#c6c6cd; }
.rep-ss-consensus td { font-weight:700; color:var(--text-primary); border-top:2px solid var(--border-strong); }
.rep-ss-th-short { display:none; }
.s6-detail { display:grid; grid-template-columns:1fr 1fr; column-gap:24px; }
/* Step 6's Market read (Bill, 2026-09-27): hidden until its three recorded lines play, then
   alone across the figure -- the signal stack and line movement windows step aside. */
.s6-fig .s6-mread { display:none; grid-column:1 / -1; }
[data-beats]:is([data-now~="mread"], [data-now~="mrows"]) .s6-fig .s6-mread { display:block; }
[data-beats]:is([data-now~="mread"], [data-now~="mrows"]) .s6-fig .rep-window:not(.s6-mread) { display:none !important; }
.rep-mread { margin:0; display:grid; gap:10px; padding:4px 8px; }
.rep-mread-row { display:grid; grid-template-columns:140px 1fr; gap:16px; align-items:baseline; }
.rep-mread dt { font-family:'IBM Plex Mono',monospace; font-size:16px; letter-spacing:0.04em; text-transform:uppercase; color:var(--text-dim); }
.rep-mread dd { margin:0; font-size:17px; line-height:1.5; color:var(--text-muted); }
@media (max-width: 639px) { .rep-mread-row { grid-template-columns:1fr; gap:2px; } }
.s6-detail .rep-signal-row { grid-template-columns:minmax(0,1fr) auto auto; padding:3px 0; }
@media (max-width: 1179px) { .s6-fig { grid-template-columns:minmax(0,1fr); } }
@media (max-width: 639px) {
  .s6-detail { grid-template-columns:1fr; }
  .rep-ss-th-long { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
  .rep-ss-th-short { display:inline; }
}

/* Step 7: the live pick beside the Free / Pro panel, one column under 1180px.
   A negative EV in the strip takes the neutral ink, never the edge green. */
.s7-fig { display:grid; grid-template-columns:minmax(0,1.7fr) minmax(0,1fr); gap:20px; align-items:start; }
.s7-fig .rep-window { margin:0; }
.s7-fig .rep-free-pro { grid-template-columns:1fr; margin-top:0; }
.rep-verdict-ev.neg { color:var(--text-secondary); font-weight:500; }
@media (max-width: 1179px) { .s7-fig { grid-template-columns:minmax(0,1fr); } }

/* Step 9: the +200 underdog, the Edge math card and the 100-bet ledger in one
   row, one column under 1180px. */
.s9-fig { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.15fr) minmax(0,1fr); gap:16px; align-items:start; }
.s9-fig .rep-window, .s9-fig .ev-example { margin:0; }
@media (max-width: 1179px) { .s9-fig { grid-template-columns:minmax(0,1fr); } }

/* Step 10: the board, the takeover's Your price card and its Line shopping
   table in one row, one column under 1180px. In the board's narrow column
   the freshness line takes a row of its own above the controls, and the Your
   price card's four results sit two by two. */
.s10-fig { display:grid; grid-template-columns:minmax(0,0.85fr) minmax(0,1.25fr) minmax(0,1fr); gap:16px; align-items:start; }
.s10-fig .rep-window { margin:0; }
.s10-fig .rep-freshness { flex-wrap:wrap; row-gap:8px; }
.s10-fig .rep-freshness > span:first-child { flex-basis:calc(100% - 22px); }
.s10-fig .rep-yp { gap:8px; }
.s10-fig .rep-yp-results { display:grid; grid-template-columns:auto auto; gap:6px 18px; justify-content:start; }
@media (max-width: 1179px) { .s10-fig { grid-template-columns:minmax(0,1fr); } }
/* From 1180 to 1439px the Line shopping window is narrower than its table,
   so the table drops Implied and tightens, as the app's does on a phone
   (slate.css .slate-ls-table--books under 640px). */
@media (min-width: 1180px) and (max-width: 1439px) {
  .s10-fig .rep-ls-table--books .rep-ls-col-implied { display:none; }
  .s10-fig .rep-ls-table--books th, .s10-fig .rep-ls-table--books td { padding:8px 6px; }
  .s10-fig .rep-ls-table--books td { font-size:16px; }
  .s10-fig .rep-ls-table--books th { letter-spacing:0.06em; }
}

/* Step 11: the top bar and Settings (the select closed on the default)
   beside the same pick at two bankrolls; across the bottom, one table of the
   four stops, each one's stake fraction and its Best Bets lambda. The table
   scrolls inside its own box where five columns do not fit. */
.s11-fig { display:grid; grid-template-columns:minmax(0,0.62fr) minmax(0,1.38fr); gap:14px 20px; align-items:start; }
.s11-fig .rep-window { margin:0; }
.s11-bottom { grid-column:1 / -1; overflow-x:auto; }
.s11-right .section-label { margin:0 0 6px; }
.s11-right .rep-repaint { margin-top:0; }
.s11-right .rep-state-l { margin-top:6px; margin-bottom:2px; }
.s11-right .rep-state .rep-ts-cell { padding:8px 12px; }
.s11-right .rep-ts-cell-v { font-size:22px; margin-top:4px; }
.s11-right .rep-ts-band { display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 14px; margin-top:4px; padding-top:4px; }
.s11-right .rep-ts-band-mark { margin-top:0; }
.s11-closed .rep-risk-option { border:none; }
.one-knob.s11-knob { width:100%; margin:0; }
.one-knob.s11-knob th, .one-knob.s11-knob td { padding:4px 10px; line-height:1.35; text-align:center; }
.one-knob.s11-knob th:first-child { text-align:left; }
.one-knob.s11-knob .is-set { color:var(--accent); font-weight:700; }
@media (max-width: 1179px) { .s11-fig { grid-template-columns:minmax(0,1fr); } }

/* Step 12: the Props Scanner window beside the Same-Game Parlay slip, drawn
   as the app draws it, a floating panel of its own at 340px (templates/
   index.html #props-sgp-panel), not a second window; one column under 1180px. */
.s12-fig { display:grid; grid-template-columns:minmax(0,1fr) 340px; gap:20px; align-items:start; }
.s12-fig .rep-window { margin:0; }
.s12-fig .rep-body { padding:10px; }
.s12-fig .rep-props-row { padding-block:3px; }
/* The slip, a little denser than the app's so the figure fits one screen:
   each leg's detail has a line of its own, and "Save Slip" keeps to one. */
.s12-fig .rep-sgp-panel-header { padding-block:8px; }
.s12-fig .rep-sgp-leg { padding-block:4px; margin-bottom:4px; line-height:1.3; }
.s12-fig .rep-sgp-actions { padding-block:6px; }
.s12-fig .rep-sgp-btn { padding-inline:8px; }
.s12-fig .rep-sgp-result-row { padding-block:4px; }
@media (max-width: 1179px) { .s12-fig { grid-template-columns:minmax(0,1fr); } }

/* Step 13: Log a Bet (its six fields three across, in the page's order), the
   CLV dashboard, and the board card's star above one alert, one column under
   1180px. The account's own spacing, tightened for one screen. */
.s13-fig { display:grid; grid-template-columns:minmax(0,1.25fr) minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:start; }
.s13-fig .rep-window { margin:0; }
.s13-fig .rep-body { padding:12px 14px; }
.s13-col { display:grid; gap:16px; align-content:start; }
.s13-fields { display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:0 10px; }
.s13-fig .rep-logbet-flash { margin-bottom:10px; padding:10px 14px; }
.s13-fig .rep-logbet-fieldset { margin:10px 0; padding:10px 14px 14px; }
.s13-fig .rep-logbet-label { margin:8px 0 4px; }
.s13-fig .rep-logbet-submit { margin-top:10px; padding-block:10px; }
.s13-fig .rep-me-clv { grid-template-columns:repeat(3, minmax(0,1fr)); }
.s13-fig .rep-me-page { padding:0; }
.s13-fig .rep-me-top-nav { margin:0; padding:4px 14px; }
.s13-fig .rep-me-top-nav > span { min-height:36px; }
.s13-fig .rep-card { margin:0; }
@media (max-width: 1179px) { .s13-fig { grid-template-columns:minmax(0,1fr); } }
@media (max-width: 639px) { .s13-fields { grid-template-columns:minmax(0,1fr); } }

/* Step 14: the conviction card, the calibration check drawn to scale, and
   step 3's Best Bets moneyline column wearing its books' number tag, one
   column under 1180px. The chart's text is at the 16px floor. */
.s14-fig { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.1fr) minmax(0,1fr); gap:16px; align-items:start; }
.s14-fig .rep-window { margin:0; }
.s14-fig .rep-conviction-row { grid-template-columns:minmax(0,1fr) auto auto; }
.s14-cal { container-type:inline-size; margin:0; padding:14px 16px 12px; background:var(--bg-card); border:1px solid var(--border); border-radius:12px; }
.s14-cal-h { font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:700; letter-spacing:0.06em; text-transform:uppercase; color:var(--text-muted); margin:0 0 6px; }
/* FIX 2026-10-05: the ticks, axis titles and note were SVG <text> in a width:100%
   viewBox="0 0 440 250": 11.1px on a phone, 15.9px at 1440. The SVG (cropped to
   y 0..202) draws marks only; the labels are HTML placed by its units. The x ticks
   and the x title are rows under it; the first and last x ticks align to their
   ends so the corner's two "50%" labels stay apart on a phone. */
.s14-plot { position:relative; }
.s14-chart { display:block; width:100%; height:auto; overflow:visible; }
.s14-grid { stroke:rgba(255,255,255,0.08); stroke-width:1; }
.s14-diag { stroke:rgba(255,255,255,0.35); stroke-width:1.5; stroke-dasharray:6 5; }
.s14-dot { fill:#10b981; }
.s14-dot--off { fill:#f59e0b; }
.s14-arrow { stroke:#f59e0b; stroke-width:2; }
.s14-arrowhead { fill:#f59e0b; }
.s14-tick { position:absolute; color:#a1a1aa; font-family:'IBM Plex Mono',monospace; font-size:16px; line-height:1.2; white-space:nowrap; }
.s14-ytick { right:calc(100% - 76 / 440 * 100%); top:calc(var(--y) / 202 * 100%); transform:translateY(-50%); }
.s14-xticks { position:relative; height:22px; margin-top:6px; }
.s14-xticks .s14-tick { top:0; left:calc(var(--x) / 440 * 100%); transform:translateX(-50%); }
.s14-xticks .s14-tick:first-child { transform:none; }
.s14-xticks .s14-tick:last-child { transform:translateX(-100%); }
.s14-axis { color:#c6c6cd; font-family:'IBM Plex Sans',system-ui,sans-serif; font-size:16px; line-height:1.2; white-space:nowrap; }
.s14-axis-x { padding:2px calc(16 / 440 * 100%) 0 calc(84 / 440 * 100%); text-align:center; }
.s14-axis-y { position:absolute; left:calc(12 / 440 * 100%); top:calc(105 / 202 * 100%); transform:translate(-50%, -50%) rotate(-90deg); }
.s14-note { position:absolute; left:calc(310.7 / 440 * 100%); top:calc(136 / 202 * 100%); transform:translateX(-50%); color:#f59e0b; font-family:'IBM Plex Sans',system-ui,sans-serif; font-size:16px; font-weight:600; line-height:1.2; white-space:nowrap; text-align:center; }
/* Its top sits under the amber dot (bottom at y 126), so a wrap grows down, clear of it.
   Narrow, the one-line note would cover the 60% dot: two lines under the arrow. */
@container (max-width:399px) { .s14-note { white-space:normal; width:6.5em; } }
.s14-cal-foot { font-size:16px; line-height:1.4; color:var(--text-muted); margin-top:4px; }
.s14-bb.rep-best-bets { border:0; border-radius:0; padding:0; background:transparent; }
.s14-bb .rep-bb-cols { grid-template-columns:minmax(0,1fr); margin-top:0; }
@media (max-width: 1179px) { .s14-fig { grid-template-columns:minmax(0,1fr); } }

/* Step 15: the live record's five figures in one row (the headline three and
   the two cohorts: their wrappers step aside with display:contents), the
   verdict under them, then the targets, the breakdown and the technical
   view's button on one footing. The win-rate tile's second paragraph is
   hidden here: the verdict under the row says the same. */
.s15-fig { display:grid; grid-template-columns:minmax(0,1.25fr) repeat(4, minmax(0,1fr)); gap:12px; align-items:stretch; }
.s15-fig > .record-live, .s15-fig > #recCohorts:not([hidden]), .s15-fig .record-cohort-tiles { display:contents; }
.s15-fig .record-tile { margin:0; }
.s15-fig #recBreakeven .dim, .s15-fig #recBreakeven br { display:none; }
#step-15 .record-verdict { margin-top:12px; }
.s15-foot { display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:start; gap:6px 20px; margin-top:12px; }
.s15-foot .record-targets, .s15-foot .record-breakdown, .s15-foot .record-tech-toggle { margin:0; }
@media (max-width: 1179px) { .s15-fig { grid-template-columns:minmax(0,1fr) minmax(0,1fr); } .s15-foot { grid-template-columns:minmax(0,1fr); } }

/* Step 16: the five pillars in one row; the deal panel's Free, Pro and
   actions side by side, one column under 1180px. */
.rep-window.s16-deal { margin-top:0; margin-bottom:0; }
.s16-deal .rep-free-pro { grid-template-columns:minmax(0,1fr) minmax(0,1.35fr) minmax(0,0.75fr); margin-top:0; align-items:start; }
.s16-deal .deal-headline { margin-bottom:12px; }
.s16-actions .deal-actions { flex-direction:column; align-items:stretch; margin-top:0; }
.s16-actions .rep-asof { margin-top:10px; }
@media (max-width: 1179px) { .s16-deal .rep-free-pro { grid-template-columns:minmax(0,1fr); } }

/* Step 7: the window opens on the app's top bar (Bill, 2026-09-25: read the
   analysis the way the narration does). The path is the deck's; the pill and
   My book are the replicas step 11 draws, a little shorter here. */
.rep-s7-bar { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px 16px; padding:0 0 10px; margin-bottom:10px; border-bottom:1px solid var(--border); }
.rep-crumbs { display:inline-flex; flex-wrap:wrap; align-items:center; gap:8px; }
.rep-crumb { font-size:16px; color:var(--text-muted); padding:4px 10px; border:1px solid var(--border); border-radius:6px; }
.rep-crumb--on { color:var(--accent); border-color:rgba(16,185,129,0.45); background:var(--accent-dim); font-weight:600; }
.rep-crumb-sep { color:var(--text-dim); font-size:18px; }
.rep-s7-bar .rep-topbar-pill, .rep-s7-bar .rep-mybook-select { min-height:36px; padding-block:4px; }
/* The takeover's recommendation badge (main.css .game-strip-badge-*). */
.rep-strip-badge { display:inline-flex; padding:1px 6px; border-radius:999px; font-size:17px; font-weight:700; text-transform:uppercase; letter-spacing:0.03em; vertical-align:1px; }
.rep-strip-badge--bet { background:rgba(34,197,94,0.12); color:#22c55e; }
.rep-strip-badge--lean { background:rgba(245,158,11,0.12); color:#f59e0b; }
.rep-strip-badge--lock { background:rgba(59,130,246,0.12); color:#3b82f6; }

/* Step 8 on one laptop screen (Bill, 2026-09-25): one title bar, the panel's
   own, with the entry pill; from 1180px the message list is a fixed height
   and scrolls itself as the app's panel does (chat_conversation.js), and the
   replay settles on the answer's top; the provenance is a line under it. */
.s8-fig, .s8-asof { margin-inline:min(0px, calc(50% - min(728px, 50vw - 40px))); }
.s8-asof { margin-top:8px; }
#exchange .rep-chat-header { flex-wrap:nowrap; padding:8px 12px; }
#exchange .rep-chat-header .rep-chat-cap { margin-left:auto; }
.s8-fab { margin-left:12px; font-size:16px; padding:4px 12px; }
#exchange .rep-chat-msg { max-width:min(92%, 1080px); }
#exchange .rep-chat-composer { padding:8px 12px; }
@media (min-width: 1180px) {
  #exchange .rep-chat-messages { height:276px; overflow-y:auto; scroll-behavior:smooth; }
}

/* Step 16: how to start, left to right, each step the app's own control
   (the replicas step 7 and step 11 draw), one line each. */
.s16-path { list-style:none; margin-block:0 14px; padding:0; display:grid; grid-template-columns:repeat(5, minmax(0,1fr)); gap:10px; }
.s16-step { position:relative; background:var(--bg-card); border:1px solid var(--border-strong); border-radius:10px; padding:10px 12px 8px; display:flex; flex-direction:column; gap:6px; }
.s16-step + .s16-step::before { content:"\203A"; position:absolute; left:-10px; top:50%; transform:translate(-50%,-50%); font-size:22px; color:var(--text-dim); }
.s16-ui { display:flex; flex-wrap:wrap; align-items:center; gap:6px; min-height:34px; }   /* one line at 1536; two in the 1180-1439 band */
.s16-cap { font-size:16px; color:var(--text-muted); }
.s16-path .rep-topbar-pill, .s16-path .rep-mybook-select { min-height:34px; padding-block:3px; }
.s16-path .rep-bb-pill { padding:4px 8px; }
.s16-bb { font-size:16px; color:var(--text-primary); padding:5px 10px; border:1px solid rgba(16,185,129,0.35); border-radius:6px; }
.s16-stake { font-family:'IBM Plex Mono',monospace; font-size:16px; color:var(--text-primary); }
.s16-path .rep-grade-chip { margin-left:0; }
.s16-sign { display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 14px; margin-top:10px; }
.s16-sign .hero-logo { font-size:22px; margin:0; }
.s16-sign .hero-tagline { font-size:16px; margin:0; }
.s16-rg { margin-left:auto; font-size:16px; color:var(--text-dim); }
.s16-rg b { color:var(--text-secondary); }
@media (max-width:1179px) { .s16-path { grid-template-columns:1fr 1fr; } .s16-step + .s16-step::before { display:none; } }
/* Step 8 on a phone: the five-column outcome table scrolls inside its bubble,
   as the app's panel does (chat.css, 2026-09-25). */
@media (max-width: 640px) {
  .rep-chat-table { display:block; overflow-x:auto; }
}
