/* =============================================================================
 * INVICTUS Knowledge Center — the two-axis presentation system
 * -----------------------------------------------------------------------------
 * TWO INDEPENDENT AXES, both attributes on <html>, both also usable on any
 * element so a picker can render a live preview:
 *
 *     <html data-presentation="focused" data-accent="purple">
 *
 *   REGISTER  `data-presentation`  vivid | focused | clear
 *             Typography, density, radius, border weight, shadow, motion, copy
 *             voice — and WHICH STOP of the accent ramp it reads.
 *   ACCENT    `data-accent`        gold | purple | green
 *             The accent ramp itself, the accent ink, the tints, the tint edge,
 *             the semantic trio, and the two hue-carrying grounds.
 *
 * Nine combinations. A member picks one of each, and the two never constrain
 * one another: legibility is not a property of liking green. `clear` is AAA in
 * all three accents; `vivid` and `focused` are AA in all three.
 *
 * THE COMPOSITION MECHANISM, WHICH IS THE WHOLE DESIGN
 *   The two blocks NEVER declare the same custom property. The ACCENT block
 *   declares the RAW value (`--acc-500: #cb9f41`); the REGISTER block declares
 *   the CONSUMER token (`--blue-600: var(--acc-500)`). Disjoint property sets,
 *   so !important on both is safe and specificity never has to be reasoned
 *   about across the seam.
 *
 *   var() inside a custom property is substituted at computed-value time ON THE
 *   ELEMENT THAT DECLARES IT, and the RESULT is what inherits. So
 *   `<div data-presentation="vivid" data-accent="green">` resolves --blue-600
 *   to green's --acc-400 — because the bare `[data-presentation="vivid"]`
 *   selector re-declares --blue-600 on that very element, where --acc-400 is
 *   green's.
 *
 *   THE CONSEQUENCE, AND IT IS THE ONE THING A PICKER CAN GET WRONG: an element
 *   that carries ONLY `data-accent` INHERITS the page's already-substituted
 *   --blue-600 and shows the page's hue, not its own. Every preview must
 *   therefore carry BOTH attributes — its own value on the axis it is
 *   previewing and the page's current value on the other — which is exactly
 *   what the pickers in center.html, m.html and quiz.html do. A preview that
 *   names one axis is a preview that lies about the other.
 *
 * TWO HAZARDS, BOTH LOAD-BEARING
 *   H1  Section A defines the COMPLETE --acc-* set on bare `:root`,
 *       unconditionally. If any --acc-* were undefined, every
 *       `--blue-600: var(--acc-N)` would compute to the guaranteed-invalid
 *       value and every consumer would fall back to unset.
 *   H2  Every block is written TWICE — `:root[data-x="v"]` AND the bare
 *       `[data-x="v"]`. The second is a PREVIEW: the settings picker and the
 *       onboarding step render a live sample of one axis value inside a page
 *       currently showing another, and custom properties inherit. A declaration
 *       ON an element always beats an inherited value, whatever the specificity
 *       of the rule that produced the inherited one, so the bare selector is
 *       all that is needed — and without it the picker is a liar.
 *
 * CONTRAST IS COMPUTED, NEVER ASSERTED. `node tools/contrast_audit.mjs` parses
 * the shipping cascade and applies the WCAG 2.1 sRGB relative-luminance formula
 * against the surface each audited ink actually sits on. Its 44 used pairings
 * x 9 register/accent combinations = 396 cells: worst enforced AA body cell
 * 4.55:1 (vivid x gold/purple, --text-3 on --au-content-plate); worst clear AAA
 * body cell 7.58:1 (clear x purple, --au-critical on --au-critical-tint).
 *
 * The AAA figure used to read 7.60 (clear x green, accent text on the accent
 * tint). That cell is still 7.60 and still passes; it simply was not the worst
 * one. The semantic-on-its-own-tint pairings were outside the set the number
 * was quoted over, and --rose-500 on --rose-100 sits two hundredths below it.
 * Both clear 7:1. Quoting the worst cell of a SMALLER set as the worst cell is
 * how a computed number turns back into an asserted one.
 *
 * THREE CONSTRAINTS THE VALUES WERE SOLVED AGAINST — a future edit may not
 * break these without re-deriving the whole matrix:
 *   B1  every --acc-300 >= Y 0.4177, which is 7:1 on clear's --surface-2. That
 *       is what makes clear AAA in all three hues.
 *   B2  every --acc-tint <= Y 0.0210. Above that, focused's --text-3 drops
 *       under 4.5 on an accent chip — the exact failure the old --blue-100
 *       #2c2545 shipped at 4.28.
 *   B3  no register's --surface-2 may exceed Y 0.0260. vivid's 0.02518 is the
 *       ceiling; above it --acc-400 stops clearing 5:1 for vivid.
 *
 * INK ON A FILL IS NEVER WHITE, IN ANY ACCENT, IN ANY REGISTER. An accent
 * bright enough to read as text on near-black can never carry white: white on
 * the lightest fill in the system is 1.5-2.5:1. That is why filled controls get
 * --acc-ink, and it is section 3's main job.
 *
 * COLOUR IS NEVER THE ONLY DIFFERENCE BETWEEN TWO STATES. All nine semantic
 * values sit at Y 0.479-0.486, which is what makes them read as one family and
 * which also means a viewer with a colour-vision difference sees three
 * near-identical values (~1.2:1 apart under a deuteranopia simulation — and the
 * palette this replaced was no better). So every status chip carries its word
 * and every category tile carries its icon and label. Both apps already satisfy
 * this; do not add a surface that breaks it.
 *
 * Declarations use !important because the apps set the originals inline and
 * inside their own @media (prefers-color-scheme) block, at equal specificity,
 * from a <style> that loads AFTER this <link>.
 *
 * DARK ONLY, AND IT SAYS SO PROPERLY. This palette has one scheme. It used to
 * re-assert itself inside `@media (prefers-color-scheme: light)`, which is a
 * page fighting the OS with !important. That block is gone; each register
 * declares `color-scheme: dark` instead, which is the standards-conformant way
 * to say "this page supports one scheme" and which also makes form controls and
 * scrollbars render correctly. A real light mode is a separate piece of work:
 * eighteen cells rather than nine, plus every literal override below.
 *
 * SECTION G now says exactly what that work is: which of these values would
 * have to change, which must NOT, and which follow for free — as a manifest a
 * test parses, so it cannot rot. It also opens ONE measured combination behind
 * a `data-scheme` attribute that no code sets. `color-scheme: dark` above is
 * still correct for every member today, and section G re-declares it per
 * combination rather than removing it.
 * ========================================================================== */

/* =============================================================================
 * SECTION A — ACCENT: the default ramp, and `purple`
 * -----------------------------------------------------------------------------
 * Six stops per accent, monotone in luminance, each with exactly one job.
 * Higher number = darker, matching the --blue-600/--blue-500 convention the
 * apps already use, where the hover is the lighter, lower-numbered one.
 *
 *   --acc-200  Y 0.600   clear: hover, text and fill
 *   --acc-300  Y 0.485   clear: accent text, links, icons, AND the fill
 *                        vivid: hover
 *   --acc-400  Y 0.424   vivid: accent text.  focused: hover.  both: the ring
 *   --acc-500  Y 0.381   focused: accent text, links, icons
 *   --acc-600  Y 0.305   vivid + focused: fill hover / pressed
 *   --acc-700  Y 0.245   vivid + focused: the filled control
 *
 * The fill is separated from the accent-as-text value in every hue, not just in
 * gold: a bright accent is a headlight as a slab whatever its hue. clear fills
 * at --acc-300 instead, because clear needs 7:1 for the label ink on the fill.
 *
 * THE SEMANTIC TRIO ROTATES PER ACCENT, and it has to. Every semantic is >=58
 * degrees from the accent and >=50 from the other two semantics. Where that was
 * impossible at the incumbent assignment the SEMANTIC moved, never the accent:
 * under gold the "note" slot leaves amber (3 degrees from the accent), under
 * green the "good" slot leaves teal. The alternative — one fixed trio — puts a
 * meaning within a few degrees of the brand accent in two of three accents,
 * which is worse than a chip changing hue when a member changes accent.
 *
 * This block is written on BARE `:root` as well, unconditionally: it is the
 * default ramp, the pre-boot ramp, and hazard H1's guarantee that no --acc-* is
 * ever missing.
 * ========================================================================== */

:root,
:root[data-accent="purple"],
[data-accent="purple"] {
  /* hue 264 — the Invictus violet the product has always been */
  --acc-200:        #dac1ff !important;   /* Y 0.6027 */
  --acc-300:        #cbaafe !important;   /* Y 0.4860 */
  --acc-400:        #c39cfc !important;   /* Y 0.4241 */
  --acc-500:        #bc91fb !important;   /* Y 0.3791 */
  --acc-600:        #af7df8 !important;   /* Y 0.3056 */
  --acc-700:        #a06cef !important;   /* Y 0.2443 */

  --acc-ink:        #120c20 !important;   /* ink on any accent fill: 5.36-9.75 */
  --acc-tint:       #2f1d48 !important;   /* Y 0.0195 — --blue-100 / --violet-100 */
  --acc-tint-2:     #231539 !important;   /* Y 0.0119 — --blue-050 */
  --acc-line:       #8c66c6 !important;   /* tint-panel edge: >=3.18 everywhere */
  --acc-ground:     #191026 !important;   /* --bg-warm */
  --acc-hero:       linear-gradient(150deg, #1f1333, #311c51) !important;
  --acc-wash:       rgba(167, 139, 250, .15) !important;  /* lesson diagram wash */

  --sem-good:       #30ceb9 !important;   /* hue 172 */
  --sem-good-tint:  #162a27 !important;
  --sem-note:       #f0ac10 !important;   /* hue  42 */
  --sem-note-tint:  #2e2510 !important;
  --sem-alert:      #fa9eb1 !important;   /* hue 348 */
  --sem-alert-tint: #451720 !important;
}

/* =============================================================================
 * SECTION B — ACCENT: `gold`
 * -----------------------------------------------------------------------------
 * Saturation is held ~35% below caution amber at the same hue: #cb9f41 is
 * hsl(41,57%,52%) against the incumbent warning #f59e0b at hsl(38,92%,50%).
 * Brass under a light, not tape across a door.
 *
 * WHAT GOLD MUST NEVER MEAN. Never a warning, caution or expiry — the amber
 * this product already uses for "heads up" is 8 degrees away, which is why
 * gold's note slot moves to hue 262. Never a tier, rank, score or quality
 * grade: gold means first place everywhere else on the internet, and this
 * product has no leaderboards. Never a premium/paid/upgrade marker — if gold
 * marks both the primary action and the paid tier, every primary action looks
 * like an upsell, and kc-checkout.css is in the same component tree. Never a
 * shimmer, sheen or metallic simulation: a flat fill with dark ink is what
 * reads as expensive; the gradient is what reads as the imitation of it.
 * ========================================================================== */

:root[data-accent="gold"],
[data-accent="gold"] {
  /* hue 41 */
  --acc-200:        #e9c780 !important;   /* Y 0.5973 */
  --acc-300:        #dcb45d !important;   /* Y 0.4865 */
  --acc-400:        #d3a84e !important;   /* Y 0.4240 */
  --acc-500:        #cb9f41 !important;   /* Y 0.3787 */
  --acc-600:        #b98f36 !important;   /* Y 0.3023 */
  --acc-700:        #a78333 !important;   /* Y 0.2469 */

  --acc-ink:        #17120a !important;   /* warm-black, not the cool violet ink */
  --acc-tint:       #2d2515 !important;   /* Y 0.0194 */
  --acc-tint-2:     #211c10 !important;   /* Y 0.0119 */
  --acc-line:       #907538 !important;
  --acc-ground:     #18150c !important;
  --acc-hero:       linear-gradient(150deg, #1e180d, #2f2714) !important;
  --acc-wash:       rgba(211, 168, 78, .15) !important;

  --sem-good:       #30ceb9 !important;   /* hue 172 */
  --sem-good-tint:  #162a27 !important;
  /* The note slot CANNOT stay amber under a gold accent: it would be three
     degrees from the brand colour while meaning something different. */
  --sem-note:       #c6acf2 !important;   /* hue 262 */
  --sem-note-tint:  #2c203f !important;
  --sem-alert:      #f59fbf !important;   /* hue 338 — 63 deg clear of the accent */
  --sem-alert-tint: #3b1c27 !important;
}

/* =============================================================================
 * SECTION C — ACCENT: `green`
 * -----------------------------------------------------------------------------
 * Eucalyptus: low chroma, deliberately NOT success-green.
 *
 * WHAT GREEN MUST NEVER MEAN, and this is the largest risk in the palette.
 * Never success, pass, complete, "healthy" or "in range". Under a green accent
 * every link, tab, filled button and focus ring is green — so if green ALSO
 * means "good", a member cannot tell a navigation affordance from a verdict.
 * Never a biomarker green zone or a traffic-light result: same failure, higher
 * stakes, and a green all-clear is a claim this product has not earned. Never
 * eco/natural/organic signalling, which is one step from the supplement
 * language the claims scanner exists to block.
 *
 * That is also why the "good" slot leaves teal here: every link and every
 * "Good" chip would otherwise be one hue.
 * ========================================================================== */

:root[data-accent="green"],
[data-accent="green"] {
  /* hue 154 */
  --acc-200:        #94dabc !important;   /* Y 0.6007 */
  --acc-300:        #7ac8a6 !important;   /* Y 0.4820 */
  --acc-400:        #5ec096 !important;   /* Y 0.4228 */
  --acc-500:        #52b88c !important;   /* Y 0.3797 */
  --acc-600:        #41a87b !important;   /* Y 0.3056 */
  --acc-700:        #38986f !important;   /* Y 0.2444 */

  --acc-ink:        #0b1a13 !important;
  --acc-tint:       #152b21 !important;   /* Y 0.0200 */
  --acc-tint-2:     #0f1f18 !important;   /* Y 0.0115 */
  --acc-line:       #3a8765 !important;
  --acc-ground:     #0c1713 !important;
  --acc-hero:       linear-gradient(150deg, #0d1d16, #142d22) !important;
  --acc-wash:       rgba(94, 192, 150, .15) !important;

  /* The good slot CANNOT stay teal under a green accent. */
  --sem-good:       #95bcee !important;   /* hue 214 */
  --sem-good-tint:  #1c2735 !important;
  --sem-note:       #eab00f !important;   /* hue  44 */
  --sem-note-tint:  #2d2510 !important;
  --sem-alert:      #f99eb4 !important;   /* hue 346 */
  --sem-alert-tint: #431722 !important;
}

/* =============================================================================
 * SECTION D — REGISTER: the default, and `focused`
 * -----------------------------------------------------------------------------
 * Professional. Dense, restrained, hierarchy carried by type. The identity
 * floor: it is what is live today, so its surfaces, its ink and its type scale
 * are unchanged and every current member's screens look the same on deploy.
 * Its restraint comes from weight, case and tracking, not from a compressed
 * scale.
 *
 * Written on bare `:root` too: this is the pre-boot fallback, before kc-boot.js
 * has put an attribute on <html>.
 *
 * Surfaces are near-neutral by design in all three registers. The violet cast
 * these three carry was correct when violet was the only accent; a violet
 * ground fights gold and green. Accent hue reaches the page only through
 * --bg-warm and --hero-grad, both computed, which is enough to be felt and
 * small enough to verify.
 *
 * ONE USAGE RULE, and it is what makes the 1.35:1 --border legal: in focused,
 * --border may never be the only thing that identifies an interactive control.
 * Control boundaries use --border-strong (>=3.12:1 on every surface). Cards are
 * containers, not components, so SC 1.4.11 does not apply to their edge.
 * ========================================================================== */

/* `:root[data-theme="light"]` and `:root[data-theme="dark"]` used to be in this
   selector list. They are gone, and their removal changes nothing today while
   removing a live trap. Both were (0,2,0), the same specificity as
   `:root[data-presentation="vivid"]` and `:root[data-presentation="clear"]`, so
   the only thing keeping vivid and clear from being reverted to focused's
   tokens on a member still carrying `theme:'light'` in kc.state.v2 was source
   order. They also bought nothing: every declaration in this file is
   !important and the apps' own light/dark palettes are not, so !important
   already wins whatever the specificity. A member with the stale attribute
   still lands on focused's palette through the bare `:root` below. */
:root,
:root[data-presentation="focused"],
[data-presentation="focused"] {
  /* Surfaces */
  --bg:            #0b0a14 !important;   /* Y 0.00327 — the landing page ground */
  --surface:       #141220 !important;   /* Y 0.00680 — cards, the landing tile */
  --surface-2:     #1b1828 !important;   /* Y 0.01030 — inset panels, chips */
  --border:        #26232f !important;   /* hairline — containers only */
  --border-strong: #74748d !important;   /* 3.71 on surface, 3.38 on surface-2 */

  /* Ink */
  --text:          #ece7df !important;   /* the landing ink */
  --text-2:        #bab5b1 !important;
  --text-3:        #9c9793 !important;
  /* --text-3 was #8b8aa0, which computed to 4.56 on --surface-2 — six
     hundredths above the floor, too thin to survive any future edit. */

  /* The "ink" ramp is the nav slab and small filled chips that carry white
     text. On a dark theme those stay dark, just a shade off the page. */
  --ink-900:       #14141e !important;   /* white ink 16.14 */
  --ink-800:       #1a1a26 !important;   /* 15.20 */
  --ink-700:       #22222f !important;   /* 13.85 */

  /* The two grounds that carry the accent's hue. */
  --bg-warm:       var(--acc-ground) !important;
  --hero-grad:     var(--acc-hero) !important;
  --amber-grad:    var(--acc-hero) !important;
  /* The lesson-diagram panel, section 7. A register token rather than a literal
     so `clear` can flatten it; see the note in section F. */
  --diagram-wash:  var(--acc-wash) !important;
  --diagram-panel: linear-gradient(180deg, var(--surface-2), var(--surface)) !important;
  /* The lesson-cover plate, section 6. These were the last two literal colours
     in this file — `rgba(255,255,255,.06)` and `rgba(255,255,255,.14)`, written
     straight into the rule. Both are a LIGHTER-THAN-THE-GROUND lift, which is
     the one thing a white alpha cannot be on a light ground, so they were also
     the only two paints a light scheme could not have reached. Same values as
     before, named. */
  --plate-inset:   rgba(255,255,255,.06) !important;
  --plate-rule:    rgba(255,255,255,.14) !important;

  /* Accent consumers. focused reads the accent at --acc-500 and fills at
     --acc-700, which is the same slab at a third of the presence. */
  --blue-600:      var(--acc-500) !important;   /* 6.88-6.90 on surface */
  --blue-500:      var(--acc-400) !important;   /* hover — lighter, not darker */
  --blue-fg:       var(--blue-600) !important;
  --acc-fill:      var(--acc-700) !important;
  --acc-fill-hover: var(--acc-600) !important;
  --acc-ring:      var(--acc-400) !important;
  --blue-100:      var(--acc-tint) !important;
  --blue-050:      var(--acc-tint-2) !important;
  --violet-500:    var(--blue-600) !important;
  --violet-100:    var(--acc-tint) !important;

  /* Semantics. These carry meaning — "Good", "On track", "Improving" — so they
     are the bright dark-theme variants, all above 8.2:1 on the card. */
  --teal-500:      var(--sem-good) !important;
  --teal-100:      var(--sem-good-tint) !important;
  --amber-500:     var(--sem-note) !important;
  --amber-100:     var(--sem-note-tint) !important;
  --rose-500:      var(--sem-alert) !important;
  --rose-100:      var(--sem-alert-tint) !important;

  /* Effects. Shadows on near-black need to be darker and tighter, not softer. */
  --shadow-sm:     0 1px 0 rgba(0,0,0,.30) !important;
  --shadow-md:     0 1px 2px rgba(0,0,0,.40) !important;
  --shadow-lg:     0 10px 24px -18px rgba(0,0,0,.60) !important;
  /* Two OPAQUE layers, not one translucent halo. The old ring composited
     rgba(167,139,250,.34) over the page to #493967 — 1.85:1, a live SC 2.4.11
     and 1.4.11 failure, and no alpha of any hue reaches 3:1 as a single wash.
     The inner layer is the surface, so the ring reads against a filled control;
     the outer is the accent, >=7.59:1 against every surface in the system. */
  --ring:          0 0 0 2px var(--surface), 0 0 0 4px var(--acc-ring) !important;

  /* Type. One pair across the platform (founder, 2026-09-13: the doors, the
     quiz and the Knowledge Center look like the front page): Nunito for body,
     Comfortaa for display, the faces the landing page and the film are set
     in. Inter and Fraunces are gone from every register but clear, which
     keeps Atkinson for legibility. Three weights and only three — 400 body,
     600 interactive labels and eyebrows, 700 headings and filled controls. */
  --font-sans:     "Nunito", ui-rounded, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif !important;
  --font-serif:    var(--font-sans) !important;

  /* THE DISPLAY FACE. --font-display is the PRESENCE slot and nothing else:
     page h1s, hero headings, section headings — the sizes a member reads once
     and does not read again. Body, labels, kickers, buttons, prose, anything
     typed into, and every figure stay on --font-sans. --font-serif is NOT this
     slot: it is an alias of --font-sans in all three registers and stays one,
     so nothing new should name it.

     focused gets Fraunces, at ONE instance: opsz pinned to 48, weight pinned to
     600. Measured against fonts.gstatic.com, latin woff2, v38:
         opsz,wght@48,600             18,460 B   <- what center.html requests
         opsz,wght@9..144,600         35,180 B     the opsz axis alone is ~17 KB
         opsz,wght@48,600..700        37,064 B     a second weight re-adds wght
         opsz,wght@9..144,400;600     67,388 B     index.html's spec. Not this.
     Pinning an axis to a single value strips it; NARROWING it does nothing —
     9..144, 24..96 and 36..144 all return the identical 35,180 B file. So a
     focused member pays +18.0 KB on top of Inter's 47.3 KB, and the combined
     CSS response goes 1,238 -> 1,372 B. 48 is the optical size these slots
     actually use (the display range here is --fs-19 to --fs-56, not Fraunces'
     144pt Display cut); 600 is focused's heading weight — this register uses
     three weights and only three, see the remap in SECTION 7.

     vivid AND clear PAY ZERO BYTES. A browser downloads a woff2 only when a
     glyph matches the face, and neither register ever names Fraunces. That
     scoping IS the cost control, and it is the whole reason this token is
     declared three times instead of once.

     WHY clear IS EXCLUDED, and it is not a preference. clear is the
     high-legibility register, held to 7:1, and Atkinson Hyperlegible is its
     entire promise. Fraunces has the SMALLEST x-height of the five faces in
     this system — 44.1 per 100px em against Atkinson's 49.6 and Inter's 54.6,
     measured in Chromium at weight 600 — so a high-contrast serif there would
     take back exactly what the register exists to give. clear's display face
     IS its UI face, and that is what the declaration below says.

     DECLARED IN ALL THREE BLOCKS ON PURPOSE. This block's selector list opens
     with a bare `:root`, so a token written HERE and nowhere else inherits
     straight into vivid and clear. That is not hypothetical: --au-font-display
     (Comfortaa) is declared on a bare :root in kc-aurora-skin.css, no register
     overrides it, and three files now carry hand-written patches to hold it out
     of clear. Every register redeclares this one.

     NOT FOR FIGURES, AT ANY SIZE. Fraunces ships no `tnum`. Measured at
     26px/600: "1111" is 48.09px and "0000" is 69.81px — a 45% swing between two
     four-digit values in the same column, against Rule 9. Numeric slots stay on
     --font-sans even when they are display-sized. */
  --font-display:  "Comfortaa", ui-rounded, system-ui, sans-serif !important;

  /* THE COMPANY VOICE, and it is a DIFFERENT ROLE from --font-display.
     --font-display is the PRODUCT's presence slot, documented above: the face
     the app is drawn in. --font-editorial is the face the COMPANY speaks in —
     the front door's h1, its act headings, its closing line. Only one surface
     in this system needs both at once (the landing page, which quotes product
     UI inside a company argument), and it needs them separately addressable so
     the quotation stays in the product's own face rather than the company's.

     WHY NOT REDEFINE --font-display, and why not a bare --font-product.
     Redefining --font-display would silently reskin ~30 live call sites across
     center.html, about.html, kc-learn.css, kc-lesson-v2.css, kc-lesson-uplift
     and kc-au-market — vivid resolves it to Comfortaa on purpose (SECTION D).
     A bare --font-product pinned to Comfortaa would DISAGREE with the token
     that already holds that role in two registers, and would put a display
     face into clear. That is the --au-font-display bug exactly: declared on a
     bare :root, never overridden per register, three files now patch it out of
     clear.

     DECLARED IN ALL THREE BLOCKS, per the rule at 415-420: this file's focused
     block opens on a bare `:root`, so a token written only there inherits into
     vivid and clear.

     clear GETS ATKINSON FOR BOTH ROLES BY ARITHMETIC, not by an override
     someone has to remember. Below, clear's --font-editorial is the identical
     expression its --font-display already uses — var(--font-sans) — and
     clear's --font-sans IS Atkinson Hyperlegible. Both display roles collapse
     onto the register's own UI face, which is the whole promise of the
     register. No serif reaches it from either direction.

     COSTS NOTHING IN vivid OR clear. Same argument as --font-display at
     396-399: a woff2 is fetched only when a glyph matches the face. Nothing in
     the app names this token; only the landing page does, and that page already
     requests Fraunces for itself. No KC screen downloads one extra byte.

     NOT FOR FIGURES. Same measurement as --font-display: Fraunces ships no
     `tnum`, so numerals stay on --font-mono/--font-sans with tabular-nums. */
  --font-editorial: "Comfortaa", ui-rounded, system-ui, sans-serif !important;

  /* Motion may confirm a state change and may not announce one. */
  --motion-fast:   90ms !important;
  --motion-base:   140ms !important;
  --motion-slow:   200ms !important;
  --motion-step:   0ms !important;
  --ease:          cubic-bezier(.2,0,0,1) !important;
  --ease-press:    var(--ease) !important;
  --target-min:    44px;

  /* Chrome fill, per register, because the header hard-coded the page colour. */
  --chrome-bg:     linear-gradient(180deg, rgba(17,17,25,.92), rgba(17,17,25,.72)) !important;

  /* The size lever is section 9's generated scale, not zoom. Kept at 1 in all
     three registers so the preview rule further down is a no-op rather than a
     special case; the seam stays in place for a future register that genuinely
     needs a box-level scale. */
  --presentation-scale: 1;

  font-variant-numeric: tabular-nums slashed-zero;
  color-scheme: dark;
}

/* =============================================================================
 * SECTION E — REGISTER: `vivid`
 * -----------------------------------------------------------------------------
 * Playful. Bigger headlines, rounder cards, real depth, and things move when
 * you tap them. Nunito at 400..800 — rounder terminals and a taller x-height
 * than Inter, so the app's existing inline 500/600 render optically heavier
 * without a single weight literal being touched.
 *
 * vivid's surfaces step further apart than focused's and its --surface-2 is the
 * lightest in the system, which is constraint B3's ceiling.
 * ========================================================================== */

:root[data-presentation="vivid"],
[data-presentation="vivid"] {
  --bg:            #0e0d14 !important;   /* Y 0.00432 */
  --surface:       #1f1e2b !important;   /* Y 0.01394 */
  --surface-2:     #2c2a3c !important;   /* Y 0.02518 — B3's ceiling */
  --border:        #787491 !important;   /* 3.66 on surface, 3.11 on surface-2 */
  --border-strong: #9994ae !important;   /* 5.60 on surface */

  --text:          #ffffff !important;   /* 16.42 on surface */
  --text-2:        #d5d2e0 !important;   /* 11.04 on surface, 9.39 on surface-2 */
  --text-3:        #a9a5b8 !important;   /*  6.85 on surface, 5.83 on surface-2 */

  --ink-900:       #0a0910 !important;   /* white ink 19.82 */
  --ink-800:       #16141f !important;   /* 18.20 */
  --ink-700:       #1e1c2a !important;   /* 16.74 */

  --bg-warm:       var(--acc-ground) !important;
  --hero-grad:     var(--acc-hero) !important;
  --amber-grad:    var(--acc-hero) !important;
  /* The lesson-diagram panel, section 7. A register token rather than a literal
     so `clear` can flatten it; see the note in section F. */
  --diagram-wash:  var(--acc-wash) !important;
  --diagram-panel: linear-gradient(180deg, var(--surface-2), var(--surface)) !important;
  /* The lesson-cover plate, section 6. See the note in section D. */
  --plate-inset:   rgba(255,255,255,.06) !important;
  --plate-rule:    rgba(255,255,255,.14) !important;

  /* vivid reads the accent one stop lighter than focused, and fills at the same
     --acc-700 — the fill is a slab either way, and the brightness belongs on
     the text, where it is read rather than sat on. */
  --blue-600:      var(--acc-400) !important;   /* 7.39-7.41 on surface */
  --blue-500:      var(--acc-300) !important;
  --blue-fg:       var(--blue-600) !important;
  --acc-fill:      var(--acc-700) !important;
  --acc-fill-hover: var(--acc-600) !important;
  --acc-ring:      var(--acc-300) !important;
  --blue-100:      var(--acc-tint) !important;
  --blue-050:      var(--acc-tint-2) !important;
  --violet-500:    var(--blue-600) !important;
  --violet-100:    var(--acc-tint) !important;

  --teal-500:      var(--sem-good) !important;
  --teal-100:      var(--sem-good-tint) !important;
  --amber-500:     var(--sem-note) !important;
  --amber-100:     var(--sem-note-tint) !important;
  --rose-500:      var(--sem-alert) !important;
  --rose-100:      var(--sem-alert-tint) !important;

  --shadow-sm:     0 2px 4px rgba(0,0,0,.50) !important;
  --shadow-md:     0 14px 32px -16px rgba(0,0,0,.72), 0 2px 6px rgba(0,0,0,.40) !important;
  --shadow-lg:     0 30px 70px -32px rgba(0,0,0,.85) !important;
  --ring:          0 0 0 2px var(--surface), 0 0 0 5px var(--acc-ring) !important;

  --font-sans:     "Nunito", ui-rounded, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif !important;
  --font-serif:    var(--font-sans) !important;

  /* vivid does NOT get Fraunces, and the reason is not the bytes. Aurora Soft
     already owns a display face — --au-font-display, Comfortaa — which every
     migrated vivid surface is already drawn in and which is already in the one
     font request. A second display face would put two of them on one screen:
     the Today h1 in Comfortaa and the Ask title in a serif. So this token names
     the face the register already has, rather than importing another. The
     literal tail is for documents that load kc-theme.css WITHOUT
     kc-aurora-skin.css (about.html does exactly that) — an undefined var()
     inside a `font:` shorthand invalidates the whole declaration. */
  --font-display:  var(--au-font-display, "Comfortaa", ui-rounded, system-ui, sans-serif) !important;

  /* The company voice. Same face in vivid as in focused, and deliberately so:
     --font-editorial does not vary by register the way --font-display does,
     because the company does not change its voice when a member changes
     their reading preference. The one exception is clear, below, where
     legibility outranks voice. Declared here because the focused block opens
     on a bare :root and would otherwise inherit into this one. */
  --font-editorial: "Comfortaa", ui-rounded, system-ui, sans-serif !important;

  /* 220ms is deliberate: it matches the `animation: pageIn .22s ease both`
     already on sixteen elements, so retiming is a change of curve and stagger
     rather than of tempo. */
  --motion-fast:   120ms !important;
  --motion-base:   220ms !important;
  --motion-slow:   320ms !important;
  --motion-step:   40ms !important;
  --ease:          cubic-bezier(.2,.8,.24,1) !important;
  --ease-press:    cubic-bezier(.34,1.2,.64,1) !important;
  --target-min:    44px;

  --chrome-bg:     linear-gradient(180deg, rgba(14,13,20,.94), rgba(14,13,20,.74)) !important;

  --presentation-scale: 1;

  font-variant-numeric: tabular-nums;
  color-scheme: dark;
}

/* =============================================================================
 * SECTION F — REGISTER: `clear`
 * -----------------------------------------------------------------------------
 * High legibility. Larger text, higher contrast, thicker edges, nothing moves.
 *
 * Strictly achromatic (R=G=B) on every surface and every ink. The accent is the
 * only chromatic thing on the screen — which is exactly what buys AAA in all
 * three hues without the accent axis having to be tuned per register.
 *
 * GRADIENTS ARE ABOLISHED HERE, because ink on a gradient sits on a ground
 * whose luminance changes across the glyph, so its ratio cannot be computed —
 * and this file's whole warrant is that ratios are computed. That now includes
 * section 7's five lesson-diagram panels, which used to keep two gradients each
 * in this register; --diagram-wash and --diagram-panel below are what flatten
 * them. Every ground in `clear` is a flat colour with one computable ratio.
 *
 * Atkinson Hyperlegible at 400 and 700 only, with `font-synthesis: none`. CSS
 * Fonts 4 matching then collapses the app's four-step ramp to a clean binary
 * with ZERO markup changes: 400->400, 500->400 (for 400 < target <= 500 the
 * algorithm searches weights <= target, descending, first), 600->700 (for
 * target > 500 it searches >= target, ascending, first), 700->700. Hierarchy
 * here is carried by size and space, never by a 500/600 step a low-vision
 * reader cannot see.
 *
 * 19px regular is NOT WCAG "large text" — that needs 24px, or 18.66px bold — so
 * every AAA claim above is made at the 7:1 NORMAL-text threshold.
 * ========================================================================== */

:root[data-presentation="clear"],
[data-presentation="clear"] {
  --bg:            #0a0a0a !important;   /* Y 0.00304 — not #000: halation */
  --bg-warm:       var(--bg) !important; /* no warm/cool ground split here */
  --surface:       #171717 !important;   /* Y 0.00857 — 1.10:1 on bg, NOT the separator */
  --surface-2:     #232323 !important;   /* Y 0.01681 */
  --border:        #757575 !important;   /* 3.89 on surface — THE separator, at 2px */
  --border-strong: #a6a6a6 !important;   /* 7.36 on surface */

  --text:          #ffffff !important;   /* 17.93 on surface, 15.72 on surface-2 */
  --text-2:        #e6e6e6 !important;   /* 14.36 / 12.59 */
  --text-3:        #c7c7c7 !important;   /* 10.61 /  9.30 */

  --ink-900:       #000000 !important;   /* white ink 21.00 */
  --ink-800:       #121212 !important;   /* 18.73 */
  --ink-700:       #1e1e1e !important;   /* 16.67 */

  --hero-grad:     linear-gradient(var(--surface), var(--surface)) !important;
  --amber-grad:    linear-gradient(var(--surface-2), var(--surface-2)) !important;
  /* Section 7's five lesson diagrams were the last two gradients in `clear`,
     and this block's own invariant three paragraphs up said there were none.
     No ratio was ACTUALLY unverifiable — the callouts layered over them are
     opaque --surface chips, so no ink ever sat on the ramp — but a stated
     invariant that is false is worse than one that is narrow. The wash
     resolves to a transparent-to-transparent no-op and the panel to a flat
     fill, so nothing in this register paints a luminance ramp. The achromatic
     line art on top is unaffected. */
  --diagram-wash:  transparent !important;
  --diagram-panel: linear-gradient(var(--surface), var(--surface)) !important;
  /* The lesson-cover plate, section 6. See the note in section D. */
  --plate-inset:   rgba(255,255,255,.06) !important;
  --plate-rule:    rgba(255,255,255,.14) !important;

  /* clear reads AND fills at --acc-300: it needs 7:1 for the label ink sitting
     on the fill, which a --acc-700 slab cannot give it. */
  --blue-600:      var(--acc-300) !important;   /* 9.08-9.16 on surface */
  --blue-500:      var(--acc-200) !important;
  --blue-fg:       var(--blue-600) !important;
  --acc-fill:      var(--acc-300) !important;
  --acc-fill-hover: var(--acc-200) !important;
  /* Deliberately hue-free. The inner 3px gap is the page ground and the outer
     6px is the primary ink, so the ring stays visible even when focus lands ON
     a filled accent control — the one case an accent-coloured ring cannot
     survive. */
  --acc-ring:      var(--text) !important;
  --blue-100:      var(--acc-tint) !important;
  --blue-050:      var(--acc-tint-2) !important;
  --violet-500:    var(--blue-600) !important;
  --violet-100:    var(--acc-tint) !important;

  --teal-500:      var(--sem-good) !important;
  --teal-100:      var(--sem-good-tint) !important;
  --amber-500:     var(--sem-note) !important;
  --amber-100:     var(--sem-note-tint) !important;
  --rose-500:      var(--sem-alert) !important;
  --rose-100:      var(--sem-alert-tint) !important;

  --shadow-sm:     none !important;
  --shadow-md:     none !important;
  --shadow-lg:     none !important;
  --ring:          0 0 0 3px var(--bg), 0 0 0 6px var(--text) !important;

  --font-sans:     "Atkinson Hyperlegible", Verdana, "Segoe UI", system-ui, sans-serif !important;
  --font-serif:    var(--font-sans) !important;

  /* NON-NEGOTIABLE: clear's display face is its UI face. A decorative serif
     here defeats the register — see the x-height measurement in SECTION D. This
     declaration is also what keeps Fraunces free in this register: no glyph
     ever matches it, so no woff2 is fetched. It additionally RETIRES three live
     violations, because the surfaces that reach for a display face now reach
     for this token instead of --au-font-display: the Today h1, the Today hero
     h2 and the Ask title were all rendering Comfortaa in clear. */
  --font-display:  var(--font-sans) !important;

  /* NON-NEGOTIABLE, and it is the same non-negotiable as the line above: in
     clear, BOTH display roles are the UI face. This is var(--font-sans) —
     the identical expression --font-display uses — so clear cannot acquire
     a display face from either token, and Fraunces stays unfetched here. */
  --font-editorial: var(--font-sans) !important;
  font-synthesis:  none;

  --motion-fast:   0ms !important;
  --motion-base:   0ms !important;
  --motion-slow:   0ms !important;
  --motion-step:   0ms !important;
  --ease:          linear !important;
  --ease-press:    linear !important;
  --target-min:    48px;

  --chrome-bg:     linear-gradient(var(--bg), var(--bg)) !important;

  --presentation-scale: 1;

  font-variant-numeric: tabular-nums;
  color-scheme: dark;
}

/* =============================================================================
 * SECTION G — THE SCHEME CONTRACT, and one measured light combination
 * -----------------------------------------------------------------------------
 * A THIRD AXIS, and the honest thing to say about it first: this is a fence
 * with one gate open, not a light mode. Eight of the nine combinations are
 * still dark, deliberately, because eight of them have not been measured. What
 * IS here is the part that keeps its value whether or not light mode ever
 * ships: the enumeration below, which says of every colour in this file whether
 * a light scheme would have to change it and why.
 *
 * WHY THE ENUMERATION IS THE DELIVERABLE. The cost of a light mode is not
 * picking light colours. It is that every ratio in this file was computed
 * against a dark ground, so none of them transfers, and finding WHICH values
 * carry a measured claim means reading 2000 lines. Sections A-F already hold
 * every colour this file paints — after section 6's two literals became
 * --plate-inset and --plate-rule, there are no others — so the archaeology is
 * done once, here, and a future light palette is a value change.
 *
 * THE MANIFEST BELOW IS PARSED BY tests/scheme.test.js. Each line is
 *   TOKEN  CLASS  note
 * and the test asserts, in both directions, that the manifest and the
 * stylesheet agree: every colour-valued token declared in sections A-F appears
 * here, and every token named here is really declared there. A token added to
 * section A tomorrow fails the suite until someone says which class it is in.
 * That is the whole mechanism by which this index cannot rot.
 *
 * FOUR CLASSES:
 *   FLIP    the value must change with the scheme. Its dark value is a claim
 *           about a dark ground and means nothing on a light one.
 *   HOLD    the value must NOT change. These are not surfaces; they are dark
 *           objects that carry light ink, and they stay dark on a light page.
 *   DERIVED declared as var() of something else, so it follows the scheme for
 *           free. var() in a custom property substitutes on the element that
 *           declares it, and the light blocks below declare their raw values on
 *           that same element, so every one of these re-resolves with no work.
 *   MAP     a var() indirection whose TARGET must change: which stop of the
 *           ramp a register reads. On a dark ground more contrast is lighter;
 *           on a light ground it is darker, so a hover moves the other way
 *           along the ramp. This class is why a light mode is not a palette
 *           swap — the consumer mapping is directional, not just the values.
 *
 * === MANIFEST =============================================================
 *   --acc-200          FLIP     lightest ramp stop
 *   --acc-300          FLIP     clear: text, links, icons AND the fill
 *   --acc-400          FLIP     vivid: text. focused: hover. both: the ring
 *   --acc-500          FLIP     focused: text, links, icons
 *   --acc-600          FLIP     vivid + focused: fill hover
 *   --acc-700          FLIP     vivid + focused: the filled control
 *   --acc-ink          FLIP     ink on a fill. Near-black on dark, near-white
 *                               on light: section header's "INK ON A FILL IS
 *                               NEVER WHITE" is a dark-ground invariant and it
 *                               inverts, it does not survive
 *   --acc-tint         FLIP     the accent chip ground
 *   --acc-tint-2       FLIP     the fainter chip ground
 *   --acc-line         FLIP     tint-panel edge, >=3:1
 *   --acc-ground       FLIP     --bg-warm's source
 *   --acc-hero         FLIP     --hero-grad's source
 *   --acc-wash         HOLD     the lesson-diagram wash. See DIAGRAMS below
 *   --sem-good         FLIP     semantic ink
 *   --sem-good-tint    FLIP     semantic chip ground
 *   --sem-note         FLIP     semantic ink
 *   --sem-note-tint    FLIP     semantic chip ground
 *   --sem-alert        FLIP     semantic ink
 *   --sem-alert-tint   FLIP     semantic chip ground
 *   --bg               FLIP     the page
 *   --surface          FLIP     cards
 *   --surface-2        FLIP     inset panels, chips
 *   --border           FLIP     hairline / in clear, THE separator
 *   --border-strong    FLIP     control boundaries, >=3:1
 *   --text             FLIP     primary ink
 *   --text-2           FLIP     secondary ink
 *   --text-3           FLIP     tertiary ink
 *   --ink-900          HOLD     a DARK SLAB, not a surface. center.html and
 *                               m.html write `color:#fff` on it at 21 sites,
 *                               hard-coded, so it stays dark on a light page or
 *                               those 21 chips turn white-on-white
 *   --ink-800          HOLD     same ramp, same reason
 *   --ink-700          HOLD     same ramp, same reason
 *   --plate-inset      FLIP     a lighter-than-ground lift; inverts
 *   --plate-rule       FLIP     a lighter-than-ground lift; inverts
 *   --shadow-sm        FLIP     alpha, not hue. Black at .30-.50 over near-
 *                               black is a shape; over near-white it is a
 *                               bruise. Every alpha needs re-deriving
 *   --shadow-md        FLIP     as above
 *   --shadow-lg        FLIP     as above
 *   --chrome-bg        FLIP     the header fill, an alpha over the page colour
 *   --diagram-panel    FLIP     but TO A DARK VALUE. See DIAGRAMS below
 *   --diagram-wash     DERIVED  var(--acc-wash), or transparent in clear
 *   --bg-warm          DERIVED  var(--acc-ground), or var(--bg) in clear
 *   --hero-grad        DERIVED  var(--acc-hero)
 *   --amber-grad       DERIVED  var(--acc-hero)
 *   --blue-fg          DERIVED  var(--blue-600)
 *   --violet-500       DERIVED  var(--blue-600)
 *   --blue-100         DERIVED  var(--acc-tint)
 *   --violet-100       DERIVED  var(--acc-tint)
 *   --blue-050         DERIVED  var(--acc-tint-2)
 *   --teal-500         DERIVED  var(--sem-good)
 *   --teal-100         DERIVED  var(--sem-good-tint)
 *   --amber-500        DERIVED  var(--sem-note)
 *   --amber-100        DERIVED  var(--sem-note-tint)
 *   --rose-500         DERIVED  var(--sem-alert)
 *   --rose-100         DERIVED  var(--sem-alert-tint)
 *   --acc-fill         DERIVED  same stop in both schemes
 *   --ring             DERIVED  composed of --surface / --bg / --acc-ring
 *   --slate-500        DERIVED  var(--text-2)
 *   --slate-100        DERIVED  var(--surface-2)
 *   --blue-600         MAP      the stop each register READS
 *   --blue-500         MAP      the hover. Lighter on dark, DARKER on light
 *   --acc-fill-hover   MAP      the same flip, on the fill
 *   --acc-ring         MAP      --acc-400 / --acc-300, or --text in clear
 * === END MANIFEST =========================================================
 *
 * SO, OF THE 60 COLOUR-CARRYING TOKENS IN THIS FILE: 33 FLIP, 4 HOLD, 19 are
 * DERIVED and 4 are MAP. The accent block carries 18 of the FLIPs; the register
 * block carries 15 plus all 4 MAPs. Three accents and three registers is
 * therefore 3x18 + 3x19 = 111 values to solve for a complete light mode, and
 * 387 new contrast cells to compute — the same 43 ink-on-ground pairings over
 * nine combinations the dark matrix was solved against, not one of which
 * transfers, because every one of them is a ratio against a dark ground.
 *
 * That is the honest estimate, and the 111 values are the small half of it. The
 * measuring is the week: the landing page alone took 20 text blocks x two
 * breakpoints back from 17 failures to zero, the figures hold 5.01:1 worst
 * across 26 combinations, and the five diagrams took three passes. All of that
 * was done once, against one ground. A light mode asks for it again.
 *
 * WHAT IS NOT IN THE MANIFEST, BECAUSE IT IS NOT A TOKEN
 *   DIAGRAMS. Section 7's five drawings are data: URIs, so their ink cannot
 *   inherit anything — it is `#ffffff` at a fixed opacity, 120 marks across
 *   five drawings, and every one of the three stated floors (.42 mark, .58
 *   text, .62 key) was computed against a DARK ground. On a light panel all 120
 *   vanish. There is no token that reaches them.
 *
 *   The way out taken below is not to redraw them: --diagram-panel FLIPS TO A
 *   DARK VALUE, pinned to `clear`'s own dark --surface, so the drawing sits on
 *   exactly the ground its floors were computed against and every one of those
 *   measurements transfers verbatim rather than approximately. A dark plate on
 *   a light page is a plate, which is what section 6 already calls the lesson
 *   covers. The callouts layered over it are opaque --surface chips (section 7
 *   made them opaque deliberately), so they stay light and stay computable.
 *   The alternative — a second set of five black-ink URIs from
 *   tools/build_diagrams.py — is about 36KB more CSS and a second set of floors
 *   to derive and hold, and it should not be taken before someone has looked at
 *   a dark plate and decided they dislike it.
 *
 * WHAT THIS PROOF ACTUALLY MEASURED, AND THE ONE THING THAT STOPS IT SHIPPING
 * Measured in the running app at 1280, `clear` x `purple` x light, ground
 * sampled from the painted pixels with each element and ITS DESCENDANTS hidden:
 *
 *   26 text blocks whose ink comes from a token   worst 9.24:1   0 failures
 *   17 text blocks whose ink is a literal in the
 *      page's own style attribute                 worst 1.04:1  15 failures
 *
 * Every failure is white ink. Not one of them is reachable from this file:
 * they are `color:#fff` and `color:rgba(255,255,255,.7)` written inline in
 * center.html and m.html on elements that have no background of their own, so
 * they inherit whatever surface they land on. On a dark page that is correct
 * and invisible; on a light one it is white on white. Counted in the source:
 * 61 inline white-ink declarations in center.html and 48 in m.html, of which 34
 * and 23 sit on a dark chip this file already owns (--ink-900 slabs and accent
 * fills, both handled by section 3), leaving 52 that would need a light value.
 *
 * THOSE 52 ARE THE COST NOBODY WOULD HAVE ESTIMATED, and they are the reason
 * this is a fence and not a feature. They cannot be fixed here in the way
 * section 3 fixes its literals: section 3 matches a substring of an inline
 * style, and a rule that rewrote every `color:#fff` would also hit the 57 that
 * are correctly white because they sit on a dark chip. Distinguishing them
 * means a selector coupled to a second string in the same attribute, which is
 * the exact fragility tests/themecoupling.test.js exists to guard against, over
 * 109 sites instead of two. The real fix is a token in the markup, and the
 * markup is not this file.
 *
 * THE FENCE. Both blocks below name ALL THREE axes. That is what keeps the
 * eight unmeasured combinations on the shipping dark product instead of on a
 * half-derived light one: `light x vivid x gold` matches nothing here and
 * renders exactly as it does today. The two halves stay disjoint the way
 * sections A-F are — the accent half declares only the --acc- and --sem- sets,
 * the register half only consumers — so the composition mechanism in the file
 * header is unchanged, and the three-attribute selector is (0,4,0) against
 * section F's (0,2,0), so specificity decides and source order never has to.
 *
 * NOTHING HERE IS REACHABLE TODAY. No code sets data-scheme, so this file is
 * inert: every member lands on dark, as they do now. `light` is an explicit
 * choice and `auto` is an explicit choice to follow the OS — an absent
 * attribute is neither, which is why the media query is gated on `auto` rather
 * than applying to everyone with a light desktop. A member who picked a scheme
 * keeps it when their OS flips, because their choice is an attribute and not a
 * media query.
 *
 * TO REACH IT, THREE THINGS ARE NEEDED THAT ARE NOT IN THIS FILE, and the third
 * one has bitten this project twice already:
 *   1. kc-boot.js applies data-scheme to <html>, as it does for the other two.
 *   2. api/kc.js: `scheme` on PROFILE_WRITABLE, PROFILE_ALLOWED
 *      (["dark","light","auto"]) and PROFILE_LABEL. pick() silently drops a key
 *      that is not on PROFILE_WRITABLE and profile.save answers 200 with the
 *      unchanged row, so a missing entry looks exactly like a save that worked.
 *      `presentation` and `accent` both shipped broken this way.
 *   3. every picker preview carries data-scheme as well as the other two
 *      attributes — hazard H2 in the file header, now with three axes. A
 *      preview that names two of three lies about the third.
 * Section 4 also hides the header's theme toggle, on the grounds that it had
 * nothing left to switch between. It would have something again.
 *
 * ONE HAZARD THIS SECTION CREATED AND PAID FOR ONCE. This file is mostly prose,
 * and prose about CSS wants to write token globs. The sequence that ends a
 * comment appeared inside a sentence here — in a glob naming the two custom
 * property families — and closed this block twenty-six lines early. The parser
 * then discarded everything up to the next closing brace, which was the whole
 * light-values rule below. Every light token resolved to the guaranteed-invalid
 * value, --text computed to nothing, and the register rendered white on white.
 * Comment delimiters still balanced across the file, and this suite's own
 * comment stripper made the same early exit the browser did, so it agreed.
 * Only measuring the painted page found it. tests/scheme.test.js now fails on
 * the surviving evidence: comment prose parsed as CSS.
 * ========================================================================== */

/* THE LIGHT VALUES, NAMED ONCE.
 *
 * Declared unconditionally on bare :root and consumed by nobody unless a gate
 * below matches — the same guarantee hazard H1 makes for --acc-*: a var() that
 * resolves to nothing takes its whole declaration with it, so these exist
 * always. They are the single source for both gates, which is what stops the
 * two from drifting apart; tests/scheme.test.js asserts the gates are identical
 * apart from their selector.
 *
 * Every value was solved from a luminance target, not chosen, and every one
 * MEETS OR BEATS the ratio its dark twin holds in the same role. The figures
 * are in the two blocks that consume them. */
:root {
  /* Surfaces. The page is pulled off the extreme for the same reason --bg is
     #0a0a0a and not #000 in dark `clear`: the largest area on screen is the one
     that haloes. In dark that meant "not black"; here it means "not white".
     The three steps are the dark steps' RATIOS, mirrored — surface/bg 1.10,
     surface-2/surface 1.14 — so the surfaces sit apart by the same amount they
     do today, and --surface-2 stays the worst-case ground it is in dark. */
  --lt-bg:            #fafafa;   /* Y 0.95597 */
  --lt-surface:       #efefef;   /* Y 0.86316 */
  --lt-surface-2:     #e1e1e1;   /* Y 0.75294 */
  --lt-border:        #767676;   /* 3.95 on surface — THE separator, at 2px */
  --lt-border-strong: #4c4c4c;   /* 7.47 on surface */

  --lt-text:          #000000;   /* 18.26 on surface, 16.06 on surface-2 */
  --lt-text-2:        #1e1e1e;   /* 14.50 / 12.75 */
  --lt-text-3:        #353535;   /* 10.67 /  9.38 */

  /* The accent ramp, hue 264 — the same violet, moved to the dark end of the
     scale. THE CONVENTION IS UNCHANGED: higher number is still darker. What
     flips is which end a register reads, and that is a MAP, not a value. */
  --lt-acc-200:       #5a27a7;   /* Y 0.06415 */
  --lt-acc-300:       #4f2292;   /* Y 0.04882 */
  --lt-acc-400:       #481e86;   /* Y 0.04027 */
  --lt-acc-500:       #41197c;   /* Y 0.03274 */
  --lt-acc-600:       #3a1571;   /* Y 0.02628 */
  --lt-acc-700:       #341266;   /* Y 0.02122 */

  --lt-acc-ink:       #f9f5fe;   /* ink on a fill: 9.88 at rest, 10.81 on hover */
  --lt-acc-tint:      #ebe0fa;   /* Y 0.77876 */
  --lt-acc-tint-2:    #f3edfc;   /* Y 0.86651 */
  --lt-acc-line:      #875ec4;   /* 4.12 / 3.63 / 3.74 — its dark twin's floor */
  --lt-acc-ground:    #f6f3fc;
  --lt-acc-hero:      linear-gradient(150deg, #f8f6fd, #eee6fb);

  /* The trio holds the property that makes it read as one family: all three sit
     at Y 0.0482-0.0488, as the dark trio sits at Y 0.479-0.486. The caveat in
     the file header comes with them — three values this close in luminance are
     ~1.2:1 apart under a deuteranopia simulation, so colour still may not be
     the only difference between two states. */
  --lt-sem-good:       #0c463f;  /* hue 172 */
  --lt-sem-good-tint:  #bdeee8;
  --lt-sem-note:       #503b0a;  /* hue  42 — amber at 9:1 on white is a brown,
                                    and that is not a compromise, it is what
                                    "readable as text on a light ground" means */
  --lt-sem-note-tint:  #f4e4be;
  --lt-sem-alert:      #761c2e;  /* hue 348 */
  --lt-sem-alert-tint: #f9dfe4;

  /* Section 6's plate. The dark alphas were solved to land the SAME ratio on
     the light plate that the white alphas land on the dark one: 1.16 vs 1.17
     for the inset, 1.52 vs 1.51 for the rule. */
  --lt-plate-inset:   rgba(0,0,0,.069);
  --lt-plate-rule:    rgba(0,0,0,.178);

  /* The lesson-diagram plate stays dark, pinned to `clear`'s own dark --surface
     #171717 — the literal, not the token, because the token is light here and
     the point is that the drawing keeps the exact ground its opacity floors
     were computed against. Section 7's .42 / .58 / .62 transfer verbatim. */
  --lt-diagram-panel: linear-gradient(#171717, #171717);
}

/* --- the gate: an explicit choice ----------------------------------------- */
/* ACCENT HALF — declares only the raw ramp, exactly as section A does. */
:root[data-scheme="light"][data-presentation="clear"][data-accent="purple"],
[data-scheme="light"][data-presentation="clear"][data-accent="purple"] {
  --acc-200:        var(--lt-acc-200) !important;
  --acc-300:        var(--lt-acc-300) !important;
  --acc-400:        var(--lt-acc-400) !important;
  --acc-500:        var(--lt-acc-500) !important;
  --acc-600:        var(--lt-acc-600) !important;
  --acc-700:        var(--lt-acc-700) !important;
  --acc-ink:        var(--lt-acc-ink) !important;
  --acc-tint:       var(--lt-acc-tint) !important;
  --acc-tint-2:     var(--lt-acc-tint-2) !important;
  --acc-line:       var(--lt-acc-line) !important;
  --acc-ground:     var(--lt-acc-ground) !important;
  --acc-hero:       var(--lt-acc-hero) !important;
  /* --acc-wash is deliberately NOT here: it is the diagram wash, and the
     diagram plate stays dark. `clear` blanks it to transparent anyway. */
  --sem-good:       var(--lt-sem-good) !important;
  --sem-good-tint:  var(--lt-sem-good-tint) !important;
  --sem-note:       var(--lt-sem-note) !important;
  --sem-note-tint:  var(--lt-sem-note-tint) !important;
  --sem-alert:      var(--lt-sem-alert) !important;
  --sem-alert-tint: var(--lt-sem-alert-tint) !important;
}
/* REGISTER HALF — declares only consumers, exactly as sections D-F do.
   Everything section F declares as a var() of one of these is left alone on
   purpose: --bg-warm, --hero-grad, --chrome-bg, --ring, --acc-ring, --blue-600,
   --acc-fill, the six semantic aliases and the two tint aliases all re-resolve
   against the values above with nothing written here, because substitution
   happens on the element that declares them and that is this same element. */
:root[data-scheme="light"][data-presentation="clear"][data-accent="purple"],
[data-scheme="light"][data-presentation="clear"][data-accent="purple"] {
  --bg:            var(--lt-bg) !important;
  --surface:       var(--lt-surface) !important;
  --surface-2:     var(--lt-surface-2) !important;
  --border:        var(--lt-border) !important;
  --border-strong: var(--lt-border-strong) !important;
  --text:          var(--lt-text) !important;
  --text-2:        var(--lt-text-2) !important;
  --text-3:        var(--lt-text-3) !important;
  /* --ink-900/800/700 are NOT here. They are the dark slab that carries the 21
     hard-coded `color:#fff` chips in center.html and m.html, so they stay at
     section F's values and stay dark. */

  /* THE MAP, and it is the part a palette swap would miss. In dark `clear` the
     hover is --acc-200, one stop LIGHTER, because on a dark ground lighter is
     more contrast. Here it is --acc-400, one stop DARKER, for the same reason
     read the other way: rest 9.24 -> hover 10.12 on --surface, a gain, exactly
     as dark's 9.15 -> 11.14 is a gain. Left as --acc-200 it would have been a
     LOSS to 8.05, and it would have looked like it worked. */
  --blue-500:      var(--acc-400) !important;
  --acc-fill-hover: var(--acc-400) !important;

  --plate-inset:   var(--lt-plate-inset) !important;
  --plate-rule:    var(--lt-plate-rule) !important;
  --diagram-panel: var(--lt-diagram-panel) !important;

  color-scheme: light;
}

/* --- the gate: following the OS, but only when asked to --------------------
   Identical to the two blocks above apart from the attribute, which is what
   tests/scheme.test.js checks. `auto` is a choice a member makes; the absence
   of the attribute is not, and that is why this is not written as a bare
   `@media (prefers-color-scheme: light)`. Section 5's shipping product is dark,
   and a member who has never been offered a light mode has not asked for one. */
@media (prefers-color-scheme: light) {
  :root[data-scheme="auto"][data-presentation="clear"][data-accent="purple"],
  [data-scheme="auto"][data-presentation="clear"][data-accent="purple"] {
    --acc-200:        var(--lt-acc-200) !important;
    --acc-300:        var(--lt-acc-300) !important;
    --acc-400:        var(--lt-acc-400) !important;
    --acc-500:        var(--lt-acc-500) !important;
    --acc-600:        var(--lt-acc-600) !important;
    --acc-700:        var(--lt-acc-700) !important;
    --acc-ink:        var(--lt-acc-ink) !important;
    --acc-tint:       var(--lt-acc-tint) !important;
    --acc-tint-2:     var(--lt-acc-tint-2) !important;
    --acc-line:       var(--lt-acc-line) !important;
    --acc-ground:     var(--lt-acc-ground) !important;
    --acc-hero:       var(--lt-acc-hero) !important;
    --sem-good:       var(--lt-sem-good) !important;
    --sem-good-tint:  var(--lt-sem-good-tint) !important;
    --sem-note:       var(--lt-sem-note) !important;
    --sem-note-tint:  var(--lt-sem-note-tint) !important;
    --sem-alert:      var(--lt-sem-alert) !important;
    --sem-alert-tint: var(--lt-sem-alert-tint) !important;
  }
  :root[data-scheme="auto"][data-presentation="clear"][data-accent="purple"],
  [data-scheme="auto"][data-presentation="clear"][data-accent="purple"] {
    --bg:            var(--lt-bg) !important;
    --surface:       var(--lt-surface) !important;
    --surface-2:     var(--lt-surface-2) !important;
    --border:        var(--lt-border) !important;
    --border-strong: var(--lt-border-strong) !important;
    --text:          var(--lt-text) !important;
    --text-2:        var(--lt-text-2) !important;
    --text-3:        var(--lt-text-3) !important;
    --blue-500:      var(--acc-400) !important;
    --acc-fill-hover: var(--acc-400) !important;
    --plate-inset:   var(--lt-plate-inset) !important;
    --plate-rule:    var(--lt-plate-rule) !important;
    --diagram-panel: var(--lt-diagram-panel) !important;
    color-scheme: light;
  }
}

html, body { background: var(--bg) !important; color: var(--text) !important; }

/* ---------------------------------------------------------------------------
 * 2. Chrome
 * ------------------------------------------------------------------------ */

header {
  background: var(--chrome-bg) !important;
  border-bottom: var(--bw-1) solid var(--border) !important;
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}

/* ---------------------------------------------------------------------------
 * 3. Where a literal beats the token
 * ---------------------------------------------------------------------------
 * The generated apps hard-code some colours instead of using a token. These are
 * matched on the INLINE STYLE, because there are no class hooks — and on BOTH
 * SPELLINGS, because the DC runtime converts an authored style string to an
 * object (kc-support.js:803) which is then re-serialised WITH spaces after the
 * colon. The static HTML the server sends has no spaces; the hydrated DOM does.
 * A selector written for one spelling matches nothing for the first paint or
 * nothing after it, and both failures look like a flash of the wrong colour.
 *
 * Everything in this section is a live AA failure TODAY, independent of the two
 * axes, and every one of them would otherwise be inherited by all nine
 * combinations.
 * ------------------------------------------------------------------------ */

/* D1 + D2 — FILLED ACCENT CONTROLS.
   48 sites are authored `background:var(--blue-600);color:#fff`, plus three on
   --violet-500 and one 24px numbered badge on --amber-500. White on the accent
   computes to 2.72:1 under the old violet and 1.87-2.50:1 under the new ramps.
   The fill drops to --acc-fill (a third of the presence of the text value) and
   the ink becomes --acc-ink: 5.03-9.75:1 in all nine combinations.
   The previous rule matched only the spaced spelling, which no source file
   uses — so every primary button flashed white-on-accent on every load. */
[style*="background:var(--blue-600)"],
[style*="background: var(--blue-600)"],
[style*="background-color:var(--blue-600)"],
[style*="background-color: var(--blue-600)"],
[style*="background:var(--violet-500)"],
[style*="background: var(--violet-500)"],
[style*="background-color:var(--violet-500)"],
[style*="background-color: var(--violet-500)"],
[style*="background:var(--amber-500)"],
[style*="background: var(--amber-500)"],
[style*="background-color:var(--amber-500)"],
[style*="background-color: var(--amber-500)"] {
  background: var(--acc-fill) !important;
  color: var(--acc-ink) !important;
}
[style*="background:var(--blue-600)"] *,
[style*="background: var(--blue-600)"] *,
[style*="background-color:var(--blue-600)"] *,
[style*="background-color: var(--blue-600)"] *,
[style*="background:var(--violet-500)"] *,
[style*="background: var(--violet-500)"] *,
[style*="background-color:var(--violet-500)"] *,
[style*="background-color: var(--violet-500)"] *,
[style*="background:var(--amber-500)"] *,
[style*="background: var(--amber-500)"] *,
[style*="background-color:var(--amber-500)"] *,
[style*="background-color: var(--amber-500)"] * {
  color: var(--acc-ink) !important;
}
[style*="background:var(--blue-600)"] svg,
[style*="background: var(--blue-600)"] svg,
[style*="background-color:var(--blue-600)"] svg,
[style*="background-color: var(--blue-600)"] svg,
[style*="background:var(--violet-500)"] svg,
[style*="background: var(--violet-500)"] svg,
[style*="background-color:var(--violet-500)"] svg,
[style*="background-color: var(--violet-500)"] svg,
[style*="background:var(--amber-500)"] svg,
[style*="background: var(--amber-500)"] svg,
[style*="background-color:var(--amber-500)"] svg,
[style*="background-color: var(--amber-500)"] svg {
  stroke: var(--acc-ink) !important;
}

/* D5 — FIFTEEN CHIP INKS ARE LIGHT-THEME LITERALS ON DARK TINTS.
   #07684F on --teal-100 computes to 1.98:1 (5 sites), #8A5A05 on --amber-100 to
   2.37:1 (8 sites), #B23A32 on --rose-100 to 2.52:1 (1 site). Nothing else in
   this file caught them. Remapped to the matching semantic, both spellings —
   >=7.58:1 in all nine combinations afterwards. */
[style*="color:#07684F"],
[style*="color: #07684F"],
[style*="color: rgb(7, 104, 79)"] { color: var(--teal-500) !important; }
[style*="color:#8A5A05"],
[style*="color: #8A5A05"],
[style*="color: rgb(138, 90, 5)"] { color: var(--amber-500) !important; }
[style*="color:#B23A32"],
[style*="color: #B23A32"],
[style*="color: rgb(178, 58, 50)"] { color: var(--rose-500) !important; }
[style*="color:#0C8E77"],
[style*="color: #0C8E77"],
[style*="color: rgb(12, 142, 119)"] { color: var(--teal-500) !important; }

/* D6 — ACCENT TINT PANELS HAVE NO PERCEIVABLE EDGE.
   15 sites pair `background:var(--blue-050)` with a border in --blue-100. Under
   every ramp in this file that edge is ~1.2:1, and the incumbent violet was
   1.17:1 — the panel reads by HUE, not by lightness, so it disappears entirely
   for a viewer who cannot see the hue. Routed to --acc-line: >=3.18:1 against
   every surface in every register. This is not an accent workaround; the apps
   already do exactly this for teal.

   Matched on `solid var(--token)` rather than on a width, because the border
   width is now a --bw-* token and the literal spelling no longer exists. */
[style*="solid var(--blue-100)"],
[style*="solid var(--violet-100)"] {
  border-color: var(--acc-line) !important;
}

/* D6b — THE ONE USAGE RULE IN SECTION D, ENFORCED RATHER THAN ASSERTED.
   Section D says it plainly: "in focused, --border may never be the only thing
   that identifies an interactive control. Control boundaries use
   --border-strong." The markup does not honour it. Counted openings of
   <button|a|input|select|textarea> carrying `solid var(--border)` and no
   --border-strong: 32 in center.html, 24 in m.html.

   Computed against the ground each control actually sits on:

       register   --border vs --surface   vs --surface-2   fill step
       focused          1.35                   1.23         1.10-1.22
       vivid            3.68                   3.13         1.18-1.38
       clear            3.89                   3.41         1.14-1.26

   In focused NOTHING about a secondary control reaches 3:1 — not the edge, not
   the step between its fill and the card behind it — so the voice-dictate
   toggle, the thumbs pair, the filter chips, both Close buttons and every
   accordion header read as text until you hit them. SC 1.4.11, in all three
   accents, in the register that is the default and the only one a current
   member has ever seen.

   --border-strong is used in ALL THREE registers rather than only in focused,
   because the sentence in section D is written about controls and not about a
   register, and because one component tree means a secondary control has one
   boundary treatment. Afterwards, on --surface: 3.71 focused, 5.63 vivid, 7.36
   clear; on --surface-2: 3.38 / 4.79 / 6.46. Every cell clears 3:1.

   Card edges are deliberately untouched: a card is a container, SC 1.4.11 does
   not apply to it, and taking every hairline up to 3.7:1 would undo section 5. */
button[style*="solid var(--border)"],
a[style*="solid var(--border)"],
input[style*="solid var(--border)"],
select[style*="solid var(--border)"],
textarea[style*="solid var(--border)"],
[role="button"][style*="solid var(--border)"],
[role="radio"][style*="solid var(--border)"],
[role="tab"][style*="solid var(--border)"] {
  border-color: var(--border-strong) !important;
}

/* D7 — FOUR HARD-CODED BLUE GLOWS. rgba(36,52,222,.9) was already wrong under
   violet; under gold it is a blue halo beneath a brass button. */
[style*="rgba(36,52,222,.9)"],
[style*="rgba(36, 52, 222, 0.9)"] {
  box-shadow: var(--shadow-md) !important;
}

/* D8 — Periwinkle accent text on the dark emphasis card in the mobile build. It
   was a literal because the old token was too dark to read there. It used to be
   pinned back to a literal violet, which left that one label purple under the
   gold and green accents. */
[style*="color: rgb(143, 160, 255)"],
[style*="color:#8FA0FF"] {
  color: var(--blue-600) !important;
}

/* Navy surfaces that never went through a token.

   BOTH SPELLINGS, and this block did not have them. The section header above
   states the rule and every rule below it obeyed it; these did not. Verified
   against the served files: `grep -c "rgb(27, 42, 107)" center.html m.html`
   returns 0 for both — the spaced rgb() form exists ONLY in the hydrated DOM,
   because collectProps() in kc-support.js runs EVERY style attribute (static
   ones included) through cssToObj and React re-serialises it with spaces. So
   the rgb()-only selectors matched nothing at all until the DC runtime had
   mounted, and until then the served markup painted its light-theme literals:
   a cream-to-navy panel and two white slabs on a near-black page. The hex
   spellings below are what the server actually sends. */
[style*="linear-gradient(160deg, rgb(27, 42, 107)"],
[style*="linear-gradient(160deg,#1B2A6B"],
[style*="linear-gradient(150deg, rgb(16, 27, 78)"],
[style*="linear-gradient(150deg,#101B4E"] {
  background: var(--hero-grad) !important;
}
[style*="background: rgb(11, 15, 30)"],
[style*="background:#0B0F1E"] {
  background-color: var(--ink-900) !important;
}
/* A cream-to-navy decorative panel, and a lavender wash. */
[style*="linear-gradient(160deg, rgb(246, 227, 201)"],
[style*="linear-gradient(160deg,#F6E3C9"] {
  background: var(--amber-grad) !important;
}
[style*="linear-gradient(160deg, rgb(239, 230, 218)"],
[style*="linear-gradient(160deg,#EFE6DA"] {
  background: linear-gradient(160deg, var(--surface-2), var(--surface)) !important;
}
/* A cool blue-white wash behind the top of some mobile screens. */
[style*="radial-gradient(120% 100% at 50% 0%, rgb(255, 255, 255) 0%, rgb(237, 239, 250)"],
[style*="radial-gradient(120% 100% at 50% 0%,#fff"] {
  background: radial-gradient(120% 100% at 50% 0%, var(--surface) 0%, var(--bg) 100%) !important;
}

/* Solid-white and near-white fills. On the old light theme these read as a
   clean chip; on near-black they are headlights. */
[style*="background: rgb(255, 255, 255)"],
[style*="background:#fff"],
[style*="background: rgba(255, 255, 255, 0.9"],
[style*="background: rgba(255, 255, 255, 0.8"] {
  background-color: var(--surface-2) !important;
  border: var(--bw-1) solid var(--border) !important;
}

/* TWO TOKENS THE APPS ASK FOR AND NOBODY EVER DEFINED. center.html's connected
   -data list styles the Apple Health row with var(--slate-100) and
   var(--slate-500, #4a6679): --slate-100 has no fallback at all, so that tile
   renders unset, and the fallback on --slate-500 is a light-theme navy that
   computes to 2.24:1 on the card. Aliased to neutrals here, and re-declared on
   the bare attribute selector so a preview resolves them against its OWN ink
   rather than inheriting a value already substituted against the page's. */
:root,
[data-presentation] {
  --slate-500: var(--text-2) !important;
  --slate-100: var(--surface-2) !important;
}

/* THE CHARTS. Two places the font and colour tokens do not reach, because the
   values are SVG presentation attributes rather than CSS: seven <text> in
   center.html carry font-family="Inter,sans-serif", and eight in m.html carry
   a light-theme ink baked in as fill=. Without this the charts stay in Inter in
   every register and stay navy-on-near-black in every accent. */
:root[data-presentation] svg text,
[data-presentation] svg text {
  font-family: var(--font-sans) !important;
}
svg text[fill="#4A5578"] { fill: var(--text-2) !important; }
svg text[fill="#8A93B2"] { fill: var(--text-3) !important; }

/* AND THE MARKS, not only the labels. The rule above was written for <text>
   and stops there, so m.html's two charts kept the retired brand blue #2434DE
   baked into the data itself: the alertness curve, its three plot points, its
   area-fill gradient stops. Computed
   against the ground each sits on, #2434DE is 2.05-2.24:1 in all three
   registers — under SC 1.4.11's 3:1 for a graphical object you have to see to
   read the chart — and it stayed blue under the gold and green accents, which
   is the one thing the accent axis exists to stop.

   `stroke`, `fill` and `stop-color` are all CSS properties as well as
   presentation attributes, and a CSS declaration beats a presentation
   attribute at any specificity, so this reaches them where var() in the
   attribute itself would not (custom properties are not substituted into
   presentation attributes).

   Afterwards: --blue-600 is 6.88-9.16:1 on --surface and 6.19-8.24:1 on
   --surface-2 across all nine, and it rotates with the accent. The axis rule
   and the ring track were light-theme greys that happened to read on a dark
   page; routed to --border-strong they now follow the register instead. */
svg [stroke="#2434DE"]  { stroke: var(--blue-600) !important; }
svg [fill="#2434DE"]    { fill:   var(--blue-600) !important; }
svg stop[stop-color="#2434DE"] { stop-color: var(--blue-600) !important; }
svg [stroke="#CDD2EC"], svg [stroke="#E6E8F4"] { stroke: var(--border-strong) !important; }
/* The one white plot point marks "you are here" on the curve; on a dark panel
   it is the brightest thing in the chart, which is correct, but it was also
   the only mark whose ring did not rotate. */
svg circle[fill="#fff"][stroke="#2434DE"] { fill: var(--text) !important; }

/* ---------------------------------------------------------------------------
 * 4. One theme only
 * ------------------------------------------------------------------------ */

/* The light/dark toggle has nothing left to switch between, so it goes rather
   than sitting there as a dead control. `color-scheme: dark` in each register
   block is what tells the browser, properly, that this page has one scheme. */
header button[aria-label*="heme"],
header button[title*="heme"] {
  display: none !important;
}

/* ---------------------------------------------------------------------------
 * 5. Minimal hierarchy
 * ---------------------------------------------------------------------------
 * "Redesign the dashboard using a more minimal hierarchy" (Trevor, Aug 2026).
 *
 * The problem was not density, it was that everything shouted equally: five
 * cards on Today, each with its own shadow, border and bold heading, so nothing
 * read as the primary action. The fix is to take emphasis AWAY from the
 * secondary surfaces rather than add more to the primary one.
 *
 * Applied app-wide, not just to Today, so the rest of the product does not
 * suddenly look busier than the dashboard. `vivid` opts back in below — depth
 * is part of what that register IS — and beats these rules by adding one
 * compound to the selector at the same !important.
 * ------------------------------------------------------------------------ */

/* Flatten every card. The originals stack a shadow AND a border AND a fill. */
[style*="box-shadow: var(--shadow-md)"],
[style*="box-shadow:var(--shadow-md)"],
[style*="box-shadow: var(--shadow-sm)"],
[style*="box-shadow:var(--shadow-sm)"] {
  box-shadow: none !important;
  border: var(--bw-1) solid var(--border) !important;
}

:root[data-presentation="vivid"] [style*="box-shadow: var(--shadow-md)"],
:root[data-presentation="vivid"] [style*="box-shadow:var(--shadow-md)"],
[data-presentation="vivid"] [style*="box-shadow: var(--shadow-md)"],
[data-presentation="vivid"] [style*="box-shadow:var(--shadow-md)"] {
  box-shadow: var(--shadow-md) !important;
  border: var(--bw-1) solid var(--border) !important;
}
:root[data-presentation="vivid"] [style*="box-shadow: var(--shadow-sm)"],
:root[data-presentation="vivid"] [style*="box-shadow:var(--shadow-sm)"],
[data-presentation="vivid"] [style*="box-shadow: var(--shadow-sm)"],
[data-presentation="vivid"] [style*="box-shadow:var(--shadow-sm)"] {
  box-shadow: var(--shadow-sm) !important;
  border: var(--bw-1) solid var(--border) !important;
}

/* Card headings: same size, one weight lighter, so the eye lands on content
   rather than on five labels of equal strength. */
main h2,
main h3 {
  font-weight: 600 !important;
  letter-spacing: -0.005em !important;
}

/* focused uses three weights and only three: 400 body, 500 interactive labels,
   600 headings. 700 does not exist in this register, so the 700 sites are
   remapped down. Emphasis inside prose is 500, never 600 — a heading and an
   emphasised body word must never share a weight. */
:root[data-presentation="focused"] [style*="font-weight:700"],
:root[data-presentation="focused"] [style*="font-weight: 700"],
[data-presentation="focused"] [style*="font-weight:700"],
[data-presentation="focused"] [style*="font-weight: 700"] {
  font-weight: 600 !important;
}

/* Eyebrow labels were competing with the headings beneath them. */
main [style*="letter-spacing: 0.1em"],
main [style*="letter-spacing:.1em"],
main [style*="letter-spacing: 0.11em"] {
  color: var(--text-3) !important;
  font-weight: 600 !important;
}

/* The dark emphasis card is the one place depth is still earned. */
section[style*="hero-grad"] {
  box-shadow: none !important;
  border: var(--bw-1) solid var(--border) !important;
}
:root[data-presentation="vivid"] section[style*="hero-grad"],
[data-presentation="vivid"] section[style*="hero-grad"] {
  box-shadow: var(--shadow-md) !important;
}

/* Touch targets. The floor is a register token so components never repeat the
   number; clear raises the same token rather than growing targets ad hoc. */
:root[data-presentation="clear"] button,
:root[data-presentation="clear"] a[href],
:root[data-presentation="clear"] input,
:root[data-presentation="clear"] select,
[data-presentation="clear"] button,
[data-presentation="clear"] a[href],
[data-presentation="clear"] input,
[data-presentation="clear"] select {
  min-height: var(--target-min);
}

/* Learn and the lesson player are audited as complete keyboard/touch journeys.
   This scope covers every control in those views in all three registers. */
.kc-a11y-targets button,
.kc-a11y-targets a[href],
.kc-a11y-targets input,
.kc-a11y-targets select,
.kc-a11y-targets textarea,
.kc-a11y-targets [role="button"],
.kc-a11y-targets [tabindex]:not([tabindex="-1"]) {
  min-block-size: var(--target-min) !important;
  min-inline-size: var(--target-min) !important;
}

/* Logical sizing only has an effect on a generated box. Lesson citations are
   short inline links, so make their target a box without making it a full row. */
.kc-a11y-targets a[href] {
  display: inline-flex;
  align-items: center;
}

/* Inline component shadows otherwise outrank the shell's focus shadow. The
   audited journeys get an explicit outline as well as the register ring, and
   !important is what makes it survive those generated inline declarations. */
.kc-a11y-targets :focus-visible {
  outline: var(--bw-2) solid var(--acc-300) !important;
  outline-offset: 3px !important;
  box-shadow: var(--ring) !important;
}

/* Persistent live regions stay in the accessibility tree without claiming
   visual space or becoming a keyboard stop. */
.kc-sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/* At 200% zoom the wide shell has roughly half its usual CSS viewport. Keep
   every destination present and let the chrome gain rows instead of widening
   the document beyond the viewport. */
@media (max-width: 720px) {
  body:has(.kc-a11y-targets) header {
    height: auto !important;
  }
  body:has(.kc-a11y-targets) header > div {
    flex-wrap: wrap !important;
    padding-top: var(--sp-2) !important;
    padding-bottom: var(--sp-2) !important;
  }
  body:has(.kc-a11y-targets) header nav {
    flex: 1 1 100% !important;
    flex-wrap: wrap !important;
    justify-content: flex-start !important;
  }
}

/* min-height DOES NOT APPLY to a non-replaced inline box, and 12 links in
   center.html plus one in m.html carry a style attribute with no `display` —
   the wordmark, the corner link back to Today, "alternate composition", the
   evidence source link, both marketplace links, both onboarding links, the
   passport link and /quiz. They stayed inline, the declaration above was
   discarded, and the register whose warrant is "easier to hit" silently did not
   enlarge a quarter of its own navigation targets.

   Made inline-flex rather than block so the box still sits in its line, and
   deliberately NOT applied to links inside prose (SC 2.5.8 exempts a target
   inline in a sentence, and stretching those would open holes in the leading). */
:root[data-presentation="clear"] a[href]:not(p a):not(li a):not(figcaption a),
[data-presentation="clear"] a[href]:not(p a):not(li a):not(figcaption a) {
  display: inline-flex;
  align-items: center;
}

/* The three multi-corner radii the generator leaves alone by construction, one
   explicit rule each per register. Placed after the single-value work so they
   cannot be undone by it. */
:root[data-presentation="focused"] [style*="border-radius:16px 16px 4px 16px"],
[data-presentation="focused"] [style*="border-radius:16px 16px 4px 16px"],
:root[data-presentation="focused"] [style*="border-radius: 16px 16px 4px 16px"],
[data-presentation="focused"] [style*="border-radius: 16px 16px 4px 16px"] { border-radius: 8px 8px 3px 8px !important; }
:root[data-presentation="focused"] [style*="border-radius:16px 16px 16px 4px"],
[data-presentation="focused"] [style*="border-radius:16px 16px 16px 4px"],
:root[data-presentation="focused"] [style*="border-radius: 16px 16px 16px 4px"],
[data-presentation="focused"] [style*="border-radius: 16px 16px 16px 4px"] { border-radius: 8px 8px 8px 3px !important; }
:root[data-presentation="vivid"] [style*="border-radius:16px 16px 4px 16px"],
[data-presentation="vivid"] [style*="border-radius:16px 16px 4px 16px"],
:root[data-presentation="vivid"] [style*="border-radius: 16px 16px 4px 16px"],
[data-presentation="vivid"] [style*="border-radius: 16px 16px 4px 16px"] { border-radius: 20px 20px 6px 20px !important; }
:root[data-presentation="vivid"] [style*="border-radius:16px 16px 16px 4px"],
[data-presentation="vivid"] [style*="border-radius:16px 16px 16px 4px"],
:root[data-presentation="vivid"] [style*="border-radius: 16px 16px 16px 4px"],
[data-presentation="vivid"] [style*="border-radius: 16px 16px 16px 4px"] { border-radius: 20px 20px 20px 6px !important; }
:root[data-presentation="clear"] [style*="border-radius:16px 16px 4px 16px"],
[data-presentation="clear"] [style*="border-radius:16px 16px 4px 16px"],
:root[data-presentation="clear"] [style*="border-radius: 16px 16px 4px 16px"],
[data-presentation="clear"] [style*="border-radius: 16px 16px 4px 16px"] { border-radius: 12px 12px 4px 12px !important; }
:root[data-presentation="clear"] [style*="border-radius:16px 16px 16px 4px"],
[data-presentation="clear"] [style*="border-radius:16px 16px 16px 4px"],
:root[data-presentation="clear"] [style*="border-radius: 16px 16px 16px 4px"],
[data-presentation="clear"] [style*="border-radius: 16px 16px 16px 4px"] { border-radius: 12px 12px 12px 4px !important; }

/* ---------------------------------------------------------------------------
 * 6. Lesson covers
 * ---------------------------------------------------------------------------
 * Removing the mascots took the illustration off the Learn cards and left a
 * 132px empty pastel rectangle in its place — the largest element on the card
 * carrying the least information, which reads as a broken image rather than a
 * design choice.
 *
 * The fix is not to put artwork back. The tile becomes a plate: the topic set
 * small in the card's own accent, over a hairline. Editorial rather than
 * illustrated, consistent with the lesson diagram, and it translates.
 * ------------------------------------------------------------------------ */

main figure[data-art^="lesson-cover-"] {
  height: 96px !important;
  border-radius: var(--r-12) !important;
  background-image: none !important;
  box-shadow: inset 0 0 0 1px var(--plate-inset);
  align-items: flex-end !important;
  justify-content: flex-start !important;
  padding: 0 0 13px 15px !important;
  position: relative;
}

/* The hairline the label sits under. */
main figure[data-art^="lesson-cover-"]::before {
  content: "";
  position: absolute;
  left: 15px; right: 15px; bottom: 36px;
  height: 1px;
  background: var(--plate-rule);
}

/* The topic. figcaption already holds the art key and is hidden; the label has
   to be written here because the app's markup has no field for it. */
main figure[data-art^="lesson-cover-"]::after {
  font: 600 var(--fs-11)/1 var(--font-sans);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--text-2);
}
main figure[data-art="lesson-cover-longevity"]::after { content: "Longevity basics"; }
main figure[data-art="lesson-cover-fitness"]::after   { content: "Cardiorespiratory fitness"; }
main figure[data-art="lesson-cover-strength"]::after  { content: "Strength & muscle"; }
main figure[data-art="lesson-cover-metabolic"]::after { content: "Metabolic health"; }
main figure[data-art="lesson-cover-bioage"]::after    { content: "Measuring ageing"; }
/* Retired covers, kept so an old link still reads sensibly. */
main figure[data-art="lesson-cover-sleep"]::after     { content: "Sleep & recovery"; }
main figure[data-art="lesson-cover-nutrition"]::after { content: "Nutrition"; }
main figure[data-art="lesson-cover-stress"]::after    { content: "Mind & stress"; }

/* ---------------------------------------------------------------------------
 * 7. Per-lesson mental models
 * ---------------------------------------------------------------------------
 * Every lesson used to render the same drawing — a sun signalling a body clock
 * — whichever lesson you were in. With five lessons that is worse than having
 * no diagram: it teaches the reader that the picture means nothing.
 *
 * The first pass at fixing that renamed the five keys but kept the five old
 * sleep-course drawings behind them. The second redrew each one to the shape of
 * its own idea. This is the third pass, and it is about two things the second
 * one left undone: the drawings could not be READ, and they did not SAY what
 * they were plotting.
 *
 * READ. Measured in the running app, the only mark in any of the five panels
 * that cleared 3:1 was the primary curve, at opacity .48. The second curve came
 * in at 2.5:1, the dots and rings at 2.0–3.1:1, the brackets and leaders at
 * 2.7–2.9:1. Every mark carrying a distinct piece of the lesson sat under the
 * floor this project holds everywhere else, in the one place nobody had
 * measured because a background-image is not a component. There are now two
 * stated floors — .42 for a mark, .58 for text — computed against the LIGHTEST
 * ground any register produces (`vivid` --surface-2 under the gold --acc-wash,
 * rgb(69,61,63)) and then confirmed on screen. The frame and the gridlines stay
 * far below both: they are ruled paper, not marks.
 *
 * SAY. The five were unlabelled line shapes. A falling line with no axes does
 * not mean "risk of dying falls as fitness rises" — it means nothing, and the
 * whole burden of meaning fell on three floating chips. Each plot now names
 * both axes, names each series ON the series rather than in a legend, and
 * labels the measurement that IS the lesson:
 *
 *   healthspan   two curves and the gap between them, measured EARLY and LATE,
 *                because one bracket cannot show a gap widening
 *   fitness      the five fitness groups the claim is actually made in, with
 *                the step out of group 1 and the sum of the other four
 *                measured against the same axis so they can be compared
 *   strength     mass and strength declining apart, and the reserve — the
 *                distance still left to the threshold — as the shaded region
 *   metabolic    two stacked plots sharing one time axis. They were on one y
 *                axis, which implied insulin and glucose are comparable in
 *                height. They are not; what is comparable is WHEN each moves,
 *                and the delay between the two is now a drawn measure
 *   bioage       three clocks reading three ages off one sample, each error
 *                dropped to the actual-age line, and the spread bracketed
 *
 * THE INK IS ACHROMATIC, and that is a decision the accent axis forced. These
 * drawings are data: URIs, so they cannot inherit currentColor through
 * background-image — under a gold or green accent a violet drawing would simply
 * stay violet. Shipping three accent variants would mean fifteen data URIs. So
 * the ink is white at a stated opacity, the wash behind it is the accent's own
 * --acc-wash, and the panel is the register's own surfaces. Both are register
 * tokens, which is what lets `clear` flatten the panel and blank the wash
 * without a sixth copy of every data: URI. The accent still shows, in the HTML
 * callouts layered on top.
 *
 * THE TEXT IN THESE DRAWINGS CANNOT BE TRANSLATED, and that is a real cost paid
 * knowingly. It is inside a data: URI, so it is also invisible to a screen
 * reader — as is every other mark here; the figure's aria-label is what carries
 * the meaning, and it should be extended to name the axes. center.html builds
 * that string, so it is not this file's to set. If the Knowledge Center is ever
 * localised, these labels have to move out into HTML and this section gets
 * rebuilt differently. Today center.html is <html lang="en"> and lesson text is
 * stored in English.
 *
 * A STAGE PER LESSON, INERT UNTIL center.html OPTS IN. The panel does not change
 * across the four steps, so on the retrieve step — where the reader is being
 * asked to commit to an answer — the picture beside the question is already
 * drawing the answer with the explain step's three labels on it. Each lesson
 * therefore also emits a stage: the same axes, labelled, with no data on them.
 * If the figure carries data-step="0" it renders the stage and hides the
 * callouts. Any other value, or no attribute at all, renders the complete
 * drawing exactly as before, so nothing here depends on that markup existing.
 *
 * Generated by tools/build_diagrams.py — which PRINTS to stdout rather than
 * writing this file, so nothing here can silently revert. Everything from the
 * next comment to the end of this section is its output, pasted verbatim: it
 * emits the tokens directly, so the four hand-substitutions the old version
 * needed on every paste (and that nobody was checking) are gone.
 *
 * [data-art] is repeated on every selector on purpose: [attr] and [attr="v"]
 * have the SAME specificity, and kc-boot.js injects `figure[data-art]{
 * background-image:none}` into <head> at runtime — after this file — so it
 * would win the tie on order. The extra attribute wins on specificity instead.
 * ------------------------------------------------------------------------ */
/* Shared panel treatment for every lesson diagram.

   The panel carries the drawing's own aspect ratio rather than a fixed height,
   because `background-size: 100% 100%` stretches the drawing to whatever box it
   lands in: at 1024 the column is 552px wide, and against the old 560px height
   that was a 12% horizontal squash -- circles became ellipses. min-height is
   the floor that keeps the callouts from crowding on the narrowest column. */
main section:has(> figure[data-art$="-diagram"]) {
  aspect-ratio: 631 / 470;
  min-height: 430px !important;
}

figure[data-art$="-diagram"][data-art] {
  background-size: 100% 100%, 100% 100%, 100% 100% !important;
  background-position: center, center, center !important;
  background-repeat: no-repeat, no-repeat, no-repeat !important;
}

/* The sun/moon strip below the panel was drawn for the old photograph. The
   diagram carries the sequence on its own, so it goes. */
figure[data-art$="-diagram"] ~ div[style*="bottom: 26px"] { display: none !important; }

/* Callouts were written for a dark photo and hard-code white or navy text. */
figure[data-art$="-diagram"] ~ div [style*="color: rgb(255, 255, 255)"],
figure[data-art$="-diagram"] ~ div [style*="color: rgb(27, 42, 107)"] { color: var(--text) !important; }

/* Give the callouts a legible chip so they hold against the wash. Opaque rather
   than translucent: a chip whose ground is 82% of one register's page colour is
   not a ground whose contrast can be computed.

   One width for all three. center.html sets 150/230/190px inline, which is
   three different shapes for three labels of the same kind, and the 230px one
   is wide enough to read as a banner rather than a label. At 168px each is two
   short lines, and a label that small can be placed against the mark it names
   instead of parked in whatever corner is free. */
figure[data-art$="-diagram"] ~ div {
  background: var(--surface) !important;
  border: var(--bw-1) solid var(--border) !important;
  border-radius: var(--r-10) !important;
  padding: 8px 11px !important;
  box-shadow: var(--shadow-sm) !important;
  color: var(--text) !important;
  max-width: 168px !important;
}

/* OPTIONAL, and inert until center.html opts in. `data-step="0"` is the
   retrieve step -- the reader is being asked to commit to an answer, and the
   panel beside the question currently draws the answer with the explain step's
   three labels on it. With the attribute set, that step gets the labelled but
   empty plot below and no callouts. Every other value, and no attribute at
   all, leaves the complete drawing exactly as it is. */
figure[data-art$="-diagram"][data-step="0"] ~ div { display: none !important; }

figure[data-art="lesson-healthspan-diagram"][data-art] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cdefs%3E%3Cmarker%20id%3D%27h%27%20viewBox%3D%270%200%2010%2010%27%20refX%3D%277%27%20refY%3D%275%27%20markerWidth%3D%275%27%20markerHeight%3D%275%27%20orient%3D%27auto-start-reverse%27%3E%3Cpath%20d%3D%27M0%201%20L9%205%20L0%209%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3C%2Fmarker%3E%3C%2Fdefs%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.07%27%20stroke-width%3D%271.4%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M193.6%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M291.2%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M388.8%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M486.4%20396%20V%2056%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3ECalendar%20decades%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3EYears%20of%20life%3C%2Ftext%3E%3Cpath%20d%3D%27M126%20350%20C%20214%20344%20272%20250%20340%20200%20C%20410%20148%20486%20118%20566%20106%20566%20246%20C%20492%20248%20428%20256%20356%20282%20C%20288%20306%20222%20346%20126%20350%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.085%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%279%206%27%3E%3Cpath%20d%3D%27M126%20350%20C%20222%20346%20288%20306%20356%20282%20C%20428%20256%20492%20248%20566%20246%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.62%27%20stroke-width%3D%273%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M126%20350%20C%20214%20344%20272%20250%20340%20200%20C%20410%20148%20486%20118%20566%20106%27%2F%3E%3C%2Fg%3E%3Ccircle%20cx%3D%27126%27%20cy%3D%27350%27%20r%3D%276%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3Ccircle%20cx%3D%27566%27%20cy%3D%27106%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27566%27%20cy%3D%27246%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20marker-start%3D%27url%28%23h%29%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M244%20294.4%20V%20320.2%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M236%20288.4%20H%20252%20M236%20326.2%20H%20252%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27230%27%20y%3D%27312.3%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27end%27%3Egap%20then%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20marker-start%3D%27url%28%23h%29%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M534%20117.8%20V%20241.3%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M526%20111.8%20H%20542%20M526%20247.3%20H%20542%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27548%27%20y%3D%27184.5%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27start%27%3Egap%20now%3C%2Ftext%3E%3Ctext%20x%3D%27430%27%20y%3D%27138%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27end%27%3ELifespan%3C%2Ftext%3E%3Ctext%20x%3D%27340%27%20y%3D%27314%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27end%27%3EHealthspan%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(120% 80% at 62% 4%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-healthspan-diagram"][data-art][data-step="0"] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.07%27%20stroke-width%3D%271.4%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M193.6%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M291.2%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M388.8%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M486.4%20396%20V%2056%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3ECalendar%20decades%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3EYears%20of%20life%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(120% 80% at 62% 4%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-healthspan-diagram"][data-art] ~ div:nth-of-type(1) { left: 4% !important; right: auto !important; top: 8% !important; }
figure[data-art="lesson-healthspan-diagram"][data-art] ~ div:nth-of-type(2) { left: 28% !important; right: auto !important; top: auto !important; bottom: 14% !important; }
figure[data-art="lesson-healthspan-diagram"][data-art] ~ div:nth-of-type(3) { left: 60% !important; right: auto !important; top: 64% !important; }

figure[data-art="lesson-fitness-diagram"][data-art] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cdefs%3E%3Cmarker%20id%3D%27h%27%20viewBox%3D%270%200%2010%2010%27%20refX%3D%277%27%20refY%3D%275%27%20markerWidth%3D%275%27%20markerHeight%3D%275%27%20orient%3D%27auto-start-reverse%27%3E%3Cpath%20d%3D%27M0%201%20L9%205%20L0%209%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3C%2Fmarker%3E%3C%2Fdefs%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EFitness%20group%2C%20least%20fit%20to%20most%20fit%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3ERisk%20of%20dying%2C%20any%20cause%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.07%27%20stroke-width%3D%271.4%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M138%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M240%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M342%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M444%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M546%20396%20V%2056%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27138%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E1%3C%2Ftext%3E%3Ctext%20x%3D%27240%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E2%3C%2Ftext%3E%3Ctext%20x%3D%27342%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E3%3C%2Ftext%3E%3Ctext%20x%3D%27444%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E4%3C%2Ftext%3E%3Ctext%20x%3D%27546%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E5%3C%2Ftext%3E%3Cpath%20d%3D%27M138%20100%20C%20176%20104%20196%20246%20240%20282%20C%20306%20330%20420%20348%20546%20356%20L546%20396%20L138%20396%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.06%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.62%27%20stroke-width%3D%273%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M138%20100%20C%20176%20104%20196%20246%20240%20282%20C%20306%20330%20420%20348%20546%20356%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%276%207%27%3E%3Cpath%20d%3D%27M138%20100%20H%20300%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%276%207%27%3E%3Cpath%20d%3D%27M168%20282.0%20H%20574%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%276%207%27%3E%3Cpath%20d%3D%27M390%20356%20H%20574%27%2F%3E%3C%2Fg%3E%3Ccircle%20cx%3D%27138%27%20cy%3D%27100%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27240%27%20cy%3D%27282.0%27%20r%3D%2715%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272%27%20fill%3D%27none%27%2F%3E%3Ccircle%20cx%3D%27240%27%20cy%3D%27282.0%27%20r%3D%276%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27546%27%20cy%3D%27356%27%20r%3D%276%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20marker-start%3D%27url%28%23h%29%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M174%20106%20V%20276.0%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M166%20100%20H%20182%20M166%20282.0%20H%20182%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27188%27%20y%3D%27196.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27start%27%3Egroup%201%20to%202%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20marker-start%3D%27url%28%23h%29%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M580%20288.0%20V%20350%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M572%20282.0%20H%20588%20M572%20356%20H%20588%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27566%27%20y%3D%27324.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27end%27%3Egroups%202%20to%205%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(120% 85% at 18% 4%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-fitness-diagram"][data-art][data-step="0"] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EFitness%20group%2C%20least%20fit%20to%20most%20fit%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3ERisk%20of%20dying%2C%20any%20cause%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.07%27%20stroke-width%3D%271.4%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M138%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M240%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M342%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M444%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M546%20396%20V%2056%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27138%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E1%3C%2Ftext%3E%3Ctext%20x%3D%27240%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E2%3C%2Ftext%3E%3Ctext%20x%3D%27342%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E3%3C%2Ftext%3E%3Ctext%20x%3D%27444%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E4%3C%2Ftext%3E%3Ctext%20x%3D%27546%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3E5%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(120% 85% at 18% 4%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-fitness-diagram"][data-art] ~ div:nth-of-type(1) { left: 36% !important; right: auto !important; top: 5% !important; }
figure[data-art="lesson-fitness-diagram"][data-art] ~ div:nth-of-type(2) { left: 30% !important; right: auto !important; top: 22% !important; }
figure[data-art="lesson-fitness-diagram"][data-art] ~ div:nth-of-type(3) { left: 56% !important; right: auto !important; top: 52% !important; }

figure[data-art="lesson-strength-diagram"][data-art] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cdefs%3E%3Cmarker%20id%3D%27h%27%20viewBox%3D%270%200%2010%2010%27%20refX%3D%277%27%20refY%3D%275%27%20markerWidth%3D%275%27%20markerHeight%3D%275%27%20orient%3D%27auto-start-reverse%27%3E%3Cpath%20d%3D%27M0%201%20L9%205%20L0%209%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3C%2Fmarker%3E%3C%2Fdefs%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.07%27%20stroke-width%3D%271.4%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M193.6%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M291.2%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M388.8%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M486.4%20396%20V%2056%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EAge%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3EMuscle%20mass%20and%20strength%3C%2Ftext%3E%3Cpath%20d%3D%27M132.0%20132.0%20L145.8%20133.2%20L159.0%20135.0%20L171.9%20137.3%20L184.4%20140.3%20L196.4%20143.8%20L208.2%20147.8%20L219.6%20152.4%20L230.7%20157.3%20L241.6%20162.8%20L252.3%20168.6%20L262.7%20174.8%20L273.0%20181.4%20L283.2%20188.3%20L293.3%20195.5%20L303.3%20203.0%20L313.3%20210.8%20L323.2%20218.7%20L333.2%20226.9%20L343.2%20235.2%20L353.3%20243.7%20L363.6%20252.3%20L372.8%20259.9%20L382.3%20267.4%20L391.9%20274.6%20L401.4%20281.6%20L411.0%20288.3%20L420.6%20294.6%20L430.1%20300.8%20L439.6%20306.7%20L449.1%20312.3%20L458.6%20317.7%20L458.6%20317.7%20L458.6%20318%20H%20132.0%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.085%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%278%207%27%3E%3Cpath%20d%3D%27M96%20318%20H%20584%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27108%27%20y%3D%27304%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27start%27%3Ethreshold%20for%20everyday%20tasks%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%279%206%27%3E%3Cpath%20d%3D%27M132%20132%20C%20240%20134%20318%20158%20398%20190%20C%20468%20216%20520%20234%20566%20248%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.62%27%20stroke-width%3D%273%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M132%20132%20C%20232%20138%20294%20194%20368%20256%20C%20436%20312%20506%20344%20566%20368%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27572%27%20y%3D%27236%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27end%27%3EMass%3C%2Ftext%3E%3Ctext%20x%3D%27400%27%20y%3D%27388%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27end%27%3EStrength%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%274%206%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M312%2096%20C%20316%20116%20318%20130%20320%20154%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27312%27%20y%3D%2786%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27middle%27%3Eglucose%20disposal%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20marker-start%3D%27url%28%23h%29%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M300%20206.3%20V%20312%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M292%20200.3%20H%20308%20M292%20318%20H%20308%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27314%27%20y%3D%27264.2%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27start%27%3Ereserve%3C%2Ftext%3E%3Ccircle%20cx%3D%27459.2%27%20cy%3D%27318.1%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27459.2%27%20cy%3D%27318.1%27%20r%3D%2716%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272%27%20fill%3D%27none%27%2F%3E%3C%2Fsvg%3E"),
    radial-gradient(115% 85% at 26% 8%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-strength-diagram"][data-art][data-step="0"] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.07%27%20stroke-width%3D%271.4%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M193.6%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M291.2%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M388.8%20396%20V%2056%27%2F%3E%3Cpath%20d%3D%27M486.4%20396%20V%2056%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EAge%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3EMuscle%20mass%20and%20strength%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(115% 85% at 26% 8%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-strength-diagram"][data-art] ~ div:nth-of-type(1) { left: 38% !important; right: auto !important; top: 4% !important; }
figure[data-art="lesson-strength-diagram"][data-art] ~ div:nth-of-type(2) { left: 62% !important; right: auto !important; top: 22% !important; }
figure[data-art="lesson-strength-diagram"][data-art] ~ div:nth-of-type(3) { left: 12% !important; right: auto !important; top: auto !important; bottom: 18% !important; }

figure[data-art="lesson-metabolic-diagram"][data-art] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cdefs%3E%3Cmarker%20id%3D%27h%27%20viewBox%3D%270%200%2010%2010%27%20refX%3D%277%27%20refY%3D%275%27%20markerWidth%3D%275%27%20markerHeight%3D%275%27%20orient%3D%27auto-start-reverse%27%3E%3Cpath%20d%3D%27M0%201%20L9%205%20L0%209%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3C%2Fmarker%3E%3C%2Fdefs%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2062%20V%20188%20H%20584%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%2730%27%20y%3D%27125.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20125.0%29%27%3EInsulin%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.62%27%20stroke-width%3D%273%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M132%20178%20C%20216%20176%20268%20140%20330%20118%20C%20412%2092%20490%2078%20560%2072%27%2F%3E%3C%2Fg%3E%3Ccircle%20cx%3D%27132%27%20cy%3D%27178%27%20r%3D%276%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3Ccircle%20cx%3D%27268.0%27%20cy%3D%27143.7%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27268.0%27%20cy%3D%27143.7%27%20r%3D%2715%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272%27%20fill%3D%27none%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%20224%20V%20350%20H%20584%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%2730%27%20y%3D%27287.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20287.0%29%27%3EGlucose%3C%2Ftext%3E%3Cpath%20d%3D%27M96%20286%20H584%20V330%20H96%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.07%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%276%207%27%3E%3Cpath%20d%3D%27M96%20286%20H%20584%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27210%27%20y%3D%27276%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27start%27%3Etop%20of%20the%20normal%20range%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.62%27%20stroke-width%3D%273%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M132%20306%20C%20250%20306%20330%20304%20400%20302%20C%20470%20300%20498%20268%20560%20218%27%2F%3E%3C%2Fg%3E%3Ccircle%20cx%3D%27132%27%20cy%3D%27306%27%20r%3D%276%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3Ccircle%20cx%3D%27468.7%27%20cy%3D%27286.0%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27468.7%27%20cy%3D%27286.0%27%20r%3D%2715%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272%27%20fill%3D%27none%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%275%206%27%3E%3Cpath%20d%3D%27M268%20143.7%20V%20376%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%275%206%27%3E%3Cpath%20d%3D%27M468.7%20286.0%20V%20376%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20marker-start%3D%27url%28%23h%29%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M274%20376%20H%20462.7%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M268%20368%20V%20384%20M468.7%20368%20V%20384%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27368.4%27%20y%3D%27364%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27middle%27%3Eyears%20of%20looking%20normal%3C%2Ftext%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EYears%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(115% 85% at 78% 96%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-metabolic-diagram"][data-art][data-step="0"] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2062%20V%20188%20H%20584%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%2730%27%20y%3D%27125.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20125.0%29%27%3EInsulin%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%20224%20V%20350%20H%20584%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%2730%27%20y%3D%27287.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20287.0%29%27%3EGlucose%3C%2Ftext%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EYears%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(115% 85% at 78% 96%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-metabolic-diagram"][data-art] ~ div:nth-of-type(1) { left: 5% !important; right: auto !important; top: 6% !important; }
figure[data-art="lesson-metabolic-diagram"][data-art] ~ div:nth-of-type(2) { left: 22% !important; right: auto !important; top: 44% !important; }
figure[data-art="lesson-metabolic-diagram"][data-art] ~ div:nth-of-type(3) { left: 66% !important; right: auto !important; top: 42% !important; }

figure[data-art="lesson-bioage-diagram"][data-art] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cdefs%3E%3Cmarker%20id%3D%27h%27%20viewBox%3D%270%200%2010%2010%27%20refX%3D%277%27%20refY%3D%275%27%20markerWidth%3D%275%27%20markerHeight%3D%275%27%20orient%3D%27auto-start-reverse%27%3E%3Cpath%20d%3D%27M0%201%20L9%205%20L0%209%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.42%27%2F%3E%3C%2Fmarker%3E%3C%2Fdefs%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EThree%20clocks%2C%20one%20person%2C%20one%20blood%20sample%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3EEstimated%20age%3C%2Ftext%3E%3Cpath%20d%3D%27M96%20182%20H584%20V328%20H96%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.055%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%278%207%27%3E%3Cpath%20d%3D%27M96%20262%20H%20584%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27108%27%20y%3D%27252%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27start%27%3Eactual%20age%3C%2Ftext%3E%3Ccircle%20cx%3D%27204%27%20cy%3D%27146%27%20r%3D%2722%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.2%27%20fill%3D%27none%27%2F%3E%3Cpath%20d%3D%27M204%20146%20L188%20132%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%2F%3E%3Ccircle%20cx%3D%27340%27%20cy%3D%27280%27%20r%3D%2722%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.2%27%20fill%3D%27none%27%2F%3E%3Cpath%20d%3D%27M340%20280%20L358%20288%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%2F%3E%3Ccircle%20cx%3D%27476%27%20cy%3D%27202%27%20r%3D%2722%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.2%27%20fill%3D%27none%27%2F%3E%3Cpath%20d%3D%27M476%20202%20L492%20192%27%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%2F%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20stroke-dasharray%3D%275%206%27%3E%3Cpath%20d%3D%27M204%20188%20V%20262%27%2F%3E%3Cpath%20d%3D%27M340%20322%20V%20262%27%2F%3E%3Cpath%20d%3D%27M476%20244%20V%20262%27%2F%3E%3C%2Fg%3E%3Ccircle%20cx%3D%27204%27%20cy%3D%27188%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27340%27%20cy%3D%27322%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ccircle%20cx%3D%27476%27%20cy%3D%27244%27%20r%3D%277%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.62%27%2F%3E%3Ctext%20x%3D%27204%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3Eclock%20A%3C%2Ftext%3E%3Ctext%20x%3D%27340%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3Eclock%20B%3C%2Ftext%3E%3Ctext%20x%3D%27476%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3Eclock%20C%3C%2Ftext%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.8%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20marker-start%3D%27url%28%23h%29%27%20marker-end%3D%27url%28%23h%29%27%3E%3Cpath%20d%3D%27M548%20194%20V%20316%27%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.42%27%20stroke-width%3D%271.6%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M540%20188%20H%20556%20M540%20322%20H%20556%27%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%27536%27%20y%3D%27166%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2713%27%20font-weight%3D%27500%27%20text-anchor%3D%27middle%27%3Ethey%20disagree%20by%20this%20much%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(125% 85% at 48% 24%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-bioage-diagram"][data-art][data-step="0"] {
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20631%20470%27%20fill%3D%27none%27%3E%3Cg%20stroke%3D%27%23ffffff%27%20stroke-opacity%3D%27.16%27%20stroke-width%3D%271.5%27%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M96%2056%20V%20396%20H%20584%27%2F%3E%3C%2Fg%3E%3Cpath%20d%3D%27M96%2052%20l%20-5%209%20l%2010%200%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M588%20396%20l%20-9%20-5%20l%200%2010%20z%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.16%27%2F%3E%3Ctext%20x%3D%27340.0%27%20y%3D%27436%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%3EThree%20clocks%2C%20one%20person%2C%20one%20blood%20sample%3C%2Ftext%3E%3Ctext%20x%3D%2730%27%20y%3D%27226.0%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2715%27%20font-weight%3D%27600%27%20text-anchor%3D%27middle%27%20transform%3D%27rotate%28-90%2030%20226.0%29%27%3EEstimated%20age%3C%2Ftext%3E%3Ctext%20x%3D%27204%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3Eclock%20A%3C%2Ftext%3E%3Ctext%20x%3D%27340%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3Eclock%20B%3C%2Ftext%3E%3Ctext%20x%3D%27476%27%20y%3D%27416%27%20fill%3D%27%23ffffff%27%20fill-opacity%3D%27.58%27%20font-family%3D%27system-ui%2Csans-serif%27%20font-size%3D%2712%27%20font-weight%3D%27400%27%20text-anchor%3D%27middle%27%3Eclock%20C%3C%2Ftext%3E%3C%2Fsvg%3E"),
    radial-gradient(125% 85% at 48% 24%, var(--diagram-wash), transparent 70%),
    var(--diagram-panel) !important;
}
figure[data-art="lesson-bioage-diagram"][data-art] ~ div:nth-of-type(1) { left: 4% !important; right: auto !important; top: 6% !important; }
figure[data-art="lesson-bioage-diagram"][data-art] ~ div:nth-of-type(2) { left: 11% !important; right: auto !important; top: auto !important; bottom: 13% !important; }
figure[data-art="lesson-bioage-diagram"][data-art] ~ div:nth-of-type(3) { left: 42% !important; right: auto !important; top: auto !important; bottom: 13% !important; }

/* The generated rules above own the drawings; this class owns their place in
   the lesson. A diagram is a media frame inside the explain step, never a
   sticky shell column. Mobile has no <main>, so the aspect ratio also lives on
   the class rather than depending only on the generated :has() selector. */
.lesson-diagram {
  position: relative;
  width: 100%;
  min-width: 0;
  aspect-ratio: 631 / 470;
  overflow: hidden;
  margin: 20px 0 0;
  border-radius: var(--r-20);
  background: var(--diagram-panel);
  box-shadow: var(--shadow-md);
}
.lesson-diagram > figure { position: absolute; inset: 0; margin: 0; }
.lesson-diagram-node {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 10px;
}
.lesson-diagram-node-dot {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: var(--r-999);
  color: var(--ink-900);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
}
.lesson-diagram-node-label {
  font-size: var(--fs-13);
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
}

/* ---------------------------------------------------------------------------
 * 8. The brief layout's remaining light literals
 * ---------------------------------------------------------------------------
 * `#/today?variant=brief` is the alternate Today composition, reachable from
 * the "Alternate composition" link at the foot of the default one. Three of its
 * colours are literals rather than tokens, so nothing above caught them and the
 * whole hero stayed white on a dark page.
 *
 * Each is matched twice, because the DC runtime re-serialises inline styles: an
 * authored `#FFFFFF` becomes `rgb(255, 255, 255)` in the DOM. Matching both
 * spellings means this holds whichever way the runtime hands it over, instead
 * of working in the source and failing on screen.
 * ------------------------------------------------------------------------ */

[style*="linear-gradient(180deg,#FFFFFF,#EFF2FC)"],
[style*="linear-gradient(180deg, rgb(255, 255, 255)"],
[style*="linear-gradient(rgb(255, 255, 255)"] {
  background: var(--hero-grad) !important;
  border-color: var(--border) !important;
}

[style*="#F6E2C6"],
[style*="rgb(246, 226, 198)"] {
  border-color: var(--border-strong) !important;
}

[style*="#e0c3b4"],
[style*="rgb(224, 195, 180)"] {
  border-color: var(--border-strong) !important;
}

/* =============================================================================
 * 9. Motion, per register
 * -----------------------------------------------------------------------------
 * ONE CORRECTNESS RULE THAT WILL BITE ANYONE WHO EDITS THIS SECTION: never put
 * the pre-animation state in a static declaration. `opacity:0` in a rule plus
 * `animation: none !important` under reduced motion leaves the element
 * permanently invisible. The `from` state lives inside the keyframe, with
 * `animation-fill-mode: both`; when the animation is removed the element
 * renders at its natural style. Verify with reduced motion ON, not by reading
 * the sheet.
 *
 * The keyframes below are UNIQUELY NAMED rather than redefinitions of the apps'
 * own `pageIn` / `riseIn` / `pop`. Those live in the generated <helmet> <style>,
 * which the runtime injects AFTER this <link> — so a redefinition from here
 * would lose the source-order tie. Re-pointing the existing hooks at a new name
 * wins on !important instead, which does not depend on order at all.
 * ========================================================================== */

@keyframes kcVividRise {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes kcFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* EVERY ADDED ANIMATION AND TRANSITION BELOW IS INSIDE
 * `@media (prefers-reduced-motion: no-preference)`, and that is not decoration.
 *
 * The blanket reset at the foot of this section matches `[data-presentation] *`,
 * which is specificity (0,1,0). The register rules that follow are (0,2,0) and
 * (0,3,0), and both carry !important — so under `reduce` the register would
 * have WON the race and the OS preference would have been quietly overridden by
 * the very sheet that claims to honour it. Specificity is the wrong tool for
 * "the OS always wins": gating on `no-preference` means that under `reduce`
 * these rules do not exist at all, so there is nothing to out-specify.
 *
 * `no-preference` is also false in a browser that does not support the feature.
 * That degrades to the apps' own `pageIn`, which their own reduced-motion block
 * already handles — the pre-existing behaviour, not a new failure mode.
 *
 * The blanket reset stays as the belt: it catches the apps' own animations,
 * which are not gated on anything. */
@media (prefers-reduced-motion: no-preference) {

/* ------------------------------------------------------------------ vivid --
 * Exactly two things, and nothing else. No confetti, no celebration, no
 * progress-bar theatre, no count-up numerals — those are the streak pattern in
 * visual grammar, and colour and motion are the two easiest ways to smuggle it
 * back in after the copy has been cleaned.
 * ------------------------------------------------------------------------ */

/* 1. Staggered entrance. */
:root[data-presentation="vivid"] [style*="animation: pageIn"],
:root[data-presentation="vivid"] [style*="animation:pageIn"],
:root[data-presentation="vivid"] [style*="animation: riseIn"],
:root[data-presentation="vivid"] [style*="animation:riseIn"],
[data-presentation="vivid"] [style*="animation: pageIn"],
[data-presentation="vivid"] [style*="animation:pageIn"],
[data-presentation="vivid"] [style*="animation: riseIn"],
[data-presentation="vivid"] [style*="animation:riseIn"] {
  animation: kcVividRise var(--motion-base) var(--ease) both !important;
}

/* Capped at four steps / 160ms. Nothing waits longer than that to exist. */
:root[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(2),
[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(2) { animation-delay: calc(var(--motion-step) * 1) !important; }
:root[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(3),
[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(3) { animation-delay: calc(var(--motion-step) * 2) !important; }
:root[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(4),
[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(4) { animation-delay: calc(var(--motion-step) * 3) !important; }
:root[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(n+5),
[data-presentation="vivid"] [style*="animation:pageIn"]:nth-child(n+5) { animation-delay: calc(var(--motion-step) * 4) !important; }

/* 2. Press response. The apps already declare `style-active="transform:
   scale(.985)"` on 82 controls, which the runtime applies instantly; this gives
   that snap a release curve instead of an instant cut. Overshoot is permitted
   ONLY on press-release, never on entrance — an overshoot on text moves
   baselines and reads as instability. */
:root[data-presentation="vivid"] button,
:root[data-presentation="vivid"] a[href],
:root[data-presentation="vivid"] [role="button"],
[data-presentation="vivid"] button,
[data-presentation="vivid"] a[href],
[data-presentation="vivid"] [role="button"] {
  transition: transform var(--motion-fast) var(--ease-press),
              background-color var(--motion-fast) linear,
              box-shadow var(--motion-fast) var(--ease);
}

/* ---------------------------------------------------------------- focused --
 * Motion may confirm a state change and may not announce one. Every entrance is
 * opacity-only: center.html's pageIn and riseIn keep the fade and drop the 8px
 * and 12px travel, and m.html's `pop` (scale .96 -> 1) loses its scale. The real
 * transitions — a meter filling, a segmented indicator moving — stay, retimed.
 *
 * `shimmer` and `slidein` are defined in m.html and used by nothing, so there is
 * nothing here to remove; if a skeleton is ever wired up it must be a static
 * --surface-2 block, because a shimmer is decoration pretending to be progress.
 * ------------------------------------------------------------------------ */

:root[data-presentation="focused"] [style*="animation: pageIn"],
:root[data-presentation="focused"] [style*="animation:pageIn"],
:root[data-presentation="focused"] [style*="animation: riseIn"],
:root[data-presentation="focused"] [style*="animation:riseIn"],
:root[data-presentation="focused"] [style*="animation: pop"],
:root[data-presentation="focused"] [style*="animation:pop"],
[data-presentation="focused"] [style*="animation: pageIn"],
[data-presentation="focused"] [style*="animation:pageIn"],
[data-presentation="focused"] [style*="animation: riseIn"],
[data-presentation="focused"] [style*="animation:riseIn"],
[data-presentation="focused"] [style*="animation: pop"],
[data-presentation="focused"] [style*="animation:pop"] {
  animation: kcFade var(--motion-base) var(--ease) both !important;
}

}   /* end @media (prefers-reduced-motion: no-preference) */

/* ------------------------------------------------------------------ clear --
 * Nothing moves unless the reader moved it. This is a stated property of the
 * register, and it is separate from prefers-reduced-motion, which is the OS
 * setting and is honoured on top of whatever register is chosen.
 * ------------------------------------------------------------------------ */

:root[data-presentation="clear"] *,
:root[data-presentation="clear"] *::before,
:root[data-presentation="clear"] *::after,
[data-presentation="clear"] *,
[data-presentation="clear"] *::before,
[data-presentation="clear"] *::after {
  animation: none !important;
  transition: none !important;
  scroll-behavior: auto !important;
}

/* The DC runtime applies `style-active="transform:scale(.985)"` as an inline
   style the instant a control is pressed, so `transition:none` does not stop
   the movement — it only stops it being smooth. Press must still be VISIBLE; it
   just must not move, so the cue becomes a surface change. */
:root[data-presentation="clear"] *:active,
[data-presentation="clear"] *:active {
  transform: none !important;
}
:root[data-presentation="clear"] button:active,
:root[data-presentation="clear"] a[href]:active,
:root[data-presentation="clear"] [role="button"]:active,
[data-presentation="clear"] button:active,
[data-presentation="clear"] a[href]:active,
[data-presentation="clear"] [role="button"]:active {
  background-color: var(--surface-2) !important;
}

/* A frozen spinner is a three-quarter arc that never turns, which reads as a
   hang — worse than nothing. It is already aria-hidden and already sits beside
   a real text label inside role="status" aria-live, so in this register
   progress is reported in words only. */
:root[data-presentation="clear"] [style*="animation:kcSpin"],
:root[data-presentation="clear"] [style*="animation: kcSpin"],
[data-presentation="clear"] [style*="animation:kcSpin"],
[data-presentation="clear"] [style*="animation: kcSpin"] {
  display: none !important;
}

/* ------------------------------------------------------------- previews --
 * A live sample of one axis value, rendered inside a page showing another. This
 * is the documented VARIANT of the component, and it is the only reason any of
 * the selectors in this file are written twice. It is used by the settings
 * picker in both apps and by the onboarding step in /quiz, all of which render
 * the same sample markup under a different data-presentation / data-accent.
 *
 * --presentation-scale is 1 in all three registers, so these resolve to zoom:1
 * and width:100%. They are kept rather than deleted so a future register that
 * genuinely does need a box-level scale has the seam already in place.
 *
 * An element carrying data-presentation WITHOUT this attribute gets the palette
 * and not the box scale. That is deliberate: re-skinning a fragment is common,
 * re-scaling one is not.
 * ------------------------------------------------------------------------ */
[data-presentation][data-presentation-preview] {
  zoom: var(--presentation-scale, 1);
  width: calc(100% / var(--presentation-scale, 1));
}

/* THE OS ALWAYS WINS. A member who asked for less motion gets less motion in
 * every register, including vivid — whose motion is the point of it. vivid's
 * motion degrades to NONE, not to "less". The bare selectors cover previews, so
 * a vivid sample cannot animate inside a page that has been asked to hold
 * still, and the duration tokens are zeroed as well so any future property that
 * reads a duration rather than being caught by the animation/transition reset
 * is also zero. */
@media (prefers-reduced-motion: reduce) {
  /* The three VALUED selectors are listed as well as the bare one. Without
     them `[data-presentation="vivid"]` on a preview tile is (0,2,0) and beats
     the bare `[data-presentation]` at (0,1,0), so that tile kept
     --motion-base:220ms under `reduce`. Nothing animated — the blanket reset
     below still fired — but the block's own stated reason for zeroing the
     durations ("any future property that reads a duration") was false for
     exactly the element the durations are most likely to be read on. */
  :root,
  :root[data-presentation],
  :root[data-presentation="vivid"],
  :root[data-presentation="focused"],
  :root[data-presentation="clear"],
  [data-presentation],
  [data-presentation="vivid"],
  [data-presentation="focused"],
  [data-presentation="clear"] {
    --motion-fast: 0ms !important;
    --motion-base: 0ms !important;
    --motion-slow: 0ms !important;
    --motion-step: 0ms !important;
  }
  :root[data-presentation] *,
  :root[data-presentation] *::before,
  :root[data-presentation] *::after,
  [data-presentation] *,
  [data-presentation] *::before,
  [data-presentation] *::after {
    animation: none !important;
    transition: none !important;
  }
  /* The one motion this block used to miss. The DC runtime applies
     `style-active="transform:scale(.985)"` as a real inline style on press, so
     it is not an animation and not a transition and neither reset above
     touches it. `clear` already neutralises it further up; focused and vivid
     still scaled by 1.5% under `reduce`. Instantaneous, so not an SC failure,
     but "the OS always wins" has to mean all of it. */
  :root[data-presentation] *:active,
  [data-presentation] *:active {
    transform: none !important;
  }
}

/* OS TEXT SIZE IS NEVER TAKEN AWAY.
 * Nothing in this file sets a font-size on :root or html, and no register's
 * scale is ever BELOW the base — focused is the base, vivid and clear only add.
 * So a member who has raised their text size, or zoomed the page, keeps every
 * bit of it in all three registers; the most any register can do is make it
 * larger still. Same for prefers-color-scheme: `color-scheme: dark` declares
 * what this page supports rather than overriding what the OS asked for. */

/* =============================================================================
 * 9b. Marketplace product covers — the box must fit the artwork
 * -----------------------------------------------------------------------------
 * REPORTED AS: "some of the cover images are super zoomed in on the testing
 * page". Measured on the Testing focus tab at 1440px: the cover box was
 * 737 x 126 (aspect 5.85) holding a 720 x 320 (aspect 2.25) image at
 * `background-size: cover`. Cover scales to the WIDER constraint, so the
 * artwork was drawn 737 x 328 and 62% of it was cropped off the top and
 * bottom — the test tube filled the card as one magnified sliver.
 *
 * It is not a Testing-specific bug, it is a one-item bug. The generated grid is
 * `repeat(auto-fit, minmax(200px, 1fr))`, and auto-fit COLLAPSES the empty
 * tracks: with four products the tracks measure 215px and the crop is invisible,
 * with two they are 346px, with one it takes the entire 767px column. Testing is
 * simply the only focus with exactly one product today, so it is where the same
 * defect became visible. Measured across the surface:
 *
 *     Selected (4 up)   215 x 126   1.71   trims the sides
 *     Sleep    (2 up)   346 x 126   2.74   trims top and bottom
 *     Testing  (1 up)   737 x 126   5.85   the reported bug
 *     Detail drawer     411 x 220   1.87   trims the sides
 *
 * Two rules, and deliberately no third.
 *
 * 1. THE COVER KEEPS THE ARTWORK'S ASPECT. Every /art/prod-*.png is authored at
 *    720 x 320 (see tools/build_product_covers.py), so pinning the box to that
 *    ratio makes `cover` a no-op instead of a crop, at every width, on every one
 *    of the four surfaces above — including the two that were quietly trimming
 *    before anyone called it a bug. `height` has to be overridden explicitly:
 *    the generated markup sets `height:126px` (and 220px in the drawer) inline,
 *    and aspect-ratio does not apply to a box whose height is definite.
 *
 * 2. THE GRID STOPS STRETCHING ONE CARD ACROSS THE COLUMN. Correcting the aspect
 *    alone would have left the lone Testing card carrying a 737 x 328 billboard.
 *    auto-fill instead of auto-fit keeps the empty tracks, and a definite cap
 *    stops the surviving tracks absorbing the slack, so a focus with one shows
 *    one normal card and empty space — which reads as a short catalogue rather
 *    than a broken layout.
 *
 * `:has()` rather than an inline-style substring match. The grid is the only
 * element in either app whose child div holds a product cover, both combinators
 * are direct, and it does not break the day the design tool re-emits that style
 * attribute with different whitespace.
 *
 * [data-art] is doubled on the figure selector for the reason given in section 7
 * — kc-boot.js injects `figure[data-art]{...}` at runtime, after this file, and
 * would win an equal-specificity tie on order.
 * ========================================================================== */

/* Two filename families, both listed. The phone renders covers as <img>, not as
   a background, so the rule has to reach them by src: `cover-*` is the current
   set from tools/build_marketplace_covers.py and `prod-*` is the four this
   supersedes, still referenced by m.html's own un-hydrated MOCK. Matching
   `art/` alone would also catch the 66x60 Research Brief thumbnails, which are
   not 2.25:1 and would be squashed. */
figure[data-art^="product-"][data-art],
img[src*="art/cover-"],
img[src*="art/prod-"] {
  height: auto !important;
  aspect-ratio: 720 / 320 !important;
}

/* 240px, not 264px, and the difference is not taste. `auto-fill` decides how
   many tracks fit using the track's MAX sizing function when that is definite,
   not its min — so minmax(196px, 264px) in the 767px column fitted two tracks
   (2 x 264 + 16 = 544) and left 223px of dead space beside a ten-item shelf.
   At 240px three fit exactly (3 x 240 + 32 = 752), and the count still grows
   with the viewport. */
main div:has(> div > figure[data-art^="product-"]) {
  grid-template-columns: repeat(auto-fill, minmax(196px, 240px)) !important;
  justify-content: start !important;
}

/* THE COVERS THEMSELVES ARE NOT RINGED, AND THAT IS A MEASUREMENT, NOT AN
   OMISSION. The obvious next move after 9b is to give each tile a border or an
   inset hairline so it "sits on the page". It was measured before it was
   written. The nine covers used to span 1.22:1 to 2.83:1 against the card they
   sit on — half of them dissolving, half sitting forward — and that spread, not
   the missing edge, was what made the shelf read as unset. Once
   tools/build_marketplace_covers.py put every tile in a luminance band, the
   quietest tile is 1.69:1 and the rest are 2.19-2.39:1 in all three registers,
   which is a boundary you can see without drawing one.

   The ring that would have been added was costed: an inset hairline at
   color-mix(--text 16%, transparent) computes to 1.46-1.59:1 against a tile in
   the band. It is below every threshold in this file and it would have been
   decoration sitting on top of a fix, so it is not here. If the band ever moves
   up toward the card, re-measure before reaching for a ring. */

/* =============================================================================
 * 9c. Marketplace price chip — the edge the markup already asked for
 * -----------------------------------------------------------------------------
 * The price is the one fact on a product card a member is looking for, and it
 * is the only chip on the card that the markup gives a border of its own:
 *
 *     border: var(--bw-1) solid rgba(138,90,5,.35)
 *
 * That is the light-theme amber ink at 35%, and it is the same class of defect
 * as D5 — a literal authored against a white ground, sitting on a dark one.
 * Composited over the chip's own --amber-100 fill it is rgb(78,56,12): 1.36:1
 * against the fill it is supposed to delimit, and 1.48-1.61:1 against the card
 * behind it. There is no edge. The chip reads as a soft amber smudge.
 *
 * WORST IN `clear`, WHICH IS THE REGISTER IT MATTERS MOST IN. --bw-1 is 2px
 * there, so the accessibility register spends two pixels drawing a boundary
 * that carries no information — while the plain category pills sitting directly
 * under it get a crisp 2px --border-strong. The one element the register cannot
 * make explicit is the one holding the price.
 *
 * ROUTED THE WAY D6 ROUTES A TINT PANEL'S EDGE: to a value derived from the
 * token the fill and the ink already come from, so it rotates with the accent
 * (--amber-500 is --sem-note, which moves off amber under the gold accent) and
 * needs no new token.
 *
 *     color-mix(in srgb, var(--amber-500) 52%, var(--amber-100))
 *              = rgb(147,107,16)
 *     vs the chip fill        3.14:1   (was 1.36)
 *     vs the card, focused    3.50:1   (was 1.52)
 *     vs the card, vivid      3.41:1   (was 1.48)
 *     vs the card, clear      3.72:1   (was 1.61)
 *
 * 52% AND NOT MORE. Every cell clears 3:1 and none of them approaches the
 * label's own 7.65:1, which is the point: an edge that out-shouts the price it
 * frames has traded one hierarchy defect for another. The mix is solved against
 * 3:1, not chosen.
 *
 * BOTH SPELLINGS, per the rule stated above D8: the served file carries the
 * compact form, and collectProps() in kc-support.js re-serialises every style
 * attribute through cssToObj, so the spaced form is what exists in the hydrated
 * DOM. Matching one of them is matching none of them half the time.
 *
 * If color-mix() is ever unavailable the declaration is invalid at
 * computed-value time and the inline literal survives — the chip degrades to
 * exactly what it renders today, not to unset.
 * ========================================================================== */
[style*="rgba(138,90,5,.35)"],
[style*="rgba(138, 90, 5, 0.35)"] {
  border-color: color-mix(in srgb, var(--amber-500) 52%, var(--amber-100)) !important;
}

/* =============================================================================
 * 9d. Marketplace acquire note — a two-column row that `clear` cannot hold
 * -----------------------------------------------------------------------------
 * The detail drawer explains how a listing is paid for in one panel: the price
 * chip, then the sentence that qualifies it ("Sold by Oura, not by us — we take
 * no payment for this and we do not fulfil it."). The markup is a bare
 * `display:flex; align-items:center` with `flex:none` on the chip, so the
 * sentence takes whatever is left and never gets a row of its own.
 *
 * Measured in the drawer at 1440px on the Oura listing, chip label / note size,
 * the column the note is left with, and what it costs the panel:
 *
 *     focused   14px / 12.5px   chip 111px   note 256px   5 lines   panel 119px
 *     vivid     15px / 13.5px   chip 114px   note 238px   6 lines   panel 145px
 *     clear   17.8px / 16.8px   chip 134px   note 215px   8 lines   panel 225px
 *
 * `clear` raises the chip's label and the note at the same time, so the chip
 * grows and the column it leaves behind shrinks — the one register where both
 * halves of a fixed two-column row move the wrong way at once. The panel
 * becomes a 225px ragged ribbon with the chip floating in the vertical middle
 * of eight lines, level with nothing. It is the exact failure the register
 * exists to surface, in the register meant to be the most readable one.
 *
 * `flex-wrap` alone is inert, because a `flex:none` sibling and a `<p>` with no
 * basis never ask for more room than is left. The note is given a basis instead
 * — 24ch, which is `ch` precisely so the threshold is measured in the
 * register's own type — and it drops to its own full-width row the moment the
 * chip leaves it less than that. Measured after:
 *
 *     focused   note 256px   5 lines   panel 119px   unchanged
 *     vivid     note 238px   6 lines   panel 145px   unchanged
 *     clear     note 361px   5 lines   panel 191px   note takes its own row
 *
 * Two of the three registers do not move at all, which is the property being
 * bought: this is a threshold, not a redesign.
 *
 * A `div` selector, not a bare attribute one: `padding:13px 15px` is unique in
 * center.html, but m.html has two spans at `padding:13px 15px 15px` that a
 * substring match would also catch, and they are a different component.
 * ========================================================================== */
div[style*="padding:13px 15px"],
div[style*="padding: 13px 15px"] {
  flex-wrap: wrap !important;
}
div[style*="padding:13px 15px"] > p,
div[style*="padding: 13px 15px"] > p {
  flex: 1 1 24ch !important;
}

/* =============================================================================
 * 9e. Marketplace external CTA — the only action must not look like Close
 * -----------------------------------------------------------------------------
 * A listing we sell ourselves ends the drawer with a filled accent button, "Buy
 * for S$49". A partner listing cannot have one — we take no payment and we do
 * not fulfil it — so its single action is an external link, and the markup
 * gives that link `background:var(--surface)` with a --border-strong edge.
 *
 * `Close`, directly beneath it, is `background:var(--surface)` with a --border
 * edge, which D6b then raises to --border-strong as well. The two are the same
 * control. Measured, the entire difference between the product's only action
 * and dismissing the drawer is 4px of height, --text against --text-2, and one
 * step of font weight. On a partner listing the drawer has no primary at all.
 *
 * The answer is NOT to fill it like the owned buy button. The copy immediately
 * above says we do not sell this and are not quoting a price; a filled accent
 * slab pushing a member off-site to pay someone else would contradict the
 * sentence it sits under, and this is a health-education product. So the link
 * takes the middle step the system already owns — the accent tint ground with
 * the --acc-line edge that D6 established for tint panels — and stops there:
 *
 *                        ground              edge vs card      label
 *     Buy (owned)        --blue-600 fill     n/a               --acc-ink
 *     View at Oura       --blue-050 tint     3.78-4.12:1       --text, 14.97-16.97:1
 *     Close              --surface           3.71-7.36:1       --text-2, 7.79-14.36:1
 *
 * Three steps that a viewer reads by lightness and by hue, not by hue alone.
 * The label stays --text rather than becoming accent-coloured: the text is the
 * partner's name, and a button whose ground, edge and label are all accent is a
 * filled button drawn the long way round.
 *
 * The `height:52px` is what makes the selector exact. center.html has five
 * `target="_blank"` links and ten `height: 52px` boxes; this is the only
 * element that is both. Both spellings again, for the reason 9c gives.
 * ========================================================================== */
a[target="_blank"][style*="height:52px"],
a[target="_blank"][style*="height: 52px"] {
  background: var(--blue-050) !important;
  border-color: var(--acc-line) !important;
}

/* =============================================================================
 * 10. Generated scales — type size, corner radius, border width
 * -----------------------------------------------------------------------------
 * GENERATED by tools/tokenise_type_scale.py — DO NOT HAND-EDIT. Re-run it after
 * the apps are regenerated from the design tool and this block updates with
 * them. It is idempotent.
 *
 * These are the three families that carry REGISTER and that the apps wrote as
 * inline literals, so there was no token to redefine. Tokenising them is what
 * lets `clear` raise the type scale instead of zooming the root: zoom scaled
 * everything, including widths, so a 360px phone laid out as if it were 325px
 * and the factor had to be held to 1.10. Scaling only TYPE means containers
 * keep their full width and the factor can be what the register actually needs.
 *
 * DEFINED ON BARE :root UNCONDITIONALLY. An undefined var() inside a `font:` or
 * `border:` shorthand invalidates the WHOLE declaration at computed-value time
 * — losing the weight, family and colour with it — so there must be no path
 * where one of these is missing.
 *
 * EVERY REGISTER GETS A BLOCK, AND EVERY BLOCK IS WRITTEN TWICE. The bare
 * `[data-presentation="X"]` selector is what a PREVIEW matches: the settings
 * picker and the onboarding step render a live sample of each register inside a
 * page that is currently showing a different one. A declaration ON an element
 * always beats an inherited value, so the bare selector is all that is needed —
 * and without it the picker showed each sample at the page's own scale, which
 * is a lie about the one thing `clear` exists for.
 * ========================================================================== */

:root {
  /* type size — focused reads at the sizes the apps were designed at */
  --fs-8: 8px;
  --fs-9: 9px;
  --fs-9-5: 9.5px;
  --fs-10: 10px;
  --fs-10-5: 10.5px;
  --fs-11: 11px;
  --fs-11-5: 11.5px;
  --fs-12: 12px;
  --fs-12-5: 12.5px;
  --fs-13: 13px;
  --fs-13-5: 13.5px;
  --fs-14: 14px;
  --fs-14-5: 14.5px;
  --fs-15: 15px;
  --fs-15-5: 15.5px;
  --fs-16: 16px;
  --fs-17: 17px;
  --fs-18: 18px;
  --fs-18-5: 18.5px;
  --fs-19: 19px;
  --fs-20: 20px;
  --fs-21: 21px;
  --fs-22: 22px;
  --fs-24: 24px;
  --fs-25: 25px;
  --fs-26: 26px;
  --fs-27: 27px;
  --fs-28: 28px;
  --fs-29: 29px;
  --fs-30: 30px;
  --fs-32: 32px;
  --fs-34: 34px;
  --fs-38: 38px;
  --fs-40: 40px;
  --fs-54: 54px;
  --fs-56: 56px;
  --fs-58: 58px;
  /* corner radius — focused halves the panel ladder, vivid rounds it, clear squares it */
  --r-3: 3px;
  --r-6: 6px;
  --r-8: 8px;
  --r-9: 9px;
  --r-10: 10px;
  --r-11: 11px;
  --r-12: 12px;
  --r-13: 13px;
  --r-14: 14px;
  --r-15: 15px;
  --r-16: 16px;
  --r-17: 17px;
  --r-18: 18px;
  --r-20: 20px;
  --r-22: 22px;
  --r-24: 24px;
  --r-999: 999px;
  /* border width — only clear moves, and only by a pixel */
  --bw-1: 1px;
  --bw-1-5: 1.5px;
  --bw-2: 2px;
  --bw-4: 4px;
}

:root[data-presentation="focused"],
[data-presentation="focused"] {
  /* --fs-* */
  --fs-8: 8px;
  --fs-9: 9px;
  --fs-9-5: 9.5px;
  --fs-10: 10px;
  --fs-10-5: 10.5px;
  --fs-11: 11px;
  --fs-11-5: 11.5px;
  --fs-12: 12px;
  --fs-12-5: 12.5px;
  --fs-13: 13px;
  --fs-13-5: 13.5px;
  --fs-14: 14px;
  --fs-14-5: 14.5px;
  --fs-15: 15px;
  --fs-15-5: 15.5px;
  --fs-16: 16px;
  --fs-17: 17px;
  --fs-18: 18px;
  --fs-18-5: 18.5px;
  --fs-19: 19px;
  --fs-20: 20px;
  --fs-21: 21px;
  --fs-22: 22px;
  --fs-24: 24px;
  --fs-25: 25px;
  --fs-26: 26px;
  --fs-27: 27px;
  --fs-28: 28px;
  --fs-29: 29px;
  --fs-30: 30px;
  --fs-32: 32px;
  --fs-34: 34px;
  --fs-38: 38px;
  --fs-40: 40px;
  --fs-54: 54px;
  --fs-56: 56px;
  --fs-58: 58px;
  /* --r-* */
  --r-3: 3px;
  --r-6: 4px;
  --r-8: 5px;
  --r-9: 5px;
  --r-10: 6px;
  --r-11: 6px;
  --r-12: 7px;
  --r-13: 7px;
  --r-14: 8px;
  --r-15: 8px;
  --r-16: 8px;
  --r-17: 8px;
  --r-18: 9px;
  --r-20: 10px;
  --r-22: 11px;
  --r-24: 12px;
  --r-999: 999px;
  /* --bw-* */
  --bw-1: 1px;
  --bw-1-5: 1.5px;
  --bw-2: 2px;
  --bw-4: 4px;
}

:root[data-presentation="vivid"],
[data-presentation="vivid"] {
  /* --fs-* */
  --fs-8: 12px;
  --fs-9: 12.2px;
  --fs-9-5: 12.4px;
  --fs-10: 12.5px;
  --fs-10-5: 12.6px;
  --fs-11: 12.8px;
  --fs-11-5: 12.9px;
  --fs-12: 13px;
  --fs-12-5: 13.5px;
  --fs-13: 14px;
  --fs-13-5: 14.5px;
  --fs-14: 15px;
  --fs-14-5: 15.5px;
  --fs-15: 16px;
  --fs-15-5: 16.6px;
  --fs-16: 17.2px;
  --fs-17: 18.4px;
  --fs-18: 19.6px;
  --fs-18-5: 20.2px;
  --fs-19: 20.8px;
  --fs-20: 22px;
  --fs-21: 23.2px;
  --fs-22: 24.5px;
  --fs-24: 27px;
  --fs-25: 28.2px;
  --fs-26: 29.5px;
  --fs-27: 30.8px;
  --fs-28: 32px;
  --fs-29: 33.1px;
  --fs-30: 34.3px;
  --fs-32: 36.6px;
  --fs-34: 38.9px;
  --fs-38: 43.4px;
  --fs-40: 45.7px;
  --fs-54: 61.7px;
  --fs-56: 64px;
  --fs-58: 64px;
  /* --r-* */
  --r-3: 6px;
  --r-6: 10px;
  --r-8: 12px;
  --r-9: 13px;
  --r-10: 14px;
  --r-11: 15px;
  --r-12: 16px;
  --r-13: 17px;
  --r-14: 18px;
  --r-15: 19px;
  --r-16: 20px;
  --r-17: 21px;
  --r-18: 22px;
  --r-20: 24px;
  --r-22: 26px;
  --r-24: 28px;
  --r-999: 999px;
  /* --bw-* */
  --bw-1: 1px;
  --bw-1-5: 1.5px;
  --bw-2: 2px;
  --bw-4: 4px;
}

:root[data-presentation="clear"],
[data-presentation="clear"] {
  /* --fs-* */
  --fs-8: 16.5px;
  --fs-9: 16.5px;
  --fs-9-5: 16.6px;
  --fs-10: 16.6px;
  --fs-10-5: 16.6px;
  --fs-11: 16.7px;
  --fs-11-5: 16.7px;
  --fs-12: 16.7px;
  --fs-12-5: 16.8px;
  --fs-13: 16.8px;
  --fs-13-5: 17.2px;
  --fs-14: 17.8px;
  --fs-14-5: 18.4px;
  --fs-15: 19px;
  --fs-15-5: 19.6px;
  --fs-16: 20.2px;
  --fs-17: 21.4px;
  --fs-18: 22.6px;
  --fs-18-5: 23.2px;
  --fs-19: 23.8px;
  --fs-20: 25px;
  --fs-21: 26px;
  --fs-22: 27px;
  --fs-24: 29px;
  --fs-25: 30px;
  --fs-26: 31px;
  --fs-27: 32px;
  --fs-28: 33px;
  --fs-29: 34px;
  --fs-30: 35px;
  --fs-32: 37px;
  --fs-34: 39px;
  --fs-38: 43px;
  --fs-40: 45px;
  --fs-54: 59px;
  --fs-56: 61px;
  --fs-58: 63px;
  /* --r-* */
  --r-3: 4px;
  --r-6: 4px;
  --r-8: 4px;
  --r-9: 8px;
  --r-10: 8px;
  --r-11: 8px;
  --r-12: 8px;
  --r-13: 8px;
  --r-14: 12px;
  --r-15: 12px;
  --r-16: 12px;
  --r-17: 12px;
  --r-18: 12px;
  --r-20: 12px;
  --r-22: 12px;
  --r-24: 12px;
  --r-999: 14px;
  /* --bw-* */
  --bw-1: 2px;
  --bw-1-5: 2px;
  --bw-2: 3px;
  --bw-4: 5px;
}
