/* atlas-browse.css — front-door "Browse the exercise library" section.
   Separate file (loaded after home.css) so it never collides with concurrent
   home.css edits. Reuses home.css :root tokens (--surface, --line-strong,
   --action-ink, --teal-ink, --mono, --r, spacing) which cascade on this page.
   Purpose: give the 227 atlas satellites real inbound links from the site's
   highest-authority page — they were an SEO island (0 front-door links). */

.atlas-browse{
  background:linear-gradient(170deg,var(--surface) 0%,var(--surface-2) 100%);
  border:1px solid var(--line-strong); border-radius:calc(var(--r) + 6px);
  padding:var(--s-4); margin:0 0 var(--s-6);
  box-shadow:0 24px 60px rgba(0,0,0,0.35), 0 0 0 1px rgba(37,99,235,0.06);
}
.atlas-browse .glance{color:var(--muted); font-size:var(--t-base); margin:0 0 var(--s-3); max-width:60ch;}
.atlas-cat{font-family:var(--mono); font-size:var(--t-cap); text-transform:uppercase; letter-spacing:0.18em; color:var(--teal-ink); margin:var(--s-3) 0 var(--s-1); font-weight:700;}
.atlas-cat:first-of-type{margin-top:0;}
.atlas-grid{
  list-style:none; margin:0 0 var(--s-2); padding:0;
  display:grid; grid-template-columns:1fr; gap:var(--s-1);
}
@media (min-width:560px){ .atlas-grid{grid-template-columns:repeat(2,1fr); gap:var(--s-2);} }
@media (min-width:860px){ .atlas-grid{grid-template-columns:repeat(4,1fr);} }
.atlas-grid a{
  display:flex; align-items:center; min-height:48px; padding:var(--s-2) var(--s-3);
  border:1px solid var(--line-strong); border-left:3px solid var(--action-ink);
  border-radius:var(--r-sm); background:var(--surface-2);
  color:var(--text); text-decoration:none;
  font-family:var(--mono); font-size:var(--t-sm); font-weight:700;
}
.atlas-grid a:hover{border-left-color:var(--teal-ink); color:var(--action-ink);}
.atlas-grid a:focus-visible{outline:var(--ring) solid var(--action-ink); outline-offset:2px;}
@media (prefers-reduced-motion:no-preference){
  .atlas-grid a{transition:color var(--dur),border-color var(--dur);}
}

/* popular badge on first exercise per category */
.atlas-badge{display:inline-block; font-family:var(--mono); font-size:0.625rem; font-weight:700; text-transform:uppercase; letter-spacing:0.08em; color:var(--on-action); background:var(--action); border-radius:4px; padding:2px 6px; margin-right:var(--s-1); flex:none; line-height:1.4;}

/* prominent full-library CTA */
.atlas-cta{display:flex; align-items:center; justify-content:center; gap:var(--s-1); min-height:52px; margin-top:var(--s-3); padding:0 var(--s-4); border:1px solid var(--action); border-radius:var(--r-sm); background:linear-gradient(135deg,var(--action) 0%,var(--action-hover) 100%); color:var(--on-action); text-decoration:none; font-family:var(--serif); font-weight:700; font-size:var(--t-base); box-shadow:0 6px 20px var(--shadow-blue); transition:transform var(--dur),box-shadow var(--dur);}
.atlas-cta:hover{transform:translateY(-2px); box-shadow:0 10px 30px var(--shadow-blue);}
.atlas-cta:focus-visible{outline:var(--ring) solid var(--action-ink); outline-offset:3px;}
@media (prefers-reduced-motion:reduce){ .atlas-cta:hover{transform:none;} }

/* full library grid — the /exercises hub lists all 227; denser columns. */
.atlas-grid-full{grid-template-columns:1fr;}
@media (min-width:560px){ .atlas-grid-full{grid-template-columns:repeat(2,1fr);} }
@media (min-width:860px){ .atlas-grid-full{grid-template-columns:repeat(3,1fr);} }

/* Screen-reader-only text must actually be screen-reader-only.
   /exercises marks up 18 elements as .sr-only — more than any other page — but
   loads only home.css + atlas-browse.css, and NEITHER defined the class. The
   rule exists in six other stylesheets (tools.css, dashboard.css, consent.css,
   free_mode.css, my-data.css, coach-chat.css), and every other page that uses
   sr-only loads one of them; this page was the single gap. So in production all
   18 were position:static, visibility:visible, opacity:1, full-size and
   hit-testable — the assistive-technology text was being shown to everyone.
   Definition copied verbatim from tools.css so all seven stay identical. */
.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;}

/* /exercises hub filter (progressive enhancement; hidden until JS reveals it) */
/* Height of the sticky filter bar at its TALLEST, which is the narrowest
   viewport: at 390px the count wraps under the input (90px), at 1440px it sits
   beside it (shorter). Anything that scrolls to an anchor under the bar offsets
   by this, so the offset is never smaller than the bar. */
:root{--ex-sticky-h:90px;}

/* The filter STICKS to the top of the results it produces.
   /exercises runs 17,517px unfiltered (about 21 screens) and still 6,547px
   filtered to a single muscle, and NOTHING on the page was sticky — so from the
   bottom of the results the search box, its live count, the 17 muscle chips and
   the family jump links were all off-screen, 5,703px away. The control that
   narrows the list has to stay reachable from inside the list.

   This was measured and REJECTED once, at 188px tall: it ate 22% of an 844px
   viewport. Cycle 12 collapsed the leaked sr-only label and the bar is now 90px,
   which is what makes it affordable.

   --ex-sticky-h is the contract between the bar and everything that scrolls to
   an anchor beneath it: .ex-fam offsets by it, so a family jump link can never
   land its heading behind the bar (before the offset, tapping "Core" put the
   heading at top:24 under a bar whose bottom was 188). Change one and the other
   follows. var(--bg) is themed in all four themes, so the bar is opaque in each. */
.ex-filter{display:flex; flex-wrap:wrap; align-items:center; gap:var(--s-2); margin:0 0 var(--s-3); position:sticky; top:0; z-index:5; background:var(--bg); padding:var(--s-2) 0; border-bottom:1px solid var(--line-strong);}
.ex-search{flex:1; min-width:200px; min-height:48px; padding:var(--s-2) var(--s-3); border:1px solid var(--line-strong); border-radius:var(--r-sm); background:var(--surface-2); color:var(--text); font-family:var(--mono); font-size:var(--t-base);}
.ex-search:focus{outline:var(--ring) solid var(--action-ink); outline-offset:2px; border-color:var(--action-ink);}
.ex-count{margin:0; font-family:var(--mono); font-size:var(--t-cap); letter-spacing:0.08em; text-transform:uppercase; color:var(--teal-ink);}
.ex-empty{color:var(--muted); font-size:var(--t-sm); margin:0 0 var(--s-3);}

/* /exercises grouped-by-movement view (2026-07-17). The 227-item library is
   grouped onto 6 movement families -> categories so what trains the same thing
   sits together; the search filter collapses empty groups (exercises.js). */
.ex-jump{display:flex; flex-wrap:wrap; gap:var(--s-1); margin:0 0 var(--s-3); padding:0 0 var(--s-3); border-bottom:1px solid var(--line-strong);}
.ex-jump a{display:inline-flex; align-items:center; gap:6px; min-height:44px; padding:0 var(--s-2); border:1px solid var(--line-strong); border-radius:999px; background:var(--surface-2); color:var(--muted); text-decoration:none; font-family:var(--mono); font-size:var(--t-cap); letter-spacing:0.06em; text-transform:uppercase;}
.ex-jump a:hover{color:var(--text); border-color:var(--action-ink);}
.ex-jump a:focus-visible{outline:var(--ring) solid var(--action-ink); outline-offset:2px;}
.ex-jump-n{font-variant-numeric:tabular-nums; color:var(--faint,var(--muted)); font-size:0.625rem;}

/* scroll-margin-top must clear the sticky .ex-filter (see --ex-sticky-h above),
   or every family jump link lands its heading behind the bar. */
.ex-fam{margin:0 0 var(--s-4); scroll-margin-top:calc(var(--ex-sticky-h) + var(--s-2));}
.ex-fam-h{display:flex; align-items:baseline; gap:var(--s-2); margin:0 0 var(--s-2); padding:0 0 var(--s-1); border-bottom:2px solid var(--action-ink);}
.ex-fam-name{font-family:var(--serif); font-weight:800; font-size:var(--t-lg); letter-spacing:-0.01em; color:var(--text);}
.ex-fam-n{font-family:var(--mono); font-size:var(--t-sm); color:var(--action-ink); font-variant-numeric:tabular-nums;}
.ex-cat{margin:0 0 var(--s-2);}
.ex-cat-h{display:flex; align-items:baseline; gap:var(--s-1); font-family:var(--mono); font-size:var(--t-cap); text-transform:uppercase; letter-spacing:0.18em; color:var(--teal-ink); margin:var(--s-2) 0 var(--s-1); font-weight:700;}
.ex-cat-n{font-variant-numeric:tabular-nums; color:var(--muted); font-size:0.625rem; letter-spacing:0.08em;}

/* --- UX ratchet 2026-07-22 (additive): raise 10px count badges to an 11px floor --- */
.ex-jump-n, .ex-cat-n, .atlas-badge{font-size:0.6875rem;}

/* --- Marketing motion pass (2026-07-22): badge shimmer + card spring --------- */
@media (prefers-reduced-motion: no-preference){
  .atlas-badge{ position:relative; overflow:hidden; }
  .atlas-badge::after{ content:""; position:absolute; inset:0; pointer-events:none;
    background: linear-gradient(100deg, transparent 35%, rgba(255,255,255,.28) 50%, transparent 65%);
    background-size: 250% 100%; animation: ab-shimmer 6s ease-in-out infinite; }
  @keyframes ab-shimmer{ 0%,100%{ background-position: 210% 0; } 40%,60%{ background-position: -60% 0; } }
  .atlas-grid a{ transition: transform .18s cubic-bezier(.34,1.56,.64,1), border-left-color .18s ease; }
  .atlas-grid a:hover{ transform: translateY(-2px); }
}

/* --- Wave 2 (2026-07-22): movement-family icons in the jump nav --------------
   Inline aria-hidden SVGs; stroke draws on hover/focus (no-preference only). */
.ex-jump a{ display:inline-flex; align-items:center; gap:6px; }
.ex-fam-ico{ width:15px; height:15px; flex:none; color:var(--action-ink); }
@media (prefers-reduced-motion: no-preference){
  .ex-fam-ico path, .ex-fam-ico circle{ stroke-dasharray:40; stroke-dashoffset:0; }
  .ex-jump a:hover .ex-fam-ico path, .ex-jump a:focus-visible .ex-fam-ico path,
  .ex-jump a:hover .ex-fam-ico circle, .ex-jump a:focus-visible .ex-fam-ico circle{
    animation: exfam-draw .6s ease-out; }
  @keyframes exfam-draw{ from{ stroke-dashoffset:40; } to{ stroke-dashoffset:0; } }
}

/* ── Browse-by-muscle chips (2026-07-25, cycle 5) ─────────────────────────────
   The hub could be searched by muscle after cycle 2, but nothing TOLD you that —
   you had to guess the word. These chips are the visible surface of that
   capability. Each one drives the same filter and carries the count the click
   actually returns (index hits, primary AND secondary), so the number on the
   chip and the number in the results readout can never disagree. */
.muscle-chips{margin:10px 0 4px;}
.muscle-chips[hidden]{display:none;}
.mc-lede{margin:0 0 8px; color:var(--muted,#9aa6b8); font-size:0.82rem; line-height:1.45;}
.mc-row{display:flex; flex-wrap:wrap; gap:7px;}
.mc-chip{display:inline-flex; align-items:center; gap:7px; min-height:44px; padding:0 13px;
  border:1px solid var(--line-strong,rgba(255,255,255,0.16)); border-radius:999px;
  background:var(--surface-2,#0a0b0e); color:var(--text,#eef2f8);
  font:600 0.84rem/1 inherit; cursor:pointer;
  transition:border-color .15s ease, background .15s ease, color .15s ease;}
.mc-chip:hover{border-color:var(--teal-ink,#2dd4bf);}
.mc-chip:focus-visible{outline:2px solid var(--teal-ink,#2dd4bf); outline-offset:2px;}
.mc-chip.is-on{border-color:var(--teal-ink,#2dd4bf); background:rgba(45,212,191,0.14); color:var(--teal-ink,#2dd4bf);}
.mc-n{font:700 0.72rem/1 ui-monospace,monospace; color:var(--muted,#9aa6b8);}
.mc-chip.is-on .mc-n{color:var(--teal-ink,#2dd4bf);}
@media (prefers-reduced-motion:reduce){ .mc-chip{transition:none;} }
