.is-hidden {
  display: none !important;
}

:root {
  --bg: #f8fafc;
  --surface: #ffffff;
  --text: #0f172a;
  --text-muted: #64748b;
  --border: #e2e8f0;
  --accent: #4338ca;
  --accent-hover: #3730a3;
  --row-alt: #f1f5f9;
  --ics-keyword: #1d4ed8;
  --ics-prop: #2563eb;
  --ics-param: #475569;
  --ics-continuation: #64748b;
  --json-key: #2563eb;
  --json-literal: #1d4ed8;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0f172a;
    --surface: #1e293b;
    --text: #f1f5f9;
    --text-muted: #94a3b8;
    --border: #334155;
    --accent: #818cf8;
    --accent-hover: #a5b4fc;
    --row-alt: #172033;
    --ics-keyword: #60a5fa;
    --ics-prop: #93c5fd;
    --ics-param: #cbd5e1;
    --ics-continuation: #94a3b8;
    --json-key: #93c5fd;
    --json-literal: #60a5fa;
  }
}

* {
  box-sizing: border-box;
}

html {
  overflow-x: hidden;
}

body {
  margin: 0;
  overflow-x: hidden;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
}

.container {
  max-width: 960px;
  margin: 0 auto;
  padding: 0 1.5rem;
}

.site-header {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.header-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding-top: 1rem;
  padding-bottom: 1rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--text);
  text-decoration: none;
}

.hamburger-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.5rem;
  border: none;
  border-radius: 6px;
  background: none;
  cursor: pointer;
  flex-shrink: 0;
}

.hamburger-btn:hover {
  background: var(--row-alt);
}

.hamburger-icon {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 1.15rem;
  height: 1.15rem;
}

.hamburger-icon span {
  display: block;
  width: 100%;
  height: 2px;
  background: var(--text);
  border-radius: 2px;
}

.nav-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  z-index: 40;
}

.nav-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}

.nav-drawer {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: 260px;
  max-width: 80vw;
  background: var(--surface);
  border-right: 1px solid var(--border);
  box-shadow: 4px 0 20px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 1rem;
  transform: translateX(-100%);
  transition: transform 0.2s ease;
  z-index: 50;
  overflow-y: auto;
}

.nav-drawer.is-open {
  transform: translateX(0);
}

.nav-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.nav-drawer-title {
  font-weight: 700;
  color: var(--text-muted);
  font-size: 0.85rem;
}

.nav-drawer-close {
  border: none;
  background: none;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  color: var(--text-muted);
  padding: 0.25rem;
  border-radius: 6px;
}

.nav-drawer-close:hover {
  background: var(--row-alt);
  color: var(--text);
}

.nav-drawer a {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.65rem 0.6rem;
  border-radius: 8px;
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
}

.nav-drawer a:hover {
  background: var(--row-alt);
  color: var(--accent);
}

body.nav-open {
  overflow: hidden;
}

.home-links {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 320px;
  margin-top: 1.5rem;
}

.home-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
}

.home-link:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* 今日の試合 (home/_next_game_day): a game a block, its pitchers and runs at stake under it. */
.next-game-day ul {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0;
}

.next-game-day li {
  margin: 0.75rem 0;
  line-height: 1.6;
}

main {
  padding: 2rem 1.5rem 4rem;
}

.og-preview {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1200 / 630;
  object-fit: cover;
  border-radius: 12px;
  border: 1px solid var(--border);
  margin-top: 2rem;
}

h1 {
  font-size: 1.75rem;
  margin-bottom: 1.5rem;
}

.week-heading {
  font-size: 1.1rem;
  margin: 2rem 0 0.75rem;
}

.week-heading:first-of-type {
  margin-top: 0;
}

.card-heading {
  font-size: 0.95rem;
  color: var(--text-muted);
  margin: 1.25rem 0 0.5rem;
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  color: var(--accent-hover);
  text-decoration: underline;
}

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

/* Each card within a week is its own separate <table>, so with the default
   auto layout, every one sizes its columns independently based only on its
   own content — the 対戦 column (score digit counts vary a lot: 6-2 vs
   1-10) ends up a different width table to table, so 観衆 doesn't line up
   between them. Fixed column widths keep every such table consistent. */
.week-games-table {
  table-layout: fixed;
}

.week-games-table .col-date {
  width: 22%;
}

.week-games-table .col-round {
  width: 13%;
}

.week-games-table .col-matchup {
  width: 40%;
}

.week-games-table .col-attendance {
  width: 25%;
}

th,
td {
  padding: 0.65rem 1rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

th {
  background: var(--row-alt);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

tbody tr:hover {
  background: var(--row-alt);
}

tbody tr:last-child td {
  border-bottom: none;
}

ul.list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.5rem;
}

ul.list li {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem 1rem;
}

@media (min-width: 640px) {
  .season-list {
    grid-template-columns: 1fr 1fr;
  }
}

.score {
  display: inline-flex;
  align-items: baseline;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0 0.35rem;
}

.score-num {
  display: inline-block;
  min-width: 1.4em;
}

.score-num-left {
  text-align: right;
}

.score-num-right {
  text-align: left;
}

.score-sep {
  padding: 0 0.3em;
}

.muted {
  color: var(--text-muted);
}

.table-scroll {
  overflow-x: auto;
}

/* table-layout: fixed (not the default auto) means the table's overall
   width is locked to its container regardless of content — col-rank/
   col-team stay pinned narrow (see their own width below) and every other
   column (the 6 vs-cells, the result/attendance stat columns) splits the
   remainder evenly. auto layout would instead grow the table past its
   container to fit each column's natural content width, which is what
   forced .table-scroll's scroll to kick in even after shrinking
   padding/font. */
.standings-table {
  table-layout: fixed;
}

.standings-table th,
.standings-table td {
  text-align: center;
  white-space: nowrap;
}

.standings-table th.col-team,
.standings-table td.col-team {
  text-align: left;
}

/* Attendance-mode cell text (e.g. "16,000/13,000/2,000") is much longer
   than results-mode's "○●○" — cell_toggle_controller.js inserts a real
   <br> after each "/" for this mode, which breaks the line regardless of
   white-space: nowrap, so no CSS wrapping rule is needed here. */

/* Wrapping instead of scrolling just traded one unreadable layout for
   another (○●○ splitting mid-cell, "勝ち点" stacking letter by letter).
   Fitting rank + team + the 6-team results grid on one line without
   either wrapping or scrolling is realistic; fitting that AND 6-8 more
   stat columns is not without shrinking text past legibility. So the
   results' trailing columns (試合 to 失点) are hidden outside "拡大表示" —
   the zoomed overlay has the room to show them on one line at a normal
   size. :not([hidden]) still defers to cell-toggle's own results-vs-
   attendance choice once zoomed. The attendance's two (総観衆/平均観衆) fit,
   and show either way, headings and figures alike; cell-toggle's hidden
   alone switches them. ~= matches a cell with other targets too (a figure
   is also an attendanceFigure): an exact match missed those, and left the
   attendance figures showing under hidden headings. */
.standings-table [data-cell-toggle-target~="resultsColumn"] {
  display: none;
}

.table-zoom.is-zoomed .standings-table [data-cell-toggle-target~="resultsColumn"]:not([hidden]) {
  display: table-cell;
}

/* table-layout: fixed takes a percentage width literally (unlike auto
   layout, where "1%" is a common shrink-to-content hack) — these need an
   actual size that fits a 1.5rem chip plus cell padding, or the column
   gets squeezed narrower than its own content and the chip/rank badge
   overlaps the next column. */
.col-rank,
.col-team {
  width: 2.75rem;
}

.season-tag {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: var(--row-alt);
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  margin: 0.15rem 0.2rem 0 0;
}

.rank-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 6px;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
}

.team-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 6px;
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
}

.grand-total-row td {
  border-top: 2px solid var(--border);
  font-weight: 700;
}

th.sortable {
  cursor: pointer;
  user-select: none;
}

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

th.sortable:hover {
  color: var(--accent);
}

/* The key's number shows only when a table is sorted by more than one
   (data-sort-rank: "1▲", "2▼"); attr() is empty otherwise. */
th.sortable.sorted-asc::after {
  content: " " attr(data-sort-rank) "▲";
}

th.sortable.sorted-desc::after {
  content: " " attr(data-sort-rank) "▼";
}

.sort-reset {
  margin-bottom: 0.5rem;
}

.avg-cell {
  font-weight: 700;
  border-left: 2px solid var(--border);
}

.sum-cell {
  font-weight: 700;
}

.result-cell {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.05em;
  background: #fff;
  color: #000;
}

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

.result-cell a .cell-line {
  display: block;
  font-size: 0.85em;
}

.result-cell a:hover {
  text-decoration: underline;
}

.standings-table tbody tr:hover td.result-cell {
  background: #fff;
}

.dash {
  color: var(--text-muted);
}

/* Every table's base th/td padding (0.65rem 1rem) is generous enough that
   dense tables (many short columns: standings, the matchup grid, a
   scoreboard's per-inning columns) don't fit unless padding/font shrink —
   not just on a phone: the standings/matchup grid (14 columns in the worst
   case) is wide enough to still overflow well past typical phone
   breakpoints, so these are unconditional, not gated to a narrow viewport.
   .table-zoom's "拡大表示" (below) sizes back up for reading comfortably. */
.standings-table th,
.standings-table td {
  padding: 0.35rem 0.4rem;
  font-size: 0.85rem;
}

.rank-badge,
.team-chip {
  width: 1.5rem;
  height: 1.5rem;
  font-size: 0.75rem;
}

.scoreboard-table th,
.scoreboard-table td {
  padding: 0.35rem 0.4rem;
  font-size: 0.85rem;
}

.scoreboard-table td.total {
  font-size: 1rem;
}

@media (max-width: 480px) {
  th,
  td {
    padding: 0.5rem 0.6rem;
  }
}

/* "拡大表示" — lets a dense table (still shrunk per above, still possibly
   needing .table-scroll's own scroll) pop out into a full-viewport overlay
   at a comfortably large, tap-friendly size instead. table-zoom-btn toggles
   .is-zoomed on the .table-zoom wrapper; [data-table-zoom-target="panel"]
   is whichever scroll container holds the table (.table-scroll or
   .scoreboard — both already scrollable, this just also resizes/repositions
   that same element, no cloning). */
.table-zoom-bar {
  text-align: right;
  margin-bottom: 0.35rem;
}

.table-zoom-btn {
  padding: 0.3rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.8rem;
  cursor: pointer;
}

.table-zoom-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.table-zoom-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 60;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

.table-zoom-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}

body.table-zoom-open {
  overflow: hidden;
}

/* top: 50% + transform (not top+bottom) centers the panel vertically in
   the original window and sizes it to its content, capped at 90vh — a
   short table (a 9-inning scoreboard) no longer sits pinned near the top
   with empty space below, or off-center once it's short enough not to
   need the full 90vh. left/right stay fixed (not centered via transform
   too) since that span is already exactly what "as wide as available,
   capped" means; only height is content-driven here. */
.table-zoom.is-zoomed [data-table-zoom-target="panel"] {
  position: fixed;
  top: 50%;
  left: 5vw;
  right: 5vw;
  max-height: 90vh;
  transform: translateY(-50%);
  z-index: 61;
  margin: 0;
  padding: 1rem;
  background: var(--surface);
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.35);
  overflow: auto;
}

.table-zoom.is-zoomed [data-table-zoom-target="panel"].scoreboard {
  background: #111827;
}

/* Both .table-zoom-bar (the zoom/close button) and .period-toolbar (on the
   standings page) are children of the panel now, not fixed-positioned
   siblings pinned to an assumed corner — the panel centers and resizes to
   its content, so there's no longer a fixed corner to pin to. Outside the
   panel, .table-zoom-backdrop (z-index: 60) would otherwise sit on top of
   their normal (unpositioned) stacking position and swallow clicks;
   sticky keeps the zoom/close button reachable at the top of the panel's
   own scroll area without leaving the panel (so it travels with it). */
.table-zoom.is-zoomed .table-zoom-bar {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  padding-bottom: 0.35rem;
}

.table-zoom.is-zoomed [data-table-zoom-target="panel"].scoreboard .table-zoom-bar {
  background: #111827;
}

/* table-layout: fixed (the default, unzoomed sizing) is what keeps the
   table from ever exceeding its container — but that guarantee comes from
   force-splitting columns evenly regardless of content, which at nowrap
   can clip/overlap text if a column ends up narrower than what's in it.
   Zoomed, there's no such requirement (the panel already scrolls both
   ways), so let the table size itself to its actual nowrap content
   instead — wider than the panel is fine, that's what the scroll is for. */
.table-zoom.is-zoomed .standings-table,
.table-zoom.is-zoomed .scoreboard-table {
  table-layout: auto;
  width: auto;
  min-width: 100%;
}

.table-zoom.is-zoomed .scoreboard-table th.team-col,
.table-zoom.is-zoomed .scoreboard-table td.team-col {
  width: auto;
}

.table-zoom.is-zoomed .standings-table th,
.table-zoom.is-zoomed .standings-table td,
.table-zoom.is-zoomed .scoreboard-table th,
.table-zoom.is-zoomed .scoreboard-table td {
  padding: 0.6rem 0.8rem;
  font-size: 1rem;
  white-space: nowrap;
}

.table-zoom.is-zoomed .rank-badge,
.table-zoom.is-zoomed .team-chip {
  width: 1.75rem;
  height: 1.75rem;
  font-size: 0.85rem;
}

.table-zoom.is-zoomed .scoreboard-table td.total {
  font-size: 1.1rem;
}

.decade {
  margin-bottom: 0.75rem;
}

.decade summary {
  cursor: pointer;
  font-weight: 700;
  padding: 0.5rem 0.25rem;
  color: var(--text);
}

.decade summary:hover {
  color: var(--accent);
}

.decade .list {
  margin-top: 0.5rem;
}

.ics-preview-toggle summary {
  cursor: pointer;
  font-weight: 700;
  padding: 0.5rem 0.25rem;
  color: var(--text);
}

.ics-preview-toggle summary:hover {
  color: var(--accent);
}

code {
  background: var(--row-alt);
  border-radius: 4px;
  padding: 0.1rem 0.35rem;
  font-size: 0.85em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: break-word;
}

.doc-code {
  margin: 0;
  padding: 0.75rem 1rem;
  overflow-x: auto;
  font-size: 0.8rem;
  line-height: 1.5;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.doc-code code {
  background: none;
  padding: 0;
}

.api-sandbox {
  margin: 0.5rem 0 1.5rem;
}

.sandbox-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

/* One bordered "window": the fixed GET/api/v1 part and the editable path
   part sit side by side with different colors, so it's clear at a glance
   which half you can actually type into. */
.sandbox-bar {
  display: flex;
  align-items: stretch;
  flex: 1;
  min-width: 200px;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}

.sandbox-fixed {
  display: flex;
  align-items: center;
  padding: 0.45rem 0.6rem;
  background: var(--row-alt);
  color: var(--text-muted);
  font-size: 0.8rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: nowrap;
  border-right: 1px solid var(--border);
}

.sandbox-editable {
  flex: 1;
  min-width: 60px;
  padding: 0.45rem 0.6rem;
  border: none;
  background: var(--surface);
  color: var(--accent);
  font-size: 0.8rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.sandbox-editable:focus {
  outline: none;
  background: var(--bg);
}

.sandbox-output {
  margin-top: 0.5rem;
}

.sandbox-output summary {
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.sandbox-output summary:hover {
  color: var(--accent);
}

.api-sandbox .doc-code {
  margin-top: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  white-space: pre-wrap;
  word-break: break-all;
}

.ics-preview {
  margin: 0.5rem 0 0;
  padding: 0.75rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow-x: auto;
  font-size: 0.8rem;
  line-height: 1.5;
  white-space: pre;
}

.ics-keyword {
  color: var(--ics-keyword);
  font-weight: 700;
}

.ics-prop {
  color: var(--ics-prop);
  font-weight: 600;
}

.ics-param {
  color: var(--ics-param);
}

.ics-continuation {
  color: var(--ics-continuation);
}

.json-key {
  color: var(--json-key);
  font-weight: 600;
}

.json-string {
  color: var(--text);
}

.json-number {
  color: var(--text-muted);
}

.json-literal {
  color: var(--json-literal);
  font-weight: 600;
}

.scoreboard {
  background: #111827;
  border-radius: 12px;
  padding: 1.25rem;
  overflow-x: auto;
  margin-bottom: 1.5rem;
}

.attendance-chart {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 1px;
  height: 120px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin: 0.5rem 0 1rem;
  /* No overflow-x here (unlike most scrollable tables in this app) —
     bars shrink to fit instead of scrolling, and this also means the
     tooltip below isn't clipped popping up above the container. */
}

.attendance-bar-wrap {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  max-width: 24px;
  height: 100%;
  display: flex;
  align-items: flex-end;
}

.attendance-bar {
  width: 100%;
  min-height: 2px;
  background: var(--accent);
  border-radius: 2px 2px 0 0;
}

.attendance-tooltip {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--text);
  color: var(--bg);
  font-size: 0.7rem;
  line-height: 1.4;
  padding: 0.25rem 0.4rem;
  border-radius: 4px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.1s;
  z-index: 10;
}

.attendance-bar-wrap:hover .attendance-tooltip,
.attendance-bar-wrap:focus .attendance-tooltip {
  opacity: 1;
}

.attendance-bar-wrap:hover .attendance-bar {
  background: var(--accent-hover);
}

.attendance-trend-chart {
  margin: 0.5rem 0 1.5rem;
}

.trend-chart-inner {
  position: relative;
}

.attendance-trend-chart svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* Invisible hit-targets positioned over each SVG point (percentage-based,
   so they track the responsive/scaled chart) — a plain HTML hover/focus
   tooltip is more reliable across browsers than the SVG-native <title>. */
.trend-hover-point {
  position: absolute;
  width: 16px;
  height: 16px;
  transform: translate(-50%, -50%);
  cursor: default;
}

.trend-tooltip {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.7rem;
  line-height: 1.4;
  padding: 0.25rem 0.4rem;
  border-radius: 4px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.1s;
  z-index: 10;
}

.trend-tooltip-current {
  background: var(--accent);
  color: #fff;
}

.trend-tooltip-previous {
  background: var(--text-muted);
  color: #fff;
}

.trend-hover-point:hover .trend-tooltip,
.trend-hover-point:focus .trend-tooltip {
  opacity: 1;
}

.trend-gridline {
  stroke: var(--border);
  stroke-width: 1;
}

.trend-axis-label {
  fill: var(--text-muted);
  font-size: 10px;
}

.trend-axis-unit {
  fill: var(--text-muted);
  font-size: 10px;
}

.trend-line {
  fill: none;
  stroke-width: 2.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.trend-line-current {
  stroke: var(--accent);
}

.trend-line-previous {
  stroke: var(--text-muted);
  stroke-dasharray: 5 4;
}

.trend-point {
  cursor: default;
}

.trend-point-current {
  fill: var(--accent);
}

.trend-point-previous {
  fill: var(--text-muted);
}

.trend-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 0.5rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.trend-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.trend-swatch {
  display: inline-block;
  width: 14px;
  height: 3px;
  border-radius: 2px;
}

.trend-swatch-current {
  background: var(--accent);
}

.trend-swatch-previous {
  background: var(--text-muted);
}

/* table-layout: fixed for the same reason as .standings-table — width:
   100% alone still lets the table grow past its container to fit every
   inning column's natural (nowrap) width. team-col gets an explicit width
   for the same reason col-rank/col-team do: a fixed-layout percentage/
   auto share would be too narrow for the team chip + name. */
.scoreboard-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  background: transparent;
  border: none;
}

.scoreboard-table th,
.scoreboard-table td {
  padding: 0.5rem 0.75rem;
  text-align: center;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  color: #f8fafc;
  white-space: nowrap;
}

.scoreboard-table th {
  background: transparent;
  color: #60a5fa;
  font-size: 0.75rem;
  letter-spacing: 0.03em;
}

.scoreboard-table th.team-col,
.scoreboard-table td.team-col {
  text-align: left;
  font-weight: 700;
  width: 5.5rem;
}

.scoreboard-table td.team-col .team-chip {
  margin-right: 0.4rem;
  vertical-align: middle;
}

.scoreboard-table td.total {
  font-weight: 700;
  color: #60a5fa;
  font-size: 1.1rem;
}

.scoreboard-table tbody tr:last-child td {
  border-bottom: none;
}

.scoreboard-table tbody tr:hover {
  background: rgba(255, 255, 255, 0.05);
}

.scoreboard-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2rem;
  margin: 0 0 1.5rem;
}

.scoreboard-meta div {
  display: flex;
  gap: 0.4rem;
}

.scoreboard-meta dt {
  color: var(--text-muted);
  font-weight: 600;
}

.scoreboard-meta dd {
  margin: 0;
}

.period-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.period-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.85rem;
  cursor: pointer;
}

.period-btn:hover {
  border-color: var(--accent);
}

.period-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* A season's pages as tabs (seasons/_tabs), scrolling sideways on a narrow screen rather than wrapping. */
.season-tabs {
  display: flex;
  gap: 0.25rem;
  margin: 0 0 1.25rem;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}

.season-tab {
  flex: none;
  padding: 0.5rem 0.9rem;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
}

.season-tab:hover {
  color: var(--text);
}

.season-tab.active {
  border-bottom-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

kbd {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--row-alt);
  color: var(--text-muted);
  font-size: 0.75rem;
  font-family: inherit;
}

.period-btn.active kbd {
  border-color: rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
}

.shortcuts-help {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

.shortcuts-help[hidden] {
  display: none;
}

.shortcuts-help-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.5rem;
  min-width: 260px;
  max-width: 90vw;
  max-height: 80vh;
  overflow-y: auto;
}

.shortcuts-help-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.shortcuts-help-panel h2 {
  margin: 0;
  font-size: 1.1rem;
}

.shortcuts-help-close {
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.25rem;
}

.shortcuts-help-close:hover {
  color: var(--text);
}

.shortcuts-help-panel ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.shortcuts-help-panel li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.shortcuts-help-panel .muted {
  margin: 1rem 0 0;
}

fieldset {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin: 0 0 1rem;
  padding: 0.75rem 1rem 1rem;
}

legend {
  padding: 0 0.4rem;
  color: var(--text-muted);
  font-size: 0.85rem;
}

.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.checkbox-label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.85rem;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.checkbox-label:hover {
  border-color: var(--accent);
}

.checkbox-label:has(input:checked) {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.checkbox-label input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.checkbox-label:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.year-range {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.year-range input[type="number"] {
  width: 6rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

.keyword-input {
  width: 100%;
  max-width: 24rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

.pagination {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 1rem 0;
}

.period-toolbar select {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

.stats-total td {
  font-weight: 700;
  border-top: 2px solid var(--border);
}

.sandbox-image {
  display: block;
  max-width: 100%;
  height: auto;
  margin-top: 0.5rem;
  border-radius: 6px;
}

.api-image img {
  display: block;
  width: 100%;
  max-width: 600px;
  height: auto;
  aspect-ratio: 1200 / 630;
  margin: 0.5rem 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--row-alt);
}

.api-image .sandbox-message {
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
}

.sort-link {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

.sort-link:hover {
  text-decoration: underline;
}

/* Headings of tables sorted in the browser (the sortable-table controller). */
th.sortable .sort-button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  white-space: nowrap;
}

th.sortable .sort-button:hover {
  color: var(--accent);
}

/* A bench member who didn't play in the game (games/_members). */
tr.bench-only td {
  color: var(--text-muted);
}

tr.bench-only td a {
  color: inherit;
}

/* A game's batting and pitching lines (games/_box_score): compact, numbers right-aligned, the name never wrapped. */
.box-score th,
.box-score td {
  padding: 0.4rem 0.6rem;
  text-align: right;
  white-space: nowrap;
}

.box-score th:first-child,
.box-score td:first-child,
.box-score td:nth-child(2),
.box-score .box-score-name,
.box-score tfoot th {
  text-align: left;
}

.box-score tfoot th,
.box-score tfoot td {
  font-weight: 700;
  background: var(--row-alt);
  border-bottom: none;
}

/* A substitute (pinch hitter, runner or defensive sub), set in under the starter replaced. */
.box-score tr.box-score-sub .box-score-name {
  padding-left: 1.4rem;
}

/* A game told in a few sentences, below its heading (games/show). */
.game-summary {
  margin: 0.5rem 0 1rem;
  line-height: 1.7;
}

/* 連続記録 (seasons/_streak_records): one run a line, its notes under it. */
.streak-records ul {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0;
}

.streak-records li {
  margin: 0.6rem 0;
  line-height: 1.6;
}

/* 優勝のゆくえ (seasons/_title_race): a compact grid, each cell the champion in its
   colours (white text, as on the team chips), a playoff's on a plain background. */
.title-race-table {
  width: auto;
}

.title-race-table th,
.title-race-table td {
  padding: 0.3rem 0.5rem;
  text-align: center;
  white-space: nowrap;
  font-size: 0.9rem;
}

.title-race-table .title-race-card {
  color: var(--text);
}

/* The faint line between the cards named down the left and the results along the top. */
.title-race-table thead th.title-race-edge {
  border-right: 1px solid var(--border);
}

.title-race-table td.title-race-cell {
  color: #fff;
  font-weight: 700;
  border: 1px solid var(--surface);
}

.title-race-table td.title-race-playoff {
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
}

/* The charts of a line for each university, game by game: the title chances
   and the strengths (seasons/_university_line_chart, line_chart_controller.js).
   The lines are in the universities' own colours, as in the title race grid.
   早大's, 慶大's and 明大's are dark, and faint on the dark surface (contrast
   1.1-1.5), and 早大's and 慶大's are close for red-green colour-blind readers:
   the line ends are labelled, and the figures are in the tooltip and the table
   under the chart. */
.line-chart {
  margin: 0.5rem 0 1rem;
}

.line-chart figcaption {
  margin-bottom: 0.25rem;
}

.line-chart-plot {
  position: relative;
}

.line-chart svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  touch-action: pan-y;
}

.line-chart svg:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.line-chart-gridline {
  stroke: var(--border);
  stroke-width: 1;
}

.line-chart-axis-label,
.line-chart-end-label {
  fill: var(--text-muted);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}

.line-chart-end-label {
  fill: var(--text);
}

.line-chart-line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* End markers and the hover dots: a ring in the surface colour keeps them clear of the lines they sit on. */
.line-chart-end {
  stroke: var(--surface);
  stroke-width: 2;
}

.line-chart-crosshair {
  stroke: var(--text-muted);
  stroke-width: 1;
}

.line-chart-tooltip {
  position: absolute;
  top: 0;
  z-index: 10;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.75rem;
  line-height: 1.5;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 2px 8px rgb(0 0 0 / 12%);
}

.line-chart-tooltip-heading {
  margin-bottom: 0.2rem;
  color: var(--text-muted);
}

.line-chart-tooltip-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-variant-numeric: tabular-nums;
}

.line-chart-tooltip-row strong {
  min-width: 3.2em;
  text-align: right;
}

/* A short stroke of the line's colour, as the key in the legend and the tooltip. */
.line-chart-key {
  display: inline-block;
  width: 14px;
  height: 2px;
  border-radius: 1px;
}

.line-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.line-chart-legend li {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.line-chart-note {
  margin: 0.25rem 0 0;
  font-size: 0.8rem;
}

.line-chart-table {
  margin-top: 0.5rem;
  font-size: 0.85rem;
}

.line-chart-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* The game buttons above the race (seasons/_title_race): a row of them for each
   week, its number first, the rows close together. */
.title-race-games {
  margin: 0.5rem 0;
}

.title-race-games .period-toolbar {
  margin-bottom: 0.4rem;
}

.title-race-week {
  min-width: 3.5em;
  font-size: 0.85rem;
}

/* 強さとは (seasons/strength): a formula set apart on a line of its own, and the
   small tables of figures, kept to their content's width. */
.formula {
  margin: 0.75rem 0;
  padding: 0.6rem 0.9rem;
  border-left: 3px solid var(--border);
  background: var(--surface);
  line-height: 1.9;
}

.university-summaries p {
  margin: 0.6rem 0;
  line-height: 1.8;
}

.formula-table {
  width: auto;
  margin: 0.5rem 0 1rem;
  font-variant-numeric: tabular-nums;
}

.formula-table th,
.formula-table td {
  padding: 0.3rem 0.6rem;
  text-align: center;
}

/* What changed from the team's previous game, above its roster (games/_roster_diff). */
.roster-diff {
  margin: 0.5rem 0;
}

.roster-diff p {
  margin: 0 0 0.25rem;
}

.roster-diff ul {
  margin: 0;
  padding-left: 1.25rem;
}

/* A message after an action, such as signing in (layouts/application). */
.flash {
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  background: var(--surface);
  padding: 0.6rem 0.9rem;
  border-radius: 6px;
}

.flash-alert {
  border-left-color: #dc2626;
}

/* The admin pages (admin/) and the sign-in page (sessions/new). */
.admin-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: space-between;
}

.admin-bar form {
  margin: 0;
}

.admin-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: 0.75rem;
  padding: 0;
  list-style: none;
}

.admin-stats li {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.6rem 0.9rem;
  background: var(--surface);
}

.admin-stats strong {
  display: block;
  font-size: 1.4rem;
}

/* How far a check has got, on the admin dashboard (CheckProgress). */
.admin-progress progress {
  width: 100%;
  max-width: 32rem;
  height: 0.9rem;
  accent-color: var(--accent);
}

.admin-progress p {
  margin: 0.25rem 0;
}

.admin-progress-table {
  max-width: 32rem;
}

.admin-progress-table td:not(:first-child),
.admin-progress-table th:not(:first-child) {
  text-align: right;
}

.admin-facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1rem;
}

.admin-facts dt {
  color: var(--text-muted);
}

.admin-facts dd {
  margin: 0;
}

.admin-decision {
  display: grid;
  gap: 0.5rem;
  max-width: 40rem;
}

.admin-decision textarea {
  font: inherit;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

@media (max-width: 600px) {
  .admin-facts {
    grid-template-columns: 1fr;
  }
}

/* The player page's game list (players/_games): a button opening a game's
   batting line in the row under it. */
.row-toggle-btn {
  border: none;
  background: none;
  color: var(--accent);
  cursor: pointer;
  font-size: 1rem;
  padding: 0 0.25rem;
  transition: transform 0.15s ease;
}

.row-toggle-btn[aria-expanded="true"] {
  transform: rotate(90deg);
}

.game-log-detail > td {
  background: var(--row-alt);
}

.game-log-detail table {
  margin: 0;
}

/* Read by screen readers, not shown. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.admin-decision input[type="text"] {
  font: inherit;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

.admin-notice {
  margin: 0 0 1rem;
  padding: 0.6rem 0.9rem;
  border-left: 4px solid var(--accent);
  background: var(--surface);
}

.admin-notice p {
  margin: 0.35rem 0 0;
  overflow-wrap: anywhere;
}

/* Notices to visitors: the latest few on the home page, all at /news. */
.news-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.75rem;
}

.news-list li {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.6rem 0.9rem;
  background: var(--surface);
}

.news-list h3 {
  margin: 0.15rem 0 0.35rem;
  font-size: 1rem;
}

.news-list p {
  margin: 0.25rem 0 0;
  overflow-wrap: anywhere; /* a long URL wraps instead of widening the page */
}

/* A notice at its own URL (news/show). */
.news-item p {
  overflow-wrap: anywhere;
}

/* The games data check (admin/game_checks). */
.game-check-games {
  margin: 0.25rem 0 0.5rem;
  padding-left: 1.2rem;
}

.game-check-review {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

.game-check-review input[type="text"] {
  flex: 1 1 16rem;
  font: inherit;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

/* The developers' notes, rendered from docs/ (developers/show). */
.markdown-body h1 {
  margin-top: 0.5rem;
}

.markdown-body h2 {
  margin-top: 2rem;
  padding-bottom: 0.25rem;
  border-bottom: 1px solid var(--border);
}

.markdown-body code {
  font-size: 0.9em;
  padding: 0.1em 0.35em;
  border-radius: 4px;
  background: var(--row-alt);
  overflow-wrap: anywhere;
}

.markdown-body pre {
  padding: 0.75rem 1rem;
  border-radius: 6px;
  background: var(--row-alt);
  overflow-x: auto;
}

.markdown-body pre code {
  padding: 0;
  background: none;
  overflow-wrap: normal;
}

.markdown-body table {
  display: block;
  overflow-x: auto;
  width: auto; /* not the 100% of other tables: it is set in from the left, and would run past the right */
}

.markdown-body blockquote {
  margin: 0 0 1rem;
  padding: 0.25rem 1rem;
  border-left: 4px solid var(--border);
  color: var(--text-muted);
}

/* The body text set in from the headings, so they stand out. */
.markdown-body > :not(h1, h2, h3, h4) {
  margin-left: 2em;
}

@media (max-width: 600px) {
  .markdown-body > :not(h1, h2, h3, h4) {
    margin-left: 1em;
  }
}

/* カードの順番で見るシーズン: each week's cards stacked, two chips a card. */
.card-orders-table td {
  vertical-align: top;
}

.card-order-card {
  display: flex;
  gap: 2px;
  margin-bottom: 4px;
  white-space: nowrap;
}

.card-orders-table td:last-child {
  min-width: 16rem;
}

/* 順位で見るシーズン: the places in a row, tied universities joined by ＝. */
.standings-orders-table td {
  vertical-align: top;
}

.standings-order-places {
  white-space: nowrap;
}

.standings-order-place {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}

.standings-order-sep,
.standings-order-tie {
  color: var(--text-muted);
  margin: 0 2px;
}

.standings-orders-table td:last-child {
  min-width: 16rem;
}

/* 日程の慣例: one column a convention, ○ × − ？. */
.conventions-rules {
  margin-bottom: 1.5rem;
}

.conventions-table .conventions-mark {
  text-align: center;
}

.conventions-broken {
  color: var(--accent);
  font-weight: 700;
}

.conventions-na,
.conventions-unknown {
  color: var(--text-muted);
}

.season-conventions {
  margin: 1rem 0;
}

.season-conventions summary {
  cursor: pointer;
}

/* A convention whose condition doesn't hold this season: greyed out. */
.conventions-row-na td {
  color: var(--text-muted);
}

/* A place in the standings that can still change: a plain number, the filled badge being kept for a decided one (seasons/standings, 順位のゆくえ). */
.rank-badge.open {
  background: transparent;
  color: var(--text);
}

/* 順位のゆくえ (seasons/_place_race): each university's possible places, then the final order for each way the open cards can end. */
.place-race-ranges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.25rem;
  padding: 0;
  list-style: none;
}

.place-race-table th,
.place-race-table td {
  text-align: center;
  white-space: nowrap;
}

.place-race-table .team-chip + .team-chip {
  margin-left: 0.15rem;
}
