/* RCJ Scoreboard — Linear Light theme
 * -------------------------------------------------------------------
 * Palette aligned to cms.robocup.org (warm off-white + RoboCup orange
 * + burgundy). Sits on top of Bootstrap 5 so un-rewritten templates
 * inherit the theme via component overrides. New pages should lean on
 * the shell + component primitives defined in this file rather than
 * Bootstrap utilities.
 *
 * Source-of-truth mockups: docs/redesign-mockups/v3/linear-light/
 * -------------------------------------------------------------------
 */

/* ═══ Fonts ═══ */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap');

/* ═══ Tokens ═══ */
:root {
  --bg:          #f8f5f1;
  --surface:     #ffffff;
  --surface-2:   #f0ebe7;
  --line:        #e8e2dc;
  --line-2:      #d4cdd2;
  --ink:         #2c1a10;
  --ink-2:       #5c5250;
  --mute:        #9b9290;
  --dim:         #b8b0ac;
  --accent:      #f26223;
  --accent-h:    #d9531a;
  --accent-soft: #fdf2f0;
  --emphasis:    #4d0b18;
  --emphasis-h:  #3a0812;
  --emphasis-soft:#f5e8e8;
  --ok:          #15803d;
  --ok-soft:     #e7f4ea;
  --warn:        #8a5a00;
  --warn-soft:   #fbefd2;
  --danger:      #4d0b18;
  --danger-soft: #f5e8e8;

  /* Bootstrap 5.2+ CSS-var hooks — reskins stock components without !important. */
  --bs-body-bg: var(--bg);
  --bs-body-color: var(--ink);
  --bs-body-font-family: 'Inter', system-ui, -apple-system, sans-serif;
  --bs-body-font-size: 13.5px;
  --bs-body-line-height: 1.5;
  --bs-border-color: var(--line);
  --bs-border-radius: 6px;
  --bs-border-radius-sm: 4px;
  --bs-primary: var(--accent);
  --bs-primary-rgb: 242, 98, 35;
  --bs-secondary: var(--ink-2);
  --bs-danger: var(--danger);
  --bs-danger-rgb: 77, 11, 24;
  --bs-success: var(--ok);
  --bs-warning: var(--warn);
  --bs-link-color: var(--accent);
  --bs-link-hover-color: var(--accent-h);
  --bs-link-color-rgb: 242, 98, 35;
}

/* ═══ Base ═══ */
*, *::before, *::after { box-sizing: border-box; }
html, body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 13.5px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  margin: 0;
}

h1, h2, h3, h4, h5, h6 {
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-top: 0;
}
h1, .h1 { font-size: 22px; line-height: 1.25; }
h2, .h2 { font-size: 18px; line-height: 1.3; }
h3, .h3 { font-size: 16px; }
h4, .h4 { font-size: 15px; font-weight: 600; }
h5, .h5 { font-size: 14px; font-weight: 600; }
h6, .h6 { font-size: 13px; font-weight: 600; }
.display-1, .display-2, .display-3, .display-4, .display-5, .display-6 {
  font-weight: 600; letter-spacing: -0.02em; color: var(--ink);
}
.display-5 { font-size: 32px; }

code, kbd, samp, pre, .mono {
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
  font-size: 0.92em;
}
code {
  color: var(--accent);
  background: var(--accent-soft);
  padding: 1px 6px;
  border-radius: 4px;
  border: 1px solid rgba(242, 98, 35, 0.22);
  font-size: 0.88em;
}
.text-muted { color: var(--mute) !important; }
.lead { color: var(--ink-2); font-weight: 400; font-size: 15px; }
small { color: var(--mute); }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-h); text-decoration: underline; text-underline-offset: 2px; }

/* ═══ App shell ═══ */
.app {
  display: grid;
  grid-template-columns: 232px 1fr;
  /* topbar | body | footer. The body row is 1fr under min-height:100vh,
     so the auto footer row sticks to the viewport bottom on short pages
     and falls below the content on long ones. */
  grid-template-rows: 48px 1fr auto;
  min-height: 100vh;
}
.app.nosidebar { grid-template-columns: 1fr; }
.app.nosidebar .sidebar { display: none; }
.app.nosidebar .main { grid-column: 1; }
.topbar {
  grid-column: 1 / -1;
  grid-row: 1;
  display: flex;
  align-items: center;
  gap: 0;
  padding: 0 14px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  position: sticky;
  top: 0;
  z-index: 20;
}
.sidebar {
  grid-column: 1;
  grid-row: 2;
  border-right: 1px solid var(--line);
  background: var(--surface);
  overflow-y: auto;
  max-height: calc(100vh - 48px);
  position: sticky;
  top: 48px;
}
.main {
  grid-column: 2;
  grid-row: 2;
  background: var(--bg);
  min-width: 0;
}

/* Drawer trigger. Hidden on desktop (the sidebar is always visible there);
   revealed as the hamburger in the ≤760px block below. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-right: 10px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--ink-2);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.nav-toggle:hover { background: var(--surface-2); color: var(--ink); }

/* Backdrop behind the open drawer. CSS-driven via .app.nav-open so it
   stays hidden when JS is unavailable. */
.nav-scrim {
  display: none;
  position: fixed;
  inset: 48px 0 0 0;
  background: rgba(44, 26, 16, 0.32);
  z-index: 25;
}

@media (max-width: 760px) {
  .app { grid-template-columns: 1fr; }
  .main { grid-column: 1; }
  /* The breadcrumb trail and the (decorative, keyboard-only) command
     bar force the topbar wider than a phone viewport, causing
     horizontal overflow of the whole page. Drop both on small screens;
     the page heading conveys location and the bar is non-functional. */
  .topbar .crumbs,
  .topbar .kbar { display: none; }

  /* Revealed only once nav.js adds .nav-ready, so a no-JS page never shows
     a hamburger that can't open the (JS-driven) drawer. */
  .app.nav-ready .nav-toggle { display: inline-flex; }

  /* The sidebar becomes an off-canvas drawer: fixed, parked off the left
     edge, slid into view when .app gains .nav-open (toggled in nav.js).
     Reuses the same _sidebar.html partial as the desktop rail. */
  .sidebar {
    position: fixed;
    top: 48px;
    left: 0;
    bottom: 0;
    width: 264px;
    max-height: none;
    z-index: 30;
    transform: translateX(-100%);
    /* Closed: off-canvas AND removed from the tab order / a11y tree so
       keyboard and screen-reader users can't land on hidden nav links.
       visibility transitions discretely at the end of the slide-out. */
    visibility: hidden;
    transition: transform 0.2s ease, visibility 0.2s ease;
    box-shadow: 2px 0 14px rgba(44, 26, 16, 0.14);
  }
  .app.nav-open .sidebar { transform: translateX(0); visibility: visible; }
  .app.nav-open .nav-scrim { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
}

/* ═══ Topbar ═══ */
.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-right: 16px;
  border-right: 1px solid var(--line);
  height: 100%;
}
.brand .brand-mark {
  width: 20px; height: 20px; border-radius: 4px;
  background: var(--accent); color: #fff;
  font-family: 'Geist Mono', monospace;
  font-weight: 700; font-size: 12px;
  display: grid; place-items: center;
}
.brand .brand-name {
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.01em;
  font-size: 14px;
}
.brand .brand-name:hover { color: var(--ink); text-decoration: none; }
.brand .brand-slash { color: var(--line-2); }
.brand .brand-sub { color: var(--mute); font-size: 12px; }

.crumbs {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 14px;
  color: var(--ink-2);
  font-family: 'Geist Mono', monospace;
  font-size: 12px;
  flex-wrap: wrap;
  min-width: 0;
  overflow: hidden;
}
.crumbs a { color: var(--mute); }
.crumbs a:hover { color: var(--ink); text-decoration: underline; }
.crumbs .sep { color: var(--line-2); }
.crumbs .cur { color: var(--ink); }

.topbar-spacer { flex: 1; }

.kbar {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  padding: 5px 10px;
  border-radius: 6px;
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 12px;
  min-width: 220px;
  cursor: pointer;
}
.kbar .kbd {
  border: 1px solid var(--line-2);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 10.5px;
  color: var(--ink-2);
  background: var(--surface);
  font-family: 'Geist Mono', monospace;
}

.avatar {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), #f47d47);
  margin-left: 12px;
  color: #fff;
  font-size: 11px;
  display: grid; place-items: center;
  font-weight: 600;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 12px;
}
.topbar-actions .logout-form { display: inline-block; margin: 0; }

/* ═══ Footer ═══ */
/* Full-width footer spanning both shell columns at the bottom row.
   Holds outbound links and the deployed-commit hash (the build that's
   live, resolved in core.context_processors). Wraps rather than hides
   the hash on narrow screens. */
.site-footer {
  grid-column: 1 / -1;
  grid-row: 3;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 16px;
  min-height: 40px;
  padding: 8px 14px;
  border-top: 1px solid var(--line);
  background: var(--surface);
  font-size: 12px;
  color: var(--mute);
}
.site-footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
.site-footer-links a,
.site-footer-commit {
  color: var(--mute);
  text-decoration: none;
}
.site-footer-links a:hover,
.site-footer-commit:hover { color: var(--accent); }

/* ═══ Sidebar ═══ */
.side-section {
  padding: 14px 14px 6px;
  color: var(--mute);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 500;
}
.side-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  color: var(--ink-2);
  cursor: pointer;
  position: relative;
  font-size: 13px;
  text-decoration: none;
  border-left: 2px solid transparent;
}
.side-item:hover {
  color: var(--ink);
  background: var(--surface-2);
  text-decoration: none;
}
.side-item.active {
  color: var(--ink);
  background: var(--accent-soft);
  font-weight: 500;
  border-left-color: var(--accent);
}
.side-item .icon {
  width: 14px;
  color: var(--mute);
  flex: 0 0 auto;
  font-size: 12px;
  display: inline-grid;
  place-items: center;
}
.side-item.active .icon { color: var(--accent); }
.side-item .count {
  margin-left: auto;
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 11px;
}
.side-item.nested { padding-left: 30px; font-size: 12.5px; }
.side-item.nested-2 { padding-left: 48px; font-size: 12px; color: var(--mute); }
.side-item.disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}
.side-sep { height: 1px; background: var(--line); margin: 8px 12px; }

/* ═══ Main head + meta ═══ */
.main-head {
  padding: 22px 28px 14px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.main-head h1 {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.main-head .eyebrow {
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 11.5px;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.main-head .sub {
  color: var(--mute);
  margin-top: 6px;
  font-family: 'Geist Mono', monospace;
  font-size: 12.5px;
  line-height: 1.5;
}
.main-head .sub a { color: var(--mute); }
.main-head .sub a:hover { color: var(--ink); }
.main-head-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.meta-row {
  display: flex;
  gap: 8px;
  padding: 0 28px 14px;
  align-items: center;
  flex-wrap: wrap;
}

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 28px;
  border-top: 1px solid var(--line);
  background: var(--surface);
}
.section-head h2 {
  font-size: 14px;
  font-weight: 600;
  margin: 0;
}
.section-head .muted {
  color: var(--mute);
  font-weight: 400;
  margin-left: 6px;
  font-family: 'Geist Mono', monospace;
  font-size: 12px;
}

/* Content wrapper used by plain pages */
.page {
  padding: 22px 28px 80px;
  max-width: 1280px;
}

/* Messages wrap (top of main) */
.messages-wrap {
  padding: 14px 28px 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.messages-wrap .alert { margin: 0; }

/* ═══ Pills + chips + identifier badges ═══ */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Geist Mono', monospace;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 4px;
  border: 1px solid var(--line-2);
  color: var(--ink-2);
  background: var(--surface);
}
.pill.ok      { color: var(--ok);       border-color: rgba(21,128,61,.3);  background: var(--ok-soft); }
.pill.accent  { color: var(--accent);   border-color: rgba(242,98,35,.3);  background: var(--accent-soft); }
.pill.mute    { color: var(--mute);     border-color: var(--line-2);       background: var(--surface-2); }
.pill.warn    { color: var(--warn);     border-color: rgba(138,90,0,.3);   background: var(--warn-soft); }
.pill.danger  { color: var(--danger);   border-color: rgba(77,11,24,.3);   background: var(--danger-soft); }
.pill.big     { font-size: 12px; padding: 3px 10px; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px dashed var(--line-2);
  padding: 3px 9px;
  border-radius: 999px;
  color: var(--mute);
  font-size: 12px;
  cursor: pointer;
}
.chip.on {
  border-style: solid;
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}

.lg-code {
  font-family: 'Geist Mono', monospace;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 3px 10px;
  border-radius: 4px;
  font-size: 13px;
  letter-spacing: 0.04em;
  border: 1px solid rgba(242, 98, 35, 0.25);
}

.kbd, kbd {
  border: 1px solid var(--line-2);
  padding: 0 5px;
  border-radius: 3px;
  font-size: 10.5px;
  color: var(--mute);
  background: var(--surface-2);
  font-family: 'Geist Mono', monospace;
}

/* ═══ Buttons (mockup + Bootstrap overrides in one block) ═══ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  padding: 6px 11px;
  border-radius: 6px;
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  transition: background .12s, border-color .12s, color .12s;
  cursor: pointer;
  line-height: 1.3;
}
.btn:hover { background: var(--surface-2); border-color: var(--ink-2); color: var(--ink); text-decoration: none; }
.btn-sm, .btn.sm { padding: 4px 9px; font-size: 11.5px; }
.btn-lg { padding: 9px 16px; font-size: 14px; }

.btn-primary, .btn.primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.btn-primary:hover, .btn-primary:focus, .btn.primary:hover {
  background: var(--accent-h); border-color: var(--accent-h); color: #fff;
}
.btn-outline-primary {
  color: var(--accent); border-color: rgba(242,98,35,.45); background: var(--surface);
}
.btn-outline-primary:hover {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent-h);
}
.btn-secondary, .btn-outline-secondary {
  color: var(--ink-2); background: var(--surface); border-color: var(--line-2);
}
.btn-outline-secondary:hover, .btn-secondary:hover {
  color: var(--ink); background: var(--surface-2); border-color: var(--ink-2);
}
.btn-danger, .btn-outline-danger, .btn.danger {
  color: var(--danger); background: var(--surface); border-color: rgba(77,11,24,.4);
}
.btn-outline-danger:hover, .btn-danger:hover, .btn.danger:hover {
  background: var(--danger-soft); border-color: var(--danger); color: var(--emphasis-h);
}
.btn-warning, .btn-outline-warning, .btn.warn {
  color: var(--warn); background: var(--surface); border-color: rgba(138,90,0,.4);
}
.btn-outline-warning:hover, .btn-warning:hover, .btn.warn:hover {
  background: var(--warn-soft); border-color: var(--warn); color: var(--warn);
}
.btn-success, .btn-outline-success {
  color: var(--ok); background: var(--surface); border-color: rgba(21,128,61,.4);
}
.btn-outline-success:hover, .btn-success:hover {
  background: var(--ok-soft); border-color: var(--ok); color: var(--ok);
}

.btn-primary .kbd, .btn.primary .kbd {
  border-color: rgba(255,255,255,.3);
  color: rgba(255,255,255,.85);
  background: rgba(255,255,255,.12);
}

/* Bootstrap btn-group — lose the default radii joins, match the mockup */
.btn-group .btn { border-radius: 0; }
.btn-group .btn:first-child { border-radius: 6px 0 0 6px; }
.btn-group .btn:last-child { border-radius: 0 6px 6px 0; }
.btn-group .btn + .btn { border-left-width: 0; }
.btn-group .btn + .btn:hover { border-left-width: 1px; margin-left: -1px; }

/* ═══ Tables ═══ */
.table {
  --bs-table-bg: var(--surface);
  --bs-table-color: var(--ink);
  --bs-table-border-color: var(--line);
  --bs-table-hover-bg: var(--surface-2);
  margin-bottom: 0;
  font-size: 13px;
}
.table > :not(caption) > * > * {
  padding: 8px 12px;
  border-bottom-color: var(--line);
}
.table thead th, .table thead td {
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 500;
  padding: 9px 12px;
  background: var(--surface);
  border-bottom: 1px solid var(--line) !important;
}
.table-sm > :not(caption) > * > * { padding: 6px 10px; }

/* Bootstrap state tints, reskinned for diff screens */
.table-danger, .table-danger > th, .table-danger > td {
  --bs-table-bg: var(--danger-soft);
  color: var(--ink-2);
  box-shadow: inset 3px 0 0 var(--danger);
}
.table-warning, .table-warning > th, .table-warning > td {
  --bs-table-bg: var(--warn-soft);
  color: var(--ink-2);
  box-shadow: inset 3px 0 0 var(--warn);
}
.table-success, .table-success > th, .table-success > td {
  --bs-table-bg: var(--ok-soft);
  color: var(--ink-2);
  box-shadow: inset 3px 0 0 var(--ok);
}

/* Wrap loose .table elements in a framed look */
main .table:not(.table-borderless),
main .table-responsive {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}

/* ═══ Linked table rows — the whole row is one clickable link ═══
 * Add `linked-rows` to the .table, `row-link` to the single per-row
 * anchor, and `data-href` to each <tr>. The anchor keeps the row
 * keyboard-focusable and working with no JS; row-link.js expands the
 * click/tap hit area to the whole row for mouse and touch. */
.table.linked-rows tbody tr[data-href] { cursor: pointer; }
.table.linked-rows tbody tr[data-href]:hover > *,
.table.linked-rows tbody tr[data-href]:active > *,
.table.linked-rows tbody tr:has(a.row-link:focus-visible) > * {
  background: var(--surface-2);
}
.table.linked-rows td a.row-link { color: var(--ink); font-weight: 500; text-decoration: none; }
/* Suppress the global a:hover accent+underline so the row reads as a row,
   not a text link, when hovered. */
.table.linked-rows td a.row-link:hover { color: var(--ink); text-decoration: none; }
.table.linked-rows td a.row-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* ═══ Badges ═══ */
.badge {
  font-family: 'Geist Mono', monospace;
  font-weight: 500;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: 4px;
  border: 1px solid transparent;
  text-transform: none;
}
.badge.bg-primary, .bg-primary    { background: var(--accent-soft) !important;  color: var(--accent) !important;  border-color: rgba(242,98,35,.3); }
.badge.bg-secondary, .bg-secondary{ background: var(--surface-2) !important;     color: var(--ink-2) !important;   border-color: var(--line-2); }
.badge.bg-success, .bg-success    { background: var(--ok-soft) !important;       color: var(--ok) !important;      border-color: rgba(21,128,61,.3); }
.badge.bg-warning, .bg-warning    { background: var(--warn-soft) !important;     color: var(--warn) !important;    border-color: rgba(138,90,0,.3); }
.badge.bg-danger, .bg-danger      { background: var(--danger-soft) !important;   color: var(--danger) !important;  border-color: rgba(77,11,24,.3); }
.badge.bg-light, .bg-light        { background: var(--surface-2) !important;     color: var(--ink-2) !important;   border-color: var(--line); }

/* ═══ Alerts ═══ */
.alert {
  border-radius: 8px;
  padding: 11px 14px;
  font-size: 13px;
  line-height: 1.55;
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--ink-2);
}
.alert strong { color: var(--ink); font-weight: 600; }
.alert em { color: var(--ink); font-style: normal; background: var(--surface); border: 1px solid var(--line-2); padding: 1px 5px; border-radius: 3px; font-family: 'Geist Mono', monospace; font-size: 12px; }
.alert-info    { background: var(--accent-soft); border-color: rgba(242, 98, 35, 0.3); color: var(--ink-2); }
.alert-success { background: var(--ok-soft); border-color: rgba(21, 128, 61, 0.35); color: var(--ink-2); }
.alert-warning { background: var(--warn-soft); border-color: rgba(138, 90, 0, 0.35); color: var(--ink-2); }
.alert-danger,
.alert-error   { background: var(--danger-soft); border-color: rgba(77, 11, 24, 0.35); color: var(--ink-2); }

/* ═══ Preconditions list (#54 next-round confirm; reusable) ═══ */
.precond-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.precond-list .precond {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  line-height: 1.5;
}
.precond-list .precond:last-child { border-bottom: none; }
.precond-list .precond::before {
  content: "";
  display: inline-block;
  flex: 0 0 14px;
  height: 14px;
  border-radius: 50%;
  position: relative;
  top: 2px;
}
.precond-list .precond .label { color: var(--ink); font-weight: 500; }
.precond-list .precond .muted { color: var(--ink-2); }
.precond-list .precond-ok::before {
  background: var(--ok-soft);
  border: 1px solid var(--ok);
  box-shadow: inset 0 0 0 3px var(--ok-soft);
}
/* No `.precond-warn` rule today: no code path emits status="warn".
   Add the rule alongside the first emit so the dead-code lifetime
   is bounded. */
.precond-list .precond-fail::before {
  background: var(--danger-soft);
  border: 1px solid var(--danger);
  box-shadow: inset 0 0 0 3px var(--danger-soft);
}
.precond-list .precond-fail .label { color: var(--danger); }
.precond-list .precond-fail .muted { color: var(--ink); }

/* ═══ Top-of-standings preview (#54) ═══ */
.standings-preview {
  list-style: none;
  margin: 0;
  padding: 0;
}
.standings-preview > li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.standings-preview > li:last-child { border-bottom: none; }
.standings-preview .rank {
  font-family: 'Geist Mono', monospace;
  color: var(--mute);
  flex: 0 0 32px;
}
.standings-preview .team { color: var(--ink); font-weight: 500; flex: 1; }
.standings-preview .muted { color: var(--ink-2); }

/* ═══ Disabled-button affordance (used everywhere) ═══ */
.btn:disabled,
.btn[disabled],
button.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  /* `pointer-events: none` would prevent the cursor from showing on
     hover, defeating its own purpose. Keep events on, intercept the
     click via `pointer-events` only on inner content if needed. */
  filter: grayscale(0.4);
}
.btn:disabled:hover,
.btn[disabled]:hover,
button.btn:disabled:hover {
  /* Hold the disabled visuals against the normal :hover overrides
     (which would otherwise lighten/darken the background and undo
     the muted look). */
  background: inherit;
  border-color: inherit;
  color: inherit;
}

/* ═══ Form action row (#54 confirm pages: submit + cancel) ═══ */
.form-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 0 0;
  margin-top: 6px;
}
.form-actions .form-actions-help {
  flex: 1;
  font-size: 12.5px;
  color: var(--ink-2);
  text-align: right;
  padding-right: 4px;
}

/* ═══ List-group (used by league list, stage list drag-reorder) ═══ */
.list-group {
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--surface);
}
.list-group-item {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--line);
  padding: 11px 14px;
  font-size: 13.5px;
}
.list-group-item:hover { background: var(--surface-2); }
.list-group-item strong { font-weight: 600; }
.list-group-item a { color: var(--accent); }

/* ═══ Forms ═══ */
.form-control, .form-select {
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 13.5px;
  padding: 7px 10px;
  border-radius: 6px;
  border-color: var(--line-2);
  background: var(--surface);
  color: var(--ink);
}
.form-control:focus, .form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(242, 98, 35, 0.15);
}
.form-label {
  font-size: 12px;
  color: var(--ink-2);
  font-weight: 500;
  margin-bottom: 4px;
  letter-spacing: 0.01em;
}
.form-text { color: var(--mute); font-size: 11.5px; }
textarea.form-control { line-height: 1.5; }
.invalid-feedback { color: var(--danger); font-size: 11.5px; }
.form-control.is-invalid, .was-validated .form-control:invalid { border-color: var(--danger); }

/* ═══ Breadcrumbs (Bootstrap, when still used) ═══ */
.breadcrumb {
  font-family: 'Geist Mono', monospace;
  font-size: 12px;
  color: var(--mute);
  margin-bottom: 10px;
}
.breadcrumb-item a { color: var(--mute); }
.breadcrumb-item a:hover { color: var(--ink); text-decoration: underline; }
.breadcrumb-item.active { color: var(--ink); }
.breadcrumb-item + .breadcrumb-item::before { color: var(--line-2); content: "/"; }

/* ═══ Definition lists (tournament dashboard) ═══ */
dl.row { margin: 0; }
dl.row dt {
  color: var(--mute);
  font-weight: 500;
  font-size: 12px;
  font-family: 'Geist Mono', monospace;
  padding-top: 8px;
}
dl.row dd {
  color: var(--ink);
  padding-top: 8px;
  border-bottom: 1px dashed var(--line);
  padding-bottom: 10px;
  margin-bottom: 0;
}
dl.row dt:last-of-type, dl.row dd:last-of-type { border-bottom: none; }

/* Reorder grip */
.bi-grip-vertical { color: var(--dim); cursor: grab; }
.bi-grip-vertical:hover { color: var(--ink-2); }

/* ═══ Panel ═══
 * Bordered white box used for grouping content (property grids, list
 * sections, stage tables). Replaces the Bootstrap "card" for the new
 * design language — tighter and flatter than Bootstrap's default card.
 */
.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  margin: 0 28px 20px;
  overflow: hidden;
}
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  gap: 12px;
}
.panel-title {
  font-weight: 600;
  font-size: 13px;
  color: var(--ink);
}
.panel-title .muted {
  color: var(--mute);
  font-weight: 400;
  margin-left: 6px;
  font-family: 'Geist Mono', monospace;
  font-size: 12px;
}
.panel-body { padding: 14px 16px; }
.panel-body.padless { padding: 0; }
.panel-empty {
  padding: 22px 16px;
  color: var(--mute);
  text-align: center;
  font-size: 13px;
}
.module-search {
  display: flex;
  align-items: center;
  gap: 8px;
}
.module-search input[type="search"] {
  width: 260px;
  max-width: 100%;
}
.module-search-count {
  font-family: 'Geist Mono', monospace;
  font-size: 12px;
  white-space: nowrap;
}

/* ═══ Key-value property grid ═══ */
dl.kv {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 0;
  margin: 0;
  font-size: 13px;
}
dl.kv dt {
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 12px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  border-top: none;
}
dl.kv dd {
  color: var(--ink);
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
dl.kv > dt:last-of-type,
dl.kv > dd:last-of-type { border-bottom: none; }
dl.kv .desc {
  white-space: pre-wrap;
  line-height: 1.55;
  color: var(--ink-2);
}

/* ═══ Leagues list (rows of clickable league cards) ═══ */
.leagues-list {
  display: flex;
  flex-direction: column;
}
.league-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  text-decoration: none;
  transition: background .12s;
}
.league-row:last-child { border-bottom: none; }
.league-row:hover {
  background: var(--surface-2);
  color: var(--ink);
  text-decoration: none;
}
.league-row .league-name {
  font-weight: 500;
  color: var(--ink);
  font-size: 14px;
}
.league-row .league-meta {
  margin-left: auto;
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 11.5px;
  display: flex;
  gap: 10px;
  align-items: center;
}

/* ═══ Group-header rows (grouped tables like stage entries) ═══ */
.table tr.group-head > td {
  background: var(--surface-2);
  color: var(--ink-2);
  font-family: 'Geist Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 7px 12px;
  border-top: 1px solid var(--line);
}
.table tr.group-head > td .muted {
  color: var(--mute);
  font-weight: 400;
  margin-left: 6px;
  text-transform: none;
  letter-spacing: 0;
}

/* ═══ Strikethrough for withdrawn/cancelled entries ═══ */
.table tr.is-withdrawn td { color: var(--mute); }
.table tr.is-withdrawn td .team-name {
  color: var(--mute);
  text-decoration: line-through;
  text-decoration-color: var(--dim);
}

/* ═══ Hint row at bottom of dense tables ═══ */
.kb-hint {
  display: flex;
  gap: 16px;
  font-family: 'Geist Mono', monospace;
  font-size: 11.5px;
  color: var(--mute);
  padding: 10px 14px;
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  flex-wrap: wrap;
}
.kb-hint .k {
  border: 1px solid var(--line-2);
  padding: 0 5px;
  border-radius: 3px;
  background: var(--surface);
  color: var(--ink-2);
  margin-right: 4px;
}
.kb-hint .k.dim { opacity: 0.45; }

/* Reorder grip */
.bi-grip-vertical { color: var(--dim); cursor: grab; }
.bi-grip-vertical:hover { color: var(--ink-2); }

/* ═══ Responsive tweaks ═══ */
@media (max-width: 760px) {
  .main-head, .meta-row, .section-head, .panel { padding-left: 16px; padding-right: 16px; }
  .panel { margin-left: 14px; margin-right: 14px; }
  dl.kv { grid-template-columns: 110px 1fr; }
}

/* Utility cleanup so pages that still use bootstrap spacing utilities behave */
.mt-4 { margin-top: 24px !important; }
.mb-3 { margin-bottom: 16px !important; }
.mb-4 { margin-bottom: 20px !important; }

/* --- Host standings view (#47) ----------------------------------- */

/* Right-align numeric stat columns. */
.table.standings td.num,
.table.standings th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Cut line between last qualifier and first non-qualifier. */
.table.standings tbody tr[data-cut="true"] > td {
  border-top: 2px solid var(--accent);
}

/* Non-qualifying rows are slightly de-emphasised. */
.table.standings tbody tr[data-qualifies="false"] > td {
  color: var(--mute);
}

/* Per-group / overall subheads between _table.html includes. */
.panel-subhead {
  padding: 14px 14px 6px;
  color: var(--mute);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 500;
}

/* --- Progress table (stage progress page) ------------------------- */
.progress-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.progress-section-head .muted {
  color: var(--mute);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}
.progress-table-wrap {
  overflow-x: auto;
  border-top: 1px solid var(--line);
}
.progress-table {
  min-width: 840px;
  table-layout: fixed;
  border: 0;
  border-radius: 0;
}
.progress-table > :not(caption) > * > * {
  vertical-align: middle;
}
.progress-table thead th {
  white-space: nowrap;
}
.progress-table th:nth-child(1),
.progress-table td:nth-child(1) { width: 78px; }
.progress-table th:nth-child(2),
.progress-table td:nth-child(2) { width: 30%; }
.progress-table th:nth-child(3),
.progress-table td:nth-child(3) { width: 150px; }
.progress-table th:nth-child(4),
.progress-table td:nth-child(4) { width: 126px; }
.progress-table th:nth-child(5),
.progress-table td:nth-child(5) { width: 88px; }
.progress-table th:nth-child(6),
.progress-table td:nth-child(6) { width: 102px; }
.progress-table th:nth-child(7),
.progress-table td:nth-child(7) { width: 70px; }
.progress-table tbody tr:last-child > td {
  border-bottom: 0;
}
.progress-table tbody tr:hover > td {
  background: #fffaf7;
}
.progress-table tbody tr.progress-status-scheduled > td {
  box-shadow: inset 3px 0 0 var(--warn);
}
.progress-code {
  color: var(--accent);
  font-weight: 600;
  white-space: nowrap;
}
.progress-teams {
  min-width: 0;
  overflow-wrap: anywhere;
}
.progress-team-pair {
  min-width: 0;
}
.progress-team {
  color: var(--ink);
  font-weight: 600;
}
.progress-vs {
  color: var(--mute);
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
  font-size: 11px;
  margin: 0 7px;
}
.progress-status-result {
  display: flex;
  align-items: center;
  gap: 8px;
}
.progress-result {
  font-weight: 600;
  white-space: nowrap;
}
.progress-nowrap {
  white-space: nowrap;
}
.progress-missing {
  color: var(--mute);
  font-style: italic;
}
.progress-action,
.progress-action-head {
  text-align: right;
}
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  padding: 3px 8px;
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
  font-size: 11px;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--ink-2);
  background: var(--surface-2);
}
.status-completed {
  color: var(--ok);
  border-color: rgba(21, 128, 61, 0.28);
  background: var(--ok-soft);
}
.status-scheduled {
  color: var(--warn);
  border-color: rgba(138, 90, 0, 0.28);
  background: var(--warn-soft);
}
.status-cancelled {
  color: var(--mute);
  border-color: var(--line-2);
  background: var(--surface-2);
}
.status-withdrawn_forfeit {
  color: var(--danger);
  border-color: rgba(77, 11, 24, 0.28);
  background: var(--danger-soft);
}

@media (max-width: 760px) {
  .progress-table-wrap {
    overflow-x: visible;
  }
  .progress-table {
    min-width: 0;
  }
  .progress-table,
  .progress-table tbody,
  .progress-table tr,
  .progress-table td {
    display: block;
    width: 100% !important;
  }
  .progress-table thead {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    white-space: nowrap;
    width: 1px;
  }
  .progress-table tbody {
    padding: 10px;
    background: var(--surface-2);
  }
  .progress-table tbody tr {
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--surface);
    overflow: hidden;
  }
  .progress-table tbody tr + tr {
    margin-top: 10px;
  }
  .progress-table tbody tr.progress-status-scheduled {
    border-left: 3px solid var(--warn);
  }
  .progress-table tbody tr.progress-status-scheduled > td {
    box-shadow: none;
  }
  .progress-table td {
    display: grid;
    grid-template-columns: 86px minmax(0, 1fr);
    gap: 12px;
    align-items: baseline;
    border-bottom: 1px solid var(--line);
    padding: 8px 10px;
    text-align: left;
  }
  .progress-table td::before {
    content: attr(data-label);
    color: var(--mute);
    font-family: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
    font-size: 10.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }
  .progress-table td:last-child {
    border-bottom: 0;
  }
  .progress-table .progress-action {
    text-align: left;
  }
  .progress-table .progress-action .btn {
    justify-self: start;
  }
  .progress-section-head {
    padding-top: 12px;
  }
}

/* --- "Up next" fixture queue (league detail) --------------------- */
/* Aligned fixture list: kickoff time anchors each row (mono, the data
   face shared with standings), team names carry the row, the field is
   a quiet tag. Every row reads with equal weight — no single match is
   highlighted, so a referee can scan for their own fixture. */
.upnext { list-style: none; margin: 0; padding: 0; }
.upnext-row { border-bottom: 1px solid var(--line); }
.upnext-row:last-child { border-bottom: 0; }
/* Day separator — only emitted when the match-day changes, so a
   single-day event shows it once instead of repeating a date per row. */
.upnext-dayhead {
  padding: 8px 16px 4px;
  font-family: 'Geist Mono', monospace;
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--mute);
  background: var(--surface);
}
.upnext-dayhead + .upnext-row { border-top: 0; }
.upnext-link {
  display: grid;
  grid-template-columns: 46px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 7px 16px;
  color: var(--ink);
  text-decoration: none;
}
a.upnext-link:hover { background: var(--surface-2); }
a.upnext-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.upnext-time {
  font-family: 'Geist Mono', monospace;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.upnext-time.upnext-tbd { color: var(--dim); }
.upnext-match {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 3px 7px;
  min-width: 0;
}
.upnext-team { font-weight: 500; color: var(--ink); }
.upnext-vs { font-size: 11px; color: var(--mute); }
.upnext-meta { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.upnext-venue {
  font-family: 'Geist Mono', monospace;
  font-size: 11px;
  color: var(--ink-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 1px 6px;
}

@media (max-width: 620px) {
  .upnext-link {
    grid-template-columns: auto 1fr;
    grid-template-areas:
      "time meta"
      "match match";
    gap: 4px 12px;
  }
  .upnext-time { grid-area: time; }
  .upnext-match { grid-area: match; }
  .upnext-meta { grid-area: meta; justify-self: end; }
}

/* Stage selector in the host standings header. */
.inline-form {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.inline-form select {
  padding: 4px 8px;
  font-size: 13px;
}

/* Sign-out form in the sidebar: looks like a side-item row but is a
   POST form for CSRF safety. Button resets the default browser
   styling so it matches surrounding side-item entries. */
.side-logout-form {
  padding: 0;
  margin: 0;
}
.side-logout-button {
  appearance: none;
  background: transparent;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  width: 100%;
  padding: 6px 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.side-logout-button:hover {
  background: var(--hover, rgba(0, 0, 0, 0.04));
}

/* ═══ Match results entry (#28) ═══
 * Scorecard-row layout for the Editor's results-entry grid.
 * Each match is a slim horizontal row inside a single .panel:
 *   home-name → stepper-:-stepper → away-name → Save
 * with a quiet mono meta sub-line below. Rows are grouped by
 * scheduled start time. Status messages absorb into an inline
 * .mre-status slot under the meta line.
 */

.mre-toolbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 28px 14px;
  flex-wrap: wrap;
}
.mre-toolbar-group {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.mre-toolbar-label {
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-right: 4px;
}
.mre-toolbar-spacer { flex: 1; }
.mre-toolbar input[type="date"] { width: auto; max-width: 160px; }
.mre-toolbar select.form-select { width: auto; max-width: 220px; }

.mre-seg {
  display: inline-flex;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: 6px;
  overflow: hidden;
}
.mre-seg button,
.mre-seg .mre-seg-link {
  appearance: none;
  background: transparent;
  border: 0;
  border-right: 1px solid var(--line);
  padding: 5px 11px;
  font-size: 12px;
  font-family: 'Inter', sans-serif;
  color: var(--ink-2);
  cursor: pointer;
  line-height: 1.3;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.mre-seg button:last-child,
.mre-seg .mre-seg-link:last-child { border-right: 0; }
.mre-seg button:hover,
.mre-seg .mre-seg-link:hover {
  background: var(--surface-2);
  color: var(--ink);
  text-decoration: none;
}
.mre-seg .on,
.mre-seg button.on,
.mre-seg .mre-seg-link.on {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 500;
}

.mre-jump {
  display: inline-flex;
  align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: 6px;
  overflow: hidden;
}
.mre-jump .mre-jump-prefix {
  display: inline-flex;
  align-items: center;
  padding: 0 9px;
  background: var(--surface-2);
  color: var(--mute);
  font-family: 'Geist Mono', monospace;
  font-size: 11px;
  border-right: 1px solid var(--line);
}
.mre-jump input {
  appearance: none;
  border: 0;
  background: var(--surface);
  padding: 5px 10px;
  font-family: 'Geist Mono', monospace;
  font-size: 12.5px;
  color: var(--ink);
  width: 160px;
  outline: none;
}
.mre-jump input::placeholder { color: var(--dim); }
.mre-jump button {
  appearance: none;
  border: 0;
  border-left: 1px solid var(--line);
  background: var(--surface);
  padding: 0 11px;
  font-size: 12px;
  color: var(--ink-2);
  cursor: pointer;
}
.mre-jump button:hover { background: var(--surface-2); color: var(--ink); }

/* Time-group separator inside the panel body. */
.mre-time-group {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 8px 18px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-family: 'Geist Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.mre-rows > .mre-time-group:first-child { border-top: none; }
.mre-time-group .mre-time-count {
  color: var(--mute);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}

/* Scorecard rows. The <form> element IS the row container so the
 * existing match_results_entry.js (which selects form.mre-row) keeps
 * working unchanged. */
.mre-rows .mre-row + .mre-row,
.mre-rows .mre-time-group + .mre-row {
  border-top: 1px solid var(--line);
}
.mre-rows > .mre-time-group + .mre-row { border-top: none; }
.mre-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto;
  align-items: center;
  column-gap: 18px;
  padding: 14px 18px 12px;
  background: var(--surface);
  transition: background .12s;
  position: relative;
  margin: 0;
}
.mre-row:hover { background: var(--surface-2); }
.mre-row.is-focus { background: var(--accent-soft); }
.mre-row.is-focus::before,
.mre-row.is-error::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
}
.mre-row.is-focus::before  { background: var(--accent); }
.mre-row.is-error::before  { background: var(--danger); }
.mre-row.is-locked { color: var(--mute); }

.mre-team {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.005em;
  line-height: 1.25;
  min-width: 0;
}
.mre-row.is-locked .mre-team { color: var(--mute); font-weight: 500; }
.mre-team-home { text-align: right; padding-right: 4px; }
.mre-team-away { text-align: left;  padding-left: 4px; }

/* Soft inspection warning marker on a match row (no hard block). */
.inspection-marker {
  display: inline-block;
  margin: 0 4px;
  font-size: 12px;
  line-height: 1;
  cursor: help;
}
.inspection-marker.inspection-missing { color: var(--warn); }
.inspection-marker.inspection-failed  { color: var(--danger); }

.mre-score {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
}

/* Stepper — keeps the legacy .match-stepper class so match_stepper.js
 * binds without changes; .mre-stepper just adds visual styling that
 * only applies inside .mre-row. */
.mre-row .match-stepper {
  display: inline-flex;
  align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  overflow: hidden;
  height: 44px;
  padding: 0;
  width: auto;
  flex-wrap: nowrap;
}
.mre-row .match-stepper button {
  appearance: none;
  border: 0;
  background: var(--surface);
  color: var(--ink-2);
  width: 32px;
  font-size: 16px;
  font-weight: 600;
  font-family: 'Geist Mono', monospace;
  cursor: pointer;
  display: grid;
  place-items: center;
  line-height: 1;
  padding: 0;
  transition: background .12s, color .12s;
}
.mre-row .match-stepper button:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.mre-row .match-stepper-input {
  appearance: none;
  border: 0;
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
  background: var(--surface);
  width: 64px;
  text-align: center;
  font-family: 'Geist Mono', monospace;
  font-weight: 600;
  font-size: 22px;
  color: var(--ink);
  padding: 0;
  outline: none;
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
  flex: 0 0 auto;
}
.mre-row .match-stepper-input::-webkit-outer-spin-button,
.mre-row .match-stepper-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.mre-row .match-stepper-input::placeholder { color: var(--dim); font-weight: 400; }
.mre-row .match-stepper:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(242, 98, 35, 0.15);
}
.mre-row .match-stepper:focus-within button { color: var(--accent); }
.mre-row .match-stepper:has(input:placeholder-shown) .match-stepper-input,
.mre-row .match-stepper:has(input[value=""]) .match-stepper-input {
  color: var(--dim);
}

.mre-colon {
  font-family: 'Geist Mono', monospace;
  font-size: 22px;
  font-weight: 600;
  color: var(--mute);
  line-height: 1;
  padding-bottom: 3px;
  user-select: none;
}

.mre-save.btn {
  height: 44px;
  padding: 0 18px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.mre-save.btn .kbd { margin-left: 8px; }

/* Quiet meta sub-line beneath the team line. */
.mre-meta {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 8px;
  margin-top: 4px;
  font-family: 'Geist Mono', monospace;
  font-size: 11.5px;
  color: var(--mute);
  flex-wrap: wrap;
}
.mre-meta .lg-code { font-size: 11.5px; padding: 2px 7px; }
.mre-meta .mre-meta-sep { color: var(--line-2); }
.mre-meta .mre-league-abbrev { color: var(--ink-2); font-weight: 500; }
.mre-meta .mre-when { color: var(--ink-2); }
.mre-meta .mre-where { color: var(--mute); }
.mre-meta .mre-open-link {
  margin-left: auto;
  color: var(--accent);
  font-weight: 500;
  text-decoration: none;
}
.mre-meta .mre-open-link:hover { text-decoration: underline; }

/* Referee-app affordance on a submittable row — a <button> (it POSTs a
   sibling mint form) reset to read as the quiet accent link the locked
   rows use for "Open →". */
.mre-meta .mre-refapp-link {
  margin-left: auto;
  font-family: inherit;
  font-size: inherit;
  color: var(--accent);
  font-weight: 500;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.mre-meta .mre-refapp-link:hover { text-decoration: underline; }

/* Inline status slot — absorbs error/conflict/lock messages from JS. */
.mre-status {
  grid-column: 1 / -1;
  font-size: 12.5px;
  color: var(--mute);
  margin-top: 6px;
  min-height: 0;
}
.mre-status:empty { display: none; }
.mre-status .mre-error {
  color: var(--danger);
  background: var(--danger-soft);
  border: 1px solid rgba(77, 11, 24, 0.18);
  border-radius: 4px;
  padding: 6px 10px;
  font-family: 'Inter', sans-serif;
}
.mre-status a {
  margin-left: 8px;
  color: var(--danger);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Ghost-undo strip below the panel. */
.mre-ghost {
  list-style: none;
  margin: 0 28px 16px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mre-ghost-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px;
  background: var(--ok-soft);
  border: 1px solid rgba(21, 128, 61, 0.3);
  border-radius: 8px;
  font-size: 13px;
  color: var(--ink-2);
}
.mre-ghost-item .lg-code { font-size: 11.5px; padding: 2px 7px; }
.mre-ghost-item strong {
  font-family: 'Geist Mono', monospace;
  font-weight: 600;
  color: var(--ok);
  font-size: 13px;
}
.mre-ghost-item a {
  margin-left: auto;
  color: var(--ink-2);
  font-size: 12.5px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.mre-ghost-item .mre-countdown {
  font-family: 'Geist Mono', monospace;
  font-size: 11.5px;
  color: var(--mute);
}
.mre-ghost-item .mre-warn { color: var(--warn); font-weight: 500; }

/* Empty-state. */
.mre-empty {
  padding: 32px 18px;
  text-align: center;
  color: var(--mute);
  font-size: 13px;
}

/* Responsive collapse — single column on narrow viewports. */
@media (max-width: 760px) {
  .mre-row {
    grid-template-columns: 1fr;
    row-gap: 8px;
    padding: 14px 14px 12px;
  }
  .mre-team-home, .mre-team-away { text-align: left; padding: 0; }
  .mre-score { justify-content: center; }
  .mre-save.btn { width: 100%; justify-content: center; }
  .mre-toolbar { padding-left: 14px; padding-right: 14px; }
  .mre-ghost { margin-left: 14px; margin-right: 14px; }
}

/* ═══ Form layout (inspection + shared) ═══ */
/* Dense field grid for forms with many short inputs (inspection
   criteria, module registry). Children are the renderer's mb-3 field
   blocks; each spans one column, wrapping responsively. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  column-gap: 18px;
}

/* Single-row upload form: file input + caption + button. */
.photo-upload-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.photo-upload-row .form-control { width: auto; flex: 1 1 200px; max-width: 320px; }

/* Searchable combobox for the "attach existing module" picker. The input
   reuses .form-control sizing (via .photo-upload-row); the wrap is the
   positioning context for the absolutely-positioned results list. */
.module-combobox { position: relative; flex: 1 1 200px; max-width: 320px; }
.module-combobox .form-control { width: 100%; max-width: none; }
/* On the horizontal (desktop) layout, pin the combobox and the register
   row's MAC field to the same fixed width so the Assign and Scan QR buttons
   that trail them line up vertically. Without this the MAC input shrinks (it
   shares its row with Label/Type/Register), pushing Scan QR left of Assign.
   Gated on min-width so it never touches the mobile column layout below,
   where a `flex-basis` would become a 320px *height*. */
@media (min-width: 761px) {
  .photo-upload-row .module-combobox,
  .photo-upload-row input[data-mac-scan] { flex: 0 0 320px; max-width: 320px; }
}
.module-combobox-list {
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
.module-combobox-option {
  padding: 6px 8px;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.module-combobox-option:hover,
.module-combobox-option.is-active {
  background: var(--hover, rgba(0, 0, 0, 0.05));
}
.module-combobox-empty { padding: 6px 8px; font-size: 13px; }

.photo-list {
  list-style: none;
  margin: 0;
  padding: 0 16px 14px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}
.photo-item { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.photo-item img { border-radius: 6px; border: 1px solid var(--line); display: block; }

/* Inline action cluster in a table row (Edit + Delete/Detach). */
.row-actions { display: inline-flex; gap: 6px; align-items: center; justify-content: flex-end; }
.row-actions form { display: inline; margin: 0; }

/* Wide tables inside a panel (which clips overflow for its rounded
   corners) scroll horizontally on narrow screens instead of having
   their right-hand columns — e.g. row actions — cut off. This is the
   fallback for tables that are NOT converted to mobile cards (`.stack`)
   below — e.g. the host-only confirm/preview grids. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-wrap > .table { margin-bottom: 0; }

@media (max-width: 760px) {
  .table-wrap .table:not(.stack) th,
  .table-wrap .table:not(.stack) td { white-space: nowrap; }
}

/* ═══ Responsive "table → labeled cards" (opt-in: <table class="… stack">) ═══
 * On phones each row becomes a bordered card and each cell a label/value
 * line, the label coming from the cell's data-label. This surfaces the
 * important fields and the row actions up front instead of clipping them
 * off the right edge or hiding them behind a horizontal scroll. Every
 * rule is scoped `.table.stack > tbody > tr > td` (specificity 0-2-3) so
 * it beats Bootstrap's `.table > :not(caption) > * > *` and the nowrap
 * fallback above without `!important`. Mono caps labels reuse the thead /
 * dl.kv look. */
@media (max-width: 760px) {
  /* Header is meaningless once stacked, but keep it for screen readers. */
  .table.stack thead {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  .table.stack,
  .table.stack > tbody,
  .table.stack > tbody > tr,
  .table.stack > tbody > tr > td,
  .table.stack > tbody > tr > th { display: block; width: auto; }

  /* Each row is a card, separated by a single line inside the panel frame. */
  .table.stack > tbody > tr {
    padding: 8px 14px 12px;
    border-bottom: 1px solid var(--line);
    background: var(--surface);
  }
  .table.stack > tbody > tr:last-child { border-bottom: 0; }

  /* Each cell: label (left) / value (right), quiet dashed separator. */
  .table.stack > tbody > tr > td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    min-height: 38px;
    padding: 7px 0;
    border: 0;
    border-bottom: 1px dashed var(--line);
    text-align: right;
    white-space: normal;
    font-variant-numeric: tabular-nums;
  }
  .table.stack > tbody > tr > td:last-child { border-bottom: 0; }
  .table.stack > tbody > tr > td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    text-align: left;
    color: var(--mute);
    font-family: 'Geist Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    font-weight: 500;
  }
  .table.stack > tbody > tr > td[data-label=""]::before { content: none; }

  /* Cells not worth a line on a phone (e.g. ordinal #, drag grip). */
  .table.stack > tbody > tr > td.hide-sm { display: none; }

  /* Title cell: the row's name/identity — a full-width heading, no label. */
  .table.stack > tbody > tr > td.stack-title {
    display: block;
    text-align: left;
    border-bottom: 0;
    padding: 2px 0 4px;
    min-height: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--ink);
  }
  .table.stack > tbody > tr > td.stack-title::before { content: none; }

  /* Actions cell: full-width tappable button band at the foot of the card. */
  .table.stack > tbody > tr > td.stack-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding-top: 10px;
    border-bottom: 0;
  }
  .table.stack > tbody > tr > td.stack-actions::before { content: none; }
  .table.stack > tbody > tr > td.stack-actions .row-actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
  }
  .table.stack > tbody > tr > td.stack-actions .row-actions form { display: block; margin: 0; }
  .table.stack > tbody > tr > td.stack-actions .btn {
    width: 100%;
    justify-content: center;
    min-height: 40px;
    padding: 9px 14px;
  }
}

/* ═══ Standings: bespoke compact card (rank · team · points + meta line) ═══
 * The 10-column standings table would stack into ~8 label/value lines per
 * team. Instead, on phones we show rank + team + points on one prominent
 * line and fold the rest (P · W-D-L · GD) into a single muted meta line;
 * GF/GA drop out. `.st-meta` is desktop-hidden and mobile-shown; the
 * per-stat `.st-stat` cells are the reverse. */
.table.standings .st-meta { display: none; }

@media (max-width: 760px) {
  .table.standings thead { display: none; }
  .table.standings > tbody > tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 10px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--line);
  }
  .table.standings > tbody > tr:last-child { border-bottom: 0; }
  /* The accent qualifier/non-qualifier divider moves from the cells to the
     row, since the cells no longer form a table row. */
  .table.standings > tbody > tr[data-cut="true"] { border-top: 2px solid var(--accent); }

  .table.standings > tbody > tr > td {
    border: 0;
    padding: 0;
    white-space: normal;
    font-variant-numeric: tabular-nums;
  }
  .table.standings .st-rank { font-weight: 600; color: var(--mute); min-width: 1.4em; }
  .table.standings .st-team { flex: 1; min-width: 0; font-weight: 500; }
  /* The verbose tie-break pill would collide with Pts on one line; on a
     phone it is folded into the compact meta line instead (see _table.html). */
  .table.standings .st-team .pill { display: none; }
  .table.standings .st-pts { font-weight: 700; }
  .table.standings .st-pts::after {
    content: " pts"; font-weight: 500; color: var(--mute); font-size: 11px;
  }
  .table.standings .st-stat { display: none; }
  .table.standings .st-meta {
    display: block;
    flex-basis: 100%;
    color: var(--mute);
    font-family: 'Geist Mono', monospace;
    font-size: 11.5px;
  }
}

/* ═══ Inline disclosure for secondary row actions (no JS) ═══
 * A native <details> "More" toggle, used to keep one or two primary
 * actions prominent while folding admin/destructive actions away. Compact
 * inline pill on desktop; full-width inside a stacked card on a phone. */
.row-disclosure { display: inline-block; }
.row-disclosure > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Geist Mono', monospace;
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink-2);
  padding: 5px 11px;
  border: 1px solid var(--line-2);
  border-radius: 6px;
  background: var(--surface);
  user-select: none;
}
.row-disclosure > summary::-webkit-details-marker { display: none; }
.row-disclosure > summary::after {
  content: "▸"; color: var(--mute); font-size: 10px; transition: transform .12s;
}
.row-disclosure[open] > summary { color: var(--ink); border-color: var(--ink-2); }
.row-disclosure[open] > summary::after { transform: rotate(90deg); }
.row-disclosure > summary:hover { background: var(--surface-2); color: var(--ink); }
.row-disclosure-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 8px;
}
.row-disclosure-body form { display: block; margin: 0; }

@media (max-width: 760px) {
  .table.stack .row-disclosure,
  .table.stack .row-disclosure > summary { width: 100%; }
  .table.stack .row-disclosure > summary { justify-content: center; min-height: 40px; }
  .table.stack .row-disclosure-body .btn { width: 100%; justify-content: center; min-height: 40px; }
}

@media (max-width: 760px) {
  /* Stack the file-upload / inline-register control rows so each field
     and button is full-width and tappable on a phone. (box-sizing is
     border-box globally via Bootstrap, so width:100% includes padding.) */
  .photo-upload-row { flex-direction: column; align-items: stretch; }
  .photo-upload-row .form-control,
  .photo-upload-row .form-select,
  .photo-upload-row .module-combobox { width: 100%; max-width: none; flex: none; }
  .photo-upload-row .btn { width: 100%; justify-content: center; }
}

/* Module MAC QR scanner (issue #67) */
.mac-scan-btn {
  margin-left: 0.5rem;
}
/* Inside .photo-upload-row (robot page) the flex gap already spaces the
   button; the margin would double-space on desktop and, combined with the
   mobile width:100% rule, overflow the row on the primary phone workflow. */
.photo-upload-row .mac-scan-btn {
  margin-left: 0;
}
.mac-scan-overlay {
  position: fixed;
  inset: 0;
  z-index: 1080;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  padding: 1rem;
}
.mac-scan-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  max-width: 32rem;
  width: 100%;
}
.mac-scan-video {
  width: 100%;
  max-height: 70vh;
  border-radius: 0.5rem;
  background: #000;
  object-fit: cover;
}
.mac-scan-hint {
  color: #fff;
  margin: 0;
  text-align: center;
}
.mac-scan-error {
  color: #fff;
  margin: 0;
  text-align: center;
}
