/* Shared styles for the two product pages: /kuinetic and /tovu. Every class is prefixed `kp-`.
   Motion comes from data-kui attributes in the page HTML; this file only lays out and styles.
   Nothing here hides content before JS runs. */

/* Safety net: nothing on these pages may widen the page on phones. clip, not hidden, so position:sticky pins keep working. */
.page-kuinetic main, .page-tovu main { overflow-x: clip; }

/* ---------- page head ---------- */
.kp-head-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; margin-left: 29%; }

/* ---------- shared bits ---------- */
.kp-progress { position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 40; background: var(--fg); transform-origin: 0 50%; }
.kp-name { margin: 0; font-family: var(--font-display); font-weight: 500; font-size: clamp(20px, 1.9vw, 26px); line-height: 1.1; letter-spacing: -0.035em; }
.kp-name--sm { font-size: clamp(15px, 1.2vw, 18px); letter-spacing: -0.02em; color: var(--muted); }
.page-kuinetic .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.kp-demo { margin-top: clamp(56px, 7vw, 112px); min-width: 0; }
.kp-demo-head { display: flex; justify-content: space-between; align-items: end; gap: 24px; margin-bottom: clamp(20px, 2.4vw, 32px); }
.kp-frame { overflow: hidden; border-radius: 16px; background: var(--surface); aspect-ratio: 16 / 10; }
.kp-frame--tall { aspect-ratio: 3 / 4; }
.section--dark .kp-frame { background: #1a1a1a; }
.kp-frame img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
.kp-frame--par { position: relative; }
.kp-frame--par img { position: absolute; inset: -96px 0; height: calc(100% + 192px); }

/* ---------- curved text ---------- */
.kp-curve { margin: clamp(48px, 7vw, 104px) 0 0; }
.kp-curve svg { display: block; width: 100%; height: auto; overflow: visible; }
/* geometricPrecision keeps glyph advances the same at every SVG scale; the loop distance on the textPath is one phrase in user units. */
.kp-curve text { text-rendering: geometricPrecision; font-family: var(--font-display); font-size: 88px; font-weight: 500; letter-spacing: -0.04em; fill: var(--fg); }

/* ---------- marquee: clip, not hidden, so scroll timelines still reach the page ---------- */
.kp-marquee { overflow: clip; margin-top: clamp(40px, 6vw, 88px); font-family: var(--font-display); font-weight: 600; font-size: clamp(64px, 13vw, 220px); line-height: 1; letter-spacing: -0.05em; white-space: nowrap; }
/* parallax-x travels from minus to plus its distance, so the -12.5% rest position keeps the travel at -25%..0 and the row never leaves a gap at its left end. */
.kp-marquee > div { display: flex; width: max-content; transform: translateX(-12.5%); }
.kp-marquee--dark { margin-top: clamp(64px, 9vw, 140px); color: #fff; }
.kp-marquee--dark + .kp-marquee--dark { margin-top: 8px; color: #6a6a6a; }
.kp-marquee--rev [data-kui-fx] { animation-direction: reverse !important; }

/* ---------- text rows ---------- */
.kp-rows { list-style: none; margin: clamp(32px, 4vw, 56px) 0 0; padding: 0; border-top: var(--hair); }
.kp-row { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 10fr); align-items: baseline; gap: 12px 24px; padding-block: clamp(24px, 3.4vw, 48px); border-bottom: var(--hair); }
.kp-line { margin: 0; min-width: 0; font-family: var(--font-display); font-weight: 500; font-size: clamp(40px, 8.6cqi, 136px); line-height: 1; letter-spacing: -0.055em; --kui-mask-bleed: 0.14em; }
.kp-line--mono { font-family: var(--font-mono); letter-spacing: -0.02em; font-size: clamp(30px, 6.8cqi, 104px); }
.kp-line--xl { font-size: clamp(56px, 13cqi, 208px); font-weight: 600; }
/* kUInetic's built-in marker is gold; the page's gray has to win over it. */
.kp-mark { color: inherit; --kui-sweep-color: var(--kp-mark); }
/* The bar sweeps the element's own box, so the box has to be as wide as the word. */
.kp-line[data-kui~="redaction-reveal"] { width: fit-content; }
.page-kuinetic { --kp-mark: #d9d9d9; }
:root:not([data-theme="light"]) .page-kuinetic { --kp-mark: #4a4a4a; }
[data-kui-fx~="redaction-reveal"]::before { background: var(--fg) !important; }

/* ---------- pinned reading ---------- */
.kp-read { margin-top: var(--section-y); background: var(--band); color: #fff; }
.kp-read-pin { display: grid; place-items: center; height: 100vh; height: calc(100svh - var(--nav-h, 68px)); padding-inline: var(--gutter); }
.kp-read-text { margin: 0; max-width: 19ch; font-family: var(--font-display); font-weight: 500; font-size: clamp(36px, 7vw, 112px); line-height: 1.04; letter-spacing: -0.05em; }

/* ---------- reveals ---------- */
.kp-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(32px, 3vw, 44px) 24px; margin-top: clamp(32px, 4vw, 56px); }
.kp-tile { margin: 0; min-width: 0; display: grid; align-content: start; gap: 14px; }
.kp-cascade { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; }
.kp-cascade figure { margin: 0; }

/* ---------- scroll ---------- */
.kp-scroll { overflow-x: clip; }
/* A pin is sticky for as long as its parent lasts, so each one needs a parent of its own, spacer included. */
.kp-pinbox { position: relative; }
.kp-pin { box-sizing: border-box; height: 100vh; height: calc(100svh - var(--nav-h, 68px)); margin-top: clamp(48px, 6vw, 88px); display: grid; place-items: center; }
/* Sized from the image's own ratio inside the pinned area, so the whole picture shows below the nav at any window height. */
.kp-pin img { display: block; width: auto; height: auto; max-width: 100%; max-height: calc(100svh - var(--nav-h, 68px)); }
.kp-pin picture { display: contents; }
.kp-htrack { color: #fff; }
.kp-track { display: flex; align-items: center; gap: 24px; padding-inline: var(--gutter); }
.kp-track figure { flex: none; margin: 0; width: clamp(280px, 44vw, 720px); }
.kp-track .kp-track-tall { width: clamp(180px, 22vw, 360px); }
.kp-para { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(12px, 2vw, 32px); padding-block: 240px; overflow-y: clip; }
.kp-para-col { display: grid; gap: clamp(12px, 2vw, 32px); }
.kp-para-col .kp-frame { margin: 0; }
.kp-rot { position: relative; display: grid; place-items: center; height: 100vh; height: calc(100svh - var(--nav-h, 68px)); }
.kp-rot-card { width: min(64vw, 960px, calc((100svh - var(--nav-h, 68px) - 32px) * 1.6)); aspect-ratio: 16 / 10; }
.kp-rot-title { position: absolute; left: var(--gutter); bottom: 8svh; margin: 0; font-size: clamp(64px, 12vw, 200px); line-height: .9; font-weight: 600; letter-spacing: -0.05em; color: #fff; }
.kp-quad { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; }
/* A whole card, title and image, has to fit under the nav at any window height. The room for the image is the screen less
   the nav, the four sticky offsets, a 24px margin, and the card's own padding, gap and title (30px). The card's width then
   follows that height at 16:9, so short windows get a smaller card instead of a cropped picture. */
.kp-stack-wrap { --kp-step: clamp(8px, 2.6svh, 24px); --kp-pad: clamp(16px, 2vw, 28px); display: grid; gap: 24px; }
.kp-stack { --kp-frame-h: max(96px, calc(100svh - var(--kp-nav) - 4 * var(--kp-step) - 24px - 2 * var(--kp-pad) - 16px - 30px)); display: grid; gap: 16px; justify-self: center; width: min(100%, calc(var(--kp-frame-h) * 16 / 9 + 2 * var(--kp-pad))); padding: var(--kp-pad); background: #171717; border: var(--hair-dark); border-radius: 24px; color: #fff; }
/* Keeps the card off the fixed replay button, which is 52px wide and 24px from the corner. */
@media (min-width: 761px) { .kp-stack { max-width: calc(100vw - 192px); } }
.kp-stack .kp-frame { aspect-ratio: 16 / 9; }
.kp-seq { position: relative; overflow: clip; height: 100vh; height: calc(100svh - var(--nav-h, 68px)); background: #000; }
/* The library's frame rule sets cover on [data-kui-step-state]; contain keeps each whole frame on screen. */
.kp-seq img, .kp-seq > img[data-kui-step-state] { object-fit: contain; object-position: 50% 50%; }

/* ---------- carousels and 3D ---------- */
.kp-set { max-width: 760px; margin-inline: auto; --card-w: min(760px, 86vw); }
.kp-set .card { width: var(--card-w); }
.kp-row-loop { gap: 20px; align-items: center; }
.kp-row-loop > figure { flex: 0 0 auto; width: clamp(160px, 18vw, 260px); margin: 0; overflow: hidden; border-radius: 12px; background: var(--surface); }
.kp-row-loop img { display: block; width: 100%; height: clamp(190px, 22vw, 320px); object-fit: cover; object-position: 50% 0; }
.kp-row-loop:not([data-kui-fx]) { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.kp-row-loop:not([data-kui-fx]) > figure { width: auto; }

.kp-ring-stage { --card-w: clamp(170px, 24vw, 340px); --card-ratio: 16 / 10; overflow-x: clip; padding-block: clamp(32px, 5vw, 72px); }
.kp-ring { height: calc(var(--card-w) * 0.625 + 20px); }
.kp-ring .card { width: var(--card-w); margin: 0; overflow: hidden; border-radius: 12px; background: var(--surface); aspect-ratio: var(--card-ratio); }
.kp-ring .card img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
.kp-ring:not([data-kui-fx]) { height: auto; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.kp-ring:not([data-kui-fx]) .card { width: auto; }

.kp-duo { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(40px, 5vw, 80px); }
.kp-helix { inline-size: min(100%, 560px); margin-inline: auto; --card-w: 100px; --card-ratio: 10 / 13; }
.kp-helix .card, .kp-sphere .card, .kp-pile .card, .kp-orbit .card { width: var(--card-w); margin: 0; overflow: hidden; border-radius: 10px; background: var(--surface); }
.kp-helix img, .kp-sphere img, .kp-pile img, .kp-orbit img { display: block; width: 100%; height: auto; aspect-ratio: var(--card-ratio, 3 / 4); object-fit: cover; object-position: 50% 0; }
.kp-sphere-stage { display: grid; justify-items: center; overflow-x: clip; padding-block: 32px; }
.kp-sphere { --card-w: clamp(56px, 7vw, 80px); --card-ratio: 8 / 11; }
.kp-pile-stage { display: grid; justify-items: center; overflow: clip; padding-block: 40px; }
.kp-pile { --card-w: min(280px, 56vw); --card-ratio: 3 / 4; }
.kp-orbit-stage { display: grid; justify-items: center; padding-block: 32px; }
.kp-orbit { width: min(100%, 560px); --card-w: clamp(64px, 9vw, 110px); --card-ratio: 3 / 4; }
.kp-flips { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.kp-flip { aspect-ratio: 3 / 4; border-radius: 16px; }
.kp-flip:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }
.kp-cube-stage { display: grid; place-items: center; padding-block: clamp(32px, 6vw, 80px); perspective: 1000px; }
.kp-cube { --kui-cube-size: clamp(180px, 26vw, 340px); width: var(--kui-cube-size); height: var(--kui-cube-size); }
.kp-cube > div { overflow: hidden; }
.kp-cube img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
/* With reduced motion kUInetic still marks a carousel with data-kui-fx but never spreads its cards, so they sit
   on top of each other and only one shows. The :not([data-kui-fx]) grids above cannot catch that; this is the same grid. */
@media (prefers-reduced-motion: reduce) {
  .kp-set[data-kui-fx], .kp-row-loop[data-kui-fx], .kp-ring[data-kui-fx], .kp-helix[data-kui-fx], .kp-sphere[data-kui-fx], .kp-pile[data-kui-fx], .kp-orbit[data-kui-fx] { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; height: auto; overflow: visible; }
  .kp-set[data-kui-fx] > .card, .kp-row-loop[data-kui-fx] > figure, .kp-ring[data-kui-fx] > .card, .kp-helix[data-kui-fx] > .card, .kp-sphere[data-kui-fx] > .card, .kp-pile[data-kui-fx] > .card, .kp-orbit[data-kui-fx] > .card { grid-area: auto; width: auto; position: static; transform: none; }
  .kp-track { flex-wrap: wrap; }
}

/* ---------- micro-interactions ---------- */
.kp-micro { list-style: none; padding: 0; margin: clamp(32px, 4vw, 56px) 0 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--border); border: var(--hair); border-radius: 16px; overflow: hidden; }
.kp-cell { display: grid; grid-template-rows: 1fr auto; gap: 12px; padding: 16px; min-height: clamp(180px, 18vw, 260px); background: var(--bg); min-width: 0; }
.kp-cell--wide { grid-column: span 2; }
.kp-cell-stage { display: grid; place-items: center; min-width: 0; }
.page-kuinetic { --kp-nav: var(--nav-h, 68px); }
.kp-micro .btn { width: auto; min-width: 0; justify-content: center; gap: 8px; padding-inline: 20px; }
.kp-micro [data-kui~="masked-label-swap"] { display: inline-grid; overflow: hidden; }
.kp-icon.kp-icon--bars { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; }
.kp-icon--bars { --kui-bar-gap: 7px; }
.kp-icon--bars .kui-bar { width: 20px; height: 3px; border-radius: 1.5px; background: currentColor; flex: none; }
/* Plus: the two bars cross, so they share one grid cell. kUInetic rotates the second bar. */
.kp-icon--bars[data-kui~="plus-to-minus"] { display: grid; place-items: center; }
.kp-icon--bars[data-kui~="plus-to-minus"] .kui-bar { grid-area: 1 / 1; }
/* Play: two wide bars. Each moves by --kui-bar-gap to close the flex gap, so the gap is twice that and the clipped halves meet as one triangle. */
.kp-icon--bars[data-kui~="play-to-pause"] { display: flex; flex-direction: row; gap: 4px; --kui-bar-gap: 2px; }
.kp-icon--bars[data-kui~="play-to-pause"] .kui-bar { width: 8px; height: 20px; border-radius: 0; }
.kp-check { position: relative; }
.kp-check > input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.kp-check > input:focus-visible ~ * { outline: 2px solid var(--fg); outline-offset: 2px; }
.btn--plain, .btn--plain:hover { background: none; color: var(--fg); border: var(--hair); }
.kp-dot { display: grid; place-items: center; width: clamp(88px, 8vw, 120px); aspect-ratio: 1; border: 0; border-radius: 50%; background: var(--fg); color: var(--bg); font: inherit; font-size: 18px; cursor: pointer; }
.kp-tilt { width: clamp(96px, 9vw, 140px); aspect-ratio: 3 / 4; overflow: hidden; border-radius: 10px; }
.kp-tilt img { display: block; width: 100%; height: 100%; object-fit: cover; }
.kp-under { color: inherit; font-size: clamp(18px, 1.5vw, 22px); text-decoration: none; }
.kp-icon { display: grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: var(--hair); border-radius: 50%; background: none; color: var(--fg); cursor: pointer; position: relative; }
.kp-check { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.kp-check .kui-thumb { --kui-thumb-color: var(--bg); }
.kp-check > input[data-kui~="checkbox-draw"] ~ svg { box-sizing: border-box; padding: 3px; border: var(--hair); border-radius: 6px; }
.kp-radios { display: flex; gap: 16px; }
.kp-radio input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.kp-radio .kui-dot { background: var(--fg); }
.kp-radio:has(input:focus-visible) { outline: 2px solid var(--fg); outline-offset: 2px; }
.kp-radio { display: inline-grid; place-items: center; position: relative; width: 24px; height: 24px; border: var(--hair); border-radius: 50%; }
.kp-search { display: inline-flex; align-items: center; gap: 0; min-height: var(--tap); padding-inline: 0; border: var(--hair); border-radius: 999px; }
.kp-search:focus-within { border-color: var(--fg); }
/* The closed pill is 2.5em wide, so these margins center a 1em icon in it. */
.kp-search svg { flex: none; width: 1em; height: 1em; margin-inline: 0.75em; }
.kp-search input::-webkit-search-cancel-button { appearance: none; }
.kp-search input { flex: 1; min-width: 0; border: 0; background: none; color: inherit; font: inherit; outline: none; }
.kp-preview { position: relative; font-size: clamp(18px, 1.5vw, 22px); text-decoration: underline; text-underline-offset: .18em; cursor: default; }
.kp-preview-img { display: block; width: 120px; aspect-ratio: 3 / 4; overflow: hidden; border-radius: 10px; }
.kp-preview-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.kp-spot { display: grid; place-items: center; width: 100%; height: 100%; min-height: 120px; border-radius: 10px; background: var(--band); color: #fff; font-size: clamp(20px, 2vw, 28px); --accent: #fff; }
.kp-spot > span { position: relative; z-index: 1; }
.kp-field { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; width: 100%; height: 100%; min-height: 120px; }
.kp-field > div { position: relative; border-radius: 10px; color: var(--fg); }
.kp-field img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.kp-expand { gap: 12px; }
.kp-expand article { min-width: 0; border-radius: 16px; outline-offset: 3px; }
.kp-expand article:focus-visible { outline: 2px solid var(--fg); }
.kp-expand img { display: block; width: 100%; height: clamp(240px, 32vw, 440px); object-fit: cover; object-position: 50% 0; border-radius: 16px; background: var(--surface); }
.kp-expand h3 { margin: 12px 0 0; font-size: clamp(20px, 1.9vw, 26px); line-height: 1.1; letter-spacing: -0.035em; font-weight: 500; }
.kp-expand p { margin: 4px 0 0; color: var(--muted); line-height: 1.3; }
@media (min-width: 48rem) { .kp-expand { min-height: calc(clamp(240px, 32vw, 440px) + 96px); align-items: flex-start; } }
.kp-dim { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; }

/* ---------- cursor trail ---------- */
.kp-trail { position: relative; isolation: isolate; display: grid; place-items: center; min-height: 100vh; min-height: 100svh; margin-top: var(--section-y); background: #000; color: #fff; overflow: clip; --kui-trail-width: clamp(140px, 17vw, 260px); --kui-trail-height: clamp(190px, 23vw, 350px); }
.kp-trail [data-kui-trail-layer] img { border-radius: 10px; object-fit: cover; object-position: 50% 0; }
.kp-trail-inner { position: relative; z-index: 1; text-align: center; pointer-events: none; padding-inline: var(--gutter); }
.kp-trail-word { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: clamp(96px, 26vw, 460px); line-height: .9; letter-spacing: -0.06em; --kui-mask-bleed: 0.18em; mix-blend-mode: difference; }
.kp-trail-sub { margin: 8px 0 0; color: #bdbdbd; font-size: var(--fs-body); }
.kp-trail-sources { display: none; }
@media (hover: none), (pointer: coarse), (prefers-reduced-motion: reduce) {
  .kp-trail { place-items: stretch; align-content: center; gap: 24px; padding-block: var(--section-y); min-height: 0; }
  .kp-trail-sub { display: none; }
  .kp-trail-sources { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; padding-inline: var(--gutter); }
  .kp-trail-sources img { display: block; width: 100%; aspect-ratio: 3 / 4; height: auto; object-fit: cover; object-position: 50% 0; border-radius: 10px; }
}

/* ---------- curtain switch ---------- */
.kp-view { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.kp-view > .kp-frame { margin: 0; }
.kp-switch--on .kp-view { grid-template-columns: minmax(0, 1fr); gap: 0; overflow: hidden; border-radius: 24px; max-width: calc((100svh - var(--nav-h, 68px) - 32px) * 16 / 9); margin-inline: auto; }
.kp-switch--on .kp-view > .kp-frame { grid-area: 1 / 1; visibility: hidden; border-radius: 0; aspect-ratio: 16 / 9; }
.kp-switch--on .kp-view[data-scene="one"] > [data-card="one"],
.kp-switch--on .kp-view[data-scene="two"] > [data-card="two"],
.kp-switch--on .kp-view[data-scene="three"] > [data-card="three"],
.kp-switch--on .kp-view[data-scene="four"] > [data-card="four"] { visibility: visible; }

/* ---------- numbers ---------- */
.kp-numbers { margin-top: clamp(40px, 5vw, 64px); }
.kp-numbers .stat { min-width: 0; }
.kp-num-line { display: block; width: 100%; height: 6px; margin-top: 18px; overflow: visible; }
.kp-num-line path { fill: none; stroke: #fff; stroke-width: 2; }

/* ---------- replay button: the ring in --bg keeps the disc visible over a band of its own colour ---------- */
.kp-fab { position: fixed; right: 24px; right: calc(24px + env(safe-area-inset-right, 0px)); bottom: 24px; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); z-index: 60; display: grid; place-items: center; width: 52px; height: 52px; padding: 0; border: 0; border-radius: 50%; background: var(--fg); color: var(--bg); box-shadow: 0 12px 32px -12px rgba(0, 0, 0, .5), 0 0 0 1.5px var(--bg); cursor: pointer; }
.kp-fab[hidden] { display: none; }
.kp-fab:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .kp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kp-cascade { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kp-micro { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kp-quad { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kp-duo { grid-template-columns: minmax(0, 1fr); }
  .kp-dim { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .kp-head-actions { margin-left: 0; }
  .kp-row { grid-template-columns: minmax(0, 1fr); }
  .kp-demo-head { align-items: start; }
  .kp-rot-card { width: min(82vw, calc((100svh - var(--nav-h, 68px) - 32px) * 1.6)); }
  .kp-row-loop:not([data-kui-fx]), .kp-ring:not([data-kui-fx]) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kp-view { grid-template-columns: minmax(0, 1fr); }
  .kp-view > .kp-frame { aspect-ratio: 4 / 5; }
  .kp-switch--on .kp-view { border-radius: 16px; max-width: calc((100svh - var(--nav-h, 68px) - 32px) * 4 / 5); }
  .kp-switch--on .kp-view > .kp-frame { aspect-ratio: 4 / 5; }
  .kp-flips { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .kp-track .kp-track-tall { width: clamp(180px, 56vw, 240px); }
}
@media (max-width: 760px) and (prefers-reduced-motion: reduce) {
  .kp-set[data-kui-fx], .kp-row-loop[data-kui-fx], .kp-ring[data-kui-fx] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .kp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px 12px; }
  .kp-cell--wide { grid-column: auto; }
  .kp-micro .btn { padding-inline: 12px; }
}


/* Skip rendering for sections far off-screen. Measured on this page (foreground, wheel-speed scroll): 167ms median
   frame with every section live, 17ms with this on. The intrinsic sizes are the 1200px layout's section heights,
   so the scrollbar stays honest until each section is first rendered. The trail section is left out because paint
   containment would turn it into the containing block of its fixed-position images. */
.page-kuinetic main > section:not(.page-head):not(.kp-trail) { content-visibility: auto; contain-intrinsic-size: auto 3000px; }
.page-kuinetic main > .kp-read { contain-intrinsic-size: auto 1550px; }

/* The rest of the library: dense grids of small titled demos. */
.kp-lib-fam { margin-top: clamp(40px, 5vw, 72px); content-visibility: auto; contain-intrinsic-size: auto 520px; }
.kp-fam { margin: 0 0 16px; font-family: var(--font-display); font-weight: 600; font-size: clamp(20px, 2vw, 28px); letter-spacing: -0.03em; }
.kp-lib { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); border-top: var(--hair); border-left: var(--hair); }
.kp-fx { display: grid; grid-template-rows: 1fr auto; gap: 10px; padding: 14px; min-height: 148px; background: var(--bg); min-width: 0; border-right: var(--hair); border-bottom: var(--hair); }
.kp-fx-stage { display: grid; place-items: center; min-width: 0; min-height: 84px; }
.kp-fx-name { margin: 0; font-family: var(--font-display); font-weight: 500; font-size: 14px; line-height: 1.15; letter-spacing: -0.015em; color: var(--muted); }
.kp-sq { width: 56px; height: 56px; background: var(--fg); }
.kp-sq--sm { width: 16px; height: 16px; } .kp-sq--dot { display: block; width: 10px; height: 10px; border-radius: 50%; }
.kp-sq--round { border-radius: 50%; } .kp-sq--tall { width: 56px; height: 76px; }
.kp-sq--img { overflow: hidden; background: none; }
.kp-sq--img img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Hover is read from this fixed box (data-kui-on from:#id). The moved element takes no pointer events, so sliding away can never end or restart the hover. */
.kp-fx-hit { display: grid; place-items: center; width: 88px; height: 84px; }
.kp-fx-hit > * { pointer-events: none; }
.kp-fx-img, .kp-fx-ken { width: 72px; height: 84px; object-fit: cover; display: block; }
.kp-fx-ken { overflow: hidden; } .kp-fx-ken img { width: 100%; height: 100%; object-fit: cover; }
.kp-fx-t { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: clamp(15px, 1.3vw, 19px); line-height: 1.15; letter-spacing: -0.02em; text-align: center; }
.kp-fx-mq { width: 100%; overflow: clip; font-family: var(--font-display); font-weight: 600; font-size: 18px; white-space: nowrap; }
.kp-fx-mq > div { display: flex; width: max-content; }
.kp-fx-svg { width: 76px; height: 56px; fill: none; stroke: var(--fg); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; overflow: visible; }
.kp-fill { fill: var(--fg); stroke: none; }
.kp-track { stroke: var(--border); } .kp-meter { stroke: var(--fg); }
.kp-fx-bars { display: flex; align-items: flex-end; gap: 4px; width: 76px; height: 64px; }
.kp-fx-bars > div { flex: 1; height: 100%; background: var(--fg); }
.kp-fx-path { width: 120px; height: 60px; position: relative; }
.kp-fx-stars { position: relative; font-size: 20px; letter-spacing: 1px; color: var(--border); line-height: 1; }
.kp-fx-stars .filled { position: absolute; inset: 0; color: var(--fg); overflow: hidden; white-space: nowrap; width: 70%; }
.kp-fx-num { font-family: var(--font-display); font-weight: 600; font-size: clamp(20px, 2vw, 26px); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.kp-fx-amb { position: relative; width: 100%; height: 84px; overflow: hidden; background-color: var(--band); color: #e6e6e6; filter: grayscale(1); }
.kp-fx-amb--ink { background-color: #000; }
.kp-fill-all { position: absolute; inset: 0; }
.kp-fx-shapes { display: flex; gap: 18px; align-items: center; height: 60px; }
.kp-fx-orbit { position: relative; width: 56px; height: 56px; border: 1px solid var(--border); border-radius: 50%; }
.kp-fx-orbit > span { position: absolute; left: 50%; top: 50%; margin: -5px 0 0 -5px; }
.kp-fx-prog { position: relative; width: 100%; height: 4px; background: var(--border); overflow: hidden; }
.kp-fx-prog > * { position: absolute; inset: 0; display: block; }
.kp-fx-prog-f { background: var(--fg); transform-origin: left; }
.kp-fx-seg { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; width: 100%; }
.kp-fx-seg i { display: block; height: 5px; background: var(--fg); transform-origin: left; }
.kp-fx-skel { display: grid; gap: 8px; width: 100%; }
.kp-fx-skel > div { height: 10px; background: var(--border); }
.kp-fx-badge { display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--fg); color: var(--bg); font-family: var(--font-display); font-weight: 600; font-size: 15px; }
.kp-fx-field { position: relative; width: 100%; max-width: 170px; }
.kp-fx-input { width: 100%; padding: 8px 0; border: 0; border-bottom: 1px solid var(--border); background: transparent; color: var(--fg); font: inherit; font-size: 16px; }
.kp-fx-input:focus { outline: none; } .kp-fx-field label { position: absolute; left: 0; top: 8px; color: var(--muted); font-size: 15px; pointer-events: none; }
.kp-fx-range { width: 100%; max-width: 170px; accent-color: var(--fg); }
.kp-mini { min-height: var(--tap); padding: 0 14px; border: 1px solid var(--fg); border-radius: 999px; background: transparent; color: var(--fg); font: inherit; font-size: 15px; cursor: pointer; }
.kp-fx-beam { position: relative; padding: 2px; border-radius: 10px; }
.kp-fx-beam-in, .kp-fx-bdr-in { position: relative; padding: 12px 18px; border-radius: 8px; background: var(--bg); font-size: 15px; }
.kp-fx-bdr { position: relative; padding: 2px; border-radius: 10px; }
.kp-fx-bdr-ring { position: absolute; inset: 0; border-radius: 10px; }
/* The library's default rings are tinted; this page keeps color to the photographs. */
.kp-beam, .kp-fx-beam, .kp-fx-bdr-ring { filter: grayscale(1); }
.kp-tilt-p { width: 72px; height: 84px; } .kp-tilt-p img { width: 100%; height: 100%; object-fit: cover; }
.kp-fx-word { font-family: var(--font-display); font-weight: 600; font-size: 20px; border-bottom: 1px solid var(--fg); cursor: default; }
.kp-fx-zone { display: grid; place-items: center; width: 100%; height: 84px; background: var(--surface); font-size: 15px; }
.kp-fx-glass { display: grid; place-items: center; width: 100%; height: 84px; background: url(/theme-assets/leon-editorial/assets/kuinetic/m-modeling-20.webp) center/cover; }
.kp-fx-glass > div { padding: 8px 14px; color: #fff; font-size: 15px; }
.kp-fx-chip { width: 72px; height: 72px; touch-action: none; cursor: grab; }
.kp-fx-chip img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.kp-fx-cmp { position: relative; width: 84px; height: 84px; margin: 0; overflow: hidden; }
.kp-fx-cmp img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kp-fx-bg { display: grid; place-items: center; width: 100%; height: 84px; color: #fff; font-size: 15px; }
.kp-fx-lb a { display: block; width: 72px; height: 84px; } .kp-fx-lb img { width: 100%; height: 100%; object-fit: cover; }
.kp-pop { padding: 18px 26px; border: 1px solid var(--border); border-radius: 12px; background: var(--bg); color: var(--fg); font-size: 16px; }
.kp-fx-car { width: 100%; max-width: 110px; height: 84px; overflow: hidden; }
.kp-fx-list { list-style: none; margin: 0; padding: 0; height: 100%; }
.kp-fx-list li { height: 100%; } .kp-fx-list img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 1020px) { .kp-lib { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 720px) { .kp-lib { grid-template-columns: repeat(3, minmax(0, 1fr)); } .kp-fx { padding: 10px; min-height: 128px; } }
@media (max-width: 460px) { .kp-lib { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.kp-swap { line-height: 1.25; }

/* The floating replay button sits after <main>, so theme.css's "last dark section meets the footer" rule never matches here. */
.page-kuinetic .site-footer { margin-top: 0; }

/* ==========================================================================
   Tovu page (render/pages/tovu.html). Every class is prefixed `tv-`.
   One layout for every video: words in 3 columns, picture in 9 (the shape of Home's project cards).
   No image or video sits on a grey fill; a hairline marks the edge instead.
   ========================================================================== */
/* The theme's .btn is 325px minimum and full width on phones; on this page a button is as wide as its label. */
.page-tovu main .btn { min-width: 0; width: auto; gap: 16px; }

.tv-head { padding-top: clamp(32px, 4vw, 56px); }
.tv-lead { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); column-gap: 24px; align-items: end; margin-top: clamp(20px, 2.4cqi, 32px); }
.tv-lead-copy { display: flex; flex-direction: column; align-items: flex-start; gap: 20px; }
.page-head .tv-lead .lede { margin: 0; max-width: 16em; }
/* Capped by the window height, so the whole film and its controls fit below the nav in the first view. */
.tv-film { margin: 0; justify-self: end; width: min(100%, calc((100svh - var(--nav-h) - 168px) * 16 / 9)); }
.tv-film video { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 24px; background: #000; outline: var(--hair); outline-offset: -1px; }
.section--dark .tv-film video { outline: var(--hair-dark); }

/* Four across from 761px; on phones the theme's plain .facts list. */
.tv-facts { margin-top: clamp(32px, 4cqi, 56px); }
@media (min-width: 761px) {
  .tv-facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: 24px; }
  .tv-facts li { flex-direction: column-reverse; justify-content: flex-end; gap: 6px; }
  .tv-facts li:last-child { border-bottom: 0; }
  .tv-facts li span:last-child { text-align: left; font-size: var(--fs-small); }
}

/* The stack. Each card has to fit under the nav and the three cards' offsets at any window height, so its video is sized by height too. */
.tv-stack { --tv-step: 12px; list-style: none; margin: clamp(48px, 6cqi, 80px) 0 0; padding: 0; display: grid; gap: 16px; }
.tv-card { --tv-pad: clamp(16px, 2cqi, 28px); display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); column-gap: 24px; padding: var(--tv-pad); background: var(--band); border: var(--hair-dark); border-radius: 24px; }
/* Number and title at the top: the next card covers a card from the bottom up, so the top stays readable longest. */
.tv-card-meta { display: flex; flex-direction: column; justify-content: flex-start; gap: 12px; min-width: 0; }
.tv-num { font-family: var(--font-mono); font-size: var(--fs-small); letter-spacing: 0; color: #9A9A9A; font-variant-numeric: tabular-nums; }
.tv-title { font-size: clamp(24px, 2.6cqi, 36px); line-height: 1.08; }
/* Keeps the grey half of the sentence on its own line when it fits. */
#tovu-title .dim { display: inline-block; }
.tv-media { justify-self: end; width: min(100%, calc((100svh - var(--nav-h) - 4 * var(--tv-step) - 32px - 2 * var(--tv-pad)) * 1.6)); }
.tv-media video { width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; border-radius: 12px; background: #000; }

/* Admin screens. Rows share one height because each tile grows by its own ratio. */
.tv-shots { display: grid; gap: clamp(28px, 3cqi, 40px); margin-top: clamp(32px, 4cqi, 56px); }
.tv-row { display: flex; gap: 16px; }
.tv-tile { --r: 1.6; flex: var(--r) 1 0; min-width: 0; margin: 0; }
/* 1.36 crops about 15% of the screenshot's width, which is its sidebar; with --x:100% the content and assistant stay whole. */
.tv-tile--narrow { --r: 1.36; }
/* clip, not hidden: the hover scale stays inside and the frame does not become a scroller. */
.tv-shot { display: block; aspect-ratio: var(--r); overflow: clip; border-radius: 16px; outline: var(--hair); outline-offset: -1px; cursor: zoom-in; }
.tv-shot:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }
.tv-shot img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: var(--x, 0%) 0; transition: scale .6s var(--ease-out); }
@media (hover: hover) { .tv-shot:hover img { scale: 1.02; } }
.tv-tile figcaption { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; margin-top: 10px; font-size: clamp(17px, 1.5cqi, 20px); letter-spacing: -0.03em; }
.tv-tile figcaption span { font-size: 15px; font-weight: 400; letter-spacing: -0.01em; color: var(--muted); }

#film .tv-lead { margin-top: clamp(32px, 4cqi, 56px); }

@media (max-width: 767px) {
  .tv-card { grid-template-columns: minmax(0, 1fr); row-gap: 12px; padding: 0; background: none; border: 0; border-radius: 0; }
  .tv-card-meta { flex-direction: row; justify-content: flex-start; align-items: baseline; gap: 12px; }
  .tv-media { width: 100%; }
  .tv-stack { gap: 40px; }
}
@media (max-width: 760px) {
  .tv-lead { grid-template-columns: minmax(0, 1fr); row-gap: 24px; }
  .tv-film { width: 100%; }
  .tv-film video { border-radius: 16px; }
  .tv-row { flex-wrap: wrap; gap: clamp(28px, 3cqi, 40px); }
  .tv-tile, .tv-tile--narrow { --r: 1.6; flex: 0 0 100%; }
  .tv-shot { border-radius: 12px; }
}
@media (prefers-reduced-motion: reduce) { .tv-shot img { transition: none; } }
