:root{
  /* ---- Philippine flag theme: blue field, red field, gold sun/stars, white ---- */
  --court:#F2F5FA;
  --ink:#0A1E3D;
  --brand-ink:#0A1E3D;     /* fixed dark navy — same in both themes; a few high-contrast
                              bars (topbar, toasts, mobile tab bar) are deliberately always
                              dark, unlike --ink which flips to a light text color in dark mode */
  --brand-turf:#0038A8;    /* fixed — --turf itself gets lightened in dark mode for on-page
                              contrast, but the topbar's brand gradient should stay put */
  --brand-turf-deep:#00256E;
  --brand-gold-pale:#FFF6D6; /* fixed — the topbar pill's text needs a light cream regardless
                                of theme; --gold-pale becomes a translucent tint in dark mode,
                                which isn't legible as solid text */
  --turf:#0038A8;          /* flag blue — primary */
  --turf-deep:#00256E;
  --turf-pale:#DEE7F7;
  --clay:#CE1126;          /* flag red — secondary/accent */
  --clay-deep:#9E0C1D;
  --gold:#FCD116;          /* flag gold — sun & stars accent */
  --gold-deep:#C79A00;
  --gold-pale:#FFF6D6;
  --slate:#5C6B82;
  --line:#DBE2EE;
  --surface:#FFFFFF;
  --danger:#C6272E;
  --danger-pale:#FAE1E2;
  --radius:14px;
  --radius-sm:9px;
  --shadow-sm:0 1px 3px rgba(10,30,61,.08), 0 1px 2px rgba(10,30,61,.06);
  --shadow-md:0 8px 26px rgba(10,30,61,.14);
  --font-display:'Archivo Black', Impact, sans-serif;
  --font-body:'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono:'IBM Plex Mono', 'SF Mono', Consolas, monospace;
  --touch:44px;            /* min. comfortable touch target */
  --touch-sm:36px;
}

/* ---------- Dark mode ----------
   Applied by toggling data-theme="dark" on <html> (see script.js). All
   color roles are re-pointed here; because nearly every component below
   is already built on these custom properties, redefining them here is
   enough to re-skin the whole app. The handful of places that hardcoded
   a literal white or pale color instead of a variable get their own
   override underneath. */
html[data-theme="dark"]{
  --court:#0B1220;
  --ink:#E8ECF5;
  --turf:#5B8DEF;
  --turf-deep:#9CBEFF;
  --turf-pale:rgba(91,141,239,.16);
  --clay:#FF6B75;
  --clay-deep:#FFB3B9;
  --gold:#FCD116;
  --gold-deep:#FFDE70;
  --gold-pale:rgba(252,209,22,.14);
  --slate:#8FA0B8;
  --line:#263242;
  --surface:#141D2B;
  --danger:#FF6B75;
  --danger-pale:rgba(255,107,117,.15);
  --shadow-sm:0 1px 3px rgba(0,0,0,.45), 0 1px 2px rgba(0,0,0,.35);
  --shadow-md:0 10px 30px rgba(0,0,0,.55);
  color-scheme:dark;
}
html[data-theme="dark"] body{background:var(--court);color:var(--ink)}
/* Surfaces that were hardcoded to a literal white/pale color instead of
   a variable, so the blanket redefinition above can't reach them. */
html[data-theme="dark"] .panel-action-btn,
html[data-theme="dark"] .add-form input:focus,
html[data-theme="dark"] .bulk-add-body textarea,
html[data-theme="dark"] .quick-add-chip,
html[data-theme="dark"] .modal,
html[data-theme="dark"] .field input:focus,
html[data-theme="dark"] .field select:focus,
html[data-theme="dark"] .watch-code-row input:focus,
html[data-theme="dark"] .stepper button,
html[data-theme="dark"] .fixed-duo-add-row select,
html[data-theme="dark"] .fixed-duo-row,
html[data-theme="dark"] .roster-manage-search input:focus,
html[data-theme="dark"] .endgame-row .choice button,
html[data-theme="dark"] .endgame-row .choice button:disabled:hover,
html[data-theme="dark"] .winner-card .score-input,
html[data-theme="dark"] .modal-icon-btn,
html[data-theme="dark"] .modal-icon-btn:disabled,
html[data-theme="dark"] .rankings-toolbar:focus-within,
html[data-theme="dark"] .rank-row{
  background:var(--surface);
}
html[data-theme="dark"] .session-banner{background:rgba(255,107,117,.1)}
html[data-theme="dark"] .session-banner .eyebrow{background:var(--surface)}
html[data-theme="dark"] .session-banner .msg{color:var(--clay-deep)}
html[data-theme="dark"] .winner-card.selected{background:rgba(255,107,117,.14)}
html[data-theme="dark"] .lvl-open{background:rgba(255,255,255,.06);color:var(--slate)}
html[data-theme="dark"] .lvl-intermediate{background:rgba(255,140,0,.16);color:#FFB870}
html[data-theme="dark"] .paddle .tag-pill.queued{background:rgba(255,200,100,.14);color:#E0BC7E}
html[data-theme="dark"] .rank-row.top1{border-color:rgba(252,209,22,.4)}
html[data-theme="dark"] .mvp-badge{background:rgba(252,209,22,.14);color:#FFD35C;border-color:rgba(252,209,22,.35)}
html[data-theme="dark"] ::selection{background:rgba(91,141,239,.35)}

*{box-sizing:border-box}
html,body{height:100%}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--court);
  color:var(--ink);
  font-family:var(--font-body);
  -webkit-font-smoothing:antialiased;
  overscroll-behavior:none;
  transition:background-color .2s,color .2s;
}
button{font-family:inherit}
input,select{font-family:inherit}
::selection{background:var(--turf-pale)}
:focus-visible{outline:3px solid var(--clay);outline-offset:2px}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}

/* ---------- Touch-device baseline (tablet/mobile polish) ----------
   Kills the tap-highlight flash and 300ms delay on every interactive
   element, and guarantees form fields never trip iOS Safari's
   auto-zoom-on-focus (which needs 16px+ to stay off). */
button,a,.icon-btn,.panel-action-btn,.btn,select,[role="button"]{
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;
}
@media (max-width:1024px){
  input[type=text],input[type=number],input[type=search],select,textarea{
    font-size:16px;
  }
}
.stack-list,.rankings-list,.arrivals-list,.block-list,.block-group,
.match-history-list,.roster-manage-list,.court-name-rows,.overlay,
.quick-add-panel,.rankings-toolbar{
  -webkit-overflow-scrolling:touch;
}

/* ---------- Flag strip ---------- */
.flag-strip{
  height:5px;width:100%;position:sticky;top:0;z-index:41;
  background:linear-gradient(90deg, var(--turf) 0 50%, var(--clay) 50% 100%);
}

/* ---------- Topbar ---------- */
.topbar{
  display:flex;align-items:center;gap:.85rem;
  padding:.75rem 1rem;
  background:linear-gradient(120deg, var(--brand-ink) 0%, var(--brand-turf-deep) 65%, var(--brand-turf) 130%);
  color:#fff;
  position:sticky;top:5px;z-index:40;
  box-shadow:var(--shadow-sm);
  overflow-x:auto;
  scrollbar-width:none;
}
.topbar::-webkit-scrollbar{display:none}
.topbar .logo{
  display:flex;align-items:center;justify-content:center;gap:.5rem;flex-shrink:0;
  position:relative;
}
.topbar .logo::before{
  content:'';position:absolute;inset:-6px;border-radius:50%;
  background:radial-gradient(circle, rgba(252,209,22,.35) 0%, transparent 70%);
}
.topbar .logo svg{width:26px;height:34px;color:var(--gold);position:relative}
.topbar .session-name{
  font-family:var(--font-display);
  font-size:1.05rem;letter-spacing:.02em;
  color:#fff;font-weight:700;
  max-width:40vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

.topbar .spacer{flex:1}
.topbar .pill{
  font-family:var(--font-mono);font-size:.72rem;font-weight:600;
  background:rgba(255,255,255,.1);color:var(--brand-gold-pale);
  border:1px solid rgba(252,209,22,.35);
  padding:.32rem .6rem;border-radius:99px;white-space:nowrap;
}
.topbar .pill.live-pill{
  background:rgba(206,17,38,.18);color:#FFD7DA;border-color:rgba(255,120,130,.5);
  cursor:pointer;animation:live-pulse 2s ease-in-out infinite;
}
.topbar .pill.live-pill.is-reconnecting{
  background:rgba(252,209,22,.18);color:var(--gold-pale);border-color:rgba(252,209,22,.5);
  animation:live-pulse 1s ease-in-out infinite;
}
@keyframes live-pulse{0%,100%{opacity:1}50%{opacity:.6}}
.icon-btn{
  width:38px;height:38px;border-radius:10px;border:none;
  background:rgba(255,255,255,.08);color:#fff;
  display:flex;align-items:center;justify-content:center;
  cursor:pointer;transition:background .15s, transform .1s;flex-shrink:0;
}
.icon-btn:hover{background:rgba(255,255,255,.18)}
.icon-btn:active{transform:scale(.94)}
.icon-btn svg{width:19px;height:19px}

/* ---------- App shell ---------- */
.app-shell{
  display:grid;
  grid-template-columns:320px 1fr;
  gap:0;
  align-items:start;
  min-height:calc(100vh - 58px);
}
.stack-rail{
  border-right:1px solid var(--line);
  background:var(--surface);
  min-height:calc(100vh - 58px);
  display:flex;flex-direction:column;
  position:sticky;top:58px;
  height:calc(100vh - 58px);
}
.panel-head{
  padding:1.1rem 1.1rem .8rem;
  display:flex;align-items:center;flex-wrap:wrap;gap:.5rem .6rem;
}
.panel-head h2{
  font-family:var(--font-display);font-size:1.02rem;margin:0;
  letter-spacing:.01em;
}
.panel-head-actions{display:flex;gap:.5rem;margin-left:auto;flex-wrap:wrap}
.count-badge{
  font-family:var(--font-mono);font-weight:600;font-size:.78rem;
  color:var(--turf-deep);background:var(--turf-pale);
  padding:.15rem .55rem;border-radius:99px;
}
.count-badge.sm{font-size:.66rem;padding:.08rem .4rem}
.panel-action-btn{
  display:flex;align-items:center;gap:.35rem;
  border:1.5px solid var(--line);background:#fff;color:var(--ink);
  font-weight:700;font-size:.8rem;padding:.45rem .75rem;border-radius:99px;cursor:pointer;
  transition:border-color .15s,background .15s,color .15s;
}
.panel-action-btn svg{width:14px;height:14px;flex-shrink:0}
.panel-action-btn:hover{border-color:var(--turf);color:var(--turf-deep)}
.panel-action-btn.solid{border-color:var(--turf);background:var(--turf);color:#fff}
.panel-action-btn.solid:hover{background:var(--turf-deep);border-color:var(--turf-deep)}
.panel-action-btn .count-badge.sm{background:rgba(255,255,255,.35);color:inherit}
.panel-action-btn.has-waiting{
  border-color:var(--turf);color:var(--turf-deep);
  animation:checkin-glow 1.6s ease-in-out infinite;
}
@keyframes checkin-glow{
  0%,100%{box-shadow:0 0 0 0 rgba(0,56,168,.45)}
  50%{box-shadow:0 0 0 7px rgba(0,56,168,0)}
}
@media (prefers-reduced-motion:reduce){
  .panel-action-btn.has-waiting{animation:none;box-shadow:0 0 0 3px rgba(0,56,168,.35)}
}
.add-form{
  display:flex;flex-wrap:wrap;gap:.4rem;padding:0;margin-bottom:.7rem;
}
.add-form input{
  flex:1;min-width:120px;border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.6rem .7rem;font-size:.88rem;background:var(--court);color:var(--ink);
}
.add-form input:focus{border-color:var(--turf);background:#fff}
.add-form select{
  flex-shrink:0;border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.6rem .5rem;font-size:.78rem;background:var(--court);color:var(--ink);
  max-width:9.5rem;
}
.add-form button{
  border:none;background:var(--turf);color:#fff;border-radius:var(--radius-sm);
  padding:0 .95rem;font-weight:700;font-size:.85rem;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;gap:.35rem;
  transition:background .15s;
}
.add-form button:hover{background:var(--turf-deep)}
.add-hint{padding:0 1.1rem .7rem;font-size:.72rem;color:var(--slate)}
.bulk-add-wrap{margin:.2rem 0 .9rem;border:1.5px solid var(--line);border-radius:10px;overflow:hidden}
.bulk-add-toggle{display:block;padding:.55rem .75rem;font-size:.78rem;font-weight:600;color:var(--turf);cursor:pointer;user-select:none;list-style:none}
.bulk-add-toggle::-webkit-details-marker{display:none}
.bulk-add-toggle:hover{background:var(--court)}
.bulk-add-body{padding:.5rem .75rem .75rem;display:flex;flex-direction:column;gap:.5rem;border-top:1.5px solid var(--line)}
.bulk-add-body textarea{width:100%;resize:vertical;border:1.5px solid var(--line);border-radius:8px;padding:.45rem .6rem;font-size:.82rem;font-family:inherit;min-height:90px;background:#fff}
.bulk-add-body textarea:focus{outline:none;border-color:var(--turf)}
.bulk-add-body button{align-self:flex-end;padding:.42rem 1rem;background:var(--turf);color:#fff;border:none;border-radius:8px;font-size:.82rem;font-weight:700;cursor:pointer}
.bulk-add-body button:hover{background:var(--turf-deep)}

.quick-add-panel{
  margin:0 0 .3rem;padding:.65rem .75rem;
  background:var(--turf-pale);border:1.5px solid var(--turf-pale);border-radius:var(--radius);
  display:flex;flex-direction:column;gap:.5rem;
}
.quick-add-panel[hidden]{display:none}
.quick-add-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem}
.quick-add-title{
  font-family:var(--font-mono);font-size:.68rem;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;color:var(--turf-deep);
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.quick-add-all-btn{
  border:none;background:var(--turf);color:#fff;font-size:.7rem;font-weight:700;
  padding:.2rem .55rem;border-radius:99px;cursor:pointer;flex-shrink:0;transition:background .15s;
  white-space:nowrap;
}
.quick-add-all-btn:hover{background:var(--turf-deep)}
.quick-add-chips{display:flex;flex-wrap:wrap;gap:.4rem}
.quick-add-chip{
  display:flex;align-items:center;gap:.3rem;
  border:1.5px solid var(--turf);background:#fff;color:var(--turf-deep);
  font-size:.78rem;font-weight:600;padding:.28rem .55rem;border-radius:99px;cursor:pointer;
  transition:background .15s,color .15s;
}
.quick-add-chip:hover{background:var(--turf);color:#fff}
.quick-add-chip svg{width:11px;height:11px;flex-shrink:0}
body.session-locked .quick-add-panel{opacity:.55;pointer-events:none}

.checkin-modal-toolbar{display:flex;justify-content:flex-end}
.checkin-all-btn{
  margin-left:auto;border:none;background:var(--turf);color:#fff;font-size:.7rem;font-weight:700;
  padding:.2rem .55rem;border-radius:99px;cursor:pointer;flex-shrink:0;transition:background .15s;
}
.checkin-all-btn:hover{background:var(--turf-deep)}
.checkin-all-btn:disabled{opacity:.4;cursor:default}
.arrivals-list{display:flex;flex-direction:column;gap:.4rem;margin-top:.6rem;max-height:min(50vh,360px);overflow-y:auto;padding-right:.1rem}
.arrivals-list:empty{margin-top:0}
#arrivalsEmptyNote{margin:.9rem 0 0}
.arrival-row{
  display:flex;align-items:center;gap:.5rem;
  background:var(--court);border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.4rem .5rem;
}
.arrival-name{flex:1;min-width:0;font-weight:600;font-size:.85rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.arrival-checkin-btn{
  border:none;background:var(--turf);color:#fff;font-weight:700;font-size:.75rem;
  padding:.32rem .6rem;border-radius:99px;cursor:pointer;flex-shrink:0;transition:background .15s;
}
.arrival-checkin-btn:hover{background:var(--turf-deep)}
.arrival-remove-btn{
  border:none;background:none;color:var(--slate);cursor:pointer;
  width:24px;height:24px;border-radius:6px;display:flex;align-items:center;justify-content:center;
  flex-shrink:0;
}
.arrival-remove-btn:hover{background:var(--danger-pale);color:var(--danger)}
.arrival-remove-btn svg{width:12px;height:12px}

.sub-row{
  display:flex;align-items:center;gap:.5rem;
  background:var(--court);border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.4rem .5rem;cursor:pointer;transition:border-color .15s,background .15s;
}
.sub-row:hover{border-color:var(--turf);background:var(--turf-pale)}
.sub-row .arrival-name{flex:1}
.sub-row .level-badge{flex-shrink:0}

.player-sub-btn{
  border:none;background:none;color:var(--slate);cursor:pointer;
  width:22px;height:22px;border-radius:6px;display:inline-flex;align-items:center;justify-content:center;
  flex-shrink:0;margin-left:.15rem;
}
.player-sub-btn:hover{background:var(--turf-pale);color:var(--turf-deep)}
.player-sub-btn svg{width:12px;height:12px}

.stack-list{
  flex:1;overflow-y:auto;padding:.2rem .75rem 1rem;
  display:flex;flex-direction:column;gap:.5rem;
}
.stack-empty{
  margin:2rem 1rem;padding:1.6rem 1rem;text-align:center;color:var(--slate);
  border:1.5px dashed var(--line);border-radius:var(--radius);font-size:.85rem;
}

.paddle{
  display:flex;align-items:center;gap:.6rem;
  background:var(--surface);border:1.5px solid var(--line);
  border-radius:var(--radius-sm);
  padding:.5rem .6rem;
  touch-action:pan-y;
  transition:box-shadow .15s, border-color .15s, transform .12s;
  position:relative;
}
.paddle .pos{
  font-family:var(--font-mono);font-weight:600;font-size:.95rem;
  color:var(--clay-deep);width:24px;text-align:center;flex-shrink:0;
}
.paddle .glyph{width:20px;height:28px;flex-shrink:0;color:var(--turf)}
.paddle .name-col{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.paddle .sub-row{display:flex;align-items:center;gap:.35rem;flex-wrap:wrap}
.paddle .name{font-weight:600;font-size:.88rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;align-items:center;gap:.3rem}
.paddle .win-chip{font-size:.68rem;color:var(--clay-deep);flex-shrink:0}
.paddle .games-chip{
  font-family:var(--font-mono);font-size:.62rem;font-weight:600;
  color:var(--slate);background:var(--court);
  padding:.05rem .4rem;border-radius:99px;flex-shrink:0;
}
.paddle .tag-pill{
  font-family:var(--font-mono);font-size:.6rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;padding:.08rem .4rem;border-radius:99px;width:fit-content;
}
.paddle .tag-pill.new{background:var(--turf-pale);color:var(--turf-deep)}
.paddle .tag-pill.queued{background:#EFE9DC;color:#8a6d2f}

/* ---- Skill levels: player badges + court-level selects ----
   Open matches with anything, so it uses a neutral gray; the rest step
   through the site's palette from calm (Beginner) to intense (Advanced). */
.level-badge{
  font-family:var(--font-mono);font-size:.6rem;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;padding:.08rem .45rem;border-radius:99px;width:fit-content;
  border:none;line-height:1.5;display:inline-block;white-space:nowrap;flex-shrink:0;
}
button.level-badge{cursor:pointer;touch-action:manipulation;-webkit-user-select:none;user-select:none}
.level-picker-modal{max-width:360px}
.level-picker-name{margin:0 0 1rem;color:var(--slate);font-size:.9rem}
.level-picker-list{display:flex;flex-direction:column;gap:.5rem}
.level-picker-option{
  display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);background:var(--court);
  padding:.7rem .85rem;font-size:.9rem;font-weight:700;color:var(--ink);cursor:pointer;
  text-align:left;transition:border-color .15s,background .15s;
}
.level-picker-option:hover{border-color:var(--turf);background:#fff}
.level-picker-option.current{border-color:var(--turf);background:var(--turf-pale)}
.level-picker-option .level-picker-check{color:var(--turf-deep);display:none}
.level-picker-option.current .level-picker-check{display:inline-flex}
.level-picker-option .level-picker-check svg{width:16px;height:16px}
.lvl-open{background:#EAEEF5;color:var(--slate)}
.lvl-beginner{background:var(--turf-pale);color:var(--turf-deep)}
.lvl-advanced-beginner{background:var(--gold-pale);color:var(--gold-deep)}
.lvl-intermediate{background:#FCE7D6;color:#B35900}
.lvl-advanced{background:var(--danger-pale);color:var(--danger)}
.court-level-badge{flex-shrink:0}
.court-name-row{display:flex;gap:.4rem;align-items:center}
.court-name-row input{
  flex:1;min-width:0;border:1.5px solid var(--line);border-radius:8px;padding:.45rem .6rem;font-size:.82rem;
}
.court-name-row select{
  flex-shrink:0;max-width:8.5rem;border:1.5px solid var(--line);border-radius:8px;
  padding:.45rem .4rem;font-size:.72rem;
}
.paddle .reorder{display:flex;flex-direction:column;gap:1px}
.paddle .reorder button{
  border:none;background:none;color:var(--slate);cursor:pointer;
  padding:0;width:18px;height:13px;display:flex;align-items:center;justify-content:center;
  border-radius:3px;
}
.paddle .reorder button:hover{background:var(--court);color:var(--ink)}
.paddle .reorder button svg{width:11px;height:11px}
.paddle .remove-btn{
  border:none;background:none;color:var(--slate);cursor:pointer;
  width:24px;height:24px;border-radius:6px;display:flex;align-items:center;justify-content:center;
  flex-shrink:0;
}
.paddle .remove-btn:hover{background:var(--danger-pale);color:var(--danger)}
.paddle.next-up{border-color:var(--turf);background:var(--turf-pale)}
.paddle.next-up .pos{color:var(--turf-deep)}

.stack-group{display:flex;flex-direction:column;gap:.5rem}
.stack-group + .stack-group{margin-top:.3rem;padding-top:.7rem;border-top:1.5px dashed var(--line)}
.stack-group-head{display:flex;align-items:center;gap:.5rem;padding:0 .1rem}
.stack-group-count{font-family:var(--font-mono);font-size:.68rem;font-weight:600;color:var(--slate)}

.blocks-panel{
  margin:.8rem 1.1rem .8rem;padding:.7rem .75rem;
  background:var(--court);border:1.5px dashed var(--line);border-radius:var(--radius);
  display:flex;flex-direction:column;gap:.65rem;
}
.blocks-panel[hidden]{display:none}
.viewer-blocks-panel{margin:1.2rem 0 0;background:var(--surface)}
.viewer-blocks-panel .block-flush-btn,
.viewer-blocks-panel .block-level-flush-btn{display:none}
.blocks-panel-title{
  font-family:var(--font-mono);font-size:.68rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:var(--slate);
}
.block-group{display:flex;flex-direction:column;gap:.35rem}
.block-head{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap}
.block-head-label{
  font-weight:700;font-size:.78rem;color:var(--ink);
  flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.block-head-count{
  font-family:var(--font-mono);font-weight:600;font-size:.68rem;
  color:var(--turf-deep);background:var(--turf-pale);
  padding:.05rem .45rem;border-radius:99px;
  white-space:nowrap;flex-shrink:0;
}
.block-flush-btn{
  margin-left:auto;border:1.5px solid var(--line);background:var(--surface);color:var(--slate);
  font-size:.66rem;font-weight:700;padding:.15rem .5rem;border-radius:99px;cursor:pointer;
  transition:border-color .15s,color .15s;
  white-space:nowrap;flex-shrink:0;
}
.block-flush-btn:hover{border-color:var(--turf);color:var(--turf-deep)}
.block-flush-btn:disabled{opacity:.4;cursor:default}
.block-flush-btn:disabled:hover{border-color:var(--line);color:var(--slate)}
.block-list{display:flex;flex-direction:column;gap:.3rem;max-height:200px;overflow-y:auto;padding-right:.1rem}
.block-item{
  display:flex;align-items:center;gap:.4rem;
  background:var(--surface);border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.35rem .55rem;font-size:.8rem;font-weight:600;
}
.block-item .block-item-pos{
  font-family:var(--font-mono);font-size:.75rem;color:var(--slate);width:16px;flex-shrink:0;
}
.block-item .block-item-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.block-item-sub-btn{
  border:none;background:none;color:var(--slate);cursor:pointer;
  width:22px;height:22px;border-radius:6px;display:inline-flex;align-items:center;justify-content:center;
  flex-shrink:0;margin-left:.1rem;
}
.block-item-sub-btn:hover{background:var(--turf-pale);color:var(--turf-deep)}
.block-item-sub-btn svg{width:12px;height:12px}
.block-empty{font-size:.72rem;color:var(--slate);padding:.15rem .1rem}
.block-level-group{display:flex;flex-direction:column;gap:.3rem}
.block-level-group + .block-level-group{margin-top:.5rem;padding-top:.5rem;border-top:1px dashed var(--line)}
.block-level-head{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap}
.block-level-head .level-badge{flex-shrink:0}
.block-level-count{
  font-family:var(--font-mono);font-weight:600;font-size:.64rem;color:var(--slate);
  white-space:nowrap;flex-shrink:0;
}
.block-level-flush-btn{
  margin-left:auto;border:1.5px solid var(--line);background:var(--surface);color:var(--slate);
  font-size:.62rem;font-weight:700;padding:.1rem .45rem;border-radius:99px;cursor:pointer;
  transition:border-color .15s,color .15s;
  white-space:nowrap;flex-shrink:0;
}
.block-level-flush-btn:hover{border-color:var(--turf);color:var(--turf-deep)}

/* ---------- Courts grid ---------- */
.courts-main{padding:1.1rem 1.2rem 4rem}
.courts-main h2{font-family:var(--font-display);font-size:1.02rem;margin:.2rem 0 1rem}
.courts-grid{
  display:grid;grid-template-columns:repeat(auto-fill, minmax(280px,1fr));
  gap:1.1rem;
}
.court-card{
  position:relative;background:var(--surface);border:1.5px solid var(--line);border-radius:var(--radius);
  padding:0 1.05rem 1.05rem;box-shadow:var(--shadow-sm);
  display:flex;flex-direction:column;min-height:268px;overflow:hidden;
  transition:box-shadow .15s, transform .15s;
  container-type:inline-size;container-name:court;
}
.court-card:hover{box-shadow:var(--shadow-md);transform:translateY(-1px)}
.court-card::before{
  content:'';display:block;height:6px;margin:0 -1.05rem;background:var(--turf);
}
.court-card.playing::before{background:var(--clay)}
.court-card.playing{border-color:var(--brand-ink);background:#0E2748;color:#fff}

.court-top{display:flex;align-items:center;justify-content:space-between;gap:.5rem .4rem;padding-top:.85rem;flex-wrap:wrap}
.court-top-right{display:flex;align-items:center;gap:.4rem;flex-shrink:0}
.timer-chip{
  font-family:var(--font-mono);font-size:.66rem;font-weight:700;letter-spacing:.02em;
  color:#A9C3EA;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);
  padding:.25rem .5rem;border-radius:99px;white-space:nowrap;
}
.court-name-wrap{display:flex;align-items:center;gap:.4rem;min-width:0}
.court-name-wrap svg{width:14px;height:14px;color:var(--slate);flex-shrink:0}
.court-card.playing .court-name-wrap svg{color:#7F9FD1}
.court-name{
  font-family:var(--font-display);font-size:1rem;background:transparent;border:none;
  color:inherit;max-width:100%;border-bottom:2px solid transparent;padding:1px 0;min-width:0;
}
.court-name:hover,.court-name:focus{border-bottom-color:var(--line)}
.court-card.playing .court-name:hover,.court-card.playing .court-name:focus{border-bottom-color:rgba(255,255,255,.3)}
.status-badge{
  font-family:var(--font-mono);font-size:.65rem;font-weight:600;letter-spacing:.05em;
  padding:.28rem .55rem;border-radius:99px;text-transform:uppercase;white-space:nowrap;flex-shrink:0;
  display:inline-flex;align-items:center;gap:.3rem;
}
.status-badge::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor}
.status-badge.open{background:var(--turf-pale);color:var(--turf-deep)}
.status-badge.playing{background:rgba(206,17,38,.18);color:#FF97A0}

/* --- Matchup: two team columns with a vs divider, tennis-net style --- */
.matchup{
  flex:1;display:flex;align-items:stretch;gap:0;margin:.9rem 0 .7rem;
  position:relative;min-height:96px;
}
.matchup .team{flex:1;display:flex;flex-direction:column;gap:.4rem;justify-content:center;min-width:0}
.matchup .team.team-b{align-items:flex-end;text-align:right}
.matchup .vs-divider{
  width:1px;background:repeating-linear-gradient(var(--line),var(--line) 4px,transparent 4px,transparent 9px);
  margin:0 .8rem;position:relative;flex-shrink:0;
}
.court-card.playing .vs-divider{background:repeating-linear-gradient(rgba(255,255,255,.25),rgba(255,255,255,.25) 4px,transparent 4px,transparent 9px)}
.vs-divider::after{
  content:'VS';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  font-family:var(--font-mono);font-size:.62rem;font-weight:700;color:var(--slate);
  background:var(--surface);padding:.15rem .3rem;border-radius:5px;letter-spacing:.05em;
}
.court-card.playing .vs-divider::after{background:#0E2748;color:#7F9FD1}

.player-col{display:flex;flex-direction:column;gap:3px;min-width:0}
.player-row{display:flex;align-items:center;gap:.4rem;min-width:0}
.team-b .player-row{flex-direction:row-reverse}
.player-actions-row{display:flex;align-items:center;gap:.28rem;min-width:0;min-height:20px}
.team-b .player-actions-row{justify-content:flex-end}
.player-games-row{display:flex}
.team-b .player-games-row{justify-content:flex-end}
.avatar{
  width:26px;height:26px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-mono);font-weight:700;font-size:.68rem;color:#fff;
}
.player-name-txt{
  font-weight:700;font-size:.95rem;line-height:1.18;
  /* The name row now only shares space with the avatar (win/preview/swap/sub
     buttons live on their own row below), so it has the full column width
     to wrap into and only clamps beyond two lines as a last resort. */
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
  overflow:hidden;word-break:break-word;overflow-wrap:anywhere;white-space:normal;
  flex:1 1 auto;min-width:0;
}
.win-chip{
  font-size:.68rem;flex-shrink:0;opacity:.85;
  display:inline-flex;align-items:center;height:20px;line-height:1;
}

/* ---- Preview full name ---- */
/* A small button next to every player name that pops up the complete,
   normal-case name (not the uppercased/clamped card version) so a long or
   ambiguous name is never a guess, even on the rare card where two lines
   still isn't enough room. */
.player-preview-btn{
  display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
  width:20px;height:20px;padding:0;margin-top:2px;border-radius:50%;
  border:1px solid rgba(255,255,255,.25);background:rgba(255,255,255,.08);color:rgba(255,255,255,.8);
  cursor:pointer;transition:background .15s,border-color .15s,color .15s;
}
.player-preview-btn svg{width:11px;height:11px}
.player-preview-btn:hover,.player-preview-btn:focus-visible{background:rgba(255,255,255,.2);border-color:rgba(255,255,255,.45);color:#fff}
.court-card:not(.playing) .player-preview-btn{
  border:1px solid var(--line);background:var(--court);color:var(--slate);
}
.court-card:not(.playing) .player-preview-btn:hover,
.court-card:not(.playing) .player-preview-btn:focus-visible{background:var(--turf-pale);border-color:var(--turf);color:var(--turf-deep)}

.name-preview-pop{
  position:fixed;z-index:9999;left:0;top:0;transform:translate(-50%,-100%);
  background:#0E2748;color:#fff;font-family:var(--font-display);font-weight:700;font-size:.9rem;
  line-height:1.3;padding:.5rem .75rem;border-radius:10px;box-shadow:var(--shadow-md);
  max-width:min(78vw,300px);text-align:center;word-break:break-word;
  opacity:0;pointer-events:none;transition:opacity .12s ease,transform .12s ease;
}
.name-preview-pop::after{
  content:'';position:absolute;left:50%;top:100%;transform:translateX(-50%);
  border:6px solid transparent;border-top-color:#0E2748;
}
.name-preview-pop.show{opacity:1;transform:translate(-50%,calc(-100% - 10px));}

/* ---- Swap partner (mid-match) ---- */
.player-swap-btn{
  display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
  width:22px;height:22px;padding:0;margin-left:.15rem;border-radius:50%;
  border:1px solid rgba(255,255,255,.25);background:rgba(255,255,255,.08);color:rgba(255,255,255,.8);
  cursor:pointer;transition:background .15s,border-color .15s,color .15s;
}
.player-swap-btn svg{width:12px;height:12px}
.player-swap-btn:hover{background:rgba(255,255,255,.2);border-color:rgba(255,255,255,.45);color:#fff}
.player-swap-btn.selecting{background:var(--gold);border-color:var(--gold);color:var(--brand-ink)}
.player-swap-btn.selecting:hover{background:var(--gold-deep);border-color:var(--gold-deep)}
.player-swap-btn:disabled,
.player-swap-btn.duo-locked{
  opacity:.35;cursor:not-allowed;background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.25);color:rgba(255,255,255,.8);
}
.swap-hint{
  font-size:.75rem;font-weight:600;color:var(--gold);text-align:center;
  background:rgba(252,209,22,.12);border:1px dashed rgba(252,209,22,.4);
  border-radius:var(--radius-sm);padding:.45rem .6rem;
}
.swap-hint b{color:#fff}
/* Cross-court variant: shown on every OTHER eligible court while a swap is
   pending elsewhere, so the host knows tapping a player here will pull
   them into a swap with whoever's already selected on the other court.
   Blue instead of gold so it reads as "elsewhere is waiting on you" rather
   than "you have something selected here" — assumes the dark .playing
   card background like the base .swap-hint above; see the light-card
   override further down alongside the other .court-card:not(.playing)
   swap overrides. */
.swap-hint-remote{color:#9CBEFF;background:rgba(91,141,239,.16);border-color:rgba(91,141,239,.4)}
.swap-hint-remote b{color:#fff}
.swap-hint-court{opacity:.8;font-weight:500}
/* The base .player-swap-btn/.swap-hint styles above assume the dark
   .court-card.playing background. The preview matchup on a not-yet-started
   court uses the regular light/surface card background, so those same
   translucent-white colors would be unreadable there — override with
   theme-aware colors instead. */
.court-card:not(.playing) .player-swap-btn{
  border:1px solid var(--line);background:var(--court);color:var(--slate);
}
.court-card:not(.playing) .player-swap-btn:hover{background:var(--turf-pale);border-color:var(--turf);color:var(--turf-deep)}
.court-card:not(.playing) .player-swap-btn.selecting{background:var(--gold);border-color:var(--gold);color:var(--brand-ink)}
.court-card:not(.playing) .player-swap-btn:disabled,
.court-card:not(.playing) .player-swap-btn.duo-locked{
  opacity:.4;cursor:not-allowed;background:var(--court);border-color:var(--line);color:var(--slate);
}
.court-card:not(.playing) .swap-hint b{color:var(--ink)}
.court-card:not(.playing) .swap-hint-remote{color:var(--turf-deep);background:var(--turf-pale);border-color:var(--turf)}
.court-card:not(.playing) .swap-hint-remote b{color:var(--turf-deep)}
.games-chip{
  font-family:var(--font-mono);font-size:.6rem;font-weight:600;
  color:var(--slate);flex-shrink:0;opacity:.85;
}
.empty-slot{font-size:.78rem;color:var(--slate);font-style:italic}
.court-card.playing .empty-slot{color:#7F9FD1}

/* --- Narrow card fallback: stack teams instead of splitting the width ---
   Card width depends on how many columns the grid decides to show, which
   varies by viewport, sidebar width, and font. Rather than re-tuning pixel
   breakpoints every time a name clips, react to the card's own measured
   width: below ~360px, drop the side-by-side split and give each team the
   full card width. */
@container court (max-width:360px){
  .matchup{flex-direction:column;align-items:stretch;gap:.6rem;min-height:0}
  .matchup .team{flex:none}
  .matchup .team.team-b{align-items:flex-start;text-align:left}
  .team-b .player-row{flex-direction:row}
  .team-b .player-actions-row{justify-content:flex-start}
  .team-b .player-games-row{justify-content:flex-start}
  .matchup .vs-divider{
    width:100%;height:1px;margin:0;align-self:stretch;flex-shrink:0;
    background:repeating-linear-gradient(90deg, var(--line) 0 4px, transparent 4px 9px);
  }
  .court-card.playing .matchup .vs-divider{
    background:repeating-linear-gradient(90deg, rgba(255,255,255,.25) 0 4px, transparent 4px 9px);
  }
  /* Header wrapping was putting the skill-level pill ("Open") top-right
     where people read it as the game status, while the real status pill
     ("On court" + timer) got bumped to its own line below — reading like
     a contradiction. Keep name+status glued together on line one; let the
     level pill be the one that drops down if space is tight. */
  .court-top>.court-name-wrap{order:1}
  .court-top>.status-badge,.court-top>.court-top-right{order:2}
  .court-top>.court-level-badge{order:3;margin-left:auto}
}

.last-result{
  font-size:.72rem;color:var(--slate);padding:.4rem .6rem;background:var(--court);border-radius:8px;
  margin-bottom:.6rem;display:flex;align-items:center;gap:.35rem;
}
.last-result svg{width:12px;height:12px;color:var(--clay);flex-shrink:0}
.last-result span{flex:1;min-width:0}
.undo-result-btn{
  flex-shrink:0;font-family:var(--font-mono);font-size:.62rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.03em;color:var(--clay);background:#fff;
  border:1px solid var(--clay);border-radius:6px;padding:.25rem .5rem;cursor:pointer;
}
.undo-result-btn:hover{background:var(--clay);color:#fff}
.undo-result-btn:active{transform:scale(.96)}

.timer{
  font-family:var(--font-mono);font-size:1.6rem;font-weight:600;letter-spacing:.02em;
  text-align:center;margin-bottom:.7rem;
}

/* --- Live scoreboard (Settings > Enable Scoring) --- */
.scoreboard-live{
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);border-radius:10px;
  padding:.65rem .7rem;margin-bottom:.7rem;
}
.scoreboard-live.has-winner{border-color:var(--clay);background:rgba(206,17,38,.16)}
.sbl-row{display:flex;gap:.6rem}
.sbl-team{flex:1;display:flex;flex-direction:column;align-items:center;gap:.35rem;min-width:0}
.sbl-label{
  font-family:var(--font-mono);font-size:.6rem;font-weight:700;letter-spacing:.03em;
  color:#A9C3EA;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;
}
.sbl-servewrap{
  min-height:1.35rem;display:flex;align-items:center;justify-content:center;
}
.serve-indicator{
  font-family:var(--font-mono);font-size:.6rem;font-weight:700;letter-spacing:.02em;
  color:#A9C3EA;text-transform:uppercase;white-space:nowrap;
}
.serve-set-btn{
  font-family:var(--font-mono);font-size:.58rem;font-weight:700;letter-spacing:.02em;
  text-transform:uppercase;color:#FF97A0;background:rgba(206,17,38,.16);
  border:1px solid rgba(206,17,38,.5);border-radius:6px;padding:.2rem .4rem;cursor:pointer;
  white-space:nowrap;line-height:1;
}
.serve-set-btn:hover{background:rgba(206,17,38,.3)}
.sbl-stepper{display:flex;align-items:center;gap:.55rem}
.sbl-stepper-readonly{justify-content:center}
.sbl-stepper-readonly .sbl-num{font-size:2rem}
.sbl-num{font-family:var(--font-mono);font-size:1.5rem;font-weight:700;min-width:1.6ch;text-align:center;color:#fff}
.score-btn{
  width:28px;height:28px;border-radius:50%;border:1px solid rgba(255,255,255,.28);
  background:rgba(255,255,255,.09);color:#fff;font-size:1rem;font-weight:700;cursor:pointer;
  display:flex;align-items:center;justify-content:center;line-height:1;padding:0;flex-shrink:0;
  transition:background .12s, transform .1s;
}
.score-btn:hover:not(:disabled){background:rgba(255,255,255,.2)}
.score-btn:active:not(:disabled){transform:scale(.92)}
.score-btn:disabled{opacity:.28;cursor:default}
.sbl-actions{display:flex;gap:.4rem;margin-top:.6rem}
.sbl-btn{
  flex:1;font-family:var(--font-mono);font-size:.64rem;font-weight:700;letter-spacing:.02em;
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.18);color:#DCE6F5;
  border-radius:7px;padding:.42rem .3rem;cursor:pointer;text-transform:uppercase;
}
.sbl-btn:hover:not(:disabled){background:rgba(255,255,255,.16)}
.sbl-btn:disabled{opacity:.28;cursor:default}

.court-cta{
  margin-top:auto;width:100%;border:none;border-radius:var(--radius-sm);
  padding:.7rem;font-weight:800;font-size:.88rem;cursor:pointer;letter-spacing:.01em;
  transition:background .15s,opacity .15s,transform .1s;
}
.court-cta.call{background:var(--clay);color:#fff}
.court-cta.call:hover:not(:disabled){background:var(--clay-deep)}
.court-cta.call:disabled{background:var(--line);color:var(--slate);cursor:not-allowed}
.court-cta.end{background:rgba(255,255,255,.12);color:#fff}
.court-cta.end:hover{background:rgba(255,255,255,.22)}
.court-cta:active:not(:disabled){transform:scale(.98)}

.court-cta-row{display:flex;gap:.5rem;margin-top:auto}
.court-cta-row .court-cta{margin-top:0;flex:1;width:auto;min-width:0}
.court-cta.call-players{background:transparent;color:var(--clay-deep);border:1.5px solid var(--clay)}
.court-cta.call-players:hover:not(:disabled){background:var(--clay);color:#fff}
.court-cta.call-players:disabled{background:transparent;color:var(--slate);border-color:var(--line);cursor:not-allowed}
.court-cta.call-players.speaking{animation:call-players-pulse 1s ease-in-out infinite}
@keyframes call-players-pulse{0%,100%{opacity:1}50%{opacity:.55}}

.auto-start-hint{
  margin-top:.4rem;font-size:.7rem;font-weight:600;color:var(--slate);text-align:center;
  font-family:var(--font-mono);letter-spacing:.01em;
}

.courts-empty{
  padding:3rem 1rem;text-align:center;color:var(--slate);border:1.5px dashed var(--line);
  border-radius:var(--radius);
}

/* ---------- History ---------- */
.history{margin-top:1.6rem}
.history summary{
  cursor:pointer;font-weight:700;font-size:.85rem;color:var(--slate);
  padding:.5rem 0;list-style:none;display:flex;align-items:center;gap:.4rem;
}
.history summary::-webkit-details-marker{display:none}
.history summary svg{width:12px;height:12px;transition:transform .15s}
.history[open] summary svg{transform:rotate(90deg)}
.history-list{display:flex;flex-direction:column;gap:.5rem;padding:.3rem 0 0}
.history-row{
  display:flex;justify-content:space-between;gap:.6rem;font-size:.78rem;color:var(--slate);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:.5rem .7rem;
}
.history-row b{color:var(--ink)}

/* On-deck rows: a mono "On deck N" pill up front so the queue order reads at
   a glance, then the matchup itself set large and bold — this used to be a
   single run-on sentence in the same small gray text as everything else,
   which made the actual players easy to miss. */
.ondeck-row{
  position:relative;isolation:isolate;
  display:flex;align-items:center;flex-wrap:wrap;gap:.35rem .9rem;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:.7rem .9rem .7rem 1.05rem;box-shadow:var(--shadow-sm);
  transition:box-shadow .15s ease,border-color .15s ease,transform .15s ease;
}
.ondeck-row::before{
  content:'';position:absolute;left:0;top:.45rem;bottom:.45rem;width:3px;
  border-radius:99px;background:var(--line);transition:background .15s ease;
}
.ondeck-row:hover{box-shadow:var(--shadow-md);transform:translateY(-1px)}
.ondeck-row:first-child{border-color:var(--turf-pale);background:linear-gradient(180deg,var(--turf-pale) 0%,var(--surface) 65%)}
.ondeck-row:first-child::before{background:var(--turf)}
.ondeck-num{
  display:inline-flex;align-items:center;gap:.3rem;
  font-family:var(--font-mono);font-size:.64rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--slate);background:var(--court);
  border:1px solid var(--line);
  padding:.26rem .55rem;border-radius:99px;white-space:nowrap;flex-shrink:0;
}
.ondeck-row:first-child .ondeck-num{color:var(--turf-deep);background:var(--surface);border-color:var(--turf-pale)}
.ondeck-matchup{
  display:flex;align-items:center;flex-wrap:wrap;gap:.4rem .55rem;
  font-size:.92rem;font-weight:700;color:var(--ink);min-width:0;flex:1;
}
.ondeck-team{min-width:0;overflow-wrap:anywhere}
.ondeck-vs{
  font-family:var(--font-mono);font-size:.6rem;font-weight:700;color:var(--slate);
  text-transform:uppercase;letter-spacing:.06em;flex-shrink:0;
  background:var(--court);border-radius:5px;padding:.1rem .35rem;
}
.ondeck-more,.ondeck-empty{
  text-align:center;color:var(--slate);font-size:.78rem;
  background:var(--court);border:1px dashed var(--line);border-radius:var(--radius-sm);
  padding:.6rem .8rem;
}

/* ---------- Match history modal ---------- */
.modal.wide{max-width:560px}
.match-history-list{display:flex;flex-direction:column;gap:.55rem;max-height:52vh;overflow-y:auto;padding:.1rem}
.match-full-row{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:.65rem .8rem;font-size:.82rem;
}
.match-full-head{display:flex;justify-content:space-between;gap:.5rem;margin-bottom:.35rem}
.match-full-court{font-weight:700;color:var(--ink)}
.match-full-when{color:var(--slate);font-size:.72rem}
.match-full-teams{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;color:var(--ink);font-weight:600}
.match-full-vs{color:var(--slate);font-weight:700;font-size:.7rem;text-transform:uppercase}
.match-team-won{color:var(--turf-deep)}
.match-full-meta{color:var(--slate);font-size:.72rem;margin-top:.3rem}
.swap-note{margin-top:.4rem;padding:.4rem .55rem;background:var(--turf-pale);border-radius:7px;border:1px dashed var(--turf)}
.swap-note-title{display:flex;align-items:center;font-size:.7rem;font-weight:700;color:var(--turf-deep);margin-bottom:.25rem}
.swap-note-line{display:block;font-size:.72rem;color:var(--ink);line-height:1.5}
.swap-note-line s{color:var(--slate);opacity:.75}

/* ---------- Modals ---------- */
.overlay{
  position:fixed;inset:0;background:rgba(21,36,32,.5);backdrop-filter:blur(2px);
  display:flex;align-items:center;justify-content:center;padding:1.2rem 1rem;z-index:100;overflow-y:auto;
}
.overlay[hidden]{display:none}
.modal{
  background:#fff;border-radius:16px;max-width:440px;width:100%;
  max-height:calc(100vh - 2.4rem);overflow-y:auto;box-shadow:var(--shadow-md);
  padding:1.6rem 1.4rem 1.8rem;margin:auto;
}
.modal h3{font-family:var(--font-display);font-size:1.1rem;margin:0 0 1rem}
.confirm-modal{max-width:400px}
.confirm-message{margin:0 0 1.2rem;color:var(--slate);line-height:1.5;font-size:.95rem}
.field{margin-bottom:1rem}
.field label{display:block;font-size:.78rem;font-weight:700;color:var(--slate);margin-bottom:.35rem;text-transform:uppercase;letter-spacing:.03em}
.field input[type=text],.field input[type=number],.field input[type=email],.field input[type=password],.field select{
  width:100%;border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.6rem .7rem;font-size:.9rem;background:var(--court);color:var(--ink);
}
.field input:focus,.field select:focus{border-color:var(--turf);background:#fff}
.seg{display:flex;border:1.5px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.seg button{
  flex:1;border:none;background:var(--court);padding:.6rem;font-weight:700;font-size:.85rem;
  cursor:pointer;color:var(--slate);
}
.seg button.active{background:var(--turf);color:#fff}
.stepper{display:flex;align-items:center;gap:.7rem}
.stepper button{
  width:36px;height:36px;border-radius:9px;border:1.5px solid var(--line);background:#fff;
  font-size:1.1rem;font-weight:700;cursor:pointer;color:var(--ink);
}
.stepper button:hover{border-color:var(--turf);color:var(--turf-deep)}
.stepper .n{font-family:var(--font-mono);font-weight:600;font-size:1.1rem;min-width:2ch;text-align:center}
.court-name-rows{display:flex;flex-direction:column;gap:.4rem;margin-top:.6rem;max-height:180px;overflow-y:auto}
.toggle-row{display:flex;align-items:center;justify-content:space-between;gap:.5rem;padding:.3rem 0}
.target-sub{margin-top:.7rem;padding:.75rem .8rem;background:var(--court);border-radius:var(--radius-sm);border:1.5px solid var(--line)}
.match-style-group{display:flex;flex-direction:column;gap:.6rem}
.match-style-card{
  display:flex;flex-direction:column;gap:.3rem;text-align:left;width:100%;
  background:var(--court);border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.75rem .85rem;cursor:pointer;font-family:var(--font-body);
  transition:border-color .15s ease,background .15s ease;
}
.match-style-card:hover{border-color:var(--turf-deep)}
.match-style-card.active{border-color:var(--turf);background:var(--turf-pale)}
.match-style-head{display:flex;align-items:center;gap:.5rem}
.match-style-check{
  width:19px;height:19px;flex:0 0 auto;border-radius:50%;border:1.5px solid var(--line);
  display:flex;align-items:center;justify-content:center;color:#fff;background:transparent;
}
.match-style-check svg{width:13px;height:13px;visibility:hidden}
.match-style-card.active .match-style-check{background:var(--turf);border-color:var(--turf)}
.match-style-card.active .match-style-check svg{visibility:visible}
.match-style-title{font-weight:800;font-size:.95rem;color:var(--ink)}
.match-style-tag{
  font-size:.68rem;font-weight:700;letter-spacing:.02em;text-transform:uppercase;
  background:var(--turf-pale);color:var(--turf-deep);padding:.15rem .5rem;border-radius:999px;
}
.match-style-desc{font-size:.83rem;color:var(--ink);line-height:1.4;padding-left:1.75rem}
.match-style-note{font-size:.83rem;font-weight:700;color:var(--turf-deep);line-height:1.4;padding-left:1.75rem}
.match-style-card:not(.active) .match-style-note{color:var(--slate)}

/* ---------- Skill Levels toggle (Settings) ----------
   Off by default: every level badge/select in the app is hidden via this
   single body-class switch, rather than each render function branching on
   the setting individually. Internally everyone still carries 'Open' (or
   whatever was set before the feature was turned off) — this only ever
   controls what's shown, never the underlying data or matching logic. */
body:not(.levels-on) .level-badge,
body:not(.levels-on) #addLevelSelect,
body:not(.levels-on) .court-level-select{
  display:none !important;
}
.target-sub label{margin-bottom:.35rem}
.target-sub input[type=number]{max-width:100px}
.fixed-duo-add-row{display:flex;gap:.4rem;align-items:center;flex-wrap:wrap}
.fixed-duo-add-row select{
  flex:1;min-width:0;padding:.5rem .6rem;border:1.5px solid var(--line);border-radius:8px;background:#fff;
  font-size:.82rem;color:var(--ink);
}
.fixed-duo-add-row select:focus{border-color:var(--turf)}
.fixed-duo-list{display:flex;flex-direction:column;gap:.4rem;margin-top:.6rem}
.fixed-duo-row{
  display:flex;align-items:center;gap:.5rem;background:#fff;border:1px solid var(--line);
  border-radius:8px;padding:.45rem .6rem;
}
.fixed-duo-row .fd-names{flex:1;min-width:0;font-size:.8rem;font-weight:700;color:var(--turf-deep);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fixed-duo-row .fd-names svg{width:12px;height:12px;vertical-align:-1px;margin:0 .25rem;color:var(--turf)}
.fixed-duo-empty{font-size:.78rem;color:var(--slate);font-style:italic;margin-top:.5rem}
.games-chip.at-target{background:var(--turf-pale);color:var(--turf-deep)}
.switch{position:relative;width:44px;height:25px;flex-shrink:0}
.switch input{opacity:0;width:0;height:0}
.switch .track{position:absolute;inset:0;background:var(--line);border-radius:99px;transition:background .15s;cursor:pointer}
.switch .track::before{content:'';position:absolute;width:19px;height:19px;left:3px;top:3px;background:#fff;border-radius:50%;transition:transform .15s;box-shadow:0 1px 2px rgba(0,0,0,.2)}
.switch input:checked + .track{background:var(--turf)}
.switch input:checked + .track::before{transform:translateX(19px)}
.modal-actions{display:flex;gap:.6rem;margin-top:1.2rem;flex-wrap:wrap}
.btn{border:none;border-radius:var(--radius-sm);padding:.65rem 1.1rem;font-weight:700;font-size:.85rem;cursor:pointer;transition:background .15s,opacity .15s}
.btn.primary{background:var(--turf);color:#fff}
.btn.primary:hover{background:var(--turf-deep)}
.btn.ghost{background:var(--court);color:var(--ink)}
.btn.ghost:hover{background:var(--line)}
.btn.danger{background:var(--danger-pale);color:var(--danger)}
.btn.danger:hover{background:var(--danger);color:#fff}
.btn.warn{background:transparent;color:var(--clay-deep);border:1.5px solid var(--clay);}
.btn.warn:hover{background:var(--clay);color:#fff}
.btn.solid-turf{background:var(--turf);color:#fff}
.btn.solid-turf:hover{background:var(--turf-deep)}
.btn.sm{padding:.4rem .75rem;font-size:.76rem;flex-shrink:0}
.divider{border:none;border-top:1px solid var(--line);margin:1.2rem 0}
.danger-zone h4{font-size:.78rem;text-transform:uppercase;letter-spacing:.03em;color:var(--slate);margin:0 0 .5rem}
.file-row{display:flex;gap:.5rem;flex-wrap:wrap}
.field-head-row{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:.35rem}

/* ---------- Roster management (Settings) ---------- */
.roster-manage-wrap{border:1.5px solid var(--line);border-radius:10px;overflow:hidden}
.roster-manage-toggle{
  display:flex;align-items:center;gap:.5rem;padding:.6rem .75rem;
  font-weight:700;font-size:.85rem;color:var(--ink);cursor:pointer;user-select:none;list-style:none;
}
.roster-manage-toggle::-webkit-details-marker{display:none}
.roster-manage-toggle:hover{background:var(--court)}
.roster-manage-toggle svg{width:12px;height:12px;flex-shrink:0;color:var(--slate);transition:transform .15s}
.roster-manage-wrap[open] .roster-manage-toggle svg{transform:rotate(90deg)}
.roster-manage-toggle span:first-of-type{flex:1;min-width:0}
.roster-manage-body{padding:0 .75rem .75rem}
.roster-manage-actions{display:flex;margin-top:.5rem}
.roster-manage-actions .btn{width:100%}
.roster-manage-search input{
  width:100%;border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.55rem .7rem;font-size:.82rem;background:var(--court);color:var(--ink);margin-bottom:.5rem;
}
.roster-manage-search input:focus{border-color:var(--turf);background:#fff}
.roster-manage-list{
  display:flex;flex-direction:column;gap:.2rem;max-height:190px;overflow-y:auto;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);padding:.35rem;
}
.roster-manage-row{display:flex;align-items:center;gap:.55rem;padding:.4rem .5rem;border-radius:7px}
.roster-manage-row:hover{background:var(--court)}
.roster-manage-row .rm-avatar{
  width:22px;height:22px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-mono);font-weight:700;font-size:.6rem;color:#fff;
}
.roster-manage-row .rm-name{flex:1;min-width:0;font-size:.85rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tag-pill.floor{background:var(--turf-pale);color:var(--turf-deep);flex-shrink:0}
.rm-del,.rm-edit{
  border:none;background:none;color:var(--slate);cursor:pointer;
  width:23px;height:23px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.rm-del:hover{background:var(--danger-pale);color:var(--danger)}
.rm-del svg,.rm-edit svg{width:12px;height:12px}
.rm-edit:hover{background:var(--turf-pale);color:var(--turf-deep)}
.roster-manage-empty{padding:1.1rem .5rem;text-align:center;color:var(--slate);font-size:.8rem}

/* ---------- Rename player modal ---------- */
.rename-player-modal #renamePlayerInput{
  width:100%;box-sizing:border-box;font-size:.95rem;padding:.55rem .7rem;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);background:var(--bg);color:inherit;
}
.rename-player-modal #renamePlayerInput:focus{outline:none;border-color:var(--accent, var(--turf-deep))}

/* ---------- Session banner (read-only / ended state) ----------
   Styled like court-closure hazard tape — diagonal stripe edges framing
   a plain notice, echoing how a real court gets physically closed off. */
.session-banner{background:#FBE3E5}
.session-banner::before,.session-banner::after{
  content:'';display:block;height:7px;
  background:repeating-linear-gradient(135deg, var(--clay) 0 10px, var(--clay-deep) 10px 20px);
}
.session-banner-inner{
  max-width:1400px;margin:0 auto;padding:.65rem 1.1rem;
  display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;
}
.session-banner .eyebrow{
  font-family:var(--font-mono);font-size:.66rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--clay-deep);background:#fff;padding:.28rem .6rem;border-radius:99px;flex-shrink:0;
  display:inline-flex;align-items:center;gap:.35rem;
}
.session-banner .eyebrow svg{width:12px;height:12px}
.session-banner .msg{flex:1;min-width:220px;font-size:.82rem;font-weight:500;color:#7a3c22}
body.session-locked .add-form{opacity:.55}
body.session-locked .add-form input,body.session-locked .add-form button{cursor:not-allowed}
body.session-locked .paddle .reorder,body.session-locked .paddle .remove-btn{
  opacity:.35;pointer-events:none;
}
.endgame-row .choice button:disabled{opacity:.4;cursor:not-allowed}
.endgame-row .choice button:disabled:hover{background:#fff;border-color:var(--line);color:var(--slate)}

.endgame-list{display:flex;flex-direction:column;gap:.5rem;margin-bottom:.4rem}
.endgame-row{display:flex;align-items:center;justify-content:space-between;gap:.6rem;padding:.55rem .7rem;border:1.5px solid var(--line);border-radius:var(--radius-sm)}
.endgame-row .who{font-weight:700;font-size:.88rem}
.endgame-row .choice{display:flex;gap:.3rem}
.endgame-row .choice button{
  border:1.5px solid var(--line);background:#fff;border-radius:7px;padding:.3rem .55rem;font-size:.72rem;font-weight:700;cursor:pointer;color:var(--slate);
}
.endgame-row .choice button.sel-requeue.active{background:var(--turf-pale);border-color:var(--turf);color:var(--turf-deep)}
.endgame-row .choice button.sel-done.active{background:var(--danger-pale);border-color:var(--danger);color:var(--danger)}

.winner-pick{display:grid;grid-template-columns:1fr 1fr;gap:.6rem;margin-bottom:1.1rem}
.winner-card{
  border:2px solid var(--line);border-radius:var(--radius-sm);background:var(--court);
  padding:.7rem .6rem;cursor:pointer;text-align:center;transition:border-color .15s,background .15s;
}
.winner-card:hover{border-color:var(--turf)}
.winner-card.selected{border-color:var(--clay);background:#FBE3E5}
.winner-card .trophy{font-size:1.1rem;display:block;margin-bottom:.3rem;opacity:.35}
.winner-card.selected .trophy{opacity:1}
.winner-card .team-label{font-family:var(--font-mono);font-size:.62rem;font-weight:700;color:var(--slate);text-transform:uppercase;letter-spacing:.04em;margin-bottom:.2rem}
.winner-card .team-names{font-weight:700;font-size:.85rem;line-height:1.3;margin-bottom:.55rem}
.winner-card .score-input{
  width:100%;max-width:64px;margin:0 auto;display:block;text-align:center;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);background:#fff;
  font-family:var(--font-mono);font-weight:700;font-size:1.05rem;color:var(--ink);
  padding:.3rem .2rem;cursor:text;
}
.winner-card .score-input:focus{border-color:var(--clay);outline:none}
.winner-card.selected .score-input{border-color:var(--clay)}
.winner-note{font-size:.75rem;color:var(--slate);text-align:center;margin:-.6rem 0 1rem}
.section-label{font-size:.78rem;font-weight:700;color:var(--slate);text-transform:uppercase;letter-spacing:.03em;margin:0 0 .5rem}
.about-steps{margin:0 0 1.2rem;padding-left:1.1rem;display:flex;flex-direction:column;gap:.5rem}
.about-steps li{font-size:.84rem;line-height:1.5;color:var(--ink)}
.about-steps li b{color:var(--turf-deep)}
.about-credit{font-size:.85rem;line-height:1.6;color:var(--ink);margin:0 0 .2rem}
.about-credit a{color:var(--turf-deep);font-weight:600;text-decoration:none}
.about-credit a:hover{text-decoration:underline}

/* ---------- Rankings modal: header, toolbar, summary ---------- */
.rankings-modal-head{display:flex;align-items:center;justify-content:space-between;gap:.6rem;margin-bottom:.7rem}
.rankings-modal-head h3{margin:0}
.rankings-head-actions{display:flex;gap:.4rem;flex-shrink:0}
.modal-icon-btn{
  width:32px;height:32px;border-radius:8px;border:1.5px solid var(--line);background:#fff;color:var(--slate);
  display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;
  transition:background .15s,border-color .15s,color .15s;
}
.modal-icon-btn svg{width:15px;height:15px}
.modal-icon-btn:hover{border-color:var(--turf);color:var(--turf-deep);background:var(--turf-pale)}
.modal-icon-btn:disabled{opacity:.5;cursor:not-allowed;border-color:var(--line);color:var(--slate);background:#fff}
.modal-icon-btn.active{border-color:var(--turf);color:var(--turf-deep);background:var(--turf-pale)}
.modal-icon-btn.spinning svg{animation:rankings-spin .8s linear infinite}
@keyframes rankings-spin{to{transform:rotate(360deg)}}

.rankings-toolbar{
  display:flex;align-items:center;gap:.5rem;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.5rem .7rem;margin-bottom:.8rem;background:var(--court);
}
.rankings-toolbar svg{width:15px;height:15px;color:var(--slate);flex-shrink:0}
.rankings-toolbar input{
  flex:1;min-width:0;border:none;background:none;font-size:.85rem;color:var(--ink);padding:0;
}
.rankings-toolbar input:focus{outline:none}
.rankings-toolbar:focus-within{border-color:var(--turf);background:#fff}

.rankings-summary{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:.7rem}
.rankings-summary .stat-chip{
  font-family:var(--font-mono);font-size:.66rem;font-weight:700;letter-spacing:.01em;
  background:var(--court);color:var(--slate);padding:.32rem .65rem;border-radius:99px;white-space:nowrap;
}
.rankings-summary .stat-chip b{color:var(--turf-deep);font-size:.78rem;margin-right:.15em}

.rankings-list{display:flex;flex-direction:column;gap:.4rem;max-height:44vh;overflow-y:auto;padding:.1rem .15rem .1rem 0}
.rank-level-group{display:flex;flex-direction:column;gap:.4rem}
.rank-level-group + .rank-level-group{margin-top:.4rem;padding-top:.7rem;border-top:1.5px dashed var(--line)}
.rank-level-head{display:flex;align-items:center;gap:.5rem;padding:0 .1rem}
.rank-level-count{font-family:var(--font-mono);font-size:.66rem;font-weight:600;color:var(--slate)}
.rank-row{
  display:flex;align-items:center;gap:.7rem;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.55rem .7rem;background:#fff;
  transition:border-color .15s,background .15s;
}
.rank-row:hover{border-color:var(--turf)}
.rank-row .rank-num{
  font-family:var(--font-mono);font-weight:700;font-size:.85rem;color:var(--slate);
  width:22px;text-align:center;flex-shrink:0;
}
.rank-row.top1{background:var(--gold-pale);border-color:#EBD27A}
.rank-row.top1 .rank-num{color:var(--gold-deep)}
.rank-row.top2 .rank-num{color:#8A8F92}
.rank-row.top3 .rank-num{color:#B4712F}
.rank-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:.28rem}
.rank-top-line{display:flex;align-items:center;gap:.4rem}
.rank-row .rank-name{flex:1;min-width:0;font-weight:700;font-size:.88rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mvp-badge{
  flex-shrink:0;font-family:var(--font-mono);font-size:.6rem;font-weight:700;letter-spacing:.02em;
  color:#B4870B;background:#FFF6E0;border:1px solid #F0D998;border-radius:99px;padding:.15rem .5rem;white-space:nowrap;
}
.rank-meta-line{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
.rank-row .rank-games{font-family:var(--font-mono);font-size:.62rem;font-weight:600;letter-spacing:.01em;color:var(--slate);flex-shrink:0;white-space:nowrap}
.rank-avg{font-family:var(--font-mono);font-size:.62rem;font-weight:600;letter-spacing:.01em;color:var(--slate);flex-shrink:0;white-space:nowrap}
.rank-row .rank-record{font-family:var(--font-mono);font-size:.78rem;color:var(--slate);flex-shrink:0}
.rank-row .rank-pct{
  font-family:var(--font-mono);font-weight:700;font-size:.78rem;color:var(--turf-deep);
  background:var(--turf-pale);padding:.1rem .5rem;border-radius:99px;flex-shrink:0;min-width:3.4em;text-align:center;
}
.rankings-empty{
  text-align:center;color:var(--slate);padding:2rem 1rem;font-size:.85rem;
  border:1.5px dashed var(--line);border-radius:var(--radius);
}

/* ---------- Rankings modal: full-screen expanded state ---------- */
.modal.rankings-full{
  max-width:min(1200px, calc(100vw - 2rem));
  width:100%;
  height:calc(100vh - 2.4rem);
  max-height:calc(100vh - 2.4rem);
  display:flex;flex-direction:column;overflow:hidden;
}
.modal.rankings-full .rankings-modal-head,
.modal.rankings-full .rankings-toolbar,
.modal.rankings-full .rankings-summary,
.modal.rankings-full .modal-actions{flex-shrink:0}
.modal.rankings-full #rankingsCaptureArea{display:flex;flex-direction:column;flex:1;min-height:0}
.modal.rankings-full .rankings-list{
  flex:1;max-height:none;overflow-y:auto;
  display:grid;grid-template-columns:repeat(auto-fill, minmax(280px, 1fr));
  align-content:start;gap:.5rem .7rem;
}
.modal.rankings-full .rank-row{font-size:1.02rem;padding:.7rem .85rem}
.modal.rankings-full .rank-row .rank-name{font-size:.95rem}
.modal.rankings-full .rank-level-group{grid-column:1 / -1}
@media (max-width:640px){
  .modal.rankings-full .rankings-list{grid-template-columns:1fr}
}

/* ---------- Toasts ---------- */
.toast-wrap{position:fixed;bottom:1.2rem;left:50%;transform:translateX(-50%);z-index:200;display:flex;flex-direction:column-reverse;gap:.5rem;align-items:center;width:100%;pointer-events:none}
/* Toasts are now just a small silent progress bar — no icon, no message
   text — a brief "something happened" pulse instead of a popup to read. */
.toast{
  position:relative;overflow:hidden;
  width:64px;height:4px;border-radius:99px;
  background:rgba(120,120,120,.22);
  box-shadow:var(--shadow-md);opacity:0;transform:translateY(6px) scale(.97);
  transition:opacity .22s,transform .22s;
}
html[data-theme="dark"] .toast{background:rgba(255,255,255,.14)}
.toast.show{opacity:1;transform:translateY(0) scale(1)}
.toast-progress{
  position:absolute;left:0;right:0;top:0;bottom:0;
  background:var(--brand-ink);transform-origin:left;
  animation:toast-shrink .9s linear forwards;
}
html[data-theme="dark"] .toast-progress{background:#fff}
@keyframes toast-shrink{from{transform:scaleX(1)}to{transform:scaleX(0)}}
@media (prefers-reduced-motion:reduce){.toast-progress{animation:none;display:none}}

/* ---------- Large screens: keep the shell from over-stretching ---------- */
@media (min-width:1440px){
  .app-shell{max-width:1680px;margin:0 auto}
}

/* ---------- Tablet (landscape iPad / Android tablet) ----------
   Between the full desktop rail and the phone tab-bar layout: keep the
   two-pane view but tighten it up so it doesn't feel like a stretched
   desktop screen. */
@media (min-width:881px) and (max-width:1180px){
  .app-shell{grid-template-columns:300px 1fr}
  .courts-grid{grid-template-columns:repeat(auto-fill, minmax(320px,1fr))}
  .courts-main{padding:1rem 1rem 3.5rem}
}

/* ---------- Touch devices: real tap targets everywhere ----------
   Applies on any device without a fine pointer (tablets, phones) rather
   than by screen width alone, so a large touch tablet still gets it.
   Kept modest inside the queue rows specifically — that list is dense by
   design, and oversizing its controls was crowding player names out. */
@media (pointer:coarse){
  .icon-btn{width:var(--touch);height:var(--touch)}
  .modal-icon-btn{width:40px;height:40px}
  .arrival-remove-btn,.rm-del{
    width:var(--touch-sm);height:var(--touch-sm)
  }
  .paddle .remove-btn{width:30px;height:30px}
  .paddle .reorder button{width:22px;height:16px}
  .stepper button{width:42px;height:42px}
  .score-btn{width:32px;height:32px}
  .seg button{padding:.75rem .6rem}
  .panel-action-btn{padding:.55rem .85rem}
  .switch{width:48px;height:27px}
  .switch .track::before{width:21px;height:21px}
  .switch input:checked + .track::before{transform:translateX(21px)}
  .quick-add-chip,.quick-add-all-btn,.arrival-checkin-btn,.checkin-all-btn,.block-flush-btn{
    min-height:var(--touch-sm);padding:.5rem .75rem;font-size:.82rem;
  }
  .quick-add-chip svg{width:13px;height:13px}
  .btn{min-height:var(--touch);display:inline-flex;align-items:center;justify-content:center}
  .btn.sm{min-height:var(--touch-sm)}
  .court-cta{min-height:var(--touch)}
  .add-form button{min-height:var(--touch)}
}

/* ---------- Queue rows: protect the name column at all costs ----------
   With pos + name + reorder + remove all sharing one row,
   the name is the one thing that must never lose the fight for space. */
.paddle{gap:.5rem}
.paddle .name-col{flex:1 1 auto;min-width:0}
.paddle .pos{width:20px}
@media (max-width:1180px){
  /* The paddle icon is purely decorative — dropping it frees enough room
     to keep the name readable without losing the up/down reorder buttons
     (which, unlike drag-and-drop, work reliably even mid-scroll). */
  .paddle .glyph{display:none}
}

/* ---------- Mobile / narrow tablet portrait ---------- */
.mobile-tabs{display:none}
@media (max-width:880px){
  .app-shell{grid-template-columns:1fr;padding-bottom:calc(64px + env(safe-area-inset-bottom))}
  .stack-rail{
    position:static;height:auto;min-height:0;border-right:none;border-bottom:1px solid var(--line);
    display:none;
  }
  .app-shell.show-stack .stack-rail{display:flex}
  .app-shell.show-courts .courts-main{display:block}
  .app-shell.show-stack .courts-main{display:none}
  .app-shell.show-courts .stack-rail{display:none}
  .stack-list{max-height:none}
  .courts-main{padding:1rem .9rem 2.5rem}
  .courts-grid{grid-template-columns:repeat(auto-fill, minmax(280px,1fr));gap:.85rem}
  .mobile-tabs{
    display:flex;position:fixed;bottom:0;left:0;right:0;background:var(--brand-ink);z-index:50;
    box-shadow:0 -2px 10px rgba(0,0,0,.15);padding-bottom:env(safe-area-inset-bottom);
  }
  .mobile-tabs button{
    flex:1;border:none;background:none;color:#8fada2;padding:.75rem;font-weight:700;font-size:.8rem;
    cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:.2rem;
    min-height:var(--touch);
  }
  .mobile-tabs button.active{color:#fff}
  .mobile-tabs button svg{width:18px;height:18px}
  .topbar .session-name{max-width:32vw}
}

/* ---------- Modals as bottom sheets on phones ----------
   A centered card modal on a 6" screen reads as "unfinished web form";
   docking it to the bottom edge with a drag-grabber reads as a native
   app component and is easier to reach one-handed. */
@media (max-width:640px){
  .overlay{align-items:flex-end;padding:0}
  .modal{
    max-width:100%;width:100%;border-radius:20px 20px 0 0;
    max-height:92vh;margin:0;
    padding:1.5rem 1.1rem calc(1.5rem + env(safe-area-inset-bottom));
    animation:sheet-up .22s ease-out;
  }
  .modal::before{
    content:'';display:block;width:36px;height:4px;border-radius:99px;
    background:var(--line);margin:-.5rem auto 1rem;
  }
  .modal.wide{max-width:100%}
  .modal.rankings-full{
    height:100%;max-height:100%;border-radius:0;animation:none;
  }
  .modal.rankings-full::before{display:none}
  .modal-actions{flex-direction:column-reverse}
  .modal-actions .btn{width:100%}
}
@keyframes sheet-up{from{transform:translateY(24px);opacity:0}to{transform:translateY(0);opacity:1}}

@media (max-width:480px){
  .topbar{gap:.4rem;padding:.65rem .6rem}
  .topbar .logo{display:none}
  .topbar .session-name{max-width:26vw;font-size:.95rem}
  .topbar .pill{display:none}
  .icon-btn{width:36px;height:36px;border-radius:9px}
  .icon-btn svg{width:17px;height:17px}
  .winner-pick{grid-template-columns:1fr 1fr;gap:.5rem}
}
@media (prefers-reduced-motion:reduce){
  *{transition:none !important;animation:none !important}
  .modal{animation:none}
}

/* ================= Host Online (Supabase live sharing) ================= */
.watch-code-block{margin-bottom:.9rem}
.watch-code-block label{display:block;font-size:.78rem;font-weight:700;color:var(--slate);margin-bottom:.35rem;text-transform:uppercase;letter-spacing:.03em}
.watch-code-row{display:flex;gap:.5rem}
.watch-code-row input{
  flex:1;min-width:0;border:1.5px solid var(--line);border-radius:var(--radius-sm);
  padding:.6rem .7rem;font-size:.95rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  background:var(--court);color:var(--ink);
}
.watch-code-row input:focus{border-color:var(--turf);background:#fff}
.watch-code-row .btn{flex-shrink:0}
.watch-code-error{color:var(--danger);font-size:.78rem;font-weight:600;margin:.4rem 0 0}
.modal-divider{display:flex;align-items:center;gap:.6rem;margin:1rem 0;color:var(--slate);font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em}
.modal-divider::before,.modal-divider::after{content:'';flex:1;height:1px;background:var(--line)}

.viewer-banner{
  display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;
  max-width:1400px;margin:0 auto;padding:.6rem 1.1rem;background:var(--turf-pale);
  border-bottom:1px solid var(--line);
}
.viewer-banner[hidden]{display:none}
.viewer-banner .eyebrow{
  font-family:var(--font-mono);font-size:.66rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--turf-deep);background:var(--surface);padding:.28rem .6rem;border-radius:99px;flex-shrink:0;
  display:inline-flex;align-items:center;gap:.35rem;
}
.viewer-banner .eyebrow svg{width:12px;height:12px}
.viewer-banner .msg{font-size:.82rem;font-weight:600;color:var(--ink);flex:1 1 auto;min-width:100px}
.viewer-banner .msg:empty{display:none}
.viewer-notify-btn{
  display:inline-flex;align-items:center;gap:.35rem;flex-shrink:0;margin-left:auto;
  background:var(--surface);color:var(--turf-deep);border:1.5px solid var(--turf);
  border-radius:99px;padding:.4rem .8rem;font-size:.76rem;font-weight:700;
  line-height:1.1;white-space:nowrap;
}
.viewer-notify-btn[hidden]{display:none}
.viewer-notify-btn svg{width:13px;height:13px;flex-shrink:0}
.viewer-notify-btn:hover{background:var(--turf-pale);color:var(--turf-deep)}
.viewer-notify-btn.active{background:var(--turf);color:#fff;border-color:var(--turf)}
.viewer-notify-status{
  display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-left:auto;
  width:2rem;height:2rem;border-radius:50%;line-height:1;
  background:var(--turf);color:#fff;border:none;cursor:pointer;
}
.viewer-notify-status[hidden]{display:none}
.viewer-notify-status svg{width:14px;height:14px}
.viewer-notify-status:hover{opacity:.85}
.viewer-history-btn{
  display:inline-flex;align-items:center;gap:.35rem;flex-shrink:0;
  background:var(--surface);color:var(--ink);border:1.5px solid var(--line);
  border-radius:99px;padding:.4rem .8rem;font-size:.76rem;font-weight:700;
  line-height:1.1;white-space:nowrap;
}
.viewer-history-btn svg{width:13px;height:13px;flex-shrink:0}
.viewer-history-btn:hover{background:var(--court)}
@media (max-width:520px){
  .viewer-banner{gap:.5rem .6rem}
  .viewer-banner .msg{order:1}
  .viewer-notify-btn{order:2;margin-left:0;flex:1 1 100%;justify-content:center}
  .viewer-history-btn{order:3;margin-left:0;flex:1 1 100%;justify-content:center}
}

/* Spectator "up next" notification: a floating card that sits above the
   courts grid so anyone watching remotely sees the very next matchup at a
   glance, instead of having to scroll down to the collapsed "Up next"
   details panel at the bottom of the page. Only ever shown in viewer mode
   (see body.viewer-mode rules below), and only when there's an actual
   on-deck matchup to report — see updateViewerUpNext() in script.js. */
.viewer-upnext-notify{
  max-width:1400px;margin:.75rem auto 0;padding:0 1.1rem;
}
.viewer-upnext-notify[hidden]{display:none}
.viewer-upnext-notify-inner{
  display:flex;align-items:flex-start;flex-wrap:wrap;gap:.5rem 1rem;
  /* Fixed brand blue (not the --turf/--turf-deep pair, which get deliberately
     LIGHTENED in dark mode for on-page text/accent contrast elsewhere) — using
     the lightened pair here turned this into a glaring pale-blue banner against
     a dark background. --brand-turf stays a deep navy in both themes, same as
     the topbar, so this card reads the same (and stays comfortable to look at)
     whether the spectator's device is in light or dark mode. */
  background:linear-gradient(135deg,var(--brand-turf) 0%,var(--brand-turf-deep) 100%);
  color:#fff;border-radius:var(--radius);padding:.85rem 1.1rem;
  box-shadow:var(--shadow-md);
  animation:viewer-upnext-in .32s cubic-bezier(.2,.8,.3,1);
}
.viewer-upnext-badge{
  display:inline-flex;align-items:center;gap:.4rem;flex-shrink:0;margin-top:.15rem;
  font-family:var(--font-mono);font-size:.68rem;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;background:rgba(255,255,255,.2);color:#fff;
  padding:.35rem .7rem;border-radius:99px;
}
.viewer-upnext-badge svg{width:13px;height:13px;flex-shrink:0}
/* Up to 2 upcoming matchups, stacked — the immediate next match reads large
   and bold, the one after it smaller and slightly dimmed so the hierarchy
   is obvious at a glance. */
.viewer-upnext-body{
  flex:1 1 auto;min-width:180px;
  display:flex;flex-direction:column;gap:.4rem;
}
.viewer-upnext-item{
  display:flex;align-items:center;flex-wrap:wrap;gap:.3rem .6rem;
  font-size:1.02rem;font-weight:800;letter-spacing:-.01em;
}
.viewer-upnext-item + .viewer-upnext-item{
  font-size:.86rem;font-weight:700;opacity:.82;
  padding-top:.3rem;border-top:1px solid rgba(255,255,255,.18);
}
.viewer-upnext-tag{
  font-family:var(--font-mono);font-size:.58rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:rgba(255,255,255,.85);
  background:rgba(255,255,255,.16);border-radius:5px;padding:.12rem .4rem;flex-shrink:0;
}
.viewer-upnext-body .ondeck-team{color:#fff}
.viewer-upnext-body .ondeck-vs{
  font-family:var(--font-mono);font-size:.62rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:rgba(255,255,255,.8);
  background:rgba(255,255,255,.16);border-radius:5px;padding:.1rem .4rem;
}
@keyframes viewer-upnext-in{
  from{opacity:0;transform:translateY(-8px)}
  to{opacity:1;transform:translateY(0)}
}
@media (max-width:520px){
  .viewer-upnext-notify{padding:0 .8rem}
  .viewer-upnext-notify-inner{padding:.7rem .85rem}
  .viewer-upnext-item{font-size:.9rem}
  .viewer-upnext-item + .viewer-upnext-item{font-size:.78rem}
}

/* Read-only mode: hide everything a spectator shouldn't touch, without
   needing a second copy of the render logic — the same court cards render,
   we just strip out the controls. */
body.viewer-mode .stack-rail,
body.viewer-mode .mobile-tabs,
body.viewer-mode #hostOnlineBtn,
body.viewer-mode #matchHistoryBtn,
body.viewer-mode #settingsBtn,
body.viewer-mode .session-banner,
body.viewer-mode .court-cta,
body.viewer-mode .player-swap-btn,
body.viewer-mode .player-sub-btn,
body.viewer-mode .undo-result-btn,
body.viewer-mode .sbl-btn,
body.viewer-mode .history{ display:none !important; } /* redundant with .viewer-upnext-notify above */
body.viewer-mode .court-name{ pointer-events:none; }
body.viewer-mode .app-shell{ grid-template-columns:1fr; }
body.viewer-mode .courts-main{ display:block !important; }

.host-auth-tabs{display:flex;gap:.4rem;margin-bottom:.9rem}
.host-auth-tabs button{
  flex:1;padding:.5rem;border-radius:var(--radius-sm);border:1.5px solid var(--line);
  background:var(--court);color:var(--slate);font-weight:700;font-size:.8rem;cursor:pointer;
}
.host-auth-tabs button.active{background:var(--turf);border-color:var(--turf);color:#fff}
.host-auth-tabs button:disabled{opacity:.6;cursor:default}

.host-auth-wrap{position:relative}
.host-auth-wrap.is-busy .host-auth-tabs,
.host-auth-wrap.is-busy form{opacity:.55}
.host-busy-overlay{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:transparent;cursor:wait;
}
.spinner,.btn-spinner{
  display:inline-block;border-radius:50%;
  border:3px solid rgba(0,0,0,.15);border-top-color:var(--turf);
  animation:host-spin .7s linear infinite;
}
.spinner{width:30px;height:30px}
.btn-spinner{
  width:14px;height:14px;border-width:2px;border-top-color:#fff;
  vertical-align:-2px;margin-right:.4rem;
}
@keyframes host-spin{to{transform:rotate(360deg)}}
.host-error{
  font-size:.78rem;color:var(--danger);background:var(--danger-pale);
  border-radius:var(--radius-sm);padding:.5rem .65rem;margin:-.3rem 0 .8rem;
}
.host-usage-row{
  display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  font-size:.8rem;color:var(--slate);margin-bottom:.8rem;
}
.host-usage-row b{color:var(--ink)}
.host-account-row{
  display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  font-size:.82rem;color:var(--slate);margin-bottom:.9rem;padding-bottom:.8rem;border-bottom:1px solid var(--line);
}
.host-account-identity{display:flex;align-items:center;gap:.55rem;min-width:0}
.host-account-identity span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.host-status-badge{
  display:inline-flex;align-items:center;padding:.12rem .55rem;border-radius:999px;
  font-size:.68rem;font-weight:700;flex-shrink:0;
}
.host-status-badge.suspended{background:var(--danger-pale);color:var(--danger)}

/* ---- Skeleton loader (matches /admin's shimmer placeholder) ---- */
.host-skeleton{
  height:13px;border-radius:6px;margin:.4rem 0;
  background:linear-gradient(90deg, var(--line) 25%, var(--court) 37%, var(--line) 63%);
  background-size:400% 100%;animation:host-shimmer 1.4s ease infinite;
}
@keyframes host-shimmer{ 0%{background-position:100% 0} 100%{background-position:0 0} }
@media (prefers-reduced-motion:reduce){ .host-skeleton{ animation:none; background:var(--line); } }
.host-account-row b{color:var(--ink)}
.host-live-card{text-align:center}
.host-live-badge{
  display:inline-flex;align-items:center;font-family:var(--font-mono);font-size:.72rem;font-weight:700;
  letter-spacing:.03em;background:var(--danger-pale);color:var(--danger);padding:.3rem .7rem;border-radius:99px;
}
.host-live-badge--stopped{background:var(--line);color:var(--slate)}
.host-live-badge--reconnecting{background:var(--gold-pale);color:var(--gold-deep);animation:live-pulse 1s ease-in-out infinite}
.host-invite-code{
  font-family:var(--font-mono);font-size:1.6rem;font-weight:700;letter-spacing:.12em;
  color:var(--turf-deep);background:var(--turf-pale);border-radius:var(--radius-sm);
  padding:.7rem;margin:.6rem 0;user-select:all;
}
.host-qr-box{display:flex;justify-content:center;margin:.8rem 0}
.host-qr-box img,.host-qr-box canvas{border-radius:8px;background:#fff;padding:8px}
.host-live-actions{display:flex;gap:.5rem;margin-top:.8rem}
.host-live-actions .btn{flex:1}
.host-live-note{font-size:.74rem;color:var(--slate);margin-top:.7rem}

/* ---- Buy credits ---- */
.host-credit-balance{color:var(--turf-deep);font-weight:700;font-size:.78rem}
.host-credit-pending{
  font-size:.78rem;color:var(--gold-deep);background:var(--gold-pale);
  border-radius:var(--radius-sm);padding:.5rem .65rem;margin:0 0 .8rem;
}
.host-buy-credits-toggle{display:flex;align-items:center;justify-content:center;gap:.35rem}
.host-buy-credits-toggle-arrow{transition:transform .15s}
.host-buy-credits-toggle:hover .host-buy-credits-toggle-arrow{transform:translateX(3px)}

.host-credit-pkgs{display:grid;grid-template-columns:1fr 1fr;gap:.7rem;margin:.7rem 0}
.host-credit-pkg-btn{
  position:relative;display:flex;flex-direction:column;align-items:center;gap:.3rem;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);
  padding:1.1rem .7rem .85rem;text-align:center;cursor:pointer;
  box-shadow:var(--shadow-sm);
  transition:border-color .15s,box-shadow .15s,transform .15s;
}
.host-credit-pkg-btn:hover{border-color:var(--turf);box-shadow:var(--shadow-md);transform:translateY(-2px)}
.host-credit-pkg-btn:active{transform:translateY(0)}
.host-credit-pkg-btn:focus-visible{outline:2px solid var(--turf);outline-offset:2px}

/* The cheaper-per-credit package gets a filled brand border, a "Best value"
   ribbon, and a subtle tinted background — the same visual language SaaS
   pricing tables use to steer the eye toward the better deal. */
.host-credit-pkg-btn.is-best{
  border-color:var(--turf);background:linear-gradient(180deg,var(--turf-pale) 0%,var(--surface) 60%);
}
.host-credit-pkg-badge{
  position:absolute;top:-.6rem;left:50%;transform:translateX(-50%);
  background:var(--turf);color:#fff;font-size:.62rem;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;padding:.22rem .55rem;border-radius:99px;white-space:nowrap;
  box-shadow:0 2px 6px rgba(10,30,61,.2);
}
.host-credit-pkg-credits{
  font-family:var(--font-display);font-size:1.5rem;line-height:1;color:var(--ink);
  display:flex;align-items:baseline;gap:.3rem;
}
.host-credit-pkg-credits small{
  font-family:var(--font-body);font-weight:600;font-size:.68rem;color:var(--slate);
  text-transform:uppercase;letter-spacing:.02em;
}
.host-credit-pkg-price{font-size:1.05rem;font-weight:700;color:var(--turf-deep)}
.host-credit-pkg-rate{font-size:.68rem;color:var(--slate)}
.is-best .host-credit-pkg-price{color:var(--turf)}
.host-credit-gcash{
  background:var(--turf-pale);border-radius:var(--radius-sm);padding:.65rem .75rem;
  font-size:.8rem;color:var(--turf-deep);margin:.6rem 0;
}
.host-credit-gcash b{font-family:var(--font-mono);user-select:all}
.host-receipt-filename{font-size:.74rem;color:var(--slate);margin-top:.4rem;word-break:break-all}
