/* ═══════════════════════════════════════════════════════════════════════════
   FitMind V3 — the design direction as a real stylesheet.
   Every value here comes from the .dc.html design components; the README's
   60/30/10 table is the source of truth for colour.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* 60 — graphite canvas */
  --canvas: #08080A;
  --page: #050506;
  --hero-bg: #0A0C14;

  /* 30 — glass */
  --glass: linear-gradient(180deg, rgba(255,255,255,.065), rgba(255,255,255,.022));
  --glass-line: rgba(255,255,255,.1);

  /* 10 — accents. Blue = work/capacity. Lime = you, now. */
  --ocean: #457BF1;
  --ocean-line: rgba(140,175,255,.24);
  --starship: #E7FE55;

  /* ink */
  --ink: #ECEFF4;
  --ink-2: rgba(236,239,244,.68);
  --ink-3: rgba(236,239,244,.45);
  --ink-4: rgba(236,239,244,.32);

  /* body map — graphite, never blue */
  --mm-base: #191C21;
  --mm-stops: #22262D|#5C646F|#B4BCC8;

  --mono: 'Martian Mono', ui-monospace, monospace;
  --sans: Manrope, system-ui, -apple-system, sans-serif;

  --frame-w: 390px;
  --frame-h: 844px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  /* 100% resolves against the LAYOUT viewport, which on iOS standalone with
     the layout viewport stops short of the home-indicator strip — while .frame
     below is sized in dvh, which includes it. The two disagreed by the height
     of the safe area, and --page showed through the difference as a dark band
     across the bottom of the app. dvh on both makes them agree. */
  height: 100%;
  height: 100dvh;
  background: var(--page);
  font-family: var(--sans);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
}

button { font-family: inherit; color: inherit; }

/* ── text selection ────────────────────────────────────────────────────────
   Off by default, on where the text is the content rather than the label.

   On a phone a long press is how you scroll a list that begins under your
   finger, and it is also how you select a word — and the browser cannot tell
   which you meant until the gesture is over, so it guesses. Over a card of
   numbers and labels it tends to guess "select", and instead of scrolling you
   get a blue highlight, drag handles and the callout menu. Two rules in here
   already fought that locally, on the ruler and on the reorderable lift rows;
   this is the same fix applied once, in the one place it belongs.

   `*` inherits rather than repeating `none`, so switching a container back to
   selectable carries to everything inside it — .bub does not need a `.bub *`
   partner, and neither will the next thing that wants real text. It sits at
   zero specificity, so every existing rule still outranks it.

   Inputs are exempt on their own account: user-select:none takes the caret
   with it in some engines, leaving a field you can type into but cannot click
   into to fix a typo — worse than the problem being solved. */
html, body {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
* {
  -webkit-user-select: inherit;
  user-select: inherit;
}
.bub,
input,
textarea,
[contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

/* ── squircles ─────────────────────────────────────────────────────────────
   corner-shape only lands in very new Chrome; everywhere else these stay
   ordinary rounded rectangles, which is a clean degradation. */
@supports (corner-shape: squircle) {
  [data-sq] { corner-shape: squircle; }
  [data-sq-soft] { corner-shape: superellipse(2.4); }
}

/* ── motion ────────────────────────────────────────────────────────────────
   One slow gesture per screen, 4–16s, no bounce. */
@keyframes fmSpin { to { transform: rotate(360deg); } }
@keyframes fmBreathe { 0%,100% { opacity:.5; transform: scale(1); } 50% { opacity:.95; transform: scale(1.05); } }
@keyframes fmDotWave { 0%,100% { opacity:.42 } 50% { opacity:1 } }
@keyframes fmRestBar { from { transform: scaleX(1) } to { transform: scaleX(0) } }
@keyframes fmRise { from { opacity:0; transform: translateY(9px) } to { opacity:1; transform:none } }
@keyframes fmSheet { from { transform: translateY(102%) } to { transform:none } }
@keyframes fmBlink { 0%,100% { opacity:.15 } 50% { opacity:.85 } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ═══ shell ═══════════════════════════════════════════════════════════════ */

.frame {
  position: relative;
  width: var(--frame-w);
  height: min(var(--frame-h), 100dvh);
  border-radius: 64px;
  overflow: hidden;
  background: var(--canvas);
  border: 1px solid rgba(255,255,255,.09);
  box-shadow: 0 30px 70px -24px rgba(0,0,0,.8);
  isolation: isolate;
}

.dots {
  position: absolute; inset: 0;
  background-image: radial-gradient(rgba(255,255,255,.075) 1px, transparent 1.2px);
  background-size: 15px 15px;
  background-position: -1px -1px;
  -webkit-mask: radial-gradient(120% 80% at 50% 30%, #000 30%, rgba(0,0,0,.35) 100%);
  mask: radial-gradient(120% 80% at 50% 30%, #000 30%, rgba(0,0,0,.35) 100%);
  pointer-events: none;
  z-index: 0;
}

.bloom {
  position: absolute;
  top: 150px; left: 50%;
  width: 370px; height: 370px; margin-left: -185px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(69,123,241,.15), transparent 62%);
  filter: blur(30px);
  animation: fmBreathe 13s ease-in-out infinite;
  pointer-events: none;
  z-index: 0;
}
.bloom.low { top: auto; bottom: -40px; width: 460px; height: 420px; margin-left: -230px;
  background: radial-gradient(circle, rgba(69,123,241,.22), transparent 62%); filter: blur(36px); }

.screen {
  position: absolute; inset: 0;
  z-index: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 28px 16px 122px;
  scrollbar-width: none;
  outline: none;

  /* -webkit-overflow-scrolling: touch is deliberately NOT here.

     It was, and it is the reason this scroller jumped to the end on an iPhone
     when a tap re-rendered the screen. The property puts the scroller on its
     own legacy compositing layer, and replacing that layer's contents —
     which every render does, via innerHTML — leaves the layer's idea of its
     own scroll position pointing at content that no longer exists. Safari
     resolves that by clamping, and clamping a stale offset against fresh
     content lands at the bottom. It has also been unnecessary since iOS 13:
     momentum scrolling is the default, and the property is deprecated.

     contain stops a gesture that reaches the end of this scroller from
     chaining out to the frame behind it. none on <body> already blocked the
     page itself, which is why this only ever showed as the screen jumping
     rather than the whole document moving.

     overflow-anchor is off because this file restores scrollTop by hand after
     every render (see app.js). Leaving the browser's own anchoring on means
     two things adjusting the same offset from different reference points, and
     the correction lands twice. */
  overscroll-behavior: contain;
  overflow-anchor: none;
}
.screen::-webkit-scrollbar { display: none; }
.screen.no-scroll { overflow: hidden; }
/* only on a tab change — re-rendering after every logged set should not
   re-animate the whole screen */
/* ── consistency ────────────────────────────────────────────────────────────
   Rounded-triangle petals, one per week. Track behind, fill in front, same
   shape both times so size alone carries the comparison.

   The rounding is a thick round-joined stroke in each path's own colour rather
   than authored arcs, which keeps one expression for the geometry and lets the
   corner radius scale with the shape as the fill grows.

   The number flips to dark once the fill has arrived under it — the `.over`
   class does that, and it is why the figure needs no legend. */
.pw-card { padding-bottom: 24px; }

/* ── training balance ───────────────────────────────────────────────────────
   The petal chart's own stylesheet handles everything inside the svg; this is
   only the slot it sits in. Width is capped rather than filled because the
   labels sit inside the wedges — past about 300px in a 390 frame the wheel
   stops gaining legibility and just crowds the card. */
.tb-card { padding-bottom: 8px; }

/* Pulled out into the card's own side padding. The card carries 34px a side,
   which on a 390 frame left the wheel at 275px — and this is a chart whose
   labels live INSIDE the wedges, so every pixel of diameter is legibility
   rather than decoration. Bleeding most of that padding back buys ~60px. */
.tb-mount { margin: 4px -30px 0; }
/* The way into the detail screen, now that the card itself is inert and the
   wheel above keeps its own taps.

   Mono uppercase to match the card's own header rather than the underlined
   page-foot links elsewhere: this belongs to the card it sits in, not to the
   screen. Full width so the target is the whole strip rather than the words —
   it is the only thing on this card that is not the wheel, and it should be
   hard to miss and impossible to hit by accident while turning a petal.

   min-height carries the 44px touch target on its own, which is why .tb-card
   gave most of its bottom padding back above. */
.tb-more {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  width: 100%; min-height: 44px; padding: 0; margin: 2px 0 0;
  border: 0; background: none; cursor: pointer;
  font: 300 9.5px/1 var(--mono); letter-spacing: .18em;
  color: rgba(255,255,255,.5);
  transition: color .18s;
}
.tb-more:hover, .tb-more:focus-visible { color: var(--ink-2); }
.tb-more .s { font-size: 13px; line-height: 0; }

/* ── training balance screen ────────────────────────────────────────────── */
.bal-verdict {
  margin: 14px auto 0; max-width: 34ch; text-align: center;
  font-size: 12.5px; line-height: 1.6; color: var(--ink-2);
}
.bal-sub { margin: 0 0 16px; font-size: 12.5px; line-height: 1.55; color: var(--ink-3); }

.bal-rs { display: flex; flex-direction: column; }
.bal-r {
  display: grid; grid-template-columns: 1fr auto;
  grid-template-areas: "name value" "meter meter" "note note";
  gap: 0 14px; align-items: baseline;
  padding: 14px 0; border-bottom: 1px solid var(--glass-line);
}
.bal-r:last-child { border-bottom: 0; padding-bottom: 0; }
.bal-r-n { grid-area: name; font-weight: 600; font-size: 14px; }
.bal-flag {
  font: 400 8.4px/1 var(--mono); letter-spacing: .14em; font-style: normal;
  color: #E8A33D; margin-left: 8px;
}
.bal-r-v {
  grid-area: value; font: 400 19px/1 var(--mono);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.bal-r-v.none { font-size: 14px; color: var(--ink-4); }
.bal-meter {
  grid-area: meter; position: relative; height: 3px; margin-top: 10px;
  background: rgba(236,239,244,.08); border-radius: 2px; overflow: hidden;
}
.bal-meter i { position: absolute; inset: 0 auto 0 0; background: var(--ocean); border-radius: 2px; }
.bal-r[data-inv="true"] .bal-meter i { background: #E8A33D; }
.bal-r-t { grid-area: note; margin-top: 8px; font-size: 12px; line-height: 1.5; color: var(--ink-3); }

.bal-split { display: flex; height: 26px; border-radius: 8px; overflow: hidden; background: rgba(236,239,244,.06); }
.bal-split i { display: block; }
.bal-split .gym { background: var(--ocean); }
.bal-split .cardio { background: rgba(140,175,255,.32); }
.bal-keys { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 14px; }
.bal-key { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; color: var(--ink-2); }
.bal-key b { width: 8px; height: 8px; border-radius: 2px; flex: none; transform: translateY(1px); }
.bal-key .gym { background: var(--ocean); }
.bal-key .cardio { background: rgba(140,175,255,.32); }
.bal-key em { font: 400 12px/1 var(--mono); font-style: normal; color: var(--ink-3); }

.bal-vs { display: flex; flex-direction: column; }
.bal-v {
  display: grid; grid-template-columns: 62px 1fr 34px;
  gap: 12px; align-items: center; padding: 10px 0;
}
.bal-v-n { font-size: 13.5px; font-weight: 600; }
.bal-v-t { position: relative; height: 7px; background: rgba(236,239,244,.07); border-radius: 4px; }
.bal-v-f { position: absolute; inset: 0 auto 0 0; background: var(--ocean); border-radius: 4px; }
.bal-v-m { position: absolute; top: -4px; bottom: -4px; width: 1px; background: rgba(236,239,244,.28); }
.bal-v-m.band { background: var(--starship); opacity: .5; }
.bal-v-v { font-size: 12px; text-align: right; color: var(--ink-2); }

.bal-log { display: flex; flex-direction: column; }
.bal-day {
  display: grid; grid-template-columns: 54px 1fr; gap: 14px;
  padding: 9px 0; border-bottom: 1px solid var(--glass-line); align-items: start;
}
.bal-day:last-child { border-bottom: 0; }
.bal-day-d { font-size: 11px; color: var(--ink-3); }
.bal-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.bal-act {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 10px 4px 8px; border-radius: 999px; font-size: 12px;
  border: 1px solid var(--glass-line); background: rgba(236,239,244,.03);
}
.bal-act i { width: 5px; height: 5px; border-radius: 50%; flex: none; }
.bal-act.gym i { background: var(--ocean); }
.bal-act.cardio i { background: rgba(140,175,255,.5); }
.bal-act em { font-size: 10.5px; font-style: normal; color: var(--ink-3); }
.bal-gap {
  display: grid; grid-template-columns: 54px 1fr; gap: 14px;
  padding: 8px 0; border-bottom: 1px solid var(--glass-line);
}
.bal-gap span {
  grid-column: 2; font: 400 8.4px/1 var(--mono);
  letter-spacing: .14em; color: #E8A33D;
}

.bal-notes { display: flex; flex-direction: column; gap: 14px; }
.bal-note { display: grid; grid-template-columns: 100px 1fr; gap: 14px; }
.bal-note p { margin: 0; font-size: 12px; line-height: 1.55; color: var(--ink-3); }

@media (max-width: 380px) {
  .bal-note { grid-template-columns: 1fr; gap: 3px; }
}
.pw-wrap { position: relative; width: 216px; height: 216px; margin: 12px auto 0; }
.pw-halo {
  position: absolute; inset: 18px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(231,254,85,.12), transparent 62%);
  filter: blur(15px);
}
.pw-svg { position: relative; width: 216px; height: 216px; display: block; overflow: visible; }

.pw-t {
  fill: rgba(255,255,255,.055);
  stroke: rgba(255,255,255,.055); stroke-width: 13; stroke-linejoin: round;
}
.pw-f {
  fill: rgba(140,175,255,.42);
  stroke: rgba(140,175,255,.42); stroke-width: 13; stroke-linejoin: round;
}
/* a week that met its plan is the point of arrival, so it takes the lime */
.pw.hit .pw-f { fill: var(--starship); stroke: var(--starship); }

.pw-n {
  fill: var(--ink); font: 400 17px/1 var(--mono); text-anchor: middle;
  dominant-baseline: middle; pointer-events: none;
}
.pw-l {
  fill: var(--ink-3); font: 400 6.8px/1 var(--mono); letter-spacing: .16em;
  text-anchor: middle; dominant-baseline: middle; pointer-events: none;
}
/* the fill has reached the label: read it against the fill, not the track */
.pw.over .pw-n { fill: #0B0D07; }
.pw.over .pw-l { fill: rgba(11,13,7,.6); }
.pw.hit.over .pw-n { fill: #0B0D07; }

.pw-mid {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.pw-mid b {
  font: 200 19px/1 var(--mono); color: rgba(236,239,244,.5); font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* the figure, at the size a detail view can afford */
.ins-body { height: 208px; margin-top: 16px; }
.sd-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 16px; }
.sd-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 10px 7px 11px; border-radius: 999px;
  font: 400 7.6px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase;
  border: 1px solid rgba(255,255,255,.10); color: var(--ink-3);
  background: rgba(255,255,255,.03);
}
.sd-chip i { font-style: normal; font-variant-numeric: tabular-nums; color: var(--ink-2); font-size: 8.6px; }
.sd-chip.building, .sd-chip.strong {
  border-color: rgba(231,254,85,.34); color: var(--starship); background: rgba(231,254,85,.07);
}
.sd-chip.building i, .sd-chip.strong i { color: var(--starship); }
.sd-chip.maintaining {
  border-color: rgba(140,175,255,.30); color: rgba(140,175,255,.9); background: rgba(92,139,232,.07);
}
.sd-chip.maintaining i { color: rgba(140,175,255,.9); }

/* ── load, lift by lift ─────────────────────────────────────────────────────
   One block per lift: name, change, the shape of the trend, and a word for
   what that shape means. The sparkline is drawn in the verdict's own colour,
   so the line and the label cannot disagree. */
.st-lifts { display: flex; flex-direction: column; gap: 2px; margin-top: 18px; }
.st-lift { padding: 14px 0; border-top: 1px solid rgba(255,255,255,.07); }
.st-lift:first-child { border-top: 0; padding-top: 4px; }
.st-l-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.st-l-name {
  font-size: 13px; font-weight: 600; letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.st-l-d { font: 300 12px/1 var(--mono); flex: none; font-variant-numeric: tabular-nums; }
.st-l-spark { display: block; width: 100%; height: 22px; margin: 10px 0 8px; }
.st-l-foot {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  font: 400 7.4px/1 var(--mono); letter-spacing: .14em; color: var(--ink-3);
}
/* the three readings, and the colour each is allowed */
.st-lift .grow { color: var(--starship); }
.st-lift .hold { color: rgba(140,175,255,.85); }
.st-lift .warn { color: #FF9A78; }
.st-l-spark { color: rgba(140,175,255,.7); }
.st-lift:has(.st-l-d.grow) .st-l-spark { color: var(--starship); }
.st-lift:has(.st-l-d.warn) .st-l-spark { color: #FF9A78; }

.st-note {
  margin: 18px 0 0; padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,.07);
  font: 400 10.5px/1.6 var(--sans); color: rgba(236,239,244,.42);
}

/* ── press feedback ─────────────────────────────────────────────────────────
   A control that does not move under the thumb reads as a picture of a control.
   This is the cheapest liveness in the app and the one felt most often.

   `scale` rather than `transform: scale()`, deliberately. GSAP writes the
   entrance into `transform`, and the reorder drag writes `translateY` there
   too; a press that also wrote `transform` would wipe whichever was mid-flight.
   The standalone property composes with both instead of competing.

   Excluded while a row is being carried — a lift held in the air is not a lift
   being pressed, and it has its own scale to keep. */
.btn, .btn-ghost, .chip, .sheet-opt, .nudge-btn, .end-x, .tab, .avatar, .pf-row {
  transition: scale .16s cubic-bezier(0.23, 1, 0.32, 1);
}
.btn:active, .btn-ghost:active, .chip:active, .nudge-btn:active,
.end-x:active, .avatar:active, .pf-row:active { scale: .97; }
.sheet-opt:not(.lifted):active { scale: .98; }
.tab:active { scale: .93; }

/* The screen's entrance is ScreenAnim's now. This ran one keyframe over every
   block at once — no order, no lead — and worse, `both` from `opacity: 0` made
   invisibility the resting state, so anything that stopped the animation
   running left the screen blank. GSAP writes only start values, so no GSAP now
   means no animation and full content. */

/* On a phone the frame IS the screen. On a short desktop window it stays a
   390px phone and simply gets shorter. */
@media (max-width: 460px) {
  /* On a phone the frame IS the screen, so there is no page behind it to see.
     Painting the body the same colour means that even if a sliver of it is ever
     exposed — a rubber-band overscroll, a rotation, a keyboard dismissal — there
     is nothing to notice. --page only exists to sit the phone frame on at desk
     sizes. */
  html, body { background: var(--canvas); overflow: hidden; }

  /* ── the iOS standalone shell ──────────────────────────────────────────────
     `position: fixed; inset: 0` rather than a computed height. Several rounds of
     this bug came from asking the browser how tall the screen is — 100%, then
     100vh, then 100dvh — and iOS answering with a number that excluded a strip
     we could not see. fixed/inset does not ask: it pins to the viewport's four
     edges and the layout follows from that rather than from a length.

     That alone never fixed the dark band, because the band was not ours — it was
     the region viewport-fit=cover handed us and then placed outside the web view.
     index.html no longer asks for cover, so the viewport is inset into the safe
     area and WebKit paints the inset with the document background. That is why
     html and body are --canvas above: on a phone, that rule is now painting the
     status-bar strip, not just insurance against overscroll.

     The body stops being a flex centring context here too: on a phone there is
     no frame to centre, and centring something exactly viewport-sized turns a
     few missing pixels into a visible band instead of an invisible overflow. */
  body {
    position: fixed;
    inset: 0;
    display: block;
    height: auto;
    width: auto;
  }

  .frame {
    position: fixed;
    inset: 0;
    width: auto; height: auto;
    border-radius: 0; border: none; box-shadow: none;
  }

  /* The tab bar floats above the home indicator, so the scroller has to clear
     both. 128px cleared the bar on a device with no indicator and left the last
     card tucked under it on one that has. */
  .screen {
    padding: max(28px, env(safe-area-inset-top)) 16px
             calc(128px + env(safe-area-inset-bottom));
  }
}

/* ═══ type ════════════════════════════════════════════════════════════════ */

.h-greet { font-size: 25px; font-weight: 600; letter-spacing: -.02em; }
.h-scr   { font-size: 23px; font-weight: 600; letter-spacing: -.02em; }
.h-card  { font-size: 14px; font-weight: 600; letter-spacing: -.01em; }
.body-s  { font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }

.mono    { font-family: var(--mono); font-weight: 400; }
.micro   { font: 400 8.4px/1 var(--mono); letter-spacing: .14em; color: var(--ink-3); }
.micro-2 { font: 300 9.5px/1 var(--mono); letter-spacing: .18em; color: rgba(255,255,255,.55); }
.num     { font-family: var(--mono); font-weight: 200; }
.lime    { color: var(--starship); }

/* ═══ cards ═══════════════════════════════════════════════════════════════ */

.card {
  position: relative;
  border-radius: 76px;
  padding: 26px 34px 24px;
  margin-bottom: 12px;
  background: var(--glass);
  border: 1px solid var(--glass-line);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
}
.card.tight { border-radius: 56px; padding: 22px 26px; }
.card.pad-narrow { padding: 26px 30px 24px; }

/* hero — near-black with the light inside the edge */
.hero {
  position: relative;
  border-radius: 96px;
  padding: 30px 40px 34px;
  margin-bottom: 12px;
  overflow: hidden;
  background: var(--hero-bg);
  border: 1px solid rgba(140,175,255,.22);
  box-shadow:
    inset 0 0 74px 26px rgba(69,123,241,.42),
    inset 0 1px 0 rgba(255,255,255,.18),
    0 28px 60px -30px rgba(69,123,241,.45);
}
.hero.sm {
  border-radius: 76px;
  padding: 30px 34px 26px;
  border-color: rgba(140,175,255,.26);
  box-shadow:
    inset 0 0 86px 30px rgba(69,123,241,.5),
    inset 0 1px 0 rgba(255,255,255,.2),
    0 30px 60px -34px rgba(69,123,241,.5);
}
.hero-top {
  display: flex; align-items: center; justify-content: space-between;
  font: 300 9.5px/1 var(--mono); letter-spacing: .18em; color: rgba(255,255,255,.58);
}
.hero-top .r { letter-spacing: .12em; font-size: 9px; color: rgba(255,255,255,.5); }

.tile {
  border-radius: 44px;
  padding: 20px 20px 18px;
  background: var(--glass);
  border: 1px solid var(--glass-line);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
}
.tile-l { font: 400 7.8px/1 var(--mono); letter-spacing: .14em; color: var(--ink-3); }
.tile-v { font: 200 19px/1 var(--mono); margin: 11px 0 9px; }
.tiles { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 12px; }

/* ═══ buttons ═════════════════════════════════════════════════════════════ */

.btn {
  width: 100%;
  border: 1px solid rgba(255,255,255,.11);
  border-radius: 40px;
  padding: 18px;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: rgba(255,255,255,.05);
  font: 700 15px var(--sans);
  letter-spacing: -.01em;
  color: var(--starship);
  cursor: pointer;
  transition: background .16s, transform .12s;
}
.btn:hover { background: rgba(255,255,255,.08); }
.btn:active { transform: scale(.985); }
.btn:disabled { opacity: .45; pointer-events: none; }

.btn-ghost {
  flex: 1;
  border: 1px solid rgba(255,255,255,.2);
  background: transparent;
  border-radius: 36px;
  padding: 16px;
  font: 600 12.5px var(--sans);
  color: rgba(255,255,255,.8);
  cursor: pointer;
  transition: background .16s;
}
.btn-ghost:hover { background: rgba(255,255,255,.06); }
.btn-ghost.solid { border-color: rgba(255,255,255,.24); background: rgba(255,255,255,.14); color: #fff; }
.btn-ghost.solid:hover { background: rgba(255,255,255,.2); }

.btn-row { display: flex; gap: 10px; }

.chip {
  border-radius: 26px;
  min-height: 44px;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255,255,255,.12);
  background: transparent;
  font: 500 11.5px var(--sans);
  color: rgba(236,239,244,.65);
  cursor: pointer;
  transition: background .16s, color .16s;
}
.chip:hover { background: rgba(255,255,255,.07); color: var(--ink); }

.seg {
  display: flex;
  border-radius: 30px;
  padding: 4px;
  background: rgba(255,255,255,.06);
  border: 1px solid var(--glass-line);
}
.seg button {
  border: none; background: transparent;
  border-radius: 26px; padding: 8px 15px;
  font: 600 11.5px var(--sans);
  color: rgba(236,239,244,.45);
  cursor: pointer;
  transition: background .18s, color .18s;
}
.seg button[aria-selected="true"] { background: rgba(255,255,255,.14); color: var(--ink); }

.icon-btn {
  width: 38px; height: 38px;
  border-radius: 26px;
  border: 1px solid rgba(255,255,255,.12);
  background: transparent;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; line-height: 1;
  color: rgba(236,239,244,.6);
  cursor: pointer;
  transition: background .16s;
}
.icon-btn:hover { background: rgba(255,255,255,.07); }

.nudge-btn {
  width: 34px; height: 34px; flex: none;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.18);
  background: transparent;
  color: #fff;
  font: 300 16px/1 var(--sans);
  cursor: pointer;
  transition: background .16s;
}
.nudge-btn:hover { background: rgba(255,255,255,.1); }

/* ═══ coach line — the lime dot + one sentence ════════════════════════════ */

.say { display: flex; align-items: flex-start; gap: 9px; }
.say .dot {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  margin-top: 6px;
  background: var(--starship);
  box-shadow: 0 0 10px rgba(231,254,85,.85);
  animation: fmDotWave 3.4s ease-in-out infinite;
}
.say p { margin: 0; font-size: 12.5px; line-height: 1.5; color: rgba(236,239,244,.6); }
.hero .say p { color: rgba(255,255,255,.82); }

/* ═══ readiness ring ══════════════════════════════════════════════════════ */

.ring { position: relative; width: 212px; height: 212px; margin: 12px auto 0; }
.ring .halo {
  position: absolute; inset: 13px; border-radius: 50%;
  box-shadow: 0 0 30px 4px rgba(231,254,85,.12);
  animation: fmBreathe 9s ease-in-out infinite;
}
.ring .sheen {
  position: absolute; inset: 8px; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0deg, rgba(255,255,255,.42) 34deg, transparent 76deg);
  -webkit-mask: radial-gradient(farthest-side, transparent 84%, #000 86%);
  mask: radial-gradient(farthest-side, transparent 84%, #000 86%);
  animation: fmSpin 14s linear infinite;
}
.ring svg { width: 212px; height: 212px; display: block; position: relative; }
.ring .mid {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.ring .state { font: 400 10px/1 var(--mono); letter-spacing: .22em; color: rgba(255,255,255,.76); margin-top: 16px; }

/* dot-matrix numbers */
.dm { display: grid; }
.dm span { border-radius: 50%; }

/* ═══ profile ═════════════════════════════════════════════════════════ */

.head-row { display: flex; align-items: flex-start; justify-content: space-between;
            gap: 14px; margin-bottom: 16px; }
.head-row .h-greet { margin: 0; }
.avatar {
  flex: none; width: 42px; height: 42px; margin-top: 2px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.035));
  border: 1px solid rgba(255,255,255,.14);
  backdrop-filter: blur(26px) saturate(180%) brightness(1.12);
  -webkit-backdrop-filter: blur(26px) saturate(180%) brightness(1.12);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45), inset 0 -1px 0 rgba(255,255,255,.1);
  cursor: pointer;
  transition: transform .3s cubic-bezier(.34,1.5,.5,1), border-color .3s;
}
.avatar:active { transform: scale(.94); }
.avatar span { font: 600 15px/1 var(--sans); letter-spacing: -.01em; color: var(--ink); }

.pf-row {
  display: flex; align-items: center; gap: 13px; min-height: 54px;
  width: 100%; text-align: left; padding: 0;
  background: none; border: 0; border-top: 1px solid rgba(255,255,255,.06);
  color: var(--ink); cursor: pointer;
}
.pf-row .n { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 500; }
.pf-row .v { font: 400 9px/1 var(--mono); letter-spacing: .12em; color: rgba(236,239,244,.34); }
.pf-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; }

/* ═══ nav ═════════════════════════════════════════════════════════════════ */

.tabbar {
  --accent: #457BF1;
  position: absolute; left: 16px; right: 16px;
  bottom: max(24px, env(safe-area-inset-bottom));
  z-index: 3;
  height: 51px;
  display: flex; align-items: center;
  padding: 0 9px;
  border-radius: 999px;
  overflow: hidden; isolation: isolate;
  background: linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.03));
  border: 1px solid rgba(255,255,255,.13);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4),
              inset 0 -1px 0 rgba(140,175,255,.28),
              0 18px 40px -14px rgba(0,0,0,.8);
}

/* The bar yields to the keyboard.

   It floats over the bottom of the frame, which is the one place the keyboard
   is guaranteed to want — in the coach it lands directly on the composer. Every
   messaging app resolves this the same way: the navigation gets out of the way
   while a field is focused and comes back when it is done.

   It slides out rather than vanishing, so it reads as the bar stepping aside
   for the keyboard instead of the app dropping a control. The distance is its
   own height plus the gap it sits in, which clears the frame at any inset. */
.tabbar {
  transition: transform .28s cubic-bezier(.32,.72,0,1), opacity .16s ease;
}
.frame.typing .tabbar {
  transform: translateY(calc(100% + max(24px, env(safe-area-inset-bottom))));
  opacity: 0;
  pointer-events: none;
}

/* ...and the scroller stops reserving room for it.

   .screen keeps ~122px of bottom padding so the last card is not tucked under
   the floating bar. With the bar gone that padding is just a hole between the
   composer and the keyboard — and the chat cannot scroll it away, because it is
   already at the end of its content.

   Not transitioned, on purpose. Padding on a scroll container relayouts every
   frame, and the keyboard sliding up covers the change anyway.

   Shrinking the padding makes the browser clamp scrollTop, which is what pulls
   the composer down to the keyboard. That clamp is destructive: growing the
   padding back does not undo it, so the view ends up short of where it started
   and the chat is no longer at its latest message. app.js re-pins it. */
.frame.typing .screen { padding-bottom: 20px; }

/* the lens rides to whichever tab is current — index set on the element */
.tab-lens {
  --i: 0; --bleed: 7px; --slot: calc((100% - 18px) / 5);
  position: absolute; top: 4px; bottom: 4px; z-index: 0;
  width: calc(var(--slot) + var(--bleed) * 2);
  left: calc(9px - var(--bleed));
  border-radius: 999px;
  background: linear-gradient(160deg, rgba(255,255,255,.26), rgba(255,255,255,.06) 55%, rgba(140,175,255,.12));
  backdrop-filter: blur(7px) saturate(210%) brightness(1.5);
  -webkit-backdrop-filter: blur(7px) saturate(210%) brightness(1.5);
  clip-path: inset(0 round 999px);
  box-shadow: inset 0 1.4px 0 rgba(255,255,255,.85),
              inset 0 -1.4px 0 rgba(140,175,255,.6),
              inset 1.2px 0 0 rgba(69,123,241,.3),
              inset -1.2px 0 0 rgba(140,175,255,.4),
              0 10px 26px -10px rgba(0,0,0,.7);
  will-change: transform;
  transition: width .3s cubic-bezier(0.23, 1, 0.32, 1);
}

.tab {
  flex: 1; min-width: 0; height: 51px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  background: none; border: 0; padding: 0; cursor: pointer;
  position: relative; z-index: 1;
  transition: transform .4s cubic-bezier(.34,1.5,.5,1);
}
.tab:active { transform: scale(.9); }
.tic { width: 24px; height: 24px; overflow: visible; display: block; shape-rendering: geometricPrecision;
       transition: transform .55s cubic-bezier(.34,1.55,.5,1); }
.tic path { fill-rule: evenodd; clip-rule: evenodd;
            transition: fill .35s ease, opacity .35s ease, transform .5s cubic-bezier(.34,1.4,.4,1); }

/* chromatic fringe on the tabs you are not on */
.tic .fa { fill: rgba(236,239,244,.5); opacity: .34; mix-blend-mode: screen; transform: translate(-.75px, .375px); }
.tic .fb { fill: rgba(236,239,244,.5); opacity: .3; mix-blend-mode: screen; transform: translate(.75px, -.375px); }
.tic .live { fill: rgba(236,239,244,.6); }
.tic .live2 { fill: rgba(236,239,244,.45); opacity: .8; }
.tab-l { font: 400 7.2px/1 var(--mono); letter-spacing: .1em; color: rgba(236,239,244,.52);
         transition: color .3s ease, text-shadow .3s ease; }

.tab[aria-current="page"] .tic { transform: scale(1.05); }
.tab[aria-current="page"] .tic .fa,
.tab[aria-current="page"] .tic .fb { opacity: 0; transform: none; }
.tab[aria-current="page"] .tic .live { fill: #FFFFFF; filter: drop-shadow(0 0 3px rgba(255,255,255,.55)); }
.tab[aria-current="page"] .tic .live2 { fill: var(--accent); opacity: 1; filter: drop-shadow(0 0 5px rgba(69,123,241,.8)); }
.tab[aria-current="page"] .tab-l { color: #FFFFFF; text-shadow: 0 0 10px rgba(255,255,255,.4); }

/* ── nav, option B: one continuous blob (gooey merged circles) ────────── */
.tabbar.beads {
  height: 64px;
  padding: 0;
  gap: 0;
  background: none;
  border: 0;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: none;
  overflow: visible;
  justify-content: center;
}
.tabbar.beads .tab-lens { display: none; }
.goo-defs { position: absolute; width: 0; height: 0; }

/* the shapes: overlapping circles melted into one strip, the accent one swollen */
.tab-goo, .tab-rims, .tab-glow { display: none; }
.tabbar.beads .tab-goo {
  --i: 0; --step: 54px; --span: 270px;
  position: absolute; inset: 0; z-index: 0;
  display: flex; align-items: center; justify-content: center; gap: 0;
  filter: url(#navGoo);
  pointer-events: none;
}
.tabbar.beads .tab-goo .gb {
  flex: none; width: 56px; height: 56px; margin: 0 -1px; border-radius: 50%;
  background: rgba(150,158,178,.22);
}
.tabbar.beads .tab-goo .gactive {
  position: absolute; top: 50%; width: 62px; height: 62px; margin-top: -31px;
  /* `left` places slot 0 and never changes again - NavAnim moves this on `x`.
     It used to animate `left`, which is a layout property, on the one element
     in the app that can least afford it: the parent carries an SVG goo filter
     and the rims carry a backdrop-filter, so every frame re-ran layout, then
     the filter, then five blurs. */
  left: calc(50% - (var(--span) / 2) - 3px);
  border-radius: 50%;
  background: rgba(236,239,244,.62);
  will-change: transform;
}

/* the halo the blob throws, unfiltered so it stays soft */
.tabbar.beads .tab-glow {
  --i: 0; --step: 54px; --span: 270px;
  display: block; position: absolute; top: 50%; width: 84px; height: 84px; margin-top: -42px;
  left: calc(50% - (var(--span) / 2) - 14px);
  border-radius: 50%; z-index: 0; pointer-events: none;
  background: radial-gradient(circle, rgba(255,255,255,.34), rgba(255,255,255,0) 68%);
  filter: blur(6px);
  will-change: transform;
}

/* glass on the melted strip: same recipe as the pill, clipped to each circle */
.tabbar.beads .tab-rims {
  display: flex; position: absolute; inset: 0; z-index: 1;
  align-items: center; justify-content: center; gap: 0; pointer-events: none;
}
.tabbar.beads .tab-rims span {
  flex: none; width: 56px; height: 56px; margin: 0 -1px; border-radius: 50%;
  box-sizing: border-box;
  background: linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.035));
  border: 1px solid rgba(255,255,255,.14);
  backdrop-filter: blur(26px) saturate(180%) brightness(1.12);
  -webkit-backdrop-filter: blur(26px) saturate(180%) brightness(1.12);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45),
              inset 0 -1px 0 rgba(255,255,255,.12);
}
/* the current circle: brighter frost, white sheen */
.tabbar.beads .tab-rims span.on {
  background: linear-gradient(160deg, rgba(255,255,255,.26), rgba(255,255,255,.07) 55%, rgba(255,255,255,.04));
  border-color: rgba(255,255,255,.3);
  box-shadow: inset 0 1.4px 0 rgba(255,255,255,.85),
              inset 0 -1.4px 0 rgba(255,255,255,.22);
  transform: scale(1.07);
  transition: transform .5s cubic-bezier(.34,1.45,.42,1);
}

.tabbar.beads .tab {
  flex: none;
  width: 54px; height: 56px;
  border-radius: 50%;
  gap: 0;
  background: none; border: 0; box-shadow: none;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  position: relative; z-index: 2;
  transition: transform .4s cubic-bezier(.34,1.5,.5,1);
}
.tabbar.beads .tab-l { display: none; }
.tabbar.beads .tic { width: 24px; height: 24px; }
.tabbar.beads .tic .fa,
.tabbar.beads .tic .fb { opacity: 0; }
.tabbar.beads .tic .live { fill: rgba(236,239,244,.5); }
.tabbar.beads .tic .live2 { fill: rgba(236,239,244,.36); opacity: 1; }
.tabbar.beads .tab[aria-current="page"] .tic { transform: scale(1.06); }
.tabbar.beads .tab[aria-current="page"] .tic .live { fill: #0D0E12; filter: none; }
.tabbar.beads .tab[aria-current="page"] .tic .live2 { fill: var(--accent); opacity: 1; filter: none; }

/* ═══ Today ═══════════════════════════════════════════════════════════════ */

.load-legend {
  display: flex; gap: 14px; margin-top: 6px;
  font: 400 8.4px/1 var(--mono); letter-spacing: .1em; color: var(--ink-3);
}
.load-legend span { display: flex; align-items: center; gap: 6px; }
.load-legend i { width: 14px; height: 2px; display: block; }
.axis {
  display: flex; justify-content: space-between;
  font: 400 8.4px/1 var(--mono); letter-spacing: .1em; color: rgba(236,239,244,.35);
  margin-top: 6px;
}
.sleep-bars { display: flex; align-items: flex-end; gap: 2px; height: 14px; }
.sleep-bars span { flex: 1; border-radius: 1.5px; }
.mm { width: 100%; height: 250px; opacity: .72; }
.mm-legend {
  display: flex; justify-content: center; gap: 16px; margin-top: 8px;
  font: 400 8.2px/1 var(--mono); letter-spacing: .1em; color: var(--ink-3);
}
.mm-legend span { display: flex; align-items: center; gap: 6px; }
.mm-legend i { width: 6px; height: 6px; border-radius: 50%; display: block; }

.row-head { display: flex; align-items: baseline; justify-content: space-between; }
.scr-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }

/* ═══ Today — training insights ═══════════════════════════════════════════ */

.ins-head {
  display: flex; align-items: center; justify-content: space-between;
  margin: 26px 2px 14px;
}
.ins-head .seg button { padding: 8px 13px; font-size: 11px; }

.ins-open {
  display: flex; align-items: center; gap: 7px;
  border: none; background: none; padding: 4px 2px; cursor: pointer;
  font: 400 8px/1 var(--mono); letter-spacing: .16em; color: rgba(236,239,244,.55);
  transition: color .16s;
}
.ins-open span { font-family: var(--sans); font-size: 14px; line-height: 1; }
.ins-open:hover { color: var(--ink); }

.card-divide {
  margin-top: 26px; padding-top: 24px;
  border-top: 1px solid rgba(255,255,255,.07);
}

/* volume per day, in the insights window */
.volbars { display: flex; align-items: flex-end; gap: 3px; height: 76px; }
.volbars i {
  flex: 1; display: block; border-radius: 2px 2px 0 0;
  background: linear-gradient(180deg, rgba(236,239,244,.5), rgba(236,239,244,.04));
}

/* Four numbers in one even row: equal columns, each centred on its own axis, so
   the group is symmetrical instead of a 2×2 block of air. Martian Mono runs
   wide, hence 16px with the tracking pulled in and one-glyph units. */
.ins-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  align-items: start;
}
.ins-stat { min-width: 0; text-align: center; }
.ins-stat .tile-l { font-size: 7.2px; letter-spacing: .1em; }
.ins-stat .tile-l em { font-style: normal; margin-left: 4px; color: rgba(236,239,244,.26); }
.ins-v {
  font: 200 16px/1 var(--mono);
  letter-spacing: -.03em;
  margin: 9px 0 6px;
  white-space: nowrap;
}
.ins-v small {
  font-size: 9px; font-weight: 300;
  color: rgba(236,239,244,.4);
  letter-spacing: 0;
  margin-left: 1px;
}
.ins-d { font: 400 7.2px/1 var(--mono); letter-spacing: .06em; }

/* below ~360px the four columns get too tight for the labels */
@media (max-width: 359px) {
  .ins-stats { grid-template-columns: repeat(2, 1fr); gap: 18px 10px; }
}

.ins-line {
  margin: 16px 0 0;
  font-size: 12.5px; line-height: 1.5; color: rgba(236,239,244,.62);
}
.ins-legend {
  display: flex; flex-wrap: wrap; gap: 10px 14px; margin-top: 12px;
  font: 400 7.8px/1 var(--mono); letter-spacing: .12em; color: var(--ink-3);
}
.ins-legend span { display: flex; align-items: center; gap: 6px; }
.ins-legend i { width: 7px; height: 7px; border-radius: 2px; display: block; flex: none; }

.ins-chips { display: flex; gap: 8px; margin-top: 14px; }
.ins-chip {
  border-radius: 999px; padding: 7px 13px;
  border: 1px solid rgba(255,255,255,.12);
  font: 400 8px/1 var(--mono); letter-spacing: .14em; color: var(--ink-3);
}
.ins-chip b { font-weight: 400; color: var(--ink); }

/* ── consistency: the current week as seven bars ──────────────────────────
   Graphite gradients, hairlines, no hue except today. Same instrument as the
   sleep stage bars and the load chart, one week wide. */
.wk { --wk-cols: repeat(7, 1fr); }
.wk-vals, .wk-labels, .wk-tracks { display: grid; grid-template-columns: var(--wk-cols); gap: 7px; }

.wk-vals { align-items: end; margin-bottom: 9px; }
.wk-v {
  text-align: center;
  font: 400 8px/1 var(--mono); letter-spacing: .06em; color: rgba(236,239,244,.38);
}
.wk-v.now { color: var(--starship); }
.wk-v.gone { color: rgba(236,239,244,.22); text-decoration: line-through; }

.wk-tracks {
  position: relative;
  align-items: end;
  border-bottom: 1px solid rgba(255,255,255,.09);          /* the baseline */
}
.wk-t {
  position: relative;
  display: flex; align-items: flex-end; justify-content: center;
  height: 100%;
  border-left: 1px solid rgba(255,255,255,.035);           /* faint column guides */
}
.wk-t:last-child { border-right: 1px solid rgba(255,255,255,.035); }
.wk-t.col-now { background: linear-gradient(180deg, rgba(231,254,85,.055), transparent 82%); }

/* the week's average load, as a dashed hairline across all seven days */
.wk-avg {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 1px dashed rgba(236,239,244,.16);
  pointer-events: none;
}

.wk-bar { width: 100%; display: block; box-sizing: border-box; border-radius: 3px 3px 0 0; }
/* done: a beam of light fading into the graphite */
.wk-bar.fill { background: linear-gradient(180deg, rgba(236,239,244,.62), rgba(236,239,244,.05)); }
/* today: hollow, outlined in the one accent colour, with a lit cap */
.wk-bar.now {
  border: 1px solid rgba(231,254,85,.5);
  border-bottom: none;
  background: linear-gradient(180deg, rgba(231,254,85,.16), transparent);
  box-shadow: inset 0 1px 0 var(--starship), 0 0 12px -2px rgba(231,254,85,.45);
}
/* still to come: hollow, dashed */
.wk-bar.todo { border: 1px dashed rgba(236,239,244,.2); border-bottom: none; }
/* missed: dotted and empty */
.wk-bar.gone { border: 1px dotted rgba(236,239,244,.16); border-bottom: none; }
/* rest: a flat cap on the baseline */
.wk-bar.flat { height: 2px; background: rgba(236,239,244,.13); border-radius: 2px; }

.wk-labels { margin-top: 10px; }
.wk-l {
  text-align: center;
  font: 400 7.8px/1 var(--mono); letter-spacing: .14em; color: var(--ink-4);
}
.wk-l.now { color: var(--ink); }

/* pattern split + per-muscle set counts */
.split { display: flex; height: 8px; border-radius: 5px; overflow: hidden; background: rgba(255,255,255,.06); }
.split i { display: block; height: 8px; }

.mrows { display: flex; flex-direction: column; gap: 9px; margin-top: 18px; }
.mrow { display: flex; align-items: center; gap: 12px; }
.mrow .n { flex: none; width: 92px; font: 400 8.6px/1.3 var(--mono); letter-spacing: .1em; color: rgba(236,239,244,.6); }
.mrow .b { flex: 1; height: 5px; border-radius: 3px; background: rgba(255,255,255,.06); overflow: hidden; }
.mrow .b i { display: block; height: 5px; border-radius: 3px; }
.mrow .s { flex: none; font: 400 9.5px/1 var(--mono); color: var(--ink-3); min-width: 16px; text-align: right; }
.mrow.rec .n { width: auto; flex: 1; }
.mrow.rec .s { color: var(--ink); }
.mrow.rec .s small { font-size: 9px; color: rgba(236,239,244,.45); }
.mrow.rec .g {
  flex: none; min-width: 34px; text-align: right;
  font: 400 9px/1 var(--mono); color: var(--starship);
}
.mrow.rec .g.flat { color: rgba(236,239,244,.3); }

/* ═══ Train ═══════════════════════════════════════════════════════════════ */

.train {
  position: relative;
  min-height: 100%;
  display: flex; flex-direction: column;
  padding: 6px 6px 0;
}
.train-top {
  display: flex; align-items: baseline; justify-content: space-between;
  font: 300 9.5px/1 var(--mono); letter-spacing: .2em; color: var(--ink-3);
}
/* Reads as the label it replaces, not as a button parked on top of one. The
   chevron is dimmer than the name so the eye still lands on the session. */
.train-min {
  background: none; border: 0; padding: 4px 10px 4px 0; margin: -4px 0;
  font: inherit; letter-spacing: inherit; color: inherit;
  cursor: pointer; transition: color .16s;
}
.train-min:hover { color: var(--ink-2); }
.train-min:active { color: var(--ink); }
.big-wrap { display: flex; flex-direction: column; align-items: center; margin-top: 28px; }
.big-label { font: 300 9px/1 var(--mono); letter-spacing: .24em; color: rgba(236,239,244,.4); margin-top: 20px; }
/* the design's session screen has no tab bar; this one does, so the body map
   gives back the height the nav takes */
.train .mm { height: 186px; margin-top: 10px; }
.train .spacer { flex: 1; min-height: 12px; }

/* ── session mode: the screen stops scrolling ───────────────────────────────
   A set is taken with a bar in your hands. Scrolling to find the Log button, or
   to check which set you are on, is the one interaction the room does not allow
   — so while a session is live the whole thing fits, and the tab bar goes with
   it. That is 128px of clearance released, which is most of what makes it fit.

   The trade: there is no way to another tab until the session ends. That is the
   same bargain Apple's Workout app and every run tracker make, and the two ways
   out of here — the X, and the header that opens the lift list — are both on
   screen. */
.frame.session .tabbar {
  transform: translateY(calc(100% + max(24px, env(safe-area-inset-bottom))));
  opacity: 0;
  pointer-events: none;
}
.frame.session .screen { overflow: hidden; padding-bottom: 20px; }
.frame.session .train { height: 100%; }

/* What gives, and in what order. The hero holds the ruler and the Log button,
   so it never shrinks — it only grows into space that is going spare. The body
   map is the piece that can lose height without losing its job: at 88px it is
   still legibly a body with lit muscles. Everything else is fixed. */
.frame.session .train .mm { height: auto; flex: 0 1 186px; min-height: 88px; }
.frame.session .train .spacer { flex: 0 0 12px; }
.frame.session .train .hero { flex: 1 0 auto; }

/* Shorter phones — an SE is 68px short of the above. Taken out of the gaps in
   the ruler stack rather than out of the controls themselves, so every tap
   target keeps its size. */
@media (max-height: 700px) {
  .frame.session .train .mm { min-height: 56px; }
  .frame.session .train .ruler-head { margin-top: 12px; }
  .frame.session .train .ruler-wrap,
  .frame.session .train .ruler-foot { margin-top: 8px; }
  .frame.session .train .set-dots { margin-top: 10px; }
  .frame.session .train .hero > .btn { margin-top: 12px !important; }
  .frame.session .train .end-x-wrap { margin-top: 6px; }
}
.train-foot { text-align: center; font-size: 12px; color: rgba(236,239,244,.35); margin: 16px 0 4px; }
.train-foot button {
  border: none; background: none; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-decoration: underline; text-underline-offset: 3px;
}
.train-foot button:hover { color: var(--ink-2); }

.set-dots { display: flex; align-items: center; gap: 6px; margin-top: 16px; }
.set-dots i { width: 9px; height: 9px; border-radius: 50%; box-sizing: border-box; display: block; }
.set-dots .n { margin-left: auto; font: 300 9px/1 var(--mono); letter-spacing: .14em; color: rgba(255,255,255,.5); }

.rest-track { height: 3px; border-radius: 2px; background: rgba(255,255,255,.12); margin-top: 22px; overflow: hidden; }
.rest-track i {
  display: block; height: 3px; border-radius: 2px; background: var(--starship);
  transform-origin: left center;
  animation-name: fmRestBar;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
  /* duration = the full rest, and a negative delay jumps it to where the timer
     actually is — so it stays correct after a reload mid-rest */
}

.hero-divide { margin-top: 20px; padding-top: 18px; border-top: 1px solid rgba(255,255,255,.14); }

.stat3 { display: grid; grid-template-columns: repeat(3,1fr); margin-top: 20px; }
.stat3 .v { font: 200 22px/1 var(--mono); }
.stat3 .v small { font-size: 11px; color: rgba(255,255,255,.5); }
.stat3 .l { font: 300 7.6px/1 var(--mono); letter-spacing: .16em; color: rgba(255,255,255,.5); margin-top: 7px; }
.stat3 > :nth-child(2) { text-align: center; }
.stat3 > :nth-child(3) { text-align: right; }

/* the ruler control — Set entry, wired live */
.ruler-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-top: 22px; }
.ruler-head button {
  background: none; border: none; padding: 0; cursor: pointer;
  display: flex; align-items: flex-end; gap: 7px;
  transition: opacity .15s;
}
.ruler-head button:hover { opacity: .85; }
.ruler-head .v {
  font: 200 44px/1 var(--mono); letter-spacing: -.03em; color: #fff;
  border-bottom: 2px solid transparent; padding-bottom: 4px;
  transition: border-color .2s;
}
.ruler-head .reps .v { font-size: 30px; }
.ruler-head .u { font: 300 11px/1 var(--mono); letter-spacing: .14em; color: rgba(255,255,255,.5); padding-bottom: 10px; transition: color .2s; }
.ruler-head .reps .u { padding-bottom: 7px; }
.ruler-head button[aria-selected="true"] .v { border-bottom-color: var(--starship); }
.ruler-head button[aria-selected="true"] .u { color: var(--starship); }

.ruler-wrap { position: relative; margin-top: 14px; }
/* The window. Not a scroller any more — see wheel() in screen-train.js for
   why the browser's own scrolling had to go. touch-action:none is what makes
   that possible: it stops iOS claiming the horizontal gesture before the first
   pointermove arrives. */
.ruler {
  overflow: hidden;
  -webkit-mask: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
  mask: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
  cursor: grab;
  touch-action: none;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.ruler.grabbing { cursor: grabbing; }
/* The padding is what puts tick 0 under the needle, so translateX(-i * 26px)
   centres tick i with no further arithmetic. */
.ruler-track {
  display: flex;
  padding: 0 calc(50% - 13px);
  will-change: transform;
}
.ruler .t { flex: none; width: 26px; display: flex; flex-direction: column; align-items: center; gap: 7px; }
.ruler .t i { width: 1.5px; border-radius: 1px; display: block; }
.ruler .t span { font: 300 8px/1 var(--mono); color: rgba(255,255,255,.4); height: 9px; }
.ruler-ghost { position: absolute; top: -2px; width: 1.5px; height: 32px; margin-left: -.75px; background: rgba(255,255,255,.45); pointer-events: none; }
.ruler-ghost-l { position: absolute; top: -14px; transform: translateX(-50%); font: 300 7px/1 var(--mono); letter-spacing: .12em; color: rgba(255,255,255,.45); pointer-events: none; white-space: nowrap; }
.ruler-now { position: absolute; left: 50%; top: -6px; width: 2px; height: 40px; margin-left: -1px; background: var(--starship); box-shadow: 0 0 14px rgba(231,254,85,.9); pointer-events: none; }
.ruler-now-cap { position: absolute; left: 50%; top: -12px; width: 0; height: 0; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 7px solid var(--starship); pointer-events: none; }
.ruler-foot { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
.ruler-foot .mid { flex: 1; text-align: center; }
.ruler-foot .last { font: 300 7.6px/1 var(--mono); letter-spacing: .16em; color: rgba(255,255,255,.4); }
.ruler-foot .delta { font: 300 8.6px/1 var(--mono); letter-spacing: .16em; margin-top: 7px; }

.lift-list { display: flex; flex-direction: column; }
.lift {
  display: flex; align-items: center; gap: 13px;
  padding: 13px 0;
  border-bottom: 1px solid rgba(255,255,255,.07);
  border-radius: 0;
  background: none; border-left: none; border-right: none; border-top: none;
  width: 100%; text-align: left; cursor: pointer; font: inherit;
}
.lift:last-child { border-bottom: none; }
.lift .i { width: 26px; font: 400 9.5px/1 var(--mono); color: var(--ink-4); flex: none; }
.lift .n { flex: 1; font-size: 13px; font-weight: 600; color: rgba(236,239,244,.85); }
.lift .s { font: 400 10px/1 var(--mono); color: var(--ink-3); }
.lift .d { width: 8px; height: 8px; border-radius: 50%; flex: none; box-sizing: border-box; }
.lift.on {
  border-radius: 40px; padding: 15px 18px; margin: 4px -18px;
  background: rgba(231,254,85,.08);
  border: 1px solid rgba(231,254,85,.3);
}
.lift.on .i { color: var(--starship); }
.lift.on .n { font-weight: 700; color: var(--ink); }
.lift.on .s { color: var(--starship); }
.lift.done .n { color: rgba(236,239,244,.5); }
.lift.rest .n, .lift.rest .s { color: var(--ink-4); }

/* ═══ Coach ═══════════════════════════════════════════════════════════════ */

/* the composer sits at the bottom of the phone even when the chat is short */
.coach { display: flex; flex-direction: column; min-height: 100%; }
.chat { display: flex; flex-direction: column; gap: 12px; flex: 1; }
.bub {
  max-width: 88%;
  border-radius: 40px;
  padding: 18px 24px;
  font-size: 13px; line-height: 1.55;
  animation: fmRise .3s cubic-bezier(.2,.7,.3,1) both;
}
.bub.me {
  align-self: flex-end; max-width: 80%;
  padding: 16px 22px;
  background: rgba(69,123,241,.24);
  border: 1px solid rgba(140,175,255,.24);
  line-height: 1.5;
}
.bub.ai {
  align-self: flex-start;
  background: linear-gradient(180deg, rgba(255,255,255,.07), rgba(255,255,255,.022));
  border: 1px solid var(--glass-line);
  color: rgba(236,239,244,.88);
}
.bub.ai .who { display: flex; align-items: center; gap: 7px; margin-bottom: 9px; }
.bub.ai .who i { width: 6px; height: 6px; border-radius: 50%; background: var(--starship); box-shadow: 0 0 8px rgba(231,254,85,.8); display: block; }
.bub.ai .who span { font: 400 8.2px/1 var(--mono); letter-spacing: .14em; color: var(--ink-3); }
.bub.ai.typing .who i { animation: fmDotWave 1.6s ease-in-out infinite; }
.caret { opacity: .4; animation: fmBlink 1s steps(1) infinite; }

.chat-card {
  align-self: flex-start;
  width: 88%;
  border-radius: 52px;
  padding: 22px 26px;
  background: var(--hero-bg);
  border: 1px solid rgba(140,175,255,.22);
  box-shadow: inset 0 0 54px 18px rgba(69,123,241,.36);
  animation: fmRise .3s cubic-bezier(.2,.7,.3,1) both;
}
.chat-card .cc-head {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px;
  font: 300 8.6px/1 var(--mono); letter-spacing: .16em; color: rgba(255,255,255,.6);
}
.chat-card .cc-head b { font-weight: 300; letter-spacing: 0; color: var(--starship); }
.cc-bars { display: grid; grid-template-columns: repeat(7,1fr); gap: 5px; align-items: end; height: 60px; }
.cc-bars i { border-radius: 3px; display: block; }
.chat-card .cc-foot { font: 400 8.2px/1 var(--mono); letter-spacing: .1em; color: rgba(255,255,255,.45); margin-top: 12px; }

.chips { display: flex; gap: 7px; margin: 18px 0 12px; flex-wrap: wrap; }

.composer {
  display: flex; align-items: center; gap: 12px;
  border-radius: 44px;
  padding: 8px 8px 8px 22px;
  background: linear-gradient(180deg, rgba(255,255,255,.075), rgba(255,255,255,.026));
  border: 1px solid rgba(255,255,255,.12);
}
.composer input {
  flex: 1; min-width: 0;
  border: none; background: transparent; outline: none;
  font: 400 13px var(--sans); color: var(--ink);
  padding: 6px 0;
}
.composer input::placeholder { color: rgba(236,239,244,.4); }
.composer .send {
  width: 44px; height: 44px; flex: none;
  border: none; border-radius: 50%;
  background: var(--starship);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: filter .16s, transform .12s;
}
.composer .send:hover { filter: brightness(1.06); }
.composer .send:active { transform: scale(.94); }
.composer .send i { width: 10px; height: 10px; border-radius: 2px; background: #0B0D07; display: block; }

/* ═══ Plan ════════════════════════════════════════════════════════════════
   Week first, with a day selected, and that day's plan underneath. */

.plan-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  margin-bottom: 14px;
}
.plan-nav { display: flex; gap: 8px; flex: none; }
.plan-label {
  display: flex; align-items: center; gap: 9px;
  border: none; background: none; padding: 0; margin-top: 7px;
  font-size: 25px; font-weight: 600; letter-spacing: -.02em;
  color: var(--ink); cursor: pointer;
}
.plan-label .caret {
  font-size: 11px; line-height: 1; color: var(--ink-3);
  transition: transform .22s cubic-bezier(.2,.7,.3,1);
}
.plan-label[aria-expanded="true"] .caret { transform: rotate(180deg); color: var(--starship); }

.jump {
  display: block; margin: 0 0 12px;
  font: 400 7.6px/1 var(--mono); letter-spacing: .16em;
  padding: 9px 15px;
}

.month-panel { animation: fmRise .26s cubic-bezier(.2,.7,.3,1) both; }
.icon-btn.sm { width: 28px; height: 28px; border-radius: 20px; font-size: 13px; }

/* the week as a selector — same instrument as Today's consistency read */
.dpick { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.dpick-d {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  border: none; background: none;
  padding: 8px 0 9px;
  border-radius: 20px 20px 4px 4px;
  cursor: pointer;
  transition: background .18s;
}
.dpick-d:hover { background: rgba(255,255,255,.035); }
.dpick-v { font: 400 8px/1 var(--mono); letter-spacing: .04em; color: rgba(236,239,244,.34); }
.dpick-track {
  position: relative; width: 100%; height: 64px;
  display: flex; align-items: flex-end; justify-content: center;
  border-bottom: 1px solid rgba(255,255,255,.09);
  border-left: 1px solid rgba(255,255,255,.03);
}
.dpick-l { font: 400 7.6px/1 var(--mono); letter-spacing: .14em; color: var(--ink-4); }
.dpick-n { font: 400 10px/1 var(--mono); color: rgba(236,239,244,.45); }

.dpick-d.sel { background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,0) 78%); }
.dpick-d.sel .dpick-l, .dpick-d.sel .dpick-n { color: var(--ink); }
.dpick-d.sel .dpick-v { color: rgba(236,239,244,.7); }
.dpick-d.sel::after {                       /* the one lit line: what's selected */
  content: ''; position: absolute; left: 22%; right: 22%; bottom: 0;
  height: 1.5px; border-radius: 1px;
  background: var(--starship);
  box-shadow: 0 0 10px rgba(231,254,85,.55);
}
.dpick-d.today .dpick-v { color: var(--starship); }
/* keep the today wash faint — next to the dashed "planned" outlines a stronger
   tint reads as a filled bar */
.dpick-d.today .dpick-track { background: linear-gradient(180deg, rgba(231,254,85,.028), transparent 75%); }
.dpick-avg-note { margin-top: 14px; }

/* the selected day, in detail */
.day-detail { padding: 26px 30px 24px; }
.dd-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.dd-title { font-size: 19px; font-weight: 600; letter-spacing: -.015em; margin-top: 9px; }
.day-detail .stat3 { margin-top: 22px; }
.dd-list { margin-top: 22px; }
.dd-list .lift { padding: 11px 0; cursor: default; }
.dd-list .lift .i { width: 20px; }
.dd-list .dd-kg { min-width: 46px; text-align: right; color: rgba(236,239,244,.55); }
.dd-say { margin-top: 20px; }
.dd-acts { margin-top: 24px; }
.dd-put { margin: 0 0 10px; }
.dd-opts { display: flex; flex-wrap: wrap; gap: 7px; }

/* The week card's one contextual action. It reads as a row leading somewhere,
   not as another technical badge competing with the training data. */
.plan-add {
  appearance: none;
  cursor: pointer;
  width: 100%;
  min-height: 60px;
  margin-top: 20px;
  padding: 10px 14px;
  border-radius: 20px;
  border: 1px solid rgba(140,175,255,.16);
  background: rgba(63,99,184,.08);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.055);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ink);
  text-align: left;
  transition: background .18s cubic-bezier(.23,1,.32,1),
              border-color .18s cubic-bezier(.23,1,.32,1),
              scale .16s cubic-bezier(.23,1,.32,1);
}
.plan-add:hover { background: rgba(63,99,184,.12); border-color: rgba(140,175,255,.24); }
.plan-add:active { scale: .985; }
.plan-add-icon {
  position: relative;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 11px;
  background: rgba(140,175,255,.1);
  border: 1px solid rgba(140,175,255,.18);
}
.plan-add-icon i { position: absolute; display: block; border-radius: 1px; background: #9BB8FF; }
.plan-add-icon i:first-child { width: 12px; height: 1.5px; left: 9px; top: 14.5px; }
.plan-add-icon i:last-child { width: 1.5px; height: 12px; left: 14.5px; top: 9px; }
.plan-add-copy { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.plan-add-copy strong { font: 600 13.5px/1.2 var(--sans); letter-spacing: -.01em; }
.plan-add-copy small {
  color: rgba(236,239,244,.38);
  font: 400 7.8px/1 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.plan-add-arrow {
  flex: none;
  width: 7px;
  height: 7px;
  margin-right: 3px;
  border-top: 1.5px solid rgba(185,206,255,.48);
  border-right: 1.5px solid rgba(185,206,255,.48);
  transform: rotate(45deg);
}

.badge {
  flex: none;
  font: 400 7.4px/1 var(--mono); letter-spacing: .16em;
  padding: 7px 11px; border-radius: 999px;
  border: 1px solid rgba(255,255,255,.14);
  color: var(--ink-3);
  white-space: nowrap;
}
.badge.done { color: rgba(236,239,244,.75); border-color: rgba(255,255,255,.22); }
.badge.today { color: var(--starship); border-color: rgba(231,254,85,.42); background: rgba(231,254,85,.06); }
.badge.missed { color: #E6A594; border-color: rgba(224,82,47,.34); }


.cal-head {
  display: grid; grid-template-columns: repeat(7,1fr); gap: 4px; margin-bottom: 12px;
  font: 400 8.4px/1 var(--mono); letter-spacing: .1em; color: rgba(236,239,244,.35); text-align: center;
}
.cal { display: grid; grid-template-columns: repeat(7,1fr); gap: 4px; }
.cal .d {
  aspect-ratio: 1;
  border-radius: 16px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  box-sizing: border-box;
  border: 1px solid rgba(255,255,255,.05);
  background: none;
  cursor: pointer;
  padding: 0;
  transition: background .16s, border-color .16s;
}
.cal .d span { font: 400 10px/1 var(--mono); }
.cal .d i { height: 3px; border-radius: 2px; display: block; }
.cal .d.empty { border-color: transparent; pointer-events: none; }
.cal .d:hover:not(.empty) { background: rgba(255,255,255,.08); }
.cal .d.sel { border-color: rgba(255,255,255,.5); background: rgba(255,255,255,.07); }
.cal .d.today { background: rgba(231,254,85,.09); border: 1px solid rgba(231,254,85,.55); }
.cal .d.drag { border-color: var(--starship); border-style: dashed; background: rgba(231,254,85,.05); }
.cal-legend {
  display: flex; gap: 14px; margin-top: 14px;
  font: 400 8.2px/1 var(--mono); letter-spacing: .1em; color: rgba(236,239,244,.4);
}
.cal-legend span { display: flex; align-items: center; gap: 6px; }
.cal-legend i { width: 12px; height: 3px; border-radius: 2px; display: block; }
.cal-legend .hint { margin-left: auto; color: rgba(236,239,244,.3); }

.pill {
  font-size: 10px; font-weight: 500; color: rgba(236,239,244,.5);
  border: 1px solid rgba(255,255,255,.14); border-radius: 999px;
  padding: 2px 7px; margin-left: 6px; white-space: nowrap;
}

.tip {
  border-radius: 56px; padding: 22px 26px;
  background: linear-gradient(180deg, rgba(231,254,85,.07), rgba(255,255,255,.02));
  border: 1px solid rgba(231,254,85,.28);
  display: flex; align-items: flex-start; gap: 9px;
}
.tip p { margin: 0; font-size: 12.5px; line-height: 1.55; color: rgba(236,239,244,.78); }
.tip .acts { display: flex; gap: 8px; margin-top: 14px; }

/* ═══ Fuel ════════════════════════════════════════════════════════════════ */

.macro { display: flex; align-items: center; gap: 18px; }
.macro-bars { flex: 1; display: flex; flex-direction: column; gap: 12px; }
.mb-l { display: flex; justify-content: space-between; font: 400 8.4px/1 var(--mono); letter-spacing: .12em; color: var(--ink-3); margin-bottom: 7px; }
.mb-t { height: 4px; border-radius: 3px; background: rgba(255,255,255,.1); overflow: hidden; }
.mb-t i { display: block; height: 4px; border-radius: 3px; transition: width .5s cubic-bezier(.2,.7,.3,1); }

.meal {
  display: flex; align-items: center; gap: 13px;
  padding: 13px 0;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.meal:last-of-type { border-bottom: none; }
.meal .t { width: 34px; font: 400 9.5px/1 var(--mono); color: var(--ink-4); flex: none; }
.meal .n { flex: 1; font-size: 13px; font-weight: 600; color: rgba(236,239,244,.85); }
.meal .n small { display: block; font: 400 8.6px/1 var(--mono); letter-spacing: .1em; color: var(--ink-4); margin-top: 6px; font-weight: 400; }
.meal .k { font: 400 10px/1 var(--mono); color: var(--ink-3); }
.meal .x { border: none; background: none; color: var(--ink-4); cursor: pointer; font-size: 15px; line-height: 1; padding: 4px; }
.meal .x:hover { color: var(--ink-2); }

/* ═══ sheet ═══════════════════════════════════════════════════════════════ */

.sheet-wrap { position: absolute; inset: 0; z-index: 5; display: flex; align-items: flex-end; }
/* MUST outrank the rule above: `display:flex` on a class beats the browser's
   [hidden]{display:none}, which would leave the scrim over the whole app. */
.sheet-wrap[hidden] { display: none; }
.sheet-scrim { position: absolute; inset: 0; background: rgba(4,5,8,.62); backdrop-filter: blur(3px); border: none; }
.sheet {
  position: relative;
  width: 100%;
  border-radius: 54px 54px 0 0;
  padding: 26px 30px calc(30px + max(0px, env(safe-area-inset-bottom)));
  background: #0B0D13;
  border: 1px solid rgba(255,255,255,.12);
  border-bottom: none;
  box-shadow: 0 -20px 60px -20px rgba(0,0,0,.9);
  animation: fmSheet .3s cubic-bezier(.2,.8,.25,1) both;
  max-height: 86%;
  overflow-y: auto;
  scrollbar-width: none;
}
.sheet::-webkit-scrollbar { display: none; }
.sheet h3 { margin: 0 0 4px; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.sheet .sub { font: 400 8.6px/1 var(--mono); letter-spacing: .14em; color: var(--ink-3); margin-bottom: 20px; }
.sheet-opts { display: flex; flex-direction: column; gap: 8px; }
.sheet-opt {
  display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left;
  min-height: 52px;
  border-radius: 20px; padding: 12px 16px;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.12);
  cursor: pointer;
  font: 600 13px var(--sans); color: var(--ink);
  transition: background .16s;
}
.sheet-opt:hover { background: rgba(255,255,255,.1); }
.sheet-opt.on { background: rgba(231,254,85,.09); border-color: rgba(231,254,85,.4); }
.sheet-opt .s { margin-left: auto; font: 400 9.5px/1 var(--mono); color: var(--ink-3); font-weight: 400; }

/* ── a lift's state, at the left where the eye starts ───────────────────────
   The list used to carry a bare position number and a tick at the far right,
   which meant reading the whole row to find out whether a lift was finished —
   and the tick sat in the same slot as the chevron, so "done" and "openable"
   were the same mark in the same place.

   State moves to the front and becomes one object with three readings:

     ring + number   not started
     lime ring       part-way, some sets banked
     lime disc       finished

   The dots underneath say how far in, in the same language the live card uses
   for the set you are on, so the list and the workout agree. The chevron at the
   right goes back to meaning only "this opens". */
.lift-mark {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  box-sizing: border-box;
  border: 1px solid rgba(255,255,255,.18);
  font: 400 9.5px/1 var(--mono); color: var(--ink-3);
  transition: background .18s, border-color .18s, color .18s;
}
.lift-mark.part { border-color: rgba(231,254,85,.55); color: var(--starship); }
.lift-mark.done {
  border-color: var(--starship); background: var(--starship); color: #0B0D07;
  font-size: 11px; font-weight: 600;
}

.lift-dots { display: inline-flex; align-items: center; gap: 4px; margin-right: 9px; vertical-align: -1px; }
.lift-dots i {
  width: 5px; height: 5px; border-radius: 50%; box-sizing: border-box; display: block;
  border: 1px solid rgba(255,255,255,.28);
}
/* banked, and the one you are on — the same two states the set dots use */
.lift-dots i.on { background: var(--starship); border-color: var(--starship); }
.lift-dots i.now { border-color: var(--starship); }

/* ── a row being carried ────────────────────────────────────────────────────
   The lift is small — 2.5% and a shadow. It has to read as picked up without
   becoming a different object, because it is going to be set back down two rows
   away and the eye has to follow it the whole way.

   The shadow is black rather than grey: the sheet it floats over is #0B0D13,
   and a neutral shadow on a near-black ground reads as fog rather than height.

   touch-action goes to none only once a row is actually held. Before that the
   list has to stay scrollable, which is the whole reason the gesture starts
   with a hold instead of with movement.

   That switch is not what holds the sheet still, though, and it never could
   be: the browser reads touch-action when the gesture begins, so a value set
   260ms in arrives too late to change who owns the finger. The rule below is
   kept for the gestures that start after a drag, and the scroll during one is
   called off by the non-passive touchmove in mountLifts. Rows declare pan-y at
   rest so vertical scrolling is all the browser is ever entitled to claim
   here — never a pinch or a double-tap zoom in the middle of a reorder. */
/* iOS treats a long press on text as "select this word", so the gesture that
   picks a row up was also starting a selection — blue highlight, grab handles,
   and the callout menu, all fighting the drag. Suppressed on the rows only, not
   on the sheet, so text elsewhere stays selectable.

   It is set on the rows at rest rather than added when the drag starts: by the
   time the 260ms hold has elapsed iOS has already decided a selection is
   happening, and taking the property away afterwards does not call it off. */
.sheet-opts .sheet-opt,
.sheet-opts .sheet-opt * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

.sheet-opts .sheet-opt { touch-action: pan-y; }
.sheet-opts.reordering { touch-action: none; }
.sheet-opts.reordering .sheet-opt { transition: none; }
.sheet-opt.lifted {
  position: relative; z-index: 2;
  background: rgba(255,255,255,.12);
  border-color: rgba(255,255,255,.22);
  scale: 1.025;
  box-shadow: 0 18px 40px -12px rgba(0,0,0,.8);
  cursor: grabbing;
}

.field { margin-bottom: 12px; }
.field label { display: block; font: 400 8.4px/1 var(--mono); letter-spacing: .14em; color: var(--ink-3); margin-bottom: 9px; }
.field input, .field select {
  width: 100%;
  border-radius: 30px;
  padding: 15px 20px;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.12);
  color: var(--ink);
  font: 500 14px var(--sans);
  outline: none;
}
.field input:focus, .field select:focus { border-color: rgba(231,254,85,.45); }
.field-row { display: flex; gap: 10px; }
.field-row .field { flex: 1; }

.empty {
  text-align: center; padding: 40px 20px;
  font-size: 12.5px; line-height: 1.5; color: var(--ink-4);
}
