/* ===========================================================================
   SBR PORTALS DESIGN KIT (2026-10-29): the web half of the mobile apps' design kit (src/ds.js in both apps, docs/SBR-Visual-Guide.md).
   ONE stylesheet for the coach website, the admin site and the clinic portal, loaded LAST on each so it wins ties with the page's own
   rules. It restyles the classes the three sites already use (same names, same markup, same behavior) and adds a few opt-in
   components (.ds-*). Light only: the apps are light-only, so there is no dark theme to match. Plan: docs/SBR-Portals-Visual-Refresh-Plan.md.
   Copies: coach ITEMS and admin tw/ in firebase/scripts/assemble-hosting.sh, and the clinic site; never hand-copy, never edit a copy.
   =========================================================================== */
:root{
  /* shape and depth (guide section 7) */
  --ds-r-control:12px; --ds-r-card:16px; --ds-r-hero:20px; --ds-r-pill:999px;
  --ds-elev-card:0 1px 2px rgba(14,23,38,.04),0 2px 8px rgba(14,23,38,.06);
  --ds-elev-raised:0 4px 12px rgba(14,23,38,.10);
  --ds-elev-hero:0 6px 12px rgba(10,60,100,.25);
  --ds-line:#E9EEF4; --ds-muted:#F5F8FB; --ds-unread:#F3F8FF;
  /* the status language (guide section 4): color = icons, bars, dots; ink = text on the tint */
  --ds-brand:#148CD2; --ds-brand-ink:#0A3C64; --ds-brand-tint:#E7F3FB;
  --ds-success:#1F9D6B; --ds-success-ink:#157A52; --ds-success-tint:#E9F7F0;
  --ds-warning:#E8902B; --ds-warning-ink:#9A5B00; --ds-warning-tint:#FFF4E0;
  --ds-danger:#E5484D;  --ds-danger-ink:#B4232A;  --ds-danger-tint:#FEECEC;
  --ds-slate:#94A3B8;   --ds-slate-ink:#33415A;   --ds-slate-tint:#F1F5F9;
  --ds-group:#7C4DFF;   --ds-group-ink:#5B34D6;   --ds-group-tint:#F1ECFF;
  --ds-session:#0A9C95; --ds-session-ink:#065F5B; --ds-session-tint:#E3F6F4;
  --ds-ai:#D6336C;      --ds-ai-ink:#A61E4D;      --ds-ai-tint:#FDEBF2;
  /* the coach site's own status tints follow the language: a missed workout is amber, not red */
  --missed-tint:rgba(232,144,43,.16);
}

/* ---- base: one focus ring everywhere (keyboard only) ------------------------------------------------------------------- */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{outline:2px solid var(--ds-brand);outline-offset:2px;border-radius:var(--ds-r-control)}
body{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}

/* ---- cards ----------------------------------------------------------------------------------------------------------- */
.card{border-radius:var(--ds-r-card);border:1px solid var(--ds-line);box-shadow:var(--ds-elev-card)}
.plan,.pg-plan,.pw-card,.pw-pcard,.q-item,.check{border-radius:var(--ds-r-card)}

/* ---- overlines: table heads, nav sections, stat labels (type.overline) ---------------------------------------------- */
th,.tbl th,.nav-section,.statc .l,.stat .l,.pw-tile span{font-size:11.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-500,#64748B)}
nav .nav-section,.nav-section{color:#64748B}   /* 4.8:1 on white; was 2.5:1 */

/* ---- stat tiles: number and label (StatTile) ------------------------------------------------------------------------ */
.statc,.stat,.pw-tile{background:#fff;border:1px solid var(--ds-line);border-radius:var(--ds-r-card);box-shadow:var(--ds-elev-card)}
.card .statc,.card .stat,.card .pw-tile{background:var(--ds-muted);border:0;box-shadow:none}   /* a tile inside a white card sits on a soft fill instead */
.statc-ic{border-radius:50%}
.statc .v,.stat .v,.pw-tile b{font-weight:800;letter-spacing:-.02em}

/* ---- pills and chips: ink on tint, the same table on every portal (Pill / STATUS_LOOK) ----------------------------- */
.pill,.chip{font-weight:800;border-radius:var(--ds-r-pill)}
.pill.ok,.chip.success,.ds-pill.success{background:var(--ds-success-tint);color:var(--ds-success-ink)}
.pill.warn,.chip.warning,.ds-pill.warning{background:var(--ds-warning-tint);color:var(--ds-warning-ink)}
.pill.bad,.chip.danger,.ds-pill.danger{background:var(--ds-danger-tint);color:var(--ds-danger-ink)}
.pill.info,.chip.brand,.ds-pill.brand{background:var(--ds-brand-tint);color:var(--ds-brand-ink)}
.pill.muted,.pill.inactive,.chip.muted,.ds-pill.slate{background:var(--ds-slate-tint);color:var(--ds-slate-ink)}
.ds-pill.group{background:var(--ds-group-tint);color:var(--ds-group-ink)}
.ds-pill.session{background:var(--ds-session-tint);color:var(--ds-session-ink)}
.ds-pill.ai{background:var(--ds-ai-tint);color:var(--ds-ai-ink)}
.chip{white-space:nowrap}
.ds-pill{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:800;padding:4px 10px;border-radius:var(--ds-r-pill)}
.ds-pill svg{width:13px;height:13px;flex:none}
/* an icon in a soft circle of its tone (row leads, empty states) */
.ds-iconcircle{width:40px;height:40px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;flex:none;background:var(--ds-brand-tint);color:var(--ds-brand-ink)}
.ds-iconcircle svg{width:20px;height:20px}
.ds-iconcircle.success{background:var(--ds-success-tint);color:var(--ds-success-ink)}
.ds-iconcircle.warning{background:var(--ds-warning-tint);color:var(--ds-warning-ink)}
.ds-iconcircle.danger{background:var(--ds-danger-tint);color:var(--ds-danger-ink)}
.ds-iconcircle.slate{background:var(--ds-slate-tint);color:var(--ds-slate-ink)}
/* the status dots keep their plain tone (a dot is an icon, not text) */
.dot.connected{background:var(--ds-success)}.dot.pending{background:var(--ds-warning)}.dot.needs_programming{background:var(--ds-brand)}
.dot.offline,.dot.archived{background:var(--ds-slate)}

/* ---- section header: a dot, the label in capitals, a count (SectionHeader) ----------------------------------------- */
.ds-section{display:flex;align-items:center;gap:8px;margin:8px 0 10px;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-500,#64748B)}
.ds-section .d{width:8px;height:8px;border-radius:50%;background:var(--ds-brand);flex:none}
.ds-section .n{color:#64748B}
.ds-section .grow{flex:1}

/* ---- the hero card: the one dark navy card a screen may have (HeroCard + StatTile dark) ----------------------------- */
.ds-hero{border:0;background:var(--ds-brand-ink,#0A3C64);color:#fff;border-radius:var(--ds-r-hero);padding:20px;box-shadow:var(--ds-elev-hero);margin-bottom:18px}
.ds-hero h2,.ds-hero h3{color:#fff}
.ds-hero .sub,.ds-hero .asof,.ds-hero p{color:rgba(255,255,255,.78)}
.ds-hero .pg-head{margin-bottom:12px}
.ds-hero .stats{margin-top:4px}
.ds-hero .stat{background:rgba(255,255,255,.10);border:0;color:#fff}
.ds-hero .stat .v{color:#fff}
.ds-hero .stat .l,.ds-hero .stat .h{color:rgba(255,255,255,.78)}
.ds-hero .pill.ok{background:rgba(255,255,255,.16);color:#fff}
.ds-hero .pill.warn,.ds-hero .pill.bad,.ds-hero .pill.info,.ds-hero .pill.muted{background:rgba(255,255,255,.16);color:#fff}
.ds-hero a{color:#fff;text-decoration:underline}

/* ---- buttons (ActionButton) ---------------------------------------------------------------------------------------- */
.btn,.btn-primary,.btn-secondary,.btn-ghost,.btn-danger{border-radius:var(--ds-r-control);font-weight:800}
.btn-sm,.btn.small,.btn.sm{border-radius:10px}
.btn-primary{box-shadow:0 4px 12px -4px rgba(20,140,210,.45)}
.btn-secondary,.btn.secondary{background:#fff;color:var(--ink-900,#0E1726);border:1px solid var(--ds-line)}
.btn-secondary:hover,.btn.secondary:hover{border-color:#CBD5E1;background:var(--ds-muted)}
.btn-danger,.btn.danger{background:var(--ds-danger-tint);color:var(--ds-danger-ink)}
.btn-danger:hover,.btn.danger:hover{background:#FCDADB}
.btn:disabled,.btn-primary:disabled{opacity:.55;cursor:default}
.icon-btn,.hamburger{border-radius:var(--ds-r-control)}

/* ---- tabs: segmented pills (Segmented) ----------------------------------------------------------------------------- */
.tabs button{font-weight:800}
.tabs button.active,.tabs button.on{box-shadow:0 2px 8px -2px rgba(20,140,210,.35)}
.clinic-tabs .tabs button{border:0}

/* ---- tables: overline head, hairline rows, a tinted hover ------------------------------------------------------------- */
table{border-collapse:collapse}
tbody tr:hover,.tbl tbody tr:hover{background:var(--ds-unread)}
td,.tbl td{border-top-color:var(--ds-line)}
.ds-tablewrap,.card:has(table){overflow-x:auto;-webkit-overflow-scrolling:touch}   /* a table wider than its card scrolls inside the card, at every width */

/* ---- inputs --------------------------------------------------------------------------------------------------------- */
input[type=text],input[type=email],input[type=password],input[type=search],input[type=number],input[type=date],input[type=tel],input[type=url],select,textarea{border-radius:var(--ds-r-control);border:1px solid #D5DEE8;background:#fff}
input:focus,select:focus,textarea:focus{border-color:var(--ds-brand);box-shadow:0 0 0 3px rgba(20,140,210,.16);outline:none}
.search{border-radius:var(--ds-r-control)}

/* ---- notices (band) and empty states ------------------------------------------------------------------------------- */
.band{border-radius:var(--ds-r-control)}
.band.info{background:var(--ds-brand-tint);color:var(--ds-brand-ink)}
.band.warn{background:var(--ds-warning-tint);color:var(--ds-warning-ink)}
.band.bad{background:var(--ds-danger-tint);color:var(--ds-danger-ink)}
.empty{border-radius:var(--ds-r-card);background:var(--ds-muted);border:1px dashed #D5DEE8}

/* ---- sheets: modals ------------------------------------------------------------------------------------------------- */
.modal-bg{background:rgba(14,23,38,.45)}
.modal{border-radius:var(--ds-r-hero)}
.modal-head h3{font-weight:800}

/* ---- navigation ------------------------------------------------------------------------------------------------------ */
.navlink,nav a,#sidebar .nav-link{border-radius:var(--ds-r-control)}
.navlink.active,nav a.on{background:var(--ds-brand-tint);color:var(--ds-brand-ink)}

/* ---- the info key: an (i) on a header line opens "What the colors mean"; CLOSED until tapped (statuskey.js) ------------ */
.ds-key-btn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;margin-left:10px;border-radius:50%;
  border:1.5px solid var(--ds-brand);background:#fff;color:var(--ds-brand);font:800 13px/1 var(--font,Manrope,system-ui,sans-serif);font-style:italic;
  cursor:pointer;vertical-align:middle;padding:0}
.ds-key-btn:hover{background:var(--ds-brand-tint)}
.ds-key-btn[aria-expanded=true]{background:var(--ds-brand);color:#fff}
.ds-key{background:#fff;border:1px solid var(--ds-line);border-radius:var(--ds-r-card);box-shadow:var(--ds-elev-card);padding:14px 16px;margin:0 0 16px}
.ds-key[hidden]{display:none}
.ds-key h4{margin:0 0 10px;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-500,#64748B)}
.ds-key ul{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:8px 18px}
.ds-key li{display:flex;align-items:center;gap:10px;font-size:13.5px;font-weight:600;color:var(--ink-700,#33415A);line-height:1.35}
.ds-key .sw{flex:none;display:inline-block}
.ds-key .sw.dot{width:10px;height:10px;border-radius:50%}
.ds-key .sw.bar{width:4px;height:18px;border-radius:2px}
.ds-key .sw.chip{width:34px;height:18px;border-radius:999px}
.ds-key .sw.cell{width:22px;height:16px;border-radius:5px}
.ds-key .sw.icon{width:18px;height:18px}
.ds-key-wrap{margin:12px 24px 0}
@media(max-width:760px){.ds-key-wrap{margin:12px 14px 0}}

/* ---- mobile width (360): nothing may push the page sideways; tables scroll inside their own card ----------------------- */
html,body{max-width:100%;overflow-x:hidden}
@media(max-width:760px){
  .card:has(>table),.card:has(>.tbl),.card:has(>div>table),.card:has(>div>.tbl){overflow-x:auto;-webkit-overflow-scrolling:touch}
  /* a soft shadow on the edge that has more to scroll to: the card says it scrolls (shadows ride the scroll, covers hide them at the ends) */
  .card:has(>table),.card:has(>.tbl),.card:has(>div>table),.card:has(>div>.tbl){background-color:#fff;background-repeat:no-repeat;
    background-image:linear-gradient(to right,#fff 30%,rgba(255,255,255,0)),linear-gradient(to left,#fff 30%,rgba(255,255,255,0)),
      radial-gradient(farthest-side at 0 50%,rgba(14,23,38,.22),rgba(14,23,38,0)),radial-gradient(farthest-side at 100% 50%,rgba(14,23,38,.22),rgba(14,23,38,0));
    background-position:left center,right center,left center,right center;background-size:36px 100%,36px 100%,12px 100%,12px 100%;
    background-attachment:local,local,scroll,scroll}
  .card{padding-left:min(var(--card-pad,22px),16px);padding-right:min(var(--card-pad,22px),16px)}
  .page{padding:16px 14px}
  .modal-body{padding:16px}
  #content table.tbl.wo-tbl{display:block;overflow-x:auto;max-width:100%}   /* the workout library's table has no card around it */
  .tbl td:last-child,.tbl th:last-child{white-space:nowrap}   /* a row's action buttons stay on one line; the card scrolls, the rows do not grow tall */
}
/* the admin site on a phone: the header wraps instead of clipping its buttons, the content gives the icon rail its room back */
@media(max-width:620px){
  body > #app > header,#app > header,header{flex-wrap:wrap;row-gap:8px;padding:12px 14px}
  header h1{white-space:normal}
  #content{padding:16px 12px 48px}
  .pw-head{flex-wrap:wrap;align-items:flex-start;gap:12px}
  .pw-head h1,.pw-head h2{font-size:clamp(22px,6vw,30px);line-height:1.15}
  .pg-plan,.pg-plan-top,.pg-plan-actions,.pw-acts,.pw-bar,.vp-find,.cp-row,.cp-row-ctl,.row{flex-wrap:wrap}
  .cp-grid{grid-template-columns:minmax(0,1fr)}
  .cp-left,.cp-right,.cp-row-main{min-width:0}
  .pg-plan-actions{flex-shrink:1;min-width:0}
  .pw-acts{flex:1 1 100%;min-width:0;flex-direction:row}
  .btn{max-width:100%;white-space:normal}
  select,input,textarea{max-width:100%}
}

/* ---- the coach calendar speaks the status language: done green, started amber, missed a stronger amber (red is for pain) ---- */
.ev.done{color:var(--ds-success-ink)}
.ev.partial{background:rgba(232,144,43,.12);color:var(--ds-warning-ink)}
.ev.missed{background:rgba(232,144,43,.28);color:var(--ds-warning-ink)}
.sched-legend .sw.partial{box-shadow:inset 0 0 0 1px var(--ds-warning);background:rgba(232,144,43,.12)}
.sched-legend .sw.missed{box-shadow:inset 0 0 0 1px var(--ds-warning);background:rgba(232,144,43,.28)}

/* the coach site on a phone: list rows wrap their actions under the title, the title keeps its (i) beside it, cards may shrink */
.card,.grid > *,.ring-card{min-width:0}
@media(max-width:620px){
  .row{flex-wrap:wrap}
  .row > .grow{flex:1 1 calc(100% - 64px)}
  .topbar{height:auto;min-height:64px;flex-wrap:wrap;row-gap:4px;column-gap:8px;padding:8px 12px}   /* title + (i) never share pixels with the buttons: if they do not fit on one line they wrap */
  .topbar h1{display:flex;align-items:center;white-space:nowrap;font-size:19px;flex:0 0 auto}
  .topbar .ds-key-btn{margin-left:6px;flex:none}
  .train-stats{gap:16px}
  .wf-wrap{padding-left:0;padding-right:0}
}
@media(max-width:900px){ .wf-wrap{grid-template-columns:minmax(0,1fr)} }

/* ===== PHASE 1 OF THE WEB PARITY WORK (2026-11-01): empty states, contrast, one control radius ===================================== */
/* an empty state carries an icon in a soft circle, like the apps' EmptyState; drawn by CSS so no screen's markup changes.
   Skipped for the one-line inline notes that reuse .empty (padding under 20px) and wherever a screen already draws its own icon. */
.empty:not(:has(svg,img,.ds-iconcircle)):not(.empty-plain)::before{content:"";display:block;width:44px;height:44px;margin:0 auto 12px;border-radius:50%;
  background:var(--ds-brand-tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230A3C64' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7.5 12 3l8 4.5v9L12 21l-8-4.5z'/%3E%3Cpath d='m4 7.5 8 4.5 8-4.5M12 12v9'/%3E%3C/svg%3E") center/22px no-repeat}
/* small gray notes and helper text were 2.5-2.8:1; this is 4.8:1 on white */
#content .muted:not(.chip):not(.pill),#content .small,#content .hint,#content .pw-meta,#content .pw-note{color:var(--ink-500,#64748B)}
/* blue text that is small uses the ink, not the vivid brand blue (3.6:1 on white) */
.tbl a:not(.btn),.card:not(.ds-hero) a:not(.btn):not(.navlink){color:var(--ds-brand-ink)}
/* every control shares the apps' control radius, including the legacy inline-styled ones */
.btn,button.btn,input[type=text],input[type=email],input[type=password],input[type=search],input[type=number],input[type=tel],input[type=date],input[type=time],select,textarea{border-radius:var(--ds-r-control)}
/* the (i) key never shares pixels with a neighbour: it stays on the title's line and the title may shrink */
.pg-head h2,.pg-head h1,.topbar h1{min-width:0}
@media(max-width:620px){ .topbar .btn{flex:none} .topbar .grow{flex:1 1 0;min-width:0} }
