/* ══ STERLING MOTION ══ currency does not bounce, it reveals.
   THIS FILE IS THE FINISHED PLATE. Every rule installing a *start* state sits
   behind `html.motion`, which only motion.js adds — no JS, no class, no start
   state, the engraving is already done. transform / opacity / dashoffset only;
   no easing leaves 0..1, so nothing overshoots. */
:root{--mo-settle:cubic-bezier(.22,.61,.36,1)} /* decelerate onto the mark */

/* paper depth — a sheet resting on a sheet, not a card floating over */
.paper{box-shadow:0 1px 1px -1px rgba(22,35,58,.13),0 5px 9px -8px rgba(22,35,58,.16),
  0 14px 28px -22px rgba(22,35,58,.24)}

/* tabular numerals: a counting figure cannot shift its own row */
[data-count]{font-variant-numeric:tabular-nums lining-nums;
  display:inline-block;white-space:nowrap}

/* line drawing — JS writes --mo-len from getTotalLength(). Absent it,
   dasharray resolves to `none` and the stroke is whole: the fail-open path.
   The burin bites in, cuts evenly, lifts — half the ink at half the time, so
   a stroke's stated duration is the duration you actually see. */
.motion [data-draw]{stroke-dasharray:var(--mo-len,none);
  stroke-dashoffset:var(--mo-len,0);
  transition:stroke-dashoffset var(--mo-dur,900ms) cubic-bezier(.45,.05,.55,.95) var(--mo-delay,0ms)}
.motion [data-draw].mo-etched{stroke-dashoffset:0}
.mo-cut,.mo-cut *{transition:none!important} /* replay: rewind, do not animate */

/* guilloche — one cycle 26s, felt not seen */
.breathe{transform-origin:50% 50%}
svg .breathe{transform-box:fill-box}
.motion .breathe{animation:mo-breathe 26s cubic-bezier(.37,0,.63,1) infinite}
@keyframes mo-breathe{0%,100%{transform:scale(1) rotate(0deg)}
  50%{transform:scale(1.0075) rotate(.5deg)}}

/* tilt to catch the light — 2.5deg ceiling, a sheen travels */
.tilt{position:relative;overflow:hidden}
.motion .tilt{transform:perspective(900px) rotateX(var(--mo-rx,0deg)) rotateY(var(--mo-ry,0deg));
  transition:transform 420ms var(--mo-settle)}
.motion .tilt.mo-lit{transition-duration:110ms}
.motion .tilt::after{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;
  background:linear-gradient(102deg,#fff0 36%,#ffffff80 50%,#fff0 64%);
  transform:translate3d(var(--mo-sheen,0),0,0);transition:opacity 320ms var(--mo-settle)}
.motion .tilt.mo-lit::after{opacity:1;transition-duration:150ms}

/* reduced motion gets the finished plate at once */
@media (prefers-reduced-motion:reduce){
  .motion [data-draw]{stroke-dasharray:none;stroke-dashoffset:0;transition:none}
  .motion .breathe{animation:none}
  .motion .tilt{transform:none;transition:none}
  .motion .tilt::after{display:none}}

/* frame tracing — the plate's rules draw themselves. Transform only, so the
   compositor carries it; geometry and colour stay in the page's own sheet. */
/* --tr-* not --mo-*: the draw engine sets --mo-dur/--mo-delay inline on every
   [data-draw] path, and those inherit, so a path nested inside a traced
   element would silently pick up the frame's timing. */
.motion [data-trace] .e{transition:transform var(--tr-dur,200ms) linear var(--tr-delay,0ms)}
.motion [data-trace] .e-t,.motion [data-trace] .e-b{transform:scaleX(0)}
.motion [data-trace] .e-r,.motion [data-trace] .e-l{transform:scaleY(0)}
.motion [data-trace].mo-traced .e{transform:none}

/* the plate inks up: ornament first, then the face rises onto it */
/* Struck, not faded. An opacity ramp prints the whole note in an intermediate
   grey that is in no sealed ink on its way to the real one, which is the exact
   photocopy look the brand exists to avoid, and it spent most of the runtime
   sitting on a blank plate first. Each layer is now wiped on at FINAL ink, in
   plate order, so at every instant what is on the paper is correctly printed
   and what is not there simply is not there yet. */
.motion [data-cue] .note-orn{clip-path:inset(0 0 100% 0);
  transition:clip-path 300ms cubic-bezier(.3,.05,.2,1) 420ms}
.motion [data-cue].mo-cued .note-orn{clip-path:inset(0 0 0 0)}
.motion [data-cue] .face{clip-path:inset(0 0 100% 0);
  transition:clip-path 320ms cubic-bezier(.3,.05,.2,1) 700ms}
.motion [data-cue].mo-cued .face{clip-path:inset(0 0 0 0)}

@media (prefers-reduced-motion:reduce){
  .motion [data-trace] .e{transform:none;transition:none}
  .motion [data-cue] .note-orn,.motion [data-cue] .face{clip-path:none;transition:none}}

/* the map is struck as one plate: a press wipe down the sheet. 101 rows is 404
   strokes, and dash animating each of them cost half the main thread; one
   clip on one element buys the same reading for a fraction of the work. */
.motion [data-cue] svg{clip-path:inset(0 0 100% 0);
  transition:clip-path 1500ms cubic-bezier(.32,.04,.22,1)}
.motion [data-cue].mo-cued svg{clip-path:inset(0 0 0 0)}
@media (prefers-reduced-motion:reduce){
  .motion [data-cue] svg{clip-path:none;transition:none}}

/* ══ PRINT ══ A sheet on its way to a printer is finished, whatever the timer
   thinks. motion.js also calls settle() on beforeprint, but a print stylesheet
   must stand on its own: Save as PDF from some browsers, and any print path
   that does not fire beforeprint, would otherwise commit a start state to
   paper. Start states are blank; blank is not a thing to print. */
@media print{
  .motion [data-draw]{stroke-dasharray:none!important;stroke-dashoffset:0!important;
    transition:none!important}
  .motion [data-trace] .e{transform:none!important;transition:none!important}
  .motion [data-cue] .note-orn,.motion [data-cue] .face,.motion [data-cue] svg{
    clip-path:none!important;transition:none!important}
  .motion .breathe{animation:none!important}
  .motion .tilt{transform:none!important}
  .motion .tilt::after{display:none!important}
  .motion .exhibit .fr-seg{transform:none!important;transition:none!important}
  .motion ol.run::before{transform:none!important;transition:none!important}
  [data-count]{min-width:0!important}
}
