/* ============================================================================
   AQW visual effects layer — first screen + pointer light. 2026-10-20
   Loaded after visual-refine.css. Pairs with visual-fx.js.

   The AQW AI hero (#home) was promoted out of the topic library to become the
   first screen. Inside the library its visual was display:none, so its phone
   and orbit composition had never been laid out at full size; the rules below
   size it for the first-screen role. The canvas and scroll cue injected with
   it must be taken out of flow, or .hero's flex row treats the 300px default
   canvas as a column and pushes all content sideways.
   ========================================================================= */

/* ------------------------------------------------------------- hero ----- */
.aqw-hero{
  position:relative;isolation:isolate;overflow:hidden;
  min-height:calc(100svh - var(--aqw-header-h,73px));
  padding:clamp(56px,7vh,96px) 0 clamp(88px,11vh,128px);
  background:
    radial-gradient(900px 620px at 78% 38%,rgba(72,149,255,.14),transparent 64%),
    radial-gradient(760px 520px at 12% 72%,rgba(73,226,205,.10),transparent 66%),
    linear-gradient(180deg,#040b12 0%,#06121b 70%,#07131c 100%);
}
.aqw-hero-canvas{
  position:absolute;inset:0;width:100%;height:100%;z-index:0;
  display:block;pointer-events:none;
  /* Keep the field quiet behind the headline, fuller around the visual. */
  mask-image:radial-gradient(120% 95% at 72% 45%,#000 30%,rgba(0,0,0,.55) 62%,transparent 100%);
}
.aqw-hero>.container{position:relative;z-index:1}
/* The grid backdrop from .v2-hero:before stays, above the canvas. */
.aqw-hero:before{z-index:0}
/* A soft floor so the hero hands over to the cockpit without a hard line. */
.aqw-hero:after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:140px;z-index:0;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(4,10,16,.85));
}

/* Headline: the 96px clamp was set for the Latin line length. In CJK it broke
   into three short lines of four glyphs; a smaller ceiling keeps it to two. */
.aqw-hero h1{font-size:clamp(50px,6.2vw,92px)}
:is([lang|="zh"],[lang|="ja"],[lang|="ko"]) .aqw-hero h1{font-size:clamp(44px,4.9vw,74px);line-height:1.12}
.aqw-hero .lead{color:#b4c6cf}
.aqw-hero .hero-actions{align-items:center}

/* Visual: phone sized by height so the 860x1864 screenshot always fits the
   stage; the AI core sits off its left shoulder instead of covering the
   balance card. */
.aqw-hero .v2-hero-visual{height:min(650px,calc(100svh - 190px));min-height:480px}
/* Anchored from the right: the original translateX(-50%) centring does not
   survive in this context, and right-anchoring keeps the phone clear of the
   node labels regardless. */
.aqw-hero .v2-hero-visual .v2-phone{
  width:auto;height:94%;left:auto;right:6%;max-width:none;
  border-radius:clamp(28px,3vw,42px);
  transform:perspective(1200px) rotateY(-7deg) rotateX(2deg);
}
.aqw-hero .v2-hero-visual .v2-phone:hover{transform:perspective(1200px) rotateY(-2deg) translateY(-5px)}

/* Promo video in the phone slot. The figure keeps the .v2-phone geometry and
   tilt; the video fills it at 9:16. Height drives width via aspect-ratio, the
   same way the 860x1864 screenshot did, so the stage layout is unchanged. */
.aqw-hero .v2-hero-visual .aqw-promo{
  margin:0;aspect-ratio:9/16;overflow:hidden;cursor:default;
  background:#05080a url("assets/video/aqw-promo-poster.webp") center/cover no-repeat;
  box-shadow:0 50px 120px rgba(0,0,0,.55),0 0 0 1px rgba(214,255,90,.16),0 0 60px rgba(150,230,80,.08);
}
.aqw-promo-video{display:block;width:100%;height:100%;object-fit:cover;border-radius:inherit}
/* Pause control: required for autoplaying motion longer than 5 seconds. */
.aqw-promo-toggle{
  position:absolute;right:14px;bottom:14px;z-index:2;width:38px;height:38px;padding:0;
  border:1px solid rgba(255,255,255,.22);border-radius:50%;cursor:pointer;
  background:rgba(4,10,16,.62);backdrop-filter:blur(8px);
  opacity:.72;transition:opacity .2s ease,background .2s ease;
}
.aqw-promo-toggle:hover,.aqw-promo-toggle:focus-visible{opacity:1;background:rgba(4,10,16,.85)}
.aqw-promo-toggle span{position:absolute;inset:0;margin:auto;width:12px;height:14px}
/* Two bars = pause; a triangle = play. */
.aqw-promo-toggle span{background:linear-gradient(90deg,#e8fbff 0 35%,transparent 35% 65%,#e8fbff 65%)}
.aqw-promo-toggle[data-state="paused"] span{
  width:0;height:0;background:none;margin-left:15px;
  border-style:solid;border-width:7px 0 7px 12px;border-color:transparent transparent transparent #e8fbff;
}
.aqw-hero .v2-ai-core{left:26%;top:40%;width:132px;height:132px}
.aqw-hero .v2-orbit{left:26%;top:40%}
.aqw-hero .v2-orbit.one{width:300px;height:160px}
.aqw-hero .v2-orbit.two{width:440px;height:250px}
/* Labels stay in the open space left of the phone so none covers its UI. */
.aqw-hero .v2-node.n1{top:12%;left:8%;right:auto}
.aqw-hero .v2-node.n2{top:64%;left:0;right:auto}
.aqw-hero .v2-node.n3{top:auto;bottom:8%;left:14%;right:auto}

/* Orbit rings turn slowly; nodes drift on their own clocks. All paused until
   visual-fx.js marks the hero as on screen. */
.aqw-fx .aqw-hero .v2-orbit.one{animation:aqw-orbit-a 38s linear infinite}
.aqw-fx .aqw-hero .v2-orbit.two{animation:aqw-orbit-b 54s linear infinite}
.aqw-fx .aqw-hero .v2-node{animation:aqw-float 7s ease-in-out infinite}
.aqw-fx .aqw-hero .v2-node.n2{animation-delay:-2.3s;animation-duration:8.2s}
.aqw-fx .aqw-hero .v2-node.n3{animation-delay:-4.1s;animation-duration:9.1s}
.aqw-fx .aqw-hero :is(.v2-orbit,.v2-node){animation-play-state:paused}
.aqw-fx .aqw-hero.aqw-fx-live :is(.v2-orbit,.v2-node){animation-play-state:running}
@keyframes aqw-orbit-a{from{transform:translate(-50%,-50%) rotate(-13deg)}to{transform:translate(-50%,-50%) rotate(347deg)}}
@keyframes aqw-orbit-b{from{transform:translate(-50%,-50%) rotate(19deg)}to{transform:translate(-50%,-50%) rotate(-341deg)}}
@keyframes aqw-float{0%,100%{translate:0 0}50%{translate:0 -9px}}

/* First-load sequence. Only the hero copy, only once, only with motion on.
   Uses `animation` with fill-mode both, so if the animation never runs the
   element simply renders in its final state. */
.aqw-fx .aqw-hero .reveal>*{animation:aqw-rise .9s var(--aqw-ease-out,cubic-bezier(.16,1,.3,1)) both}
.aqw-fx .aqw-hero .reveal>*:nth-child(2){animation-delay:.08s}
.aqw-fx .aqw-hero .reveal>*:nth-child(3){animation-delay:.18s}
.aqw-fx .aqw-hero .reveal>*:nth-child(4){animation-delay:.28s}
.aqw-fx .aqw-hero .reveal>*:nth-child(5){animation-delay:.38s}
.aqw-fx .aqw-hero .v2-hero-visual{animation:aqw-settle 1.2s var(--aqw-ease-out,cubic-bezier(.16,1,.3,1)) .15s both}
@keyframes aqw-rise{from{opacity:0;transform:translate3d(0,22px,0)}to{opacity:1;transform:none}}
@keyframes aqw-settle{from{opacity:0;transform:translate3d(0,30px,0) scale(.97)}to{opacity:1;transform:none}}

/* Scroll-linked depth: visual-fx.js writes --aqw-hero-p (0 at rest, 1 when the
   hero has scrolled away). Copy lifts a little faster than the visual. */
.aqw-fx .aqw-hero .v2-hero-grid>.reveal{
  translate:0 calc(var(--aqw-hero-p,0) * -56px);
  opacity:calc(1 - var(--aqw-hero-p,0) * .65);
}
.aqw-fx .aqw-hero .v2-hero-visual{translate:0 calc(var(--aqw-hero-p,0) * -24px)}

/* Scroll cue */
.aqw-hero-cue{
  position:absolute;left:50%;bottom:clamp(22px,4vh,40px);z-index:2;
  width:24px;height:38px;margin-left:-12px;border-radius:14px;
  border:1.5px solid rgba(160,226,232,.42);pointer-events:none;
  opacity:calc(1 - var(--aqw-hero-p,0) * 4);transition:opacity .2s linear;
}
.aqw-hero-cue i{
  position:absolute;left:50%;top:7px;width:3px;height:8px;margin-left:-1.5px;
  border-radius:2px;background:#6ee6d6;
}
.aqw-fx .aqw-hero.aqw-fx-live .aqw-hero-cue i{animation:aqw-cue 1.8s var(--aqw-ease,ease) infinite}
@keyframes aqw-cue{0%{opacity:0;transform:translateY(0)}25%{opacity:1}70%{opacity:0;transform:translateY(12px)}100%{opacity:0}}

/* Phone and tablet. */
@media(max-width:1100px){
  .aqw-hero{min-height:0}
  .aqw-hero .v2-hero-visual{height:560px;min-height:0}
  .aqw-hero .v2-ai-core{left:24%}
  .aqw-hero .v2-orbit{left:24%}
}
@media(max-width:720px){
  .aqw-hero{padding:44px 0 84px}
  .aqw-hero .v2-hero-visual{height:470px}
  /* The 9:16 video frame is wider than the old screenshot at the same height,
     so it is held to 86% to leave a clear column for the labels. */
  .aqw-hero .v2-hero-visual .v2-phone{height:86%;right:0;top:auto;bottom:4%}
  .aqw-hero .v2-ai-core{left:19%;top:38%;width:84px;height:84px}
  .aqw-hero .v2-ai-core img{width:50px;height:50px}
  .aqw-hero .v2-orbit{left:19%;top:38%}
  .aqw-hero .v2-orbit.one{width:170px;height:96px}
  .aqw-hero .v2-orbit.two{width:230px;height:136px}
  .aqw-hero .v2-node{font-size:12px!important;padding:7px 10px}
  .aqw-hero .v2-node.n1{top:6%;left:2%}
  .aqw-hero .v2-node.n2{top:62%;left:0}
  .aqw-hero .v2-node.n3{bottom:8%;left:0}
  .aqw-hero-canvas{mask-image:linear-gradient(180deg,rgba(0,0,0,.35),#000 55%,rgba(0,0,0,.6))}
}

/* ------------------------------------------------------ pointer light --- */
/* visual-fx.js injects one .aqw-spot per card and writes --fx-x/--fx-y while
   the pointer is over it. z-index:-1 inside an isolated card puts the light
   above the card's own background but beneath its text, so copy is never
   tinted. Only installed for fine pointers with motion allowed. */
.aqw-spot-host{isolation:isolate}
.aqw-spot-host.aqw-spot-static{position:relative}
.aqw-spot{
  position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  background:radial-gradient(420px circle at var(--fx-x,50%) var(--fx-y,50%),rgba(94,229,214,.13),rgba(99,166,255,.05) 40%,transparent 70%);
  opacity:0;transition:opacity .35s ease;
}
.aqw-spot-host:hover>.aqw-spot{opacity:1}
.light .aqw-spot{background:radial-gradient(380px circle at var(--fx-x,50%) var(--fx-y,50%),rgba(12,143,134,.10),transparent 70%)}
/* A rim that catches the same light, drawn as a masked border. */
.aqw-spot:after{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;
  background:radial-gradient(260px circle at var(--fx-x,50%) var(--fx-y,50%),rgba(110,230,214,.55),transparent 70%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}

/* Magnetic primary CTAs in the hero. Uses `translate`, which composes with
   the existing hover `transform` instead of replacing it. */
.aqw-fx .aqw-hero .btn.primary{translate:var(--fx-mx,0) var(--fx-my,0);transition:translate .25s var(--aqw-ease,ease),transform .2s ease,box-shadow .28s ease}

/* ------------------------------------------------------------ reduced --- */
@media(prefers-reduced-motion:reduce){
  .aqw-hero :is(.v2-orbit,.v2-node,.aqw-hero-cue i),
  .aqw-hero .reveal>*,.aqw-hero .v2-hero-visual{animation:none!important}
  .aqw-hero .v2-hero-grid>.reveal,.aqw-hero .v2-hero-visual{translate:none!important;opacity:1!important}
  .aqw-spot{display:none}
}
@media print{
  .aqw-hero-canvas,.aqw-hero-cue,.aqw-spot{display:none}
  .aqw-hero{min-height:0}
  /* Printing while scrolled down must not print the hero at its faded state. */
  .aqw-hero .v2-hero-grid>.reveal,.aqw-hero .v2-hero-visual{translate:none!important;opacity:1!important}
}
