:root {
  /* Default = Dark (green-accented) */
  --bg: #0e1311;
  --panel: #161d1a;
  --panel-2: #1d2723;
  --border: #2a352f;
  --text: #e9edea;
  --muted: #93a39a;
  --accent: #25c878;
  --accent-dark: #19a361;
  --success: #34c759;
  --danger: #ff5a5a;
  --radius: 12px;
}

/* ☀️ Light — clean white & green */
[data-theme="light"] {
  --bg: #f3f7f4;
  --panel: #ffffff;
  --panel-2: #eef3f0;
  --border: #dde6e0;
  --text: #15201b;
  --muted: #5f7068;
  --accent: #15a34a;
  --accent-dark: #11843c;
  --success: #15a34a;
  --danger: #e23b3b;
}
[data-theme="light"] body { background:
  radial-gradient(circle at 12% 6%, #e3f3e9 0, transparent 40%),
  var(--bg);
}
[data-theme="light"] .topbar { border-bottom-color: var(--border); }
[data-theme="light"] .brand { color: var(--accent); }

/* ============================================================
   THEMES — each block overrides the tokens above. The active
   one is chosen by <body data-theme="…"> (see User::THEMES).
   ============================================================ */

/* 🐱 Cat — deep purple dark theme (the orange cat pops against it) */
[data-theme="cat"] {
  --bg: #181228;
  --panel: #221a3a;
  --panel-2: #2c2250;
  --border: #3a2e5e;
  --text: #efeaff;
  --muted: #a99cc9;
  --accent: #8b5cf6;
  --accent-dark: #7c3aed;
  --success: #34d399;
  --danger: #ff6b6b;
}
[data-theme="cat"] body { background:
  radial-gradient(circle at 12% 6%, #2a1e4d 0, transparent 42%),
  radial-gradient(circle at 90% 0%, #321f57 0, transparent 36%),
  var(--bg);
}
[data-theme="cat"] .topbar { background: linear-gradient(90deg, #3a2a72, #271a4d); border-bottom-color: #4a2f8a; }
[data-theme="cat"] .brand { color: #fff; }

/* 🐶 Dog — bright sky-blue light theme with a warm secondary pop */
[data-theme="dog"] {
  --bg: #eef6fd;
  --panel: #ffffff;
  --panel-2: #e3f0fb;
  --border: #cfe3f4;
  --text: #14304a;
  --muted: #5c7693;
  --accent: #38a9e8;        /* sky blue — the action/accent color */
  --accent-dark: #1f8fd4;
  --accent-2: #ff9d4d;      /* warm orange secondary */
  --success: #1fa86a;
  --danger: #e23b3b;
}
[data-theme="dog"] body { background:
  radial-gradient(circle at 12% 6%, #d8ecfb 0, transparent 45%),
  radial-gradient(circle at 90% 0%, #e2f1fd 0, transparent 35%),
  var(--bg);
}
[data-theme="dog"] .topbar { background: linear-gradient(90deg, #5cb8ee, #2f9ee0); border-bottom: 3px solid var(--accent); }
[data-theme="dog"] .brand { color: #fff; }

/* 🦈 Shark — deep royal-blue ocean with a punchy orange bite */
[data-theme="shark"] {
  --bg: #101f52;            /* deep royal base — darker so cards lift off it */
  --panel: #294aa8;         /* vivid royal card */
  --panel-2: #3358c2;
  --border: #4a6cd6;        /* clearly lighter edge for separation */
  --text: #eef2ff;
  --muted: #aebde8;
  --accent: #ff8c3b;        /* orange — the action/accent color */
  --accent-dark: #f2701a;
  --accent-2: #ffd23f;      /* yellow highlight secondary */
  --success: #34d399;
  --danger: #ff6b6b;
}
[data-theme="shark"] body { background:
  radial-gradient(circle at 12% 6%, #1b2f74 0, transparent 46%),
  radial-gradient(circle at 90% 0%, #182a6c 0, transparent 40%),
  var(--bg);
}
[data-theme="shark"] .topbar { background: linear-gradient(90deg, #3457c8, #1d3390); border-bottom: 3px solid var(--accent); }
[data-theme="shark"] .brand { color: #fff; }

[data-theme="dino"] {
  --bg: #0c2417;            /* deep jungle floor — cards lift off it */
  --panel: #1b5e3a;         /* rich leaf-green card */
  --panel-2: #237046;
  --border: #3a8c5f;        /* lighter leaf edge for separation */
  --text: #eafff2;
  --muted: #a7d8bd;
  --accent: #7ed957;        /* bright lime — the action/accent color */
  --accent-dark: #5cb83a;
  --accent-2: #ffd23f;      /* sunny highlight secondary */
  --success: #34d399;
  --danger: #ff6b6b;
}
[data-theme="dino"] body { background:
  radial-gradient(circle at 12% 6%, #14442a 0, transparent 46%),
  radial-gradient(circle at 90% 0%, #123a24 0, transparent 40%),
  var(--bg);
}
[data-theme="dino"] .topbar { background: linear-gradient(90deg, #2b7d4d, #185a34); border-bottom: 3px solid var(--accent); }
[data-theme="dino"] .brand { color: #fff; }

/* A friendly mascot that bobs in the corner (cosmetic only) */
/* Viewport-filling, click-through layer so the mascot pins to the visual
   viewport in the native web view (a full-bleed fixed element is reliable). */
.mascot-layer { position: fixed; inset: 0; pointer-events: none; z-index: 5; }
.theme-mascot {
  position: absolute;
  right: 14px;
  bottom: 84px;
  width: 64px;
  cursor: pointer;
  pointer-events: auto;
  filter: drop-shadow(0 6px 10px rgba(180, 90, 40, 0.4));
  animation: mascot-idle 6s ease-in-out infinite;
}
.theme-mascot svg { width: 100%; height: auto; display: block; }
@media (min-width: 720px) { .theme-mascot { bottom: 18px; width: 76px; } }
/* In the native app there's no web tab bar to clear (that 84px offset), so the
   mascot would float up into content and overlap things like the Save button.
   Pin it to the actual bottom-right corner, above the native tab bar. */
body.native-app .theme-mascot { bottom: calc(14px + env(safe-area-inset-bottom)); }
@keyframes mascot-bob {
  0%, 100% { transform: translateY(0) rotate(-5deg); }
  50% { transform: translateY(-9px) rotate(5deg); }
}
/* Gentle idle life: mostly still, with an occasional bob + wiggle. */
@keyframes mascot-idle {
  0%, 70%, 100% { transform: translateY(0) rotate(0deg); }
  76% { transform: translateY(-7px) rotate(-7deg); }
  82% { transform: translateY(-2px) rotate(7deg); }
  88% { transform: translateY(-7px) rotate(-4deg); }
  94% { transform: translateY(0) rotate(0deg); }
}
/* Tap reaction: an excited little hop + shake. */
.theme-mascot.is-reacting { animation: mascot-react 0.6s ease; }
@keyframes mascot-react {
  0% { transform: translateY(0) rotate(0); }
  20% { transform: translateY(-16px) rotate(-12deg) scale(1.12); }
  45% { transform: translateY(-4px) rotate(10deg) scale(1.08); }
  70% { transform: translateY(-10px) rotate(-6deg); }
  100% { transform: translateY(0) rotate(0); }
}
.mascot-pop {
  position: absolute;
  left: 50%;
  top: -6px;
  font-size: 1.1rem;
  pointer-events: none;
  animation: mascot-pop 1s ease-out forwards;
}
@keyframes mascot-pop {
  0% { opacity: 0; transform: translate(-50%, 0) scale(0.5); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--dx, 0px)), -54px) scale(1.1); }
}

/* Paw-print tap trail (Cat/Dog modes) */
.paw-trail {
  position: fixed;
  width: 30px;
  height: 30px;
  color: var(--accent);
  opacity: 0.7;
  pointer-events: none;
  z-index: 9999;
  animation: paw-fade 1.1s ease-out forwards;
}
.paw-trail svg { width: 100%; height: 100%; display: block; }
@keyframes paw-fade {
  0% { opacity: 0.75; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.3) rotate(var(--r, 0deg)); }
}

/* Themed PR confetti (bones/balls for dog, fish/yarn for cat) */
.pr-confetti { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.pr-confetti__piece {
  position: absolute;
  top: -8%;
  left: calc(4% + var(--i) * 8%);
  width: 22px;
  opacity: 0;
  animation: pr-confetti-fall 1.7s ease-in calc(var(--i) * 0.09s) forwards;
}
.pr-confetti__piece svg { width: 100%; height: auto; display: block; }
@keyframes pr-confetti-fall {
  0% { opacity: 0; transform: translateY(0) rotate(0); }
  12% { opacity: 1; }
  100% { opacity: 0; transform: translateY(112vh) rotate(560deg); }
}

/* Paw "stamp" on a hit set row (Cat/Dog modes) */
[data-theme="cat"] .set-row--hit .set-chip::after,
[data-theme="dog"] .set-row--hit .set-chip::after {
  content: " 🐾";
  display: inline-block;
  animation: paw-stamp-in 0.45s cubic-bezier(0.18, 1.5, 0.4, 1);
}
@keyframes paw-stamp-in {
  0% { transform: scale(0) rotate(-30deg); }
  100% { transform: scale(1) rotate(0); }
}

/* Faint paw watermark behind content (Cat/Dog modes) */
[data-theme="cat"] body::before,
[data-theme="dog"] body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("/assets/paw-tile-58eb0f7f.svg");
  background-size: 90px 90px;
}

/* Themed celebration art + confetti (the trophy is swapped for the animal
   server-side under animal themes — see shared/_celebration). */
.celebrate--cat { background: linear-gradient(180deg, #ffe3d0, #ffffff); border-color: var(--accent); }
.celebrate--dog { background: linear-gradient(180deg, #ffeccb, #ffffff); border-color: var(--accent); }
.celebrate--cat .celebrate__msg,
.celebrate--dog .celebrate__msg { color: #3a2a20; }
.celebrate-animal {
  width: 104px;
  height: 104px;
  margin: 0 auto 6px;
  transform-origin: center bottom;
  animation: cat-pop 0.6s cubic-bezier(0.18, 1.5, 0.4, 1) both, mascot-bob 2.6s ease-in-out 0.6s infinite;
}
@keyframes cat-pop {
  0% { transform: scale(0) rotate(-25deg); }
  100% { transform: scale(1) rotate(0); }
}

/* Walking critter — a pup that trots up, gives you a lick, and trots off. */
#critters { position: fixed; inset: 0; pointer-events: none; z-index: 40; overflow: hidden; }
/* The set-log peek animals rise from #critters' bottom edge. In the native app
   that edge sits *behind* the native tab bar, so the peek pops up from behind
   the toolbar and gets clipped. Lift the layer's floor to the top of the tab
   bar (~tab-bar height + home-indicator inset) so the peek clears it. */
body.native-app #critters { bottom: calc(56px + env(safe-area-inset-bottom)); }
.critter { position: fixed; inset: 0; pointer-events: none; }

.critter__dog {
  position: absolute;
  bottom: 70px;
  left: 0;
  width: 124px;
  transform: translateX(-200px);
  animation: dog-visit 5.4s ease-in-out forwards;
}
@media (min-width: 720px) { .critter__dog { bottom: 16px; width: 152px; } }
.critter__dog svg { width: 100%; height: auto; display: block; }

/* walk in from the left, pause centre-ish to say hi, then trot off right */
@keyframes dog-visit {
  0%   { transform: translateX(-200px); }
  34%  { transform: translateX(40vw); }
  42%  { transform: translateX(43vw) scale(1.06); }
  66%  { transform: translateX(43vw) scale(1.06); }
  100% { transform: translateX(115vw); }
}

/* whole-body trot bob */
.critter-animal { animation: critter-bob 0.42s ease-in-out infinite; }
@keyframes critter-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-5px); }
}

/* legs swing in a diagonal gait */
.dog-side .leg { transform-box: fill-box; transform-origin: top center; }
.dog-side .leg--a { animation: trot 0.42s ease-in-out infinite; }
.dog-side .leg--b { animation: trot 0.42s ease-in-out infinite; animation-delay: 0.21s; }
@keyframes trot {
  0%, 100% { transform: rotate(18deg); }
  50% { transform: rotate(-18deg); }
}

/* happy tail wag + floppy ear */
.dog-side .tail { transform-box: fill-box; transform-origin: 100% 60%; animation: wag 0.28s ease-in-out infinite; }
@keyframes wag { 0%, 100% { transform: rotate(-12deg); } 50% { transform: rotate(16deg); } }
.dog-side .ear { transform-box: fill-box; transform-origin: top center; animation: flop 0.42s ease-in-out infinite; }
@keyframes flop { 0%, 100% { transform: rotate(-24deg); } 50% { transform: rotate(-14deg); } }

/* the lick: tongue pops out a few times during the pause */
.dog-side .lick {
  transform-box: fill-box;
  transform-origin: top center;
  transform: scaleY(0);
  animation: lick 0.45s ease-in-out 2s 3 both;
}
@keyframes lick { 0%, 100% { transform: scaleY(0); } 55% { transform: scaleY(1); } }

/* ---------- Cat corner peek (on a logged Hit, cat theme) ---------- */
.cat-peek {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: min(96vw, 480px); /* spans the page width; half pops up from the bottom */
  transform: translateX(-50%) translateY(100%);
  animation: peek-inout 2.8s ease both;
}
@media (min-width: 720px) { .cat-peek { width: 480px; } }
.cat-peek svg, .cat-peek__img { width: 100%; height: auto; display: block; }
/* round the top so a rectangular photo reads as a peeking head */
.cat-peek--photo { overflow: hidden; border-radius: 16px 16px 0 0; box-shadow: 0 -4px 16px rgba(0,0,0,0.25); }
/* the open frame is in normal flow (gives the box its height); the closed
   blink frame overlays it */
.cat-peek__img--closed { position: absolute; top: 0; left: 0; }
@keyframes peek-inout {
  0%   { transform: translateX(-50%) translateY(100%); }
  16%  { transform: translateX(-50%) translateY(46%); }
  82%  { transform: translateX(-50%) translateY(46%); }
  100% { transform: translateX(-50%) translateY(104%); }
}
/* Dog peek — same bottom-center head-pop as the cat, with dog art */
.dog-peek {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: min(96vw, 480px);
  transform: translateX(-50%) translateY(100%);
  animation: peek-inout 2.8s ease both;
}
@media (min-width: 720px) { .dog-peek { width: 480px; } }
.dog-peek svg, .dog-peek__img { width: 100%; height: auto; display: block; }
.dog-peek--photo { overflow: hidden; border-radius: 16px 16px 0 0; box-shadow: 0 -4px 16px rgba(0,0,0,0.25); }
.dog-peek__img--closed { position: absolute; top: 0; left: 0; }

/* Shark peek — same bottom-center head-pop as the cat/dog, with shark art */
.shark-peek,
.dino-peek {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: min(96vw, 480px);
  transform: translateX(-50%) translateY(100%);
  animation: peek-inout 2.8s ease both;
}
@media (min-width: 720px) { .shark-peek, .dino-peek { width: 480px; } }
.shark-peek svg, .shark-peek__img,
.dino-peek svg, .dino-peek__img { width: 100%; height: auto; display: block; }
.shark-peek--photo,
.dino-peek--photo { overflow: hidden; border-radius: 16px 16px 0 0; box-shadow: 0 -4px 16px rgba(0,0,0,0.25); }
.shark-peek__img--closed,
.dino-peek__img--closed { position: absolute; top: 0; left: 0; }

/* blink — SVG eyes squash shut twice during the peek */
.cat-peek--svg .eye,
.dog-peek--svg .eye,
.shark-peek--svg .eye,
.dino-peek--svg .eye {
  transform-box: fill-box;
  transform-origin: center;
  animation: peek-blink 0.42s ease 1.2s 2 both;
}
.dog-peek__img--closed {
  opacity: 0;
  animation: peek-blink-fade 0.42s ease 1.2s 2 both;
}
@keyframes peek-blink {
  0%, 100% { transform: scaleY(1); }
  50% { transform: scaleY(0.08); }
}
/* blink — photo cross-fades to the eyes-closed frame (if provided) */
.cat-peek__img--closed,
.shark-peek__img--closed,
.dino-peek__img--closed {
  opacity: 0;
  animation: peek-blink-fade 0.42s ease 1.2s 2 both;
}
@keyframes peek-blink-fade {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

/* ---------- Cat "licks its paw" PR celebration (reuses .face-lick shell) ---------- */
.cat-pr__cat {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 220px;
  margin: -132px 0 0 -110px; /* viewBox is 100×120 → height 264 */
  transform-origin: center center;
  animation: cat-approach 4s cubic-bezier(0.3, 0.7, 0.3, 1) both;
}
.cat-pr__cat svg { width: 100%; height: auto; display: block; }
@keyframes cat-approach {
  0%   { transform: translateY(60vh) scale(0.14); opacity: 0; }
  12%  { opacity: 1; }
  40%  { transform: translateY(4vh) scale(1.5); opacity: 1; }
  50%  { transform: translateY(-2vh) scale(2.05); }
  74%  { transform: translateY(-2vh) scale(2.05); }  /* hold while it grooms */
  100% { transform: translateY(60vh) scale(0.2); opacity: 0; }
}
/* the paw rises to the face and bobs as it's licked */
.cat-pr__cat .paw {
  transform-box: fill-box;
  transform-origin: center bottom;
  transform: translateY(40px);
  animation: paw-raise 4s ease both;
}
@keyframes paw-raise {
  0%, 42%   { transform: translateY(40px); }
  50%       { transform: translateY(0); }
  56%       { transform: translateY(-3px); }
  62%       { transform: translateY(2px); }
  68%       { transform: translateY(-3px); }
  74%       { transform: translateY(0); }
  84%, 100% { transform: translateY(40px); }
}
/* tongue flicks against the paw a few times */
.cat-pr__cat .tongue {
  transform-box: fill-box;
  transform-origin: top center;
  transform: scaleY(0);
  animation: cat-tongue 0.36s ease 2.2s 3 both;
}
@keyframes cat-tongue {
  0%, 100% { transform: scaleY(0); }
  55% { transform: scaleY(1); }
}
/* a content slow-blink as it settles in */
.cat-pr__cat .eye {
  transform-box: fill-box;
  transform-origin: center;
  animation: slow-blink 1s ease 1.6s 1 both;
}
@keyframes slow-blink {
  0%, 100% { transform: scaleY(1); }
  45%, 55% { transform: scaleY(0.1); }
}

/* ---------- Dog "lick the camera" PR celebration ---------- */
.face-lick {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 12vh;
  overflow: hidden;
  background: rgba(20, 10, 4, 0);
  animation: facelick-bg 0.5s ease 0.2s forwards;
}
@keyframes facelick-bg { to { background: rgba(20, 10, 4, 0.5); } }

.face-lick__dog {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 240px;
  margin: -120px 0 0 -120px;
  transform-origin: center center;
  animation: facelick-approach 3.4s cubic-bezier(0.3, 0.7, 0.3, 1) both;
}
.face-lick__dog svg { width: 100%; height: auto; display: block; }
@keyframes facelick-approach {
  0%   { transform: translateY(62vh) scale(0.14); opacity: 0; }
  14%  { opacity: 1; }
  46%  { transform: translateY(4vh) scale(1.55); opacity: 1; }
  58%  { transform: translateY(-1vh) scale(2.25); opacity: 1; }
  72%  { transform: translateY(4vh) scale(1.5); opacity: 1; }
  100% { transform: translateY(62vh) scale(0.2); opacity: 0; }
}

.face-lick__tongue {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 210px;
  transform: translateX(-50%) translateY(62vh) scaleY(0.3);
  opacity: 0;
  animation: facelick-tongue 3.4s ease-in-out both;
}
.face-lick__tongue svg { width: 100%; height: auto; display: block; }
@keyframes facelick-tongue {
  0%, 48% { transform: translateX(-50%) translateY(62vh) scaleY(0.3); opacity: 0; }
  56%     { transform: translateX(-50%) translateY(0) scaleY(1.15); opacity: 0.97; }
  67%     { transform: translateX(-50%) translateY(-44vh) scaleY(0.85); opacity: 0; }
  100%    { opacity: 0; }
}

.face-lick__smear {
  position: absolute;
  inset: 0;
  opacity: 0;
  background:
    radial-gradient(ellipse 70% 46% at 50% 42%, rgba(214, 238, 255, 0.6), rgba(214, 238, 255, 0.12) 60%, transparent 74%),
    linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, 0.2) 49%, transparent 57%);
  animation: facelick-smear 3.4s ease both;
}
@keyframes facelick-smear {
  0%, 52% { opacity: 0; }
  60%     { opacity: 1; }
  74%     { opacity: 0.85; }
  100%    { opacity: 0; }
}

.face-lick__card {
  position: relative;
  z-index: 2;
  text-align: center;
  color: #fff;
  max-width: 320px;
  padding: 16px;
  opacity: 0;
  animation: facelick-card 0.5s ease 2.7s both;
}
.face-lick__card .celebrate__msg {
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0 0 14px;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
}
@keyframes facelick-card {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* ---------- Shark "takes a bite" PR celebration (reuses .face-lick shell) ---------- */
/* deep-water tint instead of the dog's warm one */
.shark-pr { background: rgba(6, 20, 45, 0); animation: sharkpr-bg 0.5s ease 0.2s forwards; }
@keyframes sharkpr-bg { to { background: rgba(6, 20, 45, 0.58); } }

.shark-pr__shark {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 260px;
  margin: -130px 0 0 -130px; /* viewBox 120×120 */
  transform-origin: center center;
  animation: shark-approach 3.4s cubic-bezier(0.3, 0.7, 0.3, 1) both;
}
.shark-pr__shark svg { width: 100%; height: auto; display: block; }
@keyframes shark-approach {
  0%   { transform: translateY(62vh) scale(0.14); opacity: 0; }
  14%  { opacity: 1; }
  46%  { transform: translateY(4vh) scale(1.55); opacity: 1; }
  56%  { transform: translateY(-1vh) scale(2.2); opacity: 1; }
  70%  { transform: translateY(4vh) scale(1.5); opacity: 1; }
  100% { transform: translateY(62vh) scale(0.2); opacity: 0; }
}

/* a content slow-blink as it lunges */
.shark-pr__shark .eye {
  transform-box: fill-box;
  transform-origin: center;
  animation: slow-blink 1s ease 1.6s 1 both;
}

/* teeth marks flash across the screen at the bite */
.shark-pr__bite {
  position: absolute;
  left: 50%;
  top: 42%;
  width: min(70vw, 420px);
  transform: translate(-50%, -50%) scale(0.5);
  opacity: 0;
  animation: shark-bitemark 3.4s ease both;
}
.shark-pr__bite svg { width: 100%; height: auto; display: block; }
@keyframes shark-bitemark {
  0%, 46% { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
  52%     { opacity: 0.95; transform: translate(-50%, -50%) scale(1.06); }
  62%     { opacity: 0.8; transform: translate(-50%, -50%) scale(1); }
  74%     { opacity: 0; transform: translate(-50%, -50%) scale(1.12); }
  100%    { opacity: 0; }
}

/* ---------- Dino "claws the screen" PR celebration (reuses .face-lick shell) ---------- */
/* jungle tint instead of the shark's deep-water one */
.dino-pr { background: rgba(8, 30, 18, 0); animation: dinopr-bg 0.5s ease 0.2s forwards; }
@keyframes dinopr-bg { to { background: rgba(8, 30, 18, 0.58); } }

.dino-pr__rex {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 260px;
  margin: -130px 0 0 -130px; /* viewBox 120×120 */
  transform-origin: center center;
  animation: dino-approach 3.4s cubic-bezier(0.3, 0.7, 0.3, 1) both;
}
.dino-pr__rex svg { width: 100%; height: auto; display: block; }
@keyframes dino-approach {
  0%   { transform: translateY(62vh) scale(0.14); opacity: 0; }
  14%  { opacity: 1; }
  46%  { transform: translateY(4vh) scale(1.55); opacity: 1; }
  56%  { transform: translateY(-1vh) scale(2.2); opacity: 1; }
  70%  { transform: translateY(4vh) scale(1.5); opacity: 1; }
  100% { transform: translateY(62vh) scale(0.2); opacity: 0; }
}

/* a content slow-blink as it lunges */
.dino-pr__rex .eye {
  transform-box: fill-box;
  transform-origin: center;
  animation: slow-blink 1s ease 1.6s 1 both;
}

/* claw marks rake diagonally across the screen at the peak of the lunge */
.dino-pr__claw {
  position: absolute;
  left: 50%;
  top: 46%;
  width: min(86vw, 520px);
  height: min(58vh, 360px);
  transform: translate(-50%, -50%) rotate(-4deg);
  opacity: 0;
  animation: dino-clawshow 3.4s ease both;
}
.dino-pr__claw svg { width: 100%; height: 100%; display: block; }
.dino-pr__claw .claw {
  stroke-dasharray: 360;
  stroke-dashoffset: 360;
  filter: drop-shadow(0 0 3px rgba(0,0,0,0.35));
  animation: claw-scratch 0.5s ease both;
}
.dino-pr__claw .claw:nth-child(1) { animation-delay: 1.62s; }
.dino-pr__claw .claw:nth-child(2) { animation-delay: 1.70s; }
.dino-pr__claw .claw:nth-child(3) { animation-delay: 1.78s; }
@keyframes claw-scratch {
  to { stroke-dashoffset: 0; }
}
@keyframes dino-clawshow {
  0%, 44% { opacity: 0; }
  48%     { opacity: 1; }
  72%     { opacity: 1; }
  90%     { opacity: 0; }
  100%    { opacity: 0; }
}

/* a little slobber it leaves behind, which fades after a couple seconds */
.critter__slobber {
  position: absolute;
  bottom: 104px;
  left: calc(43vw + 86px);
  width: 40px;
  opacity: 0;
  transform: scale(0.3);
  animation: slobber 3.2s ease 2.4s forwards;
}
@media (min-width: 720px) { .critter__slobber { bottom: 52px; left: calc(43vw + 104px); } }
.critter__slobber svg { width: 100%; height: auto; display: block; }
@keyframes slobber {
  0%   { opacity: 0; transform: scale(0.3) translateY(-8px); }
  14%  { opacity: 1; transform: scale(1) translateY(0); }
  68%  { opacity: 0.95; }
  100% { opacity: 0; transform: scale(1); }
}
.celebrate__confetti span {
  position: absolute;
  top: -6%;
  left: calc(6% + var(--i) * 9%);
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--accent);
  animation: confetti-fall 1.5s ease-in calc(var(--i) * 0.07s) infinite;
}
.celebrate__confetti span:nth-child(3n) { background: #ffd166; }
.celebrate__confetti span:nth-child(3n+1) { background: #ff7a4d; }
.celebrate__confetti span:nth-child(3n+2) { background: #06d6a0; }
@keyframes confetti-fall {
  0% { transform: translateY(0) rotate(0); opacity: 1; }
  100% { transform: translateY(300px) rotate(420deg); opacity: 0; }
}

/* Theme picker (Profile) */
.theme-picker { display: flex; gap: 12px; flex-wrap: wrap; }
.theme-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-start;
  width: 168px;
  min-height: 122px;
  padding: 12px;
  text-align: left;
  cursor: pointer;
  background: var(--panel-2);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
}
.theme-card:hover { border-color: var(--accent-dark); }
.theme-card.is-active { border-color: var(--accent); }
/* "Dark Mode" (default) has no [data-theme="default"] block — it lives on :root —
   so its preview card used to inherit the *active* theme's colors and shift around.
   Pin it to a stable dark preview (near-black surface, light text) so it always
   reads as dark, mirroring the white Light Mode card. */
.theme-card[data-theme="default"] {
  --panel-2: #0e1311;
  --text: #e9edea;
  --muted: #93a39a;
  --border: #2a352f;
}
.theme-card__swatch { font-size: 1.8rem; }
.theme-card__label { font-weight: 700; }
.theme-card__blurb { font-size: 0.8rem; color: var(--muted); }

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  line-height: 1.45;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------- Top bar ---------- */
.topbar {
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar__inner {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  flex-wrap: wrap;
}
.brand { font-weight: 700; font-size: 1.1rem; color: var(--text); }
/* Segmented My-training / Coaching toggle (each side is a button_to form). */
.view-toggle {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  padding: 2px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.view-toggle form.button_to { display: inline-flex; margin: 0; }
.view-toggle__opt {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 999px;
  white-space: nowrap;
  cursor: pointer;
}
.view-toggle__opt:hover { color: var(--text); }
.view-toggle__opt.is-active,
.view-toggle__opt.is-active:hover { background: var(--accent); color: #fff; }
.brand:hover { text-decoration: none; }
.topnav { display: flex; gap: 6px; }
.navlink {
  padding: 6px 12px;
  border-radius: 8px;
  color: var(--muted);
}
.navlink:hover { background: var(--panel-2); color: var(--text); text-decoration: none; }

.unit-toggle {
  margin-left: auto;
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.unit-toggle__btn {
  background: var(--panel-2);
  color: var(--muted);
  border: 0;
  padding: 6px 14px;
  cursor: pointer;
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.78rem;
}
.unit-toggle__btn.is-active { background: var(--accent); color: white; }

/* Per-workout unit selector (header dropdown — one unit for the whole workout) */
.unit-select-form { display: inline-flex; margin: 0; }
.unit-select {
  height: 31px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  border-radius: 8px;
  padding: 0 8px;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
}

/* ---------- Layout ---------- */
.container { max-width: 1280px; margin: 0 auto; padding: 24px 24px 80px; }
/* Room for the fixed bottom tab bar on mobile only. */
.container.has-tabbar { padding-bottom: 96px; }
@media (min-width: 720px) {
  .container.has-tabbar { padding-bottom: 80px; }
}
/* Use more of the screen width on phones. */
@media (max-width: 720px) {
  .container { padding-left: 12px; padding-right: 12px; }
  .card { padding: 14px; }
  /* iOS auto-zooms the page when a focused input is under 16px — keep fields
     at 16px on mobile so login/logging never triggers the zoom. */
  input[type="text"], input[type="number"], input[type="email"], input[type="tel"],
  input[type="password"], input[type="search"], input[type="date"], input[type="time"],
  textarea, select { font-size: 16px; }
}

/* ---------- App nav ----------
   Mobile-first: a fixed bottom tab bar. On wider screens it becomes a
   horizontal top nav inside the header (see media query below). */
.tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  background: var(--panel);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom, 0);
  z-index: 20;
}
.tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 10px 4px;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 600;
}
.tab:hover { text-decoration: none; color: var(--text); }
.tab.is-active { color: var(--accent); }
.tab__icon { font-size: 1.25rem; line-height: 1; position: relative; display: inline-block; }
.tab__label { letter-spacing: 0.02em; }
.tab__badge {
  position: absolute;
  top: -7px;
  right: -11px;
  background: var(--danger);
  color: #fff;
  font-size: 0.6rem;
  font-weight: 700;
  min-width: 16px;
  height: 16px;
  line-height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  text-align: center;
}
/* Inline unread count (e.g. next to "Messages" on the Profile page) */
.count-pill {
  display: inline-block;
  background: var(--danger);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  line-height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  text-align: center;
  vertical-align: middle;
  margin-left: 6px;
}

/* Desktop / tablet: top navigation in the header instead of a bottom bar. */
@media (min-width: 720px) {
  .tabbar {
    position: static;
    margin-left: auto;
    width: auto;
    background: transparent;
    border-top: 0;
    padding-bottom: 0;
    gap: 4px;
  }
  .tab {
    flex: 0 0 auto;
    flex-direction: row;
    gap: 6px;
    padding: 8px 12px;
    border-radius: 8px;
    font-size: 0.92rem;
  }
  .tab__icon { font-size: 1rem; }
  .tab:hover { background: var(--panel-2); }
  .tab.is-active { background: var(--panel-2); }

  /* Dog's top bar is a saturated sky-blue, so the header tabs need light
     text/contrast (the mobile bottom bar above stays dark-on-white). */
  [data-theme="dog"] .tab { color: #eaf4fd; }
  [data-theme="dog"] .tab:hover { background: rgba(255, 255, 255, 0.18); color: #fff; }
  [data-theme="dog"] .tab.is-active { background: rgba(255, 255, 255, 0.22); color: #fff; }
}

/* ---------- Stats ---------- */
.stat-row { display: flex; gap: 16px; flex-wrap: wrap; }
.stat {
  flex: 1;
  min-width: 120px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  text-align: center;
}
.chart { width: 100%; height: auto; display: block; }
.chart-axis { font-size: 12px; fill: var(--muted); }

.stat__num { font-size: 1.8rem; font-weight: 700; color: var(--accent); }
.stat__label { color: var(--muted); font-size: 0.82rem; margin-top: 4px; }

.pr-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.pr-row:last-child { border-bottom: 0; }
.pr-rep {
  display: inline-block;
  min-width: 44px;
  font-weight: 700;
  color: var(--accent);
}
/* PR list (compact, scrollable so it doesn't eat the page on mobile) */
.pr-list {
  max-height: 340px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 10px;
}
/* Headline 1RM (actual or estimated) on a lift's progress page */
.pr-headline { display: flex; flex-direction: column; gap: 2px; }
.pr-headline__val { font-size: 1.9rem; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.pr-headline__lbl { font-size: 0.82rem; color: var(--muted); }

/* Key under the PR list */
.pr-key { display: flex; align-items: center; gap: 6px; margin: 12px 0 0; padding-top: 10px;
  border-top: 1px solid var(--border); font-size: 0.78rem; color: var(--muted); }

/* "est" badge on an estimated 1RM (PR list) */
.pr-est-tag {
  display: inline-block; font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 5px; padding: 0 5px; vertical-align: 1px;
}
.pr-list__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
.pr-list__row:last-child { border-bottom: 0; }
.pr-list__row:hover { background: var(--panel-2); text-decoration: none; }
.pr-list__row[hidden] { display: none; }
.pr-list__name { font-weight: 600; }
.pr-list__pr { color: var(--accent); font-weight: 600; font-size: 0.9rem; text-align: right; white-space: nowrap; }

.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.page-head h1 { margin: 0; font-size: 1.5rem; }
.subtle { color: var(--muted); }

.flash {
  padding: 10px 14px;
  border-radius: 8px;
  margin-bottom: 16px;
  font-size: 0.92rem;
}
.celebrate {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  color: var(--text);
  text-align: center;
  max-width: 360px;
  padding: 28px 24px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.celebrate::backdrop { background: rgba(0,0,0,0.6); }
.celebrate__art { font-size: 3rem; line-height: 1; margin-bottom: 8px; }
.celebrate__msg { font-size: 1.05rem; font-weight: 600; margin: 0 0 18px; }

.flash--notice { background: rgba(52,199,89,0.12); border: 1px solid rgba(52,199,89,0.4); }
.flash--alert { background: rgba(255,77,79,0.12); border: 1px solid rgba(255,77,79,0.4); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--accent);
  color: white;
  border: 1px solid transparent; /* match ghost/danger box so sizes line up */
  border-radius: 8px;
  padding: 8px 14px;
  font-family: inherit; /* <button> doesn't inherit the page font by default */
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.2;     /* equalize <a> vs <button> height */
  box-sizing: border-box;
  cursor: pointer;
}
.btn:hover { background: var(--accent-dark); text-decoration: none; }
.btn--ghost { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); }
.btn--ghost:hover { background: var(--border); }
.btn--danger { background: transparent; color: var(--danger); border: 1px solid transparent; padding: 4px 8px; }
.btn--danger:hover { background: rgba(255,77,79,0.12); }
.btn--sm { padding: 5px 10px; font-size: 0.82rem; }
.btn.is-disabled { opacity: 0.4; pointer-events: none; cursor: default; }
/* Prev/next switcher between a day's workouts (athlete header) */
/* Prev/next workout switcher on the workout page — a two-button bar that shows
   the name of the workout you'd move to, so it's clear what the arrows do. */
.workout-switch { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.workout-switch__btn {
  display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; max-width: 50%;
  border: 1px solid var(--border); border-radius: 10px; padding: 8px 12px;
  color: var(--text); text-decoration: none;
}
.workout-switch__btn:hover { border-color: var(--accent); text-decoration: none; }
.workout-switch__btn--next { justify-content: flex-end; }
.workout-switch__btn.is-disabled { opacity: 0.35; }
/* Nothing before/after: keep the slot for balance, but show nothing. */
.workout-switch__btn--empty { border-color: transparent; opacity: 0; pointer-events: none; }
.workout-switch__arrow { font-size: 1.5rem; line-height: 1; color: var(--muted); flex: none; }
.workout-switch__meta { display: flex; flex-direction: column; min-width: 0; }
.workout-switch__meta--next { align-items: flex-end; text-align: right; }
.workout-switch__label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.workout-switch__name { font-weight: 600; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.btn--alt { background: #3b82f6; color: #fff; }
.btn--alt:hover { background: #2563eb; }
.editor-add-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 12px; }
.editor-add-row .button_to { margin: 0; }

/* ---------- Calendar (month) ---------- */
.cal-nav { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.week-nav { display: inline-flex; gap: 6px; margin-left: auto; }

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}
.cal-dow {
  text-align: center;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  padding: 4px 0;
}
.cal-cell {
  min-height: 84px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--text);
}
.cal-cell:hover { border-color: var(--accent); text-decoration: none; }
.cal-cell--outside { opacity: 0.4; }
.cal-cell--today { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.cal-cell__num { font-weight: 600; font-size: 0.9rem; }
.cal-badge {
  align-self: flex-start;
  margin-top: auto;
  background: var(--accent);
  color: white;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-badge--prog { background: transparent; color: var(--accent); border: 1px solid var(--accent); }

/* Inline link-style buttons (e.g. "swap" / "undo" on programmed days) */
.linkbtn {
  border: 0;
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0 2px;
}
.linkbtn:hover { text-decoration: underline; }
.swap-form { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }

/* Superset "link to the one above" toggle (coach program editor) */
.superset-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 12px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
.superset-toggle input { width: 16px; height: 16px; accent-color: var(--accent); }

/* Video comments */
.vc { padding: 8px 0; border-bottom: 1px solid var(--border); }
.vc:last-of-type { border-bottom: 0; }
.vc__head { display: flex; gap: 8px; align-items: baseline; }
.vc__body { margin: 2px 0 0; }
.vc__body p { margin: 0; }

.cal-workout {
  display: block;
  background: var(--accent);
  color: #fff;
  border-radius: 6px;
  padding: 3px 6px;
  margin-top: 4px;
  font-size: 0.74rem;
  font-weight: 600;
}
.cal-workout:hover { background: var(--accent-dark); text-decoration: none; }
.cal-workout .subtle { color: rgba(255,255,255,0.8); font-weight: 400; }
.cal-workout--draft { background: transparent; color: var(--accent); border: 1px dashed var(--accent); }
.cal-workout--draft:hover { background: var(--panel-2); }
/* Program-colored chips on a single program's calendar (matches the all-programs
   view). --prog / --prog-text set inline per program. */
.cal-workout--prog { background: var(--prog); color: var(--prog-text); }
.cal-workout--prog:hover { background: var(--prog); filter: brightness(1.1); }
.cal-workout--prog.cal-workout--draft { background: transparent; color: var(--prog); border-color: var(--prog); }
.cal-workout--prog.cal-workout--draft:hover { background: rgba(127, 127, 127, 0.12); filter: none; }
/* Inline swatch in the header legend, mirroring the dashed draft chip. */
.cal-draft-legend { border: 1px dashed var(--accent); border-radius: 4px; padding: 0 5px; color: var(--accent); }
.cal-workout__draft { font-weight: 400; opacity: 0.85; font-size: 0.68rem; }
.cal-add {
  margin-top: auto;
  background: transparent;
  border: 1px dashed var(--border);
  color: var(--muted);
  border-radius: 6px;
  padding: 3px 6px;
  font-size: 0.74rem;
  cursor: pointer;
  width: 100%;
}
.cal-add:hover { border-color: var(--accent); color: var(--accent); }

/* Classes calendar: view toggle, session chips, week list, filter */
.seg { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
/* Full-width segmented tab bar (coach athlete page): tabs spread evenly. */
.athlete-tabs { display: flex; width: 100%; margin-bottom: 16px; }
.athlete-tabs .seg__btn { flex: 1; text-align: center; }
/* Simple data table used in the athlete tabs (check-ins, meets). */
.data-table { width: 100%; border-collapse: collapse; }
.data-table td { padding: 8px 6px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.data-table tr:last-child td { border-bottom: 0; }
.seg__btn { padding: 6px 14px; font-size: 0.85rem; font-weight: 600; color: var(--muted); background: var(--panel-2); }
.seg__btn:hover { text-decoration: none; color: var(--text); }
.seg__btn.is-active { background: var(--accent); color: #fff; }
.seg__btn + .seg__btn { border-left: 1px solid var(--border); }

.class-chip {
  display: block;
  background: var(--accent);
  color: #fff;
  border-radius: 6px;
  padding: 2px 6px;
  margin-top: 3px;
  font-size: 0.72rem;
  line-height: 1.25;
  overflow: hidden;
}
.class-chip:hover { background: var(--accent-dark); text-decoration: none; }
.class-chip--draft { background: transparent; color: var(--accent); border: 1px dashed var(--accent); }
.class-chip--draft:hover { background: var(--panel-2); }
.class-chip__time { font-weight: 700; margin-right: 4px; }
.class-chip__name { opacity: 0.95; font-weight: 600; }
.class-chip__sub { display: block; opacity: 0.85; font-weight: 400; }
/* Program-colored calendar chips (--prog / --prog-text set inline per program,
   from a colorblind-safe palette). */
.class-chip--prog { background: var(--prog); color: var(--prog-text); }
.class-chip--prog:hover { background: var(--prog); filter: brightness(1.12); }
.class-chip--prog.class-chip--draft { background: transparent; color: var(--prog); border-color: var(--prog); }
.class-chip--prog.class-chip--draft:hover { background: rgba(127, 127, 127, 0.12); filter: none; }

/* Mobile (and native app): vertical stack — one row per day, label beside its
   sessions. Too narrow to fit 7 columns across. */
.class-week { display: flex; flex-direction: column; gap: 8px; }
.class-week__day { display: flex; gap: 12px; align-items: flex-start; border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; }
.class-week__label { min-width: 64px; font-weight: 700; color: var(--muted); }
.class-week__sessions { flex: 1; display: flex; flex-wrap: wrap; gap: 6px; }
.class-week .class-chip { display: inline-block; margin-top: 0; }
/* Desktop browser: horizontal 7-day grid, like the program week view — label on
   top, that day's sessions stacked below it. */
@media (min-width: 721px) {
  /* minmax(0, 1fr) forces all 7 columns to be strictly equal width regardless of
     each day's workout-name length — plain 1fr is minmax(auto,1fr), which lets a
     longer name (e.g. "Accessories") widen its own column vs a shorter one. */
  .class-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); align-items: stretch; }
  /* align-items:stretch (vs the base mobile flex-start) makes the day's sessions
     fill the full column width — otherwise, in this flex COLUMN, flex-start shrinks
     sessions to its content so a longer workout name = a wider bubble/Add button. */
  .class-week__day { flex-direction: column; gap: 8px; min-height: 180px; min-width: 0; align-items: stretch; }
  .class-week__label { min-width: 0; }
  .class-week__sessions { flex-direction: column; flex-wrap: nowrap; min-width: 0; }
  .class-week .class-chip { display: block; }
}

/* Programs: left sidebar list + calendar */
.programs-layout { display: flex; gap: 16px; align-items: flex-start; }
.programs-sidebar { width: 250px; flex-shrink: 0; }
.programs-main { flex: 1; min-width: 0; }
.prog-side-list { max-height: 560px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; }
.prog-side-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
.prog-side-row:last-child { border-bottom: 0; }
.prog-side-row:hover { background: var(--panel-2); text-decoration: none; }
.prog-side-row[hidden] { display: none; }
.prog-side-row__name { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Name + a trailing badge (e.g. videos-to-review) that hugs the name. */
.prog-side-row__nameline { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: 6px; }
.prog-side-row__nameline .prog-side-row__name { flex: 0 1 auto; }
.prog-side-row__nameline .unread-badge { margin-left: 0; flex: none; }
/* Keep the "shared" badge fully visible — the name truncates instead of clipping it. */
.prog-side-row__badge { flex: none; font-size: 0.66rem; }
/* Color swatch matching the item's calendar chips. */
.prog-side-dot { flex-shrink: 0; width: 11px; height: 11px; border-radius: 50%; }
@media (max-width: 720px) {
  .programs-layout { flex-direction: column; }
  .programs-sidebar { width: 100%; }
  /* align-items: flex-start on the row layout makes stacked children
     shrink-to-fit — stretch the calendar column to match the sidebar. */
  .programs-main { width: 100%; }
}

.dayadd { border: 1px solid var(--accent); border-radius: 8px; padding: 10px 12px; margin-top: 12px; background: var(--panel-2); }

.class-filter { border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; }
.class-filter summary { cursor: pointer; font-weight: 600; font-size: 0.85rem; }
.class-filter__form { display: flex; flex-wrap: wrap; gap: 10px 18px; margin-top: 10px; }
.class-filter__opt { display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; }
.class-filter__opt input { width: 15px; height: 15px; accent-color: var(--accent); }

/* Drag/copy a programmed day to another date */
.cal-workout-row { display: flex; align-items: center; gap: 3px; width: 100%; }
/* One standard chip width — fill the day column like the "+ Add workout" button,
   and truncate long names instead of letting them widen the bubble. */
.cal-workout-row .cal-workout {
  flex: 1 1 0;
  min-width: 0;
  cursor: grab;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-workout-row .cal-workout:active { cursor: grabbing; }
.cal-del-btn {
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.85rem;
  padding: 0 2px;
  line-height: 1;
}
.cal-del-btn:hover { color: var(--danger); }
.cal-workout-row form.button_to { display: inline-flex; margin: 0; }
.cal-cell--drop { border-color: var(--accent) !important; background: var(--panel-2); }

@media (max-width: 720px) { .hide-mobile { display: none !important; } }

/* Week overview (Workouts + Classes) — a day heading above that day's items. */
.week-day { margin-bottom: 18px; }
.week-day__head { font-size: 1rem; margin: 0 0 8px; }
.week-day__head a { color: var(--text); text-decoration: none; }
.week-day__head--today a { color: var(--accent); }
.week-day__rest { margin: 0 0 4px; padding-left: 2px; opacity: 0.6; font-size: 0.9rem; }
/* Track name above that track's workouts within a day (athlete week view). */
.week-track-label { font-size: 0.75rem; font-weight: 700; color: var(--muted); margin: 8px 0 4px; }
.week-track-label--own { font-weight: 600; opacity: 0.85; }
.week-track-label:first-child { margin-top: 0; }
.week-items { display: flex; flex-direction: column; gap: 6px; }
.week-items + .week-track-label { margin-top: 10px; }
.week-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-radius: 10px;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
}
.week-item:hover { border-color: var(--accent); text-decoration: none; }
.week-item__title { font-weight: 600; }
.week-item__meta { font-size: 0.76rem; color: var(--muted); flex: none; }
.week-item--draft { border-style: dashed; }

/* A fieldset used only to disable a block of inputs (read-only shared program) —
   no border/padding of its own; just dims to signal it's not editable. */
.bare-fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.bare-fieldset[disabled] { opacity: 0.85; }

/* Compact "All classes" list — one card, tappable rows with dividers. */
.classlist { padding: 6px 0; }
.classlist__search { margin: 6px 14px 8px; width: calc(100% - 28px); }
.classlist-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px; color: var(--text);
}
.classlist-row + .classlist-row { border-top: 1px solid var(--border); }
.classlist-row:hover { background: var(--panel-2); text-decoration: none; }
.classlist-row__info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.classlist-row__name { font-weight: 600; }
.classlist-row__meta { font-size: 0.78rem; color: var(--muted); }
.classlist-row__chev { color: var(--muted); font-size: 1.3rem; flex: none; }
.classlist__empty { padding: 10px 16px; margin: 0; }
/* Program workout rows / chips span the full day width but keep their natural
   (small) height. flex:none is the key — the day is a flex column, so a growable
   item (flex:1 1 100%) stretches to fill the entire day; flex:none + width:100%
   gives full width without the vertical stretch. */
.class-week .cal-workout-row { flex: none; width: 100%; }
.class-week .class-chip--prog { flex: none; width: 100%; }

/* ---------- Week ---------- */
.week-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 8px;
}
.week-col {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px;
  min-height: 140px;
}
.week-col__head { font-weight: 600; margin-bottom: 8px; display:block; color: var(--text); }
.week-col--today { border-color: var(--accent); }
.week-chip {
  display: block;
  background: var(--panel-2);
  border-radius: 8px;
  padding: 6px 8px;
  margin-bottom: 6px;
  font-size: 0.82rem;
  color: var(--text);
}
.week-chip:hover { background: var(--border); text-decoration: none; }
.week-chip--prog { background: transparent; border: 1px dashed var(--accent); color: var(--accent); }
.week-chip--prog:hover { background: var(--panel-2); }
.week-chip--prog .subtle { color: var(--muted); }

/* ---------- Classes week: horizontal grid on desktop, list on mobile ----------
   Mobile-first: show the agenda list, hide the 7-day grid (it can't fit a phone
   or the native app). Widen to a browser and the grid takes over. */
.classes-weekgrid { display: none; grid-template-columns: repeat(7, 1fr); gap: 8px; }
.classes-weeklist { display: block; }
@media (min-width: 721px) {
  .classes-weekgrid { display: grid; }
  .classes-weeklist { display: none; }
}
.class-cell { background: var(--panel-2); border-radius: 8px; padding: 8px; margin-bottom: 8px; }
.class-cell__name { display: block; font-weight: 600; font-size: 0.85rem; color: var(--text); }
.class-cell__time { display: block; font-size: 0.78rem; margin: 2px 0 6px; }
.class-cell__action { display: flex; flex-direction: column; gap: 4px; }
.class-cell__action form { margin: 0; }
.class-cell__action .btn { width: 100%; }

/* ---------- Cards / panels ---------- */
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 16px;
}
.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.card__title { margin: 0; font-size: 1.05rem; }
.tag {
  font-size: 0.72rem;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 8px;
}
.tag--group { color: var(--accent); border-color: var(--accent); }

/* ---------- Superset / complex grouping ---------- */
.superset {
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 8px;
  margin-bottom: 16px;
  background: rgba(79,140,255,0.06);
}
.superset .card { margin-bottom: 8px; }
.superset .card:last-child { margin-bottom: 0; }
.superset__header {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  color: var(--accent);
  font-size: 0.85rem;
  padding: 2px 6px 8px;
}
.superset__actions { margin-left: auto; }

.card--link { display: block; color: var(--text); }
.card--link:hover { border-color: var(--accent); text-decoration: none; }

/* ---- Reusable week-selector strip (Workouts, Classes) ---- */
.week-strip { margin-bottom: 14px; }
.week-strip__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-bottom: 10px;
}
.week-strip__title {
  font-weight: 700;
  font-size: 1.05rem;
  min-width: 150px;
  text-align: center;
}
.week-strip__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--text);
  text-decoration: none;
  border: 1px solid var(--border);
}
.week-strip__arrow:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
.week-strip__days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.ws-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 5px 0;
  text-decoration: none;
  color: var(--text);
  border-radius: 12px;
}
.ws-day:hover { background: rgba(127,127,127,0.10); text-decoration: none; }
.ws-day__dow {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  opacity: 0.55;
}
.ws-day__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  font-weight: 600;
  font-size: 0.95rem;
}
/* The day being viewed: an accent ring. */
.ws-day.is-selected .ws-day__num {
  box-shadow: inset 0 0 0 2px var(--accent);
  color: var(--accent);
}
/* Today: a solid accent fill (wins over the ring when today is also selected). */
.ws-day.is-today .ws-day__num {
  background: var(--accent);
  color: #07130d;
  box-shadow: none;
}

/* A class session as a tappable box: an overlay link covers the whole card to
   open the session's details, while the register/check-in control sits above it
   (z-index) so it stays independently clickable. */
.session-card { position: relative; }
.session-card:hover { border-color: var(--accent); }
.session-card__link { position: absolute; inset: 0; border-radius: var(--radius); }
.session-card__info { min-width: 0; }
.session-card__actions { position: relative; z-index: 1; flex-wrap: wrap; }

/* Compact bar under the week strip: selected-day label + quick links. */
.daybar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}
.daybar__label { font-weight: 600; }
.daybar__actions { display: flex; gap: 8px; }

/* Track-name header above that track's workouts in the athlete day view. */
.day-track-heading {
  display: flex; align-items: center; gap: 6px;
  font-size: 0.95rem; font-weight: 700;
  margin: 20px 0 8px; padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.day-track-heading:first-of-type { margin-top: 4px; }
.day-track-heading .icon { width: 16px; height: 16px; color: var(--accent); }
.day-track-heading--own { color: var(--muted); font-weight: 600; }

/* A whole card that IS a submit button (e.g. tap a contact to open the chat).
   Strips the native button chrome so it reads as a normal tappable card row. */
.card--btn-form { margin: 0; }
.card--btn {
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.card--program {
  border-color: var(--accent);
  background: linear-gradient(180deg, rgba(79,140,255,0.10), var(--panel));
}
/* Day cards (prescribed + logged) get a theme-colored title so they read as
   tappable and match each other. */
.card--program .card__title,
.card--program .card__title a { color: var(--accent); }

.empty {
  text-align: center;
  color: var(--muted);
  padding: 28px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: 4px; }
label.lbl { font-size: 0.78rem; color: var(--muted); }
/* Type-to-search exercise picker */
.combobox { position: relative; }
.combobox__input { width: 100%; }
.combobox__list {
  position: absolute;
  z-index: 50;
  top: 100%;
  left: 0;
  right: 0;
  margin: 4px 0 0;
  padding: 4px;
  list-style: none;
  max-height: 260px;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
}
.combobox__option {
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.9rem;
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: baseline;
}
.combobox__option:hover { background: var(--panel-2); }
.combobox__option[hidden] { display: none; }

/* Weekday picker (class cadence) */
.day-picker { display: flex; flex-wrap: wrap; gap: 8px; }
.day-option {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.9rem;
  background: var(--panel-2);
}
.day-option:has(input:checked) { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.athlete-checklist {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px;
  background: var(--panel);
}
.athlete-check {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 6px;
  cursor: pointer;
}
.athlete-check:hover { background: var(--panel-2); }
.athlete-check:has(input:checked) { background: var(--panel-2); color: var(--accent); font-weight: 600; }
.athlete-check input[type="checkbox"] { flex: none; }
.schedule-row {
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  margin-bottom: 10px;
  background: var(--panel-2);
}
.audience-panel { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
/* Reveal panel under a class reminder toggle — a clean vertical stack (indented
   to line up under the checkbox), so the hours row, note, and message field
   don't wrap around each other like the flex audience chips do. */
.reminder-panel { display: flex; flex-direction: column; gap: 8px; margin: 8px 0 0 28px; max-width: 460px; }
.reminder-panel__row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.reminder-panel__hint { margin: 0; font-size: 0.78rem; }

/* Collapsible exercise cards (athlete logging view) */
.collapsible__head { cursor: pointer; }
/* A turbo-frame is inline by default, so the workout's exercise cards inside it
   didn't stretch full width like the Cardio card outside it. */
#workout_items { display: block; }
/* Each saved workout note is a turbo-frame styled as a .card; without this the
   inline frame won't wrap the note + Edit/Delete row as a proper card block. */
turbo-frame[id^="workout_note_"] { display: block; }
/* The program calendar (and each inline workout editor) are turbo-frames too —
   left inline, the frame shrink-wraps and the week grid inside sizes its columns
   to each day's content, so a longer workout name widens its own day. Block makes
   the frame full width, so repeat(7, minmax(0,1fr)) yields 7 equal columns. */
turbo-frame#program_calendar,
turbo-frame[id^="editor_programmed_workout_"] { display: block; }
/* Saved notes are short — keep the card compact so it hugs the text. */
.workout-note { padding: 10px 12px; margin-top: 8px; }
.workout-note .card__head { margin-bottom: 2px; }
.workout-note .btn--sm { padding: 3px 8px; }

/* Notes page: search box + filter chips + collapsible per-exercise groups. */
.notes-search {
  width: 100%;
  padding: 10px 12px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--text);
  font-size: 0.95rem;
}
.note-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.note-chip {
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  border-radius: 999px;
  padding: 5px 12px;
  font-size: 0.85rem;
  cursor: pointer;
}
.note-chip.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }
.note-chip__count { opacity: 0.6; margin-left: 2px; font-size: 0.78rem; }

.note-group { margin-bottom: 18px; }
.note-group__head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 2px;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.note-group__name { font-weight: 600; font-size: 1rem; }
.note-group__count {
  font-size: 0.72rem;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 8px;
}
.note-group__chev { margin-left: auto; color: var(--muted); transition: transform 0.15s ease; transform: rotate(90deg); }
.note-group.is-collapsed .note-group__chev { transform: rotate(0deg); }
.note-group__body { margin-top: 10px; }
.note-item { margin-bottom: 10px; padding: 12px; }

/* Per-session substitute panel on the coach's attendance screen. */
.sub-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 14px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-2);
}
.sub-panel .inline-form { margin: 0; flex: 1; }
.sub-assign { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* Keep the two assign forms content-sized and side by side (don't let the
   .sub-panel .inline-form flex:1 above stretch them apart). */
.sub-panel .sub-assign__form { flex: 0 0 auto; gap: 6px; align-items: center; }

/* Coach program calendar laid out as numbered weeks (Week 1, Week 2, …). */
.prog-week { margin-bottom: 18px; }
.prog-week__label { font-weight: 600; font-size: 0.95rem; margin: 0 0 6px; }
.prog-week__label .subtle { font-weight: 400; font-size: 0.82rem; }

/* Wider page for calendar-heavy screens (program editor). */
.container--wide { max-width: 1600px; }
/* Two-column program editor: athletes + sharing left, calendar right.
   row-reverse puts the DOM-second side column on the left, while the mobile
   column stack below keeps the calendar (DOM-first) on top. */
.program-layout { display: flex; gap: 20px; align-items: flex-start; flex-direction: row-reverse; }
.program-layout__main { flex: 1; min-width: 0; }
.program-layout__side { width: 380px; flex-shrink: 0; }
@media (max-width: 900px) {
  .program-layout { flex-direction: column; }
  .program-layout__side { width: 100%; }
}

/* Arrow button in the top bar that collapses/expands the side panels.
   ‹ collapses, › re-opens. Custom tooltip appears instantly on hover. */
.sidebar-toggle {
  position: relative;
  border: 1px solid var(--border); background: var(--panel); color: var(--muted);
  border-radius: 50%; width: 32px; height: 32px; line-height: 1;
  font-size: 1.3rem; cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; padding: 0; flex: none;
}
.sidebar-toggle:hover { color: var(--accent); border-color: var(--accent); }
.sidebar-toggle::after {
  content: attr(data-tip);
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  margin-top: 6px; white-space: nowrap;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border);
  padding: 3px 8px; border-radius: 6px; font-size: 0.75rem; font-weight: 500;
  opacity: 0; pointer-events: none; transition: opacity 0.08s; z-index: 30;
}
.sidebar-toggle:hover::after { opacity: 1; }

/* Expand-in-place editor, rendered inside the day cell. */
@media (min-width: 721px) { .class-week { align-items: start; } }
.cal-workout-item { width: 100%; }
/* While a workout's editor is open, hide its collapsed chip bar — the editor's
   own name field + Save/Delete take over (and it avoids showing the name twice). */
.cal-workout-item:has(.cal-workout-editor:not([hidden])) .cal-workout-row { display: none; }
/* Each expanded workout is its own bordered card, so several workouts in a single
   day read as distinct blocks (the collapsed chip is hidden while editing). */
.cal-workout-editor {
  margin: 10px 0;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  padding: 10px 12px;
  background: var(--panel-2);
}
.cal-workout-editor[hidden] { display: none; }
/* Editor header row: workout name (fills), then the open-in-new-tab + collapse icons. */
.cal-workout-editor__bar { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.cal-workout-editor__bar .prog-editor-nameform { flex: 1; min-width: 0; }
.cal-fullpage-btn {
  color: var(--muted); cursor: pointer;
  padding: 2px; line-height: 0; display: inline-flex; border-radius: 6px;
}
.cal-fullpage-btn .icon { width: 18px; height: 18px; }
.cal-fullpage-btn:hover { color: var(--accent); background: var(--panel); }
.cal-collapse-btn {
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  padding: 2px; line-height: 0; display: inline-flex; border-radius: 6px;
}
.cal-collapse-btn .icon { width: 18px; height: 18px; }
.cal-collapse-btn:hover { color: var(--accent); background: var(--panel); }
/* No per-workout collapse in expand-all — use "Collapse all". */
.is-expanded .cal-collapse-btn { display: none; }
/* "Revert to published" — appears in the editor bar only while the workout is a
   draft with a published baseline. Dashed to echo the draft chip. */
.cal-workout-editor__bar form.button_to { margin: 0; display: inline-flex; }
.cal-workout-editor__bar form.button_to[hidden] { display: none; } /* keep hidden until revealed */
.cal-revert-btn {
  border: 1px dashed var(--accent); background: transparent; color: var(--accent);
  cursor: pointer; white-space: nowrap; border-radius: 999px;
  padding: 2px 9px; font-size: 0.72rem; font-weight: 700; line-height: 1.3;
}
.cal-revert-btn:hover { background: var(--accent); color: var(--panel); }
/* Exercise cards sit on a lighter surface than the editor card that holds them. */
.cal-workout-editor .card { background: var(--panel); }
/* Compact the reused programmed-workout editor whenever it's inlined on the
   calendar — the SAME look in the single-day (✎) view and the expand-all view. */
.cal-workout-editor { font-size: 0.85rem; min-width: 0; }
.cal-workout-editor .card { padding: 9px 11px; margin-bottom: 8px; }
.cal-workout-editor .card__head { margin-bottom: 6px; }
.cal-workout-editor .card__title { font-size: 0.92rem; }
.cal-workout-editor .editor-add-row { flex-wrap: wrap; gap: 6px; }
.cal-workout-editor .btn { font-size: 0.8rem; padding: 5px 9px; }
.cal-workout-editor select, .cal-workout-editor textarea { font-size: 0.82rem; }
.cal-workout-editor .combobox__input,
.cal-workout-editor input,
.cal-workout-editor .field { min-width: 0; max-width: 100%; }
.cal-workout-editor .sets-list { margin-top: 4px; }
/* Coaching-note box shouldn't hog vertical space in the compact editor. */
.cal-workout-editor textarea { min-height: 0; height: 34px; }

/* The inline name field + Save/Delete footer live in the shared editor markup but
   only apply when it's inlined on the calendar (inside .cal-workout-editor) — the
   workout's own page has its own name field and page-head Save/Delete. */
.prog-editor-nameform { display: none; }
.prog-editor-foot { display: none; }
.cal-workout-editor .prog-editor-nameform { display: block; }
.cal-workout-editor .prog-editor-foot { display: flex; gap: 8px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border); }
.prog-editor-name { width: 100%; font-weight: 700; font-size: 0.95rem; margin: 0; }
.prog-editor-foot form.button_to { margin: 0; }

/* One-line set rows — chip · reps · weight · (%1RM|RPE) · ± — instead of
   wrapping onto 3–4 lines. `display:contents` on the inner form lets its
   fields become grid cells of the row. */
.cal-workout-editor .set-row {
  display: grid;
  grid-template-columns: auto 1fr 1.3fr 1.2fr auto;
  align-items: end;
  gap: 2px 5px;
  padding: 6px 0;
}
.cal-workout-editor .set-edit { display: contents; }
.cal-workout-editor .set-field { gap: 1px; min-width: 0; }
.cal-workout-editor .set-field .lbl { font-size: 0.58rem; line-height: 1.1; color: var(--muted); }
.cal-workout-editor .set-field input[type="number"] { width: 100%; font-size: 0.82rem; padding: 5px 6px; }
.cal-workout-editor .set-weight { display: flex; width: 100%; }
.cal-workout-editor .set-weight input[type="number"] { padding-right: 20px; }
.cal-workout-editor .set-weight__unit { right: 4px; font-size: 0.62rem; }
.cal-workout-editor .set-chip { align-self: end; font-size: 0.62rem; padding: 3px 5px; }
.cal-workout-editor .set-rowbtns { gap: 3px; }
.cal-workout-editor .set-rowbtn { width: 22px; height: 22px; font-size: 0.95rem; }

/* %1RM ⇄ RPE toggle sharing one set column. */
.set-intensity__toggle {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  color: var(--accent); display: inline-flex; align-items: center; gap: 2px; white-space: nowrap;
}
.set-intensity__toggle:hover { text-decoration: underline; }
.set-intensity [data-intensity-target="pct"],
.set-intensity [data-intensity-target="rpe"] { display: block; }
.set-intensity [data-intensity-target][hidden] { display: none; }

/* Hide number-input spin buttons app-wide — reps/weight/%/RPE don't benefit from
   them and they clutter the compact rows. */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

.prog-addweek { margin-top: 6px; }

/* Whenever a day is being edited — a single ✎ open OR expand-all — the week
   turns into one horizontally-scrolling row so nothing wraps onto a second line.
   The edited day(s) get room for the mini editor; the rest stay compact. A
   matching top scrollbar is added by the hscroll controller when it overflows. */
@media (min-width: 721px) {
  .class-week:has(.class-week__day--editing) {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    align-items: flex-start;
    gap: 8px;
    padding-bottom: 8px;
  }
  /* Non-editing days grow to share the row evenly (like the normal grid) and
     only hold a floor once the week actually overflows into a horizontal scroll —
     so a single edited day doesn't shrink all its neighbours. */
  .class-week:has(.class-week__day--editing) .class-week__day {
    flex: 1 0 175px;
    min-width: 0;
    /* keep the normal 180px min-height so non-editing days stay a uniform size;
       the edited day just grows past it to fit its editor. */
  }
  .class-week:has(.class-week__day--editing) .class-week__day--editing {
    flex: 0 0 340px;
  }
}

/* Themed scrollbars — replace the default grey OS scrollbars app-wide so they
   match the current theme (thin, rounded, border-colored, accent on hover). */
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
::-webkit-scrollbar { height: 10px; width: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); background-clip: padding-box; }

/* Mirror horizontal scrollbar shown at the TOP of each week when expanded. */
.hscroll__top { overflow-x: auto; overflow-y: hidden; margin-bottom: 6px; }
.hscroll__top[hidden] { display: none; }
.hscroll__spacer { height: 1px; }

/* Programs index — card grid of all programs. */
.prog-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.prog-card {
  border: 1px solid var(--border); border-left: 4px solid var(--prog);
  border-radius: 12px; background: var(--panel);
  display: flex; flex-direction: column; overflow: hidden;
}
.prog-card__body { display: block; padding: 16px; text-decoration: none; color: inherit; flex: 1; }
.prog-card__body:hover { background: var(--panel-2); }
.prog-card__head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.prog-card__name { font-size: 1.05rem; margin: 0; }
.prog-card__desc { margin: 0 0 8px; color: var(--muted); font-size: 0.88rem; }
.prog-card__stats { display: flex; flex-wrap: wrap; gap: 6px; font-size: 0.85rem; color: var(--muted); margin-bottom: 8px; }
.prog-card__foot { font-size: 0.8rem; }
.prog-card__actions {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 16px;
  border-top: 1px solid var(--border);
}
.prog-card__actions form.button_to { margin: 0; }
.athlete-track-row { padding: 8px 0; border-bottom: 1px solid var(--border); }
.athlete-track-row__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.athlete-track-row__name { font-weight: 600; }
.roster-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border); }
/* The search filter toggles [hidden]; override the flex display so it hides. */
.roster-row[hidden] { display: none; }
.roster-row__check { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.roster-row__check input { width: 18px; height: 18px; }
/* Collapsed exercise cards read on one compact line (see .we-title nowrap), so
   drop the head's gap-to-body when there's no body showing. */
.card:not(.is-open) .collapsible__head { margin-bottom: 0; }
.collapsible__chevron {
  display: inline-block;
  color: var(--muted);
  font-size: 0.85em;
  transition: transform 0.15s ease;
}
.card.is-open .collapsible__chevron { transform: rotate(90deg); }
.collapsible__summary { font-size: 0.9rem; }
.card.is-open .collapsible__summary { display: none; }
/* Workout-exercise heading: lay the name, icons, superset tag and summary out
   in a wrapping row so nothing (e.g. the 🔗 Superset pill) gets clipped. */
/* Show the full exercise name; let the sets/reps/RPE summary wrap to a second
   line when it doesn't fit rather than truncating the name. A tight row-gap keeps
   the wrapped (two-line) box from getting too tall. */
.we-title { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; line-height: 1.25; }
.we-title__name { font-weight: 600; font-size: 1.15rem; }
/* Every workout/cardio card head (exercise or cardio — both hold a .we-title) is
   the same height, sized for the two-line case, so single-line boxes match the
   wrapped ones instead of being shorter. */
.card__head:has(.we-title) { min-height: 42px; }
/* Reorder arrows + delete live together on the far right of the card head. */
.we-actions { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* A whole card that acts as a link (e.g. tap a program card to start logging) */
.card.is-clickable { cursor: pointer; transition: border-color 0.12s ease, transform 0.12s ease; }
.card.is-clickable:hover { border-color: var(--accent); }
.card.is-clickable:active { transform: scale(0.995); }
/* The timer is only useful while logging — hide it on a collapsed card. */
.card:not(.is-open) .timer-btn { display: none; }
.collapsible__body { display: none; }
.card.is-open .collapsible__body { display: block; margin-top: 12px; }

/* Inline form validation errors (shown at the form, not as a top flash) */
.form-errors {
  background: rgba(255, 90, 90, 0.12);
  border: 1px solid var(--danger);
  color: var(--danger);
  border-radius: 8px;
  padding: 8px 12px;
  margin-bottom: 12px;
  font-size: 0.88rem;
  font-weight: 600;
}
.combobox__cat { color: var(--muted); font-size: 0.72rem; white-space: nowrap; }
.combobox__empty { padding: 8px 10px; color: var(--muted); font-size: 0.85rem; }

input[type="text"], input[type="number"], input[type="email"], input[type="tel"],
input[type="password"], input[type="search"], input[type="date"], input[type="time"],
textarea, select {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: 8px 10px;
  font-size: 0.9rem;
  font-family: inherit;
}
input:focus, textarea:focus, select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

/* Notification preferences matrix (type x channel) */
.notif-grid { width: 100%; border-collapse: collapse; }
.notif-grid th { font-size: 0.78rem; color: var(--muted); font-weight: 600; text-align: center; padding: 4px 6px; }
.notif-grid th:first-child { text-align: left; }
.notif-grid td { padding: 8px 6px; border-top: 1px solid var(--border); font-size: 0.9rem; }
.notif-grid__cell { text-align: center; width: 64px; }
.notif-grid__cat td { border-top: none; padding: 12px 0 2px; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.notif-grid input[type="checkbox"] { width: 18px; height: 18px; cursor: pointer; }
textarea { resize: vertical; min-height: 60px; }

.inline-form { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }

/* ---------- Sets table ---------- */
.sets-table { width: 100%; border-collapse: collapse; margin-top: 4px; }
.sets-table th {
  text-align: left;
  color: var(--muted);
  font-size: 0.74rem;
  text-transform: uppercase;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
}
.sets-table td { padding: 8px; border-bottom: 1px solid var(--border); }
.sets-table tr:last-child td { border-bottom: 0; }
.set-num { color: var(--muted); width: 36px; }

.pill {
  display: inline-block;
  font-size: 0.74rem;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 999px;
}
.pill--hit { background: rgba(52,199,89,0.15); color: var(--success); }
.pill--miss { background: rgba(255,77,79,0.15); color: var(--danger); }

.row-actions { display: flex; gap: 6px; align-items: center; justify-content: flex-end; }

.add-set-row td { background: var(--panel-2); }
.add-set-row input[type="number"] { width: 90px; }
.add-set-row select { width: 70px; }

/* ---------- Editable set rows ---------- */
.sets-list { display: flex; flex-direction: column; }
.set-row {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.set-row:first-child { padding-top: 4px; }
.set-chip {
  align-self: flex-end;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 10px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
}
.set-target {
  align-self: flex-end;
  display: flex;
  flex-direction: column;
  line-height: 1.2;
  white-space: nowrap;
  background: rgba(79,140,255,0.10);
  border: 1px solid rgba(79,140,255,0.35);
  border-radius: 8px;
  padding: 4px 8px;
}
/* Filter bar (status / athlete / exercise) on the Video Uploads page. */
.video-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 14px; margin: 0 0 14px; }
.video-filters__field { display: inline-flex; flex-direction: column; gap: 3px; }
.video-filters__field .lbl { margin: 0; color: var(--muted); font-size: 0.72rem; }
.video-filters__field .combobox__input { width: auto; min-width: 140px; }
.video-filters__clear { align-self: flex-end; }

/* Review-status section + athlete grouping headings on the video views. */
.video-section-head { font-size: 1rem; font-weight: 800; margin: 18px 0 8px; padding-bottom: 5px; border-bottom: 1px solid var(--border); }
.video-section-head:first-of-type { margin-top: 0; }
.video-section-head .unread-badge { vertical-align: 1px; }
.video-athlete-head { font-size: 0.9rem; font-weight: 700; color: var(--muted); margin: 12px 0 5px; }

.set-target__pct { font-size: 0.82rem; font-weight: 700; color: var(--accent); }
.set-target__weight { font-size: 0.74rem; color: var(--muted); }

.set-form, .set-edit { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; margin: 0; }
.set-form { flex: 1; }

/* Inline set-row add/remove (± buttons) in the program editor */
.set-rowbtns { display: inline-flex; gap: 6px; align-self: flex-end; }
.set-rowbtns form.button_to { margin: 0; display: inline-flex; }
.set-rowbtn {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
  border-radius: 6px; font-size: 1.2rem; line-height: 1; cursor: pointer;
}
.set-rowbtn:hover { border-color: var(--accent); color: var(--accent); }
.set-rowbtn--ghost { visibility: hidden; }

/* "+ Add exercise" button */
.new-exercise-btn { margin-top: 14px; }
.set-field { display: flex; flex-direction: column; gap: 3px; }
.set-field .lbl { font-size: 0.72rem; }
.set-field input[type="number"] { width: 84px; }
.set-weight { position: relative; display: inline-flex; align-items: center; }

/* "Copy to sets below" ↓ — appears under a field once it's edited (copydown
   controller un-hides it). Absolutely placed so showing it never shifts the row. */
.sets-list .set-field, .sets-list [data-intensity-target] { position: relative; }
.copydown-btn {
  position: absolute; top: 100%; right: 0; margin-top: 2px; z-index: 3;
  display: inline-flex; align-items: center; justify-content: center;
  height: 18px; padding: 0 7px;
  font-size: 0.72rem; line-height: 1; font-weight: 700;
  border: 1px solid var(--accent); border-radius: 999px;
  background: var(--panel); color: var(--accent);
  cursor: pointer; white-space: nowrap;
}
.copydown-btn:hover { background: var(--accent); color: var(--panel); }
.copydown-btn[hidden] { display: none; }
.set-weight input[type="number"] { padding-right: 30px; }
.set-weight__unit { position: absolute; right: 9px; font-size: 0.78rem; font-weight: 600; color: var(--muted); pointer-events: none; }
/* The 1RM-based suggested weight is a placeholder, not a logged value — fade it
   and italicize so it reads as a hint rather than real input. */
.set-weight input::placeholder { color: var(--muted); opacity: 0.4; font-style: italic; }

.set-remove {
  align-self: center;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 0.78rem;
  color: var(--muted);
  white-space: nowrap;
}

.result-toggle { display: inline-flex; gap: 6px; align-self: flex-end; }
.result-toggle form { margin: 0; }
/* ---------- Athlete log set: single line ----------
   [Set N / 🎯 target]  ·  Reps · Weight · (RPE) · ✓/✕ · video.
   The Set label and target stack on the left, in line with the inputs. */
.set-row--log { flex-direction: row; align-items: flex-end; flex-wrap: nowrap; gap: 9px; padding: 12px 0; }
/* Left column: "Set N" centered over the target. Fixed width so a wider label
   (100% vs 86%) never shifts the reps/weight boxes — every row's inputs start
   at the same x. */
.set-meta { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 3px; width: 50px; flex: none; margin-right: 4px; }
/* With no target pill under it, "Set N" alone would bottom-align with the input
   fields — center it against the row instead. */
.set-row--log .set-meta--solo { align-self: center; transform: translateY(7px); }
/* "Set N" as plain text, not a boxed chip. (Override the base align-self:
   flex-end so it can center within .set-meta.) */
.set-row--log .set-chip { align-self: center; background: none; border: 0; padding: 0; color: var(--text); font-weight: 700; }
/* Target as a slim pill, centered under "Set N". */
.set-row--log .set-target { align-self: center; flex-direction: row; background: rgba(79,140,255,0.10); border: 1px solid rgba(79,140,255,0.30); border-radius: 999px; padding: 2px 9px; }
.set-row--log .set-target__pct { font-size: 0.78rem; }
/* Video: borderless icon at the far right, past the ✓/✕ buttons. */
.set-row--log .video-pick { border: 0; background: none; padding: 2px 4px; font-size: 1.15rem; }

.set-row--log .set-edit { display: flex; align-items: flex-end; gap: 8px; flex-wrap: nowrap; flex: 0 1 auto; min-width: 0; }
.set-row--log .set-field .lbl { font-size: 0.68rem; }
.set-row--log .set-field input[type="number"] { height: 40px; }
.set-row--log .set-field--reps { flex: none; }
.set-row--log .set-field--reps input[type="number"] { width: 44px; }   /* reps rarely exceed 2 digits */
.set-row--log .set-weight input[type="number"] { width: 84px; }        /* 3 digits + a decimal */
/* Slightly larger, more legible text across the athlete's log set row
   (Set N, Reps/Weight labels + values, target chip). */
.set-row--log .set-chip { font-size: 0.95rem; }
.set-row--log .set-field .lbl { font-size: 0.78rem; }
.set-row--log .set-field input[type="number"] { font-size: 1.05rem; }
.set-row--log .set-target__pct { font-size: 0.86rem; }
.set-row--log .set-target__weight { font-size: 0.8rem; }
.set-row--log .set-weight__unit { font-size: 0.84rem; }
/* Desktop has room to breathe — roomier reps/weight boxes (phones stay compact). */
@media (min-width: 721px) {
  .set-row--log .set-field--reps input[type="number"] { width: 62px; }
  .set-row--log .set-weight input[type="number"] { width: 108px; }
}
.set-row--log .result-toggle { gap: 6px; }
.set-row--log .result-btn { min-width: 38px; height: 40px; padding: 0 8px; }

/* ---------- Athlete lift stats: 1RM + history box ---------- */
.lift-stats { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 12px; }
.lift-stats__col { flex: 1 1 0; min-width: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2); }
.lift-stats__summary { cursor: pointer; display: flex; align-items: baseline; gap: 8px; padding: 8px 12px; list-style: none; }
.lift-stats__summary::-webkit-details-marker { display: none; }
.lift-stats__label { font-weight: 700; color: var(--muted); text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.05em; }
.lift-stats__value { font-weight: 700; color: var(--accent); font-size: 1rem; }
.lift-stats__caret { margin-left: auto; color: var(--muted); font-size: 0.72rem; transition: transform 0.15s ease; }
.lift-stats__col[open] .lift-stats__caret { transform: rotate(180deg); }
.lift-stats__scroll { max-height: 220px; overflow-y: auto; padding: 0 12px 10px; }
.lift-stats__table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
.lift-stats__table td { padding: 3px 6px; border-top: 1px solid var(--border); white-space: nowrap; }
.lift-stats__empty { padding: 0 12px 10px; margin: 0; }

.add-set-below { margin-top: 10px; }
.result-btn {
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  min-width: 38px;
  padding: 6px 10px;
  font-weight: 700;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.result-btn:hover { border-color: var(--accent); }
.result-btn--hit { color: var(--success); }
.result-btn--miss { color: var(--danger); }
.result-btn.is-hit { background: var(--success); border-color: var(--success); color: #08240f; }
.result-btn.is-miss { background: var(--danger); border-color: var(--danger); color: #2a0708; }

/* Radio-backed ✓/✕ result toggle (Meets): the whole form saves at once, so the
   result is a hidden radio inside a styled button label rather than a submit. */
.result-toggle--radio label.result-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  height: 40px;
}
.result-toggle--radio label.result-btn input { position: absolute; opacity: 0; width: 0; height: 0; }
.result-toggle--radio label.result-btn--hit:has(input:checked) {
  background: var(--success); border-color: var(--success); color: #08240f;
}
.result-toggle--radio label.result-btn--miss:has(input:checked) {
  background: var(--danger); border-color: var(--danger); color: #2a0708;
}

.add-set-form { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--border); }

/* ---------- Set video ---------- */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.video-pick { cursor: pointer; }
/* Inline line icons that replace decorative emoji — sized to the text they sit
   beside. The set-row video button keeps its own fixed size (.icon--video). */
.icon { width: 1.1em; height: 1.1em; display: inline-block; vertical-align: -0.15em; flex: none; }
.card__title .icon { margin-right: 6px; }
.week-item__title .icon { margin-right: 5px; }
.icon--video { width: 22px; height: 22px; display: block; }
.set-video { display: inline-flex; align-items: center; align-self: center; gap: 6px; }
/* On the log row, park the camera at the far right and center it against the
   40px ✓/✕ buttons (match their height so the icon lines up vertically). */
.set-row--log .set-video { align-self: flex-end; height: 40px; }
.set-video__player { max-width: 280px; width: 100%; border-radius: 8px; background: #000; }
.set-video__link { display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--accent); font-weight: 600; font-size: 0.85rem; }
.set-video__link svg { flex: none; }
.set-video__filename { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Once a video is attached, the camera + filename + ✕ sit on their own full-width
   row under the set inputs, with the ✕ pushed to the right. The base .set-row--log
   is nowrap (keeps Set/Reps/Weight/✓✕ on one line); re-enable wrapping only when a
   video is present so the full-width filename row can drop below instead of
   overlapping the inputs. */
.set-row--log:has(.set-video--has) { flex-wrap: wrap; }
.set-row--log .set-video--has { flex: 1 0 100%; height: auto; align-self: stretch; gap: 8px; margin-top: 4px; }
.set-video--has .set-video__link { flex: 1; }
.set-video--has .set-video__remove { flex: none; margin-left: auto; }
.client-video { margin-top: 6px; }

/* ---------- Compliance ---------- */
.compliance-week { display: flex; flex-wrap: wrap; gap: 8px; }
.comp-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 56px;
  padding: 8px 6px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  font-size: 0.74rem;
}
.comp-day:hover { text-decoration: none; border-color: var(--accent); }
.comp-day__icon { font-size: 1rem; font-weight: 700; }
.comp-day--done { background: rgba(52,199,89,0.15); border-color: rgba(52,199,89,0.5); }
.comp-day--done .comp-day__icon { color: var(--success); }
.comp-day--missed { background: rgba(255,77,79,0.12); border-color: rgba(255,77,79,0.45); }
.comp-day--missed .comp-day__icon { color: var(--danger); }
.comp-day--upcoming { color: var(--muted); }

/* ---------- Floating timer (stopwatch) ---------- */
.stopwatch {
  position: fixed;
  right: 16px;
  bottom: 88px; /* clear of the mobile tab bar */
  z-index: 30;
  width: 180px;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: 0 12px 40px rgba(0,0,0,0.5);
  padding: 12px 14px;
}
@media (min-width: 720px) { .stopwatch { bottom: 16px; } }
.stopwatch__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.stopwatch__title { font-weight: 600; font-size: 0.85rem; }
.stopwatch__close { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 0.9rem; }
.stopwatch__display {
  font-size: 2.2rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--accent);
  margin: 6px 0 10px;
}
.stopwatch__controls { display: flex; gap: 8px; }
.stopwatch__controls .btn { flex: 1; justify-content: center; }

/* The % calculator reuses the .stopwatch floating frame, but sits bottom-LEFT
   so it never overlaps the timer when both happen to be open. */
.calculator { left: 16px; right: auto; width: 190px; }
.calc-field { display: flex; flex-direction: column; gap: 3px; margin: 8px 0; }
.calc-lbl { font-size: 0.72rem; color: var(--muted); }
.calc-input {
  width: 100%;
  padding: 6px 8px;
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.calc-input:focus { outline: none; border-color: var(--accent); }
.calculator .stopwatch__display { font-size: 1.9rem; margin: 8px 0 2px; }

.avatar {
  border-radius: 50%;
  object-fit: cover;
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
  background: var(--panel-2);
}
.avatar--initials {
  color: #fff;
  background: var(--accent);
  text-align: center;
  font-weight: 700;
}

.drag-handle {
  cursor: grab;
  color: var(--muted);
  font-size: 1.1rem;
  user-select: none;
  margin-right: 2px;
}
.drag-handle:active { cursor: grabbing; }
.drag-handle--locked { cursor: not-allowed; }
.reorder-btn {
  background: none;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.75rem;
  padding: 0 2px;
  line-height: 1;
}
.reorder-btn:hover { color: var(--accent); }
.is-dragging { opacity: 0.5; outline: 2px dashed var(--accent); }
/* ▲/▼ reorder handle in an expanded program-workout editor bar. */
.cal-reorder { display: inline-flex; flex-direction: column; line-height: 0.8; flex: none; }
.cal-reorder .reorder-btn { padding: 0 3px; }

.info-link { font-size: 0.9rem; text-decoration: none; margin-left: 4px; }
.demo-player { width: 100%; max-width: 480px; border-radius: 8px; background: #000; display: block; }
.video-embed { position: relative; width: 100%; max-width: 560px; aspect-ratio: 16 / 9; }
.video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; border-radius: 8px; }

.invite-link { display: flex; gap: 8px; align-items: center; }
.invite-url { flex: 1; font-size: 0.82rem; font-family: monospace; }

.legal { line-height: 1.6; }
.legal h3 { margin: 18px 0 6px; font-size: 1rem; }
.legal p { margin: 0 0 10px; }

.last-time {
  margin: 4px 0 12px;
  font-size: 0.85rem;
  color: var(--muted);
}
.last-time__label { font-weight: 600; color: var(--text); }

.coach-cue {
  margin: 4px 0 12px;
  padding: 8px 12px;
  background: rgba(79,140,255,0.10);
  border-left: 3px solid var(--accent);
  border-radius: 6px;
  font-size: 0.9rem;
}

/* Athlete's per-exercise note (in the log card + collected on Profile → Notes). */
.we-note { margin-top: 10px; }
.we-note__input {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--text);
  padding: 8px 10px;
  font: inherit;
  font-size: 0.9rem;
  resize: vertical;
}
.we-note__input::placeholder { color: var(--muted); }

.swap-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
  color: var(--accent);
}
.swap-status strong { color: var(--text); }
.we-swap { margin-top: 10px; }
.we-swap > summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--muted);
  list-style: none;
  width: max-content;
}
.we-swap > summary::-webkit-details-marker { display: none; }
.we-swap[open] > summary { margin-bottom: 8px; color: var(--text); }
.we-swap__form { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.we-swap__form .combobox { width: 100%; }
.we-swap__scope { display: flex; flex-direction: column; gap: 4px; font-size: 0.85rem; }
.we-swap__scope label { display: flex; gap: 6px; align-items: center; }

.movement-notes { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.movement-notes .field { width: 100%; }
.movement-notes textarea { width: 100%; }

.muted-link { color: var(--muted); font-size: 0.85rem; }

/* ---------- Messaging ---------- */
.unread-badge {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  border-radius: 999px;
  padding: 1px 8px;
  margin-left: 6px;
}
/* B2 · playback control bar under a form-check video (slow-mo / frame / download). */
.vp-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 12px; }
.vp-speeds, .vp-frames { display: inline-flex; align-items: center; gap: 4px; }
/* Frame step — CSS-drawn triangles (no font glyphs) so both arrows are identical,
   just mirrored. currentColor picks up hover/active. */
.vp-frames .vp-btn { width: 26px; height: 26px; min-width: 0; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.vp-frame::before { content: ""; width: 0; height: 0; border-top: 5px solid transparent; border-bottom: 5px solid transparent; }
.vp-frame--back::before { border-right: 8px solid currentColor; }
.vp-frame--fwd::before { border-left: 8px solid currentColor; }
.vp-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin-right: 2px; }
.vp-btn {
  min-width: 34px; padding: 4px 8px; font-size: 0.8rem; font-weight: 600;
  font-variant-numeric: tabular-nums; cursor: pointer;
  border: 1px solid var(--border); border-radius: 7px; background: var(--panel-2); color: var(--text);
}
.vp-btn:hover { border-color: var(--accent); color: var(--accent); }
.vp-btn.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }
.vp-download { margin-left: auto; }

/* Video review layout: video/studio left, chat right on desktop; stacked on
   phone (the native app is phone-width, so it just falls back to one column). */
.vreview { display: grid; gap: 16px; align-items: start; }
.vreview > .card { margin: 0; }
@media (min-width: 900px) {
  .vreview { grid-template-columns: minmax(0, 1fr) minmax(320px, 380px); align-items: stretch; }
  /* Chat matches the video card's height and scrolls internally. The inner is
     absolutely positioned so a long thread doesn't grow the grid row (the video
     drives the height); the thread flexes + scrolls, the reply box stays pinned. */
  .vreview__chat { position: relative; overflow: hidden; padding: 0; }
  .vreview__chat-inner { position: absolute; inset: 0; display: flex; flex-direction: column; padding: 16px; }
  .vreview__thread { flex: 1 1 0; min-height: 0; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
  .vreview__reply { margin-top: 12px !important; }
}

/* B2 · P2 — draw directly on the paused video (transparent overlay) */
.vp-video { position: relative; line-height: 0; }
.vp-video video { width: 100%; max-height: 70vh; border-radius: 10px; background: #000; display: block; }
.vp-overlay { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }
.markup__toolbar { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; margin-top: 10px;
  padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel-2); }
.markup__group { display: inline-flex; align-items: center; gap: 4px; }
/* Uniform tool / undo / clear buttons so the toolbar reads as an even row. */
.markup__toolbar .vp-btn { width: 72px; height: 26px; padding: 0 4px; font-size: 0.74rem; display: inline-flex; align-items: center; justify-content: center; gap: 3px; }
.markup-swatch { width: 22px; height: 22px; border-radius: 50%; background: var(--sw); border: 2px solid var(--border); cursor: pointer; padding: 0; }
.markup-swatch.is-active { border-color: var(--text); box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--text); }
.markup__send { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.markup__note { min-width: 160px; }
.markup__file { display: none; }

/* Annotated screenshot inside a comment */
.vc__shot { display: block; margin-top: 8px; max-width: 360px; }
.vc__shot img { width: 100%; height: auto; border-radius: 8px; border: 1px solid var(--border); }
.vc__audio { display: block; margin-top: 8px; width: 100%; max-width: 360px; height: 36px; }

/* B2 · P3 — voice-note recorder */
.voice { margin-top: 14px; padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel-2); }
.voice__bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.voice .is-recording { background: var(--accent); color: #fff; border-color: var(--accent); animation: voice-pulse 1s ease-in-out infinite; }
@keyframes voice-pulse { 50% { opacity: 0.55; } }
.voice__preview { display: block; width: 100%; max-width: 360px; height: 36px; margin-top: 10px; }
.voice__form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }
.voice__note { flex: 1; min-width: 160px; }
.voice__file { display: none; }

/* Coach's review control under a clip's video. */
.video-review-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border);
  font-size: 0.85rem;
}
.video-review-bar .icon { width: 15px; height: 15px; vertical-align: -2px; }
.chat { display: flex; flex-direction: column; gap: 12px; }
.chat__messages {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 55vh;
  overflow-y: auto;
  padding: 4px;
}
.msg { display: flex; }
.msg--athlete { justify-content: flex-end; }
.msg--coach { justify-content: flex-start; }
.msg__bubble {
  max-width: 78%;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 12px;
  font-size: 0.92rem;
}
.msg--athlete .msg__bubble { background: var(--accent); border-color: var(--accent); color: #fff; }
.msg__sender { display: block; font-size: 0.7rem; font-weight: 700; opacity: 0.75; margin-bottom: 2px; }
.msg__bubble p { margin: 0; }
.msg__time { display: block; font-size: 0.66rem; opacity: 0.6; margin-top: 3px; text-align: right; }
/* Day divider between messages sent on different calendar days. */
.msg-day { text-align: center; margin: 12px 0 6px; }
.msg-day span {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 10px;
}
.chat__composer { display: flex; gap: 8px; align-items: flex-end; }
.chat__composer textarea { flex: 1; resize: none; }

.topbar__right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

.impersonation-bar {
  background: #b8860b;
  color: #1a1208;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 8px 16px;
  font-size: 0.9rem;
  font-weight: 600;
}
.impersonation-bar .btn { background: #1a1208; color: #f5e7c8; }

/* ---------- Auth ---------- */
.auth-card {
  max-width: 380px;
  margin: 48px auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px;
}
.auth-card h1 { margin: 0 0 20px; font-size: 1.4rem; }
.auth-form { display: flex; flex-direction: column; gap: 14px; }
.auth-form .btn { justify-content: center; margin-top: 4px; }
.auth-links {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 18px;
  flex-wrap: wrap;
  font-size: 0.9rem;
}

.role-choice { display: flex; gap: 10px; }
.role-option {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  cursor: pointer;
  font-size: 0.9rem;
}
.role-option:has(input:checked) { border-color: var(--accent); background: var(--panel-2); }
