/* =========================================================
   NezhaGate motion layer · 「墨韵」 (2026-09-27)
   Ideas were collected from Rare UI (rareui.com); all code here is our own.
   Every rule hangs off an fx-* class on <html>. A tiny inline head script
   adds them (and skips all motion under prefers-reduced-motion), so with
   the classes absent the page renders exactly as it does today.
   ========================================================= */

:root{--nzm-g:clamp(24px,4vw,64px);--nzm-ease:cubic-bezier(.2,.8,.2,1);--nzm-spring:cubic-bezier(.34,1.56,.64,1)}

/* ---------- 0 · gutters + layout ----------
   .hero / .section / .footer-inner sit on a .wrap, but the .hero and .section padding
   shorthands zero .wrap's 40px side padding, so from 981px to ~1520px the whole page
   sat flush on the screen edge. Narrowing the box instead of padding it leaves the
   1920px layout exactly as it is. */
@media(min-width:981px){
  .fx-gutter .wrap.hero,.fx-gutter .wrap.section,.fx-gutter .topbar-inner,.fx-gutter .wrap.footer-inner{
    width:min(var(--maxw),calc(100% - 2*var(--nzm-g)))}
  .fx-gutter .wrap.footer-inner{padding-left:0;padding-right:0}
  /* the copy column is ~2 gutters narrower now; 5.6vw was tuned to fill the old one exactly and
     would push line one onto two lines. Same 76px cap, so from ~1490px up nothing changes. */
  .fx-gutter .hero h1{font-size:clamp(44px,5.1vw,76px)}
  /* "why NezhaGate": three cards in an auto-fill grid left a hole in column four */
  .fx-gutter .section .grid:has(> .card:nth-child(3):last-child){grid-template-columns:repeat(3,minmax(0,1fr))}
}
/* phones: the 2026-09-10 mobile hero rule (.hero{padding:26px 0 22px}) zeroed the side padding again,
   so the hero copy and pictures touched both screen edges while every section below keeps 20px */
@media(max-width:600px){
  .fx-gutter .wrap.hero{padding-left:20px;padding-right:20px}
}

/* ---------- B · headline: three beats, then one brush stroke ----------
   The entrance plays on the first page view of a session (.nzm-first); after that the page is simply there. */
@keyframes nzm-rise{from{transform:translateY(var(--nzm-rise,16px));filter:blur(var(--nzm-blur,4px))}to{transform:none;filter:none}}
.fx-title .hero-band .hero{animation:none}   /* replaces the old whole-hero floatUp */
.nzm-first.fx-title .hero-band .hero-copy > *{animation:nzm-rise .9s var(--nzm-ease) both}
.nzm-first.fx-title .hero-band .hero-copy > .hero-title{animation:none;--nzm-rise:.28em;--nzm-blur:8px}
.nzm-first.fx-title .hero-band .hero-copy > .lead{animation-delay:.5s}
.nzm-first.fx-title .hero-band .hero-copy > .hero-actions{animation-delay:.6s}
.nzm-first.fx-title .hero-band .hero-copy > .hero-bonus{animation-delay:.66s}
.nzm-first.fx-title .hero-band .hero-copy > .hero-checks{animation-delay:.7s}
.nzm-first.fx-title .hero-band .hero-title > span{animation:nzm-rise 1s var(--nzm-ease) both;animation-delay:.1s}
.nzm-first.fx-title .hero-band .hero-title > .hero-beats{animation:none}
.nzm-first.fx-title .hero-band .hero-title .beat{display:inline-block;animation:nzm-rise 1s var(--nzm-ease) both;animation-delay:calc(.08s + var(--i,0)*.09s)}
.nzm-first.fx-title .hero-band .hero-title > span:last-child{animation-delay:.4s}
.nzm-first.fx-title .hero-band .collage{animation:nzm-rise 1.1s .15s var(--nzm-ease) both;--nzm-rise:16px;--nzm-blur:0px}
/* the ticks stamp in one by one */
@keyframes nzm-pop{from{transform:scale(0) rotate(-45deg)}to{transform:none}}
.nzm-first.fx-title .hero-band .hero-checks span:before{animation:nzm-pop .55s var(--nzm-spring) both}
.nzm-first.fx-title .hero-band .hero-checks span:nth-child(1):before{animation-delay:.95s}
.nzm-first.fx-title .hero-band .hero-checks span:nth-child(2):before{animation-delay:1.03s}
.nzm-first.fx-title .hero-band .hero-checks span:nth-child(3):before{animation-delay:1.11s}
.nzm-first.fx-title .hero-band .hero-checks span:nth-child(4):before{animation-delay:1.19s}
/* the brush stroke under line two ("一个接口" / "One API") */
.hero-key{position:relative}
.nzm-brush{display:none}
.fx-title .hero-title > .hero-key{align-self:flex-start;isolation:isolate}
.fx-title .nzm-brush{display:block;position:absolute;left:-.05em;bottom:-.16em;width:calc(100% + .14em);height:.26em;
  z-index:-1;pointer-events:none;overflow:visible;color:var(--accent);opacity:.9}
.nzm-first.fx-title .nzm-brush{clip-path:inset(0 100% 0 0);animation:nzm-brush .85s .95s cubic-bezier(.7,0,.25,1) forwards}
[dir=rtl] .fx-title .nzm-brush{transform:scaleX(-1)}
[dir=rtl] .nzm-first.fx-title .nzm-brush{clip-path:inset(0 0 0 100%)}
@keyframes nzm-brush{to{clip-path:inset(0 0 0 0)}}

/* ---------- A · the collage paints itself: a drop of ink, dark strokes first, washes last ---------- */
.fx-reveal .collage figure{position:relative}
/* first paint: rice-paper blocks until the script takes over; if the script never
   arrives they lift on their own, so a failed load can never hide the pictures */
.nzm-intro.fx-reveal .collage figure:after{content:"";position:absolute;inset:0;z-index:2;background:var(--bg-2);
  animation:nzm-cover-out .4s 2.5s forwards}
.fx-reveal .collage figure.nzm-genning:after{content:none}
@keyframes nzm-cover-out{to{opacity:0;visibility:hidden}}
.nzm-gen{position:absolute;inset:0;width:100%;height:100%;z-index:2;display:block;transition:opacity .28s ease}
.nzm-gen.nzm-done{opacity:0}
.nzm-pill{position:absolute;left:12px;bottom:12px;z-index:3;max-width:calc(100% - 24px);display:flex;align-items:center;gap:7px;
  padding:6px 11px 6px 9px;border-radius:999px;background:rgba(18,24,28,.46);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  color:#fff;font-size:11.5px;font-weight:600;line-height:1.3;letter-spacing:.01em;pointer-events:none;
  opacity:0;transform:translateY(5px);transition:opacity .35s ease,transform .35s var(--nzm-ease)}
.nzm-pill.on{opacity:1;transform:none}
.nzm-pill i{flex:none;width:6px;height:6px;border-radius:50%;background:#9BD5AE;animation:nzm-blink 1.1s ease-in-out infinite}
/* the prompt types itself out, caret and all */
.nzm-pill b{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.nzm-pill b:after{content:"";display:inline-block;width:1.5px;height:1.05em;margin-left:2px;vertical-align:-.2em;background:currentColor;
  animation:nzm-caret .9s steps(1) infinite}
@keyframes nzm-caret{50%{opacity:0}}
@keyframes nzm-blink{0%,100%{opacity:.35}50%{opacity:1}}

/* ---------- 1 · CTA pair: the hovered one swells, its neighbour gets nudged ---------- */
.fx-cta .hero-actions .btn{transition:transform .55s var(--nzm-spring),background-color .15s,border-color .15s,box-shadow .2s}
.fx-cta .hero-actions .btn:hover{transform:scale(1.045)}
.fx-cta .hero-actions .btn:active{transform:scale(.96);transition-duration:.12s}
.fx-cta .hero-actions:has(.btn-accent:hover) .btn-ghost{transform:translateX(-8px)}
.fx-cta .hero-actions:has(.btn-ghost:hover) .btn-accent{transform:translateX(8px)}
/* one soft ring once the story has landed: this is where the eye should end up */
@keyframes nzm-ring{from{box-shadow:0 12px 26px -14px var(--accent),0 0 0 0 var(--accent-line)}
  to{box-shadow:0 12px 26px -14px var(--accent),0 0 0 16px rgba(31,111,139,0)}}
.nzm-first.fx-cta .hero-band .hero-actions .btn-accent{animation:nzm-ring 1.5s 1.45s ease-out 1 both}

/* ---------- 2 · stats: odometer roll + a breathing "live" dot ---------- */
.nzm-num{display:inline-block;position:relative;line-height:1.5;font-variant-numeric:tabular-nums}
/* the site styles every ".stats span" as the 13px grey label; the digits must not inherit that */
.stats b .nzm-num,.stats b .nzm-num span{font-size:inherit;font-weight:inherit;color:inherit;letter-spacing:inherit}
.stats b .nzm-num.rolling > .nzm-txt,.nzm-num.rolling > .nzm-txt{color:transparent}
.nzm-odo{position:absolute;inset:0;display:flex;overflow:hidden;pointer-events:none;
  -webkit-mask-image:linear-gradient(transparent,#000 24%,#000 76%,transparent);mask-image:linear-gradient(transparent,#000 24%,#000 76%,transparent)}
.nzm-col{display:block;height:1.5em}
.nzm-strip{display:flex;flex-direction:column;will-change:transform}
.nzm-strip > span,.nzm-sep{display:block;height:1.5em;line-height:1.5em}
.nzm-live{display:none}
.fx-count .nzm-live{display:inline-block;position:relative;width:7px;height:7px;border-radius:50%;background:var(--jade);margin-right:7px;vertical-align:1px}
.fx-count .nzm-live:after{content:"";position:absolute;inset:0;border-radius:50%;background:var(--jade);animation:nzm-ping 2.2s cubic-bezier(0,0,.2,1) infinite}
@keyframes nzm-ping{0%{transform:scale(1);opacity:.55}80%,100%{transform:scale(2.9);opacity:0}}

/* ---------- 3 · cards: rise in on scroll, light follows the pointer ---------- */
.fx-cards .nzm-pre{opacity:0;translate:0 26px;
  transition:opacity .7s var(--nzm-ease),translate .85s var(--nzm-ease),transform .18s,box-shadow .18s,border-color .18s}
.fx-cards .nzm-pre.nzm-in{opacity:1;translate:0 0}
@media(hover:hover) and (pointer:fine){
  .fx-cards .mcard,.fx-cards .section .grid > .card{position:relative}
  /* a 1px ring that only lights up near the cursor */
  .fx-cards .mcard:after,.fx-cards .section .grid > .card:after{content:"";position:absolute;inset:0;z-index:3;border-radius:inherit;padding:1px;pointer-events:none;
    background:radial-gradient(200px circle at var(--mx,50%) var(--my,0%),var(--accent),transparent 70%);
    -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;
    opacity:0;transition:opacity .3s ease}
  /* and a faint wash of light on the surface under it */
  .fx-cards .mcard:before,.fx-cards .section .grid > .card:before{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
    background:radial-gradient(320px circle at var(--mx,50%) var(--my,0%),rgba(255,255,255,.18),transparent 62%);
    opacity:0;transition:opacity .3s ease}
  .fx-cards .mcard:hover:after,.fx-cards .section .grid > .card:hover:after{opacity:.9}
  .fx-cards .mcard:hover:before,.fx-cards .section .grid > .card:hover:before{opacity:1}
  :root[data-theme="dark"] .fx-cards .mcard:before,:root[data-theme="dark"] .fx-cards .section .grid > .card:before{
    background:radial-gradient(320px circle at var(--mx,50%) var(--my,0%),rgba(70,166,198,.10),transparent 62%)}
}

/* ---------- 4 · top bar: ink reading line + one sliding hover pill ---------- */
@supports (animation-timeline: scroll()){
  .fx-nav .topbar:after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;pointer-events:none;
    background:linear-gradient(90deg,var(--accent),var(--jade));transform-origin:0 50%;transform:scaleX(0);
    animation:nzm-read linear both;animation-timeline:scroll(root)}
  [dir=rtl] .fx-nav .topbar:after{transform-origin:100% 50%}
}
@keyframes nzm-read{to{transform:scaleX(1)}}
.nzm-navpill{display:none}
@media(hover:hover) and (pointer:fine){
  .fx-nav .topbar .nav{position:relative;isolation:isolate}
  .fx-nav .nzm-navpill{display:block;position:absolute;left:0;top:50%;height:36px;margin-top:-18px;border-radius:9px;background:var(--bg-2);
    z-index:-1;pointer-events:none;opacity:0;
    transition:transform .45s cubic-bezier(.3,1.3,.45,1),width .45s cubic-bezier(.3,1.3,.45,1),opacity .2s ease}
  .fx-nav .nzm-navpill.on{opacity:1}
  .fx-nav .nzm-navpill.jump{transition:opacity .2s ease}
  .fx-nav .topbar .nav .nav-link:hover,.fx-nav .topbar .nav .nav-trigger:hover{background:transparent}
}

/* ---------- 5 · FAQ opens smoothly (Chromium 131+; elsewhere it just opens) ---------- */
.fx-faq .faq{interpolate-size:allow-keywords}
.fx-faq .faq-item::details-content{block-size:0;overflow:clip;
  transition:block-size .42s var(--nzm-ease),content-visibility .42s allow-discrete}
.fx-faq .faq-item[open]::details-content{block-size:auto}
.fx-faq .faq-item[open] .faq-a{animation:nzm-rise .5s var(--nzm-ease) both;--nzm-rise:6px;--nzm-blur:3px}

/* ---------- 6 · theme switch spreads like ink from the moon button ---------- */
.nzm-vt::view-transition-old(root),.nzm-vt::view-transition-new(root){animation:none;mix-blend-mode:normal}
.nzm-vt .topbar{view-transition-name:none}
.nzm-vt.nzm-vt-mask::view-transition-new(root){-webkit-mask-image:radial-gradient(circle closest-side,#000 78%,transparent 100%);
  mask-image:radial-gradient(circle closest-side,#000 78%,transparent 100%);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}

/* ---------- 7 · ink under the pointer: the aurora leans toward it, a click drops ink ---------- */
.fx-ink .aurora.a1{translate:calc(var(--px,0)*26px) calc(var(--py,0)*18px)}
.fx-ink .aurora.a2{translate:calc(var(--px,0)*-20px) calc(var(--py,0)*-14px)}
.fx-ink .aurora.a3{translate:calc(var(--px,0)*34px) calc(var(--py,0)*26px)}
.nzm-drop{position:absolute;width:160px;height:160px;margin:-80px 0 0 -80px;border-radius:50%;pointer-events:none;z-index:0;
  background:radial-gradient(circle,rgba(28,34,38,.62) 0,rgba(31,111,139,.34) 26%,rgba(31,111,139,.12) 46%,transparent 66%);
  filter:url(#nzm-inkf);mix-blend-mode:multiply;opacity:0;animation:nzm-drop 2.6s cubic-bezier(.16,.84,.3,1) forwards}
:root[data-theme="dark"] .nzm-drop{mix-blend-mode:screen;
  background:radial-gradient(circle,rgba(232,234,231,.34) 0,rgba(70,166,198,.3) 28%,rgba(70,166,198,.1) 48%,transparent 66%)}
@keyframes nzm-drop{0%{transform:scale(calc(.1*var(--s,1)));opacity:.95}30%{opacity:.85}100%{transform:scale(calc(1.9*var(--s,1)));opacity:0}}
