/* ==========================================================================
   MOTION — the drawing set gets drawn.
   Load AFTER site.css. Everything that hides or offsets anything lives
   inside the no-preference query at the bottom. Nothing above it can make
   content invisible.
   ========================================================================== */

/* ---- 1. Interaction. Costs nothing; site.css's blanket reduce rule
         already strips these transitions for a reduced-motion visitor,
         leaving the same hover/press states as instant swaps. ---- */
.btn{transition:background-color 140ms linear,border-color 140ms linear,transform 90ms cubic-bezier(.3,.7,.3,1)}
.btn:active{transform:translateY(1px)}

.nav a{position:relative}
.nav a::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;background:var(--snap);transform:scaleX(0);transform-origin:left center;transition:transform 170ms cubic-bezier(.2,.7,.3,1)}
.nav a:hover::after,.nav a:focus-visible::after{transform:scaleX(1)}
.nav a:hover{border-bottom-color:transparent}   /* the drawn line replaces the hard one */
.nav a[aria-current]{border-bottom-color:var(--snap)}   /* state, never animated — must stay last */
.nav a[aria-current]::after{display:none}

.device{transition:transform 180ms cubic-bezier(.2,.7,.3,1),box-shadow 180ms linear,border-color 140ms linear}
@media (hover:hover){.device:hover{transform:translateY(-3px);box-shadow:0 12px 24px -14px rgba(5,42,92,.5)}}
.device:focus-visible{transform:translateY(-3px);box-shadow:0 12px 24px -14px rgba(5,42,92,.5)}
.device:active{transform:translateY(0) scale(.995);box-shadow:none}

.head{transition:border-color 220ms linear}
.head.is-stuck{border-bottom-color:var(--rule)}

.stamp{transform-origin:0 100%}   /* not a motion property: pivots the static -3deg too,
                                     so every visitor gets the identical resting position */

/* ---- 2..6 ---- */
@media (prefers-reduced-motion:no-preference){

  /* 2. The title block issues, like a sheet coming off the plotter.
        Trigger: page load. 460ms, cubic-bezier(.32,.72,.3,1), 60ms delay.
        clip-path does not affect layout, so nothing below it shifts. */
  .issued .tb{position:relative;animation:tb-issue 460ms cubic-bezier(.32,.72,.3,1) 60ms both}
  .issued .tb::after{
    content:"";position:absolute;inset:0;pointer-events:none;
    background:linear-gradient(to bottom,transparent 0 calc(100% - 2px),var(--brass) calc(100% - 2px));
    animation:tb-head 460ms cubic-bezier(.32,.72,.3,1) 60ms both}
  @keyframes tb-issue{from{clip-path:inset(0 0 100% 0)}to{clip-path:inset(0 0 0 0)}}
  @keyframes tb-head{from{transform:translateY(-100%);opacity:1}80%{opacity:1}to{transform:translateY(0);opacity:0}}

  /* 3. The dimension line draws itself at every section head.
        Trigger: IntersectionObserver. Lead line 220ms, tick 140ms @170ms,
        extension line 600ms @190ms — total 790ms, all on 1px hairlines. */
  .rule::before,.rule::after{transform-origin:left center;transition:transform 600ms cubic-bezier(.16,.72,.24,1) 190ms}
  .rule::before{transition-duration:220ms;transition-delay:0ms}
  .rule i{transition:transform 140ms linear 170ms}
  .rule.will-draw::before,.rule.will-draw::after{transform:scaleX(0);transition:none}
  .rule.will-draw i{transform:scaleY(0);transition:none}

  /* 4. Grouped items rise into place, in their own reading order.
        Trigger: IntersectionObserver. 420ms, cubic-bezier(.22,.61,.36,1),
        12px, staggered 70-110ms and capped so no group ever runs long. */
  .rise{transition:opacity 420ms cubic-bezier(.22,.61,.36,1) var(--d,0ms),transform 420ms cubic-bezier(.22,.61,.36,1) var(--d,0ms)}
  .rise.will-rise{opacity:0;transform:translateY(12px);transition:none}

  /* 5. The tape measure pulls out of the hook. 760ms.
        The explicit inset(0) base is load-bearing: clip-path:none does NOT
        interpolate to inset(), so without it the tape SNAPS open. */
  .tape .ticks{clip-path:inset(0 0 0 0);transition:clip-path 760ms cubic-bezier(.2,.72,.22,1)}
  .tape .ticks.will-pull{clip-path:inset(0 100% 0 0);transition:none}
  @media (max-width:640px){.tape .ticks.will-pull{clip-path:inset(0 0 100% 0)}}
    /* the phone grid is 4x3, so it unrolls downward the way the grid flows */

  /* 6. The stamp lands. 300ms, decelerating hard — it arrives and stops.
        No spring, no wobble, no second bounce. */
  .stamp{animation:stamp-land 300ms cubic-bezier(.18,.78,.36,1) 420ms both}
  @keyframes stamp-land{
    from{transform:rotate(-7deg) scale(1.3);opacity:0}
    55%{opacity:1}
    to{transform:rotate(-3deg) scale(1);opacity:1}}
}

**`transition:none` in every armed state is not decoration — it is bug fix #1.** See below.
