/* Copyright (c) 2026 Sam Loane. All rights reserved.
   Proprietary and confidential. Licensed to CREST under the
   CREST Software License & Revenue Share Agreement (2026). See LICENSE.md. */

:root {
  /* v245 — unanimous dark theme. The names (--cream, --cream-warm, --ink,
     --ink-soft) are kept so the whole codebase doesn't need renaming; their
     ROLES are inverted. cream = body background (now darkest), cream-warm =
     elevated panel surface (slightly lighter and faintly warm), ink = text
     (warm cream). High contrast everywhere so font colours don't drown in
     the background (Sam's old pain point with the calc cards). */
  --gold: #F5C200;
  --gold-deep: #E0AE00;
  --cream: #0E0E10;             /* body */
  --cream-warm: #1B1A18;        /* panel / card surface (slight warm tint) */
  --ink: #F5F0E2;               /* primary text — warm bright cream */
  --ink-soft: #C8C2B5;          /* secondary text */
  --muted: #A8A294;             /* tertiary muted — bumped 2026-06-04 so it survives on the dark body without drowning */
  --line: rgba(245, 240, 226, 0.10);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 8px 24px rgba(0, 0, 0, 0.45);
  /* v399 — Pure Apple system font (San Francisco). On iOS/macOS -apple-system
     resolves to SF automatically (Text vs Display chosen optically by size); the
     named "SF Pro *" entries cover macOS where SF is installed, then graceful
     fallbacks. No web-font download — instant, native, pixel-perfect.
     --serif is the DISPLAY role (headings); --sans is body. Both are SF. */
  --serif: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro", system-ui, "Helvetica Neue", Arial, sans-serif;
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro", system-ui, "Helvetica Neue", Arial, sans-serif;
  /* v400 — DISPLAY role: Bebas Neue kept on the big headers (CHECKLIST.,
     section titles, etc.) per Sam; everything else is San Francisco. Loaded via
     Google Fonts in index.html; falls back to SF Display if Bebas hasn't. */
  --display: "Bebas Neue", -apple-system, BlinkMacSystemFont, "SF Pro Display", sans-serif;
  --nav-h: 64px;
  --safe-bottom: env(safe-area-inset-bottom, 0px);

  /* v173 — Spring easing curves. Use these instead of plain ease/ease-out
     anywhere the user is meant to feel a physical bounce or settle.
     --ease-spring        : overshoots ~10%, lands soft (button taps, sheet entrances, swipe snap-back)
     --ease-spring-soft   : smooth deceleration, no overshoot (drawer slides, larger transforms)
     --ease-spring-strong : harder pop, ~20% overshoot (small icon taps, heart pops) */
  --ease-spring:        var(--ease-spring);
  --ease-spring-soft:   var(--ease-spring-soft);
  --ease-spring-strong: cubic-bezier(0.18, 1.74, 0.62, 1);
}

/* v173 — Shimmer placeholder. Lay a `.crest-skeleton` block in the shape
   of the content you're waiting on. The pulse runs across infinitely
   until the real content replaces it. Reads as "something's loading"
   without ants chasing each other. */
@keyframes crestShimmer {
  0%   { background-position: -150% 0; }
  100% { background-position: 250% 0; }
}
.crest-skeleton {
  position: relative;
  /* v334 — light-on-dark shimmer. The original v173 values were dark grey
     on the old cream theme; after the dark rebrand the pulse was invisible,
     so every "loading" state read as blank. */
  background:
    linear-gradient(
      90deg,
      rgba(255, 255, 255, 0.05) 0%,
      rgba(255, 255, 255, 0.13) 50%,
      rgba(255, 255, 255, 0.05) 100%
    );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: crestShimmer 1.4s linear infinite;
  border-radius: 8px;
  color: transparent;
  user-select: none;
  pointer-events: none;
}
.crest-skeleton.circle { border-radius: 50%; }
.crest-skeleton.pill   { border-radius: 999px; }
@media (prefers-reduced-motion: reduce) {
  .crest-skeleton { animation: none; }
}

/* Feed skeleton card layout — matches the real post card shape so the
   transition from skeleton → real content doesn't shift the page. */
.feed-skeleton .feed-skel-row {
  display: flex; align-items: center; gap: 12px; margin-bottom: 12px;
}
.feed-skeleton .feed-skel-avatar { width: 40px; height: 40px; flex: 0 0 auto; }
.feed-skeleton .feed-skel-meta   { flex: 1 1 auto; display: flex; flex-direction: column; gap: 6px; }
.feed-skeleton .feed-skel-name   { width: 40%; height: 12px; }
.feed-skeleton .feed-skel-time   { width: 22%; height: 9px; }
.feed-skeleton .feed-skel-line   { width: 100%; height: 12px; margin-top: 6px; }
.feed-skeleton .feed-skel-line.short { width: 60%; }
.feed-skeleton .feed-skel-media  { width: 100%; height: 180px; margin-top: 8px; border-radius: 10px; }

/* Chat skeleton — matches the real .msg layout so the transition doesn't jump. */
.chat-skeletons { padding: 10px 14px 0; display: flex; flex-direction: column; gap: 18px; }
.msg-skel { display: grid; grid-template-columns: 40px 1fr; gap: 10px; align-items: flex-start; }
.msg-skel-avatar { width: 40px; height: 40px; }
.msg-skel-body   { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.msg-skel-name   { width: 28%; height: 11px; }
.msg-skel-name.short { width: 20%; }
.msg-skel-line   { width: 80%; height: 11px; }
.msg-skel-line.wide  { width: 95%; }
.msg-skel-line.short { width: 50%; }

* { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale; /* v399 — crisp SF rendering on macOS/Firefox */
  text-rendering: optimizeLegibility;
  touch-action: pan-x pan-y;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
  scrollbar-width: none;
  -ms-overflow-style: none;
  overflow-x: hidden;
}
::-webkit-scrollbar { width: 0 !important; height: 0 !important; display: none !important; }
* { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { display: none !important; }

body {
  min-height: 100vh;
  /* v247 — floating pill nav, tightened margins. */
  padding-bottom: calc(var(--nav-h) + var(--safe-bottom) + 16px);
}

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 8px;
}

h1 { font-size: 32px; line-height: 1.15; }
h2 { font-size: 22px; line-height: 1.2; }
h3 { font-size: 17px; line-height: 1.3; }

p { margin: 0 0 12px; color: var(--ink-soft); }

a { color: var(--ink); text-decoration: none; }

.label {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-deep);
  font-weight: 600;
}

/* ---------- Header ---------- */

.app-header {
  display: grid;
  grid-template-columns: 50px 1fr 50px;
  align-items: center;
  padding: 14px 16px 8px;
  gap: 8px;
}
.header-profile {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--cream-warm);
  padding: 0;
  overflow: hidden;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  justify-self: start;
}
.header-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: var(--cream-warm) center/cover no-repeat;
  font-family: var(--serif);
  font-size: 16px;
  color: var(--ink);
}
.header-avatar.has-img { color: transparent; }
.brand-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-self: center;
  gap: 2px;
}
.brand-center .brand-logo {
  width: 36px;
  height: 36px;
}
.brand-center .brand-name {
  font-family: var(--serif);
  font-size: 13px;
  letter-spacing: 0.22em;
}
.header-spacer { width: 40px; height: 40px; }

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.brand-logo {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--cream-warm);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.brand-logo img { width: 84%; height: 84%; object-fit: contain; }

.brand-name {
  font-family: var(--serif);
  font-size: 20px;
  letter-spacing: 0.18em;
}

.who {
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.04em;
}

/* ---------- Sections ---------- */

main { padding: 0 20px 32px; max-width: 720px; margin: 0 auto; }

.section { display: none; }
.section.active { display: block; animation: fadein 0.18s ease; }

@keyframes fadein {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 12px 0 14px;
}

/* v214 — Section header font swapped to Bebas Neue (same as the full
   programme page titles) — heavier, bolder, lands better than Satoshi
   italic which read as too thin. Applies to every section: Feed, Workout,
   Programme, Checklist, Vault, Community, Profile, Admin. */
.section-head h1 {
  font-family: var(--display);
  font-weight: 400;
  font-style: normal;
  letter-spacing: 0.03em;
  font-size: 38px;
  line-height: 1;
}

.section-head .date {
  font-size: 13px;
  color: var(--muted);
  letter-spacing: 0.02em;
}

/* ---------- Cards ---------- */

.card {
  background: var(--cream-warm);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 18px;
  margin: 0 0 14px;
  box-shadow: var(--shadow);
}

.card.gold {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
}
.card.gold p { color: var(--ink-soft); }
.card.gold .label { color: var(--ink); opacity: 0.75; }

.card.dark {
  background: #141414;
  border-color: var(--ink);
  color: var(--ink);
}
.card.dark h2, .card.dark h3 { color: var(--ink); }
.card.dark p { color: rgba(250, 246, 236, 0.78); }
.card.dark .label { color: var(--gold); }

/* Vault: full-card tap target, subtle press feedback */
.vault-card {
  display: block;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s cubic-bezier(.4,0,.2,1), box-shadow 0.15s ease;
}
.vault-card:active {
  transform: scale(0.985);
  box-shadow: 0 1px 2px rgba(20, 20, 20, 0.04);
}
.card.dark.vault-card .muted { color: rgba(250, 246, 236, 0.55); }

/* Locked Vault item, button-styled card with a lock badge in the corner */
.vault-card.vault-locked {
  position: relative;
  width: 100%;
  text-align: left;
  border: 1px solid rgba(245, 194, 0, 0.35);
  cursor: pointer;
  font-family: var(--sans);
}
.vault-lock-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--gold);
  color: var(--ink);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
}
.vault-lock-icon { font-size: 11px; }

/* ===========================================================================
   Onboarding overlay (full-screen wizard for fresh signups)
   =========================================================================== */
/* v427 — Ladder-style onboarding: full-screen, one question per screen, big
   tappable cards that auto-advance, progress dots, top-left back arrow. */
.onboarding-overlay {
  position: fixed; inset: 0; z-index: 9500;
  background: var(--cream);
  display: flex; flex-direction: column;
  padding: max(16px, env(safe-area-inset-top)) 22px max(20px, env(safe-area-inset-bottom));
  overflow-y: auto;
}
.onboarding-overlay[hidden] { display: none; }

.onb-topbar { display: flex; align-items: center; gap: 12px; min-height: 34px; }
.onb-topback {
  background: none; border: 0; color: var(--ink-soft); padding: 4px; margin-left: -4px;
  cursor: pointer; display: inline-flex; -webkit-tap-highlight-color: transparent;
}
.onb-dots { display: flex; gap: 6px; flex: 1; }
.onb-dot { height: 4px; flex: 1; border-radius: 2px; background: rgba(245,240,226,0.12); transition: background .25s; }
.onb-dot.is-done { background: rgba(245,194,0,0.5); }
.onb-dot.is-active { background: var(--gold); }

.onb-stage { flex: 1; display: flex; flex-direction: column; justify-content: center;
  max-width: 460px; width: 100%; margin: 0 auto; padding: 12px 0; }
.onb-screen { animation: onbIn .32s cubic-bezier(0.22,1,0.36,1); }
.onb-screen[hidden] { display: none; }
@keyframes onbIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

.onb-eyebrow { display: block; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gold-deep); font-weight: 700; margin-bottom: 10px; }
.onb-q { font-family: var(--serif); font-size: 30px; line-height: 1.12; margin: 0 0 22px; color: var(--ink); }

.onb-opts { display: flex; flex-direction: column; gap: 10px; }
.onb-opt {
  display: flex; flex-direction: column; gap: 2px; text-align: left; width: 100%;
  padding: 16px 18px; border-radius: 14px;
  background: var(--cream-warm); border: 1.5px solid var(--line); color: var(--ink);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: border-color .15s, background .15s, transform .05s;
}
.onb-opt:active { transform: scale(0.985); }
.onb-opt.is-selected { border-color: var(--gold); background: rgba(245,194,0,0.08); }
.onb-opt-t { font-size: 17px; font-weight: 600; }
.onb-opt-s { font-size: 13px; color: var(--ink-soft); }

.onb-input {
  width: 100%; padding: 16px 18px; border-radius: 14px;
  border: 1.5px solid var(--line); background: var(--cream-warm); color: var(--ink);
  font-family: var(--sans); font-size: 20px; outline: none; -webkit-appearance: none;
}
.onb-input:focus { border-color: var(--gold); }
.onb-input-row { position: relative; display: flex; align-items: center; }
.onb-input-row .onb-input { padding-right: 52px; }
.onb-unit { position: absolute; right: 18px; color: var(--ink-soft); font-size: 15px; font-weight: 600; pointer-events: none; }
.onb-note { font-size: 12px; color: var(--ink-soft); margin: 10px 2px 0; }

.onb-cta {
  margin-top: 22px; width: 100%; padding: 16px; border: 0; border-radius: 14px;
  background: var(--gold); color: #0E0E10; font-family: var(--sans);
  font-size: 16px; font-weight: 700; letter-spacing: 0.04em; cursor: pointer;
  -webkit-tap-highlight-color: transparent; transition: transform .05s, background .15s;
}
.onb-cta:active { transform: scale(0.99); }
.onb-cta:hover { background: var(--gold-deep); }

.onb-done { text-align: center; align-items: center; }
.onb-done-badge { width: 72px; height: 72px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(245,194,0,0.12); color: var(--gold); margin: 0 auto 18px; }
.onb-done .onb-q { font-size: 28px; }
.onb-done-sub { font-size: 15px; color: var(--ink-soft); margin: 6px 0 26px; line-height: 1.5; }
.onb-done-sub strong { color: var(--gold-deep); }
.onb-done .onb-cta { max-width: 280px; margin-left: auto; margin-right: auto; }

.onb-err { text-align: center; color: #FF6B6B; font-size: 13px; min-height: 18px; margin: 12px 0 0; }

/* ===========================================================================
   Calorie + Macro calculator (lives inside Profile section)
   =========================================================================== */
.calc-card { background: #141414; color: var(--ink); border-color: var(--ink); }
.calc-card .label { color: var(--gold); }
.calc-card h2 { color: var(--ink); }
.calc-card .muted { color: rgba(250, 246, 236, 0.55); }
/* "Maintain" hero number */
.calc-maintain {
  text-align: center; margin: 14px 0 18px;
  padding: 18px 12px; border-radius: 14px;
  background: rgba(245, 194, 0, 0.10);
  border: 1px solid rgba(245, 194, 0, 0.28);
}
.calc-maintain-num {
  font-family: var(--serif); font-size: 44px; line-height: 1;
  color: var(--gold); letter-spacing: 0.01em;
}
.calc-maintain-label {
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(250, 246, 236, 0.6); font-weight: 600; margin-top: 6px;
}

/* Goal results table, calculator.net style */
.calc-table {
  display: flex; flex-direction: column;
  border-radius: 12px; overflow: hidden;
  border: 1px solid rgba(250, 246, 236, 0.10);
}
.calc-row {
  display: grid; grid-template-columns: 1.4fr 1fr 1fr;
  align-items: center; gap: 8px;
  padding: 12px 14px;
  background: rgba(250, 246, 236, 0.03);
  border-top: 1px solid rgba(250, 246, 236, 0.06);
  font-family: var(--sans); font-size: 14px; color: var(--ink);
}
.calc-row:first-child { border-top: 0; }
.calc-row-head {
  background: rgba(250, 246, 236, 0.06);
  font-size: 11px; letter-spacing: 0.08em;
  text-transform: uppercase; color: rgba(250, 246, 236, 0.55);
  font-weight: 600;
}
.calc-row .calc-cal {
  font-family: var(--serif); font-size: 20px; color: var(--ink); text-align: right;
}
.calc-row .calc-row-rate {
  font-size: 11px; color: rgba(250, 246, 236, 0.55);
  text-align: right; letter-spacing: 0.02em;
}
.calc-row.calc-row-pivot {
  background: rgba(245, 194, 0, 0.10);
  border-top-color: rgba(245, 194, 0, 0.28);
  border-bottom: 1px solid rgba(245, 194, 0, 0.28);
}
.calc-row.calc-row-pivot .calc-cal { color: var(--gold); }
.calc-row.calc-row-active {
  background: rgba(245, 194, 0, 0.18);
}
.calc-row.calc-row-active .calc-cal { color: var(--gold); }
.calc-macros {
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px;
}
.calc-macro {
  background: rgba(250, 246, 236, 0.04);
  border: 1px solid rgba(250, 246, 236, 0.08);
  border-radius: 12px; padding: 12px 10px; text-align: center;
}
.calc-macro-name {
  font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(250, 246, 236, 0.55); font-weight: 600; margin-bottom: 4px;
}
.calc-macro-val {
  font-family: var(--sans); font-size: 18px; font-weight: 700; color: var(--gold);
}

/* Weight progress chart */
.wlog-stats {
  display: grid; grid-template-columns: 1fr 1fr 1fr;
  gap: 10px; margin-bottom: 14px;
}
.wlog-stat {
  background: rgba(250, 246, 236, 0.04);
  border: 1px solid rgba(250, 246, 236, 0.08);
  border-radius: 12px; padding: 12px 10px; text-align: center;
}
.wlog-stat-num {
  font-family: var(--serif); font-size: 22px; line-height: 1;
  color: var(--ink); margin-bottom: 4px;
}
.wlog-stat-label {
  font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(250, 246, 236, 0.55); font-weight: 600;
}
.wlog-chart-wrap {
  position: relative;
  background: rgba(250, 246, 236, 0.03);
  border: 1px solid rgba(250, 246, 236, 0.08);
  border-radius: 12px; padding: 12px;
  margin-bottom: 14px;
}
.wlog-chart { width: 100%; height: 180px; display: block; }
#wlog-grid line { stroke: rgba(250, 246, 236, 0.08); stroke-width: 1; }
#wlog-grid text {
  fill: rgba(250, 246, 236, 0.4); font-size: 10px;
  font-family: var(--sans);
}
#wlog-dots circle {
  fill: var(--gold); stroke: var(--ink); stroke-width: 2;
}
.wlog-empty {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; color: rgba(250, 246, 236, 0.45); text-align: center; padding: 0 20px;
}
.wlog-add {
  display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: stretch;
}
.wlog-add input {
  background: rgba(250, 246, 236, 0.06);
  border: 1px solid rgba(250, 246, 236, 0.12);
  border-radius: 10px; padding: 12px 14px; color: var(--ink);
  font-family: var(--sans); font-size: 16px; -webkit-appearance: none;
}
.wlog-add input:focus { outline: none; border-color: var(--gold); }
.wlog-add .btn-primary { white-space: nowrap; padding: 12px 18px; }

/* Profile open-full button in chat sheet */
.profile-full-link {
  margin-top: 8px;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 12px;
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.profile-full-link:active { background: rgba(20, 20, 20, 0.04); }

/* Movement Library row inside the Workout section */
.workout-library-link {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  background: var(--cream-warm);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 14px 16px;
  margin-top: 14px;
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
  font-family: var(--sans);
  color: var(--ink);
  transition: border-color 0.15s ease, transform 0.12s ease;
}
.workout-library-link:active {
  transform: scale(0.99);
  border-color: var(--gold);
}
.workout-library-icon {
  width: 36px; height: 36px;
  background: var(--cream-warm);
  border-radius: 10px;
  padding: 7px;
  color: var(--gold-deep);
  flex-shrink: 0;
}
.workout-library-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.workout-library-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.workout-library-desc {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}
.workout-library-chev { color: var(--muted); flex-shrink: 0; }

/* Inline back arrow used by sub-sections (Library returns to Workout) */
.section-back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: transparent;
  border: 0;
  padding: 8px 4px 0;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.section-back:active { color: var(--ink); }

/* ===========================================================================
   Calendar
   =========================================================================== */
.cal-card { padding: 14px; }
.cal-header {
  display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
}
.cal-title {
  flex: 1; text-align: center;
  font-family: var(--serif); font-size: 18px; margin: 0;
  letter-spacing: 0.02em;
}
.cal-nav {
  background: transparent; border: 1px solid var(--line);
  width: 36px; height: 36px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s ease;
}
.cal-nav:active { background: rgba(245, 194, 0, 0.18); }

.cal-dow {
  display: grid; grid-template-columns: repeat(7, 1fr);
  gap: 4px; margin-bottom: 6px;
}
.cal-dow span {
  text-align: center;
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
  padding: 6px 0;
}

.cal-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px;
}
.cal-cell {
  position: relative;
  aspect-ratio: 1 / 1;
  background: rgba(20, 20, 20, 0.03);
  border: 1px solid var(--line);
  border-radius: 10px;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  cursor: pointer; padding: 4px;
  font-family: var(--sans);
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.cal-cell:active { background: rgba(245, 194, 0, 0.18); }
.cal-cell.other-month .cal-num { color: var(--muted); opacity: 0.5; }
.cal-cell.today {
  background: #141414;
  border-color: var(--ink);
}
.cal-cell.today .cal-num { color: var(--gold); font-weight: 700; }
/* v639 — event days: silver dot + amber glow that pulses ONLY for upcoming
   events (matches the profile calendar). Past events keep the dot, no glow. */
.cal-cell.has-events { position: relative; }
.cal-cell.has-event-glow {
  animation: crestEventGlow 2.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .cal-cell.has-event-glow { animation: none; box-shadow: 0 0 8px 2px rgba(245,166,35,0.6); }
}
.cal-num {
  font-size: 14px; color: var(--ink-soft);
}
.cal-evdot {
  position: absolute; bottom: 6px; left: 50%; transform: translateX(-50%);
  width: 5px; height: 5px; border-radius: 50%;
  background: #C7C7CC; /* flat silver, matches profile cal */
}

/* Upcoming section under the grid */
.cal-upcoming-head {
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
  margin: 20px 4px 8px;
}
.cal-upcoming { display: flex; flex-direction: column; gap: 8px; }
.cal-up-row {
  display: flex; align-items: center; gap: 14px;
  background: var(--cream-warm);
  border: 1px solid var(--line); border-radius: 12px;
  padding: 12px 14px;
  cursor: pointer; text-align: left;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease, border-color 0.12s ease;
}
.cal-up-row:active { transform: scale(0.99); border-color: var(--gold); }
.cal-up-when {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  background: var(--cream-warm); border-radius: 10px;
  flex-shrink: 0;
}
.cal-up-day { font-family: var(--serif); font-size: 18px; line-height: 1; color: var(--ink); }
.cal-up-mon { font-size: 9px; letter-spacing: 0.1em; color: var(--muted); margin-top: 2px; font-weight: 600; }
.cal-up-body { flex: 1; min-width: 0; }
.cal-up-title { font-size: 14px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-up-meta { font-size: 12px; color: var(--muted); margin-top: 2px; }

/* Event-detail sheet */
.cal-event-sheet {
  position: fixed; inset: 0; z-index: 9000;
}
.cal-event-sheet[hidden] { display: none; }
.cal-event-backdrop {
  position: absolute; inset: 0;
  background: rgba(20, 20, 20, 0.45);
  opacity: 0; transition: opacity 0.22s ease;
}
.cal-event-sheet.open .cal-event-backdrop { opacity: 1; }
.cal-event-card {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--cream);
  border-top-left-radius: 24px; border-top-right-radius: 24px;
  padding: 28px 22px calc(28px + env(safe-area-inset-bottom, 0));
  transform: translateY(100%);
  transition: transform 0.28s var(--ease-spring-soft);
  max-height: 80vh; overflow-y: auto;
}
.cal-event-sheet.open .cal-event-card { transform: translateY(0); }
.cal-event-close {
  position: absolute; top: 12px; right: 14px;
  background: transparent; border: 0;
  font-size: 28px; line-height: 1;
  color: var(--muted); cursor: pointer; padding: 4px 8px;
}
.cal-event-type-badge {
  display: inline-block;
  font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
  background: var(--gold); color: var(--ink);
  padding: 4px 10px; border-radius: 999px;
  font-weight: 700;
  margin-bottom: 10px;
}
.cal-event-title {
  font-family: var(--serif); font-size: 24px; line-height: 1.2;
  margin: 0 0 8px; color: var(--ink);
}
.cal-event-when {
  font-size: 14px; color: var(--ink-soft); margin: 0 0 12px;
}
.cal-event-desc {
  font-size: 14px; line-height: 1.5; color: var(--ink-soft);
  white-space: pre-wrap; word-wrap: break-word;
  margin: 0 0 18px;
}
.cal-event-join {
  display: block; text-align: center;
  background: var(--gold); color: var(--ink);
  padding: 14px; border-radius: 12px;
  font-family: var(--sans); font-size: 14px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.cal-event-join:active { background: var(--gold-deep); }

/* ===========================================================================
   Admin panel, visible only to sam/miles/charlie via nav-admin
   =========================================================================== */
.admin-tabs {
  display: flex; gap: 6px; margin: 0 0 14px;
  padding: 4px; border-radius: 12px;
  background: rgba(20, 20, 20, 0.04);
  border: 1px solid var(--line);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.admin-tabs::-webkit-scrollbar { display: none; }
.admin-tab {
  flex: 0 0 auto; padding: 8px 14px; border-radius: 8px;
  background: transparent; border: 0;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--muted); cursor: pointer; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s, color 0.15s;
}
.admin-tab.active { background: var(--gold); color: var(--ink); }
/* CREST AI tab, flagged with a gold dot so it stands out as the headline feature */
.admin-tab[data-admin-tab="agent"]::before {
  content: ""; display: inline-block;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--gold); margin-right: 8px;
  vertical-align: middle;
  box-shadow: 0 0 0 2px rgba(245,194,0,0.25);
}
.admin-tab[data-admin-tab="agent"].active::before { background: #141414; box-shadow: none; }

.admin-field {
  display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px;
}
.admin-field > span {
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
}
.admin-field input,
.admin-field select,
.admin-field textarea {
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--cream-warm);
  font-family: var(--sans); font-size: 14px; color: var(--ink);
  outline: none;
  -webkit-appearance: none;
}
.admin-field input:focus,
.admin-field select:focus,
.admin-field textarea:focus { border-color: var(--gold); }
.admin-field textarea { resize: vertical; min-height: 44px; }

/* Password field with show/hide eye (Settings → Password & Security). */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; padding-right: 44px; box-sizing: border-box; }
.pw-eye {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--muted); border-radius: 8px; -webkit-appearance: none;
}
.pw-eye:active { color: var(--ink); }
.pw-eye.is-on { color: var(--gold); }
.pw-forgot-link {
  display: block; margin: 14px auto 0; padding: 6px;
  background: none; border: 0; cursor: pointer;
  font-family: var(--sans); font-size: 13px; color: var(--muted);
  text-decoration: underline; text-align: center; width: 100%;
}
.pw-forgot-link:active { color: var(--ink); }

.admin-ex-row {
  display: grid; grid-template-columns: 1fr 90px 32px; gap: 6px;
  margin-bottom: 6px;
}
.admin-ex-row input {
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px;
  font-family: var(--sans); font-size: 14px; background: var(--cream-warm);
  outline: none; min-width: 0;
}
.admin-ex-row input:focus { border-color: var(--gold); }
.admin-ex-del {
  background: transparent; border: 0; font-size: 20px;
  color: var(--muted); cursor: pointer; padding: 0;
  -webkit-tap-highlight-color: transparent;
}
.admin-ex-del:active { color: #D9322F; }

.admin-add-row {
  display: block; width: 100%;
  background: transparent; border: 1px dashed rgba(20, 20, 20, 0.22);
  border-radius: 10px; padding: 10px;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  color: var(--muted); cursor: pointer; margin-top: 6px;
  -webkit-tap-highlight-color: transparent;
}
.admin-add-row:active { border-color: var(--gold); color: var(--ink); }

.admin-actions { display: flex; gap: 8px; margin-top: 14px; }
.admin-btn {
  flex: 1; padding: 10px 14px; border-radius: 10px;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  border: 1px solid var(--line); background: var(--cream-warm); color: var(--ink);
}
.admin-btn.primary { background: var(--gold); border-color: var(--gold); }
.admin-btn.destructive { background: #D9322F; border-color: #D9322F; color: var(--cream-warm); }
.admin-btn.ghost { background: transparent; }
.admin-btn:disabled { opacity: 0.5; }
.admin-btn:active { transform: scale(0.98); }

.admin-toast {
  margin-top: 10px; padding: 8px 12px; border-radius: 8px;
  background: rgba(245, 194, 0, 0.18); color: var(--ink);
  font-size: 13px; text-align: center;
}

.admin-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.admin-row {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; background: rgba(20, 20, 20, 0.03);
  border: 1px solid var(--line); border-radius: 10px;
}
.admin-row-main { flex: 1; min-width: 0; }
.admin-row-name {
  font-size: 14px; font-weight: 600; color: var(--ink);
  display: flex; gap: 8px; align-items: center;
}
.admin-row-tag {
  font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
  background: var(--cream-warm); color: var(--ink-soft);
  padding: 2px 8px; border-radius: 999px; font-weight: 700;
}
.admin-row-meta { font-size: 12px; color: var(--muted); margin-top: 2px; }
.admin-row-edit {
  background: transparent; border: 1px solid var(--line);
  padding: 6px 12px; border-radius: 8px;
  font-family: var(--sans); font-size: 12px; font-weight: 600;
  color: var(--ink-soft); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.admin-row-edit:active { background: var(--gold); border-color: var(--gold); color: var(--ink); }

.admin-edit-card { margin-top: 14px; border: 1px solid var(--gold); }

/* ===========================================================================
   Feed posts (composer + post cards + post comments)
   =========================================================================== */

.composer { padding: 14px 16px; }
.composer-head { display: flex; gap: 12px; align-items: flex-start; }
.composer-avatar {
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: 16px; color: var(--ink);
  flex-shrink: 0;
}
.composer-avatar.has-img { color: transparent; }

/* CREST-styled confirm dialog */
.crest-confirm {
  /* v333 — must sit ABOVE every sheet it can be launched from (tier sheet,
     profile sheet, admin panels live at 9000-9200). Was 9000 — only DOM
     order kept it on top. */
  position: fixed; inset: 0; z-index: 9300;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.crest-confirm[hidden] { display: none; }
.crest-confirm-backdrop {
  position: absolute; inset: 0;
  background: rgba(20, 20, 20, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.crest-confirm-card {
  position: relative;
  width: 100%; max-width: 360px;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 22px 22px 16px;
  box-shadow: 0 24px 48px rgba(20,20,20,0.18);
  text-align: center;
  animation: crestConfirmIn 0.18s var(--ease-spring);
}
@keyframes crestConfirmIn {
  from { opacity: 0; transform: scale(0.94); }
  to { opacity: 1; transform: scale(1); }
}
.crest-confirm-title {
  font-family: var(--serif); font-size: 20px; line-height: 1.2;
  color: var(--ink); margin: 0 0 10px;
}
.crest-confirm-body {
  font-size: 14px; line-height: 1.45; color: var(--ink-soft);
  margin: 0 0 18px;
}
.crest-confirm-actions {
  display: flex; gap: 10px;
}
.crest-confirm-actions button {
  flex: 1; padding: 12px 14px; border-radius: 12px;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  border: 1px solid var(--line); background: var(--cream-warm); color: var(--ink);
  transition: transform 0.15s, background 0.15s;
}
.crest-confirm-actions button:active { transform: scale(0.97); }
.crest-confirm-ok { background: var(--gold) !important; border-color: var(--gold) !important; color: var(--ink) !important; }
.crest-confirm-ok.destructive { background: #D9322F !important; border-color: #D9322F !important; color: var(--cream-warm) !important; }
.crest-confirm-ok.destructive:active { background: #B82624 !important; }
.composer textarea {
  flex: 1; min-width: 0; min-height: 44px; max-height: 200px;
  resize: none; border: 0; outline: none; background: transparent;
  font-family: var(--sans); font-size: 15px; line-height: 1.4; color: var(--ink);
  padding: 8px 0;
}
.composer textarea::placeholder { color: var(--muted); }
.composer-media-preview {
  margin-top: 12px; border-radius: 12px; overflow: hidden; background: var(--cream-warm);
}
.composer-media-preview img,
.composer-media-preview video { width: 100%; max-height: 280px; object-fit: cover; display: block; }
.composer-actions {
  display: flex; align-items: center; gap: 8px; margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--line);
}
.composer-media-btn {
  width: 36px; height: 36px; border-radius: 8px; border: 0;
  background: transparent; color: var(--muted); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  -webkit-tap-highlight-color: transparent; transition: background 0.12s;
}
.composer-media-btn:active { background: rgba(20,20,20,0.06); color: var(--ink); }
.composer-clear {
  margin-left: auto; background: transparent; border: 0;
  color: var(--muted); font-size: 13px; cursor: pointer; padding: 6px 10px;
}
.composer-post {
  background: var(--gold); color: var(--ink); border: 0;
  padding: 8px 18px; border-radius: 10px; font-family: var(--sans);
  font-size: 13px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s, opacity 0.15s;
}
.composer-post:active { transform: scale(0.97); }
.composer-post:disabled { opacity: 0.4; cursor: not-allowed; }
.composer-clear[hidden] { display: none; }

/* Feed list + cards */
.feed-posts { display: flex; flex-direction: column; gap: 14px; margin-bottom: 14px; }
.feed-post {
  /* v483 — subtle top-to-bottom gradient (lighter at the top, settling deeper
     at the foot) for a more premium, lit-from-above feel vs the flat panel. */
  background: linear-gradient(180deg, #24221F 0%, #1B1A18 55%, #161513 100%);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
  overflow: hidden;
}
.post-head { display: flex; align-items: center; gap: 10px; padding: 14px 16px 8px; }
.post-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: 15px; color: var(--ink);
  flex-shrink: 0;
}
.post-avatar.has-img { color: transparent; }
.post-head-meta { flex: 1; min-width: 0; }
.post-name { font-size: 14px; font-weight: 600; color: var(--ink); }
.post-time { font-size: 11px; color: var(--muted); margin-top: 1px; }
.post-delete {
  background: transparent; border: 0; color: var(--muted);
  font-size: 22px; line-height: 1; cursor: pointer; padding: 4px 8px;
  -webkit-tap-highlight-color: transparent;
}
.post-delete:active { color: var(--ink); }
/* v605 — admin pin toggle + pinned-post treatment. */
.post-pin {
  background: transparent; border: 0; color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 4px 6px; flex-shrink: 0;
  -webkit-tap-highlight-color: transparent; transition: color 0.15s ease, transform 0.12s ease;
}
.post-pin:active { transform: scale(0.9); }
.post-pin.is-pinned { color: #F5C200; }
.post-name { display: inline-flex; align-items: center; gap: 8px; }
.post-pinned-tag {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: #F5C200; opacity: 0.95;
}
.feed-post.pinned {
  border-color: rgba(245,194,0,0.42);
  box-shadow: var(--shadow), 0 0 0 1px rgba(245,194,0,0.18) inset;
}

.post-text {
  padding: 0 16px 12px;
  font-size: 15px; line-height: 1.45; color: var(--ink-soft);
  white-space: pre-wrap; word-wrap: break-word;
}
.post-media {
  position: relative;
  background: transparent;
  -webkit-tap-highlight-color: transparent;
  cursor: pointer;
}
.post-media img {
  width: 100%; max-height: 600px; object-fit: cover; display: block;
  aspect-ratio: 4 / 5;
}
.post-video-wrap {
  background: #141414;
  aspect-ratio: 4 / 5;
  overflow: hidden;
}
.post-video-wrap video {
  width: 100%; height: 100%; display: block;
  object-fit: cover;
  background: #141414;
}

/* Mute toggle, sits bottom-right of the video, low-key */
.post-video-mute {
  position: absolute; bottom: 12px; right: 12px;
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(20, 20, 20, 0.55);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border: 0; color: var(--cream-warm);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.15s, transform 0.15s;
  z-index: 3;
}
.post-video-mute:active { transform: scale(0.92); }
.post-video-mute.unmuted { background: rgba(245, 194, 0, 0.85); color: var(--ink); }

/* Double-tap heart pop, overlay centre, scales+fades */
.post-heart-pop {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; opacity: 0;
  z-index: 2;
}
.post-heart-pop svg { filter: drop-shadow(0 4px 14px rgba(0,0,0,0.35)); }
.post-heart-pop.animate { animation: heartPop 0.85s ease-out forwards; }
@keyframes heartPop {
  0%   { opacity: 0; transform: scale(0.6); }
  20%  { opacity: 1; transform: scale(1.15); }
  35%  { transform: scale(0.95); }
  55%  { transform: scale(1.05); }
  100% { opacity: 0; transform: scale(1.2); }
}

.post-actions {
  display: flex; align-items: center; gap: 18px; padding: 10px 16px;
  border-top: 1px solid var(--line);
}
.post-like-btn,
.post-comment-btn {
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  background: transparent; border: 0; padding: 4px 0;
  color: var(--ink-soft); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.18s var(--ease-spring), color 0.15s;
}
.post-like-btn:active { transform: scale(1.18); }
.post-like-btn.liked { color: #FF3344; }
.post-like-count,
.post-comment-count { font-size: 13px; font-weight: 500; line-height: 1; min-height: 13px; text-align: center; }

/* Inline comments thread under a post */
.post-comments { padding: 0 16px 12px; border-top: 1px solid var(--line); background: rgba(20,20,20,0.02); }
.fpc-list { display: flex; flex-direction: column; gap: 10px; padding-top: 10px; }
/* Layout moved to .fpc-comment > .swipe-row so the swipe wrapper owns full width */
.fpc-comment { display: block; }
.fpc-reply { padding-left: 36px; }
.fpc-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: 12px; color: var(--ink);
  flex-shrink: 0;
}
.fpc-avatar.has-img { color: transparent; }
.fpc-body { min-width: 0; }
.fpc-meta { display: flex; align-items: baseline; gap: 8px; }
.fpc-name { font-size: 12px; font-weight: 600; color: var(--ink); }
.fpc-time { font-size: 10px; color: var(--muted); }
.fpc-text { font-size: 13px; line-height: 1.4; color: var(--ink-soft); margin-top: 2px; word-wrap: break-word; }
.fpc-actions { display: flex; gap: 12px; margin-top: 4px; }
.fpc-reply-btn,
.fpc-delete-btn {
  background: transparent; border: 0; padding: 0;
  font-family: var(--sans); font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  color: var(--muted); cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.fpc-reply-btn:active { color: var(--gold-deep); }

/* Swipe-left to reveal red Delete on your own comments (matches workout pattern) */
.fpc-comment {
  position: relative;
  overflow-x: hidden;
  overflow-y: visible;
}
.fpc-comment > .swipe-row {
  display: grid;
  grid-template-columns: 28px 1fr auto;   /* avatar | body | heart */
  gap: 8px;
  align-items: center;                     /* heart vertically centred against body */
  background: var(--cream-warm);           /* v455 — dark theme; was hardcoded #FAFAFA (white in dark mode) */
  position: relative;
  z-index: 2;
  /* v236 — bumped horizontal padding from 2px to 4px so the avatar's tier-ring
     box-shadow has room to render inside the horizontally-clipped container. */
  padding: 4px 4px;
  transform: translateX(0);
  transition: transform 0.28s var(--ease-spring-soft);
  will-change: transform;
  touch-action: pan-y;
}
.fpc-comment.swipeable > .swipe-row.dragging { transition: none; }
.fpc-comment.swipeable.swiped > .swipe-row { transform: translateX(-88px); }
.fpc-comment .fpc-swipe-delete {
  position: absolute; top: 0; right: 0;
  height: 100%; width: 88px;
  background: #D9322F; color: var(--cream-warm);
  border: 0;
  font-family: var(--sans); font-size: 13px; font-weight: 500;
  cursor: pointer; z-index: 1;
  -webkit-tap-highlight-color: transparent;
  display: none; align-items: center; justify-content: center;
}
.fpc-comment.deletable .fpc-swipe-delete { display: flex; }
.fpc-comment .fpc-swipe-delete:active { background: #B82624; }

.fpc-like-btn {
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  background: transparent; border: 0; padding: 2px 4px; margin: 0;
  color: var(--muted); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.18s var(--ease-spring), color 0.15s;
}
.fpc-like-btn:active { transform: scale(1.25); }
.fpc-like-btn.liked { color: #FF3344; }
.fpc-like-count { font-size: 10px; font-weight: 600; line-height: 1; min-height: 10px; text-align: center; }
/* v239 — keep the slot reserved so the heart icon never jumps when 0→1. */
.fpc-like-count[hidden] { display: block !important; visibility: hidden; }

.fpc-form { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.fpc-input-row { display: flex; align-items: center; gap: 8px; }
.fpc-input {
  flex: 1; padding: 8px 12px; border: 1px solid var(--line); border-radius: 18px;
  font-family: var(--sans); font-size: 13px; background: var(--cream-warm); color: var(--ink);
  outline: none; min-width: 0;
}
.fpc-input:focus { border-color: var(--gold); }
.fpc-send {
  width: 32px; height: 32px; border-radius: 50%; border: 0;
  background: var(--gold); color: var(--ink);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; -webkit-tap-highlight-color: transparent; flex-shrink: 0;
}
.fpc-send:active { background: var(--gold-deep); }
.fpc-reply-banner {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 10px; margin-bottom: 8px;
  background: rgba(245, 194, 0, 0.12); border-left: 2px solid var(--gold);
  border-radius: 4px; font-size: 11px; color: var(--ink-soft);
}
.fpc-reply-banner .fpc-reply-name { font-weight: 600; color: var(--gold-deep); }
.fpc-reply-banner button {
  background: transparent; border: 0; color: var(--muted);
  font-size: 16px; line-height: 1; cursor: pointer; padding: 0 4px;
}

/* Workout completion button + avatar row (lives on the white workout card) */
.completion-row {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.completion-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 16px;
  background: transparent;
  border: 1.5px solid var(--gold);
  color: var(--gold);
  border-radius: 12px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.3s var(--ease-spring-soft), background 0.18s ease, color 0.18s ease;
  width: 100%;
}
.completion-btn:active { transform: scale(0.94); }
.completion-btn.done {
  background: var(--gold);
  color: var(--ink);
  border-color: var(--gold);
}
.completion-btn:disabled { opacity: 0.6; cursor: progress; }
.completion-btn-icon { flex-shrink: 0; }

.completion-avatars {
  display: flex;
  align-items: center;
  min-height: 28px;
  gap: 8px;
  flex-wrap: wrap;
}
.completion-stack { display: flex; align-items: center; }
.completion-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  margin-left: -8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 13px;
  color: var(--ink);
  flex-shrink: 0;
  box-sizing: border-box;
}
.completion-avatar:first-child { margin-left: 0; }
.completion-avatar.has-img { color: transparent; }
.completion-more {
  font-size: 12px;
  font-weight: 600;
  color: var(--gold);
  margin-left: 8px;
}
.completion-meta {
  font-size: 13px;
  color: var(--muted);
}

/* Comments under Live Daily Workout */
.comments-block {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.comments-head {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 12px;
}
.comments-list { display: flex; flex-direction: column; gap: 12px; }
.comments-list:empty { display: none; }

/* Each .comment is a swipe container. .comment-row holds the actual content; */
/* .swipe-delete sits absolutely behind it, revealed only on swipe for owner.  */
.comment {
  position: relative;
  /* Need horizontal clipping for the swipe-to-delete reveal, but vertical
     overflow visible so the avatar's tier-ring box-shadow isn't sliced off. */
  overflow-x: hidden;
  overflow-y: visible;
}
.comment-reply { padding-left: 38px; }
.comment > .swipe-row {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 10px;
  align-items: flex-start;
  background: var(--cream-warm);               /* matches white workout card so red Delete sits behind */
  position: relative;
  z-index: 2;
  transform: translateX(0);
  transition: transform 0.28s var(--ease-spring-soft);
  will-change: transform;
  touch-action: pan-y;
  /* v237 — 3px padding on ALL sides so the avatar's tier-ring box-shadow
     has room to render. Horizontal: the swipe container clips overflow-x.
     Vertical: per CSS spec, overflow-y: visible is forced to auto when
     overflow-x is hidden, so top/bottom were also clipping the ring. */
  padding: 3px;
}
.comment.swipeable > .swipe-row.dragging { transition: none; }
.comment.swipeable.swiped > .swipe-row { transform: translateX(-88px); }

.comment-delete {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 88px;
  background: #D9322F;
  color: var(--cream-warm);
  border: 0;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: pointer;
  z-index: 1;
  -webkit-tap-highlight-color: transparent;
  display: none;
  align-items: center;
  justify-content: center;
}
.comment.deletable .comment-delete { display: flex; }
.comment-delete:active { background: #B82624; }

.comment-reply-btn {
  margin-top: 4px;
  background: transparent;
  border: 0;
  padding: 0;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  color: rgba(245, 194, 0, 0.7);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
}
.comment-reply-btn:active { color: var(--gold); }

/* Instagram-style heart on each comment. v239 — count stacks BELOW the heart
   so the heart icon never shifts horizontally as the count grows. */
.comment-like-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: transparent;
  border: 0;
  padding: 2px 4px;
  margin: 0;
  color: var(--muted);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.22s var(--ease-spring-soft), color 0.15s ease;
}
.comment-like-btn:active { transform: scale(1.25); }
.comment-like-btn.liked { color: #FF3344; }
.comment-like-count {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  line-height: 1;
  min-height: 11px;       /* reserve slot so heart doesn't jump 0→1 */
  text-align: center;
}
.comment-like-btn.liked .comment-like-count { color: #FF3344; }
/* v239 — visibility:hidden keeps the slot, display:none made the heart jump */
.comment-like-count[hidden] { display: block !important; visibility: hidden; }

.reply-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 10px;
  padding: 8px 12px;
  background: rgba(245, 194, 0, 0.12);
  border-left: 2px solid var(--gold);
  border-radius: 6px;
  font-size: 12px;
  color: var(--ink-soft);
}
.reply-banner #feed-reply-banner-name,
.reply-banner #wp-reply-banner-name { color: var(--gold-deep); font-weight: 600; }
.reply-banner button {
  background: transparent;
  border: 0;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}

.comment-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 13px;
  color: var(--ink);
  flex-shrink: 0;
}
.comment-avatar.has-img { color: transparent; }
.comment-body { min-width: 0; }
.comment-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 2px;
}
.comment-meta .comment-time { margin-right: auto; }
.comment-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.comment-time {
  font-size: 11px;
  color: var(--muted);
}
.comment-text {
  font-size: 14px;
  line-height: 1.4;
  color: var(--ink-soft);
  word-wrap: break-word;
  white-space: pre-wrap;
}

.comments-form {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.comments-form input {
  flex: 1;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  padding: 8px 2px;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink);
  outline: none;
  min-width: 0;
}
.comments-form input::placeholder { color: var(--muted); }
.comments-form input:focus { border-bottom-color: var(--gold); }
.comments-form input:disabled { opacity: 0.5; }
.comments-form button {
  background: var(--gold);
  border: 0;
  border-radius: 50%;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  flex-shrink: 0;
  transition: transform 0.15s ease, background 0.18s ease;
}
.comments-form button:active { transform: scale(0.95); background: var(--gold-deep); }

.empty {
  text-align: center;
  padding: 36px 16px 8px;
  color: var(--muted);
}
.empty-line {
  font-family: var(--serif);
  font-size: 18px;
  color: var(--ink);
  margin: 0 0 6px;
  opacity: 0.85;
}
.empty-sub {
  font-size: 13px;
  margin: 0 auto;
  max-width: 280px;
  line-height: 1.45;
  color: var(--muted);
}

/* ---------- Checklist ---------- */

.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
}
.checklist li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.checklist li:last-child { border-bottom: 0; }

.checklist input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--ink);
  border-radius: 50%;        /* v437 — circular checkbox (habit-tracker style) */
  background: transparent;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
}
.checklist input[type="checkbox"]:checked {
  background: var(--gold);
  border-color: var(--gold);
}
/* v439 — the pop + check-draw fire ONCE, only on a fresh tick (JS adds
   .ck-just-ticked). Putting them on :checked made every box re-bump on reflow. */
.checklist input[type="checkbox"].ck-just-ticked { animation: ck-pop 0.3s ease; }
@keyframes ck-pop {
  0%   { transform: scale(0.82); }
  55%  { transform: scale(1.14); }
  100% { transform: scale(1); }
}
.checklist input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 6px;
  height: 12px;
  border: solid var(--ink);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  transform-origin: center;
}
.checklist input[type="checkbox"].ck-just-ticked::after {
  animation: ck-check-in 0.26s 0.06s ease backwards;
}
@keyframes ck-check-in {
  from { opacity: 0; transform: rotate(45deg) scale(0.3); }
  to   { opacity: 1; transform: rotate(45deg) scale(1); }
}
.checklist label {
  flex: 1;
  cursor: pointer;
  font-size: 15px;
}
.checklist .hint {
  font-size: 12px;
  color: var(--muted);
}

/* Custom items, iOS Mail-style swipe-left to reveal Delete */
.checklist li.swipeable {
  position: relative;
  overflow: hidden;
  padding: 0;            /* swipe-row provides its own vertical padding */
  border-bottom: 1px solid var(--line);
  display: block;        /* override the parent .checklist li flex so swipe-row fills width and covers Delete */
}
.checklist li.swipeable .swipe-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  background: var(--cream-warm);   /* matches card background; opaque so red Delete sits behind */
  position: relative;
  z-index: 2;
  transform: translateX(0);
  transition: transform 0.28s cubic-bezier(.32, .72, .25, 1);
  will-change: transform;
  touch-action: pan-y;   /* let iOS pan the page vertically; we own horizontal */
}
.checklist li.swipeable .swipe-row.dragging {
  transition: none;
}
.checklist li.swipeable.swiped .swipe-row {
  transform: translateX(-88px);
}
.checklist li.swipeable .swipe-delete {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 88px;
  background: #D9322F;
  color: var(--cream-warm);
  border: 0;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: pointer;
  z-index: 1;
  -webkit-tap-highlight-color: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
}
.checklist li.swipeable .swipe-delete:active { background: #B82624; }

/* "Add your own" row, sits at the bottom of the list */
.checklist li.ck-add-row {
  border-bottom: 0;
  padding: 14px 0 4px;
  display: block;
}
.ck-add-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: 1px dashed rgba(20, 20, 20, 0.22);
  border-radius: 12px;
  padding: 12px 14px;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--muted);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.ck-add-toggle:hover,
.ck-add-toggle:active {
  border-color: var(--gold);
  color: var(--ink);
  background: rgba(245, 194, 0, 0.05);
}
.ck-add-plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  font-size: 18px;
  line-height: 1;
  font-weight: 300;
}
.ck-add-form { display: flex; gap: 8px; align-items: center; }
.ck-add-form input {
  flex: 1;
  padding: 12px 14px;
  border: 1px solid var(--gold);
  border-radius: 12px;
  font-family: var(--sans);
  font-size: 15px;
  background: var(--cream-warm);
  color: var(--ink);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}
.ck-add-form input:focus { border-color: var(--gold-deep); }

/* ---------- Score ring ---------- */

.score-row {
  display: flex;
  align-items: center;
  gap: 16px;
}
.score-ring {
  width: 88px;
  height: 88px;
  flex-shrink: 0;
  position: relative;
}
.score-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.score-ring circle { fill: none; stroke-width: 8; }
.score-ring .track { stroke: rgba(20, 20, 20, 0.08); }
.score-ring .fill { stroke: var(--gold); stroke-linecap: round; transition: stroke-dashoffset 0.5s ease; }
.score-ring .num {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 26px;
}

/* ---------- Bottom Nav ---------- */

/* v246 — Ladder-style FLOATING PILL bottom nav. Detached from screen edges
   with margin all round, dark elevated container, active button has its own
   slightly-lighter inner pill, all icons + labels are white (no gold). */
.bottom-nav {
  /* v257 — reverted back to v255 floating pill. */
  position: fixed;
  left: 4px;
  right: 4px;
  bottom: calc(var(--safe-bottom) + 6px);
  height: var(--nav-h);
  /* v265 — Liquid Glass: translucent dark base + heavy backdrop blur +
     saturation so content behind tints and refracts through, plus a faint
     inner highlight for the glass edge. Falls back to opaque on browsers
     that don't support backdrop-filter (older Android). */
  background: rgba(20, 20, 22, 0.06);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
          backdrop-filter: blur(40px) saturate(180%);
  border-radius: 36px;
  display: flex;
  z-index: 50;
  padding: 5px 4px;
  box-sizing: border-box;
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.45),
    0 1px 0 rgba(255, 255, 255, 0.08) inset,
    0 0 0 1px rgba(255, 255, 255, 0.04);
  border: 0;
  overflow: hidden;
  /* v263.1 — REAL fix. The previous --ease-spring-soft variable was
     self-referencing (declared as var(--ease-spring-soft) of itself) and
     silently resolved to the browser default `ease`, which is why every
     attempt to soften the shrink still felt snappy. Hardcoding the Apple-
     style ultra-smooth out curve here + a much longer 750ms duration. */
  transition: transform 0.75s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}
/* v258.1 — true visual shrink (like pinching a photo). The whole pill scales
   down uniformly anchored at the bottom centre. */
.bottom-nav { transform-origin: 50% 100%; }
.bottom-nav.shrunk { transform: scale(0.82); }
/* v333 — cap the pill on wide screens (iPad / desktop). Edge-to-edge at
   1000px+ loses the floating-pill look entirely. */
@media (min-width: 640px) {
  .bottom-nav {
    left: 50%;
    right: auto;
    width: 560px;
    transform: translateX(-50%);
    transform-origin: 50% 100%;
  }
  .bottom-nav.shrunk { transform: translateX(-50%) scale(0.82); }
}
.bottom-nav button {
  /* v257 — reverted back to v254 button style (flex equal-share, ellipsis,
     white labels, lighter inner pill on active). */
  flex: 1 1 0;
  min-width: 0;
  background: transparent;
  border: 0;
  padding: 3px 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: #FFFFFF;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  font-family: var(--sans);
  border-radius: 24px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.18s ease, transform 0.18s var(--ease-spring-soft);
  -webkit-tap-highlight-color: transparent;
}
.bottom-nav button:active { transform: scale(0.94); }
/* v246 / v265.1 — Active item gets its own inner pill, now translucent
   white so it brightens the glass without breaking the liquid look. */
.bottom-nav button.active {
  background: rgba(255, 255, 255, 0.12);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.05) inset;
}
.bottom-nav button .icon-bg {
  transition: transform 0.22s var(--ease-spring-strong);
}
.bottom-nav button.active .icon-bg { transform: scale(1.04); }
.bottom-nav button .icon {
  width: 22px;
  height: 22px;
  display: block;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* v246 — Icon-bg no longer carries a gold pill; the button itself owns the
   highlight state. Keep the wrapper just for icon centering + scale animation. */
.bottom-nav .icon-bg {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0;
}

/* ---------- Misc ---------- */

.muted { color: var(--muted); }
.row { display: flex; gap: 12px; align-items: center; }
.row.between { justify-content: space-between; }
.tight { margin: 0 0 4px; }

.exercise {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px dashed var(--line);
  font-size: 14px;
}
.exercise:last-child { border-bottom: 0; }
.exercise .reps { color: var(--muted); }

.search {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  font-size: 15px;
  background: var(--cream-warm);
  font-family: var(--sans);
  margin-bottom: 14px;
}
.search:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}

/* ---------- Splash ---------- */

.splash {
  position: fixed;
  inset: 0;
  background: var(--cream);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  transition: opacity 0.45s ease;
  overflow: hidden;
  padding: 0;
  margin: 0;
}
.splash.hide {
  opacity: 0;
  pointer-events: none;
}
.splash-logo {
  width: 180px !important;
  height: 180px !important;
  max-width: 60vw !important;
  max-height: 60vw !important;
  object-fit: contain;
  display: block;
  animation: splash-pulse 1.6s ease-in-out infinite;
}
@keyframes splash-pulse {
  0%, 100% { transform: scale(1); opacity: 0.95; }
  50% { transform: scale(1.04); opacity: 1; }
}

/* ---------- Login screen ---------- */

.login-body {
  background: var(--cream);
  min-height: 100vh;
  padding: 0;
}
.login-shell {
  max-width: 420px;
  margin: 0 auto;
  padding: 12vh 28px 40px;
  text-align: center;
}
.login-mark {
  width: 88px;
  height: 88px;
  margin: 0 auto 24px;
  background: var(--cream-warm);
  border: 1px solid var(--line);
  border-radius: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  box-shadow: var(--shadow);
}
.login-mark img { width: 86%; height: 86%; object-fit: contain; }

.login-title {
  font-family: var(--serif);
  font-size: 36px;
  margin: 0 0 4px;
}
.login-sub {
  font-size: 14px;
  color: var(--muted);
  margin: 0 0 32px;
}

.login-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: left;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.field span {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  padding-left: 2px;
}
.field input {
  font-family: var(--sans);
  font-size: 16px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--cream-warm);
  color: var(--ink);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.field input:focus {
  outline: none;
  border-color: var(--gold-deep);
  box-shadow: 0 0 0 3px rgba(245, 194, 0, 0.18);
}

.btn-primary {
  margin-top: 10px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.04em;
  background: var(--gold);
  color: var(--ink);
  border: 0;
  padding: 14px;
  border-radius: 12px;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.28s var(--ease-spring-soft);
  -webkit-tap-highlight-color: transparent;
}
.btn-primary:hover { background: var(--gold-deep); }
.btn-primary:active { transform: scale(0.94); }
.btn-primary:disabled { opacity: 0.7; cursor: progress; }

.login-err {
  min-height: 18px;
  margin: 0;
  font-size: 13px;
  color: #B00020;
  text-align: center;
}
.login-foot {
  margin-top: 36px;
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}

/* ---------- Pull-to-refresh ---------- */

#ptr {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 0;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: var(--cream);
  z-index: 100;
  transition: height 0.18s ease;
  pointer-events: none;
}
#ptr.armed { height: 70px; }
#ptr.refreshing { height: 70px; }
.ptr-inner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 14px;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.ptr-spin {
  width: 14px;
  height: 14px;
  border: 2px solid var(--ink);
  border-top-color: transparent;
  border-radius: 50%;
}
#ptr.refreshing .ptr-spin {
  animation: ptrspin 0.7s linear infinite;
}
#ptr.armed .ptr-label::after { content: "Release"; }
#ptr.armed .ptr-label { font-size: 0; }
#ptr.armed .ptr-label::after { font-size: 12px; }
@keyframes ptrspin { to { transform: rotate(360deg); } }

/* ---------- Day strip ---------- */

.day-strip-wrap {
  margin: 0 -20px 14px;
  padding: 0;
  position: relative;
  height: 86px;
}
.day-indicator {
  position: absolute;
  top: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 56px;
  height: 76px;
  background: var(--gold);
  border-radius: 16px;
  z-index: 0;
  pointer-events: none;
}
.day-strip {
  position: relative;
  z-index: 1;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding: 4px calc(50vw - 26px) 10px;
  scrollbar-width: none;
}
.day-strip::-webkit-scrollbar { display: none; }

.day-cell {
  flex: 0 0 auto;
  width: 52px;
  padding: 10px 0 8px;
  border-radius: 14px;
  background: transparent;
  text-align: center;
  cursor: pointer;
  scroll-snap-align: center;
  border: 1px solid transparent;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  font-family: var(--sans);
  user-select: none;
}
.day-cell .dow {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}
.day-cell .num {
  font-family: var(--serif);
  font-size: 20px;
  color: var(--ink);
  line-height: 1;
}
.day-cell .mon {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 4px;
}

.day-cell.future {
  opacity: 0.35;
  pointer-events: none;
}

.day-cell.selected {
  background: transparent;
  border-color: transparent;
}
.day-cell.selected .dow,
.day-cell.selected .mon {
  color: var(--ink);
  opacity: 0.78;
}
.day-cell.selected .num {
  font-weight: 700;
}
.day-cell.today:not(.selected) .num {
  position: relative;
}
.day-cell.today:not(.selected) .num::after {
  content: "";
  display: block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--gold-deep);
  margin: 4px auto 0;
}

.foot-note {
  text-align: center;
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.08em;
  margin: 24px 0 8px;
  text-transform: uppercase;
}

/* ---------- Dev Chat ---------- */

.chat-section {
  position: fixed;
  /* v190 — Chat section now leaves room at the bottom for the global nav so
     members can hop between Feed / Community / Vault from any chat room
     without using the back arrow. Previously this section took the whole
     viewport and hid the nav — too easy to accidentally tap the back arrow
     next to the burger and lose your place. */
  top: 0;
  left: 0;
  right: 0;
  /* v447 — +16px so the message composer clears the FLOATING nav pill (which
     sits ~6px above nav-h with its shadow) instead of being clipped by it. */
  bottom: calc(var(--nav-h) + var(--safe-bottom) + 16px);
  background: var(--cream);
  display: none;
  flex-direction: column;
  padding: 0;
  z-index: 40;
}
.chat-section.active {
  display: flex;
  animation: fadein 0.18s ease;
}
/* v269 — Global app-header now visible on EVERY section incl. chat so the
   profile avatar lives top-right across the whole app. The chat module's own
   .chat-head-profile is hidden to avoid the duplicate. */
body.in-chat .app-header {
  display: flex;
}
body.in-chat .chat-head-profile { display: none !important; }

.chat-head {
  flex: 0 0 auto;
  padding: calc(env(safe-area-inset-top, 0px) + 10px) 14px 10px;
  border-bottom: 1px solid var(--line);
  /* v381 — was beige rgba(250,246,236,.94); dark theme. */
  background: rgba(14, 14, 16, 0.94);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  position: relative;
  display: grid;
  /* v190 — Back arrow removed (bottom nav handles navigation now). Burger
     on the left, title centred, 36px mirror spacer on the right. */
  grid-template-columns: 36px 1fr 36px;
  align-items: center;
  gap: 8px;
}
.chat-back {
  /* v190 — Killed. Members navigate via the bottom nav, no more accidental
     back-taps right next to the channel burger. */
  display: none !important;
}
/* v202 — Profile button in the right slot of the chat head. Inherits
   .header-profile styling (size, ring, avatar) so it looks identical to
   the global header avatar — same anchor, different home. */
.chat-head-profile {
  background: transparent;
  border: 0;
  padding: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  justify-self: end;
}
.chat-head-profile .header-avatar {
  width: 32px;
  height: 32px;
}
.chat-head-title {
  text-align: center;
  display: flex; flex-direction: column;
  align-items: center;
}
.chat-head-title h1 { margin: 0; font-size: 18px; font-family: var(--serif); }
.chat-head-title .chat-sub { font-size: 11px; }
.chat-head h1 {
  margin: 0;
  font-size: 24px;
}
.chat-sub {
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.06em;
}
.chat-profile-btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--cream-warm);
  padding: 0;
  overflow: hidden;
  cursor: pointer;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.chat-profile-avatar {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--cream-warm) center/cover no-repeat;
  font-family: var(--serif);
  font-size: 18px;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
}
.chat-profile-avatar.has-img { color: transparent; }

/* Channel drawer toggle, small icon in the chat header, left of title */
.chat-rooms-toggle {
  background: transparent;
  border: 0;
  padding: 6px;
  color: var(--gold-deep);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  transition: background 0.12s, transform 0.12s, color 0.12s;
  flex-shrink: 0;
}
.chat-rooms-toggle:active { transform: scale(0.92); background: rgba(245, 194, 0, 0.12); color: var(--gold); }

/* Drawer, slides in from the left, dims the rest */
.room-drawer {
  position: fixed; inset: 0;
  z-index: 9000;
  display: flex;
  pointer-events: auto;
  /* v201 — dvh covers iOS address-bar / toolbar chrome so the drawer is
     bounded by the *actual* visible viewport. Falls back to vh on older
     browsers, then to inset: 0 above. */
  height: 100vh;
  height: 100dvh;
}
.room-drawer[hidden] { display: none; }
.room-drawer-backdrop {
  position: absolute; inset: 0;
  background: rgba(20, 20, 20, 0.45);
  opacity: 0;
  transition: opacity 0.25s ease;
}
.room-drawer.open .room-drawer-backdrop { opacity: 1; }
.room-drawer-panel {
  position: relative;
  box-sizing: border-box;
  width: min(300px, 82vw);
  max-width: 300px;
  height: 100%;
  /* v201 — Hard upper bound. If the parent height is somehow miscalculated
     by Safari, this guarantees the panel still respects the visible viewport
     and the list inside gets a real overflow boundary to scroll against. */
  max-height: 100vh;
  max-height: 100dvh;
  background: var(--cream);
  transform: translateX(-100%);
  transition: transform 0.28s var(--ease-spring-soft);
  box-shadow: 8px 0 24px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.room-drawer.open .room-drawer-panel { transform: translateX(0); }

.room-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 16px 12px;
  border-bottom: 1px solid var(--line);
}
.room-drawer-title {
  font-family: var(--serif);
  font-size: 18px;
  color: var(--ink);
  letter-spacing: 0.04em;
}
.room-drawer-close {
  background: transparent;
  border: 0;
  font-size: 28px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 0 6px;
  -webkit-tap-highlight-color: transparent;
}

.room-drawer-list {
  flex: 1 1 auto;
  min-height: 0; /* v198 — required so the flex child can actually shrink + scroll instead of pushing past the panel */
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px 0 12px;
  -webkit-overflow-scrolling: touch;
}

.room-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 16px;
  background: transparent;
  border: 0;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  font-family: var(--sans);
  color: var(--ink-soft);
  transition: background 0.12s, color 0.12s;
}
.room-row:active { background: rgba(20,20,20,0.04); }
.room-row.active {
  background: rgba(245, 194, 0, 0.18);
  color: var(--ink);
}
.room-row.active::before {
  content: "";
  position: absolute;
  left: 0;
  width: 3px;
  height: 32px;
  background: var(--gold);
  border-radius: 0 3px 3px 0;
}
.room-row { position: relative; }
.room-row.locked { color: var(--muted); }
.room-row.admin { color: var(--ink); }
/* v646 — Discord-style unread badge (admins only). Red circle, white number. */
.room-unread {
  margin-left: auto;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px; background: #E5484D; color: #fff;
  font: 700 11px/20px var(--sans); text-align: center;
  box-shadow: 0 1px 4px rgba(0,0,0,.4); flex-shrink: 0;
}
.room-unread[hidden] { display: none; }
/* v647 — badge anchored to the speech-bubble icon, tucked on its top-right
   corner so it sits INSIDE the Community pill rather than off its edge. */
#nav-devchat .icon-bg { position: relative; overflow: visible; }
.nav-unread {
  position: absolute; top: -5px; right: -10px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 999px; background: #E5484D; color: #fff;
  font: 700 10px/17px var(--sans); text-align: center;
  box-shadow: 0 0 0 2px var(--cream); pointer-events: none; z-index: 3;
}
.nav-unread[hidden] { display: none; }
.room-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  font-size: 14px;
  color: var(--muted);
  flex-shrink: 0;
}
.room-row.active .room-row-icon { color: var(--gold-deep); }
.room-row-body { display: flex; flex-direction: column; min-width: 0; }
.room-row-name {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
}
.room-row-desc {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Premium section header inside the drawer */
.room-section-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 18px 16px 6px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.room-section-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-deep);
  white-space: nowrap;
}
.room-section-line {
  flex: 1;
  height: 1px;
  background: linear-gradient(to right, rgba(245, 194, 0, 0.4), transparent);
}

/* Paywalled rooms (locked or unlocked) get a subtle gold tint */
.room-row.paywalled .room-row-icon { color: var(--gold-deep); }
.room-row.paywalled.locked { background: rgba(245, 194, 0, 0.04); }

/* Emoji icons render larger than the old hash glyph */
.room-row-icon { font-size: 18px; }

/* Tier channel colour coding. Each row tints to match its programme:
   Foundations green, Development blue, Elite gold. No row reads as "above"
   another, the only signal is the colour link to the Vault programme. */
.room-row.tier-row {
  border-left: 3px solid transparent;
  margin-left: -3px;
}
.room-row.tier-row .room-row-name { font-weight: 700; }
.room-row.tier-1 { border-left-color: var(--tier-green); }
.room-row.tier-1 .room-row-name { color: var(--tier-green); }
.room-row.tier-2 { border-left-color: var(--tier-blue); }
.room-row.tier-2 .room-row-name { color: var(--tier-blue); }
.room-row.tier-3 { border-left-color: var(--gold); }
.room-row.tier-3 .room-row-name { color: var(--gold-deep); }
/* v198 — Miles' Programme chat room in the drawer. */
.room-row.tier-miles-programme { border-left-color: var(--miles-blue); }
.room-row.tier-miles-programme .room-row-name { color: var(--miles-blue-deep); }
.room-row.tier-miles-programme.active { background: rgba(126, 200, 227, 0.14); }
.room-row.tier-miles-programme.active::before { background: var(--miles-blue); }
/* v636 — Booty Programme channel, pink accent to match the programme. */
.room-row.tier-booty-programme { border-left-color: #E91E8C; }
.room-row.tier-booty-programme .room-row-name { color: #F06FB5; }
.room-row.tier-booty-programme.active { background: rgba(233, 30, 140, 0.14); }
.room-row.tier-booty-programme.active::before { background: #E91E8C; }
.room-row.tier-row.active .room-row-name { color: var(--ink); }
.room-row.tier-1.active { background: rgba(59, 109, 17, 0.12); }
.room-row.tier-1.active::before { background: var(--tier-green); }
.room-row.tier-2.active { background: rgba(24, 95, 165, 0.12); }
.room-row.tier-2.active::before { background: var(--tier-blue); }
.room-row.tier-3.active { background: rgba(245, 194, 0, 0.18); }
.room-row.tier-3.active::before { background: var(--gold); }

/* Instagram-style heart pop on double-tap of a chat message + persistent like badge.
   Suppress iOS native text-selection + Copy/Look Up/Translate callout so the only
   thing that surfaces on long-press is the app's own action sheet (Discord parity).
   The chat input field keeps default selection because the rule is scoped to .msg. */
.msg {
  position: relative;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
.msg * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.msg-heart-pop {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.2);
  opacity: 0;
  pointer-events: none;
  z-index: 5;
  filter: drop-shadow(0 4px 12px rgba(255, 51, 68, 0.4));
}
.msg-heart-pop.animate { animation: msg-heart-pop 720ms ease-out forwards; }
@keyframes msg-heart-pop {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
  35%  { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
  60%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1); }
}

/* Instagram comment style heart. Pinned to the right edge of the message and
   vertically anchored so the icon centre sits on the first line of body text
   (just below the sender row, ~24px from the top of the message box).
   Hollow heart by default, fills red when liked. Count tucked underneath,
   hidden when zero so the layout reserves the spot and never jitters when
   the first like lands. */
.msg-like {
  position: absolute;
  top: 24px;
  right: 4px;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 4px;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font: 600 10px var(--sans);
  line-height: 1;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s, transform 0.12s;
  z-index: 3;
}
.msg-like svg {
  display: block;
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.msg-like .msg-like-count { line-height: 1; min-height: 10px; }
.msg-like.liked { color: #FF3344; }
.msg-like.liked svg { fill: currentColor; stroke: currentColor; }
.msg-like.empty .msg-like-count { visibility: hidden; }
.msg-like:active { transform: scale(0.88); }
@media (hover: hover) {
  .msg-like:hover { color: #FF3344; }
}

.chat-stream {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 16px 14px 8px;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scroll-behavior: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* Skip rendering offscreen messages so iOS doesn't choke on long histories. */
.msg {
  content-visibility: auto;
  contain-intrinsic-size: auto 60px;
}
.chat-empty {
  margin: auto;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  max-width: 260px;
  padding: 30px 12px;
}

.chat-day {
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 14px 0 4px;
}

/* Discord-style flat layout. Right padding reserves space for the absolute
   .msg-like heart so body text never flows under it. Original spacing. */
.msg {
  display: grid;
  grid-template-columns: 40px 1fr;
  column-gap: 12px;
  align-self: stretch;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 6px 40px 4px 4px;
  margin: 0;
  font-size: 15px;
  line-height: 1.4;
  word-wrap: break-word;
  max-width: 100%;
}
.msg.mine { align-self: stretch; }
.msg .avatar {
  grid-column: 1;
  grid-row: 1 / span 4;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin: 0;
  border: 0;
  background: var(--cream-warm) center/cover no-repeat;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 16px;
  color: var(--ink);
  flex-shrink: 0;
}
.msg .sender-row {
  grid-column: 2;
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 2px;
}
.msg .sender {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0;
  text-transform: none;
}
.msg.mine .sender { color: var(--gold-deep); }
.msg .time {
  font-size: 11px;
  color: var(--muted);
  font-weight: 400;
  letter-spacing: 0.02em;
}
.msg .body {
  grid-column: 2;
  white-space: pre-wrap;
  color: var(--ink-soft);
}
.msg .voice-row,
.msg .img-wrap,
.msg .v-transcript {
  grid-column: 2;
}
.msg .v-transcript { margin-top: 4px; }
.msg.image .img-wrap { margin: 2px 0 0; max-width: 320px; }
.msg.image .body { margin-top: 4px; }

/* Date separator, true centre */
.chat-day {
  align-self: center;
  display: inline-block;
  padding: 4px 10px;
  background: var(--cream);
}

/* Action sheet for edit/delete */
.chat-actions {
  position: fixed;
  inset: 0;
  z-index: 75;
  display: none;
  align-items: flex-end;
  justify-content: center;
}
.chat-actions.open { display: flex; }
.chat-actions-backdrop {
  position: absolute; inset: 0;
  background: rgba(20,20,20,0.45);
}
.chat-actions-card {
  position: relative;
  width: calc(100% - 24px);
  max-width: 420px;
  margin: 0 12px calc(12px + var(--safe-bottom));
  display: flex;
  flex-direction: column;
  gap: 8px;
  animation: sheet-up 0.18s cubic-bezier(.2,.8,.2,1);
}
.chat-action-btn {
  background: rgba(255,255,255,0.96);
  border: 0;
  padding: 16px;
  font-size: 16px;
  font-family: var(--sans);
  color: var(--ink);
  border-radius: 14px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.chat-action-btn.destructive { color: #C42332; font-weight: 500; }
.chat-action-btn.cancel { font-weight: 600; }

/* Edit mode banner above composer */
.chat-edit-banner {
  display: none;
  align-items: center;
  justify-content: space-between;
  padding: 8px 14px;
  background: rgba(245, 194, 0, 0.18);
  border-top: 1px solid var(--gold);
  font-size: 12px;
  color: var(--ink-soft);
  letter-spacing: 0.04em;
}
.chat-edit-banner.open { display: flex; }
.chat-edit-banner button {
  background: transparent;
  border: 0;
  color: var(--ink-soft);
  font-size: 13px;
  cursor: pointer;
  padding: 4px 6px;
}
.msg .body .edited {
  font-size: 11px;
  color: var(--muted);
  margin-left: 6px;
  font-style: italic;
}
.msg.deleting { opacity: 0.4; pointer-events: none; }

.msg.voice .voice-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.msg.voice .v-play {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #141414;
  color: var(--ink);
  border: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}
.msg.voice .v-bar {
  flex: 1;
  height: 24px;
  background: linear-gradient(90deg, rgba(20,20,20,0.18) 0%, rgba(20,20,20,0.18) 50%, rgba(20,20,20,0.08) 50%, rgba(20,20,20,0.08) 100%);
  background-size: 200% 100%;
  background-position: right;
  border-radius: 4px;
  position: relative;
  overflow: hidden;
}
.msg.voice .v-bar::after {
  content: "";
  position: absolute;
  inset: 10px 0;
  background:
    repeating-linear-gradient(90deg,
      currentColor 0 2px,
      transparent 2px 4px);
  opacity: 0.35;
}
.msg.voice .v-dur {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.msg.voice .v-transcript {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.4;
  font-style: italic;
}
.msg.voice .v-transcript.pending { opacity: 0.5; }

.msg.image .img-wrap {
  display: inline-block;     /* hug the image — no empty right gutter */
  margin: 2px 0 4px;
  border-radius: 14px;
  overflow: hidden;
  cursor: zoom-in;
  max-width: 320px;
  line-height: 0;            /* kill the descender gap that left a flat edge */
}
.msg.image img {
  display: block;
  max-width: 100%;
  max-height: 280px;
  width: auto;
  height: auto;
  border-radius: 14px;       /* belt-and-braces in case overflow misses on iOS */
}
.msg.image .body { font-size: 14px; }

.chat-composer {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  gap: 6px;
  /* v190 — Safe-bottom moved to the bottom-nav (which now sits below us).
     Composer just needs its own 8px breathing room. */
  padding: 8px 10px 8px;
  /* v381 — was beige rgba(250,246,236,.94); dark theme. */
  background: rgba(14, 14, 16, 0.94);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-top: 1px solid var(--line);
}
/* v485 — composer restyled to match Sam's reference: round dark photo button,
   rounded pill input, round olive up-arrow send. */
.chat-composer textarea {
  flex: 1;
  min-height: 42px;
  max-height: 120px;
  resize: none;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: #1C1C1E;
  padding: 11px 16px;
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.35;
  color: var(--ink);
  outline: none;
}
.chat-composer textarea::placeholder { color: #8A8A8E; }
.chat-composer textarea:focus {
  border-color: rgba(174, 184, 63, 0.55);
  box-shadow: 0 0 0 3px rgba(174, 184, 63, 0.16);
}
.chat-composer button {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
/* round dark photo button */
.chat-composer .chat-attach { background: #1C1C1E; color: #FFFFFF; }
.chat-composer .chat-mic { background: var(--gold); }
.chat-composer .chat-mic:active,
.chat-composer .chat-mic.recording { background: var(--gold-deep); transform: scale(1.05); }
/* round YELLOW send with dark up-arrow; always visible — translucent until
   there's text/photo, then lights up (v485b, Sam). */
.chat-composer .chat-send {
  background: var(--gold);
  color: #15150A;
  opacity: 1;
  transition: opacity 0.18s ease;
}
.chat-composer .chat-send:active { background: var(--gold-deep); }
.chat-composer .chat-send.inactive {
  opacity: 0.3;
  pointer-events: none;   /* can't tap until it lights up */
}

/* Inline recording panel, two rows, replaces composer */
.chat-recording {
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 10px 14px calc(10px + var(--safe-bottom));
  background: rgba(250, 246, 236, 0.96);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-top: 1px solid var(--line);
}
.chat-recording.open { display: flex; }
/* v484 — staged photo preview (draft) above the composer, like WhatsApp. */
.chat-pending-image { display: none; }
.chat-pending-image.open {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px 0;
}
.chat-pending-image img {
  width: 56px; height: 56px;
  border-radius: 10px;
  object-fit: cover;
  box-shadow: 0 2px 6px rgba(0,0,0,0.45);
}
.chat-pending-x {
  background: rgba(0,0,0,0.55);
  color: #fff;
  border: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  flex: 0 0 auto;
}

.chat-recording.open ~ .chat-composer { display: none; }

.chat-rec-top {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 4px 0;
}
.chat-rec-elapsed {
  font-family: var(--sans);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  min-width: 40px;
}
.chat-rec-canvas {
  flex: 1;
  height: 36px;
  display: block;
  width: 100%;
}
.chat-rec-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 2px 8px;
}
.chat-rec-trash, .chat-rec-pause, .chat-rec-send {
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 0;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.chat-rec-trash {
  background: transparent;
  color: var(--ink-soft);
}
.chat-rec-pause {
  background: transparent;
  color: #E0263A;
  border: 2px solid #E0263A;
  position: relative;
}
.chat-rec-pause .rec-play-ico { display: none; }
.chat-rec-pause.paused .rec-pause-ico { display: none; }
.chat-rec-pause.paused .rec-play-ico { display: block; }
.chat-rec-send {
  background: var(--gold);
  color: var(--ink);
}

.chat-img-viewer {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 20px;
}
.chat-img-viewer img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* Toast for errors */
.chat-toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--nav-h) + 90px + var(--safe-bottom));
  transform: translateX(-50%);
  background: rgba(20,20,20,0.94);
  color: var(--cream-warm);
  font-size: 13px;
  letter-spacing: 0.02em;
  padding: 10px 16px;
  border-radius: 999px;
  z-index: 80;
  max-width: 86%;
  text-align: center;
  box-shadow: 0 4px 14px rgba(0,0,0,0.25);
  animation: toast-in 0.2s ease;
}
@keyframes toast-in {
  from { opacity: 0; transform: translate(-50%, 6px); }
  to { opacity: 1; transform: translateX(-50%); }
}

/* Recording level glow on the pulse */
.chat-rec-pulse.live {
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}


/* Profile sheet, closed by default, opens via .open class only */
.chat-sheet {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: none;
  align-items: flex-end;
  justify-content: center;
}
.chat-sheet.open {
  display: flex;
}
.chat-sheet-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20,20,20,0.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: fadein 0.18s ease;
}
.chat-sheet-card {
  position: relative;
  width: 100%;
  max-width: 520px;
  background: var(--cream);
  border-top-left-radius: 22px;
  border-top-right-radius: 22px;
  padding: 22px 22px calc(22px + var(--safe-bottom));
  box-shadow: 0 -10px 30px rgba(0,0,0,0.18);
  animation: sheet-up 0.22s cubic-bezier(.2,.8,.2,1);
  max-height: 90vh;
  overflow-y: auto;
}
@keyframes sheet-up {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}
.chat-sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.chat-sheet-head h2 { margin: 0; font-size: 24px; }
.chat-sheet-close {
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 0;
  background: transparent;
  font-size: 26px;
  line-height: 1;
  color: var(--ink);
  cursor: pointer;
}
.chat-sheet-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.profile-avatar-edit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 6px 0 4px;
  cursor: pointer;
}
.profile-avatar-img {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 36px;
  color: var(--muted);
  box-shadow: var(--shadow);
}
.profile-avatar-hint {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.profile-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.profile-field span {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  padding-left: 2px;
}
.profile-field input {
  font-family: var(--sans);
  font-size: 15px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--cream-warm);
  color: var(--ink);
  outline: none;
}
.profile-field input:focus {
  border-color: var(--gold-deep);
  box-shadow: 0 0 0 3px rgba(245, 194, 0, 0.18);
}
.profile-logout {
  margin-top: 4px;
  background: transparent;
  border: 0;
  color: var(--muted);
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 12px;
  cursor: pointer;
}

/* Admin entry-point inside the profile sheet, only shown to sam/miles/charlie */
.profile-admin {
  margin-top: 8px;
  background: transparent;
  border: 1.5px solid var(--gold);
  color: var(--gold-deep);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 12px;
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, color 0.15s ease, transform 0.12s ease;
}
.profile-admin:active {
  background: var(--gold);
  color: var(--ink);
  transform: scale(0.98);
}
.profile-admin[hidden] { display: none !important; }

/* tighter bottom-nav for 6 buttons */
.bottom-nav button { padding: 8px 2px; }
.bottom-nav button .icon-bg { width: 34px; }

/* ===========================================================================
   Tier system (Vault → tier cards → preview sheet → programme tab)
   =========================================================================== */
:root {
  --tier-green: #3B6D11;
  --tier-blue: #185FA5;
  --tier-gold: #F5C200;
  /* v198 — Extra-curricular programmes. Baby metallic blue (Blue-Eyes White
     Dragon vibe), distinct from --tier-blue Development. */
  --miles-blue: #7EC8E3;
  --miles-blue-deep: #4FAACB;
  /* v342 — Booty Programme: pink accent, distinct from Miles' baby-blue. */
  --booty-pink: #E91E8C;
  --booty-pink-deep: #C2185B;
  /* v386 — streak lightning accent, matches the lightning-loader Lottie. */
  --lightning-blue: #28ACFF;
}

.tier-card {
  text-align: left;
  padding: 20px;
  margin-bottom: 14px;
  cursor: pointer;
  border-width: 1px;
  border-style: solid;
  background: var(--cream);
  color: var(--ink);
  transition: transform 0.34s var(--ease-spring-soft), box-shadow 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}
.tier-card:active { transform: scale(0.96); }
/* v429 — Translucent tier-colour wash over the cream base. Single alpha var
   per tier so Sam can dial intensity in one place. Layered gradient keeps
   the dark cream underneath so text contrast holds. */
.tier-card.tier-foundations {
  border-color: var(--tier-green);
  background: linear-gradient(rgba(59, 109, 17, 0.14), rgba(59, 109, 17, 0.14)), var(--cream);
}
.tier-card.tier-development {
  border-color: var(--tier-blue);
  background: linear-gradient(rgba(24, 95, 165, 0.14), rgba(24, 95, 165, 0.14)), var(--cream);
}
.tier-card.tier-elite {
  border-color: var(--tier-gold);
  background: linear-gradient(rgba(245, 194, 0, 0.14), rgba(245, 194, 0, 0.14)), var(--cream);
}
/* v198 — Miles' Programme: baby metallic blue. */
.tier-card.tier-miles-programme {
  border-color: var(--miles-blue);
  background: linear-gradient(rgba(126, 200, 227, 0.14), rgba(126, 200, 227, 0.14)), var(--cream);
}
/* v342 — Booty Programme: pink. */
.tier-card.tier-booty-programme {
  border-color: var(--booty-pink);
  background: linear-gradient(rgba(233, 30, 140, 0.14), rgba(233, 30, 140, 0.14)), var(--cream);
}

/* v535 — Vault overhaul. Big tier-coloured label on every card, all text white. */
.tier-card-eyebrow {
  display: block;
  font-family: var(--display);
  font-size: 40px;            /* v538 — the tier label is the hero, bigger than the title */
  font-weight: 900;
  letter-spacing: 1px;
  text-transform: uppercase;
  line-height: 1;
  margin: 0 0 8px;
}
.tier-card.tier-foundations     .tier-card-eyebrow { color: var(--tier-green); }
.tier-card.tier-development      .tier-card-eyebrow { color: var(--tier-blue); }
.tier-card.tier-elite           .tier-card-eyebrow { color: var(--tier-gold); }
.tier-card.tier-miles-programme  .tier-card-eyebrow { color: var(--miles-blue); }
.tier-card.tier-booty-programme  .tier-card-eyebrow { color: var(--booty-pink); }
.tier-card-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.tier-card-title {
  font-family: var(--display);
  font-weight: 400;
  font-size: 23px;           /* v538 — now a subheading under the big tier label */
  letter-spacing: 0.02em;
  line-height: 1.1;
  margin: 0 0 8px;
  color: #F6F2E8;
}
.tier-card-blurb {
  margin: 0 0 12px; font-size: 14px; line-height: 1.55; color: #E4DFD3;
}
.tier-card-meta {
  display: flex; flex-wrap: wrap; gap: 6px;
  font-size: 12.5px; color: #CBC5B8; letter-spacing: 0.02em;
}

.tier-badge {
  display: inline-block; padding: 4px 10px;
  border-radius: 999px; font-size: 11px;
  letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 700; color: var(--cream-warm);
}
.tier-badge-foundations { background: var(--tier-green); }
.tier-badge-development { background: var(--tier-blue); }
.tier-badge-elite { background: var(--tier-gold); color: var(--ink); }
.tier-badge-miles-programme { background: var(--miles-blue); color: var(--ink); }
/* v342 — Booty Programme badge. Both class spellings: the Vault card uses the
   hyphen form, the preview-sheet badge is generated as tier-badge-${tier}
   (underscore). Define both so the pink renders in both places. */
.tier-badge-booty-programme,
.tier-badge-booty_programme { background: var(--booty-pink); color: var(--cream-warm); }

/* v198 — Extra-curricular header inside the Vault. Visually separates the
   sideways programmes from the three tiers. */
/* v536 — centred, big "EXTRA PROGRAMMES" heading. */
.vault-extras-head {
  text-align: center;
  margin: 32px 2px 18px;
  padding-top: 24px;
  border-top: 1px solid rgba(250, 246, 236, 0.10);
}
.vault-extras-eyebrow {
  display: block;
  font-family: var(--display);
  font-size: 30px; font-weight: 900; letter-spacing: 1px;
  text-transform: uppercase;
  color: #F6F2E8;
  margin-bottom: 8px;
}
.vault-extras-blurb {
  margin: 0 auto; max-width: 330px; font-size: 13px; line-height: 1.55;
  color: #CBC5B8; text-align: center;
}
/* v535 — Vault: lift every remaining dim grey to readable white. */
#section-vault .section-head .date,
#section-vault .muted { color: #CBC5B8 !important; }
/* v537/539 — Vault title stays TOP-LEFT; intro line + every card centred. */
#section-vault .section-head { justify-content: flex-start; text-align: left; }
#section-vault > .muted { text-align: center; }
#section-vault .tier-card { text-align: center; position: relative; }
/* v540 — mini Apple pass tuned for the DARK theme. Black drop-shadows vanish on
   a near-black bg, so depth comes from: a THICKER brighter tier border, a
   per-tier COLOURED glow (visible on dark), a top inner light highlight (raised
   glass), and a subtle sheen gradient over the surface. */
#section-vault .tier-card {
  border-radius: 20px;
  border-width: 3.5px;       /* v542 — chunkier, clearly-visible tier border */
  padding: 24px 20px;
  /* v544 — barely-there drop shadow + a top inner highlight. */
  box-shadow: 0 3px 9px -7px rgba(0,0,0,0.16), inset 0 1px 0 rgba(255,255,255,0.10);
}
#section-vault .tier-card::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  background: linear-gradient(180deg, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0) 34%, rgba(0,0,0,0.16) 100%);
}
#section-vault .tier-card > * { position: relative; }
#section-vault .tier-card:active { transform: scale(0.975); }
#section-vault .tier-card-eyebrow { text-shadow: 0 1px 2px rgba(0,0,0,0.12); }
#section-vault .tier-card .tier-card-meta { justify-content: center; }
/* v538 — drop the redundant name pill; the big tier label says it all. The
   status sits quietly in the top-right corner instead of a centred row. */
#section-vault .tier-card .tier-badge { display: none; }
#section-vault .tier-card .tier-card-head {
  position: absolute; top: 14px; right: 14px; margin: 0;
  justify-content: flex-end;
}
#section-vault .tier-card-status:empty { display: none; }
/* v538 — the active programme gets a pulsing pill in its tier colour. */
#section-vault .tier-card-status.active {
  color: #0E0E10; padding: 5px 13px; border-radius: 999px;
  font-weight: 800; background: #fff;
  animation: vault-active-pulse 1.9s ease-in-out infinite;
}
#section-vault .tier-foundations    .tier-card-status.active { background: var(--tier-green); }
#section-vault .tier-development     .tier-card-status.active { background: var(--tier-blue);  color: #fff; }
#section-vault .tier-elite           .tier-card-status.active { background: var(--tier-gold); }
#section-vault .tier-miles-programme .tier-card-status.active { background: var(--miles-blue); }
#section-vault .tier-booty-programme .tier-card-status.active { background: var(--booty-pink); color: #fff; }
@keyframes vault-active-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

/* v343 — UNIVERSAL data-driven tier ring. One set of rules for every avatar
   surface in the app. Colour comes from --ring-colour, set inline by
   crestApplyRing()/crestRingFrag() (app.js) from the programme's colour. To add
   a new programme's ring everywhere: nothing here changes — just give it a
   `colour` in tiers.js TIER_META. The legacy per-tier rules below are now dead
   (no element carries has-tier-<slug> anymore) but left in place to avoid churn.
   Header gets a border (its overflow:hidden clips a shadow); everything else a
   box-shadow ring; profile heroes a slightly thicker 3px ring. */
.header-profile.has-tier-ring { border: 2px solid var(--ring-colour) !important; }
.avatar.has-tier-ring,
.feed-post-avatar.has-tier-ring,
.fpc-comment-avatar.has-tier-ring,
.post-avatar.has-tier-ring,
.fpc-avatar.has-tier-ring,
.comment-avatar.has-tier-ring,
.composer-avatar.has-tier-ring,
.completion-avatar.has-tier-ring,
.chat-avatar.has-tier-ring { box-shadow: 0 0 0 2px var(--ring-colour); }
.prof-hero-avatar.has-tier-ring { box-shadow: 0 0 0 3px var(--ring-colour); }
.strip-avatar.has-tier-ring .strip-avatar-photo { box-shadow: 0 0 0 3px var(--ring-colour); }
/* v402 — tier ring on the profile + member-sheet avatar. Rendered as a box-shadow
   ring OUTSIDE the (border-less, v398) photo, so the picture stays clean edge-to-
   edge and the tier colour reads as a deliberate ring — not a flatten border on
   the image. Matches the strip avatars. Fires for every tier via --ring-colour
   (crestApplyRing), so Marina's Booty pink shows when you open her profile. */
.prof-v2-hero.has-tier-ring .prof-v2-avatar { box-shadow: 0 0 0 3px var(--ring-colour); }
.prof-v2-tier.has-tier-ring { color: var(--ring-colour); }
.member-sheet .prof-v2-hero.has-tier-ring,
.member-sheet .prof-v2-tier.has-tier-ring { box-shadow: none; }

.tier-card-status {
  font-size: 11px; letter-spacing: 0.08em;
  text-transform: uppercase; color: #CBC5B8; font-weight: 600;
}
.tier-card-status.active {
  color: var(--ink); background: rgba(245, 194, 0, 0.18);
  padding: 4px 10px; border-radius: 999px;
}

/* Preview sheet */
.tier-sheet {
  position: fixed; inset: 0; z-index: 9000;
  display: flex; align-items: flex-end; justify-content: center;
}
.tier-sheet[hidden] { display: none; }
.tier-sheet-backdrop {
  position: absolute; inset: 0; background: rgba(0,0,0,0.45);
  animation: tier-fade-in 0.2s ease;
}
.tier-sheet-panel {
  position: relative; z-index: 1;
  width: 100%; max-width: 560px;
  background: var(--cream); color: var(--ink);
  border-radius: 24px 24px 0 0;
  padding: 0;
  max-height: 92vh; overflow-y: auto;
  display: flex; flex-direction: column;
  /* v512 — literal easing. --ease-spring-soft is self-referencing (invalid),
     which killed the whole animation → the sheet "spawned" instead of sliding. */
  animation: tier-slide-up 0.42s cubic-bezier(0.22, 0.9, 0.3, 1);
}
.tier-sheet-body { padding: 20px 24px 6px; }
.tier-sheet-close {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 36px; height: 36px; border-radius: 50%;
  border: 0; background: rgba(0,0,0,0.45);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  font-size: 22px; line-height: 1; color: #fff;
  cursor: pointer;
}

/* v507 — Coach intro video hero (Ladder-style). */
.tier-hero {
  position: relative; flex: 0 0 auto;
  width: 100%; height: 78vh; max-height: none;
  background: #000; overflow: hidden;
  border-radius: 24px 24px 0 0;
}
.tier-hero[hidden] { display: none; }
/* v534 — lock the hero so the video/still can't be dragged or flung around the
   screen (native image/video drag). Only the grab-handle's vertical dismiss moves it. */
.tier-hero, .tier-hero-video, .tier-hero-poster {
  -webkit-user-select: none; user-select: none;
  -webkit-user-drag: none; user-drag: none;
  -webkit-touch-callout: none;
}
.tier-hero-video {
  width: 100%; height: 100%; object-fit: cover; display: block; background: #000;
}
/* v526 — custom still (Charlie smiling) crossfades into the video on play, and
   back in when it ends. Sits over the video; fades out (not to black) when the
   hero is in 'playing' state. */
.tier-hero-poster {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 1; pointer-events: none;
  /* v533 — slower, smooth ease-in-out (auto-bezier) crossfade. */
  transition: opacity 0.95s cubic-bezier(0.42, 0, 0.58, 1);
}
.tier-hero.playing-video .tier-hero-poster { opacity: 0; }
/* v531/533 — at the end the video fades to black; after a beat the still rolls back in. */
.tier-hero-video { transition: opacity 0.95s cubic-bezier(0.42, 0, 0.58, 1); }
.tier-hero.video-faded .tier-hero-video { opacity: 0; }
.tier-hero-controls {
  position: absolute; inset: 0; z-index: 2;
  display: flex; align-items: center; justify-content: center; gap: 18px;
  transition: opacity 0.25s ease;
}
.tier-hero.controls-hidden .tier-hero-controls { opacity: 0; pointer-events: none; }
.tier-hero-ctrl {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  background: transparent; border: 0; cursor: pointer; color: #fff; padding: 0;
  -webkit-tap-highlight-color: transparent;
}
.tier-hero-ico {
  width: 62px; height: 62px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; border: 0;
  /* v515 — liquid-glass WITHOUT backdrop-filter (blurring a moving video
     flickers). A frosted fill + a light top rim + depth shadow fakes the glass
     and stays rock-steady. */
  /* v520 — clean translucent glass: a soft light fill + a single hairline of
     inner light (no heavy gradient, no border, no drop-shadow stack). Reads as
     Apple liquid glass, not a plasticky button. */
  background: rgba(255,255,255,0.13);
  box-shadow: inset 0 1px 1px rgba(255,255,255,0.30), 0 2px 10px rgba(0,0,0,0.18);
}
.tier-hero-ctrl-main .tier-hero-ico {
  width: 78px; height: 78px;
  background: rgba(255,255,255,0.18);
  box-shadow: inset 0 1px 2px rgba(255,255,255,0.42), 0 2px 12px rgba(0,0,0,0.20);
}
/* v515 — marching-ants loader removed; the video loads fast enough that it's
   just noise. */
.tier-hero-loader { display: none !important; }
/* v515 — feather the bottom of the video so it melts seamlessly into the dark
   sheet body below instead of a hard edge. */
.tier-hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 96px; pointer-events: none; z-index: 1;
  background: linear-gradient(to bottom, rgba(14,14,16,0) 0%, var(--cream) 100%);
}

/* v510 — grab handle + swipe-down-to-close (matches the profile sheets). */
.tier-sheet-grab {
  position: absolute; top: 0; left: 0; right: 0; height: 92px; z-index: 5;
  display: flex; align-items: flex-start; justify-content: center;
  cursor: grab; touch-action: none;
}
.tier-sheet-grab::before {
  content: ""; width: 40px; height: 5px; border-radius: 3px; margin-top: 9px;
  background: rgba(255,255,255,0.75);
  box-shadow: 0 1px 4px rgba(0,0,0,0.45);
}
.tier-sheet-panel.snap { transition: transform 0.3s ease; }
/* fade the video back to its first frame when it ends */
.tier-hero-lbl {
  font-size: 12px; font-weight: 600; color: #fff;
  text-shadow: 0 1px 4px rgba(0,0,0,0.65);
}
.tier-hero-loader {
  position: absolute; inset: 0; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.32);
}
.tier-hero-loader[hidden] { display: none; }
.tier-hero-spinner {
  width: 46px; height: 46px; border-radius: 50%;
  border: 3px dashed rgba(255,255,255,0.9);
  animation: tier-ants-spin 1.1s linear infinite;
}
@keyframes tier-ants-spin { to { transform: rotate(360deg); } }

/* Pinned CTA footer — sticks to the bottom as the sheet scrolls. */
.tier-sheet-cta {
  position: sticky; bottom: 0; z-index: 2;
  margin-top: auto;
  padding: 14px 24px calc(20px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(to top, var(--cream) 74%, rgba(0,0,0,0));
}
/* v522 — restructured header. NAME under the big TIER N, centred. */
.tier-sheet-badge {
  text-align: center;
  font-family: var(--display);
  font-size: 21px; letter-spacing: 2px; text-transform: uppercase;
  color: #F4F0E4; font-weight: 700;
  text-indent: 2px; /* v523 — cancel trailing letter-spacing → truly centred */
  margin: -6px 0 10px;
}
.tier-sheet-title { display: none; }
.tier-sheet-blurb {
  font-size: 14px; line-height: 1.55; color: #CFC9BC;
  margin: 0 auto 18px; max-width: 300px; text-align: center;
}
/* v522 — three stat cards replace the dim meta line. */
.tier-sheet-meta {
  display: flex; gap: 8px; justify-content: center;
  margin-bottom: 22px;
}
.tier-stat {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 13px 6px; border-radius: 12px;
  background: rgba(255,255,255,0.05);
}
.tier-stat-num {
  font-family: var(--display); font-size: 26px; line-height: 1;
  letter-spacing: 0.5px; white-space: nowrap; color: #F4F0E4;
}
/* v534 — word values (e.g. "Intermediate") sized down so they fit the pill. */
.tier-stat-num.is-word { font-size: 18px; letter-spacing: 0.3px; }
.tier-stat-lbl {
  font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase;
  color: #A39D90; font-weight: 700;
}
.tier-foundations-bg     .tier-stat-num { color: var(--tier-green); }
.tier-development-bg     .tier-stat-num { color: var(--tier-blue); }
.tier-elite-bg           .tier-stat-num { color: var(--tier-gold); }
.tier-miles_programme-bg .tier-stat-num { color: var(--miles-blue); }
.tier-booty_programme-bg .tier-stat-num { color: var(--booty-pink); }
.tier-sheet-preview { margin-bottom: 22px; }
.tier-sheet-days {
  display: flex; flex-direction: column; gap: 11px; margin-top: 14px;
}
/* v519 — centred, single-line day rows. "DAY 1" eyebrow on top, the session on
   one line below (smaller, never wraps into a paragraph). */
.tier-day-row {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  text-align: center;
  padding: 13px 14px; background: rgba(255,255,255,0.05);
  border-radius: 12px;
}
.tier-day-row .day-label {
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: #A39D90; font-weight: 700;
}
.tier-day-row strong,
.tier-day-row .day-rest {
  font-family: var(--serif); font-size: 13.5px; font-weight: 600; font-style: normal;
  color: #F2EEE2; max-width: 100%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* v521 — big tier name at the TOP of the black body section (off the video). */
.tier-hero-title {
  text-align: center;
  font-family: var(--display);
  font-size: clamp(40px, 14vw, 62px); font-weight: 900;
  letter-spacing: 1px; text-transform: uppercase; line-height: 0.95;
  text-indent: 1px; /* v523 — cancel the trailing letter-spacing so it's truly centred */
  margin: 2px 0 12px;
}
.tier-hero-title:empty { display: none; }
.tier-foundations-bg     .tier-hero-title { color: var(--tier-green); }
.tier-development-bg     .tier-hero-title { color: var(--tier-blue); }
.tier-elite-bg           .tier-hero-title { color: var(--tier-gold); }
.tier-miles_programme-bg .tier-hero-title { color: var(--miles-blue); }
.tier-booty_programme-bg .tier-hero-title { color: var(--booty-pink); }
.tier-sheet-start {
  width: 100%; padding: 16px; font-size: 16px;
  font-family: var(--serif); border-radius: 12px;
  border: 0; cursor: pointer;
}
.tier-foundations-bg .tier-sheet-start { background: var(--tier-green); color: var(--cream-warm); }
.tier-development-bg .tier-sheet-start { background: var(--tier-blue); color: var(--cream-warm); }
.tier-elite-bg .tier-sheet-start { background: var(--tier-gold); color: var(--ink); }
/* v342 — Booty Programme preview-sheet start button (generated class uses the
   underscore form tier-booty_programme-bg). */
.tier-booty_programme-bg .tier-sheet-start { background: var(--booty-pink); color: var(--cream-warm); }
/* v534 — Miles' Programme start button in its baby-blue accent. */
.tier-miles_programme-bg .tier-sheet-start { background: var(--miles-blue); color: var(--cream-warm); }

/* v516 — rest-day rows in the sample week wear the tier colour. */
.tier-foundations-bg     .tier-day-row .day-rest { color: var(--tier-green); font-style: normal; font-weight: 600; }
.tier-development-bg     .tier-day-row .day-rest { color: var(--tier-blue);  font-style: normal; font-weight: 600; }
.tier-elite-bg           .tier-day-row .day-rest { color: var(--tier-gold);  font-style: normal; font-weight: 600; }
.tier-miles_programme-bg .tier-day-row .day-rest { color: var(--miles-blue); font-style: normal; font-weight: 600; }
.tier-booty_programme-bg .tier-day-row .day-rest { color: var(--booty-pink); font-style: normal; font-weight: 600; }

/* v517 — "View full programme" link styled like the workout-page button, but in
   the colour of the tier the card is on. */
#tier-sheet-preview {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; padding: 13px; margin: 16px 0 0;
  border-radius: 12px; border: 1px solid currentColor;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.02em; text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.tier-foundations-bg     #tier-sheet-preview { color: var(--tier-green);  background: color-mix(in srgb, var(--tier-green) 12%, transparent); }
.tier-development-bg     #tier-sheet-preview { color: var(--tier-blue);   background: color-mix(in srgb, var(--tier-blue) 13%, transparent); }
.tier-elite-bg           #tier-sheet-preview { color: var(--tier-gold);   background: color-mix(in srgb, var(--tier-gold) 14%, transparent); }
.tier-miles_programme-bg #tier-sheet-preview { color: var(--miles-blue);  background: color-mix(in srgb, var(--miles-blue) 14%, transparent); }
.tier-booty_programme-bg #tier-sheet-preview { color: var(--booty-pink);  background: color-mix(in srgb, var(--booty-pink) 13%, transparent); }

@keyframes tier-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes tier-slide-up { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* ===========================================================================
   Programme tab, appears in bottom nav after starting a tier
   =========================================================================== */
.section#section-programme {}
.programme-hero {
  background: #141414; color: var(--ink);
  border-radius: 16px; padding: 22px 22px 28px;
  margin-bottom: 16px;
}
.programme-hero .label { color: var(--gold); }
.programme-hero h1 { color: var(--ink); margin-top: 6px; margin-bottom: 6px; }
.programme-hero .programme-day {
  font-family: var(--serif); font-size: 16px;
  color: rgba(250,246,236,0.7); margin: 0 0 16px;
}
.programme-progress {
  height: 6px; background: rgba(250,246,236,0.12);
  border-radius: 999px; overflow: hidden; margin-bottom: 8px;
}
.programme-progress-bar {
  height: 100%; background: var(--gold);
  transition: width 0.4s ease;
}
.programme-progress-label {
  font-size: 11px; color: rgba(250,246,236,0.55); letter-spacing: 0.06em;
}
.programme-session {
  margin-top: 8px; padding: 22px;
  background: #141414;
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 16px;
}
.programme-session h3 {
  font-family: var(--serif); font-size: 18px; font-weight: 500;
  margin: 0 0 10px; color: var(--ink);
}
.programme-exercises {
  list-style: none; padding: 0; margin: 0 0 16px;
}
.programme-exercises li {
  padding: 12px 0; border-top: 1px solid rgba(250,246,236,0.08);
  font-size: 14px;
}
.programme-exercises li:first-child { border-top: 0; }
.programme-exercises .ex-name { color: var(--ink); font-weight: 500; }
.programme-exercises .ex-meta { color: rgba(250,246,236,0.55); font-size: 12px; margin-top: 4px; }

.programme-complete-btn {
  width: 100%; padding: 14px;
  background: var(--prog-accent, var(--gold)); color: var(--ink);
  border: 0; border-radius: 12px;
  font-family: var(--serif); font-size: 15px; cursor: pointer;
}
.programme-complete-btn:disabled { background: var(--prog-accent-soft, rgba(245,194,0,0.4)); cursor: default; }
.programme-switch {
  margin-top: 14px; text-align: center;
}
.programme-switch button {
  background: transparent; border: 0;
  color: var(--ink-soft); font-size: 13px;
  text-decoration: underline; cursor: pointer;
}

/* Programme nav button visibility, only shown when active_tier is set */
.bottom-nav button[data-target="programme"] { display: none; }
body.has-tier .bottom-nav button[data-target="programme"] { display: flex; }
body.has-tier .bottom-nav button[data-target="workout"] {
  /* Workout tab still shows alongside programme */
}

/* ===========================================================================
   Add-to-home-screen smart sheet
   =========================================================================== */
.a2hs-sheet {
  position: fixed; inset: 0; z-index: 9100;
  display: flex; align-items: flex-end; justify-content: center;
}
.a2hs-sheet[hidden] { display: none; }
.a2hs-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.5); }
.a2hs-panel {
  position: relative; z-index: 1;
  width: 100%; max-width: 480px;
  background: var(--cream); color: var(--ink);
  border-radius: 24px 24px 0 0;
  padding: 28px 24px 36px;
  text-align: center;
  animation: tier-slide-up 0.3s cubic-bezier(0.2,0.8,0.2,1);
}
.a2hs-mark {
  width: 72px; height: 72px; margin: 0 auto 16px;
  border-radius: 16px; background: #141414;
  display: flex; align-items: center; justify-content: center;
}
.a2hs-mark img { width: 52px; height: 52px; }
.a2hs-panel h2 {
  font-family: var(--serif); font-weight: 500; font-size: 22px;
  margin: 0 0 8px;
}
.a2hs-panel p { font-size: 14px; color: #5C564C; margin: 0 0 22px; line-height: 1.55; }
.a2hs-steps {
  text-align: left; margin: 0 0 22px; padding: 0; list-style: none;
}
.a2hs-steps li {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 10px 0; font-size: 14px; line-height: 1.45;
  border-top: 1px solid rgba(20,20,20,0.06);
}
.a2hs-steps li:first-child { border-top: 0; }
.a2hs-steps em { font-style: normal; color: var(--muted-dark, #8B857A); font-size: 12px; }
.a2hs-icon {
  display: inline-block; vertical-align: -3px; margin: 0 2px;
  color: var(--gold-deep);
}
.a2hs-tip {
  margin: 0 0 18px; padding: 10px 12px;
  background: rgba(245, 194, 0, 0.10);
  border: 1px solid rgba(245, 194, 0, 0.25);
  border-radius: 8px;
  font-size: 12px; line-height: 1.5;
  color: var(--ink); text-align: left;
}
.a2hs-steps .step-n {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--gold); color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; flex-shrink: 0;
}
.a2hs-steps .step-icon {
  width: 22px; height: 22px; opacity: 0.7;
}
.a2hs-actions {
  display: flex; gap: 10px;
}
.a2hs-actions button {
  flex: 1; padding: 14px; border: 0;
  border-radius: 12px; font-size: 14px; cursor: pointer;
  font-family: var(--sans); font-weight: 600;
}
.a2hs-actions .a2hs-later {
  background: rgba(20,20,20,0.06); color: var(--ink);
}
.a2hs-actions .a2hs-got-it {
  background: var(--gold); color: var(--ink);
}


/* Calendar in the top header */
.header-cal {
  background: transparent;
  border: 0;
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-soft);
  cursor: pointer;
  border-radius: 10px;
  -webkit-tap-highlight-color: transparent;
  margin-right: 8px;
}
.header-cal:active { background: rgba(20,20,20,0.06); }

/* Progress hero with separated day-of-N from progress bar */
.programme-undo-btn {
  margin-top: 12px; width: 100%;
  background: transparent;
  border: 1px solid rgba(250, 246, 236, 0.22);
  color: rgba(250, 246, 236, 0.75);
  padding: 12px; border-radius: 10px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  font-family: var(--sans);
}
.programme-undo-btn:hover { color: var(--ink); border-color: rgba(250, 246, 236, 0.40); }
.programme-undo-btn[hidden] { display: none !important; }

/* Tier colour ring on avatars.
   Note: .header-profile uses overflow:hidden so a box-shadow on the inner
   .header-avatar would be clipped. The ring is applied to the OUTER button
   via a coloured border instead. Other avatar contexts use box-shadow. */
.header-profile.has-tier-foundations { border: 2px solid var(--tier-green) !important; }
.header-profile.has-tier-development { border: 2px solid var(--tier-blue) !important; }
.header-profile.has-tier-elite       { border: 2px solid var(--gold) !important; }
.header-profile.has-tier-miles_programme { border: 2px solid var(--miles-blue) !important; }
.header-profile.has-tier-booty_programme { border: 2px solid var(--booty-pink) !important; }

.avatar.has-tier-foundations,
.feed-post-avatar.has-tier-foundations,
.fpc-comment-avatar.has-tier-foundations,
.post-avatar.has-tier-foundations,
.fpc-avatar.has-tier-foundations,
.comment-avatar.has-tier-foundations,
.composer-avatar.has-tier-foundations,
.completion-avatar.has-tier-foundations,
.chat-avatar.has-tier-foundations { box-shadow: 0 0 0 2px var(--tier-green); }
.avatar.has-tier-development,
.feed-post-avatar.has-tier-development,
.fpc-comment-avatar.has-tier-development,
.post-avatar.has-tier-development,
.fpc-avatar.has-tier-development,
.comment-avatar.has-tier-development,
.composer-avatar.has-tier-development,
.completion-avatar.has-tier-development,
.chat-avatar.has-tier-development { box-shadow: 0 0 0 2px var(--tier-blue); }
.avatar.has-tier-elite,
.feed-post-avatar.has-tier-elite,
.fpc-comment-avatar.has-tier-elite,
.post-avatar.has-tier-elite,
.fpc-avatar.has-tier-elite,
.comment-avatar.has-tier-elite,
.composer-avatar.has-tier-elite,
.completion-avatar.has-tier-elite,
.chat-avatar.has-tier-elite { box-shadow: 0 0 0 2px var(--gold); }
/* v207 — Miles' Programme baby-blue ring on every avatar surface. */
.avatar.has-tier-miles_programme,
.feed-post-avatar.has-tier-miles_programme,
.fpc-comment-avatar.has-tier-miles_programme,
.post-avatar.has-tier-miles_programme,
.fpc-avatar.has-tier-miles_programme,
.comment-avatar.has-tier-miles_programme,
.composer-avatar.has-tier-miles_programme,
.completion-avatar.has-tier-miles_programme,
.chat-avatar.has-tier-miles_programme { box-shadow: 0 0 0 2px var(--miles-blue); }
/* v342 — Booty Programme avatar ring (pink), same selector set as above. */
.avatar.has-tier-booty_programme,
.feed-post-avatar.has-tier-booty_programme,
.fpc-comment-avatar.has-tier-booty_programme,
.post-avatar.has-tier-booty_programme,
.fpc-avatar.has-tier-booty_programme,
.comment-avatar.has-tier-booty_programme,
.composer-avatar.has-tier-booty_programme,
.completion-avatar.has-tier-booty_programme,
.chat-avatar.has-tier-booty_programme { box-shadow: 0 0 0 2px var(--booty-pink); }

/* Programme day-strip, horizontal scroll of day pills, like the workout day-strip */
.prog-day-strip-wrap {
  margin-bottom: 14px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.prog-day-strip-wrap::-webkit-scrollbar { display: none; }
.prog-day-strip {
  display: inline-flex;
  gap: 8px;
  padding: 4px 2px;
}
.prog-day-pill {
  flex: 0 0 auto;
  min-width: 56px;
  padding: 10px 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--cream-warm);
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, color 0.15s ease;
}
.prog-day-pill .pill-num {
  font-family: var(--serif);
  font-size: 18px;
  color: var(--ink);
  letter-spacing: 0;
}
.prog-day-pill.selected {
  border-color: var(--prog-accent, var(--ink));
  background: var(--prog-accent-soft, #141414);
  color: var(--ink);
}
.prog-day-pill.selected .pill-num { color: var(--ink); }
.prog-day-pill.done {
  background: var(--prog-accent-soft, rgba(245, 194, 0, 0.18));
  border-color: var(--prog-accent, var(--gold));
}
.prog-day-pill.done .pill-num { color: var(--ink); }
.prog-day-pill.done.selected {
  background: var(--prog-accent, var(--gold));
  border-color: var(--prog-accent, var(--gold));
}
.prog-day-pill.done.selected .pill-num { color: var(--ink); }
.prog-day-pill.rest-day .pill-num::after {
  content: " ·";
  color: var(--muted);
}

/* Programme session head, day number + status badge */
.prog-session-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px;
}
.prog-session-day {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--prog-accent, var(--gold)); font-weight: 700;
}
.prog-session-status {
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  color: rgba(250,246,236,0.55); font-weight: 600;
}
.prog-session-status.done {
  background: var(--prog-accent-soft, rgba(245,194,0,0.22));
  color: var(--prog-accent, var(--gold));
  padding: 4px 10px; border-radius: 999px;
}
.prog-rest-line {
  font-style: italic;
  color: rgba(250,246,236,0.6);
  margin: 0 0 14px;
  font-size: 14px;
}

/* Completion-style button reused on programme (matches Workout tab .completion-btn pattern) */
.programme-complete-btn.done {
  background: rgba(245,194,0,0.18);
  color: var(--gold);
  border: 1px solid var(--gold);
}

/* Movement library shortcut button at the bottom of the programme session card */
.programme-library-btn {
  margin-top: 10px; width: 100%;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: rgba(250, 246, 236, 0.06);
  border: 1px solid rgba(250, 246, 236, 0.18);
  color: var(--ink);
  padding: 12px; border-radius: 10px;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.programme-library-btn:hover { background: rgba(250, 246, 236, 0.10); border-color: rgba(250, 246, 236, 0.32); }
.programme-library-btn svg { opacity: 0.8; }

/* CREST Agent voice mic button, pulses while recording */
.agent-mic-btn {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(20, 20, 20, 0.06);
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease;
}
.agent-mic-btn:hover { background: rgba(20, 20, 20, 0.10); }
.agent-mic-btn.recording {
  background: #B00020;
  border-color: #B00020;
  color: var(--cream-warm);
  animation: agent-mic-pulse 1.2s infinite ease-in-out;
}
.agent-mic-btn.transcribing {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
}
@keyframes agent-mic-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(176, 0, 32, 0.5); }
  50%      { box-shadow: 0 0 0 8px rgba(176, 0, 32, 0); }
}

/* ===========================================================================
   CREST AI. ChatGPT mobile clone, black with gold accents.
   When the agent panel is active, the section becomes an immersive dark
   chat surface. Other admin tools live behind the burger (see admin-burger).
   =========================================================================== */
.admin-panel.agent-panel { margin: 0; padding: 0; }
.admin-panel.agent-panel[hidden] { display: none !important; }

.agent-shell {
  display: flex; flex-direction: column;
  background: #0A0A0A;
  border-radius: 18px;
  border: 1px solid rgba(245, 194, 0, 0.18);
  overflow: hidden;
  height: calc(100dvh - var(--nav-h) - 180px);
  min-height: 520px;
  position: relative;
}

/* Header, burger left | "CREST AI" pill center | profile circle right */
.agent-header {
  display: grid;
  grid-template-columns: 44px 1fr 44px;
  align-items: center;
  padding: 12px 14px;
  border-bottom: 1px solid rgba(245, 194, 0, 0.10);
  background: #0A0A0A;
}
.agent-title {
  justify-self: center;
  display: inline-flex; align-items: center;
  background: rgba(245, 194, 0, 0.12);
  color: var(--gold);
  font-family: var(--sans);
  font-size: 14px; font-weight: 700;
  letter-spacing: 0.06em;
  padding: 8px 18px;
  border-radius: 999px;
  border: 1px solid rgba(245, 194, 0, 0.25);
}
.agent-clear {
  background: transparent; border: 0;
  color: rgba(250,246,236,0.55);
  cursor: pointer; padding: 0; width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  -webkit-tap-highlight-color: transparent;
  font-size: 0;
}
.agent-clear svg { display: block; }
.agent-clear:hover { background: rgba(245,246,236,0.06); color: var(--gold); }
.agent-clear-label { display: none; }

.agent-pending {
  padding: 12px 18px;
  background: rgba(245, 194, 0, 0.08);
  border-bottom: 1px solid rgba(245, 194, 0, 0.20);
  flex: 0 0 auto;
  max-height: 35%;
  overflow-y: auto;
}
.agent-pending-head {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gold); font-weight: 700; margin-bottom: 10px;
}

.agent-thread {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 18px 18px 8px;
  -webkit-overflow-scrolling: touch;
  background: #0A0A0A;
}

.agent-empty {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center;
  padding: 40px 20px;
  color: rgba(250,246,236,0.55);
  min-height: 240px;
}
.agent-empty-mark {
  width: 56px; height: 56px;
  border-radius: 14px;
  background: rgba(245, 194, 0, 0.10);
  border: 1px solid rgba(245, 194, 0, 0.32);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 16px;
}
.agent-empty-mark img { width: 38px; height: 38px; }
.agent-empty h3 {
  font-family: var(--sans); font-size: 22px; font-weight: 600;
  color: var(--gold); margin: 0 0 6px;
  letter-spacing: 0.01em;
}
.agent-empty p { font-size: 14px; margin: 0 0 22px; color: rgba(250,246,236,0.55); }
.agent-suggestions {
  display: flex; flex-direction: column; gap: 8px;
  width: 100%; max-width: 360px;
}
.agent-suggestion {
  background: rgba(250,246,236,0.04);
  border: 1px solid rgba(250,246,236,0.10);
  border-radius: 14px;
  padding: 14px 16px;
  font-family: var(--sans); font-size: 14px;
  color: var(--ink); text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.agent-suggestion:hover { background: rgba(245,194,0,0.10); border-color: var(--gold); color: var(--gold); }

/* Footer. ChatGPT-style pill input with + on left, mic+send on right */
.agent-footer {
  display: grid;
  grid-template-columns: 44px 1fr 44px;
  gap: 8px;
  padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
  background: #0A0A0A;
  border-top: 1px solid rgba(245, 194, 0, 0.10);
  align-items: end;
}
.agent-footer .agent-mic-btn {
  background: rgba(250,246,236,0.05);
  border: 1px solid rgba(250,246,236,0.12);
  color: rgba(250,246,236,0.8);
}
.agent-footer .agent-mic-btn:hover { background: rgba(245,194,0,0.10); border-color: var(--gold); color: var(--gold); }
.agent-footer .agent-mic-btn.recording {
  background: #B00020 !important;
  border-color: #B00020 !important;
  color: var(--cream-warm) !important;
}

.agent-input-wrap {
  position: relative;
  display: flex;
  background: rgba(250,246,236,0.06);
  border: 1px solid rgba(250,246,236,0.12);
  border-radius: 22px;
  overflow: hidden;
}
.agent-input-wrap:focus-within { border-color: var(--gold); }
.agent-footer textarea {
  width: 100%;
  padding: 14px 16px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  resize: none;
  outline: none;
  min-height: 44px;
  max-height: 140px;
  line-height: 1.4;
}
.agent-footer textarea::placeholder { color: rgba(250,246,236,0.4); }

.agent-send-btn {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: var(--gold);
  border: 0; border-radius: 50%;
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, transform 0.05s ease;
}
.agent-send-btn:hover { background: var(--gold-deep); }
.agent-send-btn:active { transform: scale(0.94); }
.agent-send-btn:disabled { opacity: 0.4; cursor: progress; }

/* Waveform deliberately disabled, it masked the live transcript. Indicator is
   the red mic button + the words appearing in the textarea as you speak. */
.agent-rec-inline { display: none !important; }

/* Bubbles inside the dark thread */
.agent-bubble .agent-bubble-user {
  background: var(--gold); color: var(--ink);
  border-radius: 18px 18px 4px 18px;
}
.agent-bubble .agent-bubble-assistant {
  background: rgba(250,246,236,0.06);
  color: var(--ink);
  border: 1px solid rgba(250,246,236,0.10);
  border-radius: 18px 18px 18px 4px;
}
.agent-wave {
  display: flex; align-items: center; gap: 3px;
  height: 28px;
  flex: 0 0 auto;
}
.agent-wave span {
  display: inline-block;
  width: 4px; height: 8px;
  background: var(--gold);
  border-radius: 2px;
  animation: agent-wave-bounce 0.9s infinite ease-in-out;
}
.agent-wave span:nth-child(2)  { animation-delay: 0.05s; }
.agent-wave span:nth-child(3)  { animation-delay: 0.10s; }
.agent-wave span:nth-child(4)  { animation-delay: 0.15s; }
.agent-wave span:nth-child(5)  { animation-delay: 0.20s; }
.agent-wave span:nth-child(6)  { animation-delay: 0.25s; }
.agent-wave span:nth-child(7)  { animation-delay: 0.30s; }
.agent-wave span:nth-child(8)  { animation-delay: 0.35s; }
.agent-wave span:nth-child(9)  { animation-delay: 0.40s; }
.agent-wave span:nth-child(10) { animation-delay: 0.45s; }
@keyframes agent-wave-bounce {
  0%, 100% { height: 6px; opacity: 0.5; }
  50%      { height: 30px; opacity: 1; }
}
.agent-rec-label {
  font-size: 13px;
  color: var(--muted);
}

/* Make the shell positioned so the overlay can anchor */
.agent-shell { position: relative; }


/* ===========================================================================
   Profile section additions: active programme card + admin AI quick-link
   =========================================================================== */
.profile-active-tier {
  width: 100%;
  text-align: left;
  border-left: 4px solid var(--gold);
  background: #141414;
  color: var(--ink);
  padding: 18px 20px;
  cursor: pointer;
}
.profile-active-tier[hidden] { display: none !important; }
.profile-active-tier.tier-foundations { border-left-color: var(--tier-green); }
.profile-active-tier.tier-development { border-left-color: var(--tier-blue); }
.profile-active-tier.tier-elite       { border-left-color: var(--gold); }

.profile-active-tier-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 12px;
}
.profile-active-tier-day {
  font-family: var(--serif); font-size: 14px;
  color: rgba(250,246,236,0.85);
}
.profile-active-tier-progress {
  height: 6px; border-radius: 999px;
  background: rgba(250,246,236,0.12);
  overflow: hidden;
  margin-bottom: 10px;
}
.profile-active-tier-bar {
  height: 100%; background: var(--gold);
  transition: width 0.4s ease;
}
.profile-active-tier.tier-foundations .profile-active-tier-bar { background: var(--tier-green); }
.profile-active-tier.tier-development .profile-active-tier-bar { background: var(--tier-blue); }
.profile-active-tier-meta {
  font-size: 12px; color: rgba(250,246,236,0.6);
  letter-spacing: 0.02em;
}

.profile-ai-link {
  width: 100%;
  display: grid;
  grid-template-columns: 40px 1fr 20px;
  align-items: center;
  gap: 14px;
  text-align: left;
  padding: 16px 20px;
  cursor: pointer;
  background: rgba(245, 194, 0, 0.08);
  border: 1px solid rgba(245, 194, 0, 0.32);
}
.profile-ai-link[hidden] { display: none !important; }
.profile-ai-icon {
  width: 40px; height: 40px; border-radius: 10px;
  background: #141414; color: var(--gold);
  display: flex; align-items: center; justify-content: center;
}
.profile-ai-text { display: flex; flex-direction: column; gap: 2px; }
.profile-ai-text strong { font-family: var(--serif); font-size: 17px; color: var(--ink); font-weight: 500; }
.profile-ai-text span { font-size: 12px; color: var(--muted); }
.profile-ai-arrow { color: var(--gold-deep); font-size: 22px; font-weight: 500; }

/* ===========================================================================
   Admin burger + drawer
   =========================================================================== */
.admin-burger {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 16px; margin-bottom: 14px;
  background: var(--cream); border: 1px solid var(--line);
  border-radius: 12px;
  font-family: var(--sans); font-size: 13px;
  font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--ink-soft);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.admin-burger:hover { background: rgba(245, 194, 0, 0.08); border-color: var(--gold); }

.admin-drawer {
  position: fixed; inset: 0; z-index: 9200;
  display: flex; align-items: stretch; justify-content: flex-end;
}
.admin-drawer[hidden] { display: none !important; }
.admin-drawer-backdrop {
  position: absolute; inset: 0; background: rgba(0,0,0,0.5);
  animation: tier-fade-in 0.2s ease;
}
.admin-drawer-panel {
  position: relative; z-index: 1;
  width: 80%; max-width: 340px;
  background: var(--cream);
  display: flex; flex-direction: column;
  padding: 18px 16px;
  box-shadow: -10px 0 30px rgba(0,0,0,0.2);
  animation: drawer-in 0.24s cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes drawer-in {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}
.admin-drawer-head {
  display: flex; justify-content: space-between; align-items: center;
  font-family: var(--serif); font-size: 16px;
  color: var(--ink); margin-bottom: 14px;
  padding-bottom: 14px; border-bottom: 1px solid var(--line);
  letter-spacing: 0.04em;
}
.admin-drawer-close {
  width: 32px; height: 32px; border: 0; background: rgba(20,20,20,0.06);
  border-radius: 50%; font-size: 20px; line-height: 1; color: var(--ink);
  cursor: pointer;
}
.admin-drawer-item {
  width: 100%;
  background: transparent; border: 0;
  text-align: left; padding: 14px 12px;
  font-family: var(--sans); font-size: 15px;
  color: var(--ink); cursor: pointer;
  border-radius: 8px;
  -webkit-tap-highlight-color: transparent;
}
.admin-drawer-item:hover { background: rgba(245, 194, 0, 0.10); }
.admin-drawer-item.active { background: var(--gold); color: var(--ink); font-weight: 600; }


/* When CREST AI is the active panel, hide the outer admin-burger, the dark agent
   header has its own burger to keep the ChatGPT-style layout coherent. */
#section-admin:has(.admin-panel.agent-panel:not([hidden])) > .admin-burger { display: none; }

/* Restyle the admin drawer to match the dark ChatGPT sidebar look */
.admin-drawer { justify-content: flex-start; }
.admin-drawer-panel {
  background: #0A0A0A;
  color: var(--ink);
  box-shadow: 10px 0 30px rgba(0,0,0,0.5);
  animation: drawer-in-left 0.24s cubic-bezier(0.2, 0.8, 0.2, 1);
  padding: 22px 18px;
}
@keyframes drawer-in-left {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}
.admin-drawer-head {
  color: var(--gold); font-family: var(--sans);
  font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  font-size: 12px; border-bottom-color: rgba(245,194,0,0.18);
}
.admin-drawer-close {
  background: rgba(250,246,236,0.10); color: var(--ink);
}
.admin-drawer-item {
  color: var(--ink); padding: 14px 14px;
  display: flex; align-items: center; gap: 12px;
}
.admin-drawer-item::before {
  content: ""; display: inline-block;
  width: 18px; height: 18px;
  border-radius: 4px;
  background: rgba(250,246,236,0.10);
}
.admin-drawer-item[data-drawer-target="agent"]::before { background: var(--gold); }
.admin-drawer-item:hover { background: rgba(245,194,0,0.10); color: var(--gold); }
.admin-drawer-item.active { background: rgba(245,194,0,0.20); color: var(--gold); }

/* Drawer section header (Projects-style) */
.admin-drawer-section {
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(250,246,236,0.45); font-weight: 700;
  padding: 16px 14px 8px;
}

/* ===========================================================================
   CREST AI TRUE FULL-SCREEN
   When body has .agent-fullscreen, every chrome element steps out of the way
   and the agent shell covers the whole viewport.
   =========================================================================== */
body.agent-fullscreen .app-header,
body.agent-fullscreen .bottom-nav,
body.agent-fullscreen .foot-note,
body.agent-fullscreen #ptr,
body.agent-fullscreen #section-admin > .section-head,
body.agent-fullscreen #section-admin > .admin-burger { display: none !important; }

body.agent-fullscreen main { padding: 0 !important; }
body.agent-fullscreen .section.active { padding: 0 !important; margin: 0 !important; }

body.agent-fullscreen .admin-panel.agent-panel { position: fixed; inset: 0; z-index: 8500; }
body.agent-fullscreen .agent-shell {
  position: fixed; inset: 0;
  height: 100dvh; min-height: 0;
  border-radius: 0; border: 0;
}
body.agent-fullscreen .agent-header { padding-top: max(14px, env(safe-area-inset-top)); }

/* ===========================================================================
   Drawer items, replace the generic colour-square with real icons
   =========================================================================== */
.admin-drawer-item::before { display: none !important; }
.admin-drawer-item .drawer-icon {
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--gold);
  flex-shrink: 0;
}
.admin-drawer-item .drawer-icon svg { width: 20px; height: 20px; }
.admin-drawer-item.drawer-back .drawer-icon { color: rgba(250,246,236,0.7); }

/* ===========================================================================
   Black-and-gold admin section (matches CREST AI aesthetic)
   When inside section-admin (and NOT in fullscreen AI), everything is black+gold.
   =========================================================================== */
body:not(.agent-fullscreen) #section-admin {
  background: #0A0A0A;
  color: var(--ink);
  margin: 0 -24px;
  padding: 24px 24px calc(var(--nav-h) + 32px);
  min-height: calc(100dvh - var(--nav-h));
}
body:not(.agent-fullscreen) #section-admin .section-head h1 { color: var(--gold); }
body:not(.agent-fullscreen) #section-admin .section-head .date { color: rgba(250,246,236,0.55); }

body:not(.agent-fullscreen) #section-admin .admin-burger {
  background: rgba(250,246,236,0.05);
  border-color: rgba(245,194,0,0.18);
  color: var(--ink);
}
body:not(.agent-fullscreen) #section-admin .admin-burger:hover {
  background: rgba(245,194,0,0.10); border-color: var(--gold); color: var(--gold);
}

body:not(.agent-fullscreen) #section-admin .card {
  background: rgba(250,246,236,0.04);
  border-color: rgba(245,194,0,0.14);
  color: var(--ink);
  box-shadow: none;
}
body:not(.agent-fullscreen) #section-admin .card h2,
body:not(.agent-fullscreen) #section-admin .card h3 { color: var(--ink); }
body:not(.agent-fullscreen) #section-admin .card .label { color: var(--gold); }
body:not(.agent-fullscreen) #section-admin .card .muted,
body:not(.agent-fullscreen) #section-admin .card p { color: rgba(250,246,236,0.65); }

body:not(.agent-fullscreen) #section-admin .admin-field > span { color: rgba(250,246,236,0.55); }
body:not(.agent-fullscreen) #section-admin .admin-field input,
body:not(.agent-fullscreen) #section-admin .admin-field select,
body:not(.agent-fullscreen) #section-admin .admin-field textarea {
  background: rgba(250,246,236,0.06);
  border-color: rgba(250,246,236,0.12);
  color: var(--ink);
}
body:not(.agent-fullscreen) #section-admin .admin-field input:focus,
body:not(.agent-fullscreen) #section-admin .admin-field select:focus,
body:not(.agent-fullscreen) #section-admin .admin-field textarea:focus {
  border-color: var(--gold);
}

body:not(.agent-fullscreen) #section-admin .admin-btn,
body:not(.agent-fullscreen) #section-admin .admin-add-row {
  background: rgba(250,246,236,0.06);
  border: 1px solid rgba(250,246,236,0.12);
  color: var(--ink);
}
body:not(.agent-fullscreen) #section-admin .admin-btn.primary {
  background: var(--gold); color: var(--ink); border-color: var(--gold);
}

body:not(.agent-fullscreen) #section-admin .admin-list > * {
  background: rgba(250,246,236,0.03);
  border-color: rgba(250,246,236,0.08);
  color: var(--ink);
}

body:not(.agent-fullscreen) #section-admin .admin-toast {
  background: rgba(245,194,0,0.14); color: var(--gold);
  border: 1px solid rgba(245,194,0,0.30);
}

/* ===========================================================================
   Pending review bar, collapsible, dark-themed draft cards
   =========================================================================== */
.agent-pending {
  padding: 0; /* override earlier */
  background: #0E0E0E;
  border-bottom: 1px solid rgba(245,194,0,0.18);
}
.agent-pending-head {
  width: 100%;
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 18px;
  background: rgba(245,194,0,0.10);
  border: 0; cursor: pointer;
  font-family: var(--sans);
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--gold); font-weight: 700;
  -webkit-tap-highlight-color: transparent;
}
.agent-pending-chev {
  display: inline-block;
  transition: transform 0.2s ease;
  font-size: 14px;
}
.agent-pending.collapsed .agent-pending-chev { transform: rotate(-90deg); }
.agent-pending-list {
  max-height: 38vh;
  overflow-y: auto;
  padding: 10px 14px 14px;
  -webkit-overflow-scrolling: touch;
}
.agent-pending.collapsed .agent-pending-list { display: none; }

.agent-draft-card {
  background: rgba(250,246,236,0.04);
  border: 1px solid rgba(245,194,0,0.18);
  border-radius: 12px;
  padding: 12px;
  margin-bottom: 10px;
}
.agent-draft-card:last-child { margin-bottom: 0; }
.agent-draft-meta {
  font-size: 10px;
  color: rgba(250,246,236,0.5);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.agent-draft-text {
  width: 100%;
  border: 1px solid rgba(250,246,236,0.10);
  border-radius: 8px;
  padding: 10px 12px;
  background: rgba(250,246,236,0.04);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  resize: vertical;
  margin-bottom: 10px;
  outline: none;
}
.agent-draft-text:focus { border-color: var(--gold); }
.agent-draft-actions {
  display: flex; gap: 8px;
}
.agent-draft-publish {
  flex: 1; padding: 10px;
  border: 0; border-radius: 8px;
  background: var(--gold); color: var(--ink);
  font-weight: 700; cursor: pointer;
  font-family: var(--sans); font-size: 13px;
}
.agent-draft-discard {
  padding: 10px 16px;
  border: 1px solid rgba(250,246,236,0.18);
  border-radius: 8px;
  background: transparent;
  color: rgba(250,246,236,0.65);
  cursor: pointer;
  font-family: var(--sans); font-size: 13px;
}
.agent-draft-discard:hover { color: var(--ink); border-color: rgba(250,246,236,0.32); }

/* CREST AI scroll containment, stop pull-to-refresh hijacking the chat scroll.
   The thread should scroll independently and never trigger PTR or document scroll. */
body.agent-fullscreen { overflow: hidden; touch-action: none; }
body.agent-fullscreen .agent-thread { overscroll-behavior: contain; touch-action: pan-y; }
body.agent-fullscreen .agent-pending-list { overscroll-behavior: contain; touch-action: pan-y; }
body.agent-fullscreen #ptr { display: none !important; }

.agent-draft-publish.destructive {
  background: #B00020;
  color: var(--cream-warm);
}
.agent-draft-publish.destructive:hover { background: #8A0019; }

/* =========================================================================
   Fullscreen image viewer (pinch-zoom + pan). Used by feed and chat. v109
   ========================================================================= */
html.crest-no-scroll, html.crest-no-scroll body { overflow: hidden; touch-action: none; }

.crest-img-viewer {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(0,0,0,0.96);
  display: none;
  align-items: center; justify-content: center;
  -webkit-user-select: none; user-select: none;
  touch-action: none;
}
.crest-img-viewer.open { display: flex; }
.crest-img-viewer-stage {
  position: relative; width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; touch-action: none;
}
.crest-img-viewer-stage img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  transform-origin: center center;
  will-change: transform;
  -webkit-user-drag: none; user-drag: none;
  pointer-events: auto;
  touch-action: none;
}
.crest-img-viewer-close {
  /* v656 — frosted glass X, matching the tier video player (.mv-quick-close). */
  position: absolute; top: max(14px, env(safe-area-inset-top));
  right: 14px; z-index: 2;
  width: 38px; height: 38px; border-radius: 50%;
  background: rgba(255,255,255,0.16); color: #fff;
  border: 1px solid rgba(255,255,255,0.28);
  box-shadow: 0 2px 12px rgba(0,0,0,0.4);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease, background 0.2s ease;
  backdrop-filter: blur(16px) saturate(140%); -webkit-backdrop-filter: blur(16px) saturate(140%);
}
.crest-img-viewer-close:hover { background: rgba(255,255,255,0.2); }
.crest-img-viewer-close:active { transform: scale(0.9); background: rgba(255,255,255,0.26); }

/* Make feed and chat images look tappable */
.post-image-wrap img, .img-wrap img { cursor: zoom-in; }

/* =========================================================================
   Display-name gate modal — shown before a member can post in chat. v109
   ========================================================================= */
.name-gate {
  position: fixed; inset: 0; z-index: 900;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.name-gate[hidden] { display: none; }
.name-gate-backdrop {
  position: absolute; inset: 0;
  background: rgba(20,20,20,0.55);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.name-gate-card {
  position: relative; z-index: 1;
  background: var(--cream, #FAF6EC); color: var(--ink, #141414);
  border: 1px solid rgba(20,20,20,0.08);
  border-radius: 18px;
  padding: 22px 22px 18px;
  width: 100%; max-width: 380px;
  box-shadow: 0 18px 48px rgba(20,20,20,0.18);
}
.name-gate-card h3 {
  font-family: "Satoshi", sans-serif; font-style: italic;
  font-size: 20px; margin: 0 0 8px; font-weight: 500;
}
.name-gate-card p {
  font-size: 14px; line-height: 1.5; color: #5C564C;
  margin: 0 0 16px;
}
.name-gate-field { display: flex; flex-direction: column; gap: 6px; }
.name-gate-field span {
  font-family: "Satoshi", sans-serif; font-style: italic;
  font-size: 12px; color: #8B857A; letter-spacing: 0.04em;
  padding-left: 2px; font-style: italic;
}
.name-gate-field input {
  font-family: "Satoshi", -apple-system, BlinkMacSystemFont, "Inter", sans-serif;
  font-size: 16px; padding: 13px 14px;
  border: 1px solid rgba(20,20,20,0.14); border-radius: 12px;
  background: var(--cream-warm); color: #141414; -webkit-appearance: none;
}
.name-gate-field input:focus {
  outline: none; border-color: #E0AE00;
  box-shadow: 0 0 0 3px rgba(245,194,0,0.18);
}
.name-gate-save {
  margin-top: 14px; width: 100%;
  font-family: "Satoshi", sans-serif; font-style: italic;
  font-size: 15px; letter-spacing: 0.02em;
  background: #F5C200; color: #141414;
  border: 0; padding: 13px; border-radius: 12px;
  cursor: pointer; transition: background .15s ease, transform .05s ease;
}
.name-gate-save:hover { background: #E0AE00; }
.name-gate-save:active { transform: scale(0.99); }
.name-gate-save:disabled { opacity: 0.65; cursor: progress; }
.name-gate-err {
  min-height: 18px; margin: 8px 0 0;
  font-size: 13px; color: #B00020; text-align: center;
}

/* =========================================================================
   Workout-done button feedback: optimistic flip + tick pulse. v109
   ========================================================================= */
.completion-btn { position: relative; overflow: hidden; }
.completion-btn.flash-done::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at center, rgba(245,194,0,0.55) 0%, rgba(245,194,0,0) 70%);
  animation: crest-flash 0.6s ease-out forwards;
  pointer-events: none;
}
@keyframes crest-flash {
  0% { transform: scale(0.85); opacity: 1; }
  100% { transform: scale(1.4); opacity: 0; }
}
.programme-complete-btn { position: relative; overflow: hidden; }
.programme-complete-btn.flash-done::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at center, color-mix(in srgb, var(--prog-accent, #F5C200) 55%, transparent) 0%, transparent 70%);
  animation: crest-flash 0.6s ease-out forwards;
  pointer-events: none;
}

/* v110 — Profile section: separate Save button from the calorie card so they
   don't visually overlap on phones. Sam flagged this on his test pass. */
#section-profile .admin-actions { margin-top: 18px; margin-bottom: 8px; }
#section-profile .calc-card { margin-top: 22px; }
#section-profile .card + .card { margin-top: 16px; }
/* v209 — Reverted v208 dark-mode pass. Profile page back to default light
   theme; only the calc-card / macros / weight-chart cards stay dark, as
   they were before. */

/* v111 — Tier sheet "Reset progress" button (only visible when tier has progress). */
.tier-sheet-reset {
  display: block; width: 100%;
  margin-top: 10px; padding: 12px 14px;
  background: transparent; color: rgba(20,20,20,0.62);
  border: 1px solid rgba(20,20,20,0.16); border-radius: 12px;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.15s, color 0.15s;
}
.tier-sheet-reset:hover { background: rgba(20,20,20,0.04); color: var(--ink); }
.tier-sheet-reset:disabled { opacity: 0.6; cursor: progress; }

/* v113 — "Download my data" card. Reuses .admin-btn but laid out as a link. */
#section-profile .data-export-card { margin-top: 22px; }
#section-profile #prof-export {
  display: inline-block; text-decoration: none;
  padding: 10px 18px; border-radius: 10px;
  background: var(--cream-warm); color: var(--ink);
  border: 1px solid var(--line);
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
}
#section-profile #prof-export:hover { background: rgba(20,20,20,0.04); }

/* v116 — WhatsApp-style voice player. Clear grey waveform that reads on
   both cream and gold bubbles. Play button is a bare black triangle. */
.msg.voice .voice-row.whatsapp {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 2px;
}
.msg.voice .voice-row.whatsapp .v-play {
  width: 28px; height: 28px;
  background: transparent !important;
  color: #141414 !important;
  border: 0; padding: 0;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.msg.voice .voice-row.whatsapp .v-play svg { width: 22px; height: 22px; }
.msg.voice .v-wave {
  flex: 1; height: 34px;
  display: flex; align-items: center;
  gap: 2px;
  cursor: pointer;
  touch-action: pan-y;
  -webkit-tap-highlight-color: transparent;
  background: transparent !important;
  overflow: visible;
}
.msg.voice .v-wave::after { content: none; }
.msg.voice .v-bar-seg {
  flex: 1 1 0;
  min-width: 2px;
  max-width: 4px;
  background: #8E867A;          /* warm grey, visible on cream bubble */
  border-radius: 2px;
  transition: background 0.08s linear;
  height: 30%; align-self: center;
  opacity: 0.9;
}
.msg.voice .v-bar-seg.played { background: #141414; opacity: 1; }
/* On the user's own gold bubble, dark grey reads cleanly. White-on-gold
   in v115 was the "fades into background" complaint Sam flagged. */
.msg.voice.mine .v-bar-seg { background: #5C544C; opacity: 0.95; }
.msg.voice.mine .v-bar-seg.played { background: #141414; opacity: 1; }
.msg.voice.mine .voice-row.whatsapp .v-play { color: #141414 !important; }
.msg.voice .voice-row.whatsapp .v-dur {
  font-size: 12px;
  min-width: 36px;
  text-align: right;
}
/* Hide the deprecated transcript element entirely if any old code still adds it. */
.msg.voice .v-transcript { display: none !important; }

/* v117 — Big profile hero avatar at the top of section-profile.
   Front-and-centre upload spot; previously hidden in the chat sheet. */
#section-profile .prof-hero-avatar {
  display: block; position: relative;
  width: 120px; height: 120px;
  margin: 18px auto 6px;
  border-radius: 50%;
  background: var(--cream-warm, #EFE7D3);
  border: 1px solid var(--line);
  overflow: visible;
  cursor: pointer;
  transition: box-shadow 0.18s ease;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 8px 22px rgba(20,20,20,0.10);
}
#section-profile .prof-hero-avatar-img {
  position: absolute; inset: 0;
  border-radius: 50%;
  background: var(--cream-warm, #EFE7D3) center/cover no-repeat;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: 42px; color: var(--ink);
  overflow: hidden;
}
#section-profile .prof-hero-avatar-img.has-img { color: transparent; }
#section-profile .prof-hero-avatar-cam {
  position: absolute; right: -2px; bottom: -2px;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--ink, #141414); color: var(--cream-warm);
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--cream, #FAF6EC);
  box-shadow: 0 4px 10px rgba(20,20,20,0.18);
}
#section-profile .prof-hero-hint {
  text-align: center; margin: 0 0 18px;
  font-size: 12px; color: #8B857A;
  letter-spacing: 0.04em;
}

/* v119 — iOS-native style avatar cropper. Fullscreen, top-bar nav, circle
   mask with a faint 3x3 grid, pinch + drag. No slider, no rotate button. */
.crest-cropper {
  position: fixed; inset: 0; z-index: 1200;
  display: none;
  background: #000; color: var(--cream-warm);
  flex-direction: column;
}
.crest-cropper.open { display: flex; }
.crest-cropper-bar {
  flex: 0 0 auto;
  padding: calc(env(safe-area-inset-top, 0px) + 12px) 18px 12px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  font-family: -apple-system, BlinkMacSystemFont, "Inter", "Satoshi", sans-serif;
  background: #000;
}
.crest-cropper-cancel, .crest-cropper-done {
  background: transparent; border: 0; padding: 6px 2px;
  font-size: 17px; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  font-family: inherit;
}
.crest-cropper-cancel { color: #FAF6EC; text-align: left; justify-self: start; }
.crest-cropper-done { color: #F5C200; font-weight: 600; text-align: right; justify-self: end; }
.crest-cropper-title {
  font-size: 16px; font-weight: 600; color: var(--cream-warm);
  letter-spacing: 0.01em;
}
.crest-cropper-stage {
  flex: 1 1 auto; position: relative;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.crest-cropper-canvas {
  display: block; touch-action: none; cursor: grab;
  background: #000;
}
.crest-cropper-canvas:active { cursor: grabbing; }
.crest-cropper-mask {
  position: absolute; pointer-events: none;
  /* Dim the corners outside the circle */
  background: radial-gradient(circle at center, transparent 0 49.6%, rgba(0,0,0,0.62) 50%);
}
.crest-cropper-mask::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.4) inset;
  -webkit-mask: radial-gradient(circle at center, black 49.5% 50%, transparent 50.5%);
          mask: radial-gradient(circle at center, black 49.5% 50%, transparent 50.5%);
}
/* Faint 3x3 grid lines inside the circle */
.crest-cropper-grid {
  position: absolute; inset: 0;
  -webkit-mask: radial-gradient(circle at center, black 0 50%, transparent 50%);
          mask: radial-gradient(circle at center, black 0 50%, transparent 50%);
  background:
    linear-gradient(to right,  transparent 33.2%, rgba(255,255,255,0.22) 33.2% 33.5%, transparent 33.5%) center/100% 100% no-repeat,
    linear-gradient(to right,  transparent 66.5%, rgba(255,255,255,0.22) 66.5% 66.8%, transparent 66.8%) center/100% 100% no-repeat,
    linear-gradient(to bottom, transparent 33.2%, rgba(255,255,255,0.22) 33.2% 33.5%, transparent 33.5%) center/100% 100% no-repeat,
    linear-gradient(to bottom, transparent 66.5%, rgba(255,255,255,0.22) 66.5% 66.8%, transparent 66.8%) center/100% 100% no-repeat;
}

/* v165 — Zoom slider. Fail-safe for when pinch doesn't register on iOS, or
   when the user doesn't realise they need two fingers. Slider position
   syncs with pinch so they're never out of step. */
.crest-cropper-zoom {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 14px;
  padding: 16px 24px calc(env(safe-area-inset-bottom, 0px) + 18px);
  background: #000;
}
.crest-cropper-zoom-ico {
  flex: 0 0 auto;
  font-size: 22px; line-height: 1;
  color: rgba(255,255,255,0.65);
  width: 18px; text-align: center;
  user-select: none;
}
.crest-cropper-zoom-slider {
  flex: 1 1 auto;
  -webkit-appearance: none; appearance: none;
  height: 4px; border-radius: 2px;
  background: rgba(255,255,255,0.22);
  outline: none;
}
.crest-cropper-zoom-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 24px; height: 24px; border-radius: 50%;
  background: #F5C200; border: 2px solid #000;
  box-shadow: 0 2px 6px rgba(0,0,0,0.45);
  cursor: pointer;
}
.crest-cropper-zoom-slider::-moz-range-thumb {
  width: 24px; height: 24px; border-radius: 50%;
  background: #F5C200; border: 2px solid #000;
  cursor: pointer;
}

/* v125 — Optimistic-send shimmer. WhatsApp/Telegram pattern: the user's
   own bubble appears instantly with a subtle ~0.65 opacity until the
   server confirms, at which point it settles to full. send-failed shows
   a red rim if the network drops mid-flight. */
.msg.sending { opacity: 0.65; }
.msg.sending .body { color: rgba(20,20,20,0.55); }
.msg.mine.sending .body { color: rgba(20,20,20,0.5); }
.msg.send-failed { opacity: 0.85; box-shadow: 0 0 0 1px #B00020 inset; border-radius: 12px; }

/* v128 — Swipe-to-delete on chat messages. Matches the feed-comment style:
   compact red rectangle pinned to the right edge, centred to the body of
   the bubble (not full-height of tall messages). */
.msg.msg-swipeable {
  position: relative;
  --swipe-x: 0px;
}
.msg.msg-swipeable > *:not(.msg-swipe-delete):not(.msg-heart-pop) {
  transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.2, 1);
  transform: translateX(var(--swipe-x));
}
/* v490 — while actively dragging, no transition so the bubble tracks the finger
   1:1 instead of lagging behind (that lag read as "sticky"). */
.msg.msg-swipeable.swipe-dragging > *:not(.msg-swipe-delete):not(.msg-heart-pop) {
  transition: none;
}
.msg-swipe-delete {
  position: absolute;
  top: 50%;
  left: 4px;
  transform: translate(-94px, -50%);   /* v492 — parked off-screen LEFT; revealed by swipe-RIGHT */
  width: 78px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  background: #D9322F; color: var(--cream-warm);
  border: 0; padding: 0;
  font-family: var(--sans); font-size: 13px; font-weight: 500;
  letter-spacing: 0.02em;
  border-radius: 10px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  opacity: 0;
  pointer-events: none;
  transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.2, 1), opacity 0.18s ease;
}
.msg.swiped .msg-swipe-delete {
  transform: translate(0, -50%);
  opacity: 1;
  pointer-events: auto;
}
.msg-swipe-delete:active { background: #B82624; }

/* v132 — Smooth section transitions. Cross-fade + tiny upward slide so
   moving between Feed / Workout / Community feels intentional, not janky.
   Images inside sections also fade in instead of pop-loading. */
.section { opacity: 0; transform: translateY(8px); transition: opacity 0.22s ease, transform 0.34s var(--ease-spring-soft); }
.section.active { opacity: 1; transform: none; }
.feed-post img, .post-media img { transition: opacity 0.22s ease; }
.feed-post img:not([src]), .feed-post img[src=""] { opacity: 0; }
img.lazy-fade { opacity: 0; transition: opacity 0.22s ease; }
img.lazy-fade.loaded { opacity: 1; }

/* v138 — Comment list breathing. v137's `padding: 2px 0` on .comment let
   the absolute swipe-delete (top:0, height:100% of .comment) protrude past
   the white swipe-row → red horizontal bars bleeding through. Reverted.
   Gap alone gives the ring its breathing room. */
.comments-list { gap: 16px !important; }
/* Centre the avatar photo dead-on. v137 tried a 30% top bias which made
   Sam's selfie show the top of his head instead of his face. Reverted —
   the cropper output is the source of truth, render it untouched. */
.comment-avatar.has-img,
.completion-avatar.has-img,
.fpc-comment-avatar.has-img,
.feed-post-avatar.has-img,
.post-avatar.has-img,
.composer-avatar.has-img,
.chat-avatar.has-img,
.avatar.has-img {
  background-position: center center !important;
  background-size: cover !important;
  background-repeat: no-repeat !important;
}

/* v168 — Universal avatar guarantee. Any element whose class name contains
   the word "avatar" AND has an image loaded MUST render the photo as cover,
   centred. Sam reported gaps appearing in the community chat circles even
   though the cropped output was perfect — the issue was that some avatar
   variants (.fpc-avatar, .header-avatar, .profile-avatar-img, etc.) weren't
   in the explicit list above and lost cover whenever their background
   shorthand was re-applied. This catch-all means we never have to
   remember to add a new variant to a list. */
[class*="avatar"].has-img,
[id*="avatar"].has-img {
  background-position: center center !important;
  background-size: cover !important;
  background-repeat: no-repeat !important;
}

/* v170 — Universal tier ring on the profile hero avatar (and any other
   wrapper with avatar inside). Same colour rules as every other surface.
   Sam wanted this to feel completely consistent across the app. */
.prof-hero-avatar.has-tier-foundations { box-shadow: 0 0 0 3px var(--tier-green); }
.prof-hero-avatar.has-tier-development { box-shadow: 0 0 0 3px var(--tier-blue); }
.prof-hero-avatar.has-tier-elite       { box-shadow: 0 0 0 3px var(--gold); }

/* v140 — "View full programme" link inside the tier sheet. Subtle text
   button below the primary Start CTA. Only shown for tiers that have a
   real content page (currently elite = tier-3, Charlie's design). */
.tier-sheet-preview {
  display: block;
  text-align: center;
  margin-top: 10px;
  padding: 8px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink, #141414);
  text-decoration: none;
  border-radius: 8px;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease;
}
.tier-sheet-preview:hover { background: rgba(20,20,20,0.04); }

/* v145 — "View full programme" button on Programme tab. Same shape as the
   movement-library button but with the tier accent gold tint. */
.programme-pdf-btn {
  margin-top: 10px; width: 100%;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: rgba(245, 194, 0, 0.10);
  border: 1px solid rgba(245, 194, 0, 0.32);
  color: #fff;
  padding: 12px; border-radius: 10px;
  font-family: var(--sans, "Satoshi", sans-serif); font-size: 13px; font-weight: 600;
  text-decoration: none;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.programme-pdf-btn:hover { background: rgba(245, 194, 0, 0.18); border-color: rgba(245, 194, 0, 0.55); }
.programme-pdf-btn svg { opacity: 0.85; }

/* =========================================================================
   v147 — Programme tab redesign (matches Miles's UI reference).
   Dark theme, Bebas Neue titles, week strip pills, coloured exercise blocks.
   Only TODAY's day card is shown; "View full programme" opens the full
   static tier-N.html page for the brochure-style view.
   ========================================================================= */
#section-programme.prog-section {
  background: #0F0F0F;
  color: var(--ink);
  margin: -20px -16px 0;            /* break out of the cream chrome */
  padding: 0 16px 80px;
  min-height: calc(100vh - var(--nav-h, 88px));
}
#section-programme.prog-section .section-back { color: var(--cream-warm); }
#section-programme .programme-switch { margin: 0; }
/* v505 — inconspicuous gold button (not tier-accent — gold is the app's
   "switch / vault" colour). A real button, but quiet. NOTE: selector is id-only
   because the `.prog-section` class is never actually applied (that whole rule
   block was dead — v504 gold edit never took because of it). */
#section-programme .programme-switch button {
  width: 100%; padding: 13px;
  background: rgba(245,194,0,0.07);
  border: 1px solid rgba(245,194,0,0.32);
  color: #F5C200; border-radius: 12px;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.02em; cursor: pointer;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, border-color 0.15s ease;
}
#section-programme .programme-switch button:hover {
  background: rgba(245,194,0,0.13); border-color: rgba(245,194,0,0.5);
}
#section-programme .programme-switch button:active { transform: scale(0.99); }

/* v505 — Footer box: encapsulates Switch + Reset in one quiet container. */
#section-programme .prog-footer-box {
  margin: 22px 0 28px;
  padding: 14px;
  background: #131313;
  border: 1px solid #242424;
  border-radius: 16px;
  display: flex; flex-direction: column; gap: 4px;
}
#section-programme .prog-footer-box .prog-reset-row { margin: 2px 0 0; }

/* Top bar */
.prog-topbar {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 18px 8px 16px;
  border-bottom: 1px solid #2A2A2A;
  margin-bottom: 16px;
}
.prog-tb-left { min-width: 0; }
.prog-eyebrow {
  font-size: 11px; color: #888; letter-spacing: 2px;
  margin-bottom: 2px;
}
.prog-h1 {
  font-size: 20px; font-weight: 800; letter-spacing: -0.5px;
  color: var(--cream-warm);
}
.prog-tb-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.prog-split-pill {
  background: rgba(245,194,0,0.12);
  border: 1px solid rgba(245,194,0,0.27);
  border-radius: 10px; padding: 5px 12px;
  font-size: 11px; font-weight: 700; color: #F5C200; letter-spacing: 0.5px;
}
.prog-cr-badge {
  width: 36px; height: 36px; background: #1A1A1A;
  border-radius: 10px; border: 1.5px solid #F5C200;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 900; color: #F5C200;
}

/* Week strip — horizontal scroll of day pills */
.prog-week-strip {
  display: flex; gap: 8px; padding: 4px 0 16px;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 -4px;
}
.prog-week-strip::-webkit-scrollbar { display: none; }
.prog-week-strip .prog-day-pill {
  flex-shrink: 0; min-width: 64px;
  background: #1A1A1A; border: 1px solid #2A2A2A;
  border-radius: 12px; padding: 10px 14px;
  text-align: center; cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.12s;
  display: flex; flex-direction: column; gap: 3px;
}
.prog-week-strip .prog-day-pill:active { transform: scale(0.97); }
.prog-week-strip .pill-num {
  font-size: 18px; font-weight: 900; color: var(--cream-warm); line-height: 1;
}
.prog-week-strip .pill-day {
  font-size: 9px; color: #888; letter-spacing: 0.5px;
}
.prog-week-strip .prog-day-pill.selected {
  background: #F5C200; border-color: #F5C200;
}
.prog-week-strip .prog-day-pill.selected .pill-num,
.prog-week-strip .prog-day-pill.selected .pill-day { color: #0F0F0F; }
.prog-week-strip .prog-day-pill.done { border-color: var(--prog-accent, rgba(245,194,0,0.5)); }
.prog-week-strip .prog-day-pill.rest-day { opacity: 0.5; }

/* Progress */
.prog-progress-wrap { padding: 8px 0 16px; }
.prog-progress-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 8px;
}
.prog-progress-head .prog-progress-label {
  font-size: 11px; font-weight: 700; color: #F5C200; letter-spacing: 1.5px;
}
.prog-week-label { font-size: 11px; color: #888; }
/* v505 — Embossed progress track. Always visible (even at 0%) as a recessed
   groove, so the bar reads as "filling a channel" rather than appearing from
   nowhere. Programme-wide — one rule, all tiers. */
#section-programme .programme-progress {
  background: #242424;
  border-radius: 999px;
  height: 8px;
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.6), inset 0 0 0 1px rgba(255,255,255,0.05);
}
#section-programme .programme-progress-bar {
  background: var(--prog-accent, #F5C200); height: 100%; border-radius: 999px;
  box-shadow: 0 0 8px -1px var(--prog-accent, #F5C200);
  transition: width 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}
/* v496 — "Programme progress" label tinted to the active tier's accent colour. */
#section-programme #prog-active-card .label {
  color: var(--prog-accent, var(--gold));
}

/* v496 — Tier identity banner at the top of the Workout tab. Left accent bar +
   a tier-tinted wash so each programme has a clear sense of place. */
/* v582 — tier identity is a big FADED watermark; the progress card sits over
   its lower half. No card chrome, no "DEVELOPMENT / add structure" sub-lines. */
/* v583 — TIER label sits top-left under "Workout" (no longer a watermark behind
   the progress card). Big, solid, left-aligned. */
.prog-identity {
  display: block;
  margin: 2px 0 14px;
  padding: 0 2px;
  background: none; border: 0; overflow: visible;
}
.prog-identity::before { display: none; }
.prog-identity-eyebrow {
  display: block;
  font-family: var(--display);
  font-size: clamp(56px, 20vw, 88px); font-weight: 900;
  letter-spacing: -1px; line-height: 0.85; white-space: nowrap;
  color: var(--prog-accent, #F5C200);
  text-transform: uppercase;
}
.prog-identity-name, .prog-identity-tagline { display: none; }
.prog-progress-meta {
  display: flex; justify-content: space-between; margin-top: 6px;
  font-size: 10px;
}
.prog-progress-meta .left { color: #888; }
.prog-progress-meta .right { color: var(--prog-accent, #F5C200); font-weight: 700; }

/* v504 — Reset-programme link: HOLD to reset. A red bar fills left→right while
   held; release early and it cancels. Quiet grey at rest. */
/* v506 — Reset is now a FULL-SIZE button (same footprint as the gold Switch
   button) so the red hold-to-confirm fill is obvious, not a tiny link someone
   misses until it's too late. Quiet red-outlined at rest, fills solid red on
   hold. */
.prog-reset-row { margin: 0; }
.prog-reset-link {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  width: 100%; padding: 13px; border-radius: 12px;
  background: rgba(220, 38, 38, 0.06);
  border: 1px solid rgba(220, 38, 38, 0.30);
  color: #D98A8A; font-size: 13px; font-weight: 600; font-family: var(--sans);
  letter-spacing: 0.02em; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none; user-select: none; touch-action: none;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.prog-reset-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: rgba(220, 38, 38, 0.45);
  pointer-events: none;
}
.prog-reset-link.holding .prog-reset-fill {
  width: 100%;
  transition: width 1.5s linear;
}
.prog-reset-label { position: relative; z-index: 1; }
.prog-reset-link.holding {
  color: #fff; border-color: rgba(220, 38, 38, 0.7);
}
.prog-reset-link:disabled { color: #D98A8A; cursor: default; opacity: 0.8; }

/* Day card */
/* v548 — Apple gradient texture, PROGRAMME-WIDE (all tiers). Neutral black→grey
   gradient surface on each element (day pills + programme card + progress card),
   rounded, with a top inner highlight. No drop shadow, no colour. Selected/done
   pills keep their tier accent (excluded below). */
#section-programme .prog-day-card,
#section-programme #prog-active-card {
  border-radius: 20px;
  background: linear-gradient(180deg, #1A1A1D 0%, #0D0D0F 100%);
  border: 1px solid rgba(255,255,255,0.08);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.10);
}
/* v564 — the workout DAY card loses its surrounding pill so the session spreads
   full-width across the page (progress card + day pills keep their surface). */
#section-programme #prog-session {
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding-left: 0;
  padding-right: 0;
}
#section-programme .prog-day-pill:not(.selected):not(.done) {
  background: linear-gradient(180deg, #1F1F22 0%, #101012 100%);
  border-color: rgba(255,255,255,0.09);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.10);
}

/* v549 — programme-wide: lift every dim grey label to readable off-white. */
#section-programme .prog-warm-up,
#section-programme .prog-cool-down,
#section-programme .prog-tagline,
#section-programme .prog-rest-line,
#section-programme .prog-rest-list li,
#section-programme .prog-ex-table .ex-reps,
#section-programme .prog-ex-table .ex-rest,
#section-programme .prog-week-label,
#section-programme .prog-eyebrow,
#section-programme .prog-day-meta,
#section-programme .prog-progress-meta .left,
#section-programme .programme-exercises li .ex-detail,
#section-programme .prog-ex-table .ex-name .ex-note-inline,
#section-programme .prog-session-status {
  color: #E5E0D4 !important;
}
#section-programme .prog-day-pill:not(.selected):not(.done) { color: #E5E0D4; }
#section-programme #prog-progress-label { color: #E5E0D4 !important; }

.prog-day-card {
  background: #1A1A1A; border: 1px solid #2A2A2A; border-radius: 16px;
  overflow: hidden; margin-top: 6px;
}
.prog-day-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 16px; padding: 20px 22px 16px;
}
.prog-day-head-left { flex: 1; min-width: 0; }
.prog-day-meta {
  font-size: 11px; font-weight: 600; color: #888;
  letter-spacing: 2px; margin-bottom: 6px;
}
.prog-day-meta .prog-session-status:not(:empty) {
  margin-left: 8px; color: var(--prog-accent, #F5C200);
}
.prog-day-title {
  font-family: var(--display);
  font-size: clamp(30px, 9.5vw, 40px); font-weight: 900; color: var(--ink);
  letter-spacing: -0.5px; text-transform: uppercase;
  margin-bottom: 12px; line-height: 1.0;
}
.prog-day-tag {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 8px; padding: 5px 10px;
  font-size: 11px; font-weight: 700; letter-spacing: 1px;
  background: var(--prog-accent-soft, rgba(245,194,0,0.12));
  border: 1px solid var(--prog-accent, rgba(245,194,0,0.33));
  color: var(--prog-accent, #F5C200);
}
.prog-day-num-ghost {
  font-family: var(--display);
  font-size: clamp(44px, 13vw, 56px); font-weight: 900;
  color: var(--prog-accent-soft, #2A2A2A); line-height: 1; flex-shrink: 0;
  /* v506 — embossed (pressed-into-the-card) look, same tier colour. Dark
     bottom shadow + faint top highlight reads as letterpress on the dark card. */
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.6), 0 -1px 1px rgba(255, 255, 255, 0.07);
}

.prog-day-body { padding: 16px 22px 8px; border-top: 1px solid #2A2A2A; }
#section-programme .programme-exercises {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column;
}
#section-programme .programme-exercises li {
  display: flex; justify-content: space-between; align-items: center;
  padding: 11px 0; border-bottom: 1px solid #2A2A2A;
  color: var(--ink); font-size: 14px; font-weight: 500;
  border-left: 3px solid var(--prog-accent, rgba(245,194,0,0.4));
  padding-left: 14px;
}
#section-programme .programme-exercises li:last-child { border-bottom: 0; }
#section-programme .programme-exercises li .ex-detail {
  color: #888; font-size: 13px; font-weight: 600;
  flex-shrink: 0; margin-left: 12px;
}
.prog-rest-line {
  color: #888; font-size: 14px; font-style: italic;
  padding: 8px 0 14px;
}

/* v205 — Inline programme exercise table. Same look as /programmes/tier-N.html.
   Accent colour driven by the active tier via the body class set elsewhere. */
#section-programme .prog-warm-up {
  background: rgba(74,144,217,0.06);
  border: 1.5px solid var(--prog-accent, #4A90D9);
  border-radius: 14px;
  padding: 12px 16px;
  margin-bottom: 20px;
  font-size: 13px;
  color: #888;
  line-height: 1.5;
}
#section-programme .prog-warm-up strong { color: var(--ink); font-weight: 500; }
#section-programme .prog-ex-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  color: var(--cream-warm);
  table-layout: fixed;   /* v564 — fixed columns so Sets/Reps/Rest align under their headers */
}
/* v564 — locked column widths (header + values share them in fixed layout). */
#section-programme .prog-ex-table thead th:nth-child(1) { width: 44%; }
#section-programme .prog-ex-table thead th:nth-child(2) { width: 13%; }
#section-programme .prog-ex-table thead th:nth-child(3) { width: 17%; }
#section-programme .prog-ex-table thead th:nth-child(4) { width: 26%; }
#section-programme .prog-ex-table .ex-sets,
#section-programme .prog-ex-table .ex-reps,
#section-programme .prog-ex-table .ex-rest { overflow-wrap: break-word; }
#section-programme .prog-ex-table thead th {
  text-align: left;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: #888;
  padding: 0 10px 10px 0;
  font-weight: 500;
  border-bottom: 1px solid #2A2A2A;
}
#section-programme .prog-ex-table tbody tr {
  border-bottom: 1px solid rgba(255,255,255,0.04);
}
#section-programme .prog-ex-table tbody tr:last-child { border-bottom: 0; }
#section-programme .prog-ex-table td {
  padding: 11px 10px 11px 0;
  vertical-align: middle;
}
#section-programme .prog-ex-table .ex-name {
  font-weight: 500;
  color: var(--ink);
}
/* Form-cue note under each exercise name — mirrors the full programme page's
   "Notes" column, folded into the name cell so it fits the mobile table. */
#section-programme .prog-ex-table .ex-name .ex-note-inline {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  font-weight: 400;
  line-height: 1.4;
  color: #8A857A;
}
/* Rest-day guidance list — same bullets the full programme page shows. */
#section-programme .prog-rest-list {
  margin: 4px 0 0; padding-left: 18px;
  list-style: disc;
}
#section-programme .prog-rest-list li {
  font-size: 13px; color: #9A958A; line-height: 1.7;
}
/* v565 — all three values share one font + size + baseline so they sit on one
   line (Sets was a big Bebas font, which staggered it against Reps/Rest). */
#section-programme .prog-ex-table .ex-sets,
#section-programme .prog-ex-table .ex-reps,
#section-programme .prog-ex-table .ex-rest {
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.25;
  vertical-align: middle;
  /* v587 — wrap instead of nowrap so long values (e.g. "4 @80%", "15 (slow)")
     stay inside their column rather than overlapping the next. */
  white-space: normal;
  overflow-wrap: break-word;
  word-break: break-word;
}
#section-programme .prog-ex-table .ex-sets { color: var(--prog-accent, #4A90D9); font-weight: 700; }
#section-programme .prog-ex-table .ex-reps,
#section-programme .prog-ex-table .ex-rest { color: #E5E0D4; }
#section-programme .prog-cool-down {
  margin-top: 18px;
  padding: 12px 14px;
  background: rgba(255,255,255,0.02);
  border-radius: 6px;
  font-size: 13px;
  color: #888;
  line-height: 1.5;
}
#section-programme .prog-cool-down strong {
  color: var(--ink);
  font-weight: 500;
  display: block;
  margin-bottom: 4px;
}
/* Per-tier accent is set inline by tiers.js renderProgramme via
   --prog-accent on #prog-session. No body-level CSS rule needed. */

.prog-day-actions {
  padding: 8px 22px 22px;
  display: flex; flex-direction: column; gap: 10px;
}
#section-programme .programme-complete-btn {
  width: 100%;
  font-family: var(--display); font-size: 15px; letter-spacing: 3px;
  background: var(--prog-accent, #F5C200); color: #1a1300;
  border: 0; padding: 14px; border-radius: 10px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: filter 0.15s ease;
  text-transform: uppercase;
}
#section-programme .programme-complete-btn:hover { filter: brightness(1.08); }
#section-programme .programme-complete-btn.done {
  background: transparent; color: #888;
  border: 1px solid #2A2A2A;
}
#section-programme .programme-library-btn,
#section-programme .programme-pdf-btn {
  background: transparent; color: #fff;
  border: 1px solid #2A2A2A;
  text-decoration: none;
}
#section-programme .programme-pdf-btn {
  background: var(--prog-accent-soft, rgba(245,194,0,0.08));
  border-color: var(--prog-accent, rgba(245,194,0,0.3));
  color: var(--prog-accent, #F5C200);
}

/* v149 — Rich session-bubble content: section concept, tagline, coloured
   block labels, sub-exercise highlights. Matches Miles's React reference. */
#section-programme .prog-concept {
  font-family: var(--display);
  font-size: 18px; font-weight: 800; color: var(--ink);
  letter-spacing: 0.5px; text-transform: uppercase;
  margin: 4px 0 6px;
}
#section-programme .prog-tagline {
  font-size: 12px; color: #CBC5B8; font-style: italic;
  line-height: 1.5; margin-bottom: 16px;
}
/* v659 — in-day session split (e.g. Miles Push morning → Sprints evening).
   A full-width divider inside the exercise table: CAPS title + blue pill + sub. */
#section-programme .prog-session-break td {
  padding: 22px 0 8px;
  border-top: 1px solid var(--line, rgba(255,255,255,0.12));
}
#section-programme .prog-break-title { margin: 6px 0 4px; }
#section-programme .prog-break-pill {
  display: inline-block;
  background: rgba(74,144,217,0.14); color: #7EC8E3;
  border: 1px solid rgba(74,144,217,0.40);
  font: 800 11px/1 var(--display, sans-serif);
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 5px 12px; border-radius: 999px;
}
#section-programme .prog-session-sub {
  font-size: 12px; font-weight: 700; color: #7EC8E3;
  letter-spacing: 0.04em; margin: 8px 0 4px;
}
/* v557 — Miles/Elite read as ONE clean, spaced list like the tier-1/2 tables.
   No A/B/C labels, no coloured rails/bars — just exercises with breathing room. */
#section-programme .prog-block { margin: 0; }
#section-programme .prog-block:last-child { margin-bottom: 0; }
#section-programme .prog-block-label-row { display: none; }
#section-programme .prog-block-bar { display: none; }
#section-programme .prog-block-label { display: none; }
#section-programme .prog-block-items {
  list-style: none; padding: 0; margin: 0; border-left: 0;
}
#section-programme .prog-block-items li {
  display: flex; justify-content: space-between; align-items: center; gap: 14px;
  padding: 13px 2px; border-bottom: 1px solid rgba(255,255,255,0.06);
  font-size: 14px; font-weight: 500;
}
#section-programme .programme-exercises.rich .prog-block:last-child .prog-block-items li:last-child { border-bottom: 0; }
#section-programme .prog-block-items li.ex-sub { font-weight: 500; }
#section-programme .prog-block-items li.ex-sub .ex-name {
  color: #9A958A; font-style: italic; font-size: 12.5px; padding-left: 14px;
}
#section-programme .prog-block-items li.ex-sub .ex-detail { color: #9A958A; font-style: italic; font-weight: 500; }
#section-programme .prog-block-items .ex-name { color: #F4F0E4; }
#section-programme .prog-block-items .ex-detail {
  font-family: var(--display); font-size: 16px; letter-spacing: 0.04em;
  color: var(--prog-accent, #CBC5B8); font-weight: 400;
  margin-left: 12px; flex-shrink: 0; white-space: nowrap;
}
/* Rich container itself — no padding, blocks handle their own gutters */
#section-programme .programme-exercises.rich { padding: 0; border: 0; background: transparent; }
/* v558 — sub (↳) note rows inside the block-as-table render. */
#section-programme .prog-ex-table tr.prog-ex-subrow td { padding: 2px 0 9px 18px; }
#section-programme .prog-ex-table .ex-subname { font-style: italic; font-size: 12px; color: #9A958A; line-height: 1.4; }
#section-programme .prog-ex-table .ex-subnote { font-style: italic; font-size: 11px; color: #9A958A; margin-left: 8px; white-space: nowrap; }

/* v561 — Tier 2 / Monday: row movement thumbnail + clean no-bubble log panel. */
#section-programme tr.loggable { cursor: pointer; }
#section-programme tr.loggable .ex-name,
/* v607 — loggable rows need the SAME flex name-cell as has-thumb rows so the
   thumbnail + a long name (e.g. "↳ Copenhagen Plank") stays inside the Exercise
   column instead of overlapping Reps. The flex:1/min-width:0 on .ex-name-text
   below was already there expecting this. */
#section-programme tr.has-thumb .ex-name,
#section-programme tr.loggable .ex-name { display: flex; align-items: center; gap: 12px; }
#section-programme .ex-thumb {
  flex-shrink: 0; width: 50px; height: 50px; border-radius: 12px; overflow: hidden;
  border: 1px solid rgba(255,255,255,0.12); padding: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* v584 — shimmer placeholder while the poster loads, so it never pops in. */
  background: linear-gradient(90deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.13) 50%, rgba(255,255,255,0.05) 100%);
  background-size: 200% 100%; animation: crestShimmer 1.4s linear infinite;
}
#section-programme .ex-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0; transition: opacity 0.35s ease; }
#section-programme .ex-thumb.loaded { animation: none; background: #161618; }
#section-programme .ex-thumb.loaded img { opacity: 1; }
#section-programme .ex-thumb-empty { animation: none; background: linear-gradient(135deg, #202024, #141416); }
/* v588 — pump the thumbnail on tap to acknowledge the click. */
@keyframes exThumbPump { 0% { transform: scale(1); } 38% { transform: scale(1.2); } 100% { transform: scale(1); } }
#section-programme .ex-thumb.pumping { animation: exThumbPump 0.3s ease; }
#section-programme tr.loggable .ex-name-text,
#section-programme tr.has-thumb .ex-name-text {
  flex: 1; min-width: 0;
  /* v608 — hard guarantee the name stays inside the Exercise column (a long
     single word like "Copenhagen" was poking into the Sets "—"). */
  overflow-wrap: break-word;
}
/* v654 — green tick once an exercise has been logged today. */
#section-programme tr.loggable.is-logged .ex-name-text::after {
  content: "✓";
  color: #2ECC71;
  font-weight: 800;
  margin-left: 6px;
  display: inline-block;
}
/* v563 — caret lives at the far right of the Rest column: bigger + blue. */
/* v566 — caret in its own centred column so Rest stays a normal aligned cell. */
#section-programme .ex-caret { text-align: center; vertical-align: middle; }
#section-programme .prog-log-caret { display: inline-block; color: var(--prog-accent, #4A90D9); font-size: 26px; line-height: 1; transition: transform 0.2s; }
#section-programme tr.loggable.open .prog-log-caret { transform: rotate(180deg); }
/* v566 — 5-column widths for the logging table + more breathing room per row. */
/* v587 — more room for Sets/Reps/Rest (Elite values are longer than Tier 2's). */
/* v608 — wider Exercise column so a long name + thumbnail doesn't bleed into
   Sets. Room reclaimed from the caret (just a chevron), Sets (short values) and
   Rest. Reps stays 21% — Elite values like "4 @ 80%" / "15 (slow)" need it. */
#section-programme .prog-ex-table.has-log thead th:nth-child(1) { width: 44%; }
#section-programme .prog-ex-table.has-log thead th:nth-child(2) { width: 12%; }
#section-programme .prog-ex-table.has-log thead th:nth-child(3) { width: 21%; }
#section-programme .prog-ex-table.has-log thead th:nth-child(4) { width: 17%; }
#section-programme .prog-ex-table.has-log thead th:nth-child(5) { width: 6%; }
#section-programme .prog-ex-table.has-log td { padding-top: 15px; padding-bottom: 15px; vertical-align: middle; }
#section-programme tr.loggable.open .ex-name-text { color: var(--prog-accent, #4A90D9); }
#section-programme tr.prog-log-panel > td { padding: 0 0 18px; border-bottom: 1px solid rgba(255,255,255,0.06); }
/* v571 — no bubble; one row PER SET; last-time per set; top-set trend spark. */
#section-programme .plog { display: flex; flex-direction: column; gap: 16px; padding: 12px 2px; }
#section-programme .plog-sets { display: flex; flex-direction: column; gap: 16px; }
#section-programme .plog-set { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 11px 14px; }
#section-programme .plog-set-no {
  flex-shrink: 0; width: 46px; font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.06em; color: #9A958A; font-weight: 700; padding-bottom: 12px;
}
#section-programme .plog-field { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
#section-programme .plog-field span { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: #9A958A; }
#section-programme .plog-field input {
  width: 100%; background: #0D0D0F; border: 1px solid rgba(255,255,255,0.12);
  border-radius: 10px; padding: 12px; color: #F4F0E4; font-size: 15px;
  font-family: inherit; -webkit-appearance: none;
}
#section-programme .plog-field input:focus { outline: none; border-color: var(--prog-accent, #4A90D9); }
#section-programme .plog-set-last { flex-basis: 100%; padding-left: 60px; font-size: 11.5px; color: #8E887B; margin-top: -2px; }
#section-programme .plog-set-last:empty { display: none; }
#section-programme .plog-last-tag {
  font-size: 9px; font-weight: 800; letter-spacing: 0.08em;
  color: var(--prog-accent, #4A90D9); margin-right: 5px;
}
#section-programme .plog-actions { display: flex; justify-content: flex-end; }
#section-programme .plog-save {
  background: var(--prog-accent, #4A90D9); color: #0E0E10; border: 0; border-radius: 10px;
  padding: 12px 22px; font-weight: 700; font-size: 13px; cursor: pointer; white-space: nowrap;
}
#section-programme .plog-save:disabled { opacity: 0.7; }
#section-programme .plog-spark { display: flex; flex-direction: column; gap: 5px; padding-bottom: 2px; border-bottom: 1px solid rgba(255,255,255,0.06); margin-bottom: 2px; }
#section-programme .plog-spark-svg { width: 100%; height: 40px; display: block; }
#section-programme .plog-spark-meta { font-size: 11px; color: #9A958A; }
#section-programme .plog-spark-meta strong { color: var(--prog-accent, #4A90D9); font-weight: 700; }
/* v569 — cardio/circuit days: full-width "Option/Block + description" list. */
#section-programme .prog-options { display: flex; flex-direction: column; }
#section-programme .prog-option {
  padding: 14px 2px; border-bottom: 1px solid rgba(255,255,255,0.06);
}
#section-programme .prog-option:last-child { border-bottom: 0; }
#section-programme .prog-option-name {
  font-weight: 700; color: var(--prog-accent, #4A90D9); font-size: 13px;
  text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 5px;
}
#section-programme .prog-option-detail { color: #E5E0D4; font-size: 14px; line-height: 1.5; }
/* v596 — movement clip as a CARD: frosted glass X (top-right) to close (swipe-down
   removed, it misfired), with VERTICALLY stacked glass Pause + Replay controls
   (Pause central, Replay beneath) that fade out after a beat. */
.mv-quick-overlay {
  position: fixed; inset: 0; z-index: 4000; background: rgba(0,0,0,0.82);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  opacity: 0; visibility: hidden; transition: opacity 0.22s ease;
}
.mv-quick-overlay.open { opacity: 1; visibility: visible; }
.mv-quick-card {
  position: relative; display: flex; flex-direction: column; align-items: center;
  background: #0E0E10; border-radius: 22px; overflow: hidden;
  max-width: 92vw; max-height: 86vh;
  box-shadow: 0 24px 64px rgba(0,0,0,0.6);
}
.mv-quick-close {
  position: absolute; top: 12px; right: 12px; z-index: 6;
  width: 38px; height: 38px; border-radius: 50%; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,0.16); color: #fff;
  border: 1px solid rgba(255,255,255,0.28);
  -webkit-backdrop-filter: blur(16px) saturate(140%); backdrop-filter: blur(16px) saturate(140%);
  box-shadow: 0 2px 12px rgba(0,0,0,0.4);
  transition: transform 0.12s ease, background 0.2s ease;
}
.mv-quick-close:active { transform: scale(0.9); background: rgba(255,255,255,0.26); }
.mv-quick-media { position: relative; line-height: 0; }
.mv-quick-video { display: block; max-width: 92vw; max-height: 76vh; border-radius: 22px; background: #000; }
.mv-quick-controls {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  transition: opacity 0.4s ease; opacity: 1;
}
.mv-quick-card.controls-hidden .mv-quick-controls { opacity: 0; pointer-events: none; }
.mv-quick-btn {
  width: 58px; height: 58px; border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(255,255,255,0.18); color: #fff;
  display: flex; align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 2px 12px rgba(0,0,0,0.35);
  transition: transform 0.12s ease;
}
.mv-quick-btn:active { transform: scale(0.9); }

/* v381 — READABILITY FIX. Programme body text was set to var(--cream-warm),
   which is #1B1A18 — the DARK panel surface, NOT a text colour (naming trap).
   On the dark card that rendered the writing near-invisible ("drowned"). Force
   all exercise text to --ink (#F5F0E2) for primary, --ink-soft for secondary.
   The coloured block bars/borders stay for visual structure. */
#section-programme .prog-concept,
#section-programme .prog-block-items li,
#section-programme .prog-block-items li.ex-sub,
#section-programme .prog-block-items li.ex-sub .ex-name,
#section-programme .prog-block-items .ex-name,
#section-programme .prog-ex-table .ex-name,
#section-programme .programme-exercises .ex-name,
#section-programme .prog-warm-up,
#section-programme .prog-warm-up strong,
#section-programme .prog-cool-down,
#section-programme .prog-cool-down strong { color: var(--ink) !important; }
#section-programme .prog-tagline,
#section-programme .prog-block-label,
#section-programme .prog-block-items .ex-detail,
#section-programme .prog-block-items li.ex-sub .ex-detail,
#section-programme .prog-ex-table .ex-reps,
#section-programme .prog-ex-table .ex-rest { color: var(--ink-soft) !important; }

/* v152 — Workout (follow along) typography to mirror the Programme bubble.
   Keeps the cream + gold colourway. Only the type hierarchy moves to match. */
#section-workout #workout-card .label {
  font-family: var(--sans);
  font-size: 11px; font-weight: 600;
  letter-spacing: 2px; text-transform: uppercase;
  color: var(--ink-soft);
}
#section-workout #workout-card #workout-title,
#section-workout #workout-card .workout-block-title {
  font-family: var(--display);
  font-weight: 400;            /* Bebas Neue is bold by default */
  font-size: clamp(28px, 6.4vw, 38px);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  line-height: 1.05;
  color: var(--ink);
  margin: 6px 0 8px;
}
#section-workout #workout-card #workout-blurb,
#section-workout #workout-card .workout-block-blurb {
  font-family: var(--sans);
  font-style: italic;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
  margin-bottom: 18px;
}
/* v243 — dual-author workout blocks (legacy shared layout). */
#section-workout #workout-card .workout-block + .workout-block {
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}
#section-workout .workout-block-author {
  display: inline-block;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 2px;
}
/* v243.1 — independent per-author cards stacked in #workout-cards-host.
   Each card carries its OWN completion button + comments thread so members
   can finish Miles' or Charlie's separately. */
#section-workout .workout-author-card + .workout-author-card {
  margin-top: 16px;
}
#section-workout .workout-author-card .workout-label {
  font-family: var(--sans);
  font-size: 11px; font-weight: 600;
  letter-spacing: 2px; text-transform: uppercase;
  color: var(--ink-soft);
  display: block;
  margin-bottom: 6px;
}
#section-workout .workout-author-card .workout-block-title {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(28px, 6.4vw, 38px);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  line-height: 1.05;
  color: var(--ink);
  margin: 6px 0 8px;
}
#section-workout .workout-author-card .workout-block-blurb {
  font-family: var(--sans);
  font-style: italic;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
  margin-bottom: 18px;
}
#section-workout .workout-author-card .exercise {
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  border-left: 3px solid rgba(245,194,0,0.3);
  padding-left: 14px;
  font-size: 14px;
  font-family: var(--sans);
}
#section-workout .workout-author-card .exercise:last-child { border-bottom: 0; }
#section-workout .workout-author-card .exercise > span:first-child {
  font-weight: 600; color: var(--ink);
}
#section-workout .workout-author-card .exercise .reps {
  font-weight: 600; color: var(--muted); font-size: 13px;
}
#section-workout #workout-card .exercise {
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  border-left: 3px solid rgba(245,194,0,0.3);
  padding-left: 14px;
  font-size: 14px;
  font-family: var(--sans);
}
#section-workout #workout-card .exercise:last-child { border-bottom: 0; }
#section-workout #workout-card .exercise > span:first-child {
  font-weight: 600;
  color: var(--ink);
}
#section-workout #workout-card .exercise .reps {
  font-weight: 600;
  color: var(--muted);
  font-size: 13px;
}
/* Headline above the day strip ("Live session" / "Past session") */
#section-workout .section-head #workout-headline {
  font-family: var(--display);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: 3px;
  text-transform: uppercase;
}

/* v153 — Sign-out button at the bottom of the profile section. Quiet
   destructive style so it's clearly available but not loud. */
#section-profile .prof-signout {
  display: block; width: 100%;
  margin: 24px 0 12px;
  padding: 14px;
  background: transparent;
  border: 1px solid rgba(176,0,32,0.32);
  color: #B00020;
  border-radius: 12px;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, border-color 0.15s ease;
}
#section-profile .prof-signout:hover { background: rgba(176,0,32,0.06); border-color: rgba(176,0,32,0.55); }
#section-profile .prof-signout:disabled { opacity: 0.6; cursor: progress; }

/* v203 — Collapsible profile sections (Identity / Body stats / Training).
   Tap header to expand. Native <details> for accessibility + zero-JS. */
#section-profile .prof-collapse {
  padding: 0;
  overflow: hidden;
}
#section-profile .prof-collapse > summary {
  list-style: none;
  cursor: pointer;
  padding: 16px 18px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  -webkit-tap-highlight-color: transparent;
}
#section-profile .prof-collapse > summary::-webkit-details-marker { display: none; }
#section-profile .prof-collapse-label {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--ink);
  letter-spacing: 0.01em;
}
#section-profile .prof-collapse-sub {
  font-size: 12px;
  color: var(--muted-dark, #8B857A);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#section-profile .prof-collapse-chev {
  font-size: 22px;
  color: var(--muted-dark, #8B857A);
  line-height: 1;
  transition: transform 0.2s ease;
  transform: rotate(0deg);
}
#section-profile .prof-collapse[open] > summary .prof-collapse-chev {
  transform: rotate(90deg);
}
#section-profile .prof-collapse-body {
  padding: 4px 18px 18px;
  border-top: 1px solid var(--line, rgba(20,20,20,0.06));
}
#section-profile .prof-collapse-body .admin-field { margin-top: 12px; }

/* v203 — Tiny GDPR data-export link under the sign-out button. */
#section-profile .prof-data-export-tiny {
  margin: 4px 4px 60px;
  font-size: 11px;
  color: var(--muted-dark, #8B857A);
  text-align: center;
  line-height: 1.5;
}
#section-profile .prof-data-export-tiny a {
  color: var(--muted-dark, #8B857A);
  text-decoration: underline;
  text-decoration-color: rgba(139,133,122,0.4);
}
#section-profile .prof-data-export-tiny .prof-data-export-why {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  opacity: 0.7;
}

/* v159 — Onboarding banners (post-wizard guided flow). Same shape on
   profile + vault so the journey feels stitched. Pulses softly to draw
   the eye without screaming. */
.onb-banner {
  background: rgba(245,194,0,0.10);
  border: 1px solid rgba(245,194,0,0.32);
  border-radius: 14px;
  padding: 14px 16px;
  margin: 0 0 18px;
  position: relative;
  animation: onb-pulse 2.4s ease-in-out infinite;
}
@keyframes onb-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245,194,0,0); }
  50%      { box-shadow: 0 0 0 6px rgba(245,194,0,0.06); }
}
.onb-banner-eyebrow {
  display: inline-block;
  font-size: 10px; font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--gold-deep, #C99A00);
  margin-bottom: 4px;
}
.onb-banner-body {
  margin: 0; font-size: 14px; color: var(--ink);
  line-height: 1.5;
}
.onb-banner-body strong { color: var(--ink); font-weight: 600; }

/* Recommended tier card glow — slight border lift so the matched card pops */
#section-vault .tier-card.is-recommended {
  box-shadow: 0 0 0 2px var(--gold), 0 12px 28px rgba(245,194,0,0.18);
  transform: translateY(-1px);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

/* ============================================================ */
/* v217 — Movement Library: tier pills, grid cards, fullscreen */
/* vertical video player with swipe nav.                       */
/* ============================================================ */
.movement-tier-pills {
  display: flex; gap: 8px;
  margin: 4px 0 14px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
}
.movement-pill {
  flex-shrink: 0;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(20, 20, 20, 0.06);
  border: 1px solid rgba(20, 20, 20, 0.10);
  font-family: var(--sans);
  font-size: 13px; font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
/* v221 — Pill text colours follow the tier (green / blue / gold). The
   pill background stays neutral; only the text picks up the tier ink. */
.movement-pill[data-tier="foundations"]     { color: #5FA800; }
.movement-pill[data-tier="development"]     { color: #185FA5; }
.movement-pill[data-tier="elite"]           { color: #C99A00; }
.movement-pill.active[data-tier="foundations"] { background: rgba(95, 168, 0, 0.12); border-color: rgba(95, 168, 0, 0.40); }
.movement-pill.active[data-tier="development"] { background: rgba(24, 95, 165, 0.12); border-color: rgba(24, 95, 165, 0.40); }
.movement-pill.active[data-tier="elite"]       { background: rgba(245, 194, 0, 0.16); border-color: rgba(245, 194, 0, 0.45); }

.movement-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-bottom: 24px;
}
.movement-card {
  position: relative;
  display: flex; flex-direction: column;
  background: #141414;
  border: 1px solid rgba(250, 246, 236, 0.10);
  border-radius: 14px;
  overflow: hidden;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease, border-color 0.15s ease;
}
.movement-card:active { transform: scale(0.98); }
.movement-card:hover { border-color: rgba(245, 194, 0, 0.45); }
.movement-card-thumb {
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  background: #0d0d0d;
  display: block;
}
/* v334 — poster-image grid. Shimmer wrapper sits behind the poster until
   it paints; img fades in on load. Skeleton cards reuse the same shapes. */
.movement-card-thumb-wrap {
  display: block;
  width: 100%;
  aspect-ratio: 9 / 16;
  overflow: hidden;
}
.movement-card-thumb-wrap .movement-card-thumb {
  opacity: 0;
  transition: opacity 0.25s ease;
}
.movement-card-thumb-wrap .movement-card-thumb.is-loaded { opacity: 1; }
.movement-card-skel { pointer-events: none; }
.movement-card-skel .movement-card-meta { gap: 6px; }
.movement-card-meta {
  padding: 10px 12px 12px;
  display: flex; flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  text-align: left;
  background: #141414;
}
.movement-card-label {
  font-family: var(--sans);
  font-size: 14px; font-weight: 600;
  color: var(--ink);
  line-height: 1.25;
}
.movement-card-sub {
  font-size: 11px;
  letter-spacing: 0.06em;
  color: rgba(250, 246, 236, 0.55);
}
.movement-card-edit {
  position: absolute; top: 8px; right: 8px;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  border: 0;
  color: var(--gold);
  font-size: 14px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.movement-empty {
  text-align: center;
  padding: 40px 16px;
  color: var(--muted-dark, #8B857A);
}
.movement-empty .empty-line { font-size: 15px; font-weight: 600; margin: 0 0 6px; }
.movement-empty .empty-sub  { font-size: 13px; opacity: 0.7; }

/* v218 — TikTok-style snap-scroll vertical player.
   Each .movement-slide is a full-viewport section. CSS scroll-snap
   handles the roll animation; JS picks the in-view one to autoplay. */
.movement-player {
  position: fixed; inset: 0;
  z-index: 9500;
  background: #000;
  height: 100vh; height: 100dvh;
  user-select: none;
  -webkit-user-select: none;
  overflow: hidden;
}
.movement-player[hidden] { display: none; }
.movement-player-close {
  position: absolute; top: calc(env(safe-area-inset-top, 0px) + 12px); right: 16px;
  z-index: 3;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  border: 0;
  color: var(--cream-warm);
  font-size: 28px; line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.movement-player-feed {
  position: absolute; inset: 0;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.movement-player-feed::-webkit-scrollbar { display: none; }
.movement-slide {
  position: relative;
  height: 100vh; height: 100dvh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  background: #000;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.movement-slide-video {
  width: 100%;
  height: 100%;
  /* v219 — Cover-fit fills the whole viewport so there's no black gap
     between clips even when Miles shoots in 4:3 or 16:9. Some edge
     cropping is the trade — TikTok pattern. The blurred backdrop layer
     below keeps the empty space visually filled if cover ever falls
     short. */
  object-fit: cover;
  background: #000;
  position: relative;
  z-index: 1;
}
.movement-slide-bg {
  position: absolute;
  inset: -10%;
  width: 120%;
  height: 120%;
  object-fit: cover;
  filter: blur(28px) brightness(0.45);
  z-index: 0;
  pointer-events: none;
}
.movement-slide-meta {
  position: absolute;
  /* v218 — Raised the meta block off the bottom so the iOS home indicator
     + the swipe hint underneath have room. Was clipping out of frame. */
  bottom: calc(env(safe-area-inset-bottom, 0px) + 110px);
  left: 20px; right: 20px;
  /* v220 — Force the label above the cover-fitted video + blurred backdrop. */
  z-index: 2;
  color: var(--cream-warm);
  pointer-events: none;
  text-shadow: 0 2px 10px rgba(0,0,0,0.7);
}
/* v221 — Branded loading state. CREST logo pulses softly in the centre
   of a deep-black slide while the video buffers. Hides as soon as the
   video reports loadeddata. */
.movement-slide-shimmer {
  position: absolute; inset: 0;
  z-index: 1;
  background:
    radial-gradient(ellipse at center, #1a1a1a 0%, #0a0a0a 70%);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.35s ease;
}
.movement-slide-shimmer::before {
  content: "";
  display: block;
  width: 88px;
  height: 88px;
  background-image: url('/assets/shield-header.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: 0.55;
  filter: drop-shadow(0 0 24px rgba(245, 194, 0, 0.30));
  animation: movementLoadingPulse 1.6s ease-in-out infinite;
}
.movement-slide.is-ready .movement-slide-shimmer { opacity: 0; }
@keyframes movementLoadingPulse {
  0%, 100% { transform: scale(0.96); opacity: 0.45; }
  50%      { transform: scale(1.04); opacity: 0.80; }
}
.movement-slide-tier {
  font-family: var(--display);
  font-size: 13px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  margin-bottom: 6px;
  /* colour set inline per slide so each tier glows green / blue / gold */
}
.movement-slide-label {
  font-family: var(--sans);
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  margin-bottom: 6px;
}
.movement-slide-counter {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.7);
  letter-spacing: 0.06em;
}
.movement-player-hint {
  position: absolute;
  /* v218 — Lifted clear of the iOS home indicator + safe area. */
  bottom: calc(env(safe-area-inset-bottom, 0px) + 56px);
  left: 0; right: 0;
  z-index: 2;
  text-align: center;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.55);
  letter-spacing: 0.04em;
  pointer-events: none;
}

@media (min-width: 480px) {
  .movement-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ============================================================
   v245 — DARK THEME CONTRAST GUARDS
   The whole app inverted to dark. Two classes of element broke:
   (1) gold backgrounds with --ink coloured text — once --ink became cream,
       the text drowned in the yellow.
   (2) the calc-card / wp-complete-btn / day-strip indicator which used
       var(--ink) AS the background to be the "dark special card" in the
       otherwise-light app. Now redundant — they need explicit dark colours.
   Local --ink override re-tames child text under these surfaces.
   ============================================================ */
.onb-next,
.crest-confirm-ok,
.admin-tab.active,
.admin-row-edit:active,
.composer-post,
.completion-btn.done,
.day-cell.selected,
.day-cell.today,
.gold-cta,
.programme-cta {
  --ink: #141414; /* keep text dark when sitting on yellow */
}

.calc-card {
  background: #141414;
  color: #F5F0E2;
  border-color: #141414;
}
.calc-card h1, .calc-card h2, .calc-card h3, .calc-card p, .calc-card span,
.calc-card .label, .calc-card .calc-row, .calc-card .calc-cal {
  color: #F5F0E2;
}
.calc-card .label, .calc-card .muted { color: #C8C2B5; }

/* Day-strip pill — keep its dark-on-gold contrast even though variables flipped. */
.day-cell.selected .num,
.day-cell.selected .dow,
.day-cell.selected .mon,
.day-cell.today .num,
.day-cell.today .dow,
.day-cell.today .mon { color: #141414; }

/* iOS standalone (PWA) status-bar background colour. */
html, body { background: var(--cream); }

/* Inputs sometimes inherited white from user-agent. Force panel colour. */
input, textarea, select {
  background: var(--cream-warm);
  color: var(--ink);
  border-color: var(--line);
}
input::placeholder, textarea::placeholder { color: var(--muted); }

/* ============================================================
   v270 — Ladder-style community avatar strip on the Feed.
   Double-tap a circle to send a hype. Tier ring stays as the
   identity layer; streak pill at the bottom-right shows activity.
   ============================================================ */
.community-strip-wrap {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  /* v341 — full-bleed: break out of main's 20px gutters so scrolling avatars
     run to the true screen edge instead of clipping 20px short (Sam's
     "black bar cutting the images off"). The strip's own side padding keeps
     the resting position aligned with the rest of the feed content. */
  margin: 0 -20px;
  padding: 4px 0 10px;
}
/* v451 — left-of-carousel hype-sent counter: a gold ring ("N / sent" + flame)
   or a "Double-tap to send hype" prompt in the same ring. Pinned, with a
   vertical divider before the scrolling avatars (Ladder pattern). */
.strip-hype-counter {
  flex: 0 0 auto;
  align-self: center;
  display: flex;
  align-items: center;
  gap: 12px;
  padding-left: 2px;
  /* v604 — counter sat low because the avatars carry name labels below them, so
     align-self:center dragged the ring downward. Nudge up 5px to line the ring
     up with the avatar circles. Carousel untouched. Easy to tweak ±1px. */
  transform: translateY(-5px);
}
.strip-hype-counter::after {
  content: "";
  width: 1px;
  height: 46px;
  background: var(--line);
}
.strip-hype-counter .shc-wrap { position: relative; width: 60px; height: 60px; flex: 0 0 auto; }
.strip-hype-counter .shc-ring {
  width: 60px; height: 60px; border-radius: 50%;
  /* v470 — plain cream disc; the gold OPEN ring (gap + rounded ends) is the
     overlaid SVG below, so the caps round cleanly. */
  background: var(--cream-warm);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; line-height: 1;
}
.strip-hype-counter .open-ring.sent-ring {
  position: absolute;
  top: -3px;
  left: 50%;
  width: 66px;
  height: 66px;
  transform: translateX(-50%);
  color: var(--gold);
  pointer-events: none;
  z-index: 1;
}
/* v469 — empty state (brand-new user, no hypes sent) has no flame to fill the
   gap, so keep its ring fully closed. */
.strip-hype-counter .shc-ring.is-empty {
  background: var(--cream-warm);
  box-shadow: 0 0 0 3px var(--gold);
}
.strip-hype-counter .shc-num { font-family: var(--serif); font-weight: 700; font-size: 15px; color: var(--ink); }
.strip-hype-counter .shc-label { font-size: 10px; color: var(--ink-soft); letter-spacing: 0.05em; margin-top: 2px; }
.strip-hype-counter .shc-prompt {
  font-size: 8.5px; font-weight: 600; color: var(--ink);
  line-height: 1.18; letter-spacing: 0.01em; padding: 0 7px;
}

.community-strip {
  flex: 1 1 auto;
  display: flex;
  gap: 12px;
  overflow-x: auto;
  overflow-y: hidden;        /* v458 — lock to horizontal scroll only (no diagonal/vertical drift) */
  touch-action: pan-x;       /* v458 — touch can only pan the strip left/right */
  scroll-snap-type: x proximity;
  padding: 6px 20px 16px;    /* v479 — extra bottom room so overflow-y:hidden doesn't clip the rhomboid's drop shadow */
  scrollbar-width: none;
}
.community-strip::-webkit-scrollbar { display: none; }

.strip-avatar {
  flex: 0 0 auto;
  position: relative;
  background: transparent;
  border: 0;
  padding: 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  scroll-snap-align: start;
  transition: transform 0.18s var(--ease-spring-soft);
}
.strip-avatar:active { transform: scale(0.94); }

.strip-avatar-photo {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  position: relative;   /* v456 — anchor for the nested on-fire flame */
  background-color: var(--cream-warm);
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 22px;
  color: var(--ink);
  box-shadow: 0 0 0 2px rgba(255,255,255,0.06);
}

/* v470 — Tier ring is now the SVG OPEN ring (gap at the bottom, rounded ends),
   NOT a box-shadow. Colour comes from the SVG stroke (set per tier in JS). The
   old box-shadow tier rings are gone so there's no double ring. */
.strip-avatar .open-ring.strip-ring {
  position: absolute;
  top: -2px;            /* 68px ring box centred over the 60px photo (2px pad) */
  left: 50%;
  width: 68px;
  height: 68px;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 1;
}

/* Rhomboid streak pill, seated in the ring's bottom gap. Always shown (even 0
   streak) — Ladder layout. The hype flame takes this slot for 2 min on a hype. */
.strip-streak-pill {
  position: absolute;
  left: 50%;
  bottom: -3px;
  transform: translateX(-50%);
  background: #1E1E20;       /* v479 — darker charcoal (Sam: was too light) */
  color: #FFFFFF;
  font-family: var(--sans);
  font-size: 9px;          /* v472 — smaller (Sam) */
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 1px 5px;        /* v472 — narrower so the ring ends peek out either side */
  display: inline-flex;
  align-items: center;
  gap: 1px;
  z-index: 3;
  white-space: nowrap;
  border-radius: 3px;
  /* v478 — soft pooled drop shadow → floating effect (Sam's Ladder ref). filter
     (NOT box-shadow) so it follows the clip-path rhomboid instead of being clipped. */
  /* v482 — dark pill on a dark bg: a black shadow alone is invisible. So pair a
     faint white hairline rim (separates the rhomboid edge from the background)
     with a wide, feathered black drop (the float). */
  filter:
    drop-shadow(0 0 0.6px rgba(255,255,255,0.35))
    drop-shadow(0 4px 9px rgba(0,0,0,0.95));
}
.strip-streak-pill svg { width: 7px; height: 7px; }  /* v472 — shrink the bolt to match */
.strip-streak-pill.rhomboid { clip-path: polygon(16% 0%, 100% 0%, 84% 100%, 0% 100%); }

/* Open-ring colour per tier (stroke = currentColor). No-tier members get a
   faint white ring, like Ladder's "CB" placeholder. */
.strip-avatar .open-ring.strip-ring { color: rgba(255,255,255,0.18); }
.strip-avatar.has-tier-foundations .open-ring.strip-ring { color: var(--tier-green); }
.strip-avatar.has-tier-development .open-ring.strip-ring { color: var(--tier-blue); }
.strip-avatar.has-tier-elite       .open-ring.strip-ring { color: var(--gold); }
.strip-avatar.has-tier-miles_programme .open-ring.strip-ring { color: #7DD3FC; }
.strip-avatar.has-tier-booty_programme .open-ring.strip-ring { color: var(--booty-pink); }
/* v481 — bolt matches the user's programme colour (echoes their ring). Default
   light blue for no-tier members. */
.strip-streak-pill svg { fill: #8FC2FF; color: #8FC2FF; }
.strip-avatar.has-tier-foundations    .strip-streak-pill svg { fill: var(--tier-green); }
.strip-avatar.has-tier-development     .strip-streak-pill svg { fill: var(--tier-blue); }
.strip-avatar.has-tier-elite           .strip-streak-pill svg { fill: var(--gold); }
.strip-avatar.has-tier-miles_programme .strip-streak-pill svg { fill: #7DD3FC; }
.strip-avatar.has-tier-booty_programme .strip-streak-pill svg { fill: var(--booty-pink); }
/* v391 — reverted the v386 blue "lightning" recolour of the streak bolt (Sam):
   the streak number + bolt stay gold/white everywhere as before. The lightning
   is ONLY the Lottie on the big profile/member-sheet avatars. */

.strip-avatar-name {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-soft);
  max-width: 70px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.strip-avatar.is-me .strip-avatar-name { color: var(--gold); }

/* Heart burst on double-tap */
/* v351 — Ladder-style flame eruption. Emoji glyphs spawn around the hyped
   avatar and float up out of the screen like helium balloons: rise, sway
   (S-curve via the 55% keyframe), spin and fade — all randomised per flame
   through CSS custom properties set inline by heartBurst(). */
.hype-emoji {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  line-height: 1;
  will-change: transform, opacity;
  transform: translate(-50%, -50%) scale(0.3);
  animation: hypeFloat var(--dur, 1400ms) cubic-bezier(0.18, 0.6, 0.4, 1) var(--delay, 0ms) forwards;
}
@keyframes hypeFloat {
  0% {
    transform: translate(-50%, -50%) scale(0.3) rotate(var(--rot0, 0deg));
    opacity: 0;
  }
  12% {
    transform: translate(-50%, -65%) scale(var(--scale, 1)) rotate(var(--rot0, 0deg));
    opacity: 1;
  }
  55% {
    transform: translate(calc(-50% - var(--sway, 0px) * 0.5), calc(-50% - var(--rise, 200px) * 0.55)) scale(var(--scale, 1)) rotate(var(--rot1, 0deg));
    opacity: 1;
  }
  100% {
    transform: translate(calc(-50% + var(--sway, 0px)), calc(-50% - var(--rise, 200px))) scale(calc(var(--scale, 1) * 0.85)) rotate(var(--rot0, 0deg));
    opacity: 0;
  }
}

/* v355 — Sam's fire-ring SPRITE SHEET (25 frames, 112px, extracted from
   his ChatGPT sheet). Plays once around the avatar on hype: ignite → burn →
   break apart. steps(24) walks background-position across the strip;
   screen blending kills the sheet's dark interior so only flame light
   shows over the app. The photo sits on top — ring peeks around it. */
.hype-fire {
  position: relative;
  z-index: 0; /* own stacking context so the -1 pseudo stays inside */
}
.hype-fire::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 165%;
  height: 165%;
  border-radius: 50%;
  pointer-events: none;
  z-index: -1;
  background: url("/assets/fire-ring-sprite.png") 0 0 no-repeat;
  background-size: 2500% 100%;
  mix-blend-mode: screen;
  opacity: 0;
  transform: translate(-50%, -50%);
  animation:
    hypeFireSprite 1.2s steps(24) forwards,
    hypeFireFade 1.2s linear forwards;
}
@keyframes hypeFireSprite {
  from { background-position-x: 0%; }
  to   { background-position-x: 100%; }
}
@keyframes hypeFireFade {
  0%   { opacity: 0; }
  6%   { opacity: 1; }
  82%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Brightness flash on whatever got hyped (strip circle or card avatar) */
.hype-flash {
  animation: hypeFlash 0.6s ease;
}
@keyframes hypeFlash {
  0%   { filter: brightness(1); }
  28%  { filter: brightness(1.65) saturate(1.35); }
  100% { filter: brightness(1); }
}

/* Tier colour vars — declared once so the rings have something to reach for */
:root {
  --tier-green: #5BC85B;
  --tier-blue:  #5B9BFF;
}

/* v272 — Fix the rectangular blue artifact around .strip-avatar buttons on
   some iOS Safari versions (default button render leaked a tap rect). Lock
   the wrapper to a circle, kill any native button appearance / focus ring. */
.strip-avatar {
  appearance: none;
  -webkit-appearance: none;
  outline: none;
  border-radius: 50%;
  box-shadow: none;
}
.strip-avatar:focus,
.strip-avatar:focus-visible,
.strip-avatar:active {
  outline: none;
  box-shadow: none;
}
/* Wrapper button must NOT carry the tier ring; only the inner photo does. */
.strip-avatar[class*="has-tier-"] { box-shadow: none !important; }

/* v272 — Brand title inside the section head. Replaces the global header
   logo. Logo sits BEFORE the wordmark, both inline. */
.brand-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
}
.brand-title-logo {
  /* v320 — Lift the shield up so its top edge aligns with the cap line of
     the "C" instead of sitting on the baseline. */
  height: 1.05em;
  width: auto;
  object-fit: contain;
  display: inline-block;
  flex-shrink: 0;
  position: relative;
  top: -0.08em;
}

/* v276 — Tighten the dead space between the top header (profile pic) and
   the Feed content. Cuts header padding + section-head top margin in half. */
.app-header {
  padding: 8px 16px 4px;
}
#section-feed .section-head {
  margin: 6px 0 10px;
}

/* v281 — iOS-style activity-spinner pull-to-refresh. 12 yellow radial ticks,
   each fading sequentially as the spinner rotates. The Feed section translates
   down with the finger (Instagram-style tactile pull). */
.ptr-indicator {
  /* v288 — Instagram-style. Fixed-position spinner just below the pinned
     CREST title row. The pulled-down content slides away from it; spinner
     stays planted, dead-centre, in the gap. */
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 72px);
  left: 0;
  right: 0;
  margin: 0 auto;
  width: 28px;
  height: 28px;
  pointer-events: none;
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.18s ease, transform 0.18s ease;
  z-index: 60;
}
.ptr-indicator.visible {
  opacity: 1;
  transform: scale(1);
}
.ptr-spinner {
  position: relative;
  width: 100%;
  height: 100%;
}
.ptr-spinner span {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2.5px;
  height: 7px;
  margin-left: -1.25px;
  margin-top: -14px;
  background: var(--gold);
  border-radius: 2px;
  transform-origin: 50% 14px;
  opacity: 0.18;
}
.ptr-spinner span:nth-child(1)  { transform: rotate(  0deg); }
.ptr-spinner span:nth-child(2)  { transform: rotate( 30deg); }
.ptr-spinner span:nth-child(3)  { transform: rotate( 60deg); }
.ptr-spinner span:nth-child(4)  { transform: rotate( 90deg); }
.ptr-spinner span:nth-child(5)  { transform: rotate(120deg); }
.ptr-spinner span:nth-child(6)  { transform: rotate(150deg); }
.ptr-spinner span:nth-child(7)  { transform: rotate(180deg); }
.ptr-spinner span:nth-child(8)  { transform: rotate(210deg); }
.ptr-spinner span:nth-child(9)  { transform: rotate(240deg); }
.ptr-spinner span:nth-child(10) { transform: rotate(270deg); }
.ptr-spinner span:nth-child(11) { transform: rotate(300deg); }
.ptr-spinner span:nth-child(12) { transform: rotate(330deg); }
.ptr-indicator.spinning .ptr-spinner span { animation: ptrTick 1.1s linear infinite; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(1)  { animation-delay: -1.10s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(2)  { animation-delay: -1.00s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(3)  { animation-delay: -0.91s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(4)  { animation-delay: -0.82s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(5)  { animation-delay: -0.73s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(6)  { animation-delay: -0.64s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(7)  { animation-delay: -0.55s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(8)  { animation-delay: -0.46s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(9)  { animation-delay: -0.37s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(10) { animation-delay: -0.28s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(11) { animation-delay: -0.19s; }
.ptr-indicator.spinning .ptr-spinner span:nth-child(12) { animation-delay: -0.10s; }
@keyframes ptrTick {
  0%   { opacity: 1; }
  100% { opacity: 0.18; }
}

/* v288 — Only the CONTENT below the CREST title slides on pull. The
   section-head with the title + profile pic stays pinned, Instagram-style. */
#feed-scroll {
  transform: translateY(var(--ptr-pull, 0px));
  transition: transform 0.32s cubic-bezier(0.18, 1.4, 0.5, 1);
}
#section-feed.ptr-active #feed-scroll {
  transition: none;
}

/* v276 — Section needs relative positioning so the absolutely-positioned
   ptr-indicator anchors to the section, not the body. */
#section-feed { position: relative; }

/* v278 — Aggressive native pull-to-refresh kill. iOS PWA standalone still
   showed "Pull to refresh" because `contain` allows browser chrome refresh.
   `none` blocks it outright. */
html, body {
  overscroll-behavior: none;
}

/* v278 — Profile pic moved INLINE with the CREST section heading on the right.
   Pads the safe-area top so it sits below the iOS status bar. */
.section-head-with-profile {
  align-items: center;
  padding-top: calc(env(safe-area-inset-top, 0px) + 4px);
  gap: 12px;
}
.section-head-with-profile .header-profile {
  margin-left: auto;
  flex: 0 0 auto;
}

/* v289 — Settings cog button on Profile section-head, right-aligned next
   to the CREST heading. Same vibe as the inline profile pic on Feed. */
.prof-settings-cog {
  margin-left: auto;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  transition: background 0.18s ease, transform 0.18s var(--ease-spring-soft);
  -webkit-tap-highlight-color: transparent;
}
.prof-settings-cog:active { transform: scale(0.92); background: var(--cream-warm); }

#section-settings { padding-top: env(safe-area-inset-top, 0px); }

/* ============================================================
   v290 — Ladder-style profile hero (read-only display layer)
   The Settings sub-page still owns all editing. This section
   just renders name + avatar + tier + bio from the existing
   endpoints (/api/chat/profile + /api/auth/me + /api/member/streak).
   ============================================================ */
.prof-v2-hero {
  position: relative;
  padding: 20px 18px 24px;
  margin: 0 -16px;
}
.prof-v2-name-banner {
  position: absolute;
  /* v303 — shifted down so the default repeating tier banner doesn't
     collide with the grabber pill at the very top of the profile page.
     Custom user backgrounds are images on a different layer, so they're
     unaffected. */
  top: 18px;
  right: -8px;
  font-family: var(--display);
  font-size: 54px;
  letter-spacing: 0.02em;
  line-height: 0.95;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--gold);
  text-stroke: 1.5px var(--gold);
  opacity: 0.16;
  pointer-events: none;
  text-align: right;
  white-space: pre;
  z-index: 0;
}
.prof-v2-avatar-wrap {
  position: relative;
  width: 130px;
  height: 130px;
  z-index: 1;
}
.prof-v2-avatar {
  display: block;
  width: 130px;
  height: 130px;
  border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  /* v398 — no border on the profile photo (Sam). The tier "ring" used to paint
     here as a thick coloured border on the picture; with border:none the
     has-tier-* / has-tier-ring colour overrides become inert, so the photo is
     clean edge-to-edge. Tier still reads via the tier label + streak lightning;
     small avatars (strip/feed) keep their box-shadow ring. */
  border: none;
}
/* Tier rings on the hero avatar — same colour vocabulary used everywhere */
.prof-v2-hero.has-tier-foundations .prof-v2-avatar { border-color: var(--tier-green); }
.prof-v2-hero.has-tier-development .prof-v2-avatar { border-color: var(--tier-blue); }
.prof-v2-hero.has-tier-elite       .prof-v2-avatar { border-color: var(--gold); }

.prof-v2-streak-pill {
  position: absolute;
  /* v471 — slim RHOMBOID seated in the open ring's bottom gap (Ladder). Was a
     big rounded pill that covered the ring; now a small parallelogram with a
     hair of space from the ring's rounded ends on each side. */
  left: 50%;
  bottom: -11px;            /* v473 — down a touch so the number lines up with the ring's bottom edge */
  transform: translateX(-50%);
  background: #474C52;       /* v473 — gunmetal gray (Sam) */
  color: #FFFFFF;
  border: none;
  border-radius: 4px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 3px 12px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  z-index: 6;   /* above the open ring + on-fire flame */
  white-space: nowrap;
}
.prof-v2-streak-pill.rhomboid { clip-path: polygon(15% 0%, 100% 0%, 85% 100%, 0% 100%); }

/* v474 — profile reverts to a FULL closed tier ring. The streak already lives in
   the Streak gauge below, so the avatar pill was redundant (Sam) — removed, and
   with the flame also gone the open-ring gap had nothing to hold. The open ring
   is now a CAROUSEL-ONLY signature. (Box-shadow full ring restored via the
   existing .prof-v2-hero.has-tier-ring .prof-v2-avatar rule.) */
.prof-v2-avatar-wrap .open-ring.profile-ring { display: none; }
.prof-v2-streak-pill { display: none; }
.prof-v2-streak-pill svg { color: var(--gold); }
.prof-v2-streak-pill[hidden] { display: none; }

.prof-v2-name {
  font-family: var(--display);
  font-weight: 400;
  font-size: 38px;
  letter-spacing: 0.5px;
  line-height: 1;
  color: var(--ink);
  margin: 18px 0 6px;
  position: relative;
  z-index: 1;
}
.prof-v2-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  position: relative;
  z-index: 1;
}
.prof-v2-tier {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}
.prof-v2-tier.has-tier-foundations { color: var(--tier-green); }
.prof-v2-tier.has-tier-development { color: var(--tier-blue); }
.prof-v2-tier.has-tier-elite       { color: var(--gold); }
.prof-v2-bio {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink-soft);
  line-height: 1.55;
  margin: 12px 0 0;
  position: relative;
  z-index: 1;
  /* v303 — render the bio as stacked vertical lines (one per newline)
     instead of collapsing into a single horizontal paragraph. Mirrors
     the way Ladder shows the three bio lines on a public profile. */
  white-space: pre-line;
}
/* v303 — Feed-as-backdrop. While the user pulls the Profile page down,
   #section-feed renders behind at full brightness so it reads as the real
   page sitting beneath the lifted profile card (matches the Ladder
   reference Sam shared — no dimming, no blur). */
#section-feed.feed-as-backdrop {
  display: block !important;
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 1;
  overflow: hidden;
  /* v339 — mirror main's side gutters (main: padding 0 20px, max-width 720,
     centered). position:fixed rips the section out of <main>, so without
     these the backdrop renders 40px WIDER than the real feed — Sam saw the
     feed "snap thinner" when the profile dismiss finished and the element
     swapped back into flow. Match the box, kill the snap. */
  padding: 0 20px;
  max-width: 720px;
  left: 50%;
  right: auto;
  width: 100%;
  transform: translateX(-50%);
}
/* Keep the profile above the feed-backdrop during the drag. */
#section-profile.active {
  position: relative;
  z-index: 1;
  /* v344 — no generic fade-in for the profile: its entrance is the slide-up.
     Without this, removing .slide-up-enter flipped animation back to fadein
     and restarted it = opacity dip + 4px jolt at the end of the slide. */
  animation: none;
}
/* Card-on-top-of-deck look during the pull-down. Rounded top edge + a
   crisp top shadow so the profile reads as a real card lifted off the
   feed beneath. Applied only while pulling. */
/* v344 — full-bleed card surface WITHOUT changing the section's geometry.
   v342 used position:fixed + padding, which widened the section box by 40px:
   absolutely-positioned children (the settings cog) anchor to the box edges,
   so the cog jumped 20px left when the class came off. Now the card surface
   is a ::before pseudo extending past the gutters — the section box never
   changes, so nothing anchored to it can move. Shared by the drag-dismiss
   (is-pulling) and the slide-up entrance. */
#section-profile.is-pulling,
#section-profile.slide-up-enter {
  position: relative;
  z-index: 2; /* v345 — above the blur veil (z 1), which is above the feed backdrop (z 0) */
}
#section-profile.is-pulling::before,
#section-profile.slide-up-enter::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  left: -20px;
  right: -20px;
  height: max(100%, 110vh);
  background: var(--cream);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -14px 32px rgba(0, 0, 0, 0.55);
}
/* v343 — profile ENTRANCE: slides up from the bottom as a full-bleed
   rounded card over the still-painted feed — the same surface the pull-down
   drag uses, so open and close are mirror images (matches the member card).
   The class is removed ~440ms later and the section returns to normal flow;
   the box is pixel-identical so the handoff is invisible. */
#section-profile.slide-up-enter {
  animation: profileSlideUp 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
  transition: none;
}
@keyframes profileSlideUp {
  from { transform: translate3d(0, 100vh, 0); }
  to   { transform: translate3d(0, 0, 0); }
}

/* v345 — blur veil behind the own-profile card (entrance + pull-down).
   Same dim+blur recipe as the member card's .profile-sheet-backdrop; JS
   drives opacity from the drag position so the feed un-blurs as the card
   nears the bottom. pointer-events:none — purely visual. */
.profile-pull-veil {
  position: fixed;
  inset: 0;
  z-index: 1;
  /* v346 — solid black at the very top, fading to the standard dim. The
     webview stops just below the iOS status bar (status-bar-style=default),
     and the lighter blurred feed made that boundary visible while dragging.
     Blending to pure black matches the system bar above = seamless. */
  background: linear-gradient(to bottom, #000 0, rgba(0, 0, 0, 0.45) calc(env(safe-area-inset-top, 0px) + 48px));
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* v343 — one-shot mute for a section's entry fade. Used when the feed
   re-activates after the profile dismiss: it's already fully painted as the
   backdrop, so re-running the fade made the screen flash. */
.section.no-anim {
  animation: none !important;
  transition: none !important;
}

/* v303 — iOS-style grabber pill at the very top of the main profile page,
   signalling the existing pull-down-to-close gesture. */
.prof-grabber {
  width: 36px;
  height: 5px;
  background: rgba(255, 255, 255, 0.34);
  border-radius: 999px;
  margin: 8px auto 4px;
  pointer-events: none;
  position: relative;
  z-index: 2;
}

/* ============================================================
   v291 — Profile stats + history calendar + last workout
   ============================================================ */
.prof-v2-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 24px 0 10px;
  padding: 0 4px;
}
.prof-v2-stat {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 6px 0 4px;
}
/* v417 — number-hero gauges. The ring is a DESIGNED container (full circle in
   the gauge colour, soft glow, faint radial tint behind), not a progress meter.
   The rolling number in the middle is the hero. */
.prof-v2-ring {
  width: 72px;
  height: 72px;
  margin-bottom: 4px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, rgba(245,194,0,0.10), transparent 68%);
}
.prof-v2-stat[data-key="streak"]  .prof-v2-ring { background: radial-gradient(circle at 50% 50%, rgba(255,138,61,0.12), transparent 68%); }
.prof-v2-stat[data-key="longest"] .prof-v2-ring { background: radial-gradient(circle at 50% 50%, rgba(125,211,252,0.12), transparent 68%); }
.prof-v2-stat[data-key="hypes"]   .prof-v2-ring { background: radial-gradient(circle at 50% 50%, rgba(255,107,129,0.12), transparent 68%); }

.prof-v2-ring .ring-bg { stroke: rgba(255,255,255,0.06); }
.prof-v2-ring .ring-fg {
  stroke: var(--gold);
  stroke-linecap: round;
  transition: stroke-dashoffset 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  filter: drop-shadow(0 0 3px rgba(245,194,0,0.55));
}
.prof-v2-stat[data-key="streak"]  .ring-fg { stroke: #FF8A3D; filter: drop-shadow(0 0 3px rgba(255,138,61,0.55)); }
.prof-v2-stat[data-key="longest"] .ring-fg { stroke: #7DD3FC; filter: drop-shadow(0 0 3px rgba(125,211,252,0.55)); }
.prof-v2-stat[data-key="hypes"]   .ring-fg { stroke: #FF6B81; filter: drop-shadow(0 0 3px rgba(255,107,129,0.55)); }
/* v467 — transient "just hyped" flame. SOLO emoji — no chip, no ring, no pill.
   Sits at the foot of the avatar. While .flaming, the streak pill is hidden so
   it's purely the flame; after 2 min .flaming is removed → flame fades out and
   the streak fades back in. */
.hyped-flame {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  line-height: 1;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s ease;
}
/* v469 — flame pops in (scale up, settle to 1) when it appears, just after the
   burst. The pop handles the entrance; opacity fades it out on removal. */
.strip-avatar.flaming .hyped-flame,
.member-sheet-avatar-wrap.flaming .hyped-flame {
  opacity: 1;
  animation: hypeFlamePop 0.44s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes hypeFlamePop {
  0%   { transform: translateX(-50%) scale(0.2); }
  60%  { transform: translateX(-50%) scale(1.3); }
  100% { transform: translateX(-50%) scale(1); }
}
/* hide the streak UI while the flame is showing; both cross-fade */
.strip-streak-pill,
.prof-v2-streak-pill { transition: opacity 0.45s ease; }
.strip-avatar.flaming .strip-streak-pill,
.member-sheet-avatar-wrap.flaming .prof-v2-streak-pill { opacity: 0; }
/* v469 — bottom of the emoji sits ON the bottom of the avatar ring (was hanging
   too low). Small on the packed carousel, large on the profile card. */
.strip-avatar .hyped-flame { font-size: 15px; bottom: -3px; }  /* v476 — up 1px (Sam) */
.member-sheet-avatar-wrap .hyped-flame { font-size: 30px; bottom: 3px; }

/* v467 — flame at the foot of the "N sent" counter ring (Ladder's "30 sent" +
   peach reference). SOLO emoji, no chip — just sits on the bottom edge. */
.strip-hype-counter .shc-flame {
  position: absolute;
  left: 50%;
  bottom: -3px;          /* v469 — sits IN the ring's bottom gap, Ladder-style */
  transform: translateX(-50%);
  font-size: 16px;
  line-height: 1;
  z-index: 2;
  pointer-events: none;
}
.prof-v2-stat-num {
  /* v419 — overlay the number as a flexbox sized EXACTLY to the ring (top =
     stat padding-top, height = ring height) and flex-centre it. Replaces the
     old magic top/left that sat the number high-and-right of centre. */
  position: absolute;
  top: 6px;            /* = .prof-v2-stat padding-top, aligns with ring top */
  left: 0; right: 0;
  height: 72px;        /* = .prof-v2-ring height */
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-weight: 400;
  font-size: 24px;
  color: var(--ink);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  z-index: 2;           /* v420 — sit above the streak lightning FX */
}

/* v420 — lightning Lottie for the Streak gauge. A circle smaller than the ring
   stroke, clipped, sitting behind the number (z-index 1 < num's 2) so bolts
   strike INSIDE the ring without spilling over it or covering the number. */
.prof-v2-stat .streak-fx {
  position: absolute;
  top: 42px;            /* ring centre: 6px padding-top + half of 72px ring */
  left: 50%;
  transform: translate(-50%, -50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  overflow: hidden;
  z-index: 1;
  pointer-events: none;
  transition: opacity 0.25s ease;   /* v421 — smooth fade between strikes */
}
/* v422 — inner wrapper holds the Lottie + the per-strike mirror/offset transform
   (transform set instantly while fx is faded out, so no visible sliding). */
.prof-v2-stat .streak-fx-inner {
  position: relative;
  width: 100%;
  height: 100%;
}
/* v423 — fire FX for the hypes ring. Same clipped circle, warmed to orange
   (source flame is yellow) + an orange glow halo. Flames are pushed down via
   the player's offsetY so they rise from the bottom of the circle. */
.prof-v2-stat .hypes-fx {
  position: absolute;
  top: 42px;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  overflow: hidden;
  z-index: 1;
  pointer-events: none;
  filter: hue-rotate(-22deg) saturate(1.5) brightness(1.05) drop-shadow(0 0 4px rgba(255,94,58,0.55));
}
.prof-v2-stat-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--ink-soft);
  margin-top: 2px;
  text-transform: uppercase;
}

/* History calendar */
.prof-v2-history { margin: 28px 0 14px; padding: 0 4px; }
.prof-v2-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.prof-v2-history-head h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 22px;
  letter-spacing: 0.04em;
  color: var(--ink);
  margin: 0;
}
.prof-v2-month-nav {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: var(--ink-soft);
}
.prof-v2-month-nav button {
  background: transparent;
  border: 0;
  width: 32px;
  height: 32px;
  color: var(--ink-soft);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.prof-v2-month-nav button:active { background: var(--cream-warm); }
.prof-v2-month-label {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.02em;
  min-width: 110px;
  text-align: center;
}
.prof-v2-cal-dow {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-align: center;
  margin-bottom: 6px;
}
.prof-v2-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.prof-v2-cal-day {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-soft);
  background: transparent;
}
.prof-v2-cal-day.empty { visibility: hidden; }
.prof-v2-cal-day.done {
  background: var(--gold);
  color: #141414;
}
/* v615 — today's gold ring removed (Sam). Today is no longer outlined; the
   gold "done" fill and the glowing event ring carry the calendar on their own. */
.prof-v2-cal-day.is-today { outline: 0; }
.prof-v2-cal-day.future { color: var(--muted); opacity: 0.4; }
/* v616 — event days: SOFT GLOW only (the hard amber ring line is gone, per Sam)
   that slowly pulses, plus a silver dot tucked JUST UNDER the number. No inset
   ring of any kind. */
@keyframes crestEventGlow {
  0%, 100% { box-shadow: 0 0 5px 1px rgba(245,166,35,0.45); }
  50%      { box-shadow: 0 0 13px 3px rgba(245,166,35,0.90); }
}
.prof-v2-cal-day.has-event {
  cursor: pointer;
  position: relative;
}
/* v639 — glow only for events that haven't started yet. Past events keep the
   silver dot but no longer pulse. */
.prof-v2-cal-day.has-event.is-upcoming {
  animation: crestEventGlow 2.6s ease-in-out infinite;
}
/* silver dot sits right below the number (not at the bottom of the circle). */
.prof-cal-evdot {
  position: absolute; left: 50%; top: calc(50% + 8px); transform: translateX(-50%);
  width: 5px; height: 5px; border-radius: 50%;
  /* v617 — flat 2D silver, no gradient, no outline/shadow (Sam). */
  background: #C7C7CC;
}
@media (prefers-reduced-motion: reduce) {
  .prof-v2-cal-day.has-event.is-upcoming { animation: none; box-shadow: 0 0 8px 2px rgba(245,166,35,0.6); }
}
/* v613 — calendar grabber pill (swipe the section down to dismiss → profile). */
.cal-grabber {
  width: 40px; height: 5px; border-radius: 3px;
  background: rgba(255,255,255,0.22);
  margin: 8px auto 4px;
}

/* Last workout card */
.prof-v2-last-workout {
  margin: 18px 4px 6px;
  padding: 14px 16px;
  background: var(--cream-warm);
  border: 1px solid var(--line);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.prof-v2-last-date {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.prof-v2-last-title {
  font-family: var(--display);
  font-weight: 400;
  font-size: 20px;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.prof-v2-last-author {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--ink-soft);
}

/* v292 — Edit Profile pill button between hero and stats. */
.prof-v2-edit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  margin: 18px 0 4px;
  padding: 14px 22px;
  background: #1F1F22;
  border: 0;
  border-radius: 999px;
  color: #FFFFFF;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.12em;
  cursor: pointer;
  transition: background 0.18s ease, transform 0.18s var(--ease-spring-soft);
  -webkit-tap-highlight-color: transparent;
}
.prof-v2-edit:active { transform: scale(0.97); background: #2A2A2D; }
.prof-v2-edit svg { color: #FFFFFF; }

/* v298 — Floating cog on profile. Sits top-right above the hero, clears
   the iOS safe-area cleanly. The page now has no heading row above the
   big name below the avatar (Sam: name should appear only once). */
.prof-settings-cog.floating {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 8px);
  right: 12px;
  z-index: 5;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
#section-profile {
  position: relative;
  padding-top: calc(env(safe-area-inset-top, 0px) + 16px);
}

/* ============================================================
   v300 — Profile sheet (Edit Profile modal) + tap-to-upload affordance
   ============================================================ */

/* Tap-to-upload affordance — small plus chip overlapping bottom-right of
   the avatar. Indicates the avatar is interactive. */
.prof-v2-avatar-wrap {
  cursor: pointer;
  display: inline-block;
  position: relative;
}
.prof-v2-avatar-edit {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--gold);
  color: #141414;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 2.5px solid var(--cream);
  box-shadow: 0 1px 4px rgba(0,0,0,0.5);
  z-index: 2;
}

/* v471 — own-profile streak pill now shows as the rhomboid in the open-ring gap
   (Ladder look), same as the carousel + member card. Was hidden pre-redesign. */

/* Profile sheet — full-height modal that slides up from the bottom.
   Hosts the Edit Profile editors (Identity, Body stats, Training,
   Calorie calc, Macros, Weight chart, Sign out, GDPR export). */
.profile-sheet {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.profile-sheet[hidden] { display: none; }
.profile-sheet-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  cursor: pointer;
  animation: sheetFadeIn 0.18s ease forwards;
}
.profile-sheet-card {
  position: relative;
  z-index: 1;
  background: var(--cream);
  border-radius: 20px 20px 0 0;
  /* v303 — Settings home pane sizes to content (no more 96vh of empty
     space). Sub-panes (Profile, Nutrition, Support) snap back to the old
     full-height feel via the :has() rule below. */
  max-height: 88vh;
  height: auto;
}
/* v303 — when a sub-pane is active, expand the sheet to the original tall
   Ladder layout so the editor has room to breathe. */
.profile-sheet-card:has(.profile-sheet-head[data-on-pane]:not([data-on-pane="home"])) {
  height: 96vh;
  max-height: 96vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 -16px 40px rgba(0,0,0,0.45);
  animation: sheetSlideUp 0.42s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.profile-sheet-grabber {
  /* v303 — Lift the grabber above the sticky head so it's visible on every
     pane (including Profile + Nutrition) and reads as the iOS dismiss
     affordance. Brighter rgba so it actually pops against the dark cream. */
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 48px;
  height: 5px;
  background: rgba(255,255,255,0.34);
  border-radius: 999px;
  margin: 0;
  z-index: 5;
  pointer-events: none;
}
.profile-sheet-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  background: rgba(255,255,255,0.06);
  border: 0;
  border-radius: 50%;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 2;
}
.profile-sheet-head {
  /* v344 — more clearance below the iOS grabber pill (top:8px) so the cog +
     "Settings" title don't crowd it. */
  padding: 38px 16px 12px;
}
/* v314 — Old Bebas Neue rule killed. The new .profile-sheet-title rule
   (further down) is the sole authority for the sheet title now. */
.profile-sheet-head h1 {
  margin: 0;
}
.profile-sheet-body {
  flex: 1 1 auto;
  overflow-y: auto;
  /* v353 — vertical ONLY. The absolute tier banner (DEVELOPMENT etc.)
     overflows right, which silently made the body a horizontal scroller —
     Sam could drag the whole card contents around the screen. Safe with
     overflow-y already auto (see swipe-row clipping guard). */
  overflow-x: hidden;
  touch-action: pan-y;
  overscroll-behavior-x: none;
  padding: 0 16px 24px;
  -webkit-overflow-scrolling: touch;
}
@keyframes sheetSlideUp {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
@keyframes sheetFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ===== v306 — DARK THEME FIX. The app is dark (--cream = #0E0E10). My
   earlier rules used dark RGB on dark = invisible. Everything now uses
   light text on dark surfaces. Also dropping the uppercase Bebas title
   per Sam — sentence case, system sans. */
.profile-sheet-head {
  display: flex;
  align-items: center;
  gap: 10px;
  /* v303 — extra top padding so the centered cog/title clears the drag
     grabber pill that sits above it inside the sheet card. */
  padding: 30px 16px 14px;
  background: var(--cream);
  position: sticky;
  top: 0;
  z-index: 3;
  border-bottom: 1px solid var(--line);
}
.profile-sheet-back {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(245, 240, 226, 0.08);
  border: 0;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1), background 0.18s ease;
}
.profile-sheet-back:active { transform: scale(0.92); background: rgba(245, 240, 226, 0.16); }
.profile-sheet-back[hidden] { display: none; }
/* v305 — Yellow tick save button (Ladder pattern, top-right of sub-pane) */
.profile-sheet-save {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--gold);
  color: #111;
  border: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  margin-left: auto;
  box-shadow: 0 2px 10px rgba(245, 194, 0, 0.35);
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.18s ease;
}
.profile-sheet-save:active { transform: scale(0.9); box-shadow: 0 1px 4px rgba(245, 194, 0, 0.5); }
.profile-sheet-save[hidden] { display: none; }
.profile-sheet-save.is-saving {
  opacity: 0.6;
  pointer-events: none;
}
/* v314 — Title perfectly centered in the sheet head. Use absolute positioning
   so the title doesn't drift left when only the right-hand tick is visible. */
.profile-sheet-title {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-family: var(--sans) !important;
  font-weight: 700 !important;
  font-size: 17px !important;
  letter-spacing: 0.005em !important;
  text-transform: none !important;
  color: var(--ink) !important;
  margin: 0;
  line-height: 1.2;
  text-align: center;
  pointer-events: none;       /* title should never block sheet drag */
  white-space: nowrap;
}
.profile-sheet-head {
  position: relative;          /* anchor for absolute title */
}
.profile-sheet-head[data-on-pane="home"] .profile-sheet-title {
  /* home pane shows the cog beside "Settings" — keep it centered too */
}
.profile-sheet-cog { opacity: 0.9; }
.profile-sheet-head[data-on-pane="home"] .profile-sheet-cog { display: inline-block; }
.profile-sheet-head:not([data-on-pane="home"]) .profile-sheet-cog { display: none; }

/* Settings row list (matches Ladder layout in IMG_7949). v306 — light on dark. */
.settings-list {
  padding: 4px 0 24px;
}
.settings-group {
  background: var(--cream-warm);
  border: 1px solid var(--line);
  border-radius: 14px;
  margin: 14px 0 0;
  overflow: hidden;
}
.settings-group-logout {
  background: rgba(217, 67, 67, 0.10);
  border-color: rgba(217, 67, 67, 0.22);
}
.settings-row {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 14px 14px;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--line);
  width: 100%;
  text-align: left;
  cursor: pointer;
  color: var(--ink);
  text-decoration: none;
  font: 600 15px/1.2 var(--sans);
}
.settings-row:first-child { border-top: 0; }
.settings-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
}
.settings-row-label {
  color: var(--ink);
}
.settings-row-sub {
  grid-column: 2;
  grid-row: 2;
  font: 400 12px/1.3 var(--sans);
  color: var(--ink-soft);
  margin-top: 2px;
}
.settings-row-chev {
  color: var(--ink-soft);
  opacity: 0.6;
  font-size: 22px;
  line-height: 1;
}
.settings-row-logout {
  grid-template-columns: 1fr;
  justify-content: center;
  text-align: center;
  color: #ff6b6b;
  font-weight: 600;
}
.settings-row-static {
  cursor: default;
}

/* ===== v303 — Shimmer for Profile + Health & Nutrition sub-panes =====
   data-loading="1" sits on each pane until member.js loadProfile() resolves.
   Real fields, avatars and stat numbers are masked by a light-on-dark
   shimmer so the pane lands smooth instead of popping in element by element. */
.psheet-pane[data-loading="1"] .admin-field input,
.psheet-pane[data-loading="1"] .admin-field select,
.psheet-pane[data-loading="1"] .admin-field textarea,
.psheet-pane[data-loading="1"] .prof-media-circle,
.psheet-pane[data-loading="1"] .prof-media-square,
.psheet-pane[data-loading="1"] .calc-maintain-num,
.psheet-pane[data-loading="1"] .calc-macro-val,
.psheet-pane[data-loading="1"] .calc-cal,
.psheet-pane[data-loading="1"] .wlog-stat-num {
  background:
    linear-gradient(90deg,
      rgba(245, 240, 226, 0.05) 0%,
      rgba(245, 240, 226, 0.14) 50%,
      rgba(245, 240, 226, 0.05) 100%);
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: crestShimmer 1.4s linear infinite;
  color: transparent !important;
  border-color: transparent !important;
  text-shadow: none !important;
}
.psheet-pane[data-loading="1"] .prof-media-bg-ghost,
.psheet-pane[data-loading="1"] .calc-maintain-label,
.psheet-pane[data-loading="1"] .wlog-stat-label {
  visibility: hidden;
}
@media (prefers-reduced-motion: reduce) {
  .psheet-pane[data-loading="1"] .admin-field input,
  .psheet-pane[data-loading="1"] .admin-field select,
  .psheet-pane[data-loading="1"] .admin-field textarea,
  .psheet-pane[data-loading="1"] .prof-media-circle,
  .psheet-pane[data-loading="1"] .prof-media-square,
  .psheet-pane[data-loading="1"] .calc-maintain-num,
  .psheet-pane[data-loading="1"] .calc-macro-val,
  .psheet-pane[data-loading="1"] .calc-cal,
  .psheet-pane[data-loading="1"] .wlog-stat-num {
    animation: none;
  }
}
.settings-data-export {
  text-align: center;
  font: 400 12px/1.3 var(--sans);
  color: var(--ink-soft);
  margin: 18px 0 6px;
}
.settings-data-export a { color: var(--ink-soft); text-decoration: underline; }
.settings-version {
  text-align: center;
  font: 500 11px/1 var(--sans);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(245, 240, 226, 0.32);
  margin: 8px 0 0;
}
.psheet-pane {
  padding-top: 18px;
}
.psheet-pane[hidden] { display: none; }

/* v306 — Flat Ladder-style sections on a DARK theme. All text now uses the
   light ink palette so it's actually readable. Sentence-case labels (no
   uppercase) per Sam — the global .admin-field > span uppercase is overridden
   inside the sheet. */
.psheet-section {
  margin: 0 0 26px;
  padding: 0;
  background: transparent;
  border: 0;
}
.psheet-section-title {
  font: 600 14px/1 var(--sans);
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--ink-soft);
  margin: 10px 4px 8px;
}
.psheet-section .admin-field {
  display: grid;
  grid-template-columns: 110px 1fr;
  align-items: center;
  gap: 14px;
  margin: 0;
  padding: 14px 4px;
  border-top: 1px solid var(--line);
}
.psheet-section .admin-field:first-of-type { border-top: 0; }
.psheet-section .admin-field > span {
  /* override the global uppercase + tracking on .admin-field > span */
  font: 600 14px/1.2 var(--sans);
  color: var(--ink);
  letter-spacing: 0.005em;
  text-transform: none;
}
.psheet-section .admin-field > input,
.psheet-section .admin-field > select,
.psheet-section .admin-field > textarea {
  background: transparent;
  border: 0;
  outline: none;
  padding: 4px 0;
  font: 500 15px/1.3 var(--sans);
  color: var(--ink);
  width: 100%;
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}
.psheet-section .admin-field > input::placeholder,
.psheet-section .admin-field > textarea::placeholder {
  color: rgba(245, 240, 226, 0.32);
}
.psheet-section .admin-field > select {
  background: transparent;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' stroke='%23C8C2B5' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 2px center;
  padding-right: 18px;
}
.psheet-section .admin-field > textarea {
  resize: vertical;
  min-height: 40px;
}

/* Support pane: stacked form fields (label above input), still dark-friendly. */
.psheet-pane[data-psheet-pane="support"] .psheet-section .admin-field {
  display: block;
  border-top: 0;
  padding: 8px 0;
}
.psheet-pane[data-psheet-pane="support"] .psheet-section .admin-field > span {
  display: block;
  margin-bottom: 6px;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--ink-soft);
}
.psheet-pane[data-psheet-pane="support"] .psheet-section .admin-field > input,
.psheet-pane[data-psheet-pane="support"] .psheet-section .admin-field > textarea {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px;
  background: var(--cream-warm);
  color: var(--ink);
}

/* v305 — Hide the inline Save Profile button on the Profile pane; the yellow
   tick in the sheet header now handles saving. Keep the toast for messages. */
.psheet-pane[data-psheet-pane="profile"] .admin-actions,
.psheet-pane[data-psheet-pane="nutrition"] .admin-actions { display: none; }

/* v307 — Kill the "big pill" card outlines on the Profile edit pane. Ladder
   ref shows only hairline dividers between fields, no card outlines at all.
   The programme + AI link cards aren't relevant on the edit screen. */
.psheet-pane[data-psheet-pane="profile"] #profile-active-tier,
.psheet-pane[data-psheet-pane="profile"] #profile-ai-link { display: none !important; }

/* v305/v306 — Larger "Change Photo" circle, Ladder-style (kept for legacy
   placements outside the new Profile pane). */
.profile-sheet .prof-hero-avatar {
  position: relative;
  display: block;
  width: 120px;
  height: 120px;
  margin: 10px auto 10px;
  border-radius: 50%;
  background: var(--cream-warm);
  cursor: pointer;
  overflow: visible;
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.profile-sheet .prof-hero-avatar:active { transform: scale(0.96); }

/* v308 — Two-tile media row matching Ladder Profile & Personal Details. */
.prof-media-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  padding: 18px 6px 22px;
}
.prof-media-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.prof-media-tile:active { transform: scale(0.97); }
.prof-media-circle,
.prof-media-square {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--cream-warm);
  color: var(--ink-soft);
  font: 700 36px/1 var(--sans);
  letter-spacing: 0.02em;
  overflow: hidden;
  position: relative;
}
.prof-media-circle {
  width: 132px;
  height: 132px;
  border-radius: 50%;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.prof-media-square {
  width: 132px;
  height: 132px;
  border-radius: 14px;
}
.prof-media-bg-ghost {
  font: 800 22px/1 var(--sans);
  letter-spacing: 0.04em;
  color: rgba(255, 105, 180, 0.55);
  text-align: left;
  padding-left: 6px;
  pointer-events: none;
}
.prof-media-label {
  font: 600 14px/1.2 var(--sans);
  color: var(--ink);
}

/* v309 — Sheet-level toast that floats above the panes. Used by the yellow
   tick save flow so feedback shows on any pane. */
.profile-sheet-toast {
  position: absolute;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  padding: 12px 18px;
  background: var(--ink);
  color: #111;
  border-radius: 999px;
  font: 600 14px/1 var(--sans);
  box-shadow: 0 8px 24px rgba(0,0,0,0.45);
  z-index: 6;
  max-width: calc(100% - 32px);
  text-align: center;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.profile-sheet-toast[hidden] { display: none; }
.profile-sheet-toast.is-error {
  background: #d94343;
  color: #fff;
}
.profile-sheet-toast.is-ok {
  background: var(--gold);
  color: #111;
}

/* v308 — Tighter flat field rows (Ladder style, hairlines only) */
.psheet-section-fields {
  margin-top: 4px;
}
.psheet-section-fields .admin-field {
  grid-template-columns: 120px 1fr;
  padding: 18px 4px;
}
.psheet-section-fields .admin-field-bio {
  grid-template-columns: 120px 1fr;
  align-items: start;
}
.psheet-section-fields .admin-field-bio > span { padding-top: 2px; }
.psheet-section-fields .admin-field-bio > textarea {
  min-height: 96px;
  line-height: 1.55;
  font-size: 15px;
}
.psheet-section-fields .admin-field-bio > textarea::placeholder {
  white-space: pre-line;
  color: rgba(245, 240, 226, 0.32);
}
/* Email read-only — looks like a normal field but no tap-edit hint */
.psheet-section-fields #prof-email-display {
  font-weight: 600;
  color: var(--ink);
  caret-color: transparent;
}

/* Birthday rendered as a pill chip on the right (Ladder pattern) */
.psheet-section-fields .admin-field-chip {
  grid-template-columns: 120px 1fr;
  align-items: center;
}
.psheet-section-fields .admin-field-chip > input[type="date"] {
  justify-self: end;
  background: var(--cream-warm);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 8px 14px;
  font: 600 14px/1 var(--sans);
  color: var(--ink);
  text-align: center;
  max-width: 160px;
  width: auto;
  -webkit-appearance: none;
  appearance: none;
}
.profile-sheet .prof-hero-avatar-img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--cream-warm) center/cover no-repeat;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  font: 700 32px/1 var(--sans);
}
.profile-sheet .prof-hero-avatar-cam {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--gold);
  color: #111;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0,0,0,0.45);
  border: 2px solid var(--cream);
}
.profile-sheet .prof-hero-hint {
  text-align: center;
  font: 500 13px/1.3 var(--sans);
  color: var(--ink-soft);
  margin: 0 0 18px;
}

/* ============================================================
   v336 — Member profile card. Opens on a single tap of a Feed
   strip avatar. Reuses the profile-sheet chrome + the global
   prof-v2 layout vocabulary (hero, gauges, calendar).
   ============================================================ */
.member-sheet .profile-sheet-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* v337 — fixed height. auto made the card open small then grow when the
     stats/calendar landed (half-load-then-jump Sam reported on Miles). */
  height: 88vh;
  max-height: 88vh;
  box-shadow: 0 -16px 40px rgba(0, 0, 0, 0.45);
  animation: sheetSlideUp 0.42s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.member-sheet .profile-sheet-body {
  padding-top: 6px;
  padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
}
/* Clear the grabber pill at the top of the card */
.member-sheet .prof-v2-hero { padding-top: 30px; }
/* Initial fallback when the member has no photo (mirrors the own-profile
   hero's inline fallback styling) */
.member-sheet .prof-v2-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 44px;
  color: var(--ink);
}
/* v346 — hypes-sent ticker under the tier line */
.member-sheet-hypes-sent {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 10px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  position: relative;
  z-index: 1;
}
.member-sheet-hypes-sent svg { color: var(--gold); }

/* v347 — hype button removed: double-tap the member's image instead. */

/* v348 — CIRCULAR shimmer while the stats fetch is in flight. The v347
   version shimmered the number as a small rectangular pill floating on a
   circular gauge — Sam: "dreadful". Now the whole 72px ring area shimmers
   as a circle; ring + number hide until the data lands. Cached reopens
   paint instantly with no shimmer at all. */
.member-sheet.is-loading .prof-v2-stat .prof-v2-ring,
.member-sheet.is-loading .prof-v2-stat .prof-v2-stat-num {
  visibility: hidden;
}
.member-sheet.is-loading .prof-v2-stat::before {
  content: "";
  position: absolute;
  top: 6px; /* matches .prof-v2-stat padding-top */
  left: 50%;
  transform: translateX(-50%);
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.05) 0%,
    rgba(255, 255, 255, 0.13) 50%,
    rgba(255, 255, 255, 0.05) 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: crestShimmer 1.4s linear infinite;
}
/* Month nav arrows: no rules needed — the sheet's buttons sit inside
   .prof-v2-month-nav, whose existing `button` rule styles them. */

/* v337 — Miles' Programme tier inside the card. The bare v198 rule
   (.has-tier-miles_programme { box-shadow: ... }) was written for the small
   strip circles and leaks a blue BOX onto anything carrying the class —
   here, the hero div and the tier label. Kill the leak and put the ring
   where it belongs: the avatar border + tier text colour, mirroring the
   foundations/development/elite pattern. */
.member-sheet .prof-v2-hero.has-tier-miles_programme,
.member-sheet .prof-v2-tier.has-tier-miles_programme { box-shadow: none; }
.prof-v2-hero.has-tier-miles_programme .prof-v2-avatar { border-color: var(--miles-blue); }
.prof-v2-tier.has-tier-miles_programme { color: var(--miles-blue); }
.member-sheet .prof-v2-hero.has-tier-booty_programme,
.member-sheet .prof-v2-tier.has-tier-booty_programme { box-shadow: none; }
.prof-v2-hero.has-tier-booty_programme .prof-v2-avatar { border-color: var(--booty-pink); }
.prof-v2-tier.has-tier-booty_programme { color: var(--booty-pink); }

/* v337 — make the sheet feel STUCK. Scroll stays inside the card body (no
   chaining to the feed behind when it hits top/bottom), the backdrop never
   pans, and the page behind can't scroll while a sheet is open. */
.member-sheet .profile-sheet-body { overscroll-behavior: contain; }
.member-sheet .profile-sheet-backdrop {
  touch-action: none;
  /* v346 — same black top-cap as .profile-pull-veil (status-bar seam) */
  background: linear-gradient(to bottom, #000 0, rgba(0, 0, 0, 0.45) calc(env(safe-area-inset-top, 0px) + 48px));
}
body.sheet-open { overflow: hidden; }


/* ============================================================
   v357 — Gold confetti celebration (checklist 100%, reusable for
   ring closes + milestones). Particles explode upward from the
   origin (35% keyframe = peak), then fall off-screen with spin.
   ============================================================ */
.crest-confetti {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
  transform: translate(-50%, -50%);
  animation: crestConfettiFly var(--dur, 1600ms) cubic-bezier(0.22, 0.61, 0.36, 1) var(--delay, 0ms) forwards;
}
@keyframes crestConfettiFly {
  0% {
    transform: translate(-50%, -50%) rotate(0deg);
    opacity: 1;
  }
  35% {
    transform: translate(calc(-50% + var(--px)), calc(-50% + var(--py))) rotate(var(--r1));
    opacity: 1;
  }
  80% { opacity: 1; }
  100% {
    transform: translate(calc(-50% + var(--fx)), calc(-50% + var(--fy))) rotate(var(--r2));
    opacity: 0;
  }
}
/* Score ring pulse when the checklist completes */
.score-celebrate {
  animation: scorePop 0.7s cubic-bezier(0.16, 1.6, 0.3, 1);
  transform-origin: center;
}
@keyframes scorePop {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.14); }
  60%  { transform: scale(0.97); }
  100% { transform: scale(1); }
}


/* v358 — Lottie overlay host: centered on its origin element, above all */
.crest-lottie-overlay {
  position: fixed;
  z-index: 9998;
  pointer-events: none;
  transform: translate(-50%, -50%);
}

/* v383 — full-screen confetti celebration (checklist 100%). Covers the whole
   viewport, sits above content, never intercepts taps. */
.crest-confetti-overlay {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: 9999;
  pointer-events: none;
}

/* v403 — centre-screen streak celebration (MyFitnessPal-style). */
.crest-streak-cel {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  /* v496 — the bolt animation is tall and sits ABOVE the number, so plain
     centring drops the number into the lower third. This padding shifts the
     whole cluster up by ~half the bolt height so the NUMBER lands dead-centre,
     bolt above it, "DAY STREAK" + message below. */
  padding-bottom: calc(min(84vw, 440px) - 108px);
  box-sizing: border-box;
  background: rgba(8, 8, 10, 0.74);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 0.13s ease; /* v405 — snappier */
}
.crest-streak-cel.show { opacity: 1; }
.crest-streak-cel-card {
  text-align: center;
  padding: 24px 28px;
  transform: scale(0.7);
  transition: transform 0.22s cubic-bezier(0.2, 1.3, 0.4, 1); /* v405 — fast pop with overshoot */
}
.crest-streak-cel.show .crest-streak-cel-card { transform: scale(1); }
.crest-streak-cel-anim {
  width: min(84vw, 440px);
  height: min(84vw, 440px);
  margin: 0 auto -16px;
  filter: drop-shadow(0 0 26px rgba(40, 172, 255, 0.9));
  /* v500 — feather the square edge of the animation into a soft circle so you
     can't see the bounding box. 13px feather at the rim; the centre stays fully
     opaque so the bolt itself is untouched. */
  -webkit-mask-image: radial-gradient(circle closest-side, #000 calc(100% - 13px), rgba(0, 0, 0, 0) 100%);
          mask-image: radial-gradient(circle closest-side, #000 calc(100% - 13px), rgba(0, 0, 0, 0) 100%);
}
.crest-streak-cel-num {
  font-family: var(--display);
  font-size: 92px;
  line-height: 0.9;
  color: var(--lightning-blue);
  text-shadow: 0 0 26px rgba(40, 172, 255, 0.55);
}
/* v499 — the streak number is resolved BEFORE the card is drawn, so the bolt
   and number paint together as one finished asset. Reserve the number's height
   so the card is full-size from the first frame — nothing ever grows or shoves
   the bolt out of place. */
.crest-streak-cel-num {
  min-height: 0.9em;
}
.crest-streak-cel-title {
  font-family: var(--display);
  font-size: 26px;
  letter-spacing: 3px;
  color: #fff;
  margin-top: 6px;
}
.crest-streak-cel-sub {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.82);
  margin: 14px auto 0;
  max-width: 280px;
}


/* ============================================================
   v359 — Checklist long-press drag-to-reorder.
   ============================================================ */
/* The lifted copy that follows the finger */
.ck-drag-clone {
  position: fixed;
  z-index: 9999;
  margin: 0;
  list-style: none;
  pointer-events: none;
  border-radius: 14px;
  background: var(--cream-warm);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
  transform: scale(1.03);
  opacity: 0.97;
}
.ck-drag-clone .swipe-row { transform: none !important; }
.ck-drag-clone .swipe-delete { display: none !important; }
/* The real row left behind in the list while dragging */
.ck-drag-ghost { opacity: 0.32; }
.ck-drag-ghost .swipe-row { transform: none !important; }
/* Smooth reflow of the other rows as the dragged item moves past them */
#checklist.reordering li.swipeable { transition: transform 0.18s ease; }
#checklist.reordering { cursor: grabbing; }

/* v361 — No text selection / iOS callout while interacting with the
   checklist (long-press was highlighting the row text). The add-item
   input stays editable + selectable. */
#checklist,
#checklist li,
#checklist .swipe-row,
#checklist label,
.ck-drag-clone {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
#checklist .ck-add-row input,
#checklist input[type="text"] {
  -webkit-user-select: text;
  user-select: text;
}

/* ============================================================
   v411 — Workout-tab collapsible folds (Programme / Miles / Charlie)
   Workout is the master tab. Three folds stack; each toggles its body
   with a grid-rows collapse (1fr↔0fr) that never clips dynamic comment
   threads. Programme (sequence-clock) on top, then the live drops.
   ============================================================ */
.wo-accordion { display: flex; flex-direction: column; gap: 12px; margin: 4px 0 14px; }

.wo-fold {
  background: var(--cream-warm);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
  overflow: hidden;
}

.wo-fold-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 15px 16px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ink);
  text-align: left;
  font: inherit;
}
.wo-fold-head:active { background: rgba(245, 240, 226, 0.03); }

.wo-fold-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  border-radius: 9px;
  background: rgba(245, 194, 0, 0.10);
  color: var(--gold);
  flex: 0 0 auto;
}
.wo-fold-icon-live { background: rgba(245, 240, 226, 0.06); color: var(--ink-soft); }

.wo-fold-title {
  flex: 1 1 auto;
  font-family: var(--display, var(--serif));
  font-size: 18px;
  letter-spacing: 0.3px;
  color: var(--ink);
  min-width: 0;
}
.wo-fold-sub {
  color: var(--ink-soft);
  font-size: 13px;
  font-family: -apple-system, system-ui, sans-serif;
  letter-spacing: 0;
}

.wo-fold-status {
  font-size: 12px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
  white-space: nowrap;
}
.wo-fold-status.is-active { color: var(--gold-deep); }
.wo-fold-head.is-done .wo-fold-status {
  color: #0E0E10;
  background: var(--gold);
  padding: 2px 9px;
  border-radius: 999px;
  font-weight: 700;
}
.wo-fold-head.is-done .wo-fold-icon-live { background: var(--gold); color: #0E0E10; }

.wo-fold-chev {
  flex: 0 0 auto;
  color: var(--ink-soft);
  transition: transform 0.28s ease;
}
.wo-fold:not(.open) .wo-fold-chev { transform: rotate(-90deg); }

/* grid-rows collapse — inner wrapper clips, padding lives on it so it
   collapses with the row. */
.wo-fold-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
}
.wo-fold.open .wo-fold-body { grid-template-rows: 1fr; }
.wo-fold-inner { overflow: hidden; min-height: 0; padding: 0 14px 14px; }

/* Author folds: strip the wrapped card's outer chrome + the redundant author
   label (the fold head already names the coach). */
.wo-fold-author .wo-fold-inner .workout-author-card {
  border: none;
  box-shadow: none;
  background: none;
  padding: 4px 0 2px;
  margin: 0;
}
.wo-fold-author .workout-label,
.wo-fold-author .workout-block-author { display: none; }

/* Programme fold keeps its inner .card chrome — trim gutters to avoid doubling. */
#wo-fold-programme .wo-fold-inner { padding: 2px 12px 12px; }

/* Empty-state slim card → Vault */
.wo-prog-empty {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  margin: 2px 0;
  background: rgba(245, 240, 226, 0.03);
  border: 1px dashed var(--line);
  border-radius: 13px;
  cursor: pointer;
  color: var(--ink);
  text-align: left;
}
.wo-prog-empty:active { background: rgba(245, 240, 226, 0.06); }
.wo-prog-empty-icon { display: inline-flex; color: var(--gold); flex: 0 0 auto; }
.wo-prog-empty-body { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wo-prog-empty-title { font-size: 15px; font-weight: 600; color: var(--ink); }
.wo-prog-empty-sub { font-size: 12.5px; color: var(--ink-soft); }
.wo-prog-empty-chev { color: var(--ink-soft); flex: 0 0 auto; }

/* v414 — global mini toast (e.g. "already hyped today") + repeat-hype pulse.
   Bottom-centre, above the nav, fades + rises. Non-interactive. */
.crest-mini-toast {
  position: fixed;
  left: 50%;
  bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 8px);
  z-index: 6000;
  max-width: 80vw;
  padding: 10px 16px;
  border-radius: 999px;
  background: rgba(27, 26, 24, 0.96);
  border: 1px solid var(--line);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  color: var(--ink);
  font-size: 13.5px;
  font-family: var(--sans, -apple-system, system-ui, sans-serif);
  white-space: nowrap;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.crest-mini-toast.show { opacity: 1; transform: translate(-50%, 0); }

/* repeat-hype acknowledgement pulse on the tapped strip avatar */
@keyframes crest-hype-already-pulse {
  0%   { transform: scale(1); }
  35%  { transform: scale(0.92); }
  70%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}
.hype-already { animation: crest-hype-already-pulse 0.55s ease; }

/* v416 — rolling-milestone gauges: tiny "next N" goal sub-label under each
   ring, plus a coloured glow when a ring has passed its top milestone (MAX). */
.prof-v2-stat-goal {
  font-family: var(--sans);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.55;
  margin-top: 1px;
  line-height: 1;
}
.prof-v2-stat.is-maxed .prof-v2-stat-goal { color: var(--gold); opacity: 1; }
.prof-v2-stat.is-maxed .ring-fg { filter: drop-shadow(0 0 3px var(--gold)); }
.prof-v2-stat[data-key="streak"].is-maxed  .ring-fg { filter: drop-shadow(0 0 3px #FF8A3D); }
.prof-v2-stat[data-key="streak"].is-maxed  .prof-v2-stat-goal { color: #FF8A3D; }
.prof-v2-stat[data-key="longest"].is-maxed .ring-fg { filter: drop-shadow(0 0 3px #7DD3FC); }
.prof-v2-stat[data-key="longest"].is-maxed .prof-v2-stat-goal { color: #7DD3FC; }
.prof-v2-stat[data-key="hypes"].is-maxed   .ring-fg { filter: drop-shadow(0 0 3px #FF6B81); }
.prof-v2-stat[data-key="hypes"].is-maxed   .prof-v2-stat-goal { color: #FF6B81; }

/* v432 — checklist-complete celebration card (gold check springs in + confetti). */
.crest-cl-cel {
  position: fixed; inset: 0; z-index: 9997;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; opacity: 0; transition: opacity 0.25s ease;
}
.crest-cl-cel.show { opacity: 1; pointer-events: auto; }
.crest-cl-cel-card {
  background: var(--cream-warm); border: 1px solid var(--line);
  border-radius: 22px; padding: 30px 38px; text-align: center;
  box-shadow: 0 26px 64px rgba(0,0,0,0.55);
  transform: scale(0.82) translateY(10px);
  transition: transform 0.4s cubic-bezier(0.2, 1.3, 0.35, 1);
}
.crest-cl-cel.show .crest-cl-cel-card { transform: scale(1) translateY(0); }
.crest-cl-cel-check { width: 66px; height: 66px; margin: 0 auto 16px; }
.crest-cl-cel-check svg { width: 66px; height: 66px; display: block; }
.crest-cl-cel-check circle { fill: var(--gold); }
.crest-cl-cel-check path {
  fill: none; stroke: #0E0E10; stroke-width: 4.5; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 40; stroke-dashoffset: 40;
}
.crest-cl-cel.show .crest-cl-cel-check path { animation: cl-check-draw 0.5s 0.18s ease forwards; }
@keyframes cl-check-draw { to { stroke-dashoffset: 0; } }
.crest-cl-cel-title {
  font-family: var(--display, var(--serif)); font-size: 32px; line-height: 1;
  letter-spacing: 0.5px; color: var(--ink);
}
.crest-cl-cel-sub { font-size: 14px; color: var(--ink-soft); margin-top: 9px; }

/* v434 — per-tick gold confetti burst from behind the checkbox */
.ck-burst {
  position: fixed; width: 6px; height: 6px; border-radius: 50%;
  background: var(--gold); pointer-events: none; z-index: 9996;
  transform: translate(-50%, -50%);
  animation: ck-burst-fly 0.5s ease-out forwards;
}
@keyframes ck-burst-fly {
  from { opacity: 1; }
  to { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.35); opacity: 0; }
}
/* v439 — bigger, slightly longer particles for the checklist-complete confetti */
.ck-burst.cl-confetti { width: 9px; height: 9px; z-index: 9998; animation-duration: 0.72s; }
/* completed items sink + dim (MS To-Do style). v437.1 — dim ONLY the text, never
   the .swipe-row itself: the row is the opaque panel that hides the Delete
   button, and making it translucent let the red Delete show through behind it. */
.checklist li.ck-done label {
  opacity: 0.5;
  text-decoration: line-through;
  text-decoration-color: rgba(245,240,226,0.45);
}

/* v442 — perimeter progress frame: a gold border that draws around the checklist
   card as items are ticked, starting + closing at the top, glowing when sealed. */
/* v443 — the frame IS the card's edge now; drop the card's own border so there
   aren't two parallel lines (the "3D duplicate" look). */
.ck-card { position: relative; border-color: transparent; }
.ck-frame {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; overflow: visible; z-index: 1;
}
.ck-frame-track { stroke: rgba(245,240,226,0.10); stroke-width: 4; vector-effect: non-scaling-stroke; }
.ck-frame-fill {
  stroke: var(--gold); stroke-width: 4; stroke-linecap: round;
  stroke-dasharray: 100; stroke-dashoffset: 100;
  vector-effect: non-scaling-stroke;
  transition: stroke-dashoffset 0.55s cubic-bezier(0.4, 0, 0.2, 1);
}
.ck-card.ck-complete .ck-frame-fill {
  filter: drop-shadow(0 0 4px rgba(245,194,0,0.75)) drop-shadow(0 0 9px rgba(245,194,0,0.4));
}

/* v453 — Workout-tab empty state: "Choose your programme" → Vault */
.prog-empty-cta {
  display: flex; flex-direction: column; gap: 4px; width: 100%;
  text-align: left; cursor: pointer; border: 0;
  background: var(--gold); color: #0E0E10;
  border-radius: 16px; padding: 20px 22px; margin-bottom: 16px;
  box-shadow: 0 10px 28px rgba(245,194,0,0.22);
  transition: transform 0.05s ease;
}
.prog-empty-cta:active { transform: scale(0.99); }
.prog-empty-cta-title { font-family: var(--display, var(--serif)); font-size: 22px; letter-spacing: 0.3px; }
.prog-empty-cta-sub { font-size: 13px; font-weight: 600; opacity: 0.72; }

/* v454 — Live workout: composer toggle + Mark-complete button on feed posts */
.composer-workout-toggle {
  display: inline-flex; align-items: center; gap: 5px;
  background: transparent; border: 1px solid var(--line); color: var(--ink-soft);
  border-radius: 999px; padding: 6px 11px; font-family: var(--sans);
  font-size: 12px; font-weight: 600; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.composer-workout-toggle.active { background: var(--gold); color: #0E0E10; border-color: var(--gold); }
.post-workout { display: flex; align-items: center; gap: 10px; margin: 10px 0 2px; }
.post-workout-badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--gold);
}
.post-workout-complete {
  margin-left: auto; background: var(--gold); color: #0E0E10; border: 0;
  border-radius: 999px; padding: 9px 18px; font-family: var(--sans);
  font-size: 13px; font-weight: 700; cursor: pointer; transition: transform .05s ease;
}
.post-workout-complete:active { transform: scale(0.97); }
.post-workout-complete.done { background: transparent; color: var(--ink-soft); border: 1px solid var(--line); cursor: default; }

/* v573 — kill the old "latest workout" card (own-profile one removed from markup). */
#member-sheet-last-workout { display: none !important; }

/* Progression entry card (profile, under the calendar). */
.prof-progress-card {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; margin-top: 14px; padding: 16px 18px;
  background: linear-gradient(180deg, #1C1C20 0%, #101012 100%);
  border: 1px solid rgba(255,255,255,0.08); border-radius: 16px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08);
  color: var(--ink, #F5F0E2); cursor: pointer; text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.prof-progress-card:active { transform: scale(0.985); }
.prof-progress-card-text { display: flex; flex-direction: column; gap: 3px; }
.prof-progress-card-title { font-weight: 700; font-size: 15px; color: #F4F0E4; }
.prof-progress-card-sub { font-size: 12px; color: #9A958A; }
.prof-progress-card svg { color: #6b6b6b; flex-shrink: 0; }

/* v575 — Progression sheet: full-height, grabber, centred title, roomy. */
.prof-progress-sheet-card {
  display: flex; flex-direction: column; overflow: hidden;
  height: 92vh; max-height: 92vh; padding: 10px 18px 20px;
  box-shadow: 0 -16px 40px rgba(0,0,0,0.45);
}
.prof-progress-head { display: flex; align-items: center; justify-content: center; padding: 12px 4px 4px; flex-shrink: 0; }
.prof-progress-head h3 { font-family: var(--display, inherit); font-size: 30px; letter-spacing: 0.5px; color: #F5F0E2; margin: 0; text-align: center; }
.prof-progress-toolbar { display: flex; align-items: center; gap: 12px; padding: 18px 0 0; flex-shrink: 0; }
.prof-progress-tabs { display: flex; gap: 8px; overflow-x: auto; flex: 1; min-width: 0; }
.prof-progress-export {
  flex-shrink: 0; background: transparent; border: 1px solid var(--tier, #4A90D9); color: var(--tier, #4A90D9);
  border-radius: 999px; padding: 8px 16px; font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; cursor: pointer;
}
.prog-tab {
  flex-shrink: 0; padding: 9px 17px; border-radius: 999px; border: 1px solid rgba(255,255,255,0.14);
  background: transparent; color: #CBC5B8; font-size: 13px; font-weight: 700; cursor: pointer;
}
.prog-tab.on { background: var(--tier, #4A90D9); color: #0E0E10; border-color: var(--tier, #4A90D9); }
/* v576 — vertical card stack (no spreadsheet, no sideways scroll). */
.prof-progress-body { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; margin-top: 22px; }
.prof-progress-empty { margin: 60px auto; padding: 0 20px; text-align: center; color: #9A958A; font-size: 13px; line-height: 1.7; }
.prog-cards { display: flex; flex-direction: column; gap: 14px; padding-bottom: 24px; }
.prog-ex-card {
  background: linear-gradient(180deg, #1A1A1D 0%, #0F0F11 100%);
  border: 1px solid rgba(255,255,255,0.08); border-radius: 16px; padding: 16px 18px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06);
}
.prog-ex-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.prog-ex-card-name { font-weight: 700; font-size: 16px; color: #F4F0E4; }
.prog-ex-card-trend { font-size: 12px; font-weight: 700; color: var(--tier, #4A90D9); white-space: nowrap; flex-shrink: 0; }
.prog-ex-chart { margin: 8px 0 16px; }
.prog-ex-chart-svg { width: 100%; height: auto; display: block; }
.prog-axis { fill: #8E887B; font-size: 9px; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif; }
.prog-ex-sessions { display: flex; flex-direction: column; }
.prog-ex-session { display: flex; justify-content: space-between; gap: 14px; padding: 10px 0; border-top: 1px solid rgba(255,255,255,0.06); }
.prog-ex-session:first-child { border-top: 0; }
.prog-ex-session-date { color: #9A958A; font-size: 12px; flex-shrink: 0; }
.prog-ex-session-sets { color: #E5E0D4; font-size: 13px; text-align: right; }
.prog-ex-blank { color: #7a7468; font-size: 12.5px; padding: 2px 0; }
