/* ============================================================================
   YogaPath — site layer on top of the shared styles.css / data.css.
   Pure CSS and inline SVG. No external images, no icon fonts, no libraries:
   the target is a mid-range Android phone on a slow Indian connection.
   ========================================================================== */

/* AAA+++ 2026-07-31. The site used to run TWO purples: the shared accent
   (#7B3F6B, contrast-tuned plum) and a much brighter violet ramp of its own
   (#7e22ce). Two unrelated purples on one page is the cheapest tell there is,
   so the whole yp ramp is now derived from the accent and the site reads as
   one dyed cloth. Values are literal rather than color-mix() so the ramp
   holds where a step needs to be darker than a mix can reach. */
:root {
  --yp: #7B3F6B;
  --yp-2: #9A5C88;
  --yp-3: #BC8DAC;
  --yp-soft: #F6F0F4;
  --yp-line: #E4D2DE;
  --yp-ink: #4A2540;
  --sky-1: #F1E9EE;
  --sky-2: #FBF6F2;
  --fig: #7B3F6B;
  --fig-2: #9A5C88;
  --mat: #E4D2DE;
  /* the site's drawing hand — 1.6px, round cap, nobody else's in the ring */
  --hand: 1.6;
  /* the same hand, for CSS boxes that draw a tick rather than an SVG stroke */
  --hand-px: 1.6px;
}

[data-theme="dark"] {
  --yp: #C58FBA;
  --yp-2: #B078A4;
  --yp-3: #8A5A7C;
  --yp-soft: #241A21;
  --yp-line: #3B2C36;
  --yp-ink: #EDD9E6;
  --sky-1: #1E181C;
  --sky-2: #221A20;
  --fig: #C58FBA;
  --fig-2: #A9749B;
  --mat: #3B2C36;
}

/* ====================================================== THE SESSION STRIP
   The set piece (AAA+++ §5, "yoga | Ashram timetable"). A practice laid out
   on a time ruler in the site's own 1.6px round hand. Every stroke here is
   the same weight and the same terminal; no fills except the hold band.   */
.yp-strip { margin: 22px 0 0; padding: 0; }
.yp-strip svg { display: block; width: 100%; height: auto; }
.yp-strip-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  justify-content: space-between;
  border-bottom: 1px solid var(--line); padding-bottom: 8px; margin-bottom: 6px;
}
.yp-strip-head .spec { color: var(--muted); }

.yp-strip path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.yp-strip .rule  { stroke: var(--line-2); stroke-width: 1; }
.yp-strip .tick  { stroke: var(--line-2); stroke-width: 1; }
.yp-strip .comb  { stroke: var(--yp-3); stroke-width: 1; }
.yp-strip .lead  { stroke: var(--line-2); stroke-width: 1; stroke-dasharray: 2 4; }
.yp-strip .glyph path { stroke: var(--ink-2); stroke-width: var(--hand); }
.yp-strip .seg   { stroke: var(--yp); stroke-width: calc(var(--hand) * 2); }
.yp-strip .band  { fill: var(--yp-soft); stroke: none; }
.yp-strip text {
  font-family: var(--mono); font-size: 12px; letter-spacing: .06em;
  fill: var(--muted); font-variant-numeric: tabular-nums lining-nums;
}
.yp-strip .idx { font-size: 11px; fill: var(--faint); }
.yp-strip .unit { fill: var(--faint); }
/* the current pose, when a strip is drawn around one */
.yp-strip .st.on .glyph path { stroke: var(--yp); }
.yp-strip .st.on .idx { fill: var(--yp); }
.yp-strip .st.on .lead { stroke: var(--yp-3); stroke-dasharray: none; }

.yp-strip-key {
  list-style: none; display: flex; flex-wrap: wrap; gap: 4px 18px;
  margin: 10px 0 0; padding: 10px 0 0; border-top: 1px solid var(--line);
  font-size: .84rem;
}
.yp-strip-key li { color: var(--ink-2); }
.yp-strip-key li.on { color: var(--ink); font-weight: 650; }
.yp-strip-key .n {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .06em;
  color: var(--faint); margin-right: 6px;
}
.yp-strip-key a { color: inherit; text-decoration: none; border-bottom: 1px solid var(--line-2); }
.yp-strip-key a:hover { border-bottom-color: var(--yp); }

@media (max-width: 560px) {
  .yp-strip text { font-size: 15px; }
  .yp-strip .idx { font-size: 14px; }
}

/* DELETED 2026-08-10 — the hero 3D scene (.yp-scene / .yp-cap / .yp-float-a /
   .yp-float-b / .yp-breathe / .yp-glow and their four keyframe blocks). The
   seated-figure illustration they styled was removed from build.mjs on
   2026-07-31 because it was a second, softer drawing hand — gradients and
   filled shapes — with nothing to do with the 1.6px round line the rest of the
   site is built from. The CSS outlived the markup by ten days. Verified zero
   occurrences of every one of those classes across dist/ before removing.

/* ------------------------------------------------------------- name block */
.yp-names {
  display: grid; gap: 10px; margin: 18px 0 0;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.yp-name {
  background: var(--yp-soft); border: 1px solid var(--yp-line);
  border-radius: 12px; padding: 12px 14px;
}
.yp-name .k {
  display: block; font-size: .72rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--muted); font-weight: 700; margin-bottom: 3px;
}
.yp-name .v { display: block; font-size: 1.05rem; font-weight: 700; color: var(--ink); line-height: 1.35; }
.yp-name .v.dev { font-size: 1.3rem; }
.yp-name .s { display: block; font-size: .8rem; color: var(--muted); margin-top: 2px; }

/* --------------------------------------------------------------- fact strip */
.yp-facts {
  display: grid; gap: 10px; margin-top: 18px;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}
.yp-fact {
  border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px;
  background: var(--card);
}
.yp-fact b { display: block; font-size: 1.22rem; font-weight: 800; color: var(--ink); line-height: 1.2; }
.yp-fact span { display: block; font-size: .74rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 700; margin-bottom: 4px; }
.yp-fact em { display: block; font-style: normal; font-size: .78rem; color: var(--muted); margin-top: 3px; }

/* ---------------------------------------------------------------- the steps */
.yp-steps { counter-reset: ypstep; list-style: none; padding: 0; margin: 0; }
.yp-steps li {
  counter-increment: ypstep; position: relative;
  padding: 0 0 18px 46px; margin: 0;
  border-left: 2px solid var(--yp-line); margin-left: 15px;
}
.yp-steps li:last-child { border-left-color: transparent; padding-bottom: 0; }
.yp-steps li::before {
  content: counter(ypstep);
  position: absolute; left: -16px; top: -2px;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--yp); color: #fff;
  display: grid; place-items: center;
  font-size: .85rem; font-weight: 800;
}
.yp-steps li p { margin: 4px 0 0; }

/* ------------------------------------------------------- contraindications
   Deliberately the loudest block on the page. On a yoga site this is the
   part that matters most and the part everybody else buries.                */
/* AAA+++ §7.4: contraindications are a SAFETY SURFACE, not an alert. The
   amber-on-yellow box read as liability panic — the register that makes a
   reader discount the warning. Hairline rules, an accent keel and ordinary
   ink carry more weight, because they read as a page that always says this
   rather than a page that has just been frightened. */
.yp-care {
  border: 0; background: none; border-radius: 0; padding: 0; margin: 0;
  border-top: 1px solid var(--ink-2); border-bottom: 1px solid var(--line);
  padding: 18px 0 20px;
}
.yp-care h2, .yp-care h3 {
  margin: 0 0 12px; font-size: 1.12rem; color: var(--ink);
  display: flex; align-items: center; gap: 9px;
}
.yp-care h2 svg, .yp-care h3 svg { width: 18px; height: 18px; flex: none; color: var(--yp); stroke-width: 1.6; }
.yp-care ul { margin: 0; padding-left: 0; list-style: none; }
.yp-care li {
  margin: 0; color: var(--ink); padding: 9px 0 9px 20px;
  border-top: 1px solid var(--line); position: relative;
}
.yp-care li::before {
  content: ""; position: absolute; left: 0; top: 17px;
  width: 10px; height: 1.6px; background: var(--yp); border-radius: 1px;
}
.yp-care .yp-care-note { margin: 14px 0 0; font-size: .86rem; color: var(--muted); }

/* -------------------------------------------------------------- mistakes */
.yp-mis { display: grid; gap: 12px; }
.yp-mis-row {
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  background: var(--card);
}
.yp-mis-row p { margin: 0; padding: 12px 14px; }
.yp-mis-row .m { border-bottom: 1px solid var(--line); }
.yp-mis-row .m b, .yp-mis-row .f b {
  display: inline-block; font-size: .7rem; text-transform: uppercase;
  letter-spacing: .07em; margin-right: 8px; font-weight: 800;
}
.yp-mis-row .m b, .yp-mis-row .f b {
  font-family: var(--mono); font-size: .7rem; letter-spacing: .1em; font-weight: 400;
}
.yp-mis-row .m b { color: var(--muted); }
.yp-mis-row .f b { color: var(--yp); }
.yp-mis-row .f { background: var(--yp-soft); }

/* --------------------------------------------------------------- muscles */
.yp-muscles { display: grid; gap: 8px; }
.yp-muscle {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 10px; border: 1px solid var(--line);
  background: var(--card);
}
.yp-muscle i {
  width: 10px; height: 10px; border-radius: 3px; flex: none; background: var(--yp-3);
}
.yp-muscle.pri i { background: var(--yp); }
.yp-muscle span { font-weight: 600; color: var(--ink); }
.yp-muscle small { margin-left: auto; color: var(--muted); font-size: .76rem; }

/* --------------------------------------------------------------- filters */
.yp-filter {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin: 0 0 18px; padding: 14px; border-radius: 14px;
  border: 1px solid var(--line); background: var(--card);
}
.yp-filter label {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 800; color: var(--muted); margin-right: 2px;
}
.yp-filter button {
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  border-radius: 999px; padding: 7px 14px; font-size: .86rem; font-weight: 600;
  cursor: pointer; font-family: inherit;
}
.yp-filter button:hover { border-color: var(--yp-2); }
.yp-filter button[aria-pressed="true"] { background: var(--yp); border-color: var(--yp); color: #fff; }
.yp-count { margin: 0 0 14px; color: var(--muted); font-size: .88rem; }

.yp-list { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.yp-card {
  display: block; border: 1px solid var(--line); border-radius: 14px;
  padding: 14px 16px; background: var(--card); text-decoration: none;
  border-left: 4px solid var(--yp-3);
}
.yp-card:hover { border-color: var(--yp-2); border-left-color: var(--yp); }
.yp-card .en { display: block; font-weight: 700; color: var(--ink); font-size: 1.02rem; }
.yp-card .sa { display: block; color: var(--yp); font-size: .88rem; font-weight: 600; margin-top: 1px; }
.yp-card .me { display: block; color: var(--muted); font-size: .78rem; margin-top: 6px; }
.yp-card[data-lvl="intermediate"] { border-left-color: var(--yp-2); }
.yp-card[data-lvl="advanced"] { border-left-color: var(--yp-ink); }

.yp-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.yp-tag {
  font-size: .7rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px; background: var(--yp-soft);
  color: var(--yp-ink); border: 1px solid var(--yp-line);
}

/* -------------------------------------------------------------- sequence */
.yp-seq { list-style: none; padding: 0; margin: 0; counter-reset: ypseq; }
.yp-seq > li {
  counter-increment: ypseq; display: grid; gap: 4px;
  grid-template-columns: 44px 1fr auto; align-items: start;
  padding: 14px 0; border-bottom: 1px solid var(--line);
}
.yp-seq > li:last-child { border-bottom: 0; }
.yp-seq .n {
  grid-row: span 2; width: 32px; height: 32px; border-radius: 50%;
  background: var(--yp-soft); border: 1px solid var(--yp-line);
  color: var(--yp-ink); display: grid; place-items: center;
  font-weight: 800; font-size: .85rem;
}
.yp-seq .nm { font-weight: 700; color: var(--ink); }
.yp-seq .nm a { color: inherit; }
.yp-seq .nm em { font-style: normal; color: var(--yp); font-weight: 600; }
.yp-seq .st {
  grid-column: 3; font-size: .8rem; color: var(--muted); font-weight: 600;
  white-space: nowrap; padding-left: 12px;
}
.yp-seq .no { grid-column: 2 / span 2; color: var(--muted); font-size: .9rem; margin: 0; }

@media (max-width: 560px) {
  .yp-seq > li { grid-template-columns: 36px 1fr; }
  .yp-seq .st { grid-column: 2; padding-left: 0; }
  .yp-seq .no { grid-column: 2; }
}

/* ------------------------------------------------------------ misc bits */
.yp-quick {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px;
}
.yp-quick a {
  border: 1px solid var(--yp-line); background: var(--yp-soft); color: var(--yp-ink);
  border-radius: 999px; padding: 7px 14px; font-size: .85rem; font-weight: 700;
  text-decoration: none;
}
.yp-quick a:hover { border-color: var(--yp); }

.yp-lvl {
  display: inline-block; font-size: .7rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; padding: 3px 9px; border-radius: 999px;
  background: var(--yp); color: #fff;
}
.yp-lvl.intermediate { background: var(--yp-2); }
.yp-lvl.advanced { background: var(--yp-ink); }
[data-theme="dark"] .yp-lvl { color: #1a1024; }
/* SAME BUG, TWO MORE INSTANCES — found by audit 2026-08-09. `--yp` is crimson
   on light but MARIGOLD on dark, so `color:#fff` on it is ~1.7:1 in dark mode.
   The step numerals are the most-read element on every asana page, which is
   the worst possible place for it on a site whose brand is being careful.
   #1a1024 on #F0A44E is ~9.9:1 — the pair already proven for .yp-lvl above. */
[data-theme="dark"] .yp-steps li::before,
[data-theme="dark"] .yp-filter button[aria-pressed="true"] { color: #1a1024; }

.hindi, .dev { font-family: "Noto Sans Devanagari", "Nirmala UI", "Mangal", system-ui, sans-serif; }

.yp-two { display: grid; gap: 18px; grid-template-columns: 1fr 1fr; }
@media (max-width: 720px) { .yp-two { grid-template-columns: 1fr; } }

.yp-src {
  font-size: .84rem; color: var(--muted); border-top: 1px solid var(--line);
  padding-top: 16px; margin: 0;
}

/* ================================================ AAA+++ site-local adopts
   The mechanics themselves live in data.css §20; these are the three places
   this site has to say how they attach to ITS markup.                      */

/* 1. entrance choreography. The classes are on inline elements inside the
   shared hero, so they need a block box or the translate does nothing. */
.hero .eyebrow .reveal,
.hero h1 .reveal { display: block; }

/* 2. the answer, unboxed. The hold or the session length is the figure the
   page exists to give, so it is set as display type with the unit in the
   mono voice beneath it — not as a bolded run of body copy. */
.yp-answer { margin: 22px 0 0; }
.yp-answer .stat-display { display: block; margin: 0; color: var(--ink); }
.yp-answer .stat-display .u { display: block; margin: 6px 0 0; vertical-align: baseline; }
.yp-answer p { margin: 12px 0 0; color: var(--ink-2); max-width: 62ch; }
.yp-answer .srcline { max-width: 62ch; }

/* 3. in-content links draw their underline (§3.6) rather than swapping a
   colour. Applied by class in the markup; this makes the accent the plum. */
.prose a.draw, .tnote a.draw, .yp-strip-head a.draw { color: var(--ink); }

/* the timetable rule above a wall-posted section heading */
.yp-hours {
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: .06em;
  color: var(--faint); text-transform: uppercase; margin: 0 0 4px;
}

/* ============================================================================
   CINEMA LAYER -- 2026-08-07. "Cinematic Bollywood", briefed off
   theshilpashetty.com: generous ivory, ONE vivid accent, editorial display
   type, image-forward rhythm. Everything below is additive and lives only in
   this file, so the shared ring stylesheet (styles.css) is untouched and no
   other site in the portfolio moves.

   Two hard constraints from the existing build are respected on purpose:
     - ZERO new network requests. The "cinematic" grade is gradients, a CSS
       grain and a vignette -- no webfont, no hero photograph, no library. The
       target is still a mid-range Android phone on a slow Indian connection.
     - Contrast stays AAA-grade. --accent carries white text, so it is the
       deep rose-crimson, not the marigold; the marigold is ORNAMENT ONLY
       (hairlines, eyebrows, rules) and never sits under text on light.
   ========================================================================== */
:root {
  /* the film stock */
  --bg: #FAF5EF;            /* ivory paper, warm */
  --bg-tint: #F4EAE0;
  --surface: #FFFDFA;
  --surface-2: #F6EFE7;
  --surface-sunken: #F1E8DE;
  --ink: #17101A;           /* aubergine-black -- 17.9:1 on surface */
  --ink-2: #43303F;         /*  9.6:1 */
  --muted: #6B5462;         /*  5.9:1 */
  --line: #E6D8CC;
  --line-2: #CDB8A6;
  --accent: #A3123E;        /* deep rose-crimson -- 8.4:1; #fff on it = 8.4:1 */
  --accent-2: #7C0C2E;
  --accent-3: #A3123E;
  --accent-soft: #FBEDF0;
  --accent-line: #EBC9D2;
  --ink-num: #17101A;
  /* ornament only -- never text on light */
  --gold: #C08A2E;
  --gold-soft: #F6E9CE;
  /* the site ramp is re-dyed from the new accent so the page reads as one
     cloth, exactly as the plum ramp did before it */
  --yp: #A3123E;
  --yp-2: #B94465;
  --yp-3: #D89BAC;
  --yp-soft: #FBEDF0;
  --yp-line: #EBC9D2;
  --yp-ink: #5C0A24;
  --sky-1: #F4E6DA;
  --sky-2: #FBF4EC;
  --fig: #A3123E;
  --fig-2: #B94465;
  --mat: #E6D8CC;
  /* the display voice -- a system serif stack, so it costs nothing to load and
     still reads as a poster rather than a dashboard */
  /* ⚠ CORRECTED 2026-08-09. This was a system-serif stack, chosen on the belief
     that the ring shipped no webfonts. That belief was WRONG: globalsite.mjs
     loads Fraunces + Inter from Google Fonts on every page, and Fraunces is
     served as a VARIABLE font with its opsz 9-144 axis plus real optical
     tuning in datasite.css. So the old value downloaded Fraunces and then
     refused to use it — paying the whole cost of the request and taking none
     of the benefit, while swapping a tuned display face for Palatino.
     Identity A is Fraunces for display; this now honours it. */
  --display: var(--serif, "Fraunces", Georgia, serif);
}

:root[data-theme="dark"], [data-theme="dark"] {
  --bg: #0C0910;            /* cinema-black, warm */
  --bg-tint: #1A1119;
  --surface: #16101A;
  --surface-2: #1E1622;
  --surface-sunken: #120C16;
  --ink: #F6EDE6;
  --ink-2: #D3C0C9;
  --muted: #A18F9A;
  --line: #2E2231;
  --line-2: #453346;
  --accent: #F0A44E;        /* marigold carries on black; ink on it = 9.9:1 */
  --accent-2: #D98A34;
  --accent-3: #F0A44E;
  --accent-soft: #241A1F;
  --accent-line: #4A3427;
  --ink-num: #F6EDE6;
  --gold: #F0A44E;
  --gold-soft: #2A1E16;
  --yp: #F0A44E;
  --yp-2: #D98A34;
  --yp-3: #A97638;
  --yp-soft: #241A1F;
  --yp-line: #3E2C33;
  --yp-ink: #F6E0C6;
  --sky-1: #1A1119;
  --sky-2: #16101A;
  --fig: #F0A44E;
  --fig-2: #D98A34;
  --mat: #3E2C33;
}

/* ---------------------------------------------------------------- the type
   Display serif on the headline voice only. Body copy, data and the mono
   voice are left alone -- the numbers are the product and they stay in the
   engineered register. */
/* ⚠ `.stat-display` was in this selector and must not be. datasite.css gives
   the hero numeral font-weight 340 with "opsz" 144 on purpose — the light
   extreme against h1's opsz 84 is the "two extremes per page" that stops
   display type reading like one weight applied everywhere. Blanket-setting 600
   here flattened exactly the contrast the shared sheet was written to create.
   Headings only; the numeral keeps its own tuning. */
h1, .sec {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -0.015em;
}
h1 { line-height: 1.06; }
h1 em {
  font-family: var(--display);
  font-style: italic;
  font-weight: 500;
  color: var(--accent);
}
.sec { font-weight: 600; letter-spacing: -0.01em; }

/* ------------------------------------------------------------- the hero
   A lit stage rather than a page top: a warm key light from upper-left, a
   rose fill from the right, a vignette closing the corners, and one gold
   hairline as the letterbox rule. All gradients -- 0 bytes of imagery. */
.hero {
  padding: 64px 0 34px;
  isolation: isolate;
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  inset: -30% -20% auto -20%;
  height: 150%;
  z-index: -2;
  background:
    radial-gradient(58% 46% at 22% 8%,  color-mix(in srgb, var(--gold) 26%, transparent) 0%, transparent 68%),
    radial-gradient(52% 44% at 84% 22%, color-mix(in srgb, var(--accent) 20%, transparent) 0%, transparent 66%),
    radial-gradient(90% 70% at 50% 0%,  var(--bg-tint) 0%, transparent 72%);
  opacity: 1;
  pointer-events: none;
}
/* the vignette + the grain, one pseudo-element, so the top of the page has
   the falloff of a frame instead of the flatness of a div */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 30%, transparent 42%, color-mix(in srgb, var(--ink) 9%, transparent) 100%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/></filter><rect width='120' height='120' filter='url(%23n)' opacity='0.32'/></svg>");
  background-size: auto, 120px 120px;
  mix-blend-mode: multiply;
  opacity: .5;
}
[data-theme="dark"] .hero::after { mix-blend-mode: screen; opacity: .28; }

/* the letterbox rule under the eyebrow -- the one piece of gold that shows */
.hero .eyebrow::after {
  content: "";
  display: block;
  width: 56px;
  height: 2px;
  margin: 12px auto 0;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}

/* ------------------------------------------------------- section rhythm
   Shilpa's page alternates a plain band and a tinted band so the eye is
   handed a beat. Same move here, but the ring's border rule is kept. */
.section + .section { border-top: 1px solid var(--line); }
/* DELETED 2026-08-10: the zebra tint and the 34px gold section tick. Both were
   created here in CINEMA and then switched off again in CINEMA-7 — an override
   war inside one file, which is how the next bug ships. The heading now carries
   an act numeral instead (CINEMA-9); there is nothing left to suppress. */

/* ------------------------------------------------------- cards, on film
   The library cards pick up a warm edge and a slow lift instead of the flat
   utility box. Radius is untouched -- CLS stays 0. */
.grid > a, .card {
  border-color: var(--line);
  background: var(--surface);
  transition: transform var(--t-med) var(--ease-out),
              border-color var(--t-med) var(--ease-out),
              box-shadow var(--t-med) var(--ease-out);
}
.grid > a:hover, .card:hover {
  transform: translateY(-2px);
  border-color: var(--accent-line);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--ink) 4%, transparent),
              0 20px 40px -28px color-mix(in srgb, var(--accent) 55%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .grid > a, .card { transition: none; }
  .grid > a:hover, .card:hover { transform: none; }
}

/* the chip row reads as a marquee strip rather than a tag cloud */
.chip { border-color: var(--line-2); }
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip b { color: var(--muted); font-variant-numeric: tabular-nums lining-nums; }

/* ------------------------------------------------------------- the frame
   A hairline gold border on the drawn set piece, so the timetable reads as a
   plate in a book. The drawing itself is unchanged. */
.yp-strip { border-top: 1px solid var(--gold); padding-top: 14px; }
.yp-strip-head { border-bottom-color: var(--line); }

/* --------------------------------------------- the model slot (reserved)
   Empty by design until the AI model stills exist. `.yp-still` is a 4:5
   editorial plate with a film grade over it; the moment a still is dropped
   into the markup it inherits the whole treatment and nothing else moves.
   Aspect-ratio is declared so adding the image cannot shift layout. */
.yp-still {
  position: relative;
  /* 3:4 is NOT a style choice — it is the aspect Flow's Nano Banana 2 emits
     (896x1200). The plate was briefly 4:5, which made object-fit:cover shave
     ~35px off the top of the frame; on a standing asana that is the top of the
     head. Matching the generator means the plate never crops. */
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--sky-1), var(--surface-2));
  border: 1px solid var(--line);
}
.yp-still img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ⚠ NEVER LET A PLATE UPSCALE. The source webp is 800px wide. On asana pages
   the plate sits directly in the hero `wrap` with no column to constrain it,
   so at 1280px it was rendering 1122px wide — a 1.40x upscale of an 800px
   file, i.e. visibly soft, on the single largest element of every photographed
   page. The homepage was fine because its herogrid caps the column; that
   earlier "proportions are correct" check simply never covered this page type.

   420px keeps it crisp on 2x displays (840 device px against an 800px source)
   and is the same visual weight as the homepage plate. */
.yp-still { max-width: 420px; }
.yp-hero-plate { max-width: 420px; }
.yp-still::after {
  content: "";
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(180deg, transparent 46%, color-mix(in srgb, var(--ink) 62%, transparent) 100%),
    radial-gradient(100% 80% at 50% 20%, transparent 50%, color-mix(in srgb, var(--ink) 22%, transparent) 100%);
}
.yp-still figcaption {
  position: absolute; left: 14px; right: 14px; bottom: 12px; z-index: 1;
  font-family: var(--mono); font-size: .72rem; letter-spacing: var(--track-label);
  text-transform: uppercase; color: #fff; opacity: .92;
}


/* THE ACCENT PLUMBING. Worth stating, because the :root block above is NOT
   where this site's accent actually comes from and half an hour was lost to
   that. shell() writes the hue INLINE -- <body style="--site-accent:#A3123E">
   from the registry row in globalsite.mjs -- and data.css binds
   `body { --accent: var(--site-accent) }`. An inline custom property outranks
   every stylesheet, so re-declaring --accent at :root does nothing below the
   body. Two consequences:

     1. The LIGHT accent is changed in globalsite.mjs (the registry row), not
        here. The :root value above is only the fallback for chrome that sits
        outside <body>.
     2. The DARK accent needs a selector that outranks `body`, which is why
        the rule below is written the long way. Crimson on cinema-black is
        2.3:1 and would have failed AAA everywhere; marigold is 9.9:1. */
:root[data-theme="dark"] body[data-site="yoga"] {
  --accent: #F0A44E;
  --accent-2: #D98A34;
  --accent-3: #F0A44E;
  --accent-soft: #241A1F;
  --accent-line: #4A3427;
  --site-accent: #F0A44E;
}

/* The cinema hero costs ~30px of vertical chrome (padding + the gold rule).
   On a 375x812 phone that is real estate the fold cannot spare, so the stage
   is lit just as hard but sits tighter. Measured, not guessed. */
@media (max-width: 560px) {
  .hero { padding: 40px 0 26px; }
  .hero .eyebrow::after { margin-top: 9px; width: 44px; }
  .section .sec::before { margin-bottom: 11px; }
}

/* the AI-provenance line inside a pose plate caption. Deliberately quiet but
   never hidden — it must survive a screenshot, so it is IN the caption. */
.yp-still figcaption .yp-ai {
  display: block;
  margin-top: 3px;
  font-size: .66rem;
  letter-spacing: .08em;
  opacity: .78;
}

/* the photographed-pose marker on a card. A small filled dot, not a badge or a
   camera glyph: the list is dense and a loud marker on 209 cards would read as
   noise. It only ever appears on the minority that HAVE a photograph. */
.yp-card .yp-shot {
  display: inline-block;
  margin-left: 7px;
  font-size: .55em;
  vertical-align: middle;
  color: var(--accent);
  opacity: .85;
}
.yp-card.has-shot { border-color: var(--accent-line); }

/* ============================================================================
   CINEMA-2 — AI provenance, the follow band, and scroll-driven depth.
   Appended 2026-08-09. Additive only; the CINEMA LAYER above is untouched.

   "Epic 3D cinematic" here means DEPTH, not geometry. No WebGL, no three.js,
   no video, no webfont — the target is still a mid-range Android on a slow
   Indian connection, and the shipped grade already proved that light and grain
   from gradients read as film for 0 bytes. Depth comes from scroll-driven
   animation, which is GPU-composited and costs no JavaScript at all.
   ========================================================================== */

/* -------------------------------------------------- AI PROVENANCE, LAYER 1
   The hallmark on the plate. Amit asked for the disclosure sentence to move to
   the bottom of the page and it has (layer 2). This stays because a caption
   and a footer are not equivalent: the plate gets screenshotted, the footer
   does not travel with it. Sized and weighted like a photographer's corner
   stamp — present, legible, not shouting. */
.yp-still .yp-hallmark {
  position: absolute;
  right: 10px;
  bottom: 62px;            /* clear of the two-line figcaption band (measured 2026-08-10:
                              caption is 39px tall at bottom 12px, so 42px sat ON it) */
  z-index: 2;
  font-family: var(--mono);
  font-size: .62rem;
  letter-spacing: .16em;
  padding: 2px 6px;
  border-radius: 3px;
  color: #fff;
  background: color-mix(in srgb, #000 42%, transparent);
  backdrop-filter: blur(2px);
  pointer-events: none;
}
.yp-still figcaption .yp-by {
  display: block;
  margin-top: 3px;
  font-size: .66rem;
  letter-spacing: .08em;
  opacity: .78;
}

/* ============================================================ SCROLL DEPTH
   Everything below is progressive enhancement, gated twice: on @supports for
   scroll-driven timelines, and on prefers-reduced-motion. A browser without
   either gets the finished frame — never a half-applied transform, never a
   blank element waiting for an animation that will not arrive. That ordering
   is the whole safety property: the static state IS the design. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* Pose plates tilt up out of the page as they enter. The single most
       "3D cinematic" move available, and it costs ~12 lines. `entry 0% → 55%`
       so it has finished well before the plate is centred and being read. */
    .yp-still {
      animation: yp-plate-rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
      transform-origin: 50% 100%;
      will-change: transform, opacity;
    }
    @keyframes yp-plate-rise {
      from { opacity: 0; transform: perspective(1100px) rotateX(7deg) translateY(26px) scale(.985); }
      to   { opacity: 1; transform: perspective(1100px) rotateX(0)    translateY(0)    scale(1); }
    }

    /* Section headings lift in. Small amplitude on purpose — the design bible
       is explicit that motion must not steal attention from the content. */
    .section .sec {
      animation: yp-lift linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 40%;
    }
    @keyframes yp-lift {
      from { opacity: 0; transform: translateY(12px); }
      to   { opacity: 1; transform: translateY(0); }
    }

    /* The hero key light pans as the hero scrolls away. The TYPE never moves:
       only the light rig does, which is what makes it read as a lit stage
       rather than as a parallax gimmick. */
    .hero::before {
      animation: yp-keylight linear both;
      animation-timeline: scroll();
      animation-range: 0 620px;
    }
    @keyframes yp-keylight {
      from { transform: translate3d(0, 0, 0); }
      to   { transform: translate3d(-3.5%, 2%, 0); }
    }
  }
}

/* ============================================================================
   CINEMA-3 REMOVED 2026-08-09 (audit). It duplicated the mobile hero-alignment
   fix that now lives ring-wide in _shared/datasite.css, and duplicated it
   worse: the shared rule is scoped with :has(.answer) to the heroes that
   actually conflict, while this local copy targeted .hero unscoped and would
   have overruled the shared contract on any future hero without an answer.

   It also carried a stray closing brace left by an earlier edit. CSS error
   recovery swallowed the next rule's prelude, silently dropping the
   .yp-herogrid display:block declaration. Benign only because divs are block
   by default - a landmine rather than a visible bug, until it wasn't.
   ========================================================================== */

/* ============================================================================
   CINEMA-4 — the hero plate, the film strip, and the timetable that draws
   itself. 2026-08-09. Additive; nothing above is modified.
   ========================================================================== */

/* ------------------------------------------------------------- THE HERO GRID
   Text left, one photographed pose right, from 760px up. Below that the plate
   drops under the answer and is capped at 40vh so the fold — fought for and
   won at 375×812 — does not get eaten by an image. */
.yp-herogrid { display: block; }
.yp-hero-plate { margin: 20px 0 0; }
.yp-hero-plate a { display: block; }

@media (min-width: 760px) {
  .yp-herogrid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
    gap: 30px;
    align-items: start;
    text-align: left;          /* the hero centres above 560px; this column doesn't */
  }
  .yp-herogrid-text { text-align: left; }
  .yp-hero-plate { margin: 0; }
}

@media (max-width: 759px) {
  /* keep the hero image from pushing the search + stats off the first screen */
  .yp-hero-plate { max-width: 260px; }
}

/* --------------------------------------------------------------- FILM STRIP
   A scroll-snap contact sheet. No carousel library and no dots: a horizontal
   scroller with snap points is the native control, it is keyboard- and
   touch-accessible for free, and it costs no JavaScript.
   `overflow-x: auto` on THIS element only — the page body must never scroll
   sideways, which is the rule the whole ring is built on. */
.yp-film {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(190px, 210px);
  gap: 14px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  padding: 4px 2px 14px;
  margin: 18px 0 0;
  scrollbar-width: thin;
}
.yp-film-item {
  scroll-snap-align: center;
  text-decoration: none;
  display: block;
}
.yp-film-shot {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;         /* matches the generator; no crop, no CLS */
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: linear-gradient(160deg, var(--sky-1), var(--surface-2));
}
.yp-film-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.yp-film-shot::after {           /* the same film grade as the full plate */
  content: "";
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent 55%, color-mix(in srgb, var(--ink) 42%, transparent) 100%);
}
.yp-film-item .en {
  display: block; margin-top: 9px;
  font-family: var(--display); font-size: 1rem; color: var(--ink);
}
.yp-film-item .sa {
  display: block; margin-top: 1px;
  font-size: .8rem; color: var(--muted);
}
.yp-film-item:hover .yp-film-shot { border-color: var(--accent-line); }
.yp-film .yp-hallmark { bottom: 8px; }

/* ============================================ THE TIMETABLE DRAWS ITSELF
   The session strip is inline SVG of the site's own data, which makes it the
   one set piece a competitor cannot screenshot-copy. Giving its strokes a
   dash-offset that resolves on scroll makes the practice appear to be drawn.

   Gated on @supports AND prefers-reduced-motion, and — critically — the
   dasharray is only ever applied INSIDE that gate. A browser without
   scroll-timelines must never be left holding a half-drawn diagram: outside
   the gate the SVG renders complete, exactly as it does today. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .yp-strip .seg,
    .yp-strip .glyph path {
      stroke-dasharray: 320;
      animation: yp-draw linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 65%;
    }
    @keyframes yp-draw {
      from { stroke-dashoffset: 320; opacity: .25; }
      to   { stroke-dashoffset: 0;   opacity: 1; }
    }

    /* the film strip plates settle as the strip scrolls into view */
    .yp-film-shot {
      animation: yp-plate-rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 50%;
    }
  }
}

/* ---------------------------------------------- AI PROVENANCE, FOOTER SIZE
   Amit asked twice for this to be small and to sit down with the footer, so it
   does. The SENTENCE is unchanged — shrinking type is a layout decision,
   shrinking the claim would be a different thing — and the alt text plus the
   JSON-LD carry the same statement to crawlers at any type size. */
.yp-aifoot {
  max-width: var(--max);
  margin: 0 auto;
  padding: 14px 20px 26px;
  font-size: .72rem;
  line-height: 1.5;
  color: var(--faint, var(--muted));
  border-top: 1px solid var(--line);
}
.yp-aifoot strong { color: var(--muted); font-weight: 600; }



/* ============================================================================
   CINEMA-5 — the "feels expensive" layer. 2026-08-09.

   Taken from the $10k-website method: the thing that separates a site that
   LOOKS expensive from one that FEELS expensive is a restrained, cursor-aware
   motion pass — one interaction per flat section, subtle enough that you
   notice the room, not the effect.

   Two rules kept throughout:
     · pointer only. `@media (hover: hover) and (pointer: fine)` so a phone —
       which is most of this audience — pays nothing and gets no jitter.
     · reduced-motion off. Every block below is inside the no-preference query.
   ========================================================================== */

/* ------------------------------------------------- 1. THE HERO KEY LIGHT
   A warm light that follows the cursor across the hero and LAGS behind it.
   The lag is the whole trick: a halo pinned exactly to the pointer reads as a
   cheap flashlight gimmick, one that trails by a beat reads as candlelight in
   a room. --mx/--my are set by ten lines of JS in app.js; when that JS never
   runs the fallback centres the light and the hero looks exactly as it does
   today, which is the safe state. */
/* @property REGISTRATION is what makes the lag real. Custom properties are
   untyped by default, so the browser cannot interpolate them and every
   pointermove SNAPS the light to the cursor. The first version of this block
   tried `transition: background-position`, which does nothing here at all —
   the position is driven by --mx/--my, not by background-position — so the
   signature "candlelight that lags a beat behind the cursor" described in the
   comment did not exist in production. Registering the properties as
   <percentage> lets them animate, and the transition below is what actually
   produces the lag. Unregistered browsers simply snap, i.e. today's behaviour. */
@property --mx { syntax: "<percentage>"; inherits: false; initial-value: 50%; }
@property --my { syntax: "<percentage>"; inherits: false; initial-value: 40%; }
@property --px { syntax: "<percentage>"; inherits: false; initial-value: 50%; }
@property --py { syntax: "<percentage>"; inherits: false; initial-value: 50%; }

@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .hero {
    --mx: 50%; --my: 40%;
    transition: --mx 620ms cubic-bezier(.22,1,.36,1),
                --my 620ms cubic-bezier(.22,1,.36,1);
  }
  /* The key light is painted on ::before, NOT ::after. ::after carries
     mix-blend-mode: multiply on the light theme, and a light that multiplies
     can only ever darken what it touches — the effect was physically backwards
     from the thing its own comment claimed. ::before has no blend mode, so the
     warm pool actually lightens. */
  .hero::before {
    background:
      radial-gradient(34% 30% at var(--mx) var(--my),
        color-mix(in srgb, var(--gold) 26%, transparent) 0%, transparent 72%),
      radial-gradient(58% 46% at 22% 8%,  color-mix(in srgb, var(--gold) 26%, transparent) 0%, transparent 68%),
      radial-gradient(52% 44% at 84% 22%, color-mix(in srgb, var(--accent) 20%, transparent) 0%, transparent 66%),
      radial-gradient(90% 70% at 50% 0%,  var(--bg-tint) 0%, transparent 72%);
  }
}


/* ------------------------------------------- 2. THE HEADLINE, LINE BY LINE
   The h1 is authored as two spans (`.reveal`, `.reveal-2`), so the reveal is
   per LINE rather than per word. Word-by-word on a headline that already
   carries an em-dash clause reads as a slot machine; line-by-line reads as a
   title card, which is the register this site is in. */
@media (prefers-reduced-motion: no-preference) {
  .hero h1 .reveal { animation: yp-line 620ms cubic-bezier(.22,1,.36,1) both; }
  .hero h1 .reveal-2 { animation-delay: 110ms; }
  @keyframes yp-line {
    from { opacity: 0; transform: translateY(14px); clip-path: inset(0 0 100% 0); }
    to   { opacity: 1; transform: none;             clip-path: inset(0 0 -8% 0); }
  }
}

/* ------------------------------------------------ 3. THE PLATE, LIT BY HAND
   Pose plates get a soft specular that tracks the cursor across the image.
   It is doing the job a photographer's fill light does — telling you the thing
   is an object in a room rather than a rectangle on a page. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .yp-still { --px: 50%; --py: 50%; }
  .yp-still::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    opacity: 0;
    background: radial-gradient(30% 26% at var(--px) var(--py),
      rgba(255,255,255,.30) 0%, transparent 72%);
    transition: opacity 420ms var(--ease-out);
  }
  .yp-still:hover::before { opacity: 1; }
}

/* --------------------------------------------- 4. THE SECTION HAIRLINE DRAW
   Section rules draw themselves in from the leading edge instead of simply
   being there. Costs nothing — it is the existing 1px border, animated. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .section .sec::before {
      animation: yp-rule linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 42%;
    }
    @keyframes yp-rule { from { width: 0; opacity: 0; } to { width: 34px; opacity: .85; } }
  }
}

/* ============================================================================
   CINEMA-6 — image PROPORTION repair. 2026-08-09.

   Amit: "stretched on desktop and squashed on mobile, especially the images."
   Measured before changing anything, and the images were NOT geometrically
   distorted — 0.0% deviation from their natural 3:4 at both widths. The fault
   was scale relative to their column:

     desktop 1440 : hero text 794px beside a 300px plate — a 2.6:1 split, so
                    the photograph read as a postage stamp pinned to a very
                    wide slab of text. That is what "stretched" describes.
     mobile 375   : plate capped at 258px inside a 375px viewport, leaving
                    ~117px of dead gutter beside it. That is the "squashed".

   So the fix is proportion, not object-fit. Two moves: give the plate real
   presence next to the text on desktop, and let it use the full column on
   mobile instead of hiding in the middle of it.
   ========================================================================== */

@media (min-width: 760px) {
  .yp-herogrid {
    /* was minmax(0,1fr) / minmax(0,300px). The text column is now capped by
       measure rather than by whatever is left over, so the plate keeps its
       weight as the viewport grows instead of being squeezed thinner. */
    grid-template-columns: minmax(0, 1fr) clamp(300px, 30%, 400px);
    gap: 38px;
  }
  /* 68ch is the upper bound of comfortable reading. Beyond it the eye loses
     the line return, which is the other half of what reads as "stretched". */
  .yp-herogrid-text .yp-answer,
  .yp-herogrid-text .answer { max-width: 68ch; }
}

@media (max-width: 759px) {
  /* Full column width. A 258px image adrift in a 375px screen looks like a
     mistake; the same image edge-to-edge looks like a photograph. */
  .yp-hero-plate { max-width: none; width: 100%; }
}

/* The film strip cards were 190px wide on a 375 screen — thumbnail scale, not
   photograph scale, on the one section whose whole job is showing the poses.
   76vw gives a card that fills most of the screen with the next one peeking in
   at the edge, which is also the affordance that says "this scrolls". */
@media (max-width: 640px) {
  .yp-film { grid-auto-columns: 76vw; gap: 12px; }
}

/* ============================================================================
   CINEMA-7 — THE EDITORIAL PASS. 2026-08-09.

   Amit: "looks cheap." The audit found why, and it was not the hero: the hero
   got the cinema and the BODY never did. Below the fold every page was the
   same chassis repeated eight times — h2 + gold tick + note + a grid of 1px
   rounded boxes — which is the grammar of an admin dashboard, not a book.
   Boxes, tag pills, a 4px left accent border and a coloured hover glow are the
   most recognisable "AI template" fingerprints on the site.

   So: rule the index instead of boxing it. `.yp-care` was already the best
   component on the page precisely because it was unboxed; this extends that
   logic outward. Nothing here changes markup — it is a pure restyle, which is
   also why it is safe.
   ========================================================================== */

/* ---------------------------------------------------------- THE SCALE
   17 improvised font sizes between .66 and 1.3rem is not a scale, it is
   per-component guesswork, and the eye reads the result as "nothing here was
   decided". Seven tokens on a 1.2 minor third, and an 8px space base. */
:root {
  --sp-1: 8px;  --sp-2: 16px; --sp-3: 24px;
  --sp-4: 40px; --sp-5: 64px; --sp-6: 96px;
  --t-label: .694rem;   /* the ONE small voice */
  --t-meta:  .833rem;
  --t-body:  1rem;
  --t-lead:  1.2rem;
}

/* Rhythm comes from space, not stripes. The zebra tint made every section the
   same weight while pretending to differentiate them. */
.section { padding: var(--sp-6) 0; }
@media (max-width: 560px) { .section { padding: var(--sp-5) 0; } }

/* An accent used fourteen times a page is not an accent. Gold is kept for
   three moments only: the hero eyebrow, the strip frame, the film band.
   ⚠ The `display:none` that used to sit here was DELETED 2026-08-10 along with
   the rule it suppressed. It also out-specified (0,2,1) any later `h2.sec`
   styling of the same pseudo-element, which would have silently swallowed the
   CINEMA-9 act numeral. */

/* ------------------------------------------------------- RULE THE INDEX
   The card wall becomes a ruled list: hairline-separated rows, no boxes, no
   radius, no fill. Name in the display face, Sanskrit in italic, the meta
   pushed right in the mono voice. This is a book's index. */
.yp-list {
  display: block;
  border-top: 1px solid var(--line);
}
.yp-card {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 4px var(--sp-3);
  padding: 14px 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: none;
  box-shadow: none;
  transition: border-color var(--t-fast) var(--ease-out);
}
.yp-card .en {
  font-family: var(--display);
  font-size: var(--t-lead);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -.01em;
}
.yp-card .sa {
  grid-column: 1;
  font-style: italic;
  font-size: var(--t-meta);
  color: var(--muted);
}
.yp-card .me {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  text-align: right;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: .04em;
  color: var(--muted);
  text-transform: none;
}
/* the tag pills were pure dashboard — the meta line already says level,
   family and hold, so they were saying it twice in a louder voice */
.yp-card .yp-tags { display: none; }
.yp-card .yp-shot { color: var(--accent); font-size: .5em; }
.yp-card.has-shot { border-color: var(--line); }
.yp-card:hover {
  transform: none;
  box-shadow: none;
  border-bottom-color: var(--accent);
}
.yp-card:hover .en { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

/* the same de-boxing for the sequence grid */
.grid > a {
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: none;
  padding: 14px 0;
  box-shadow: none;
}
.grid > a:hover { transform: none; box-shadow: none; border-bottom-color: var(--accent); }

/* names + facts: hairline spec strips, not centred pink boxes */
.yp-names, .yp-facts { gap: 0; }
.yp-name, .yp-fact {
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  background: none;
  text-align: left;
  padding: 12px 0;
}
.yp-name .k, .yp-fact > span:first-child {
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 500;          /* weight is not what makes a label read as one */
  letter-spacing: .12em;
  color: var(--muted);
}

/* chips stop being a cloud of pills and become a set line */
.chip {
  border: 0;
  border-bottom: 1px solid var(--line-2);
  border-radius: 0;
  padding: 6px 0;
  margin-right: var(--sp-3);
  background: none;
}
.chip:hover { border-bottom-color: var(--accent); background: none; }

/* -------------------------------------------------------- CALM THE LIGHT
   At 1280 the hero read as a smooth pink-to-ivory wash — the Canva-gradient
   tell — because the accent radial spread 20% chroma across half the hero.
   Pull both lights up and halve the accent so ivory dominates under the h1. */
.hero::before {
  background:
    radial-gradient(52% 40% at 22% 0%,  color-mix(in srgb, var(--gold) 22%, transparent) 0%, transparent 66%),
    radial-gradient(46% 38% at 84% 6%,  color-mix(in srgb, var(--accent) 10%, transparent) 0%, transparent 62%),
    radial-gradient(90% 62% at 50% 0%,  var(--bg-tint) 0%, transparent 70%);
}

/* ------------------------------------------------- PROVENANCE, ONE LINE
   The same facts were restated four times a page, and inside the hero the
   srcline wrapped to three lines of tracked uppercase mono. Integrity is the
   brand; repetition is just clutter, and clutter reads cheap. */
.srcline, .srcline-min {
  font-size: .66rem;
  letter-spacing: .05em;
  color: var(--faint, var(--muted));
}
.hero .srcline { max-width: 62ch; }

/* film strip scrim was muddying the one thing the strip exists to show */
.yp-film-shot::after {
  background: linear-gradient(180deg, transparent 62%, color-mix(in srgb, var(--ink) 22%, transparent) 100%);
}

/* On a phone the two-column ruled row collapses: 1fr + auto forces the meta
   to fight the name for a 335px line, and both wrap — rows came out 139px
   tall, which is a card again by another name. Stack it: name, Sanskrit,
   then the meta as one quiet mono line. */
@media (max-width: 560px) {
  .yp-card {
    grid-template-columns: 1fr;
    gap: 2px;
    padding: 12px 0;
  }
  .yp-card .me {
    grid-column: 1;
    grid-row: auto;
    text-align: left;
    margin-top: 2px;
  }
}

/* ============================================================================
   CINEMA-8 — the $100k completion pass. 2026-08-10. Additive.
   Three items: the BREATH CLOCK (the signature instrument), the timetable's
   own ACT on the home page (M4), and the Devanagari TITLE-CARD lockup.
   ========================================================================== */

/* -------------------------------------------------------- THE BREATH CLOCK
   One hold on a dial, in the site's 1.6px round hand. The crimson arc draws
   itself over the SHORT end of the published hold in real seconds — the
   drawing is the data at 1:1 scale in time. Static state (reduced motion,
   old engines): the arc fully drawn. */
.yp-clock { margin: 22px auto 0; max-width: 240px; }
.yp-clock svg { display: block; width: 100%; height: auto; }
.yp-clock circle, .yp-clock line { fill: none; stroke-linecap: round; }
.yp-clock .face { stroke: var(--line-2); stroke-width: 1; }
.yp-clock .tk   { stroke: var(--line-2); stroke-width: 1; }
.yp-clock .tk.maj { stroke: var(--ink-2); stroke-width: var(--hand); }
.yp-clock .win  { stroke: var(--yp-soft); stroke-width: 9; }
.yp-clock .arc  {
  stroke: var(--yp); stroke-width: calc(var(--hand) * 2);
  stroke-dasharray: var(--f) 100;   /* always: without this the arc is a full circle */
}
.yp-clock .big {
  font-family: var(--display); font-weight: 600; font-size: 34px;
  fill: var(--ink); font-variant-numeric: lining-nums;
}
.yp-clock .sub {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em;
  fill: var(--muted);
}
.yp-clock figcaption {
  margin-top: 8px; text-align: center;
  font-family: var(--mono); font-size: .72rem; letter-spacing: .04em;
  color: var(--faint); line-height: 1.5;
}
@media (prefers-reduced-motion: no-preference) {
  .yp-clock .arc { animation: yp-sweep var(--sweep, 30s) linear .9s both; }
  @keyframes yp-sweep {
    from { stroke-dashoffset: var(--f); }  /* arc length 0 */
    to   { stroke-dashoffset: 0; }         /* arc fully swept */
  }
}

/* The asana hero: answer left, dial right from 760px, exactly the geometry
   the homepage herogrid already owns. Below 760px the dial sits under the
   answer, left-anchored like everything else on a phone (the mobile hero
   contract in _shared/datasite.css). */
.yp-herogrid.clockgrid .yp-clock { margin: 22px 0 0; }
@media (min-width: 760px) {
  .yp-herogrid.clockgrid { grid-template-columns: minmax(0, 1fr) 230px; }
  .yp-herogrid.clockgrid .yp-clock { margin: 4px 0 0; }
}
@media (max-width: 759px) {
  .yp-herogrid.clockgrid .yp-clock { max-width: 200px; }
}

/* ------------------------------------------------- THE TIMETABLE'S OWN ACT
   M4. The site's one big drawing opens the body inside a framed panel —
   nothing else on stage. The gold top rule it already wears (CINEMA-3) now
   reads as the panel's proscenium. */
.yp-act-sec { padding-top: clamp(26px, 5vw, 44px); }
.yp-act {
  border: 1px solid var(--line);
  background: var(--surface, var(--sky-2));
  border-radius: 12px;
  padding: clamp(16px, 3.4vw, 34px) clamp(14px, 3.4vw, 34px) clamp(14px, 2.6vw, 24px);
}
.yp-act .yp-strip { margin-top: 0; }
.yp-act .tnote { margin-bottom: 0; }

/* --------------------------------------------- THE DEVANAGARI TITLE CARD
   The asana h1 used to run English and Devanagari as one headline, which
   meant Fraunces carried the Latin and the engine's fallback carried the
   Devanagari — a visible font break MID-HEADLINE, the single cheapest tell
   on the page. The cure is not a webfont (this audience pays for bytes);
   it is to stop pretending they are one line. Bollywood one-sheets solved
   this decades ago: the Latin title big, the Devanagari beneath it as its
   own smaller, letter-spaced credit line. Deliberate contrast reads as
   design; accidental contrast reads as a bug. */
.hero h1 .dev {
  display: block;
  font-style: normal;
  font-size: clamp(1.05rem, .72rem + 1.3vw, 1.5rem);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: .06em;
  color: var(--yp);
  margin-top: .45em;
}

/* ------------------------------------------------- THE FOLLOW, ON THE PLATE
   2026-08-10, Amit's call: the follow links live ON the pose photographs.
   The demonstrator's own handle, bottom-left — mirror of the AI hallmark at
   bottom-right, same scrim language, so the two overlays read as one system.
   Pages that carry a plate drop the shared cast band (noCastBand in shell),
   so no page ever shows two follow surfaces. */
/* 2026-08-10: the pills became a ROW (Instagram + Facebook), so the
   positioning moved from the anchor to this wrapper. Two absolutely-positioned
   anchors would have sat on top of each other. */
.yp-still .yp-plate-follows {
  position: absolute;
  left: 10px;
  bottom: 62px;                    /* same measured baseline as .yp-hallmark */
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 6px;
  max-width: calc(100% - 58px);    /* never collides with the AI hallmark */
}
.yp-still .yp-plate-follow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 5px 5px 5px 11px;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .07em;
  color: #fff;
  text-decoration: none;
  background: color-mix(in srgb, #000 46%, transparent);
  border: 1px solid rgba(255, 255, 255, .28);
  backdrop-filter: blur(3px);
  transition: background .18s ease;
}
.yp-still .yp-plate-follow:hover,
.yp-still .yp-plate-follow:focus-visible { background: color-mix(in srgb, #000 64%, transparent); }
.yp-still .yp-plate-follow svg { width: 13px; height: 13px; flex: none; }
.yp-still .yp-plate-follow .h {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.yp-still .yp-plate-follow .f {
  flex: none;
  padding: 3px 9px;
  border-radius: 999px;
  background: #fff;
  color: #14090f;                  /* 15.8:1 on white — fine in both themes */
  font-weight: 700;
}
/* The secondary network carries the SAME pill shape and the same white "Follow"
   chip as the handle pill — Amit, 2026-08-10: the two links should read as one
   object in two networks. Only the HANDLE is dropped, and only because the
   plate is 300px wide and two full handles do not fit; the pill beside it has
   already named the account. */
/* `align-self: stretch` matches its height to the handle pill beside it. The
   handle pill is taller because it carries the white "Follow" chip; without
   this the two pills are 32px and 23px and the row reads as a mistake. */
.yp-still .yp-plate-alt { padding: 5px 5px 5px 10px; flex: none; align-self: stretch; }

/* the tiny hero plate on a phone: keep the pills inside the frame */
@media (max-width: 759px) {
  .yp-hero-plate .yp-plate-follow .h { display: none; }
  .yp-hero-plate .yp-plate-follow { gap: 0; padding-left: 8px; }
  .yp-hero-plate .yp-plate-follow svg { margin-right: 6px; }
  .yp-hero-plate .yp-plate-alt { padding: 5px 8px; }
  .yp-hero-plate .yp-plate-alt svg { margin-right: 0; }
}

/* ============================================================================
   CINEMA-9 — the studio pass. 2026-08-10. Additive.

   Amit: "the design is still basic... some parts aren't aligned properly."
   Both were true. This layer does three jobs:
     A. the alignment seams a Fable audit measured in the built HTML,
     B. the typographic hierarchy that makes the site's OWN claim true,
     C. the family mark, so the ~200 pages with no photograph are still
        designed pages rather than pages with a hole in them.

   The through-line: this site's luxury is rigor made visible — numbered acts,
   numbered cautions, one drawing hand, no fills. Everything added below is
   the site quoting its own instruments; everything deleted above was a
   leftover from when it was quoting a dashboard.
   ========================================================================== */

/* --------------------------------------------------------- A. THE SEAMS
   Each of these is one layer overriding another's geometry without restating
   the whole contract — the failure mode this stylesheet keeps producing
   because it is append-only by doctrine. */

/* CINEMA-7 turned the name and fact strips into hairline spec rows by zeroing
   the gap — but left them multi-column. At 375px the four facts formed two
   167px columns with ZERO between them, so "per side where the pose has
   sides" ended flush against "Energy, 30 min". The row gap must stay 0 (the
   hairline IS the separator); the COLUMN gap was never optional. */
.yp-names, .yp-facts { gap: 0 28px; }

/* Same disease, sequence grid. data.css builds this grid with `gap: 0` and
   makes the 18px right padding do the gutter's job; CINEMA-7 rewrote the
   padding to `14px 0` without knowing it was load-bearing, so adjacent
   columns of left-aligned text touched at 0px. */
.grid > a { padding: 14px 18px 14px 0; }

/* Flex `gap` and a trailing `margin-right` are not additive by intent: the
   chips got 24px of phantom margin at every line end and wrapped a chip early,
   so the two chip rows never reached the gutter the sections above them do. */
.chip { margin-right: 0; }
.chips { gap: 8px 24px; }

/* The AI disclosure is a direct child of <main>, not inside a .wrap, so it
   carried its own 20px gutter against .wrap's 28px — every asana page had one
   paragraph starting 8px left of everything above it, above 640px only. */
.yp-aifoot { padding: 14px 28px 26px; }
@media (max-width: 640px) { .yp-aifoot { padding: 14px 20px 26px; } }

/* Three overlays on the pose plate, two x-datums: the caption sat at 14px
   while the hallmark and the follow pill sat at 10px. On the single most
   looked-at component on the site. One inset for all three. */
.yp-still figcaption { left: 14px; right: 14px; }
.yp-still .yp-hallmark { right: 14px; }
.yp-still .yp-plate-follow { left: 14px; }

/* --------------------------------------------------- B. THE ACT NUMERALS
   Every h2 on the page wore the same full-width hairline underline from the
   shared sheet — fourteen identical stamps per asana page, which is the
   grammar of a template rather than a document. Replaced with the mark this
   site already speaks: the mono index numeral the timetable prints over every
   pose (01, 02, 03...). Sections become numbered acts of one document.

   WHY a CSS counter and not markup: build.mjs never has to know, and a shared
   component dropped into the page numbers itself correctly. The numeral is
   read aloud ("zero one") before the heading, which is true and useful.

   Contrast: --accent on --bg is 8.4:1 light, ~8.6:1 dark. */
body { counter-reset: ypact; }
h2.sec {
  border-bottom: 0;
  padding-bottom: 0;
  font-size: clamp(1.7rem, 3.4vw, 2.3rem);   /* one real step clear of the body cluster */
  font-weight: 500;                          /* Fraunces ships 400/500/600 - 500 is loaded */
  margin-bottom: var(--sp-2);
}
h2.sec::before {
  counter-increment: ypact;
  content: counter(ypact, decimal-leading-zero);
  display: block;
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: .16em;
  color: var(--accent);
  margin-bottom: 10px;
  opacity: 1;
  width: auto; height: auto; background: none;
}
/* The footer ring block and the cast band are FURNITURE, not acts of this
   page's argument — numbering them would claim the ring promo is chapter 15
   of an article about Plough Pose. */
.ring h2.sec::before,
.cast-band h2::before,
.pub h2::before { content: none; counter-increment: none; }

/* The deck under a heading was one of four voices sitting within 0.2rem of
   each other, all regular weight — so nothing led the eye into a section.
   It now speaks in the display face, italic: h2 -> deck -> body is three
   audibly different registers instead of three sizes of the same one. */
.sec-note {
  font-family: var(--display);
  font-style: italic;
  font-size: 1.08rem;
  line-height: 1.55;
  color: var(--ink-2);
  margin-bottom: var(--sp-3);
}

/* ------------------------------------------- B2. THE CAUTIONS, ACTUALLY BOLD
   The site's whole positioning is "the cautions in bold", and the homepage
   claims they are the loudest block on the page. They measured the QUIETEST:
   1.12rem, smaller than the calorie table's heading. The one section that
   defines the site was whispering while a MET table shouted.

   Fixed structurally, not with colour panic — AAA+++ 7.4 stands, there is no
   amber alert box here. The largest display heading below the h1, a 2px accent
   keel where every other section gets a hairline, and each condition numbered
   in the mono voice like a line on a posted notice. "Five named conditions"
   reads as diligence; bullets read as boilerplate.

   Trade-off: the page now has exactly one section that outranks all others.
   That is the point, and it must stay the only one. */
.yp-care {
  border-top: 2px solid var(--accent);
  padding: 26px 0 24px;
  counter-reset: ypcare;
}
.yp-care h2, .yp-care h3 {
  font-family: var(--display);
  font-size: clamp(1.9rem, 4vw, 2.7rem);
  font-weight: 500;
  letter-spacing: -.02em;
  line-height: 1.12;
  display: block;                 /* the flex+icon row made a heading look like a widget */
  margin: 0 0 18px;
}
.yp-care h2 svg, .yp-care h3 svg {
  width: 22px; height: 22px;
  display: inline-block;
  vertical-align: baseline;
  margin-right: 10px;
  transform: translateY(2px);
}
.yp-care li {
  counter-increment: ypcare;
  padding: 12px 0 12px 44px;
  font-size: 1.06rem;             /* bold by SIZE, not by weight */
  line-height: 1.55;
}
.yp-care li::before {
  content: counter(ypcare, decimal-leading-zero);
  width: auto; height: auto; background: none; border-radius: 0;
  top: 14px;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: .1em;
  color: var(--accent);
}

/* ------------------------------------------- B3. THE STEPS, IN OUR OWN HAND
   The 30px solid crimson discs were the loudest FILLED shapes on a site whose
   drawing law is "1.6px, round cap, no fill, ever" — SaaS onboarding dots
   sitting on the instructional heart of all 209 pages. Now the timetable's own
   idx voice hangs in the margin on the existing spine, with a 1.6px crimson
   tick leaving the rule at each step: exactly the leader language
   sessionStrip() already draws. One hand everywhere is what separates
   designed from assembled.

   Trade-off: numerals are quieter than discs. The spine and the tick carry
   the wayfinding instead. */
.yp-steps li {
  padding: 0 0 22px 52px;
  border-left: 1px solid var(--yp-line);
  margin-left: 0;
}
.yp-steps li::before {
  content: counter(ypstep, decimal-leading-zero);
  left: 0; top: 2px;
  width: 40px; height: auto;
  background: none;
  border-radius: 0;
  display: block;
  text-align: left;
  padding-left: 14px;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: .1em;
  font-weight: 400;
  color: var(--accent);
}
.yp-steps li::after {
  content: "";
  position: absolute; left: 0; top: 10px;
  width: 10px; height: var(--hand-px);
  background: var(--accent);
  border-radius: 1px;
}
.yp-steps li p { margin: 0; font-size: 1.02rem; line-height: 1.65; }
/* the old dark patch set these numerals to near-black ink to sit on a fill
   that no longer exists; the accent is correct in both themes now */
[data-theme="dark"] .yp-steps li::before { color: var(--accent); }

/* --------------------------------------------- B4. THE LAST THREE BOXES
   CINEMA-7 ruled the cards, names, facts and chips — then stopped. Mistakes
   stayed a rounded tinted box, muscles stayed chips with FILLED colour
   squares (a second breach of the no-fill hand), quick links stayed tinted
   pills, and the first thing on every asana page was a filled dashboard badge.
   Two design periods visible on one page is precisely what "assembled rather
   than designed" looks like. Trade-off: less visual "product", more book —
   which is the brief. */
.yp-mis { gap: 0; border-top: 1px solid var(--line); }
.yp-mis-row {
  border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0; background: none; overflow: visible;
}
.yp-mis-row p { padding: 12px 0; }
.yp-mis-row .m { border-bottom: 1px dashed var(--yp-line); }
.yp-mis-row .f { background: none; }
.yp-mis-row .m b, .yp-mis-row .f b {
  display: block; margin: 0 0 3px;
  font-size: var(--t-label); letter-spacing: .14em;
}

.yp-muscles { gap: 0; border-top: 1px solid var(--line); }
.yp-muscle {
  border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0; background: none;
  padding: 11px 0;
}
/* primary is marked by the same 1.6px crimson dash the steps and the cautions
   now carry — one alphabet, third use — not a filled square */
.yp-muscle i {
  width: 14px; height: var(--hand-px);
  border-radius: 1px;
  background: var(--line-2);
}
.yp-muscle.pri i { background: var(--accent); }
.yp-muscle small {
  font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: .08em; text-transform: uppercase;
}

.yp-quick { gap: 6px 26px; }
.yp-quick a {
  border: 0; border-bottom: 1px solid var(--line-2);
  border-radius: 0; background: none;
  padding: 4px 0;
  color: var(--ink); font-weight: 600; font-size: .9rem;
}
.yp-quick a:hover { border-bottom-color: var(--accent); color: var(--accent); }

/* The eyebrow is already an uppercase mono voice; the level joins it as text
   with a hairline separator rather than opening all 209 pages with a badge. */
.yp-lvl, .yp-lvl.intermediate, .yp-lvl.advanced {
  background: none; color: var(--accent);
  padding: 0 10px 0 0; margin-right: 6px;
  border-right: 1px solid var(--line-2);
  border-radius: 0;
  font-family: var(--mono); font-weight: 400;
  font-size: inherit; letter-spacing: inherit;
}
[data-theme="dark"] .yp-lvl { color: var(--accent); }

/* ------------------------------------------------ C. THE INDEX, LETTERED
   The site owns eight family glyphs in the protected hand and used them in
   exactly one place: inside the timetable SVG. The 209-row index — a page
   whose entire content is classification — was bare text. Every ruled row now
   opens with its family's mark, so a reader scanning the wall can see the
   inversions cluster before reading a word.

   Paid for by no longer emitting 209 hidden tag pills on the same page (CSS
   had hidden them since CINEMA-7; a hidden element on a slow Indian
   connection is not a design decision, it is freight). */
.yp-card { grid-template-columns: 34px 1fr auto; }
.yp-card .yp-fam {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: center;
  width: 24px; height: 24px;
  fill: none;
  stroke: var(--muted);
  stroke-width: var(--hand);
  stroke-linecap: round;
  stroke-linejoin: round;
}
.yp-card .en, .yp-card .sa { grid-column: 2; }
.yp-card .me { grid-column: 3; }
.yp-card:hover .yp-fam { stroke: var(--accent); }
@media (max-width: 560px) {
  .yp-card { grid-template-columns: 34px 1fr; }
  .yp-card .en, .yp-card .sa { grid-column: 2; }
  .yp-card .me { grid-column: 2; grid-row: auto; text-align: left; margin-top: 2px; }
}

/* ------------------------------------------------- C2. THE FAMILY MARK
   THE SIGNATURE MOVE, and the answer to the hard part of the brief: 200 of
   209 pages have no photograph. Where the plate would stand, the page hangs
   its family's glyph at poster scale — the same 24-unit drawing the timetable
   writes, with vector-effect pinning the stroke to the literal 1.6px at any
   size — captioned with the pose's real position in its family. It is made of
   the site's own data (the classification and the library counts), so it is a
   drawing OF something, not decoration. Neither yogainternational.com nor
   yogawithadriene.com owns a glyph alphabet; they cannot copy this without
   first inventing one.

   Reuses .yp-still wholesale: same 3:4 frame, same cap, same scroll rise.
   One plate system, two kinds of plate. Trade-off: it is austere. That is the
   register — a mark, not a mural. */
.yp-fmark { background: linear-gradient(160deg, var(--sky-1), var(--surface-2)); }
.yp-fmark::after { content: none; }        /* no photographic scrim on a drawing */
.yp-fmark svg {
  position: absolute;
  inset: 10% 14% 18%;
  width: auto; height: auto;
  overflow: visible;
}
.yp-fmark svg path {
  fill: none;
  stroke: var(--accent);
  stroke-width: var(--hand-px);            /* honoured literally via non-scaling-stroke */
  stroke-linecap: round;
  stroke-linejoin: round;
}
.yp-fmark figcaption {
  position: absolute; left: 14px; right: 14px; bottom: 12px;
  font-family: var(--mono); font-size: .72rem;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted);                     /* 5.9:1 on this field - NOT the white
                                              photographic caption, which would fail */
  opacity: 1;
  background: none;
}
/* draws itself on scroll, double-gated; the dasharray exists only inside the
   gate, so no engine is ever left holding a half-drawn figure */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .yp-fmark svg path {
      stroke-dasharray: 90;                /* user-space units; longest glyph path ~46 */
      animation: yp-fmark-draw linear both;
      animation-timeline: view();
      animation-range: entry 10% entry 70%;
    }
    @keyframes yp-fmark-draw {
      from { stroke-dashoffset: 90; }
      to   { stroke-dashoffset: 0; }
    }
  }
}

/* ----------------------------------------------------------- D. THE MARK
   The header mark is the seated glyph sitting on the strip's own ruler (see
   BRAND_MARK in _shared/globalsite.mjs for the reasoning). The ticks run
   lighter than the figure for the same reason they do on the strip: the ruler
   is the stage, the body is the actor. */
.yp-mark { display: block; }
.yp-mark .m2 { stroke-width: 1.4; opacity: .55; }

/* It draws itself ONCE on arrival, in the order a practice is actually built:
   ground, ticks, legs, spine, head. ~1.2s, then it never moves again — this is
   a reference site, not a splash screen.

   DOUBLE-GATED: stroke-dasharray exists ONLY inside this block, so with
   reduced motion, or on any engine that drops the animation, the static
   markup IS the finished mark. Nothing here can leave the logo half-drawn or
   invisible, and nothing here touches layout, so CLS stays zero. */
@media (prefers-reduced-motion: no-preference) {
  .yp-mark .m1, .yp-mark .m3, .yp-mark .m4 {
    stroke-dasharray: 1; stroke-dashoffset: 1;
    animation: ypMarkDraw .45s cubic-bezier(.22,1,.36,1) both;
  }
  .yp-mark .m1 { animation-duration: .38s; }
  .yp-mark .m3 { animation-delay: .30s; }
  .yp-mark .m4 { animation-delay: .62s; animation-duration: .4s; }
  .yp-mark .m2 { animation: ypMarkIn .35s ease-out .22s both; }
  .yp-mark .m5 { animation: ypMarkIn .30s ease-out .92s both; }

  /* the only hover: one quiet inhale. transform, so the header never reflows */
  .yp-mark .m5 { transition: transform .35s cubic-bezier(.22,1,.36,1); }
  .brand:hover .yp-mark .m5,
  .brand:focus-visible .yp-mark .m5 { transform: translateY(-1.5px); }
}
@keyframes ypMarkDraw { to { stroke-dashoffset: 0; } }
@keyframes ypMarkIn   { from { opacity: 0; } }

/* "Yoga" is the subject and "Path" is the claim, so they are not set alike —
   the same division of labour the mark makes, where the ruler is quiet and the
   crimson dot is the point. */
.brand > span {
  font-family: var(--display);
  font-size: 1.09rem;
  font-weight: 620;
  letter-spacing: .004em;
  font-variation-settings: "opsz" 32;
  color: var(--ink);
}
.brand .bp { font-weight: 400; color: var(--accent); font-style: normal; }

/* ------------------------------------------------- CINEMA-9 E. PLATE SHARPNESS
   Amit, 2026-08-10: "the images of the poses ... look blurred." Measured, and
   he was right twice over. The generator hands us 896x1200; the build was
   resampling that DOWN to 800 and encoding at quality 72, then the CSS let the
   plate display at 420px — which is 840 device pixels on a 2x phone and 1260
   on a 3x one, against an 800px source that had already been softened by a
   pointless 0.89 resample.

   Fixed at both ends. The webp is now encoded from the native 896x1200 with NO
   resample at all and quality 86 (see the recipe in the ring-faces skill);
   ~48-96KB each, against 33KB before — a fair trade for the one image on the
   page. And the plate caps at 380px, so 896/380 = 2.36x density: sharp on
   every 2x screen and honest on a 3x one. Declared width/height in build.mjs
   move to 896x1200 with it, so the aspect box still matches the file exactly
   and CLS stays zero. */
.yp-still { max-width: 380px; }
.yp-hero-plate { max-width: 380px; }

/* ----------------------------------------- CINEMA-9 F. THE TWO-COLUMN HERO
   Measured at 1280 on an asana page: eyebrow x=71, h1 x=293, lede x=287,
   answer x=71, source line x=71 — the centred-masthead-vs-left-answer clash
   again, this time on DESKTOP, where the ring-wide repair deliberately stops.

   It stops there for a good reason: at 1280 a centred masthead has air either
   side and reads as a title page. That reasoning holds for a hero that is one
   centred column — and fails completely for THIS hero, which is a two-column
   grid with the answer hard against the left rail and the breath clock or the
   pose plate in the right-hand column. A centred headline over a left-aligned
   grid is not a masthead, it is a mistake.

   So the scope is `:has(.yp-herogrid)`, not `:has(.answer)`: only the heroes
   that are actually built as a grid, at every width. Any future single-column
   hero on this site keeps the shared centred treatment untouched. */
.hero:has(.yp-herogrid),
.hero:has(.yp-herogrid) .wrap,
.hero:has(.yp-herogrid) .eyebrow,
.hero:has(.yp-herogrid) h1,
.hero:has(.yp-herogrid) .lede { text-align: left; }
.hero:has(.yp-herogrid) h1,
.hero:has(.yp-herogrid) .eyebrow,
.hero:has(.yp-herogrid) .lede { margin-left: 0; margin-right: auto; }
.hero:has(.yp-herogrid) .eyebrow::after { margin-left: 0; margin-right: auto; }

/* ============================================================================
   CINEMA-10 — 2026-08-10. Amit: images smaller, the social link on them, the
   AI disclosure as tiny type at the foot only, and a bookmark.
   ========================================================================== */

/* ------------------------------------------------------- SMALLER PLATES
   The photographs were carrying too much of the page. At 380px the plate was
   still the biggest thing on an asana page after the headline, and this is a
   reference site whose product is the text. 300px keeps the pose legible —
   a full figure at 300x400 is larger than a passport photo — while returning
   the page to the copy. It also raises the effective resolution again: the
   file is 896px wide, so 300 CSS px is a 2.99x density. Nothing on any screen
   can now render it soft. */
.yp-still { max-width: 300px; }
.yp-hero-plate { max-width: 300px; }
@media (max-width: 759px) { .yp-hero-plate { max-width: 240px; } }

/* The corner AI badge is gone from the markup (build.mjs) — the disclosure is
   tiny type at the foot of the page and nowhere else, which is what Amit asked
   for twice. This rule stays only so an older cached page does not show an
   unstyled floating "AI". */
.yp-still .yp-hallmark { display: none; }

/* The follow pill was pinned clear of a two-line caption. With the badge gone
   and the plate smaller it can sit tighter, and it drops its handle text below
   the widest phone so it never crowds a 240px frame. */
.yp-still .yp-plate-follow { bottom: 56px; font-size: .6rem; padding: 4px 4px 4px 9px; }
.yp-still .yp-plate-follow .f { padding: 3px 8px; }
@media (max-width: 560px) {
  .yp-still .yp-plate-follow .h { display: none; }
  .yp-still .yp-plate-follow { gap: 0; padding-left: 7px; }
  .yp-still .yp-plate-follow svg { margin-right: 5px; }
}

/* The film strip gets the same treatment: smaller cards, and each one carries
   its demonstrator's handle so the social link is on EVERY photograph rather
   than only the two large ones. */
.yp-film { grid-auto-columns: minmax(150px, 168px); }
@media (max-width: 560px) { .yp-film { grid-auto-columns: 62vw; } }

/* ------------------------------------------------------------ THE BOOKMARK
   A reader who finds four poses that work for their back can now keep them.
   Styled as one more ruled control in the site's own voice — not a filled
   "primary action" button, because saving a pose is not the point of the page
   and should not out-shout the pose. Filled only in the SAVED state, where the
   fill is doing real work: it is the difference the reader is looking for.

   The button is written by JavaScript into an empty host, so a reader without
   it sees nothing rather than a dead control. */
.yp-saverow { margin: 18px 0 0; }
.yp-save {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 9px 16px 9px 13px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: none;
  color: var(--ink);
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .18s var(--ease-out), color .18s var(--ease-out);
}
.yp-save svg { width: 15px; height: 15px; }
.yp-save:hover { border-color: var(--accent); color: var(--accent); }
.yp-save.on {
  border-color: var(--accent);
  background: var(--accent);
  color: #fff;                     /* 8.4:1 on the crimson; on marigold the rule below flips it */
}
[data-theme="dark"] .yp-save.on { color: #1a1024; }   /* 9.9:1 on marigold */

/* the remove control inside the saved list — a link, not a button-looking box */
.yp-drop {
  border: 0; background: none; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: .06em;
  color: var(--muted); text-transform: uppercase;
  border-bottom: 1px solid var(--line-2);
}
.yp-drop:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* the count on the quick-links row, only ever shown when there IS a count */
.yp-quick a[data-practice-link] b {
  font-family: var(--mono); font-size: .72rem; color: var(--accent);
  margin-left: 5px; font-weight: 400;
}

/* the contact-sheet mark: the Instagram glyph on each photograph. Not a link
   of its own — the whole card is already a link to the pose page, and nesting
   an anchor inside an anchor is invalid HTML that browsers silently unpick.
   It is a SIGN that the pose page carries the handle, which it does. */
.yp-film-ig {
  position: absolute; right: 8px; bottom: 8px;
  display: grid; place-items: center;
  width: 24px; height: 24px;
  border-radius: 999px;
  color: #fff;
  background: color-mix(in srgb, #000 48%, transparent);
  backdrop-filter: blur(2px);
}
.yp-film-ig svg { width: 13px; height: 13px; }

/* ============================================================================
   CINEMA-11 — 2026-08-10. The premium pass, measured rather than restyled.

   Brief: "Apple and Sony level ... use the assets and structures, but improve
   the UI & UX." So nothing here re-art-directs the site. The palette, the
   Fraunces/Inter pairing, the glyph alphabet, the breath dial and the drawn
   timetable are kept exactly as they are — they are the good part. What this
   layer does is fix what MEASUREMENT found underneath them, which turned out
   to be five things, none of them a matter of taste.
   ========================================================================== */

/* -------------------------------------------------- 1. THE COOL-GREY LEAK
   The single most expensive line on the site, and it was inherited rather than
   chosen. `--faint` is declared in the ring-wide datasite.css as #7E868D — a
   BLUE-grey, correct on the ring's neutral-paper sites and wrong twice here:

     - chromatically. Every other value on this page is warm (ivory #FAF5EF,
       aubergine ink, mauve --muted, crimson accent). A cool grey dropped into
       a warm cloth is the most recognisable "template" tell there is, and it
       was running on 19 elements per page — every source line, every dot
       separator, every timetable numeral.
     - legally. #7E868D measures 3.41:1 on this ivory. That is a WCAG AA
       failure on the site's own provenance lines — the type whose entire job
       is to be read and checked.

   Overridden site-locally, NOT in the shared sheet: the other ~50 ring sites
   are on neutral paper where the blue-grey is right, so this is a yoga
   problem rather than a ring problem. The replacement is a lighter sibling of
   --muted in the same mauve family: 4.79:1 on the page, 5.11:1 on a card. */
:root { --faint: #7E6675; }
[data-theme="dark"], :root[data-theme="dark"] { --faint: #9C8D96; }

/* -------------------------------------------------------- 2. THE FIRST CARD
   Measured at 1280x720: the hero stood 978px, so a laptop reader saw the
   headline and nothing else — not the answer, not the photograph, not the
   search. A hero that does not resolve inside one screen is the difference
   between a title page and a wall of scrolling.

   The 73px the search box spent on its own row went back to the grid (build.mjs
   moved it into the left column, which was carrying 94px of dead rail beside a
   400px plate). The rest comes from the masthead itself: its vertical rhythm
   was authored in fixed pixels for a tall desktop and never adapted, so it is
   now tied to the viewport. On a short screen the masthead compresses and the
   answer and plate make the fold; on a tall one it opens back out to exactly
   the spacing it has today. Nothing is removed and nothing is resized. */
.hero { padding-top: clamp(28px, 5.2vh, 64px); padding-bottom: clamp(24px, 3.4vh, 34px); }
.hero h1 { margin-bottom: clamp(8px, 1.4vh, 14px); }
.hero .lede { margin-top: clamp(8px, 1.6vh, 16px); }
.hero .eyebrow { margin-bottom: clamp(4px, 1vh, 8px); }

/* the search, now a column citizen: it sits under the answer on the same rail,
   so it aligns to the answer's left edge instead of running full-bleed */
.yp-herogrid-text .search { margin: 22px 0 0; max-width: 34rem; }
@media (max-width: 759px) {
  .yp-herogrid-text .search { margin-top: 18px; max-width: none; }
}

/* The stat row was three stacked blocks, 112px tall, restating numbers the
   eyebrow already says ("209 asanas · 16 practices"). Demoted to what it
   actually is: a ruled credit line under the masthead — same three facts, a
   third of the height, and it now reads as the foot of a title page rather
   than a dashboard. */
.stats.yp-stats-rule {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 0 26px; margin-top: clamp(16px, 2.4vh, 26px);
  border-top: 1px solid var(--line); padding-top: 14px;
  text-align: left;
}
.stats.yp-stats-rule .stat {
  display: block; border: 0; background: none; padding: 0;
  border-radius: 0; text-align: left;
}
.stats.yp-stats-rule .stat .k {
  display: block; font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: .08em; text-transform: uppercase; color: var(--faint);
}
.stats.yp-stats-rule .stat .v {
  display: inline-block; font-family: var(--display); font-weight: 500;
  font-size: 1.55rem; line-height: 1.15; color: var(--ink);
  margin: 2px 8px 0 0; font-variant-numeric: tabular-nums;
}
.stats.yp-stats-rule .stat .s { display: inline; font-size: .8rem; color: var(--muted); }
/* On a phone the three-up becomes three ruled rows — but stacked as authored
   above they measured 72px each, 216px of masthead spent on three numbers.
   They take the shape the site already owns for exactly this job: the hairline
   spec strip (.yp-name / .yp-fact), label left, figure right, one rule under.
   Same three facts, 44px a row — which is also the touch floor, so the rhythm
   and the target size land on the same number rather than fighting. */
@media (max-width: 560px) {
  .stats.yp-stats-rule { grid-template-columns: 1fr; gap: 0; padding-top: 4px; }
  .stats.yp-stats-rule .stat {
    display: grid; grid-template-columns: 1fr auto; align-items: baseline;
    column-gap: 14px; border-bottom: 1px solid var(--line);
    min-height: 44px; padding: 11px 0 9px;
  }
  .stats.yp-stats-rule .stat:last-child { border-bottom: 0; }
  .stats.yp-stats-rule .stat .k { grid-column: 1; margin: 0; }
  .stats.yp-stats-rule .stat .v { grid-column: 2; grid-row: 1; font-size: 1.25rem; margin: 0; }
  /* the gloss drops below the label rather than pushing the row taller */
  .stats.yp-stats-rule .stat .s {
    grid-column: 1 / -1; display: block; font-size: .76rem; margin-top: 1px;
  }
}

/* the follow pill sits ON the photograph, so it cannot grow vertically without
   covering the pose; it gets its target on the horizontal axis instead */
@media (pointer: coarse) {
  .yp-still .yp-plate-follow { min-height: 38px; padding-top: 6px; padding-bottom: 6px; }
}

/* ------------------------------------------------------- 3. THE TOUCH FLOOR
   62 controls measured under 44px tall — the quick links, the chip row, the
   family filters, the whole footer ring. 44px is not a preference; it is the
   target size Apple's HIG and the WCAG 2.2 target-size rule independently
   settle on, and this site's audience is overwhelmingly on a phone.

   Bought with real height on the controls themselves, not with an invisible
   overlay: two ruled rows sitting 10px apart cannot both claim a 44px
   overlay, and a hit area reaching past its own row is a worse bug than the
   one it fixes. Height is honest — it makes the row genuinely that tall.

   ⚠ GATED ON `pointer: coarse`, which is the whole point and the part that is
   easy to get wrong. 44px is a FINGER measurement. Applying it to a mouse
   pointer does not help anyone and does real damage here — the header, the
   netbar and the language picker are dense chrome whose compactness is a
   deliberate part of the desktop composition, and inflating a 31px netbar to
   44px would push the masthead down and undo the fold this same pass just
   won. So the desktop keeps its drawing, and the phone — which is most of
   this audience — gets targets it can actually hit.

   Centred with flex rather than padded, so the extra height is split evenly
   above and below the text and no baseline moves off the grid CINEMA-7 set. */
.yp-quick { row-gap: 8px; }
.yp-quick a { padding-top: 8px; padding-bottom: 8px; }
.yp-card { min-height: 56px; }

@media (pointer: coarse) {
  .chip,
  .yp-quick a,
  .yp-filter button,
  .netbar-links a,
  .head-nav a,
  .foot-links a,
  .lang-opt,
  .pub-soc,
  .brand,
  .yp-save,
  .yp-drop,
  .icon-btn {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* icon-only controls need the other axis too — a 44x24 target is still a miss */
  .pub-soc, .icon-btn { min-width: 44px; justify-content: center; }
  /* the header search pair are form controls, where min-height is enough */
  .hsearch input, .hsearch select.pscope { min-height: 44px; }
  /* .chips is a set line; with taller chips it needs its own row rhythm back */
  .chips { row-gap: 6px; }
}

/* ---------------------------------------------------------- 4. ONE MOTION
   Six easings and eight durations had accumulated across ten passes. The
   reason Apple's motion reads as one hand is that every transition on a page
   shares a curve and differs only in distance. Consolidated to one pair: a
   standard curve for anything under a reader's finger, and the existing
   --ease-out left alone for scroll entrances. Both values are the site's own,
   taken from whichever was already most common. */
:root { --dur: .22s; --ease-ui: cubic-bezier(.22, 1, .36, 1); }
.yp-card, .grid > a, .card, .chip, .yp-quick a, .yp-filter button,
.yp-save, .yp-drop, .yp-film-item, .yp-muscle {
  transition: color var(--dur) var(--ease-ui),
              border-color var(--dur) var(--ease-ui),
              background-color var(--dur) var(--ease-ui),
              transform var(--dur) var(--ease-ui);
}
@media (prefers-reduced-motion: reduce) {
  .yp-card, .grid > a, .card, .chip, .yp-quick a, .yp-filter button,
  .yp-save, .yp-drop, .yp-film-item, .yp-muscle { transition: none; }
}

/* ------------------------------------------------- 5. THE SEDIMENT, SETTLED
   `.yp-still` had max-width declared three times in this file with three
   different values (380px at CINEMA-9, 300px at CINEMA-10, over an earlier
   rule). The last one wins, so the site has been correct — but a stylesheet
   whose truth is "whichever line is lowest" is how the next change breaks
   something silently. The live value is stated once, here, as the one that is
   meant. Identical to what CINEMA-10 shipped, so nothing moves. */
.yp-still, .yp-hero-plate { max-width: 300px; }
@media (max-width: 759px) { .yp-hero-plate { max-width: none; width: 100%; } }

/* ============================================================================
   THE PEAKFORM BRIDGE — 2026-08-10.

   This block replaces the house ad on all 2,550 pages. It must therefore look
   like the OPPOSITE of one, because it is: PeakForm publishes ten
   /strength/<region> pages built on this site's own concern taxonomy, and this
   is a genuine next step in the reader's question, not a placement.

   So it borrows the grammar the site already uses for its most trusted
   surface — the cautions block: no card, no fill, no shadow, no rounded box.
   One accent rule down the left, the site's mono label voice, body copy in the
   reading face, and a drawn underline on the link exactly like every other
   in-content link (§3.6). The only accent is the rule and the link, which is
   the site's own rationing rule for crimson.

   Deliberately NOT reusing .pf-cinema: that class carries the dark cinematic
   scene, the countdown and the "Advertisement" label, all of which would be
   lying here. */
.yp-bridge {
  margin: 0;
  padding: 2px 0 2px 20px;
  border-left: 2px solid var(--accent);
  max-width: 62ch;
  /* two columns so the region mark can sit top-right, echoing the poster-scale
     mark PeakForm hangs beside its headline for the very same region */
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 18px;
  align-items: start;
}
.yp-bridge > :not(.yp-bridge-m) { grid-column: 1; }

/* THE SHARED MARK. Same 24-unit grid, same 1.6px round-cap hand as the pose
   family glyphs — and the same drawing PeakForm shows at the top of the page
   this links to. Seeing it on both sides of the click is the family
   resemblance; it is doing the job a shared colour cannot do here. */
.yp-bridge-m {
  grid-column: 2;
  grid-row: 1 / span 4;
  width: 44px; height: 44px;
  color: var(--accent);
  opacity: .5;
}
@media (max-width: 560px) { .yp-bridge-m { width: 32px; height: 32px; } }

.yp-bridge-k {
  margin: 0 0 8px;
  font-family: var(--mono);
  /* ⚠ THESE THREE NUMBERS ARE SHARED WITH PEAKFORM and must move together —
     11px / .22em / 600 is the <Label> component in PeakForm's
     app/strength/family.tsx. The mono label voice is the quietest family tell
     on either site and the easiest one to let drift; both sides were nudged to
     meet here (yoga was .12em, peak was .24em/700). */
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--accent);
}
.yp-bridge-b {
  margin: 0;
  color: var(--ink-2);
  line-height: 1.6;
}
.yp-bridge-b strong { color: var(--ink); font-weight: 650; }
.yp-bridge-a {
  display: inline-block;
  margin-top: 12px;
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--accent-line);
  padding-bottom: 2px;
  transition: color var(--dur) var(--ease-ui), border-color var(--dur) var(--ease-ui);
}
.yp-bridge-a:hover,
.yp-bridge-a:focus-visible { color: var(--accent); border-bottom-color: var(--accent); }
.yp-bridge-n {
  margin: 8px 0 0;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
}
@media (pointer: coarse) {
  /* the one control in the block clears the touch floor like everything else */
  .yp-bridge-a { min-height: 44px; display: inline-flex; align-items: center; }
}
