/* 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: var(--shadow-l2);
}
.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); }

/* 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: var(--muted); background: var(--bg); }
/* 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: var(--shadow-l2);
}
.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: var(--shadow-l3);
}
.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(--slate); }
.wk-day .num { font-size: var(--fs-xl); font-weight: var(--fw-semibold); color: var(--slate); }
/* 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. Blue fill only,
   no glow (user decision 260905). */
.wk-day.today { background: var(--blue-fill); }
.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: var(--shadow-l2);
}
.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-fill); }
.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(--slate); }
.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: var(--amber-light); color: var(--amber-dark);
  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(--slate); margin-top: 2px; }
.xl-card-status {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  text-align: right;
}
.xl-card-actions {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
}
/* ───────── reorder mode (Step 6 rewrite, new-features/033-...) ───────── */
.xl-drag-handle {
  flex: 0 0 auto;
  min-width: 34px;
  height: 100%;
  display: flex; align-items: center; justify-content: center;
  color: var(--slate);
  cursor: grab;
  touch-action: none; /* this element owns the drag gesture, not page scroll */
}
.xl-drag-handle svg { width: 20px; height: 20px; }
.xl-card-delete {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: transparent; color: #c0392b; /* matches .xl-cs-act-del's red, ui.css:56 */
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
}
/* Touch keeps :hover on the last-tapped element, and `key={ex.seq}` renumbers
   on delete — so React reuses this exact DOM node for the NEXT exercise and the
   red state rides along to a card that was never tapped. Desktop keeps the
   affordance; touch gets none. Same reasoning as the .xl-card-head comment above. */
@media (hover: hover) {
  .xl-card-delete:hover { border-color: #c0392b; background: rgba(192, 57, 43, 0.08); }
}
.xl-card-delete svg { width: 14px; height: 14px; }
/* The dragged card is lifted, not ghosted — it follows the finger via an inline
   translateY on THIS element, so the shadow lives here too (a shadow on a
   different element than the transform is exactly how the previous attempt
   broke). Level 4, natural-shadows skill §3: a temporary surface floating over
   content with no backdrop. .xl-card already has `transition: all 0.2s ease`,
   which would lag the finger by 200ms — hence transition: none. */
.xl-card.dragging {
  position: relative;
  z-index: 10;
  transition: none;
  box-shadow: var(--shadow-l4);
}
.xl-card.drop-top { box-shadow: inset 0 2px 0 0 var(--blue); transition: none; }
.xl-card.drop-bottom { box-shadow: inset 0 -2px 0 0 var(--blue); transition: none; }
/* 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;
  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; }
.xl-muscle-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;
  cursor: pointer; transition: border-color .15s, color .15s, background .15s;
}
.xl-muscle-btn:hover,
.xl-muscle-btn.active { border-color: var(--blue); color: var(--blue); background: var(--blue-light); }
.xl-muscle-icon {
  display: block;
  width: 15px;
  height: 15px;
  background: currentColor;
  -webkit-mask: center / contain no-repeat;
  mask: center / contain no-repeat;
}
.xl-card.in-progress .xl-muscle-btn,
.xl-card.target-met .xl-muscle-btn,
.xl-card.over-target .xl-muscle-btn { border-color: rgba(0,0,0,0.18); color: var(--slate); }
/* 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-fill); 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; }
.xl-cs-cat-C { background: var(--split-cardio); }

/* 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: full-width line under the set. The blue accent pipe lines up with
   the FIRST character of the weight column (margin-left 0) — an indent here
   pushes it past the weight and reads as belonging to the next column. */
.xl-cs-rmk {
  flex-basis: 100%;
  margin: 1px 0 0 0;              /* was: 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: calc(16px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  width: calc(100% - 24px);
  max-width: min(96%, 420px);
  box-sizing: border-box;
  padding: 10px 12px 10px 16px;
  border-radius: 14px;
  background: var(--ink);
  color: var(--canvas);
  box-shadow: var(--shadow-l4);
  z-index: 90;
}
.xl-session-warn.urgent { background: var(--error); color: #fff; }
.xl-session-warn-text { display: flex; flex-direction: column; gap: 1px; flex: 1; }
.xl-session-warn-title { font-size: var(--fs-base); font-weight: var(--fw-bold); white-space: nowrap; }
.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: var(--canvas);
  color: var(--ink);
  cursor: pointer;
}
.xl-session-warn-extend:disabled { opacity: .6; cursor: default; }
.xl-session-warn-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--canvas);
  opacity: .75;
  font-size: var(--fs-2xl);
  line-height: 1;
  width: 36px; height: 36px;
  padding: 0;
  flex: 0 0 36px;
  cursor: pointer;
}
.xl-session-warn-dismiss:hover { opacity: 1; }

.xl-session-warn.urgent .xl-session-warn-extend {
  background: #ffffff;
  color: #0f172a;
}
.xl-session-warn.urgent .xl-session-warn-dismiss {
  color: #fff;
}

/* When the rest timer is active, keep the warning in the same bottom stack
   rather than letting the two fixed controls occupy the same space. */
body:has(.xl-rest-pill) .xl-session-warn {
  bottom: calc(16px + env(safe-area-inset-bottom, 0px) + 62px);
}

/* ───────── 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: var(--scrim);
  backdrop-filter: blur(2px);
}
.xl-finish-card {
  position: relative;
  width: min(100%, 420px);
  background: var(--white);
  border-radius: 18px;
  padding: 24px 20px 18px;
  box-shadow: var(--shadow-l5);
  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: var(--white);
  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: var(--bg);
  color: var(--blue);
}
.xl-finish-mood.selected .xl-finish-mood-icon {
  background: var(--blue-fill);
  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;
}
/* ───────── 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: var(--shadow-l3);
  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: */
html.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-fill);
  -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: var(--shadow-l4);
  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: var(--border); }
.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-fill); 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; }

/* Target-sets sheet — reuses the stepper/preset controls from the rest-timer
   popover inside a docked .cp-sheet. Only the subtitle + vertical rhythm are
   new; do NOT restate any .cp-sheet geometry here
   (docs/bottom-sheet-guidelines.md R0/R1). */
.xl-target-sheet-sub {
  font-size: var(--fs-xs);
  color: var(--muted);
  text-align: center;
  margin-bottom: 14px;
}

/* ───────── suggestion list & action row ───────── */

/* searchable exercise field suggestion list */
.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: var(--shadow-l4);
  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; }

/* Keep keyboard-accessible food suggestions visually identical to the picker
   rows, whose original markup is a non-interactive div. */
.cp-suggest > button.xl-sheet-opt {
  display: block;
  width: 100%;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
}

/* 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-log-sheet .xl-form {
  border-top: none;
  padding: 0;
  background: transparent;
}

/* 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: var(--shadow-l2);
}
.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); }
.cp-input-pill { border-radius: 999px; padding-left: 14px; }

/* Validation-failed state for a .cp-input — same red as .xl-form's
   input.xl-invalid (ui.css), scoped to this input family since .cp-sheet
   forms don't carry .xl-form. Also usable on a non-input wrapper (e.g.
   MultiChips' .cx-chip-row) for fields with no native input to redden. */
.cp-input.xl-invalid { border-color: #c0392b; }
.cp-input.xl-invalid:focus { border-color: #c0392b; box-shadow: 0 0 0 3px rgba(192,57,43,.1); }
.cx-chip-row.xl-invalid, .xl-split-row.xl-invalid { outline: 1.5px solid #c0392b; outline-offset: 4px; border-radius: 8px; }

/* 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 a fixed dropdown, so it's a select 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
   select font. Custom chevron (same artwork as select.cp-input) replaces the
   browser's default arrow, right-aligned in its own reserved space so it
   doesn't overlap the unit text. */
.cal-unit-input {
  pointer-events: auto;
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  width: 50px;
  border: 0;
  background-color: transparent;
  background-repeat: no-repeat; background-position: right center; background-size: 14px;
  outline: none;
  padding: 0;
  text-align: right;
  text-align-last: right;
  height: auto;
  font-family: var(--font);
  font-size: var(--fs-md);
  font-weight: var(--fw-regular);
  color: var(--muted);
}

/* Chevron (+ its reserved 16px gutter) only once a unit is actually chosen —
   on first render (before any food is picked/typed, uom === '') there's no
   affordance to make room for, so the blank "—" sits flush right like plain
   text. Class is applied from JS (PortionField), not an attribute selector,
   since a React controlled <select>'s live value isn't reflected by
   [value=""]. */
.cal-unit-input.has-value {
  padding-right: 16px;
  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");
}

/* Portion's unit when a catalog food is picked (AddEntrySheet) — plain text,
   no chevron, no interaction. Reuses .cal-unit's positioning as-is. */
.cal-unit-static { text-align: right; }

/* Right-hand affordance stack inside a DecimalField: the optional "+" chip,
   then the unit. Positioned as one group so the chip never has to know how
   wide the unit is. PortionField keeps the standalone absolute .cal-unit. */
.cal-suffix {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; gap: 8px;
  pointer-events: none;                 /* taps fall through to the input */
  white-space: nowrap;
}
.cal-suffix .cal-unit { position: static; transform: none; right: auto; top: auto; }
.cal-plus {
  pointer-events: auto;
  flex: none; width: 22px; height: 22px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 999px;
  background: none; color: var(--blue);
  font-family: var(--font); font-size: var(--fs-md); font-weight: var(--fw-bold);
  line-height: 1; cursor: pointer;
}
.cal-plus:active { transform: scale(0.92); }
.cal-unit-wrap.has-plus .cp-input { padding-right: 84px; }

.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: var(--shadow-l2);
}
.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: var(--shadow-l4);
  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-suggest > .cp-hint {
  padding: 10px 12px 8px;
  margin: 0;
}

.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: var(--shadow-l1);
}
.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-fill);
  border-color: var(--blue);
}
.cp-optional-knob {
  display: block;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: var(--shadow-l1);
  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: var(--scrim);
  backdrop-filter: blur(2px);
}
.xl-celebrate-card {
  position: relative;
  z-index: 1;
  width: min(100%, 380px);
  background: var(--white);
  border-radius: 18px;
  padding: 28px 24px 22px;
  text-align: center;
  box-shadow: var(--shadow-l5);
  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-fill);
  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: var(--shadow-l5-deep);
  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-fill); 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: var(--shadow-l5-deep);
  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; }

/* Target-muscle sheet */
.xl-muscle-sheet-copy { color: var(--slate); font-size: var(--fs-md); text-align: center; margin-bottom: 8px; }
.xl-muscle-illustration { width: min(100%, 300px); margin: 0 auto; }
.xl-muscle-illustration svg { display: block; width: 100%; height: auto; }
.xl-muscle-illustration .m-secondary  { fill: #d9756a; }
.xl-muscle-illustration .m-body-light { fill: var(--muscle-body-light, #e4e7ec); }
.xl-muscle-illustration .m-primary    { fill: #c0392b; }
.xl-muscle-illustration .m-body-dark  { fill: var(--muscle-body-dark, #aeb4c0); }
.xl-muscle-illustration .m-none       { fill: none; }
.xl-muscle-views { display: flex; gap: 12px; justify-content: center; align-items: flex-start; }
.xl-muscle-view { flex: 1 1 0; min-width: 0; margin: 0; }
.xl-muscle-view-label {
  color: var(--slate);
  font-size: var(--fs-md);
  text-align: center;
  margin-top: 8px;
}

:root { --muscle-body-light: #e4e7ec; --muscle-body-dark: #aeb4c0; }
:root[data-theme="dark"] { --muscle-body-light: #d8d4cc; --muscle-body-dark: #8e8a82; }
:root[data-theme="midnight"] { --muscle-body-light: #c9d5e6; --muscle-body-dark: #71829d; }

/* 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;
}

/* Single-combo summary: same label-over-value rhythm as the multi-combo
   controls, so Equipment and Category read identically. Category sits on its
   own line below its label rather than right-aligned. */
.xls-single-combo { margin-bottom: 12px; }
.xls-single-value {
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  color: var(--ink);
}

/* PR-summary sheet keeps a stable height whether the exercise has 10 sessions
   or none — otherwise the empty state renders as a thin strip that reads as a
   broken sheet. Min, not fixed: the ladder is capped at 5 entries, so this floor
   only ever applies to the empty/sparse case. */
.cp-sheet.xl-pr-sheet { min-height: 38dvh; }

.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-divider { height: 1px; background: var(--border); 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: var(--blue-light); 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-fill); 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: var(--bg); 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; }
