/* ShapeUp — Exercise Log SPA styles (Log tab, hero, weekly plan, program cards,
 * log form, manual picker, session details, finish/celebration/trial modals,
 * rest timer, guide/nudge, summary panel). Shell chrome (root tokens, sidebar,
 * header, profile menu, .xl-main, tab bar) lives in shell.css; shared
 * primitives (form fields, PR badge, swipe row, bottom-sheet shell, full-tab
 * shell, empty card) live in ui.css — both must load before this file. */

/* ───────── workout setup card ───────── */

.xl-setup {
  height: var(--setup-hero-height, auto);
  display: flex;
  flex-direction: column;
  background: var(--white);
  border-radius: 16px;
  padding: 16px;
  margin-bottom: 16px;
  /* natural shadow: layered, offset downward (light from above), no hard border */
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 10px rgba(15, 23, 42, 0.05),
    0 12px 28px rgba(15, 23, 42, 0.07);
}
.xl-setup-label {
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  color: var(--slate); margin-bottom: 6px;
}

.xl-split-row { display: flex; flex-wrap: nowrap; gap: 6px; margin-bottom: 14px; }

/* In a bottom sheet the row is the field's control, so .cp-field owns the gap
   below it — the card's own 14px would stack on top of the sheet's rhythm. */
.xl-split-row-sheet { margin-bottom: 0; }

/* Custom focus name, revealed under the select — same gap the sheet uses
   between a label and its control. */
.xl-focus-custom { margin-top: 6px; }

/* Split-type pill. Base pill recipe (radius/padding/font/selected-color)
   lives in shell.css's shared .sa-chip — this only adds the split-row-
   specific layout (equal-width flex, centered text). */
.xl-chip { flex: 1; text-align: center; }

.xl-focus-field { display: flex; flex-direction: column; gap: 6px; }
.xl-focus-label {
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  color: var(--slate);
}
.xl-focus {
  display: block;
  width: 100%;
  height: var(--control-h); box-sizing: border-box;
  font-family: var(--font); font-size: var(--fs-md);
  padding: 0 12px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--white); color: var(--ink);
  -webkit-appearance: none; appearance: none;
}
.xl-focus:disabled { background: var(--bg); color: var(--muted); }
.xl-focus:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(37,99,235,.1); }

/* margin-top:auto pins the button row to the card's bottom edge (both cards
   share a fixed height); padding-top keeps the old 12px minimum gap. */
.xl-setup-actions { display: flex; gap: 10px; margin-top: auto; padding-top: 12px; }

/* Weekly Plan states 2 (Ready) + 4 (Preview) — PlanCard.tsx. Card shell is the
   real .xl-setup (reused, not reinvented); only this badge/name/focus/Change
   row is new. */
.plan-card { justify-content: flex-start; }
.plan-top { display: flex; align-items: flex-start; gap: 12px; }
.plan-badge {
  display: inline-block; font-size: var(--fs-xs); font-weight: var(--fw-bold);
  padding: 4px 10px; border-radius: 999px;
}
.plan-badge.today { color: var(--blue); background: var(--blue-light); }
.plan-badge.other { color: #767c89; background: #F1F3F6; }
/* Inline pill next to Start session (or alone on Preview cards) — reuses
   .xl-nosession-secondary's light-blue chip look ("Input manual"), just
   width:auto instead of that class's flex-shared-row sizing. */
.plan-delete { width: auto; flex: 1; }
.plan-delete:disabled { border-color: var(--border); background: var(--border); color: var(--muted); cursor: not-allowed; }
.plan-name { font-size: var(--fs-3xl); font-weight: var(--fw-extrabold); color: var(--ink); margin-top: 14px; }
.plan-focus { font-size: var(--fs-md); color: var(--slate); margin-top: 2px; }

/* ───────── program meta + cards ───────── */

.xl-program-meta {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.xl-program-meta-label {
  font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--muted);
}
/* Log-tab active-session "Exercises" label — matched to the History tab's
   .hist-collapse-label (12px / 600 / slate). */
.xl-program-meta-label--hist {
  font-size: var(--fs-base); font-weight: var(--fw-semibold); color: var(--slate);
}
/* Day picker's "+ Add More", below the last card — centered so it reads as
   the end of the list rather than a header action. Top gap clears the last
   card's shadow, so it's bigger than the card stack's own 6px rhythm. */
.xl-add-more-row { display: flex; justify-content: center; padding: 14px 0 8px; }
.xl-program-meta-add {
  font-family: var(--font); font-size: var(--fs-md); font-weight: var(--fw-semibold);
  color: var(--blue); background: none; border: none; cursor: pointer;
  padding: 0;
}
.xl-program-meta-add:hover { color: var(--blue-dark); }
/* Log-tab "+ Add More" action — matches the History-styled "Exercises" label
   typography (12px / 600), kept blue as the clickable action. */
.xl-program-meta-add--hist {
  font-size: var(--fs-base); font-weight: var(--fw-semibold);
}
/* The list-end "+ Add More" takes the "Exercises" label's slate instead of the
   ghost button's blue — it reads as the end of the list, not a CTA. */
.xl-add-more-row .sa-btn-ghost { color: var(--slate); }
.xl-add-more-row .sa-btn-ghost:hover:not(:disabled) { color: var(--ink); }
/* Read-only "N exercises · M sets" count (Weekly Plan detail card) — sibling
   of xl-program-meta-add, muted text instead of a clickable blue action. */
.xl-program-meta-count {
  font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--muted); font-variant-numeric: tabular-nums;
}

/* ───────── active-session hero (State 4) ─────────
   Replaces .xl-setup once a program is committed. White stat card, per
   example/active-session-card: Back + elapsed row, title, 3-stat row
   (Exercises/Weight lifted/Records) with dividers, full-width Finish. */
.xl-hero {
  position: relative;
  height: var(--setup-hero-height, auto);
  display: flex;
  flex-direction: column;
  background: var(--white);
  border-radius: 18px;
  padding: 16px 20px 20px;
  color: var(--ink);
  margin-bottom: 16px;
  /* natural shadow: layered, offset downward (light from above), no hard border */
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 10px rgba(15, 23, 42, 0.05),
    0 12px 28px rgba(15, 23, 42, 0.07);
}
.xl-hero-topbar { display: flex; align-items: center; justify-content: space-between; }
/* Reuses the .xl-manual-back "< Back" pattern (see manual-picker section
   below) — same muted-gray styling, no override needed on a white card. */
.xl-hero-back.xl-hero-back { margin-left: -4px; }
.xl-hero-elapsed {
  font-size: var(--fs-base); font-weight: var(--fw-semibold); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.xl-hero-title {
  margin-top: 14px; font-size: var(--fs-2xl); font-weight: var(--fw-extrabold); color: var(--ink);
  text-align: center;
}
.xl-hero-subtitle {
  margin-top: 2px; font-size: var(--fs-md); font-weight: var(--fw-medium); color: var(--slate);
  text-align: center;
}
.xl-hero-stats {
  display: flex; align-items: center;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--bg);
}
.xl-hero-stat { flex: 1; text-align: center; }
.xl-hero-stat-divider { width: 1px; height: 28px; background: var(--bg); }
.xl-hero-stat-value {
  font-size: var(--fs-lg); font-weight: var(--fw-extrabold); color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.xl-hero-stat-unit { font-size: var(--fs-2xs); font-weight: var(--fw-semibold); color: var(--muted); }
.xl-hero-stat-label { margin-top: 2px; font-size: var(--fs-2xs); font-weight: var(--fw-semibold); color: var(--muted); }
.xl-hero-actions { display: flex; gap: 9px; margin-top: 16px; }

/* "Session details" pill — sits between the hero and the Exercises list,
   opens the .cp-sheet-based session log (SessionDetailsSheet.tsx). */
.xl-cs-pill {
  width: 100%; margin: 10px 0 16px;
  display: flex; align-items: center; gap: 10px;
  background: var(--white); border: 1px solid transparent;
  border-radius: 8px; padding: 11px 14px;
  cursor: pointer; font-family: var(--font);
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.18);
}
.xl-cs-pill-txt {
  flex: 1; text-align: left;
  font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--ink);
}
.xl-cs-pill-chevron { display: flex; flex: 0 0 auto; color: var(--muted); }
.xl-cs-pill-chevron svg { width: 15px; height: 15px; }

.xl-empty {
  text-align: center; color: var(--muted); font-size: var(--fs-md);
  padding: 40px 20px; line-height: 1.6;
}

/* ───────── Weekly Plan strip ─────────
   Always the top of the Log tab (example/weekly-plan-state/
   weekly-plan-log-tab-spec.md). The only genuinely new UI in that redesign —
   everything below the strip reuses existing xl-* components. */
.wk-strip { margin-bottom: 16px; }
.wk-row { display: flex; align-items: center; gap: 4px; }
.wk-arrow {
  flex-shrink: 0;
  width: 30px; height: 30px; border-radius: 50%;
  background: none; border: none;
  display: flex; align-items: center; justify-content: center;
  color: var(--slate); cursor: pointer;
}
.wk-arrow svg { width: 15px; height: 15px; }
.wk-arrow.next svg { transform: scaleX(-1); }
.wk-arrow:disabled { color: #c3c9d3; cursor: default; }
/* Locked (active session) reads the same as :disabled, but the button stays
   clickable so tapping it can surface the "session running" toast. */
.wk-arrow.locked { color: #c3c9d3; cursor: default; }

.wk-days { flex: 1; min-width: 0; display: flex; gap: 2px; }
.wk-days.ranging { gap: 0; }
.wk-day {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 6px 2px; border-radius: 12px; cursor: pointer;
  background: none; border: none;
  font-family: inherit; transition: transform 0.12s ease, background-color 0.12s ease;
}
.wk-day:active { transform: scale(0.96); }
.wk-day:disabled { opacity: 0.45; cursor: default; }
.wk-day:disabled:active { transform: none; }
.wk-day .lbl { font-size: var(--fs-3xs); font-weight: var(--fw-medium); color: var(--muted); }
.wk-day .num { font-size: var(--fs-xl); font-weight: var(--fw-semibold); color: var(--muted); }
/* planned = darker date number only — explicitly NO dot/marker */
.wk-day.planned .num { color: var(--ink); }
/* selected (not today) */
.wk-day.sel { background: var(--blue-light); }
.wk-day.sel .lbl, .wk-day.sel .num { color: var(--blue); }
/* today — highest priority, wins over selected/planned styling. Colored
   key-glow (natural-shadows skill §7): shadow tints the fill's own blue. */
.wk-day.today { background: var(--blue); box-shadow: 0 6px 14px rgba(37, 99, 201, 0.35); }
.wk-day.today .lbl { color: rgba(255, 255, 255, 0.72); }
.wk-day.today .num { color: #fff; }

/* Calories date-range gesture (range-mode-plan.md) — drag or long-press+tap
   across the strip. Square edges through the run so it reads as one
   continuous bar; only the two ends round. today still wins over range, same
   priority as it already has over .sel. */
.wk-day.in-range { background: var(--blue-light); border-radius: 0; }
.wk-day.in-range .lbl, .wk-day.in-range .num { color: var(--blue); }
.wk-day.today.in-range { box-shadow: none; }
.wk-day.range-start { border-top-left-radius: 12px; border-bottom-left-radius: 12px; }
.wk-day.range-end { border-top-right-radius: 12px; border-bottom-right-radius: 12px; }
/* Long-press-armed start, before the end tap lands. */
.wk-day.range-armed { background: var(--blue-light); box-shadow: inset 0 0 0 1.5px var(--blue); }

/* ───────── manual-input exercise picker (session-states State 2) ───────── */
/* Reached via "Input manual" / "+ Add More". Back row + sticky search/chips +
   selectable exercise cards (the shared .xl-card in select mode); the
   "Save N Exercises" footer is .xl-fulltab-footer. The header + tab bar stay
   put (they live outside .xl-main). */

/* Back row + search + chips. Warm app-canvas bg (matches .xl-app) so it blends
   with the rest of the screen; the negative side margins + padding let its
   background bleed to the frame edges over .xl-main's 18px gutter. */
.xl-manual-sticky {
  background: var(--canvas);
  margin: 0 -18px; padding: 4px 18px 0;
}
/* Search bar shared component: react/src/components/SearchInput.tsx (Tailwind). */
.xl-manual-chips {
  display: flex; gap: 8px; padding: 14px 0; overflow-x: auto;
  scrollbar-width: none; -ms-overflow-style: none;
}
.xl-manual-chips::-webkit-scrollbar { display: none; }
/* Muscle chips share shell.css's .sa-chip base recipe (type scale, padding,
   pill radius, light-tint selected colors). They scroll horizontally (many
   muscles) so they keep flex-shrink:0 instead of the split row's flex:1. */
.xl-manual-chip { flex-shrink: 0; }

.xl-manual-list { padding: 4px 0 8px; }
.xl-manual-hint { font-size: var(--fs-base); color: var(--muted); text-align: center; margin-top: 8px; }
.xl-manual-empty { font-size: var(--fs-md); color: var(--muted); text-align: center; margin-top: 24px; }

/* Card visuals ported 1:1 from the old app (example/appscript/Index.html
   .xl-card*): 8px radius, compact 10px/12px head padding, circular seq badge,
   column-stacked status, and the success/optional state backgrounds. */
.xl-card {
  border: 1px solid transparent;
  border-radius: 8px;
  background: var(--white);
  margin-bottom: 6px;
  overflow: hidden;
  transition: all 0.2s ease;
  /* natural shadow: layered, offset downward (light from above), no hard border */
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 10px rgba(15, 23, 42, 0.05),
    0 12px 28px rgba(15, 23, 42, 0.07);
}
.xl-card.in-progress { border-color: var(--blue); background: var(--white); }
/* Select mode (both exercise pickers): the left slot is a check circle
   instead of the set counter, and the border shifts on selection — no width
   change, so picking never causes layout shift. */
/* Multi-select uses a CHECKBOX (rounded square), not a circle — a circle
   reads as a radio, i.e. "pick exactly one", which is the wrong affordance
   for a list where any number of exercises can be picked. The checkbox is
   the only selection signal; the card keeps its resting border either way,
   so a picked list doesn't turn into a wall of blue outlines. */
.xl-card-check {
  width: 22px; height: 22px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--white);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.xl-card-check.on { border-color: var(--blue); background: var(--blue); }
.xl-card-check svg { width: 13px; height: 13px; }
/* No opacity here: a translucent card lets the swipe actions (blue Edit / red
   Delete) underneath show through. Flat green fill instead. */
.xl-card.target-met { background: var(--green-light); border-color: var(--green-dark); box-shadow: none; }
.xl-card.over-target { background: var(--green-light); border-color: var(--green-dark); box-shadow: none; }
/* Optional exercises match the default white floating card — only the "OPT"
   pill (.xl-opt-tag below) stays amber to flag optional status. Excludes the
   completed states so a finished optional card still turns green like a
   regular one. */
.xl-card.is-optional:not(.target-met):not(.over-target) { background: var(--white); border-color: transparent; }

.xl-card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  cursor: pointer;
  user-select: none;
}
/* No hover state on exercise cards, deliberately — they're tapped constantly on
   touch (where :hover sticks after a tap anyway), and the blue tint/border read
   as a selected state that isn't real. */
/* Count (left slot, replaced the old .xl-seq circle): plain "N/target" over
   "Sets", stacked, muted grey — no background. */
.xl-count-badge {
  flex: 0 0 auto;
  min-width: 34px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  line-height: 1.15;
}
.xl-count-num { font-size: var(--fs-base); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; color: var(--slate); }
.xl-count-word { font-size: var(--fs-3xs); font-weight: var(--fw-medium); color: var(--muted); }
.xl-card-main { flex: 1; min-width: 0; }
.xl-card-name {
  font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--ink);
}
/* "ALT N" pill on a swapped exercise (old app .xl-alt-badge). */
.xl-swap-tag {
  display: inline-block;
  font-size: var(--fs-3xs); font-weight: var(--fw-bold);
  padding: 2px 6px; border-radius: 8px; margin-left: 6px;
  background: var(--green-light); color: var(--green-dark);
  vertical-align: middle;
}
/* "Opt" pill on an optional exercise — amber to match the cream card theme. */
.xl-opt-tag {
  display: inline-block;
  font-size: var(--fs-3xs); font-weight: var(--fw-bold);
  padding: 2px 6px; border-radius: 8px; margin-left: 6px;
  background: #fdf3df; color: #ba7517;
  vertical-align: middle;
}
/* Logged-equipment tag appended to the name once a set is in (old app
   .xl-equipment-tag). */
.xl-equip-tag {
  display: inline-block;
  font-size: var(--fs-3xs); font-weight: var(--fw-semibold);
  color: var(--blue); background: rgba(37,99,201,0.1);
  padding: 1px 5px; border-radius: 3px; margin-left: 4px;
  vertical-align: middle;
}
.xl-card-muscle { font-size: var(--fs-2xs); color: var(--muted); margin-top: 2px; }
.xl-card-status {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  text-align: right;
}
/* Compact label for the "done"/"active" hint. */
.xl-over {
  font-size: var(--fs-3xs); font-weight: var(--fw-bold);
  padding: 1px 6px; border-radius: 8px; background: var(--green-dark); color: #fff;
}
.xl-swap-btn {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: transparent; color: var(--slate);
  display: inline-flex; align-items: center; justify-content: center;
  margin-left: 8px;
  cursor: pointer; transition: border-color 0.15s, color 0.15s;
}
.xl-swap-btn:hover { border-color: var(--blue); color: var(--blue); }
.xl-swap-btn svg { width: 14px; height: 14px; }
/* On the colored states the swap button keeps a light readable outline. */
.xl-card.in-progress .xl-swap-btn,
.xl-card.target-met .xl-swap-btn,
.xl-card.over-target .xl-swap-btn {
  border-color: rgba(0,0,0,0.18); color: var(--slate);
}

/* ───────── current logged exercises (this session) ─────────
   Rendered below the program cards (current-session-mockup.html). A collapsible
   blue status bar reveals per-exercise blocks of logged sets. Typography reuses
   the card/set sizes already in this file for consistency. */

#xl-current { margin-top: 4px; }

/* status bar (sets logged · elapsed) — tap to collapse/expand the body */
.xl-cs-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 13px;
  border-radius: 8px;
  background: var(--blue); color: #fff;
  cursor: pointer; user-select: none;
}
.xl-cs-bar.open { border-radius: 8px 8px 0 0; }
.xl-cs-pulse {
  width: 8px; height: 8px; border-radius: 50%;
  background: #7ee787; flex: 0 0 auto;
  animation: xlCsPulse 2s infinite;
}
@keyframes xlCsPulse {
  0%   { box-shadow: 0 0 0 0 rgba(126, 231, 135, 0.7); }
  70%  { box-shadow: 0 0 0 6px rgba(126, 231, 135, 0); }
  100% { box-shadow: 0 0 0 0 rgba(126, 231, 135, 0); }
}
.xl-cs-txt { flex: 1; font-size: var(--fs-base); font-weight: var(--fw-semibold); }
.xl-cs-sub { opacity: 0.8; font-weight: var(--fw-regular); }
.xl-cs-link { font-size: var(--fs-xs); font-weight: var(--fw-semibold); opacity: 0.9; }

/* body — white card hanging off the bar */
.xl-cs-body {
  background: var(--white);
  border: 1px solid var(--border); border-top: none;
  border-radius: 0 0 8px 8px;
  padding: 4px 12px 8px;
}

/* one exercise block; divider between, none on the last */
.xl-cs-ex { border-bottom: 1px solid var(--border); padding: 8px 0; }
.xl-cs-ex:last-child { border-bottom: none; }
.xl-cs-ex-hd { display: flex; align-items: center; gap: 7px; margin-bottom: 4px; }
.xl-cs-ex-nm { font-size: var(--fs-md); font-weight: var(--fw-medium); color: var(--slate); flex: 1; min-width: 0; }

/* B/U category badge */
.xl-cs-cat {
  flex: 0 0 auto;
  width: 18px; height: 18px; border-radius: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-2xs); font-weight: var(--fw-bold); color: #fff;
}
.xl-cs-cat-B { background: #0f6e56; }
.xl-cs-cat-U { background: #993c1d; }

/* logged-equipment tag — matches the exercise card's .xl-equip-tag (flat blue). */
.xl-cs-equip {
  flex: 0 0 auto;
  font-size: var(--fs-3xs); font-weight: var(--fw-semibold);
  color: var(--blue); background: rgba(37, 99, 201, 0.1);
  padding: 1px 5px; border-radius: 3px;
}

/* set row: id / weight×reps / RIR·RPE / time */
.xl-cs-set {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-base); flex-wrap: wrap;
}
.xl-cs-ex > .xl-cs-set {
  padding: 6px 12px; margin-bottom: 2px;
}
.xl-cs-ex > .xl-cs-set:last-child { margin-bottom: 0; }
.xl-cs-w {
  /* Match the History detail's "weight × reps" (.hist-set-wr): 12px / 500, not
     bold — the user flagged this column reading too heavy. */
  font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--ink);
  font-variant-numeric: tabular-nums; min-width: 84px;
}
/* PR badge — SHARED by the Log tab's logged sets AND the History tab (exercise.css
   loads on both pages). One source of truth: a solid filled pill with white text,
   colored per type by a modifier class. Don't redefine this in history.css. */
/* Matches .xl-cs-w's size/weight/color now that both columns read the same
   (was fs-xs/muted — the user flagged weight vs. RIR·RPE reading inconsistently). */
.xl-cs-meta { flex: 1; font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--ink); font-variant-numeric: tabular-nums; }
.xl-cs-time { font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; }

/* remark (new design): full-width line under the set, indented under the weight
   column with a blue left accent. Replaces the old inline remark. */
.xl-cs-rmk {
  flex-basis: 100%;
  margin: 1px 0 0 34px; padding-left: 9px;
  border-left: 2px solid var(--blue);
}
.xl-cs-rmk-txt { font-size: var(--fs-xs); color: var(--slate); font-style: italic; line-height: 1.4; }


/* ── Inline edit form (Current panel + History detail) ──
   Reuses the shared .xl-form card design (equipment chips, pill toggles, RIR/RPE
   selects). No grey slide behind it (1b "no header") — it sits directly on the
   sheet background as a plain white card set off by a 1px border only. */
.xl-edit-form.xl-form {
  border-top: none;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px;
  margin: 2px 0;
  background: var(--white);
}

/* Validation line above the edit-form actions. */

.xl-muted { font-size: var(--fs-base); color: var(--muted); }

/* ───────── placeholder panels ───────── */

.xl-placeholder {
  text-align: center; color: var(--muted);
  padding: 60px 20px; line-height: 1.7;
}
.xl-placeholder .xl-ph-title { font-size: var(--fs-lg); font-weight: var(--fw-bold); color: var(--slate); margin-bottom: 6px; }
.xl-placeholder .xl-ph-sub { font-size: var(--fs-md); }

/* ───────── session-expiry warning (§2B.5) ───────── */
.xl-session-warn {
  position: fixed;
  left: 50%; bottom: max(88px, calc(env(safe-area-inset-bottom) + 88px));
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(92%, 420px);
  padding: 10px 12px 10px 16px;
  border-radius: 14px;
  background: var(--ink);
  color: #fff;
  box-shadow: 0 8px 24px rgba(15,23,42,.28);
  z-index: 90;
}
.xl-session-warn.urgent { background: var(--error); }
.xl-session-warn-text { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.xl-session-warn-title { font-size: var(--fs-base); font-weight: var(--fw-bold); }
.xl-session-warn-time { font-size: var(--fs-xs); opacity: .8; font-variant-numeric: tabular-nums; }
.xl-session-warn-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.xl-session-warn-extend {
  border: none;
  border-radius: 999px;
  padding: 7px 12px;
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  background: #fff;
  color: var(--ink);
  cursor: pointer;
}
.xl-session-warn-extend:disabled { opacity: .6; cursor: default; }
.xl-session-warn-dismiss {
  border: none;
  background: transparent;
  color: #fff;
  opacity: .75;
  font-size: var(--fs-2xl);
  line-height: 1;
  width: 22px; height: 22px;
  cursor: pointer;
}
.xl-session-warn-dismiss:hover { opacity: 1; }

/* ───────── finish session modal ───────── */
.xl-finish-modal {
  position: fixed;
  inset: 0;
  z-index: 9998;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.xl-finish-modal.active { display: flex; }
.xl-finish-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.58);
  backdrop-filter: blur(2px);
}
.xl-finish-card {
  position: relative;
  width: min(100%, 420px);
  background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%);
  border: 1px solid rgba(255, 255, 255, 0.85);
  border-radius: 18px;
  padding: 24px 20px 18px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
  z-index: 1;
}
.xl-finish-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 34px;
  height: 34px;
  border: none;
  background: none;
  color: var(--slate);
  font-size: var(--fs-3xl);
  line-height: 1;
  cursor: pointer;
}
.xl-finish-close:hover { color: var(--blue); }
.xl-finish-kicker {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  color: var(--muted);
  margin-bottom: 10px;
}
.xl-finish-title {
  font-size: var(--fs-4xl);
  line-height: 1.1;
  color: var(--ink);
  margin-bottom: 8px;
}
.xl-finish-copy {
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--slate);
  margin-bottom: 18px;
}
.xl-finish-moods {
  display: grid;
  gap: 10px;
  margin-bottom: 18px;
}
.xl-finish-mood {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 13px;
  border: 1px solid #dde3eb;
  border-radius: 14px;
  background: #fff;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.16s ease, background 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease;
}
.xl-finish-mood:hover {
  border-color: var(--blue);
  background: var(--blue-light);
  transform: translateY(-1px);
}
.xl-finish-mood.selected {
  border-color: var(--blue);
  background: linear-gradient(180deg, rgba(37, 99, 201, 0.12), rgba(37, 99, 201, 0.06));
  box-shadow: 0 0 0 3px rgba(37, 99, 201, 0.08);
}
.xl-finish-mood-icon {
  width: 42px;
  height: 42px;
  border-radius: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  background: #f4f7fb;
  color: var(--blue);
}
.xl-finish-mood.selected .xl-finish-mood-icon {
  background: var(--blue);
  color: #fff;
}
.xl-finish-mood-icon svg { width: 22px; height: 22px; }
.xl-finish-mood-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.xl-finish-mood-label {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  color: var(--ink);
}
.xl-finish-mood-sub {
  font-size: var(--fs-base);
  color: var(--muted);
}
.xl-finish-actions {
  display: flex;
  gap: 10px;
}
/* ───────── trial-reward modal (add active number → +7 days) ───────── */
.xl-trial-modal {
  position: fixed;
  inset: 0;
  z-index: 9998;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.xl-trial-modal.active { display: flex; }
.xl-trial-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.58);
  backdrop-filter: blur(2px);
}
.xl-trial-card {
  position: relative;
  width: min(100%, 420px);
  background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%);
  border: 1px solid rgba(255, 255, 255, 0.85);
  border-radius: 18px;
  padding: 26px 22px 20px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
  z-index: 1;
  text-align: center;
}
.xl-trial-badge {
  width: 66px;
  height: 66px;
  border-radius: 50%;
  background: linear-gradient(135deg, #2563C9, #0d47a1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  box-shadow: 0 12px 26px rgba(37, 99, 201, 0.38);
  margin-bottom: 14px;
}
.xl-trial-badge-diamond {
  width: 25px;
  height: 25px;
  background: #fff;
  border-radius: 6px;
  transform: rotate(45deg);
}
.xl-trial-badge-spark {
  position: absolute;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 2px;
  transform: rotate(45deg);
}
.xl-trial-badge-spark--tr {
  width: 8px; height: 8px;
  top: 11px; right: 13px;
}
.xl-trial-badge-spark--bl {
  width: 5px; height: 5px;
  bottom: 13px; left: 12px;
  background: rgba(255, 255, 255, 0.75);
}

.xl-trial-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.06);
  color: var(--slate);
  font-size: var(--fs-3xl);
  line-height: 1;
  cursor: pointer;
}
.xl-trial-close:hover { background: rgba(37, 99, 201, 0.1); color: var(--blue); }
.xl-trial-kicker {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  color: var(--blue);
  margin-bottom: 10px;
}
.xl-trial-title {
  font-size: var(--fs-3xl);
  font-weight: var(--fw-bold);
  line-height: 1.15;
  color: var(--ink);
  margin-bottom: 8px;
}
.xl-trial-copy {
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--slate);
  margin-bottom: 18px;
}
.xl-trial-contrast {
  display: flex;
  align-items: stretch;
  gap: 12px;
  margin-bottom: 20px;
}
.xl-trial-day {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 11px 8px;
  border-radius: 14px;
  background: #f4f7fb;
  border: 1.5px solid var(--border);
}
.xl-trial-day:last-child {
  background: var(--blue-light);
  border-color: var(--blue);
}
.xl-trial-day-num {
  font-size: var(--fs-4xl);
  font-weight: var(--fw-bold);
  line-height: 1;
  color: var(--muted);
}
.xl-trial-day-num.reward { color: var(--blue); }
.xl-trial-day-date {
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  color: #64748b;
  white-space: nowrap;
  margin-top: 5px;
}
.xl-trial-day-date.reward { color: #2563C9; }
.xl-trial-day-label {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  color: #94a3b8;
}
.xl-trial-arrow {
  font-size: var(--fs-3xl);
  color: var(--muted);
  font-weight: var(--fw-bold);
  flex: none;
  display: flex;
  align-items: center;
}
.xl-trial-btn {
  display: block;
  width: 100%;
  font-family: var(--font);
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  padding: 13px 14px;
  border-radius: 12px;
  cursor: pointer;
  border: none;
  text-decoration: none;
  text-align: center;
}
.xl-trial-btn.primary { background: var(--blue); color: #fff; }
.xl-trial-btn.primary:hover { background: var(--blue-dark); }
.xl-trial-btn.ghost {
  background: none;
  color: var(--slate);
  margin-top: 8px;
}
.xl-trial-btn.ghost:hover { color: var(--ink); }

/* ───────── bottom rest-timer pill ("Ambient Fill" redesign) ─────────
   new-features/rest-timer/rest-timer-redesign-plan.md. Rounded (999px) glass
   pill, same recipe as the top .xl-tabbar (shell.css): translucent track +
   backdrop blur, Level-3 natural shadow. Spans the same width as the exercise
   cards (frame-clamped both edges — .xl-card's effective width via .xl-main's
   18px padding inside the 640px-capped centered frame), NOT content-width like
   the top tab bar. Rendered ONLY while a rest is active (RestTimerBar.tsx
   returns null when idle) — no idle/collapsed state exists in CSS anymore. */

.xl-rest-pill {
  position: fixed;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  /* Card-width clamp: matches .xl-main's 18px padding inside the 640px-capped
     centered frame (same math the old content-width .xl-fabbar used for its
     left edge — extended here to both edges). */
  left: max(18px, calc(50% - 320px + 18px));
  right: max(18px, calc(50% - 320px + 18px));
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 8px 6px 6px;
  /* Glass — exact .xl-tabbar recipe (shell.css ~462-471). Solid fallback first
     for browsers without rgb(from). */
  background: var(--tab-track);
  background: rgb(from var(--tab-track) r g b / 0.72);
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
  backdrop-filter: blur(14px) saturate(1.15);
  border-radius: 999px;
  /* Level 3 — floating control (natural-shadows skill §3). Copied verbatim. */
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.18);
  z-index: 95;
}
/* Manual-picker full-tab takeover hides the pill — see ui.css's
   .xl-app:has(.xl-panel.active .xl-fulltab) .xl-rest-pill rule (co-located
   with every other full-tab override). While the log-form sheet is open, hand
   its footprint
   to the sheet: */
.xl-app.sheet-open .xl-rest-pill { opacity: 0; pointer-events: none; }

/* Invisible hit shield mirroring .xl-tabbar::after (shell.css) — content
   scrolling behind the pill above/below its rounded corners must not be
   tappable through it. Per docs/tabbar-scroll-guidelines.md §6 direction 1e:
   the airspace is deliberately left VISUALLY transparent (content shows raw
   through/around the glass); only tap exposure is fixed. z:-1 keeps it under
   the pill's own buttons. Left/right now match the pill's own edges (no side
   gaps exist anymore at card width — only top/bottom need covering). */
.xl-rest-pill::after {
  content: '';
  position: absolute;
  z-index: -1;
  top: -16px;
  bottom: -16px;
  left: 0;
  right: 0;
}

.xl-rest-ring { width: 38px; height: 38px; flex-shrink: 0; position: relative; }
.xl-rest-ring svg.xl-rest-ring-svg { transform: rotate(-90deg); }
.xl-rest-ring circle.bg { stroke: rgba(15, 23, 42, 0.1); }
.xl-rest-ring circle.fg { stroke: var(--blue); transition: stroke-dashoffset 1s linear; }
.xl-rest-pill.timer-urgent .xl-rest-ring circle.bg { stroke: rgba(255, 255, 255, 0.3); }
.xl-rest-pill.timer-urgent .xl-rest-ring circle.fg { stroke: #fff; }
.xl-rest-pill.timer-done .xl-rest-ring circle.fg { stroke: var(--green-dark); }

/* Play/pause glyph centered inside the ring. Tap to freeze/resume an
   already-running or paused countdown — never starts one (change #4). */
.xl-rest-pp {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--blue);
}
.xl-rest-pp:active { transform: scale(0.9); }
.xl-rest-pill.timer-urgent .xl-rest-pp { color: #fff; }
.xl-rest-pill.timer-done .xl-rest-pp { display: none; }   /* no controls once finished */
.xl-rest-pp svg { width: 15px; height: 15px; display: block; }
.xl-rest-pp .xl-rest-pp-pause { display: none; }
.xl-rest-pp .xl-rest-pp-play  { display: block; }
.xl-rest-pill.timer-running .xl-rest-pp .xl-rest-pp-pause { display: block; }
.xl-rest-pill.timer-running .xl-rest-pp .xl-rest-pp-play  { display: none; }

/* flex-shrink: 0 — the countdown must never be squeezed; on narrow (Android)
   widths the nowrap buttons used to paint over the digits. */
.xl-rest-meta { display: flex; align-items: center; flex-shrink: 0; }
.xl-rest-time {
  font-size: var(--fs-display); font-weight: var(--fw-extrabold); font-variant-numeric: tabular-nums;
  color: var(--blue); line-height: 1.1;
}
.xl-rest-pill.timer-urgent .xl-rest-time { color: #fff; }
.xl-rest-pill.timer-done .xl-rest-time { color: var(--green-dark); }
/* dimmed while paused or while the adjust popover holds it frozen. */
.xl-rest-pill.timer-paused .xl-rest-time { opacity: 0.4; }

.xl-rest-btns { margin-left: auto; display: flex; align-items: center; gap: 4px; }
/* Chip/pill-style controls (999px) — matches the pill container's own rounded
   language instead of the old square-with-rounded-corners (8px) look. */
.xl-rb-ctrl {
  border: 1px solid var(--border);
  background: var(--white);
  color: var(--ink);
  font-family: var(--font);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-2xs);
  padding: 7px 9px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
}
.xl-rb-ctrl:active { transform: scale(0.95); }
.xl-rb-ctrl.skip { color: var(--error); border-color: rgba(220, 38, 38, 0.3); }
.xl-rest-pill.timer-urgent .xl-rb-ctrl {
  color: #fff; border-color: rgba(255, 255, 255, 0.4); background: rgba(255, 255, 255, 0.08);
}
.xl-rest-pill.timer-urgent .xl-rb-ctrl.skip { color: #fff; border-color: rgba(255, 255, 255, 0.4); }
.xl-rest-pill.timer-done .xl-rb-ctrl.skip { color: var(--green-dark); border-color: rgba(46, 125, 50, 0.4); }
.xl-rb-edit {
  width: 32px; height: 32px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--white);
  border-radius: 999px; cursor: pointer; color: var(--muted);
}
.xl-rb-edit:active { transform: scale(0.95); }
.xl-rb-edit svg { width: 15px; height: 15px; }
.xl-rest-pill.timer-urgent .xl-rb-edit {
  color: #fff; border-color: rgba(255, 255, 255, 0.4); background: rgba(255, 255, 255, 0.08);
}

/* Urgent (≤10s remaining, running) — the change #1 fix. The ENTIRE pill goes
   solid/opaque primary blue (override the glass — background +
   backdrop-filter: none) so white text and controls are NEVER on a
   light/translucent background. Flat --blue, no gradient (per design ask —
   was linear-gradient(90deg, #2563C9, #3d7ae0), now a single flat fill). No
   draining fill anywhere — see the plan doc's rationale for why a fill and a
   translucent glass pill are mutually exclusive. */
.xl-rest-pill.timer-urgent {
  background: var(--blue);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  animation: xlRestUrgentPulse 1s ease-in-out infinite;
}
@keyframes xlRestUrgentPulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.012); }
}
@media (prefers-reduced-motion: reduce) {
  .xl-rest-pill.timer-urgent { animation: none; }
}

/* Done — green wash (override the glass, opaque). */
.xl-rest-pill.timer-done {
  background: var(--green-light);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* ───────── rest-duration adjust popover ───────── */
.xl-rest-pop-backdrop {
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, 0.25);
  z-index: 96;
}
.xl-rest-pop-backdrop[hidden] { display: none; }
.xl-rest-pop {
  position: fixed;
  left: 14px; right: 14px;
  bottom: calc(82px + env(safe-area-inset-bottom, 0px));
  max-width: 612px;          /* frame width (640) minus the 14px side gutters */
  margin: 0 auto;
  background: var(--white);
  border-radius: 14px;
  box-shadow: 0 8px 28px rgba(15, 23, 42, 0.22);
  padding: 16px;
  z-index: 97;
}
.xl-rest-pop[hidden] { display: none; }
/* The 82px above clears the rest-timer pill, which is the only thing that
   ever sits under this popover. Every other stepper (target sets) has nothing
   below it, so it drops to the app's normal sheet offset (.cp-sheet, 16px). */
.xl-rest-pop.xl-stepper-low { bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
.xl-rest-pop-title { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink); }
.xl-rest-pop-sub { font-size: var(--fs-xs); color: var(--muted); margin: 2px 0 14px; }
.xl-rest-stepper {
  display: flex; align-items: center;
  border: 1px solid var(--border); border-radius: 999px;
  overflow: hidden; width: fit-content; margin: 0 auto;
}
.xl-rest-stepper button {
  width: 48px; height: 48px; border: none;
  background: var(--bg); font-size: var(--fs-3xl); font-weight: var(--fw-semibold);
  color: var(--blue); cursor: pointer; font-family: var(--font);
}
.xl-rest-stepper button:active { background: #e6e6e6; }
.xl-rest-stepper .val {
  min-width: 96px; text-align: center;
  font-size: var(--fs-3xl); font-weight: var(--fw-bold); color: var(--ink);
  font-variant-numeric: tabular-nums;
  display: flex; flex-direction: column; line-height: 1.1; padding: 0 6px;
}
.xl-rest-stepper .val small {
  font-size: var(--fs-3xs); font-weight: var(--fw-semibold);
 color: var(--muted);
}
.xl-rest-presets {
  display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; margin: 14px 0;
}
/* Round like the rest of the app's chips/pills. Fixed min-width so a 1- and a
   2-digit preset render the same size instead of the row jittering. */
.xl-rest-preset {
  border: 1px solid var(--border); background: var(--white);
  color: var(--slate); font-family: var(--font); font-weight: var(--fw-semibold);
  font-size: var(--fs-base); padding: 7px 12px; border-radius: 999px; cursor: pointer;
  min-width: 44px;
}
.xl-rest-preset.active { background: var(--blue); border-color: var(--blue); color: #fff; }
/* Buttons themselves come from the shared Button component (.sa-btn-primary /
   .sa-btn-secondary, shell.css) — this row only lays them out. Save is first
   in the DOM, so it lands on the left. */
.xl-rest-pop-actions { display: flex; gap: 10px; }
.xl-rest-pop-actions .sa-btn:active:not(:disabled) { transform: scale(0.98); }
.xl-rest-pop-note { font-size: var(--fs-2xs); color: var(--muted); text-align: center; margin-top: 10px; }

/* ───────── manual-entry bottom sheet ───────── */

.xl-sheet-scrim {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0);
  z-index: 9997;
  display: block;                   /* [hidden] handles show/hide */
  transition: background 0.25s;
}
.xl-sheet-scrim[hidden] { display: none; }
.xl-sheet-scrim.show { background: rgba(15, 23, 42, 0.5); }

.xl-sheet {
  position: absolute;
  /* Floating card occupying the FAB bar's exact footprint. On open it grows
     UPWARD out of the bar (origin = bottom), animating its HEIGHT from the bar's
     58px to fit its content — so it reads as the "+ Add Exercise" bar itself
     expanding into the form rather than a separate panel sliding up. Animating
     height (not scaleY) keeps the inner content crisp — no squish/stretch. */
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% - 28px);
  max-width: 612px;                 /* match the FAB bar's footprint */
  background: var(--white);
  border-radius: 16px;              /* same radius as the bar */
  padding: 0 18px;                  /* vertical padding fades in with the body */
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.18);  /* bar's shadow, lifts on open */
  /* Collapsed = the bar's height; expands to content height on open. */
  height: 58px;
  overflow: hidden;
  transition: height 0.3s cubic-bezier(0.32, 0.72, 0, 1),
              padding 0.3s cubic-bezier(0.32, 0.72, 0, 1),
              box-shadow 0.3s ease, border-radius 0.3s ease;
  -webkit-overflow-scrolling: touch;
}
.xl-sheet-scrim.show .xl-sheet {
  /* JS sets the explicit pixel height (content height, capped); these just
     restore the open chrome. */
  padding: 14px 18px 22px;
  border-radius: 18px;
  box-shadow: 0 12px 40px rgba(15, 23, 42, 0.28);
  overflow-y: auto;
}

/* ── Genie open (only when launched from the + FAB) ──────────────────────────
   A scale-genie approximation of macOS's minimize/restore: the sheet appears to
   fly OUT of the + button, scaling up from that point with a slight vertical
   stretch and a fast→slow ease-out. A true genie warp (curved edges) is
   non-affine and can't be done with CSS transforms, so this is the clean,
   iOS-Safari-safe stand-in. `--genie-x` / `--genie-y` are set by JS to the +
   button's center; the bar's height-morph is suppressed here so the two
   animations don't fight (the transform alone carries the open).  */
.xl-sheet-scrim.genie .xl-sheet {
  transform-origin: var(--genie-x, 50%) var(--genie-y, 100%);
  /* OPEN: height jumps instantly to target (no height transition); scale carries it */
  transition: transform 0.34s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.18s ease,
              padding 0s, box-shadow 0.3s ease, border-radius 0.3s ease;
}
/* Collapsed genie start / CLOSE target: a near-zero speck at the + button,
   slightly squashed vertically so the motion reads as a stretch from/into the
   point. The CLOSE transition (this `:not(.show)` state) is a touch SHORTER than
   the open and eases IN (accelerates), so the sheet drops into the button and the
   FAB returns without the brief dead gap. opacity clears fast so the input fields
   are already gone before the box finishes shrinking. */
.xl-sheet-scrim.genie:not(.show) .xl-sheet {
  transform: translateX(-50%) scale(0.04, 0.02);
  opacity: 0;
  transition: transform 0.26s cubic-bezier(0.4, 0, 1, 1),
              opacity 0.14s ease,
              padding 0s, box-shadow 0.26s ease, border-radius 0.26s ease;
}
.xl-sheet-scrim.genie.show .xl-sheet {
  transform: translateX(-50%) scale(1, 1);
  opacity: 1;
}

/* The body cross-fades in slightly after the bar starts growing, so the morph
   reads as the bar opening up rather than text popping in. Collapsed, only the
   "+ Add Exercise" affordance height is visible.
   On CLOSE (the .show class removed) the content fades out FAST and up front so
   the box is already empty before the height finishes collapsing — that's what
   keeps the tail of the close animation smooth (no content snapping away at the
   very end). */
.xl-sheet-handle,
.xl-sheet-head,
.xl-sheet-body {
  opacity: 0;
  transition: opacity 0.12s ease;        /* fade-out: quick, no delay */
}
.xl-sheet-scrim.show .xl-sheet-handle,
.xl-sheet-scrim.show .xl-sheet-head,
.xl-sheet-scrim.show .xl-sheet-body {
  opacity: 1;
  transition: opacity 0.18s ease 0.04s;   /* fade-in: start earlier so the open reads continuous */
}

.xl-sheet-handle {
  position: relative;
  width: 40px; height: 4px;
  background: var(--border);
  border-radius: 2px;
  margin: 0 auto 14px;
  cursor: pointer;                  /* tap the handle to close (no × button) */
}
/* Bigger invisible hit-target around the thin handle so it's easy to tap. */
.xl-sheet-handle::after {
  content: '';
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 80px; height: 22px;
}
.xl-sheet-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 14px;
}
.xl-sheet-title { font-size: var(--fs-xl); font-weight: var(--fw-semibold); color: var(--ink); }
.xl-sheet-close {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: none; background: var(--bg); color: var(--slate);
  font-size: var(--fs-lg); cursor: pointer; transition: background 0.13s;
  flex-shrink: 0;
}
.xl-sheet-close:hover { background: var(--border); }

/* searchable exercise field + suggestion list */
.xl-sheet-search { position: relative; margin-bottom: 12px; }
.xl-sheet-suggest {
  position: absolute;
  top: calc(100% + 4px); left: 0; right: 0;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
  max-height: 220px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  z-index: 5;
}
.xl-sheet-suggest[hidden] { display: none; }
.xl-sheet-opt {
  padding: 10px 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--bg);
}
.xl-sheet-opt:last-child { border-bottom: none; }
.xl-sheet-opt:hover, .xl-sheet-opt.active { background: var(--blue-light); }
.xl-sheet-opt-name { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink); }
.xl-sheet-opt-muscle { font-size: var(--fs-xs); color: var(--muted); margin-top: 2px; }
.xl-sheet-empty { padding: 12px; font-size: var(--fs-base); color: var(--muted); text-align: center; }

/* The sheet body reuses the card's .xl-form (same field helpers → identical
   inputs), but the sheet already supplies its own padding and has no card frame,
   so drop the form's card-only chrome (top border + 16px box padding). The
   inputs/labels/selects keep the card's exact font, size, color and 12px field
   padding — only the wrapper differs. */
.xl-sheet .xl-form,
.xl-log-sheet .xl-form {
  border-top: none;
  padding: 0;
  background: transparent;
}

.xl-sheet-fields { display: none; }   /* revealed once an exercise is picked */
.xl-sheet-fields.show { display: block; }

/* Bottom action row: trash/clear (square slot, like the FAB bar's clock) on the
   left + "Save set" filling the rest — mirrors the FAB bar's add/clock layout. */
.xl-sheet-actions {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-top: 6px;
}

/* ===== WORKOUT SETUP HEADER ===== */
.xl-setup-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}
.xl-setup-head .xl-setup-label { margin-bottom: 0; }

/* ===== CUSTOM PROGRAM BOTTOM SHEET ===== */

.cp-section-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  color: var(--muted);
  margin-bottom: 8px;
}
.cp-card {
  background: var(--white);
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 13px;
  margin-bottom: 14px;
  /* natural shadow: layered, offset downward (light from above), no hard border */
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 10px rgba(15, 23, 42, 0.05),
    0 12px 28px rgba(15, 23, 42, 0.07);
}
.cp-field { margin-bottom: 11px; }
.cp-field:last-child { margin-bottom: 0; }
.cp-field-tight { margin-bottom: 8px; }
/* For fields inside a grid: the grid's gap owns the spacing, so the field's
   own bottom margin would add to it (11px + gap). */
.cp-field-flat { margin-bottom: 0; }
.cp-label {
  display: block;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--slate);
  margin-bottom: 6px;
}
.cp-req { color: var(--blue); }
.cp-input {
  width: 100%;
  height: var(--control-h); box-sizing: border-box;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0 10px;
  font-size: var(--fs-md);
  font-family: var(--font);
  color: var(--ink);
  outline: none;
}
.cp-input:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(37,99,235,.1); }
.cp-input-pill { border-radius: 999px; padding-left: 14px; }

/* select.cp-input (Food Type/Macro Type, etc.) — custom chevron so it sits on
   the same right edge as .cal-unit's "g" suffix (right: 14px) instead of the
   browser's default arrow, which renders further right/inconsistently. */
select.cp-input {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; background-size: 16px;
  padding-right: 36px;
}

/* Unit suffix inside a field (Calories/Protein/... "kcal"/"g", and Portion's
   editable unit) — CaloriesTab's DecimalField/PortionField. The unit is NOT
   part of the input's value; it's overlaid at the right edge and the input
   reserves room for it via padding-right, so a long number can never slide
   underneath. */
.cal-unit-wrap { position: relative; display: block; }
.cal-unit-wrap .cp-input { padding-right: 52px; }

.cal-unit {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font);
  /* Matches the input's own type (.cp-input is --fs-md at normal weight) so the
     unit sits on the same optical line as the value; only the color sets it
     back as secondary. */
  font-size: var(--fs-md);
  font-weight: var(--fw-regular);
  color: var(--muted);
  pointer-events: none;  /* taps fall through to the input behind it */
}

/* Portion's unit is user-typed, so it's an input rather than static text:
   re-enable pointer events and strip the inherited field chrome so it reads as
   a suffix, not a second box inside the pill. Type is restated rather than
   `font: inherit` — inherit resolves against the wrapper div, not the .cal-unit
   rule above, so it would silently fall back to the browser's input font. */
.cal-unit-input {
  pointer-events: auto;
  width: 34px;
  border: 0;
  background: none;
  outline: none;
  padding: 0;
  text-align: right;
  height: auto;
  font-family: var(--font);
  font-size: var(--fs-md);
  font-weight: var(--fw-regular);
  color: var(--muted);
}
.cal-unit-input::placeholder { color: var(--muted); }

.cp-ex-row {
  background: var(--white);
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 11px;
  margin-bottom: 9px;
  /* natural shadow: layered, offset downward (light from above), no hard border */
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 10px rgba(15, 23, 42, 0.05),
    0 12px 28px rgba(15, 23, 42, 0.07);
}
.cp-ex-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 9px; }
.cp-ex-seq {
  background: var(--bg);
  padding: 3px 10px;
  border-radius: 9px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);

  color: var(--slate);
}
/* Override — square + bordered + red hover, on top of .sa-btn-icon's base circle */
.cp-ex-del {
  width: 27px; height: 27px;
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--slate);
}
.cp-ex-del:hover:not(:disabled) { border-color: #b00020; color: #b00020; }
.cp-ex-del svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 2; }
.cp-ex-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.cp-suggest-wrap { position: relative; }
.cp-suggest {
  position: absolute;
  top: calc(100% + 4px); left: 0; right: 0;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
  max-height: 200px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  z-index: 2;  /* in-scroller ceiling — docs/tabbar-scroll-guidelines.md R2 */
}
.cp-suggest[hidden] { display: none; }

.cp-hint {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-bottom: 14px;
}
.cp-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  color: var(--muted);
  margin: 16px 0 12px;
}
.cp-divider::before, .cp-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}
.cp-saved-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 13px;
  margin-bottom: 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
}
.cp-saved-name { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink); }
.cp-saved-meta { font-size: var(--fs-xs); color: var(--muted); margin-top: 2px; }
.cp-saved-actions { display: flex; gap: 6px; flex-shrink: 0; align-items: center; }
/* Override — text label, compact box shape, on top of .sa-btn-icon's base circle */
.cp-mini-btn {
  width: auto; height: auto;
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 11px;
  font-size: var(--fs-xs);
  color: var(--slate);
}
.cp-mini-btn.edit:hover:not(:disabled) { border-color: var(--blue); color: var(--blue); }
/* Delete uses the shared .sa-btn-secondary (blue outline pill) — just sized
   down to sit compactly next to the .cp-mini-btn "Edit" box in the same row. */
.cp-saved-actions .sa-btn-secondary {
  height: auto;
  padding: 5px 11px;
  font-size: var(--fs-xs);
}

/* Optional toggle — real sliding switch: fixed-width track, knob slides from
   left (off) to right (on). "Yes"/"No" text sits beside it, static position. */
.cp-optional-row { display: flex; align-items: center; gap: 8px; height: 32px; }
.cp-optional-toggle {
  position: relative;
  flex-shrink: 0;
  width: 40px; height: 24px;
  padding: 2px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.cp-optional-toggle.on {
  background: var(--blue);
  border-color: var(--blue);
}
.cp-optional-knob {
  display: block;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.25);
  transform: translateX(0);
  transition: transform 0.15s;
}
.cp-optional-toggle.on .cp-optional-knob { transform: translateX(16px); }
.cp-optional-label {
  font-family: var(--font);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--slate);
}
/* ── PR celebration: confetti canvas + result card ─────────────────────────
   Spec: example/confetti-spec.md. Colors come from the live tokens (gold is a
   fixed accent matching confetti.js). */
#xl-confetti {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;   /* never blocks taps */
  z-index: 10000;         /* above the celebrate card backdrop */
}

.xl-celebrate {
  position: fixed;
  inset: 0;
  z-index: 9999;          /* below the confetti, above everything else */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
/* CRITICAL: while hidden the overlay must be display:none, otherwise it covers
   the whole viewport and (even at opacity:0) swallows every click. The JS drops
   the [hidden] attribute one frame before adding .active so the fade still runs. */
.xl-celebrate[hidden] { display: none; }
.xl-celebrate.active { opacity: 1; }
.xl-celebrate-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.58);
  backdrop-filter: blur(2px);
}
.xl-celebrate-card {
  position: relative;
  z-index: 1;
  width: min(100%, 380px);
  background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%);
  border: 1px solid rgba(255, 255, 255, 0.85);
  border-radius: 18px;
  padding: 28px 24px 22px;
  text-align: center;
  box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
  transform: translateY(8px) scale(0.98);
  transition: transform 0.22s ease;
}
.xl-celebrate.active .xl-celebrate-card { transform: translateY(0) scale(1); }

.xl-celebrate-badge {
  width: 64px;
  height: 64px;
  margin: 0 auto 18px;
  border-radius: 50%;
  background: var(--blue);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.xl-celebrate-badge svg { width: 32px; height: 32px; stroke: #fff; }
.xl-celebrate-pill {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 24px;
  height: 24px;
  padding: 0 6px;
  border-radius: 12px;
  background: #BA7517;            /* gold accent (matches confetti.js) */
  color: #fff;
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #fff;
}

.xl-celebrate-eyebrow {
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  color: #BA7517;
  margin-bottom: 8px;
}
.xl-celebrate-title {
  font-weight: var(--fw-bold);
  font-size: var(--fs-3xl);
  line-height: 1.15;
  color: var(--blue-dark);
  margin-bottom: 6px;
}
.xl-celebrate-sub {
  font-size: var(--fs-lg);
  color: var(--slate);
  line-height: 1.5;
  margin-bottom: 22px;
}

.xl-celebrate-prs {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 22px;
  text-align: left;
}
.xl-celebrate-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg);
  border-radius: 10px;
  padding: 12px 14px;
  opacity: 0;
  transform: translateY(8px);
  animation: xlCelebrateRowIn 0.4s ease forwards;
}
@keyframes xlCelebrateRowIn {
  to { opacity: 1; transform: translateY(0); }
}
.xl-celebrate-icon {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 8px;
  background: var(--ok);
  display: flex;
  align-items: center;
  justify-content: center;
}
.xl-celebrate-icon svg { width: 16px; height: 16px; stroke: #fff; }
.xl-celebrate-info { flex: 1; min-width: 0; }
.xl-celebrate-name {
  font-weight: var(--fw-semibold);
  font-size: var(--fs-lg);
  color: var(--ink);
}
.xl-celebrate-detail {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-top: 1px;
}
.xl-celebrate-delta {
  font-weight: var(--fw-bold);
  font-size: var(--fs-lg);
  color: var(--ok);
  flex-shrink: 0;
}

/* Reduced motion: card still renders, animations suppressed. */
@media (prefers-reduced-motion: reduce) {
  .xl-celebrate,
  .xl-celebrate-card { transition: none; }
  .xl-celebrate-row { animation: none; opacity: 1; transform: none; }
}

/* The inline "i" field-info tooltip system (icon + dark popover + dark bottom
   sheet) was removed — field help now lives entirely in the header "?" Field
   Guide below. */

/* ===== Help icon + new-user nudge + Field Guide sheet =====================
   Additive — ported from example/shapeup-help-nudge-design.html, recut to the
   project tokens (--blue/--ink/--slate/--muted/--border/--white). The help icon
   sits in the header left of the avatar; the nudge is anchored under it; the
   Field Guide is a light bottom sheet. */

/* New-user nudge — floating popover under the help icon */
.xl-nudge-overlay {
  position: fixed;
  inset: 0;
  z-index: 920;
  pointer-events: none;
}
.xl-nudge-overlay.show { pointer-events: auto; }
.xl-nudge {
  position: absolute;
  top: 56px;
  right: 64px;
  width: 270px;
  max-width: calc(100vw - 24px);
  background: var(--white);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  opacity: 0;
  transform: translateY(-10px) scale(0.96);
  transform-origin: top right;
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.xl-nudge-overlay.show .xl-nudge { opacity: 1; transform: translateY(0) scale(1); }
.xl-nudge::before {
  content: "";
  position: absolute;
  top: -7px;
  right: 18px;
  width: 14px;
  height: 14px;
  background: var(--white);
  transform: rotate(45deg);
  border-radius: 3px;
}
.xl-nudge-body { position: relative; padding: 18px 16px 16px; }
.xl-nudge-x {
  position: absolute;
  top: 12px;
  right: 12px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  padding: 4px;
  display: flex;
}
.xl-nudge-lang {
  position: absolute;
  top: 14px;
  right: 38px;
  display: flex;
  background: var(--bg);
  border-radius: 6px;
  padding: 2px;
}
.xl-nudge-lang button {
  font-family: inherit;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  padding: 3px 7px;
  border: none;
  background: none;
  color: var(--muted);
  cursor: pointer;
  border-radius: 4px;
}
.xl-nudge-lang button.on { background: var(--blue); color: #fff; }
.xl-nudge h4 { font-size: var(--fs-lg); font-weight: var(--fw-semibold); color: var(--ink); }
.xl-nudge p { font-size: var(--fs-xs); color: var(--slate); line-height: 1.55; margin-top: 5px; }
.xl-nudge-acts { margin-top: 14px; display: flex; align-items: center; gap: 18px; }
.xl-nudge-btn {
  font-family: inherit;
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  border: none;
  background: none;
  padding: 2px;
}
.xl-nudge-btn.primary { color: var(--blue); }
.xl-nudge-btn.ghost { color: var(--muted); font-weight: var(--fw-medium); }

/* Field Guide — light bottom sheet (search + accordions) */
.xl-guide-back {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  z-index: 930;
}
.xl-guide-back.open { opacity: 1; pointer-events: auto; }
.xl-guide {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom));
  background: var(--white);
  border-radius: 18px;
  max-height: 82vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  transform: translateY(calc(100% + 12px));
  transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
  z-index: 931;
}
.xl-guide.open { transform: translateY(0); }
.xl-guide-grab {
  width: 40px;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  margin: 10px auto 2px;
}
.xl-guide-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 18px 14px;
  border-bottom: 1px solid var(--border);
}
.xl-guide-head h3 { font-size: var(--fs-xl); font-weight: var(--fw-semibold); color: var(--ink); }
.xl-guide-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  padding: 6px;
  display: flex;
  margin-right: -6px;
}
.xl-guide-search { padding: 12px 16px 4px; }
.xl-guide-search-wrap { position: relative; }
.xl-guide-search input {
  width: 100%;
  height: var(--control-h); box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 0 36px 0 14px;
  font-size: var(--fs-md);
  font-family: inherit;
  color: var(--ink);
  background: var(--bg);
}
.xl-guide-search input:focus { outline: none; border-color: var(--blue); background: var(--white); }
.xl-guide-search-clear {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  padding: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.xl-guide-search-clear[hidden] { display: none; }
.xl-guide-body {
  overflow-y: auto;
  padding: 6px 16px 32px;
  padding-bottom: calc(32px + env(safe-area-inset-bottom));
  -webkit-overflow-scrolling: touch;
}
.xl-fld { border-bottom: 1px solid var(--border); }
.xl-fld-q {
  width: 100%;
  background: none;
  border: none;
  text-align: left;
  padding: 11px 2px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  cursor: pointer;
  font-family: inherit;
}
.xl-fld-name { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink); }
.xl-fld-chev {
  stroke: var(--muted);
  stroke-width: 2;
  width: 18px;
  height: 18px;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
.xl-fld.open .xl-fld-chev { transform: rotate(180deg); }
.xl-fld-a { max-height: 0; overflow: hidden; transition: max-height 0.26s ease; }
.xl-fld.open .xl-fld-a { max-height: 600px; }
.xl-fld-a .xl-fld-lang-tag {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);

  color: var(--blue);
  margin-bottom: 2px;
}
.xl-fld-a .xl-fld-lang-block { padding: 0 2px 8px; }
.xl-fld-a .xl-fld-lang-block:last-child { padding-bottom: 12px; }
.xl-fld-a p { font-size: var(--fs-base); line-height: 1.5; color: var(--slate); }

@media (prefers-reduced-motion: reduce) {
  .xl-nudge, .xl-guide-back, .xl-guide, .xl-fld-a, .xl-fld-chev { transition: none; }
}

/* ===== summary panel (inline per-exercise chart + PR ladder) ===== */

.xl-summary-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  width: 28px; height: 28px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--slate); cursor: pointer; flex-shrink: 0;
  transition: border-color .15s, color .15s, background .15s;
}
.xl-summary-btn:hover { border-color: var(--blue); color: var(--blue); }
.xl-summary-btn.active { background: var(--blue-light); border-color: var(--blue); color: var(--blue); }
.xl-summary-btn svg { width: 14px; height: 14px; }

/* On the colored (light-green) states keep a dark readable icon — matches the
   swap button. (Was near-white, invisible on the light-green target-met card.) */
.xl-card.in-progress .xl-summary-btn,
.xl-card.target-met .xl-summary-btn,
.xl-card.over-target .xl-summary-btn {
  border-color: rgba(0,0,0,0.18); color: var(--slate);
}

/* Moved here from summary.css when that file was migrated to Tailwind
   (2026-07-26). It must stay UNLAYERED CSS, not a Tailwind utility: it
   overrides .xl-card's own border-color above, and unlayered legacy CSS
   always beats layered utilities. Migrate it together with .xl-card. */
.xl-sum-card.open { border-color: var(--blue); }

.xl-summary-panel {
  border-top: 1px solid var(--border);
  padding: 12px;
  background: var(--white);
}

.xls-controls { margin-bottom: 12px; }
.xls-control-group { margin-bottom: 10px; }
.xls-control-group:last-child { margin-bottom: 0; }
.xls-control-label {
  display: block; font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--slate); margin-bottom: 4px;
}

.xls-eq-chips { display: flex; gap: 6px; flex-wrap: wrap; padding: 4px 0; }
/* Base pill recipe lives in shell.css's shared .sa-chip — nothing left to
   add here (kept as a hook class for JS/TSX). */

.xls-radio-group { display: flex; gap: 16px; padding: 4px 0; }
.xls-radio-option { display: flex; align-items: center; gap: 4px; cursor: pointer; }
.xls-radio-option input[type="radio"] { cursor: pointer; margin: 0; }
.xls-radio-option label { cursor: pointer; font-size: var(--fs-lg); color: var(--ink); margin: 0; display: inline; }

.xls-divider { height: 1px; background: #ececec; margin: 12px 0; }

.xls-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.xls-title {
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold); color: var(--muted);
}
.xls-max { font-size: var(--fs-xs); color: var(--slate); }
.xls-max strong { color: var(--blue-dark); font-size: var(--fs-base); }

.xls-chart { height: 72px; position: relative; }

.xls-pr-block { margin-top: 12px; }
.xls-pr-label {
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  color: var(--muted); margin-bottom: 6px;
}
.xls-ladder { display: flex; flex-direction: column; }
.xls-ladder-row {
  display: flex; align-items: center; gap: 8px; padding: 5px 0; font-size: var(--fs-base);
  border-top: 1px solid #f3f3f3;
}
.xls-ladder-row:first-child { border-top: none; }
.xls-rank {
  width: 16px; height: 16px; border-radius: 50%;
  background: #eef2fb; color: var(--blue-dark); font-size: var(--fs-3xs); font-weight: var(--fw-bold);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.xls-ladder-row.is-top .xls-rank { background: var(--blue-dark); color: #fff; }
.xls-w { font-weight: var(--fw-semibold); min-width: 68px; color: var(--ink); }
.xls-rmk { flex: 1; font-size: var(--fs-2xs); color: var(--muted); font-style: italic; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xls-d { font-size: var(--fs-2xs); color: var(--muted); margin-left: auto; }

.xls-empty { text-align: center; padding: 18px 12px; color: var(--muted); font-size: var(--fs-base); }
.xls-empty svg { width: 28px; height: 28px; opacity: .4; margin-bottom: 6px; display: block; margin-left: auto; margin-right: auto; }
.xls-empty .sub { font-size: var(--fs-2xs); margin-top: 2px; }
.xls-partial {
  font-size: var(--fs-2xs); color: var(--muted); font-style: italic; text-align: center;
  padding: 8px; background: #f4f6f8; border-radius: 4px; margin-bottom: 10px;
}

/* ─── custom exercise ─── */
/* Programs | Exercises segmented toggle atop the Custom tab (plan.md §3b) —
   reuses .sa-chip/.xl-chip, just spaced like a header row above the panel. */
.cx-mode-toggle { display: flex; gap: 8px; margin-bottom: 12px; }

/* "Mine" badge on a created-by-you row in the Exercises list. */
.cx-mine-pill {
  font-size: var(--fs-3xs); font-weight: var(--fw-bold); color: var(--blue-dark);
  background: var(--blue-light); border-radius: 999px; padding: 3px 9px;
}

/* Equipment/Category multi-select chip rows in the add/edit sheet — same
   wrapping row as the split-picker's .xl-split-row, just field-scoped. */
.cx-chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
