/* ============================================================
   Endury — components/surfaces.css
   Full-surface components: session detail, plan editor. Classes carry
   every literal that is constant across instances; per-item colors/sizes
   (sport tints, race priority, bar heights/widths) are set inline by
   the renderers because they vary per data row.
   ============================================================ */

/* ---- shared primitives ------------------------------------------- */

/* .cb-badge (base + --good/--warn/--done/--muted + the --agenda/--grid size
   variants), and .cb-outline/.cb-outline__seg--* (workout-outline mini-bars)
   live in kit.css — session_detail.js reuses them via session_card.js's
   badgeMeta() and workout_outline.js's renderOutline(), so this file adds
   no badge/outline rules of its own. */

.cb-btn-primary {
  font-size: var(--cb-fs-body);
  font-weight: 600;
  color: var(--cb-accent-ink);
  background: var(--cb-accent);
  border: none;
  border-radius: var(--cb-r-card);
  padding: 12px;
  cursor: pointer;
  font-family: inherit;
}
.cb-btn-primary:disabled { opacity: .5; cursor: default; }
.cb-btn-primary--block { width: 100%; padding: var(--cb-sp-3-5); }

.cb-btn-secondary {
  font-size: var(--cb-fs-body);
  font-weight: 500;
  color: var(--cb-accent);
  background: var(--cb-surface-2);
  border: 1px solid var(--cb-border);
  border-radius: var(--cb-r-card);
  padding: 12px 16px;
  cursor: pointer;
  font-family: inherit;
}

.cb-divider {
  height: 1px;
  background: var(--cb-border);
  margin: 14px 0;
}

/* .cb-section-label base lives in insights.css (shared with the insight
   cards); only the margin here is specific to this component. */
.cb-plan .cb-section-label { margin-bottom: var(--cb-sp-2-5); }

.cb-stat-label { font-size: var(--cb-fs-micro); color: var(--cb-text-muted); }
.cb-stat-value { font-size: var(--cb-fs-title); font-weight: 600; margin-top: 0; }
.cb-stat-sub { font-size: var(--cb-fs-micro); color: var(--cb-text-muted); margin-top: 0; }

/* ---- session detail ------------------------------------------------ */

.cb-detail { display: flex; flex-direction: column; gap: 14px; }

.cb-detail-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.cb-detail-title-left { display: flex; align-items: center; gap: 8px; }
.cb-detail-dot { width: 10px; height: 10px; border-radius: var(--cb-r-bar); flex: none; }
.cb-detail-title { font-size: var(--cb-fs-title); font-weight: 600; }

.cb-detail-stats {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px;
}

.cb-recorded {
  background: var(--cb-surface-2);
  border: 1px solid var(--cb-border);
  border-radius: var(--cb-r-card);
  padding: var(--cb-sp-3) var(--cb-sp-3-5);
}
.cb-recorded-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--cb-sp-3);
}
.cb-recorded-title {
  font-size: var(--cb-fs-micro);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cb-text-muted);
}
/* color comes from insights.css's .cb-good-text/.cb-warn-text utilities */
.cb-recorded-compliance { font-size: var(--cb-fs-label); font-weight: 600; }
.cb-recorded-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
}
.cb-recorded-grid .cb-stat-value { font-size: var(--cb-fs-body); }
/* The intensity trace the shell fills in under the recorded extras; a swim
   has no extras, so the gap belongs to the grid-then-trace pair only. */
.cb-recorded-grid + [data-trace-slot] { margin-top: var(--cb-sp-3); }

.cb-detail-note { font-size: var(--cb-fs-body); line-height: 1.5; color: var(--cb-text-muted); }

.cb-detail-cues { display: flex; flex-direction: column; gap: 4px; }
.cb-detail-cue { font-size: var(--cb-fs-body); line-height: 1.5; color: var(--cb-text-muted); }

.cb-why-content { margin-top: 6px; }
.cb-why-para { font-size: var(--cb-fs-body); line-height: 1.5; color: var(--cb-text-muted); margin: 0 0 6px; }
.cb-why-para:last-child { margin-bottom: 0; }

.cb-workout-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: var(--cb-surface-2);
  border: 1px solid var(--cb-border);
  border-radius: var(--cb-r-tile);
  padding: var(--cb-sp-3) var(--cb-sp-3-5);
  cursor: pointer;
  font-family: inherit;
  color: var(--cb-text);
}
.cb-workout-toggle-label { font-size: var(--cb-fs-body); font-weight: 600; }
.cb-workout-chevron { transition: transform var(--cb-dur-fast) var(--cb-ease); color: var(--cb-text-muted); }
.cb-workout-toggle[aria-expanded="true"] .cb-workout-chevron { transform: rotate(180deg); }

.cb-workout-steps {
  max-height: 220px;
  overflow-y: auto;
  margin-top: 6px;
  padding: 2px 4px 2px 2px;
}
.cb-workout-repeat-head {
  font-size: var(--cb-fs-micro);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cb-accent);
  padding: var(--cb-sp-2-5) 0 var(--cb-sp-0-5);
}
.cb-workout-row {
  display: flex;
  align-items: center;
  gap: var(--cb-sp-2);
  padding: var(--cb-sp-2) 0;
  border-bottom: 1px solid var(--cb-border);
}
.cb-workout-row--child { margin-left: 16px; }
.cb-workout-bar { width: 3px; border-radius: 2px; align-self: stretch; flex: none; }
.cb-workout-info { flex: 1; min-width: 0; }
.cb-workout-name { font-size: var(--cb-fs-body); font-weight: 500; color: var(--cb-text); }
.cb-workout-target { font-size: var(--cb-fs-label); color: var(--cb-text-muted); }
.cb-workout-dur { font-size: var(--cb-fs-meta); font-weight: 600; color: var(--cb-text-muted); white-space: nowrap; }

/* Activity debrief: time-in-zones bar + legend (activity_debrief.js) */
.cb-zonebar {
  display: flex;
  height: 8px;
  border-radius: var(--cb-r-bar);
  overflow: hidden;
  background: var(--cb-surface-3);
}
.cb-zonebar__seg { height: 100%; }
.cb-zonebar-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-sp-1) var(--cb-sp-2-5);
  margin-top: var(--cb-sp-1-5);
}
.cb-zonebar-item {
  display: flex;
  align-items: center;
  gap: var(--cb-sp-1);
  font-size: var(--cb-fs-label);
  color: var(--cb-text-muted);
}
.cb-zonebar-dot { width: 7px; height: 7px; border-radius: var(--cb-r-bar); flex: none; }

/* Activity debrief: recorded intensity trace (activity_trace.js). Bar
   height/width/fill vary per bucket and are set inline by the renderer; the
   frame, the threshold rule and the scrub cursor are constant and live here.
   .cb-trace__plan / .cb-trace__plot carry their share of the shared time
   axis as an inline width, so a short session draws a short box. */
.cb-trace { display: flex; flex-direction: column; gap: var(--cb-sp-1-5); }
.cb-trace-skeleton {
  height: 112px;
  border-radius: var(--cb-r-tile);
  background: var(--cb-surface-3);
}
/* Sentence case, not the uppercase section-label voice: these labels carry a
   duration, and text-transform renders fmtDur's "1h" as "1H". */
.cb-trace__rowlabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--cb-sp-2);
  font-size: var(--cb-fs-meta);
  font-weight: 600;
  color: var(--cb-text-muted);
}
.cb-trace__delta { font-weight: 500; }
.cb-trace__plan, .cb-trace__plot { max-width: 100%; }
.cb-trace__box {
  position: relative;
  height: 72px;
  border-radius: var(--cb-r-tile);
  /* The track colour .cb-zonebar uses: the only surface token that stays
     visible the whole length of the modal's own --cb-sheet-top/bot gradient. */
  background: var(--cb-surface-3);
  overflow: hidden;
  /* Horizontal drag scrubs; vertical drag still scrolls the sheet. */
  touch-action: pan-y;
}
.cb-trace__bars { display: flex; align-items: flex-end; height: 100%; }
.cb-trace__bars--even { gap: 1px; }
/* Measured: a 96-bucket trace is ~3.9px per bar in the 520px web modal, where
   the hairline separates the buckets and the rounded cap reads as a bar, but
   ~1.4px in the 342px phone sheet, where the 1px gap is as wide as the bar
   (picket fence) and 96 caps scallop the top edge. The phone therefore draws
   the same data as one continuous profile. Same scoping idiom as kit.css's
   .cb-toast. */
html[data-shell="mobile"] .cb-trace__bars--even { gap: 0; }
html[data-shell="mobile"] .cb-trace__bars--even > .cb-trace__bar { border-radius: 0; }
.cb-trace__bar {
  flex: 1 1 0;
  min-width: 0;
  border-radius: var(--cb-r-bar) var(--cb-r-bar) 0 0;
}
/* Rest, or a bucket the recording dropped: a flat floor segment the width of
   the interval it stands for. Capped at the bar radius it rendered as a 3px
   speck between the reps rather than as part of the trace. */
.cb-trace__bar--rest {
  height: 8%;
  border-radius: 0;
  background: var(--cb-text-muted);
  opacity: .4;
}
/* Muted, not a border tone: this is the one datum the whole strip is read
   against, and a hairline in --cb-border-strong disappears into the track. */
.cb-trace__thresh {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px dashed var(--cb-text-muted);
  pointer-events: none;
}
.cb-trace__cursor {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--cb-text);
  pointer-events: none;
}
.cb-trace__elev {
  display: block;
  width: 100%;
  height: 18px;
  margin-top: var(--cb-sp-0-5);
  border-radius: var(--cb-r-bar);
  background: var(--cb-surface-3);
}
.cb-trace__elev-fill { fill: var(--cb-text-muted); opacity: .3; }
/* Caption left, the dashed rule's legend right. The legend lives out here
   rather than on the rule: inside the plot it sat on top of whichever bars
   were nearest threshold — in a threshold session, all of them. */
.cb-trace__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-sp-2);
  font-size: var(--cb-fs-meta);
  color: var(--cb-text-muted);
}
.cb-trace__legend { display: flex; align-items: center; gap: var(--cb-sp-1-5); flex: none; }
.cb-trace__legend-rule { width: 14px; border-top: 1px dashed var(--cb-text-muted); }

.cb-reschedule-label {
  font-size: var(--cb-fs-micro);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cb-text-muted);
  margin-bottom: var(--cb-sp-2);
}
.cb-reschedule-row { display: flex; gap: var(--cb-sp-1-5); }
.cb-reschedule-btn {
  flex: 1;
  font-size: var(--cb-fs-meta);
  font-weight: 600;
  border-radius: var(--cb-r-tile);
  padding: 8px 0;
  cursor: pointer;
  font-family: inherit;
  background: var(--cb-surface-2);
  color: var(--cb-accent);
  border: 1px solid var(--cb-border);
}
.cb-reschedule-btn--current {
  background: var(--cb-accent);
  color: var(--cb-accent-ink);
  border-color: var(--cb-accent);
}
/* .4 put the past-day pills at 2.37:1 — legible only if you already knew what
   they said (design panel finding 21). .55 reads 3.25:1 against the sheet
   gradient, still visibly "off" but no longer a smudge. */
.cb-reschedule-btn:disabled { opacity: .55; cursor: default; }

.cb-detail-actions { display: flex; gap: 8px; margin-top: 2px; }
.cb-detail-actions .cb-btn-primary { flex: 1; }
.cb-detail-actions .cb-btn-secondary { flex: none; }
/* A session with no primary action (anything not yet completed) leaves Ask
   coach alone in the row — it fills it rather than sitting there as a stub. */
.cb-detail-actions .cb-btn-secondary:only-child { flex: 1; }

.cb-detail-pair { display: flex; flex-direction: column; gap: var(--cb-sp-2); margin-bottom: var(--cb-sp-3); }
.cb-detail-pair-caption { font-size: var(--cb-fs-label); color: var(--cb-text-muted); }
.cb-detail-pair .cb-btn-secondary { width: 100%; }

/* ---- plan editor ----------------------------------------------------- */

.cb-plan { display: flex; flex-direction: column; gap: 18px; }

/* One selection primitive. Three single-select rows once
   spoke three selected grammars — fill-invert on a 9px rect, outline +
   16% tint on a stadium pill, outline + 12% tint on a tile with the ink
   swap on a child. One answer now: tile radius, outline + one canonical
   12% tint, ink on the control itself. Size variants change padding and
   layout only — never fill, border, or radius. */
.cb-fam-row { display: flex; gap: 6px; margin-bottom: 10px; }
.cb-goal-row { display: flex; flex-wrap: wrap; gap: 6px; }
.cb-amb-row { display: flex; gap: 6px; }
.cb-select {
  cursor: pointer;
  font-family: inherit;
  font-size: var(--cb-fs-body);
  border-radius: var(--cb-r-tile);
  border: 1px solid var(--cb-border);
  background: var(--cb-surface-2);
  color: var(--cb-text-muted);
}
.cb-select[aria-checked="true"] {
  border-color: var(--cb-accent);
  background: color-mix(in srgb, var(--cb-accent) 12%, transparent);
  color: var(--cb-text);
}
.cb-select--fill { flex: 1; padding: var(--cb-sp-2-5) 0; font-weight: 600; text-align: center; }
.cb-select--sm { padding: var(--cb-sp-2) var(--cb-sp-3-5); font-weight: 500; white-space: nowrap; }
.cb-select--stacked {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 8px;
  text-align: left;
}
.cb-amb-label { font-size: var(--cb-fs-body); font-weight: 600; }
.cb-amb-sub { font-size: var(--cb-fs-micro); color: var(--cb-text-muted); }
/* Blocking condition, not a caption: generation refuses with
   athlete_data_required until these fields are filled in, so the note carries
   --cb-alert rather than the muted ink it shared with .cb-amb-sub. */
.cb-assess-note { font-size: var(--cb-fs-body); color: var(--cb-alert); }

.cb-arace {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--cb-surface-3);
  border: 1px solid color-mix(in srgb, var(--cb-race-a) 40%, transparent);
  border-radius: var(--cb-r-tile);
  padding: 12px 14px;
}
.cb-arace-tag { display: flex; align-items: center; gap: 6px; }
.cb-arace-badge {
  font-size: var(--cb-fs-micro);
  font-weight: 700;
  color: var(--cb-accent-ink);
  background: var(--cb-race-a);
  border-radius: var(--cb-r-chip);
  padding: 2px 6px;
}
.cb-arace-badge--maint { background: var(--cb-phase-maintain); color: var(--cb-ink-light); }
.cb-maint-stepper { display: flex; align-items: center; gap: 10px; margin-top: 6px; }
.cb-maint-step {
  width: 26px;
  height: 26px;
  border-radius: var(--cb-r-chip);
  border: 1px solid var(--cb-border);
  background: var(--cb-surface-3);
  color: var(--cb-text);
  font-size: var(--cb-fs-body);
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cb-maint-step:disabled { opacity: 0.35; cursor: default; }
.cb-maint-weeks { font-size: var(--cb-fs-title); font-weight: 600; min-width: 44px; text-align: center; }
.cb-arace-label {
  font-size: var(--cb-fs-micro);
  color: var(--cb-text-muted);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.cb-arace-date-input {
  display: block;
  font-size: var(--cb-fs-body);
  font-weight: 600;
  color: var(--cb-text);
  margin-top: 4px;
  background: transparent;
  border: none;
  font-family: inherit;
  padding: 0;
  cursor: pointer;
}
.cb-arace-away { text-align: right; }
.cb-arace-away-val { font-size: var(--cb-fs-body); font-weight: 600; margin-top: 2px; }
/* Refusal ahead of time: the planner will reject this race date, so the
   hint carries --cb-alert like .cb-assess-note. --warn is the softer,
   still-buildable short-notice mid-join advisory — muted text, not a status
   hue, so it doesn't compete with --cb-alert/--cb-warn's own reserved
   meanings (tokens.css COLOR SEMANTICS rules 2/3). */
.cb-arace-hint { font-size: var(--cb-fs-micro); color: var(--cb-alert); margin-top: 6px; }
.cb-arace-hint--warn { color: var(--cb-text-muted); }

.cb-races-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--cb-sp-2-5);
}
.cb-races-label {
  font-size: var(--cb-fs-label);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--cb-text-muted);
}
.cb-races-add {
  font-size: var(--cb-fs-meta);
  font-weight: 600;
  color: var(--cb-accent);
  background: var(--cb-surface-2);
  border: 1px solid var(--cb-border);
  border-radius: var(--cb-r-tile);
  padding: var(--cb-sp-1-5) var(--cb-sp-2-5);
  cursor: pointer;
  font-family: inherit;
}
.cb-races-list { display: flex; flex-direction: column; gap: var(--cb-sp-2); }
.cb-race-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--cb-surface-2);
  border: 1px solid var(--cb-border);
  border-radius: 9px;
  padding: var(--cb-sp-2-5) var(--cb-sp-3);
}
.cb-race-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.cb-race-info { flex: 1; min-width: 0; }
.cb-race-label { font-size: var(--cb-fs-body); font-weight: 500; color: var(--cb-text); }
.cb-race-date {
  display: block;
  font-size: var(--cb-fs-label);
  color: var(--cb-text-muted);
  background: transparent;
  border: none;
  font-family: inherit;
  padding: 0;
  cursor: pointer;
}

/* iOS zooms the page whenever a focused text control sits below 16px, and it
   does not zoom back out. Touch pointers only, so the desktop wizard keeps the
   redline sizes. See DEVIATIONS #15 for the coach composer. */
@media (pointer: coarse) {
  .cb-arace-date-input,
  .cb-race-date { font-size: var(--cb-fs-input); }
}
.cb-race-pri {
  font-size: var(--cb-fs-micro);
  font-weight: 700;
  letter-spacing: .03em;
  color: var(--cb-accent-ink);
  border-radius: 6px;
  padding: var(--cb-sp-0-5) var(--cb-sp-2);
  cursor: pointer;
  border: none;
  font-family: inherit;
}
.cb-race-remove {
  width: 24px;
  height: 24px;
  border-radius: var(--cb-r-chip);
  border: 1px solid var(--cb-border);
  background: var(--cb-surface-3);
  color: var(--cb-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: none;
}
.cb-pri-a { background: var(--cb-race-a); }
.cb-pri-b { background: var(--cb-race-b); }
.cb-pri-c { background: var(--cb-race-c); }
.cb-pri-peak { background: var(--cb-accent); }

/* Ink follows the fill: the dark accent-ink above wins on race-a (5.63:1) and
   the light accent (8.38:1); race-b/race-c are mid-toned, where white reads
   better — their fills were darkened so white now clears AA at 4.60:1. */
.cb-pri-b, .cb-pri-c { color: var(--cb-ink-light); }

.cb-preview { background: var(--cb-surface-3); border: 1px solid var(--cb-border); border-radius: 12px; padding: var(--cb-sp-4); }
.cb-preview-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 12px;
}
.cb-preview-title {
  font-size: var(--cb-fs-label);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--cb-text-muted);
}
.cb-preview-eyebrow { font-size: var(--cb-fs-micro); color: var(--cb-text-muted); }
.cb-preview-peak { display: flex; align-items: baseline; gap: var(--cb-sp-1); }
.cb-preview-peak-num { font-size: var(--cb-fs-hero); font-weight: 700; }
.cb-preview-peak-label { font-size: var(--cb-fs-body); color: var(--cb-text-muted); }
/* Experimental-plan-type disclaimer, last row of the preview card. Muted,
   not --cb-alert like .cb-assess-note: it is a caveat, not a blocking
   condition — and sized at --cb-fs-body, since --cb-fs-micro is the
   badge/axis-tick size (DEVIATIONS #16). */
.cb-preview-note {
  font-size: var(--cb-fs-body);
  color: var(--cb-text-muted);
  margin-top: var(--cb-sp-3);
}

.cb-marker-row { display: flex; gap: 4px; margin-top: 14px; }
.cb-marker-cell { flex: 1; display: flex; justify-content: center; align-items: flex-end; height: 9px; }
.cb-marker-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--cb-surface-3);
}

.cb-ramp-row { display: flex; align-items: flex-end; gap: 4px; height: 56px; margin-top: var(--cb-sp-1-5); }
.cb-ramp-bar { flex: 1; border-radius: 2px 2px 0 0; background: var(--cb-bar-muted); }

.cb-phase-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  font-size: var(--cb-fs-micro);
  color: var(--cb-text-muted);
}

.cb-race-legend { display: flex; gap: 12px; margin-top: 10px; font-size: var(--cb-fs-micro); color: var(--cb-text-muted); }
.cb-legend-item { display: flex; align-items: center; gap: var(--cb-sp-1); }
.cb-legend-dot { width: 7px; height: 7px; border-radius: 50%; }

.cb-sport-strip { display: flex; height: 9px; border-radius: var(--cb-r-bar); overflow: hidden; gap: 2px; margin-bottom: 12px; }
.cb-sport-rows { display: flex; flex-direction: column; gap: var(--cb-sp-2-5); }
.cb-sport-row { display: flex; align-items: center; gap: var(--cb-sp-2); font-size: var(--cb-fs-body); }
.cb-sport-dot { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.cb-sport-label { color: var(--cb-text); }
.cb-sport-hours { color: var(--cb-text-muted); margin-left: auto; }
.cb-sport-pct { color: var(--cb-text-muted); width: 34px; text-align: right; }
