/* Every colour in the site is a token, and the tokens are the only thing that
   changes between programs: V5RC is black and red, VIQRC white and blue. The
   theme is chosen by the data-program attribute the server puts on <html>, so
   adding a program means adding one block here, not a second stylesheet. */
:root, [data-program="v5rc"] {
  --bg: #0c0c0e;
  --panel: #161619;
  --panel-alt: #1b1b1f;
  --surface: #1a1a1e;
  --inset: #101012;
  --sunken: #08080a;
  --line: #2b2b31;
  --text: #ededf0;
  --muted: #a0a0aa;
  --accent: #d0211f;
  --accent-dim: #8f1d1d;
  --on-accent: #ffffff;
  /* Red at full strength is too dark to read as body text on near-black, so
     links and highlights use a lighter red than surfaces do. */
  --link: #ff5a52;
  --selected-bg: #2a1416;
  --control: #2a2a30;
  --control-hover: #35353d;
  --disabled-bg: #212127;
  --disabled-text: #6e6e78;
  --good: #4ecb71;
  --good-line: #2b5c3a;
  --bad: #ff8a80;
  --bad-line: #6b3a34;
  --warn: #d9a441;
  --warn-line: #6b5524;
  --won-bg: #17261b;
  /* Alliance colours are the game's, not the theme's: red and blue have to
     stay red and blue on a page about red and blue alliances. */
  --alliance-red: #c0392b;
  --alliance-red-text: #ff8a86;
  --alliance-blue: #2b6fb5;
  --alliance-blue-text: #6fb4ff;
  --pending-bg: #3a1a1f;
  --pending-hover: #462026;
  --pending-text: #ffc2c2;
  --pending-edge: #e5484d;
  --done-bg: #16301f;
  --done-hover: #1d3d29;
  --done-text: #9ff0c0;
  --done-edge: #30c07a;
}

[data-program="viqrc"] {
  --bg: #f5f7fb;
  --panel: #ffffff;
  --panel-alt: #eef2f8;
  --surface: #f7f9fc;
  --inset: #ffffff;
  --sunken: #e7edf5;
  --line: #d5dbe6;
  --text: #14181f;
  --muted: #5c6473;
  --accent: #0b63ce;
  --accent-dim: #9cc4ee;
  --on-accent: #ffffff;
  --link: #0b63ce;
  --selected-bg: #e8f1fc;
  --control: #e4e9f1;
  --control-hover: #d4dbe7;
  --disabled-bg: #eceff4;
  --disabled-text: #6e7684;
  --good: #157f46;
  --good-line: #a9d9bd;
  --bad: #c0392b;
  --bad-line: #eab5ad;
  --warn: #8a6100;
  --warn-line: #e3cf9a;
  --won-bg: #e7f5ec;
  --alliance-red: #c0392b;
  --alliance-red-text: #b52d20;
  --alliance-blue: #1565c0;
  --alliance-blue-text: #1565c0;
  --pending-bg: #fdecea;
  --pending-hover: #fadbd7;
  --pending-text: #8c2318;
  --pending-edge: #d9422f;
  --done-bg: #e8f6ee;
  --done-hover: #d8efe2;
  --done-text: #17603a;
  --done-edge: #2f9e63;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
}

header {
  padding: 22px 28px 14px;
  border-bottom: 1px solid var(--line);
}
h1 { margin: 0; font-size: 21px; font-weight: 600; }
.sub { margin: 4px 0 0; color: var(--muted); font-size: 13px; }

main { max-width: 1400px; margin: 0 auto; padding: 22px 28px 60px; }

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 18px 20px;
  margin-bottom: 18px;
}
.panel h2 {
  margin: 0 0 12px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.panel h2:not(:first-child) { margin-top: 22px; }

.hidden { display: none; }
.muted { color: var(--muted); }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.note { color: var(--muted); font-size: 13px; }

.list { display: flex; flex-direction: column; gap: 6px; }

.item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: 7px;
  cursor: pointer;
  background: var(--surface);
}
.item:hover { border-color: var(--accent-dim); }
.item.selected { border-color: var(--accent); background: var(--selected-bg); }
.item.disabled { opacity: .5; cursor: not-allowed; }
.item .name { flex: 1; }
.item .meta { color: var(--muted); font-size: 12px; }

.tag {
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 20px;
  border: 1px solid var(--line);
  color: var(--muted);
}
.tag.ok { color: var(--good); border-color: var(--good-line); }
.tag.missing { color: var(--bad); border-color: var(--bad-line); }

.row { display: flex; align-items: center; gap: 14px; margin-top: 14px; flex-wrap: wrap; }

button {
  background: var(--accent);
  color: var(--on-accent);
  border: 0;
  border-radius: 7px;
  padding: 9px 16px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
button:disabled { background: var(--disabled-bg); color: var(--disabled-text); cursor: not-allowed; }

button.secondary { background: var(--control); color: var(--text); }
button.secondary:hover { background: var(--control-hover); }

/* Compact enough to sit in a table row; one width so the column lines up. */
button.stream-button { padding: 4px 10px; font-size: 12px; min-width: 88px; white-space: nowrap; }

.tag.saved { color: var(--link); border-color: var(--accent-dim); }

a { color: var(--link); }

.bar {
  height: 9px;
  background: var(--sunken);
  border-radius: 20px;
  overflow: hidden;
  border: 1px solid var(--line);
}
.bar-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent-dim), var(--accent));
  transition: width .3s ease;
}

.log {
  margin: 12px 0 0;
  padding: 10px 12px;
  background: var(--inset);
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  max-height: 190px;
  overflow-y: auto;
  white-space: pre-wrap;
}

video {
  width: 100%;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: #000;
  margin-top: 6px;
}

table { border-collapse: collapse; width: 100%; margin-top: 14px; font-size: 13px; }
th, td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
td.num { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.warn { color: var(--bad); }

.seed-stage {
  position: relative;
  overflow: auto;
  max-height: 62vh;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--sunken);
  margin-bottom: 14px;
}
#seed-canvas { display: block; cursor: crosshair; max-width: 100%; }

button.status { border-left: 5px solid transparent; }
button.status.pending { background: var(--pending-bg); color: var(--pending-text); border-left-color: var(--pending-edge); }
button.status.pending:hover { background: var(--pending-hover); }
button.status.done { background: var(--done-bg); color: var(--done-text); border-left-color: var(--done-edge); }
button.status.done:hover { background: var(--done-hover); }
#field-canvas { display: block; cursor: grab; max-width: 100%; }
#field-canvas:active { cursor: grabbing; }

/* --- team-centric pages ------------------------------------------------- */

.nav { display: flex; align-items: baseline; gap: 18px; margin-bottom: 14px; font-size: 13px; }
.nav a { color: var(--muted); text-decoration: none; }
.nav a:hover { color: var(--text); }
.nav a.on { color: var(--text); font-weight: 600; }
.nav .brand { color: var(--link); font-weight: 600; margin-right: 6px; letter-spacing: .02em; }

/* Two rows: the three tabs, then the sections of whichever tab is open. The
   program switch sits at the far right of the top row, where it reads as a
   property of the whole site rather than of the page under it. */
.nav-top { margin-bottom: 6px; font-size: 14px; }
.nav-top a:not(.brand) { padding-bottom: 5px; border-bottom: 2px solid transparent; }
.nav-top a.on { border-bottom-color: var(--accent); }
.nav-sections { margin-bottom: 14px; }
.nav-sections a.on { color: var(--link); }

/* A sliding switch rather than two buttons: equal columns, so the knob can be
   half the track wide and land exactly on the other option. Which side it sits
   on follows the data-program attribute, not the server-rendered .on class, so
   a click can move it before the new page has loaded. */
.program-switch {
  position: relative;
  display: inline-grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-self: center;
  margin-left: auto;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
}
.program-knob {
  position: absolute;
  top: 2px;
  bottom: 2px;
  /* Both sides are written as calc() so the browser interpolates between a
     pixel offset and a percentage; the travel is `left` rather than a
     transform because a transform runs on the compositor, where it is the one
     animation on the page that does not reliably play. */
  left: calc(0% + 2px);
  width: calc(50% - 2px);
  border-radius: 999px;
  background: var(--accent);
}
[data-program="viqrc"] .program-knob { left: calc(50% + 0px); }
.nav .program-switch a {
  position: relative;           /* above the knob */
  padding: 3px 14px;
  text-align: center;
  white-space: nowrap;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .03em;
  color: var(--muted);
  border-bottom: 0;
}
[data-program="v5rc"] .program-switch a[data-program-code="v5rc"],
[data-program="viqrc"] .program-switch a[data-program-code="viqrc"] { color: var(--on-accent); }
.nav .program-switch a:hover { color: var(--text); }
.program-switch .label-short { display: none; }
[data-program="v5rc"] .program-switch a[data-program-code="v5rc"]:hover,
[data-program="viqrc"] .program-switch a[data-program-code="viqrc"]:hover { color: var(--on-accent); }

/* Transitions are switched on only while a program change is in flight, so
   they cost nothing on every other hover and click. The class is dropped by
   the navigation that follows. */
html.switching, html.switching *, html.switching *::before, html.switching *::after {
  transition: background-color .32s ease, border-color .32s ease, color .32s ease,
              fill .32s ease, outline-color .32s ease;
}
html.switching .program-knob {
  transition: background-color .32s ease, left .32s cubic-bezier(.4, 0, .2, 1);
}
/* No prefers-reduced-motion guard here on purpose. This animation was asked
   for explicitly, it is one small control moving 60px once per switch, and
   guarding it is what made both animations look broken: browsers report
   `reduce` whenever Windows has animation effects turned off, which is a
   common default. To honour the setting again, wrap the two rules above in
   `@media (prefers-reduced-motion: no-preference)`. */

/* A tab with nothing in it yet says so, rather than showing an empty page. */
.stub { padding: 34px 20px; text-align: center; color: var(--muted); }
.stub h3 { margin: 0 0 8px; color: var(--text); font-size: 16px; }
.stub p { margin: 0 auto; max-width: 62ch; font-size: 14px; }
.stub ul { margin: 14px auto 0; max-width: 62ch; text-align: left; font-size: 14px; line-height: 1.8; }

.panel.notice { border-left: 3px solid var(--accent); color: var(--muted); font-size: 14px; }
.panel.notice strong { color: var(--text); }

h1 .light { color: var(--muted); font-weight: 400; margin-left: 8px; }

.search {
  flex: 1;
  min-width: 240px;
  background: var(--inset);
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--text);
  padding: 9px 12px;
  font-size: 14px;
}
.search:focus { outline: none; border-color: var(--accent-dim); }

/* The shared Filters menu (templates/_filters.html). */
.filter-form { margin: 0; }
details.filters { margin-top: 12px; }
details.filters > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
details.filters > summary::-webkit-details-marker { display: none; }
.filters-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--control);
  color: var(--text);
  border-radius: 7px;
  padding: 7px 14px;
  font-size: 14px;
  font-weight: 600;
}
details.filters > summary:hover .filters-toggle { background: var(--control-hover); }
details.filters[open] .filters-toggle { background: var(--accent-dim); }
details.filters > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 7px; }
.filters-count {
  background: var(--accent);
  color: var(--on-accent);
  border-radius: 999px;
  min-width: 20px;
  padding: 0 6px;
  font-size: 12px;
  line-height: 20px;
  text-align: center;
}
.filters-active { color: var(--muted); font-size: 13px; }
.filters-panel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  margin-top: 10px;
  padding: 14px;
  background: var(--panel-alt);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.filters-panel label { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.filters-panel select { max-width: 100%; }

/* Filters on the left, Add on the right, directly above the table. */
.table-toolbar { display: flex; align-items: flex-start; gap: 12px; margin-top: 12px; }
.table-toolbar details.filters { flex: 1; min-width: 0; margin-top: 0; }
.add-toggle { margin-left: auto; padding: 7px 14px; white-space: nowrap; }
.add-toggle[aria-expanded="true"] { background: var(--accent-dim); color: var(--text); }
.add-panel {
  margin-top: 10px;
  padding: 14px;
  background: var(--panel-alt);
  border: 1px solid var(--line);
  border-radius: 8px;
}

th.right, td.right { text-align: right; }
tbody tr:hover { background: var(--surface); }
td a { text-decoration: none; }
td a:hover { text-decoration: underline; }

.tabs { display: flex; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
.tab {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 500;
}
.tab:hover { color: var(--text); border-color: var(--accent-dim); }
.tab.on { background: var(--panel); color: var(--text); border-color: var(--accent); }

.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 10px; }
.card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.card .k { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
.card .v { font-size: 22px; font-weight: 600; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.card .f { color: var(--muted); font-size: 11px; }

.side { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
.side.red { color: var(--alliance-red-text); }
.side.blue { color: var(--alliance-blue-text); }

.res { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
.res.win { color: var(--good); }
.res.loss { color: var(--bad); }
.res.tie { color: var(--muted); }

a.item { text-decoration: none; color: inherit; }

.form { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; align-items: end; }
.form label { display: flex; flex-direction: column; gap: 4px; color: var(--muted); font-size: 12px; }
.form input, .form select {
  background: var(--inset);
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--text);
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
}
.form input:focus, .form select:focus { outline: none; border-color: var(--accent-dim); }
.form-actions { grid-column: 1 / -1; }
select {
  background: var(--inset);
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--text);
  padding: 8px 10px;
  font-size: 14px;
}

.tag.state-past { color: var(--muted); }
.tag.state-ongoing { color: var(--good); border-color: var(--good-line); }
.tag.state-upcoming { color: var(--warn); border-color: var(--warn-line); }
.tag.state-unknown { color: var(--muted); }

th.sortable { padding: 0; }
th.sortable a {
  display: block;
  padding: 7px 10px;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
th.sortable a:hover { color: var(--text); background: var(--surface); }
th.sortable.sorted a { color: var(--link); }
th.sortable .arrow { margin-left: 5px; font-size: 10px; }

td.approx { font-style: italic; opacity: .75; }

/* Long channel names would otherwise widen the teams table past the screen. */
.channel-cell { max-width: 220px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.channel-cell a { text-decoration: none; }
.channel-cell a:hover { text-decoration: underline; }

.item .name a { text-decoration: none; }
.item .name a:hover { text-decoration: underline; }
.item .name a.muted { margin-left: 8px; font-size: 12px; }

/* --- elimination bracket ------------------------------------------------- */

.bracket { display: flex; gap: 16px; overflow-x: auto; padding-bottom: 8px; }
.bracket-round {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  gap: 10px;
  min-width: 196px;
  flex: 1;
}
.bracket-label {
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  text-align: center;
  margin-bottom: 2px;
}
.slot {
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--surface);
  overflow: hidden;
}
.slot.unplayed { opacity: .55; }
.slot-side {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 9px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  border-left: 3px solid transparent;
}
.slot-side.red { border-left-color: var(--alliance-red); }
.slot-side.blue { border-left-color: var(--alliance-blue); }
.slot-side.won { background: var(--won-bg); font-weight: 600; }
.slot-side.won .slot-score { color: var(--good); }
.slot-teams { flex: 1; }
.slot-teams a { text-decoration: none; }
.slot-teams a:hover { text-decoration: underline; }
.slot-score { color: var(--muted); }
.slot-games {
  display: flex;
  gap: 8px;
  padding: 4px 9px;
  border-top: 1px solid var(--line);
  background: var(--bg);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
}
.slot-games a { color: var(--muted); text-decoration: none; }
.slot-games a:hover { color: var(--link); }

td.highlight { color: var(--link); font-weight: 600; }

.bar-mini {
  display: block;
  height: 3px;
  width: 52px;
  margin: 3px 0 0 auto;
  background: var(--sunken);
  border-radius: 2px;
  overflow: hidden;
}
.bar-mini span { display: block; height: 100%; background: var(--accent-dim); }
.imp-parts { color: var(--muted); font-size: 10px; letter-spacing: .02em; cursor: help; }

/* Robot videos on the team page. */
.video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; margin-top: 14px; }
.video-card { display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.video-thumb { display: block; aspect-ratio: 16 / 9; background: var(--sunken); }
.video-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.video-body { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px 12px; }
.video-title { color: var(--text); text-decoration: none; font-weight: 600; font-size: 14px; line-height: 1.35; }
.video-title:hover { text-decoration: underline; }
.video-meta { color: var(--muted); font-size: 12px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.video-actions { display: flex; gap: 8px; margin-top: 2px; }
.inline-form { display: inline; margin: 0; }
button.small { padding: 4px 10px; font-size: 12px; }
details.suggestions { margin-top: 16px; }
details.suggestions > summary { cursor: pointer; color: var(--muted); font-size: 13px; }


/* Footage: one long event stream, played from the match's timestamp. The
   poster is a button until someone presses it, so nothing loads from YouTube
   until it is asked for. */
.match-footage { margin: 0 0 4px; max-width: 640px; }
.video-play {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 16 / 9;
  padding: 0;
  border-radius: 10px;
  border: 1px solid var(--line);
  background-color: var(--sunken);
  background-size: cover;
  background-position: center;
  cursor: pointer;
}
.video-play-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 22px;
  padding-left: 4px;
}
.video-play:hover .video-play-mark { transform: scale(1.06); }
.video-frame { width: 100%; max-width: 640px; aspect-ratio: 16 / 9; border: 0; border-radius: 10px; }
.match-footage figcaption { color: var(--muted); font-size: 13px; margin-top: 8px; }

/* --- phones -------------------------------------------------------------
   A 14-column teams table used to make <body> wider than the screen, and
   everything else - the program switch, the search button, whole paragraphs -
   was clipped along with it. Each table now scrolls inside its own strip, so
   the page itself always fits. */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

@media (max-width: 720px) {
  header { padding: 14px 16px 10px; }
  main { padding: 16px 16px 48px; }
  h1 { font-size: 21px; }
  .sub { font-size: 13.5px; }

  .panel { padding: 14px 14px 16px; border-radius: 10px; }
  .panel h2 { font-size: 13px; }

  /* Read at arm's length on a phone, not on a desk. Everything here is a
     size, not a layout: the arrangement is the same as above. */
  body { font-size: 16px; }
  table { font-size: 14.5px; }
  th { font-size: 12.5px; }
  td, th { padding: 10px 10px; }
  .note, .item .meta, .filters-active { font-size: 13.5px; }
  .tag { font-size: 12px; padding: 3px 9px; }
  .nav-top { font-size: 15px; }
  .nav-sections { font-size: 14px; }
  .card .k { font-size: 12px; }
  .card .v { font-size: 21px; }

  /* Both nav rows wrap, so the program switch drops to a line of its own
     instead of being cut in half at the right edge. */
  .nav { flex-wrap: wrap; gap: 4px 16px; }
  .nav-top { margin-bottom: 4px; }
  /* Bare text links were 19px tall - the smallest target on the page, and the
     one people press most. Padding makes them about 38px without moving
     anything. */
  .nav a { padding: 9px 0; }
  .nav-top a:not(.brand) { padding-bottom: 9px; }
  .program-switch { margin-left: auto; }
  /* "VEX V5" and "VEX IQ" need 145px of a 390px nav row; the short names say
     the same thing in a third of the space. */
  .program-switch .label-full { display: none; }
  .program-switch .label-short { display: inline; }
  .nav .program-switch a { padding: 8px 14px; }

  /* Search and its buttons stack rather than running off the side. */
  .row { gap: 8px; }
  .search { flex: 1 1 100%; min-width: 0; }

  /* Under 16px, iOS zooms the page in when a field is focused and leaves it
     zoomed. The size is the fix; there is no other way to stop it. */
  input, select, .search, .form input, .form select { font-size: 16px; }

  /* Tappable: roughly 44px tall, which is the smallest target a thumb hits
     reliably. Everything that is pressed gets it, not just <button>. */
  button { padding: 12px 18px; font-size: 15px; }
  button.small { padding: 9px 14px; font-size: 14px; }
  button.stream-button { padding: 10px 14px; font-size: 14px; min-width: 96px; }

  .tab { padding: 11px 18px; font-size: 15px; }
  .tabs { gap: 8px; }

  .filters-toggle { padding: 11px 16px; font-size: 15px; }
  .filters-count { font-size: 13px; min-width: 22px; line-height: 22px; }
  .add-toggle { padding: 11px 16px; }

  /* A checkbox at its default 13px is a poor target; the label goes with it. */
  .filters-panel input[type="checkbox"] { width: 20px; height: 20px; }
  .filters-panel label { font-size: 15px; gap: 9px; padding: 4px 0; }
  .filters-panel select { padding: 11px 10px; }

  .filters-panel { padding: 12px; gap: 10px; }
  .filters-panel select, .filters-panel label { width: 100%; }
  .table-toolbar { flex-wrap: wrap; }
  .add-toggle { margin-left: 0; }

  /* Tabs scroll sideways instead of wrapping into a tall block. */
  .tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tab { white-space: nowrap; }

  .cards { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
  .card { padding: 10px 12px; }
  .card .v { font-size: 19px; }

  /* The table strip reaches the panel's edges, so the full width is usable.
     No horizontal padding here on purpose: a sticky cell pins to the padding
     box, so 14px of padding leaves a 14px strip of scrolled-away content
     visible to the left of the pinned column. The inset is put back on the
     first column's own cells instead, where it scrolls with nothing. */
  .table-scroll { margin: 0 -14px; }
  .table-scroll table { min-width: max-content; }
  .table-scroll th:first-child,
  .table-scroll td:first-child { padding-left: 14px; }
  .table-scroll th.sortable:first-child { padding-left: 0; }
  .table-scroll th.sortable:first-child a { padding-left: 14px; }

  /* A pinned column wider than the screen hides the very thing it is meant to
     let you scroll behind it. The events table's first column is as wide as
     the longest event name - 400px and more - so on a phone it covered the
     viewport and scrolling appeared to do nothing. Capped and ellipsised; the
     cell is a link to the full record either way.

     The cap sits on the link rather than the cell because a table cell's
     max-width is advisory under automatic layout and the content can win. */
  .table-scroll tbody td:first-child { max-width: 46vw; }
  .table-scroll tbody td:first-child > a {
    display: inline-block;
    /* Per cent of the cell, not of the viewport: 46vw here would be the cell's
       full width again and the link would hang 24px past its own padding,
       outside the pinned background and over the scrolling columns. */
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
  }

  /* The first column stays put while the rest scrolls under it, so a row is
     always identifiable. It needs its own background or the scrolling cells
     show through. */
  .table-scroll th:first-child,
  .table-scroll td:first-child {
    position: sticky;
    left: 0;
    background: var(--panel);
    z-index: 2;
    /* A line down the right, and an opaque block to the left wide enough to
       cover anything a rounding error would otherwise let through. */
    box-shadow: 1px 0 0 var(--line), -24px 0 0 var(--panel);
  }
  th.sortable:first-child { background: var(--panel); }

  /* A 49-character URL with no spaces in it is wider than the screen and has
     nowhere to break; let it break anywhere rather than push the page out.
     Not inside tables, where a team number breaking across lines would be
     worse than scrolling. */
  .mono, .note { overflow-wrap: anywhere; }
  .table-scroll .mono { overflow-wrap: normal; }

  .guide { max-width: 100%; }
  .compare-pair { grid-template-columns: 1fr; }
  .guide-steps li { grid-template-columns: 28px 1fr; gap: 10px; }
  .video-play-mark { width: 48px; height: 48px; font-size: 18px; }

  .bracket { gap: 10px; }
  .bracket-round { min-width: 170px; }
}

@media (max-width: 420px) {
  main { padding: 14px 12px 40px; }
  header { padding: 12px 12px 8px; }
  .panel { padding: 12px 12px 14px; }
  .table-scroll { margin: 0 -12px; }
  .table-scroll th:first-child,
  .table-scroll td:first-child { padding-left: 12px; }
  .table-scroll th.sortable:first-child a { padding-left: 12px; }
  .nav { font-size: 12.5px; }
  .nav-top { font-size: 13px; }
  h1 { font-size: 18px; }
}

/* --- Tools → Parts --------------------------------------------------------- */
/* Status is the left edge and the label's colour, from the same good / warn /
   bad tokens as everywhere else, so both programs' themes carry it. */

.parts-access .note { margin: 0; }
.parts-access-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; justify-content: space-between; }
.parts-unlock { margin-bottom: 10px; }
.parts-unlock .form-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.parts-unlock-error { font-size: 13px; }

.parts-n-missing { color: var(--bad); }
.parts-n-low { color: var(--warn); }
.parts-n-have { color: var(--good); }

.parts-need-toggle { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; }
.parts-chips { margin: 12px 0 4px; }
.parts-error { margin: 10px 0 0; font-size: 13px; }

.parts-group { margin-top: 18px; }
.parts-group-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding-bottom: 6px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.panel .parts-group-head h2 { margin: 0; }
.parts-group-head .parts-mark-all { margin-left: auto; padding: 5px 12px; font-size: 12px; }

.parts-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px; }
.part {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 10px 12px;
  text-align: left;
  font: inherit;
  font-size: 14px;
  font-weight: 400;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: 8px;
}
button.part { cursor: pointer; }
button.part:hover { border-color: var(--accent-dim); }
button.part:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.part[hidden], .parts-group[hidden] { display: none; }
.part-name { line-height: 1.3; }
.part-status { font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.part[data-state="missing"] { border-left-color: var(--bad); }
.part[data-state="low"] { border-left-color: var(--warn); }
.part[data-state="have"] { border-left-color: var(--good); }
[data-state="missing"] > .part-status, .part-status[data-state="missing"] { color: var(--bad); }
[data-state="low"] > .part-status, .part-status[data-state="low"] { color: var(--warn); }
[data-state="have"] > .part-status, .part-status[data-state="have"] { color: var(--good); }

.parts-log { margin-top: 0; }
.parts-log td { white-space: nowrap; }
.parts-log td:nth-child(3) { white-space: normal; }

@media (max-width: 720px) {
  /* Three short numbers fit one row; wrapped 2 + 1 they read as two groups. */
  .parts-summary { grid-template-columns: repeat(3, 1fr); }
  .parts-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .part { padding: 12px; font-size: 15px; min-height: 64px; }
  .part-status { font-size: 12px; }
  .parts-need-toggle { font-size: 15px; padding: 6px 0; }
  .parts-need-toggle input { width: 20px; height: 20px; }
  .parts-group-head .parts-mark-all { padding: 9px 14px; font-size: 14px; }
  .parts-log td { white-space: normal; }
}
