/* ─────────────────────────────────────────────────────────────────────────
   utilities.css — layout primitives, small helpers, the opt-in .dense density
   layer, and print rules. var(--token) only. Loaded last so utilities win.
   ───────────────────────────────────────────────────────────────────────── */

/* ═══════════════ Layout & text helpers ════════════════════════════════════*/
.container { max-width: var(--maxw); margin-inline: auto; }
.stack > * + * { margin-top: var(--space-4); }
.cluster { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; }
.between { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); }
.grow { flex: 1; }
.spacer { flex: 1 1 auto; }

.muted  { color: var(--text-soft); }
.faint  { color: var(--text-muted); }
.mono   { font-family: var(--font-mono); }
.tnum   { font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }        /* dates + IDs: never wrap */
.text-xs { font-size: var(--fs-xs); }
.text-sm { font-size: var(--fs-sm); }
.text-danger  { color: var(--st-danger-fg); }
.text-warning { color: var(--st-warning-fg); }
.text-success { color: var(--st-success-fg); }

.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-4 { margin-bottom: var(--space-4); }

/* Visibility toggles (JS-driven). .is-hidden wins over any display. */
.is-hidden { display: none !important; }
.sr-only, .vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Card / KPI grids that establish a query container for their children. */
.card-grid {
  display: grid; gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  container-type: inline-size;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Density layer (opt-in) — add `.dense` to a page container to compact the
   vertical rhythm on data-heavy internal-tool pages.

   Research-backed values ported verbatim from farmbelt (2026-07): mouse-first
   32px controls (WCAG 2.2 target-size ≥24px, comfortably clear), input font
   held at 16px so iOS never zooms, line-height ≥1.35. Compaction comes ONLY
   from cutting margins/padding — never from shrinking fonts or crushing
   line-height. Scoped so untouched pages keep comfortable spacing.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Sticky action bar + back link */
.dense .page-action-bar         { padding: 0.65rem 0; margin-bottom: 0.6rem; }
.dense .page-action-bar-actions { gap: 0.4rem; }
.dense .back-link               { min-height: 36px; padding: 0.3rem 0.45rem; font-size: var(--fs-sm); }
.dense .page-action-bar .btn    { min-height: 36px; }

/* Cards */
.dense .card + .card { margin-bottom: var(--space-2); }
.dense .card-header  { padding: 0.4rem var(--space-3); }     /* 16/20 → ~6/12 */
.dense .card-body    { padding: var(--space-3); }            /* 20 → 12 */
.dense .card-body > * + * { margin-top: var(--space-3); }

/* Fields — 32px control, 16px font kept (inherited), tighter box only */
.dense .form-group  { margin-bottom: var(--space-2); }       /* 20 → 8 */
.dense .form-label  { margin-bottom: 0.125rem; font-size: var(--fs-sm); }   /* 6 → 2 */
.dense .form-input,
.dense .form-select,
.dense .form-textarea {
  min-height: var(--control-dense);                          /* 44 → 32 */
  padding: 0.25rem 0.5rem;                                   /* 10/12 → 4/8 */
  line-height: 1.35;
  /* font-size stays 16px (inherited) — keeps iOS zoom off */
}
.dense .form-textarea { min-height: 52px; }                  /* 96 → 52 */
.dense .form-select   { min-width: 0; padding-right: 1.75rem; }
.dense .form-help     { margin-top: 0.0625rem; font-size: var(--fs-xs); }
.dense .form-row      { gap: 0.4rem 0.75rem; }
.dense .form-actions  { padding-top: var(--space-2); margin-top: var(--space-3); }

/* Buttons — still ≥24px (WCAG 2.2 floor) */
.dense .btn    { min-height: var(--control-dense); padding: 0.3rem 0.7rem; }
.dense .btn-sm { min-height: 28px; padding: 0.2rem 0.55rem; }

/* Tables + tiles pull their block padding in (inline padding/type untouched) */
.dense .data-table th,
.dense .data-table td { padding-block: var(--space-2); }
.dense .kpi-card { padding: var(--space-3) var(--space-4); gap: var(--space-1); }
.dense .kpi-grid { gap: var(--space-3); margin-bottom: var(--space-4); }

/* ═══════════════════════════════════════════════════════════════════════════
   Print — strip app chrome, flatten to black-on-white documents.
   ═══════════════════════════════════════════════════════════════════════════ */
@media print {
  .sidebar, .bottom-nav, .mobile-topbar,
  .page-action-bar, .filter-bar, .toast-region,
  .back-link, .danger-zone, .no-print { display: none !important; }

  body { background: #fff; color: #000; }
  .app { display: block; }
  .main { padding: 0; }
  .card { border: 1px solid #000; box-shadow: none; break-inside: avoid; }

  .table-scroll { overflow: visible; border: none; }
  .data-table { font-size: 11pt; }
  .data-table thead th { color: #000; border-bottom: 1px solid #000; }
  .data-table td { border-bottom: 1px solid #999; }
  .data-table tbody tr:nth-child(even) { background: #fff; }
  a { color: #000; text-decoration: none; }
}

/* One invite per slip, each its own page-break unit, so a sheet can be cut up
   and handed out at practice. */
.invite-slip {
  padding: var(--space-4); margin-bottom: var(--space-3);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  break-inside: avoid;
}
.invite-slip-who { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.invite-slip-code { display: flex; align-items: center; gap: var(--space-3); margin: var(--space-2) 0; flex-wrap: wrap; }
.invite-slip-code code {
  font-size: var(--fs-lg); font-weight: 700; letter-spacing: 0.10em;
  padding: var(--space-2) var(--space-3); background: var(--bg-sunken); border-radius: var(--radius-sm);
}
.invite-slip-how { font-size: var(--fs-sm); color: var(--text-soft); margin: 0; }
.invite-once { padding: var(--space-3); background: var(--bg-sunken); border-radius: var(--radius-sm); }

/* ── Setup wizard ──────────────────────────────────────────────────────────*/
.setup { max-width: 720px; }
.setup-rail { display: flex; flex-wrap: wrap; gap: var(--space-2); list-style: none; margin: 0 0 var(--space-5); padding: 0; }
.setup-rail-item { font-size: var(--fs-xs); color: var(--text-soft); padding: 4px var(--space-2); border-radius: 999px; background: var(--bg-sunken); }
.setup-rail-item.is-now  { color: var(--color-on-primary); background: var(--color-primary); font-weight: 600; }
.setup-rail-item.is-done { color: var(--text); }
.setup-rail-item.is-done::before { content: "\2713\00a0"; }

.setup-choices { display: grid; gap: var(--space-2); margin-bottom: var(--space-4); }
.setup-choice {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm);
  cursor: pointer;
}
.setup-choice:has(input:checked) { border-color: var(--color-primary); background: var(--bg-sunken); }
.setup-hint { font-size: var(--fs-sm); color: var(--text-soft); }
.setup-picked { padding: var(--space-3); background: var(--bg-sunken); border-radius: var(--radius-sm); }
.setup-got { font-weight: 600; }
.setup-results { margin-top: var(--space-4); display: grid; gap: var(--space-2); }
.setup-result {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.setup-bail { margin-top: var(--space-4); text-align: center; }
