/* =====================================================================
   AIAGE MOTION KIT — aiage-motion.css  (v1.0.0 · 2026-06-23)
   Brand-agnostic, themeable motion + interaction system.
   Generalized from a production landing page (v7). See CHANGELOG.md.

   No build step. No frameworks. No CDN libraries.
   Pair with aiage-motion.js. Recolour everything via the :root tokens.

   HOW IT GATES
   ------------
   All motion is class-gated on  html.reduce-motion  (a.k.a. ".motion-off").
   The kit defaults to MOTION ON. It does NOT hard-gate on the OS
   prefers-reduced-motion media query — that is exposed as a one-line opt-in
   (see the OPTIONAL block at the very bottom of this file, and the README).
   ===================================================================== */

/* =====================================================================
   §0 — THEME TOKENS  (recolour a new brand here, one place)
   ===================================================================== */
:root {
  /* ---- Palette (override these per brand) ---- */
  --mk-bg: #FAFAF8;          /* page background          */
  --mk-surface: #FFFFFF;     /* cards / panels           */
  --mk-ink: #0A0A0A;         /* primary text / borders   */
  --mk-ink-2: #2C2C2C;       /* body text                */
  --mk-ink-3: #5C5C5C;       /* muted text               */
  --mk-ink-4: #8A8A8A;       /* faint text / disabled    */
  --mk-rule: #E2E0DA;        /* hairlines                */
  --mk-accent: #FFD60A;      /* primary accent (signal)  */
  --mk-accent-2: #E5BD00;    /* darker accent            */
  --mk-accent-ink: #0A0A0A;  /* text on the accent       */
  --mk-secondary: #006D77;   /* secondary accent (teal)  */
  --mk-secondary-2: #00525A; /* darker secondary         */

  /* Aurora shader colours, expressed 0..1 (see js: window.AIAGEMotion.config) */
  /* Off-white base, secondary tint, accent bloom — defaults mirror the brand. */

  /* ---- Typography (override per brand; system-font fallbacks built in) ---- */
  --mk-font-display: 'Bricolage Grotesque', system-ui, sans-serif;
  --mk-font-serif: 'DM Serif Display', Georgia, serif;
  --mk-font-sans: 'Inter Tight', system-ui, sans-serif;
  --mk-font-mono: 'JetBrains Mono', ui-monospace, monospace;

  /* ---- Layout ---- */
  --mk-maxw: 1320px;
  --mk-gutter: clamp(16px, 4vw, 40px);
  --mk-shadow-lift: 0 24px 50px -22px rgba(10,10,10,0.34), 0 8px 18px -10px rgba(10,10,10,0.18);

  /* ---- §0c PREMIUM EASING TOKENS (single source of truth) ---- */
  --mk-ease-out-expo: cubic-bezier(0.16, 1, 0.30, 1);   /* reveals, settles      */
  --mk-ease-std:      cubic-bezier(0.40, 0, 0.20, 1);    /* hovers, focus         */
  --mk-ease-spring:   cubic-bezier(0.34, 1.4, 0.64, 1);  /* tiny springs ONLY     */
  /* convenience alias */
  --mk-ease: var(--mk-ease-out-expo);
}

/* =====================================================================
   §0a — TINY RESET / PRIMITIVES (scoped, safe to drop into a page)
   ===================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--mk-font-sans);
  background: var(--mk-bg);
  color: var(--mk-ink);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;            /* §a11y — never allow horizontal scroll */
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }
img, svg { display: block; }
::selection { background: var(--mk-accent); color: var(--mk-accent-ink); }

/* §a11y — big display headings must wrap, never force horizontal scroll at 320px */
h1, h2, h3, h4 { text-wrap: balance; }
.mk-balance,
[data-line-mask], [data-lines] { overflow-wrap: break-word; word-break: break-word; }

/* §⑪ — refined focus-visible (AA contrast); accent ring on dark surfaces */
:focus-visible { outline: 2px solid var(--mk-ink); outline-offset: 3px; transition: outline-offset 0.15s var(--mk-ease-std); }
.mk-on-dark :focus-visible,
[data-focus-ring="accent"]:focus-visible { outline-color: var(--mk-accent); }

/* generic shell / container */
.mk-shell { max-width: var(--mk-maxw); margin: 0 auto; padding-left: var(--mk-gutter); padding-right: var(--mk-gutter); min-width: 0; }

/* visually-hidden (screen-reader only) helper used by the odometer */
.mk-vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* =====================================================================
   §1 — SCROLL REVEAL  [data-reveal]  (fade + rise, with stagger)
   Add data-d="1..4" to delay an element within a staggered group.
   ===================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s var(--mk-ease-out-expo), transform 0.7s var(--mk-ease-out-expo);
  will-change: opacity, transform;
}
[data-reveal].is-in { opacity: 1; transform: none; }
[data-reveal][data-d="1"] { transition-delay: 0.06s; }
[data-reveal][data-d="2"] { transition-delay: 0.12s; }
[data-reveal][data-d="3"] { transition-delay: 0.18s; }
[data-reveal][data-d="4"] { transition-delay: 0.24s; }

/* Section-entry grammar: a stamp wipes in, a right-link slides in, when the
   header (carrying [data-reveal]) reveals. Opt in with the helper classes. */
[data-reveal] .mk-reveal-stamp {
  transition: transform 0.7s var(--mk-ease-out-expo) 0.05s, opacity 0.7s var(--mk-ease-out-expo) 0.05s;
  transform: translateX(-14px); opacity: 0;
}
[data-reveal].is-in .mk-reveal-stamp { transform: none; opacity: 1; }
[data-reveal] .mk-reveal-right {
  transition: transform 0.7s var(--mk-ease-out-expo) 0.12s, opacity 0.7s var(--mk-ease-out-expo) 0.12s;
  transform: translateX(18px); opacity: 0;
}
[data-reveal].is-in .mk-reveal-right { transform: none; opacity: 1; }

/* =====================================================================
   §2 — LINE-MASK / SPLIT-TEXT REVEAL
   (a) Generic single-line clip+rise wrapper:  [data-lines]  (JS wraps it)
   (b) Multi-line cascade authored by hand:     [data-line-mask] with
       .mk-line > .mk-line-i  children (per-line clip + staggered rise)
   ===================================================================== */

/* (a) JS-built single masked line (keeps inline <em>/<span> intact) */
.mk-lines { display: block; }
.mk-lines .mk-line { display: block; overflow: hidden; }
.mk-lines .mk-line-i { display: block; transform: translateY(115%); transition: transform 0.9s var(--mk-ease-out-expo); }
.mk-lines.is-in .mk-line-i { transform: translateY(0); }

/* (b) Hand-authored / hero cascade: each .mk-line clips, .mk-line-i rises.
   Reveal fires when the container gets .is-in (scroll) or .is-armed+body.mk-loaded (hero). */
[data-line-mask] .mk-line { display: block; overflow: hidden; }
[data-line-mask] .mk-line-i { display: block; transform: translateY(110%); transition: transform 0.85s var(--mk-ease-out-expo); }
[data-line-mask].is-in .mk-line-i,
body.mk-loaded [data-line-mask].is-armed .mk-line-i { transform: translateY(0); }

/* staggered per-line delay (both variants) */
.mk-lines .mk-line:nth-child(1) .mk-line-i,
[data-line-mask] .mk-line:nth-child(1) .mk-line-i { transition-delay: 0.02s; }
.mk-lines .mk-line:nth-child(2) .mk-line-i,
[data-line-mask] .mk-line:nth-child(2) .mk-line-i { transition-delay: 0.10s; }
.mk-lines .mk-line:nth-child(3) .mk-line-i,
[data-line-mask] .mk-line:nth-child(3) .mk-line-i { transition-delay: 0.18s; }
.mk-lines .mk-line:nth-child(4) .mk-line-i,
[data-line-mask] .mk-line:nth-child(4) .mk-line-i { transition-delay: 0.26s; }

/* Animated underline draw for an accent inside a masked line: wrap text in
   .mk-accent and drop an inline <svg><path/></svg>. Fires with the hero. */
.mk-accent { position: relative; white-space: nowrap; }
.mk-accent svg { position: absolute; left: -3%; bottom: -0.1em; width: 106%; height: 16px; pointer-events: none; overflow: visible; }
.mk-accent svg path { fill: none; stroke: var(--mk-accent); stroke-width: 5; stroke-linecap: round; stroke-dasharray: 600; stroke-dashoffset: 600; }
body.mk-loaded [data-line-mask].is-armed .mk-accent svg path,
.mk-lines.is-in .mk-accent svg path { animation: mkDrawLine 1.3s var(--mk-ease-std) 0.4s forwards; }
@keyframes mkDrawLine { to { stroke-dashoffset: 0; } }

/* =====================================================================
   §3 — ANIMATED UNDERLINE DRAW  .mk-underline  (background-size grow)
   Works on links/buttons; AA-friendly (colour change on hover too).
   ===================================================================== */
.mk-underline {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-size: 0% 2px;
  background-position: 0 100%;
  padding-bottom: 2px;
  transition: color 0.2s var(--mk-ease-std), background-size 0.4s var(--mk-ease-out-expo);
}
.mk-underline:hover, .mk-underline:focus-visible { background-size: 100% 2px; }
/* a persistent (always-drawn) accent underline variant */
.mk-underline-accent {
  background-image: linear-gradient(var(--mk-accent), var(--mk-accent));
  background-repeat: no-repeat;
  background-size: 100% 3px;
  background-position: 0 100%;
  padding-bottom: 2px;
  transition: color 0.2s var(--mk-ease-std), background-size 0.4s var(--mk-ease-out-expo), opacity 0.2s var(--mk-ease-std);
}

/* =====================================================================
   §4 — EDITORIAL PRELOADER  #mk-preloader  (band-split + counter)
   Removed synchronously when motion is off; hard-timeout in JS (<=1.3s).
   Markup nodes are built by the kit if absent, but you may author them.
   ===================================================================== */
#mk-preloader { position: fixed; inset: 0; z-index: 9999; pointer-events: none; }
#mk-preloader .mk-pre-band { position: absolute; left: 0; right: 0; height: 50%; background: var(--mk-ink); will-change: transform; transition: transform 0.7s var(--mk-ease-out-expo); }
#mk-preloader .mk-pre-band.top { top: 0; transform: translateY(0); }
#mk-preloader .mk-pre-band.bot { bottom: 0; transform: translateY(0); }
#mk-preloader.done .mk-pre-band.top { transform: translateY(-100%); }
#mk-preloader.done .mk-pre-band.bot { transform: translateY(100%); }
#mk-preloader .mk-pre-mid { position: absolute; left: 0; right: 0; top: 50%; height: 2px; background: var(--mk-accent); transform: translateY(-50%) scaleX(var(--mk-pre-p, 0)); transform-origin: left center; z-index: 2; transition: opacity 0.3s; }
#mk-preloader.done .mk-pre-mid { opacity: 0; }
#mk-preloader .mk-pre-mark { position: absolute; left: var(--mk-gutter); top: calc(50% - 56px); color: var(--mk-bg); font-family: var(--mk-font-display); font-weight: 800; font-size: clamp(28px, 5vw, 54px); letter-spacing: -0.03em; z-index: 3; }
#mk-preloader .mk-pre-mark em { font-family: var(--mk-font-serif); font-style: italic; color: var(--mk-accent); font-weight: 400; }
#mk-preloader .mk-pre-count { position: absolute; right: var(--mk-gutter); bottom: calc(50% - 56px); color: var(--mk-bg); font-family: var(--mk-font-mono); font-size: clamp(40px, 9vw, 96px); font-weight: 500; letter-spacing: -0.02em; z-index: 3; line-height: 1; }
#mk-preloader .mk-pre-count::after { content: '%'; font-size: 0.4em; vertical-align: super; color: var(--mk-accent); margin-left: 4px; }
#mk-preloader .mk-pre-edition { position: absolute; left: var(--mk-gutter); top: calc(50% + 18px); color: rgba(255,255,255,0.5); font-family: var(--mk-font-mono); font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; z-index: 3; }

/* =====================================================================
   §5 — SCROLL-PROGRESS RAIL  .mk-read-rail  (CSS scroll-timeline first)
   ===================================================================== */
.mk-read-rail { position: fixed; left: 0; right: 0; top: 0; height: 3px; z-index: 70; pointer-events: none; background: transparent; }
.mk-read-rail .mk-rail-fill { height: 100%; background: var(--mk-accent); transform-origin: 0 50%; transform: scaleX(var(--mk-rail, 0)); will-change: transform; }
@supports (animation-timeline: scroll()) {
  .mk-read-rail .mk-rail-fill { transform: scaleX(0); animation: mkRailGrow linear both; animation-timeline: scroll(root); }
  @keyframes mkRailGrow { to { transform: scaleX(1); } }
}

/* =====================================================================
   §6 — KINETIC GIANT-WORDMARK BANDS  .wm-band  (two opposite rows)
   JS fills the rows and drives the marquee + scroll-drift parallax.
   Recolour the stroke / accent via the tokens below.
   ===================================================================== */
.wm-band { position: relative; overflow: hidden; pointer-events: none; width: 100%; user-select: none; }
.wm-band .wm-row { display: flex; white-space: nowrap; width: max-content; will-change: transform; font-family: var(--mk-font-display); font-weight: 800; letter-spacing: -0.02em; line-height: 0.92; text-transform: uppercase; }
.wm-band .wm-word { display: inline-block; padding-right: 0.06em; color: transparent; -webkit-text-stroke: 2px rgba(10,10,10,0.16); }
.wm-band .wm-word:nth-child(4n) { color: var(--mk-accent); -webkit-text-stroke: 2px rgba(10,10,10,0); }
.wm-band .wm-row.rev .wm-word { -webkit-text-stroke-color: rgba(10,10,10,0.10); }
.wm-band .wm-row.rev .wm-word:nth-child(4n) { color: var(--mk-secondary); }
/* sizing presets */
.wm-band.wm-hero { position: absolute; left: 0; right: 0; top: clamp(40px, 7vw, 96px); z-index: 0; will-change: transform; }
.wm-band.wm-hero .wm-row { font-size: clamp(96px, 20vw, 320px); opacity: 0.55; }
.wm-band.wm-sep { margin: clamp(8px, 2vw, 24px) 0; }
.wm-band.wm-sep .wm-row { font-size: clamp(54px, 11vw, 150px); }
.wm-band.wm-sep .wm-row + .wm-row { margin-top: -0.12em; }
/* on dark surfaces (e.g. footer) flip stroke to light */
.mk-on-dark .wm-band .wm-word { -webkit-text-stroke-color: rgba(255,255,255,0.07); }
.mk-on-dark .wm-band .wm-word:nth-child(4n) { color: rgba(255,255,255,0.10); }

/* =====================================================================
   §7 — AURORA WEBGL LAYER  [data-aurora]  (canvas) + CSS fallback host
   The JS guards on  if(!gl)return  and paints a CSS gradient fallback.
   ===================================================================== */
.mk-aurora { position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.mk-aurora canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
/* readability scrim so overlaid text holds WCAG AA against the brightest frame */
.mk-aurora::after { content: ''; position: absolute; inset: 0; background:
  radial-gradient(120% 100% at 35% 40%, rgba(250,250,248,0.72), rgba(250,250,248,0.46) 55%, rgba(250,250,248,0.32) 100%); }

/* =====================================================================
   §8 — CONSTELLATION CANVAS  [data-constellation]  (mouse-reactive)
   Place inside a positioned host that fills its panel.
   ===================================================================== */
.mk-viz { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.mk-viz canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

/* =====================================================================
   §9 — TICKER / MARQUEE  .mk-ticker  (CSS keyframe marquee, pause on hover)
   ===================================================================== */
.mk-ticker { overflow: hidden; position: relative; }
.mk-ticker::before, .mk-ticker::after { content: ''; position: absolute; top: 0; bottom: 0; width: 64px; z-index: 2; pointer-events: none; }
.mk-ticker::before { left: 0; background: linear-gradient(90deg, var(--mk-surface), transparent); }
.mk-ticker::after { right: 0; background: linear-gradient(270deg, var(--mk-surface), transparent); }
.mk-ticker-track { display: inline-flex; white-space: nowrap; will-change: transform; animation: mkMarquee 46s linear infinite; }
.mk-ticker:hover .mk-ticker-track { animation-play-state: paused; }
.mk-ticker-item { display: inline-flex; align-items: center; gap: 14px; padding: 14px 0; font-family: var(--mk-font-mono); font-size: 12px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--mk-ink); }
.mk-ticker-item::after { content: '\2726'; margin: 0 26px; color: var(--mk-secondary); font-size: 11px; }
@keyframes mkMarquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* =====================================================================
   §10 — ODOMETER COUNTERS  [data-odometer]  (digit reels)
   JS turns a target number into per-digit reels and rolls to it on reveal.
   ===================================================================== */
.mk-odo { display: inline-flex; vertical-align: bottom; }
.mk-odo .mk-odo-col { display: inline-block; height: 1em; overflow: hidden; line-height: 1; }
.mk-odo .mk-odo-reel { display: block; will-change: transform; transition: transform 1s var(--mk-ease-out-expo); }
.mk-odo .mk-odo-reel span { display: block; height: 1em; line-height: 1; text-align: center; }
/* optional ledger rule that draws under a counted stats band */
.mk-stat-rule { display: block; height: 2px; background: var(--mk-accent); margin-top: 14px; transform: scaleX(0); transform-origin: left center; transition: transform 0.8s var(--mk-ease-out-expo); }
.is-counted .mk-stat-rule { transform: scaleX(1); }

/* =====================================================================
   §11 — MAGNETIC BUTTONS  [data-magnetic]
   Wrap the inner label in .mk-mag-label for the parallax sub-shift.
   Elastic press/hover via the .mk-btn base (optional styling helper).
   ===================================================================== */
[data-magnetic] { will-change: transform; position: relative; transition: transform 0.6s var(--mk-ease-out-expo), background 0.2s var(--mk-ease-std), box-shadow 0.3s var(--mk-ease-out-expo); }
[data-magnetic] .mk-mag-label { display: inline-flex; align-items: center; gap: 8px; transition: transform 0.6s var(--mk-ease-out-expo); }
[data-magnetic]:active { transform: scale(0.97); }

/* optional button skin (purely cosmetic; theme-driven) */
.mk-btn { display: inline-flex; align-items: center; gap: 8px; padding: 14px 22px; background: var(--mk-accent); color: var(--mk-accent-ink); border: 2px solid var(--mk-ink); font-family: var(--mk-font-display); font-size: 14px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; cursor: pointer; }
.mk-btn .mk-arr { transition: transform 0.3s var(--mk-ease-out-expo); }
.mk-btn:hover { background: var(--mk-surface); box-shadow: 5px 5px 0 var(--mk-accent); }
.mk-btn:hover .mk-arr { transform: translateX(4px); }

/* =====================================================================
   §12 — 3-D TILT + SPECULAR GLARE CARDS  [data-tilt]  (book/poster)
                                          [data-tilt-card] (flat card)
   JS sets the rotation + --mx/--my glare position; CSS renders the sheen.
   Children with transform: translateZ(...) get parallax depth.
   ===================================================================== */
[data-tilt] { transform-style: preserve-3d; transition: transform 0.5s var(--mk-ease-out-expo); will-change: transform; position: relative; }
[data-tilt-card] { transform-style: preserve-3d; transition: transform 0.5s var(--mk-ease-out-expo), background 0.25s var(--mk-ease-std), box-shadow 0.4s var(--mk-ease-out-expo); will-change: transform; position: relative; }
/* specular glare layer driven by --mx/--my */
[data-tilt-card]::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0; z-index: 2;
  transition: opacity 0.3s var(--mk-ease-std);
  background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), rgba(255,214,10,0.18), transparent 45%);
}
[data-tilt-card].tilting::after { opacity: 1; }
/* sheen sweep for a book/poster cover on hover */
[data-tilt].mk-sheen::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.25s;
  background: linear-gradient(115deg, rgba(255,255,255,0) 30%, rgba(255,255,255,0.42) 50%, rgba(255,255,255,0) 70%);
}
[data-tilt].mk-sheen:hover::after { opacity: 1; }

/* perspective stage helper (parent of a [data-tilt] element) */
.mk-stage { perspective: 1000px; }

/* =====================================================================
   §13 — CUSTOM CURSOR  (pointer:fine only; native cursor NEVER hidden)
   Drop two nodes:  <div class="mk-cur-ring"></div><div class="mk-cur-dot"></div>
   ===================================================================== */
.mk-cur-dot, .mk-cur-ring { position: fixed; top: 0; left: 0; z-index: 9998; pointer-events: none; border-radius: 50%; opacity: 0; }
.mk-cur-dot { width: 7px; height: 7px; background: var(--mk-ink); margin: -3.5px 0 0 -3.5px; transition: opacity 0.3s, background 0.2s, transform 0.18s var(--mk-ease-std); }
.mk-cur-ring { width: 34px; height: 34px; margin: -17px 0 0 -17px; border: 1.5px solid var(--mk-ink); transition: opacity 0.3s, width 0.25s var(--mk-ease-std), height 0.25s var(--mk-ease-std), margin 0.25s var(--mk-ease-std), background 0.25s, border-color 0.2s, transform 0.18s var(--mk-ease-std); }
body.mk-has-cursor.mk-cursor-ready .mk-cur-dot,
body.mk-has-cursor.mk-cursor-ready .mk-cur-ring { opacity: 1; }
body.mk-cursor-hot .mk-cur-ring { width: 60px; height: 60px; margin: -30px 0 0 -30px; background: rgba(255,214,10,0.18); border-color: var(--mk-secondary); }
body.mk-cursor-hot .mk-cur-dot { background: var(--mk-secondary); transform: scale(1.4); }
body.mk-cursor-cover .mk-cur-ring { width: 78px; height: 78px; margin: -39px 0 0 -39px; background: var(--mk-accent); border-color: var(--mk-ink); }
body.mk-cursor-cover .mk-cur-dot { background: var(--mk-ink); transform: scale(1.6); }

/* =====================================================================
   §14 — STATIC GRAIN OVERLAY  #mk-grain  (print-stock tactility)
   Cheap; stays on under reduced motion. JS generates the tile.
   ===================================================================== */
.mk-grain { position: fixed; inset: 0; z-index: 9990; pointer-events: none; mix-blend-mode: overlay; opacity: 0.035; background-repeat: repeat; background-size: 128px 128px; }

/* =====================================================================
   §15 — SCROLL-VELOCITY SKEW  .mk-velo-skew  (allowlist target)
   Keep it OFF body copy / mid-flip cards. JS skews on fast scroll.
   ===================================================================== */
.mk-velo-skew { transform-origin: center top; will-change: transform; }

/* =====================================================================
   §16 — CURTAIN / PAGE-TURN SWEEP  [data-curtain]  (optional)
   JS injects a sweeping panel when the section scrolls in.
   data-curtain-color="accent" tints the panel.
   ===================================================================== */
.mk-curtain-wrap { position: relative; }
.mk-curtain { position: absolute; inset: 0; z-index: 30; pointer-events: none; background: var(--mk-ink); transform: scaleX(0); transform-origin: left center; will-change: transform; }
.mk-curtain.accent { background: var(--mk-accent); }
.mk-curtain.is-sweeping { animation: mkCurtainSweep 1.05s var(--mk-ease-out-expo) forwards; }
@keyframes mkCurtainSweep {
  0%   { transform: scaleX(0); transform-origin: left center; }
  45%  { transform: scaleX(1); transform-origin: left center; }
  46%  { transform: scaleX(1); transform-origin: right center; }
  100% { transform: scaleX(0); transform-origin: right center; }
}

/* =====================================================================
   §17 — STICKY-NAV CONDENSE + SLIDING INK INDICATOR (optional helpers)
   Apply to your own nav; JS toggles .mk-condensed and positions .mk-nav-ind.
   ===================================================================== */
.mk-nav-condense { transition: box-shadow 0.4s var(--mk-ease-std); }
.mk-nav-condense.mk-condensed { box-shadow: 0 10px 30px -18px rgba(10,10,10,0.4); }
.mk-nav-ind { position: absolute; bottom: -1px; left: 0; height: 2px; width: 0; background: var(--mk-secondary); transform: translateX(0); transform-origin: left center; transition: transform 0.3s var(--mk-ease-std), width 0.3s var(--mk-ease-std), opacity 0.3s var(--mk-ease-std); pointer-events: none; opacity: 0; }
.show-ind .mk-nav-ind { opacity: 1; }

/* =====================================================================
   §18 — MOTION TOGGLE CONTROL  .mk-motion-toggle  (visible opt-out FAB)
   The kit also supports any element with [data-motion-toggle].
   ===================================================================== */
.mk-motion-toggle { position: fixed; right: 18px; bottom: 18px; z-index: 80; display: inline-flex; align-items: center; gap: 8px; background: var(--mk-ink); color: var(--mk-accent); border: 2px solid var(--mk-ink); font-family: var(--mk-font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; padding: 9px 13px; cursor: pointer; box-shadow: 0 8px 22px -10px rgba(0,0,0,0.55); transition: transform 0.2s var(--mk-ease-out-expo); }
.mk-motion-toggle:hover { transform: translateY(-2px); }
.mk-motion-toggle:active { transform: scale(0.97); }
.mk-motion-toggle .mk-mt-ico { width: 9px; height: 9px; border-radius: 50%; background: var(--mk-accent); }
.mk-motion-toggle:not(.is-off) .mk-mt-ico { animation: mkMtPulse 1.8s ease-out infinite; }
.mk-motion-toggle.is-off { color: #9A9A9A; }
.mk-motion-toggle.is-off .mk-mt-ico { background: #9A9A9A; }
@keyframes mkMtPulse { 0% { box-shadow: 0 0 0 0 rgba(255,214,10,0.55); } 70% { box-shadow: 0 0 0 7px rgba(255,214,10,0); } 100% { box-shadow: 0 0 0 0 rgba(255,214,10,0); } }
@media (max-width: 600px) { .mk-motion-toggle { right: 12px; bottom: 12px; font-size: 10px; padding: 8px 11px; } }

/* =====================================================================
   §19 — REDUCED MOTION  (class-gated — this IS the Motion control)
   html.reduce-motion  OR  html.motion-off  freezes everything to a
   resting state. The visible toggle adds/removes this class (persisted).
   ===================================================================== */
html.reduce-motion, html.motion-off { scroll-behavior: auto; }
html.reduce-motion *, html.reduce-motion *::before, html.reduce-motion *::after,
html.motion-off *,   html.motion-off *::before,   html.motion-off *::after {
  animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important;
}
html.reduce-motion [data-reveal], html.motion-off [data-reveal] { opacity: 1 !important; transform: none !important; }
html.reduce-motion [data-reveal] .mk-reveal-stamp, html.reduce-motion [data-reveal] .mk-reveal-right,
html.motion-off   [data-reveal] .mk-reveal-stamp, html.motion-off   [data-reveal] .mk-reveal-right { opacity: 1 !important; transform: none !important; }
html.reduce-motion .mk-lines .mk-line-i, html.reduce-motion [data-line-mask] .mk-line-i,
html.motion-off   .mk-lines .mk-line-i, html.motion-off   [data-line-mask] .mk-line-i { transform: none !important; }
html.reduce-motion .mk-accent svg path, html.motion-off .mk-accent svg path { stroke-dashoffset: 0 !important; }
html.reduce-motion .mk-underline, html.reduce-motion .mk-underline-accent,
html.motion-off   .mk-underline, html.motion-off   .mk-underline-accent { background-size: 0 0; }
html.reduce-motion .mk-ticker-track, html.motion-off .mk-ticker-track { animation: none !important; }
html.reduce-motion .wm-band .wm-row, html.motion-off .wm-band .wm-row { animation: none !important; transform: none !important; }
html.reduce-motion .wm-band.wm-hero, html.reduce-motion .wm-band.wm-sep,
html.motion-off   .wm-band.wm-hero, html.motion-off   .wm-band.wm-sep { transform: none !important; }
html.reduce-motion .mk-curtain, html.motion-off .mk-curtain { display: none !important; animation: none !important; }
html.reduce-motion .mk-cur-dot, html.reduce-motion .mk-cur-ring,
html.motion-off   .mk-cur-dot, html.motion-off   .mk-cur-ring { display: none !important; }
html.reduce-motion .mk-odo .mk-odo-reel, html.motion-off .mk-odo .mk-odo-reel { transition: none !important; }
html.reduce-motion .mk-stat-rule, html.motion-off .mk-stat-rule { transform: scaleX(1) !important; }
html.reduce-motion .mk-velo-skew, html.motion-off .mk-velo-skew { transform: none !important; }
html.reduce-motion #mk-preloader, html.motion-off #mk-preloader { display: none !important; }
html.reduce-motion .mk-read-rail .mk-rail-fill, html.motion-off .mk-read-rail .mk-rail-fill { animation: none !important; }
/* no aurora layer at all under reduced motion (drops its scrim too) */
html.reduce-motion .mk-aurora, html.motion-off .mk-aurora { display: none !important; }

/* =====================================================================
   §20 — OPTIONAL PRODUCTION A11Y OPT-IN
   The kit defaults to MOTION ON regardless of the OS setting. To ALSO
   honour the operating-system "reduce motion" preference automatically,
   UNCOMMENT this block (and see the JS opt-in noted in the README).
   ===================================================================== */
/*
@media (prefers-reduced-motion: reduce) {
  html:not(.motion-on) * , html:not(.motion-on) *::before, html:not(.motion-on) *::after {
    animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important;
  }
  html:not(.motion-on) [data-reveal] { opacity: 1 !important; transform: none !important; }
  html:not(.motion-on) .mk-aurora { display: none !important; }
}
*/
