/* ═══════════════════════════════════════════════════════════
   SKIPPER APP STYLES
   Tokens live in tokens.css. This file: base, app shell
   (topbar / sidebar / bottom tab bar), core components, then
   view-specific styles pending migration onto the new system.
   ═══════════════════════════════════════════════════════════ */

/* ── BASE ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{background:var(--bg);color:var(--text-1);font-family:var(--font-ui);font-size:var(--fs-md);line-height:1.5;min-height:100dvh}
img{max-width:100%}
button{font-family:var(--font-ui)}
.page{display:none;min-height:100dvh;flex-direction:column}
.page.active{display:flex}
#app-root{flex:1;display:flex;flex-direction:column}
:focus-visible{outline:none;box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--focus-ring)}  /* ≥3:1 in BOTH themes (MOB-002, #115) — measured, not asserted in a comment */
::selection{background:var(--accent-dim)}
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
}

/* ── TOPBAR ── */
.topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);height:calc(var(--topbar-h) + env(safe-area-inset-top));padding:env(safe-area-inset-top) var(--sp-5) 0;border-bottom:1px solid var(--border);position:sticky;top:0;background:color-mix(in srgb, var(--bg) 88%, transparent);z-index:100;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.topbar-l{display:flex;align-items:center;gap:var(--sp-3);min-width:0}
#org-switch-slot,#team-switch-slot{display:contents}
.logo{font-family:var(--font-display);font-size:22px;letter-spacing:3px;color:var(--accent-text);text-decoration:none;line-height:1}
.logo-img{height:30px;width:auto;display:block}
.topbar-r{display:flex;align-items:center;gap:var(--sp-2);flex-shrink:0}
/* padding 8px, from 6: at 28px tall these were the smallest targets in the app
   AND the first thing a coach touches, at the very top of the screen where a
   thumb reaches worst (#125). */
.team-switch{display:flex;align-items:center;gap:6px;max-width:200px;min-width:88px;background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-full);color:var(--text-1);font-size:var(--fs-sm);font-weight:600;padding:8px 12px;cursor:pointer;transition:border-color .15s,background .15s;white-space:nowrap;overflow:hidden}
.team-switch:hover{border-color:var(--border-strong)}
.team-switch:active{background:var(--surface-2)}
.team-switch .ts-label{overflow:hidden;text-overflow:ellipsis;min-width:0}
.team-switch svg{flex-shrink:0;color:var(--text-3)}
/* Season indicator when the org has exactly one season for the active sport —
   still shown so it is never ambiguous which season a roster belongs to. */
.season-pill{display:inline-flex;align-items:center;background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-full);color:var(--text-2);font-size:var(--fs-xs,11px);font-weight:600;letter-spacing:.5px;padding:5px 11px;white-space:nowrap}
/* Team + season switchers share the topbar on phones. Both are .team-switch, so
   without this they shrink proportionally and the team name collapses to an
   ellipsis. Shrink the logo instead and let each switcher size to its label. */
@media (max-width:600px){
  .topbar{padding-left:var(--sp-3);padding-right:var(--sp-3);gap:var(--sp-2)}
  .topbar-l{gap:var(--sp-2);flex:1 1 auto}
  .logo-img{height:24px}
  /* The base padding bump for #125 has to be repeated here or it never reaches
     a phone — this override is the one that applies where the reach problem
     actually is. 8px takes it from 28px tall to 32px. */
  .team-switch{min-width:0;flex:0 1 auto;padding:8px 9px;gap:3px;font-size:var(--fs-xs)}
  #season-switch-slot .team-switch,.season-pill{flex-shrink:0}
  .season-pill{padding:5px 8px}
}
.role-pill{font-size:var(--fs-xs);font-weight:700;letter-spacing:1.5px;text-transform:uppercase;padding:4px 9px;border-radius:var(--r-full);white-space:nowrap;flex-shrink:0;border:none;cursor:default}
.role-pill .rp-short{display:none}
@media(max-width:480px){
  .role-pill .rp-full{display:none}
  .role-pill .rp-short{display:inline}
  /* Only actionable once it's actually abbreviated — nothing to confirm
     once the full label already fits. */
  /* It only becomes interactive here (it opens the full-title popover), and at
     35x21 it was the one control in the shell genuinely under WCAG 2.5.8's
     24x24 minimum (#125). */
  #role-pill{cursor:pointer;min-height:24px;display:inline-flex;align-items:center}
}
/* Tap-to-reveal under the abbreviated role pill: same pill look, fixed below
   the trigger, dismissed like every other popover (outside tap/Esc/scroll). */
.role-pill-detail{position:fixed;z-index:600;box-shadow:var(--shadow-2);animation:menuIn .12s ease}
.rp-coach{background:var(--accent-dim);color:var(--accent-text)}
.rp-player{background:var(--info-dim);color:var(--info)}
.rp-parent{background:var(--success-dim);color:var(--success)}
.rp-pending{background:var(--surface-2);color:var(--text-3)}
.icon-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;background:none;border:1px solid transparent;border-radius:var(--r-md);color:var(--text-2);cursor:pointer;transition:.15s;flex-shrink:0}
.icon-btn:hover{background:var(--surface-1);color:var(--text-1)}
.icon-btn:active{transform:scale(.94)}

/* ── APP SHELL LAYOUT ── */
.shell{flex:1;display:flex;align-items:stretch;min-height:0}
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.content{flex:1;width:100%;max-width:var(--content-max);margin:0 auto;padding:var(--sp-6) var(--sp-5) var(--sp-10)}

/* Sidebar (≥1024px) */
.appnav{display:none}
.appnav .nav-item{display:flex;align-items:center;gap:var(--sp-3);width:100%;padding:10px 14px;border:none;border-radius:var(--r-md);background:none;color:var(--text-2);font-size:var(--fs-sm);font-weight:600;cursor:pointer;transition:background .15s,color .15s;text-align:left;white-space:nowrap}
.appnav .nav-item:hover{background:var(--surface-1);color:var(--text-1)}
.appnav .nav-item:active{transform:scale(.98)}
.appnav .nav-item.on{background:var(--accent-dim);color:var(--accent-text)}
.appnav .nav-item svg{flex-shrink:0}
@media(min-width:1024px){
  .appnav{display:flex;flex-direction:column;gap:2px;width:var(--sidebar-w);flex-shrink:0;padding:var(--sp-5) var(--sp-3);border-right:1px solid var(--border);position:sticky;top:calc(var(--topbar-h) + env(safe-area-inset-top));height:calc(100dvh - var(--topbar-h) - env(safe-area-inset-top));overflow-y:auto}
}
/* Top-row nav (768–1023px) */
@media(min-width:768px) and (max-width:1023.9px){
  .appnav{display:flex;flex-direction:row;gap:2px;padding:var(--sp-2) var(--sp-4);border-bottom:1px solid var(--border);overflow-x:auto;scrollbar-width:none}
  .appnav::-webkit-scrollbar{display:none}
  .shell{flex-direction:column}
  .appnav .nav-item{width:auto;padding:8px 14px}
}

/* Bottom tab bar (<768px) */
.tabbar{display:none}
@media(max-width:767.9px){
  .tabbar{position:fixed;bottom:0;left:0;right:0;z-index:100;display:flex;align-items:stretch;background:color-mix(in srgb, var(--bg) 92%, transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-top:1px solid var(--border);padding-bottom:env(safe-area-inset-bottom);height:calc(var(--tabbar-h) + env(safe-area-inset-bottom))}
  /* 11px/--text-2, not 10px/--text-3: this is the only navigation on a phone
     and it measured 4.01:1 against the blurred bar in light (#114). --text-3
     keeps its >=4.5:1 promise against --bg; the tab bar is not --bg. */
  .tabbar .tb-item{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;background:none;border:none;color:var(--text-2);font-size:var(--fs-xs);font-weight:600;letter-spacing:.2px;cursor:pointer;padding:6px 0 4px;transition:color .15s}
  .tabbar .tb-item.on{color:var(--accent-text)}
  .tabbar .tb-item:active{transform:scale(.94)}
  .content{padding:var(--sp-5) var(--sp-4) calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--sp-8))}
}

/* ── SEGMENTED CONTROL (one sub-nav language) ── */
/* Scroll shadows appear only when the control overflows: 'cover' gradients ride
   the content (background-attachment:local) and hide the fixed edge shadows at
   the ends, so scrollable segs get an edge fade hint even with the bar hidden (MOB-010). */
.seg{display:flex;gap:2px;background-color:var(--surface-1);background-image:linear-gradient(to right,var(--surface-1),transparent),linear-gradient(to left,var(--surface-1),transparent),radial-gradient(farthest-side at 0 50%,color-mix(in srgb,var(--text-1) 22%,transparent),transparent),radial-gradient(farthest-side at 100% 50%,color-mix(in srgb,var(--text-1) 22%,transparent),transparent);background-position:0 0,100% 0,0 0,100% 0;background-size:28px 100%,28px 100%,14px 100%,14px 100%;background-repeat:no-repeat;background-attachment:local,local,scroll,scroll;border:1px solid var(--border);border-radius:var(--r-md);padding:3px;margin-bottom:var(--sp-5);width:fit-content;max-width:100%;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.seg::-webkit-scrollbar{display:none}
.seg-item{flex:0 0 auto;padding:8px 14px;font-size:var(--fs-sm);font-weight:600;color:var(--text-2);border:none;border-radius:calc(var(--r-md) - 3px);background:none;cursor:pointer;transition:background .15s,color .15s;white-space:nowrap}
.seg-item:hover:not(.on){color:var(--text-1)}
.seg-item.on{background:var(--surface-3);color:var(--text-1)}

/* ── PAGE HEADINGS ── */
.eye{font-size:var(--fs-xs);letter-spacing:2.5px;text-transform:uppercase;color:var(--text-3);margin-bottom:6px;font-weight:600}
.head{font-family:var(--font-display);font-size:var(--fs-2xl);letter-spacing:1.5px;margin-bottom:var(--sp-5);line-height:1.05}
.section-row{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-4)}

/* ── BUTTONS ── */
/* background:transparent is load-bearing, not tidiness. Every variant sets its
   own, but a bare .btn fell through to the UA `buttonface` keyword — which
   follows color-scheme, so it renders #EFEFEF under light and #6B6B6B under
   dark. That is what made Present mode's Back/Next white-on-near-white (#44):
   the fix at the time pinned the text and border and never touched the face,
   because a button nobody had styled a background onto looked fine in the only
   theme anyone could reach. */
.btn{width:100%;padding:12px 16px;border-radius:var(--r-md);font-family:var(--font-ui);font-size:var(--fs-sm);font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,color .15s,transform .1s;border:1px solid transparent;background:transparent;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;white-space:nowrap;text-decoration:none}
.btn:active:not(:disabled){transform:scale(.98)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn-gold{background:var(--accent);color:var(--on-accent)}
.btn-gold:hover:not(:disabled){background:var(--accent-strong)}
/* --input-border, not --border. The face is transparent, so the border IS the
   button: --border is a divider and measured 1.30:1 dark / 1.20:1 light behind
   View, Remove, + Quick charge and both topbar switchers (#113). --input-border
   already carries the ">=3:1 so field edges are visible" promise and had only
   ever been spent on inputs. Third time this bug has been found here: #44 in
   Present mode, --border-2 on the marketing site, now the app shell. */
.btn-outline{background:transparent;border-color:var(--input-border);color:var(--text-1)}
/* --text-3, not --border-strong: hover has to be MORE visible than rest, and
   light --border-strong (#C9C9C5) is lighter than the new rest border, so
   hovering would have dimmed the edge it is meant to emphasise. --text-3 is
   6.6:1 dark / 5.2:1 light, above the rest state in both. */
.btn-outline:hover:not(:disabled){border-color:var(--text-3);background:var(--surface-1)}
.btn-green{background:var(--success);color:#fff}
.btn-green:hover:not(:disabled){background:color-mix(in srgb, var(--success) 85%, black)}
.btn-red{background:var(--danger-dim);border-color:var(--danger-border);color:var(--danger)}
.btn-red:hover:not(:disabled){background:color-mix(in srgb, var(--danger) 20%, transparent)}
.btn-blue{background:var(--info-dim);border-color:var(--info-border);color:var(--info)}
.btn-google{background:#fff;color:#141414}
.btn-google:hover:not(:disabled){background:#ececec}
/* 36px, not 32. WCAG 2.5.8 is satisfied either way (24x24), but these are the
   buttons a coach taps one-handed at a field — View and Remove sit 8px apart
   on every roster row and one of them is destructive (#125). */
.btn-sm{width:auto;padding:8px 13px;font-size:var(--fs-xs);border-radius:var(--r-sm);min-height:36px}
.btn-xs{width:auto;padding:5px 10px;font-size:var(--fs-xs);border-radius:var(--r-sm);min-height:26px}
.btn-signout{background:none;border:1px solid var(--border);color:var(--text-2);font-size:var(--fs-xs);padding:6px 12px;border-radius:var(--r-sm);cursor:pointer;transition:.15s}
.btn-signout:hover{border-color:var(--border-strong);color:var(--text-1)}

/* ── INPUTS ── */
.field{margin-bottom:var(--sp-4)}
.field label{display:block;font-size:var(--fs-xs);letter-spacing:1.5px;text-transform:uppercase;color:var(--text-2);margin-bottom:7px;font-weight:600}
.input{width:100%;background:var(--surface-2);border:1px solid var(--input-border);color:var(--text-1);font-family:var(--font-ui);font-size:var(--fs-md);padding:11px 13px;border-radius:var(--r-md);outline:none;transition:border-color .15s;min-height:44px}
.input:focus{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-dim)}
.input::placeholder{color:var(--text-3)}
textarea.input{resize:vertical;min-height:80px}
select.input{cursor:pointer}
.field-err .input{border-color:var(--danger)}
.field-msg{font-size:var(--fs-xs);color:var(--danger);margin-top:5px}

/* ── CARDS + LIST ROWS ── */
.card{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--sp-4) var(--sp-5);margin-bottom:var(--sp-3);overflow:hidden;word-break:break-word}
a.card,.card[onclick],.card.tappable{transition:border-color .15s,background .15s}
.card[onclick]:hover,.card.tappable:hover{border-color:var(--border-strong)}
.card[onclick]:active,.card.tappable:active{background:var(--surface-2)}
.card-row{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-3);min-width:0}
.card-title{font-size:var(--fs-md);font-weight:600;margin-bottom:3px}
.card-meta{font-size:var(--fs-xs);color:var(--text-2)}
.card-actions{display:flex;gap:6px;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;max-width:100%;align-items:center}
.card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:var(--sp-3)}
.list-row{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--sp-4);background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-md);margin-bottom:6px;transition:border-color .15s}
.list-row.tappable{cursor:pointer}
.list-row.tappable:hover{border-color:var(--border-strong)}
.chev{color:var(--text-3);flex-shrink:0}

/* ── POSITION CHIPS ── */
.pos-chip{padding:6px 12px;border-radius:var(--r-full);border:1.5px solid var(--border);background:var(--surface-1);color:var(--text-2);font-size:var(--fs-xs);font-weight:700;cursor:pointer;transition:.15s;min-height:32px}
.pos-chip:hover{border-color:var(--border-strong);color:var(--text-1)}
.pos-chip:active{transform:scale(.95)}
.pos-chip.pos-secondary{border-color:var(--info-border);background:var(--info-dim);color:var(--info)}
.pos-chip.pos-primary{border-color:var(--accent-border);background:var(--accent-dim);color:var(--accent-text)}

/* ── PILLS / STATUS ── */
.pill{display:inline-block;font-size:var(--fs-xs);font-weight:700;letter-spacing:1.2px;text-transform:uppercase;padding:3px 8px;border-radius:var(--r-sm)}
.pill-gold{background:var(--accent-dim);color:var(--accent-text)}
.pill-dark{background:var(--surface-2);color:var(--text-2)}
/* Positions spelled out ("Center Field", not "CF"). Uppercase at 10px with
   1.2px tracking turns a four-position drill into four wrapped rows, and gold
   would say a position is the same kind of fact as "You + 1". */
.pill-pos{background:var(--surface-2);color:var(--text-1);border:1px solid var(--border-strong);
  text-transform:none;letter-spacing:.2px;font-size:var(--fs-xs);font-weight:600;padding:2px 8px}
.pill-both{background:var(--info-dim);color:var(--info)}
.pub-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:5px}
.pub-dot.live{background:var(--success)}
.pub-dot.draft{background:var(--text-3)}
.status-txt{font-size:var(--fs-xs)}
.status-live{color:var(--success)}
.status-draft{color:var(--text-3)}

/* ── MENU (overflow / dropdown) ── */
.menu{position:fixed;z-index:600;min-width:180px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r-md);box-shadow:var(--shadow-2);padding:5px;animation:menuIn .12s ease}
@keyframes menuIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.menu-item{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:none;border-radius:var(--r-sm);background:none;color:var(--text-1);font-size:var(--fs-sm);font-weight:500;cursor:pointer;text-align:left;transition:background .1s;white-space:nowrap}
.menu-item:hover{background:var(--surface-3)}
.menu-item.danger{color:var(--danger)}
.menu-item.on{color:var(--accent-text)}
.menu-item svg{flex-shrink:0;color:var(--text-2)}
.menu-item.danger svg{color:var(--danger)}
.menu-sep{height:1px;background:var(--border);margin:5px 8px}
.menu-label{font-size:10px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-3);font-weight:700;padding:8px 12px 4px}
/* Second grouping level (age group under a sport). Lighter than .menu-label so
   the hierarchy reads sport > age > team at a glance. */
.menu-orglabel{font-size:12px;color:var(--text-1);font-weight:700;padding:10px 12px 6px;border-bottom:1px solid var(--border);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:260px}
.menu-sublabel{font-size:10px;letter-spacing:1px;text-transform:uppercase;color:var(--text-3);font-weight:600;opacity:.75;padding:6px 12px 2px 22px}
.menu-item.indent{padding-left:30px}

/* ── MODAL / SHEET ── */
dialog.modal{border:1px solid var(--border);border-radius:var(--r-lg);background:var(--surface-1);color:var(--text-1);padding:0;width:min(480px,calc(100vw - 32px));max-height:min(82dvh,720px);box-shadow:var(--shadow-2);margin:auto}
dialog.modal.modal-wide{width:min(880px,calc(100vw - 32px));max-height:min(90dvh,860px)}
dialog.modal::backdrop{background:var(--overlay);backdrop-filter:blur(2px)}
dialog.modal[open]{animation:modalIn .18s ease}
@keyframes modalIn{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}
.modal-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--border);position:sticky;top:0;background:var(--surface-1);z-index:1}
.modal-title{font-size:var(--fs-lg);font-weight:700}
.modal-body{padding:var(--sp-5);overflow-y:auto}
.modal-foot{display:flex;gap:var(--sp-2);justify-content:flex-end;padding:var(--sp-4) var(--sp-5);border-top:1px solid var(--border);position:sticky;bottom:0;background:var(--surface-1)}
.modal-foot .btn{width:auto}
.sheet-handle{display:none}
@media(max-width:767.9px){
  dialog.modal{width:100vw;max-width:100vw;margin:auto 0 0;border-radius:var(--r-lg) var(--r-lg) 0 0;border-bottom:none;max-height:88dvh}
  dialog.modal[open]{animation:sheetIn .22s cubic-bezier(.32,.72,0,1)}
  @keyframes sheetIn{from{transform:translateY(40%);opacity:.6}to{transform:none;opacity:1}}
  .sheet-handle{display:block;width:36px;height:4px;border-radius:var(--r-full);background:var(--border-strong);margin:10px auto 0}
  .modal-foot{padding-bottom:calc(var(--sp-4) + env(safe-area-inset-bottom))}
}

/* ── TOAST ── */
.toast-stack{position:fixed;bottom:calc(var(--sp-5) + env(safe-area-inset-bottom));left:50%;transform:translateX(-50%);z-index:700;display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none;width:max-content;max-width:calc(100vw - 32px)}
@media(max-width:767.9px){.toast-stack{bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--sp-4))}}
.toast{display:flex;align-items:center;gap:9px;background:var(--surface-2);border:1px solid var(--border-strong);color:var(--text-1);font-size:var(--fs-sm);font-weight:500;padding:11px 16px;border-radius:var(--r-full);box-shadow:var(--shadow-2);animation:toastIn .2s ease;pointer-events:auto;max-width:100%}
.toast.out{opacity:0;transform:translateY(6px);transition:.25s}
@keyframes toastIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.toast-ok svg{color:var(--success)}
.toast-err{border-color:var(--danger-border)}
.toast-err svg{color:var(--danger)}

/* ── EMPTY / LOADING / SKELETON ── */
.empty{text-align:center;padding:var(--sp-10) var(--sp-5);color:var(--text-2);font-size:var(--fs-sm)}
.empty-icon{font-size:30px;margin-bottom:10px}
.empty-icon svg{display:block;margin:0 auto;color:var(--text-3)}
.empty .btn{width:auto;margin:var(--sp-4) auto 0}
.loading{text-align:center;color:var(--text-2);font-size:var(--fs-sm);padding:28px 0}
.skel{position:relative;overflow:hidden;background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);margin-bottom:var(--sp-3)}
.skel::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,color-mix(in srgb, var(--text-1) 4%, transparent),transparent);animation:skel 1.4s infinite}
@keyframes skel{from{transform:translateX(-100%)}to{transform:translateX(100%)}}

/* ── MESSAGES ── */
.msg-err{background:var(--danger-dim);border:1px solid var(--danger-border);border-radius:var(--r-sm);color:var(--danger);font-size:var(--fs-xs);padding:9px 13px;margin:8px 0}
.msg-ok{background:var(--success-dim);border:1px solid var(--success-border);border-radius:var(--r-sm);color:var(--success);font-size:var(--fs-xs);padding:9px 13px;margin:8px 0}
.sep{height:1px;background:var(--border);margin:var(--sp-5) 0}
.back-btn{background:none;border:none;color:var(--accent-text);font-family:var(--font-ui);font-size:var(--fs-xs);font-weight:600;cursor:pointer;padding:0;margin-bottom:var(--sp-4);display:flex;align-items:center;gap:5px}
.back-btn:hover{text-decoration:underline}
.big-icon{font-size:44px;text-align:center;margin:32px 0 14px}
.big-title{font-family:var(--font-display);font-size:30px;text-align:center;letter-spacing:2px;color:var(--accent-text);margin-bottom:8px}
.big-sub{font-size:var(--fs-sm);color:var(--text-2);text-align:center;line-height:1.7}

/* ── HOME DASHBOARD ── */
.home-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--sp-4);align-items:start}
.home-sec{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--sp-4) var(--sp-5)}
.home-sec-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);margin-bottom:var(--sp-3)}
.home-sec-title{font-size:var(--fs-xs);letter-spacing:2px;text-transform:uppercase;color:var(--text-2);font-weight:700}
.home-link{background:none;border:none;color:var(--accent-text);font-size:var(--fs-xs);font-weight:600;cursor:pointer;padding:6px 8px;margin:-6px 0;border-radius:var(--r-sm)}  /* padding lifts tap target ≥24px, negative block margin keeps rows tight (MOB-008) */
.home-link:hover{text-decoration:underline}
.home-row{display:flex;align-items:center;gap:var(--sp-3);padding:10px 0;border-bottom:1px solid var(--border);cursor:pointer;border-radius:var(--r-sm)}
.home-row:last-child{border-bottom:none}
.home-row:hover .hr-title{color:var(--accent-text)}
.hr-date{display:flex;flex-direction:column;align-items:center;justify-content:center;width:44px;height:44px;border-radius:var(--r-md);background:var(--surface-2);flex-shrink:0}
.hr-date .d{font-family:var(--font-display);font-size:19px;line-height:1;color:var(--text-1)}
.hr-date .m{font-size:9px;letter-spacing:1px;text-transform:uppercase;color:var(--text-3);font-weight:700}
.hr-title{font-size:var(--fs-sm);font-weight:600;transition:color .1s}
.hr-meta{font-size:var(--fs-xs);color:var(--text-2)}
.hr-fill{flex:1;min-width:0}
.home-greet{margin-bottom:var(--sp-5)}
.home-empty{color:var(--text-3);font-size:var(--fs-sm);padding:var(--sp-3) 0}

/* ── TRAIN ── */
.streak-hero{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);background:linear-gradient(135deg,var(--accent-dim),var(--surface-1));border:1px solid var(--accent-border);border-radius:var(--r-lg);padding:var(--sp-5);margin-bottom:var(--sp-4)}
.streak-num{display:flex;align-items:baseline;gap:10px}
.streak-num .n{font-family:var(--font-display);font-size:56px;line-height:1;color:var(--accent-text)}
/* "day streak" must not break under the numeral — at 360px the dots were
   reserving 180px and leaving the label ~52px, so it wrapped onto two lines. */
.streak-num .l{font-size:var(--fs-sm);font-weight:600;color:var(--text-2);white-space:nowrap}
.streak-dots{display:flex;gap:4px;flex-wrap:wrap;max-width:132px;justify-content:flex-end}
@media(min-width:420px){.streak-dots{max-width:180px}}
.streak-dots .sd{width:10px;height:10px;border-radius:50%;background:var(--surface-3)}
.streak-dots .sd.on{background:var(--accent)}
.challenge-card{background:var(--surface-1);border:1px solid var(--info-border);border-radius:var(--r-lg);padding:var(--sp-4) var(--sp-5);margin-bottom:var(--sp-3)}
.prog-track{height:8px;border-radius:var(--r-full);background:var(--surface-3);overflow:hidden;margin-top:8px}
.prog-fill{height:100%;border-radius:var(--r-full);background:var(--accent);transition:width .4s ease}
.badge-earned{display:inline-flex;align-items:center;gap:6px;background:var(--accent-dim);border:1px solid var(--accent-border);color:var(--accent-text);border-radius:var(--r-full);padding:5px 12px;font-size:var(--fs-xs);font-weight:700}
.lb-rank{font-family:var(--font-display);font-size:20px;width:44px;text-align:center;flex-shrink:0;color:var(--text-2)}
.lb-pts{font-family:var(--font-display);font-size:22px;color:var(--accent-text);flex-shrink:0}
.lb-pts span{font-family:var(--font-ui);font-size:var(--fs-xs);color:var(--text-3);font-weight:600}
.lb-mine{border-color:var(--accent-border);background:color-mix(in srgb, var(--accent) 5%, var(--surface-1))}

/* ── TRYOUTS ── */
.tp-scorecard{position:relative;background:linear-gradient(120deg,var(--surface-1) 55%,var(--accent-dim));border:1px solid var(--accent-border);border-radius:var(--r-lg);padding:var(--sp-5);overflow:hidden}
.tp-stamp{position:absolute;bottom:12px;right:14px;transform:rotate(-7deg);font-family:var(--font-display);text-transform:uppercase;letter-spacing:1px;font-size:18px;padding:4px 12px;border:2.5px solid;border-radius:7px;opacity:0;transition:opacity .15s}
.tp-stamp.show{opacity:1}
.tp-stamp.offer{color:var(--success);border-color:var(--success)}
.tp-stamp.second{color:var(--accent-text);border-color:var(--accent-text)}
.tp-stamp.pass{color:var(--danger);border-color:var(--danger)}
.tp-gchip{flex:1;min-height:46px;border:1.5px solid var(--border);background:var(--surface-2);border-radius:var(--r-md);font-family:var(--font-display);font-size:20px;color:var(--text-1);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .05s,background .15s}
.tp-gchip:active:not(:disabled){transform:scale(.94)}
.tp-gchip.on{background:var(--accent);border-color:var(--accent-strong);color:var(--on-accent);box-shadow:0 2px 0 var(--accent-strong)}
.tp-tbtn{flex:1;min-height:42px;border:1.5px solid var(--border);background:var(--surface-2);border-radius:var(--r-md);font-weight:600;font-size:var(--fs-sm);cursor:pointer;color:var(--text-1)}
.tp-tbtn.on{background:var(--text-1);color:var(--bg);border-color:var(--text-1)}
.tp-dbtn{flex:1;min-height:52px;border:2px solid var(--border);background:var(--surface-2);border-radius:var(--r-md);font-family:var(--font-display);font-size:16px;letter-spacing:1px;text-transform:uppercase;cursor:pointer;color:var(--text-1);line-height:1}
.tp-dbtn.offer.on{background:var(--success);border-color:var(--success);color:#fff}
.tp-dbtn.second.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.tp-dbtn.pass.on{background:var(--danger);border-color:var(--danger);color:#fff}
#tp-sheet textarea.input{margin-top:8px;min-height:58px}

/* ── MONEY ── */
.money-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-3);margin-bottom:var(--sp-5)}
.money-tile{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--sp-4);text-align:center}
.mt-val{font-family:var(--font-display);font-size:26px;letter-spacing:.5px;font-variant-numeric:tabular-nums}
.mt-lbl{font-size:var(--fs-xs);color:var(--text-2);font-weight:600;margin-top:2px}

/* ── PLAYBOOK ── */
.pb-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:var(--sp-4)}
.pb-card{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;cursor:pointer;transition:border-color .15s}
.pb-card:hover{border-color:var(--border-strong)}
.pb-card:active{transform:scale(.99)}
.pb-thumb{aspect-ratio:4/3;background:var(--surface-2);position:relative}
.pb-thumb svg{width:100%;height:100%;display:block}
/* Play or alignment, on the picture rather than in the meta line —
   the thumbnail is what you are reading when you decide to tap, and
   a still diagram and a moving one look identical there. */
.pb-kind{position:absolute;left:8px;top:8px;display:inline-flex;align-items:center;gap:4px;
  font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  padding:3px 7px 3px 5px;border-radius:var(--r-full);border:1px solid;
  backdrop-filter:blur(3px)}
.pb-kind svg{width:12px;height:12px;flex:0 0 auto}
.pb-kind.is-play{background:var(--accent-dim);color:var(--accent-text);border-color:var(--accent-border)}
.pb-kind.is-align{background:var(--surface-1);color:var(--text-3);border-color:var(--border-strong)}
.pb-card-body{padding:var(--sp-3) var(--sp-4)}
.pb-card-form{font-size:var(--fs-xs);font-weight:600;color:var(--text-2);margin-top:1px}
/* Formation grouping: a playbook is installed set by set, so the
   heading is the formation and the count tells you how much you run
   from it. */
.pb-group+.pb-group{margin-top:var(--sp-5)}
.pb-group-head{display:flex;align-items:center;gap:9px;margin:0 0 var(--sp-3);
  font-size:var(--fs-sm);font-weight:700;letter-spacing:.02em;color:var(--text-1)}
.pb-group-head::after{content:'';flex:1;height:1px;background:var(--border);order:3}
.pb-group-head span{order:2;font-size:var(--fs-xs);font-weight:600;color:var(--text-3);
  background:var(--surface-2);border-radius:var(--r-full);padding:1px 8px;font-variant-numeric:tabular-nums}
.pb-stage{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;max-width:820px;touch-action:none}
.pb-stage svg{width:100%;height:auto;display:block}
.pb-svg .pb-marker circle{fill:var(--accent);stroke:color-mix(in srgb, var(--accent) 60%, black);stroke-width:3}
.pb-svg .pb-m-opp circle{fill:var(--surface-3);stroke:var(--border-strong)}
.pb-svg .pb-m-ball circle{fill:var(--text-1);stroke:var(--bg);stroke-width:2}
.pb-svg .pb-m-cone path{fill:var(--danger);stroke:none}
/* No font-size here: it is set per marker in the SVG, because the
   marker radius is per FIELD (five linemen sit a yard apart and a
   26-unit marker drew them as one blob). A fixed size in CSS beats
   a presentation attribute, so putting one back silently breaks it. */
.pb-svg .pb-marker text{fill:var(--on-accent);font-family:'DM Sans',sans-serif;font-weight:800;user-select:none}
.pb-svg .pb-m-opp text{fill:var(--text-1)}
.pb-svg .pb-m-sel circle{stroke:var(--text-1);stroke-width:5}
.pb-svg .pb-route{fill:none;stroke:var(--accent);stroke-width:5;stroke-dasharray:14 10;opacity:.9;stroke-linejoin:round;stroke-linecap:round}
/* Path styles are the notation a coach already reads off a
   whiteboard: an arrow is a route, a flat bar is a block, a dotted
   line is a pass, a dashed one before the snap is motion. Drawing a
   block with an arrow says the lineman ran downfield. */
.pb-svg .pb-path-carry{stroke-dasharray:none}
.pb-svg .pb-path-pass{stroke-dasharray:2 12;stroke-width:4}
.pb-svg .pb-path-block{stroke-dasharray:none;stroke-width:6}
.pb-svg .pb-path-screen{stroke-dasharray:6 6}
.pb-svg .pb-path-motion{stroke-dasharray:4 9;stroke-width:4;opacity:.75}
.pb-svg .pb-path-zone-drop{stroke-dasharray:16 8;stroke-width:4}
.pb-svg .pb-path-pressure{stroke:var(--danger);stroke-dasharray:9 5}
/* An OPTION branch is what this player does INSTEAD, so it is
   deliberately quieter than the primary — one of them happens. */
.pb-svg .pb-route-alt{stroke:var(--text-3);stroke-width:3.5;opacity:.85}
/* No font-size: it scales with the marker radius, like every
   other piece of text drawn into the field. */
.pb-svg .pb-optlabel{fill:var(--text-2);stroke:var(--surface-1);font-family:'DM Sans',sans-serif;font-weight:600}

/* ZONES — an area somebody owns. The tone is a meaning, not a
   palette slot: deep / under / flat / man / press. */
.pb-svg .pb-zone rect,.pb-svg .pb-zone ellipse,.pb-svg .pb-zone path{stroke-width:2.5;stroke-dasharray:9 7}
.pb-svg .pb-zone text{font-family:'DM Sans',sans-serif;font-weight:700;stroke:var(--surface-1);paint-order:stroke}
.pb-svg .pb-zone-deep rect,.pb-svg .pb-zone-deep ellipse,.pb-svg .pb-zone-deep path{fill:var(--info);fill-opacity:.16;stroke:var(--info)}
.pb-svg .pb-zone-deep text{fill:var(--info)}
.pb-svg .pb-zone-under rect,.pb-svg .pb-zone-under ellipse,.pb-svg .pb-zone-under path{fill:var(--accent);fill-opacity:.14;stroke:var(--accent)}
.pb-svg .pb-zone-under text{fill:var(--accent-text)}
.pb-svg .pb-zone-flat rect,.pb-svg .pb-zone-flat ellipse,.pb-svg .pb-zone-flat path{fill:var(--success);fill-opacity:.14;stroke:var(--success)}
.pb-svg .pb-zone-flat text{fill:var(--success)}
.pb-svg .pb-zone-man rect,.pb-svg .pb-zone-man ellipse,.pb-svg .pb-zone-man path{fill:var(--danger);fill-opacity:.13;stroke:var(--danger)}
.pb-svg .pb-zone-man text{fill:var(--danger)}
.pb-svg .pb-zone-press rect,.pb-svg .pb-zone-press ellipse,.pb-svg .pb-zone-press path{fill:var(--text-2);fill-opacity:.12;stroke:var(--text-2)}
.pb-svg .pb-zone-press text{fill:var(--text-2)}
/* A GAP is the hole in the coverage, and it is drawn UNFILLED on
   purpose: it is the one area nobody is standing in, so filling it
   would say the opposite of what it means. Wider dashes and no
   fill read as "open" at a glance. */
.pb-svg .pb-zone-gap rect,.pb-svg .pb-zone-gap ellipse,.pb-svg .pb-zone-gap path{
  fill:none;stroke:var(--danger);stroke-dasharray:4 12;stroke-width:3}
.pb-svg .pb-zone-gap text{fill:var(--danger)}
/* Assignment lines sit behind the routes: they are context (who
   has whom), not movement. */
.pb-svg .pb-link{stroke:var(--text-3);stroke-width:2.5;stroke-dasharray:5 6;opacity:.8}
.pb-svg .pb-link-block{stroke:var(--accent);stroke-dasharray:none;opacity:.5}
/* A rule that says somebody is offside is no use without the line
   they are offside of. */
.pb-svg .pb-guide line{stroke:var(--text-2);stroke-width:2.5;stroke-dasharray:12 8;opacity:.7}
.pb-svg .pb-guide text{fill:var(--text-2);stroke:var(--surface-1);paint-order:stroke;font-family:'DM Sans',sans-serif;font-weight:700}
/* Red only when something is actually wrong. A permanently red
   line is a line people stop reading. */
.pb-svg .pb-guide-warn line{stroke:var(--danger);stroke-width:3;opacity:.9}
.pb-svg .pb-guide-warn text{fill:var(--danger)}

.pb-controls{display:flex;align-items:center;gap:var(--sp-3);margin-top:var(--sp-3);flex-wrap:wrap;max-width:820px}
.pb-controls .btn{width:auto}
.pb-toolbar{display:flex;flex-direction:column;gap:var(--sp-2);margin-bottom:var(--sp-3)}
.pb-toolbar-row{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.pb-toolbar-row .btn{width:auto}
.pb-hint{font-size:var(--fs-sm);color:var(--text-3);margin-bottom:var(--sp-2);min-height:18px}
.pb-filters{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap;margin-bottom:var(--sp-4)}
.pb-fbtn{width:auto;display:inline-flex;align-items:center;gap:6px}
.pb-fbtn.on{border-color:var(--accent-border);color:var(--accent-text)}
.pb-fbtn[disabled]{opacity:.45;pointer-events:none}
.pb-unit{margin-left:6px;font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;
  padding:2px 6px;border-radius:var(--r-sm);vertical-align:2px}
.pb-unit-offense{background:var(--accent-dim);color:var(--accent-text)}
.pb-unit-defense{background:var(--info-dim);color:var(--info)}
.pb-unit-special{background:var(--success-dim);color:var(--success)}
/* The legend is what turns a coloured rectangle into a coaching
   point. A zone nobody can name is decoration. */
.pb-legend{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3);max-width:820px}
.pb-key{font-size:var(--fs-xs);font-weight:600;padding:3px 9px;border-radius:var(--r-full);border:1px solid transparent}
.pb-key-deep{background:var(--info-dim);color:var(--info);border-color:var(--info-border)}
.pb-key-under{background:var(--accent-dim);color:var(--accent-text);border-color:var(--accent-border)}
.pb-key-flat{background:var(--success-dim);color:var(--success);border-color:var(--success-border)}
.pb-key-man{background:var(--danger-dim);color:var(--danger);border-color:var(--danger-border)}
.pb-key-press{background:var(--surface-2);color:var(--text-2);border-color:var(--border-strong)}
.pb-key-gap{background:transparent;color:var(--danger);border-color:var(--danger-border);border-style:dashed}
.pb-key-line{background:var(--surface-2);color:var(--text-2);border-color:var(--border)}
.pb-key-opt{background:var(--surface-2);color:var(--text-3);border-color:var(--border);font-style:italic}
.pb-gapnote{display:flex;gap:7px;align-items:center;margin-top:var(--sp-2);max-width:820px;
  font-size:var(--fs-sm);color:var(--text-2)}
.pb-gapnote svg{color:var(--danger);flex:0 0 auto}
/* One symbol, one meaning — generated from the same tables the
   renderer uses, so the key cannot drift from the drawing. Behind
   a disclosure because a coach who already knows what blue means
   should not scroll past it on every play. */
.pb-keybox{margin-top:var(--sp-3);max-width:820px}
.pb-keybox summary{font-size:var(--fs-sm);color:var(--text-2);cursor:pointer;padding:6px 0;
  list-style:none;display:flex;align-items:center;gap:6px}
.pb-keybox summary::-webkit-details-marker{display:none}
.pb-keybox summary::before{content:'';width:6px;height:6px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(-45deg);transition:transform .15s}
.pb-keybox[open] summary::before{transform:rotate(45deg)}
.pb-keygrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px 16px;
  padding:10px 0 4px}
.pb-keyrow{display:flex;gap:9px;align-items:center;font-size:var(--fs-sm);color:var(--text-2)}
.pb-keyrow b{color:var(--text-1);font-weight:600}
.pb-swatch{flex:0 0 auto;width:20px;height:20px;border-radius:var(--r-full)}
.pb-sw-player{background:var(--accent);border:2px solid color-mix(in srgb, var(--accent) 60%, black)}
.pb-sw-opponent{background:var(--surface-3);border:2px solid var(--border-strong)}
/* Matches `.pb-m-ball` exactly. A key that disagrees with the drawing
   is worse than no key, so these swatches track the marker rules
   rather than restating them from memory — the ball stopped being
   hardcoded white when Present mode started following the theme. */
.pb-sw-ball{background:var(--text-1);border:2px solid var(--bg);width:13px;height:13px}
.pb-sw-cone{background:var(--danger);border-radius:2px;width:0;height:0;border-left:9px solid transparent;
  border-right:9px solid transparent;border-bottom:16px solid var(--danger)}
.pb-sw-line{height:0;border-radius:0;border-top:3px solid var(--accent);width:26px}
.pb-sw-route{border-top-style:dashed}
.pb-sw-carry{border-top-style:solid}
.pb-sw-pass{border-top-style:dotted}
.pb-sw-block{border-top-width:4px}
.pb-sw-screen{border-top-style:dashed;border-top-width:4px}
.pb-sw-motion{border-top-style:dashed;opacity:.7}
.pb-sw-zone-drop{border-top-style:dashed;border-top-width:2px}
.pb-sw-pressure{border-top-color:var(--danger);border-top-style:dashed}
.pb-sw-alt{border-top-color:var(--text-3);border-top-style:dashed;border-top-width:2px}
.pb-sw-link{border-top-color:var(--text-3);border-top-style:dashed;border-top-width:2px;width:20px}
.pb-sw-zone{width:22px;height:14px;border-radius:4px;border:2px dashed currentColor}
/* THE MATCHUP AND THE READS.
   A diagram shows where everybody goes; it cannot show what a
   defence looks like before it moves, or what a player is meant
   to see. Both panels sit directly under the field and above the
   cues, because that is the order the questions get asked:
   what am I facing, what am I looking at, what do I shout. */
.pb-matchup{margin-top:var(--sp-3);max-width:820px;background:var(--surface-1);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:var(--sp-3) var(--sp-4);display:grid;gap:var(--sp-2)}
.pb-matchup-head{display:flex;align-items:center;gap:7px;font-size:var(--fs-sm);color:var(--text-2)}
.pb-matchup-head b{color:var(--text-1)}
.pb-matchup-head svg{color:var(--accent);flex:0 0 auto}
.pb-tell,.pb-soft{font-size:var(--fs-sm);color:var(--text-2);line-height:1.5}
.pb-soft{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
/* The label sits on its own line on a phone: an inline key plus a
   two-line sentence beside it wraps into a ragged block that reads
   as one run-on. */
.pb-tell-k{display:block;font-size:var(--fs-xs);font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:var(--text-3);margin-bottom:3px}
.pb-soft .pb-tell-k{flex:0 0 100%;margin-bottom:0}
.pb-vs{display:flex;align-items:center;gap:7px;font-size:var(--fs-sm)}
.pb-vs svg{flex:0 0 auto}
.pb-vs-good{color:var(--success)}
.pb-vs-bad{color:var(--text-2)}
.pb-vs-bad svg{color:var(--warn,var(--danger))}
.pb-reads{margin-top:var(--sp-3);max-width:820px;background:var(--surface-1);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:var(--sp-3) var(--sp-4)}
.pb-reads-head{display:flex;align-items:center;gap:7px;font-size:var(--fs-sm);font-weight:600;color:var(--text-1)}
.pb-reads-head svg{color:var(--accent)}
.pb-read-when{font-size:var(--fs-xs);font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--text-3);margin-top:var(--sp-3)}
.pb-read{margin-top:6px;padding-left:var(--sp-3);border-left:2px solid var(--border-strong)}
.pb-read-look{font-size:var(--fs-sm);font-weight:600;color:var(--text-1)}
/* "If you see X, do Y" is one thought, so it stays one row on a
   wide screen and stacks on a phone rather than being two lists
   the reader has to pair up themselves. */
.pb-read-row{display:grid;grid-template-columns:minmax(120px,34%) 1fr;gap:var(--sp-3);
  padding:5px 0;font-size:var(--fs-sm);line-height:1.5}
.pb-read-row+.pb-read-row{border-top:1px dashed var(--border)}
.pb-read-if{color:var(--accent-text);font-weight:600}
.pb-read-then{color:var(--text-2)}
/* A `sees` that redraws the play is a CONTROL. Only those become
   buttons — a row that looks tappable and does nothing is worse than
   the prose it replaced. `background:transparent` is load-bearing:
   a bare <button> otherwise falls through to the UA `buttonface`
   keyword, which follows color-scheme and goes near-white under
   light. That is the bug Present mode shipped with. */
button.pb-read-row{width:100%;text-align:left;background:transparent;border:0;
  border-radius:var(--r-sm);cursor:pointer;font:inherit;align-items:center;
  grid-template-columns:minmax(120px,34%) 1fr auto}
button.pb-read-row:hover{background:var(--surface-2)}
button.pb-read-row:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.pb-read-go{color:var(--text-3);display:flex;align-items:center}
.pb-read-on{background:var(--surface-2)}
.pb-read-on .pb-read-go{color:var(--accent)}
@media(max-width:560px){.pb-read-row{grid-template-columns:1fr;gap:2px}
  button.pb-read-row{grid-template-columns:1fr auto}}
/* Cues are what a coach says out loud, kept with the play —
   because the play is what a fourteen-year-old opens on their
   phone the night before, and the coach is not there. */
.pb-cues{margin-top:var(--sp-4);max-width:820px;background:var(--surface-1);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:var(--sp-3) var(--sp-4)}
.pb-cues-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  font-size:var(--fs-sm);font-weight:600;color:var(--text-1)}
.pb-cues-head>span{display:flex;align-items:center;gap:7px}
.pb-cues-head svg{color:var(--accent)}
.pb-cues-head .btn{width:auto}
.pb-cues ul{margin:8px 0 0;padding-left:18px}
.pb-cues li{font-size:var(--fs-sm);color:var(--text-2);line-height:1.55;margin-bottom:5px}
.pb-cues-per{list-style:none;padding-left:0;margin-top:6px}
.pb-cues-per li{display:flex;gap:8px;align-items:baseline}
.pb-cue-who{flex:0 0 auto;min-width:34px;font-size:var(--fs-xs);font-weight:700;letter-spacing:.5px;
  color:var(--accent-text);background:var(--accent-dim);border-radius:var(--r-sm);padding:2px 6px;text-align:center}

/* THE STICKS. The line to gain, so "a yard past the sticks" is a
   thing on the field and not only a thing a coach says. */
.pb-svg .pb-sticks line{stroke:var(--accent);stroke-width:4;stroke-dasharray:18 7;opacity:.95}
.pb-svg .pb-sticks text{fill:var(--accent-text);stroke:var(--surface-1);paint-order:stroke;
  font-family:'DM Sans',sans-serif;font-weight:800}
.pb-svg .pb-depthtick{fill:var(--text-1);stroke:var(--surface-1);paint-order:stroke;
  font-family:'DM Sans',sans-serif;font-weight:700}

/* The detail editor: a route as numbers. Dragging says "about
   here"; this is where a coach says twelve and means twelve. */
.pb-detail-hint{font-size:var(--fs-sm);color:var(--text-3);line-height:1.5;margin-bottom:12px}
.pb-sticksrow{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between;
  background:var(--accent-dim);border:1px solid var(--accent-border);border-radius:var(--r-md);
  padding:9px 12px;margin-bottom:12px;font-size:var(--fs-sm);color:var(--text-1);font-weight:600}
.pb-sticksbtns{display:flex;gap:6px;flex-wrap:wrap}
.pb-sticksbtns .btn{width:auto}
.pb-detail-grid{display:flex;flex-direction:column;gap:8px}
.pb-detail-head,.pb-detail-row{display:grid;grid-template-columns:minmax(64px,1fr) 1fr 1fr;gap:8px;align-items:center}
.pb-detail-head{font-size:var(--fs-xs);color:var(--text-3);text-transform:uppercase;letter-spacing:.6px}
.pb-detail-label{font-size:var(--fs-sm);font-weight:600;color:var(--text-1)}
.pb-detail-row .input{min-height:44px;text-align:center}
.pb-detail-verdict{display:flex;gap:8px;align-items:center;margin-top:12px;padding:9px 12px;
  border-radius:var(--r-md);font-size:var(--fs-sm);line-height:1.5;border:1px solid var(--border)}
.pb-detail-verdict.ok{background:var(--success-dim);border-color:var(--success-border);color:var(--text-1)}
.pb-detail-verdict.ok svg{color:var(--success)}
.pb-detail-verdict.thin{background:var(--accent-dim);border-color:var(--accent-border);color:var(--text-1)}
.pb-detail-verdict.thin svg{color:var(--accent)}
.pb-detail-verdict.short{background:var(--danger-dim);border-color:var(--danger-border);color:var(--text-1)}
.pb-detail-verdict.short svg{color:var(--danger)}
/* Duties are what this position owns whatever play is on screen.
   A diagram says where somebody goes; it never said what their job
   is, and a player who just got moved needs the second thing more. */
.pb-duties{margin-bottom:12px;border:1px solid var(--border);border-radius:var(--r-md);
  padding:8px 12px;background:var(--surface-2)}
.pb-duties summary{font-size:var(--fs-sm);font-weight:600;color:var(--text-1);cursor:pointer;
  list-style:none;display:flex;align-items:center;gap:6px}
.pb-duties summary::-webkit-details-marker{display:none}
.pb-duties summary::before{content:'';width:6px;height:6px;border-right:2px solid var(--text-3);
  border-bottom:2px solid var(--text-3);transform:rotate(-45deg);transition:transform .15s}
.pb-duties[open] summary::before{transform:rotate(45deg)}
.pb-duties ul{margin:8px 0 4px;padding-left:18px}
.pb-duties li{font-size:var(--fs-sm);color:var(--text-2);line-height:1.55;margin-bottom:5px}
.pb-detail-cue{margin-top:16px;margin-bottom:0}
.pb-detail-cuebtns{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
.pb-detail-cuebtns .btn{width:auto}
/* Rule findings are ADVISORY — a coach diagramming a deliberate
   offside trap wants to see the line, not be stopped. Same bargain
   as the training sign-off flags. */
.pb-rulebox{display:flex;flex-direction:column;gap:6px;margin-top:var(--sp-3);max-width:820px}
.pb-rule{display:flex;gap:8px;align-items:flex-start;font-size:var(--fs-sm);line-height:1.5;
  padding:8px 11px;border-radius:var(--r-md);border:1px solid var(--border)}
.pb-rule svg{flex:0 0 auto;margin-top:2px}
.pb-rule-warn{background:var(--danger-dim);border-color:var(--danger-border);color:var(--text-1)}
.pb-rule-warn svg{color:var(--danger)}
.pb-rule-info{background:var(--surface-1);color:var(--text-2)}
.pb-rule-info svg{color:var(--text-3)}
/* Present mode follows the app theme like every other surface. It used to be a
   pinned-dark "theater" with its controls hard-coded to white, which is where
   #44 came from — and the compromise never held anyway: the court/field SVG has
   always been token-driven, so a light-theme user got a bright court floating in
   a black frame. Following the theme is also the better answer on a field: a
   light screen is far easier to read in direct sun, which is exactly where a
   coach holds a play up. One token set, no second palette to keep in step. */
.pb-present{position:fixed;inset:0;z-index:900;background:var(--bg);display:flex;flex-direction:column;padding:env(safe-area-inset-top) 16px env(safe-area-inset-bottom);color:var(--text-1)}
.pb-present-head{display:flex;align-items:center;justify-content:space-between;padding:12px 4px}
.pb-present-stage{flex:1;display:flex;align-items:center;justify-content:center;min-height:0}
.pb-present-stage svg{max-width:100%;max-height:100%;width:auto;height:auto}
.pb-present-speed{display:flex;justify-content:center;padding:6px 0 0}
.pbp-speed-btn{padding:6px 14px;border-radius:var(--r-full);border:1px solid var(--text-3);
  background:transparent;color:var(--text-2);font-size:13px;font-weight:600;cursor:pointer;transition:.15s}
.pbp-speed-btn:hover{border-color:var(--text-2);color:var(--text-1)}
/* Fixed-position clone-plus-options cluster: escapes the flow entirely (see
   presentToggleSpeed) so opening it can never push the step dots or controls
   below — it only ever grows upward into the stage's empty space. Its own
   bottom edge is pinned to the real pill's original bottom edge, so the pill
   reads as having "moved up" while the options land right under it, exactly
   where the tapping finger already is. */
.pb-speed-cluster{position:fixed;z-index:950;display:flex;flex-direction:column;align-items:center;gap:8px;animation:menuIn .12s ease}
.pb-speed-options{display:flex;gap:8px}
.pb-speed-opt{padding:6px 12px;border-radius:var(--r-full);border:1px solid var(--text-3);
  background:var(--bg);color:var(--text-2);font-size:13px;font-weight:700;cursor:pointer;transition:.15s;white-space:nowrap}
.pb-speed-opt:hover:not(.on){border-color:var(--text-2);color:var(--text-1)}
.pb-speed-opt.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.pb-present-frames{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;padding:8px 0 0}
.pbp-fdot{width:28px;height:28px;flex-shrink:0;border-radius:50%;border:1px solid var(--text-3);
  background:transparent;color:var(--text-2);font-size:13px;font-weight:700;cursor:pointer;transition:.15s}
.pbp-fdot:hover:not(.on){border-color:var(--text-2);color:var(--text-1)}
.pbp-fdot.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.pb-present-controls{display:flex;gap:10px;justify-content:center;padding:14px 0 8px}
/* Back/Next now sit on a themed backdrop, so they are ordinary outline buttons.
   The explicit background is what stops the UA buttonface from coming back —
   see the note on .btn. These controls are outlined with --text-3 rather than
   --border-strong: with a transparent fill the border is the whole tap target,
   and --border-strong is a panel divider at ~1.5:1, under WCAG 1.4.11's 3:1.
   It matters most in the place this screen is actually used — outdoors. */
.pbp-nav-btn{background:transparent;border-color:var(--text-3);color:var(--text-2)}
.pbp-nav-btn:hover:not(:disabled){border-color:var(--text-2);background:var(--surface-2);color:var(--text-1)}
.pb-present-note{text-align:center;color:var(--text-2);font-size:14px;min-height:22px;padding-bottom:10px}

/* ── BOOT SPLASH ──
   Deliberately almost nothing: a logo and a moving bar. It stands in for the
   half-second of session restore, and anything more (a card, a headline)
   would read as a screen rather than as the app opening. */
.boot-wrap{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:22px;padding:40px 20px}
.boot-bar{width:132px;height:3px;border-radius:2px;background:var(--surface-2);overflow:hidden}
.boot-bar span{display:block;width:40%;height:100%;border-radius:2px;background:var(--accent);animation:bootBar 1.1s ease-in-out infinite}
@keyframes bootBar{0%{transform:translateX(-110%)}100%{transform:translateX(360%)}}
.boot-slow{display:none;flex-direction:column;align-items:center;gap:12px;color:var(--text-2);font-size:var(--fs-sm)}
.boot-slow.show{display:flex}
.boot-slow .btn{width:auto;padding:9px 22px}
/* No animation means no indeterminate bar to watch, so hold it steady and
   let the text carry the wait. */
@media(prefers-reduced-motion:reduce){
  .boot-bar span{animation:none;width:100%;opacity:.5}
}

/* ── AUTH PAGE ── */
.auth-wrap{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px}
.auth-logo-mark{margin-bottom:28px}
.auth-title{font-family:var(--font-display);font-size:52px;letter-spacing:4px;text-align:center}
.auth-sub{color:var(--text-2);font-size:var(--fs-sm);text-align:center;margin:10px 0 36px;letter-spacing:.5px}
.auth-card{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);padding:28px;width:100%;max-width:380px}
.or-row{display:flex;align-items:center;gap:10px;margin:16px 0}
.or-row::before,.or-row::after{content:'';flex:1;height:1px;background:var(--border)}
.or-row span{font-size:var(--fs-xs);color:var(--text-3);letter-spacing:1px;text-transform:uppercase}
.auth-tab{flex:1;padding:8px;font-size:var(--fs-xs);font-weight:600;background:transparent;border:none;color:var(--text-2);border-radius:var(--r-sm);cursor:pointer;transition:.15s}
.auth-tab-active{background:var(--surface-3);color:var(--text-1)}

/* ── PENDING PAGE ── */
.pending-wrap{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;text-align:center}
.pending-icon{font-size:52px;margin-bottom:24px}
.pending-title{font-family:var(--font-display);font-size:36px;letter-spacing:2px;color:var(--accent-text);margin-bottom:12px}
.pending-sub{font-size:var(--fs-sm);color:var(--text-2);line-height:1.7;max-width:340px}

/* ── PLAYER INFO UPDATE PAGE (texted /u/<token> link) ── */
.pu-wrap{max-width:620px;margin:0 auto;padding:26px 18px calc(48px + env(safe-area-inset-bottom))}
.pu-lede{font-size:var(--fs-sm);color:var(--text-2);line-height:1.6;margin:-8px 0 18px}
.pu-sec{font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:var(--accent-text);margin-bottom:12px}
.pu-hint{font-size:var(--fs-xs);color:var(--text-3);line-height:1.6;margin:-6px 0 12px}
/* Pairs sit side by side down to a narrow phone and stack below that. */
.pu-row{display:flex;gap:10px;flex-wrap:wrap}
.pu-row .field{flex:1 1 140px;min-width:0}
/* The three uniform sizes stay one row at every width — short labels, short
   values, and the whole point of the screen is that they read as one answer. */
.pu-row-3{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.pu-row-3 .field{min-width:0}
.pu-skip{display:block;width:100%;background:none;border:none;color:var(--text-3);font-family:inherit;font-size:var(--fs-xs);text-decoration:underline;cursor:pointer;padding:14px 0 0;text-align:center}
.pu-skip:hover{color:var(--text-2)}
/* The same block on the sign-in screen, where it explains why an account is
   being asked for at all. */
.pu-note{background:var(--accent-dim);border:1px solid var(--accent-border);border-radius:var(--r-lg);padding:16px 18px;margin-bottom:18px;text-align:left}
.pu-note-eye{font-size:var(--fs-xs);letter-spacing:2px;text-transform:uppercase;color:var(--text-3);margin-bottom:5px;font-weight:600}
.pu-note-title{font-family:var(--font-display);font-size:24px;letter-spacing:1px;line-height:1.1;color:var(--text-1);margin-bottom:7px}
.pu-note-sub{font-size:var(--fs-xs);color:var(--text-2);line-height:1.6}

/* ── READ-ONLY BANNER ── */
.ro-banner{background:var(--info-dim);border-bottom:1px solid var(--info-border);padding:8px var(--sp-4);font-size:var(--fs-xs);color:var(--info);display:flex;align-items:center;gap:8px;justify-content:center}

/* ═══════════════════════════════════════════════════════════
   VIEW-SPECIFIC STYLES (pending migration; run on compat tokens)
   ═══════════════════════════════════════════════════════════ */

.fan-cat-active{background:var(--s2)!important;color:var(--white)!important;border-color:var(--border-strong)!important}
.store-cat-btn{padding:7px 14px;border-radius:8px;border:1px solid var(--border);background:var(--s1);color:var(--gray);font-size:12px;font-weight:500;cursor:pointer;transition:.15s;white-space:nowrap;font-family:'DM Sans',sans-serif}
.store-cat-btn:hover{border-color:var(--border-strong);color:var(--white)}
.store-cat-btn.active{background:var(--gold);color:var(--on-accent);border-color:var(--gold);font-weight:700}

/* ── STOREFRONT CARDS (facelift) ── */
.store-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:16px}
.store-card{background:var(--s1);border:1px solid var(--border);border-radius:14px;overflow:hidden;cursor:pointer;display:flex;flex-direction:column;transition:transform .16s ease,border-color .16s ease,box-shadow .16s ease}
.store-card:hover{transform:translateY(-3px);border-color:var(--border-strong);box-shadow:0 12px 30px rgba(0,0,0,.28)}
/* Uniform, square media area on a clean white ground so mixed Printful photos
   (model shots, flat lays) and generated mockups all frame consistently. */
.store-media{position:relative;aspect-ratio:1/1;background:#fff;overflow:hidden}
.store-media-img{position:absolute;inset:0;width:100%;height:100%;display:block}
/* Team logo composited over a blank product when no Printful mockup exists,
   so every product visibly carries the design. Hidden when a real mockup shows. */
.store-logo{position:absolute;left:50%;transform:translateX(-50%);pointer-events:none;object-fit:contain;filter:drop-shadow(0 2px 7px rgba(0,0,0,.30))}
.store-media-fallback{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:6px;background:var(--s2);color:var(--gray)}
.store-media-badge{position:absolute;top:9px;left:9px;background:rgba(0,0,0,.62);color:#fff;font-size:10px;font-weight:600;letter-spacing:.3px;padding:3px 8px;border-radius:20px;backdrop-filter:blur(2px)}
.store-card-body{padding:12px 13px;display:flex;flex-direction:column;gap:7px;flex:1}
.store-card-name{font-size:13.5px;font-weight:650;line-height:1.32;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.6em}
.store-card-meta{font-size:11px;color:var(--text-3)}
.store-card-pricerow{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-top:auto}
.store-price{font-family:'Bebas Neue',sans-serif;font-size:22px;letter-spacing:.6px;color:var(--gold);line-height:1}
.store-swatches{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.store-swatch{width:18px;height:18px;border-radius:50%;cursor:pointer;flex-shrink:0;border:2px solid transparent;box-shadow:0 0 0 1px var(--border) inset;transition:transform .12s ease,box-shadow .12s ease}
.store-swatch:hover{transform:scale(1.14)}
.store-swatch.on{box-shadow:0 0 0 2px var(--gold)}

/* ── FORM PANEL ── */
.form-panel{background:var(--s1);border:1px solid var(--border);border-radius:12px;padding:20px;margin-bottom:14px}
.form-panel-title{font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--gray);margin-bottom:16px}

/* ── BUILDER ── */
.build-head{font-size:10px;letter-spacing:3px;text-transform:uppercase;color:var(--gray);margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--border)}
.bat-slot{display:flex;align-items:center;gap:10px;background:var(--s1);border:1px solid var(--border);border-radius:9px;padding:10px 13px;margin-bottom:7px}
.bat-num{font-family:'Bebas Neue';font-size:20px;color:var(--accent-text);width:22px;text-align:center;flex-shrink:0}
.def-grid{display:grid;grid-template-columns:1fr 1fr;gap:7px}
.def-slot{background:var(--s1);border:1px solid var(--border);border-radius:9px;padding:10px 13px}
.def-pos{font-family:'Bebas Neue';font-size:13px;letter-spacing:2px;color:var(--accent-text);margin-bottom:5px}
.pitch-slot{background:var(--s1);border:1px solid var(--border);border-radius:9px;padding:10px 13px;margin-bottom:7px;display:flex;align-items:center;gap:10px}
.pitch-lbl{font-size:12px;font-weight:500;width:100px;flex-shrink:0}
.slot-sel{flex:1;background:transparent;border:none;color:var(--white);font-family:'DM Sans';font-size:13px;outline:none;cursor:pointer}
.slot-sel option{background:var(--s2)}

/* ── DEPTH CHART ── */
.depth-pos-block{margin-bottom:20px}
.depth-pos-name{font-family:'Bebas Neue';font-size:16px;letter-spacing:2px;color:var(--accent-text);margin-bottom:8px}
.depth-row{display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--s1);border:1px solid var(--border);border-radius:8px;margin-bottom:5px}
.depth-num{font-family:'Bebas Neue';font-size:16px;color:var(--gray2);width:20px;text-align:center;flex-shrink:0}
.depth-name{font-size:14px;font-weight:500;flex:1}
.depth-note{font-size:11px;color:var(--gray);flex:1}

/* ── PRACTICE ── */
.practice-section{background:var(--s2);border:1px solid var(--border);border-radius:9px;padding:14px;margin-bottom:8px}
.practice-section-title{font-size:13px;font-weight:600;margin-bottom:4px}
.practice-section-meta{font-size:11px;color:var(--gray);margin-bottom:6px}
.yt-link{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:#ef4444;text-decoration:none;font-weight:500}
.yt-link:hover{text-decoration:underline}
.player-tag{display:inline-block;background:var(--s3);border:1px solid var(--border);border-radius:5px;font-size:11px;padding:3px 8px;margin:2px}

/* ── LINEUP VIEW ── */
.lv-title{font-family:'Bebas Neue';font-size:15px;letter-spacing:2px;color:var(--accent-text);margin-bottom:9px}
.lv-table{width:100%;border-collapse:collapse;margin-bottom:20px}
.lv-table th{font-size:9px;letter-spacing:2px;text-transform:uppercase;color:var(--text-3);text-align:left;padding:0 0 6px;border-bottom:1px solid var(--border)}
.lv-table td{padding:8px 0;border-bottom:1px solid var(--s1);font-size:13px}
.lv-table td:first-child{font-family:'Bebas Neue';font-size:16px;color:var(--accent-text);width:32px}

/* ── USERS TABLE ── */
.users-table{width:100%;border-collapse:collapse}
.users-table th{font-size:9px;letter-spacing:2px;text-transform:uppercase;color:var(--text-3);text-align:left;padding:0 0 8px;border-bottom:1px solid var(--border)}
.users-table td{padding:10px 0;border-bottom:1px solid var(--s1);font-size:13px;vertical-align:middle}
.users-table td:last-child{text-align:right}

/* ── PEOPLE ──
   Three zones, one page. Rows are a grid so the name column can shrink and the
   role/team column can wrap without the action button ever leaving the row —
   the old table put two <select>s in a cell and overflowed the screen on a
   phone, which is where this screen is actually read. */
.ppl-tools{margin-bottom:var(--sp-5)}
.ppl-tools .input{width:100%}

.ppl-sec{margin-bottom:var(--sp-8)}
.ppl-sec-head{display:flex;align-items:baseline;gap:var(--sp-3);margin-bottom:var(--sp-3);
  padding-bottom:var(--sp-2);border-bottom:1px solid var(--border)}
.ppl-sec-head h3{font-size:var(--fs-md);font-weight:700;letter-spacing:-.01em;margin:0}
.ppl-count{font-size:var(--fs-xs);color:var(--text-3);letter-spacing:.06em}
.ppl-none{font-size:var(--fs-sm);color:var(--text-3);padding:var(--sp-5) 0}
.ppl-dim{color:var(--text-3);font-size:var(--fs-xs)}

/* rows */
.ppl-row,.ppl-g-row{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1.2fr) auto;
  gap:var(--sp-3);align-items:center;padding:var(--sp-3) 0;border-bottom:1px solid var(--surface-2)}
.ppl-row:last-child,.ppl-g-row:last-child{border-bottom:0}
.ppl-who{min-width:0}
.ppl-name{font-size:var(--fs-sm);font-weight:600;color:var(--text-1);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ppl-sub{font-size:var(--fs-xs);color:var(--text-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ppl-mid{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;min-width:0}
.ppl-act{display:flex;gap:var(--sp-2);justify-content:flex-end;white-space:nowrap}

.ppl-chips{display:flex;gap:var(--sp-1);flex-wrap:wrap}
.ppl-chip{display:inline-flex;align-items:center;gap:4px;background:var(--surface-2);
  border:1px solid var(--border);border-radius:var(--r-sm);padding:3px 8px;
  font-size:var(--fs-xs);color:var(--text-2);white-space:nowrap}
.ppl-chip-warn{background:var(--accent-dim);border-color:var(--accent-border);color:var(--accent-text)}
.ppl-x{background:none;border:none;color:var(--danger);cursor:pointer;padding:0;
  line-height:1;display:inline-flex;align-items:center}

/* zone 1 — what is waiting */
.ppl-queue{background:var(--accent-dim);border:1px solid var(--accent-border);
  border-radius:var(--r-md);padding:var(--sp-4);margin-bottom:var(--sp-8)}
.ppl-q-head{display:flex;align-items:center;gap:var(--sp-2);color:var(--accent-text);
  font-size:var(--fs-xs);font-weight:700;letter-spacing:.1em;text-transform:uppercase;margin-bottom:var(--sp-2)}
.ppl-q-head svg{flex-shrink:0}
.ppl-q-row{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  flex-wrap:wrap;padding:var(--sp-3) 0;border-top:1px solid var(--accent-border)}
.ppl-q-what{min-width:0;flex:1}
.ppl-q-title{font-size:var(--fs-sm);font-weight:600;color:var(--text-1)}
.ppl-q-sub{font-size:var(--fs-xs);color:var(--text-2);margin-top:2px}
.ppl-q-acts{display:flex;gap:var(--sp-2);flex-shrink:0}

/* zone 2 — a staff seat that disagrees with the org role */
.ppl-warn{display:flex;gap:var(--sp-2);align-items:flex-start;background:var(--danger-dim);
  border:1px solid var(--danger-border);border-radius:var(--r-sm);padding:var(--sp-3);
  margin-bottom:var(--sp-3);font-size:var(--fs-xs);color:var(--text-2);line-height:1.5}
.ppl-warn svg{flex-shrink:0;color:var(--danger);margin-top:1px}

/* zone 3 — families, grouped under the player */
.ppl-group{border:1px solid var(--border);border-radius:var(--r-md);
  margin-bottom:var(--sp-3);overflow:hidden}
.ppl-g-head{display:flex;align-items:baseline;gap:var(--sp-2);flex-wrap:wrap;
  background:var(--surface-2);padding:var(--sp-2) var(--sp-3);border-bottom:1px solid var(--border)}
.ppl-g-name{font-size:var(--fs-sm);font-weight:700;color:var(--text-1)}
.ppl-g-team{font-size:var(--fs-xs);color:var(--text-3)}
.ppl-g-row{padding:var(--sp-3);border-bottom:1px solid var(--surface-2)}
.ppl-note{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-sm);
  padding:var(--sp-3);margin-top:var(--sp-3);font-size:var(--fs-xs);color:var(--text-2);line-height:1.6}
.ppl-note strong{color:var(--text-1)}

/* zone 4 — volunteers */
.ppl-vols{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--sp-3)}
.ppl-vol{border:1px solid var(--border);border-radius:var(--r-sm);padding:var(--sp-3)}
.ppl-vol-head{font-size:var(--fs-xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--accent-text);margin-bottom:var(--sp-2)}
.ppl-vol-row{display:flex;justify-content:space-between;gap:var(--sp-2);
  font-size:var(--fs-xs);color:var(--text-2);padding:3px 0}

/* manage sheet */
.ppl-help{font-size:var(--fs-xs);color:var(--text-3);line-height:1.5;margin-top:var(--sp-1)}
.ppl-teamgrid{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.ppl-check{display:inline-flex;align-items:center;gap:6px;background:var(--surface-2);
  border:1px solid var(--border);border-radius:var(--r-sm);padding:8px 10px;
  font-size:var(--fs-sm);color:var(--text-1);cursor:pointer;min-height:40px}
.ppl-check input{accent-color:var(--accent);width:16px;height:16px}
/* One row per team: the tick and the role that team gets. A wrapping grid of
   chips could not carry a per-team control without the role drifting away from
   the team it belongs to. */
.ppl-teamlist{display:flex;flex-direction:column;gap:var(--sp-2)}
.ppl-teamrow{display:flex;align-items:center;gap:var(--sp-2)}
.ppl-teamrow .ppl-check{flex:1;min-width:0}
.ppl-teamrow .ppl-seatsel{width:auto;flex-shrink:0;font-size:var(--fs-sm);padding:8px 10px;min-height:40px}
.ppl-teamrow .ppl-seatsel:disabled{opacity:.45}

@media (max-width:560px){
  .ppl-row,.ppl-g-row{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:'who act' 'mid mid'}
  .ppl-who{grid-area:who}
  .ppl-act{grid-area:act}
  .ppl-mid{grid-area:mid}
}

/* ── PLAYER BADGES ── */
.pbadge{display:inline-flex;align-items:center;gap:4px;border-radius:4px;font-size:10px;font-weight:600;letter-spacing:1px;padding:2px 6px;text-transform:uppercase}
.pbadge-gold{background:var(--gold-dim);color:var(--accent-text)}
.pbadge-black{background:rgba(255,255,255,.06);color:#888}
.pbadge-both{background:rgba(100,180,255,.1);color:#64b4ff}
.pbadge-cap{background:rgba(255,200,0,.1);color:#ffc800}
.player-card{background:var(--s1);border:1px solid var(--border);border-radius:10px;padding:14px 16px;margin-bottom:8px}
/* wrap + min-width:0, which the generic .card-row already had and this one
   never did (#120). Without them the roster measured 503px of content in a
   390px viewport — .card-actions goes width:100% under 768px, and a full-width
   block inside a nowrap row is what pushed the page sideways. .pcr-main is the
   flexible column: a flex child defaults to min-width:auto, so it refuses to
   shrink below the name-plus-badges row however narrow the screen gets. */
.player-card-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.pcr-main{flex:1;min-width:0}
.player-num{font-family:'Bebas Neue';font-size:22px;color:var(--gray2);width:28px;flex-shrink:0;text-align:center}
.player-name{font-size:14px;font-weight:600;flex:1}
.player-badges{display:flex;gap:5px;flex-wrap:wrap}
.player-expand{display:none;margin-top:12px;padding-top:12px;border-top:1px solid var(--border)}
.inline-edit{display:flex;align-items:center;gap:6px}
.inline-edit input{background:var(--s2);border:1px solid var(--border);color:var(--white);font-family:'DM Sans';font-size:13px;padding:6px 10px;border-radius:6px;outline:none;flex:1}
.inline-edit input:focus{border-color:var(--gold)}

/* ── TARGETING BADGES ── */
.target-badge{display:inline-flex;align-items:center;gap:4px;border-radius:5px;font-size:10px;font-weight:600;letter-spacing:1px;padding:3px 8px;margin:2px;cursor:pointer;border:2px solid transparent;transition:.15s}
.target-badge.active{border-color:var(--gold);background:var(--gold-dim);color:var(--accent-text)}
.target-badge.pos-active{border-color:#64b4ff;background:rgba(100,180,255,.1);color:#64b4ff}
.target-badge:not(.active):not(.pos-active){background:var(--s2);color:var(--gray2)}
.target-badge:hover:not(.active):not(.pos-active){border-color:var(--border);color:var(--white)}
.YOUR-PLAN{font-size:10px;background:var(--gold-dim);color:var(--accent-text);padding:2px 7px;border-radius:3px;letter-spacing:1px;font-weight:600}
.seg-ctrl{display:flex;background:var(--s2);border-radius:8px;padding:3px;gap:3px}
.seg-btn{flex:1;padding:8px 6px;text-align:center;font-size:12px;font-weight:500;color:var(--gray);border-radius:6px;cursor:pointer;border:none;background:none;transition:.15s;white-space:nowrap}
.seg-btn.active{background:var(--s3);color:var(--white)}
.targeting-section{display:none;margin-top:12px}
.targeting-section.visible{display:block}
.pos-plan{font-size:10px;background:rgba(100,180,255,.12);color:#64b4ff;padding:2px 7px;border-radius:3px;letter-spacing:1px;font-weight:600}

/* ── DRAG AND DROP ── */
.draggable{cursor:grab;user-select:none}
.draggable:active{cursor:grabbing}
.drag-handle{display:flex;align-items:center;justify-content:center;min-width:24px;min-height:24px;flex-shrink:0;color:var(--gray2);font-size:14px;cursor:grab;padding:0 2px}
.drag-handle:hover{color:var(--gray)}
.drag-over{opacity:.4;border:2px dashed var(--gold)!important}
.drag-ghost{opacity:.5;background:var(--s3)!important}

/* ── TEMPLATE / BADGE CARDS ── */
.tpl-scope{display:inline-block;font-family:'Bebas Neue';font-size:10px;letter-spacing:2px;padding:2px 7px;border-radius:3px;margin-right:6px}
.scope-private{background:rgba(255,255,255,.05);color:var(--gray)}
.scope-team{background:var(--gold-dim);color:var(--accent-text)}
.scope-age{background:rgba(100,180,255,.1);color:#64b4ff}
.scope-org{background:rgba(34,197,94,.1);color:var(--green)}
.tpl-tag{display:inline-block;background:var(--s2);border:1px solid var(--border);border-radius:4px;font-size:10px;color:var(--gray);padding:1px 6px;margin:1px}
.bdg-icon{width:46px;height:46px;border-radius:10px;background:var(--gold-dim);border:2px solid var(--gold-border);display:flex;align-items:center;justify-content:center;font-size:24px;flex-shrink:0}
.bdg-mini{display:inline-flex;align-items:center;gap:6px;background:var(--s2);border:1px solid var(--border);border-radius:8px;padding:5px 10px;margin:3px;font-size:11px}
.bdg-mini-icon{font-size:16px}

/* ── SECTION CHECK-OFFS ── */
.sec-check-row{display:flex;align-items:center;gap:10px;margin-top:10px;padding-top:10px;border-top:1px solid var(--border);flex-wrap:wrap}
.sec-check{display:inline-flex;align-items:center;gap:6px;background:var(--s2);border:1px solid var(--border);border-radius:6px;padding:5px 10px;cursor:pointer;font-size:11px;color:var(--gray);transition:.15s;user-select:none;font-family:'DM Sans',sans-serif}
.sec-check:hover{border-color:var(--gray);color:var(--white)}
.sec-check.sec-done{background:var(--green-dim);border-color:var(--green-border);color:var(--green)}
.sec-check input{accent-color:var(--green);cursor:pointer;margin:0}

/* ── BADGE EARNED TOAST ── */
.bdg-toast{position:fixed;bottom:20px;right:20px;z-index:500;background:linear-gradient(135deg,var(--gold-dim),var(--s2));border:2px solid var(--gold);border-radius:12px;padding:14px 18px;display:flex;align-items:center;gap:12px;max-width:320px;animation:bdgPop .5s cubic-bezier(.34,1.56,.64,1);box-shadow:0 8px 24px rgba(0,0,0,.4)}
@keyframes bdgPop{0%{transform:translateY(20px) scale(.9);opacity:0}100%{transform:translateY(0) scale(1);opacity:1}}
.bdg-toast-icon{font-size:32px;flex-shrink:0}
.bdg-toast-eyebrow{font-size:9px;letter-spacing:2px;text-transform:uppercase;color:var(--accent-text);font-weight:700}
.bdg-toast-name{font-family:'Bebas Neue';font-size:18px;letter-spacing:1px;color:var(--white);line-height:1.1;margin-top:2px}
.bdg-toast-desc{font-size:11px;color:var(--gray);margin-top:3px;line-height:1.4}

@media(max-width:768px){
  .card{padding:14px}
  .card-row{flex-wrap:wrap}
  .card-actions{width:100%;justify-content:flex-start;margin-top:10px}
  .section-row{flex-wrap:wrap;gap:8px}
  .form-panel{padding:14px}
  .build-head{font-size:13px}
  .bat-slot{flex-wrap:wrap}
  table{font-size:12px}
  th,td{padding:6px 8px}
}

/* ══ LINEUP AVG CHIP ══ */
.lup-avg{font-size:10px;font-weight:700;letter-spacing:.5px;color:var(--accent-text);background:var(--gold-dim);border-radius:3px;padding:1px 5px;font-family:'Bebas Neue';flex-shrink:0}
.lup-avg.avg-low{color:#888;background:rgba(255,255,255,.05)}

/* ══ STATS VIEW ══ */
.sv-wrap{width:100%;padding:4px 0 60px;font-family:'DM Sans',sans-serif}
.sv-header{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:20px;flex-wrap:wrap}
.sv-title{font-family:'Bebas Neue';font-size:26px;letter-spacing:2px;color:var(--accent-text);line-height:1;margin:0}
.sv-season{font-size:11px;color:var(--gray);letter-spacing:1px;text-transform:uppercase;margin-top:3px}
.sv-team-toggle{display:flex;gap:0;background:var(--s1);border:1px solid var(--border);border-radius:10px;padding:3px;flex-shrink:0}
.sv-team-btn{padding:6px 14px;border-radius:7px;font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;cursor:pointer;border:none;background:none;color:var(--gray);transition:.15s;font-family:'DM Sans',sans-serif}
.sv-team-btn.sv-active{background:var(--gold);color:var(--on-accent)}
.sv-team-btn.sv-active.sv-black{background:#e8e8e8;color:#111}
.sv-stat-tabs{display:flex;gap:2px;margin-bottom:16px;border-bottom:1px solid var(--border);overflow-x:auto;scrollbar-width:none}
.sv-stat-tab{padding:7px 14px;font-size:11px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;cursor:pointer;border:none;background:none;color:var(--gray);border-bottom:2px solid transparent;margin-bottom:-1px;transition:.15s;font-family:'DM Sans',sans-serif;white-space:nowrap;flex-shrink:0}
.sv-stat-tab.sv-active{color:var(--accent-text);border-bottom-color:var(--gold)}
.sv-table-wrap{overflow-x:auto;border-radius:10px;border:1px solid var(--border);margin-bottom:20px}
.sv-table{width:100%;border-collapse:collapse;font-size:12px;font-variant-numeric:tabular-nums}
.sv-table thead tr{background:var(--s1)}
.sv-table th{padding:10px 12px;text-align:right;font-size:10px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;color:var(--gray);border-bottom:1px solid var(--border);white-space:nowrap;cursor:pointer;user-select:none;transition:color .1s}
.sv-table th:first-child{text-align:left;min-width:110px;max-width:160px}
.sv-table th:hover{color:var(--text-1)}
.sv-table th.sv-sorted{color:var(--accent-text)}
.sv-table td{padding:9px 12px;text-align:right;border-bottom:1px solid var(--s1);color:var(--text-2);white-space:nowrap}
.sv-table td:first-child{text-align:left}
.sv-table tr:last-child td{border-bottom:none}
.sv-table tbody tr:hover td{background:var(--s2)!important;cursor:pointer}
.sv-player-cell{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.sv-player-num{width:22px;height:22px;background:var(--s2);border-radius:4px;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:var(--gray);flex-shrink:0}
.sv-player-name{font-weight:600;color:var(--white);font-size:13px;white-space:normal;word-break:break-word;min-width:60px}
.sv-both-badge{font-size:9px;background:rgba(100,180,255,.1);color:#64b4ff;border:1px solid rgba(100,180,255,.25);border-radius:3px;padding:1px 5px;letter-spacing:.5px;text-transform:uppercase;font-weight:700}
.sv-team-badge{font-size:9px;border-radius:3px;padding:1px 5px;letter-spacing:.5px;text-transform:uppercase;font-weight:700}
.sv-badge-gold{background:var(--gold-dim);color:var(--accent-text)}
.sv-badge-black{background:rgba(255,255,255,.06);color:#888}
.sv-stat-top{color:var(--accent-text)!important;font-weight:700}
.sv-player-panel{background:var(--s1);border:1px solid var(--border);border-radius:12px;overflow:hidden;margin-bottom:16px}
.sv-panel-hdr{display:flex;align-items:center;gap:14px;padding:16px 18px;background:var(--s2);border-bottom:1px solid var(--border)}
.sv-panel-av{width:46px;height:46px;background:var(--gold-dim);border:2px solid var(--gold-border);border-radius:10px;display:flex;align-items:center;justify-content:center;font-family:'Bebas Neue';font-size:20px;color:var(--accent-text);flex-shrink:0}
.sv-panel-name{font-family:'Bebas Neue';font-size:22px;letter-spacing:1px;line-height:1;margin-bottom:3px}
.sv-panel-meta{font-size:11px;color:var(--gray);display:flex;gap:10px;flex-wrap:wrap}
.sv-panel-close{background:none;border:1px solid var(--border);border-radius:7px;color:var(--gray);padding:5px 11px;cursor:pointer;font-size:11px;font-family:'DM Sans',sans-serif;margin-left:auto;transition:.15s;flex-shrink:0}
.sv-panel-close:hover{border-color:var(--gray);color:var(--white)}
.sv-ptabs{display:flex;border-bottom:1px solid var(--border);padding:0 18px;background:var(--s1)}
.sv-ptab{padding:10px 16px;font-size:12px;font-weight:600;color:var(--gray);border:none;border-bottom:2px solid transparent;background:none;cursor:pointer;font-family:'DM Sans',sans-serif;transition:.15s;white-space:nowrap}
.sv-ptab:hover{color:var(--white)}
.sv-ptab-on{color:var(--white);border-bottom-color:var(--gold)}
.sv-hero-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(80px,1fr));gap:10px;margin-bottom:6px}
.sv-hero-box{background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:16px 10px 12px;text-align:center}
.sv-hero-val{font-family:'Bebas Neue';font-size:34px;color:var(--white);line-height:1;margin-bottom:5px}
.sv-hero-lbl{font-size:9px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--gray)}
.sv-hero-tip{font-size:10px;color:var(--gray2);margin-top:2px}
.sv-panel-body{padding:16px 18px}
.sv-split-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:10px;margin-bottom:12px}
.sv-split-card{background:var(--s2);border:1px solid var(--border);border-radius:9px;padding:12px 14px}
.sv-split-lbl{font-size:10px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;color:var(--gray);margin-bottom:10px;display:flex;align-items:center;gap:6px}
.sv-split-dot{width:7px;height:7px;border-radius:50%}
.sv-dot-gold{background:var(--gold)}
.sv-dot-black{background:#aaa}
.sv-dot-combined{background:var(--green)}
.sv-combined-card{background:rgba(34,197,94,0.04);border:1px solid var(--green-border);border-radius:9px;padding:12px 14px;margin-top:0}
.sv-stat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:8px}
.sv-stat-box{background:var(--bg);border:1px solid var(--border);border-radius:7px;padding:8px 8px 6px;text-align:center}
.sv-stat-val{font-family:'Bebas Neue';font-size:20px;line-height:1;color:var(--white)}
.sv-stat-val.sv-key{color:var(--accent-text)}
.sv-stat-lbl{font-size:9px;color:var(--gray);text-transform:uppercase;letter-spacing:.5px;margin-top:2px}
.sv-adv-section{margin-top:14px;padding-top:14px;border-top:1px solid var(--border)}
.sv-adv-lbl{font-size:10px;letter-spacing:1.5px;text-transform:uppercase;color:var(--gray2);margin-bottom:8px}
.sv-empty{text-align:center;padding:40px 20px;color:var(--gray2);font-size:13px}
.sv-loading{text-align:center;color:var(--gray);font-size:13px;padding:32px 0;display:flex;align-items:center;justify-content:center;gap:8px}
.sv-spinner{width:16px;height:16px;border:2px solid var(--border);border-top-color:var(--gold);border-radius:50%;animation:sv-spin .7s linear infinite}
@keyframes sv-spin{to{transform:rotate(360deg)}}
@media(max-width:600px){.sv-header{flex-direction:column;align-items:flex-start}.sv-stat-grid{grid-template-columns:repeat(3,1fr)}}

/* ══ GAMES LOG ══ */
.sv-games-wrap{display:flex;flex-direction:column;gap:6px}
.sv-filter-bar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:14px;padding:11px 14px;background:var(--s1);border:1px solid var(--border);border-radius:10px}
.sv-filter-bar label{font-size:10px;font-weight:700;letter-spacing:.7px;text-transform:uppercase;color:var(--gray);white-space:nowrap}
.sv-fi{background:var(--s2);border:1px solid var(--border);border-radius:6px;color:var(--white);font-size:12px;padding:5px 8px;font-family:'DM Sans',sans-serif}
.sv-fi:focus{outline:none;border-color:var(--gold-border)}
.sv-fi::placeholder{color:var(--gray2)}
.sv-fg{display:flex;align-items:center;gap:6px}
.sv-fb-reset{background:none;border:1px solid var(--border);border-radius:6px;color:var(--gray);padding:5px 10px;cursor:pointer;font-size:11px;font-family:'DM Sans',sans-serif;transition:.15s;white-space:nowrap}
.sv-fb-reset:hover{border-color:var(--gray);color:var(--white)}
.sv-fb-count{font-size:11px;color:var(--gray2);margin-left:auto;white-space:nowrap}
.sv-game-row{background:var(--s1);border:1px solid var(--border);border-radius:10px;overflow:hidden;transition:border-color .15s;cursor:pointer}
.sv-game-row:hover{border-color:var(--gray2)}
.sv-game-row.sv-game-open{border-color:var(--gold-border)}
.sv-game-hdr{display:flex;align-items:center;gap:10px;padding:11px 14px}
.sv-game-result{font-family:'Bebas Neue';font-size:22px;width:22px;text-align:center;flex-shrink:0}
.sv-res-w{color:#4ade80!important}.sv-res-l{color:#f87171!important}.sv-res-t{color:var(--gray)!important}
.sv-game-score{font-family:'Bebas Neue';font-size:17px;color:var(--white);flex-shrink:0;min-width:34px}
.sv-game-opp{font-weight:600;font-size:13px;color:var(--text-1);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sv-game-date{font-size:11px;color:var(--gray);flex-shrink:0}
.sv-game-ha{font-size:9px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--gray2);background:var(--s2);border-radius:3px;padding:2px 5px;flex-shrink:0}
.sv-game-chev{color:var(--gray);font-size:11px;flex-shrink:0;transition:transform .2s;margin-left:2px}
.sv-game-row.sv-game-open .sv-game-chev{transform:rotate(180deg);color:var(--accent-text)}
.sv-game-body{border-top:1px solid var(--border);padding:13px 14px;display:none}
.sv-game-row.sv-game-open .sv-game-body{display:block}
.sv-gbox-sec{margin-bottom:12px}
.sv-gbox-lbl{font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--gray);margin-bottom:7px}
.sv-gbox-t{width:100%;border-collapse:collapse;font-size:11px;font-variant-numeric:tabular-nums}
.sv-gbox-t th{text-align:right;padding:4px 7px;font-size:9px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:var(--gray2);border-bottom:1px solid var(--s2)}
.sv-gbox-t th:first-child{text-align:left}
.sv-gbox-t td{text-align:right;padding:5px 7px;color:var(--text-2);border-bottom:1px solid var(--s1)}
.sv-gbox-t td:first-child{text-align:left;color:var(--text-1);font-weight:600}
.sv-gbox-t tr:last-child td{border-bottom:none}
.sv-gbox-hi{color:var(--accent-text)!important;font-weight:700}

/* ══ TRENDS ══ */
.sv-trend-sec{margin-top:14px;padding-top:14px;border-top:1px solid var(--border)}
.sv-trend-hdr{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px;flex-wrap:wrap}
.sv-trend-lbl{font-size:10px;letter-spacing:1.5px;text-transform:uppercase;color:var(--gray2)}
.sv-tw-btns{display:flex;gap:5px}
.sv-tw-btn{background:var(--s2);border:1px solid var(--border);border-radius:5px;color:var(--gray);padding:3px 9px;cursor:pointer;font-size:10px;font-weight:700;letter-spacing:.5px;font-family:'DM Sans',sans-serif;transition:.15s}
.sv-tw-btn:hover{border-color:var(--gray)}
.sv-tw-btn.sv-tw-on{background:var(--gold-dim);border-color:var(--gold-border);color:var(--accent-text)}
.sv-trend-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(155px,1fr));gap:8px;margin-bottom:12px}
.sv-tc{background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:9px 11px}
.sv-tc-lbl{font-size:9px;font-weight:700;letter-spacing:.7px;text-transform:uppercase;color:var(--gray);margin-bottom:4px}
.sv-tc-val{font-family:'Bebas Neue';font-size:18px;color:var(--white);line-height:1;margin-bottom:4px}
.sv-tr-up{color:#4ade80;font-size:9px;font-family:'DM Sans';font-weight:700;margin-left:3px}
.sv-tr-dn{color:#f87171;font-size:9px;font-family:'DM Sans';font-weight:700;margin-left:3px}
.sv-tc-svg{width:100%;height:32px;overflow:visible;display:block}
.sv-gbl{width:100%;border-collapse:collapse;font-size:11px;font-variant-numeric:tabular-nums}
.sv-gbl th{text-align:right;padding:4px 6px;font-size:9px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:var(--gray2);border-bottom:1px solid var(--border)}
.sv-gbl th:first-child,.sv-gbl th:nth-child(2),.sv-gbl th:nth-child(3),.sv-gbl th:nth-child(4){text-align:left}
.sv-gbl td{text-align:right;padding:5px 6px;color:var(--text-2);border-bottom:1px solid var(--s1)}
.sv-gbl td:first-child,.sv-gbl td:nth-child(2),.sv-gbl td:nth-child(3),.sv-gbl td:nth-child(4){text-align:left;font-size:11px}
.sv-gbl tr:last-child td{border-bottom:none}
.sv-gbl tr:hover td{background:var(--s2)}

/* Stats visibility banner — who can see this team's numbers. */
.sv-vis-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-md);
  padding:10px 14px;margin-bottom:14px;font-size:var(--fs-xs);color:var(--text-2);line-height:1.5}

/* ── Badge progress: "what does this work toward" ────────────────────────── */
/* Chip on a drill row naming the badge it advances. */
.badge-chip-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:5px}
.badge-chip{display:inline-flex;align-items:center;gap:5px;background:var(--accent-dim);
  border:1px solid var(--accent-border);color:var(--accent-text);border-radius:var(--r-full);
  padding:2px 9px;font-size:10px;font-weight:700;line-height:1.6;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.badge-chip .bc-prog{color:var(--text-2);font-weight:600;font-variant-numeric:tabular-nums}
.badge-chip.tappable{cursor:pointer}

/* How many people a drill needs — the first thing a player at home wants. */
.drill-setting{color:var(--accent-text);font-weight:600;white-space:nowrap;
  display:inline-flex;align-items:center;gap:4px;vertical-align:-2px}
.drill-setting svg{flex-shrink:0}
.pos-chip.chip-ic{display:inline-flex;align-items:center;gap:2px}
.pill svg{vertical-align:-2px;margin-right:3px}
.field-hint{font-size:var(--fs-xs);color:var(--text-3);margin-top:6px;line-height:1.5;text-transform:none;letter-spacing:0}
.db-teamtoggle{display:flex;align-items:center;gap:8px;font-size:var(--fs-xs);color:var(--text-2);
  margin-bottom:12px;cursor:pointer;line-height:1.4}
.db-teamtoggle input{flex-shrink:0;accent-color:var(--accent)}
.bc-more{font-size:10px;color:var(--text-3);font-weight:600}
.bc-done{color:var(--success);font-weight:700}

.badge-row{cursor:pointer}

/* ── Medals ───────────────────────────────────────────────────────────────
   A badge is a stroke glyph inside a tier ring. Tier reads three ways so it
   survives greyscale and colour-blindness: hue, ring weight, and — from gold
   up — a second ring. Sizes come from --medal-size so one rule serves the
   20px chip and the 64px sheet hero. */
.medal{position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:var(--medal-size,44px);height:var(--medal-size,44px);flex-shrink:0;
  color:var(--medal-fg);transition:opacity .3s ease,transform .3s ease}
.medal svg{width:56%;height:56%;position:relative;z-index:1}
.medal-txt{position:relative;z-index:1;font-weight:800;letter-spacing:.02em;
  font-size:calc(var(--medal-size,44px) * .3);line-height:1;font-variant-numeric:tabular-nums}
/* The ring itself: base disc + border, with the second ring drawn as an inset
   box-shadow so no extra element is needed. */
.medal-ring{position:absolute;inset:0;border-radius:50%;
  background:var(--medal-bg);border:var(--medal-bw,2px) solid var(--medal-fg)}

.medal-bronze  {--medal-fg:#C98A5B;--medal-bg:rgba(201,138,91,.12); --medal-bw:1.5px}
.medal-silver  {--medal-fg:#B9C2CF;--medal-bg:rgba(185,194,207,.12);--medal-bw:2px}
.medal-gold    {--medal-fg:var(--accent);--medal-bg:rgba(245,166,35,.14);--medal-bw:2px}
.medal-platinum{--medal-fg:#9FE8E0;--medal-bg:rgba(159,232,224,.14);--medal-bw:2.5px}
/* Gold and platinum earn a second ring — the outline, not just the colour,
   says which rung you are on. */
.medal-gold .medal-ring{box-shadow:inset 0 0 0 3.5px var(--surface-1),inset 0 0 0 5px var(--medal-fg)}
.medal-platinum .medal-ring{box-shadow:inset 0 0 0 3px var(--surface-1),inset 0 0 0 4.5px var(--medal-fg),
  0 0 12px -2px var(--medal-fg)}

/* Not earned yet: drained, but still legible — a player has to be able to see
   what they are climbing toward, and which tier it is. Dimming it into a grey
   blank was worse than showing nothing. */
.medal.is-locked{opacity:.72;filter:saturate(.5)}
.medal.is-locked .medal-ring{background:transparent;border-style:dashed}

/* js/theme.js always stamps a concrete data-theme, so the attribute is the
   single light-mode selector here — the prefers-color-scheme copies these
   rules used to carry alongside it are gone. */
:root[data-theme="light"] .medal-silver{--medal-fg:#7C8798}
:root[data-theme="light"] .medal-platinum{--medal-fg:#2E9E93}

/* Earned badges: a trophy case, not a row of text pills. */
.medal-case{display:grid;grid-template-columns:repeat(auto-fill,minmax(74px,1fr));gap:12px 8px}
.medal-case-item{display:flex;flex-direction:column;align-items:center;gap:6px;
  background:none;border:none;padding:4px 2px;cursor:pointer;color:inherit;font:inherit;
  border-radius:var(--r-md)}
.medal-case-item:hover{background:var(--surface-2)}
.medal-case-item .mc-name{font-size:10px;font-weight:600;color:var(--text-2);text-align:center;
  line-height:1.25;overflow-wrap:anywhere}

/* Tier as a word, for when the ring alone is not enough context. */
.tier-tag{display:inline-block;font-size:9px;font-weight:800;letter-spacing:.09em;
  text-transform:uppercase;padding:1px 6px;border-radius:var(--r-full);vertical-align:middle;
  border:1px solid currentColor;line-height:1.5}
.tier-bronze{color:#C98A5B}
.tier-silver{color:#B9C2CF}
.tier-gold{color:var(--accent)}
.tier-platinum{color:#9FE8E0}
:root[data-theme="light"] .tier-silver{color:#7C8798}
:root[data-theme="light"] .tier-platinum{color:#2E9E93}

/* The "works toward" chip picks up its tier's colour. */
.badge-chip.chip-bronze{border-color:#C98A5B58;background:#C98A5B1f;color:#D8A277}
.badge-chip.chip-silver{border-color:#B9C2CF58;background:#B9C2CF1a;color:#C6CEDA}
.badge-chip.chip-platinum{border-color:#9FE8E055;background:#9FE8E01a;color:#9FE8E0}
.badge-chip .medal{margin-right:1px}
.badge-chip .medal-ring{border-width:1.25px}
.badge-chip .medal-gold .medal-ring,.badge-chip .medal-platinum .medal-ring{box-shadow:none}
/* Silver and platinum are pale by design; on a light surface they need to come
   down to stay readable (WCAG AA on small bold text). */
:root[data-theme="light"] .badge-chip.chip-silver{border-color:#7C879855;background:#7C87981a;color:#5A6474}
:root[data-theme="light"] .badge-chip.chip-platinum{border-color:#2E9E9355;background:#2E9E931a;color:#217A71}
:root[data-theme="light"] .badge-chip.chip-bronze{color:#9A6238}

.badge-won{display:inline-flex;align-items:center;gap:5px;margin-top:6px;font-size:var(--fs-xs);
  font-weight:700;color:var(--success)}
.badge-sheet-hero{display:flex;gap:14px;align-items:flex-start}
.badge-sheet-name{font-size:var(--fs-md);font-weight:700;margin-bottom:2px}

/* The bar eases to its new width; the sheen fires once when it grows, so a
   completion reads as progress rather than a silent redraw. Respects
   prefers-reduced-motion via the media query below. */
.prog-fill{position:relative}
.prog-fill.prog-bumped::after{content:'';position:absolute;inset:0;border-radius:inherit;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);
  animation:prog-sheen .9s ease-out 1}
@keyframes prog-sheen{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
@media (prefers-reduced-motion:reduce){
  .prog-fill{transition:none}
  .prog-fill.prog-bumped::after{animation:none}
  .badge-emoji{transition:none}
}

/* ── Attention motion + one-time tips ─────────────────────────────────────
   THE RULE for every attention animation here: the 0% and 100% frames must be
   IDENTICAL, with the emphasis in the middle.

   The blanket reduced-motion rule at the top of this file is
     *{animation-duration:.01ms!important; animation-iteration-count:1!important}
   which does not disable an animation. It collapses it to one instantaneous
   iteration, so the keyframes still apply and the element is left holding the
   animation's END state. A pulse that ends on a glow would leave a permanently
   glowing button for every reduced-motion user. Start and end where you began
   and that whole class of bug cannot happen, with no JS guard needed.
   prefersReducedMotion() in ui.js is for motion JS sequences, not this. */
.cta-pulse{animation:ctaPulse var(--dur-4) var(--ease-out) 2}
@keyframes ctaPulse{
  0%  {box-shadow:0 0 0 0 var(--accent-dim)}
  50% {box-shadow:0 0 0 7px transparent}
  100%{box-shadow:0 0 0 0 var(--accent-dim)}
}
.nav-nudge{animation:navNudge var(--dur-3) var(--ease-out) 3}
@keyframes navNudge{0%{transform:none}50%{transform:translateY(-2px)}100%{transform:none}}

/* A one-time hint. Built off .ro-banner's shape but dismissible, and it sits in
   the flow rather than over the top of anything. */
.tip-card{display:flex;gap:10px;align-items:flex-start;background:var(--accent-dim);
  border:1px solid var(--accent-border);border-radius:var(--r-md);
  padding:10px var(--sp-3);margin-bottom:var(--sp-3);
  animation:tipPop var(--dur-3) var(--ease-out)}
@keyframes tipPop{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.tip-card .tip-body{flex:1;min-width:0}
.tip-card .tip-title{font-size:var(--fs-sm);font-weight:700;color:var(--text-1);margin-bottom:2px}
.tip-card .tip-text{font-size:var(--fs-xs);color:var(--text-2);line-height:1.5}
.tip-card .tip-x{background:none;border:none;color:var(--text-2);cursor:pointer;
  padding:4px;margin:-4px -4px 0 0;border-radius:var(--r-sm);flex-shrink:0;min-width:24px;min-height:24px}
.tip-card .tip-x:hover{color:var(--text-1);background:var(--surface-2)}

/* Welcome sheet: a short list of what this app is for, not a tour. */
.welcome-list{display:flex;flex-direction:column;gap:var(--sp-3);margin:var(--sp-2) 0 var(--sp-4)}
.welcome-item{display:flex;gap:10px;align-items:flex-start}
.welcome-item .wi-icon{color:var(--accent-text);flex-shrink:0;margin-top:1px}
.welcome-item .wi-text{font-size:var(--fs-sm);color:var(--text-2);line-height:1.5}
.welcome-item .wi-text b{color:var(--text-1);font-weight:600}

/* ── MESSAGES ────────────────────────────────────────────────────────────
   A thread has to be readable one-handed at a field, so bubbles are wide and
   the composer is pinned where a thumb already is. */
.conv-avatar{width:34px;height:34px;border-radius:9px;flex-shrink:0;display:flex;
  align-items:center;justify-content:center;background:var(--surface-2);color:var(--text-2)}
.conv-avatar.dm{border-radius:50%;background:var(--accent-dim);color:var(--accent-text)}
.conv-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--accent);
  margin-left:7px;vertical-align:middle}
.conv-time{font-size:var(--fs-xs);color:var(--text-3);flex-shrink:0;font-variant-numeric:tabular-nums}
/* Says who else can read this, on the row, before it is opened. */
.conv-note{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:600;
  color:var(--text-3);margin-top:3px}

/* The supervision banner is deliberately plain rather than a warning colour:
   parents being in the thread is normal, not an error. */
.msg-supervised{display:flex;gap:10px;align-items:flex-start;background:var(--surface-1);
  border:1px solid var(--border);border-left:2px solid var(--accent);border-radius:var(--r-md);
  padding:11px var(--sp-3);margin-bottom:var(--sp-3);font-size:var(--fs-xs);
  color:var(--text-2);line-height:1.5}
.msg-supervised svg{color:var(--accent-text);flex-shrink:0;margin-top:1px}

/* The thread grows with the page rather than scrolling inside a box of its own.
   The previous max-height was a guess at everything above and below it, and a
   guess stops being right the moment a reply chip or a reaction row appears --
   which is how the composer ended up underneath the tab bar. The page is the
   scroller now; the composer sticks to the bottom of it. */
.msg-thread{display:flex;flex-direction:column;gap:3px;padding:2px 0 8px}
.msg-day{align-self:center;font-size:10px;font-weight:700;letter-spacing:1.4px;text-transform:uppercase;
  color:var(--text-3);margin:14px 0 8px}
/* A column, because the bubble now stacks over its reaction/action row. The
   side a message sits on is align-items, not justify-content. */
.msg-row{display:flex;flex-direction:column;align-items:flex-start;max-width:100%}
.msg-row.mine{align-items:flex-end}
.msg-bubble{max-width:min(78%,520px);background:var(--surface-2);border-radius:14px 14px 14px 4px;
  padding:9px 13px;transition:transform .12s ease}
/* Long press and double tap are hijacked on TOUCH only, so a phone does not
   raise the OS text callout mid-gesture or zoom on the second tap. Desktop
   keeps text selection and the right-click menu untouched; "Copy text" in the
   message menu is what replaces long-press-to-select on a phone. */
@media (hover:none){
  .msg-bubble{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;
    touch-action:manipulation}
}
/* Held, but not yet long enough to count. */
.msg-row.msg-pressing .msg-bubble{transform:scale(.975)}
.msg-bubble.msg-liked{animation:msgLike .42s cubic-bezier(.34,1.56,.64,1)}
@keyframes msgLike{0%{transform:scale(1)}42%{transform:scale(1.06)}100%{transform:scale(1)}}
@media (prefers-reduced-motion:reduce){
  .msg-bubble{transition:none}
  .msg-row.msg-pressing .msg-bubble{transform:none}
  .msg-bubble.msg-liked{animation:none}
}
.msg-row.mine .msg-bubble{background:var(--accent-dim);border-radius:14px 14px 4px 14px}
.msg-from{font-size:11px;font-weight:700;color:var(--accent-text);margin-bottom:3px}
.msg-body{font-size:var(--fs-sm);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
.msg-time{font-size:10px;color:var(--text-3);margin-top:4px;text-align:right;font-variant-numeric:tabular-nums}

/* Sticky, so the composer is reachable however long the thread is. On mobile
   the tab bar is fixed over the bottom of the scrollport, so the offset has to
   clear it -- bottom:0 would park the composer behind it. */
.msg-foot-wrap{position:sticky;bottom:0;z-index:5;background:var(--bg);
  padding-bottom:var(--sp-2)}
@media(max-width:767.9px){
  .msg-foot-wrap{bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom))}
}
.msg-composer{display:flex;gap:8px;align-items:flex-end;padding-top:var(--sp-3);
  border-top:1px solid var(--border);margin-top:var(--sp-2)}
/* The composer is a contenteditable div, not a textarea, because Chrome only
   offers a keyboard's rich content (Gboard's GIF search) to a contenteditable.
   It has to be dressed to look and behave exactly like the input it replaced. */
.msg-composer .msg-input{flex:1;min-width:0;min-height:44px;max-height:140px;overflow-y:auto;
  line-height:1.45;padding:11px 13px;white-space:pre-wrap;overflow-wrap:anywhere;
  cursor:text}
/* A div gets no placeholder attribute. :empty is enough because plaintext-only
   leaves the element genuinely empty rather than holding a stray <br>. */
.msg-composer .msg-input:empty::before{content:attr(data-placeholder);color:var(--text-3);
  pointer-events:none;display:block}
.msg-composer .msg-input:focus{outline:none;border-color:var(--accent)}
.msg-composer .btn{width:auto;flex-shrink:0;padding:0 16px;min-height:44px}
/* ── "Covers which seasons" on a dues plan ── */
.season-picks{display:flex;flex-direction:column;gap:2px;border:1px solid var(--border);
  border-radius:9px;padding:4px;max-height:170px;overflow-y:auto}
.season-pick{display:flex;align-items:center;gap:9px;padding:8px 9px;border-radius:7px;
  cursor:pointer;font-size:var(--fs-sm);min-height:40px}
.season-pick:hover{background:var(--surface-2)}
.season-pick input{width:16px;height:16px;accent-color:var(--accent);flex-shrink:0;margin:0}

/* A prior season scopes the whole app to last year. Saying so beats letting an
   empty-looking roster read as a bug. */
.season-past{font-size:9px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;
  background:var(--surface-2);color:var(--text-2);border:1px solid var(--border);
  border-radius:4px;padding:1px 4px;margin-left:2px}
.team-switch.is-prior{border-color:var(--text-3)}

/* ── Unread badge on nav / tab bar ── */
.nav-item,.tb-item{position:relative}
.nav-badge{display:inline-flex;align-items:center;justify-content:center;
  min-width:18px;height:18px;padding:0 5px;border-radius:999px;
  background:var(--accent);color:#0B0B0D;font-size:10px;font-weight:800;
  line-height:1;font-variant-numeric:tabular-nums;letter-spacing:0}
.nav-item .nav-badge{margin-left:auto}
/* On the bar the label sits under the icon, so the badge rides the icon's
   corner instead of taking a third line. */
.tb-item .nav-badge{position:absolute;top:4px;left:50%;margin-left:2px}

/* ── Quoted reply ── */
.msg-quote{display:block;width:100%;text-align:left;background:transparent;border:0;
  border-left:2px solid var(--accent);padding:2px 0 3px 8px;margin:0 0 5px;cursor:pointer;
  color:var(--text-2);font:inherit}
.msg-quote-who{display:block;font-size:10px;font-weight:700;color:var(--accent-text);
  letter-spacing:.4px}
.msg-quote-text{display:block;font-size:11.5px;line-height:1.4;opacity:.85;
  overflow-wrap:anywhere}
/* Jumping to a message that is already on screen is invisible without this. */
.msg-flash .msg-bubble{animation:msgFlash 1.4s ease-out}
@keyframes msgFlash{0%,25%{background:var(--accent-dim2,var(--accent-dim))}100%{}}

/* ── Reaction / action row under a bubble ── */
.msg-foot{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin:3px 2px 6px}
.msg-row.mine .msg-foot{flex-direction:row-reverse}
.msg-reacts{display:contents}
.msg-react{display:inline-flex;align-items:center;gap:4px;background:var(--surface-2);
  border:1px solid var(--border);border-radius:999px;padding:2px 8px 2px 6px;cursor:pointer;
  line-height:1;min-height:26px}
.msg-react.mine{border-color:var(--accent);background:var(--accent-dim)}
.msg-react-e{font-size:13px}
.msg-react-n{font-size:11px;color:var(--text-2);font-variant-numeric:tabular-nums}
.msg-react.mine .msg-react-n{color:var(--accent-text)}
/* Quiet by default so a long thread is not a wall of controls, and full
   strength on hover, focus, or any touch device where hover cannot happen. */
.msg-act{background:transparent;border:0;color:var(--text-3);font-size:11px;font-weight:600;
  padding:5px 7px;border-radius:7px;cursor:pointer;opacity:.4;transition:opacity .15s,background .15s;
  min-height:28px;display:inline-flex;align-items:center;gap:3px}
.msg-act:hover{background:var(--surface-2)}
.msg-row:hover .msg-act,.msg-row:focus-within .msg-act{opacity:1}
.msg-act:hover,.msg-act:focus-visible{color:var(--text-1)}
@media (hover:none){.msg-act{opacity:.75}}

/* ── Mentions ── */
.msg-mention{color:var(--accent-text);font-weight:600}
.msg-bubble.at-me{box-shadow:inset 2px 0 0 var(--accent)}
.msg-mention-menu{display:flex;flex-direction:column;gap:2px;margin-top:var(--sp-2);
  border:1px solid var(--border);border-radius:10px;background:var(--surface-1);
  padding:4px;max-height:190px;overflow-y:auto}
.msg-mention-menu[hidden]{display:none}
.msg-mention-opt{display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  background:transparent;border:0;color:var(--text-1);font:inherit;font-size:var(--fs-sm);
  padding:9px 10px;border-radius:7px;cursor:pointer;min-height:40px}
.msg-mention-opt:hover,.msg-mention-opt:focus-visible{background:var(--surface-2)}
.msg-mention-opt svg{color:var(--text-3);flex-shrink:0}

/* ── "Replying to…" chip above the composer ── */
.msg-replying{display:flex;align-items:center;gap:8px;margin-top:var(--sp-2);
  padding:7px 10px;border-radius:9px;background:var(--surface-2);
  border-left:2px solid var(--accent)}
.msg-replying-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.msg-replying-text span:last-child{font-size:11.5px;color:var(--text-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.msg-replying .msg-act{opacity:1}

.report-row{padding:11px 0;border-bottom:1px solid var(--border)}
.report-row:last-child{border-bottom:0}
.report-row.is-open{border-left:2px solid var(--accent);padding-left:10px}
.report-snap{font-size:var(--fs-sm);line-height:1.5;background:var(--surface-2);
  border-radius:8px;padding:8px 10px;overflow-wrap:anywhere}

/* ── Report ── */
.report-reasons{display:flex;flex-direction:column;gap:2px}
.report-reason{display:flex;align-items:flex-start;gap:10px;padding:10px;border-radius:9px;
  cursor:pointer;border:1px solid transparent}
.report-reason:hover{background:var(--surface-2)}
.report-reason:has(input:checked){border-color:var(--accent);background:var(--accent-dim)}
.report-reason input{width:17px;height:17px;accent-color:var(--accent);flex-shrink:0;margin-top:1px}
.report-reason span{display:flex;flex-direction:column;gap:2px;font-size:var(--fs-sm)}
.report-reason em{font-style:normal;font-size:11.5px;color:var(--text-2)}

/* ── Photos in a message ── */
.msg-media{display:block;padding:0;border:0;background:transparent;cursor:zoom-in;
  margin:0 0 6px;border-radius:10px;overflow:hidden;line-height:0}
.msg-media img{max-width:100%;height:auto;display:block;border-radius:10px}
.msg-media-missing{display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--text-3);
  padding:10px;border:1px dashed var(--border);border-radius:9px;margin-bottom:6px}
.msg-photo-full{width:100%;height:auto;border-radius:10px;display:block}
/* Staged, before sending. */
.msg-media-draft{display:flex;align-items:center;gap:10px;margin-top:var(--sp-2);
  padding:7px 10px;border-radius:9px;background:var(--surface-2);border-left:2px solid var(--accent)}
.msg-media-draft img{width:38px;height:38px;object-fit:cover;border-radius:6px;flex-shrink:0}
.msg-media-draft-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.msg-media-draft-text span:last-child{font-size:11.5px;color:var(--text-2)}
.msg-media-draft .msg-act{opacity:1}
.msg-composer.drop-on{outline:2px dashed var(--accent);outline-offset:4px;border-radius:10px}
.msg-attach-btn{width:auto;flex-shrink:0;padding:0 12px;min-height:44px}

/* ── Emoji picker ── */
.emoji-quick{display:flex;gap:6px;justify-content:center;padding:2px 0 10px;
  border-bottom:1px solid var(--border);margin-bottom:10px}
.react-pick{font-size:23px;line-height:1;background:var(--surface-2);border:1px solid var(--border);
  border-radius:11px;flex:1;min-width:0;max-width:56px;aspect-ratio:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center}
.react-pick:hover,.react-pick:focus-visible{border-color:var(--accent);background:var(--accent-dim)}
.emoji-search{margin-bottom:8px;font-size:var(--fs-sm)}
.emoji-tabs{display:flex;gap:2px;overflow-x:auto;padding-bottom:6px;margin-bottom:6px;
  border-bottom:1px solid var(--border)}
.emoji-tab{font-size:19px;line-height:1;background:transparent;border:0;border-radius:8px;
  padding:6px 9px;cursor:pointer;opacity:.5;flex-shrink:0;min-height:36px}
.emoji-tab:hover{opacity:.85;background:var(--surface-2)}
.emoji-tab.on{opacity:1;background:var(--accent-dim)}
/* auto-fill, so the grid keeps its 44px touch targets on a narrow phone and
   simply fits fewer per row rather than shrinking them. */
.emoji-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(44px,1fr));gap:2px;
  max-height:min(46vh,320px);overflow-y:auto;padding-right:2px}
/* Section heading inside the grid. Full width so the columns keep flowing. */
.emoji-sec{grid-column:1/-1;font-size:10px;font-weight:700;letter-spacing:1.2px;
  text-transform:uppercase;color:var(--text-3);padding:10px 2px 4px;position:sticky;top:0;
  background:var(--surface-1);z-index:1}
.emoji-sec:first-child{padding-top:2px}
/* On touch the OS keyboard already has a full emoji picker -- better than ours,
   always current, and it knows the user's language and skin tone. Ours is for
   desktop, where there is no obvious equivalent. */
@media (hover:none){.msg-emoji-btn{display:none}}
.emoji-cell{font-size:23px;line-height:1;background:transparent;border:0;border-radius:8px;
  height:44px;cursor:pointer;display:flex;align-items:center;justify-content:center}
.emoji-cell:hover,.emoji-cell:focus-visible{background:var(--accent-dim)}
.msg-emoji-btn{width:auto;flex-shrink:0;padding:0 12px;min-height:44px;font-size:19px;line-height:1}

.new-msg-list{max-height:52vh;overflow-y:auto}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ── Drill effort capture (Train) ──
   The timer is the primary path and reads as one: big, centred, unmistakable.
   Manual entry is a <details> so it is available without competing with it —
   present for the kid who forgot to hit Start, not offered first. */
.dt-timer{font-family:var(--font-display);font-size:44px;letter-spacing:2px;
  text-align:center;color:var(--accent);font-variant-numeric:tabular-nums;line-height:1}
.dt-hint{text-align:center;font-size:var(--fs-xs);color:var(--text-3);margin:6px 0 12px}
.dt-manual{margin-top:12px;border-top:1px solid var(--border);padding-top:10px}
.dt-manual summary{font-size:var(--fs-sm);color:var(--text-2);cursor:pointer;padding:4px 0}
.dt-manual-row{display:flex;gap:10px;margin:10px 0}
.dt-manual-row label{flex:1;font-size:var(--fs-xs);color:var(--text-2);
  display:flex;flex-direction:column;gap:4px}
.dt-opt{color:var(--text-3)}

/* ── Sign-off queue ── */
.sq-row{display:flex;align-items:center;gap:10px;padding:11px 0;
  border-bottom:1px solid var(--border)}
.sq-row:last-child{border-bottom:none}
.sq-main{flex:1;min-width:0}
.sq-name{font-weight:600;font-size:var(--fs-sm)}
.sq-meta{font-size:var(--fs-xs);color:var(--text-3);margin-top:2px}
.sq-flag{display:inline-block;font-size:10px;letter-spacing:.04em;text-transform:uppercase;
  color:var(--accent-text);border:1px solid var(--accent-border);border-radius:999px;
  padding:1px 7px;margin-right:4px;margin-top:4px}
.sq-acts{display:flex;gap:6px;flex-shrink:0}

/* A quiet line under a dashboard section — the "why this matters" note and the
   "N more waiting" link. Deliberately not a row: it is not something to act on
   one at a time. */
.home-note{font-size:var(--fs-xs);color:var(--text-3);padding-top:8px}
.home-note .home-link{font-size:var(--fs-xs)}
/* The sign-off buttons sit in a home-row, which is a flex line already. */
.home-row .sq-acts{flex-shrink:0}
