/* Webus motion kit: shared by the prospect pages (home.html.j2) and the Webus site (scripts/build_site.py).
   Rules: nothing is hidden without JS or under reduced motion; only transform/opacity/clip-path move;
   reveal classes stay named .rise / .reveal (the contrast scanner forces them visible). */
[data-count]{font-variant-numeric:tabular-nums}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.btn{transition:background .2s,color .2s,transform .2s,translate .3s cubic-bezier(.2,.7,.2,1)}
@media (pointer:fine){.btn{translate:var(--mx,0px) var(--my,0px)}}

/* marquee: static and wrapped by default (reduced motion, no JS), scrolling only when motion is welcome */
.marq{border-block:1px solid var(--line);padding:18px 0;overflow:hidden;position:relative}
.marq-track{display:flex;flex-wrap:wrap;justify-content:center;gap:6px 0}
.marq-set{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;justify-content:center;flex:none}
.marq-set[aria-hidden]{display:none}
.marq-set li{font:400 clamp(20px,2vw,26px)/1.3 var(--display,Georgia,serif);display:flex;align-items:center;white-space:nowrap}
.marq-set li::after{content:"";width:6px;height:6px;border-radius:50%;background:var(--accent);margin:0 26px;flex:none}
.marq-btn{all:unset;box-sizing:border-box;cursor:pointer;display:none;position:absolute;right:8px;top:50%;translate:0 -50%;width:44px;height:44px;border-radius:50%;border:1.5px solid var(--line);background:var(--paper);color:var(--ink);place-items:center;z-index:2}
.marq-btn:focus-visible{outline:3px solid var(--soft);outline-offset:2px}
.marq-btn svg{width:16px;height:16px;fill:currentColor}
.marq-btn .play{display:none}.marq.paused .marq-btn .play{display:block}.marq.paused .marq-btn .pause{display:none}

/* gallery tiles + lightbox */
.tile{all:unset;box-sizing:border-box;display:block;overflow:hidden;border-radius:var(--radius);cursor:zoom-in;position:relative}
.tile:focus-visible{outline:3px solid var(--soft);outline-offset:3px}
dialog.lb{border:0;padding:0;background:transparent;max-width:min(96vw,1400px);max-height:94vh;overflow:visible}
dialog.lb::backdrop{background:rgba(6,8,10,.88)}
dialog.lb img{display:block;max-width:100%;max-height:88vh;margin:0 auto;border-radius:var(--radius)}
dialog.lb .x{all:unset;box-sizing:border-box;cursor:pointer;position:absolute;right:0;top:-52px;width:44px;height:44px;border-radius:50%;background:#fff;color:#000;display:grid;place-items:center;font:600 22px/1 system-ui,sans-serif}
dialog.lb .x:focus-visible{outline:3px solid var(--soft);outline-offset:2px}
.lift{transition:translate .35s cubic-bezier(.2,.7,.2,1),box-shadow .35s}
.lift:hover{translate:0 -4px;box-shadow:0 18px 40px -22px rgba(0,0,0,.45)}

@media (prefers-reduced-motion:no-preference){
  html{scroll-behavior:smooth}
  /* reveals: hidden only once JS has promised to reveal them */
  .js .rise{opacity:0;transform:translateY(28px);transition:opacity var(--rev,.9s) ease calc(var(--i,0)*var(--stg,90ms)),transform var(--rev,.9s) cubic-bezier(.2,.7,.2,1) calc(var(--i,0)*var(--stg,90ms))}
  .js .rise.in{opacity:1;transform:none}

  /* hero title: words rise out of a mask. If the script dies the title still appears after 2.2s. */
  .js .hero h1,.js h1[data-words]{opacity:0;animation:failsafe 0s linear 2.2s forwards}
  .js .hero h1.ws,.js h1[data-words].ws{opacity:1;animation:none}
  @keyframes failsafe{to{opacity:1}}
  .ws .w{display:inline-block;overflow:hidden;vertical-align:top;padding:0 .08em .16em 0;margin:0 -.08em -.16em 0}
  .ws .w>i{display:inline-block;font-style:inherit;transform:translateY(112%);animation:wup var(--rev,.9s) cubic-bezier(.2,.7,.2,1) calc(.12s + var(--n)*65ms) forwards}
  @keyframes wup{to{transform:none}}
  [data-enter]{animation:fadeUp 1s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--d,0)*1ms)}
  @keyframes fadeUp{from{opacity:0;transform:translateY(22px)}}

  /* marquee */
  .js .marq-track{flex-wrap:nowrap;justify-content:flex-start;width:max-content;animation:marq 46s linear infinite}
  .js .marq-set{flex-wrap:nowrap}
  .js .marq-set[aria-hidden]{display:flex}
  .js .marq.paused .marq-track{animation-play-state:paused}
  .js .marq-btn{display:grid}
  .js .marq:hover .marq-track,.js .marq:focus-within .marq-track{animation-play-state:paused}
  .js .marq::after{content:"";position:absolute;inset:0 0 0 auto;width:84px;background:linear-gradient(90deg,transparent,var(--paper) 62%);pointer-events:none}
  @keyframes marq{to{transform:translateX(-50%)}}

  /* gallery: slow zoom on hover */
  .tile img{transition:transform 1s cubic-bezier(.2,.7,.2,1)}
  .tile:hover img{transform:scale(1.05)}

  /* timeline: the line draws, then the dots pop in */
  .js .timeline::before{clip-path:inset(0 100% 0 0);transition:clip-path 1.8s cubic-bezier(.2,.7,.2,1)}
  .js .timeline.in::before{clip-path:inset(0)}
  .js .timeline li::before{transform:scale(0);transition:transform .6s cubic-bezier(.3,1.6,.5,1) calc(.3s + var(--i,0)*var(--stg,90ms))}
  .js .timeline li.in::before{transform:none}
  @media (max-width:960px){.js .timeline::before{clip-path:inset(0 0 100% 0)}}

  /* theme switch: a circle of the new theme grows from the button */
  html.theming::view-transition-old(root),html.theming::view-transition-new(root){animation:none;mix-blend-mode:normal}
  html.theming::view-transition-old(root){z-index:1}
  html.theming::view-transition-new(root){z-index:2}

  @supports (animation-timeline:scroll()){
    /* reading progress bar, no JS */
    body::before{content:"";position:fixed;inset:0 0 auto 0;height:3px;z-index:60;background:linear-gradient(90deg,var(--accent),var(--soft));transform:scaleX(0);transform-origin:0 50%;animation:prog linear both;animation-timeline:scroll(root)}
    @keyframes prog{to{transform:scaleX(1)}}
    /* hero: the photo drifts slower than the page, the copy lifts away */
    .hero>img{inset:-8% 0 auto 0;height:116%;animation:slow 14s ease-out both,par linear both;animation-timeline:auto,scroll(root);animation-range:normal,0px 100vh}
    @keyframes par{to{translate:0 6%}}
    .hero>.wrap{animation:heroOut linear both;animation-timeline:view();animation-range:exit 0% exit 80%}
    @keyframes heroOut{to{transform:translateY(-8vh)}}
  }
  @keyframes slow{from{transform:scale(1.07)}to{transform:scale(1)}}
  .hero.plain::before,.hero.split::before{content:"";position:absolute;inset:-25%;pointer-events:none;background:radial-gradient(38% 38% at 72% 28%,color-mix(in srgb,var(--accent) 26%,transparent),transparent 70%);animation:drift 14s ease-in-out both}
  @keyframes drift{from{transform:translate3d(-4%,2%,0) scale(1)}to{transform:translate3d(6%,-4%,0) scale(1.15)}}
}
