/* LUMA - progress + InBody (Layer 3)
   Sheet 5 of 9. Source order decides the cascade - see the link tags in luma.html. */

/* ============================================================
   LAYER 3 — PROGRESS + INBODY
   ============================================================ */

.progress-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding-top: calc(env(safe-area-inset-top) + 8px);
  margin-bottom: 20px;
  gap: 10px;
}

.progress-header .day-topbar-left { min-width: 0; }

#tab-progress .day-stack { padding-bottom: 64px; }

/* ---------- Mission timeline ---------- */
.timeline-card { overflow: visible; }

.timeline-track {
  position: relative;
  margin: 20px 0 16px;
}

/* Layer 7: with no InBody baseline there is no zero point, so the track collapses
   rather than drawing an empty 12-week rail she has not started yet. */
.timeline-empty-mode .timeline-track { display: none; }
.timeline-empty-mode #timeline-day-tag { background: var(--surface-3); color: var(--text-2); }
.timeline-empty-mode .timeline-detail { margin-top: 14px; }

.timeline-line {
  position: absolute;
  top: 20px;
  left: 10px;
  right: 10px;
  height: 2px;
  background: var(--surface-3);
  border-radius: 2px;
}

.timeline-line::after {
  content: '';
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  width: var(--progress, 0%);
  background: var(--lime);
  border-radius: 2px;
  box-shadow: 0 0 8px var(--lime-glow);
  transition: width var(--dur-slow) var(--ease-spring);
}

.timeline-nodes {
  display: flex;
  justify-content: space-between;
  position: relative;
}

.timeline-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  flex: 1;
  min-width: 0;
}

.timeline-node-dot {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--surface-2);
  border: 2px solid var(--border-2);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--dur-mid) var(--ease-spring),
              border-color var(--dur-mid) var(--ease-spring),
              box-shadow var(--dur-mid) var(--ease-spring);
  position: relative;
  z-index: 1;
}

.timeline-node-dot svg {
  width: 18px;
  height: 18px;
  stroke: var(--text-3);
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke var(--dur-mid) var(--ease-out);
}

.timeline-node.completed .timeline-node-dot {
  background: var(--lime);
  border-color: var(--lime);
  box-shadow: 0 0 16px var(--lime-glow);
}

.timeline-node.completed .timeline-node-dot svg { stroke: #0A0A0C; }

.timeline-node.active .timeline-node-dot {
  background: var(--surface-3);
  border-color: var(--lime);
  box-shadow: 0 0 12px var(--lime-glow);
  animation: nodePulse 2s ease-in-out infinite;
}

.timeline-node.active .timeline-node-dot svg { stroke: var(--lime); }

.timeline-node.pending .timeline-node-dot {
  background: var(--surface-2);
  border-color: var(--border);
  opacity: 0.5;
}

@keyframes nodePulse {
  0%, 100% { box-shadow: 0 0 12px var(--lime-glow); }
  50%      { box-shadow: 0 0 24px var(--lime-glow); }
}

.timeline-node-label {
  font-family: var(--font-ka);
  font-size: 10px;
  font-weight: 600;
  color: var(--text-3);
  text-align: center;
  white-space: nowrap;
}

.timeline-node.completed .timeline-node-label { color: var(--lime); }
.timeline-node.active    .timeline-node-label { color: var(--text-1); }

.timeline-node-sub {
  font-family: var(--font-num);
  font-size: 9px;
  color: var(--text-3);
  text-align: center;
  white-space: nowrap;
}

.timeline-detail {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  animation: fadeIn var(--dur-mid) var(--ease-out) both;
}

.timeline-detail-empty {
  font-family: var(--font-ka);
  font-size: 13px;
  color: var(--text-3);
  text-align: center;
  padding: 8px 0;
}

.timeline-inbody-mini {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.tim-stat {
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  padding: 10px;
  text-align: center;
  min-width: 0;
}

.tim-stat-val {
  font-family: var(--font-num);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-1);
}

.tim-stat-label {
  font-family: var(--font-ka);
  font-size: 10px;
  color: var(--text-3);
  margin-top: 2px;
}

.tim-stat-delta {
  font-family: var(--font-num);
  font-size: 11px;
  font-weight: 600;
  margin-top: 3px;
}

.tim-stat-delta.good { color: var(--teal); }
.tim-stat-delta.bad  { color: var(--red); }

/* ---------- Processing modal ---------- */
.modal-bg {
  position: fixed;
  inset: 0;
  /* Same keyboard correction, for every bottom sheet and centred modal that
     carries a field. Shortening the flex container is what moves its content
     up — no per-sheet handling needed. Zero when no keyboard is open. */
  bottom: var(--kb, 0px);
  background: rgba(10, 10, 12, 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-mid) var(--ease-out);
}

.modal-bg.show {
  opacity: 1;
  pointer-events: all;
}

.inbody-processing-card {
  width: 100%;
  max-width: 320px;
  text-align: center;
  padding: 32px 24px;
}

.inbody-proc-spinner {
  width: 48px;
  height: 48px;
  border: 3px solid var(--surface-3);
  border-top-color: var(--lime);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  margin: 0 auto 20px;
}

@keyframes spin { to { transform: rotate(360deg); } }

.inbody-proc-title {
  font-family: var(--font-ka);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-1);
  margin-bottom: 8px;
}

.inbody-proc-step {
  font-family: var(--font-ka);
  font-size: 13px;
  color: var(--text-2);
  margin-bottom: 20px;
}

.inbody-proc-steps-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
}

.proc-step {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-ka);
  font-size: 13px;
  color: var(--text-3);
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  border: 1px solid transparent;
  transition: color var(--dur-mid) var(--ease-out),
              background var(--dur-mid) var(--ease-out),
              border-color var(--dur-mid) var(--ease-out);
}

.proc-step svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: 0 0 auto;
}

.proc-step.active {
  color: var(--lime);
  background: var(--lime-dim);
  border-color: rgba(201, 245, 59, 0.2);
}

.proc-step.done {
  color: var(--text-2);
  background: var(--surface-2);
}

/* ---------- InBody history ---------- */
.inbody-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 10px;
  cursor: pointer;
  transition: border-color var(--dur-mid) var(--ease-out),
              transform var(--dur-fast) var(--ease-spring);
}

.inbody-card:active { transform: scale(0.99); }
.inbody-card:hover  { border-color: var(--border-2); }

.inbody-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  gap: 10px;
}

.inbody-card-date {
  font-family: var(--font-ka);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-1);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-width: 0;
}

.inbody-score-circle {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--lime-dim);
  border: 2px solid var(--lime);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-num);
  font-size: 14px;
  font-weight: 800;
  color: var(--lime);
  flex: 0 0 auto;
}

/* The trash sits between the date and the score circle, dim until touched —
   a delete on a body-composition test should never be the loudest thing in
   the card. 34px keeps the tap target honest without crowding the score. */
.inbody-card-del {
  /* The header is space-between with three children now; auto margin keeps the
     trash paired with the score circle instead of stranded mid-row. */
  margin-left: auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  cursor: pointer;
  padding: 0;
  transition: border-color var(--dur-mid) var(--ease-out),
              background var(--dur-mid) var(--ease-out),
              transform var(--dur-fast) var(--ease-spring);
}

.inbody-card-del svg {
  width: 15px;
  height: 15px;
  stroke: var(--text-3);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke var(--dur-mid) var(--ease-out);
}

.inbody-card-del:hover { border-color: var(--red); background: var(--red-dim); }
.inbody-card-del:hover svg { stroke: var(--red); }
.inbody-card-del:active { transform: scale(0.9); }

.inbody-card-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

.ib-stat { text-align: center; min-width: 0; }

.ib-stat-val {
  font-family: var(--font-num);
  font-size: 16px;
  font-weight: 700;
  color: var(--text-1);
}

.ib-stat-label {
  font-family: var(--font-ka);
  font-size: 10px;
  color: var(--text-3);
  margin-top: 2px;
}

.ib-stat-delta {
  font-family: var(--font-num);
  font-size: 10px;
  font-weight: 600;
  margin-top: 2px;
}

.ib-stat-delta.good { color: var(--teal); }
.ib-stat-delta.bad  { color: var(--red); }

.inbody-demo-badge {
  font-size: 10px;
  color: var(--amber);
  background: var(--amber-dim);
  border-radius: var(--radius-pill);
  padding: 2px 8px;
  font-family: var(--font-ka);
  font-weight: 600;
}

.inbody-pending-card {
  background: var(--surface);
  border: 2px dashed var(--border-2);
  border-radius: var(--radius);
  padding: 24px 16px;
  text-align: center;
  cursor: pointer;
  transition: border-color var(--dur-mid) var(--ease-out);
}

.inbody-pending-card:hover { border-color: var(--lime); }

.inbody-pending-icon svg {
  width: 30px;
  height: 30px;
  stroke: var(--text-3);
  fill: none;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  margin-bottom: 10px;
}

.inbody-pending-title {
  font-family: var(--font-ka);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-1);
  margin-bottom: 4px;
}

.inbody-pending-sub {
  font-family: var(--font-ka);
  font-size: 12px;
  color: var(--text-3);
}

.inbody-manual-link {
  margin-top: 12px;
  text-align: center;
}

/* ---------- Full detail overlay ---------- */
.inbody-detail-sheet {
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  background: var(--bg);
  min-height: 100dvh;
  /* Bug fix: without a max, the sheet grows to its content (~1450px) inside a
     position:fixed overlay, so .inbody-detail-scroll's flex:1 had no definite
     height to scroll within and everything past the first screen — segmental,
     interpretation, the edit and delete buttons — was unreachable. Pinning the
     height to the viewport gives the inner scroller something to scroll. */
  max-height: 100dvh;
  display: flex;
  flex-direction: column;
  /* Named sheetRise, not slideUp — Layer 2's evening CTA already owns slideUp
     and its keyframes carry translateX(-50%). */
  animation: pageIn var(--dur-page) var(--ease-out) both;   /* 2026-09-24: slides in from the right */
}

@keyframes sheetRise {
  from { transform: translateY(30px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}

.inbody-detail-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: calc(env(safe-area-inset-top) + 12px) 16px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}

.inbody-detail-headings { flex: 1; min-width: 0; }

.inbody-detail-header .btn-icon svg {
  width: 18px;
  height: 18px;
  stroke: var(--text-1);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.inbody-detail-title {
  font-family: var(--font-ka);
  font-size: 16px;
  font-weight: 700;
  color: var(--text-1);
}

.inbody-detail-date {
  font-family: var(--font-num);
  font-size: 12px;
  color: var(--text-2);
  margin-top: 2px;
}

.inbody-detail-scroll {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 40px;
}

/* Red text on the ghost button, not a filled red block — destructive, but it
   sits under the edit button and should not read as the primary action. */
.inbody-detail-del {
  margin-top: 8px;
  color: var(--red);
  border-color: var(--red-dim);
}

.inbody-detail-del:hover { border-color: var(--red); background: var(--red-dim); }

.inbody-detail-section { padding: 20px 16px 0; }

.inbody-detail-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

.inbody-detail-stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  min-width: 0;
}

.inbody-detail-stat-label {
  font-family: var(--font-ka);
  font-size: 11px;
  color: var(--text-3);
  margin-bottom: 4px;
}

.inbody-detail-stat-val {
  font-family: var(--font-num);
  font-size: 22px;
  font-weight: 800;
  color: var(--text-1);
}

.inbody-detail-stat-unit {
  font-family: var(--font-ka);
  font-size: 12px;
  color: var(--text-2);
  margin-left: 2px;
}

.inbody-detail-stat-delta {
  font-family: var(--font-num);
  font-size: 12px;
  font-weight: 600;
  margin-top: 4px;
}

.inbody-detail-stat-delta.good { color: var(--teal); }
.inbody-detail-stat-delta.bad  { color: var(--red); }

/* ---------- Composition bar ---------- */
.comp-bar {
  height: 20px;
  border-radius: var(--radius-pill);
  overflow: hidden;
  display: flex;
  margin-bottom: 10px;
  background: var(--surface-3);
}

.comp-bar-seg { height: 100%; transition: width var(--dur-slow) var(--ease-spring); }

.comp-bar-legend {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  font-family: var(--font-ka);
  font-size: 11px;
  color: var(--text-2);
}

.comp-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 4px;
}

/* ---------- Segmental ---------- */
.segmental-row {
  display: grid;
  grid-template-columns: 74px 1fr 72px;
  align-items: center;
  gap: 10px;
}

.seg-label {
  font-family: var(--font-ka);
  font-size: 12px;
  color: var(--text-2);
}

.seg-bars { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

.seg-bar-wrap {
  height: 5px;
  background: var(--surface-3);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.seg-bar-fill {
  height: 100%;
  border-radius: var(--radius-pill);
  transition: width var(--dur-slow) var(--ease-spring);
}

.seg-vals {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-family: var(--font-num);
  font-size: 11px;
  font-weight: 600;
  text-align: right;
}

.seg-lean { color: var(--teal); }
.seg-fat  { color: var(--red); }

/* ---------- Weight chart ---------- */
.chart-range-pills { display: flex; gap: 4px; }

.chart-range-btn {
  font-family: var(--font-num);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 4px 10px;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-spring);
}

.chart-range-btn:active { transform: scale(0.94); }

.chart-range-btn.active {
  color: var(--lime);
  background: var(--lime-dim);
  border-color: rgba(201, 245, 59, 0.3);
}

.chart-wrap { margin: 12px 0 8px; position: relative; }

/* var() does not resolve inside SVG presentation attributes, so every chart
   colour is set here as a real CSS declaration instead. */
.chart-line   { stroke: var(--teal); fill: none; }
.chart-avg    { stroke: var(--lime); fill: none; }
.chart-dot    { fill: var(--teal); stroke: var(--bg); }
.chart-grid   { stroke: rgba(255, 255, 255, 0.05); }
.chart-axis   { fill: rgba(255, 255, 255, 0.3); font-family: var(--font-num); font-size: 9px; }
.chart-grad-a { stop-color: #00DDB3; stop-opacity: 0.15; }
.chart-grad-b { stop-color: #00DDB3; stop-opacity: 0; }

.chart-empty {
  font-family: var(--font-ka);
  font-size: 13px;
  color: var(--text-3);
  text-align: center;
  padding: 40px 0;
}

.chart-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  font-family: var(--font-ka);
  font-size: 11px;
  color: var(--text-2);
}

.chart-legend-item { display: flex; align-items: center; gap: 6px; }

/* ---------- Sticky upload ---------- */
.sticky-upload {
  position: fixed;
  bottom: calc(72px + env(safe-area-inset-bottom) + 12px);
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% - 40px);
  max-width: 440px;
  z-index: 40;
}

.sticky-upload .btn svg {
  width: 16px;
  height: 16px;
  stroke: #0A0A0C;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- Manual entry form ---------- */
.manual-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

.manual-field { min-width: 0; }

.manual-field-label {
  font-family: var(--font-ka);
  font-size: 11px;
  color: var(--text-3);
  margin-bottom: 4px;
}

.manual-input {
  width: 100%;
  font-family: var(--font-num);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-1);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  outline: none;
}

.manual-input:focus { border-color: var(--lime); }
.manual-input::placeholder { color: var(--text-3); font-weight: 400; }

.sheet-scroll {
  /* Shrinks with the keyboard too, or the InBody form's scroller stays 62% of
     the FULL screen and pushes the sheet's own buttons back off the top.
     The max() floor stops it collapsing to nothing on a small phone. */
  max-height: max(120px, min(62dvh, calc(100dvh - var(--kb, 0px) - 200px)));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 calc(-1 * var(--pad));
  padding: 0 var(--pad);
}

/* ============================================================
   The InBody cycle card (2026-09-18)
   ============================================================
   The full version of the day screen's .ib-row. Same five stages and the same
   --stage contract, so a stage is one rule here too rather than five copies.
   The stage classes (.ib-sleeping … .ib-stale) are shared with the row and
   declared in css/03-day.css — only the geometry differs. */
.ib-card {
  padding: 16px;
  transition: background var(--dur-mid) var(--ease-out),
              border-color var(--dur-mid) var(--ease-out);
}

.ib-card-top { display: flex; align-items: center; gap: 14px; }

.ib-card-ring { position: relative; width: 56px; height: 56px; flex: 0 0 auto; }
.ib-card-ring svg { width: 100%; height: 100%; display: block; }
.ib-card-track { stroke: var(--surface-3); }
.ib-card-fill  { stroke: var(--stage); }
.ib-card-over  { stroke: var(--red); }
.ib-card-ring-n {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  font-weight: 700;
  color: var(--text-1);
}

.ib-card-head { min-width: 0; flex: 1; }
.ib-card-kicker {
  font-family: var(--font-num);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: var(--stage);
  opacity: 0.85;
  margin-bottom: 3px;
}
.ib-card-title {
  font-size: 17px;
  font-weight: 700;
  color: var(--text-1);
  letter-spacing: -0.2px;
}
.ib-card-sub { font-size: 12px; color: var(--text-2); margin-top: 4px; }
.ib-card-sub .num { font-weight: 700; color: var(--stage); }
.ib-card.ib-overdue .ib-card-sub .num { color: var(--red); }

.ib-card-body {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.ib-card-note { font-size: 12.5px; line-height: 1.5; color: var(--text-2); }
.ib-card-note-2 { margin-top: 6px; color: var(--text-3); }
.ib-card-btn { margin-top: 12px; }
.ib-card-later { margin-top: 8px; }

/* ---- the stale state: a baseline too old to measure from ----
   Amber like 'ready', because the action is the same one — upload a test — but
   without the red: nothing is wrong, the app simply has nothing to count from.
   Declared here rather than beside the other stages because the row's version
   is text-only and needs no colour of its own. */
.ib-row.ib-stale,
.ib-card.ib-stale {
  --stage: var(--amber);
  border-color: rgba(232, 134, 58, 0.28);
  background: linear-gradient(180deg, rgba(232, 134, 58, 0.07), transparent 70%), var(--surface);
}

/* ============================================================
   The chapter close (2026-09-18)
   ============================================================
   Lives inside .wk-hist-sheet, so it inherits that sheet's max-height:100dvh
   and its scroller rather than cloning them. */
.cs { padding: 28px var(--pad) 32px; }

.cs-head { text-align: center; margin-bottom: 4px; }
.cs-kicker {
  font-family: var(--font-num);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--lime);
  opacity: 0.85;
  margin-bottom: 12px;
}
.cs-cycles { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 10px; }
.cs-num { font-size: 52px; font-weight: 800; line-height: 1; letter-spacing: -2px; }
.cs-num.old { color: var(--text-3); }
.cs-num.new { color: var(--lime); text-shadow: 0 0 30px rgba(201, 245, 59, 0.35); }
.cs-arrow { width: 26px; height: 26px; stroke: var(--text-3); stroke-width: 2; fill: none; }
.cs-range { font-family: var(--font-num); font-size: 12.5px; color: var(--text-2); }
.cs-range .num { color: var(--text-1); font-weight: 600; }

/* The first test has no arrows and no deltas — there is nothing to compare it
   to, and drawing a 1 → 2 with an empty left side would be a lie about it. */
.cs-first-title {
  font-size: 22px; font-weight: 700; color: var(--text-1);
  letter-spacing: -0.3px; margin-bottom: 8px;
}
.cs-first-sub {
  font-size: 12.5px; line-height: 1.55; color: var(--text-2);
  text-align: center; margin: 16px 0 4px;
}

.cs-label { display: flex; align-items: center; gap: 10px; margin: 26px 0 14px; }
.cs-label span { font-size: 11px; font-weight: 700; color: var(--text-2); white-space: nowrap; }
.cs-label::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.cs-body-card {
  background: linear-gradient(180deg, rgba(201, 245, 59, 0.05), transparent 60%), var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 18px 16px 14px;
}
.cs-hero { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.cs-hero-cell { text-align: center; }
.cs-hero-val { font-size: 26px; font-weight: 800; letter-spacing: -0.8px; line-height: 1; }
.cs-hero-val em {
  font-family: var(--font-ka); font-style: normal; font-size: 11px;
  font-weight: 500; color: var(--text-2); margin-left: 2px;
}
.cs-hero-lab { font-size: 10.5px; color: var(--text-2); margin-top: 5px; }
/* Green is the RIGHT DIRECTION, not the sign: fat going down and muscle going
   up are both progress, so the colour follows the meaning. */
.cs-delta {
  display: inline-block; margin-top: 7px; font-size: 12px; font-weight: 800;
  padding: 3px 9px; border-radius: var(--radius-pill);
}
.cs-delta.good { color: var(--lime); background: var(--lime-dim); }
.cs-delta.bad  { color: var(--red);  background: var(--red-dim); }

.cs-score {
  display: flex; align-items: center; gap: 12px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border);
}
.cs-score-txt { flex: 1; min-width: 0; }
.cs-score-lab { font-size: 12px; color: var(--text-1); font-weight: 600; }
.cs-score-sub { font-size: 11px; color: var(--text-2); margin-top: 3px; }
.cs-score-sub b { color: var(--lime); font-weight: 700; }

/* The wire between her body and the work. This is the point of the screen: four
   weeks of logging is what bought the three numbers above it. */
.cs-link { display: flex; flex-direction: column; align-items: center; gap: 6px; margin: 18px 0 6px; }
.cs-link-line { width: 1px; height: 18px; background: linear-gradient(180deg, var(--border), var(--lime)); }
.cs-link-txt {
  font-family: var(--font-num); font-size: 10px; letter-spacing: 0.8px;
  text-transform: uppercase; color: var(--text-3);
}

.cs-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.cs-tile {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 13px; position: relative; overflow: hidden;
}
/* Each tile is lit in the colour that thing already wears elsewhere in the app.
   The last stop is rgba(...,0), never `transparent` — transparent is transparent
   BLACK and a coloured gradient fading to it goes through grey. Same trap the
   supplement glow cards document. */
.cs-tile::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 44px;
  background: radial-gradient(70% 100% at 50% 100%, var(--glow, transparent), transparent 72%);
  pointer-events: none;
}
.cs-tile-val { font-size: 22px; font-weight: 800; letter-spacing: -0.6px; line-height: 1; position: relative; }
.cs-tile-val small { font-size: 12px; font-weight: 600; color: var(--text-2); margin-left: 1px; }
.cs-tile-lab { font-size: 10.5px; color: var(--text-2); margin-top: 6px; position: relative; }

/* InBody's own prescription — read off every sheet since Layer 3, shown nowhere
   until now. */
.cs-presc {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 4px 14px;
}
.cs-presc-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 0; border-bottom: 1px solid var(--border);
}
.cs-presc-row:last-child { border-bottom: none; }
.cs-presc-lab { font-size: 12.5px; color: var(--text-2); }
.cs-presc-val { font-size: 15px; font-weight: 700; color: var(--text-1); }
.cs-presc-val em {
  font-family: var(--font-ka); font-style: normal; font-size: 11px;
  font-weight: 500; color: var(--text-2); margin-left: 2px;
}

.cs-next {
  margin-top: 22px; padding: 13px 14px; text-align: center;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 12px; color: var(--text-2);
}
.cs-btn { margin-top: 16px; }

/* The way back into a past cycle's chapter close, from its history card.
   2026-09-24: it wears .btn-soft (css/02-base.css) now — a solid lime button
   labelled S.ibCycleOpen. Only the spacing is its own; any look set here would
   win over .btn-soft, which is earlier in the cascade. */
.inbody-card-cycle { margin-top: 14px; }

/* The water balance — the one InBody number that explains a weight jump which
   is not fat, so it gets a line of context rather than a cell in the grid. */
.ib-water {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin: 0 16px;
}
.ib-water-val {
  font-size: 28px;
  font-weight: 800;
  color: var(--c-water);
  letter-spacing: -0.5px;
  line-height: 1;
}
.ib-water-note { font-size: 11.5px; line-height: 1.5; color: var(--text-2); margin-top: 8px; }

/* The machine's own words — body type and the two status verdicts. They arrive
   as free text from the sheet, so they are tags rather than numbers. */
.ib-verdict { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 16px 0; }
.ib-verdict-tag {
  font-family: var(--font-num);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 5px 11px;
}

/* The analysis continuing inside the chapter close. Its sections carry their own
   16px padding (.inbody-detail-section), so this cancels the .cs padding around
   them rather than letting the two stack into a 36px gutter. */
.cs-analysis { margin: 22px calc(-1 * var(--pad)) 0; }
.cs-analysis .inbody-detail-section:first-child { padding-top: 0; }

/* ---- the healthy band (2026-09-18) ----
   A target weight is one number; this is the range around it, and where she
   actually sits on it. */
.ib-band { margin-bottom: 16px; }
.ib-band:last-of-type { margin-bottom: 0; }

.ib-band-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}
.ib-band-lab { font-size: 12.5px; color: var(--text-2); }
.ib-band-state {
  font-family: var(--font-num);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
}
.ib-band-state.is-in    { color: var(--lime);  background: var(--lime-dim); }
.ib-band-state.is-over  { color: var(--amber); background: var(--amber-dim); }
.ib-band-state.is-under { color: var(--amber); background: var(--amber-dim); }

.ib-band-rail {
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: var(--surface-3);
  overflow: visible;
}
/* The healthy stretch occupies the middle two thirds of the rail; the quarter
   of a band either side is the room a value outside the range lands in. */
.ib-band-good {
  position: absolute;
  left: 16.67%;
  right: 16.67%;
  top: 0;
  bottom: 0;
  border-radius: 3px;
  background: var(--lime-dim);
  border: 1px solid rgba(201, 245, 59, 0.25);
}
.ib-band-mark {
  position: absolute;
  top: 50%;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: var(--text-1);
  box-shadow: 0 0 0 3px var(--surface), 0 0 10px rgba(0, 0, 0, 0.6);
}

.ib-band-ends {
  display: flex;
  justify-content: space-between;
  margin-top: 7px;
  font-size: 10.5px;
  color: var(--text-3);
}
.ib-band-now { color: var(--text-1); font-weight: 700; }

.ib-band-note {
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-3);
  margin-top: 12px;
}

/* ============================================================
   THE INBODY ANALYSIS — rebuilt 2026-09-18
   Last in the sheet on purpose: several selectors below restyle blocks declared
   earlier in this file, and source order is what decides the cascade (rule 2).
   ============================================================ */

/* ---------- section chrome ---------- */
.ib-sec-h {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 11px;
}

.ib-sec-x {
  font-size: 10.5px;
  color: var(--text-3);
  flex: 0 0 auto;
}

/* ---------- the delta chip ---------- */
.ib-chip {
  font-family: var(--font-num);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  padding: 3px 7px;
  border-radius: var(--radius-pill);
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.ib-chip.good { color: var(--lime); background: var(--lime-dim); }
.ib-chip.bad  { color: var(--amber); background: var(--amber-dim); }
.ib-chip.flat { color: var(--text-3); background: rgba(255, 255, 255, 0.05); }

/* ---------- the hero: the score, and what moved ---------- */
.ib-hero {
  margin: 16px;
  padding: 20px 18px 18px;
  border-radius: var(--radius-lg);
  /* Green-black rather than flat --surface: this is the one card on the screen
     that is about her result rather than about a number. */
  background: linear-gradient(160deg, #1a2118 0%, var(--surface) 58%);
  border: 1px solid var(--border);
  position: relative;
  overflow: hidden;
}

.ib-hero::after {
  content: '';
  position: absolute;
  top: -70px;
  right: -60px;
  width: 210px;
  height: 210px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--lime-dim), transparent 68%);
  pointer-events: none;
}

.ib-hero-top {
  display: flex;
  align-items: center;
  gap: 18px;
  position: relative;
}

.ib-ring { width: 104px; height: 104px; flex: 0 0 auto; position: relative; }
.ib-ring svg { display: block; transform: rotate(-90deg); }

.ib-ring-track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.07);
  stroke-width: 8;
}

.ib-ring-fill {
  fill: none;
  stroke: url(#ibRingGrad);
  stroke-width: 8;
  stroke-linecap: round;
  transition: stroke-dashoffset var(--dur-slow) var(--ease-out);
}

.ib-ring-in {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
}

.ib-ring-n {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text-1);
}

.ib-ring-l {
  font-family: var(--font-ka);
  font-size: 9.5px;
  color: var(--text-3);
  margin-top: 5px;
}

.ib-hero-lines {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.ib-hero-line { display: flex; align-items: baseline; gap: 8px; }

.ib-hero-k {
  font-family: var(--font-ka);
  font-size: 11.5px;
  color: var(--text-2);
  width: 56px;
  flex: 0 0 auto;
}

.ib-hero-v {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text-1);
}

.ib-hero-u {
  font-family: var(--font-ka);
  font-size: 11px;
  color: var(--text-3);
  margin-left: 1px;
}

/* The score of every test up to this one — a direction, not a number. */
.ib-spark {
  margin-top: 16px;
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 34px;
  position: relative;
}

.ib-spark-b {
  flex: 1;
  border-radius: 3px 3px 2px 2px;
  background: rgba(255, 255, 255, 0.14);
}

.ib-spark-b.on { background: linear-gradient(180deg, var(--lime), var(--lime-glow)); }

.ib-spark-l {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 9.5px;
  color: var(--text-3);
}

/* ---------- the three that move ---------- */
.ib-board {
  display: flex;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.ib-board-c {
  flex: 1;
  min-width: 0;
  padding: 14px 8px 13px;
  text-align: center;
}

.ib-board-c + .ib-board-c { border-left: 1px solid var(--border); }

.ib-board-k {
  font-family: var(--font-ka);
  font-size: 10.5px;
  color: var(--text-3);
  margin-bottom: 7px;
  /* The three labels are long Georgian words in a third of the width each, so
     they wrap rather than clip and the cells keep the same height. */
  line-height: 1.25;
  min-height: 26px;
}

.ib-board-v {
  font-size: 25px;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--text-1);
}

.ib-board-u {
  font-family: var(--font-ka);
  font-size: 10px;
  font-weight: 600;
  color: var(--text-3);
  margin-left: 1px;
}

.ib-board-d { margin-top: 8px; }

/* ---------- the ones that sit still ---------- */
.ib-rows {
  margin-top: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

/* A GRID, not a flex row, and this is what makes the card read as a column of
   numbers rather than a ragged list: the figure gets a right-aligned column of
   its own, the unit a fixed one beside it, and the change the last. With the
   unit inside the value the right edge moved with every label. */
.ib-row {
  display: grid;
  grid-template-columns: 1fr auto minmax(24px, auto);
  align-items: center;
  gap: 0 8px;
  padding: 12px 14px;
}

/* A grid sizes its columns across every row, so the value column is as wide as
   the widest figure in the card and the unit column as wide as the widest unit
   - which is exactly what lines them all up. */
.ib-rows.has-delta .ib-row,
.ib-fold-b.has-delta .ib-row { grid-template-columns: 1fr auto minmax(24px, auto) 52px; }

/* Nothing to compare against: the column goes, rather than sitting empty and
   pushing every figure into the middle of the card. */
.ib-rows:not(.has-delta) .ib-row-d,
.ib-fold-b:not(.has-delta) .ib-row-d { display: none; }

.ib-row + .ib-row { border-top: 1px solid var(--border); }

.ib-row-k {
  min-width: 0;
  font-family: var(--font-ka);
  font-size: 12.5px;
  color: var(--text-2);
}

.ib-row-v {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-1);
  text-align: right;
  white-space: nowrap;
}

/* The top of a scale, not a unit: visceral fat is a level out of twenty. */
.ib-row-max {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-3);
  margin-left: 1px;
}

.ib-row-u {
  font-family: var(--font-ka);
  font-size: 10px;
  font-weight: 600;
  color: var(--text-3);
  /* Its own column, left-aligned, so every unit in the card starts at the same
     x and the digits to its left end at the same one. */
  text-align: left;
}

.ib-row-d { text-align: right; overflow: hidden; }

/* ---------- composition ---------- */
.ib-comp {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 14px 13px;
}

/* Restyles the Layer 3 block above: a thicker bar with real gaps between the
   four segments, because butted edge to edge they read as one striped object. */
.ib-comp .comp-bar {
  height: 16px;
  gap: 3px;
  background: none;
  overflow: visible;
  border-radius: 0;
  margin-bottom: 14px;
}

.ib-comp .comp-seg { border-radius: 4px; transition: width var(--dur-slow) var(--ease-spring); }
.ib-comp .comp-seg:first-child { border-radius: 8px 4px 4px 8px; }
.ib-comp .comp-seg:last-child  { border-radius: 4px 8px 8px 4px; }

.comp-legend {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 12px;
}

.comp-leg { display: flex; align-items: center; gap: 8px; min-width: 0; }

.ib-comp .comp-dot {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  margin-right: 0;
  flex: 0 0 auto;
}

.comp-leg-k {
  flex: 1;
  min-width: 0;
  font-family: var(--font-ka);
  font-size: 11.5px;
  color: var(--text-2);
}

.comp-leg-v {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-1);
  white-space: nowrap;
}

.comp-leg-s {
  font-size: 10px;
  font-weight: 500;
  color: var(--text-3);
  margin-left: 3px;
}

/* ---------- the segmental figure ---------- */
.ib-seg {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px 14px 16px;
}

.ib-seg-toggle {
  display: flex;
  gap: 4px;
  background: var(--surface-2);
  border-radius: var(--radius-pill);
  padding: 3px;
  margin: 10px 0 4px;
}

.ib-seg-tb {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--text-2);
  font-family: var(--font-ka);
  font-size: 11.5px;
  font-weight: 600;
  padding: 7px 4px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background var(--dur-mid) var(--ease-out), color var(--dur-mid) var(--ease-out);
}

.ib-seg-tb.on {
  background: var(--surface-3);
  color: var(--text-1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

/* ---------- the body figure ----------
   Capped rather than full width. The viewBox is 200x380, so stretching it to a
   330px card would render the figure 627px tall - three quarters of an 844px
   screen for one card. At 280 it lands around 530 and the text inside it, which
   scales with the viewBox, stays in the 12-16px range the rest of the app uses. */
.ib-body {
  display: block;
  width: 100%;
  /* 2026-09-24: 300, was 280 — the anatomical viewBox is 260x442, wider for the
     pill gutters, and at 300 it lands ~510px tall, a little under the old 532. */
  max-width: 300px;
  height: auto;
  margin: 2px auto 0;
  /* One colour family at a time, and the view decides which. The tokens move
     together: the ground a segment holding nothing lands on, the colour the
     heaviest one reaches, that colour as a triplet for the glow, the colour
     the pills print in, and the look of the body underneath. */
  --seg-lo:  var(--seg-lean-lo);
  --seg-hi:  var(--seg-lean-hi);
  --seg-rgb: var(--seg-lean-rgb);
  --seg-ink: var(--seg-lean-hi);
  --seg-line:   rgba(0, 0, 0, 0.42);
  --seg-ground: #3a3a40;
  --seg-edge:   transparent;
  /* Low layer's opacity is lo-a + f * lo-b. Muscle keeps every segment plainly
     green (it IS all muscle); fat lets a near-empty segment fade to an outline. */
  --seg-lo-a: 0.7;
  --seg-lo-b: 0.3;
}

/* The THERMAL look: a line drawing on a dark ground, heat where the fat is. */
.ib-body.is-fat {
  --seg-lo:  var(--ib-warm, var(--seg-fat-lo));
  --seg-hi:  var(--ib-hot, var(--seg-fat-hi));
  --seg-rgb: var(--seg-fat-rgb);
  --seg-ink: var(--seg-fat-ink);
  --seg-line:   rgba(255, 255, 255, 0.16);
  --seg-ground: #17171a;
  --seg-edge:   rgba(255, 255, 255, 0.24);
  --seg-lo-a: 0.05;
  --seg-lo-b: 0.85;
}

/* The body and the jaw line. They carry no measurement, so they never take
   the accent - the figure would otherwise claim the machine weighed her head. */
.ib-sil {
  fill: var(--seg-ground);
  stroke: var(--seg-edge);
  stroke-width: 1;
  transition: fill var(--ib-seg-morph) var(--ease-out),
              stroke var(--ib-seg-morph) var(--ease-out);
}

.ib-jaw {
  fill: none;
  stroke: var(--seg-line);
  stroke-width: 1.2;
  stroke-linecap: round;
}

/* Layer 1 of the interpolation: the low colour, painted once. It takes the
   fraction too, so an empty segment still reads as part of a body rather than
   as a hole in one. It also carries the dark seams between muscles. */
.ib-zone-lo {
  fill: var(--seg-lo);
  fill-opacity: calc(var(--seg-lo-a) + var(--f, 0.3) * var(--seg-lo-b));
  stroke: var(--seg-line);
  stroke-width: 1;
  pointer-events: none;
  transition: fill var(--ib-seg-morph) var(--ease-out),
              fill-opacity var(--ib-seg-morph) var(--ease-out);
}

/* Layer 2: the high colour over it at the fraction. Fading one hex over another
   IS the interpolation between them, and it needs no color-mix() - the function
   01-tokens.css avoids by name.

   The three numbers are Giorgi's brief verbatim: fill at the intensity, stroke
   at 0.3 + 70% of it, and a glow whose radius runs 4 -> 20px and whose opacity
   runs 0.2 -> 0.7, so the heaviest segment is the brightest thing on the card. */
.ib-zone {
  fill: var(--seg-hi);
  /* The brief's intensity, held back from 1. At a flat var(--f) the trunk - which
     is ALWAYS the heaviest segment, so always 1 - paints as an opaque lime slab
     with the white figure on it barely readable. At 0.78 it is still plainly the
     brightest thing on the card and the low layer still tints it. */
  fill-opacity: calc(var(--f, 0.3) * 0.78);
  /* 2026-09-24: no outline and a small glow — the figure is sixteen muscles
     now, not five blocks, and a 1.6 lit stroke on each read as a wireframe. */
  stroke: none;
  cursor: pointer;
  filter: drop-shadow(0 0 calc(1px + var(--f, 0.3) * 4px)
          rgba(var(--seg-rgb), calc(0.1 + var(--f, 0.3) * 0.35)));
  transition: fill var(--ib-seg-morph) var(--ease-out),
              fill-opacity var(--ib-seg-morph) var(--ease-out),
              stroke var(--ib-seg-morph) var(--ease-out),
              stroke-opacity var(--ib-seg-morph) var(--ease-out),
              filter var(--ib-seg-morph) var(--ease-out);
}

/* The tapped limb lifts out of the figure rather than the label alone pointing
   at it - both halves of an arm light, because both halves are one measurement. */
.ib-zone.is-tapped {
  fill-opacity: calc(0.30 + var(--f, 0.3) * 0.5);
  stroke: rgba(255, 255, 255, 0.7);
  stroke-width: 1;
}

/* The heat-map is soft-edged: the mockup's blur, on both layers. */
.ib-body.is-fat .ib-zone,
.ib-body.is-fat .ib-zone-lo { filter: blur(1.1px); }
.ib-body.is-fat .ib-zone { fill-opacity: calc(var(--f, 0.3) * 0.95); }

/* The trunk's figure sits ON the brightest shape on the card, so it carries a
   dark halo: paint-order puts the stroke BEHIND the fill, which is the only way
   to outline SVG text without eating into the letterforms. White on lime is the
   case that needs it; it costs the red view nothing. */
.ib-zval {
  font-family: var(--font-num);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -0.02em;
  fill: var(--text-1);
  paint-order: stroke fill;
  stroke: rgba(10, 10, 12, 0.55);
  stroke-width: 3;
  stroke-linejoin: round;
  pointer-events: none;
}

.ib-zval.big { font-size: 19px; }

.ib-zunit {
  font-family: var(--font-ka);
  font-size: 7px;
  font-weight: 600;
  fill: rgba(255, 255, 255, 0.7);
  paint-order: stroke fill;
  stroke: rgba(10, 10, 12, 0.5);
  stroke-width: 2;
  stroke-linejoin: round;
  pointer-events: none;
}

/* ---------- the limb pills ----------
   Drawn INSIDE the svg, not positioned over it in HTML: in the viewBox they
   scale with the figure and cannot leave the card at any screen width. They sit
   in the gutters the arms leave either side. */
.ib-pill { cursor: pointer; }

.ib-pill rect {
  fill: var(--sup-card-bg);
  stroke: var(--border-2);
  stroke-width: 0.5;
}

.ib-pill-v {
  font-family: var(--font-num);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.02em;
  fill: var(--seg-ink);
  transition: fill var(--ib-seg-morph) var(--ease-out);
}

.ib-pill-u {
  font-family: var(--font-ka);
  font-size: 6.5px;
  font-weight: 600;
  fill: var(--text-3);
}

/* ---------- the tap label ----------
   One group, moved and refilled on tap rather than five drawn and hidden. */
.ib-tap {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
}

/* NOT the shared fadeIn, and this one bites silently: fadeIn carries a
   translateY, a CSS transform beats an SVG transform ATTRIBUTE, and the label is
   positioned by exactly such an attribute - it would be thrown to the top-left
   corner of the viewBox for the length of the animation. Opacity only. */
.ib-body.has-tap .ib-tap {
  visibility: visible;
  animation: ibTapIn var(--dur-mid) var(--ease-out) both;
}

@keyframes ibTapIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.ib-tap rect {
  fill: var(--surface-3);
  stroke: var(--border-2);
  stroke-width: 0.5;
}

.ib-tap-n {
  font-family: var(--font-ka);
  font-size: 9px;
  font-weight: 600;
  fill: var(--text-2);
}

.ib-tap-v {
  font-family: var(--font-num);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.02em;
  fill: var(--text-1);
}

.ib-tap-u {
  font-family: var(--font-ka);
  font-size: 7.5px;
  font-weight: 600;
  fill: var(--text-3);
}

/* ---------- what the machine says ---------- */
.ib-rx {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.ib-rx-r {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
}

.ib-rx-r + .ib-rx-r { border-top: 1px solid var(--border); }

.ib-rx-ic {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.05);
  --rx: var(--lime);
}

.ib-rx-ic svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: var(--rx);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ib-rx-k {
  flex: 1;
  min-width: 0;
  font-family: var(--font-ka);
  font-size: 12.5px;
  color: var(--text-2);
}

.ib-rx-v {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--text-1);
  white-space: nowrap;
}

.ib-rx-u {
  font-family: var(--font-ka);
  font-size: 10px;
  font-weight: 600;
  color: var(--text-3);
  margin-left: 2px;
}

.ib-rx .ib-verdict {
  margin: 0;
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.015);
}

/* ---------- healthy range + water ---------- */
.ib-band {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 15px 14px;
  margin-bottom: 10px;
}

.ib-band:last-of-type { margin-bottom: 0; }

/* Room for the value bubble, which rides above the marker. 36px, not 26:
   a value at the right-hand end of the rail puts the bubble under the state
   pill, and at 26 the two overlapped. */
.ib-band-top { margin-bottom: 36px; }

.ib-band-rail {
  position: relative;
  height: 8px;
  border-radius: 4px;
  background: var(--surface-3);
  overflow: visible;
}

.ib-band-good {
  border-radius: 4px;
  background: linear-gradient(90deg, var(--lime-glow), var(--teal-dim));
}

.ib-band-mark {
  width: 14px;
  height: 14px;
  box-shadow: 0 0 0 3px var(--surface), 0 2px 8px rgba(0, 0, 0, 0.6);
}

.ib-band-bub {
  position: absolute;
  bottom: 16px;
  transform: translateX(-50%);
  font-size: 11px;
  font-weight: 800;
  color: var(--text-1);
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  padding: 3px 7px;
  border-radius: 7px;
  white-space: nowrap;
}

.ib-water {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 15px 14px;
}

.ib-water-top {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.ib-water-val {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  color: #3B82F6;
}

.ib-water-note {
  font-family: var(--font-ka);
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--text-3);
  margin-top: 11px;
}

/* ---------- the extras, folded ---------- */
.ib-fold {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.ib-fold-h {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px;
  cursor: pointer;
  user-select: none;
}

.ib-fold-t {
  flex: 1;
  min-width: 0;
  font-family: var(--font-ka);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2);
}

.ib-fold-n { font-size: 10.5px; color: var(--text-3); }

.ib-fold-c {
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  transition: transform var(--dur-mid) var(--ease-out);
}

.ib-fold.open .ib-fold-c { transform: rotate(180deg); }

.ib-fold-c svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: var(--text-3);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The file has no max-height transitions anywhere; expansion is a swap plus
   fadeIn, the .weight-form idiom. */
.ib-fold-b { display: none; border-top: 1px solid var(--border); }
.ib-fold.open .ib-fold-b { display: block; animation: fadeIn var(--dur-mid) var(--ease-out) both; }

/* A glow is a translucent wash, which is the effect this setting opts out of -
   the same call the supplement cards made. The figure keeps its colour and its
   outline, so nothing about the reading is lost with the light. */
@media (prefers-reduced-transparency: reduce) {
  .ib-zone { filter: none; }
}

/* ---- the machine's verdicts, lit (2026-09-18) ----
   Three grey chips gave "Athletic Shape" less weight than the units beside the
   numbers. They carry their meaning now, in .ib-band-state's colours — the
   healthy band is directly above them and lime/amber already mean in-range and
   outside-it there. A tag whose wording the classifier does not recognise keeps
   the neutral base below and is styled by nothing here. */
.ib-verdict-tag.is-in {
  color: var(--lime);
  background: var(--lime-dim);
  border-color: rgba(201, 245, 59, 0.30);
  box-shadow: 0 0 14px rgba(201, 245, 59, 0.14);
}
.ib-verdict-tag.is-over,
.ib-verdict-tag.is-under {
  color: var(--amber);
  background: var(--amber-dim);
  border-color: rgba(232, 134, 58, 0.32);
  box-shadow: 0 0 14px rgba(232, 134, 58, 0.14);
}

/* A glow is a translucent wash, which is the effect this setting opts out of —
   the colour stays, it is only the halo that goes. */
@media (prefers-reduced-transparency: reduce) {
  .ib-verdict-tag.is-in,
  .ib-verdict-tag.is-over,
  .ib-verdict-tag.is-under { box-shadow: none; }
}

/* ============================================================
   The progress dashboard (2026-09-23) — the reference screen Giorgi sent:
   a period switcher, calories bars, the weight line, streak + goal tiles,
   and three insights. Built by renderProgDash() in js/06-progress.js.
   ============================================================ */
#tab-progress { --pd-stagger: 40ms; }

.pd-card {
  background: var(--surface-flat);
  border: 1px solid var(--hdr-btn);
  border-radius: 18px;
  padding: 16px 16px 12px;
}

/* ---- the switcher: four steps, one lime pill sliding between them ---- */
.pd-switch {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--surface-flat);
  border: 1px solid var(--hdr-btn);
}
.pd-switch-ind {
  position: absolute;
  top: 4px; bottom: 4px; left: 4px;
  width: calc((100% - 8px) / 4);
  border-radius: var(--radius-pill);
  background: var(--lime);
  box-shadow: 0 0 18px rgba(201, 245, 59, 0.28);
  transform: translateX(calc(var(--pd-i, 0) * 100%));
  transition: transform var(--dur-mid) var(--ease-spring);
}
.pd-seg {
  position: relative;
  z-index: 1;
  border: none;
  background: none;
  padding: 9px 4px;
  font-family: var(--font-ka);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--dur-mid) var(--ease-out);
}
.pd-seg.active { color: var(--bg); }

/* ---- card head: title, big number, and the "vs previous" chip ---- */
.pd-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.pd-head-l { min-width: 0; }
.pd-title {
  font-family: var(--font-ka);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 4px;
}
.pd-big-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px; }
.pd-big {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--text-1);
}
.pd-unit {
  font-family: var(--font-ka);
  font-size: 12px;
  color: var(--text-2);
}
.pd-unit-lead { align-self: center; }
.pd-unit-block { display: block; margin-top: 2px; }

.pd-vs {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex: 0 0 auto;
  text-align: right;
}
.pd-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  padding: 4px 9px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 700;
  background: var(--surface-3);
  color: var(--text-2);
}
.pd-chip-u { font-family: var(--font-ka); font-weight: 600; font-size: 11px; }
.pd-chip.is-good, .pd-chip.is-in   { background: var(--lime-dim);  color: var(--lime); }
.pd-chip.is-bad,  .pd-chip.is-over { background: var(--amber-dim); color: var(--amber); }
.pd-vs-l { font-family: var(--font-ka); font-size: 11px; color: var(--text-3); }

.pd-hint {
  font-family: var(--font-ka);
  font-size: 12px;
  color: var(--text-3);
  text-align: center;
  margin-top: 2px;
}

/* ---- the two charts ---- */
.pd-chart { display: block; width: 100%; height: auto; overflow: visible; }
.pd-grid   { stroke: rgba(255, 255, 255, 0.05); stroke-width: 1; }
.pd-target { stroke: rgba(255, 255, 255, 0.32); stroke-width: 1; stroke-dasharray: 4 4; }
.pd-yl { fill: var(--text-3); font-size: 10px; }
.pd-yl-target { fill: var(--lime); font-weight: 700; }
.pd-xl { fill: var(--text-3); font-size: 10.5px; }
.pd-xl .pd-ka { font-family: var(--font-ka); }
.pd-xl .num   { font-family: var(--font-num); }

/* Bars grow up from the axis in a stagger; the colour is the scoring range. */
.pd-bar {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: pdGrow var(--dur-slow) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--pd-stagger));
}
.pd-bar.is-in    { fill: var(--lime); }
.pd-bar.is-over  { fill: var(--amber); }
.pd-bar.is-under { fill: rgba(201, 245, 59, 0.38); }
.pd-bar.is-none  { fill: rgba(255, 255, 255, 0.07); animation: none; }
.pd-bar.is-now   { filter: drop-shadow(0 0 6px rgba(201, 245, 59, 0.55)); }
.pd-bar.is-over.is-now { filter: drop-shadow(0 0 6px rgba(232, 134, 58, 0.6)); }
@keyframes pdGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.pd-line { fill: none; stroke: var(--lime); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.pd-wgrad-a { stop-color: #C9F53B; stop-opacity: 0.18; }
.pd-wgrad-b { stop-color: #C9F53B; stop-opacity: 0; }
.pd-dot { fill: var(--lime); stroke: var(--surface-flat); stroke-width: 2; }
.pd-dot.is-last { filter: drop-shadow(0 0 6px rgba(201, 245, 59, 0.7)); }

.pd-empty { padding: 8px 0 14px; }

/* .pd-more became the shared .more-pill (css/02-base.css) on 2026-09-24. */

/* ---- the tiles ---- */
.pd-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.pd-tile, .pd-mini {
  width: 100%;
  min-width: 0;
  text-align: left;
  color: inherit;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  display: flex;
  flex-direction: column;
  padding-bottom: 14px;
  transition: transform var(--dur-fast) var(--ease-out);
}
.pd-mini { cursor: default; }
.pd-best { cursor: pointer; }
.pd-tile:active, .pd-best:active { transform: scale(0.97); }

.pd-tile-mid {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin: 2px 0 8px;
}
.pd-ring { position: relative; width: 58px; height: 58px; flex: 0 0 auto; }
.pd-ring svg { width: 100%; height: 100%; }
.pd-ring-track { fill: none; stroke: rgba(255, 255, 255, 0.07); stroke-width: 5; }
.pd-ring-fill {
  fill: none;
  stroke: var(--amber);
  stroke-width: 5;
  stroke-linecap: round;
  transition: stroke-dashoffset var(--dur-slow) var(--ease-out);
  filter: drop-shadow(0 0 5px rgba(232, 134, 58, 0.5));
}
.pd-flame { position: absolute; inset: 0; display: grid; place-items: center; }
.pd-flame .sp-flame-svg {
  width: 26px; height: 26px;
  filter: drop-shadow(0 0 6px rgba(255, 120, 40, 0.6));
}

.pd-foot {
  margin-top: auto;
  font-family: var(--font-ka);
  font-size: 11.5px;
  color: var(--text-3);
}
.pd-foot .num { font-weight: 700; color: var(--text-2); }
.pd-foot.is-good, .pd-foot.is-good .num { color: var(--lime); }
.pd-foot.is-bad { color: var(--amber); }

.pd-bar-track {
  height: 6px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
  margin: 10px 0;
}
.pd-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: var(--lime);
  box-shadow: 0 0 10px rgba(201, 245, 59, 0.5);
  transition: width var(--dur-slow) var(--ease-out);
}

/* ---- the insights ---- */
.pd-insights-title { margin: 6px 0 -4px; }
.pd-insights { display: flex; flex-direction: column; gap: 12px; }

.pd-donut-row { display: flex; align-items: center; gap: 16px; margin-top: 4px; }
.pd-donut { position: relative; width: 104px; height: 104px; flex: 0 0 auto; }
.pd-donut svg { width: 100%; height: 100%; }
.pd-donut-track { fill: none; stroke: rgba(255, 255, 255, 0.06); stroke-width: 12; }
.pd-donut-arc {
  fill: none;
  stroke-width: 12;
  transition: stroke-dasharray var(--dur-slow) var(--ease-out);
}
.pd-donut-c {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 22px; font-weight: 800; color: var(--text-1);
}
.pd-legend { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.pd-leg-row { display: flex; align-items: center; gap: 8px; }
.pd-leg-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.pd-leg-l {
  flex: 1; min-width: 0;
  font-family: var(--font-ka); font-size: 12.5px; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pd-leg-v { font-size: 13px; font-weight: 700; color: var(--text-1); white-space: nowrap; }
.pd-leg-max { font-weight: 500; color: var(--text-3); font-size: 11px; margin-left: 1px; }

.pd-mini .pd-vs { align-items: flex-start; margin-top: 8px; }
.pd-star { color: #F5C542; margin-left: 6px; font-size: 13px; }
.pd-best-day {
  font-family: var(--font-ka);
  font-size: 19px;
  font-weight: 700;
  color: var(--lime);
  line-height: 1.2;
}
.pd-best-date { font-size: 12px; color: var(--text-2); margin: 2px 0 8px; }
.pd-best-date span, .pd-foot span:not(.num) { font-family: var(--font-ka); }

/* ============================================================
   The InBody look (2026-09-23)
   ============================================================
   Giorgi: the InBody pieces were "too flat" and should "have their own feeling
   that it's an InBody". So the two InBody surfaces - the mission rail and the
   history cards - share one identity nothing else on the progress tab wears:

   - a teal SCAN colour (the body-composition machine, not the lime of the daily
     score - lime still means "earned" everywhere else),
   - a faint measuring grid, like the paper the sheet is printed on,
   - a slow scan line passing down the mission card,
   - big, tight numerals - the Nike reference: the number is the headline and
     the label is small print beneath it.

   Everything here is later in the file than the rules it overrides, so source
   order wins at equal specificity. */
.timeline-card,
.inbody-card {
  --ib-scan: 0, 221, 179;              /* --teal as a triplet, for alphas */
  --ib-scan-dur: 6400ms;
  --ib-ping-dur: 2600ms;
  --ib-spin-dur: 14000ms;
  --ib-grid: rgba(255, 255, 255, 0.028);
}

/* ---- the mission card ---- */
.timeline-card {
  overflow: hidden;
  isolation: isolate;
  border-color: rgba(var(--ib-scan), 0.16);
  background:
    radial-gradient(120% 70% at 100% 0%, rgba(var(--ib-scan), 0.13), rgba(var(--ib-scan), 0) 60%),
    var(--surface);
}

/* The measuring grid, faded out towards the bottom so the numbers stay clean. */
.timeline-card::before,
.inbody-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(var(--ib-grid) 1px, rgba(0, 0, 0, 0) 1px),
    linear-gradient(90deg, var(--ib-grid) 1px, rgba(0, 0, 0, 0) 1px);
  background-size: 18px 18px;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0) 75%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0) 75%);
}

/* The scan line: a soft teal band with a bright leading edge that passes down
   the card and off the bottom, waits, and goes again. */
.timeline-card::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 70px;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(var(--ib-scan), 0) 0%,
    rgba(var(--ib-scan), 0.07) 85%,
    rgba(var(--ib-scan), 0.35) 99%,
    rgba(var(--ib-scan), 0) 100%);
  animation: ibScan var(--ib-scan-dur) var(--ease-in-out) infinite;
}

@keyframes ibScan {
  0%   { transform: translateY(-80px); opacity: 0; }
  8%   { opacity: 1; }
  55%  { transform: translateY(420px); opacity: 0; }
  100% { transform: translateY(420px); opacity: 0; }
}

.timeline-empty-mode.timeline-card::after { display: none; }

/* The day tag in the scan colour, not lime. */
.timeline-card #timeline-day-tag {
  background: rgba(var(--ib-scan), 0.14);
  color: var(--teal);
}
.timeline-empty-mode.timeline-card #timeline-day-tag {
  background: var(--surface-3);
  color: var(--text-2);
}

/* The rail runs node-centre to node-centre: four flex:1 nodes put the centres at
   12.5% and 87.5%, so the percentage the JS writes lands exactly on a node. The
   unlit part is dashed - the road not yet taken, with no dates on it. */
.timeline-card .timeline-line {
  top: 22px;
  left: 12.5%;
  right: 12.5%;
  background: repeating-linear-gradient(90deg,
    var(--surface-3) 0 6px, rgba(0, 0, 0, 0) 6px 10px);
}
.timeline-card .timeline-line::after {
  background: linear-gradient(90deg, rgba(var(--ib-scan), 0.5), var(--teal));
  box-shadow: 0 0 10px rgba(var(--ib-scan), 0.45);
}

/* The nodes are numbered tests: 01 02 03 04. */
.timeline-card .timeline-node-dot {
  width: 46px;
  height: 46px;
  background: var(--surface-2);
  border: 1.5px solid var(--border-2);
}

.tl-num {
  font-family: var(--font-num);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--text-3);
  line-height: 1;
}

.timeline-card .timeline-node.completed .timeline-node-dot {
  background: var(--teal);
  border-color: var(--teal);
  box-shadow: 0 0 18px rgba(var(--ib-scan), 0.45);
}
.timeline-card .timeline-node.completed .tl-num { color: var(--bg); }
.timeline-card .timeline-node.completed .timeline-node-label { color: var(--teal); }

/* The newest test sends out a slow ring: "the numbers below are from this one". */
.timeline-card .timeline-node.latest .timeline-node-dot::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  border: 1.5px solid var(--teal);
  animation: ibPing var(--ib-ping-dur) var(--ease-out) infinite;
}

@keyframes ibPing {
  0%   { transform: scale(1);    opacity: 0.8; }
  70%  { transform: scale(1.55); opacity: 0; }
  100% { transform: scale(1.55); opacity: 0; }
}

/* The next test: open, a dashed ring turning slowly - waiting, not scheduled. */
.timeline-card .timeline-node.active .timeline-node-dot {
  background: var(--surface);
  border-color: rgba(0, 0, 0, 0);
  box-shadow: none;
  animation: none;
}
.timeline-card .timeline-node.active .timeline-node-dot::before {
  content: '';
  position: absolute;
  inset: -1.5px;
  border-radius: 50%;
  border: 1.5px dashed rgba(var(--ib-scan), 0.7);
  animation: ibSpin var(--ib-spin-dur) linear infinite;
}
.timeline-card .timeline-node.active .tl-num { color: var(--teal); }
.timeline-card .timeline-node.active .timeline-node-label { color: var(--text-2); }

@keyframes ibSpin { to { transform: rotate(360deg); } }

.timeline-card .timeline-node.pending .timeline-node-dot { opacity: 0.45; }

/* The three numbers under the rail: big and tight, the unit small beside them. */
.timeline-card .tim-stat {
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--border);
  text-align: left;
  padding: 12px 10px 10px;
}
.timeline-card .tim-stat-val {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.045em;
  line-height: 1;
  white-space: nowrap;
}
.timeline-card .tim-stat-val .inbody-detail-stat-unit {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--text-3);
  margin-left: 3px;
}
.timeline-card .tim-stat-label { margin-top: 6px; }
.timeline-card .section-action { color: var(--teal); }

/* ---- the history cards ---- */
.inbody-card {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding-left: 19px;
  background:
    radial-gradient(90% 80% at 100% 0%, rgba(var(--ib-scan), 0.08), rgba(var(--ib-scan), 0) 60%),
    var(--surface);
}

/* The spine: a teal edge down the left, like the colour band on the sheet. */
.inbody-card::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  pointer-events: none;
  background: linear-gradient(180deg, var(--teal), rgba(var(--ib-scan), 0.12));
}

.inbody-card .inbody-card-date { gap: 10px; flex-wrap: nowrap; }
.inbody-card .inbody-card-date > span:not(.ib-no):not(.inbody-demo-badge) {
  color: var(--text-2);
  font-weight: 500;
}

/* The test number is the headline of the card. */
.ib-no {
  font-family: var(--font-num);
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 0.9;
  color: var(--teal);
}

/* The score as a gauge: the ring fills to the score out of 100. */
.inbody-card .inbody-score-circle {
  width: 50px;
  height: 50px;
  border: none;
  color: var(--text-1);
  font-size: 15px;
  background:
    radial-gradient(closest-side, var(--surface) 80%, rgba(0, 0, 0, 0) 82%),
    conic-gradient(var(--teal) calc(var(--p, 0) * 1%), var(--surface-3) 0);
  box-shadow: 0 0 16px rgba(var(--ib-scan), 0.18);
}

.inbody-card .inbody-card-stats {
  padding-top: 12px;
  border-top: 1px dashed var(--border-2);
}
.inbody-card .ib-stat { text-align: left; }
.inbody-card .ib-stat-val {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.04em;
}

/* ---- each body measure has its own colour and picture (2026-09-23) ----
   Giorgi: "everything is the same colour, so it does not differentiate between
   fat, muscle..." The badge is the day rows' tinted square with a Noto emoji in
   it, so the InBody numbers speak the same visual language as the main screen.
   The number itself stays white; the colour lives in the badge, the label and a
   soft wash, so the digits stay easy to read. */
.ib-k-weight { --k: 59, 200, 245; }    /* blue  - the scale */
.ib-k-fat    { --k: 255, 92, 92; }     /* red   - fat */
.ib-k-muscle { --k: 74, 222, 128; }    /* green - muscle */
.ib-k-bmi    { --k: 232, 134, 58; }    /* amber - BMI */

.ib-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: rgba(var(--k), 0.16);
  box-shadow: inset 0 0 0 1px rgba(var(--k), 0.22);
  margin-bottom: 8px;
}
.ib-badge img { width: 19px; height: 19px; display: block; }

.timeline-card .tim-stat[class*="ib-k-"] {
  border-color: rgba(var(--k), 0.22);
  background: linear-gradient(180deg, rgba(var(--k), 0.10), rgba(var(--k), 0) 75%),
              rgba(255, 255, 255, 0.02);
}
.tim-stat[class*="ib-k-"] .tim-stat-label,
.ib-stat[class*="ib-k-"] .ib-stat-label { color: rgb(var(--k)); opacity: 0.85; }

.inbody-card .ib-stat[class*="ib-k-"] .ib-badge {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  margin-bottom: 6px;
}
.inbody-card .ib-stat[class*="ib-k-"] .ib-badge img { width: 16px; height: 16px; }
