/* Aurora — motion layer
   Zie MOTION-PLAN.md. Eén idee: niets wordt gegoten, alles wordt geprint. Elke
   reveal groeit van de onderrand omhoog, en terugscrollen print hem weg.

   Dit bestand bezit twee dingen en niets anders: de from-states (zodat er nooit
   iets kan flitsen voordat JS er is) en de vormen die JS niet kan bezitten
   zonder ze elke frame te herschrijven. Alle bewegende getallen staan in
   motion.js. */

/* --rv is het enige getal in de clip. De pseudo-element printkop leest hem, dus
   inherits: true is DRAAGKRACHTIG, niet netheid: met inherits:false blijft
   ::after op de initial-value staan en tekent de kop nooit. Zie
   _lib/BUILD-PITFALLS.md 29. En als getal in plaats van string, want een
   clip-path-string onder scrub blijft op zijn eindwaarde staan, wet 45. */
@property --rv { syntax: '<percentage>'; inherits: true; initial-value: 0%; }
@property --dy { syntax: '<length>';     inherits: false; initial-value: 0px; }
@property --vel { syntax: '<length>';    inherits: true;  initial-value: 0px; }
@property --dspeed { syntax: '<number>'; inherits: false; initial-value: 0; }
/* ook door ::after gelezen, dus ook inherits: true en ook draagkrachtig */
@property --print-on { syntax: '<number>'; inherits: true; initial-value: 0; }

/* ---------------------------------------------------------------------------
   PARK
   De rust-toestand van alles wat motion.js overneemt. Staat hier en niet in JS,
   want een from-state die pas bestaat als een script draait is een flits.

   motion.js parkeert dezelfde elementen nog een keer inline met gsap.set en
   wisselt daarna .has-motion om naar .motion-ready. Wat JS niet heeft
   overgenomen wordt op dat moment gewoon zichtbaar, dus een init die faalt kan
   nooit een blok onzichtbaar achterlaten. De head-snippet haalt .has-motion er
   sowieso af als motion.js zich binnen 2,5s niet meldt.
   --------------------------------------------------------------------------- */
.has-motion [data-rise],
.has-motion [data-mob] section > *,
.has-motion [data-mob] > footer > * { opacity: 0; }

/* ---------------------------------------------------------------------------
   HET PRINTBED
   --------------------------------------------------------------------------- */

/* Elk blok dat geprint wordt. De clip loopt van boven naar beneden dicht, dus
   het beeld groeit vanaf de onderrand omhoog. overflow-clip-margin staat in em
   en blijft onder de reisafstand: stokletters en schaduwen overleven, er lekt
   niets tijdens de rit (wet 18). */
/* De clip-marge staat in em en blijft onder de reisafstand (wet 18), maar hij
   moet OOK onder de afstand tot het volgende element blijven: een marge van
   0,34em op een cijfer van 76px is 26px, en dat dekt het label 12px eronder af.
   Gemeten op de vier footprint-getallen, 2026-07-30: vier occlusiemeldingen die
   met deze twee waarden alle vier verdwijnen. */
[data-rv] {
  clip-path: inset(var(--rv) 0 0 0);
  overflow: clip;
  overflow-clip-margin: 0.16em;
}

/* De printkop. Precies drie op de pagina, en dat aantal is een controle in de
   harness, geen belofte in de tekst. Hij zit op de voorrand van de clip: alles
   boven --rv is weggeknipt, de regel staat er net onder en is dus het eerste
   wat je ziet bewegen. */
[data-print] { position: relative; }
[data-print]::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: var(--rv);
  height: 2px;
  background: var(--print-ink, #FF5C33);
  opacity: var(--print-on, 0);
  pointer-events: none;
  z-index: 6;
}

/* Regelmasker voor koppen. De kop knipt, de regel erbinnen rijdt omhoog: twee
   nodes, twee snelheden, en geen enkele property die twee eigenaren heeft. */
[data-mask] {
  display: block;
  overflow: clip;
  overflow-clip-margin: 0.09em;
}
[data-ln] { display: block; will-change: transform; }

/* Diepte. translate is een eigen property, los van transform, dus de gescrubde
   parallax en de reveal-y van GSAP zitten elkaar niet in de weg (wet 44, één
   eigenaar per property). --vel is de geëasede scrollsnelheid, staat op :root
   en wordt één keer per frame geschreven. */
[data-depth] { translate: 0 calc(var(--dy) + var(--vel) * var(--dspeed)); }

/* Fotoput: de clip zit op de put, de schaal op de foto. */
[data-well] { overflow: hidden; }
[data-well] > img { will-change: transform; }

/* ---------------------------------------------------------------------------
   STATE
   --------------------------------------------------------------------------- */

/* Wet 5: sluiten gaat sneller dan openen. Openen is een aanbod en mag genoten
   worden, sluiten is een besluit dat de lezer al genomen heeft en moet niet
   opnieuw bekeken worden. De duur staat inline op het element, dus dit moet
   !important zijn om er overheen te komen. */
[data-faqbody].is-closing,
[data-mfaqbody].is-closing { transition-duration: .22s !important; }
[data-faqmark].is-closing,
[data-mfaqmark].is-closing { transition-duration: .2s !important; }

/* Eén curve voor de hele pagina. De bestaande knoppen hebben hem al, de rest
   liep op vier verschillende. */
[data-view], [data-size], [data-filter], [data-msize] {
  transition: transform .26s cubic-bezier(.2,.8,.3,1),
              background .22s cubic-bezier(.2,.8,.3,1),
              border-color .22s cubic-bezier(.2,.8,.3,1),
              color .22s cubic-bezier(.2,.8,.3,1) !important;
}
/* Indrukken is korter dan loslaten, zelfde reden als de accordeon. */
[data-view]:active, [data-size]:active, [data-filter]:active, [data-msize]:active {
  transform: translateY(1px) scale(.985);
  transition-duration: .09s !important;
}

/* De step-fills lopen op scaleX in plaats van width: een per-frame breedte op
   drie elementen is layout, een schaal is compositor. */
[data-stepfill] {
  width: 100% !important;
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* ---------------------------------------------------------------------------
   HYGIENE
   --------------------------------------------------------------------------- */

/* will-change alleen op wat echt elke frame beweegt. Op alles zetten is een
   laag per element en dat is duurder dan wat het bespaart. */
[data-rise] { will-change: auto; }
[data-rise].is-moving { will-change: transform, clip-path; }

/* De poort staat om de hele init, niet om elke tween: met reduced motion wordt
   .has-motion nooit gezet, dus er wordt niets geparkeerd en de pagina staat in
   rust en klopt. Dit blok is de vangnetlaag voor het geval een van beide toch
   ergens blijft hangen. */
@media (prefers-reduced-motion: reduce) {
  .has-motion [data-rise],
  .has-motion [data-mob] section > *,
  .has-motion [data-mob] > footer > * { opacity: 1; }
  [data-rv] { clip-path: none; }
  [data-print]::after { display: none; }
  [data-depth] { translate: none; }
  [data-ln] { transform: none !important; }
}
