/* Special Teams Instance Explorer -- surfaces, ink and grid chrome.
   Light and dark are both selected palettes, not an automatic flip. */

:root {
  --st-surface: #fcfcfb;
  --st-plane: #f9f9f7;
  --st-ink: #0b0b0b;
  --st-ink2: #52514e;
  --st-muted: #898781;
  --st-grid: #e1e0d9;
  --st-axis: #c3c2b7;
  --st-border: rgba(11, 11, 11, 0.10);
}
[data-mantine-color-scheme="dark"] {
  --st-surface: #1a1a19;
  --st-plane: #0d0d0d;
  --st-ink: #ffffff;
  --st-ink2: #c3c2b7;
  --st-muted: #898781;
  --st-grid: #2c2c2a;
  --st-axis: #383835;
  --st-border: rgba(255, 255, 255, 0.10);
}

body { background: var(--st-plane); }

/* ------------------------------------------------------------------ shell */
.st-header {
  background: var(--st-surface);
  border-bottom: 1px solid var(--st-border);
  padding: 0 16px;
  display: flex;
  align-items: center;
}
.st-navbar {
  background: var(--st-surface);
  border-right: 1px solid var(--st-border);
  overflow-y: auto;
}
.st-brand { font-weight: 650; letter-spacing: -0.01em; }

/* ------------------------------------------------------------------ tiles */
.tile { background: var(--st-surface); }
.tile-label { text-transform: uppercase; letter-spacing: 0.04em; font-size: 10px; }
.tile-value {
  font-size: 24px;
  font-weight: 600;
  line-height: 1.15;
  color: var(--st-ink);
  /* proportional figures for a standalone number, per the type spec */
}
.tile-sub { min-height: 14px; }

/* ------------------------------------------------------------------ notes */
.note { padding: 2px 0; }
.note-icon {
  min-width: 14px; text-align: center; font-weight: 700;
  color: var(--st-muted);
}
.note-warn .note-icon { color: #fab219; }

/* ------------------------------------------------------------------ charts */
.viz {
  background: var(--st-surface);
  border: 1px solid var(--st-border);
  border-radius: 8px;
}

/* ------------------------------------------------------------------ grid */
.st-grid {
  --ag-font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  --ag-font-size: 12px;
  /* Every colour is set here rather than relying on a theme variant: only the
     light quartz stylesheet is bundled, so a dark theme class does nothing. */
  --ag-foreground-color: var(--st-ink);
  --ag-data-color: var(--st-ink);
  --ag-header-foreground-color: var(--st-muted);
  --ag-secondary-foreground-color: var(--st-muted);
  --ag-disabled-foreground-color: var(--st-muted);
  --ag-icon-font-color: var(--st-ink2);
  --ag-menu-background-color: var(--st-plane);
  --ag-menu-foreground-color: var(--st-ink);
  --ag-panel-background-color: var(--st-plane);
  --ag-control-panel-background-color: var(--st-plane);
  --ag-input-background-color: var(--st-plane);
  --ag-input-border-color: var(--st-border);
  --ag-input-focus-box-shadow: none;
  --ag-checkbox-unchecked-color: var(--st-axis);
  --ag-checkbox-checked-color: #3987e5;
  --ag-range-selection-border-color: #3987e5;
  --ag-tooltip-background-color: var(--st-plane);
  --ag-chip-background-color: var(--st-plane);
  --ag-background-color: var(--st-surface);
  --ag-header-background-color: var(--st-surface);
  --ag-odd-row-background-color: var(--st-surface);
  --ag-border-color: var(--st-border);
  --ag-row-border-color: var(--st-border);
  --ag-header-column-separator-display: none;
  --ag-wrapper-border-radius: 8px;
  --ag-row-hover-color: color-mix(in srgb, var(--st-ink) 5%, transparent);
  --ag-selected-row-background-color: color-mix(in srgb, var(--st-ink) 9%, transparent);
  --ag-cell-horizontal-padding: 10px;
}
.st-grid .ag-header-cell-text {
  font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--st-muted); text-transform: uppercase;
}
/* ONE header layout for every column in the app: name hard left, filter hard right,
   sort arrow beside the name. Text columns get that from quartz for free. Numeric ones
   do not -- `type: "rightAligned"` makes quartz flip `.ag-cell-label-container` to
   `row`, which parks the filter icon to the LEFT of the name, so a grid whose first two
   columns are text and whose next dozen are measures showed two header designs in one
   row.

   Both declarations are needed and they do different things. The container flip puts
   the ICON back on the right. `justify-content: flex-start` on the label puts the NAME
   back on the left: the label box grows to fill whatever the icon leaves, and quartz's
   right-aligned variant pushes the text to the far end of it, which left the name
   floating in the middle of the cell against the filter icon.

   The trade is deliberate and worth naming: a numeric header no longer sits over its
   own digits, because the cells stay right-aligned and the name does not. Consistency
   across every header in the app was the ask, and a column's name is a label rather
   than a value -- it is not something a reader scans down the way they scan the
   numbers under it.

   No gap is added between name and icon: 4px of it clipped `Season` and `<30 made` on
   the season tables, the narrowest right-aligned headers here. */
.st-grid .ag-right-aligned-header .ag-cell-label-container {
  flex-direction: row-reverse;
}
.st-grid .ag-right-aligned-header .ag-header-cell-label {
  flex-direction: row; justify-content: flex-start;
}
.st-grid .ag-row { cursor: pointer; }
.st-grid .num-cell { font-variant-numeric: tabular-nums; }
.st-grid .name-cell { font-weight: 550; }
.st-grid .bool-cell { text-align: center; color: var(--st-ink2); }
.st-grid .mono-cell {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; color: var(--st-ink2);
}

/* ------------------------------------------------------------------ detail drawer */
.kv-row {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 5px 0; border-bottom: 1px solid var(--st-border);
}
.kv-row:last-child { border-bottom: none; }
.kv-key { color: var(--st-muted); font-size: 12px; }
.kv-val { color: var(--st-ink); font-size: 12px; font-variant-numeric: tabular-nums; }
.person-card { background: var(--st-surface); }
.person-role {
  text-transform: uppercase; letter-spacing: 0.05em; font-size: 10px;
  color: var(--st-muted);
}
.person-name { font-size: 16px; font-weight: 600; color: var(--st-ink); }
.playtext {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px; line-height: 1.55; color: var(--st-ink2);
  background: var(--st-plane); border: 1px solid var(--st-border);
  border-radius: 6px; padding: 10px;
}

/* ------------------------------------------------------------------ misc */
.filter-label {
  text-transform: uppercase; letter-spacing: 0.04em;
  font-size: 10px; font-weight: 600; color: var(--st-muted);
}
a.st-link { color: inherit; text-decoration: none; border-bottom: 1px solid var(--st-axis); }
a.st-link:hover { border-bottom-color: var(--st-ink); }

/* ------------------------------------------------------------------ sidebar hints */
/* The caveat dot. Sized to the uppercase filter label beside it rather than to body
   text, so the pair reads as one line of chrome and not as a label with a bullet
   after it. `cursor: help` is the only signal that it is interactive -- a button
   ring here would out-weigh the control it annotates. */
.hint-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 1px solid var(--st-axis);
  color: var(--st-muted);
  font-size: 9px;
  font-weight: 700;
  font-style: italic;
  font-family: Georgia, "Times New Roman", serif;  /* a legible 9px dotless-i */
  line-height: 1;
  cursor: help;
  user-select: none;
  flex: none;
}
.hint-dot:hover, .hint-dot:focus-visible {
  border-color: var(--st-ink2);
  color: var(--st-ink);
  outline: none;
}
.hint-info { border-color: color-mix(in srgb, #3987e5 55%, transparent); }
.hint-info:hover, .hint-info:focus-visible { border-color: #3987e5; }

/* ------------------------------------------------------------------ filter drawer */
/* The three groups inside `More filters`. Mantine's default accordion pads each
   control generously for a page; nested two deep in a 296px panel that padding is
   what pushed the groups apart in the first place, so it is pulled back here and the
   left inset is dropped entirely -- the outer card already provides one. */
.f-subgroups .mantine-Accordion-control { padding: 7px 0; }
.f-subgroups .mantine-Accordion-content { padding: 0 0 8px 0; }
.f-subgroups .mantine-Accordion-item { border-color: var(--st-border); }
.f-subgroups .mantine-Accordion-item:first-of-type { border-top: none; }
.f-subgroups .mantine-Accordion-item:last-of-type { border-bottom: none; }

/* The `More filters` disclosure. Styled to match the Accordion cards it replaced --
   it reads as the same control, it just does not measure its own height. */
.f-drawer { background: transparent; border-color: var(--st-border); }
.f-drawer-toggle { padding: 10px 12px; border-radius: var(--mantine-radius-sm); }
.f-drawer-toggle:hover { background: color-mix(in srgb, var(--st-ink) 4%, transparent); }
.f-drawer-toggle:focus-visible { outline: 1px solid var(--st-axis); outline-offset: -1px; }
#f-drawer-body { padding: 0 12px 10px 12px; }
.f-chevron {
  color: var(--st-muted); font-size: 14px; line-height: 1;
  transition: transform 150ms; transform-origin: center 40%;
}
.f-chevron-open { transform: rotate(180deg); }

/* Tooltips carry this app's surfaces rather than Mantine's default light-grey chip.
   Applies to every tooltip -- the caveat dots, the snapshot stamp, the partial-season
   badges -- because a popover that inverts the palette reads as belonging to the
   browser rather than to the page. The border is what separates a dark tooltip from
   the dark surface under it, so it is not optional here the way a shadow would be. */
.mantine-Tooltip-tooltip {
  background: var(--st-surface) !important;
  color: var(--st-ink) !important;
  border: 1px solid var(--st-border);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.28);
  font-size: 12px;
  line-height: 1.5;
}
.mantine-Tooltip-arrow { background: var(--st-surface) !important; border: 1px solid var(--st-border); }

/* ------------------------------------------------------------------ header type */
/* The wordmark and its subtitle. The brand was `size="sm"` body text with a weight on
   it; at 15px with tight tracking it reads as a title, which is what lets the corpus
   line sit under it as a subtitle instead of competing with it. */
.st-brand {
  font-size: 15px; font-weight: 680; letter-spacing: -0.015em;
  line-height: 1.1; color: var(--st-ink);
}
.st-brand-sub {
  font-size: 10.5px; color: var(--st-muted); line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
/* Captions over the selectors and over the live count. One face for every small
   uppercase label in the chrome -- the same one the sidebar's filter labels use, so
   the header and the panel read as the same system. */
.st-cap {
  text-transform: uppercase; letter-spacing: 0.06em;
  font-size: 9px; font-weight: 600; color: var(--st-muted); line-height: 1;
}
/* The one number on the header that moves with every click. Tabular so the row does
   not jitter sideways as the count changes width. */
.st-readout {
  font-size: 15px; font-weight: 600; color: var(--st-ink);
  line-height: 1.1; font-variant-numeric: tabular-nums;
}
.st-vrule { height: 34px; align-self: center; border-color: var(--st-border); }
.st-header { padding: 0 18px; }

/* ------------------------------------------------------------------ panel chrome */
.st-panel-title {
  text-transform: uppercase; letter-spacing: 0.08em;
  font-size: 10px; font-weight: 700; color: var(--st-ink2);
}
/* Hairlines between the facets above the fold. Barely there on purpose: the job is to
   group four questions, not to draw four boxes. */
.st-facet-rule { margin: 14px 0 2px 0; border-color: var(--st-border); opacity: 0.6; }
/* The filter labels grew with the controls under them. Still the smallest type in the
   panel, but no longer at the size where the tracking closed the letters up. */
.filter-label { font-size: 10.5px; letter-spacing: 0.05em; }

/* ------------------------------------------------------------------ header fit */
/* Both header groups are nowrap, and at full dress the row needs ~1150px. That is
   fine on the machines this runs on and NOT fine on a 1024 laptop, so the row sheds
   its optional parts on the way down rather than letting the two groups collide.
   The right group is the one that must survive: it holds the live count and the
   theme switch. So the left group is the one allowed to shrink and clip. */
.st-head-left { min-width: 0; overflow: hidden; }
.st-head-right { flex: none; }

@media (max-width: 1280px) {
  /* The corpus line is the widest thing in the brand block and the least urgent --
     it is a constant, not a reading. It goes first. */
  .st-brand-sub { display: none; }
}
@media (max-width: 1140px) {
  .st-vrule { display: none; }
  .st-header { padding: 0 12px; }
  .st-cap { font-size: 8.5px; letter-spacing: 0.04em; }
}

/* ------------------------------------------------------------------ page intro
   The strip above the season band, where the work-in-progress alert used to be. It
   is chrome, not content: the title sits a step under the tile values so it frames
   the page rather than competing with the first number on it, and the line under it
   is the same muted face as the header's corpus line. */
.st-intro-title {
  font-size: 15px; font-weight: 650; letter-spacing: -0.01em;
  line-height: 1.2; color: var(--st-ink);
}
.st-intro-sub {
  font-size: 12px; color: var(--st-muted); line-height: 1.35;
}
/* At the width where the header drops its corpus line, the intro is the widest
   fixed text on the page. The title carries the page; the sentence under it is the
   part a returning reader has already read. */
@media (max-width: 900px) {
  .st-intro-sub { display: none; }
}

/* ------------------------------------------------------------------ footer
   The source credit. Every row in the app comes from ESPN's play-by-play, so the
   credit sits under every page, in the header's muted face. */
.st-footer {
  margin-top: 28px; padding: 12px 0 4px 0;
  border-top: 1px solid var(--st-border);
  font-size: 11px; color: var(--st-muted); line-height: 1.3;
}
.st-footer a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.st-footer a:hover { color: var(--st-ink); }
.st-footer-source { margin: 0; }

/* The estate row: the same links, in the same order, as the footer of every
   other site on the box (see web/estate.py). Same muted face as the credit. */
.st-estate { margin-top: 12px; }
.st-estate-label {
  margin: 0 0 4px 0; font-size: 10px; font-weight: 650; letter-spacing: .08em;
  text-transform: uppercase;
}
.st-estate ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 2px 0; }
.st-estate li { display: inline-flex; align-items: center; font-size: 12px; }
.st-footer .st-estate-link { text-decoration: none; font-weight: 550; color: var(--st-ink); }
.st-footer .st-estate-link:hover { text-decoration: underline; }
.st-footer .st-estate-link.is-current { color: var(--st-muted); font-weight: 650; }
.st-estate-sep { margin: 0 6px; opacity: .6; }
.st-estate-meta { margin: 10px 0 0 0; }

/* ------------------------------------------------------ the season band
   The season range, promoted out of the sidebar on 2026-09-29. It is the filter
   most questions here start with and it had the least room to be one: the sidebar
   track measured 264px, which cannot carry thirteen year marks, so it carried six
   two-digit ones. In the main pane the track measures 830px and carries all
   thirteen as four-digit years.

   NOTE THE CLASS PREFIX. Mantine names these parts `mantine-RangeSlider-*`, not
   `mantine-Slider-*` -- RangeSlider is its own component, not a Slider with two
   thumbs. The first version of this block used the Slider names, matched nothing,
   and left the marks at Mantine's default 14px while appearing to have styled
   them. Verified against the live DOM rather than assumed. */
.st-season-band {
  background: var(--st-surface);
  padding: 10px 18px 6px 18px;
}
.st-season-head { min-width: 104px; }
/* Fixed-width and tabular. The readout sits left of a track that takes the rest of
   the row, so a readout that changed width with the range -- "2019" is narrower
   than "2014-2026" -- would drag the track sideways under the thumb being held. */
.st-season-readout {
  font-size: 15px; font-weight: 600; color: var(--st-ink);
  line-height: 1.2; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.st-season-slider { flex: 1; min-width: 0; padding-bottom: 20px; }
.st-season-band .mantine-RangeSlider-markLabel {
  font-size: 11px; color: var(--st-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Narrow: the band wraps to a readout over a full-width track, and the marks thin
   to every other year rather than overlapping -- the sidebar's old compromise,
   reached only at the width that actually forces it.

   The even/odd count is on the WRAPPER, not the label. Each mark renders as
   `markWrapper > mark + markLabel`, so every label is the second child of its own
   wrapper and `markLabel:nth-child(even)` selects all thirteen -- it would hide the
   marks entirely instead of thinning them. The wrappers are the only children of
   their parent, so counting them counts marks. */
@media (max-width: 900px) {
  .st-season-band .mantine-Group-root { flex-wrap: wrap; }
  .st-season-slider { flex: 1 0 100%; }
  .st-season-band .mantine-RangeSlider-markWrapper:nth-child(even)
  .mantine-RangeSlider-markLabel { display: none; }
}

/* ------------------------------------------------------------------ view tabs
   Two routes the reader moves between, drawn as a tab strip. Underline rather than a
   filled pill: the header already carries two SegmentedControls, and a third filled
   control directly under them read as a filter rather than as a place. */
.st-nav { display: flex; gap: 2px; align-items: flex-end; }
.st-nav-item {
  font-size: 12px; font-weight: 600; color: var(--st-muted);
  text-decoration: none; padding: 5px 10px 6px 10px;
  border-bottom: 2px solid transparent; line-height: 1.2;
}
.st-nav-item:hover { color: var(--st-ink); }
.st-nav-item.is-active {
  color: var(--st-ink); border-bottom-color: #3987e5;
}
