/* ============================================================================
   PROJECT X design language v2 — "the scoreboard"  (foundation: tokens + chrome)
   ----------------------------------------------------------------------------
   PRIMARY BUTTON — standardized treatment (use this one, everywhere):
     The single primary CTA per view = `.btn` (gold, var(--gold)) WITH `.px-display`
     added:  <button class="btn px-display">Unlock</button>
     That renders the gold button in the athletic display stack — italic, uppercase,
     ~15px, faux-condensed — for the Reps "scoreboard" feel. Secondary actions stay
     `.btn-outline`. A plain `.btn` (no .px-display) is still valid for non-hero gold
     actions and keeps its original 13px/800 uppercase look, so nothing breaks.
     Rule of thumb for the page agents: ONE `.btn.px-display` gold primary per view;
     demote every other action to `.btn-outline`.
   TOKENS: --radius=10px (controls) · --radius-card=14px (cards) · warmer canvas #FAF9F6.
   Additive only — every existing class keeps working; dark overrides re-verified.
   ============================================================================ */
* { margin: 0; padding: 0; box-sizing: border-box; }
/* kill iOS double-tap zoom app-wide (taps stay instant; scroll + pinch on
   canvas/media unaffected). Rim-drag handles keep their own touch-action:none. */
html, body { touch-action: manipulation; }
a, button, input, select, textarea, label, [role="button"] { touch-action: manipulation; }
/* ---------- iOS edge-swipe "goes back" guard ----------
   In the Capacitor WKWebView every section switch is a real location.href page
   load, so the webview keeps a back/forward history stack. A horizontal pan that
   over-scrolls a strip (the .tabs row, a .px-shelf, a segmented -seg control) or
   the page body then chains outward and can trip iOS's edge-swipe navigation,
   yanking the athlete back a page mid-scroll. overscroll-behavior stops the
   chaining WITHOUT disabling any scrolling: vertical scroll and the horizontal
   tab/shelf strips still scroll normally, they just no longer bubble the pan.
   `none` on the root also kills pull-to-refresh / rubber-band at the viewport. */
html, body { overscroll-behavior: none; }
/* Any horizontal scroller (the shared .tabs-inner, plus the page-scoped shelves
   and segmented strips that set overflow-x inline) contains its own overscroll so
   a swipe that hits the end doesn't chain out to a back gesture. */
.tabs-inner, .px-shelf-scroll, [style*="overflow-x"] { overscroll-behavior-x: contain; }
:root {
  --canvas: #FAF9F6;
  --card: #FFFFFF;
  --border: #E4E4E4;
  --text: #202124;
  --muted: #808080;
  --gold: #F8D24B;
  --gold-dark: #E5BE33;
  --gold-ink: #A8842A; /* readable gold for TEXT/icons on light backgrounds (brand antique gold) */
  --star: #B8860B; /* rating stars — darker amber clears contrast on white */
  --blue: #4B7BEC;
  --green: #259A46;
  --radius: 10px;
  --radius-card: 14px;
  --shadow: 0 1px 2px rgba(0,0,0,.07);
  --hover: #F4F2EC;
  --gold-tint: #FDF6DF;
  --track: #EFEDE6;
  --body-text: #444444;
  --px-display-font: 'Arial Narrow', Impact, 'Helvetica Neue', sans-serif;
}
[data-theme="dark"] {
  --canvas: #141119;  /* slight purple cast (was #121212) */
  --card: #1E1A24;    /* slight purple cast (was #1C1C1C) */
  --border: #322D3B;
  --text: #EDEDED;
  --muted: #9A9A9A;
  --shadow: 0 1px 2px rgba(0,0,0,.4);
  --hover: #242424;
  --gold-tint: #2A2412;
  --track: #2E2E2E;
  --body-text: #C9C9C9;
  --gold-ink: #F8D24B; /* on dark backgrounds full-brightness gold reads fine */
  --star: #E5A400; /* on dark, vibrant amber stars read fine */
}
[data-theme="dark"] .badge-green { background: #173420; color: #7ED9A0; }
[data-theme="dark"] .search input { background: #242424; color: var(--text); }
html { background: var(--canvas); }
body { transition: background .2s ease, color .2s ease; }
body {
  background: var(--canvas);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
}
a { color: inherit; text-decoration: none; }

/* ---------- Topbar ---------- */
.topbar { background: var(--card); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 50; }
.topbar-inner { max-width: 1085px; margin: 0 auto; display: flex; align-items: center; gap: 16px; height: 60px; padding: 0 16px; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 17px; white-space: nowrap; }
.logo-mark { background: var(--text); color: var(--gold); font-size: 13px; font-weight: 800; width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; }
.search { flex: 1; }
.search input { width: 100%; max-width: 420px; height: 38px; border: 1px solid var(--border); border-radius: 20px; padding: 0 16px; font-size: 14px; background: var(--canvas); outline: none; }
.search input:focus { border-color: #c9c9c9; }
.topbar-icons { display: flex; align-items: center; gap: 12px; }
.icon-btn { background: none; border: none; font-size: 18px; cursor: pointer; opacity: .75; }
.icon-btn:hover { opacity: 1; }

/* ---------- Tabs ---------- */
.tabs { background: var(--card); border-bottom: 1px solid var(--border); }
.tabs-inner { max-width: 1085px; margin: 0 auto; display: flex; gap: 4px; padding: 0 16px; overflow-x: auto; }
.tab { padding: 12px 14px; font-size: 14px; font-weight: 500; color: var(--muted); border-bottom: 2px solid transparent; white-space: nowrap; position: relative; }
.tab:hover { color: var(--text); }
.tab.active { color: var(--text); font-weight: 700; border-bottom-color: var(--text); }
.tab-train::after { content: ""; width: 6px; height: 6px; background: var(--gold-dark); border-radius: 50%; position: absolute; top: 10px; right: 4px; }

/* ---------- Layout ---------- */
.container { max-width: 1085px; margin: 0 auto; padding: 20px 16px 60px; }
.layout { display: flex; gap: 20px; align-items: flex-start; }
.main-col { flex: 1; min-width: 0; }
.sidebar { width: 300px; flex-shrink: 0; display: flex; flex-direction: column; gap: 16px; }
@media (max-width: 860px) { .layout { flex-direction: column; } .sidebar { width: 100%; } }

/* ---------- Cards ---------- */
.card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow); }
.card-pad { padding: 16px; }

/* ---------- Buttons ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; background: var(--gold); color: var(--text); border: none; border-radius: var(--radius); height: 40px; padding: 0 18px; font-size: 13px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; cursor: pointer; }
.btn:hover { background: var(--gold-dark); }
.btn:disabled { opacity: .5; cursor: default; }
.btn-block { width: 100%; }
.btn-outline { background: transparent; border: 1px solid var(--border); color: var(--text); }
.btn-outline:hover { background: var(--canvas); }
/* Standardized primary CTA: gold .btn + athletic display type (see header comment) */
.btn.px-display { font-size: 15px; letter-spacing: .02em; text-transform: uppercase; }

/* ---------- Avatars + level badge ---------- */
.avatar { width: 40px; height: 40px; border-radius: 50%; color: #fff; font-weight: 700; font-size: 14px; display: flex; align-items: center; justify-content: center; position: relative; flex-shrink: 0; }
.avatar-sm { width: 32px; height: 32px; font-size: 12px; }
.avatar-lg { width: 64px; height: 64px; font-size: 22px; }
.lvl { position: absolute; bottom: -3px; right: -3px; background: var(--blue); color: #fff; font-size: 10px; font-weight: 700; width: 17px; height: 17px; border-radius: 50%; border: 2px solid var(--card); display: flex; align-items: center; justify-content: center; }
.avatar-lg .lvl { width: 22px; height: 22px; font-size: 12px; }

/* ---------- Feed ---------- */
.composer { display: flex; align-items: center; gap: 12px; padding: 14px 16px; margin-bottom: 16px; cursor: text; }
.composer .prompt { color: var(--muted); font-size: 15px; }
.pills { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.pill { background: var(--card); border: 1px solid var(--border); border-radius: 20px; padding: 7px 14px; font-size: 13px; font-weight: 500; color: var(--muted); cursor: pointer; }
.pill.active { background: var(--text); color: #fff; border-color: var(--text); }
.post { margin-bottom: 16px; padding: 16px; }
.post-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.post-meta { font-size: 12px; color: var(--muted); }
.post-author { font-weight: 700; font-size: 14px; }
.post-title { font-size: 16px; font-weight: 700; margin-bottom: 4px; }
.post-body { color: var(--body-text); font-size: 14px; margin-bottom: 12px; }
.post-flex { display: flex; gap: 16px; }
.post-flex > div:first-child { flex: 1; min-width: 0; }
.thumb { width: 120px; height: 80px; border-radius: 8px; flex-shrink: 0; }
.post-actions { display: flex; gap: 18px; color: var(--muted); font-size: 13px; font-weight: 500; }
.post-actions button { background: none; border: none; color: var(--muted); font-size: 13px; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 6px; }
.post-actions button:hover { color: var(--text); }
.pin { color: var(--muted); font-size: 12px; font-weight: 600; margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.auto-post { border-left: 4px solid var(--gold); }
.micro-label { font-size: 10px; font-weight: 800; letter-spacing: .8px; color: #a8842a; margin-bottom: 6px; }
.workout-summary { background: var(--gold-tint); border-radius: 8px; padding: 12px; font-size: 14px; margin-bottom: 10px; }

/* ---------- Sidebar community card ---------- */
.cover { height: 140px; border-radius: 8px 8px 0 0; background: linear-gradient(135deg, #202124 0%, #3d3d3d 60%, #a8842a 100%); display: flex; align-items: center; justify-content: center; color: var(--gold); font-weight: 800; font-size: 26px; letter-spacing: 3px; }
.stats-row { display: flex; text-align: center; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); margin: 12px 0; }
.stats-row > div { flex: 1; padding: 10px 0; }
.stats-row > div + div { border-left: 1px solid var(--border); }
.stat-num { font-family: var(--px-display-font); font-style: italic; font-weight: 800; text-transform: uppercase; letter-spacing: -.01em; font-size: 21px; line-height: 1; }
.stat-label { font-size: 12px; color: var(--muted); }

/* ---------- Leaderboard rows ---------- */
.lb-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.lb-rank { width: 22px; color: var(--muted); font-weight: 700; font-size: 13px; text-align: center; flex-shrink: 0; }
.lb-name { flex: 1; font-weight: 500; font-size: 14px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-val { font-weight: 700; font-size: 14px; }
.lb-me { border: 2px solid var(--gold); border-radius: 8px; padding: 8px 10px; background: var(--gold-tint); }

/* ---------- Progress ---------- */
.progress { height: 8px; background: var(--track); border-radius: 4px; overflow: hidden; }
.progress > div { height: 100%; background: var(--gold-dark); border-radius: 4px; }

/* ---------- Misc ---------- */
.badge { display: inline-block; font-size: 10px; font-weight: 800; letter-spacing: .6px; padding: 3px 8px; border-radius: 4px; background: var(--text); color: var(--gold); }
.badge-green { background: #E3F5E9; color: #1a7f3c; }
.online-dot { width: 8px; height: 8px; background: var(--green); border-radius: 50%; display: inline-block; }
.muted { color: var(--muted); }
.duotone-1 { background: linear-gradient(135deg, #33322E, #191919); }
.duotone-2 { background: linear-gradient(135deg, #8A6A1F, #1B1B1B); }
.duotone-3 { background: linear-gradient(135deg, #4A3D18, #141414); }
.duotone-4 { background: linear-gradient(135deg, #55524A, #1B1B1B); }
h1 { font-size: 22px; margin-bottom: 16px; }
h2 { font-size: 17px; margin-bottom: 12px; }
input[type="number"], input[type="text"] { border: 1px solid var(--border); border-radius: var(--radius); height: 38px; padding: 0 12px; font-size: 14px; outline: none; width: 100%; background: var(--card); color: var(--text); }
input:focus { border-color: #c9c9c9; }

/* ---------- Athletic display language (Reps DNA) ---------- */
/* .px-display — the display stack. On page h1s, big stat numbers, primary CTAs only.
   Never on body copy, post titles, or member names. */
.px-display, .page-head h1 {
  font-family: var(--px-display-font);
  font-style: italic;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: -.02em;
}
/* .px-eyebrow — micro-label above every page h1 (e.g. THE FEED). Optional gold dot. */
.px-eyebrow {
  display: block;
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .35em;
  color: var(--muted);
}
.px-eyebrow.dot::before {
  content: "";
  display: inline-block;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--gold);
  margin-right: 8px;
  vertical-align: 1px;
}
/* .page-head — eyebrow + display h1 + muted sub, consistent rhythm. */
.page-head { margin-bottom: 24px; }
.page-head .px-eyebrow { margin-bottom: 8px; }
.page-head h1 { font-size: 30px; line-height: 1.04; margin-bottom: 6px; }
.page-head .page-sub, .page-head .sub { font-size: 14px; color: var(--muted); margin-bottom: 0; }
/* .px-score — signature dark scoreboard tile. Dark in BOTH themes (this is what
   separates us from Skool). Gold display number + spaced gray label. */
.px-score {
  background: #101010;
  border: 1px solid #262626;
  border-radius: var(--radius-card);
  padding: 14px 12px;
  text-align: center;
}
.px-score .n {
  display: block;
  font-family: var(--px-display-font);
  font-style: italic;
  font-weight: 800;
  letter-spacing: -.01em;
  font-size: 34px;
  line-height: 1;
  color: var(--gold);
}
.px-score .l {
  display: block;
  margin-top: 7px;
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .18em;
  color: #8C8C8C;
}

/* ---------- Mobile polish ---------- */
@media (max-width: 640px) {
  .container { padding: 14px 12px 84px; }
  h1 { font-size: 19px; }
  h2 { font-size: 16px; }
  .page-head { margin-bottom: 18px; }
  .page-head h1 { font-size: 25px; }
  .post, .card-pad { padding: 14px; }
  .thumb { width: 92px; height: 64px; }
  .topbar-inner { height: 54px; gap: 10px; }
  .logo { font-size: 15px; }
  .logo-mark { width: 28px; height: 28px; font-size: 12px; }
  .pills { gap: 6px; }
  .pill { padding: 6px 12px; font-size: 12px; }
  .post-title { font-size: 15px; }
}

/* ---------- Dark-mode fixes for shared components (light mode unchanged) ----------
   These invert cleanly in dark: components that use a light var(--text) as a *background*
   with white/gold text, or gold buttons whose var(--text) label goes light in dark. */
[data-theme="dark"] .btn { color: #1a1a1a; }              /* gold btn: dark label stays readable */
[data-theme="dark"] .btn-outline { color: var(--text); }  /* outline btn keeps light label */
[data-theme="dark"] .pill.active { color: #1a1a1a; }      /* active pill bg is light var(--text) */
[data-theme="dark"] .badge:not(.badge-green) { background: var(--gold); color: #1a1a1a; }
[data-theme="dark"] .logo-mark { background: var(--gold); color: #1a1a1a; }

/* ---------- iOS zoom guard (BUG2) ----------
   iOS Safari/WKWebView auto-zooms when a focused text field has font-size < 16px and
   never zooms back out. Several fields ship at 14px (input[type=text|number], .search
   input, etc.). Force >=16px for text-entry controls on mobile ONLY so tapping them no
   longer zooms. Desktop sizing above is untouched. The type-selectors below match the
   (0,1,1) specificity of the offending `input[type="text"]` rule and come last, so they
   win; the bare input/textarea/select line covers everything else. */
@media (max-width: 760px) {
  input, textarea, select { font-size: 16px; }
  input[type="text"], input[type="number"], input[type="email"], input[type="tel"],
  input[type="url"], input[type="password"], input[type="search"], input[type="date"] { font-size: 16px; }
  .search input { font-size: 16px; }

  /* Bottom cushion: the fixed bottom nav is 62px + the phone's home-indicator
     safe-area, so every page's content must reserve at least that PLUS breathing
     room, or the last card/section hides under the nav and you can't scroll to it.
     Overrides the tighter 84px above so content always clears the bar with slack. */
  .container { padding-bottom: calc(62px + env(safe-area-inset-bottom) + 40px) !important; }
  html.px-native .container { padding-bottom: calc(62px + var(--px-sab) + 40px) !important; }
}

/* ---------- Premium section transitions (feel like an app, not a website) ----------
   shell.js stamps .px-enter on the page's OWN content (never the topbar / bottom nav /
   siderail — those stay persistent), so switching sections reads as a smooth horizontal
   SLIDE-IN: since each section is a real page load (location.href), the new page's own
   content slides in from the right + fades, so navigation feels like moving forward
   through screens instead of a hard cut. Pure CSS animation ⇒ content is clickable the
   whole time (never gates interactivity). Smooth ~400ms decelerating ease-out slide. */
@keyframes pxContentIn {
  from { opacity: 0; transform: translateX(38px); }
  to   { opacity: 1; transform: translateX(0); }
}
.px-enter,
html.px-shell .container { animation: pxContentIn 400ms cubic-bezier(.22,1,.36,1) both; }
/* html.px-shell .container covers the common case: the page's main content wrapper
   (built by shell.js-following scripts on JS-heavy pages like the feed) slides in the
   moment it's inserted. .px-enter is stamped by shell.js on EVERY top-level body child
   (see shell.js), so full-screen app shells (.screen / .day-screen / .lab-screen etc.)
   that aren't wrapped in a .container get the same slide. The chrome is never a
   .container and is force-disabled below, so it stays put. */
/* Overflow guard: the entrance starts 28px to the right of final position, so for one
   ~200ms frame the content extends past the right edge (full-width on mobile). clip that
   transient overflow on the shell root so it can never spawn a horizontal scrollbar.
   overflow-x:clip (NOT hidden) does not create a scroll container, so it leaves the
   sticky topbar / fixed overlays and vertical scrolling completely intact. Supported in
   the iOS Capacitor webview (Safari 16+); older engines simply ignore it and fall back
   to a harmless one-frame scrollbar. */
html.px-shell, html.px-shell body { overflow-x: clip; }
/* Chrome is persistent — belt-and-suspenders so it can never inherit the entrance. */
.topbar, .siderail, .bottomnav, .sheet, .drawer, #px-offline-banner { animation: none; }

/* ============================================================================
   PREMIUM MOTION LAYER — kills the "pop, pop, pop".
   Every overlay/sheet/modal in the app opens by toggling display:none → flex on
   a backdrop element (.x.open / .x.show). display can't be transitioned, so we
   attach a keyframe *animation* to the open state instead — it fires the instant
   the element is shown. Two coordinated moves so it reads as one premium gesture:
     1. the backdrop (dim + blur) FADES in                → pxScrimIn (opacity only, zero layout risk)
     2. the content panel ZOOMS/RISES into place          → pxSurfaceIn (scale .965→1 + 10px rise + fade)
   Loaded on every page via styles.css, so it lands app-wide without touching the
   40+ per-page overlay definitions. Where a page already animates its own content
   the higher-specificity ">*" rule below wins and unifies it to one feel.
   Timing (~.30s decelerating ease-out) is intentionally a hair slower than snappy
   so it feels expensive, per request. ============================================================================ */
@keyframes pxScrimIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes pxSurfaceIn {
  from { opacity: 0; transform: translateY(10px) scale(.965); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}
/* --- 1. backdrop fade — broad list, opacity-only so it can never shift layout --- */
.modal-backdrop.open, .sheet-bg.open, .sheet.open, .pxs-overlay.open, .pxlink-overlay.open,
.rc-modal.open, .vmodal-bg.open, .wiz-bg.open, .wr-detail.open, .fr-scrim.open, .lab-sheet.open,
.spotsheet.open, .search-pop.open, .admin-menu.open, .chat-panel.open, .room.open, .shell-pop.open,
.vlb.open, .ca-editor.open, .sheet-bg.open, .manual-rim-link.show, .dm-upsell.show, .dc-complete.show,
.detwarn.show, .lab-countdown.show, .startveil.show, .req-sent.show, .promo-msg.show, .unlock-note.show,
.pl-saved.show, .rp-ci-sent.on, .drillpanel.on, .drillcheck.on {
  animation: pxScrimIn .24s ease both;
}
/* --- 2. content zoom/rise — only the clear centered/sheet modals (single content child).
       ">*" beats any inline content animation so the whole app shares one entrance. --- */
.modal-backdrop.open > *, .sheet-bg.open > *, .pxs-overlay.open > *, .rc-modal.open > *,
.vmodal-bg.open > *, .wiz-bg.open > *, .spotsheet.open > *, .lab-sheet.open > * {
  animation: pxSurfaceIn .30s cubic-bezier(.22,1,.36,1) both;
}
/* Dropdowns (admin menu, notifications, search) are the positioned element itself, not a
   backdrop+child — so they only get the fade above, plus a small drop-from-top so they feel
   like they hinge open rather than blink in. transform-origin keeps them pinned to their anchor. */
.admin-menu.open, .shell-pop.open, .search-pop.open {
  animation: pxDropIn .2s cubic-bezier(.22,1,.36,1) both; transform-origin: top center;
}
@keyframes pxDropIn { from { opacity: 0; transform: translateY(-7px) scale(.98); } to { opacity: 1; transform: none; } }

/* Respect the OS reduced-motion setting: no entrance, no theme cross-fade, no overlay motion. */
@media (prefers-reduced-motion: reduce) {
  .px-enter,
  html.px-shell .container,
  [class*="open"], [class*="show"], [class*="open"] > *, [class*="show"] > * { animation: none !important; }
  body { transition: none; }
}
