/* ============================================================
   DMITRY MOTION KIT (K2, redesign-2026-09). Site-wide interaction
   language, applied by selector so no page markup needs to change.
   Ported from the SSF redesign 5.5 motion kit (ssf_motion_kit.liquid,
   ssf_cards_css.liquid), recoloured to navy / crimson / white and
   adapted to this site's own class names (see REQUIREMENTS.md,
   section E and F).

   Everything here is compositor only at rest: transform and opacity.
   No loop ever animates box-shadow, filter, width or top/left. Every
   loop pauses off-screen and in a hidden tab (assets/js/motion-kit.js,
   DMK.live). Reduced motion resolves every effect to its finished
   state through --mkx-m = 0. Nothing in this file hides content on
   its own: every hidden start state is keyed to a class the runtime
   adds, so a page with no JS renders exactly as it does today, only
   without the shine or the living background.

   Class prefix: mkx- (Dmitry Motion Kit eXtension), chosen on purpose
   to never collide with fable.css's own small .mk-draw / .mk-heart /
   .mk-reset SVG draw-in helpers (scoped to .secmark illustrations).

   Token contract (shared with every other build in this pass; K1
   defines the real values in fable.css :root, this file only ever
   reads them, always with the literal fallback so it still works if
   K1 has not run yet):
     --navy-ground   (#0C1833)  the one dark ground
     --crimson-vivid (#E23A46)  lines, fills, large accent type on navy
     --crimson-glow  (#FF6B75)  small crimson text on navy
     --grad-shine-dark / --grad-shine-light   accent word gradients
     --ink-on-dark   (#F4F7FB)  headings on navy
   No em or en dashes anywhere in this file, including comments.
   ============================================================ */

/* ---------- 1. tokens + the one reduced-motion multiplier ---------- */
:root{
  --mkx-m:1;
  --mkx-ease-in:cubic-bezier(.16,1,.3,1);
  --mkx-ease-soft:cubic-bezier(.4,0,.15,1);
  --mkx-ease-emph:cubic-bezier(.05,.7,.1,1);
  --mkx-spring:cubic-bezier(.2,.9,.3,1.01);

  --mkx-navy:var(--navy-ground,#0C1833);
  --mkx-crimson:var(--crimson-vivid,#E23A46);
  --mkx-glow:var(--crimson-glow,#FF6B75);
  --mkx-shine-dark:var(--grad-shine-dark,linear-gradient(100deg,#E23A46 0%,#FF6B75 30%,#FF8F6B 50%,#FF6B75 70%,#E23A46 100%));
  --mkx-shine-light:var(--grad-shine-light,linear-gradient(100deg,#8E1620 0%,#C0343C 45%,#E23A46 55%,#8E1620 100%));
  --mkx-ink-dark:var(--ink-on-dark,#F4F7FB);

  /* Halo tiers: a crimson glow that reads on navy AND on white, never a flooded fill.
     Round 2 (HOVER PARITY pass, recoloured SSF round 2 standard): thicker ring, wider
     glow spread, so the ring reads as vivid at a glance, matching the SSF bar. */
  --mkx-halo:0 0 0 1.5px rgb(226 58 70 / .55),0 22px 48px -18px rgb(12 24 51 / .6),0 0 46px -4px rgb(226 58 70 / .62);
  --mkx-halo-soft:0 0 0 1.5px rgb(226 58 70 / .40),0 16px 36px -20px rgb(12 24 51 / .42),0 0 34px -8px rgb(226 58 70 / .46);
  --mkx-halo-white:0 0 0 1.5px rgb(226 58 70 / .45),0 20px 42px -22px rgb(12 24 51 / .32),0 0 38px -7px rgb(226 58 70 / .42);
}
@media (prefers-reduced-motion:reduce){:root{--mkx-m:0}}

/* ---------- 2. off-screen / hidden-tab pause (the runtime adds this class) ---------- */
.mkx-off,.mkx-off *,.mkx-off::before,.mkx-off::after,.mkx-off *::before,.mkx-off *::after{animation-play-state:paused !important}

/* ================================================================
   3. HOVER ON EVERYTHING: generic underline + arrow for text links
   ================================================================ */
.mkx-u{position:relative}
.mkx-u__line{position:absolute;left:0;right:0;bottom:-.22em;height:1.5px;border-radius:1px;background:currentColor;opacity:.85;
  pointer-events:none;transform:scaleX(0);transform-origin:100% 50%;transition:transform calc(280ms * var(--mkx-m)) var(--mkx-ease-in)}
.mkx-u:hover .mkx-u__line,.mkx-u:focus-visible .mkx-u__line,.mkx-u.mkx-hot .mkx-u__line{transform:scaleX(1);transform-origin:0 50%;transition-duration:calc(210ms * var(--mkx-m))}
.mkx-u__arr{display:inline-block;transition:translate calc(280ms * var(--mkx-m)) var(--mkx-ease-in)}
.mkx-u:hover .mkx-u__arr,.mkx-u:focus-visible .mkx-u__arr{translate:4px 0}
@media (prefers-reduced-motion:reduce){.mkx-u:hover .mkx-u__line,.mkx-u:focus-visible .mkx-u__line{transform:scaleX(1)}.mkx-u:hover .mkx-u__arr,.mkx-u:focus-visible .mkx-u__arr{translate:0}}

/* generic focus-visible ring for anything the kit could not classify further */
.mkx-focusable:focus-visible{outline:none;box-shadow:var(--mkx-halo-soft);border-radius:var(--r-sm,6px)}

/* ================================================================
   4. SHINE HEADINGS (REQUIREMENTS section E1 and J3). Steady vivid
   gradient on every accent word (an <em> inside a recognised heading),
   always on; the specular sweep is the rare, ephemeral part (JS,
   section 9 below). Headings without an <em> get no gradient, on
   purpose, but still get their own sweep (J3: "a shine animation
   throughout the text" is not conditional on having an accent word).
   ================================================================ */
:where(.mkx-shine){background-image:linear-gradient(transparent,transparent)}
.mkx-shine--dark :is(em,.mkx-shine__em),
.mkx-shine--light :is(em,.mkx-shine__em){
  font-style:normal;-webkit-box-decoration-break:clone;box-decoration-break:clone;
  padding-right:.06em;margin-right:-.06em;
}
.mkx-shine--dark :is(em,.mkx-shine__em){
  background-image:var(--mkx-shine-dark) !important;background-size:220% 100%;
  -webkit-background-clip:text !important;background-clip:text !important;-webkit-text-fill-color:transparent !important;
  color:var(--mkx-glow) !important;
}
.mkx-shine--light :is(em,.mkx-shine__em){
  background-image:var(--mkx-shine-light) !important;background-size:220% 100%;
  -webkit-background-clip:text !important;background-clip:text !important;-webkit-text-fill-color:transparent !important;
  color:var(--mkx-crimson) !important;
}
/* the ephemeral lens that carries the specular sweep across the WHOLE
   heading (J3 fix, 2026-09-30 night: the JS now marks the entire cloned
   copy .mkx-lit, not only the accent word inside it, so the band of
   light visibly crosses every word as it travels, not just a flash on
   one word). On a navy ground the lit copy is bright white, a light
   passing over dark; on a light/paper ground it is a soft crimson glint
   (--mkx-glow) instead of the near-white peach this used to be, so the
   sweep reads as light on both grounds rather than washing to white
   twice.

   J3 RENDER fix (2026-09-30, verification pass): the mask's "visible"
   stops were #000 (black). This element is promoted to its own GPU
   compositor layer the instant its WAAPI transform animation starts
   (every sweep), and on that path Chromium's mask-image resolves a
   plain black stop to ZERO LUMINANCE, i.e. fully masked OUT, not "fully
   opaque": with both stops evaluating to 0 (transparent is alpha 0,
   #000 is luminance 0) the entire window rendered invisible even
   though every computed style (visibility, transform, mask geometry,
   text color) looked correct in devtools. Proven by disabling either
   mask declaration or swapping the stop to white, both of which make
   the band appear; the static, non-animated masks elsewhere in
   fable.css (marquees, image fades) are not compositor-promoted the
   same way and keep #000 safely, so only this animated mask changes.
   #fff has full luminance, so it reads as fully opaque as intended,
   restoring the actual visible band. This was why the shine sweep
   never appeared for any non-hero heading despite the JS completing
   the animation every time (Dev: "when i show up it should have like
   a shine animation throughout the text" was still failing silently). */
.mkx-shine-host{position:relative}
.mkx-shine-win{position:absolute;left:0;top:0;height:0;overflow:hidden;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:3;visibility:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent 0%,#fff 42%,#fff 58%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0%,#fff 42%,#fff 58%,transparent 100%)}
.mkx-shine-win.is-on{visibility:visible}
.mkx-shine-copy{position:absolute;left:0;top:0;display:block;box-sizing:border-box;transform-origin:0 0}
.mkx-shine-copy,.mkx-shine-copy *{color:transparent !important;-webkit-text-fill-color:transparent !important;background:none !important;
  text-shadow:none !important;animation:none !important;transition:none !important;box-shadow:none !important;
  border-color:transparent !important;opacity:1 !important}
.mkx-shine-copy.mkx-lit,.mkx-shine-copy.mkx-lit *,.mkx-shine-copy .mkx-lit,.mkx-shine-copy .mkx-lit *{
  -webkit-text-fill-color:#FFFFFF !important;color:#FFFFFF !important}
.mkx-shine-win.mkx-shine-win--light .mkx-shine-copy.mkx-lit,.mkx-shine-win.mkx-shine-win--light .mkx-shine-copy.mkx-lit *,
.mkx-shine-win.mkx-shine-win--light .mkx-shine-copy .mkx-lit,.mkx-shine-win.mkx-shine-win--light .mkx-shine-copy .mkx-lit *{
  -webkit-text-fill-color:var(--mkx-glow,#FF6B75) !important;color:var(--mkx-glow,#FF6B75) !important}
.mkx-shine-win{pointer-events:none}
/* overflow fix: .mkx-shine-win is an absolutely positioned child of the
   heading, translated past the end of the text on purpose (so its already
   mask-faded-to-transparent tail glides off clean instead of popping);
   nothing clipped that travel, so on a heading near the page or column
   edge the whole document's scrollable width grew by 38-96px for as long
   as the sweep played (REQUIREMENTS D6, measured reproducible "bugged
   out" layout). :has() scopes the clip to exactly the moment a sweep is
   actually in the DOM (sweep() appends it for about a second and removes
   it on finish/cancel), so a heading's own overflow is never restricted
   the rest of the time. */
.js-reveal-title:has(>.mkx-shine-win),.ihero__t:has(>.mkx-shine-win),.nl__title:has(>.mkx-shine-win),
main h1:has(>.mkx-shine-win),main h2:has(>.mkx-shine-win){overflow:clip}

/* ================================================================
   5. BUTTONS (REQUIREMENTS section E2). Every .btn, nav CTA, submit
   button and the hero quiet links get: a band of light that crosses
   after a hover dwell, a soft crimson glow on hover/focus, a press,
   and (primary CTAs, fine pointers only) a gentle magnetic pull.
   ================================================================ */
.mkx-btn{-webkit-tap-highlight-color:transparent;position:relative;isolation:isolate}
/* press: an INDIVIDUAL property, so it composes with a button's own
   transform (the .btn hover lift is transform:translateY(-2px)) */
.mkx-btn:active:not(:disabled){scale:.97;transition:scale calc(90ms * var(--mkx-m)) ease-out}
@media (prefers-reduced-motion:reduce){.mkx-btn:active:not(:disabled){scale:1}}

/* HOVER PARITY (buttons): a filled button's gradient shifts brighter, crimson into
   coral, with its own soft glow, painted on a layer BEHIND the label whose OPACITY
   animates (never the button's own background, never a looping box-shadow). Ghost
   and secondary buttons (.mkx-btn--ink: the alpha/luminance test already run in
   motion-kit.js) get a crimson-tinted glass fill and their border glows instead. */
.mkx-btn:not(.mkx-btn--ink)::after{content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:0;
  background:linear-gradient(135deg,var(--mkx-crimson) 0%,var(--mkx-glow) 100%);
  box-shadow:0 0 0 1px rgb(255 255 255 / .12) inset,0 0 30px -4px rgb(255 107 117 / .7);
  transition:opacity calc(360ms * var(--mkx-m)) ease}
@media (hover:hover) and (pointer:fine){.mkx-btn:not(.mkx-btn--ink):hover:not(:disabled)::after{opacity:1}}
.mkx-btn:not(.mkx-btn--ink):focus-visible::after{opacity:1}
.mkx-btn--ink{transition:background-color calc(320ms * var(--mkx-m)) ease,border-color calc(320ms * var(--mkx-m)) ease}
@media (hover:hover) and (pointer:fine){
  .mkx-btn--ink:hover:not(:disabled){background-color:rgb(226 58 70 / .14) !important;border-color:var(--mkx-crimson) !important;
    -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
}
.mkx-btn--ink:focus-visible{background-color:rgb(226 58 70 / .14) !important;border-color:var(--mkx-crimson) !important;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
@media (prefers-reduced-motion:reduce){.mkx-btn:not(.mkx-btn--ink)::after{transition:none}.mkx-btn--ink{transition:none}}

.mkx-glint-clip{position:absolute;inset:0;border-radius:inherit;overflow:hidden;pointer-events:none;z-index:2}
.mkx-glint{position:absolute;top:-20%;bottom:-20%;left:0;width:42%;opacity:0;
  background:linear-gradient(100deg,rgba(255,255,255,0) 0%,rgba(255,255,255,.12) 24%,rgba(255,255,255,.62) 50%,rgba(255,255,255,.12) 76%,rgba(255,255,255,0) 100%);
  transform:translateX(-130%) skewX(-16deg)}
.mkx-btn--ink .mkx-glint{background:linear-gradient(100deg,rgba(226,58,70,0) 0%,rgba(255,107,117,.22) 26%,rgba(226,58,70,.48) 50%,rgba(255,107,117,.22) 74%,rgba(226,58,70,0) 100%)}
@media (prefers-reduced-motion:no-preference){.mkx-glint-go .mkx-glint{animation:mkx-glint 1100ms var(--mkx-ease-in) both}}
@keyframes mkx-glint{0%{transform:translateX(-130%) skewX(-16deg);opacity:0}16%{opacity:1}100%{transform:translateX(340%) skewX(-16deg);opacity:0}}

/* the glow: instant, a steady state on hover and keyboard focus, not a one-shot cue */
@media (hover:hover){
  html .mkx-btn:hover:not(:disabled){box-shadow:var(--mkx-halo)}
}
html .mkx-btn:focus-visible{box-shadow:var(--mkx-halo);outline:none}
/* input[type=submit] cannot hold a clipped child span: the band rides the background instead */
.mkx-btn--bg{background-image:linear-gradient(100deg,rgba(255,255,255,0) 30%,rgba(255,255,255,.55) 50%,rgba(255,255,255,0) 70%) !important;
  background-repeat:no-repeat;background-size:240% 100%,100% 100%;background-position:160% 0,0 0}
@media (prefers-reduced-motion:no-preference){.mkx-btn--bg.mkx-glint-go{animation:mkx-bg-sweep 1100ms var(--mkx-ease-in) both}}
@keyframes mkx-bg-sweep{from{background-position:160% 0,0 0}to{background-position:-60% 0,0 0}}

/* magnetic pull: primary CTAs only, fine pointers only, an individual translate
   so it stacks with the button's own hover lift instead of replacing it */
@media (hover:hover) and (pointer:fine){
  .mkx-magnet{transition:translate calc(260ms * var(--mkx-m)) var(--mkx-ease-emph)}
}
@media (prefers-reduced-motion:reduce){.mkx-magnet{translate:0 0 !important}}

/* ================================================================
   6. THE BOX RULE (REQUIREMENTS P3: "when i hover over it, i dont want to
   see that line, just highlight the boundaries of that box thats all,
   make it minimalist"). Every box (card, panel, tile, door, slide, quote
   card, article card, stat card, FAQ item, a list row drawn as a box, a
   photo frame) answers hover and keyboard focus with ONE thing: a 1.5px
   crimson outline on its own edge. Nothing else: no lift, scale, tilt,
   glow, coloured shadow, wash, gradient, top or side bar, border beam,
   cursor light, shine sweep or image zoom. Buttons are not boxes and keep
   their M2 glow (section 5).

   How a page applies it: put class "box" (or the attribute data-box) on
   the element that LOOKS like the box (the one with the border or the
   background). The kit classes and the legacy page classes in the list
   below already carry it. data-box="off" opts a listed element out. A box
   that wraps a link, or sits inside one, lights up when the link is
   hovered or focused.

   Why an outline and not a ::before/::after layer: a box that already uses
   either pseudo-element for its own art would collide, and an outline
   outside the border edge can never be covered by a positioned child
   (a full-bleed photo inside a frame), which an inset shadow or an inset
   outline can. It costs no layout (outlines take no space), follows the
   border-radius, and leaves the box's own resting shadow alone.
   Width: --mkx-ring-w is 1.5px. Chrome draws an outline in whole CSS pixels, so
   there it is a crisp 1px line (2 device pixels on a 2x laptop); Firefox and
   Safari draw the full 1.5px. Set the token to 2px to make it bolder everywhere.
   The colour is #E23A46 on light grounds and #FF6B75 on navy: the section
   classes below give a no-JS default, motion-kit.js writes data-ring from
   the box's own text colour the first time a pointer or the keyboard
   reaches it (a light card inside a navy section still gets crimson).
   The transition lives only on the hovered and focused state, so it never
   replaces a box's own arrival transition (data-rise, reveal-sec).
   ================================================================ */
:root{--mkx-ring:#E23A46;--mkx-ring-w:1.5px}
:is(.sec-dark,.on-dark,.phero--dark,.glass-1,.glass-2,.glass-3,.k4-sec--dark,.footer,.xi){--mkx-ring:#FF6B75}
.sec-crimson{--mkx-ring:#F4F7FB}
[data-ring="light"]{--mkx-ring:#E23A46}
[data-ring="dark"]{--mkx-ring:#FF6B75}
[data-ring="paper"]{--mkx-ring:#F4F7FB}

:is(
  .box,[data-box],
  .k4-card,.k4-explain__panel,.il-stage,
  .rb-card,.navcard,.vidcard,.medcard,.presscard,.nlfan__card,.pgp-share__card,.voice--card,
  .pressrow,.prow,.pub-row,.issuerow,.engage__row,.speak__li,.qa__btn,
  .figc,.imgframe,.consult__fig,.mssn-figsec__fig,.story__photolink,.xi__card,
  .hx-story__photo,.pgp-vid__frame,.pgp-prow,.pgp-vcard,.pgp-qa__btn,.pgp-site,.rt-grp,.ms-panel,.ms-tri,.spk-fr,.spk-art,.stg,.rx__next,.hx-stage,.pgp-stage,.pc,.tl__row,.slide,.dl,.irefs li,.rf,.ra-row,.lcard,.ro-panel,.ro-list li,.bd-ph,.ld-row,.pa-card,.mc-card,.mc-ask
):not([data-box="off"]){outline:var(--mkx-ring-w) solid transparent;outline-offset:0}

@media (hover:hover) and (pointer:fine){
  :is(
  .box,[data-box],
  .k4-card,.k4-explain__panel,.il-stage,
  .rb-card,.navcard,.vidcard,.medcard,.presscard,.nlfan__card,.pgp-share__card,.voice--card,
  .pressrow,.prow,.pub-row,.issuerow,.engage__row,.speak__li,.qa__btn,
  .figc,.imgframe,.consult__fig,.mssn-figsec__fig,.story__photolink,.xi__card,
  .hx-story__photo,.pgp-vid__frame,.pgp-prow,.pgp-vcard,.pgp-qa__btn,.pgp-site,.rt-grp,.ms-panel,.ms-tri,.spk-fr,.spk-art,.stg,.rx__next,.hx-stage,.pgp-stage,.pc,.tl__row,.slide,.dl,.irefs li,.rf,.ra-row,.lcard,.ro-panel,.ro-list li,.bd-ph,.ld-row,.pa-card,.mc-card,.mc-ask
  ):not([data-box="off"]):hover{outline-color:var(--mkx-ring);transition:outline-color calc(220ms * var(--mkx-m)) ease}
  :is(a,button,[role="link"]):not(.box,[data-box]):hover :is(.box,[data-box]):not([data-box="off"]){
    outline-color:var(--mkx-ring);transition:outline-color calc(220ms * var(--mkx-m)) ease}
}
:is(
  .box,[data-box],
  .k4-card,.k4-explain__panel,.il-stage,
  .rb-card,.navcard,.vidcard,.medcard,.presscard,.nlfan__card,.pgp-share__card,.voice--card,
  .pressrow,.prow,.pub-row,.issuerow,.engage__row,.speak__li,.qa__btn,
  .figc,.imgframe,.consult__fig,.mssn-figsec__fig,.story__photolink,.xi__card,
  .hx-story__photo,.pgp-vid__frame,.pgp-prow,.pgp-vcard,.pgp-qa__btn,.pgp-site,.rt-grp,.ms-panel,.ms-tri,.spk-fr,.spk-art,.stg,.rx__next,.hx-stage,.pgp-stage,.pc,.tl__row,.slide,.dl,.irefs li,.rf,.ra-row,.lcard,.ro-panel,.ro-list li,.bd-ph,.ld-row,.pa-card,.mc-card,.mc-ask
):not([data-box="off"]):is(:focus-visible,:has(:focus-visible)){
  /* !important on purpose: keyboard focus must look exactly like hover, so a page's own offset focus ring cannot win */
  outline:var(--mkx-ring-w) solid var(--mkx-ring) !important;outline-offset:0 !important;transition:outline-color calc(220ms * var(--mkx-m)) ease}
:is(a,button,[role="link"]):not(.box,[data-box]):focus-visible :is(.box,[data-box]):not([data-box="off"]){
  outline:var(--mkx-ring-w) solid var(--mkx-ring) !important;outline-offset:0 !important;transition:outline-color calc(220ms * var(--mkx-m)) ease}

/* the hero quiet links (index hero: Speaking & Media / Patient Education) had
   no visual state at all before this kit; a small filled tick that draws in
   plus the standard underline draw. Links, not boxes: they keep this. */
.hero-quiet{position:relative;display:inline-flex;align-items:center;gap:.6rem;color:inherit;text-decoration:none}
.hero-quiet__tick{position:relative;width:9px;height:9px;border-radius:50%;flex:none;
  background:var(--mkx-glow);box-shadow:0 0 0 3px rgb(255 107 117 / .18);
  transition:scale calc(300ms * var(--mkx-m)) var(--mkx-ease-in),box-shadow calc(300ms * var(--mkx-m)) ease}
@media (hover:hover) and (pointer:fine){.hero-quiet:hover .hero-quiet__tick{scale:1.35;box-shadow:0 0 0 6px rgb(255 107 117 / .24)}}
.hero-quiet:focus-visible .hero-quiet__tick{scale:1.35;box-shadow:0 0 0 6px rgb(255 107 117 / .24)}


/* ================================================================
   7. INNER ANSWERS (R10 restore, REQUIREMENTS Q8). The box answers with its
   border ring and nothing else (section 6); what is INSIDE a box may move.
   motion-kit.js tags every box .mkx-box, the card families .mkx-card and the
   list rows .mkx-row, then these rules give the parts their R8 answers back:
   the row's content nudges, the FAQ question recolours, the small icon pops,
   the "go" arrow nudges, a card title turns crimson and draws its underline,
   a photo inside a clipping frame zooms, a publication row shows its "Read" pill.
   Never on the box itself: no lift, no wash or fill, no glow, no tilt, no top
   line. Transform-free properties only (translate, scale, rotate, opacity,
   colour), all gated to (hover:hover) and (pointer:fine) with :focus-within
   twins, all resolved to 0 under prefers-reduced-motion.
   ================================================================ */

/* rows: the row's own content slides 4px; the row itself stays put inside its ring */
.mkx-row > *{transition:translate calc(320ms * var(--mkx-m)) var(--mkx-ease-in)}
@media (hover:hover) and (pointer:fine){
  .mkx-row:hover > *{translate:4px 0}
}
.mkx-row:focus-within > *{translate:4px 0}
@media (prefers-reduced-motion:reduce){.mkx-row:hover > *,.mkx-row:focus-within > *{translate:0 0}}

/* FAQ questions recolour (the row's ground class, set by darkGround() in JS, picks crimson or glow) */
.mkx-row .qa__q{transition:color calc(280ms * var(--mkx-m)) ease}
@media (hover:hover) and (pointer:fine){
  .mkx-row:not(.mkx-row--dark):hover .qa__q{color:var(--mkx-crimson)}
  .mkx-row--dark:hover .qa__q{color:var(--mkx-glow)}
}
.mkx-row:not(.mkx-row--dark):focus-visible .qa__q{color:var(--mkx-crimson)}
.mkx-row--dark:focus-visible .qa__q{color:var(--mkx-glow)}

/* small icons inside a card or row pop and turn a little (a glyph, never an icon-in-disc used as art) */
:where(.mkx-row,.mkx-card) :where([class*="ico"]){transition:scale calc(360ms * var(--mkx-m)) var(--mkx-ease-in),rotate calc(360ms * var(--mkx-m)) var(--mkx-ease-in)}
@media (hover:hover) and (pointer:fine){
  :is(.mkx-row,.mkx-card):hover :where([class*="ico"]){scale:calc(1 + .1 * var(--mkx-m));rotate:calc(-6deg * var(--mkx-m))}
}
:is(.mkx-row,.mkx-card):focus-within :where([class*="ico"]){scale:calc(1 + .1 * var(--mkx-m));rotate:calc(-6deg * var(--mkx-m))}

/* generic arrow nudge: a "go" arrow (the site's __go / -go naming) slides 5px inside its card, row or document */
:where(.mkx-card,.mkx-row,.mkx-doc) :where([class$="__go"],[class*="__go "],[class*="-go"]){
  transition:translate calc(320ms * var(--mkx-m)) var(--mkx-ease-in)}
@media (hover:hover) and (pointer:fine){
  :is(.mkx-card,.mkx-row,.mkx-doc):hover :where([class$="__go"],[class*="__go "],[class*="-go"]){translate:5px 0}
}
:is(.mkx-card,.mkx-row,.mkx-doc):focus-within :where([class$="__go"],[class*="__go "],[class*="-go"]){translate:5px 0}
@media (prefers-reduced-motion:reduce){
  :is(.mkx-card,.mkx-row,.mkx-doc):hover :where([class$="__go"],[class*="__go "],[class*="-go"]){translate:0 0}
}

/* card titles are plain spans on this site (navcard__t, vidcard__title, medcard__title, nlfan__t, rb-eyebrow,
   voice__q), never heading tags: the title turns crimson (coral on navy) and draws its underline (.mkx-u__line) */
:where(.mkx-card) :where(.navcard__t,.vidcard__title,.medcard__title,.nlfan__t,.rb-eyebrow,.voice__q){
  transition:color calc(280ms * var(--mkx-m)) ease}
@media (hover:hover) and (pointer:fine){
  .mkx-card:not(.mkx-card--dark):hover :where(.navcard__t,.vidcard__title,.medcard__title,.nlfan__t,.rb-eyebrow,.voice__q){color:var(--mkx-crimson)}
  .mkx-card--dark:hover :where(.navcard__t,.vidcard__title,.medcard__title,.nlfan__t,.rb-eyebrow,.voice__q){color:var(--mkx-glow)}
}
.mkx-card:not(.mkx-card--dark):focus-within :where(.navcard__t,.vidcard__title,.medcard__title,.nlfan__t,.rb-eyebrow,.voice__q){color:var(--mkx-crimson)}
.mkx-card--dark:focus-within :where(.navcard__t,.vidcard__title,.medcard__title,.nlfan__t,.rb-eyebrow,.voice__q){color:var(--mkx-glow)}
/* the underline under that title draws when its card is hovered or focused, not only when the title is */
@media (hover:hover) and (pointer:fine){
  .mkx-card:hover :where(.navcard__t,.vidcard__title,.medcard__title,.nlfan__t,.rb-eyebrow,.voice__q) .mkx-u__line{transform:scaleX(1);transform-origin:0 50%;transition-duration:calc(210ms * var(--mkx-m))}
}
.mkx-card:focus-within :where(.navcard__t,.vidcard__title,.medcard__title,.nlfan__t,.rb-eyebrow,.voice__q) .mkx-u__line{transform:scaleX(1);transform-origin:0 50%}
.mkx-imgframe.mkx-frame-hot img,.mkx-imgframe.mkx-frame-hot picture{scale:1.05}

/* PHOTO ZOOM INSIDE ITS FRAME. A photo that sits in a clipping frame (the box or a wrapper with overflow hidden)
   carries data-zoom (motion-kit.js adds it; a page can add it by hand, or data-zoom="off" to opt out). Hover or
   keyboard focus on its box, or on the frame itself, zooms it 5 percent. It uses the individual scale property, so
   it composes with any transform a page already gives the image. The frame never grows or moves. */
.mkx-imgframe{overflow:hidden;position:relative}
[data-zoom]:not([data-zoom="off"]){transition:scale calc(800ms * var(--mkx-m)) var(--mkx-ease-in)}
@media (hover:hover) and (pointer:fine){
  .mkx-box:hover [data-zoom]:not([data-zoom="off"]),.mkx-imgframe:hover [data-zoom]:not([data-zoom="off"]),.mkx-imgframe:hover > img,.mkx-imgframe:hover picture{scale:1.05}
}
.mkx-box:is(:focus-visible,:focus-within) [data-zoom]:not([data-zoom="off"]),.mkx-imgframe:focus-within [data-zoom]:not([data-zoom="off"]),.mkx-imgframe:focus-within > img{scale:1.05}
.mkx-imgframe img,.mkx-imgframe picture{transition:scale calc(800ms * var(--mkx-m)) var(--mkx-ease-in)}
@media (prefers-reduced-motion:reduce){.mkx-box:hover [data-zoom],.mkx-imgframe:hover img{scale:1 !important}}

/* DOCUMENTS: a publication row or a newsletter issue row shows a small "Read" pill (or the arrow alone) that
   slides in at its corner. The row does not tilt (box rule); only the pill moves. */
.mkx-doc{position:relative}
.mkx-doc__pill{position:absolute;top:8px;right:8px;z-index:2;display:inline-flex;align-items:center;gap:.3rem;
  padding:.32rem .6rem;border-radius:999px;pointer-events:none;opacity:0;
  font-family:var(--label,inherit);font-size:.68rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:#fff;background:linear-gradient(135deg,var(--mkx-crimson),var(--mkx-glow));
  translate:8px -6px;transition:opacity calc(300ms * var(--mkx-m)) ease,translate calc(340ms * var(--mkx-m)) var(--mkx-ease-in)}
.mkx-doc__pill svg{width:11px;height:11px;flex:none}
@media (hover:hover) and (pointer:fine){.mkx-doc:hover .mkx-doc__pill{opacity:1;translate:0 0}}
.mkx-doc:focus-within .mkx-doc__pill{opacity:1;translate:0 0}
@media (prefers-reduced-motion:reduce){.mkx-doc__pill{transition:opacity calc(200ms * var(--mkx-m)) ease}}

/* ================================================================
   9. SCROLL ENTRANCES + TEXT WALLS (REQUIREMENTS A4). Integrates
   with the site's own .reveal-sec/.is-in system: children of a
   marked grid stagger in once; paragraphs in a marked text block
   rise one at a time; <strong>/<b> get a one-shot highlight sweep;
   the CSS fallback below means nothing can stay hidden if the JS
   observer never fires.
   ================================================================ */
.js .mkx-stagger .mkx-st{opacity:0;transform:translate3d(0,calc(20px * var(--mkx-m)),0)}
.js .mkx-stagger.mkx-in .mkx-st{opacity:1;transform:none;
  transition:opacity calc(650ms * var(--mkx-m)) var(--mkx-ease-in),transform calc(750ms * var(--mkx-m)) var(--mkx-ease-in);
  transition-delay:calc(var(--mkx-i,0) * 65ms * var(--mkx-m))}
/* fallback: a stagger host that never got observed (JS never loaded, or the
   observer missed it) still shows every child, because the base state above
   is scoped to .js and only hides once .mkx-stagger is actually present;
   this rule removes that class if reveal never completed in time */
@media (prefers-reduced-motion:reduce){
  .mkx-stagger .mkx-st{opacity:1;transform:none}
}

.mkx-para{opacity:0;transform:translate3d(0,calc(16px * var(--mkx-m)),0)}
.mkx-para.mkx-in{opacity:1;transform:none;
  transition:opacity calc(600ms * var(--mkx-m)) var(--mkx-ease-in),transform calc(700ms * var(--mkx-m)) var(--mkx-ease-in);
  transition-delay:calc(var(--mkx-i,0) * 90ms * var(--mkx-m))}
@media (prefers-reduced-motion:reduce){.mkx-para{opacity:1;transform:none}}

/* strong / b highlight sweep, first time seen: a crimson wash wipes left to
   right behind the word, once, then leaves the text in its normal weight */
.mkx-strong{position:relative;display:inline}
.mkx-strong__wash{position:absolute;inset:-.05em -.12em;z-index:-1;border-radius:.2em;pointer-events:none;
  background:rgb(226 58 70 / .16);transform:scaleX(0);transform-origin:0 50%}
.mkx-strong--dark .mkx-strong__wash{background:rgb(255 107 117 / .22)}
.mkx-strong.mkx-run .mkx-strong__wash{animation:mkx-strong-wash calc(700ms * var(--mkx-m)) var(--mkx-ease-in) both}
@keyframes mkx-strong-wash{0%{transform:scaleX(0);transform-origin:0 50%}70%{transform:scaleX(1);transform-origin:0 50%}
  70.01%{transform-origin:100% 50%}100%{transform:scaleX(0);transform-origin:100% 50%}}
@media (prefers-reduced-motion:reduce){.mkx-strong__wash{display:none}}

/* a brief landing pulse when a reused count-up (.count, .js-count) actually
   finishes changing, so the number feels like it arrived rather than static */
.mkx-count-land{animation:mkx-count-pulse calc(560ms * var(--mkx-m)) var(--mkx-ease-in) both}
@keyframes mkx-count-pulse{0%{opacity:.35;transform:translateY(2px)}100%{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.mkx-count-land{animation:none}}

/* ================================================================
   10. EXIT OVERLAY (REQUIREMENTS D7). The cards of the fanned stack are
   boxes like any other: .xi__card is in the box list, so the hovered or
   focused card gets the 1.5px ring and nothing else (no rise, no scale,
   no dimming of its neighbours). The one thing kept is the stacking order:
   motion-kit.js marks the hovered or focused card .mkx-xi-hot so its ring
   is never painted under the card next to it.
   ================================================================ */
html.xi-on .xi__panel .xi__stack .xi__card.mkx-xi-hot{z-index:5}
/* inside the card (R10 restore): the lesson label and the title slide, the read time brightens. The card keeps its place. */
html.xi-on .xi__panel .xi__stack .xi__card :is(.xi__card-n,.xi__card-t){transition:translate calc(320ms * var(--mkx-m)) var(--mkx-ease-in)}
html.xi-on .xi__panel .xi__stack .xi__card .xi__card-r{transition:color calc(280ms * var(--mkx-m)) ease}
html.xi-on .xi__panel .xi__stack .xi__card.mkx-xi-hot .xi__card-t{translate:5px 0}
html.xi-on .xi__panel .xi__stack .xi__card.mkx-xi-hot .xi__card-n{translate:3px 0}
html.xi-on .xi__panel .xi__stack .xi__card.mkx-xi-hot .xi__card-r{color:#fff}
@media (prefers-reduced-motion:reduce){html.xi-on .xi__panel .xi__stack .xi__card.mkx-xi-hot :is(.xi__card-t,.xi__card-n){translate:0 0}}

/* ---------- print: painted gradient words print blank on paper, so print in solid ink ---------- */
@media print{
  .mkx-shine--dark :is(em,.mkx-shine__em),.mkx-shine--light :is(em,.mkx-shine__em){
    -webkit-text-fill-color:currentColor !important;background-image:none !important;color:inherit !important}
  .mkx-shine-win,.mkx-glint-clip{display:none !important}
}

/* ================================================================
   11. READING LIGHT (R9 foundation, A8): put data-readlight on a block of
   text and its words light in reading order as it crosses the screen.
   Unlit .34 (.55 on a photo so the copy stays readable), lit 1. The class
   rl-armed is added by motion-kit.js only when it can run, so with no JS,
   no IntersectionObserver or reduced motion every word simply shows lit.
   ================================================================ */
[data-readlight]{--rl-floor:.34}
:is(.has-bgphoto,.phero--photo,[data-photo-hero]) [data-readlight],[data-readlight]:is(.has-bgphoto,.phero--photo){--rl-floor:.55}
[data-readlight].rl-armed .rl-w{opacity:var(--rl-floor);transition:opacity .45s ease}
[data-readlight].rl-armed .rl-w.is-lit{opacity:1}
@media (prefers-reduced-motion:reduce){[data-readlight] .rl-w{opacity:1 !important;transition:none}}
