@import url('./tokens.css');

/* ---------------------------------------------------------------------------
   Design tokens — docs/04-design-system.md and docs/11-structure-and-feel.md E.
   The only place these are defined.

   The colour scheme is derived from art/source/bg-retired scenic.jpg, sampled
   from the file rather than estimated. Jet black was austere and joyless; this
   is a retired scenic ground, lit through the middle, with every accent drawn
   from something actually in the picture.

   Two systems, doing different jobs and never competing: the five attribute
   colours identify attributes, and acid marks action. See docs/11 A and E.
   --------------------------------------------------------------------------- */


@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-state: 0ms;
    --motion-screen: 0ms;
  }
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  /* The gradient IS the ground. The artwork sits behind it at low opacity, so
     the scheme still reads correctly if the image never loads. */
  background: var(--surface-1);
  background-attachment: fixed;
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--text-md);
  line-height: 1.35;
  /* Weights and reps must not reflow as they change. */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------------------
   The backdrop — docs/11 E.

   Cory's own artwork, fixed rather than scrolling, anchored to the bottom so
   the path and lanterns land under the tab bar: that is where the picture is
   busiest and where the content is not.

   It is a decorative layer and nothing but. Held at 15% with a 2.5px blur, it
   gives the ground depth without competing with a single number on screen —
   and because the gradient underneath carries the scheme on its own, the app
   looks right even if the image never arrives.
   --------------------------------------------------------------------------- */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background-image: none;
  background-size: cover;
  background-position: center bottom;
  background-repeat: no-repeat;
  opacity: 0.15;
  filter: none;
  /* The blur samples past the viewport edge, so grow the layer to keep the
     blurred edge off screen rather than showing a soft grey border. */
  transform: scale(1.04);
  transform-origin: center bottom;
  pointer-events: none;
}

/* Decoration only: it must never be announced, and it must never be the reason
   a number is hard to read. */
@media (prefers-reduced-transparency: reduce) {
  body::before { opacity: 0.08; }
}

/* Respect the iPhone safe area once installed to the home screen. */
.shell {
  min-height: 100%;
  padding: max(var(--s4), env(safe-area-inset-top)) var(--s4)
    max(var(--s4), env(safe-area-inset-bottom));
  display: grid;
  place-items: center;
}

.shell__wordmark {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 800;
  letter-spacing: 0;
  color: var(--text-3);
}

/* ---------------------------------------------------------------------------
   Shell

   Four tabs on a bar that floats, inset from all three edges over a blurred
   translucent surface. Never welded to the screen edge.
   --------------------------------------------------------------------------- */

.app {
  position: relative;
  min-height: 100%;
  display: grid;
  grid-template-rows: 1fr auto;
}

.app__body {
  overflow-y: auto;
  padding: calc(env(safe-area-inset-top) + 16px) var(--s3) calc(77px + env(safe-area-inset-bottom));
}

/* `display: flex` outranks the user-agent `[hidden] { display: none }`, so the
   hidden state has to be restated or the bar — and its FAB — stays on screen
   through a whole session. */
.tabbar[hidden] { display: none; }

.active-workout-dock[hidden] { display: none; }
.active-workout-dock {
  position: fixed;
  z-index: 39;
  left: var(--s4);
  right: var(--s4);
  bottom: calc(76px + var(--s3) + env(safe-area-inset-bottom));
}
.active-workout-dock__button {
  appearance: none;
  width: 100%;
  min-height: 62px;
  border: 0;
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--text);
  box-shadow: none;
  padding: var(--s2) var(--s3);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  text-align: left;
}
#app:has(.active-workout-dock:not([hidden])) .app__body {
  padding-bottom: calc(133px + env(safe-area-inset-bottom));
  scroll-padding-bottom: calc(149px + env(safe-area-inset-bottom));
}
.active-workout-dock__copy { display: grid; gap: 2px; min-width: 0; }
.active-workout-dock__copy strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.active-workout-dock__copy small { color: var(--text-2); }
.active-workout-dock__resume {
  color: var(--acid);
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0;
}

.tabbar {
  position: fixed;
  z-index: 40;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: var(--s1);
  padding: 8px 12px env(safe-area-inset-bottom);
  border-top: 1px solid var(--hairline);
  border-radius: 0;
  background: var(--tabbar);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.tabbar__tabs {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s1);
  min-width: 0;
}

.tabbar__tab {
  appearance: none;
  background: none;
  border: 0;
  border-radius: var(--r-lg);
  /* An inactive tab is still a label to be read. */
  color: var(--text-2);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0;
  padding: var(--s3) var(--s1);
  min-height: 44px;
  cursor: pointer;
  transition: color var(--motion-state) ease, background var(--motion-state) ease;
}

.tabbar__tab[data-active='true'] {
  color: var(--text);
  background: var(--raised);
}

/* --------------------------------------------------------------------------- */

.screen { display: grid; gap: var(--s4); }

/* Headings are big, bold and all caps. The old system's timidity was mostly a
   type failure: a section heading was a small grey label. */
.screen__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xxl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.05;
}

.block { display: grid; gap: var(--s3); }

.block__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.1;
  color: var(--text);
}

.block__hint { margin: 0; font-size: var(--text-sm); color: var(--text-2); }

/* Cards are generous and rounded, and hold their own separation from the
   ground. No border: the surface step is the separation. */
.card {
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: var(--s4);
  display: grid;
  gap: var(--s3);
}

/* --------------------------------------------------------------------------- */

.button {
  appearance: none;
  border: 0;
  background: var(--raised);
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 800;
  letter-spacing: 0;
  padding: var(--s3) var(--s4);
  border-radius: var(--r-full);
  cursor: pointer;
  min-height: 44px; /* a thumb, mid-set */
  transition: background var(--motion-state) ease;
  /* A pill with a full radius and an unsized icon becomes a circle the size of
     a coaster. Sizing the icon here rather than per screen is what stops that
     happening again the next time a button gets one. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
}
.button .icon { width: 16px; height: 16px; flex: none; }

.button--quiet { background: none; color: var(--text-2); }
.button--wide { width: 100%; }
/* A primary action that carries acid is a pill, never the full width: filling
   the width of a phone with the accent spends the whole 5% budget on one
   control. See docs/04-design-system.md and DECISIONS.md. */
.button--pill { justify-self: end; padding: var(--s3) var(--s5); }

.search {
  width: 100%;
  background: var(--well);
  border: 0;
  border-radius: var(--r-md);
  color: var(--text);
  font-size: var(--text-md);
  padding: var(--s3);
  min-height: 44px;
}

/* --------------------------------------------------------------------------- */

.routine__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.1;
}
.routine__meta, .routine__primary { margin: 0; font-size: var(--text-sm); color: var(--text-2); }

.training-rhythm { display: grid; gap: 8px; padding: 14px 15px; }
.training-rhythm__head { display: flex; align-items: start; justify-content: space-between; gap: 12px; }
.training-rhythm__eyebrow {
  display: block; color: var(--acid); font-size: var(--text-xs); font-weight: 800;
  letter-spacing: 0;
}
.training-rhythm__streak { display: block; margin-top: 2px; font-size: var(--text-md); }
.training-rhythm__keeper {
  flex: 0 0 auto; border: 0; border-radius: 999px; padding: 7px 9px;
  color: var(--text-2); font-size: var(--text-xs); font-weight: 750; white-space: nowrap;
}
.training-rhythm__keeper[data-ready='true'] { border-color: var(--text-2); color: var(--acid); }
.training-rhythm__week, .training-rhythm__note { margin: 0; color: var(--text-2); font-size: var(--text-xs); }
.training-calendar__month { display: flex; justify-content: space-between; gap: 10px; color: var(--text-3); font-size: 12px; font-weight: 800; letter-spacing: 0; }
.training-calendar__month strong { color: var(--text-2); font-size: 12px; letter-spacing: 0; }
.training-calendar-scroll {
  min-width: 0; display: flex; overflow-x: auto; overscroll-behavior-inline: contain;
  scroll-snap-type: x mandatory; scrollbar-width: none; touch-action: pan-x pan-y;
}
.training-calendar-scroll::-webkit-scrollbar { display: none; }
.training-calendar__week-panel {
  flex: 0 0 100%; min-width: 100%; display: grid; gap: 5px;
  scroll-snap-align: start; scroll-snap-stop: always;
}
.training-calendar__week-label {
  display: block; color: var(--text-2); font-size: 12px; font-weight: 800;
  letter-spacing: 0; text-align: right;
}
.training-calendar__week-panel[data-current-week='true'] .training-calendar__week-label { color: var(--acid); }
.training-calendar { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; text-align: center; }
.training-calendar__weekday { color: var(--text-3); font-size: 12px; font-weight: 800; }
.training-calendar__day, .training-calendar__blank {
  display: grid; place-items: center; min-width: 0; width: 34px; height: 34px; justify-self: center; border-radius: 50%;
  color: var(--text-2); font-size: var(--text-xs); font-variant-numeric: tabular-nums;
}
.training-calendar__day[data-trained='true'] {
  box-shadow: none;
  color: var(--text); font-weight: 780;
}
.training-calendar__day[data-qualified='true'] {
  background: var(--acid); color: var(--text-2); font-weight: 850;
  box-shadow: none;
}
.training-calendar__day[data-today='true'] { outline: 1px solid var(--text); outline-offset: -2px; }

.training-control { display: grid; gap: 12px; padding: 15px; }
.training-control__head { display: grid; grid-template-columns: minmax(0,1fr) auto; align-items: center; gap: 12px; }
.training-control__head > div:first-child { min-width: 0; }
.training-control__eyebrow { display: block; color: var(--acid); font-size: 12px; font-weight: 820; letter-spacing: 0; }
.training-control__head h2 { margin: 3px 0 0; font-size: 17px; line-height: 1.15; }
.training-readiness {
  width: 66px; height: 66px; display: grid; place-content: center; justify-items: center;
  border: 0; border-radius: 50%;
  background: var(--surface-1);
}
.training-readiness strong { color: var(--acid); font-size: 22px; line-height: 1; }
.training-readiness span { margin-top: 3px; color: var(--text-2); font-size: 12px; font-weight: 800; letter-spacing: 0;  }
.training-readiness[data-readiness='ready'] { border-color: var(--text-2); background: var(--surface-1); }
.training-readiness[data-readiness='ready'] strong { color: var(--text-2); }
.training-readiness[data-readiness='steady'] { border-color: var(--text-2); background: var(--surface-1); }
.training-readiness[data-readiness='steady'] strong { color: var(--text-2); }
.training-readiness[data-readiness='recover'] { border-color: var(--text-2); background: var(--surface-1); }
.training-readiness[data-readiness='recover'] strong { color: var(--text-2); }
.training-control__stats { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 6px; }
.training-control__stat { min-width: 0; display: grid; gap: 3px; padding: 10px 4px; border: 0; border-radius: 13px; background: var(--surface-1); text-align: center; }
.training-control__stat strong { font-size: 17px; font-variant-numeric: tabular-nums; }
.training-control__stat span { color: var(--text-3); font-size: 12px; font-weight: 780; letter-spacing: 0; }
.training-control__readiness-note { margin: -3px 0 0; color: var(--text-3); font-size: 12px; }
.training-control__readiness-explainer { margin:-5px 0 0; color: var(--text-2); font-size: 12px; line-height:1.45; }
.training-coach { display: grid; grid-template-columns: minmax(0,1fr) auto; align-items: center; gap: 10px; padding-top: 11px; border-top: 1px solid var(--edge); }
.training-coach > div { min-width: 0; display: grid; gap: 2px; }
.training-coach strong { font-size: 12px; }
.training-coach__status { color: var(--text-3); font-size: 12px; line-height: 1.3; }
.training-coach__action {
  min-height: 42px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 12px; border: 0;
  border-radius: 13px; background: var(--surface-1);
  color: var(--acid); font-size: 12px; font-weight: 820; letter-spacing: 0; text-decoration: none;
}

@media (max-width: 390px) {
  .training-calendar__day, .training-calendar__blank { width: 31px; height: 31px; }
  .training-coach { grid-template-columns: 1fr; }
  .training-coach__action { width: 100%; }
}

/* Separation from the surface step and from space — never a hairline. */
.library { display: grid; gap: var(--s1); }

.libraryrow {
  appearance: none;
  border: 0;
  background: var(--surface);
  border-radius: var(--r-md);
  color: var(--text);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3);
  text-align: left;
  cursor: pointer;
  min-height: 56px;
}

.libraryrow__main { display: grid; gap: 2px; }
.libraryrow__name { font-size: var(--text-md); font-weight: 600; }
.libraryrow__meta { font-size: var(--text-xs); color: var(--text-3); }
.libraryrow__stats { display: grid; gap: 2px; justify-items: end; }
.libraryrow__pr { font-size: var(--text-sm); color: var(--text); font-variant-numeric: tabular-nums; }
.libraryrow__last { font-size: var(--text-xs); color: var(--text-3); }

/* ---------------------------------------------------------------------------
   The session — the centre of the app.
   --------------------------------------------------------------------------- */

.sessionbar { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); }
.sessionbar__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xxl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.05;
}
.sessionbar__meta { margin: 0; font-size: var(--text-sm); color: var(--text-2); }
.sessionbar__elapsed {
  flex: none;
  min-width: 76px;
  display: grid;
  justify-items: end;
  gap: 3px;
  padding: 9px 11px;
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface-1);
  font-variant-numeric: tabular-nums;
}
.sessionbar__elapsed-label { color: var(--text-3); font-size: 12px; font-weight: 800; letter-spacing: 0; }
.sessionbar__elapsed-value { color: var(--acid); font-size: var(--text-lg); line-height: 1; }

.session-minimize {
  appearance: none;
  border: 0;
  border-radius: var(--r-full);
  background: var(--surface-1);
  color: var(--text-2);
  min-height: 44px;
  padding: 0 var(--s3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0;
}
.session-minimize .icon { width: 16px; height: 16px; }

.session-add {
  display: grid;
  gap: var(--s3);
  padding: var(--s4);
  border: 0;
  border-radius: var(--r-lg);
  background: var(--surface);
}
.session-add__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); }
.session-add__title { margin: 0; font-size: var(--text-xl);  }
.session-add__note { margin: 3px 0 0; color: var(--text-2); font-size: var(--text-sm); }
.session-add__search {
  width: 100%;
  min-height: 48px;
  border: 0;
  border-radius: var(--r-md);
  background: var(--raised);
  color: var(--text);
  padding: 0 var(--s3);
  font: inherit;
}
.session-add__open { border: 0; background: var(--surface); color: var(--text); }

.exercise { padding-bottom: var(--s4); }

.exercise__head { display: flex; align-items: flex-start; gap: var(--s3); }

/* A rounded square at the left of the name, roughly three lines tall. */
.exercise__art {
  appearance: none;
  border: 0;
  border-radius: var(--r-md);
  background: var(--raised);
  padding: 0;
  width: 72px;
  height: 72px;
  overflow: hidden;
  cursor: pointer;
  flex: none;
}
.exercise__thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.exercise__full { width: 100%; border-radius: var(--r-md); background: var(--surface-1); display: block; }
.panel--art { padding: 0; overflow: hidden; }

.exercise__title { flex: 1; min-width: 0; display: grid; gap: var(--s1); }

/* INCLINE BARBELL BENCH PRESS. Not a small grey label. */
.exercise__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.05;
}

/* Prescribed, as distinct from performed: the second accent's whole job. */
.exercise__range {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--blue);
  font-variant-numeric: tabular-nums;
}
.exercise__cue { margin: 0; font-size: var(--text-sm); color: var(--text-2); }
.exercise__sub { margin: 0; font-size: var(--text-sm); color: var(--text-2); }
.exercise__method {
  margin: 0;
  color: var(--text-2);
  font-size: var(--text-xs);
  font-weight: 750;
  letter-spacing: 0;
}
.exercise__proposal { margin: 0; font-size: var(--text-sm); color: var(--text-2); }

.exercise__order { display: flex; flex-direction: column; gap: var(--s1); flex: none; }

.iconbutton {
  appearance: none;
  background: var(--raised);
  border: 0;
  border-radius: var(--r-full);
  color: var(--text);
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  cursor: pointer;
}
.iconbutton:disabled { color: var(--text-3); cursor: default; opacity: 0.5; }
.iconbutton .icon { width: 16px; height: 16px; }

/* Last performance and PR. The number is the content; its unit is a footnote
   beside it at half the size, dimmed. */
.exercise__history { display: flex; gap: var(--s2); flex-wrap: wrap; }

.pill {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s2);
  background: var(--well);
  border-radius: var(--r-full);
  padding: var(--s2) var(--s3);
}
.pill__label { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0; color: var(--text-3); }
.pill__value { font-size: var(--text-lg); font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.pill__unit { font-size: var(--text-xs); color: var(--text-3); }
.pill__aside { font-size: var(--text-xs); color: var(--text-2); }

/* Exercise actions: full-round grey pills with a small icon and a label, in a
   horizontal scroller directly under the name. Not a menu. Not an overflow. */
.actions {
  display: flex;
  gap: var(--s2);
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 calc(var(--s4) * -1);
  padding: var(--s1) var(--s4);
}
.actions::-webkit-scrollbar { display: none; }

.actionpill {
  appearance: none;
  flex: none;
  background: var(--raised);
  border: 0;
  border-radius: var(--r-full);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0;
  padding: 0 var(--s3);
  min-height: 44px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  white-space: nowrap;
}
.actionpill[data-open='true'] { background: var(--well); }
.actionpill .icon { width: 16px; height: 16px; flex: none; }
.actionpill__value { font-variant-numeric: tabular-nums; color: var(--text-2); }

.panel {
  border-radius: var(--r-md);
  padding: var(--s3);
  display: grid;
  gap: var(--s2);
  background: var(--well);
}
.panel__note { margin: 0; font-size: var(--text-sm); color: var(--text-2); }

/* ---------------------------------------------------------------------------
   The set row.

   Each field is its own rounded outlined cell. The row being worked gets a
   filled olive tint and a 4px acid bar down its left edge. Completed rows keep
   full text brightness — dimming them is conventional and wrong here, because
   those numbers are what you read to choose the next weight. The check control
   carries the state.
   --------------------------------------------------------------------------- */

.setrow {
  position: relative;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) minmax(56px, 1.15fr) minmax(48px, 0.85fr) 48px;
  gap: var(--s2);
  align-items: center;
  padding: var(--s2) 0 var(--s2) var(--s3);
  border-radius: var(--r-md);
}

.setrow[data-editing='true'] {
  grid-template-columns: 28px minmax(0, 1fr) minmax(56px, 1.15fr) minmax(48px, 0.85fr) 48px 44px;
}

.setrow[data-active='true'] { background: var(--active-tint); }

.setrow__edge {
  position: absolute;
  left: 0;
  top: var(--s2);
  bottom: var(--s2);
  width: 4px;
  border-radius: 2px;
}

.setrow--head {
  padding-top: 0;
  padding-bottom: var(--s1);
}
.setrow--head span:not([data-acid]) {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0;
  color: var(--text-3);
}
.setrow--head span[data-acid] { font-size: var(--text-xs); font-weight: 800; letter-spacing: 0; }
.setrow--head .setrow__col { text-align: center; }

.setrow__index { font-size: var(--text-sm); font-weight: 700; color: var(--text-2); }

/* Prescribed versus actual — the blue's only job in the tracker. */
.setrow__record {
  font-size: var(--text-sm);
  color: var(--blue);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Numbers are the largest thing in the row, and the brightest thing on the
   screen. They are read at arm's length in bad gym lighting, mid-set. */
input.setrow__num,
span.setrow__num {
  background: transparent;
  border: 0;
  border-radius: var(--r-md);
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  text-align: center;
  padding: var(--s1) 2px;
  min-height: 48px;
  width: 100%;
}

/* The field being worked is a deep well. */
.setrow[data-active='true'] input.setrow__num {
  background: var(--well);
  border-color: var(--edge-strong);
}

/* A logged set is not a dimmed set: same cell, same brightness. The check
   carries the state, because these numbers are what you read to choose the
   next weight. */
input.setrow__num[readonly] { color: var(--text); }

.setrow__check {
  appearance: none;
  border: 0;
  background: var(--raised);
  color: var(--text-2);
  border-radius: var(--r-md);
  min-height: 48px;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background var(--motion-state) ease, color var(--motion-state) ease;
}
.setrow__check .icon { width: 20px; height: 20px; }

.setrow[data-active='true'] .setrow__check {
  background: transparent;
  border-color: var(--acid);
}

.setrow[data-done='true'] .setrow__check {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}

.setrow__remove {
  appearance: none;
  background: var(--raised);
  border: 0;
  border-radius: var(--r-md);
  color: var(--text-2);
  min-height: 44px;
  display: grid;
  place-items: center;
  cursor: pointer;
}
.setrow__remove .icon { width: 16px; height: 16px; }

.addset {
  appearance: none;
  background: var(--raised);
  border: 0;
  border-radius: var(--r-full);
  color: var(--text-2);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0;
  padding: 0 var(--s4);
  cursor: pointer;
  min-height: 44px;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
}
.addset .icon { width: 14px; height: 14px; }

/* ---------------------------------------------------------------------------
   The plate calculator — beside the weight field of the set being worked,
   never behind a menu. Bar weight and the plates you own are configured from
   the EQUIPMENT pill; what is on the bar right now is read here.
   --------------------------------------------------------------------------- */

.plates {
  grid-column: 3 / -1;
  grid-row: 2;
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
  padding-top: var(--s1);
}
.plates__label { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0; color: var(--text-3); }
.plate {
  background: var(--well);
  border: 0;
  border-radius: var(--r-sm);
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 2px var(--s2);
  display: inline-flex;
  align-items: center;
}
.plates__empty, .plates__note { font-size: var(--text-xs); color: var(--text-3); margin: 0; }
.plates__note[data-exact='false'] { color: var(--text-2); }

/* Equipment: the bar, and the plates you actually own. */
.equipment { display: grid; gap: var(--s2); }
.equipment__row { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.equipment__label { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0; color: var(--text-3); }
.equipment__bar {
  width: 72px;
  background: var(--bg);
  border: 0;
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: var(--text-md);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
  padding: var(--s1);
  min-height: 44px;
}
.equipment__plate {
  appearance: none;
  background: var(--bg);
  border: 0;
  border-radius: var(--r-full);
  color: var(--text-3);
  font-size: var(--text-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0 var(--s3);
  min-height: 44px;
  cursor: pointer;
}
.equipment__plate[data-on='true'] { background: var(--raised); color: var(--text); border-color: var(--edge-strong); }

/* Rest, edited in the session. */
.restedit { display: flex; gap: var(--s2); flex-wrap: wrap; }
.restedit__option {
  appearance: none;
  background: var(--bg);
  border: 0;
  border-radius: var(--r-full);
  color: var(--text-2);
  font-size: var(--text-md);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0 var(--s4);
  min-height: 44px;
  cursor: pointer;
}
.restedit__option[data-active='true'] { background: var(--raised); color: var(--text); border-color: var(--edge-strong); }

.methodlist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s2);
}
.methodlist__option {
  appearance: none;
  min-height: 48px;
  padding: 0 var(--s3);
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-2);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 750;
  cursor: pointer;
}
.methodlist__option[data-selected='true'] {
  border-color: var(--edge-strong);
  background: var(--raised);
  color: var(--text);
}
.methodlist__option:disabled { cursor: default; opacity: 0.58; }

.historyline { display: flex; justify-content: space-between; gap: var(--s3); font-size: var(--text-sm); padding: var(--s1) 0; }
.historyline__date { color: var(--text-2); white-space: nowrap; }
.historyline__sets { color: var(--text); font-variant-numeric: tabular-nums; text-align: right; }

.swaplist { display: grid; gap: var(--s1); max-height: 260px; overflow-y: auto; }
.swaplist__option {
  appearance: none;
  background: var(--surface);
  border: 0;
  border-radius: var(--r-sm);
  color: var(--text);
  text-align: left;
  padding: var(--s3);
  min-height: 44px;
  cursor: pointer;
  font-size: var(--text-md);
}

/* FINISH is separated from every set control by its own zone, and asks before
   it ends anything. Its confirm is the screen's one primary action. */
.finishzone {
  margin-top: var(--s6);
  padding-top: var(--s5);
  display: grid;
  gap: var(--s3);
}
.finishzone__ask { margin: 0; font-size: var(--text-lg); font-weight: 700; }
.finishzone__pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.finishzone__confirm { display: grid; gap: var(--s3); }

.deload {
  margin: 0;
  font-size: var(--text-md);
  color: var(--text);
  background: var(--surface);
  border-radius: var(--r-md);
  padding: var(--s3) var(--s4);
}

/* ---------------------------------------------------------------------------
   Summary, records, history
   --------------------------------------------------------------------------- */

.screen--summary {
  position: relative;
  gap: var(--s3);
  padding-bottom: calc(var(--s6) + env(safe-area-inset-bottom));
  isolation: isolate;
}
.summary-hero {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: var(--s1);
  padding: var(--s4) 0 var(--s2);
  text-align: center;
}
.summary-hero .screen__title {
  margin: 0;
  font-size: clamp(32px, 9vw, 44px);
  letter-spacing: 0;
}
.summary-hero__eyebrow,
.summary-records__eyebrow {
  color: var(--acid);
  font-size: var(--text-xs);
  font-weight: 850;
  letter-spacing: 0;
}
.summary-hero__date {
  margin: 0;
  color: var(--text-2);
  font-size: var(--text-sm);
}
.summary-recap { display: grid; gap: var(--s3); }
.summary-recap .stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s2);
}
.summary-recap .stat {
  min-width: 0;
  padding: var(--s3) var(--s2);
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface-1);
  text-align: center;
}
.summary-recap .stat__value {
  overflow: hidden;
  font-size: clamp(20px, 6vw, 30px);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.summary-recap .stat__label { font-size: 12px; }
.summary-records {
  display: grid;
  gap: var(--s3);
  border-color: var(--text-2);
  background: var(--surface-1);
}
.summary-records .badge { color: var(--acid); }
.summary-actions {
  position: sticky;
  z-index: 5;
  bottom: calc(var(--s2) + env(safe-area-inset-bottom));
  display: grid;
  padding: var(--s2);
  border: 0;
  border-radius: var(--r-full);
  background: var(--surface-1);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.summary-actions .button { width: 100%; }
.summary-confetti {
  position: absolute;
  z-index: 0;
  top: 0;
  left: 0;
  right: 0;
  height: 230px;
  overflow: hidden;
  pointer-events: none;
}
.summary-confetti i {
  position: absolute;
  top: -18px;
  left: calc(var(--confetti-x) * 1%);
  width: 6px;
  height: 12px;
  border-radius: 2px;
  background: var(--confetti-color);
  transform: rotate(var(--confetti-rotate));
  animation: summary-confetti-fall 900ms cubic-bezier(.2,.65,.4,1) both;
  animation-delay: var(--confetti-delay);
}
.summary-confetti i[data-piece='1'] { --confetti-x:7; --confetti-color: var(--text-2); --confetti-rotate:18deg; --confetti-delay:20ms; }
.summary-confetti i[data-piece='2'] { --confetti-x:15; --confetti-color: var(--text-2); --confetti-rotate:-25deg; --confetti-delay:120ms; }
.summary-confetti i[data-piece='3'] { --confetti-x:24; --confetti-color: var(--text-2); --confetti-rotate:42deg; --confetti-delay:65ms; }
.summary-confetti i[data-piece='4'] { --confetti-x:34; --confetti-color: var(--text-2); --confetti-rotate:-12deg; --confetti-delay:170ms; }
.summary-confetti i[data-piece='5'] { --confetti-x:44; --confetti-color: var(--text-2); --confetti-rotate:54deg; --confetti-delay:85ms; }
.summary-confetti i[data-piece='6'] { --confetti-x:54; --confetti-color: var(--text-2); --confetti-rotate:-36deg; --confetti-delay:210ms; }
.summary-confetti i[data-piece='7'] { --confetti-x:63; --confetti-color: var(--text-2); --confetti-rotate:24deg; --confetti-delay:40ms; }
.summary-confetti i[data-piece='8'] { --confetti-x:71; --confetti-color: var(--text-2); --confetti-rotate:-45deg; --confetti-delay:145ms; }
.summary-confetti i[data-piece='9'] { --confetti-x:79; --confetti-color: var(--text-2); --confetti-rotate:9deg; --confetti-delay:230ms; }
.summary-confetti i[data-piece='10'] { --confetti-x:87; --confetti-color: var(--text-2); --confetti-rotate:-20deg; --confetti-delay:95ms; }
.summary-confetti i[data-piece='11'] { --confetti-x:93; --confetti-color: var(--text-2); --confetti-rotate:38deg; --confetti-delay:190ms; }
.summary-confetti i[data-piece='12'] { --confetti-x:49; --confetti-color: var(--text-2); --confetti-rotate:-52deg; --confetti-delay:260ms; }
@keyframes summary-confetti-fall {
  0% { opacity: 0; transform: translateY(0) rotate(var(--confetti-rotate)); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translateY(210px) translateX(18px) rotate(230deg); }
}

.summary-recap .stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.stats { display: flex; gap: var(--s5); flex-wrap: wrap; }
.stat { display: grid; gap: 2px; }
.stat__value {
  font-family: var(--font-display);
  font-size: var(--text-xxl);
  font-weight: 800;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.stat--small .stat__value { font-size: var(--text-xl); }
.stat__label { font-size: var(--text-xs); letter-spacing: 0;  color: var(--text-3); }

.badge {
  display: inline-block;
  background: var(--raised);
  color: var(--text);
  border-radius: var(--r-full);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0;
  padding: var(--s1) var(--s3);
}

.pr { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.pr__detail { font-size: var(--text-md); text-transform: none; }

.grew { display: grid; grid-template-columns: 1fr auto; gap: 2px var(--s3); align-items: baseline; }
.grew__attr { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; }
.grew__xp { font-size: var(--text-xl); font-weight: 800; font-variant-numeric: tabular-nums; }
.grew__why { grid-column: 1 / -1; font-size: var(--text-sm); color: var(--text-2); }

/* Attributes are the subject here, so the attribute colours apply. */
.grew[data-attribute='might'] .grew__xp { color: var(--might); }
.grew[data-attribute='wind'] .grew__xp { color: var(--wind); }
.grew[data-attribute='grit'] .grew__xp { color: var(--grit); }
.grew[data-attribute='vitality'] .grew__xp { color: var(--vitality); }
.grew[data-attribute='mind'] .grew__xp { color: var(--mind); }

.levelup { margin: 0; font-size: var(--text-md); }
.directive__headline { margin: 0; font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; }
.directive__detail { margin: 0; font-size: var(--text-sm); color: var(--text-2); }

.segmented { display: flex; gap: var(--s1); }
.segmented__option {
  flex: 1;
  appearance: none;
  border: 0;
  background: var(--surface);
  border-radius: var(--r-full);
  color: var(--text-2);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0;
  padding: var(--s3);
  cursor: pointer;
  min-height: 44px;
}
.segmented__option[data-active='true'] { background: var(--raised); color: var(--text); }

.historyrow__head, .recordrow__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.historyrow__name, .recordrow__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
}
.historyrow__date { font-size: var(--text-sm); color: var(--text-2); }
.historyrow__meta { margin: 0; font-size: var(--text-sm); color: var(--text-2); }
.recordrow__stats { display: flex; gap: var(--s4); flex-wrap: wrap; }
.spark { width: 96px; height: 24px; color: var(--text-2); }

/* ---------------------------------------------------------------------------
   Programs, the week, the guide
   --------------------------------------------------------------------------- */

.program__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.program__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.1;
}
.program__week { font-size: var(--text-md); font-weight: 700; color: var(--blue); white-space: nowrap; font-variant-numeric: tabular-nums; }
.program__note { margin: 0; font-size: var(--text-sm); color: var(--text-2); }

.programday {
  appearance: none;
  border: 0;
  border-radius: var(--r-md);
  background: var(--raised);
  color: var(--text);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  text-align: left;
  cursor: pointer;
  min-height: 60px;
}

.programday__main { display: grid; gap: 2px; }
.programday__name { font-family: var(--font-display); font-size: var(--text-md); font-weight: 700; }
.programday__focus { font-size: var(--text-xs); color: var(--text-2); }
.programday__count { font-size: var(--text-xl); font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }

.weekview { display: grid; gap: var(--s2); padding-top: var(--s2); }
.weekview__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.weekview__label { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0; color: var(--text-3); }
.weekview__count { font-size: var(--text-sm); color: var(--text); font-variant-numeric: tabular-nums; }

.weekday { display: grid; grid-template-columns: 110px 1fr 40px; gap: var(--s3); align-items: center; }
.weekday__name { font-size: var(--text-sm); color: var(--text-2); }
.weekday__bar { height: 6px; border-radius: 3px; background: var(--raised); position: relative; overflow: hidden; }
.weekday__bar::after { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--fill); background: var(--text-2); }
.weekday__count { font-size: var(--text-sm); text-align: right; font-variant-numeric: tabular-nums; color: var(--text-2); }

.guide { display: grid; gap: var(--s2); }
.guide__row { display: grid; grid-template-columns: 96px 1fr 60px; gap: var(--s3); align-items: center; }
.guide__group { font-size: var(--text-sm); color: var(--text-2); text-transform: none; }
.guide__bar { height: 6px; border-radius: 3px; background: var(--raised); position: relative; overflow: hidden; }
.guide__bar::after { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--fill); background: var(--text-3); }
.guide__row[data-met='true'] .guide__bar::after { background: var(--text); }
.guide__sets { font-size: var(--text-sm); text-align: right; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   Today
   Nothing here has an overdue state. Outstanding is neutral, never red.
   --------------------------------------------------------------------------- */

.today__frame { margin: 0; font-size: var(--text-md); color: var(--text-2); }

/* Today is the one screen with a hard height budget: Phase 4 requires the whole
   outstanding day to fit a 6.1" phone without scrolling, and docs/11 adds tiles
   and section headings on top of that. It therefore runs a tighter rhythm than
   the other screens, which have no such constraint. */
.screen--today { gap: var(--s2); }
.screen--today .block { gap: 6px; }
.screen--today .rows { gap: 2px; }
.footers { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.footers > * { min-height: 36px; }
/* The title earns its size on every other screen; here it is competing with
   twelve rows for one phone, and the sections carry the navigation anyway. */
.screen--today .screen__title { font-size: var(--text-lg); }

/* ---------------------------------------------------------------------------
   D — the summary strip. How today is going, before a single row is read.
   --------------------------------------------------------------------------- */

.strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: var(--s1) var(--s4);
}
.strip__head { display: flex; flex-direction: column; gap: 2px; }
.strip__label { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0; color: var(--text-2); }
.strip__xp { font-size: var(--text-lg); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1; }

/* Five bars, scaled to the largest of them. There is no daily quota in this
   app, so there is nothing to draw a bar against except the day's own shape. */
.strip__bars {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--s2);
  height: 34px;
  width: 40%;
  max-width: 168px;
  align-items: end;
  justify-items: center;
}
.strip__bar {
  position: relative;
  display: block;
  width: 100%;
  max-width: 34px;
  height: 100%;
  border-radius: var(--r-sm);
  /* Tinted with its own attribute even when empty: five identical dark slots
     would say nothing about which attribute is which. */
  background: var(--surface-1);
  overflow: hidden;
}
.strip__fill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  min-height: 3px;
  border-radius: var(--r-sm);
  background: var(--stone);
  transition: height var(--motion-screen) ease-out;
}
.strip__bar[data-moved='true'] .strip__fill { background: currentColor; }
.strip__bar[data-attribute='might'] { color: var(--might); }
.strip__bar[data-attribute='wind'] { color: var(--wind); }
.strip__bar[data-attribute='grit'] { color: var(--grit); }
.strip__bar[data-attribute='vitality'] { color: var(--vitality); }
.strip__bar[data-attribute='mind'] { color: var(--mind); }

/* ---------------------------------------------------------------------------
   B — named sections, each carrying its own count.
   --------------------------------------------------------------------------- */

.sect__title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  font-size: var(--text-md);
  letter-spacing: 0;
}
.sect__count {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.sect__title[data-complete='true'] .sect__count { color: var(--acid); }

/* C — a section finishing gets one brief acid flash, then nothing. */
@keyframes sect-flash {
  0% { color: var(--text); }
  30% { color: var(--acid); }
  100% { color: var(--text); }
}
.sect__title[data-flash='true'] { animation: sect-flash 380ms ease-out; }

/* ---------------------------------------------------------------------------
   A — the row, and the tile that opens it.

   One object, whatever it tracks: a tile in the attribute's colour, a name, an
   optional value or field, and the control that completes it wrapped in a ring.
   --------------------------------------------------------------------------- */

/* Grid and flex children default to `min-width: auto`, which means "never
   narrower than my content" — so one long movement name silently widened the
   whole column past the phone and `.app__body` absorbed it as a sideways
   scroll. Every link in the chain from screen to row has to be allowed to
   shrink, or the ellipsis on .row__name can never take effect. */
.screen > *, .block, .rows, .row { min-width: 0; }

.rows { display: grid; gap: 3px; }

.row {
  position: relative;
  appearance: none;
  border: 0;
  background: var(--surface);
  border-radius: var(--r-md);
  color: var(--text);
  display: flex;
  gap: var(--s2);
  align-items: center;
  /* No vertical padding: the 44px action button sets the row's height, which is
     the iOS minimum target and the smallest a row may honestly be. Phase 4's
     one-view rule and docs/11's tiles both have to fit on one 6.1" screen. */
  padding: 0 var(--s3);
  text-align: left;
  min-height: 44px;
  width: 100%;
}
/* The name is the only part that may take the slack, and the only part that may
   be cut short. Everything else keeps its size. */
.row > * { flex: none; }
/* `min-width: 0` is what actually lets a long movement name ellipsize instead
   of forcing the row wider than the phone. Without it a flex item refuses to
   shrink below its content, and the whole screen scrolls sideways. */
.row .row__name { flex: 1 1 auto; min-width: 0; }
/* The name may shrink, but not to an initial. Below this it stops being a
   label; the row would rather drop a pixel elsewhere. */
.row:has(.quick) .row__name { min-width: 52px; }
.row:has(.quick) .entry__value { max-width: 54px; }
button.row { cursor: pointer; }

.tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  /* The glyph is the darkest thing in the palette, which clears 6.2:1 or better
     on every one of the five tiles. Measured, not judged — see surface.html. */
  color: var(--canopy);
  background: var(--stone);
  flex: none;
}
.tile .icon { width: 18px; height: 18px; stroke-width: 1.9; }
.tile[data-attribute='might'] { background: var(--might); }
.tile[data-attribute='wind'] { background: var(--wind); }
.tile[data-attribute='grit'] { background: var(--grit); }
.tile[data-attribute='vitality'] { background: var(--vitality); }
.tile[data-attribute='mind'] { background: var(--mind); }

.row__name {
  font-size: var(--text-md);
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.row__value {
  font-size: var(--text-sm);
  color: var(--blue);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.row[data-done='true'] .row__value { color: var(--text-3); }

/* The control that completes the row, with its progress drawn around it. */
.row__act {
  position: relative;
  appearance: none;
  border: 0;
  background: none;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  padding: 0;
}
button.row__act { cursor: pointer; }
.row__act .icon { width: 17px; height: 17px; position: relative; }

.ring { position: absolute; inset: 5px; width: 34px; height: 34px; overflow: visible; }
.ring__track, .ring__fill { fill: none; stroke-width: 2.5; }
.ring__track { stroke: var(--edge); }
.ring__fill {
  stroke: var(--acid);
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
  transition: stroke-dashoffset var(--motion-screen) ease-out;
}

/* C — the ring completing, with a short spring. Under 400ms, and the global
   reduced-motion rule flattens it to nothing. */
@keyframes ring-spring {
  0% { transform: rotate(-90deg) scale(0.82); }
  55% { transform: rotate(-90deg) scale(1.12); }
  100% { transform: rotate(-90deg) scale(1); }
}
.row[data-justlogged='true'] .ring__fill { animation: ring-spring 340ms cubic-bezier(0.22, 1.2, 0.36, 1); }

/* C — the XP floats up in the attribute's colour, beside the thing that earned
   it. Every attribute colour clears 4.5:1 on --surface; that is why they were
   lifted from the raw art values. */
@keyframes float-up {
  0% { opacity: 0; transform: translateY(4px); }
  25% { opacity: 1; transform: translateY(-2px); }
  75% { opacity: 1; transform: translateY(-10px); }
  100% { opacity: 0; transform: translateY(-16px); }
}
.float {
  position: absolute;
  right: 52px;
  top: 6px;
  font-size: var(--text-sm);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  opacity: 0;
  animation: float-up 900ms ease-out;
}
.float[data-attribute='might'] { color: var(--might); }
.float[data-attribute='wind'] { color: var(--wind); }
.float[data-attribute='grit'] { color: var(--grit); }
.float[data-attribute='vitality'] { color: var(--vitality); }
.float[data-attribute='mind'] { color: var(--mind); }

/* F3 — things that arrive in pieces get quick-add buttons. */
.row:has(.quick) { gap: 6px; }
.quick { display: flex; gap: 3px; flex: none; }
.quick__add {
  appearance: none;
  border: 0;
  box-shadow: none;
  background: none;
  color: var(--text-2);
  border-radius: var(--r-full);
  font-size: var(--text-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 30px;
  min-height: 34px;
  padding: 0 3px;
  cursor: pointer;
}
.quick__add:active { background: var(--raised); color: var(--text); }

.entry__field { display: block; min-width: 0; flex: 0 1 auto; }
.entry__value {
  width: 100%;
  min-width: 44px;
  max-width: 62px;
  appearance: none;
  border: 0;
  background: var(--well);
  color: var(--text);
  border-radius: var(--r-sm);
  font: inherit;
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
  text-align: center;
  min-height: 38px;
  padding: 0 var(--s1);
}
.entry__value:focus { border-color: var(--acid); outline: none; }
.entry__unit { font-size: 12px; color: var(--text-3); letter-spacing: 0; margin-left: 3px; }

/* A row already worked is evidence, not a control. */
.row--worked .row__act { color: var(--text-3); }

/* C — the day finishing is one beat over the whole screen, not a modal. It
   fades on its own; there is nothing to dismiss. */
@keyframes day-beat {
  0% { opacity: 0; }
  20% { opacity: 1; }
  70% { opacity: 1; }
  100% { opacity: 0; }
}
.daybeat {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  pointer-events: none;
  background: var(--surface-1);
  animation: day-beat 1400ms ease-out forwards;
}
.daybeat__word {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 800;
  letter-spacing: 0;
  color: var(--acid);
}

/* What the last entry earned, said once, then gone. */
.earned { margin: 0; display: flex; align-items: baseline; gap: var(--s2); min-height: 21px; }
.earned__xp { font-size: var(--text-md); font-weight: 800; font-variant-numeric: tabular-nums; }
.earned__what { font-size: var(--text-sm); color: var(--text-2); text-transform: none; }

/* Everything off the daily list. One control, never a menu. */
.elsewhere__toggle {
  appearance: none;
  border: 0;
  background: none;
  color: var(--text-2);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0;
  padding: 0;
  min-height: 44px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--s2);
  justify-self: start;
}
.elsewhere__toggle .icon { width: 14px; height: 14px; }
.elsewhere { display: grid; gap: var(--s2); }

/* Logged work is collapsed by default: it is evidence, not a to-do list. */
.worked__toggle {
  appearance: none;
  border: 0;
  background: none;
  color: var(--text-2);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0;
  padding: 0;
  min-height: 44px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--s2);
  justify-self: start;
}
.worked__toggle .icon { width: 14px; height: 14px; }

.worked { display: grid; gap: var(--s1); }
.worked__row {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  background: var(--surface);
  border-radius: var(--r-sm);
  padding: var(--s2) var(--s3);
  font-size: var(--text-sm);
}
.worked__name { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.worked__value { color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }

.setting { margin: 0; display: flex; justify-content: space-between; gap: var(--s3); font-size: var(--text-md); }
.setting__label { color: var(--text-2); }
.setting__value { color: var(--text); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   Character — Phase 5.

   The one screen where the five attribute colours belong. docs/04: they survive
   only where attributes are the subject, and never in the tracker.
   --------------------------------------------------------------------------- */

.rank { grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--s4); }
.rank__letter {
  font-family: var(--font-display);
  font-size: 56px;
  font-weight: 800;
  letter-spacing: 0;
  line-height: 1;
}
.rank__main { display: grid; gap: 2px; min-width: 0; }
.rank__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.05;
}
.rank__meta { margin: 0; font-size: var(--text-sm); color: var(--text-2); }

.attr { gap: var(--s2); }

.attr__head {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  color: var(--text);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s3);
  text-align: left;
  cursor: pointer;
  min-height: 44px;
}
.attr__title { display: grid; gap: 2px; min-width: 0; }
.attr__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  letter-spacing: 0;

  line-height: 1.05;
}
.attr__tier { font-size: var(--text-md); color: var(--text-2); }
.attr__numbers { display: grid; justify-items: end; gap: 0; flex: none; }
.attr__level {
  font-family: var(--font-display);
  font-size: var(--text-xxl);
  font-weight: 800;
  letter-spacing: 0;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.attr__levellabel { font-size: 12px; letter-spacing: 0; color: var(--text-3); }

.attr__bar { height: 6px; border-radius: 3px; background: var(--well); position: relative; overflow: hidden; }
.attr__bar::after { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--fill); background: var(--text-2); }
.attr[data-attribute='might'] .attr__bar::after { background: var(--might); }
.attr[data-attribute='wind'] .attr__bar::after { background: var(--wind); }
.attr[data-attribute='grit'] .attr__bar::after { background: var(--grit); }
.attr[data-attribute='vitality'] .attr__bar::after { background: var(--vitality); }
.attr[data-attribute='mind'] .attr__bar::after { background: var(--mind); }

.attr__xp { margin: 0; font-size: var(--text-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }

.attr__detail { display: grid; gap: var(--s2); padding-top: var(--s2); }
.attr__subhead {
  margin: 0;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0;

  color: var(--text-3);
}

.feeds { display: grid; gap: var(--s2); }
.feed { display: grid; gap: 1px; }
.feed__label { font-size: var(--text-md); font-weight: 600; }
.feed__worth { font-size: var(--text-sm); color: var(--text-2); }

.fed { display: grid; gap: var(--s2); }
.fed__row { display: grid; grid-template-columns: minmax(0, 1fr) 72px auto; gap: var(--s3); align-items: center; }
.fed__label { font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fed__bar { height: 6px; border-radius: 3px; background: var(--well); position: relative; overflow: hidden; }
.fed__bar::after { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--fill); background: var(--text-2); }
.attr[data-attribute='might'] .fed__bar::after { background: var(--might); }
.attr[data-attribute='wind'] .fed__bar::after { background: var(--wind); }
.attr[data-attribute='grit'] .fed__bar::after { background: var(--grit); }
.attr[data-attribute='vitality'] .fed__bar::after { background: var(--vitality); }
.attr[data-attribute='mind'] .fed__bar::after { background: var(--mind); }
.fed__xp { font-size: var(--text-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }

.titles { display: grid; gap: var(--s2); }
.title {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px var(--s3);
  background: var(--surface);
  border-radius: var(--r-md);
  padding: var(--s3) var(--s4);
}
.title__name { font-family: var(--font-display); font-size: var(--text-md); font-weight: 700; }
.title__date { font-size: var(--text-sm); color: var(--text-2); white-space: nowrap; }
.title__why { grid-column: 1 / -1; font-size: var(--text-sm); color: var(--text-2); }

/* Icons are stroked line art at currentColor — one set, no emoji. */
.icon { display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ---------------------------------------------------------------------------
   The accent, and the only way to paint it.

   Three roles, three values. A screen may use all three; it may not invent a
   fourth, because there is no other selector in this file that sets --acid.
   `test/browser/surface.html` asserts both halves: at most three roles on a
   screen, and nothing painted acid without the attribute naming its role.

   Last in the file on purpose. These are single-attribute selectors, so a
   component rule of equal specificity defined below them would quietly win and
   the state would go unpainted.
   --------------------------------------------------------------------------- */

/* 1. The single primary action — the FAB, or the confirm. */
[data-acid='primary'] {
  background: var(--acid);
  color: var(--bg);
  border-color: var(--acid);
}

/* 2. The active state — the set being worked, the column being logged. */
[data-acid='active'] { color: var(--acid); }

/* 3. A value worth noticing — a PR, a max, a live counter. */
[data-acid='value'] { color: var(--acid); }

/* The 4px bar down the left edge of the row being worked. */
.setrow__edge[data-acid='active'] { background: var(--acid); }

/* ---------------------------------------------------------------------------
   The daily battle — docs/06.

   The one screen allowed theatre, and the theatre is motion and colour rather
   than illustration: sprites are the product's only real art requirement and
   CLAUDE.md forbids inventing them. Nothing in here may leak into the tracker.
   --------------------------------------------------------------------------- */

.battle__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.battle__rank {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 800;
  letter-spacing: 0;
  color: var(--text-2);
}

.fight {
  display: grid;
  gap: var(--s3);
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: var(--s4);
}
.fighter {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  grid-template-areas: 'mark name hp' 'mark meter hp';
  gap: var(--s1) var(--s3);
  align-items: center;
}
.fighter__mark { grid-area: mark; }
.fighter__name { grid-area: name; }
.fighter__hp { grid-area: hp; }
.meter { grid-area: meter; }
.fighter__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--r-md);
  color: var(--canopy);
  background: var(--stone);
}
.fighter__mark[data-attribute='might'] { background: var(--might); }
.fighter__mark[data-attribute='mind'] { background: var(--mind); }
.fighter__mark[data-attribute='vitality'] { background: var(--vitality); }
.fighter__mark .icon { width: 22px; height: 22px; }
.fighter__name { font-size: var(--text-md); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fighter__hp { font-size: var(--text-sm); font-variant-numeric: tabular-nums; color: var(--text-2); }
.fighter[data-boss='true'] .fighter__name { color: var(--vitality); }

/* A hurt hero is not a failure state, so the meter never turns red. It empties,
   which is information, and that is all. */
.meter { display: block; height: 6px; border-radius: var(--r-full); background: var(--well); overflow: hidden; }
.meter__fill { display: block; height: 100%; background: var(--text-2); transition: width 140ms linear; }
.meter[data-who='hero'] .meter__fill { background: var(--acid); }
.meter[data-who='enemy'] .meter__fill { background: var(--wind); }

.fight__vs {
  justify-self: center;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  letter-spacing: 0;
  color: var(--text-2);
}

.feed { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1); min-height: 108px; }
.feed__line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  font-size: var(--text-sm);
  color: var(--text-2);
  animation: feed-in 180ms ease-out;
}
@keyframes feed-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
.feed__line[data-by='note'] .feed__what { color: var(--text); font-weight: 600; }
.feed__dmg { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--wind); }
.feed__line[data-by='enemy'] .feed__dmg { color: var(--text-2); }
.feed__line[data-crit='true'] .feed__dmg { color: var(--acid); }

.outcome { display: grid; gap: var(--s3); }
.outcome__line { margin: 0; font-size: var(--text-sm); color: var(--text-2); }
.outcome__rewards { display: flex; gap: var(--s5); }
.reward { display: grid; gap: 2px; }
.reward__value { font-size: var(--text-lg); font-weight: 800; font-variant-numeric: tabular-nums; }
.reward__label { font-size: var(--text-xs); letter-spacing: 0; color: var(--text-2); }
.outcome__flavour { margin: 0; font-size: var(--text-sm); color: var(--text-2); font-style: italic; }

/* Pills in a row, sized to their words. `flex: 1 1 auto` turned the two-word
   PAUSE button into a circle the size of a coaster — the radius is --r-full, so
   any button given height without width becomes one. */
.battle__controls { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.battle__controls .button { flex: 0 0 auto; }
.battle__controls .button[data-battle='close'] { margin-left: auto; }

/* ---------------------------------------------------------------------------
   Settings — maintenance.

   Erasing everything is the one destructive action in the app, so it is the one
   place a warning colour is correct. It is not an overdue state or a judgement
   on the person; it is the button that cannot be taken back.
   --------------------------------------------------------------------------- */

.screen--settings .card > .button { justify-self: start; }

.reset__confirm { display: grid; gap: var(--s2); }
.reset__input {
  max-width: none;
  width: 100%;
  text-align: left;
  padding: 0 var(--s3);
  letter-spacing: 0;
  font-weight: 700;
}

.button--danger {
  background: none;
  box-shadow: none;
  color: var(--vitality);
}
.button--danger:disabled { box-shadow: none; color: var(--text-3); cursor: default; }
.button--danger:not(:disabled):active { background: var(--surface-3); color: var(--text-1); }

.notice {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-2);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  background: var(--well);
}
.notice[data-update='true'] { color: var(--acid); }
.notice[data-restore-preview] {
  display: grid;
  gap: var(--s2);
  line-height: 1.45;
}
.notice[data-restore-preview] .button { justify-self: start; margin-top: var(--s1); }

/* ---------------------------------------------------------------------------
   The daily-list chips in Settings.

   Restored after Phase 4.5: rebuilding Today replaced the block these lived in,
   and Settings still renders chips. Nothing asserted their appearance, so they
   went unstyled for a phase and only a screenshot found it — which is what the
   "some bugs are only visible to an eye" rule in CLAUDE.md is for.

   Scoped through `.marks` so Today's `.row.mark`, which is a row rather than a
   chip, is untouched.
   --------------------------------------------------------------------------- */

.marks { display: flex; flex-wrap: wrap; gap: var(--s2); }

.marks .mark {
  appearance: none;
  border: 0;
  box-shadow: none;
  background: none;
  color: var(--text-2);
  border-radius: var(--r-full);
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 0 var(--s3);
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  cursor: pointer;
}
.marks .mark .icon { width: 15px; height: 15px; flex: none; }

/* On is a filled chip, off is an outline. Neither is a problem state: an
   activity you do not track every day is a choice, not an omission. */
.marks .mark[data-on='true'] { background: var(--surface-2); color: var(--text); box-shadow: none; }


/* Redesign V1 — R1 shell foundation. */
html, body {
  background: var(--bg);
  color: var(--text-1);
  font-family: var(--font-ui);
}
body::before { content: none; background-image: none; }
.app {
  min-height: 100%;
  background: var(--bg);
}
.app__body {
  padding: calc(env(safe-area-inset-top) + 16px) 16px calc(77px + env(safe-area-inset-bottom));
}
#app:has(.screen--session) .app__body {
  padding-top: 0;
}
.screen { gap: 16px; }
.card,
.block {
  border: 0;
  border-radius: 16px;
  background: var(--surface-1);
  padding: 16px;
  box-shadow: none;
}
.screen__title {
  font-family: var(--font-ui);
  font-size: 34px;
  line-height: 41px;
  font-weight: 700;
  letter-spacing: 0;
}
.block__title {
  font-size: 17px;
  line-height: 22px;
  font-weight: 600;
  letter-spacing: 0;
}
.button {
  min-height: 44px;
  border-radius: var(--r-full);
  font-family: var(--font-ui);
  font-size: 17px;
  line-height: 22px;
  font-weight: 600;
  letter-spacing: 0;
  box-shadow: none;
}
.button[data-acid='primary'] {
  min-height: 52px;
  width: 100%;
  background: var(--train);
  color: var(--on-accent);
  border-color: var(--train);
}
.tabbar__tabs { gap: 0; }
.tabbar__tab {
  min-height: 52px;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 4px;
  border-radius: 10px;
  color: var(--text-3);
  font-family: var(--font-ui);
  font-size: 11px;
  line-height: 13px;
  font-weight: 500;
  letter-spacing: 0;
  padding: 4px 2px 0;
}
.tabbar__tab .icon { width: 22px; height: 22px; stroke-width: 1.5; }
.tabbar__tab[data-active='true'] { color: var(--train-ink); background: transparent; }
.active-workout-dock {
  left: 0;
  right: 0;
  bottom: calc(61px + env(safe-area-inset-bottom));
  height: 56px;
  background: var(--surface-3);
  border-top: 1px solid var(--hairline);
}
.active-workout-dock__button {
  min-height: 56px;
  height: 56px;
  border: 0;
  border-radius: 0;
  background: var(--surface-3);
  color: var(--text-1);
  box-shadow: none;
  padding: 6px 16px;
}
.active-workout-dock__copy strong { font-size: 17px; line-height: 22px; font-weight: 600; }
.active-workout-dock__resume {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 0 16px;
  border-radius: var(--r-full);
  background: var(--surface-2);
  color: var(--text-1);
  font-size: 15px;
  line-height: 20px;
  font-weight: 600;
  letter-spacing: 0;
}
.settings-access {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 16px);
  right: 16px;
  z-index: 40;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: var(--text-3);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.settings-access .icon { width: 22px; height: 22px; stroke-width: 1.5; }


/* Moved from the former inline index styles: keep shell behavior in the real stylesheet. */
html,
body,
.app {
  touch-action: pan-x pan-y;
  overscroll-behavior-x: none;
}
.row.entry[data-goal='true'] .entry__label {
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
  gap: 1px;
}
.row.entry[data-goal='true'] .entry__label .row__name {
  flex: none;
  min-width: 0;
}
.entry__progress {
  color: var(--chart);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.confirm-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  align-items: end;
  justify-items: center;
  padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
  background: var(--tabbar);
}
.confirm-sheet {
  width: min(100%, 520px);
  display: grid;
  gap: 12px;
  padding: 16px;
  border: 0;
  border-radius: 16px;
  background: var(--surface-3);
  box-shadow: none;
}
.confirm-sheet__eyebrow {
  margin: 0;
  color: var(--text-3);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
}
.confirm-sheet__title {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 22px;
  line-height: 28px;
  font-weight: 600;
}
.confirm-sheet__copy {
  margin: 0;
  color: var(--text-2);
  font-size: 17px;
  line-height: 22px;
}
.confirm-sheet__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding-top: 4px;
}
.confirm-sheet__discard {
  background: var(--surface-2);
  border-color: var(--danger);
  color: var(--danger);
}


/* ---------------------------------------------------------------------------
   Redesign V1 — Train (R4)
   --------------------------------------------------------------------------- */

.screen--train-r4 { gap: 16px; padding-bottom: 8px; }

.screen--train-r4 > .screen__title,
.train-r4__subheader .screen__title {
  margin: 0;
  font-size: 34px;
  line-height: 41px;
  font-weight: 700;
}

.train-r4__card {
  display: grid;
  gap: 12px;
  padding: 16px;
  border: 0;
  border-radius: 16px;
  background: var(--surface-1);
}

.train-r4__card h2 {
  margin: 0;
  font-size: 22px;
  line-height: 28px;
  font-weight: 600;
}

.train-r4__card p {
  margin: 0;
  color: var(--text-2);
  font-size: 15px;
  line-height: 20px;
}

.train-r4__segments {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 4px;
  padding-block: 2px;
}

.train-r4__segment {
  height: 6px;
  border-radius: var(--r-full);
  background: var(--surface-2);
}

.train-r4__segment[data-filled='true'] { background: var(--train); }

.train-r4__row {
  appearance: none;
  width: 100%;
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
  border: 0;
  background: transparent;
  color: var(--text-1);
  font: inherit;
  font-size: 17px;
  line-height: 22px;
  text-align: left;
}

.train-r4__row + .train-r4__row { border-top: 1px solid var(--hairline); }

.train-r4__row-copy {
  min-width: 0;
  display: grid;
  gap: 1px;
}

.train-r4__row-copy strong {
  overflow: hidden;
  font-size: 17px;
  line-height: 22px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.train-r4__row-copy small {
  overflow: hidden;
  color: var(--text-2);
  font-size: 13px;
  line-height: 18px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.train-r4__chevron {
  flex: none;
  color: var(--text-3);
  font-size: 28px;
  line-height: 1;
  font-weight: 400;
}

.train-r4__rows { margin-bottom: -4px; }

.train-r4__details {
  display: grid;
  gap: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--hairline);
}

.train-r4__secondary {
  appearance: none;
  width: 100%;
  min-height: 52px;
  border: 0;
  border-radius: var(--r-full);
  background: var(--surface-2);
  color: var(--text-1);
  font: inherit;
  font-size: 17px;
  line-height: 22px;
  font-weight: 600;
}

.train-r4__next { gap: 8px; }
.train-r4__next .train-r4__secondary { margin-top: 4px; }

.train-r4__list-card { gap: 4px; }
.train-r4__list-card > h2 { margin-bottom: 4px; }

.train-r4__utilities { gap: 0; padding-block: 4px; }

.train-r4__subheader {
  position: sticky;
  top: calc(env(safe-area-inset-top) + 10px);
  z-index: 30;
  background: var(--bg);
  min-height: 44px;
  display: grid;
  grid-template-columns: 44px 1fr 44px;
  align-items: center;
  gap: 4px;
}

.train-r4__subheader .screen__title {
  grid-column: 2;
  font-size: 22px;
  line-height: 28px;
  text-align: center;
}

.train-r4__back {
  appearance: none;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--train-ink);
  font: 400 34px/1 var(--font-ui);
}

.train-r4__routine-detail { gap: 16px; }
.train-r4__routine-exercises { display: grid; gap: 0; }
.train-r4__routine-exercises p { min-height: 44px; display: flex; align-items: center; }
.train-r4__routine-exercises p + p { border-top: 1px solid var(--hairline); }

.train-r4__card-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.train-r4__card-heading > span { color: var(--text-2); font-size: 13px; line-height: 18px; }

.train-r4__rhythm-scroll {
  display: flex;
  min-width: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.train-r4__rhythm-scroll::-webkit-scrollbar { display: none; }
.train-r4__rhythm-week { flex: 0 0 100%; min-width: 0; display: grid; gap: 8px; scroll-snap-align: start;
  box-sizing: border-box;
}
.train-r4__rhythm-week > strong { color: var(--train-ink); font-size: 13px; line-height: 18px; font-weight: 600; }
.train-r4__calendar { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; text-align: center; }
.train-r4__weekday { color: var(--text-3); font-size: 12px; line-height: 16px; font-weight: 500; }
.train-r4__day {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  justify-self: center;
  border: 2px solid var(--hairline);
  border-radius: 50%;
  color: var(--text-2);
  font-size: 13px;
  line-height: 18px;
  font-variant-numeric: tabular-nums;
}
.train-r4__day[data-trained='true'] { border-color: var(--train); }
.train-r4__day[data-qualified='true'] { background: var(--train); color: var(--on-accent); }
.train-r4__day[data-today='true'][data-qualified='false'] { border-color: var(--train); }

.train-r4__rhythm-card { appearance: none; width: 100%; min-width: 0; text-align: left; color: var(--text-1); font: inherit; }

.train-r4__rhythm-meta { color: var(--train-ink); }

.train-r4__hard-set-row { display: flex; justify-content: space-between; min-height: 32px; }

.train-r4__hard-set-row span:last-child { color: var(--train-ink); }
/* Local exercise creation, shared by every exercise picker. */
.custom-exercise { display: grid; gap: 12px; padding: 16px; background: var(--surface); border-radius: 20px; margin-block: 16px; }
.custom-exercise h2 { margin: 0; font-size: 22px; }
.custom-exercise p { margin: 0; font-size: 15px; }
.custom-exercise .notice:empty { display: none; }
.custom-exercise__field { display: grid; gap: 8px; font-weight: 600; }
.custom-exercise input, .custom-exercise select { width: 100%; min-width: 0; min-height: 48px; padding: 12px; border-radius: 12px; font: inherit; color: var(--text); background: var(--raised); border: 0; }
.custom-exercise__actions { display: flex; flex-wrap: wrap; gap: 12px; }
.plate-calculator-link { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex: 0 0 44px; border: 0; border-radius: 14px; background: var(--raised); color: var(--train-ink); }
.plate-calculator-link svg { width: 24px; height: 24px; }
.train-calculator-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; position: sticky; top: calc(env(safe-area-inset-top) + 10px); z-index: 30; background: var(--bg); padding-block: 4px; }
.train-calculator-bar .screen__title { margin: 0; }
.plate-calculator { position: fixed; inset: 0; width: 100%; height: 100%; max-width: 100%; max-height: 100%; margin: 0; padding: 0; border: 0; color: var(--text-1); background: var(--bg); overflow-y: auto; overscroll-behavior: contain; }
.plate-calculator::backdrop { background: var(--bg); }
.plate-calculator__header { position: sticky; top: 0; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: calc(env(safe-area-inset-top) + 16px) 16px 12px; background: var(--bg); }
.plate-calculator__header h1 { margin: 0; font-size: 24px; }
.plate-calculator__body { display: grid; gap: 16px; max-width: 430px; margin-inline: auto; padding: 8px 16px calc(env(safe-area-inset-bottom) + 24px); }
.plate-calculator__modes { display: flex; gap: 4px; padding: 4px; border-radius: 16px; background: var(--surface-1); }
.plate-calculator__modes button { flex: 1; min-height: 48px; padding: 8px; border: 0; border-radius: 12px; background: transparent; color: var(--text-2); font: inherit; font-size: 15px; font-weight: 600; }
.plate-calculator__modes button[aria-pressed="true"] { background: var(--surface-3); color: var(--text-1); }
.plate-calculator__field { display: grid; gap: 8px; font-weight: 600; }
.plate-calculator__field input { width: 100%; min-width: 0; height: 56px; padding: 12px 16px; border: 0; border-radius: 16px; background: var(--surface-2); color: var(--text-1); font: inherit; font-size: 24px; font-variant-numeric: tabular-nums; }
.plate-calculator__result { padding: 20px 16px; border-radius: 20px; background: var(--surface-1); text-align: center; }
.plate-calculator__total { display: block; color: var(--train-ink); font-size: 32px; font-variant-numeric: tabular-nums; }
.plate-calculator__note { margin: 8px 0; color: var(--text-2); font-size: 15px; line-height: 1.4; }
.plate-calculator__bar { position: relative; isolation: isolate; display: flex; align-items: center; gap: 6px; min-height: 160px; overflow-x: auto; padding: 8px; }
.plate-calculator__shaft { position: absolute; top: calc(50% - 6px); left: 0; width: 100%; height: 12px; background: var(--hairline); z-index: -1; }
.plate-calculator__bar-label { flex: 0 0 60px; padding: 8px 4px; border-radius: 8px; background: var(--surface-3); font-size: 14px; font-weight: 600; }
.plate-calculator__plate { display: flex; align-items: center; justify-content: center; flex: 0 0 40px; border-radius: 8px; background: var(--train); color: var(--on-accent); font-weight: 700; font-size: 15px; }
.plate-calculator__loading { margin: 8px 0 0; font-weight: 600; line-height: 1.5; overflow-wrap: anywhere; }
.plate-calculator__controls { display: grid; gap: 12px; }
.plate-calculator__inventory { padding: 8px 16px; border-radius: 20px; background: var(--surface-1); }
.plate-calculator__plate-row { display: grid; grid-template-columns: 1fr 48px 36px 48px; align-items: center; gap: 4px; min-height: 56px; }
.plate-calculator__plate-row span { text-align: center; font-variant-numeric: tabular-nums; }
.plate-calculator__plate-row button { min-height: 44px; border: 0; border-radius: 12px; background: var(--surface-2); color: var(--text-1); font: inherit; font-size: 24px; }
.plate-calculator__plate-row button:disabled { color: var(--text-3); background: transparent; }
.weekly-recap { width: calc(100% - 24px); max-width: 430px; max-height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 32px); padding: 0; border: 0; border-radius: 24px; background: var(--bg); color: var(--text-1); overscroll-behavior: contain; }
.weekly-recap::backdrop { background: var(--tabbar); opacity: .78; }
.weekly-recap__header { position: sticky; top: 0; z-index: 1; display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 16px; background: var(--bg); }
.weekly-recap__header h1 { margin: 4px 0 0; font-size: 24px; }
.weekly-recap__eyebrow { margin: 0; color: var(--train-ink); font-size: 15px; font-weight: 600; }
.weekly-recap__body { display: grid; gap: 16px; padding: 0 12px 16px; }
.weekly-recap__card { padding: 16px; border-radius: 20px; background: var(--surface-1); }
.weekly-recap__card h2 { margin: 0 0 12px; font-size: 20px; }
.weekly-recap__card p { font-size: 15px; line-height: 1.45; }
.weekly-recap__score { color: var(--train-ink); font-size: 36px; }
.weekly-recap__muted { color: var(--text-2); }
.weekly-recap__component { margin-top: 16px; }
.weekly-recap__breakdown summary { min-height: 44px; padding-block: 12px; color: var(--train-ink); font-weight: 600; }
.weekly-recap__component-label { display: flex; justify-content: space-between; gap: 12px; }
.weekly-recap__component p { margin: 4px 0 0; }
.weekly-recap__stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.weekly-recap__stats div { display: grid; gap: 4px; }
.weekly-recap__stats strong { font-size: 28px; font-variant-numeric: tabular-nums; }
.weekly-recap__stats span { color: var(--text-2); font-size: 14px; }
.weekly-recap__row { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-block: 10px; }
.weekly-recap__row div { text-align: right; }
.weekly-recap__row strong, .weekly-recap__row small { display: block; }
.weekly-recap__row small { margin-top: 4px; font-size: 13px; color: var(--text-2); }
.weekly-recap__progress { width: 100%; }
