/* Hand-built, shadcn-inspired styling — NO library, no Tailwind/Radix/React.
   Just the design tokens + component treatments reproduced in plain CSS, so the
   look matches shadcn/ui while staying within the project's zero-dependency rule.
   System font only (no external font request). */

:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --card: 0 0% 100%;
  --muted: 210 40% 96.1%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --border: 214.3 31.8% 91.4%;
  --input: 214.3 31.8% 91.4%;
  --primary: 222.2 47.4% 11.2%;
  --primary-foreground: 210 40% 98%;
  --accent: 210 40% 96.1%;
  --ring: 222.2 84% 4.9%;
  --success: 142 71% 45%;
  --success-bg: 138 76% 96%;
  /* Rel.% gradient sat/light (bg + fg) — theme-aware, forced light in print */
  --rel-sb: 76%; --rel-lb: 96%; --rel-sf: 71%; --rel-lf: 45%;
  --radius: 0.5rem;
}

/* dark mode — shadcn dark token set; every component reads these vars so it
   recolors automatically (national chart colors stay fixed for recognizability). */
html.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  --card: 222.2 47% 7%;
  --muted: 217.2 32.6% 17.5%;
  --muted-foreground: 215 20.2% 65.1%;
  --border: 217.2 32.6% 22%;
  --input: 217.2 32.6% 24%;
  --primary: 210 40% 98%;
  --primary-foreground: 222.2 47.4% 11.2%;
  --accent: 217.2 32.6% 17.5%;
  --ring: 212.7 26.8% 83.9%;
  --success: 142 64% 52%;
  --success-bg: 142 40% 16%;
  --rel-sb: 40%; --rel-lb: 16%; --rel-sf: 64%; --rel-lf: 52%;
}

* { box-sizing: border-box; }
/* overflow-anchor:none — rebuilding the tall race table above the compare panel made the
   browser's scroll-anchoring shift the page AFTER our scroll restore (the remove-race jump). */
html { -webkit-text-size-adjust: 100%; overflow-anchor: none; }
body {
  margin: 0;
  font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: hsl(var(--foreground));
  background: hsl(var(--background));
  -webkit-font-smoothing: antialiased;
}
[hidden] { display: none !important; }

/* slim, themed scrollbars (replaces the chunky native ones) */
* { scrollbar-width: thin; scrollbar-color: hsl(var(--border)) transparent; }
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: hsl(var(--border)); border-radius: 999px;
  border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: hsl(var(--muted-foreground) / 0.55); background-clip: padding-box; }

/* ---- top bar ---- */
.topbar {
  display: flex; align-items: center; gap: 0.75rem;
  height: 56px; padding: 0 1rem;
  border-bottom: 1px solid hsl(var(--border));
  background: hsl(var(--background));
  position: sticky; top: 0; z-index: 30;
}
.brand-logo { height: 28px; width: auto; display: block; }
.topbar h1 { margin: 0; font-size: 0.95rem; font-weight: 600; letter-spacing: -0.01em; white-space: nowrap; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid hsl(var(--input)); background: hsl(var(--background));
  border-radius: var(--radius); height: 2rem; width: 2rem; min-width: 2rem; flex-shrink: 0; padding: 0; cursor: pointer;
  font-size: 0.95rem; color: hsl(var(--foreground)); line-height: 1;
}
.icon-btn:hover { background: hsl(var(--muted)); }
/* filter show/hide toggle (far-left of the topbar, above the sidebar column) */
.filter-toggle svg { width: 1.05rem; height: 1.05rem; display: block; }
.filter-toggle[aria-pressed="true"] { border-color: hsl(var(--primary)); color: hsl(var(--primary)); }
.btn-toggle { display: inline-flex; align-items: center; gap: 0.35rem; height: 2rem; padding: 0 0.65rem;
  border: 1px solid hsl(var(--input)); background: hsl(var(--background)); color: hsl(var(--foreground));
  border-radius: var(--radius); cursor: pointer; font-size: 0.82rem; font-weight: 500; white-space: nowrap; }
.btn-toggle:hover { background: hsl(var(--muted)); }
.link-btn {
  border: 0; background: none; color: hsl(var(--muted-foreground));
  cursor: pointer; font-size: 0.78rem; text-decoration: underline; padding: 0;
}
.link-btn:hover { color: hsl(var(--foreground)); }

/* ---- view nav (pages) ---- */
.viewnav { margin-left: auto; display: inline-flex; gap: 0.25rem;
  padding: 0.25rem; background: hsl(var(--muted)); border-radius: var(--radius); }
.viewnav button {
  border: 0; background: transparent; cursor: pointer;
  padding: 0.35rem 0.75rem; border-radius: calc(var(--radius) - 0.2rem);
  font-size: 0.8rem; font-weight: 500; color: hsl(var(--muted-foreground));
}
.viewnav button:hover { color: hsl(var(--foreground)); }
.viewnav button.on {
  background: hsl(var(--background)); color: hsl(var(--foreground));
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.08);
}

/* ---- shell: sidebar + content ---- */
.shell { display: grid; grid-template-columns: 268px 1fr; align-items: start; }
/* Collapse to a SINGLE column. (Not `0 1fr`: with the sidebar display:none'd,
   the main content auto-flows into the first column — at 0 width it would hide
   the whole body. One `1fr` track keeps the content full-width.) */
.shell.collapsed { grid-template-columns: 1fr; }
.sidebar {
  border-right: 1px solid hsl(var(--border));
  background: hsl(var(--background));
  position: sticky; top: 56px; height: calc(100vh - 56px);
  overflow-y: auto; overflow-x: hidden;
}
.shell.collapsed .sidebar { display: none; }
.sidebar-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.85rem 1rem 0.5rem; font-size: 0.8rem; font-weight: 600;
  color: hsl(var(--muted-foreground)); text-transform: uppercase; letter-spacing: 0.04em;
  position: sticky; top: 0; z-index: 5; background: hsl(var(--background));
  border-bottom: 1px solid hsl(var(--border));
}

/* active-filter chips: one removable chip per selected value, at the top of
   the filter bar — an at-a-glance view of what's applied + quick removal. */
.chips { display: flex; flex-wrap: wrap; gap: 0.3rem; padding: 0.5rem 0.6rem 0; }
.chips:empty { padding: 0; }
.chip {
  display: inline-flex; align-items: center; gap: 0.3rem;
  background: hsl(var(--muted)); color: hsl(var(--foreground));
  border: 1px solid hsl(var(--border)); border-radius: 999px;
  padding: 0.1rem 0.2rem 0.1rem 0.5rem; font-size: 0.72rem; max-width: 100%;
}
.chip .chip-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chip .chip-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1rem; height: 1rem; border: 0; cursor: pointer; border-radius: 999px;
  background: transparent; color: hsl(var(--muted-foreground)); font-size: 0.85rem; line-height: 1;
}
.chip .chip-x:hover { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); }

/* expand/collapse-all groups control */
.groups-toggle { font-size: 0.72rem; }

/* ---- filter groups (native collapsible <details>) ---- */
.filters { padding: 0 0.5rem 2rem; }
.fgroup { border-bottom: 1px solid hsl(var(--border)); }
.fgroup > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.55rem 0.6rem; font-size: 0.82rem; font-weight: 500;
}
.fgroup > summary::-webkit-details-marker { display: none; }
.fgroup > summary:hover { background: hsl(var(--muted) / 0.6); border-radius: calc(var(--radius) - 0.2rem); }
.fgroup .count {
  font-size: 0.7rem; font-weight: 600; color: hsl(var(--primary-foreground));
  background: hsl(var(--primary)); border-radius: 999px; padding: 0.05rem 0.4rem; min-width: 1.1rem; text-align: center;
}
.fgroup .count.zero { display: none; }
.optlist { max-height: 220px; overflow-y: auto; padding: 0.15rem 0.6rem 0.6rem; }
.opt { display: flex; align-items: center; gap: 0.45rem; padding: 0.18rem 0.1rem;
  font-size: 0.82rem; cursor: pointer; }
.opt:hover { color: hsl(var(--foreground)); }
.opt input { margin: 0; }
.opt input[type=checkbox] {
  appearance: none; -webkit-appearance: none; flex: none; position: relative; cursor: pointer;
  width: 0.95rem; height: 0.95rem; border: 1px solid hsl(var(--input));
  border-radius: 4px; background: hsl(var(--background));
}
.opt input[type=checkbox]:checked { background: hsl(var(--primary)); border-color: hsl(var(--primary)); }
.opt input[type=checkbox]:checked::after { content: '✓'; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; font-size: 0.68rem; color: hsl(var(--primary-foreground)); }
.opt input[type=checkbox]:focus-visible { outline: none; box-shadow: 0 0 0 2px hsl(var(--ring) / 0.4); }
/* dark mode: the CHECKED box used the near-white --primary token, which read as a
   cheap flat white square. Give it a crisp accent blue with a white tick.
   The unchecked box already looks right, so it's left alone. */
html.dark .opt input[type=checkbox]:checked {
  background: hsl(213 94% 60%); border-color: hsl(213 94% 60%);
}
html.dark .opt input[type=checkbox]:checked::after { color: #fff; }
.opt .flag { width: 0.95rem; height: 0.95rem; object-fit: cover; border-radius: 50%;
  box-shadow: 0 0 0 1px hsl(var(--border)); }

/* filter group open/close caret + per-section actions + search */
.fgroup > summary { justify-content: flex-start; gap: 0.4rem; }
.fgroup > summary::before { content: ''; flex: none; width: 0; height: 0;
  border-left: 6px solid hsl(var(--muted-foreground));
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform .15s; }
.fgroup[open] > summary::before { transform: rotate(90deg); }
.fgroup .count { margin-left: auto; }
.fgrp-actions { display: flex; justify-content: flex-end; gap: 0.6rem; padding: 0.1rem 0.6rem 0.3rem 1.15rem; }
.tbl td.nowrap { white-space: nowrap; }
.mini-link { border: 0; background: none; color: hsl(var(--muted-foreground)); cursor: pointer;
  font-size: 0.72rem; text-decoration: underline; padding: 0; }
.mini-link:hover { color: hsl(var(--foreground)); }
.fsearch { width: calc(100% - 1.2rem); margin: 0 0.6rem 0.35rem; height: 1.9rem; padding: 0 0.5rem;
  font-size: 0.8rem; color: hsl(var(--foreground)); background: hsl(var(--background));
  border: 1px solid hsl(var(--input)); border-radius: calc(var(--radius) - 0.2rem); }

/* custom hover tooltip */
/* Above the lightbox (z-index 60) and the back-to-top control, because a tooltip has to be visible
   over whatever it describes. At 50 the marker tips were drawn and then covered inside the overlay:
   present in the DOM, invisible on screen. */
.ctip { position: absolute; z-index: 70; pointer-events: none;
  background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); font-size: 0.75rem;
  padding: 0.25rem 0.5rem; border-radius: calc(var(--radius) - 0.2rem);
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.18); white-space: normal;
  max-width: min(340px, calc(100vw - 16px)); line-height: 1.4;
  display: inline-flex; align-items: center; }
.ctip-flag { width: 0.85rem; height: 0.85rem; object-fit: cover; margin-left: 0.4rem; vertical-align: middle; border-radius: 50%; }

/* on-page dropdowns (progression / full-regatta) */
.pgbar { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0 0 1rem; }
.pgsel { height: 2.4rem; padding: 0 0.6rem; font-size: 0.875rem; color: hsl(var(--foreground));
  background: hsl(var(--background)); border: 1px solid hsl(var(--input)); border-radius: var(--radius); min-width: 12rem; }
.medal-after { margin-left: 0.35rem; }

/* searchable dropdown */
.ssel { position: relative; display: inline-block; }
/* persistent dropdown caret — stays visible even when a value is selected */
.ssel::after { content: ''; position: absolute; right: 0.7rem; top: 50%; transform: translateY(-50%);
  pointer-events: none; width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 6px solid hsl(var(--muted-foreground)); }
.ssel-input { height: 2.4rem; padding: 0 1.7rem 0 0.6rem; font-size: 0.875rem; min-width: 15rem;
  max-width: 100%; color: hsl(var(--foreground)); background: hsl(var(--background));
  border: 1px solid hsl(var(--input)); border-radius: var(--radius); }
/* wide variant — long labels ("2026 World Rowing Under 23 Championships") read in
   full instead of truncating; max-width above keeps it inside narrow screens. */
.ssel--wide { max-width: 100%; }
.ssel--wide .ssel-input { min-width: 21rem; }
.ssel-input:focus-visible { outline: none; border-color: hsl(var(--ring));
  box-shadow: 0 0 0 2px hsl(var(--background)), 0 0 0 4px hsl(var(--ring) / 0.35); }
.ssel-list { display: none; position: absolute; z-index: 40; top: 2.6rem; left: 0; right: 0;
  max-height: 260px; overflow-y: auto; background: hsl(var(--card));
  border: 1px solid hsl(var(--border)); border-radius: var(--radius); box-shadow: 0 8px 24px rgb(0 0 0 / 0.14); }
.ssel-list.open { display: block; }
.ssel-item { padding: 0.4rem 0.6rem; font-size: 0.85rem; cursor: pointer; }
.ssel-item:hover { background: hsl(var(--muted)); }

main.content { padding: 1.5rem; max-width: 1180px; }
h2 { font-size: 1rem; font-weight: 600; letter-spacing: -0.01em; margin: 1.25rem 0 0.75rem; }
h2:first-child { margin-top: 0; }
.subhead { color: hsl(var(--muted-foreground)); font-size: 0.85rem; margin: -0.4rem 0 0.85rem; }
/* "USA Only" race-list toggle above the race table */
.allraces-banner { margin: 0 0 0.9rem; }
/* floating jump-to-top */
.totop { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 60; display: none;
  align-items: center; gap: 0.3rem; padding: 0.45rem 0.75rem; font-size: 0.78rem; font-weight: 500;
  cursor: pointer; border: 1px solid hsl(var(--border)); border-radius: 999px;
  background: hsl(var(--card)); color: hsl(var(--foreground)); box-shadow: 0 4px 14px rgb(0 0 0 / 0.2); }
.totop.show { display: inline-flex; }
.totop:hover { background: hsl(var(--muted)); }
.muted { color: hsl(var(--muted-foreground)); font-size: 0.85rem; }

/* ---- collapsible content sections ---- */
.sect { margin-top: 1.25rem; }
.sect > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 0.45rem;
  font-size: 1rem; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 0.75rem;
}
.sect > summary::-webkit-details-marker { display: none; }
.sect > summary::before {
  content: ''; flex: none; width: 0; height: 0;
  border-left: 7px solid hsl(var(--muted-foreground));
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  transition: transform .15s;
}
.sect[open] > summary::before { transform: rotate(90deg); }

/* ---- race summary header ---- */
.summary {
  background: hsl(var(--card)); border: 1px solid hsl(var(--border));
  border-radius: var(--radius); padding: 0.9rem 1.1rem;
  margin: 1.25rem 0 0;     /* same gap as .sect, so all sections are evenly spaced (no divider line) */
}
.summary .title { font-size: 1.02rem; font-weight: 600; letter-spacing: -0.01em; }
.summary .meta { color: hsl(var(--muted-foreground)); font-size: 0.85rem; margin-top: 0.15rem; }
.summary .usa { margin-top: 0.6rem; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.usa-chip {
  display: inline-flex; align-items: center; gap: 0.4rem;
  background: hsl(var(--muted)); border-radius: 999px; padding: 0.2rem 0.6rem; font-size: 0.8rem;
}

/* ---- tables ---- */
.tbl {
  width: 100%; border-collapse: separate; border-spacing: 0;
  background: hsl(var(--card));
  border: 1px solid hsl(var(--border)); border-radius: var(--radius);
  overflow: hidden; font-size: 0.875rem;
}
.tbl th {
  text-align: left; font-weight: 500; font-size: 0.8rem;
  color: hsl(var(--muted-foreground));
  padding: 0.6rem 0.75rem; height: 2.75rem;
  background: hsl(var(--background));
  border-bottom: 1px solid hsl(var(--border));
  user-select: none; white-space: nowrap;
}
.tbl th.sortable { cursor: pointer; }
.tbl th.sortable:hover { color: hsl(var(--foreground)); }
.tbl th .arrow { color: hsl(var(--muted-foreground)); margin-left: 0.25rem; opacity: 0.45; font-size: 0.7rem; }
.tbl th.sorted .arrow { opacity: 1; color: hsl(var(--foreground)); }
.info {
  margin-left: 0.3rem; font-size: 0.85rem; cursor: default;
  color: hsl(var(--muted-foreground)); vertical-align: middle;
}
/* A note under the chart about values that WERE recorded but cannot be right. Sits below the
   caption chips, quiet enough not to compete with the chart and legible enough to be read. */
.datanote { margin-top: 0.35rem; font-size: 0.8rem; line-height: 1.4; }

/* A blank that has a REASON behind it. The dotted underline is the affordance: without it the
   tooltip is undiscoverable and a coach has no way to learn that this particular dash is
   explained while the ones around it are not. Theme vars only, so it follows dark mode. */
.missing { text-decoration: underline dotted hsl(var(--muted-foreground)); cursor: help; }
.tbl td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid hsl(var(--border));
  font-variant-numeric: tabular-nums;
}
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr.rowlink { cursor: pointer; transition: background .12s; }
.tbl tbody tr.rowlink:hover { background: hsl(var(--muted) / 0.6); }
.tbl td.good {
  color: hsl(var(--success)); background: hsl(var(--success-bg)); font-weight: 600;
}
/* Rel.% gradient cell: carries only the hue (--relh); sat/light come from theme vars
   so it adapts to dark mode AND prints light (no baked-in inline dark colors). */
.tbl td.relcell {
  background: hsl(var(--relh) var(--rel-sb) var(--rel-lb));
  color: hsl(var(--relh) var(--rel-sf) var(--rel-lf)); font-weight: 600;
}
/* USA-vs-field (T2): many columns — tighten padding/size so it fits with no h-scroll */
.tbl.t2 { font-size: 0.8rem; }
.tbl.t2 th, .tbl.t2 td { padding: 0.45rem 0.4rem; }
.tbl.t2 th { font-size: 0.72rem; height: auto; }
.cc { cursor: default; border-bottom: 1px dotted hsl(var(--muted-foreground)); }
.medal { margin-right: 0.3rem; }
/* page-6 thick section dividers + day columns; progression selected row + current round */
.tbl th.divider, .tbl td.divider { border-left: 2px solid hsl(var(--muted-foreground) / 0.5); }
/* The pinned Field-average row is a summary, not a crew, so it is separated from the crews above it
   rather than emphasised: bolding would say "important" and a tint would collide with the green
   performance shading that already carries meaning in these cells. Same 2px muted line as the
   column divider beside it, turned horizontal, so the table speaks one visual language. */
.tbl tr.fieldavg td { border-top: 2px solid hsl(var(--muted-foreground) / 0.5); }
.tbl td.daycol { color: hsl(var(--muted-foreground)); font-size: 0.82rem; }
.tbl td.col-here { background: hsl(var(--muted) / 0.7); font-weight: 600; }
.tbl tbody tr.selrow td { background: hsl(var(--primary) / 0.14); font-weight: 600; }
.tbl tbody tr.selrow:hover td { background: hsl(var(--primary) / 0.2); }
.tbl tbody tr.selrow td:first-child { box-shadow: inset 3px 0 0 hsl(var(--primary)); }

.sw { display: inline-block; width: 0.7rem; height: 0.7rem; border-radius: 3px;
  margin-right: 0.45rem; vertical-align: middle; }
.flag-sm { width: 0.95rem; height: 0.95rem; object-fit: cover; border-radius: 50%;
  margin-right: 0.45rem; vertical-align: middle; box-shadow: 0 0 0 1px hsl(var(--border)); }
.flag-after { width: 0.95rem; height: 0.95rem; object-fit: cover; border-radius: 50%;
  margin-left: 0.45rem; vertical-align: middle; box-shadow: 0 0 0 1px hsl(var(--border)); }

/* Compare: inline panel under the race table + the per-row "Compare" checkbox */
.selection:not(:empty) { margin: 1.5rem 0 0; }   /* one host for single-race + compare; spacing only, no divider */
.cmp-keyx { display: inline-flex; align-items: center; justify-content: center; width: 1rem; height: 1rem;
  margin-left: 0.2rem; border: none; cursor: pointer; border-radius: 999px; background: transparent;
  color: hsl(var(--muted-foreground)); font-size: 0.8rem; line-height: 1; }
.cmp-keyx:hover { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); }

/* Compare: per-race mini-summary inside the card (regatta title · meta · USA · ✕), legend rows, country filter */
.cmp-race { margin-top: 0.75rem; }
.cmp-race-head { display: flex; align-items: center; gap: 0.5rem; }   /* ✕ aligned with the title */
.cmp-race-title { font-weight: 600; font-size: 0.92rem; }
.cmp-race-meta { padding-left: 1.5rem; }                 /* = ✕ width (1rem) + head gap (0.5rem): indent under title */
/* each race's legend heading doubles as a show/hide EYE toggle; hidden race stays listed */
.cmp-racetoggle { cursor: pointer; border: 1px solid hsl(var(--border)); background: hsl(var(--muted));
  color: hsl(var(--foreground)); font-weight: 600; font-size: 0.8rem; border-radius: 999px;
  padding: 0.1rem 0.5rem; margin-right: 0.3rem; display: inline-flex; align-items: center; gap: 0.3rem; }
.cmp-racetoggle:hover { border-color: hsl(var(--primary)); }
.cmp-racetoggle.off { opacity: 0.7; }            /* still clearly clickable to restore */
.cmp-eye { display: inline-flex; align-items: center; }
.cmp-leg-race.off .leg { opacity: 0.4; }         /* hidden race: boats greyed but still shown */
/* greyed (unavailable) chart tab — e.g. Gap to USA without a single USA boat; ⓘ stays active */
.tab.disabled { color: hsl(var(--muted-foreground)); cursor: default; display: inline-flex; align-items: center; gap: 0.15rem; }
.tab.disabled:hover { color: hsl(var(--muted-foreground)); }
/* legend grouped one race per line, headed by the race label (not A/B) */
.cmp-leg-race { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.5rem; flex-basis: 100%; }
.cmp-leg-racelabel { font-weight: 600; font-size: 0.8rem; margin-right: 0.3rem; }
/* compare legend footer: reset/show-all buttons next to the hint, right-aligned */
.leg-footer { margin-left: auto; display: inline-flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.legend .leg-footer .hint { margin-left: 0; }
.cmp-racelabel { font-weight: 500; }
/* graph caption rows: a title then one line each, used by distance-to-pace and top speed.
   .cap-row is full-width so a row starts on its own line instead of flowing on after the
   previous one; it is NOT compare-only, which is why it lost its cmp- prefix. */
/* No margin of its own: the caption's row gap is the ONE thing that sets the distance between its
   lines. This carried margin-top: 0.2rem, which added to that gap, so the compare panel's lines sat
   further apart than the single-race panel's and further apart than the space above them. */
.legend.caption .cap-title { flex-basis: 100%; font-weight: 600; }
.cap-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.5rem; flex-basis: 100%; }
/* Row gap only, so the horizontal gap between chips on one line keeps the legend's value. 0.2rem was
   chosen by eye rather than derived: it inherited the legend's 0.9rem, which applies to both axes,
   and matching it to the 0.5rem above the block still read too wide on screen. It governs the whole
   caption: the two stat lines, the missing-data chips and the negative-speed note. */
.legend.caption { row-gap: 0.2rem; }
.cmp-ccfilter { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; margin: 0.75rem 0 0; }
.cmp-ccbtn { cursor: pointer; border: 1px solid hsl(var(--border)); background: hsl(var(--card));
  border-radius: 999px; padding: 0.15rem 0.55rem; font-size: 0.78rem; color: hsl(var(--foreground)); }
.cmp-ccbtn:hover { background: hsl(var(--muted)); }
.cmp-ccbtn.on { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); border-color: hsl(var(--primary)); }

/* ---- tabs (shadcn segmented control) ---- */
.tabs {
  display: inline-flex; gap: 0.25rem; margin: 1.25rem 0 0.5rem;
  padding: 0.25rem; background: hsl(var(--muted)); border-radius: var(--radius);
  flex-wrap: wrap;
}
.tab {
  border: 0; background: transparent; cursor: pointer;
  padding: 0.35rem 0.8rem; border-radius: calc(var(--radius) - 0.2rem);
  font-size: 0.8rem; font-weight: 500; color: hsl(var(--muted-foreground));
  transition: background .12s, color .12s;
}
.tab:hover { color: hsl(var(--foreground)); }
.tab.on {
  background: hsl(var(--background)); color: hsl(var(--foreground));
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.08);
}

.legend { display: flex; flex-wrap: wrap; align-items: center; gap: 0.9rem; margin: 0.5rem 0;
  font-size: 0.82rem; color: hsl(var(--muted-foreground)); }
.leg { display: inline-flex; align-items: center; gap: 0.35rem; cursor: pointer;
  border-radius: calc(var(--radius) - 0.2rem); padding: 0.1rem 0.25rem; transition: opacity .12s, background .12s; }
.leg:hover { background: hsl(var(--muted) / 0.6); }
.leg.dim { opacity: 0.4; }
/* per-boat color picker (the legend swatch) + line-style sample */
.swpick { width: 14px; height: 14px; padding: 0; border: 1px solid hsl(var(--border)); border-radius: 3px;
  background: none; cursor: pointer; -webkit-appearance: none; appearance: none; }
.swpick::-webkit-color-swatch-wrapper { padding: 0; }
.swpick::-webkit-color-swatch { border: none; border-radius: 2px; }
.swpick::-moz-color-swatch { border: none; border-radius: 2px; }
.legend .hint { cursor: default; margin-left: auto; font-size: 0.75rem; opacity: 0.8; }
.legend .hint:hover { background: none; }

/* ---- chart toolbar + interactions ---- */
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin: 0.25rem 0 0.5rem; }
.toolbtn {
  display: inline-flex; align-items: center; gap: 0.35rem;
  border: 1px solid hsl(var(--input)); background: hsl(var(--background));
  color: hsl(var(--foreground)); border-radius: calc(var(--radius) - 0.2rem);
  padding: 0.3rem 0.6rem; font-size: 0.78rem; font-weight: 500; cursor: pointer;
}
.toolbtn:hover { background: hsl(var(--muted)); }
.toolbtn input { accent-color: hsl(var(--primary)); margin: 0; }
/* toggle switch (Top speed / Lead change) */
.switch { display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer;
  font-size: 0.78rem; font-weight: 500; color: hsl(var(--foreground)); user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track { position: relative; flex: none; width: 30px; height: 17px; border-radius: 9px;
  background: hsl(var(--muted-foreground) / 0.4); transition: background .15s; }
.switch-track::after { content: ''; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgb(0 0 0 / 0.3); transition: transform .15s; }
.switch input:checked + .switch-track { background: hsl(var(--success)); }
.switch input:checked + .switch-track::after { transform: translateX(13px); }
.switch input:focus-visible + .switch-track { box-shadow: 0 0 0 2px hsl(var(--ring) / 0.5); }
/* Reset colors + Reset zoom sit at the RIGHT edge; .rightgroup grabs the slack so
   it and every button after it (Reset zoom) float right. */
.toolbtn.rightgroup { margin-left: auto; }
/* The right-hand buttons of the single-race toolbar, as ONE item. The auto margin above absorbs the
   free space but does not keep a button's followers beside it, so when the toolbar wrapped, Expand
   was stranded on a line above the two resets. A group wraps as a unit. The compare panel keeps the
   single-button form, because its resets live in the legend footer and Expand is alone there. */
.toolgroup { display: flex; align-items: center; gap: 0.4rem; margin-left: auto; }
.zoomsel { fill: hsl(var(--ring) / 0.14); stroke: hsl(var(--ring) / 0.45); stroke-dasharray: 3 2; }
.chart { touch-action: pan-y; }

/* ---- responsive table wrapper (horizontal scroll on narrow screens) ---- */
.tblwrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ---- chart card ---- */
.chart-wrap {
  background: hsl(var(--card)); border: 1px solid hsl(var(--border));
  border-radius: var(--radius); padding: 0.75rem;
}
.chart-title { font-size: 13px; font-weight: 600; fill: hsl(var(--foreground)); }
.chart-axis { font-size: 11px; fill: hsl(var(--muted-foreground)); }
.tick { font-size: 10px; fill: hsl(var(--muted-foreground)); }
.grid { stroke: hsl(var(--border)); stroke-width: 1; }
.vgrid { stroke: hsl(var(--border)); stroke-width: 1; stroke-dasharray: 2 4; }
/* stroke + dash come inline per marker (boat color + per-type dash); these are fallbacks */
.marker { stroke: hsl(var(--muted-foreground)); stroke-width: 1.5; stroke-dasharray: 4 3; }
.marker-label { font-size: 10px; fill: hsl(var(--muted-foreground)); }
.marker-glyph { font-size: 13px; font-weight: 600; }
.hover-x { stroke: hsl(var(--border)); stroke-width: 1; }

/* ---- tooltip (shadcn popover, dark) ---- */
.tip {
  position: absolute; pointer-events: none;
  background: hsl(var(--primary)); color: hsl(var(--primary-foreground));
  font-size: 12px; padding: 0.45rem 0.6rem; border-radius: calc(var(--radius) - 0.1rem);
  line-height: 1.5; white-space: nowrap; box-shadow: 0 4px 12px rgb(0 0 0 / 0.18);
}
.tip .sw { width: 0.6rem; height: 0.6rem; }

.err { color: hsl(0 72% 45%); background: hsl(0 86% 97%);
  border: 1px solid hsl(0 80% 90%); padding: 1rem; border-radius: var(--radius); }
.spinner { display: inline-block; width: 1rem; height: 1rem; vertical-align: middle;
  border: 2px solid hsl(var(--border)); border-top-color: hsl(var(--primary));
  border-radius: 999px; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- login page ---- */
.login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 1.5rem; }
.login-card {
  width: 100%; max-width: 360px; display: flex; flex-direction: column; gap: 0.85rem;
  background: hsl(var(--card)); border: 1px solid hsl(var(--border));
  border-radius: var(--radius); padding: 1.75rem; box-shadow: 0 8px 30px rgb(0 0 0 / 0.08);
}
.login-card .brand-logo { height: 34px; width: auto; align-self: flex-start; }
.login-card h1 { margin: 0; font-size: 1.05rem; font-weight: 600; letter-spacing: -0.01em; }
.login-card .muted { margin: -0.4rem 0 0.2rem; }
.login-card label { display: flex; flex-direction: column; gap: 0.3rem;
  font-size: 0.8rem; font-weight: 500; color: hsl(var(--muted-foreground)); }
.login-card input {
  height: 2.4rem; padding: 0 0.75rem; font-size: 0.9rem;
  color: hsl(var(--foreground)); background: hsl(var(--background));
  border: 1px solid hsl(var(--input)); border-radius: var(--radius);
}
.login-card input:focus-visible { outline: none; border-color: hsl(var(--ring));
  box-shadow: 0 0 0 2px hsl(var(--background)), 0 0 0 4px hsl(var(--ring) / 0.35); }
.btn-primary {
  height: 2.4rem; margin-top: 0.25rem; border: 0; cursor: pointer;
  background: hsl(var(--primary)); color: hsl(var(--primary-foreground));
  border-radius: var(--radius); font-size: 0.9rem; font-weight: 600;
}
.btn-primary:hover { opacity: 0.92; }
.link-btn.logout { margin-left: 0.25rem; white-space: nowrap; }

/* ---- narrow screens: sidebar overlays content ---- */
@media (max-width: 820px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { position: fixed; z-index: 25; width: 268px; top: 56px; bottom: 0; height: auto;
    box-shadow: 0 8px 30px rgb(0 0 0 / 0.18); }
  .shell.collapsed .sidebar { display: none; }
  .viewnav { margin-left: 0; }
  .topbar h1 { display: none; }
  /* Mobile data tables: size to content + keep cells on one line, so the
     .tblwrap scrolls horizontally instead of squishing columns into many
     wrapped lines. (th is already nowrap; this adds td.) */
  .tbl { width: auto; min-width: 100%; }
  .tbl td { white-space: nowrap; }
}

/* ---- print / save-as-PDF (the "Print / PDF" button calls window.print) ---- */
/* Expanded graph overlay (decision 6). The panel's own toolbar, legend, chart and caption are MOVED
   in here and moved back on close, so this is chrome only: it must not restyle what it holds. */
.lb { position: fixed; inset: 0; z-index: 60; display: flex; padding: 1.2rem;
  background: hsl(var(--background) / 0.96); overflow: auto; }
.lb-inner { position: relative; margin: auto; width: 100%; max-width: 1400px;
  background: hsl(var(--card)); border: 1px solid hsl(var(--border)); border-radius: 10px;
  padding: 2.2rem 1rem 1rem; }
/* A fixed square that centres its glyph, rather than a glyph positioned by padding. The old rule
   was `padding: 0.1rem 0.45rem` with no size, so the x sat off-centre and would drift again with any
   change of font. Flex centring does not care about the glyph's own metrics. */
.lb-close { position: absolute; top: 0.5rem; right: 0.6rem; cursor: pointer; line-height: 1;
  display: flex; align-items: center; justify-content: center; width: 1.8rem; height: 1.8rem;
  border: 1px solid hsl(var(--border)); background: hsl(var(--card)); border-radius: 6px;
  padding: 0; font-size: 1.1rem; color: hsl(var(--foreground)); }

/* Expand travels into the overlay with the rest of the toolbar, where it can only re-expand what is
   already expanded. Hidden here rather than by moving the button, so the toolbar that goes in is the
   same one that comes back out and closing restores the panel unchanged. */
.lb .toolbtn.expand { display: none; }
.lb-close:hover { background: hsl(var(--muted)); }

@media print {
  @page { margin: 12mm; }
  /* Controls do not print. .allraces-banner (the USA-only toggle) was missed, and a control on the
     page is not merely untidy: it eats the top of a page, and anything below carrying break-inside
     then will not fit in what is left and is pushed whole to the next one. */
  .topbar, .sidebar, .toolbar, .tabs, .legend .hint, .pgbar,
  .allraces-banner { display: none !important; }
  .shell { display: block; }
  html, body { width: auto; background: #fff; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  main.content { max-width: none !important; width: auto !important; padding: 0; font-size: 10px; }
  .summary .title { font-size: 13px; }
  h2, .sect > summary { font-size: 12px; margin: 8px 0 6px; }
  .chart-wrap { width: 100% !important; padding: 0; border: 0; }
  .chart { width: 100% !important; height: auto !important; }
  .tblwrap { overflow: visible !important; width: 100%; }
  .tbl { width: 100%; font-size: 8px; }
  /* uniform table text in print — !important beats the more-specific .tbl th .arrow
     (0.7rem), .daycol (0.82rem), .t2 th (0.72rem), .muted (0.85rem) on the (P#), etc. */
  .tbl th, .tbl td { padding: 2px 4px; height: auto; white-space: normal; font-size: 8px !important; }
  .tbl th *, .tbl td * { font-size: 8px !important; }
  .summary, .tbl, .chart-wrap, .tblwrap, .legend, .sect { break-inside: avoid; page-break-inside: avoid; }
  /* force the light palette for a clean printout even from dark mode */
  html.dark {
    --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%;
    --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%;
    --border: 214.3 31.8% 91.4%; --success: 142 71% 45%; --success-bg: 138 76% 96%;
    --rel-sb: 76%; --rel-lb: 96%; --rel-sf: 71%; --rel-lf: 45%;   /* gradient prints light even from dark mode */
  }
}
