/* Durata — public exercise pages.
 *
 * DELIBERATELY SMALL. These pages load tokens.css + chrome.css + programs.css
 * first and reuse .pp-main / .pp-hero / .pp-section / .crumbs / .badge /
 * .set-chip / .table-wrap / .day-table / .btn-* wholesale, so a program page and
 * an exercise page can never drift apart visually. Only the components that do
 * not exist on a program page live here. If you find yourself restyling a
 * heading or a chip, you are in the wrong file — fix programs.css.
 *
 * Palette values come from tokens.css. Never write a hex here. */

/* ── Hero ─────────────────────────────────────────────────────────────── */
.pp-hero-solo { grid-template-columns: 1fr; }
.pp-hero-solo .pp-hero-text { max-width: 720px; }

/* contain, not cover: the clip is 854x480 so the two are identical for the
   video itself, but the POSTER is the 256x256 square still, and cover cropped
   it for as long as the clip took to arrive. */
.ex-clip {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 9;
  border-radius: 14px; border: 1px solid var(--border);
  background: var(--slab); object-fit: contain;
  box-shadow: 0 18px 44px rgba(0,0,0,0.5);
}
/* The nav is sticky, so an in-page jump lands under it without this. */
.pp-section[id], .ex-clip[id] { scroll-margin-top: 84px; }

/* Held-back clip (prefers-reduced-motion, or Save-Data). exercises-page.js adds
   .clip-held and the button; both are gone the moment it is played, so nothing
   here should assume it can style the played state. Same button language as
   .btn-secondary in chrome.css, just centred on the poster. */
.pp-hero-art.clip-held { position: relative; }
.ex-clip-play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(0,0,0,0.72); border: 1px solid var(--border);
  color: var(--text); font-weight: 600; font-size: 14px; font-family: inherit;
  padding: 12px 22px; border-radius: 12px; cursor: pointer;
  backdrop-filter: blur(6px);
  transition: background 0.2s;
}
.ex-clip-play::before { content: '\25B6'; font-size: 11px; }  /* ▶ */
.ex-clip-play:hover { background: rgba(0,0,0,0.85); }
/* Never animate the affordance itself — the people who see it are, more often
   than not, the ones who asked for less motion. */
@media (prefers-reduced-motion: reduce) { .ex-clip-play { transition: none; } }
.ex-hero-anatomy { display: flex; justify-content: center; }
.ex-hero-anatomy svg { max-height: 320px; width: auto; }

/* ── Consensus stat strip ─────────────────────────────────────────────────
   The lead evidence: numbers counted off the catalogue, not asserted. Wide
   tiles hold a prescription string ("5×5 @ 75%"), narrow ones hold a count. */
.stat-strip {
  display: grid; gap: 10px; margin: 4px 0 26px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.stat-tile {
  border: 1px solid var(--border); border-radius: 12px;
  background: linear-gradient(180deg, var(--surface), var(--paper-2));
  padding: 16px 16px 14px; display: flex; flex-direction: column; gap: 6px;
}
.stat-tile b {
  font-size: 30px; line-height: 1; letter-spacing: -0.02em; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.stat-wide { grid-column: span 2; }
.stat-wide b { font-size: 21px; line-height: 1.2; font-family: var(--mono); letter-spacing: -0.01em; }
.stat-tile span { font-size: 12.5px; line-height: 1.35; color: var(--muted); }
@media (max-width: 520px) { .stat-wide { grid-column: span 1; } .stat-wide b { font-size: 18px; } }

/* ── Program prescription table (inherits .day-table) ─────────────────── */
.pgm-table .pgm-cell a { color: var(--text); text-decoration: none; font-weight: 600; }
.pgm-table .pgm-cell a:hover { color: var(--accent); text-decoration: underline; }
/* Wraps on purpose: session names run long ("Workout A - 5s week") and under
   table-layout:fixed a nowrap cell does not clip, it overflows across the next
   column. */
.pgm-table .day-cell { color: var(--muted); font-size: 13px; }
.pgm-table .rule-cell { color: var(--muted2); font-size: 13px; }
/* This table carries four columns the day table does not, so it must restate the
   fixed-layout column widths: .day-table pins column 3 to 84px (right for a rest
   time, hopeless for a row of set chips), and under table-layout:fixed a td
   min-width cannot argue with that. Chips stacked one per line is how a single
   wave-program row grew to 1300px tall. Below 620px .table-wrap scrolls, which
   is the established behaviour of every table on the program pages. */
.pgm-table { width: 100%; min-width: 720px; }
.pgm-table th:nth-child(1) { width: 26%; }
.pgm-table th:nth-child(2) { width: 20%; }
.pgm-table th:nth-child(3) { width: 230px; }
/* Chips flow and wrap inside the cell for the same reason: a three-chip 5/3/1
   week is wider than any column width worth giving this table. Two prescriptions
   are separated by a rule rather than an inline mark — a Madcow ramp is nine
   chips over three lines, and a "/" between two of those cannot be found. */
.shape { display: block; }
.shape + .shape { margin-top: 7px; padding-top: 7px; border-top: 1px dashed var(--border); }
.shape-more { display: block; margin-top: 5px; font-size: 12px; color: var(--muted); }

/* ── Anatomy ──────────────────────────────────────────────────────────────
   BodyMap SVGs are emitted server-side with their own inline fills; this only
   frames them. Do not restyle the paths — the heat colours are the app's. */
.anatomy-pair { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; }
.anatomy {
  margin: 0; flex: 1 1 220px; max-width: 300px;
  border: 1px solid var(--border); border-radius: 14px;
  background: radial-gradient(120% 90% at 50% 0%, var(--surface2), var(--paper-2));
  padding: 18px 12px 12px;
}
.anatomy-art { display: flex; justify-content: center; }
/* Height pinned, width left to follow the viewBox. NOT interchangeable with
   `height: auto; max-height: 300px`, which is what this was: WebKit will not
   derive an SVG's width from its viewBox when the height is auto inside a flex
   container, so the same figure that laid out at 150x300 in Chromium computed to
   width 0 and the body map vanished from the Muscles worked section. The hero art
   below never broke because it always pinned one axis and set `width: auto`.
   The generator's only BodyMap call site emits height="300", so these two numbers
   are the rendered heights, not a guess at them. */
.anatomy-art svg { display: block; height: 300px; width: auto; max-width: 100%; }
.anatomy figcaption {
  text-align: center; margin-top: 10px; font-family: var(--mono);
  font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--muted);
}
.anatomy-tight .anatomy { flex: 1 1 150px; padding: 12px 8px 8px; }
.anatomy-tight .anatomy-art svg { height: 240px; }

.muscle-legend { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.muscle-chip {
  display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  border: 1px solid var(--border); border-radius: 999px; padding: 7px 14px 7px 10px;
  background: var(--surface); color: var(--muted2); font-size: 13px;
}
.muscle-chip:hover { border-color: var(--accent); color: var(--text); }
.muscle-chip i { width: 9px; height: 9px; border-radius: 50%; background: var(--muted); flex: none; }
.muscle-chip.is-primary { color: var(--text); }
.muscle-chip.is-primary i { background: var(--ink); box-shadow: 0 0 0 3px rgba(242,241,237,0.12); }
.muscle-chip em { font-style: normal; font-size: 11px; color: var(--muted); }

/* ── Technique lists ──────────────────────────────────────────────────── */
.how-list, .cue-list { margin: 0; padding: 0; list-style: none; counter-reset: step; }
.how-list li, .cue-list li {
  position: relative; padding: 14px 16px 14px 52px; margin-bottom: 8px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  color: var(--muted2); font-size: 15px; line-height: 1.55;
}
.how-list li::before {
  counter-increment: step; content: counter(step);
  position: absolute; left: 14px; top: 13px;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent-dim); border: 1px solid var(--accent);
  color: var(--text); font-family: var(--mono); font-size: 12px;
}
.cue-list li::before {
  content: ""; position: absolute; left: 22px; top: 22px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
}

/* ── Exercise cards ───────────────────────────────────────────────────── */
.ex-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.ex-card {
  display: flex; align-items: center; gap: 12px; text-decoration: none;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  padding: 8px; transition: background .15s, border-color .15s, transform .15s;
}
.ex-card:hover { background: var(--surface-hover); border-color: rgba(91,123,166,0.35); transform: translateY(-2px); }
/* SQUARE, because the stills are 256x256 squares — they are the app's carousel
   artwork, not frames pulled off the 854x480 clip. A 16/9 box with object-fit:
   cover centre-cropped every one of them, which took the head off the lifter.
   contain as well as square: if a future still arrives at another ratio it
   letterboxes on the slab rather than silently cropping again. */
.ex-card-thumb {
  flex: none; width: 64px; aspect-ratio: 1; border-radius: 8px; overflow: hidden;
  background: var(--slab); display: grid; place-items: center;
}
.ex-card-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ex-card-mono { font-family: var(--mono); font-size: 15px; color: var(--muted); letter-spacing: .06em; }
.ex-card-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ex-card-body b { color: var(--text); font-size: 14px; font-weight: 600; line-height: 1.25; }
.ex-card-meta { color: var(--muted); font-size: 12px; }

/* ── Library index: search + muscle chips ─────────────────────────────── */
.ex-controls { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; }
.ex-search { display: block; }
#ex-search {
  width: 100%; box-sizing: border-box; padding: 13px 16px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); color: var(--text); font: inherit; font-size: 15px;
}
#ex-search:focus { outline: none; border-color: var(--accent); }
#ex-search::placeholder { color: var(--muted); }
.ex-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.ex-chip {
  border: 1px solid var(--border); border-radius: 999px; background: transparent;
  color: var(--muted2); font: inherit; font-size: 12.5px; padding: 6px 13px; cursor: pointer;
}
.ex-chip:hover { color: var(--text); border-color: var(--accent); }
.ex-chip.is-on { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.ex-count { font-size: 12.5px; color: var(--muted); margin: 0 0 16px; min-height: 1em; }
.ex-group { margin-bottom: 30px; }
.ex-group h3 {
  display: flex; align-items: baseline; gap: 10px; margin: 0 0 12px;
  font-size: 15px; font-weight: 600; color: var(--text);
}
.ex-group h3 a { color: inherit; text-decoration: none; }
.ex-group h3 a:hover { color: var(--accent); }
.ex-group h3 span { font-family: var(--mono); font-size: 11px; color: var(--muted); }
.ex-empty { color: var(--muted); font-size: 14px; }

/* ── Ranked lists (most-programmed, muscle volume) ─────────────────────────
   A real bar chart, not a decorated list: the bar owns its own column, sits on
   a zero baseline and is scaled against a STATED maximum (the axis prints it),
   so a row's length means something on its own rather than only relative to
   whatever happens to be top. One series, so one flat colour — no ramp, no
   gradient. Bar widths are the only inline style on the page.
   Columns are declared once here and shared by the axis and every row; they are
   in rem, not em, because the axis sets a smaller font and an em-sized column
   would then be narrower there and throw the ticks out of line with the bars. */
.rank-chart { --rank-cols: 22px minmax(0, 14rem) minmax(0, 1fr) 2.6rem; }
.rank-axis {
  display: grid; grid-template-columns: var(--rank-cols); gap: 14px; align-items: end;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em; color: var(--muted);
  padding-bottom: 7px; border-bottom: 1px solid var(--border);
}
.rank-axis .rank-ticks { display: flex; justify-content: space-between; }
.rank-axis i { font-style: normal; }
.rank-list { list-style: none; margin: 0; padding: 0; }
.rank-list li {
  display: grid; grid-template-columns: var(--rank-cols); gap: 14px;
  align-items: center; padding: 7px 0;
}
.rank-n { font-family: var(--mono); font-size: 11px; color: var(--muted); text-align: right; }
.rank-list a {
  color: var(--text); text-decoration: none; font-size: 14.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rank-list a:hover { color: var(--accent); }
/* The track carries the scale: a faint slot to the stated maximum, with a
   hairline at every tick so a bar can be read off without a gridline overlay. */
.rank-track {
  position: relative; height: 12px; border-radius: 2px; background-color: rgba(242,241,237,0.045);
  background-image: repeating-linear-gradient(90deg, var(--border) 0 1px, transparent 1px var(--rank-tick, 20%));
}
.rank-bar { position: absolute; inset: 0 auto 0 0; background: var(--accent); border-radius: 0 3px 3px 0; }
.rank-list b {
  text-align: right; font-family: var(--mono); font-size: 13px; font-weight: 400;
  font-variant-numeric: tabular-nums; color: var(--muted2);
}
.rank-list li:first-child b { color: var(--text); }
/* Narrow: the name gets the full width and the bar drops under it, so neither
   is squeezed to a stub. */
@media (max-width: 640px) {
  .rank-chart { --rank-cols: 22px minmax(0, 1fr) 2.6rem; }
  .rank-axis { row-gap: 5px; }
  .rank-axis .rank-axis-label { grid-column: 2 / 4; grid-row: 1; }
  .rank-axis .rank-ticks { grid-column: 2 / 4; grid-row: 2; }
  .rank-list li { row-gap: 7px; padding: 9px 0; }
  .rank-n, .rank-list a, .rank-list b { grid-row: 1; }
  .rank-list a { grid-column: 2; }
  .rank-list b { grid-column: 3; }
  .rank-track { grid-column: 2 / 4; grid-row: 2; }
}

/* ── Hubs + cross-navigation ──────────────────────────────────────────── */
.hub-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.hub-card {
  display: flex; flex-direction: column; gap: 4px; text-decoration: none;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  padding: 16px 18px; transition: background .15s, border-color .15s;
}
.hub-card:hover { background: var(--surface-hover); border-color: rgba(91,123,166,0.35); }
.hub-card b { color: var(--text); font-size: 15px; }
.hub-card span { color: var(--muted); font-size: 12.5px; }

.ex-crossnav {
  display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  margin: 44px 0 20px;
}
.ex-crossnav a {
  display: flex; flex-direction: column; gap: 4px; text-decoration: none;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  padding: 16px 18px;
}
.ex-crossnav a:hover { background: var(--surface-hover); border-color: rgba(91,123,166,0.35); }
.ex-crossnav span {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted);
}
.ex-crossnav b { color: var(--text); font-size: 15px; font-weight: 600; }

/* ── Small shared bits ────────────────────────────────────────────────── */
.badge-on { border-color: var(--accent); color: var(--text); }
.badge-link { text-decoration: none; }
.badge-link:hover { border-color: var(--accent); color: var(--text); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
