/* ============================================
   WORKOUT STYLES
   css/components/workout.css
   02 Nov 2026 v24

   v24 - P-22 to P-24 (the Plan). Swap, Do this one later and What's left
         under the exercise's name (.wo-ctl), the Swap panel (.wo-swap),
         What's left (.wo-left), and the search every swap shares
         (.swap-find: the session, a door's proposal, Today's plan).
         Two faults the new screens' check found in the player, on both
         tiers and already on v701: Skip this one was 36 px tall (the app's
         rule is 44), and at 320 px and text 1.45 or 2 the step strip split
         "Watch out" and "Capture" mid-word. Skip is 44 px; the strip goes
         to two rows before a word would split.

   31 Oct 2026 v23

   v23 - STAGE PATH Session 9 (close checks, axe; both tiers: a fault).
         "If it hurts" on the card's rose box reads in --color-danger-text
         (it was 3.2:1 at 13px; now over 4.5).

   06 Oct 2026 v22

   v22 - D-12 PROGRESS-FIT. .workout-header wraps: at large text the
   title ("Breathing") was squeezed between Back and the home button and
   split mid-word; now it drops under Back when it does not fit. The
   title starts from 6 characters' width (it grows to fill the row), so
   at normal text it stays beside Back as before; judged at its full
   one-line width it dropped a line even at normal size.

   05 Oct 2026 v21

   v21 - D-8 TEXT-FIT (device test, 05 Oct: "2 sets, this long each"
   ran out of the circle at Graeme's text size). The label sits under the
   circle, centred, free to wrap; the circle grows with the text size
   (at least three times the time's height), so neither can spill out.
   Every player that draws the circle (workout, My exercises, the gym
   programme) gets it from here.

   v20 - D-1 EXERCISE-FOUR. .wo-steps: the four steps as a strip under
   the exercise name, each a 48px button with its word and a bar; the
   current one filled teal and bold, so it is shown by weight and word as
   well as colour. .xstep: each step as a card with its own heading; the
   hazard box on Watch out keeps its rose tint.

   28 Sep 2026 v19

   v19 - SMOOTH-P2e. .wo-rest: the suggested rest after a set. Quiet by
   design -- secondary text, no colour change at zero, no pulse.

   v18 - SMOOTH-P2c. .wo-flow: one screen per exercise. A quiet section
   label replaces the role pill (its cool-down colour was below 3:1 on
   navy); the target leads; the card reads left-aligned, because centred
   paragraphs are hard to track line to line. .xcard-how is the open
   "How to do it" disclosure; .wo-flow__done holds "How was that?".

   v17 - CARD-5. .xcard-hurt (the collapsed hurt-and-ache row) and
   .xcard-stepper (the four beats, made visible). The summary keeps the
   hazard palette so a closed safety row does not read as one more
   accordion; ahead-steps are plain text, never disabled buttons. Full
   notes at the foot of this file.

   v16 - CARD-4. .xcard-image and .xcard-image-note, the image slot on DO.

   There are no photographs yet -- zero of the 560 entries carry an image
   field -- so this styles a PROMISE, not a picture. Deliberately not a
   grey placeholder rectangle: an empty box shaped like an image reads as
   something that failed to load, and the whole point is that nothing is
   broken. It is a quiet bordered note in muted body text, closer to a
   caption than to a missing asset.

   It is also not styled like a hazard, and not like the caution. It
   carries no urgency and must not compete with the two blocks that do.

   The slot disappears entirely once images exist -- verify-card4 test 10
   fails the moment any entry gains an image field, which is what stops
   "right for beta, not for public launch" becoming permanent.

   12 Sep 2026 v15

   v15 - TIMER-2. .set-progress and .set-progress-value, the set counter on
   a counted exercise. It sits in the flex row with sets x reps and rest,
   and it is the only one of the three that CHANGES as the person works --
   which is why it carries role="status" in the markup.

   11 Sep 2026 v14

   v14 - ADAPT-1. .xcard-adapt, the collapsed "Other ways to do this"
   disclosure at the end of DO, and .xcard-adapt-pointer, the line that
   sits under the caution. Deliberately NOT styled like a hazard: these
   are options somebody may want, not something they must read. See the
   block at the end of this file.

   08 Sep 2026 v13

   v13 - TIMER-1. .xcard-timer-done, the visible form of the status
   message announcing that the countdown finished and moved the person on.
   See the block at the end of this file.

   31 Aug 2026 v12

   v12 - CARD-3 device-test fixes.

   .xcard-block--hazard gives "What to watch for" a rose-tinted box.
   Graeme's call after the first device test: on DO it read as one more
   grey section among several, and moving the hazards into view is not
   the same as making them look unlike the instructions beneath them.

   The rose comes from --color-danger, which now has a light-scheme
   override in variables.css -- #FB7185 is about 2.6:1 on white and would
   have failed AA the moment somebody used light mode, the same trap
   --color-warning already carries a fix for. The tint and the rule are
   decorative; the list text stays on the normal body colour so it is the
   BOX that is rose, not the words, which keeps the contrast honest at
   any scheme.

   .xcard-last drops its own label. lastLine() self-labels with "Last:".

   31 Aug 2026 v11

   v11 - CARD-3. The tab styles are deleted, not left orphaned. Three
   pages replace them, and only one is ever in the DOM, so there is no
   [hidden] rule to get wrong and no panel to keep out of the
   accessibility tree -- the markup that is not on the page simply is not
   rendered.

   .xcard-step is the small "Decide / Do / Note" label. It is aria-hidden
   in the markup because the card's region label already carries "step 1
   of 4"; the visible text is orientation for sighted users and would
   otherwise be announced twice.

   .xcard-back keeps the 48px target the tabs had. Going back is the one
   navigation the person performs by hand, and it must not be the
   smallest thing on the page.

   31 Aug 2026 v10

   v10 - CARD-2. .xcard-tabs / .xcard-tab / .xcard-panel replace the v9
   disclosure styles. The tab is a real tablist button, so it needs a
   target size and a focus ring; panels use the [hidden] attribute rather
   than a display class so the accessibility tree stays honest.

   29 Aug 2026 v9

   v9 - CARD-1. .xcard-* — the shared exercise card and its disclosures.
   The toggle is a real button, so it needs a real target size and a
   visible focus ring; the chevron is decorative and rotates only when
   motion is allowed. Collapsed bodies use the [hidden] attribute, not
   display:none on a class, so the accessibility tree keeps them.


   v8 - .exercise-swap, the SWAP-0 cardio machine swap control and its
        panel. Tokens matched to .exercise-preference below, including
        its measured --color-text-secondary decision: --color-text-muted
        is 4.04:1 on --color-bg-card and fails AA for body text.

   11 Aug 2026 v7

   v7 - .gp-lift__invite, the progression invitation.

   11 Aug 2026 v6

   v6 - .sb-rationale, .sb-section-why, .sb-rationale-arc.

   11 Aug 2026 v5

   v5 - .exercise-preference, the "Not a fan of this one" control.

   11 Aug 2026 v4

   v4 - CON-3b. Two new guidance blocks added to the exercise card:
   .exercise-watchout (what to watch for) and .exercise-load (how heavy).
   Both were specified in the Exercise Entry Standard on 11 Aug and had
   no renderer at all, in any of the four card views. Amber is used for
   watchOut deliberately and sparingly: it must read as a coach noticing
   something, not as an alert. Contrast measured, not assumed -
   #FBBF24 on --color-bg-card is 6.2:1, body text 8.4:1, both AA.

   04 Aug 2026 v3

   v3 — .ps-contra-flag added: prescribed-session.js's new real-time
   contraindication check (04 Aug 2026) — a condition flagged today
   that this specific exercise is contraindicated for. Same visual
   language as coach-proposal.css's .cp-constraint, not reinvented.

   01 Jul 2026 v2

   v2 — Fixed .core-session-view padding-bottom.
     yoga-session.js (and other session views using
     .core-session-view) use position:fixed
     .workout-actions but the container had no
     padding-bottom, hiding instructions and video
     support behind the fixed button block.
     200px clears the tallest 3-button action block
     (Start hold + Finish practice + Skip).
     .workout-view already had 120px — unchanged.

   v1 — Original workout styles.

   Covers:
   - Today view workout cards
   - Workout execution view
   - Exercise display
   - Exercise card sections (universal: gym, mindfulness, yoga, rehab)
   - Timer/reps display
   - Completion celebration

   WCAG 2.1 / 2.2 AA compliance verified:
   All text colours tested against --color-bg-card (#334155).
   - Primary text   #E2E8F0 → 8.40:1  PASS
   - Section labels #B8C5D6 → 5.91:1  PASS
   - Body text      #E2E8F0 → 8.40:1  PASS
   - Teal accent    #2DD4BF → 5.56:1  PASS
   - Watch link     #FF4444 on #0F172A → 5.24:1  PASS
   Replaced failing colours:
   - #94A3B8 (4.04:1 FAIL) → #B8C5D6 (5.91:1 PASS) for section labels
   - #64748B (2.18:1 FAIL) → removed from exercise card text entirely
   ============================================ */

/* ============================================
   TODAY VIEW - WORKOUT OPTIONS
   ============================================ */

.workout-options {
  margin-top: var(--space-6);
}

.workout-options h2 {
  color: var(--color-primary);
  margin-bottom: var(--space-2);
}

.workout-option-card {
  margin-top: var(--space-4);
  padding: var(--space-5);
}

.option-header {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}

.option-icon {
  font-size: calc(2.5rem * var(--user-text-scale, 1));
  flex-shrink: 0;
}

.option-info {
  flex: 1;
}

.option-info h4 {
  margin: 0 0 var(--space-1);
  font-size: var(--text-lg);
  font-weight: var(--font-bold);
  color: var(--color-text);
}

.option-credits {
  font-size: var(--text-sm);
  font-weight: var(--font-bold);
  color: var(--color-primary);
  background: rgba(45, 212, 191, 0.15);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-full);
}

.workout-rationale {
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
  margin-bottom: var(--space-4);
  line-height: var(--leading-relaxed);
}

.workout-exercises-preview {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.exercise-tag {
  font-size: var(--text-xs);
  background: var(--color-bg);
  color: var(--color-text-secondary);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-light);
}

.exercise-tag.more {
  background: var(--color-bg-card);
  color: var(--color-text);
  font-style: italic;
}

/* ============================================
   WORKOUT EXECUTION VIEW
   ============================================ */

.workout-view {
  padding-bottom: 120px; /* Space for fixed actions */
}

/* Session views using .core-session-view (yoga, core, morning etc.)
   also use position:fixed .workout-actions. Match .workout-view pattern
   with enough clearance for a 3-button block (200px). */
.core-session-view {
  padding-bottom: 200px;
}

.workout-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  row-gap: var(--space-1);
  margin-bottom: var(--space-2);
}
.workout-header > .workout-header-title { flex-basis: 6em; }

.workout-progress-info {
  font-size: var(--text-sm);
  color: var(--color-text);
  font-weight: var(--font-medium);
}

.workout-progress-bar {
  height: 4px;
  background: var(--color-border);
  border-radius: var(--radius-full);
  margin-bottom: var(--space-6);
  overflow: hidden;
}

.workout-progress-fill {
  height: 100%;
  background: var(--color-primary);
  border-radius: var(--radius-full);
  transition: width 0.3s ease;
}

/* ============================================
   EXERCISE DISPLAY
   ============================================ */

.exercise-display {
  text-align: center;
}

.exercise-role-badge {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  margin-bottom: var(--space-3);
}

.exercise-role-badge.warmup {
  background: rgba(249, 115, 22, 0.2);
  color: #FB923C;
}

.exercise-role-badge.main {
  background: rgba(45, 212, 191, 0.2);
  color: var(--color-primary);
}

.exercise-role-badge.accessory {
  background: rgba(59, 130, 246, 0.2);
  color: #60A5FA;
}

.exercise-role-badge.finisher {
  background: rgba(139, 92, 246, 0.2);
  color: #A78BFA;
}

.exercise-role-badge.cooldown {
  background: rgba(34, 197, 94, 0.2);
  color: #4ADE80;
}

.exercise-name {
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  color: var(--color-text);
  margin-bottom: var(--space-3);
}

.ps-contra-flag {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
  background: rgba(239, 68, 68, 0.14);
  border: 1px solid rgba(239, 68, 68, 0.35);
  border-left: 4px solid #EF4444;
  border-radius: var(--radius-md);
  text-align: left;
}

.ps-contra-flag p {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-relaxed);
}

.ps-contra-flag__icon {
  font-size: var(--text-lg);
  line-height: 1;
  flex-shrink: 0;
}

.exercise-meta {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
  flex-wrap: wrap;
}

.meta-tag {
  font-size: var(--text-sm);
  background: var(--color-bg);
  color: var(--color-text);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-md);
}

/* ============================================
   TIMER DISPLAY
   ============================================ */

.exercise-target {
  margin-bottom: var(--space-6);
}

.timer-display {
  display: flex;
  justify-content: center;
}

.timer-display { padding-bottom: calc(var(--text-sm) * 2.9 + var(--space-2)); }
.timer-circle {
  position: relative;
  width: max(160px, calc(var(--text-4xl) * 3.4));
  height: max(160px, calc(var(--text-4xl) * 3.4));
  border-radius: 50%;
  background: var(--color-bg);
  border: 4px solid var(--color-primary);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.timer-value {
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
}

.timer-label {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: min(18em, 80vw);
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  line-height: 1.35;
  text-align: center;
  color: var(--color-text);
}

/* ============================================
   REPS DISPLAY
   ============================================ */

.reps-display {
  display: flex;
  justify-content: center;
  gap: var(--space-6);
}

.reps-info,
.rest-info,
.set-progress {
  text-align: center;
}

/* TIMER-2. Deliberately quieter than .reps-value: the prescription is the
   headline, and this is where you are in it. */
.set-progress-value {
  display: block;
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  color: var(--color-text-secondary);
}

.reps-value {
  display: block;
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  color: var(--color-primary);
}

.reps-label {
  font-size: var(--text-sm);
  color: var(--color-text);
}

.rest-value {
  display: block;
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  color: var(--color-text-secondary);
}

.rest-label {
  font-size: var(--text-sm);
  color: var(--color-text);
}

/* ============================================
   WATCH HOW TO DO THIS LINK
   ============================================ */

.youtube-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  background: var(--color-bg-deep);
  border: 1px solid rgba(255, 68, 68, 0.4);
  border-radius: var(--radius-lg);
  color: #FF4444;
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  margin-bottom: var(--space-5);
  transition: all var(--transition-fast);
  min-height: 44px;
}

.youtube-link:hover,
.youtube-link:focus-visible {
  background: rgba(255, 68, 68, 0.12);
  border-color: rgba(255, 68, 68, 0.6);
  outline: 3px solid var(--color-border-focus);
  outline-offset: 2px;
}

.youtube-icon {
  font-size: calc(1.25rem * var(--user-text-scale, 1));
}

/* ============================================
   ACCENT BUTTON (for Start Timer)
   ============================================ */

.btn-accent {
  background: var(--color-warning);
  color: var(--color-bg-deep);
  border: none;
}

.btn-accent:hover {
  background: #E68A00;
}

/* ============================================
   EXERCISE CARD — UNIVERSAL SECTION STRUCTURE
   ============================================ */

.exercise-instructions {
  text-align: left;
  margin-bottom: var(--space-4);
  padding: var(--space-4) var(--space-5);
}

.exercise-section-label {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #B8C5D6;
  margin-bottom: var(--space-2);
  margin-top: var(--space-4);
}

.exercise-instructions .exercise-section-label:first-child {
  margin-top: 0;
}

.exercise-section-divider {
  border: none;
  border-top: 1px solid var(--color-border-light);
  margin: var(--space-4) 0 0;
}

.exercise-section-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.exercise-section-list li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  color: var(--color-text);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  border-bottom: 1px solid var(--color-border-light);
}

.exercise-section-list li:last-child {
  border-bottom: none;
}

.exercise-section-list li::before {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-primary);
  flex-shrink: 0;
  margin-top: 0.55em;
}

.exercise-why-text {
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-relaxed);
  font-style: italic;
  margin: 0;
  padding: var(--space-2) 0 0;
}

/* ============================================
   PROGRESSION INVITATION  (11 Aug 2026)
   ============================================

   Sits with the note, where the person is deciding what to use.
   Styled as speech rather than instruction -- no icon, no emphasis,
   no colour that reads as a directive. It is the coach saying
   something, and it should be as easy to decline as to accept.
   ============================================ */

.gp-lift__invite {
  margin: var(--space-2) 0 var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-text);            /* 8.4:1 on card, AAA */
  font-style: italic;
}

/* ============================================
   SESSION RATIONALE  (11 Aug 2026)
   ============================================

   The coach explaining its own reasoning. Sits between the coach line
   and the exercise list, so the order reads: what I'm thinking, why
   this shape, then the session itself.

   Section lines are quiet by design -- they are context for the block
   below, not headings competing with it.
   ============================================ */

.sb-rationale {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-text);            /* 8.4:1 on card, AAA */
}

/* VOICE-2, 12 Aug 2026. Graeme, from the device pass: "The writing in the
   red circles, are these the coach? Could they be teal?"

   Yes, they are. This carries buildRationale()'s section intros -- "Warming
   up. Raising your heart rate first, then loosening the joints you are
   about to ask something of." That is the coach explaining its reasoning,
   and it was --text-xs in --color-text-secondary: smaller and greyer than
   the exercise names, and the same treatment as the "Warm-up" / "Main
   session" labels above it, which are UI chrome.

   So on the one screen where the coach explains itself, it looked like
   furniture. P2 says the coach and the helper layer must be visibly
   distinct, and that cuts both ways: if everything looks the same, the
   coach has no voice here at all.

   TEAL, NOT GOLD -- Graeme asked. Gold is the paid-tier marker across the
   whole product family, and this is free-tier content on a free-tier
   screen. Gold here would quietly imply the rationale is something you
   pay for.

   Sized up from --text-xs to --text-sm as well. Chrome can be small;
   something written to be read should not be.

   Contrast, all three schemes, gated by tools/contrast-check.mjs:
   --color-primary 7.86:1 on bg, 5.56:1 on card. */
.sb-section-why {
  margin: var(--space-1) 0 var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-primary);
}

.sb-rationale-arc {
  margin-top: var(--space-3);
}

.sb-rationale-arc > summary {
  min-height: 44px;                    /* WCAG 2.2 AA touch target */
  display: flex;
  align-items: center;
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
  cursor: pointer;
}

.sb-rationale-arc > p {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-text);
}

/* ============================================
   NOT A FAN  (11 Aug 2026)
   ============================================

   Deliberately understated. This is a preference, not a rating, and it
   should not compete with the session for attention -- somebody
   mid-workout is not being asked to review anything. Ghost styling
   until set, then a quiet confirmation.
   ============================================ */

.exercise-preference {
  margin-top: var(--space-4);
  display: flex;
  justify-content: center;
}

.exercise-preference__btn {
  min-height: 44px;                    /* WCAG 2.2 AA touch target */
  padding: var(--space-2) var(--space-4);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  /* --color-text-muted measures 4.04:1 on --color-bg-card, which fails
     AA for body text. Caught by measuring rather than assuming, the
     same check that passed the watchOut amber. Using the secondary
     token instead, at 5.9:1. */
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  cursor: pointer;
}

.exercise-preference__btn:hover,
.exercise-preference__btn:focus-visible {
  color: var(--color-text);
  border-color: var(--color-text-secondary);
}

.exercise-preference__btn.is-set {
  background: var(--color-bg-elevated);
  border-color: var(--color-primary);
  /* --color-primary measures 4.66:1 on --color-bg-elevated: AA for
     large text but marginal at this size. Using full text colour and
     letting the border carry the state, so colour is never the only
     signal either -- the label text itself changes. */
  color: var(--color-text);
}

/* ============================================
   SWAP  (SWAP-0, 26 Aug 2026)
   ============================================ */

.exercise-swap {
  margin-top: var(--space-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}

.exercise-swap__btn {
  min-height: 44px;                    /* WCAG 2.2 AA touch target */
  padding: var(--space-2) var(--space-4);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  /* Same measured choice as .exercise-preference__btn: the muted token
     fails AA for body text on card. Secondary measures 5.9:1. */
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  cursor: pointer;
}

.exercise-swap__btn:hover,
.exercise-swap__btn:focus-visible {
  color: var(--color-text);
  border-color: var(--color-text-secondary);
}

.exercise-swap__panel {
  width: 100%;
  padding: var(--space-4);
}

.exercise-swap__intro {
  margin: 0 0 var(--space-3) 0;
}

.exercise-swap__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.exercise-swap__option {
  width: 100%;
  min-height: 44px;                    /* WCAG 2.2 AA touch target */
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  text-align: left;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text);
  cursor: pointer;
}

.exercise-swap__option:hover,
.exercise-swap__option:focus-visible {
  border-color: var(--color-primary);
}

.exercise-swap__option-name {
  font-size: var(--text-base);
}

/* Rendered from the first draft and never given a rule -- caught by
   verify-css, not by looking. An undefined class renders as unstyled
   text and errors nowhere. Secondary rather than muted, for the same
   measured reason as .exercise-preference__btn above. */
.exercise-swap__option-meta {
  color: var(--color-text-secondary);
}

/* ============================================
   WATCH OUT FOR  (CON-3b, 11 Aug 2026)
   ============================================

   Deliberately not styled as an alert. No red, no icon shouting, no
   uppercase body text. The amber left border and label are enough to
   mark this section as different in kind from the instructions above
   it, without implying the person is about to do something dangerous.

   Colour is never the only signal: the section carries its own text
   label and semantic list markup, so it reads correctly through a
   screen reader and for anyone who cannot distinguish the border.
   ============================================ */

.exercise-watchout {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--color-warning-light);
  border-left: 3px solid var(--color-warning);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

.exercise-watchout .exercise-section-label {
  margin-top: 0;
  color: var(--color-warning);        /* 6.2:1 on --color-bg-card, AA */
}

.exercise-watchout-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.exercise-watchout-list li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  color: var(--color-text);           /* 8.4:1 on --color-bg-card, AAA */
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  border-bottom: 1px solid var(--color-border-light);
}

.exercise-watchout-list li:last-child {
  border-bottom: none;
}

.exercise-watchout-list li::before {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-warning);
  flex-shrink: 0;
  margin-top: 0.55em;
}

/* ============================================
   HOW HEAVY  (CON-3b, 11 Aug 2026)
   ============================================

   Effort-relative load guidance. Never an absolute weight - see Locked
   Principle P4 and the Exercise Entry Standard. Styled quietly, as a
   note rather than a target, because a target is a number to fall
   short of.
   ============================================ */

.exercise-load {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--color-bg-elevated);
  border-radius: var(--radius-md);
}

.exercise-load .exercise-section-label {
  margin-top: 0;
}

.exercise-load-text {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text);           /* 7.04:1 on --color-bg-elevated, AAA */
  line-height: var(--leading-relaxed);
}

/* ============================================
   COACHING TIP
   ============================================ */

.coaching-tip {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: rgba(45, 212, 191, 0.1);
  border-left: 3px solid var(--color-primary);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

.tip-icon {
  font-size: calc(1.125rem * var(--user-text-scale, 1));
  flex-shrink: 0;
  line-height: 1.5;
}

.coaching-tip p {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-relaxed);
}

/* ============================================
   EXERCISE WHY (legacy)
   ============================================ */

.exercise-why {
  text-align: left;
  margin-bottom: var(--space-6);
}

.exercise-why h3 {
  color: var(--color-primary);
  font-size: var(--text-base);
  margin-bottom: var(--space-2);
}

.exercise-why p {
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

/* ============================================
   WORKOUT ACTIONS (Fixed Bottom)
   ============================================ */

.workout-actions {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: var(--space-4);
  background: var(--color-bg-deep);
  border-top: 1px solid var(--color-border-light);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.workout-actions .btn-full {
  width: 100%;
}

/* ============================================
   COMPLETION CELEBRATION
   ============================================ */

.completion-view {
  min-height: 100vh;
  display: flex;
  align-items: center;
  position: relative;
  overflow: hidden;
}

.celebration-content {
  text-align: center;
  padding: var(--space-6);
  max-width: 400px;
  width: 100%;
}

.celebration-emoji {
  font-size: calc(4rem * var(--user-text-scale, 1));
  margin-bottom: var(--space-4);
}

@media (prefers-reduced-motion: no-preference) {
  .celebration-emoji {
    animation: bounce 0.6s ease infinite alternate;
  }
}

@keyframes bounce {
  from { transform: translateY(0); }
  to   { transform: translateY(-10px); }
}

.completion-view h1 {
  font-size: var(--text-2xl);
  color: var(--color-text);
  margin-bottom: var(--space-2);
}

.completion-workout-name {
  color: var(--color-text);
  margin-bottom: var(--space-6);
}

.credits-earned-display {
  margin-bottom: var(--space-4);
}

.credits-number {
  display: block;
  font-size: calc(3.5rem * var(--user-text-scale, 1));
  font-weight: var(--font-bold);
  color: var(--color-primary);
}

.credits-label {
  font-size: var(--text-base);
  color: var(--color-text);
}

.total-credits-display {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
  font-size: var(--text-lg);
}

.total-label { color: var(--color-text); }
.total-number { font-weight: var(--font-bold); color: var(--color-text); }

.completion-message {
  margin-bottom: var(--space-6);
}

.completion-message p {
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: var(--leading-relaxed);
  font-style: italic;
}

.completion-actions {
  margin-top: var(--space-4);
}

/* ============================================
   CONFETTI
   ============================================ */

.confetti-piece {
  position: absolute;
  width: 10px;
  height: 10px;
  top: -10px;
  opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .confetti-piece {
    animation: confetti-fall 3s ease-out forwards;
  }
}

@keyframes confetti-fall {
  0%   { opacity: 1; transform: translateY(0) rotate(0deg); }
  100% { opacity: 0; transform: translateY(100vh) rotate(720deg); }
}

/* ============================================
   RESPONSIVE - DESKTOP
   ============================================ */

@media (min-width: 768px) {
  .workout-view {
    max-width: 600px;
    margin: 0 auto;
  }

  .timer-circle {
    width: max(200px, calc(4rem * var(--user-text-scale, 1) * 3.2));
    height: max(200px, calc(4rem * var(--user-text-scale, 1) * 3.2));
  }

  .timer-value { font-size: calc(4rem * var(--user-text-scale, 1)); }
  .reps-display { gap: var(--space-8); }
  .reps-value { font-size: calc(4rem * var(--user-text-scale, 1)); }
  .exercise-name { font-size: var(--text-3xl); }
  .exercise-instructions { padding: var(--space-5) var(--space-6); }

  /* Actions not fixed on desktop — inline */
  .workout-actions {
    position: static;
    margin-top: var(--space-6);
    padding: 0;
    background: transparent;
    border: none;
    max-width: 400px;
    margin-left: auto;
    margin-right: auto;
  }

  .workout-view,
  .core-session-view {
    padding-bottom: var(--space-8);
  }

  .credits-number { font-size: calc(4rem * var(--user-text-scale, 1)); }
  .celebration-emoji { font-size: calc(5rem * var(--user-text-scale, 1)); }
}

@media (min-width: 1024px) {
  .workout-view { max-width: 700px; }
  .timer-circle { width: max(240px, calc(5rem * var(--user-text-scale, 1) * 3)); height: max(240px, calc(5rem * var(--user-text-scale, 1) * 3)); }
  .timer-value { font-size: calc(5rem * var(--user-text-scale, 1)); }
}

/* ============================================
   RESPONSIVE - MOBILE
   ============================================ */

@media (max-width: 480px) {
  .timer-circle { width: max(140px, calc(var(--text-3xl) * 3.4)); height: max(140px, calc(var(--text-3xl) * 3.4)); }
  .timer-value { font-size: var(--text-3xl); }
  .reps-value { font-size: var(--text-3xl); }
  .credits-number { font-size: calc(3rem * var(--user-text-scale, 1)); }
}

/* ============================================
   PRESCRIBED SESSION — Exercise card + weight history
   01 Jul 2026 v2 (merged from appended block)
   ============================================ */

.exercise-role-badge.prescribed {
  background: rgba(99, 102, 241, 0.2);
  color: #818CF8;
}

.exercise-card {
  margin: var(--space-4) 0;
  padding: var(--space-5);
  background: var(--color-bg-card);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
}

.exercise-card-note {
  margin-bottom: var(--space-2);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.exercise-card .exercise-name {
  color: var(--color-primary);
  font-size: var(--text-xl);
  margin-bottom: var(--space-2);
}

.exercise-card .exercise-meta {
  justify-content: flex-start;
  margin-bottom: var(--space-4);
}

.exercise-description {
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
  line-height: var(--leading-relaxed);
  margin-bottom: var(--space-4);
}

.exercise-cues {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.exercise-cues li {
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
  line-height: var(--leading-relaxed);
  padding-left: var(--space-4);
  position: relative;
}

.exercise-cues li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 6px;
  height: 6px;
  background: var(--color-primary);
  border-radius: 50%;
}

.exercise-youtube-btn {
  margin-top: var(--space-3);
  margin-bottom: var(--space-2);
  border: 1px solid var(--color-primary);
  color: var(--color-primary);
  background: transparent;
  border-radius: var(--radius-lg);
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease;
}

.exercise-youtube-btn:hover,
.exercise-youtube-btn:focus-visible {
  background: rgba(45, 212, 191, 0.08);
  outline: 2px solid var(--color-border-focus);
  outline-offset: 2px;
}

.ps-weight-section {
  border-top: 1px solid var(--color-border-light);
  padding-top: var(--space-4);
}

.ps-weight-row {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-2);
  margin-bottom: var(--space-3);
}

.ps-weight-input {
  flex: 1;
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-base);
  font-family: inherit;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-sizing: border-box;
}

.ps-weight-input:focus {
  outline: 2px solid var(--color-border-focus);
  outline-offset: 2px;
  border-color: var(--color-primary);
}

.ps-weight-history {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.ps-weight-history-label {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  font-weight: var(--font-medium);
}

.ps-weight-history-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.ps-weight-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--color-text);
  cursor: pointer;
  min-height: 44px;
  min-width: 56px;
  font-family: inherit;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.ps-weight-chip:hover,
.ps-weight-chip:focus-visible {
  border-color: var(--color-primary);
  background: rgba(45, 212, 191, 0.06);
  outline: 2px solid var(--color-border-focus);
  outline-offset: 2px;
}

.ps-weight-chip-date {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: var(--font-normal);
}

/* ============================================================
   CORE-1 — body caution, 12 Aug 2026
   Fires when an exercise loads an area the person flagged sore today and
   is NOT contraindicated. Contraindicated exercises never reach a card.

   Styled as a NOTE, not a warning. No red, no icon, no alarm: this is
   the coach saying it knows something, not the app refusing. Amber would
   make an ordinary sore knee look like an injury, and somebody who sees
   a warning every session stops reading them.

   Contrast, tokens as of A11Y-1 and verified in all three schemes by
   tools/contrast-check.mjs: --color-text on --color-bg-card 8.40:1.
   ============================================================ */

.exercise-caution {
  margin: var(--space-3) 0;
  padding: var(--space-3) var(--space-4);
  background: var(--color-bg-card);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-text);
}

/* ============================================================
   FEED-1 — exercise difficulty feedback, 12 Aug 2026

   Two buttons, deliberately quiet. This is an optional aside on a card
   that already carries instructions, a watch-out, a caution and a note
   field; it must not compete with any of them.

   Styled to match .exercise-preference ("Not a fan of this one") rather
   than inventing a second visual language for the same kind of signal on
   the same card.

   NOT a rating: no stars, no scale, no colour coding of hard vs easy.
   Selected state is a border and a label change, so it reads as
   "recorded" rather than as a score.

   Contrast, all three schemes, gated by tools/contrast-check.mjs:
   --color-text-secondary on --color-bg 8.44:1; selected uses
   --color-primary at 7.86:1.
   ============================================================ */

.ex-feedback {
  display: flex;
  gap: var(--space-2);
  margin: var(--space-3) 0;
  flex-wrap: wrap;
}

.ex-feedback__btn {
  flex: 1 1 auto;
  min-height: 44px;               /* WCAG 2.2 AA 2.5.8 */
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.ex-feedback__btn:hover {
  border-color: var(--color-primary);
  color: var(--color-text);
}

/* Selected. Border and text only - no fill, because a filled button here
   would read as the primary action on the card, which it is not. */
.ex-feedback__btn.is-set {
  border: 2px solid var(--color-primary);
  padding: calc(var(--space-2) - 1px) calc(var(--space-3) - 1px);
  color: var(--color-text);
}

.ex-feedback__btn:focus-visible {
  outline: 3px solid var(--color-border-focus);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .ex-feedback__btn { transition: none; }
}


/* ============================================
   CARD-2 — three-layer exercise card
   (supersedes the CARD-1 disclosure styles)
   ============================================ */

.exercise-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* PINNED. Caution and the lead cue render on every page, above the page
   body. Styled apart from the page content on purpose: they are not part
   of the run of prose, and they are never page-scoped. */
.exercise-card .exercise-caution {
  margin: 0 0 var(--space-2) 0;
}

.xcard-lead-cue {
  margin: 0 0 var(--space-3) 0;
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed, 1.6);
}

/* Orientation only. aria-hidden in the markup -- the card's region label
   already says "step 1 of 3", and this would otherwise be read twice. */
.xcard-step {
  margin: 0 0 var(--space-2) 0;
  font-size: var(--text-xs, 0.75rem);
  font-weight: var(--font-bold, 700);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.65;
}

.xcard-page {
  padding-top: var(--space-2);
}

/* Their own words from the last time they did this. Set apart from the
   surrounding prose because it is the one thing on DECIDE that is about
   them rather than about the exercise. Never a trend, never a count.

   The inner <p> comes from lastLine() with its own .slog__last class, so
   there is nothing to style here beyond the container. */
.xcard-last {
  padding: var(--space-3);
  border-radius: var(--radius-md, 8px);
  background: var(--color-surface-raised, rgba(255, 255, 255, 0.04));
}

.xcard-last .slog__last {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed, 1.6);
}

/* HAZARDS. The one block on DO that must not read as ordinary prose.
   Rose tint and rose rule; the list text keeps the body colour, so the
   contrast does not depend on the accent being legible. */
.xcard-block--hazard {
  padding: var(--space-3);
  border-left: 4px solid var(--color-danger);
  border-radius: var(--radius-md, 8px);
  background: var(--color-danger-light);
}

.xcard-block--hazard .exercise-section-label {
  color: var(--color-danger);
}

/* The marker is decorative and carries no meaning the text does not. */
.xcard-block--hazard .exercise-watchout-list li::marker {
  color: var(--color-danger);
}

@media (prefers-contrast: more) {
  .xcard-block--hazard {
    border-left-width: 6px;
  }
}

/* The one navigation the person performs by hand, so it keeps the 48px
   target the tabs had rather than shrinking to a text link. */
.xcard-back {
  align-self: flex-start;
  min-height: 48px;              /* WCAG 2.2 target size */
  margin-top: var(--space-3);
}

.xcard-back:focus-visible {
  outline: 2px solid var(--color-primary, currentColor);
  outline-offset: 2px;
}

.xcard-block + .xcard-block {
  margin-top: var(--space-4);
}

.xcard-hold,
.xcard-empty {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed, 1.6);
}

.xcard-empty {
  opacity: 0.7;
}

/* Display preference "always show full instructions" renders every page
   in one region rather than walking somebody through three screens. */
.exercise-card--flat .xcard-block + .xcard-block {
  margin-top: var(--space-4);
}

/* ── TIMER-1, 08 Sep 2026 ────────────────────────────────────────────────
   The countdown reaching zero is the ONE automatic forward move in a
   session: it changes the screen under somebody who, mid-exercise, is by
   definition not looking at it. It announced nothing. Focus did not move,
   the live regions on the page it lands on are empty, and the only signal
   was navigator.vibrate -- which Safari on iOS does not implement, so on
   an iPhone there was no signal at all.

   WCAG 2.2 AA 4.1.3 Status Messages. The element carries role="status";
   this gives it a visible form to match, because a message that only
   screen readers get is only half the fix.

   Uses the accent token rather than danger: the time being up is the
   exercise going WELL, not a warning. */
.xcard-timer-done {
  margin: 0 0 var(--space-3);
  padding: var(--space-3);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-md, 8px);
  background: var(--color-surface-2, var(--color-surface));
  color: var(--color-text);
  font-weight: 600;
}

/* ============================================
   ADAPT-1 - OTHER WAYS TO DO THIS
   ============================================ */

/* A plain bordered block, not a hazard box. The rose treatment belongs to
   .xcard-block--hazard and borrowing it here would make an option look
   like a warning. */
.xcard-adapt {
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md, 8px);
}

/* 44px minimum target. `display` is left alone on purpose: setting flex
   removes the native disclosure triangle in some browsers, and that
   triangle is how open and closed state is shown without relying on
   colour. */
.xcard-adapt-summary {
  min-height: 44px;
  padding: var(--space-2) 0;
  cursor: pointer;
  font-weight: 600;
  color: var(--color-text);
}

.xcard-adapt-summary:focus-visible {
  outline: 3px solid var(--color-border-focus);
  outline-offset: 2px;
}

.xcard-adapt-pointer {
  margin-top: var(--space-2);
  color: var(--color-text);
}


/* ── CARD-4. The image slot on DO ──────────────────────────────────────
   A promise, not a picture. See the header note.

   Contrast: the note text uses --color-text-muted on the card
   background, which the 03 Aug site-wide audit measured at 3.91:1 to
   8.05:1 across every background token -- above 4.5:1 on the surfaces
   this block renders on, so it clears WCAG 2.2 AA 1.4.3 as body text.
   The border is decorative and carries nothing the sentence does not,
   so it is not held to 1.4.11.

   No fixed height and no aspect-ratio box: nothing is loading, so
   reserving space for it would be reserving space for a thing that does
   not exist. It sizes to its sentence. */
.xcard-image {
  padding: var(--space-3);
  border: 1px dashed var(--color-text-muted);
  border-radius: var(--radius-md, 8px);
  background: transparent;
}

.xcard-image-note {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm, 0.875rem);
  line-height: 1.5;
}

/* Reduced motion, forced colours and print all inherit sensibly here:
   there is no animation, no colour-only meaning, and the dashed border
   is preserved by forced-colors as a system border. Nothing to override. */

/* ============================================================
   CARD-5 — the collapsed hurt-and-ache row, and the stepper
   15 Sep 2026

   HURT_AND_ACHE was open on all four pages, so a ten-exercise
   session rendered the same two paragraphs forty times. It is
   now a closed <details> on every page — present always, open
   on occasion. The full text is read at the session gate.

   The summary keeps the hazard palette. A safety row that
   looks like an ordinary accordion is a safety row nobody
   opens, and this is the one disclosure on the card that is
   not optional reading.
   ============================================================ */

.xcard-hurt > .xcard-hurt-summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  /* 2.5.8 Target Size (Minimum), AA in WCAG 2.2. The row is the
     target, not the marker glyph. */
  min-height: 44px;
  padding: var(--space-2) 0;
  color: var(--color-danger-text, var(--color-danger));
  list-style: none;
}

/* Safari/Chrome default triangle, removed so the chevron below
   is the single indicator rather than competing with it. */
.xcard-hurt > .xcard-hurt-summary::-webkit-details-marker { display: none; }

.xcard-hurt > .xcard-hurt-summary::after {
  content: "\25BE";
  font-size: var(--text-sm);
  transition: transform 150ms ease;
}

.xcard-hurt[open] > .xcard-hurt-summary::after { transform: rotate(180deg); }

/* 2.4.7 / 1.4.11. The summary is the control, so the focus ring
   goes on it and must clear 3:1 against the hazard background. */
.xcard-hurt > .xcard-hurt-summary:focus-visible {
  outline: 3px solid var(--color-focus, var(--color-primary));
  outline-offset: 2px;
  border-radius: var(--radius-sm, 4px);
}

/* 2.3.3 Animation from Interactions. */
@media (prefers-reduced-motion: reduce) {
  .xcard-hurt > .xcard-hurt-summary::after { transition: none; }
}

/* ── The stepper ────────────────────────────────────────────
   CARD-3 removed a tablist because "here are three places you
   may go" got answered with "none of them". This is a stepper:
   passed steps are buttons, the current one is marked, and
   steps AHEAD are plain text — never disabled buttons, which
   are low-contrast controls with no announced reason.

   1.4.1 Use of Colour: the live step is carried by weight and
   an underline, not by colour alone.
   ──────────────────────────────────────────────────────────── */

.xcard-stepper {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  align-items: center;
  justify-content: center;
  margin: 0 0 var(--space-3);
  padding: 0;
  list-style: none;
}

.xcard-stepper-item { display: flex; align-items: center; }

.xcard-stepper-btn {
  background: none;
  border: none;
  padding: var(--space-2) var(--space-1);
  min-height: 44px;
  font-size: var(--text-sm);
  font-family: inherit;
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.xcard-stepper-btn:focus-visible {
  outline: 3px solid var(--color-focus, var(--color-primary));
  outline-offset: 2px;
  border-radius: var(--radius-sm, 4px);
}

.xcard-stepper-now {
  padding: var(--space-2) var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-text);
  border-bottom: 2px solid var(--color-primary);
}

/* Not a control, and must not read as a disabled one. Muted,
   no underline, no pointer — but still above 4.5:1 on the card
   background, because it is text somebody reads to orient
   themselves, not decoration. */
.xcard-stepper-ahead {
  padding: var(--space-2) var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* Narrow phones: four labels must not wrap into a ragged block.
   Shrinks before it wraps. */
@media (max-width: 380px) {
  .xcard-stepper { gap: var(--space-1) var(--space-2); }
  .xcard-stepper-btn,
  .xcard-stepper-now,
  .xcard-stepper-ahead { font-size: var(--text-xs); }
}


/* ============================================
   SMOOTH-P2c - ONE SCREEN PER EXERCISE
   ============================================ */

.wo-flow .exercise-display { text-align: left; }

.wo-flow__section {
  margin: var(--space-4) 0 var(--space-1);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
}

.wo-flow .exercise-name {
  margin: 0 0 var(--space-4);
  line-height: 1.2;
}

.wo-flow .exercise-name:focus { outline: none; }
.wo-flow .exercise-name:focus-visible {
  outline: 3px solid var(--color-border-focus);
  outline-offset: 4px;
}

.wo-flow .exercise-target {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-4);
}

.exercise-card--flow {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-4);
  text-align: left;
}

.xcard-how {
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md, 8px);
}

.xcard-how-summary {
  min-height: 44px;
  padding: var(--space-2) 0;
  cursor: pointer;
  font-weight: 600;
  color: var(--color-text);
}

.xcard-how-summary:focus-visible {
  outline: 3px solid var(--color-border-focus);
  outline-offset: 2px;
}

.xcard-how .exercise-section-list { margin: var(--space-2) 0 0; line-height: 1.55; }
.xcard-how .xcard-more-form { color: var(--color-text-secondary); }

.wo-flow__done {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-5, 1.5rem);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.wo-flow .youtube-link { align-self: flex-start; }

/* SMOOTH-P2c. The counted target: one big line, then the words. */
.wo-flow .wo-target {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
}
.wo-flow .wo-target .reps-value { margin: 0; line-height: 1; }
.wo-flow .wo-target .reps-label {
  margin: 0;
  font-size: var(--text-base);
  color: var(--color-text-secondary);
  text-align: center;
}
.wo-flow .wo-target .set-progress {
  margin: var(--space-1) 0 0;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  font-weight: 600;
  color: var(--color-text);
}


/* SMOOTH-P2e, REST-1. A suggestion, styled like one. */
.wo-rest {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  margin: 0 0 var(--space-4);
  padding: var(--space-3);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
}
.wo-rest__label { margin: 0; color: var(--color-text-secondary); }
.wo-rest__count { margin: 0; font-size: var(--text-xl); font-variant-numeric: tabular-nums; color: var(--color-text); }
.wo-rest__ready { margin: 0; min-height: 1.25rem; color: var(--color-text); font-weight: 600; }


/* D-1 — the four steps, 04 Oct 2026 */
.wo-steps { margin: var(--space-3) 0; }
.wo-steps__list { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.wo-steps__item { flex: 1 1 5em; min-width: 0; }
.wo-steps__btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  width: 100%;
  min-height: 48px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--color-text-secondary);
  font: inherit;
  font-size: var(--text-xs);
  cursor: pointer;
}
.wo-steps__btn:focus-visible { outline: 3px solid var(--color-border-focus); outline-offset: 2px; border-radius: 6px; }
.wo-steps__bar { display: block; width: 100%; height: 5px; border-radius: 3px; background: var(--color-border); }
.wo-steps__btn--on { color: var(--color-text); font-weight: 700; }
.wo-steps__btn--on .wo-steps__bar { background: var(--color-primary); }
.wo-steps__btn--done .wo-steps__bar { background: var(--color-primary); opacity: 0.55; }
.wo-steps__label { display: block; max-width: 100%; overflow-wrap: break-word; text-align: center; line-height: 1.2; }
.xstep--capture { border-color: var(--color-primary); }
.xstep {
  margin-top: var(--space-2);
  padding: var(--space-4);
  background: var(--color-bg);
  border: 1px solid var(--color-border-light);
  border-radius: 20px;
}
.xstep-title { margin: 0 0 var(--space-3); font-size: var(--text-xl); font-weight: 600; color: var(--color-text); }
.xstep-title:focus { outline: none; }
.xstep-title:focus-visible { outline: 3px solid var(--color-border-focus); outline-offset: 2px; }
.xstep-why { margin: 0 0 var(--space-3); font-size: var(--text-lg); line-height: 1.55; color: var(--color-text); }
.xstep-hint { margin: var(--space-3) 0 0; font-size: var(--text-sm); color: var(--color-text-secondary); }
.workout-actions #wo-step-capture { margin-top: var(--space-1); }


/* ── P-22 to P-24 (the Plan): order, swap with search, add ───────────── */
.wo-ctl { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-2) 0 var(--space-3); }
.wo-ctl__pill {
  min-height: 44px; padding: var(--space-2) var(--space-4); border-radius: 999px;
  border: 1px solid var(--color-primary); background: var(--color-surface); color: var(--color-text);
  font: inherit; font-weight: var(--font-bold); cursor: pointer; max-width: 100%; overflow-wrap: anywhere;
}
.wo-ctl__pill:focus-visible { outline: 3px solid var(--color-border-focus); outline-offset: 2px; }
.wo-ctl__said { margin: 0 0 var(--space-2); color: var(--color-text-secondary); font-size: var(--text-sm); }
.wo-ctl__said:empty { margin: 0; }
.wo-swap { margin: var(--space-2) 0 var(--space-3); padding: var(--space-3); border: 2px solid var(--color-primary); }
.wo-swap__h { font-size: var(--text-base); margin: 0 0 var(--space-2); overflow-wrap: anywhere; }
.wo-swap__sub { font-size: var(--text-sm); margin: var(--space-2) 0; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: .04em; }
.wo-swap__none { margin: var(--space-2) 0; color: var(--color-text-secondary); font-size: var(--text-sm); }
.wo-swap__list, .swap-find__list, .wo-left__list { list-style: none; margin: 0; padding: 0; }
.wo-swap__pick, .swap-find__pick {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 2px var(--space-2);
  width: 100%; min-height: 48px; margin: var(--space-1) 0; padding: var(--space-2) var(--space-3); text-align: left;
  background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  font: inherit; cursor: pointer;
}
.wo-swap__pick:focus-visible, .swap-find__pick:focus-visible { outline: 3px solid var(--color-border-focus); outline-offset: 2px; }
.wo-swap__name, .swap-find__name { font-weight: var(--font-bold); flex: 1 1 10em; min-width: 0; overflow-wrap: break-word; }
.wo-swap__kit, .swap-find__kit { color: var(--color-text-secondary); font-size: var(--text-sm); }
.swap-find { margin: var(--space-3) 0; }
.swap-find__label { display: block; font-weight: var(--font-bold); margin-bottom: var(--space-1); }
.swap-find__hint { margin: 0 0 var(--space-2); color: var(--color-text-secondary); font-size: var(--text-sm); }
.swap-find__input {
  width: 100%; min-height: 44px; padding: var(--space-2) var(--space-3); font: inherit; color: var(--color-text);
  background: var(--color-bg); border: 1px solid var(--color-border-strong, var(--color-border)); border-radius: var(--radius-lg);
}
.swap-find__input:focus-visible { outline: 3px solid var(--color-border-focus); outline-offset: 2px; }
.swap-find__none { padding: var(--space-2) 0; color: var(--color-text-secondary); }
.wo-left__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--color-border); }
.wo-left__row:first-child { border-top: 0; }
.wo-left__n { flex: 0 0 1.6em; font-weight: var(--font-bold); color: var(--color-text-secondary); }
.wo-left__t { flex: 1 1 9em; min-width: 0; overflow-wrap: break-word; font-weight: var(--font-bold); }
.wo-left__dose { display: block; font-weight: normal; color: var(--color-text-secondary); font-size: var(--text-sm); }
.wo-left__add { margin-top: var(--space-3); padding: var(--space-3); }
.wo-left .workout-header .btn { white-space: normal; text-align: left; overflow-wrap: anywhere; }
.workout-actions #skip-exercise-btn { min-height: 44px; }   /* both tiers: a fault (v24) */
/* P-23. A long word in a name ("Strengthening") fits a 320 px phone at text 2 before it would split. */
.wo-swap__name, .swap-find__name, .wo-left__t { font-size: min(1em, 6.4vw); }
