/* Roboto and Roboto Condensed served from this site (public/fonts, latin and latin-ext; Apache 2.0 / OFL): every page sent
   each visitor's address to Google Fonts while the privacy policy said the pages load nothing from other companies'
   servers (launch check 2026-10-03). Roboto is one variable file for 400, 500 and 700. */
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400 700; font-stretch: 100%; font-display: swap; src: url(../fonts/roboto-latin-ext.woff2) format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400 700; font-stretch: 100%; font-display: swap; src: url(../fonts/roboto-latin.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Roboto Condensed'; font-style: normal; font-weight: 700; font-display: swap; src: url(../fonts/roboto-condensed-700-latin-ext.woff2) format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Roboto Condensed'; font-style: normal; font-weight: 700; font-display: swap; src: url(../fonts/roboto-condensed-700-latin.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
/* ============================================================
   One token set, two themes: the look Pigskin Lab has, shared by the
   three sibling sites (the engine CSS is byte-identical across them).

   Look: a reference database, not an app. Flat surfaces, hairline rules,
   square corners, dense tables, condensed uppercase section heads.
   Light is the default; dark is neutral charcoal (no tinted blues).
   Each site's accent (Pigskin Lab's red) comes from body[data-sport]:
   Batter Lab green, HoopVision Lab orange, Rinkside Lab blue, taken
   from each site's logo. Every colour in charts, tables and exported
   PNGs comes from these tokens.
   ============================================================ */

:root {
  color-scheme: light;
  --bg: #ffffff;
  --surface: #ffffff;
  --surface-2: #f4f4f4;
  --surface-3: #e8e8e8;
  --row-alt: #fafafa;
  --row-hover: #fff8d6;
  --border: #d0d0d0;
  --border-strong: #9a9a9a;
  --grid: #e9e9e9;
  --text: #111111;
  --text-2: #3b3b3b;
  --muted: #5f5f5f;
  --link: #0b57d0;
  --focus: #0b57d0;
  --brand: #c8102e;
  --brand-ink: #c8102e;   /* the brand red as small text: AA on the page background */
  --brand-btn: #c8102e;   /* the brand red behind white text */
  --ink-btn: #111111;
  --ink-btn-text: #ffffff;
  --header-bg: #111111;
  --header-ink: #ffffff;
  --header-muted: #bdbdbd;
  --sel: #0b57d0;

  --real: #0f7a34;
  --noise: #a84a06;
  --early: #1f4fc4;
  --void: #5f5f5f;
  --right: #0f7a34;
  --wrong: #b3261e;

  --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --s6: #008300;
  --div-neg: #c8322f; --div-mid: #f0efec; --div-pos: #2a78d6;

  --font: "Roboto", "Helvetica Neue", Arial, system-ui, sans-serif;
  --display: "Roboto Condensed", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #161616; --surface: #1d1d1d; --surface-2: #252525; --surface-3: #2f2f2f;
  --row-alt: #212121; --row-hover: #3a3520;
  --border: #3a3a3a; --border-strong: #6a6a6a; --grid: #2c2c2c;
  --text: #ededed; --text-2: #cfcfcf; --muted: #a8a8a8;
  --link: #8ab4f8; --focus: #8ab4f8; --brand: #e0443c; --brand-ink: #ff6b61; --brand-btn: #b8302a;
  --ink-btn: #ededed; --ink-btn-text: #111111;
  --header-bg: #0c0c0c; --header-ink: #ededed; --header-muted: #a8a8a8; --sel: #8ab4f8;
  --real: #16803c; --noise: #b4570c; --early: #2d5fd6; --void: #5f5f5f; --right: #3ecf73; --wrong: #ff7b72;
  --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500; --s5: #d55181; --s6: #2e9e2e;
  --div-neg: #e66767; --div-mid: #383835; --div-pos: #3987e5;
}

/* Each site's accent, where Pigskin Lab has its red: the rule under the header, the kicker, the
   headline's second line, step numbers, the sign-in panel, chart highlights. --brand is the colour
   as a large mark (3:1 on the page at least), --brand-ink as small text (4.5:1), --brand-btn behind
   white text (4.5:1). Links stay blue and buttons black, as on Pigskin Lab. */
body[data-sport="mlb"] { --brand: #138a43; --brand-ink: #0f6e36; --brand-btn: #0f7a3c; --brand-2: #1fa855; }
body[data-sport="nba"] { --brand: #e06a14; --brand-ink: #b4500a; --brand-btn: #b4500a; --brand-2: #f39a1a; }
body[data-sport="nhl"] { --brand: #0a7fe0; --brand-ink: #0864b0; --brand-btn: #0864b0; --brand-2: #00a3ee; }
:root[data-theme="dark"] body[data-sport="mlb"] { --brand: #2fb866; --brand-ink: #4cc97e; --brand-btn: #117a3d; }
:root[data-theme="dark"] body[data-sport="nba"] { --brand: #f08a36; --brand-ink: #ff9d4d; --brand-btn: #b4500a; }
:root[data-theme="dark"] body[data-sport="nhl"] { --brand: #3d9df0; --brand-ink: #6bb6ff; --brand-btn: #0864b0; }
/* The names the charts, widgets and makers read (public/js/charts.js tokens()), on this palette. */
:root, body { --line: var(--border); --faint: #7a7a7a; --accent: var(--brand); --accent-ink: #ffffff; --hl: #d4a72c; --good: var(--right); --bad: var(--wrong); --shadow: none; --radius: 0; --mono: ui-monospace, Consolas, monospace; }
:root[data-theme="dark"], :root[data-theme="dark"] body { --faint: #8a8a8a; }
[hidden] { display: none !important; }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--header-h, 90px) + 8px); }
body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.5 var(--font); min-height: 100vh; display: flex; flex-direction: column; }
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }
/* Links inside running text are underlined, not told apart by colour alone (WCAG 1.4.1). */
p a:not(.btn), .site-footer a, dd a, .notice a { text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
h1, h2, h3, h4 { font-family: var(--display); font-weight: 700; line-height: 1.15; margin: 0 0 .4em; }
h1 { font-size: 2rem; }
h2 { font-size: 1.15rem; text-transform: uppercase; letter-spacing: .02em; }
h3 { font-size: 1rem; }
p { margin: 0 0 .75em; }
.muted { color: var(--muted); }
.small { font-size: .85rem; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.wrap { width: 100%; max-width: 1320px; margin: 0 auto; padding: 0 16px; }
.wrap.wide { max-width: none; }
/* A screen tall before the page arrives: the footer then starts below the fold instead of
   sitting on screen and being shoved down (Lighthouse measured that jump as 0.15 layout shift). */
main { flex: 1; min-width: 0; padding-bottom: 40px; min-height: 100vh; }
main.flush { padding-bottom: 0; }
.skip { position: absolute; left: -999px; top: 8px; background: var(--surface); color: var(--text); padding: 8px 12px; z-index: 100; }
.skip:focus { left: 8px; }

/* ---------- header ---------- */
.site-header { background: var(--header-bg); color: var(--header-ink); position: sticky; top: 0; z-index: 40; border-bottom: 3px solid var(--brand); }
.site-header .wrap { display: flex; align-items: center; gap: 22px; height: 50px; max-width: none; }
.brand { color: var(--header-ink); font: 700 1.35rem/1 var(--display); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; display: flex; align-items: center; gap: 10px; }
.brand:hover { text-decoration: none; }
.brand .mark { display: inline-block; width: 12px; height: 12px; border: 3px solid var(--brand); transform: rotate(45deg); }
.nav { display: flex; flex: 1; overflow-x: auto; scrollbar-width: none; height: 100%; }
.nav::-webkit-scrollbar { display: none; }
.nav a { color: var(--header-muted); padding: 0 11px; font: 600 .8rem/50px var(--font); text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; border-bottom: 3px solid transparent; }
.nav a:hover { color: var(--header-ink); text-decoration: none; }
.nav a[aria-current="page"] { color: var(--header-ink); border-bottom-color: var(--header-ink); }
.header-tools { display: flex; align-items: center; gap: 8px; }
.site-header .search { position: relative; }
.site-header .search input { width: 210px; background: #2a2a2a; border: 1px solid #4a4a4a; color: #fff; padding: 5px 9px; }
.site-header .search input::placeholder { color: #a3a3a3; }
.search-results { position: absolute; right: 0; top: calc(100% + 4px); width: 320px; background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); padding: 4px 0; display: none; z-index: 60; }
.search-results.open { display: block; }
.search-results a { display: flex; justify-content: space-between; gap: 8px; padding: 6px 10px; color: var(--text); }
.search-results a small { color: var(--muted); }
.search-results a:hover, .search-results a.active { background: var(--row-hover); text-decoration: none; }
.icon-btn { background: transparent; border: 1px solid #4a4a4a; color: #ededed; height: 30px; padding: 0 9px; display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font: 600 .74rem/1 var(--font); text-transform: uppercase; letter-spacing: .04em; }
.icon-btn:hover { background: #2a2a2a; }
a.icon-btn { text-decoration: none; }
.icon-btn svg { width: 14px; height: 14px; }
/* Below 1366px the logo, eight links and the tools do not fit on one line (on a 1280px laptop
   "Trend watch" was cut off), so the links move to their own row and wrap there instead of
   scrolling sideways, where the last ones sat out of sight. */
@media (max-width: 1365px) {
  .site-header .wrap { flex-wrap: wrap; height: auto; padding-top: 8px; gap: 8px; }
  .nav { order: 3; flex-basis: 100%; height: auto; flex-wrap: wrap; justify-content: center; overflow: visible; padding-bottom: 2px; }
  .nav a { line-height: 34px; padding: 0 9px; }
  .header-tools { margin-left: auto; }
}
@media (max-width: 960px) {
  .site-header .search input { width: 150px; }
}

/* ---------- page furniture ---------- */
.page-head { padding: 16px 0 10px; border-bottom: 1px solid var(--border); margin-bottom: 14px; }
.page-head h1 { margin: 0 0 4px; }
.page-head p { color: var(--text-2); max-width: 72em; margin: 0; }
.crumbs { font-size: .78rem; color: var(--muted); margin-bottom: 4px; }
.crumbs a { color: var(--muted); }
.controls-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: end; margin-top: 10px; }
.section { margin-top: 26px; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; border-bottom: 2px solid var(--text); padding-bottom: 3px; margin-bottom: 10px; }
.section-head h2 { margin: 0; }
.section-head .more { font-size: .8rem; }
.box { background: var(--surface); border: 1px solid var(--border); padding: 10px 12px; }
.box > h3:first-child { margin-top: 0; }
.grid { display: grid; gap: 16px; }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr)); }
.grid.three { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.grid.side { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
@media (max-width: 960px) { .grid.side { grid-template-columns: minmax(0, 1fr); } }
.btn { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; height: 30px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); font: 600 .8rem/1.2 var(--font); cursor: pointer; white-space: nowrap; }
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn.primary { background: var(--ink-btn); color: var(--ink-btn-text); border-color: var(--ink-btn); }
.btn.primary:hover { opacity: .88; }
.btn.small { height: 26px; padding: 3px 8px; font-size: .75rem; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn svg { width: 14px; height: 14px; }
.seg { display: inline-flex; border: 1px solid var(--border-strong); height: 30px; }
.seg button { border: 0; border-right: 1px solid var(--border-strong); background: var(--surface); color: var(--text-2); padding: 0 10px; font: 600 .78rem/1 var(--font); cursor: pointer; }
.seg button:last-child { border-right: 0; }
.seg button[aria-pressed="true"], .seg button[aria-selected="true"] { background: var(--text); color: var(--bg); }
select, input[type="number"], input[type="text"], input[type="search"] {
  font: inherit; font-size: .84rem; color: var(--text); background: var(--surface); border: 1px solid var(--border-strong); border-radius: 0; padding: 3px 6px; min-width: 0; height: 30px;
}
input[type="number"] { width: 76px; }
input[type="color"] { width: 32px; height: 26px; padding: 1px; border: 1px solid var(--border-strong); background: var(--surface); cursor: pointer; }
input[type="checkbox"] { accent-color: var(--text); }
label.field { display: grid; gap: 2px; font-size: .68rem; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
label.check { display: inline-flex; gap: 6px; align-items: center; font-size: .84rem; color: var(--text-2); height: 30px; }
.notice { border-left: 3px solid var(--noise); background: var(--surface-2); padding: 8px 10px; font-size: .86rem; color: var(--text-2); }
.notice.info { border-color: var(--early); }
.error { color: var(--wrong); }
.loading { color: var(--muted); padding: 24px 0; }
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); border: 1px solid var(--border); background: var(--surface); }
.kpi { padding: 8px 12px; border-right: 1px solid var(--border); }
.kpi:last-child { border-right: 0; }
.kpi .v { font: 700 1.55rem/1.1 var(--display); font-variant-numeric: tabular-nums; }
.kpi .l { font-size: .7rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }

/* ---------- tables (reference-site style) ---------- */
.tbl-wrap { overflow: auto; border: 1px solid var(--border); max-width: 100%; background: var(--surface); }
.tbl-wrap.tall { max-height: 72vh; }
table.stats { border-collapse: collapse; width: 100%; font-size: .8rem; font-variant-numeric: tabular-nums; }
table.stats th, table.stats td { padding: 3px 7px; border-bottom: 1px solid var(--grid); white-space: nowrap; text-align: right; }
table.stats th.l, table.stats td.l { text-align: left; }
table.stats thead th { position: sticky; top: 0; z-index: 2; background: var(--surface-2); color: var(--text); font-weight: 700; border-bottom: 1px solid var(--border-strong); cursor: pointer; user-select: none; }
table.stats thead th[aria-sort="descending"]::after { content: " \25BC"; font-size: .6em; }
table.stats thead th[aria-sort="ascending"]::after { content: " \25B2"; font-size: .6em; }
table.stats thead th:hover { background: var(--surface-3); }
table.stats tbody tr:nth-child(even) td { background: var(--row-alt); }
table.stats tbody tr:hover td { background: var(--row-hover); }
table.stats td.rk { color: var(--muted); }
table.stats td.lead { font-weight: 700; }
table.stats tr.pin td { font-weight: 700; background: var(--row-hover); }
table.stats tfoot td { font-weight: 700; border-top: 1px solid var(--border-strong); background: var(--surface-2); position: sticky; bottom: 0; }
table.stats td .bar { display: inline-block; height: 8px; background: var(--s1); opacity: .35; vertical-align: middle; margin-right: 4px; }
.tbl-tools { display: flex; gap: 8px; flex-wrap: wrap; align-items: end; padding: 8px 0; }
.tbl-meta { font-size: .76rem; color: var(--muted); padding: 4px 0; }
.pop { position: relative; }
.pop .menu { position: absolute; z-index: 45; top: calc(100% + 2px); left: 0; background: var(--surface); border: 1px solid var(--border-strong); padding: 8px 10px; max-height: 380px; overflow: auto; min-width: 250px; display: none; }
.pop.open .menu { display: block; }
.pop .menu h4 { font-size: .68rem; text-transform: uppercase; color: var(--muted); margin: 8px 0 2px; letter-spacing: .05em; }
.pop .menu label { display: flex; gap: 6px; font-size: .82rem; padding: 1px 0; align-items: center; }
.filter-row { display: flex; gap: 4px; align-items: center; margin-bottom: 4px; }

/* ---------- team chip, badges ---------- */
.tchip { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--text); }
.tchip i { width: 4px; height: 15px; display: inline-block; background: var(--tc, var(--muted)); }
/* A club's colour on the dark card (fix.colour): the element carries --tc (3:1 on the light card) and --tc-dark (3:1 on
   the dark card, labcolor.js tcVars); a stylesheet !important beats the inline --tc, so navy and black strips stay visible. */
:root[data-theme="dark"] [style*="--tc-dark"] { --tc: var(--tc-dark) !important; }
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 2px 6px; font: 700 .66rem/1.3 var(--font); letter-spacing: .06em; text-transform: uppercase; color: #fff; white-space: nowrap; }
.badge svg { width: 11px; height: 11px; }
.badge.real { background: var(--real); }
.badge.noise { background: var(--noise); }
.badge.early { background: var(--early); }
.badge.void { background: var(--void); }
.outcome { display: inline-flex; align-items: center; gap: 4px; font-weight: 700; }
.outcome.right { color: var(--right); }
.outcome.wrong { color: var(--wrong); }
.outcome svg { width: 14px; height: 14px; }

/* ---------- trend cards (flat) ---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 310px), 1fr)); border-top: 1px solid var(--border); border-left: 1px solid var(--border); }
.vcard { display: flex; flex-direction: column; gap: 5px; background: var(--surface); border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 9px 12px 10px 14px; color: var(--text); position: relative; }
.vcard::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--tc, var(--border)); }
.vcard:hover { background: var(--row-hover); text-decoration: none; }
.vcard .top { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: .78rem; }
.vcard h3 { font: 700 1rem/1.2 var(--display); margin: 0; }
.vcard .vals { display: flex; gap: 12px; font-size: .78rem; color: var(--text-2); flex-wrap: wrap; font-variant-numeric: tabular-nums; }
.vcard .vals b { color: var(--text); }
.vcard .when { font-size: .78rem; color: var(--text-2); }
.vcard .when strong { color: var(--text); }
.meter { height: 6px; background: var(--surface-3); position: relative; }
.meter span { position: absolute; inset: 0 auto 0 0; background: var(--early); }
.meter.done span { background: var(--real); }
.meter-label { display: flex; justify-content: space-between; font-size: .7rem; color: var(--muted); margin-top: 2px; font-variant-numeric: tabular-nums; }

/* ---------- charts ---------- */
.chart { position: relative; width: 100%; }
.chart svg { display: block; width: 100%; height: auto; }
.chart.fill { height: 100%; min-height: 60px; }
.chart.fill svg { height: 100%; }
.chart-note { font-size: .74rem; color: var(--muted); margin-top: 4px; }
.legend { display: flex; flex-wrap: wrap; gap: 3px 14px; margin: 0 0 4px; font-size: .76rem; }
.legend button { display: inline-flex; align-items: center; gap: 5px; background: none; border: 0; padding: 1px 0; color: var(--text-2); font: inherit; cursor: pointer; }
.legend button[aria-pressed="false"] { opacity: .45; text-decoration: line-through; }
.legend svg { width: 12px; height: 12px; }
.tooltip { position: fixed; z-index: 90; pointer-events: none; background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); padding: 6px 8px; font-size: .78rem; line-height: 1.4; max-width: 320px; opacity: 0; }
.tooltip.on { opacity: 1; }
.tooltip .tt-h { font-weight: 700; margin-bottom: 2px; }
.tooltip .tt-r { display: flex; align-items: center; gap: 10px; justify-content: space-between; }
.tooltip .tt-r span:first-child { display: inline-flex; align-items: center; gap: 5px; color: var(--text-2); }
.tooltip .tt-r b { font-variant-numeric: tabular-nums; }
.tooltip .tt-note { color: var(--muted); margin-top: 2px; }

/* ---------- home ---------- */
.scoreboard { display: flex; overflow-x: auto; border: 1px solid var(--border); background: var(--surface); scrollbar-width: thin; }
.score { min-width: 142px; padding: 5px 10px; border-right: 1px solid var(--border); font-size: .78rem; color: var(--text); font-variant-numeric: tabular-nums; }
.score:hover { background: var(--row-hover); text-decoration: none; }
.score .ln { display: flex; justify-content: space-between; gap: 8px; }
.score .ln.win { font-weight: 700; }
.score .st { color: var(--muted); font-size: .66rem; text-transform: uppercase; letter-spacing: .04em; }
/* Six links, always in full rows: 3 across on a desktop, 2 on a tablet, 1 on a phone (auto-fit left five and an orphan). */
.tool-links { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--border); border-left: 1px solid var(--border); }
@media (max-width: 900px) { .tool-links { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .tool-links { grid-template-columns: minmax(0, 1fr); } }
.tool-links a { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); color: var(--text); background: var(--surface); }
.tool-links a:hover { background: var(--row-hover); text-decoration: none; }
.tool-links b { display: block; font: 700 1.05rem/1.2 var(--display); text-transform: uppercase; letter-spacing: .03em; }
.tool-links b::after { content: " ›"; color: var(--brand-ink); }
.tool-links span { color: var(--text-2); font-size: .86rem; line-height: 1.45; }

/* ---------- dashboard maker ---------- */
.dash-top { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; padding: 8px 0 6px; }
.dash-top .title-input { font: 700 1.25rem/1 var(--display); border: 1px solid transparent; background: transparent; height: 34px; width: 340px; max-width: 100%; }
.dash-top .title-input:hover, .dash-top .title-input:focus { border-color: var(--border-strong); background: var(--surface); }
.dash-top .spacer { flex: 1; }
.dash-top .sep { width: 1px; height: 22px; background: var(--border); margin: 0 4px; }
.board-scroll { overflow: auto; border: 1px solid var(--border-strong); background: var(--surface-2); }
.board { position: relative; background-color: var(--surface-2); }
.board.grid-on { background-image: linear-gradient(var(--grid) 1px, transparent 1px), linear-gradient(90deg, var(--grid) 1px, transparent 1px); background-size: 20px 20px; }
.board-empty { position: absolute; left: 0; right: 0; top: 60px; display: grid; place-items: center; text-align: center; color: var(--muted); }
.board-empty > div { max-width: 620px; background: var(--surface); border: 1px solid var(--border); padding: 16px 18px; }
.board-empty .presets { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: 10px; }
.widget { position: absolute; background: var(--surface); border: 1px solid var(--border-strong); display: flex; flex-direction: column; }
.widget.selected { outline: 2px solid var(--sel); z-index: 20; }
.widget .wbar { display: flex; align-items: center; gap: 6px; padding: 3px 4px 3px 9px; border-bottom: 1px solid var(--border); cursor: grab; user-select: none; touch-action: none; min-height: 34px; }
.widget.dragging .wbar { cursor: grabbing; }
.widget .wtitle { flex: 1; min-width: 0; }
.widget.pcoded { border-top: 5px solid var(--pc); }
.widget.pcoded .wtitle span::before { content: ''; display: inline-block; width: .6em; height: .6em; margin-right: .35em; background: var(--pc); vertical-align: baseline; }
.widget .wtitle b { display: block; font: 700 .9rem/1.2 var(--display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.widget .wtitle span { display: block; font-size: .7rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.widget .wtools { display: flex; gap: 1px; }
.widget .wtools button { width: 24px; height: 24px; display: grid; place-items: center; border: 1px solid transparent; background: none; color: var(--text-2); cursor: pointer; }
.widget .wtools button:hover { border-color: var(--border-strong); background: var(--surface-2); }
.widget .wtools svg { width: 13px; height: 13px; }
.widget .wbody { flex: 1; min-height: 0; padding: 4px 8px 6px; overflow: hidden; display: flex; flex-direction: column; }
.widget .wbody > .chart { flex: 1; min-height: 0; }
.widget .wbody > .tbl-wrap { flex: 1; min-height: 0; }
/* How it swung: the biggest swings listed under the game's margin chart, numbered like its markers, two lines each.
   A widget too short for both keeps the chart and its numbered markers (each marker's tip still tells the play). */
.widget .wbody:has(> .swings) { container-type: size; }
.widget .wbody > .swings { flex: none; list-style: none; counter-reset: swing; margin: 6px 0 0; padding: 6px 0 0; border-top: 1px solid var(--grid); font-size: .74rem; line-height: 1.35; color: var(--text-2); }
.swings li { counter-increment: swing; position: relative; padding-left: 24px; margin: 0 0 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.swings li::before { content: counter(swing); position: absolute; left: 0; top: 0; width: 17px; height: 17px; box-sizing: border-box; border-radius: 50%; border: 1.5px solid var(--text-2); display: grid; place-items: center; font-size: .66rem; font-weight: 700; color: var(--text); }
.swings li b { color: var(--text); font-weight: 700; }
@container (max-height: 330px) { .swings { display: none; } }
.widget .wnote { font-size: .68rem; color: var(--muted); padding: 2px 8px 3px; border-top: 1px solid var(--grid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.widget .h-se { position: absolute; width: 14px; height: 14px; right: -1px; bottom: -1px; cursor: nwse-resize; background: linear-gradient(135deg, transparent 55%, var(--border-strong) 55%); touch-action: none; }
.widget .h-e { position: absolute; top: 34px; bottom: 14px; right: -5px; width: 10px; cursor: ew-resize; touch-action: none; }
.widget .h-s { position: absolute; left: 0; right: 14px; bottom: -5px; height: 10px; cursor: ns-resize; touch-action: none; }
.widget.text .wbody { overflow: auto; }
.widget .note-edit { outline: none; min-height: 100%; font-size: .9rem; white-space: pre-wrap; }
.widget .kpi-big { font: 700 2.8rem/1 var(--display); font-variant-numeric: tabular-nums; }
.inspector { position: fixed; z-index: 70; width: 310px; max-height: 76vh; overflow: auto; background: var(--surface); border: 1px solid var(--text); padding: 10px 12px; box-shadow: 0 8px 28px rgba(0, 0, 0, .2); }
.inspector h3 { display: flex; justify-content: space-between; align-items: center; margin: 0 0 8px; font-size: .95rem; text-transform: uppercase; }
.inspector .row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 8px; }
.inspector .row.one { grid-template-columns: 1fr; }
.inspector .colors { display: grid; gap: 4px; margin-bottom: 8px; }
.inspector .colors label { display: flex; align-items: center; gap: 8px; font-size: .8rem; }
.inspector hr { border: 0; border-top: 1px solid var(--border); margin: 8px 0; }
.series-row { display: flex; gap: 4px; align-items: center; margin-top: 4px; }
.series-row .sw { width: 10px; height: 10px; flex: none; }
.series-row .x { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 1.1rem; padding: 0 2px; }
.ac { position: relative; }
.ac input { width: 170px; }
.ac-list { position: absolute; z-index: 80; left: 0; min-width: 270px; bottom: 100%; background: var(--surface); border: 1px solid var(--border-strong); max-height: 240px; overflow: auto; display: none; }
.ac-list.open { display: block; }
.ac-list button { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 5px 8px; color: var(--text); font: inherit; font-size: .8rem; cursor: pointer; }
.ac-list button:hover { background: var(--row-hover); }

/* ---------- misc ---------- */
.list { list-style: none; margin: 0; padding: 0; }
.list li { display: flex; gap: 10px; align-items: center; justify-content: space-between; padding: 5px 0; border-bottom: 1px solid var(--grid); flex-wrap: wrap; }
.results { display: flex; flex-wrap: wrap; gap: 2px; }
.results a { min-width: 28px; height: 22px; padding: 0 4px; display: grid; place-items: center; font: 700 .68rem/1 var(--font); color: #fff; }
.results a.w { background: var(--real); }
.results a.l { background: #b3261e; }
.results a.t { background: var(--void); }
.results a:hover { text-decoration: none; opacity: .85; }
.rule { display: grid; gap: 4px; padding: 10px 0; border-bottom: 1px solid var(--grid); }
.rule .rh { display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; align-items: center; }
.rule .nums { display: flex; gap: 16px; flex-wrap: wrap; font-size: .8rem; color: var(--text-2); }
.rule .nums b { color: var(--text); font-variant-numeric: tabular-nums; }
.src { font-size: .76rem; color: var(--muted); }
.site-footer { border-top: 1px solid var(--border); background: var(--surface-2); padding: 14px 0; font-size: .78rem; color: var(--muted); }
.site-footer .wrap { display: flex; gap: 16px; justify-content: space-between; flex-wrap: wrap; }
/* The sister sites and the author's site: a name and a caption each, above the credits. */
.site-footer .site-family { justify-content: flex-start; align-items: stretch; gap: 10px 12px; padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--border); }
.site-family .family-head { flex-basis: 100%; font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text-2); }
.site-footer .site-family a { display: grid; align-content: start; gap: 2px; flex: 1 1 140px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface, transparent); text-decoration: none; color: var(--text); }
.site-family a b { font-size: .86rem; }
.site-family a small { font-size: .74rem; color: var(--muted); }
/* Each site's colour, the same on every site: football red, baseball green, basketball orange,
   hockey blue, Mason Obegi purple. Darker shades on light, lighter on dark, for readable names. */
.site-family a { --fam: var(--text-2); }
.site-footer .site-family a { border-left: 4px solid var(--fam); }
.site-family a b { color: var(--fam); }
.site-footer .site-family a:hover, .site-footer .site-family a:focus-visible { border-color: var(--fam); }
.site-family .fam-football { --fam: #c8102e; }
.site-family .fam-baseball { --fam: #15803d; }
.site-family .fam-basketball { --fam: #c2410c; }
.site-family .fam-hockey { --fam: #1d4ed8; }
.site-family .fam-chess { --fam: #3f3f46; }
.site-family .fam-mason { --fam: #6d28d9; }
:root[data-theme="dark"] .site-family .fam-football { --fam: #f87171; }
:root[data-theme="dark"] .site-family .fam-baseball { --fam: #4ade80; }
:root[data-theme="dark"] .site-family .fam-basketball { --fam: #fb923c; }
:root[data-theme="dark"] .site-family .fam-hockey { --fam: #93c5fd; }
:root[data-theme="dark"] .site-family .fam-chess { --fam: #d4d4d8; }
:root[data-theme="dark"] .site-family .fam-mason { --fam: #c4b5fd; }

@media (prefers-reduced-motion: reduce) { * { transition-duration: 0s !important; animation-duration: 0s !important; } }
/* Phones: the wrapped header is too tall to pin, so it scrolls away with the page. */
@media (max-width: 600px) { .site-header { position: static; } }
/* Phones: logo and Menu on the first row, search and the two buttons on the second; the page
   links open under Menu. The tip bar stays off (the footer has the tip link and feedback), so the
   first screen is the page, not the site's furniture. */
.menu-btn { display: none; }
@media (max-width: 600px) {
  .site-header .wrap { padding-bottom: 8px; }
  .menu-btn { display: inline-flex; }
  .site-header:not(.menu-open) .nav { display: none; }
  .header-tools { flex-basis: 100%; margin-left: 0; order: 2; }
  .header-tools .search { flex: 1; min-width: 0; }
  .site-header .search input { width: 100%; }
  #theme-label { display: none; }
}
@media (max-width: 480px) { .nav a { padding: 0 7px; font-size: .74rem; line-height: 30px; } }
@media print { .site-header, .site-footer, .dock { display: none; } }
#theme-toggle[data-mode="dark"] .moon, #theme-toggle[data-mode="light"] .sun { display: none; }
body.no-select, body.no-select * { user-select: none !important; }

/* ============================================================
   Frames: panels, tables and widgets get a dark outline so each box
   reads as its own unit (light: near-black; dark: light gray).
   ============================================================ */
:root { --frame: #1f1f1f; --cat-chart: #1f5fbf; --cat-model: #6a3ca8; --cat-table: #0f7a34; --cat-note: #5f5f5f; }
:root[data-theme="dark"] { --frame: #8f8f8f; --cat-chart: #6ea2f0; --cat-model: #b996ec; --cat-table: #5fcf88; --cat-note: #b0b0b0; }
.box, .tbl-wrap, .kpis, .scoreboard, .widget, .board-scroll, .inspector { border-color: var(--frame); }
.tool-links, .tool-links a { border-color: var(--frame); }
.cards { border-color: var(--frame); }
.vcard { border-color: var(--frame); }
.grid.two > .box, .grid.side > .box { border-width: 1px; }

/* brand mark: a small grid, drawn in CSS */
.brand .mark { width: 16px; height: 16px; border: 0; transform: none; background:
  linear-gradient(var(--brand), var(--brand)) 0 0 / 100% 3px no-repeat,
  linear-gradient(var(--brand), var(--brand)) 0 50% / 100% 2px no-repeat,
  linear-gradient(var(--brand), var(--brand)) 0 100% / 100% 3px no-repeat,
  linear-gradient(var(--brand), var(--brand)) 0 0 / 3px 100% no-repeat,
  linear-gradient(var(--brand), var(--brand)) 50% 0 / 2px 100% no-repeat,
  linear-gradient(var(--brand), var(--brand)) 100% 0 / 3px 100% no-repeat; }

/* ---------- dashboard: zoom and width ---------- */
.board-zoom { position: relative; }
.board { transform-origin: 0 0; position: absolute; left: 0; top: 0; }
.board.fixed-width { box-shadow: inset calc(-1 * 2px) 0 0 var(--frame); }
.inline-field { display: inline-flex; align-items: center; gap: 6px; font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.dash-top .seg button { min-width: 30px; font-size: .85rem; }

/* ---------- dashboard dock, colour-coded by category ---------- */
.cat-chart { --cat: var(--cat-chart); } .cat-model { --cat: var(--cat-model); } .cat-table { --cat: var(--cat-table); } .cat-note { --cat: var(--cat-note); }
.form-title { display: flex; flex-direction: column; gap: 1px; padding: 6px 16px 0; }
.form-title b { font: 700 .95rem/1.2 var(--display); color: var(--cat); text-transform: uppercase; letter-spacing: .03em; }
.form-title span { font-size: .76rem; color: var(--text-2); }
.pick-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 1px 10px; max-height: 120px; overflow: auto; }
.pick-list label { display: flex; gap: 5px; align-items: center; font-size: .78rem; }

/* Wide tables: keep rank and name in view while scrolling sideways, like a reference site. */
table.stats td { background: var(--surface); }
table.stats tbody tr:nth-child(even) td { background: var(--row-alt); }
table.stats tbody tr:hover td { background: var(--row-hover); }
table.stats tr > :first-child { position: sticky; left: 0; z-index: 1; }
table.stats tr > :nth-child(2) { position: sticky; left: var(--rk-w, 34px); z-index: 1; box-shadow: inset -1px 0 0 var(--border); }
table.stats thead th:first-child, table.stats thead th:nth-child(2) { z-index: 3; }
table.stats tfoot td:first-child, table.stats tfoot td:nth-child(2) { z-index: 2; }
.model-card { display: flex; flex-direction: column; }
.model-body { height: 400px; display: flex; flex-direction: column; min-height: 0; }
.model-body > .chart { flex: 1; min-height: 0; }
.model-body > div:has(> .tbl-wrap) { flex: 1; min-height: 0; overflow: auto; }

/* ---------- dashboard focus bar ---------- */
.focus-bar { display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center; padding: 6px 10px; margin-bottom: 8px; border: 1px solid var(--frame); border-left: 6px solid var(--tc); background: var(--surface); }
.focus-bar > b { font: 700 .8rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em; margin-right: 4px; }
.focus-bar select { max-width: 220px; }
.focus-note { font-size: .78rem; color: var(--text-2); flex: 1 1 260px; }

/* ---------- chart window ---------- */
.chart-window { position: fixed; inset: 0; z-index: 85; background: rgba(0, 0, 0, .55); display: grid; place-items: center; padding: 16px; }
.win-panel { background: var(--surface); border: 2px solid var(--frame); width: min(1500px, 100%); height: min(920px, 100%); display: flex; flex-direction: column; }
.win-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--frame); }
.win-head h2 { margin: 0 0 2px; font-size: 1.15rem; }
.win-head p { margin: 0; max-width: 90ch; }
.win-body { flex: 1; min-height: 0; display: grid; grid-template-columns: 340px minmax(0, 1fr); }
.win-side { border-right: 1px solid var(--frame); overflow: auto; padding: 10px 12px; }
.win-side h3 { font-size: .8rem; text-transform: uppercase; letter-spacing: .05em; margin: 4px 0 6px; }
.win-side .form { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.win-side .form > fieldset, .win-side .form > .hint, .win-side .form > .pick-list, .win-side .form > div:last-child { grid-column: 1 / -1; }
.win-side .form select, .win-side .form input[type="text"] { width: 100%; }
.win-side .row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 8px; }
.win-side .row.one { grid-template-columns: 1fr; }
.win-side .colors { display: grid; gap: 4px; margin-bottom: 8px; }
.win-side .colors label { display: flex; gap: 8px; align-items: center; font-size: .8rem; }
.win-side hr { border: 0; border-top: 1px solid var(--border); margin: 8px 0; }
.win-style { margin-top: 10px; border-top: 2px solid var(--frame); padding-top: 6px; }
.win-chart { padding: 10px 14px; display: flex; flex-direction: column; min-height: 0; }
.win-chart > .chart { flex: 1; min-height: 0; }
.win-chart > div:has(> .tbl-wrap) { flex: 1; min-height: 0; overflow: auto; }
@media (max-width: 900px) { .win-body { grid-template-columns: 1fr; grid-template-rows: auto 1fr; } .win-side { max-height: 40vh; border-right: 0; border-bottom: 1px solid var(--frame); } }
.widget .wbody { cursor: zoom-in; }
.widget.text .wbody, .widget .wbody:has(.tbl-wrap), .widget .wbody:has(.story) { cursor: auto; }

/* ---------- dashboard front door ---------- */
.quick-start { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.quick-start > b { font: 700 .8rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em; }

/* phones: stacked board, no drag or resize handles */
.board.stacked .wbar { cursor: default; }
.board.stacked .h-e, .board.stacked .h-s, .board.stacked .h-se { display: none; }
@media (max-width: 700px) { .dash-top .seg, .dash-top .inline-field, .dash-top [title^="Zoom so"] { display: none; } .focus-note { display: none; } }
/* model cards on narrow screens: let the view buttons wrap under the title */
.model-card .section-head > span { flex-wrap: wrap; }
.model-card .seg { flex-wrap: wrap; height: auto; }
.model-card .seg button { height: 28px; }

/* Picking a widget type: the set-up panel slides in and flashes in its category colour. */
@keyframes form-in { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
@keyframes form-flash {
  0%, 20% { box-shadow: inset 0 0 0 3px var(--cat); background: color-mix(in srgb, var(--cat) 16%, var(--surface)); }
  100% { box-shadow: inset 0 0 0 0 transparent; background: transparent; }
}
@keyframes title-flash { 0%, 30% { transform: scale(1.06); } 100% { transform: none; } }
.dock-form.flash { animation: form-in .3s ease-out, form-flash 1.4s ease-out; }
.dock-form.flash .form-title b { display: inline-block; transform-origin: left center; animation: title-flash .6s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .dock-form.flash { animation: form-flash 1.4s linear; }
  .dock-form.flash .form-title b { animation: none; }
}

/* Add panel, step 1: a scrollable menu of groups that open and close. */
.dock-menu { overflow: auto; flex: 1; scrollbar-width: thin; }
.step-head { display: flex; align-items: center; gap: 8px; font: 700 .74rem/1 var(--font); text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); padding: 8px 12px 6px; }
.step { display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: var(--text); color: var(--bg); font: 700 .72rem/1 var(--font); flex: none; }
.dock-group { border-top: 1px solid var(--border); border-left: 4px solid var(--cat); }
.dock-group > summary { display: grid; grid-template-columns: 1fr auto; grid-template-areas: "l c" "d c"; align-items: center; column-gap: 10px; padding: 7px 12px 7px 10px; cursor: pointer; list-style: none; }
.dock-group > summary::-webkit-details-marker { display: none; }
.dock-group > summary::after { content: ""; grid-area: c; justify-self: end; width: 7px; height: 7px; border-right: 2px solid var(--text-2); border-bottom: 2px solid var(--text-2); transform: rotate(-45deg); margin-right: 2px; transition: transform .15s; }
.dock-group[open] > summary::after { transform: rotate(45deg); }
.dock-group > summary:hover { background: var(--surface-2); }
.g-label { grid-area: l; font: 700 .82rem/1.2 var(--display); text-transform: uppercase; letter-spacing: .04em; color: var(--cat); }
.g-desc { grid-area: d; font-size: .72rem; color: var(--muted); }
.g-count { grid-area: c; justify-self: end; margin-right: 22px; font: 700 .68rem/1 var(--font); color: var(--text-2); border: 1px solid var(--border-strong); padding: 2px 6px; }
.dock-group .cat-types { display: flex; flex-direction: column; flex-wrap: nowrap; gap: 0; padding: 0 0 6px; }
.dock-group .cat-types button { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left; border: 0; border-left: 3px solid transparent; background: none; padding: 5px 12px 5px 14px; color: var(--text); }
.dock-group .cat-types button b { font: 600 .8rem/1.25 var(--font); }
.dock-group .cat-types button span { font-size: .72rem; line-height: 1.3; color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.dock-group .cat-types button:hover { background: var(--surface-2); color: var(--text); border-left-color: var(--cat); }
.dock-group .cat-types button[aria-pressed="true"] { background: color-mix(in srgb, var(--cat) 12%, var(--surface)); border-left-color: var(--cat); color: var(--text); }
.dock-group .cat-types button[aria-pressed="true"] b { color: var(--cat); }
:root[data-theme="dark"] .dock-group .cat-types button[aria-pressed="true"] { color: var(--text); }
/* Steps 2 and 3: the fields scroll, the add button stays in view. */
.form-title .step-head { padding: 2px 0 4px; }
.add-bar { display: flex; gap: 8px; align-items: center; padding: 8px 16px; border-top: 1px solid var(--border); background: var(--surface); }
.form-title .step-head .step { color: var(--bg); font-size: .72rem; }

/* Wide tooltips: the similar-seasons comparison and other rich hovers. */
.tooltip.wide { max-width: min(460px, calc(100vw - 16px)); padding: 8px 10px; }
.tooltip .tt-why { margin: 2px 0 6px; color: var(--text-2); }
.tooltip table.tt-cmp { border-collapse: collapse; width: 100%; font-size: .74rem; font-variant-numeric: tabular-nums; }
.tooltip table.tt-cmp th, .tooltip table.tt-cmp td { padding: 1px 6px 1px 0; text-align: right; white-space: nowrap; }
.tooltip table.tt-cmp th:first-child, .tooltip table.tt-cmp td:first-child { text-align: left; color: var(--text-2); white-space: normal; }
.tooltip table.tt-cmp thead th { color: var(--text); font-weight: 700; border-bottom: 1px solid var(--border); }
.tooltip table.tt-cmp tr.tt-sep td { border-top: 1px solid var(--border); padding-top: 3px; }
.tooltip table.tt-cmp td.tt-rk { color: var(--muted); font-size: .68rem; padding-right: 8px; }
.tooltip .tt-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; vertical-align: 0; }
.tooltip .tt-dot.m0 { background: var(--right); }
.tooltip .tt-dot.m1 { background: #8fbf5a; }
.tooltip .tt-dot.m2 { background: #d4a72c; }
.tooltip .tt-dot.m3 { background: var(--wrong); }
.tooltip .tt-next { margin-top: 6px; color: var(--text-2); }

/* Storylines: a written summary of one team, one line per topic. */
.story { list-style: none; margin: 0; padding: 4px 2px; overflow: auto; flex: 1; min-height: 0; font-size: .9rem; line-height: 1.45; }
.story li { padding: 5px 0 5px 12px; border-bottom: 1px solid var(--grid); position: relative; }
.story li:last-child { border-bottom: 0; }
.story li::before { content: ''; position: absolute; left: 0; top: 11px; width: 6px; height: 6px; border-radius: 50%; background: var(--border-strong); }
.story li.tone-good::before { background: var(--right); }
.story li.tone-bad::before { background: var(--wrong); }
.story li b { font-family: var(--display); text-transform: uppercase; letter-spacing: .02em; font-size: .78rem; color: var(--text-2); margin-right: 4px; }

/* ---------- dashboard: add drawer ----------
   Wide screens: a column beside the board, sticky while the page scrolls.
   Narrower: a sheet over the right of the board. Phones: full screen. */
.dash-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-items: start; }
.dock { position: fixed; top: 61px; right: 8px; bottom: 8px; width: min(400px, calc(100vw - 16px)); z-index: 60; display: flex; flex-direction: column; background: var(--surface); border: 2px solid var(--frame); min-width: 0; box-shadow: 0 10px 40px rgba(0, 0, 0, .28); }
.dock[hidden] { display: none; }
.dock .dock-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px 8px 14px; border-bottom: 1px solid var(--frame); }
.dock .dock-head h2 { margin: 0; font-size: 1rem; }
.dock .dock-close { font-size: 1.1rem; line-height: 1; width: 30px; padding: 0; }
.dock-search { padding: 0 12px 8px; }
.dock-search input { width: 100%; }
.dock-menu { overflow: auto; flex: 1; min-height: 0; scrollbar-width: thin; }
.dock-added { padding: 8px 12px; border-top: 1px solid var(--border); background: color-mix(in srgb, var(--right) 12%, var(--surface)); font-size: .8rem; }
.dock-form { display: flex; flex-direction: column; min-height: 0; flex: 1; overflow: auto; border-top: 4px solid var(--cat); }
.dock-form .form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 10px; align-items: end; padding: 8px 14px 12px; }
.dock-form .form > fieldset, .dock-form .form > .hint, .dock-form .form > .pick-list, .dock-form .form > div:last-child, .dock-form .form > .ac { grid-column: 1 / -1; }
.dock-form .form select, .dock-form .form input[type="text"], .dock-form .form input[type="number"] { width: 100%; }
.dock-form .form fieldset { border: 1px solid var(--border); padding: 2px 8px 8px; margin: 0; min-width: 0; }
.dock-form .form legend { font-size: .66rem; font-weight: 700; color: var(--muted); text-transform: uppercase; padding: 0 4px; letter-spacing: .05em; }
.dock-form .form .hint { font-size: .74rem; color: var(--muted); }
.dock-form .series-row { flex-wrap: wrap; }
.dock-form .series-row select { flex: 1 1 120px; min-width: 0; }
.dock-form .pick-list { grid-template-columns: repeat(2, minmax(0, 1fr)); max-height: 200px; }
.dock-back { align-self: flex-start; border: 0; background: none; color: var(--link); font: 600 .8rem/1 var(--font); padding: 8px 14px 2px; cursor: pointer; }
.dock-back:hover { text-decoration: underline; }
.form-title { display: flex; flex-direction: column; gap: 1px; padding: 6px 14px 0; }
.form-title b { font: 700 .95rem/1.2 var(--display); color: var(--cat); text-transform: uppercase; letter-spacing: .03em; }
.form-title span { font-size: .76rem; color: var(--text-2); }
.add-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding: 10px 14px; border-top: 1px solid var(--frame); background: var(--surface); }
.add-widget span { font-weight: 700; font-size: 1.05em; margin-right: 2px; }
.widget.just-added { animation: just-added 1.6s ease-out; }
@keyframes just-added { 0%, 30% { box-shadow: 0 0 0 4px var(--sel); } 100% { box-shadow: 0 0 0 0 transparent; } }
@media (prefers-reduced-motion: reduce) { .widget.just-added { animation: none; outline: 3px solid var(--sel); } }
@media (max-width: 700px) {
  .dock { inset: 0; width: auto; border: 0; z-index: 80; }
  .dock-form .form { grid-template-columns: minmax(0, 1fr); }
}
/* Toolbar: the title takes what is left, so everything fits on one line at 1366px and up. */
.dash-top .title-input { flex: 1 1 180px; width: auto; min-width: 150px; max-width: 380px; text-overflow: ellipsis; }
.dash-top .spacer { flex: 0 1 auto; }
.dock .dock-close { display: inline-grid; place-items: center; height: 30px; }
@media (max-width: 1500px) { .dash-top .inline-field .lbl { display: none; } }
@media (max-width: 700px) {
  .dash-top .desk-only, .dash-top .sep { display: none; }
  .dash-top .title-input { flex: 1 1 100%; max-width: none; order: -2; }
  .dash-top .add-widget { order: -1; }
  .board-empty { top: 16px; padding: 0 8px; }
  .board-empty > div { max-width: 100%; padding: 12px; }
  .board-empty .quick-start { justify-content: center; }
  .board-empty .presets .btn { white-space: normal; height: auto; min-height: 32px; text-align: center; }
}
.board.stacked .w-dup { display: none; }
/* A wide Storylines widget reads in two columns instead of scrolling. */
.story { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 420px), 1fr)); column-gap: 24px; align-content: start; }
/* Touch: rich tooltips open as a bottom sheet. */
.tip-sheet { position: fixed; inset: 0; z-index: 95; background: rgba(0, 0, 0, .45); display: flex; align-items: flex-end; justify-content: center; }
.tip-sheet-panel { background: var(--surface); color: var(--text); width: min(560px, 100%); max-height: 82vh; display: flex; flex-direction: column; border-top: 3px solid var(--frame); font-size: .82rem; line-height: 1.4; }
.tip-sheet-bar { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border); }
.tip-sheet-body { overflow: auto; padding: 10px 12px 16px; }
.tip-sheet.wide .tip-sheet-panel { width: min(920px, 100%); }
@media (min-width: 700px) { .tip-sheet.wide { align-items: center; } .tip-sheet.wide .tip-sheet-panel { border: 1px solid var(--border); border-top: 3px solid var(--frame); } }
/* A drive's plays: one row per snap; the description wraps, numbers line up. */
.play-table { border-collapse: collapse; width: 100%; font-size: .8rem; font-variant-numeric: tabular-nums; }
.play-table th { text-align: left; font-weight: 700; color: var(--text-2); border-bottom: 1px solid var(--border-strong); padding: 4px 6px; position: sticky; top: 0; background: var(--surface); }
.play-table td { padding: 5px 6px; border-bottom: 1px solid var(--border); vertical-align: top; white-space: nowrap; }
.play-table td.desc { white-space: normal; min-width: 220px; }
.play-table td.num, .play-table th:nth-last-child(-n+2) { text-align: right; }
.play-table td.pos { color: var(--right); font-weight: 600; } .play-table td.neg { color: var(--wrong); font-weight: 600; }
.play-table tr.np td { color: var(--muted); }
.play-table tbody tr:nth-child(even) td { background: var(--row-alt); }
.tip-sheet .tt-h { font-weight: 700; margin-bottom: 2px; }
.tip-sheet .tt-why { margin: 2px 0 8px; color: var(--text-2); }
.tip-sheet .tt-note { color: var(--muted); margin-top: 6px; font-size: .74rem; }
.tip-sheet .tt-next { margin-top: 6px; color: var(--text-2); }
.tip-sheet table.tt-cmp { border-collapse: collapse; width: 100%; font-size: .78rem; font-variant-numeric: tabular-nums; }
.tip-sheet table.tt-cmp th, .tip-sheet table.tt-cmp td { padding: 2px 4px 2px 0; text-align: right; }
.tip-sheet table.tt-cmp th:first-child, .tip-sheet table.tt-cmp td:first-child { text-align: left; color: var(--text-2); }
.tip-sheet table.tt-cmp thead th { border-bottom: 1px solid var(--border); }
.tip-sheet table.tt-cmp tr.tt-sep td { border-top: 1px solid var(--border); padding-top: 4px; }
.tip-sheet table.tt-cmp td.tt-rk { color: var(--muted); font-size: .7rem; padding-right: 6px; }
.tip-sheet .tt-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; }
.tip-sheet .tt-dot.m0 { background: var(--right); } .tip-sheet .tt-dot.m1 { background: #8fbf5a; } .tip-sheet .tt-dot.m2 { background: #d4a72c; } .tip-sheet .tt-dot.m3 { background: var(--wrong); }
/* Series rows in the add drawer: swatch, who, from, to, remove on one line. */
.dock-form .series-row { display: grid; grid-template-columns: 10px minmax(0, 1fr) 76px 76px 22px; gap: 4px; align-items: center; }
.dock-form .series-row select, .dock-form .series-row .ac, .dock-form .series-row .ac input { width: 100%; min-width: 0; }
.dock-form .series-row .x { justify-self: center; }
.dock-form .series-row.wk { grid-template-columns: 10px minmax(0, 1fr) 76px 22px; }
.wloading { margin: auto; color: var(--muted); font-size: .8rem; }
.help-dialog { position: fixed; inset: 0; z-index: 96; background: rgba(0, 0, 0, .45); display: grid; place-items: center; padding: 16px; }
.help-panel { background: var(--surface); border: 2px solid var(--frame); width: min(520px, 100%); padding: 12px 16px 16px; }
.help-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.help-head h2 { margin: 0; font-size: 1.05rem; }
.help-panel dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0; font-size: .86rem; }
.help-panel dt { white-space: nowrap; }
.help-panel dd { margin: 0; color: var(--text-2); }
.help-panel kbd { font: 600 .78rem/1 var(--font); border: 1px solid var(--border-strong); border-bottom-width: 2px; padding: 2px 6px; background: var(--surface-2); }
/* Phones: the chart window fills the screen, chart first, settings below it. */
@media (max-width: 700px) {
  .chart-window { padding: 0; }
  .win-panel { width: 100%; height: 100%; border: 0; }
  .win-hint { display: none; }
  .win-head { padding: 8px 10px; }
  .win-head h2 { font-size: .95rem; }
  .win-head p { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .win-body { grid-template-rows: minmax(300px, 55vh) minmax(0, 1fr); }
  .win-chart { order: -1; padding: 6px 8px; border-bottom: 1px solid var(--frame); }
  .win-side { max-height: none; border-bottom: 0; }
  .inspector { left: 8px !important; right: 8px; width: auto; max-height: 70vh; }
}

/* After adding a widget: a short note with a way straight back to the add panel. */
.dash-toast { position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 70; display: flex; gap: 10px; align-items: center; background: var(--text); color: var(--bg); padding: 8px 10px 8px 14px; font-size: .85rem; box-shadow: 0 6px 24px rgba(0, 0, 0, .3); max-width: calc(100vw - 24px); }
.dash-toast .btn { background: var(--bg); color: var(--text); border-color: var(--bg); }
.dock-form .form > .full, .win-side .form > .full { grid-column: 1 / -1; }
.dock-form .form > .full .field select, .win-side .form > .full .field select { width: 100%; }
.full .ac, .full .ac input { width: 100%; }

/* Ask: describe a dashboard in words. */
.ask-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; padding: 6px 10px; margin-bottom: 8px; border: 1px solid var(--frame); background: var(--surface); }
.ask-bar > label { display: inline-flex; align-items: center; gap: 6px; font: 700 .8rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em; }
.ask-mark { color: var(--brand); font-size: 1rem; }
.ask-input { flex: 1 1 360px; min-width: 0; height: 32px; font-size: .9rem; }
.ask-msg { flex: 1 1 100%; font-size: .8rem; color: var(--text-2); }
.ask-msg:empty { display: none; }
.ask-msg.ok { color: var(--text); }
.ask-msg.err { color: var(--wrong); }
.ask-msg .ask-note { color: var(--noise); }
.ask-msg .ask-answer { display: block; margin: 4px 0; }
.ask-wrong input { font: inherit; font-size: .85rem; padding: 2px 6px; width: min(280px, 60vw); }
.linkish { border: 0; background: none; padding: 0; color: var(--link); font: inherit; cursor: pointer; text-decoration: underline; }
.chip { border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text); font: 500 .74rem/1.2 var(--font); padding: 3px 8px; margin: 2px 3px; cursor: pointer; border-radius: 12px; }
.chip:hover { border-color: var(--text); }
@media (max-width: 700px) { .ask-input { flex-basis: 100%; } }
.btn[hidden] { display: none; }
.btn.mic { width: 32px; height: 32px; padding: 0; justify-content: center; }
.btn.mic.on { border-color: var(--wrong); color: var(--wrong); animation: mic-pulse 1.2s ease-in-out infinite; }
@keyframes mic-pulse { 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .btn.mic.on { animation: none; } }
.home-ask { margin: 0 0 10px; border-color: var(--border-strong); }

/* Ads, tip jar and Pro. Ad slots take no room until something fills them. */
.ad-slot[hidden] { display: none; }
.ad-slot { margin: 12px 0; padding: 6px 8px; border: 1px solid var(--border); background: var(--surface); text-align: center; min-height: 60px; overflow: hidden; }
.ad-slot .ad-label { display: block; font-size: .62rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-bottom: 4px; text-align: left; }
.ad-slot.placeholder { border: 2px dashed var(--border-strong); color: var(--muted); display: grid; place-items: center; min-height: 90px; font-size: .8rem; }
.ad-wrap:empty, .ad-wrap:has(> .ad-slot[hidden]) { display: none; }
.pro-box { max-width: 640px; }
.pass-code { font-size: .95rem; padding: 4px 8px; background: var(--surface-2); border: 1px solid var(--border-strong); user-select: all; }
.ok-note { color: var(--right); font-weight: 500; }
/* The dashboard maker has its own slot under the board; the page-wide top slot would push the board down. */
#ad-top:has(+ main.flush) { display: none; }
/* Ask conversation: a short log under the box. */
.ask-thread { flex: 1 1 100%; order: 3; display: flex; flex-direction: column; gap: 2px; max-height: 150px; overflow: auto; font-size: .8rem; }
.ask-thread:empty { display: none; }
.ask-turn { display: flex; flex-wrap: wrap; gap: 0 8px; padding: 2px 0; border-bottom: 1px solid var(--grid); }
.ask-turn .you { color: var(--text); }
.ask-turn .did { color: var(--text-2); }
.ask-thread > .linkish { align-self: flex-end; font-size: .76rem; position: sticky; top: 0; background: var(--surface); padding: 0 2px; }
.ask-msg { order: 4; }
/* Privacy and terms */
.legal > * { max-width: 820px; }   /* the column sits on the page grid, left, as every other page (and the sister sites) */
.legal-sec h2 { font-size: 1.05rem; margin: 22px 0 6px; }
.legal-sec p, .legal-sec li { line-height: 1.55; color: var(--text-2); }
.legal li a { text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.legal-now { margin: 12px 0 4px; padding: 10px 14px; background: var(--surface-2); }
.legal-now h2, .legal-now h3 { margin: 0 0 4px; font-size: .9rem; text-transform: uppercase; letter-spacing: .04em; }
.legal-now ul { margin: 0; padding-left: 18px; font-size: .88rem; }

/* ============================================================
   Home: the dashboard maker's advertisement, with a looping demo.
   Motion eases out on an expo curve and staggers by --i.
   ============================================================ */
.home { --ease: cubic-bezier(.16, 1, .3, 1); --la: var(--s1); --lb: var(--s2); }
.hero-ad { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 28px; align-items: center; padding: 30px 0 22px; }
@media (max-width: 1020px) { .hero-ad { grid-template-columns: minmax(0, 1fr); gap: 18px; padding-top: 20px; } }
.eyebrow { margin: 0 0 8px; font: 700 .78rem/1 var(--display); text-transform: uppercase; letter-spacing: .12em; color: var(--brand-ink); }
.hero-title { font-size: clamp(2.1rem, 4.4vw, 3.4rem); line-height: 1.02; margin: 0 0 14px; text-transform: uppercase; letter-spacing: -.01em; }
.hero-title .line { display: block; overflow: hidden; padding-bottom: .04em; }
.hero-title .line > span { display: inline-block; animation: line-up .9s var(--ease) both; }
.hero-title .line + .line > span { animation-delay: .09s; }
.hero-title .accent { color: var(--brand); }
@keyframes line-up { from { transform: translateY(105%); } }
.lede { font-size: 1.05rem; color: var(--text-2); margin: 0 0 16px; max-width: 46ch; }
.home-ask { margin: 0 0 10px; border: 2px solid var(--frame); padding: 8px 10px; }
.home-ask .ask-input { font-size: 1rem; }
.try { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: .8rem; }
.try-chip { border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); padding: 4px 9px; font: 500 .8rem/1.2 var(--font); cursor: pointer; transition: border-color .15s, background .15s; }
.try-chip:hover { border-color: var(--brand); background: var(--row-hover); }
.hero-note { margin: 12px 0 0; font-size: .82rem; color: var(--muted); }
.hero-also { margin: 6px 0 0; font-size: .82rem; }

/* The demo window. Decorative (aria-hidden); a hidden paragraph describes it. */
.demo-wrap { position: relative; min-width: 0; padding-bottom: 26px; }
.demo-wrap.demo-none { display: none; }
.demo { position: relative; border: 2px solid var(--frame); background: var(--surface); box-shadow: 8px 8px 0 var(--surface-3); overflow: hidden; transition: opacity .5s; }
.demo.fade { opacity: 0; }
.demo-chrome { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; background: var(--header-bg); color: var(--header-muted); font-size: .72rem; }
.demo-chrome i { width: 9px; height: 9px; border-radius: 50%; background: #555; }
.demo-url { margin-left: 8px; padding: 2px 10px; background: #2a2a2a; color: #cfcfcf; flex: 1 1 auto; min-width: 0; max-width: 260px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.demo-share { margin-left: auto; padding: 3px 10px; border: 1px solid #555; color: #eee; font-weight: 600; transition: transform .15s, background .15s; }
.demo-share.pressed { transform: scale(.94); background: var(--brand); border-color: var(--brand); }
.demo-ask { display: flex; align-items: center; gap: 8px; margin: 10px 10px 0; padding: 6px 8px; border: 1px solid var(--frame); font-size: .85rem; }
.demo-mark { font: 700 .72rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em; color: var(--brand-ink); white-space: nowrap; }
.demo-field { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; display: flex; align-items: center; }
.demo-caret { display: inline-block; flex: none; width: 2px; height: 1.1em; margin-left: 1px; background: var(--text); animation: caret 1s steps(1) infinite; }
@keyframes caret { 50% { opacity: 0; } }
.demo-btn { padding: 4px 10px; background: var(--ink-btn); color: var(--ink-btn-text); font-weight: 600; font-size: .75rem; white-space: nowrap; transition: transform .15s; }
.demo-btn.pressed { transform: scale(.92); }
.demo-status { height: 26px; margin: 0 10px; padding: 6px 0 0; font-size: .75rem; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: 0; transition: opacity .25s; }
.demo-status.on { opacity: 1; }
.demo-dots { display: inline-flex; gap: 4px; }
.demo-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); animation: dot-bob 1.1s ease-in-out infinite; }
.demo-dots i:nth-child(2) { animation-delay: .15s; }
.demo-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes dot-bob { 0%, 60%, 100% { transform: translateY(0); opacity: .45; } 30% { transform: translateY(-4px); opacity: 1; } }
.demo.held, .demo.held * { animation-play-state: paused !important; }

.demo-board { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: 74px minmax(0, 1fr) 118px; gap: 8px; height: 370px; margin: 4px 10px 10px;
  transition: grid-template-rows .7s var(--ease), row-gap .7s var(--ease); }
.demo-w { min-width: 0; min-height: 0; overflow: hidden; border: 1px solid var(--frame); background: var(--surface); padding: 6px 8px; opacity: 0; transform: translateY(12px) scale(.97);
  transition: opacity .35s, transform .7s var(--ease); transition-delay: calc(var(--i, 0) * 80ms); }
.demo-board.on .demo-w { opacity: 1; transform: none; }
/* While the demo types, the board area shows the dashboard maker's dotted canvas rather than
   a blank white box that reads as a page still loading. */
.demo-board { background-image: radial-gradient(var(--border-strong) 1px, transparent 1.2px); background-size: 18px 18px; background-position: -4px -4px; }
.demo-w .k { display: block; font: 700 .62rem/1.2 var(--display); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.demo-tile .vals { display: flex; align-items: baseline; gap: 8px; margin: 3px 0 1px; }
.demo-tile .v, .demo-tile .v2 { font: 700 1.35rem/1 var(--display); font-variant-numeric: tabular-nums; white-space: nowrap; }
.demo-tile .v2 { display: none; color: var(--lb); }
.demo-tile .sub { display: block; font-size: .64rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmp .demo-tile .v { color: var(--la); }
.cmp .demo-tile .v2 { display: inline; animation: pop-in .5s var(--ease); }
.cmp .demo-tile .v, .cmp .demo-tile .v2 { font-size: 1.1rem; }
@keyframes pop-in { from { opacity: 0; transform: translateY(6px); } }

.demo-barsw { grid-column: 1 / 3; }
.demo-linew { grid-column: 3 / 5; }
.demo-tablew { grid-column: 1 / 5; }
.demo-chart { display: flex; flex-direction: column; }
.demo-chart svg { flex: 1; width: 100%; min-height: 0; margin-top: 4px; overflow: visible; }
.demo-ch-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 8px; align-items: center; }   /* full names can push the legend to a second line */
.demo-legend { display: none; gap: 4px; align-items: center; font-size: .62rem; color: var(--muted); white-space: nowrap; }
.demo-legend i { width: 8px; height: 8px; display: inline-block; }
.demo-legend .la { background: var(--la); }
.demo-legend .lb { background: var(--lb); margin-left: 4px; }
.cmp .demo-legend { display: inline-flex; animation: pop-in .4s var(--ease); }
.demo-x { display: flex; justify-content: space-between; font-size: .58rem; color: var(--muted); }
.demo-chart .axis { stroke: var(--border-strong); stroke-width: 1; vector-effect: non-scaling-stroke; }
.demo-chart .zero { stroke: var(--border-strong); stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.bar-a, .bar-b { transform-box: fill-box; transform-origin: 0 100%; transform: scaleY(0); transition: transform .9s var(--ease); transition-delay: var(--d, 0ms); }
.bar-a { fill: var(--la); }
.bar-b { fill: var(--lb); }
.grown .bar-a { transform: scaleY(1); transition-delay: calc(var(--d, 0ms) + 250ms); }
.cmp .bar-a { transform: scaleX(.543); transition-delay: 0ms; }
.cmp .bar-b { transform: scaleY(1); }
.line-a, .line-b { fill: none; stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; clip-path: inset(0 100% 0 0); transition: clip-path 1.2s var(--ease); }
.demo-chart .dots { stroke-width: 7; }
.line-a { stroke: var(--la); }
.line-b { stroke: var(--lb); }
.area-a { fill: var(--la); opacity: 0; transition: opacity .8s .6s; }
.grown .line-a { clip-path: inset(0 0 0 0); transition-delay: .35s; }
.grown .area-a { opacity: .12; }
.cmp .line-b { clip-path: inset(0 0 0 0); }
.cmp .area-a { opacity: 0; transition-delay: 0s; }

.demo-tablew table { width: 100%; border-collapse: collapse; font-size: .68rem; font-variant-numeric: tabular-nums; margin-top: 3px; }
.demo-tablew th, .demo-tablew td { text-align: right; padding: 2px 4px; border-bottom: 1px solid var(--grid); white-space: nowrap; }
.demo-tablew th:first-child, .demo-tablew td:first-child { text-align: left; }
.demo-tablew th { font-weight: 700; color: var(--muted); }
.demo-tablew tbody tr { opacity: 0; transform: translateX(-8px); transition: opacity .3s, transform .5s var(--ease); }
.grown .demo-tablew tbody tr { opacity: 1; transform: none; }
.grown .demo-tablew tbody tr:nth-child(2) { transition-delay: .06s; }
.grown .demo-tablew tbody tr:nth-child(3) { transition-delay: .12s; }
.grown .demo-tablew tbody tr:nth-child(4) { transition-delay: .18s; }
.grown .demo-tablew tbody tr:nth-child(5) { transition-delay: .24s; }
.demo-tablew .cmp-rows { display: none; }
.cmp .demo-tablew tbody.cmp-rows { display: table-row-group; }
.cmp .demo-tablew thead.cmp-rows { display: table-header-group; }
.cmp .demo-tablew thead:not(.cmp-rows), .cmp .demo-tablew tbody:not(.cmp-rows) { display: none; }
.cmp .demo-tablew tbody.cmp-rows tr:first-child td:first-child { color: var(--la); font-weight: 700; }
.cmp .demo-tablew tbody.cmp-rows tr:last-child td:first-child { color: var(--lb); font-weight: 700; }

/* "only leave the charts": tiles and table fade and sink first, then their rows fold away and
   the charts grow into the room. Padding and borders ease out with the rows; snapped to zero
   at once they made the whole board jump. */
.demo-board.only-charts { grid-template-rows: 0 minmax(0, 1fr) 0; row-gap: 0;
  transition: grid-template-rows .8s var(--ease) .22s, row-gap .8s var(--ease) .22s; }
.demo-board.only-charts .demo-tile, .demo-board.only-charts .demo-tablew { opacity: 0; transform: scale(.96); padding-block: 0; border-width: 0; border-color: transparent;
  transition: opacity .28s, transform .4s var(--ease), padding .8s var(--ease) .22s, border-width .8s var(--ease) .22s, border-color .28s; }
.demo-board.only-charts .demo-tile { transform-origin: 50% 0; }
.demo-board.only-charts .demo-tablew { transform-origin: 50% 100%; }

.demo-toast { position: absolute; right: 14px; bottom: 14px; padding: 8px 12px; background: var(--header-bg); color: #eee; font-size: .78rem; border-left: 4px solid var(--brand);
  opacity: 0; transform: translateY(24px); transition: transform .5s var(--ease), opacity .3s; }
.demo-toast.on { transform: none; opacity: 1; }
.demo-toast .muted { color: #bdbdbd; }
.demo-cursor { position: absolute; left: 0; top: 0; width: 18px; height: 18px; opacity: 0; transform: translate(60%, 70%); transition: transform .7s var(--ease), opacity .2s; pointer-events: none; z-index: 2; }
.demo-cursor.on { opacity: 1; }
.demo-cursor svg { width: 18px; height: 18px; fill: #111; stroke: #fff; stroke-width: 1.2; }
.demo-pause { position: absolute; right: 0; bottom: 0; border: 0; background: none; color: var(--muted); font-size: .75rem; cursor: pointer; text-decoration: underline; padding: 4px 0; }
.demo-pause:hover { color: var(--text); }
.demo-foot { position: absolute; left: 0; right: 0; bottom: 0; display: flex; justify-content: space-between; align-items: center; }
.demo-foot .demo-pause { position: static; }
.demo-open { font-size: .8rem; font-weight: 700; color: var(--link); }
.demo-link { cursor: pointer; }
.demo-link:hover { box-shadow: 8px 8px 0 var(--accent, var(--surface-3)); }

@media (max-width: 640px) {
  .demo-board { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: 64px 64px minmax(0, 1fr) minmax(0, 1fr); height: 440px; }
  .demo-barsw, .demo-linew { grid-column: 1 / 3; }
  .demo-tablew { display: none; }
  .demo-board.only-charts { grid-template-rows: 0 0 minmax(0, 1fr) minmax(0, 1fr); }
  .demo { box-shadow: 5px 5px 0 var(--surface-3); }
}

/* Sections below the fold. */
.home-sec { margin-top: 44px; }
.home-h { font-size: 1.5rem; text-transform: uppercase; letter-spacing: .01em; margin: 0 0 12px; }
.home-h-row { display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline; margin-bottom: 12px; }
.home-h-row .home-h { margin: 0; }
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .6s, transform .9s var(--ease); transition-delay: calc(var(--i, 0) * 70ms); }
.reveal.in { opacity: 1; transform: none; }
.steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 2px solid var(--frame); }
.how-step { padding: 16px 18px 18px 0; }
.how-step + .how-step { padding-left: 18px; border-left: 1px solid var(--border); }
.how-step:nth-child(2) { --i: 1; }
.how-step:nth-child(3) { --i: 2; }
.step-n { display: block; font: 700 2.6rem/1 var(--display); color: var(--brand); margin-bottom: 6px; }
.how-step h3 { font-size: 1.15rem; text-transform: uppercase; margin: 0 0 4px; }
.how-step p { margin: 0 0 8px; color: var(--text-2); }
.step-eg { font-size: .85rem; color: var(--muted); font-style: italic; margin: 0; }
@media (max-width: 800px) { .steps { grid-template-columns: minmax(0, 1fr); } .how-step, .how-step + .how-step { padding: 14px 0; border-left: 0; border-bottom: 1px solid var(--border); } }
.examples { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: 10px; }
.example { position: relative; display: flex; flex-direction: column; gap: 6px; text-align: left; padding: 14px 16px 12px; border: 1px solid var(--frame); border-left: 4px solid var(--frame); background: var(--surface); color: var(--text); cursor: pointer; font: inherit;
  transition: opacity .6s, transform .5s var(--ease), border-color .2s, box-shadow .3s var(--ease); transition-delay: calc(var(--i, 0) * 70ms); }
.example q { font: 700 1.05rem/1.2 var(--display); quotes: "\201C" "\201D"; }
.example span { color: var(--muted); font-size: .82rem; }
.example .go { color: var(--brand); font-weight: 700; font-size: .75rem; text-transform: uppercase; letter-spacing: .06em; opacity: 0; transform: translateX(-6px); transition: opacity .2s, transform .3s var(--ease); }
.example.in:hover, .example.in:focus-visible { border-left-color: var(--brand); transform: translateY(-3px); box-shadow: 4px 4px 0 var(--surface-3); transition-delay: 0ms; }
.example:hover .go, .example:focus-visible .go { opacity: 1; transform: none; }
@media (hover: none) { .example .go { opacity: 1; transform: none; } }
.facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border: 2px solid var(--frame); background: var(--surface); }
.fact { padding: 16px 18px; }
.fact + .fact { border-left: 1px solid var(--border); }
.fact:nth-child(2) { --i: 1; }
.fact:nth-child(3) { --i: 2; }
.fact:nth-child(4) { --i: 3; }
.fact b { display: block; font: 700 2.8rem/1 var(--display); font-variant-numeric: tabular-nums; }
.fact span { color: var(--text-2); font-size: .85rem; }
@media (max-width: 800px) { .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } .fact:nth-child(3) { border-left: 0; } .fact:nth-child(n+3) { border-top: 1px solid var(--border); } }
.by-hand { display: flex; flex-wrap: wrap; gap: 12px 28px; align-items: center; justify-content: space-between; padding: 18px 20px; border: 1px solid var(--frame); border-left: 6px solid var(--brand); background: var(--surface); }
.by-hand .home-h { margin-bottom: 4px; }
.by-hand p { margin: 0; max-width: 56ch; }
.home .tool-links { margin-bottom: 30px; }
@media (prefers-reduced-motion: reduce) { .hero-title .line > span { animation: none; } .reveal { opacity: 1; transform: none; } }

/* Export menu opens leftward from the right end of the toolbar; the bare blank-board note. */
.pop .menu.right { left: auto; right: 0; }
.board-empty.bare { top: 40px; }
.board-empty.bare > div { background: var(--surface); border: 1px dashed var(--border-strong); padding: 12px 16px; display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; justify-content: center; }
.board { color: var(--text); }
/* Toast: one line at the bottom of the screen, gone after a few seconds. */
.toast { position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 120; background: var(--text); color: var(--bg); padding: 10px 14px; font-size: .85rem; max-width: calc(100% - 32px); box-shadow: 0 4px 18px rgba(0, 0, 0, .25); animation: toast-in .18s ease-out; }
.toast a { color: inherit; font-weight: 700; text-decoration: underline; }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }
.box-head > :first-child { margin-right: auto; }
.box-head { display: flex; align-items: baseline; gap: 8px; }
.box-head h3 { margin: 0 0 4px; }

/* ---------- Graphics maker: controls on the left, the card on the right ---------- */
.gfx { display: grid; grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); gap: 20px; max-width: 1500px; margin: 0 auto; padding: 16px; align-items: start; }
.gfx-panel { display: flex; flex-direction: column; gap: 10px; }
.gfx-head h1 { margin: 0 0 2px; font-family: var(--display); font-size: 1.6rem; }
.gfx-head p { margin: 0; }
.gfx-sec { border: 1px solid var(--border); background: var(--surface); padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.gfx-sec h3 { margin: 0; font-family: var(--display); font-size: .95rem; text-transform: uppercase; letter-spacing: .03em; }
.gfx-sec .field { display: flex; flex-direction: column; gap: 3px; font-size: .78rem; color: var(--text-2); flex: 1; min-width: 0; }
.gfx-sec input[type=text], .gfx-sec input[type=search], .gfx-sec select { width: 100%; min-width: 0; }
.gfx-row { display: flex; gap: 8px; flex-wrap: wrap; }
.gfx-examples { display: flex; flex-wrap: wrap; gap: 6px; }
.gfx-layouts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.gfx-layouts button { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; text-align: left; padding: 8px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); cursor: pointer; font: inherit; }
.gfx-layouts button span { font-size: .72rem; color: var(--muted); }
.gfx-layouts button[aria-pressed=true] { border-color: var(--frame); box-shadow: inset 0 -3px 0 var(--brand); background: var(--surface); }
.gfx-subj { border-left: 4px solid var(--tc); padding: 6px 0 6px 8px; display: flex; flex-direction: column; gap: 6px; }
.gfx-subj-top { display: flex; justify-content: space-between; gap: 6px; align-items: center; }
.gfx-subj-tools { display: inline-flex; gap: 3px; }
.gfx-subj-tools .btn.small { padding: 2px 7px; min-width: 26px; }
.gfx-span { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; font-size: .8rem; }
.gfx-span select { width: auto; }
.gfx-check { display: flex; gap: 6px; align-items: center; font-size: .82rem; }
/* Blind (who is who hidden): a bar above the card, big enough to find at a glance; outlined in the brand colour while on. */
.gfx-blind { margin: 0 0 8px; padding: 8px 12px; border: 2px solid var(--border-strong); background: var(--surface-2); }
.gfx-blind.on { border-color: var(--brand); }
.gfx-blind .gfx-check { font-size: .95rem; font-weight: 700; cursor: pointer; }
.gfx-blind .gfx-check input { width: 18px; height: 18px; }
.gfx-credit { margin: 6px 0 0; overflow-wrap: anywhere; }
/* What the card's numbers leave out (incomplete box scores), under the preview: read, not fine print. */
.gfx-caveat { margin: 6px 0 0; overflow-wrap: anywhere; color: var(--text); }
.gfx-acwrap { position: relative; }
.gfx-ac { position: absolute; z-index: 30; left: 0; right: 0; top: 100%; margin: 0; padding: 0; list-style: none; background: var(--surface); border: 1px solid var(--border-strong); max-height: 260px; overflow: auto; box-shadow: 0 6px 18px rgba(0, 0, 0, .18); }
.gfx-ac:empty { display: none; }
.gfx-ac li { padding: 6px 8px; cursor: pointer; font-size: .85rem; }
.gfx-ac li:hover, .gfx-ac li.on { background: var(--row-hover); }
.gfx-stats { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; counter-reset: st; }
.gfx-stats li { display: flex; justify-content: space-between; align-items: center; gap: 6px; padding: 4px 6px; background: var(--surface-2); font-size: .85rem; }
.gfx-stats li::before { counter-increment: st; content: counter(st); color: var(--muted); font-size: .72rem; width: 14px; }
.gfx-stats li > span:first-of-type { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gfx-games { display: flex; flex-direction: column; gap: 3px; max-height: 220px; overflow: auto; }
.gfx-stage { position: sticky; top: 12px; display: flex; flex-direction: column; gap: 10px; }
.gfx-frame { background: repeating-linear-gradient(45deg, var(--surface-2) 0 10px, var(--surface) 10px 20px); border: 1px solid var(--border); padding: 14px; display: flex; justify-content: center; }
.gfx-canvas { width: auto; height: auto; max-width: 100%; max-height: 68vh; display: block; box-shadow: 0 10px 34px rgba(0, 0, 0, .28); background: #111; }
.gfx-status { min-height: 1.2em; margin: 0; }
.gfx-status:empty { display: none; }

/* player: play button, scrubber, clock */
.gfx-player { display: flex; align-items: center; gap: 10px; }
.gfx-play { min-width: 92px; font-variant-numeric: tabular-nums; }
.gfx-scrub { flex: 1; min-width: 0; accent-color: var(--brand); }
.gfx-clock { font-variant-numeric: tabular-nums; white-space: nowrap; min-width: 88px; text-align: right; }

/* motion controls */
.gfx-motion { border: 1px solid var(--border); background: var(--surface); padding: 10px 12px; display: flex; flex-direction: column; gap: 10px; }
.gfx-motion-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.gfx-motion-label { font-family: var(--display); text-transform: uppercase; font-size: .85rem; letter-spacing: .03em; width: 72px; }
.gfx-motion-opts .field { display: flex; flex-direction: column; gap: 3px; font-size: .74rem; color: var(--text-2); text-transform: uppercase; letter-spacing: .03em; }
.gfx-motion-opts .seg { height: 28px; }
.gfx-anims { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; flex: 1; min-width: 0; }
.gfx-anims button { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 8px 4px 6px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); cursor: pointer; font: 600 .78rem/1 var(--font); }
.gfx-anims button:hover { border-color: var(--border-strong); }
.gfx-anims button[aria-pressed=true] { border-color: var(--frame); box-shadow: inset 0 -3px 0 var(--brand); background: var(--surface); }
/* each entrance button shows its own motion in miniature: three bars, on hover or when picked */
.gfx-demo { display: flex; flex-direction: column; gap: 3px; width: 46px; height: 26px; justify-content: center; }
.gfx-demo i { display: block; height: 6px; background: var(--text-2); transform-origin: center; }
.gfx-demo i:nth-child(1) { background: var(--brand); width: 100%; }
.gfx-demo i:nth-child(2) { width: 80%; }
.gfx-demo i:nth-child(3) { width: 90%; }
.gfx-anims button:hover .gfx-demo i, .gfx-anims button[aria-pressed=true] .gfx-demo i { animation: 1.6s cubic-bezier(.2, .8, .2, 1) infinite both; }
.gfx-anims button .gfx-demo i:nth-child(2) { animation-delay: .12s !important; }
.gfx-anims button .gfx-demo i:nth-child(3) { animation-delay: .24s !important; }
[data-anim=slide] .gfx-demo i { animation-name: gfx-slide !important; }
[data-anim=blinds] .gfx-demo i { animation-name: gfx-blinds !important; }
[data-anim=wipe] .gfx-demo i { animation-name: gfx-wipe !important; }
[data-anim=pop] .gfx-demo i { animation-name: gfx-pop !important; }
[data-anim=none] .gfx-demo i { animation: none !important; }
@keyframes gfx-slide { 0% { transform: translateX(-120%); opacity: 0; } 35%, 100% { transform: none; opacity: 1; } }
@keyframes gfx-blinds { 0% { transform: scaleY(0); filter: brightness(.4); } 30%, 100% { transform: none; filter: none; } }
@keyframes gfx-wipe { 0% { clip-path: inset(0 100% 0 0); } 35%, 100% { clip-path: inset(0 0 0 0); } }
@keyframes gfx-pop { 0% { transform: scale(.3); opacity: 0; } 22% { transform: scale(1.12); opacity: 1; } 34%, 100% { transform: none; } }

.gfx-actions { display: flex; flex-wrap: wrap; gap: 6px; }

/* ready-made cards, drawn live */
.gfx-gallery { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.gfx-thumb { display: flex; flex-direction: column; gap: 5px; padding: 0 0 6px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); cursor: pointer; text-align: left; font: inherit; overflow: hidden; transition: transform .18s ease, box-shadow .18s ease; }
.gfx-thumb:hover, .gfx-thumb:focus-visible { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0, 0, 0, .2); }
.gfx-thumb canvas { width: 100%; height: auto; display: block; background: #111; }
.gfx-thumb > span { display: flex; flex-direction: column; gap: 1px; padding: 0 8px; font-size: .78rem; }
.gfx-thumb > span .muted { font-size: .7rem; }

/* layout buttons get a small picture of their shape */
.gfx-lay-ico { display: flex; gap: 2px; height: 16px; width: 34px; margin-bottom: 3px; }
.gfx-lay-ico i { flex: 1; background: var(--text-2); opacity: .55; }
.gfx-layouts button[aria-pressed=true] .gfx-lay-ico i { background: var(--brand); opacity: 1; }
.gfx-lay-ico[data-lay=h2h] i:nth-child(2) { flex: 1.4; background: var(--border-strong); }
.gfx-lay-ico[data-lay=games] i:first-child { flex: 1.3; }
.gfx-lay-ico[data-lay=bars] { flex-direction: column; justify-content: center; }
.gfx-lay-ico[data-lay=bars] i { flex: none; height: 4px; }
.gfx-lay-ico[data-lay=bars] i:nth-child(1) { width: 100%; }
.gfx-lay-ico[data-lay=bars] i:nth-child(2) { width: 65%; }
.gfx-lay-ico[data-lay=bars] i:nth-child(3) { width: 85%; }
@media (max-width: 900px) {
  .gfx { grid-template-columns: minmax(0, 1fr); padding: 12px 16px; }
  /* Phones: the preview stays pinned (smaller) while the editor scrolls under it; motion,
     export and the ready-made cards follow the editor instead of pushing it off screen. */
  .gfx-stage { display: contents; }
  .gfx-frame { order: -3; position: sticky; top: 0; z-index: 5; padding: 8px; }
  /* (The Blind bar above the preview here too: it sat under the whole editor, 3,000 px down a phone, 2026-10-24.) */
  .gfx-blind { order: -4; }
  .gfx-credit { order: -2; }   /* the photos' credit in words, under the pinned preview */
  .gfx-caveat { order: -2; }
  .gfx-canvas { max-height: 34vh; }
  .gfx-player { order: -2; }
  .gfx-status { order: -1; }
  .gfx-motion { order: 1; }
  .gfx-actions { order: 2; }
  .gfx-start { order: 3; }
  .gfx-anims { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .gfx-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gfx-motion-label { width: 100%; }
}
.gfx > *, .gfx-sec, .gfx-subj { min-width: 0; }
.gfx-layouts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.gfx-subj-top .seg { flex-shrink: 0; }

/* ---------- Account ---------- */
.account .acct-card { border: 1px solid var(--border); background: var(--surface); padding: 16px; display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; max-width: 100%; }
.account > .acct-card { max-width: 460px; }
.account .acct-card h2 { margin: 0; font-family: var(--display); font-size: 1.15rem; }
.acct-form { display: flex; flex-direction: column; gap: 10px; }
.acct-field { display: flex; flex-direction: column; gap: 4px; }
.acct-field > span:first-child { font-size: .8rem; font-weight: 600; color: var(--text-2); }
.acct-field input { width: 100%; }
.acct-form .btn { align-self: flex-start; }
.acct-msg { margin: 0; min-height: 1.2em; font-size: .88rem; }
.acct-msg.error { color: var(--wrong); }
.acct-code { font-family: ui-monospace, Consolas, monospace; font-size: 1.25rem; letter-spacing: .06em; padding: 10px 12px; background: var(--surface-2); border: 1px dashed var(--border-strong); user-select: all; margin: 0; overflow-wrap: anywhere; }
.acct-trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.acct-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.acct-list li { display: flex; gap: 10px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--border); }
.acct-list li a { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
/* A saved item's row: name, when, then Pin / Rename / Delete; on a phone the buttons wrap under the name. */
.acct-list li { flex-wrap: wrap; row-gap: 4px; }
.acct-list li a { flex-basis: 40%; }
.acct-when { display: inline-flex; gap: 6px; align-items: center; white-space: nowrap; }
.acct-pin-tag { font-weight: 700; color: var(--text); text-transform: uppercase; letter-spacing: .06em; font-size: .66rem; }
.acct-acts { display: flex; gap: 4px; margin-left: auto; }
.acct-rename { display: flex; gap: 6px; flex: 1; align-items: center; min-width: 0; }
.acct-rename input { flex: 1; min-width: 0; font-size: 16px; }
.acct-danger { border-top: 1px solid var(--border); padding-top: 12px; margin-top: 6px; }
.acct-danger h3 { margin: 0; font-size: 1rem; }
.btn.danger { background: var(--wrong); border-color: var(--wrong); color: #fff; }
.account-link { text-decoration: none; white-space: nowrap; }
.acct-mini { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; max-height: 200px; overflow: auto; }
.acct-mini a { font-size: .85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-field .small { text-transform: none; letter-spacing: normal; font-weight: 400; }
.acct-card > .btn, .acct-card > a.btn, .acct-card > button { align-self: flex-start; }
/* The sign-in screen's three choices (Sign in, Create account, Sponsored account): one row, the
   full width of the card, so each is a comfortable tap on a phone. */
.account .seg.acct-tabs { display: flex; width: 100%; height: auto; }
.account .seg.acct-tabs button { flex: 1 1 0; min-width: 0; height: 36px; padding: 0 6px; white-space: normal; line-height: 1.15; font-size: .8rem; }
.acct-forgot { margin: 0; }
/* "Email me when new features launch": the box, a touch larger than a menu checkbox. */
.account .acct-updates { font-size: .9rem; }
.account .acct-updates input { width: 16px; height: 16px; margin: 0; flex: none; }
/* A sister site's choices all go to Pigskin Lab; Sign in, the usual one, stands out. */
.account .acct-choices button:first-child { background: var(--text); color: var(--bg); }
.acct-pro { display: inline-block; margin-left: 4px; padding: 2px 7px; background: var(--text); color: var(--bg); font: 700 .66rem/1.3 var(--font); letter-spacing: .06em; text-transform: uppercase; vertical-align: 2px; }

/* ---------- Home: the graphics maker section and its demo ---------- */
.gfx-ad { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 28px; align-items: center; }
.gfx-ad-copy p { max-width: 46ch; }
@media (max-width: 1020px) { .gfx-ad { grid-template-columns: minmax(0, 1fr); } }
.gdemo { position: relative; border: 2px solid var(--frame); box-shadow: 8px 8px 0 var(--surface-3); overflow: hidden; transition: opacity .5s; background: #0a0f1c; }
.gdemo.fade { opacity: 0; }
.gdemo.held, .gdemo.held * { animation-play-state: paused !important; }
.gd-segs { display: inline-flex; margin-left: auto; border: 1px solid #555; }
.gd-seg { padding: 3px 8px; color: #bbb; transition: background .2s, color .2s, transform .15s; }
.gd-seg.on { background: #eee; color: #111; font-weight: 700; }
.gd-seg.pressed, .gd-dl.pressed { transform: scale(.92); }
.gd-dl { margin-left: 6px; padding: 3px 10px; background: var(--brand-btn); color: #fff; font-weight: 700; transition: transform .15s; }
.gd-card { --ease: cubic-bezier(.16, 1, .3, 1); position: relative; aspect-ratio: 16 / 9; padding: 3.5% 5% 2%; display: flex; flex-direction: column; gap: 3%;
  background: repeating-linear-gradient(-45deg, rgba(255, 255, 255, .035) 0 14px, transparent 14px 46px), linear-gradient(135deg, #0a0f1c, #1a2233); color: #fff; font-family: var(--display); overflow: hidden; }
.gd-title { background: #f4f4f4; color: #0d0d0d; text-align: center; padding: .6% 0; border-bottom: 3px solid #f5c542; font-size: clamp(1rem, 2.6vw, 1.9rem); letter-spacing: .02em;
  transform: translateY(-140%); opacity: 0; transition: transform .6s var(--ease), opacity .3s; }
.s-title .gd-title { transform: none; opacity: 1; }
.gd-body { flex: 1; min-height: 0; display: grid; grid-template-columns: 26% minmax(0, 1fr) 26%; gap: 1.2%; }
.gd-side { position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: flex-end; background: linear-gradient(180deg, color-mix(in srgb, var(--c) 88%, #fff), color-mix(in srgb, var(--c) 60%, #000));
  transition: transform .75s var(--ease), opacity .4s; opacity: 0; }
.gd-side.a { transform: translateX(-115%); }
.gd-side.b { transform: translateX(115%); }
.s-sides .gd-side { transform: none; opacity: 1; }
.gd-ghost { position: absolute; inset: 0; display: grid; place-items: center; font-size: clamp(2rem, 7vw, 5rem); opacity: .14; letter-spacing: .02em; }
.gd-side canvas { position: absolute; left: 50%; top: 38%; width: 84%; height: auto; translate: -50% -50%; opacity: 0; transition: transform .9s var(--ease) .25s, opacity .4s .25s; }
.gd-side.a canvas { transform: rotate(-35deg) scale(.6); }
.gd-side.b canvas { transform: rotate(35deg) scale(.6); }
.s-sides .gd-side canvas { transform: none; opacity: 1; }
.gd-name { position: relative; background: rgba(0, 0, 0, .62); padding: 6% 4%; text-align: center; display: flex; flex-direction: column; }
.gd-name b { font-size: clamp(.9rem, 2.2vw, 1.6rem); }
.gd-name span { font-family: var(--font); font-size: clamp(.55rem, 1vw, .75rem); opacity: .8; }
.gd-rows { display: flex; flex-direction: column; gap: 2%; min-height: 0; }
.gd-row { position: relative; flex: 1; min-height: 0; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 4%; padding: 0 5%;
  background: #111; font-size: clamp(.95rem, 2.4vw, 1.8rem); clip-path: inset(0 50% 0 50%); transition: clip-path .5s var(--ease) calc(var(--i) * 170ms); }
.gd-row:nth-child(even) { background: #1b1b1b; }
.s-rows .gd-row { clip-path: inset(0 0 0 0); }
.gd-v { font-variant-numeric: tabular-nums; transition: color .35s, text-shadow .35s, opacity .35s; }
.va { text-align: center; }
.vb { text-align: center; }
.gd-lab { font-size: .52em; color: #a9b0bd; text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; transition: opacity .35s; }
.s-lead .gd-row[data-lead="a"] .va, .s-lead .gd-row[data-lead="b"] .vb { color: #f5c542; text-shadow: 0 0 14px rgba(245, 197, 66, .55); animation: gd-glint .9s calc(var(--i) * 120ms) both; }
@keyframes gd-glint { 0% { transform: scale(1); } 35% { transform: scale(1.18); } 100% { transform: scale(1); } }
/* Bars: the numbers slide to the ends, bars grow from the centre line toward each side. */
.gd-bar { position: absolute; top: 22%; height: 56%; width: 0; transition: width .8s var(--ease) calc(var(--i) * 120ms); opacity: .92; }
.gd-bar.ba { right: 50%; background: var(--ca); }
.gd-bar.bb { left: 50%; background: var(--cb); }
.s-bars .gd-row.has-bar .gd-bar.ba { width: calc(var(--wa) * .36); }
.s-bars .gd-row.has-bar .gd-bar.bb { width: calc(var(--wb) * .36); }
.s-bars .gd-row.has-bar .gd-lab { opacity: 0; }
.s-bars .gd-row:not(.has-bar) { opacity: .35; transition: opacity .5s, clip-path .5s; }
.gd-row .gd-v { position: relative; z-index: 1; }
.gd-foot { display: flex; justify-content: space-between; font-family: var(--font); font-size: clamp(.5rem, .9vw, .7rem); color: #a9b0bd; }
.gd-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; transition: opacity .12s; }
.gd-flash.on { opacity: .85; }
.gd-toast { z-index: 3; }
@media (prefers-reduced-motion: reduce) {
  .gd-title, .gd-side, .gd-side canvas, .gd-row, .gd-bar, .gd-v { transition: none !important; animation: none !important; }
}

/* What crawlers read before the app starts (lib/og.js inject); replaced on load. */
.prerender { padding: 24px 0; }
.prerender h1 { font-family: var(--display); margin: 0 0 8px; }

/* The tip strip under the header (public/js/pro.js decorateShell). */
.tip-strip { background: #1c1a14; border-bottom: 1px solid #3a3322; color: #d8d2c0; font-size: .85rem; }
.tip-strip .wrap { display: flex; align-items: center; justify-content: center; gap: 12px; padding-top: 6px; padding-bottom: 6px; flex-wrap: wrap; }
.tip-strip-link { color: #f2d27a; font-weight: 700; text-decoration: none; border: 1px solid #6b5a2a; padding: 3px 10px; }
.tip-strip-link:hover { background: #2e2716; }
.tip-strip-close { background: none; border: 0; color: #9a927e; font-size: 1.1rem; cursor: pointer; padding: 0 4px; line-height: 1; }
.tip-strip-close:hover { color: #fff; }
/* Phones keep the strip: "free during the beta" has to be seen there too. Compact, the line on its own row. */
@media (max-width: 600px) { .tip-strip { font-size: .78rem; } .tip-strip .wrap { gap: 6px 10px; padding-top: 5px; padding-bottom: 5px; } .tip-strip .wrap > span:first-child { flex-basis: 100%; text-align: center; } .tip-strip-link { padding: 2px 8px; } }

/* The tip ask after a download. */
.tip-nudge { position: fixed; right: 16px; bottom: 16px; z-index: 60; max-width: 340px; background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); border-top: 3px solid #d4a72c; box-shadow: 0 10px 30px rgba(0, 0, 0, .25); padding: 12px 14px; animation: tip-in .25s cubic-bezier(.2, .8, .2, 1); }
.tip-nudge p { margin: 0 0 10px; font-size: .88rem; line-height: 1.4; }
.tip-nudge-row { display: flex; gap: 8px; }
.tip-nudge.leaving { opacity: 0; transform: translateY(8px); transition: opacity .2s, transform .2s; }
@keyframes tip-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@media (max-width: 520px) { .tip-nudge { left: 12px; right: 12px; max-width: none; } }

/* The thank-you after a tip (public/js/pro.js): centred over a dimmed page. */
.tip-thanks-back { position: fixed; inset: 0; z-index: 80; background: rgba(0, 0, 0, .55); display: flex; align-items: center; justify-content: center; padding: 16px; animation: tip-fade .2s ease; }
.tip-thanks { background: var(--surface); color: var(--text); border-top: 5px solid #d4a72c; box-shadow: 0 24px 60px rgba(0, 0, 0, .4); max-width: 520px; width: 100%; padding: 32px 32px 28px; text-align: center; animation: tip-in .3s cubic-bezier(.2, .8, .2, 1); }
.tip-thanks-icon { font-size: 3rem; line-height: 1; margin-bottom: 10px; }
.tip-thanks h2 { font-family: var(--display); font-size: 2rem; margin: 0 0 10px; text-transform: uppercase; }
.tip-thanks p { font-size: 1.05rem; margin: 0 0 22px; color: var(--text-2); }
@keyframes tip-fade { from { opacity: 0; } to { opacity: 1; } }

/* Beta badge beside the logo: opens the feedback form (public/js/feedback.js). */
.beta-pill { align-self: center; border: 1px solid #6b5a2a; color: #f2d27a; font: 700 .66rem/1 var(--font); text-transform: uppercase; letter-spacing: .06em; padding: 4px 6px; white-space: nowrap; text-decoration: none; flex-shrink: 0; }
@media (min-width: 1366px) { .beta-pill { margin-left: -12px; } }   /* one-line header: sit close to the logo */
.beta-pill:hover { background: #2e2716; text-decoration: none; color: #ffe39a; }
/* "Check your spam" while the sending domain is new (account page). */
.acct-spam { background: #fff7e0; border-left: 3px solid #d4a72c; padding: 8px 10px; font-size: .9rem; color: #3a2f10; }
:root[data-theme="dark"] .acct-spam { background: #2a2414; color: #f0e2b8; }
.tip-strip-feedback { color: #d8d2c0; text-decoration: underline; text-underline-offset: 2px; }
.tip-strip-feedback:hover { color: #fff; }

/* Jargon with a hover explanation (public/js/glossary.js). */
.jargon { text-decoration: underline dotted; text-decoration-color: var(--muted); text-underline-offset: 3px; cursor: help; }

/* Phones: tighter cells, a capped name column (it stays pinned, so every pixel it takes is
   one the stats lose), bigger tap targets on the sortable headers, and a shadow on the
   right edge while there are more columns to swipe to. */
.tbl-wrap { position: relative; }
.tbl-wrap.more { box-shadow: inset -14px 0 10px -10px rgba(0, 0, 0, .28); }
@media (max-width: 600px) {
  table.stats { font-size: .78rem; }
  table.stats th, table.stats td { padding: 4px 5px; }
  table.stats thead tr:last-child th { padding-top: 9px; padding-bottom: 9px; }
  table.stats tbody td { padding-top: 6px; padding-bottom: 6px; }
  table.stats tr > :nth-child(2) { max-width: 118px; overflow: hidden; text-overflow: ellipsis; }
  table.stats td.rk { padding-left: 4px; padding-right: 3px; }
}

/* ---------- trend watch: summary and the by-team view ---------- */
.trend-summary { border: 1px solid var(--border); border-left: 4px solid var(--brand); background: var(--surface); padding: 10px 14px; margin: 12px 0 4px; max-width: 820px; }
.trend-summary p { margin: 0 0 6px; }
.trend-summary p:last-child { margin: 0; }
.trend-summary .lead { font-size: 1.02rem; }
.nowrap { white-space: nowrap; }
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; vertical-align: middle; flex: none; }
.dot.real { background: var(--real); } .dot.early { background: var(--early); } .dot.noise { background: var(--noise); } .dot.void { background: var(--void); }
.tgroups { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr)); gap: 10px; }
.tgroup { border: 1px solid var(--border); border-top: 3px solid var(--tc, var(--border)); background: var(--surface); padding: 8px 10px; }
.tgroup-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 4px; }
.tgroup ul { list-style: none; margin: 0; padding: 0; }
.tgroup li a { display: flex; gap: 7px; align-items: baseline; padding: 5px 0; border-top: 1px solid var(--grid); color: var(--text); font-size: .84rem; line-height: 1.3; }
.tgroup li a .dot { transform: translateY(-1px); }
.tgroup li a .what { flex: 1; }
.tgroup li a .nums { white-space: nowrap; font-variant-numeric: tabular-nums; font-weight: 700; }
/* The words are what matter (colour alone must not carry it); the colour is a quick cue. */
.tgroup .dir { font-weight: 600; font-size: .76rem; }
.tgroup .dir.up { color: var(--right); } .tgroup .dir.down { color: var(--wrong); }
.tgroup li a:hover .what { text-decoration: underline; }

/* ---------- glossary ---------- */
.gloss-index { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 4px 0 18px; font-size: .86rem; }
.gloss { max-width: 60em; margin: 0; }
.gloss dt { font: 700 1.1rem/1.3 var(--display); margin-top: 18px; padding-top: 10px; border-top: 1px solid var(--border); }
.gloss dd { margin: 4px 0 0; }
.gloss dd p { margin: 0 0 6px; }
.gloss-ex { color: var(--text-2); }
/* Glossary sections, the filter and each term's parts (public/js/views/glossary.js, from public/js/defs.js). */
.gloss-group { margin-top: 22px; }
.gloss-filter { width: 100%; max-width: 420px; min-height: 44px; margin: 4px 0 12px; font-size: 1rem; }
.gloss-k { color: var(--muted); font-weight: 600; }
.gloss-how, .gloss-src { color: var(--text-2); font-size: .92rem; }
.gloss-try a { display: inline-block; padding: 8px 0; min-height: 44px; box-sizing: border-box; }
.gloss dt[hidden], .gloss dd[hidden], .gloss-index[hidden] { display: none; }
/* The explanation of a stat: on touch screens a tap-to-open card (public/js/jargon.js). */
.jargon-i { border: 0; background: none; color: var(--link, var(--brand)); font-size: .95em; padding: 0 2px 0 4px; margin: 0; cursor: pointer; line-height: 1; vertical-align: baseline; min-width: 22px; min-height: 22px; position: relative; }
.jargon-i::after { content: ''; position: absolute; inset: -11px; }
.jargon-pop { position: absolute; z-index: 90; background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); box-shadow: 0 6px 20px rgba(0, 0, 0, .25); padding: 10px 12px; font: 400 .86rem/1.4 var(--font); text-transform: none; letter-spacing: 0; text-align: left; white-space: normal; }
.jargon-pop b { display: block; margin-bottom: 4px; }
.jargon-pop p { margin: 0 0 6px; }
.jargon-pop .jargon-how, .jargon-pop .jargon-src, .jargon-pop .jargon-chart { color: var(--text-2); font-size: .82rem; }
.jargon-k { color: var(--muted); font-weight: 600; }
.jargon-pop a { display: inline-block; padding: 6px 0 2px; }
/* A widget title: the explanation is on the whole title, without underlining the tools. */
.w-title.jargon { text-decoration-thickness: 1px; }
.w-head > .jargon-i { flex: none; align-self: center; }
/* Ask's answer to "what is OPS?" (jargon.js defineItem). */
.define-answer .define-more { color: var(--text-2); }
.ask-gloss { font-size: .76rem; margin-left: 8px; }
/* "View the SQL" in an Ask reply's row, beside "What the stats mean" and looking like it (public/js/sqlview.js). */
.ask-sql { font-size: .76rem; margin-left: 8px; text-decoration: none; }
.ask-sql:hover { text-decoration: underline; }

/* ---------- teams index ---------- */
.team-index { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: 14px; }
.team-div h2 { font-size: .9rem; border-bottom: 2px solid var(--text); padding-bottom: 3px; margin-bottom: 4px; }
.team-div ul { list-style: none; margin: 0; padding: 0; }
.team-div li { display: flex; justify-content: space-between; align-items: center; padding: 7px 0; border-bottom: 1px solid var(--grid); }
.team-div li a:hover { text-decoration: none; }
.team-div li a:hover .tchip { text-decoration: underline; }
.team-div h2 { display: flex; justify-content: space-between; align-items: baseline; }
.team-div-cols, .team-rec { font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }
.team-div-cols { font-size: .7rem; font-weight: 600; }
.team-div-cols span, .team-rec span { display: inline-block; min-width: 3.2em; text-align: right; }
.team-season { max-width: 140px; margin-top: 8px; }

/* ---------- the dashboard's graphic widget ---------- */
.widget .wbody > .w-graphic { flex: 1; min-height: 0; width: 100%; object-fit: contain; }
.w-graphic-links { padding-top: 4px; text-align: right; color: var(--muted); }

/* ---------- "Edit dashboard": moving and resizing widgets, on every screen (build.js setEditing) ----------
   Outside it there is no grip and no resize corner, so a drag on a widget scrolls its table or reads its chart
   (the owner, 2026-09-29). In it, each widget is outlined and has its grip and corner. */
.dash-page:not(.editing) .board.cells .w-grip, .dash-page:not(.editing) .board.cells .w-resize { display: none; }
.dash-page.editing .board.cells > .widget { outline: 1px dashed var(--border-strong); outline-offset: 2px; }
.dash-page.editing .edit-toggle { background: var(--text); color: var(--bg); border-color: var(--text); }
.dash-page.locked .edit-toggle { display: none; }
.w-grip { min-width: 24px; min-height: 24px; display: inline-grid; place-items: center; font-size: .95rem; }
/* ---------- phones: a reading view of the dashboard until "Edit dashboard" ---------- */
@media (max-width: 700px) {
  .dash-page:not(.editing) .dash-top > :not(.title-input):not(.edit-toggle):not(.share-btn) { display: none; }
  .dash-page:not(.editing) .focus-bar { display: none; }
  .dash-page:not(.editing) .board.stacked .wtools { display: none; }
  .dash-top .edit-toggle { order: -1; }
  .dash-top .share-btn { order: -1; }
}

/* ---------- jargon on touch screens: a tap-to-open explanation ---------- */
.jargon-i { border: 0; background: none; color: var(--link); font-size: .95em; padding: 0 2px 0 4px; margin: 0; cursor: pointer; line-height: 1; vertical-align: baseline; min-width: 22px; min-height: 22px; }
.jargon-pop { position: absolute; z-index: 90; background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); box-shadow: 0 6px 20px rgba(0, 0, 0, .25); padding: 10px 12px; font: 400 .86rem/1.4 var(--font); text-transform: none; letter-spacing: 0; text-align: left; white-space: normal; }
.jargon-pop b { display: block; margin-bottom: 4px; }
.jargon-pop p { margin: 0 0 6px; }

/* The key to a two-tone bar chart (above or below a player's average, or the league's). */
.tone-key { display: flex; flex-wrap: wrap; gap: 2px 14px; margin: 0 0 4px; font-size: .74rem; color: var(--text-2); }
.tone-key-item { display: inline-flex; align-items: center; gap: 5px; }
.tone-key-item i { width: 10px; height: 10px; flex: none; }
/* Nothing on the board follows the focus (players each in his own season): greyed out. */
.focus-bar.idle { border-left-color: var(--border); opacity: .55; }
.focus-bar.idle select:disabled { cursor: not-allowed; }

/* Which games count (public/js/weekpick.js): the kind first, then the weeks as a sentence. */
.week-pick { display: flex; flex-direction: column; gap: 6px; }
.week-pick-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: .82rem; }
.week-pick-line select { width: auto; }
.week-pick-line > span:first-child { min-width: 2.6em; }
.week-pick-says { margin: 0; font-size: .76rem; color: var(--text-2); }

/* ---------- the makers need an account (ui.js signInGate / signInBar) ---------- */
.signin-gate { max-width: 560px; margin: 48px auto; padding: 24px; border: 1px solid var(--border); border-top: 4px solid var(--brand); background: var(--surface); }
.signin-gate h1 { margin: 0 0 10px; font-family: var(--display); font-size: 1.5rem; }
.signin-gate p { margin: 0 0 10px; }
.signin-gate-btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.signin-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; padding: 8px 12px; margin-bottom: 8px; border: 1px solid var(--border); border-left: 4px solid var(--brand); background: var(--surface); font-size: .86rem; }
/* A shared dashboard, signed out: the board to read, Share, and nothing that edits it. */
.dash-page.locked .dash-top > :not(.title-input):not(.share-btn) { display: none; }
.dash-page.locked .focus-bar, .dash-page.locked .wtools, .dash-page.locked .dock, .dash-page.locked .h-e, .dash-page.locked .h-s, .dash-page.locked .h-se { display: none; }
.dash-page.locked .wbar { cursor: default; }
.dash-page.locked .title-input { border-color: transparent; background: none; }
/* A shared graphic, signed out: the card and its Play button, nothing that edits it. */
.gfx.locked { display: block; max-width: 1100px; margin: 0 auto; }
.gfx.locked .gfx-panel, .gfx.locked .gfx-motion, .gfx.locked .gfx-actions, .gfx.locked .gfx-start { display: none; }

/* ---------- plays widget (build.js renderPlays): a summary line, then every play ---------- */
.plays-sum { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 0 0 6px; font-size: .82rem; color: var(--text-2); }
.plays-sum b { color: var(--text); font-variant-numeric: tabular-nums; }
.plays-table .tbl-wrap { flex: 1; min-height: 0; }
.plays-table table.stats td:last-child { white-space: normal; min-width: 340px; max-width: 640px; }
.plays-list { list-style: none; margin: 0; padding: 0; overflow: auto; flex: 1; min-height: 0; }
.plays-list li { padding: 6px 0; border-top: 1px solid var(--border); font-size: .82rem; }
.plays-list .plays-top { color: var(--text-2); font-variant-numeric: tabular-nums; }
.plays-list .plays-top b { color: var(--text); }
.plays-list .plays-descr { margin-top: 2px; line-height: 1.35; }
/* The spider's "Choose stats" line, under the chart (build.js renderRadar). */
.radar-pick { font-size: .76rem; padding-top: 2px; }
/* A ranking's profile chart says it is not the ranking (lib/boards.js profileChart): in full, on a phone too. */
.profile-note { font-size: .78rem; line-height: 1.25; padding: 0 2px 4px; white-space: normal; }
.widget:has(.profile-note) .w-title { white-space: normal; }
.dash-page.locked .radar-pick { display: none; }
.btn.preset[aria-pressed="true"] { background: var(--text); color: var(--bg); border-color: var(--text); }

/* ============================================================
   The sibling sites' own markup, in the same look.
   Everything above is Pigskin Lab's stylesheet as it is; below, the class
   names the siblings' engine uses (the dashboard maker, the graphics
   maker, widgets, tables, charts, Ask, dialogs) drawn the same way:
   square corners, frame borders, condensed uppercase heads.
   ============================================================ */

/* The page: <main> is the column (Pigskin Lab puts a .wrap inside it). */
main#app { width: 100%; max-width: 1320px; margin: 0 auto; padding: 0 16px 40px; outline: none; }
main#app .wrap { padding: 0; max-width: none; }
/* The dashboard maker fills the window, with small side margins (Pigskin Lab's .wrap.wide); app.js sets .wide. */
main#app.wide { max-width: none; padding-bottom: 16px; }
/* Zero specificity, so Pigskin Lab's own picker rule above still wins: .84rem (13.4px), bold inside a .field. */
:where(button, input, select, textarea) { font: inherit; color: inherit; }
input[type="email"], input[type="password"], textarea { font: inherit; font-size: .84rem; color: var(--text); background: var(--surface); border: 1px solid var(--border-strong); border-radius: 0; padding: 3px 6px; min-width: 0; height: 30px; max-width: 100%; }
textarea { height: auto; resize: vertical; }
select { max-width: 100%; }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.field { display: grid; gap: 2px; font-size: .68rem; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.field > input, .field > select, .field > textarea { color: var(--text); text-transform: none; letter-spacing: normal; }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.ghost:hover { border-color: var(--border-strong); background: var(--surface-2); }
a.btn:hover, .btn:hover, a:hover > .btn { text-decoration: none; }
a:has(> .btn):hover { text-decoration: none; }
.linkish { color: var(--link); }
.error { padding: 8px 0; }
.section { margin-top: 26px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Chips: the "Try" chips of the home page, square; a picked one is black. */
.chips { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.chips .chip, .chip { border-radius: 0; margin: 0; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); padding: 4px 9px; font: 500 .8rem/1.2 var(--font); cursor: pointer; }
.chips .chip:hover, .chip:hover { border-color: var(--brand); background: var(--row-hover); color: var(--text); }
.chip.on, .chip[aria-pressed="true"], .chip.on:hover { background: var(--text); color: var(--bg); border-color: var(--text); }

/* Tabs (older markup): the segmented control. */
.tabs { display: inline-flex; flex-wrap: wrap; border: 1px solid var(--border-strong); margin: 0 0 12px; }
.tabs button { border: 0; border-right: 1px solid var(--border-strong); background: var(--surface); color: var(--text-2); padding: 0 10px; height: 30px; font: 600 .78rem/1 var(--font); cursor: pointer; }
.tabs button:last-child { border-right: 0; }
.tabs button.on, .tabs button[aria-selected="true"] { background: var(--text); color: var(--bg); }

/* Panels: a card is Pigskin Lab's box. */
.card { background: var(--surface); border: 1px solid var(--frame); padding: 10px 12px; min-width: 0; }
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }
.card > h2 { font-size: 1.05rem; }
.card > h3 { font-size: 1rem; }
.grid2 { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr)); }
.grid3 { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.grid2 > *, .grid3 > * { min-width: 0; }
.page-head > p.muted { color: var(--text-2); }

/* ---------- Ask (public/js/ask.js): Pigskin Lab's ask bar ---------- */
.ask { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; padding: 6px 10px; border: 1px solid var(--frame); background: var(--surface); }
.ask::before { content: "\2726  Ask"; font: 700 .8rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em; color: var(--text); white-space: pre; }
.ask input { flex: 1 1 300px; min-width: 0; height: 32px; font-size: .9rem; border: 1px solid var(--border-strong); background: var(--surface); padding: 3px 8px; box-shadow: none; }
.ask .btn { height: 32px; }
.ask .btn.ghost { width: 32px; padding: 0; justify-content: center; border-color: var(--border-strong); }
.ask.busy { opacity: .7; }
.ask-log { display: flex; flex-direction: column; gap: 2px; margin: 6px 0 0; max-height: 150px; overflow: auto; font-size: .8rem; }
.ask-log:empty { display: none; }
.ask-log .you, .ask-log .it { align-self: stretch; background: none; color: var(--text); padding: 2px 0; border-radius: 0; max-width: none; border-bottom: 1px solid var(--grid); }
.ask-log .you::before { content: "You: "; color: var(--muted); font-weight: 700; }
.ask-log .it { color: var(--text-2); }
.ask-log .it.miss { color: var(--wrong); }
.ask-log .read { font-size: .74rem; color: var(--muted); }
.ask-wrong { display: inline; margin-left: 8px; font-size: .76rem; color: var(--muted); }
@media (max-width: 700px) { .ask input { flex-basis: 100%; } }

/* ---------- the dashboard maker (views/build.js) ---------- */
/* The board: twelve columns of widgets in rows 78 px tall, inside Pigskin Lab's frame (.board-scroll). Its width is the
   design width (Width, or the window's at this zoom) and its zoom the board's, both set by build.js; Grid shows the
   lines. Empty, it is as tall as Pigskin Lab's and holds its "Start here" card (.board-empty). */
.board.cells { --cols: 12; --row: 78px; position: relative; left: auto; top: auto; display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); grid-auto-rows: var(--row); align-content: start; gap: 10px; padding: 10px; transform: none;
  background-color: var(--board-bg, var(--surface-2)); background-image: none; min-height: max(640px, calc(100vh - var(--header-h, 53px) - 190px)); color: var(--text); }
.board.cells.grid-on { background-image: linear-gradient(var(--grid) 1px, transparent 1px), linear-gradient(90deg, var(--grid) 1px, transparent 1px); background-size: 20px 20px; }
.board.cells.empty { min-height: 1000px; }
/* Pigskin Lab's round chips: "try one" on the empty board, and the suggestions under Ask. */
.board.cells .board-empty .chip, .dash-page .ask-bar .chip { margin: 2px; border-radius: 12px; background: var(--surface-2); font-size: .74rem; padding: 3px 8px; }
.board.cells .board-empty .chip:hover, .dash-page .ask-bar .chip:hover { border-color: var(--text); background: var(--surface-2); }
.board.cells .board-empty .quick-start { justify-content: center; margin-top: 6px; }
.board.cells .board-empty .search { position: relative; }
.board.cells .board-empty .search-results { left: 0; right: auto; text-align: left; }
.dash-page .board-scroll { min-height: calc(100vh - var(--header-h, 53px) - 190px); scroll-margin-top: calc(var(--header-h, 53px) + 8px); }
.dash-page .data-note { margin: -2px 0 8px; }
.dash-page .ask-bar .ask-log { flex: 1 1 100%; order: 4; margin: 0; }
.dash-page .ask-bar .ask-ideas { flex: 1 1 100%; order: 3; display: flex; flex-wrap: wrap; align-items: center; gap: 2px; margin: 0; }
.dash-page .ask-bar .ask-ideas:empty { display: none; }
/* The board's filters as chips (each x takes off that one filter) and the Kept / Changed / Dropped line after every
   request (lib/facets.js, FR-01). The x is drawn 24 px and answers a 44 px tap (DESIGN_SYSTEM INT-02, INT-12). */
.ask-filters { flex: 1 1 100%; order: 5; display: flex; flex-direction: column; gap: 4px; font-size: .8rem; }
.ask-filters:empty { display: none; }
.ask-kept { margin: 0; color: var(--text-2); line-height: 1.45; }
.ask-kept b { color: var(--text); font-weight: 700; }
.filter-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.filter-chips > .muted { margin-right: 2px; }
.chip.filter-chip, .dash-page .ask-bar .chip.filter-chip { display: inline-flex; align-items: center; gap: 2px; margin: 0; min-height: 0; padding: 1px 2px 1px 10px; cursor: default; border-color: var(--text-2); background: var(--surface); border-radius: 999px; }
.chip.filter-chip:hover, .dash-page .ask-bar .chip.filter-chip:hover { border-color: var(--text-2); background: var(--surface); }
.chip-x { position: relative; z-index: 1; display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 999px; background: none; color: var(--text-2); font: 700 1rem/1 var(--font); cursor: pointer; transition: background-color 120ms, color 120ms; }
.chip-x::before { content: ''; position: absolute; inset: -10px; }
.chip-x:hover, .chip-x:focus-visible { background: var(--surface-3); color: var(--text); }
.chip-x:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.chip.filter-chip.ro, .dash-page .chip.filter-chip.ro { padding: 2px 10px; cursor: default; border-color: var(--text-2); background: var(--surface); border-radius: 999px; font-size: .74rem; }
/* A shared board seen signed out: its filters under the sign-in bar, without the x (FR-01). */
.locked-filters { margin: 0 0 8px; padding: 6px 10px; border: 1px solid var(--frame); background: var(--surface); font-size: .8rem; }
.locked-filters:empty { display: none; }
.dash-page .pop .menu { z-index: 50; }
.board.cells > .widget { position: relative; background: var(--surface); border: 1px solid var(--frame); display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }
.widget.dragging { opacity: .4; }
.widget.drop-before { box-shadow: -4px 0 0 var(--sel); }
.widget.drop-after { box-shadow: 4px 0 0 var(--sel); }
.w-head { display: flex; align-items: center; gap: 6px; padding: 3px 4px 3px 9px; min-height: 34px; border-bottom: 1px solid var(--border); }
.w-title { flex: 1; min-width: 0; font: 700 .9rem/1.2 var(--display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.w-tools { display: flex; gap: 1px; }
.w-tools button { width: 24px; height: 24px; display: grid; place-items: center; border: 1px solid transparent; background: none; color: var(--text-2); cursor: pointer; font-size: .85rem; border-radius: 0; }
.w-tools button:hover { border-color: var(--border-strong); background: var(--surface-2); color: var(--text); }
.w-grip { cursor: grab; touch-action: none; }
.w-body { flex: 1; min-height: 0; padding: 4px 8px 6px; overflow: auto; position: relative; }
.w-body.chart { overflow: hidden; display: flex; flex-direction: column; }
/* A chart takes the room its key leaves, however many lines the key wraps to: a key of three clubs wrapped to two lines on a
   phone and pushed the seasons under the line chart out of its box (a fixed "100% - 24px", MLB story check, 2026-10-02). */
.w-body.chart > * { flex: none; }
.w-body.chart > .chart-box { flex: 1 1 0; min-height: 0; height: auto !important; }
.w-resize { position: absolute; width: 14px; height: 14px; right: -1px; bottom: -1px; cursor: nwse-resize; background: linear-gradient(135deg, transparent 55%, var(--border-strong) 55%); touch-action: none; }
.widget.answer { border-left: 4px solid var(--brand); }
.answer-text { font-size: 1rem; line-height: 1.45; }
.answer-text .answer-line { margin: 0 0 4px; }
.answer-text .answer-line:last-child { margin-bottom: 0; }
.note-text { white-space: pre-wrap; font-size: .9rem; }
@media (max-width: 720px) {
  .board.cells { --cols: 1; grid-auto-rows: auto; min-height: 400px; }
  .board.cells.empty { min-height: 1100px; }
  .board.cells > .widget { grid-column: 1 / -1 !important; grid-row: auto !important; min-height: 280px; }
  .board.cells > .widget.tiles-w, .board.cells > .widget.answer { min-height: 0; }
  .dash-page:not(.editing) .board.cells .w-tools > :not(.w-copy) { display: none; }
  .dash-page .board-scroll { min-height: 0; }
  .w-resize { display: none; }
  .w-body.chart { flex: none; height: 300px; }
  .widget.radar-w .w-body.chart { height: 430px; }
}
/* Stat tiles: Pigskin Lab's KPI strip. */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 0; border: 1px solid var(--border); height: 100%; align-content: stretch; }
.tile { padding: 8px 12px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); margin-bottom: -1px; min-width: 0; background: var(--surface); display: flex; flex-direction: column; justify-content: center; }
.tile .k { font-size: .7rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tile .v { font: 700 1.55rem/1.1 var(--display); font-variant-numeric: tabular-nums; }
.tile .r { font-size: .72rem; color: var(--muted); }
.tile .r.best { color: var(--right); font-weight: 700; }
/* The add drawer and dialogs: Pigskin Lab's dock and help panel. */
.drawer { position: fixed; inset: 0; background: rgba(0, 0, 0, .45); z-index: 60; display: flex; justify-content: flex-end; }
.drawer-in { width: min(420px, 100%); height: 100%; background: var(--surface); border-left: 2px solid var(--frame); padding: 14px 16px; overflow: auto; display: flex; flex-direction: column; gap: 12px; box-shadow: 0 10px 40px rgba(0, 0, 0, .28); }
.drawer-in h2 { margin: 0; font-size: 1rem; }
.modal { position: fixed; inset: 0; background: rgba(0, 0, 0, .45); z-index: 96; display: grid; place-items: center; padding: 16px; }
.modal-in { background: var(--surface); border: 2px solid var(--frame); padding: 12px 16px 16px; width: min(560px, 100%); max-height: 90vh; overflow: auto; display: grid; gap: 12px; }
.modal-in h2 { margin: 0; font-size: 1.05rem; }
/* ---------- "View the SQL" (public/js/sqlview.js): the button under a page that read data, and its panel ----------
   The panel is the site's dialog, wide enough for SQL; only a query's own block scrolls sideways, never the panel. */
.sql-foot { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 28px 16px 24px; text-align: center; }
.sql-foot[hidden] { display: none; }
.sql-foot .sql-sub { margin: 0; font-size: .82rem; color: var(--muted); }
.modal-in.sql-modal { width: min(900px, 100%); overflow-x: hidden; overscroll-behavior: contain; }
.sql-modal > * { min-width: 0; }
.sql-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; position: sticky; top: -12px; z-index: 1; background: var(--surface); margin: -12px 0 0; padding: 12px 0 8px; border-bottom: 1px solid var(--border); }
.sql-intro { margin: 0; font-size: .86rem; color: var(--text-2); }
.sql-list { display: grid; gap: 18px; min-width: 0; }
.sql-req { display: grid; gap: 10px; min-width: 0; }
.sql-req h3 { margin: 0; font-size: .86rem; overflow-wrap: anywhere; }
.sql-req h3 code { font: 600 .84rem/1.3 var(--mono); }
.sql-q { display: grid; gap: 6px; min-width: 0; border-left: 3px solid var(--border-strong); padding-left: 10px; }
.sql-qhead { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: .8rem; color: var(--text-2); }
.sql-qhead b { color: var(--text); }
.sql-cached { margin: 0; font-size: .76rem; color: var(--muted); font-style: italic; }
.sql-code { margin: 0; padding: 8px 10px; max-width: 100%; overflow-x: auto; white-space: pre; background: var(--surface-2); border: 1px solid var(--border); color: var(--text); font: .76rem/1.45 var(--mono); tab-size: 2; }
.sql-code code { font: inherit; }
.sql-params { margin: 0; padding: 0; list-style: none; display: grid; gap: 2px; }
.sql-params li { min-width: 0; overflow-wrap: anywhere; }
.sql-params code { font: .74rem/1.4 var(--mono); color: var(--text-2); }
/* (A phone keeps a margin round the panel, as the site's other dialogs do: a tap there closes it.) */
@media (max-width: 600px) {
  .modal:has(> .sql-modal) { padding: 10px; }
  .modal-in.sql-modal { padding: 10px 12px 16px; }
  .sql-head { top: -10px; margin-top: -10px; padding-top: 10px; }
}
.picks { display: flex; gap: 6px; flex-wrap: wrap; }
.pick { display: inline-flex; gap: 4px; align-items: center; border: 1px solid var(--border-strong); background: var(--surface-2); padding: 2px 2px 2px 8px; font-size: .8rem; }
.pick button { border: 0; background: none; cursor: pointer; color: var(--muted); width: 22px; height: 22px; }
.pick button:hover { background: var(--surface-3); color: var(--text); }
.add-list { display: grid; gap: 0; border-top: 1px solid var(--border); }
.add-list button { text-align: left; border: 0; border-bottom: 1px solid var(--border); border-left: 4px solid var(--frame); background: var(--surface); padding: 8px 12px; cursor: pointer; color: var(--text); }
.add-list button:hover { background: var(--surface-2); border-left-color: var(--brand); }
.add-list b { display: block; font: 700 .85rem/1.2 var(--display); text-transform: uppercase; letter-spacing: .03em; }
.add-list span { font-size: .75rem; color: var(--text-2); }
.drawer .search, .modal .search { position: relative; }
.drawer .search input, .modal .search input { width: 100%; }
/* Search results: the header's list, and the makers' player pickers (shown with [hidden]). */
.search-results { display: block; }
.search-results a.on { background: var(--row-hover); text-decoration: none; }
.search-results a .muted { color: var(--muted); font-size: .78rem; }
.toasts { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); display: grid; gap: 8px; z-index: 120; max-width: calc(100% - 32px); }
.toasts .toast { position: static; transform: none; animation: none; }

/* ---------- tables (public/js/table.js): the reference-site table ---------- */
.tbl-wrap { overflow: auto; border: 1px solid var(--frame); max-width: 100%; background: var(--surface); }
.w-body > .tbl-wrap { border-color: var(--border); }
table.tbl { border-collapse: collapse; width: 100%; font-size: .8rem; font-variant-numeric: tabular-nums; }
.tbl th, .tbl td { padding: 3px 7px; border-bottom: 1px solid var(--grid); white-space: nowrap; text-align: right; }
.tbl th.l, .tbl td.l { text-align: left; }
.tbl thead th { position: sticky; top: 0; z-index: 2; background: var(--surface-2); color: var(--text); font-weight: 700; border-bottom: 1px solid var(--border-strong); cursor: pointer; user-select: none; }
.tbl thead th:hover { background: var(--surface-3); }
.tbl th.sorted::after { content: " \25BC"; font-size: .6em; }
.tbl th.sorted.asc::after { content: " \25B2"; font-size: .6em; }
.tbl td { background: var(--surface); }
.tbl tbody tr:nth-child(even) td { background: var(--row-alt); }
.tbl tbody tr:hover td { background: var(--row-hover); }
.tbl tr.hl td { background: var(--row-hover); font-weight: 700; }
/* A row of one game opens its game page (public/js/table.js gameRow); its date is the link. */
.tbl tr.game-row { cursor: pointer; }
.tbl a.game-link { font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.tbl .rk { width: 1%; }
.tbl td.rk { color: var(--muted); }   /* the rank number is grey; its heading stays the text colour, as on Pigskin Lab */
.team-dot { display: inline-block; width: 4px; height: 13px; margin-right: 6px; vertical-align: -2px; }
@media (max-width: 600px) {
  table.tbl { font-size: .78rem; }
  .tbl th, .tbl td { padding: 4px 5px; }
  .tbl tbody td { padding-top: 6px; padding-bottom: 6px; }
  .tbl td.rk { padding-left: 4px; padding-right: 3px; }
}

/* ---------- charts (public/js/charts.js) ---------- */
.chart-box { width: 100%; height: 100%; position: relative; }
.chart-box svg { display: block; width: 100%; height: 100%; overflow: visible; }
.chart-tip { position: absolute; pointer-events: none; background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); font-size: .78rem; line-height: 1.4; padding: 6px 8px; white-space: nowrap; z-index: 5; transform: translate(-50%, calc(-100% - 10px)); }
.legend { color: var(--text-2); }
.legend > span { display: inline-flex; align-items: center; }
.legend i { display: inline-block; width: 10px; height: 10px; margin-right: 5px; }

/* ---------- the graphics maker (views/graphic.js) ---------- */
.gfx.section { max-width: none; margin: 14px 0 0; padding: 0; grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); }
.gfx-side { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.gfx-side h3 { margin: 0 0 6px; font-family: var(--display); font-size: .95rem; text-transform: uppercase; letter-spacing: .03em; }
.gfx-stage { position: sticky; top: calc(var(--header-h, 0px) + 12px); background: repeating-linear-gradient(45deg, var(--surface-2) 0 10px, var(--surface) 10px 20px); border: 1px solid var(--border); padding: 14px; display: grid; place-items: center; min-height: 300px; }
.gfx-stage svg { width: 100%; height: auto; max-height: 72vh; display: block; box-shadow: 0 10px 34px rgba(0, 0, 0, .28); }
.gfx-stage-only .gfx-stage { max-width: 1100px; margin: 0 auto; position: static; }
.subject { border: 0; border-left: 4px solid var(--tc, var(--frame)); padding: 6px 0 6px 8px; display: flex; flex-direction: column; gap: 6px; background: none; }
.subject-top { display: flex; justify-content: space-between; gap: 6px; align-items: center; font: 700 .9rem/1.2 var(--display); }
@media (max-width: 900px) {
  .gfx.section { grid-template-columns: minmax(0, 1fr); }
  .gfx-stage { position: sticky; top: 0; z-index: 5; padding: 8px; order: -1; min-height: 0; }
  .gfx-stage svg { max-height: 34vh; }
}

/* ---------- team marks (views/team.js, views/player.js) ---------- */
.team-head { display: flex; gap: 14px; align-items: center; }
.team-badge { width: 44px; height: 44px; display: grid; place-items: center; color: #fff; font: 700 .9rem/1 var(--display); letter-spacing: .02em; flex: none; }
.radar-pick { text-align: center; }

/* ---------- accounts (views/account.js) ---------- */
.account .page-head { display: block; }
.acct-msg:empty { display: none; }
.account .seg { flex-wrap: wrap; height: auto; width: fit-content; max-width: 100%; }
.account .seg button { height: 30px; }
.signin-bar span { flex: 1; min-width: 200px; }
.signin-gate .row { justify-content: flex-start !important; }

/* ---------- the header's logo mark and the footer's source notice ---------- */
.brand-logo { width: 30px; height: 30px; display: block; flex: none; margin: -4px -2px -4px 0; }
.site-footer .notice-src { flex-basis: 100%; font-size: .72rem; }

/* ---------- the graphics demo's bar on phones: buttons keep one line, the address gives way ---------- */
.gd-seg, .gd-dl { white-space: nowrap; }
@media (max-width: 480px) { .gdemo-wrap .demo-url { display: none; } .gd-seg { padding: 3px 6px; } .gd-dl { padding: 3px 8px; } }

/* "More from Mason Obegi" (the footer's sister-site cards, .site-family and .fam-*) comes with Pigskin Lab's own
   stylesheet above, byte for byte, so it is not repeated here: a rebuild keeps it. */

/* ---------- chart tooltips (public/js/charts.js): a pinned value, and the phone sheet's rows ----------
   A click or tap pins a tooltip; on a phone a game's numbers open in the bottom sheet, whose rows keep
   the label and the value apart as the floating tooltip's do. */
.tip-sheet .tt-r { display: flex; align-items: center; gap: 10px; justify-content: space-between; }
.tip-sheet .tt-r span:first-child { display: inline-flex; align-items: center; gap: 5px; color: var(--text-2); }
.tip-sheet .tt-r b { font-variant-numeric: tabular-nums; }
.tooltip .tt-sw, .tip-sheet .tt-sw { display: inline-block; width: 9px; height: 9px; flex: none; }
.tooltip.pinned { border-color: var(--text); }
.chart-box svg:focus { outline: none; }
.chart-box svg:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* ---------- the header's eight links on one line at 1366px ----------
   Games (views/games.js) made eight links, as on Pigskin Lab; with these sites' longer names and a
   signed-in "My account" the last one (Trend watch) was cut off at 1366px, so the links sit closer there. */
@media (min-width: 1366px) and (max-width: 1499px) { .nav a { padding: 0 7px; letter-spacing: .02em; } }

/* ---------- a stat tile's rank floor and its two parts (public/js/widgets.js tiles) ----------
   Under the rank, the players it is over ("among 502+ plate appearances"); with postseason games in the span, what
   came in each part ("Regular season 60 (151 g) · Postseason 2 (4 g)"), on two lines on a narrow tile, the second
   without the separator. */
.tile .q { font-size: .66rem; color: var(--muted); line-height: 1.2; }
.tile .p { display: flex; flex-wrap: wrap; font-size: .66rem; color: var(--text-2); line-height: 1.25; margin-top: 3px; font-variant-numeric: tabular-nums; }
/* (Each part moves to its own line first; one still wider than the tile wraps its words: "Regular season .634 (82 g)"
   ran past a 126 px tile on an iPad and was cut, sweep 2026-10-04.) */
.tile .p span { white-space: normal; min-width: 0; }
.tile .p .sep { white-space: pre; }
.tile .p.wrapped .sep { display: none; }

/* ---------- a postseason game in a table (public/js/table.js): its round and game of the series ---------- */
.post-tag { display: inline-block; margin-left: 5px; padding: 0 4px; border: 1px solid var(--border); border-radius: 3px; background: var(--surface-2); color: var(--text); font-size: .66rem; font-weight: 700; letter-spacing: .03em; line-height: 1.35; white-space: nowrap; vertical-align: 1px; }

/* ---------- a widget's settings (public/js/views/build.js settings): Save and close and Discard changes ----------
   At the top right beside the title and again at the bottom; on a phone the pair drops under the title. */
.settings-head { justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.settings-head h2 { margin: 0; }
.settings-ways { display: inline-flex; gap: 8px; margin-left: auto; flex-wrap: wrap; }
.settings-foot { justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; }

/* ---------- suggestion chips under Ask (public/js/ask.js, lib/chips.js): a row of follow-ups, gone when empty ---------- */
.ask-chips { margin: 6px 0 2px; }
.ask-chips:empty { display: none; }

/* ---------- a widget's settings (⚙, public/js/views/build.js): the chart as the settings stand, above them ---------- */
.modal-in.settings-modal { width: min(760px, 100%); }
.settings-modal .w-body.settings-preview { flex: none; height: 260px; overflow: auto; border: 1px solid var(--border); background: var(--surface); }
/* Phones: the window is the whole screen and ONE scroll, the chart first at a fixed height, then every setting at full
   height, with room under the last. A small inner scroll box under a tall chart was too cramped to scroll with a thumb.
   Nothing in it stops a thumb that starts on the chart from scrolling (no touch-action: none there). */
@media (max-width: 700px) {
  .modal.settings-shade { padding: 0; place-items: stretch; }
  .modal-in.settings-modal { width: 100%; height: 100%; max-height: none; border: 0; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; padding: 0 10px 96px; }
  .settings-modal > * { flex: 0 0 auto; }
  .settings-modal .settings-head { position: sticky; top: 0; z-index: 2; background: var(--surface); padding: 8px 0 6px; margin: 0; border-bottom: 1px solid var(--frame); flex-wrap: nowrap; }
  .settings-modal .settings-head h2 { font-size: .95rem; min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .settings-modal .settings-ways { display: flex; gap: 6px; flex-shrink: 0; }
  .settings-modal .settings-ways .btn { padding: 6px 10px; font-size: .8rem; }
  .settings-modal .w-body.settings-preview { height: 58vh; min-height: 280px; }
  .settings-modal .w-body.settings-preview.chart { overflow: hidden; }
}

/* The email box (public/js/feedback.js): a mailto: link (the legal pages' contact) opens this instead of the mail program.
   The address to copy, Copy, and "Open email app" for anyone who wants it. */
.fb-back { position: fixed; inset: 0; z-index: 90; background: rgba(0, 0, 0, .5); display: flex; align-items: center; justify-content: center; padding: 16px; animation: tip-fade .15s ease; }
.fb-box { position: relative; background: var(--surface); color: var(--text); border-top: 4px solid #d4a72c; box-shadow: 0 20px 50px rgba(0, 0, 0, .4); width: 100%; max-width: 440px; padding: 22px 22px 16px; animation: tip-in .2s cubic-bezier(.2, .8, .2, 1); }
.fb-title { font-family: var(--display); font-size: 1.35rem; text-transform: uppercase; margin: 0 36px 6px 0; }
.fb-prompt { margin: 0 0 12px; color: var(--text-2); }
.fb-row { display: flex; gap: 8px; align-items: stretch; }
.fb-addr { flex: 1; min-width: 0; display: flex; align-items: center; padding: 8px 10px; border: 1px solid var(--border-strong); background: var(--surface-2); font: 500 1rem/1.3 var(--font); overflow-wrap: anywhere; user-select: all; -webkit-user-select: all; cursor: text; }
.fb-row .fb-copy { height: auto; min-height: 44px; min-width: 88px; justify-content: center; font-size: .9rem; }
.fb-status { min-height: 1.3em; margin: 8px 0 0; font-size: .85rem; color: var(--text-2); }
.fb-alt { margin: 4px 0 0; font-size: .85rem; }
.fb-open-app { display: inline-block; padding: 8px 0; color: var(--link); text-decoration: underline; text-underline-offset: 2px; }
.fb-close { position: absolute; top: 6px; right: 6px; width: 44px; height: 44px; background: none; border: 0; color: var(--muted); font-size: 1.5rem; line-height: 1; cursor: pointer; }
.fb-close:hover { color: var(--text); }
@media (max-width: 420px) { .fb-box { padding: 18px 16px 12px; } .fb-row { flex-direction: column; } .fb-row .fb-copy { width: 100%; } }

/* The feedback form (public/js/feedback.js openFeedback): in the site's own colours (--brand: NBA orange,
   MLB green, NHL blue). It shares the shade (.fb-back), so the page behind is locked while it is open. */
.fb-box.fb-form-box { max-width: 520px; max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px); overflow-y: auto; border-top-color: var(--brand); }
.fb-form { display: flex; flex-direction: column; gap: 6px; }
.fb-field { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-top: 6px; font-weight: 600; font-size: .9rem; }
.fb-opt, .fb-count { font-weight: 400; font-size: .8rem; color: var(--text-2); }
.fb-count { font-variant-numeric: tabular-nums; }
.fb-text, .fb-email { width: 100%; box-sizing: border-box; font: 400 1rem/1.4 var(--font); padding: 8px 10px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); border-radius: 0; }
.fb-text { min-height: 120px; resize: vertical; }
.fb-text:focus-visible, .fb-email:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.fb-error { margin: 4px 0 0; color: var(--wrong, #b3261e); font-size: .88rem; font-weight: 600; }
.fb-error[hidden] { display: none; }
.fb-actions { display: flex; gap: 8px; margin-top: 10px; }
.fb-actions .btn { height: 40px; min-width: 96px; justify-content: center; font-size: .9rem; }
.fb-actions .btn.primary { background: var(--brand-btn); border-color: var(--brand-btn); color: #fff; }
.fb-form-box .fb-alt { margin: 12px 0 0; padding-top: 10px; border-top: 1px solid var(--border); color: var(--text-2); }
.fb-alt-addr { color: var(--text); user-select: all; -webkit-user-select: all; overflow-wrap: anywhere; }
.fb-form-box .fb-copy { font-size: .85rem; padding: 6px 2px; }
@media (max-width: 420px) { .fb-actions .btn { flex: 1; } }
/* The feedback controls are buttons now (they open the form, not a mail program). */
button.beta-pill { background: transparent; cursor: pointer; }
button.tip-strip-feedback { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.site-footer .footer-feedback { color: var(--link); font-size: inherit; text-underline-offset: 2px; text-decoration-thickness: 1px; }
@media (pointer: coarse), (max-width: 700px) { .site-footer .footer-feedback { display: inline-flex; align-items: center; min-height: 32px; padding: 4px 0; } }

/* ---------- signing in: the moment before the shared sign-in page (account.js handoff()) ----------
   In this site's own colours, so the jump to pigskinlab.com is expected, not a surprise. */
.handoff { position: fixed; inset: 0; z-index: 120; display: grid; place-items: center; padding: 16px; background: var(--bg); }
.handoff-in { width: min(440px, 100%); display: grid; justify-items: center; gap: 10px; text-align: center; padding: 28px 22px 24px; background: var(--surface); border: 1px solid var(--border); border-top: 5px solid var(--brand); }
.handoff-logo { width: 72px; height: 72px; }
.handoff-logo.on-dark, :root[data-theme="dark"] .handoff-logo.on-light { display: none; }
:root[data-theme="dark"] .handoff-logo.on-dark { display: block; }
.handoff-site { margin: 0; font: 700 1.1rem/1 var(--display); letter-spacing: .06em; text-transform: uppercase; color: var(--brand-ink); }
.handoff h2 { margin: 0; font-size: 1.25rem; }
.handoff-note { margin: 0; color: var(--text-2); font-size: .9rem; max-width: 36em; }
.handoff-bar { width: 100%; height: 4px; background: var(--surface-3); overflow: hidden; margin: 6px 0 4px; }
.handoff-bar span { display: block; height: 100%; width: 100%; background: var(--brand); transform-origin: left; animation: handoff-fill 1s linear both; }
@keyframes handoff-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.handoff .btn.primary { background: var(--brand-btn); border-color: var(--brand-btn); color: #fff; min-width: 140px; justify-content: center; }
@media (prefers-reduced-motion: reduce) { .handoff-bar span { animation: none; } }

/* ---------- one game, drawn (public/js/gamewidgets.js): paired bars, the storyline, the game page's board ---------- */
.pair-rows { display: flex; flex-direction: column; gap: 8px; padding: 2px 4px 2px 0; }
.pair-row { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pair-label { font-size: .8rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pair-label .muted { font-weight: 400; }
.pair-bar { display: grid; grid-template-columns: 64px minmax(0, 1fr) 64px; align-items: center; gap: 6px; font-size: .78rem; }
.pair-name { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pair-track { height: 12px; background: var(--surface-2); position: relative; min-width: 0; }
/* The bar's value end rounded and a soft sheen toward it, like the charts' bars (the owner, 2026-10-24: colour and pop); never an outline. */
.pair-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 0 3px 3px 0; }
.pair-fill::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(90deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, .22)); pointer-events: none; }
.pair-val { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.game-story { display: block; }
/* (The page grows a row to fit what is in it: the storyline and the paired bars show whole, not in a scroll box.) */
.game-board.board.cells { min-height: 0; background-image: none; padding: 0; background-color: transparent; margin: 14px 0 24px; grid-auto-rows: minmax(var(--row), auto); }
.game-board .widget .w-body:not(.chart) { overflow: visible; }
@media (max-width: 720px) {
  .board.cells > .widget.radar-w .w-body.chart, .game-board .widget.radar-w .w-body.chart { height: 430px; }
  .game-board .widget.story-w, .board.cells > .widget.story-w { min-height: 0; }
  .pair-bar { grid-template-columns: 56px minmax(0, 1fr) 56px; }
}
/* ---------- an open pop-up scrolls on its own; the page behind it is locked (ui.js syncScrollLock) ---------- */
.modal, .modal-in, .drawer, .drawer-in, .tip-sheet, .tip-sheet-body, .help-dialog, .help-panel, .fb-back, .fb-box, .handoff, .clip-menu { overscroll-behavior: contain; }
.modal-in, .drawer-in, .tip-sheet-body, .help-panel, .fb-box, .clip-menu { -webkit-overflow-scrolling: touch; }
.help-panel { max-height: 90vh; overflow: auto; }
html.scroll-locked { scrollbar-gutter: stable; }

/* ---------- an empty dashboard shows only what an empty board can use (build.js draw) ----------
   Nothing to move, clear, tidy, zoom, share or export yet: Add widget, Paste, Dashboards, Undo and Redo stay. On a
   phone those show without "Edit dashboard" (there is nothing to edit). */
.dash-page.empty-board .dash-top > .edit-toggle, .dash-page.empty-board .dash-top > .dash-clear, .dash-page.empty-board .dash-top > .desk-only:not([aria-label="Keyboard shortcuts"]),
.dash-page.empty-board .dash-top > .seg, .dash-page.empty-board .dash-top > .dash-fit, .dash-page.empty-board .dash-top > .inline-field,
.dash-page.empty-board .dash-top > .share-btn, .dash-page.empty-board .dash-top > .export-pop, .dash-page.empty-board .focus-bar { display: none; }
@media (max-width: 700px) {
  .dash-page.empty-board:not(.locked):not(.editing) .dash-top > .add-widget:not(.x), .dash-page.empty-board:not(.locked):not(.editing) .dash-top > .paste-pop:not(.x), .dash-page.empty-board:not(.locked):not(.editing) .dash-top > .saves-pop:not(.x) { display: inline-flex; }
}
/* The clipboard (build.js drawPaste): each copy with a tick, Paste one, remove one; Paste ticked, Paste all, Clear. */
.clip-menu { min-width: min(340px, calc(100vw - 32px)); max-height: min(420px, 70vh); overflow: auto; }
.clip-row { display: flex; align-items: center; gap: 6px; padding: 4px 0; border-bottom: 1px solid var(--border); }
.clip-row label { flex: 1; min-width: 0; }
.clip-row label > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clip-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
/* A shared board open to look at can be copied from: its widgets keep Copy and Save as PNG. */
.w-copy { font-size: 1rem !important; }

/* ---------- the graphics maker opens empty, and its two columns scroll on their own (views/graphic.js) ----------
   Things to try under Ask, in the dashboard maker's "Try:" style; in the card's place a short "here are a few things you
   can make" until there is a card, and no Play, export or share for a card that is not there (the owner, 2026-09-29). */
.gfx-ask .gfx-ideas { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; margin: 6px 0 2px; }
.gfx-ask .gfx-ideas .chip { margin: 2px; border-radius: 12px; background: var(--surface-2); font-size: .74rem; padding: 3px 8px; }
.gfx-ask .gfx-ideas .chip:hover { border-color: var(--text); background: var(--surface-2); }
.gfx-placeholder { display: none; width: 100%; border: 1px dashed var(--border-strong); background: var(--surface); padding: 22px 20px; }
.gfx-placeholder h2 { margin: 0 0 4px; font-family: var(--display); font-size: 1.35rem; }
.gfx-placeholder p { margin: 0 0 14px; }
.gfx-try { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 8px; }
.gfx-try-card { display: flex; flex-direction: column; gap: 3px; text-align: left; padding: 10px 12px; min-height: 44px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); cursor: pointer; font: inherit; }
.gfx-try-card:hover, .gfx-try-card:focus-visible { border-color: var(--frame); box-shadow: inset 0 -3px 0 var(--brand); }
.gfx-try-card .muted { font-size: .78rem; }
.gfx-stage.gfx-blank > .gfx-placeholder { display: block; }
.gfx-stage.gfx-blank > .gfx-frame, .gfx-stage.gfx-blank > .gfx-player, .gfx-stage.gfx-blank > .gfx-status, .gfx-stage.gfx-blank > .gfx-motion, .gfx-stage.gfx-blank > .gfx-actions { display: none; }
.gfx-stage > * { width: 100%; }
.gfx-stage > .gfx-player { width: auto; }
/* Side by side (over 900 px), each column scrolls on its own: both stick under the header and scroll inside, by wheel
   and by touch, and a scroll that reaches a column's end does not carry on into the page (the owner, 2026-09-29: on
   iPad scrolling the settings moved the card). */
@media (min-width: 901px) {
  .gfx:not(.locked):not(.section) > .gfx-panel, .gfx:not(.locked):not(.section) > .gfx-stage { position: sticky; top: calc(var(--header-h, 0px) + 12px); max-height: calc(100dvh - var(--header-h, 0px) - 24px);
    overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; touch-action: pan-y; scrollbar-gutter: stable; }
  .gfx:not(.locked):not(.section) > .gfx-panel { padding-right: 4px; }
  .gfx:not(.locked):not(.section) > .gfx-stage { align-content: start; }
  .gfx:not(.locked):not(.section) .gfx-canvas { max-height: min(68vh, calc(100dvh - var(--header-h, 0px) - 190px)); }
}
/* Stacked (phones and narrow tablets): the page scrolls; the card sits on top of the settings and stays in view. */
@media (max-width: 900px) {
  .gfx:not(.section) > .gfx-stage { display: contents; }
  .gfx:not(.section) .gfx-frame { order: -3; position: sticky; top: var(--header-h, 0px); z-index: 5; padding: 8px; }
  .gfx:not(.section) .gfx-placeholder { order: -3; padding: 14px 12px; }
  .gfx-try { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- touch screens and phones: every control big enough to hit with a thumb (QoL, 2026-09-29) ----------
   Measured at 390 px and on a 1024 px touch tablet: Ask chips were 22 px tall, "Wrong answer?" 18, footer links 15,
   breadcrumbs and glossary links 15-18, the graphics maker's ticks 13 and slider 16, "Open this dashboard" 19, the
   widget grip 13 x 21. Each gets at least 24 px (WCAG 2.2 target size), most 32 or more, without changing the layout on
   a desktop with a mouse. */
@media (pointer: coarse), (max-width: 700px) {
  .chip, .chips .chip, .board.cells .board-empty .chip, .dash-page .ask-bar .chip, .gfx-ask .gfx-ideas .chip { min-height: 32px; padding: 6px 10px; }
  .ask-wrong .linkish, .ask-wrong .btn.small { display: inline-flex; align-items: center; min-height: 32px; padding: 4px 6px; }
  .gloss-index a, .tgroup-head .linkish, .demo-open, .board-empty .linkish { display: inline-flex; align-items: center; min-height: 32px; padding: 4px 2px; }
  /* Breadcrumbs keep Pigskin Lab's line (a 32 px line pushed every page's heading 7-13 px down) and get an invisible hit area. */
  .crumbs a { position: relative; }
  .crumbs a::after { content: ''; position: absolute; inset: -8px -4px; }
  .site-footer a:not(.site-family a) { display: inline-flex; align-items: center; min-height: 32px; padding: 4px 0; }
  .gfx-check { min-height: 32px; }
  .gfx-check input[type=checkbox], input[type=checkbox] { width: 20px; height: 20px; }
  .gfx-scrub { min-height: 32px; }
  .gfx-subj-tools .btn.small { min-width: 32px; min-height: 32px; }
  .w-tools button { width: 34px; height: 34px; }
  .w-grip { min-width: 36px; min-height: 36px; }
  .w-resize { width: 28px; height: 28px; }
  .jargon-i { position: relative; }
  .jargon-i::after { content: ''; position: absolute; inset: -11px; }
}

/* ---------- phones: the reply is not printed twice (MLB QoL, 2026-09-29) ----------
   With an Answer widget on the board, the conversation keeps the request and "Wrong answer?", and points to the Answer
   instead of repeating it above the board. (.said: a reply about the board itself, "what filters are on?", is not in the Answer.) */
/* Every size since the launch check (2026-10-03): on a desktop the same sentence sat in the log and in the Answer under it. */
@media all {
  .dash-page.has-answer .ask-bar .ask-log > .it:last-child:not(.miss):not(.said) { font-size: 0; }
  .dash-page.has-answer .ask-bar .ask-log > .it:last-child:not(.miss):not(.said)::before { content: 'Answered in the Answer box below.'; font-size: .82rem; }
  .dash-page.has-answer .ask-bar .ask-log > .it:last-child:not(.miss):not(.said) > * { font-size: .76rem; }
}

/* ---------- a table wider than its box says so: its edge fades on the side there is more (MLB QoL, 2026-09-29) ----------
   "Side by side" on a phone was cut off after W with nothing to say more columns were there (table.js scrollHint). */
.tbl-wrap.more-right { -webkit-mask-image: linear-gradient(to left, transparent 0, #000 30px); mask-image: linear-gradient(to left, transparent 0, #000 30px); }
.tbl-wrap.more-left { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 30px); mask-image: linear-gradient(to right, transparent 0, #000 30px); }
.tbl-wrap.more-left.more-right { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 30px, #000 calc(100% - 30px), transparent 100%); mask-image: linear-gradient(to right, transparent 0, #000 30px, #000 calc(100% - 30px), transparent 100%); }
@media (max-width: 720px) {
  /* A table as tall as its rows, not a 280 px box with an empty space under a two-row table. */
  .board.cells > .widget:has(.w-body .tbl-wrap):not(:has(svg)) { min-height: 0; }
  .board.cells > .widget:has(.w-body .tbl-wrap):not(:has(svg)) .w-body { flex: none; max-height: 70vh; }
  /* A game page's table is drawn whole (its body does not scroll there): capped at 70vh it ran under the widget's edge and
     the last skaters of a 20-man lineup could not be reached at all (sweep 2026-10-04, NHL game page on a phone). */
  .game-board.board.cells > .widget:has(.w-body .tbl-wrap):not(:has(svg)) .w-body { max-height: none; }
}
.gfx-stage.gfx-blank > .gfx-player { display: none !important; }
/* A stat tile's name wraps instead of ending in "…" ("Time on ice per ga…" on a phone, NHL QoL 2026-09-29; "Goals per ga…",
   "Points (regul…" on an iPad's six tiles a row, sweep 2026-10-04): every width, so the board grows the widget to it. */
.tile .k { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
/* Phones: the graphics maker's things to try wrap, each chip onto as many lines as it needs (launch check 2026-10-03: a
   sideways-scrolling row left "Judge vs Ohtani 2022 to 2025 home runs, OPS and RBI" running off the right edge). */
@media (max-width: 700px) {
  .gfx-ask .gfx-ideas { flex-wrap: wrap; }
  .gfx-ask .gfx-ideas .chip { white-space: normal; text-align: left; max-width: 100%; }
}
.dash-page .ask-bar { scroll-margin-top: calc(var(--header-h, 0px) + 8px); }
@media (pointer: coarse), (max-width: 700px) {
  .gfx-check input[type=checkbox], input[type=checkbox] { width: 24px; height: 24px; }
  .gloss-index a { min-width: 28px; justify-content: center; }
  .tbl td a, .tgroup a, .tgroups a { display: inline-block; padding: 5px 0; min-width: 24px; }
  summary { min-height: 32px; display: flex; align-items: center; }
  .site-header .brand { min-height: 32px; }
}
/* Touch screens: a text box or menu is 40 px tall, as on Pigskin Lab (the header search was 30 px, a thin target). */
@media (pointer: coarse) {
  input[type=text], input[type=email], input[type=password], input[type=search], input[type=number], select { min-height: 40px; }
}
/* The layout tools (Grid, Tidy up, Width, Theme) arrange and dress the board, so they sit with moving and resizing in Edit dashboard: the
   toolbar stays on one row at 1366-1440 px with Paste in it. */
.dash-page:not(.editing) .dash-top > .arrange-only, .dash-page:not(.editing) .dash-top > .dash-width { display: none; }
/* A refusal that is never a dead end (public/js/ask.js missBlock, lib/nearest.js): the reason, what the Lab keeps, and the
   nearest questions as chips that each build a board here, or another Lab's link. */
.ask-log .it.near { display: flex; flex-direction: column; gap: 4px; padding: 4px 0 6px; }
.ask-log .it.near .near-said { color: var(--wrong); }
.ask-log .it.near .near-keeps { color: var(--muted); font-size: .76rem; }
.ask-log .it.near .near-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.ask-log .it.near .near-lead { color: var(--muted); font-size: .76rem; font-weight: 700; }
.ask-log .it.near .near-chip { margin: 0; border-radius: 12px; background: var(--surface-2); color: var(--text); font-size: .76rem; padding: 3px 9px; text-decoration: none; max-width: 100%; overflow-wrap: anywhere; text-align: left; }
.ask-log .it.near .near-chip:hover { border-color: var(--brand); color: var(--text); }
.ask-log .it.near .near-lab { border-color: var(--brand); }
.ask-log .it.near .near-wrong { font-size: .74rem; }
.ask-log:has(.it.near:last-child) { max-height: min(75vh, 560px); }
@media (pointer: coarse) { .ask-log .it.near .near-chip { min-height: 44px; display: inline-flex; align-items: center; } }
/* The sample under a widget's title (lib/sample.js): games counted and the window's real dates, and a small-sample mark in
   words. The season banner says once that a season is still being played. */
.w-sample { display: flex; align-items: baseline; gap: 6px; padding: 2px 12px 0; font-size: .7rem; line-height: 1.3; color: var(--muted); font-variant-numeric: tabular-nums; min-width: 0; }
.w-sample .wsample-n, .sample-line .wsample-n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.wsample .wthin { flex: none; font-style: normal; font-weight: 600; font-size: .7rem; letter-spacing: .02em; color: var(--noise); border: 1px solid currentColor; padding: 0 4px; line-height: 1.35; white-space: nowrap; }
.sample-line { display: flex; align-items: baseline; gap: 8px; font-size: .78rem; color: var(--muted); font-variant-numeric: tabular-nums; margin: 2px 0 6px; }
.season-banner { margin: 0 0 8px; }
.season-banner.early { border-left-color: var(--noise); }
.page-head .season-banner { margin: 10px 0 0; }


/* ---------- touch screens: every control is a 44 x 44 target (lane touch, 2026-10-01; INT-02, INT-07, INT-12) ----------
   Measured at 390 px and on a 1024 px touch tablet (user-research/tools/capture/touch/touchcheck.js): most controls on a
   board were under 44 px with a finger: widget copy and tool buttons 24 px, legend switches 20 px, chips 22 px, "Wrong
   answer?" and the other text buttons 18-20 px, buttons 30 px, sortable table headings 29-41 px, inputs and menus 40 px,
   the header's links 30-37 px. Each keeps its drawn size and gets an invisible hit area at least 44 px each way, centred
   on it (::before; no control here draws with it). Neighbours closer than 44 px overlap and the nearer one takes the tap.
   :where() keeps the position rule weaker than any rule that already places a control (absolute, sticky). Chart marks
   get theirs in charts.js (whole rows and columns, end rows reaching the edges, a nearest-point layer for dots and
   spider points). */
@media (pointer: coarse) {
  :where(.btn, .chip, .linkish, .icon-btn, .beta-pill, .brand, .nav a, .legend button, .wtools button, .w-tools button, .w-copy, .w-dup, .w-grip, .seg button, .mic, .crumbs a, .site-footer a, .footer-feedback, .tip-strip-feedback, .tip-strip-close, .tbl td a, table.stats td a, .tgroup a, .gloss-index a, .tip-sheet .btn, summary) { position: relative; }
  :where(.btn, .chip, .linkish, .icon-btn, .beta-pill, .brand, .nav a, .legend button, .wtools button, .w-tools button, .w-copy, .w-dup, .w-grip, .seg button, .mic, .crumbs a, .site-footer a, .footer-feedback, .tip-strip-feedback, .tip-strip-close, .tbl td a, table.stats td a, .tgroup a, .gloss-index a, .tip-sheet .btn, summary)::before {
    content: ''; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%);
  }
  /* A thin text control above a block drawn after it ("Wrong answer?" over the board, a legend over its chart): its
     target is lifted over that block so its lower half is not lost. */
  :where(.linkish, .legend button, .chip) { z-index: 1; }
  input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=hidden]), select { min-height: 44px; }
  /* Sortable table headings sit edge to edge: each is 44 px tall instead (a dense row, INT-12). */
  .tbl th, table.stats thead th, table th[tabindex] { height: 44px; }
  /* Controls packed side by side, or inside a box that clips them, cannot borrow room around them (a widget's corner
     clips its copy button; the next zoom button's target would cover this one's edge): they are drawn 44 px instead.
     The header's links, the widget bar's tools and the zoom group. */
  .nav a { line-height: 44px; }
  .widget .wbar, .w-head { min-height: 44px; }
  .widget .wtools button, .w-tools button, .w-copy, .w-dup { width: 44px; height: 44px; }
  .seg { height: auto; }
  .seg button { min-width: 44px; min-height: 44px; }
}
/* Chart lines and words are not targets: a grid line or a value printed over a bar took the tap (or the hover) meant
   for the bar under it. The spider's names keep theirs (their full name shows on hover). */
.widget svg line, .chart-box svg line, .widget svg text:not(.radar-label), .chart-box svg text:not(.radar-label) { pointer-events: none; }
/* A tooltip never taller than the screen: a long one scrolls inside itself (INT-04; place() in charts.js keeps it 8 px
   inside every edge). */
.tooltip { max-height: calc(100vh - 16px); max-height: calc(100dvh - 16px); overflow-y: auto; overscroll-behavior: contain; }
/* The tap sheet (a phone's tooltip) is never cut by the browser's bar or a phone's home indicator: it is measured against
   the visible screen (dvh) and keeps the bottom safe area. */
.tip-sheet-panel { max-height: 82dvh; padding-bottom: env(safe-area-inset-bottom, 0px); }

/* ---------- launch check, 2026-10-03 (phone 390, iPad 1024 and 1366 touch, desktop 1440) ---------- */
/* A ranked list longer than its widget ends on a whole row with "N more" pinned under it (charts.js moreCue); a table that
   scrolls down fades at its bottom edge while more is below (moreBelow). */
.chart-box .more-cue { position: sticky; bottom: 0; height: 20px; margin-top: -20px; line-height: 22px; font-size: .72rem; font-weight: 600; color: var(--muted); text-align: center; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--surface) 55%); transition: opacity .15s; }
.chart-box .more-cue.done { opacity: 0; }
.w-body.more-below { -webkit-mask-image: linear-gradient(to top, transparent 0, #000 26px); mask-image: linear-gradient(to top, transparent 0, #000 26px); }
/* Widget titles: up to two lines instead of one cut line, the full title on hover; on touch and under 1100 px the tools
   other than Copy fold behind "⋯" (build.js w-more) and open on a row of their own under the title. */
.w-title { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow-wrap: anywhere; }
.w-tools .w-more { display: none; }
@media (pointer: coarse), (max-width: 1100px) {
  .w-head { flex-wrap: wrap; }
  .w-tools .w-more { display: grid; font-size: 1.05rem; }
  .board.cells .widget:not(.tools-open) .w-tools > :not(.w-copy):not(.w-more) { display: none; }
  .board.cells .widget.tools-open .w-tools { flex: 1 0 100%; justify-content: flex-end; flex-wrap: wrap; order: 3; border-top: 1px solid var(--grid); }
  .board.cells .widget.tools-open .w-tools > * { display: grid; }
  .widget.tools-open .w-more { background: var(--surface-2); }
}
/* The board's title wraps instead of ending in "…" ("Hits: top 10, 2005-06 to 2025-26 (incl. pl…"): a one-row text box that
   grows with its words (build.js fitTitle). */
.dash-top textarea.title-input { resize: none; overflow: hidden; white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.2; height: auto; min-height: 34px; padding-top: 4px; padding-bottom: 4px; font-family: var(--display); max-width: min(100%, 760px); }
.w-note:not([hidden]) { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
/* The graphics maker's motion settings (Numbers, Finish, Speed) wrap and grow on a touch screen: the group was 28 px tall
   around 44 px buttons, so "Pulse leaders", "Flip digits" and "Fast" were cut and covered the labels under them. */
.gfx-motion-opts .seg { height: auto; min-height: 28px; flex-wrap: wrap; max-width: 100%; }
.model-card .seg { height: auto; }
/* Touch screens: the buttons a visitor presses most are a full 44 px tall where they are drawn, not only where they take
   the tap (header Sign in, theme and Menu, Build it, the mic, the toolbar). Chips and inline links keep their look and
   their 44 px invisible hit area (above). */
@media (pointer: coarse) {
  .btn:not(.small), .icon-btn, .mic, .site-header .icon-btn, .dock-close { min-height: 44px; }
  .icon-btn, .mic { min-width: 44px; }
  .site-header .search input { min-height: 44px; }
}
/* Home: Build it stays on the Ask row from 701 px (it wrapped under the box on a desktop). */
@media (min-width: 701px) {
  .home-ask { flex-wrap: nowrap; }
  .home-ask .ask-input { flex: 1 1 0; }
}
/* Phones: the home demo was two screens of mostly empty dots while it typed; the example chips and the Ask box are the start. */
@media (max-width: 600px) { .hero-ad .demo-wrap { display: none; } }
/* The add-widget drawer: kinds in three groups, each with its picture beside its name. */
.add-group { display: flex; flex-direction: column; gap: 6px; }
.add-head { margin: 4px 0 0; font: 700 .72rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.add-list > button { display: flex; align-items: flex-start; gap: 10px; text-align: left; }
.add-icon { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text-2); }
.add-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.drawer-close { min-height: 36px; }
/* The account page's ways in: buttons, not tabs; the Ask wall's on a row of their own under its sentence. */
.acct-card .acct-choices { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.wall-btns { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; color: var(--text); font-weight: 400; }
/* A missing-games note folded to its first sentence; "Details" opens the list (ui.js foldNote). */
details.note-fold { display: inline; }
details.note-fold > summary { display: inline; cursor: pointer; color: var(--link); text-decoration: underline; list-style: none; }
details.note-fold > summary::-webkit-details-marker { display: none; }
details.note-fold[open] > summary { margin-right: 4px; }
details.note-fold > span { display: block; margin-top: 2px; }
/* A link to a page that needs an account, while signed out: a small lock after its name (app.js showAccount). */
a.needs-account::after { content: ''; display: inline-block; width: .62em; height: .72em; margin-left: .3em; vertical-align: -.02em; opacity: .7;
  background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 12'%3E%3Cpath d='M2 5V3.5a3 3 0 016 0V5h1v7H1V5zm1.4 0h3.2V3.5a1.6 1.6 0 00-3.2 0z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 12'%3E%3Cpath d='M2 5V3.5a3 3 0 016 0V5h1v7H1V5zm1.4 0h3.2V3.5a1.6 1.6 0 00-3.2 0z'/%3E%3C/svg%3E") center / contain no-repeat; }
/* A sign-in wall is one card: the footer follows it instead of a screen of empty page (launch check 2026-10-03). */
main:has(> .wrap > .signin-gate:only-child) { min-height: 0; }

/* ---------- arriving with a question: the next step (public/js/ask.js drawChips, 2026-10-06) ----------
   A visitor from a Reddit ad or a shared link lands on a board built from their question. Under the reply, right
   above the board: "Now try" and three of the board's own follow-ups as big one-tap chips, then the box for their own
   question and the free allowance in plain words. The 35 ad visitors of 2026-10-05..06 saw their board and none asked a
   second one: the "Try:" chips were small, shuffled and above the reply, and the allowance a muted line. Pigskin Lab has the
   same rules, word for word (Pigskin Lab views/build.js). */
.dash-page .ask-bar .ask-ideas.ask-next { order: 6; display: flex; flex-direction: column; align-items: stretch; gap: 6px; margin: 2px 0 0; padding: 8px 10px; border: 0; border-left: 3px solid var(--brand); background: var(--surface-2); min-width: 0; }
.ask-next .next-lead { font: 700 .8rem/1 var(--display); text-transform: uppercase; letter-spacing: .06em; color: var(--text); }
.ask-next .next-chips { display: flex; flex-wrap: wrap; gap: 6px 8px; min-width: 0; }
.dash-page .ask-bar .ask-next .chip { margin: 0; min-height: 36px; padding: 6px 14px; display: inline-flex; align-items: center; max-width: 100%; border: 1px solid var(--brand); border-radius: 18px; background: var(--surface); color: var(--text); font: 600 .86rem/1.2 var(--font); text-align: left; overflow-wrap: anywhere; }
@media (hover: hover) { .dash-page .ask-bar .ask-next .chip:hover { background: var(--brand-btn); border-color: var(--brand-btn); color: #fff; } }
.dash-page .ask-bar .ask-next .chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.ask-next .next-own { margin: 0; font-size: .8rem; line-height: 1.4; color: var(--text-2); }
.ask-next .next-own b { color: var(--text); font-weight: 600; }
.dash-page .ask-bar.guided .ask-left { display: none; }
/* (A follow-up brings its reply to the top of a phone's screen, under nothing; the conversation log of the Answer's
   line shows on a computer only: on a phone it pushed the row and the Answer off the screen.) */
.dash-page .ask-bar.guided :is(.ask-msg, .ask-log) { scroll-margin-top: 72px; }
@media (max-width: 700px) { .dash-page .ask-bar.guided .ask-thread { display: none; } }
@media (max-width: 600px) { .dash-page .ask-bar.guided :is(.ask-msg, .ask-log) { scroll-margin-top: 8px; } }
/* (The one question an arrival asked is said in the reply under it: "You:" shows from the second.) */
.dash-page .ask-bar.guided .ask-log > .you:first-child:nth-last-child(2) { display: none; }
@media (pointer: coarse) { .dash-page .ask-bar .ask-next .chip { min-height: 44px; } }
/* (The tenth free question answered: the row offers the free account as buttons a thumb can hit; account.js wallWays. The
   shared sign-in page on Pigskin Lab has "Continue with Google".) */
.ask-next-wall .next-chips .btn { min-height: 40px; display: inline-flex; align-items: center; gap: 6px; }
@media (pointer: coarse) { .ask-next-wall .next-chips .btn { min-height: 44px; } }

/* ---------- phones and iPads: device pass (2026-10-09) ----------
   The same block ends all four sports sites' site.css.
   1. iOS Safari zooms the whole page into any field whose text is under 16 px, and every field here was
      13.4 px (the Ask box, the search box, every select in the dashboard maker). On a touch screen every
      field is 16 px. The board title is left out: it is 20 px already, and on Pigskin Lab it is an input, so
      this rule (0,4,1) would beat its font (0,2,0) and shrink the board's visible heading to 16 px.
   2. Buttons and header icons were drawn 30 px tall on touch on Pigskin Lab, and small buttons 26 px on all four
      (each already had an invisible 44 px hit area): every .btn and .icon-btn is drawn 44 px tall on touch, small
      ones included. That overrides the siblings' older .btn:not(.small) rule; whether small buttons stay 44 px is
      Mason's call (DEVICES, Open). Two older, more specific rules keep their own size, with their 44 px hit area:
      an empty board's preset buttons on a phone (32 px, .board-empty .presets .btn) and, on the siblings, the
      graphics maker's subject tools (32 x 32, .gfx-subj-tools .btn.small). Header icons and the mic are 44 px wide
      as well (34 x 44 and 32 x 44 on Pigskin Lab), as the siblings already drew them.
   3. A segmented control (Regular / Playoffs / All on the team and game pages) was 340 px wide inside a
      320 px phone and pushed the page sideways; it wraps instead. */
@media (pointer: coarse) {
  input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not(.title-input), select, textarea { font-size: 16px; }
  .btn, .icon-btn { min-height: 44px; }
  .icon-btn, .mic { min-width: 44px; }
  .seg { height: auto; }
  .seg button { min-height: 44px; }
}
.controls-row .seg { flex-wrap: wrap; height: auto; max-width: 100%; }
.controls-row .seg button { min-height: 28px; }
@media (pointer: coarse) { .controls-row .seg button { min-height: 44px; } }
/* A 320 px phone: a primary button in a page head ("Open this breakdown in the dashboard maker ›" on a game page) was
   344 px of unbroken text, and a model card's select (16 px on touch) pushed its heading past the edge. Both wrap
   inside the page instead. The wrap rule is outside any media query, so the two after it give a small page-head button
   its 26 px back on a computer and every page-head button its 44 px on touch (without them it beat the touch rule
   above, 0,2,0 over 0,1,0, and drew them 30 px). */
.page-head .btn { white-space: normal; height: auto; min-height: 30px; max-width: 100%; text-align: left; }
.page-head .btn.small { min-height: 26px; }
@media (pointer: coarse) { .page-head .btn, .page-head .btn.small { min-height: 44px; } }
.section-head { flex-wrap: wrap; }
.section-head > span { min-width: 0; max-width: 100%; }
.section-head select { max-width: 100%; }
/* Touch, found by the tap check after the review fixes: the tip bar (on every page until it is closed) and the board
   title. The bar's "Leave a tip" link was 25 px tall with no hit area on all four, and on Pigskin Lab "Beta: send
   feedback" was 19 px and the close 18 x 18 (the siblings already gave those two theirs). The siblings' board title is a
   textarea, which the touch lane's input rule never reached: 34 px tall, where Pigskin Lab's input is 44. fitTitle sets
   its height from scrollHeight, so 9 px top and bottom make one line exactly 44 px with the words centred. */
@media (pointer: coarse) {
  :where(.tip-strip-link, .tip-strip-feedback, .tip-strip-close) { position: relative; }
  :where(.tip-strip-link, .tip-strip-feedback, .tip-strip-close)::before { content: ''; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%); }
  .dash-top textarea.title-input { min-height: 44px; padding-top: 9px; padding-bottom: 9px; }
}

/* The working panel (ui.js busy): shown when something takes longer than a second. In the middle of the screen, large
   (ported from Pigskin Lab, 2026-10-26). `div.busy` so it never meets the Ask form's own `.busy` state. */
div.busy { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 120; display: flex; align-items: center; gap: 16px;
  max-width: calc(100vw - 32px); padding: 22px 30px; background: var(--surface); color: var(--text); border: 3px solid var(--frame);
  box-shadow: 0 12px 48px rgba(0, 0, 0, .35); font-weight: 700; font-size: 1.25rem; pointer-events: none; }
div.busy .busy-spin { width: 34px; height: 34px; border-width: 4px; }
.busy-spin { flex: none; width: 18px; height: 18px; border-radius: 50%; border: 3px solid var(--muted); border-top-color: var(--sel); animation: busy-spin .8s linear infinite; }
@keyframes busy-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .busy-spin { animation: busy-pulse 1.6s ease-in-out infinite !important; } }
@keyframes busy-pulse { 50% { opacity: .35; } }

/* Front-page trust line, owner 2026-10-26: Reddit readers called a game graphic "AI slop". Nothing on the site is generated by
   AI, so the home page says so where people look, not in the footer. */
.no-ai { margin: 14px 0 0; padding: 2px 0 2px 10px; border-left: 3px solid var(--brand); font-size: .85rem; line-height: 1.45; color: var(--text); max-width: 46em; }
.no-ai b { font-weight: 700; }

/* Comparison pages (lib/compare.js): written by the server, fetched and shown by the app. */
.compare-page section { margin: 22px 0; }
.compare-page h2 { font-family: var(--display); margin: 0 0 8px; font-size: 1.2rem; }
.cmp-table { border-collapse: collapse; width: 100%; max-width: 640px; font-variant-numeric: tabular-nums; font-size: .95rem; border: 1px solid var(--border); background: var(--surface); }
.cmp-table th, .cmp-table td { padding: 6px 10px; border-bottom: 1px solid var(--grid); text-align: right; }
.cmp-table thead th { background: var(--surface-2); }
.cmp-table tbody th { text-align: left; font-weight: 500; color: var(--text-2); }
.cmp-table td.lead { font-weight: 700; background: var(--row-hover); }
.cmp-links { padding-left: 1.2em; line-height: 1.7; }
.cmp-list { columns: 2 280px; }
.compare-page .crumbs { font-size: .85rem; color: var(--muted); margin-bottom: 6px; }
.compare-page .crumbs a { color: var(--muted); }
