/* ===== Rad Force shared design tokens =====
 * Canonical source. To propagate changes, run `ops/scripts/sync-tokens.sh`
 * which replaces the `:root { ... }` block at the top of each site's style.css.
 * Do NOT edit `:root` blocks in site stylesheets directly.
 */
:root {
  --pink: #ff2a8e;
  --cyan: #18e8ff;
  --orange: #ff6b3d;
  --bg: #0a0014;
  --fg: #f0e9ff;
  --fg-dim: #b9b0d9;

  --glow-pink: 0 0 6px rgba(255, 42, 142, 0.85),
               0 0 18px rgba(255, 42, 142, 0.55),
               0 0 36px rgba(255, 42, 142, 0.3);
  --glow-cyan: 0 0 6px rgba(24, 232, 255, 0.85),
               0 0 18px rgba(24, 232, 255, 0.55),
               0 0 36px rgba(24, 232, 255, 0.3);
  --glow-orange: 0 0 6px rgba(255, 107, 61, 0.85),
                 0 0 18px rgba(255, 107, 61, 0.55),
                 0 0 36px rgba(255, 107, 61, 0.3);

  --ff-display: "Monoton", system-ui, sans-serif;
  --ff-mono: "Space Mono", ui-monospace, monospace;
  --ff-body: "Space Grotesk", system-ui, sans-serif;
}

/* ===== Lineup Tool ===== */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { overflow-x: clip; }

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--ff-body);
  font-size: 16px;
  line-height: 1.5;
  min-height: 100vh;
  overflow-x: hidden;
}

/* ---------- Scanlines overlay (matches house style) ---------- */
.scanlines {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1000;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.03) 0 1px,
    transparent 1px 3px
  );
  mix-blend-mode: overlay;
}

.app {
  max-width: 720px;
  width: 100%;
  margin: 0 auto;
  padding: 24px 16px 56px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

@media (min-width: 40rem) {
  .app { padding: 40px 24px 72px; gap: 28px; }
}

/* ---------- Header ---------- */
.app-header { text-align: center; }

.app-title {
  font-family: var(--ff-display);
  font-weight: 400;
  font-size: clamp(1.8rem, 8vw, 2.6rem);
  letter-spacing: 0.02em;
  line-height: 1.1;
  margin: 0 0 8px;
  background: linear-gradient(90deg, var(--pink) 0%, var(--pink) 45%, var(--cyan) 55%, var(--cyan) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 12px rgba(255, 42, 142, 0.5)) drop-shadow(0 0 22px rgba(24, 232, 255, 0.35));
}

.app-subtitle {
  font-family: var(--ff-mono);
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  color: var(--fg-dim);
  margin: 0;
}

/* ---------- Nav ---------- */
.app-nav {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

@media (min-width: 40rem) {
  .app-nav { grid-template-columns: repeat(5, 1fr); gap: 10px; }
}

.nav-btn {
  min-height: 44px;
  padding: 10px 8px;
  border-radius: 8px;
  border: 1px solid var(--fg-dim);
  background: rgba(255, 255, 255, 0.02);
  color: var(--fg-dim);
  font-family: var(--ff-mono);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: border-color 120ms ease, color 120ms ease, box-shadow 120ms ease, background 120ms ease;
}

.nav-btn:last-child {
  grid-column: 1 / -1;
}

@media (min-width: 40rem) {
  .nav-btn:last-child { grid-column: auto; }
}

.nav-btn:hover,
.nav-btn:focus-visible {
  color: var(--fg);
  border-color: var(--cyan);
  outline: none;
}

.nav-btn[aria-current="true"] {
  color: var(--cyan);
  border-color: var(--cyan);
  background: rgba(24, 232, 255, 0.08);
  box-shadow: var(--glow-cyan);
  text-shadow: 0 0 6px rgba(24, 232, 255, 0.6);
}

/* ---------- Error banner ---------- */
.app-error {
  border: 1px solid var(--orange);
  border-radius: 8px;
  background: rgba(255, 107, 61, 0.08);
  color: var(--fg);
  font-family: var(--ff-mono);
  font-size: 0.85rem;
  line-height: 1.5;
  padding: 12px 14px;
  margin: 0;
  text-shadow: 0 0 6px rgba(255, 107, 61, 0.4);
}

/* ---------- Panels ---------- */
.panels { display: flex; flex-direction: column; }

.panel[hidden] { display: none; }

.panel-title {
  font-family: var(--ff-mono);
  font-size: 1.1rem;
  letter-spacing: 0.1em;
  color: var(--pink);
  text-shadow: var(--glow-pink);
  margin: 0 0 16px;
}

.panel-subtitle {
  font-family: var(--ff-mono);
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  color: var(--cyan);
  text-shadow: 0 0 6px rgba(24, 232, 255, 0.5);
  margin: 28px 0 12px;
}

.panel-placeholder {
  font-family: var(--ff-body);
  color: var(--fg-dim);
  line-height: 1.6;
}

/* ---------- Form fields ---------- */
.field-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
}

@media (min-width: 40rem) {
  .field-row { flex-direction: row; align-items: center; gap: 16px; }
  .field-row label { width: 220px; flex-shrink: 0; }
  .field-row input,
  .field-row select,
  .field-row textarea { flex: 1; }
}

label {
  font-family: var(--ff-mono);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--fg-dim);
}

input[type="text"],
input[type="number"],
input[type="date"],
input[type="file"],
select,
textarea {
  min-height: 44px;
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid var(--fg-dim);
  background: rgba(255, 255, 255, 0.03);
  color: var(--fg);
  font-family: var(--ff-body);
  font-size: 1rem;
}

input[type="file"] {
  padding: 8px 12px;
  font-family: var(--ff-mono);
  font-size: 0.85rem;
}

textarea {
  min-height: 110px;
  resize: vertical;
  font-family: var(--ff-mono);
  line-height: 1.5;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  border-color: var(--cyan);
  box-shadow: 0 0 0 2px rgba(24, 232, 255, 0.35);
}

input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

button {
  min-height: 44px;
  padding: 10px 18px;
  border-radius: 8px;
  border: 1px solid var(--orange);
  background: rgba(255, 107, 61, 0.06);
  color: var(--orange);
  font-family: var(--ff-mono);
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: background 120ms ease, box-shadow 120ms ease, transform 120ms ease;
}

button:hover,
button:focus-visible {
  background: rgba(255, 107, 61, 0.14);
  box-shadow: var(--glow-orange);
  outline: none;
  transform: translateY(-1px);
}

#add-kids { margin-bottom: 20px; }

/* ---------- Roster table ---------- */
.table-scroll {
  overflow-x: auto;
  border: 1px solid rgba(185, 176, 217, 0.35);
  border-radius: 8px;
}

.roster-table {
  width: 100%;
  min-width: 30rem;
  border-collapse: collapse;
  font-family: var(--ff-body);
  font-size: 0.92rem;
}

.roster-table th {
  text-align: left;
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--fg-dim);
  padding: 10px 12px;
  border-bottom: 1px solid rgba(185, 176, 217, 0.35);
}

.roster-table td {
  padding: 8px 12px;
  border-bottom: 1px solid rgba(185, 176, 217, 0.15);
  vertical-align: middle;
}

.roster-name { white-space: nowrap; }

.jersey-input {
  min-width: 4.5rem;
  min-height: 44px;
}

.size-select { min-height: 44px; }

.remove-btn {
  border-color: var(--pink);
  color: var(--pink);
  padding: 8px 14px;
  font-size: 0.78rem;
}

.remove-btn:hover,
.remove-btn:focus-visible {
  background: rgba(255, 42, 142, 0.1);
  box-shadow: var(--glow-pink);
}

/* ---------- Checkboxes ---------- */
.checkbox-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  margin-bottom: 14px;
  cursor: pointer;
}

.checkbox-row input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  min-height: 44px;
  margin: 0;
  border-radius: 8px;
  border: 1px solid var(--fg-dim);
  background: rgba(255, 255, 255, 0.03);
  cursor: pointer;
  position: relative;
}

.checkbox-row input[type="checkbox"]:checked {
  border-color: var(--cyan);
  background: rgba(24, 232, 255, 0.1);
  box-shadow: var(--glow-cyan);
}

.checkbox-row input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 15px;
  top: 9px;
  width: 8px;
  height: 16px;
  border-right: 3px solid var(--cyan);
  border-bottom: 3px solid var(--cyan);
  transform: rotate(45deg);
}

.checkbox-row input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(24, 232, 255, 0.35);
}

.checkbox-row input[type="checkbox"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.checkbox-row span {
  font-family: var(--ff-body);
  color: var(--fg);
  font-size: 0.95rem;
  line-height: 1.4;
}

.checkbox-note {
  display: block;
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  color: var(--fg-dim);
  margin-top: 2px;
}

.field-hint {
  font-family: var(--ff-mono);
  font-size: 0.75rem;
  color: var(--fg-dim);
  margin: -8px 0 20px;
}

/* ---------- Keep-apart rules ---------- */
.severity-copy {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  line-height: 1.7;
  color: var(--fg-dim);
  margin: -6px 0 20px;
}

.severity-copy strong {
  color: var(--fg);
}

#add-rule { margin-bottom: 20px; }

.rule-empty {
  font-family: var(--ff-body);
  color: var(--fg-dim);
  margin-bottom: 20px;
}

.rule-list {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rule-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid rgba(185, 176, 217, 0.35);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}

.rule-pair {
  font-family: var(--ff-body);
  color: var(--fg);
  font-weight: 600;
}

.rule-severity-badge {
  font-family: var(--ff-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid currentColor;
}

.rule-severity-hard { color: var(--pink); }
.rule-severity-soft { color: var(--cyan); }

.rule-note {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  color: var(--fg-dim);
  flex-basis: 100%;
}

.rule-row .remove-btn {
  margin-left: auto;
  border-color: var(--pink);
  color: var(--pink);
  padding: 8px 14px;
  font-size: 0.78rem;
}

.rule-row .remove-btn:hover,
.rule-row .remove-btn:focus-visible {
  background: rgba(255, 42, 142, 0.1);
  box-shadow: var(--glow-pink);
}

/* ---------- Position eligibility ---------- */
#add-eligibility { margin-bottom: 20px; }

.eligibility-empty {
  font-family: var(--ff-body);
  color: var(--fg-dim);
  margin-bottom: 20px;
}

.eligibility-rows {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 20px;
}

.eligibility-row {
  padding: 12px;
  border: 1px solid rgba(185, 176, 217, 0.35);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}

.eligibility-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}

.eligibility-pos-label {
  font-family: var(--ff-mono);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--fg);
}

.eligibility-count {
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  color: var(--fg-dim);
}

.eligibility-warning {
  font-family: var(--ff-body);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--fg);
  text-shadow: 0 0 6px rgba(255, 107, 61, 0.4);
  border: 1px solid rgba(255, 107, 61, 0.4);
  border-radius: 6px;
  background: rgba(255, 107, 61, 0.08);
  padding: 8px 10px;
  margin: 0 0 10px;
}

.eligibility-kids { margin-bottom: 0; }
.eligibility-kids .checkbox-row { margin-bottom: 4px; }

/* ---------- Guides links ---------- */
.rules-links {
  margin-top: 28px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rules-links a {
  font-family: var(--ff-mono);
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  color: var(--cyan);
  text-decoration: none;
  text-shadow: 0 0 6px rgba(24, 232, 255, 0.4);
}

.rules-links a:hover,
.rules-links a:focus-visible {
  text-decoration: underline;
  outline: none;
}

/* ---------- Game Day: attendance ---------- */
.attendance-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
  margin-bottom: 20px;
}

@media (min-width: 40rem) {
  .attendance-grid { grid-template-columns: repeat(2, 1fr); gap: 6px 16px; }
}

.gameday-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 4px 0 8px;
}

/* ---------- Game Day: the swap grid ---------- */
.grid-table {
  border-collapse: collapse;
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  min-width: 100%;
}

.grid-table th,
.grid-table td {
  padding: 4px;
  text-align: center;
}

.grid-table thead th {
  color: var(--fg-dim);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  padding: 8px 6px;
  white-space: nowrap;
}

.grid-table tbody th[scope="row"] {
  text-align: left;
  color: var(--fg-dim);
  white-space: nowrap;
  padding: 4px 10px 4px 4px;
  font-size: 0.72rem;
}

.grid-cell {
  min-height: 44px;
  min-width: 44px;
  width: 100%;
  padding: 6px 8px;
  border-radius: 6px;
  border: 1px solid rgba(185, 176, 217, 0.35);
  background: rgba(255, 255, 255, 0.03);
  color: var(--fg);
  font-family: var(--ff-mono);
  font-size: 0.76rem;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 120ms ease, box-shadow 120ms ease, color 120ms ease;
}

.grid-cell:hover,
.grid-cell:focus-visible {
  border-color: var(--cyan);
  outline: none;
}

.grid-cell.selected {
  border-color: var(--cyan);
  color: var(--cyan);
  box-shadow: var(--glow-cyan);
}

.grid-cell.violation {
  border-color: var(--pink);
  color: var(--pink);
  box-shadow: var(--glow-pink);
}

.grid-cell.violation-bent {
  border-color: var(--orange);
  color: var(--orange);
  box-shadow: var(--glow-orange);
}

.grid-cell:disabled {
  opacity: 0.6;
  cursor: default;
}

/* ---------- Game Day: field diagrams ---------- */
.field-views {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

@media (min-width: 40rem) {
  .field-views {
    flex-direction: row;
    flex-wrap: wrap;
  }

  /* flex: 1 1 0 alone lets three diagrams shrink to an equal share of the
   * row no matter how little that leaves each one — max-width below only
   * caps growth, never shrink, and the viewBox is fixed at 200x200, so a
   * narrower render means smaller absolute label spacing. At 15 kids and
   * three innings on this tool's own default width (.app caps out around
   * 672px of usable row) that shrinks each diagram to ~215px, where
   * labels crowd into each other. min-width plus flex-wrap gives the row
   * somewhere to put the overflow — two-across, with the third wrapping
   * to its own line — instead of squeezing all three to fit. */
  .field-diagram {
    flex: 1 1 0;
    min-width: 16rem;
  }
}

.field-diagram svg {
  width: 100%;
  height: auto;
  max-width: 22rem;
}

.fv-line {
  fill: none;
  stroke: var(--fg-dim);
  stroke-width: 0.7;
}

.fv-dot {
  fill: var(--cyan);
}

.fv-name {
  fill: var(--fg);
  font-family: var(--ff-mono);
  font-size: 9px;
  text-anchor: middle;
}

.fv-title {
  fill: var(--cyan);
  font-family: var(--ff-mono);
  font-size: 11px;
  text-anchor: middle;
}

.fv-bench {
  fill: var(--fg-dim);
  font-family: var(--ff-mono);
  font-size: 8px;
  text-anchor: middle;
}

/* ---------- Game Day: batting order ---------- */
.batting-order {
  list-style: decimal;
  margin: 0 0 24px;
  padding-left: 24px;
  font-family: var(--ff-body);
  color: var(--fg);
  line-height: 1.9;
}

/* ---------- Game Day: why panel ---------- */
.relax-heading {
  font-family: var(--ff-mono);
  font-size: 0.82rem;
  letter-spacing: 0.05em;
  margin: 16px 0 8px;
}

.relax-heading-broken { color: var(--pink); text-shadow: var(--glow-pink); }
.relax-heading-bent { color: var(--orange); text-shadow: 0 0 6px rgba(255, 107, 61, 0.4); }

.relax-list {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.relax-list li {
  font-family: var(--ff-body);
  font-size: 0.88rem;
  color: var(--fg);
  padding: 8px 10px;
  border: 1px solid rgba(185, 176, 217, 0.25);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
}

.relax-list li[data-severity="broken"] { border-color: rgba(255, 42, 142, 0.4); }
.relax-list li[data-severity="bent"] { border-color: rgba(255, 107, 61, 0.35); }

.relax-clean {
  font-family: var(--ff-mono);
  font-size: 0.9rem;
  color: var(--cyan);
  text-shadow: 0 0 6px rgba(24, 232, 255, 0.4);
  margin: 8px 0 24px;
}

/* ---------- Season table ---------- */
.season-table {
  width: 100%;
  min-width: 30rem;
  border-collapse: collapse;
  font-family: var(--ff-body);
  font-size: 0.92rem;
}

.season-table caption {
  caption-side: top;
  text-align: left;
  font-family: var(--ff-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--fg-dim);
  padding: 10px 12px;
}

.season-table th {
  text-align: left;
  font-family: var(--ff-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--fg-dim);
  padding: 10px 12px;
  border-bottom: 1px solid rgba(185, 176, 217, 0.35);
  white-space: nowrap;
}

.season-table td {
  padding: 8px 12px;
  border-bottom: 1px solid rgba(185, 176, 217, 0.15);
}

/* ---------- Backup screen ---------- */
.privacy-note {
  font-family: var(--ff-body);
  color: var(--fg-dim);
  line-height: 1.6;
  border: 1px solid rgba(185, 176, 217, 0.35);
  border-radius: 8px;
  padding: 12px 14px;
  margin: 0 0 24px;
}

#export { margin-bottom: 8px; }

/* ---------- Game Day: backup nudge ---------- */
.backup-nudge {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  color: var(--orange);
  text-shadow: 0 0 6px rgba(255, 107, 61, 0.4);
  margin: 0 0 16px;
}

/* ---------- Print card (screen: hidden; @media print: the whole page) ---------- */
.print-card,
.print-rules {
  display: none;
}

/* ---------- Back-link to the guides ----------
 * The spec's link graph runs both ways: guides link to the tool where
 * relevant, and the tool links back. Marked `.no-print` so it never lands
 * on the dugout card. */
.app-guides-link {
  margin: 32px 0 0;
  text-align: center;
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  color: var(--fg-dim);
}
.app-guides-link a {
  color: var(--cyan);
  text-decoration: none;
  border-bottom: 1px solid rgba(24, 232, 255, 0.35);
  text-shadow: 0 0 6px rgba(24, 232, 255, 0.45);
  transition: border-color 120ms ease, text-shadow 120ms ease;
}
.app-guides-link a:hover,
.app-guides-link a:focus-visible {
  border-bottom-color: var(--cyan);
  text-shadow: 0 0 10px rgba(24, 232, 255, 0.7);
  outline: none;
}

/* ---------- Footer ---------- */
.site-footer {
  margin-top: auto;
  text-align: center;
  color: var(--fg-dim);
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  opacity: 0.6;
  padding-top: 12px;
}

/* ---------- Print: the lineup card ----------
 * The one deliberate exception to "tokens only": the neon palette prints
 * as mud on a home inkjet, so this block hardcodes black-on-white instead
 * of var(--bg)/var(--fg). Everything interactive (nav, forms, buttons,
 * the why panel) is hidden; only the printable card survives — team name,
 * date/opponent, the innings grid, the batting order, and the league's
 * own rules text. Game Day's markup is never torn down to build this, it
 * is the same DOM the coach was just looking at, with chrome hidden and
 * the print-only card unhidden (see gameday-panel.js's `.no-print` /
 * `.print-card` / `.print-rules` wrappers). `#panel-gameday` and its
 * `!important` below are deliberately robust to printing from *any*
 * screen — e.g. a Ctrl+P — not just from a Print button click, which by
 * construction only ever fires while Game Day is already the visible
 * panel.
 *
 * `.app-header` (the `.app-title`) is hidden outright rather than
 * color-overridden: it renders via `background: linear-gradient(...)` +
 * `-webkit-background-clip: text; color: transparent`, so a naive
 * `color: #000` override does nothing while the clip/background are
 * still active — the safe fix is removing it from the page, not fighting
 * its fill. */
@media print {
  /* Landscape (round 3): portrait ran out of height before it ran out of
   * width — a 5-diagram softball card, at a diagram size that keeps labels
   * legible, needed more vertical room than an A4-portrait page has left
   * once the table, batting order, and rules are accounted for, and no
   * further screen-padding trim closed that gap without shrinking diagrams
   * back into illegibility. Landscape swaps which dimension is scarce:
   * ~1030px usable width against ~700px usable height, instead of
   * portrait's ~700×1030 (margin below is 0.6cm — matching what Chrome's
   * own print dialog calls "narrow" margins — rather than a roomier
   * 1.2cm, for the same reason: the 5-diagram softball card needed every
   * spare pixel of usable height it could get without shrinking diagrams
   * past the glyph floor). See `.print-layout` below for the two-column
   * shape that spends the now-abundant width instead of stacking
   * everything down the now-scarce height.
   *
   * `size` carries the ORIENTATION ONLY, deliberately — never a paper name.
   * Round 3 briefly wrote `size: A4 landscape`, which pins the page box to
   * 297×210mm; these are US volunteer coaches, and US Letter landscape is
   * 279.4×215.9mm, so the CSS box would be 18mm wider than the paper in the
   * tray and the driver would either crop it or scale it to fit (279.4/297
   * ≈ 94%). Under scaling the whole card shrinks 6% and the diagrams'
   * effective glyph drops from ~9.9px to ~9.3px — through the ~9.8px
   * legibility floor that `.print-layout`'s fixed 444px column exists to
   * defend. Orientation-only restores the paper-agnostic behaviour the card
   * had before this branch: the page box follows whatever is loaded, at
   * 1:1, so the glyph stays ~9.9px on both papers. Verified by generating
   * the card at both `format: "A4"` and `format: "Letter"` with
   * `preferCSSPageSize` — the PDF MediaBox comes back 842×596pt and
   * 792×612pt respectively (i.e. landscape, and following the paper),
   * against a pinned `A4 landscape`'s 842×595pt for BOTH. Note the repo's
   * one-page regression test necessarily prints A4, so it cannot see a
   * Letter regression here: keep the paper name out of `size`.
   *
   * Why 0.6cm and not less: 6mm is roughly 1mm clear of the hard
   * non-printable edge common on consumer inkjets, and their bottom feed
   * edge is often 10-12mm — which is exactly where the softball card's
   * ~8px of spare height puts the last diagram row and its `Bench:` line,
   * so anything tighter buys page-fit headroom by feeding content into the
   * clip zone. Why not more: 0.8cm costs ~15.1px of usable height, which is
   * essentially all of 15-kid tball's A4 slack (measured: A4 spills to two
   * pages at 0.85cm, i.e. ~15px spare; softball at 0.75cm, ~8px spare).
   * Letter's shorter-but-wider landscape page is the easier fit of the two,
   * not the harder one — ~204mm usable height against A4's ~198mm, worth
   * ~19-23px more room per config. */
  @page {
    size: landscape;
    margin: 0.6cm;
  }

  body {
    background: #fff;
    color: #000;
  }

  /* `.app`'s screen padding (40px/72px top/bottom at this width, sized for
   * scroll comfort and bottom-nav clearance) and `.panel-subtitle`'s 28px
   * top margin (sized for breathing room between screen sections) both
   * come along for free once `#panel-gameday` prints — together they cost
   * over 150px of blank page that a `@page` margin (below) already
   * covers. Trimmed here rather than lowered globally: on screen this is
   * still a comfortable scroll layout, not a printed page. `max-width`
   * also has to go: 720px was sized for a comfortable *portrait* reading
   * column, and left over 300px of the landscape page's width unused. */
  .app {
    padding: 4px 0 0;
    max-width: none;
  }

  .panel-subtitle {
    margin: 10px 0 6px;
  }

  .scanlines,
  .app-header,
  .app-nav,
  .app-error,
  .site-footer,
  .no-print {
    display: none !important;
  }

  .panel {
    display: none !important;
  }

  #panel-gameday {
    display: block !important;
  }

  .print-card,
  .print-rules {
    display: block;
  }

  .print-card-title {
    font-family: var(--ff-body);
    font-size: 1.4rem;
    font-weight: 700;
    color: #000;
    margin: 0 0 4px;
  }

  .print-card-meta {
    font-family: var(--ff-body);
    color: #000;
    margin: 0 0 6px;
  }

  .print-rules-title {
    font-family: var(--ff-body);
    font-size: 1rem;
    color: #000;
    margin: 10px 0 6px;
  }

  .print-rules p {
    color: #000;
    white-space: pre-wrap;
    margin: 0;
  }

  .panel-title,
  .panel-subtitle {
    color: #000;
    text-shadow: none;
  }

  .table-scroll {
    overflow: visible;
    border: 1px solid #000;
  }

  /* REVISION (round 3, landscape): two earlier shapes are preserved here
   * only in comment history, not in the cascade — round 1 was a 60/40
   * split sharing one row (table left, diagrams squeezed to ~128px in a
   * 40% column, sized against a stale vertical-budget guess); round 2 was
   * a full-width table on top with diagrams as a full-width row below,
   * legible (~230px) but unable to fit a 5-diagram softball card on one
   * *portrait* page. Landscape (see `@page` above) makes width the
   * abundant resource, so this goes back to a column split, but a
   * measured one: `.print-left` groups the table, batting order, and
   * rules into one grid item (the same grouping fix round 1 needed —
   * un-grouped siblings scatter across auto-placed grid cells); the
   * diagrams are the second column, sized in `.field-views` below. The
   * right column is a fixed 444px, not a fraction of the page width,
   * deliberately: at 2-across that gives a ~220px diagram cell (~9.9px
   * effective glyph, clearing round 2's ~9.8px floor, tightly — softball's
   * 5-diagram card needed every spare pixel of height that a smaller
   * fixed cell size banks, 1:1, since the diagrams are square) and, just
   * as importantly, keeps that size fixed if the
   * `@page` margin below is ever retuned again — an `fr` split would
   * have let a wider page inflate the diagrams (and, for softball's
   * 5-diagram card, their row height right along with them), silently
   * eating back any margin savings instead of banking them as page-count
   * headroom. The left column absorbs whatever width is left, which is
   * comfortably enough for the table (short cell content, non-wrapping)
   * at every roster size.
   *
   * Real printing never sees anything but the two-column shape below —
   * `@page`'s landscape A4 box is ~1077px usable wide at this margin, so
   * `min-width: 700px` always holds when a browser actually rasterizes
   * the page. It only matters as a fallback for print *contexts* narrower
   * than that: `page.emulateMedia({media:'print'})` (used by this file's
   * own tests, and by anyone eyeballing print styles via devtools) lays
   * the page out at the browser's *current* viewport rather than paper
   * size, and on a phone-width viewport a bare `minmax(0, 1fr)` beside a
   * fixed 444px track has nowhere to go but 0 — collapsing `.print-left`
   * and hiding the league-rules text inside it entirely (caught by
   * `backup.spec.js`'s "one page of black on white" test on the `mobile`
   * project, which doesn't pin a viewport — deliberately, since it's
   * testing print styles generally, not this specific layout). Below
   * `min-width: 700px`, stack single-column instead: block flow can't
   * collapse the way a starved grid track can. */
  .print-layout {
    display: block;
  }

  .field-views {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 6px;
    margin-top: 8px;
  }

  .field-diagram {
    min-width: 0;
    break-inside: avoid;
  }

  @media (min-width: 700px) {
    .print-layout {
      display: grid;
      grid-template-columns: minmax(0, 1fr) 444px;
      column-gap: 20px;
      align-items: start;
    }

    .print-left {
      min-width: 0;
    }

    .field-views {
      grid-template-columns: repeat(2, 1fr);
      gap: 4px;
      align-content: start;
      margin-top: 0;
    }
  }

  .field-diagram svg {
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    max-width: 100%;
    margin: 0 auto;
    display: block;
  }

  /* Forces the diagrams' neon screen colours (--fg-dim, --cyan, --fg) to
   * the same hardcoded black ink as the rest of this block, for the same
   * reason: those tokens render as mud, or vanish outright, on a home
   * inkjet. */
  .fv-line {
    stroke: #000;
  }

  .fv-dot {
    fill: #000;
  }

  .fv-name,
  .fv-title,
  .fv-bench {
    fill: #000;
  }

  .grid-table,
  .batting-order {
    color: #000;
  }

  .grid-table th,
  .grid-table td {
    border: 1px solid #000;
    padding: 1px 3px;
  }

  .grid-table thead th {
    padding: 2px 4px;
  }

  .grid-table tbody th[scope="row"] {
    padding: 1px 6px 1px 3px;
  }

  /* One page is the whole point of the card: a coach holds it in one hand
   * in the dugout. Keep the grid and the order each whole, and keep the
   * pair of them off a second sheet. */
  .grid-table,
  .batting-order {
    break-inside: avoid;
  }

  .batting-order {
    line-height: 1.35;
    margin-bottom: 6px;
    columns: 2;
    column-gap: 28px;
  }

  .batting-order li {
    break-inside: avoid;
  }

  .grid-table thead th {
    color: #000;
  }

  .grid-table tbody th[scope="row"] {
    color: #000;
  }

  /* The 44px floor is a touch target — meaningless on paper, and at 12
   * rows x 3 innings it was most of the reason the card ran to two pages.
   * Dropped here rather than lowered globally: on screen this is still a
   * button a coach taps with a thumb, standing on grass. */
  .grid-cell {
    min-height: 0;
    min-width: 0;
    padding: 1px 4px;
    border-radius: 0;
    border: 1px solid #000 !important;
    background: transparent !important;
    color: #000 !important;
    box-shadow: none !important;
    text-shadow: none !important;
    font-size: 0.68rem;
    line-height: 1.2;
  }

  /* A locked game — the one a coach actually prints — renders its cells
   * `disabled`, which on screen fades them to 60% opacity. Left alone,
   * that reads as washed-out grey ink instead of the solid black the
   * rest of this block establishes. */
  .grid-cell:disabled {
    opacity: 1;
  }
}
