/* Boot sequence: the projector strikes a line, the window unfolds, the scene loads,
   and the display decodes its digits. 2.2s, once per page view.

   Rules of the file:
   - Only transform / opacity / clip-path / stroke-dashoffset animate. Glow changes
     are class swaps with a transition, never keyframes.
   - Every animation ends on the value the element already had, so the finished
     scene is byte-for-byte the scene without the intro.
   - The hidden state hangs off `html.js-intro .nm-hero:not(.is-ready)`, so a page
     without JS (or with reduced motion) never hides anything. */

/* ── The pane outline, written once. The collapsed form keeps the same eight
      vertices so clip-path interpolates instead of snapping. ── */
.nm-hero{--intro-pane:polygon(0 22px,22px 0,calc(100% - 22px) 0,100% 22px,100% calc(100% - 22px),calc(100% - 22px) 100%,22px 100%,0 calc(100% - 22px));
  --intro-shut:polygon(0 50%,22px 50%,calc(100% - 22px) 50%,100% 50%,100% 50%,calc(100% - 22px) 50%,22px 50%,0 50%)}

/* ── 1. Nothing but the navy ground until the line strikes. ── */
html.js-intro .nm-hero:not(.is-ready)::before,
html.js-intro .nm-hero:not(.is-ready)::after,
html.js-intro .nm-hero:not(.is-ready) .nm-glass-optics{clip-path:var(--intro-shut)}
html.js-intro .nm-hero:not(.is-ready) .nm-window-frame path,
html.js-intro .nm-hero:not(.is-ready) .nm-hud-frame path{stroke-dasharray:1;stroke-dashoffset:1}
html.js-intro .nm-hero:not(.is-ready) :is(.nm-event,.nm-copy h1,.nm-title-jp,.nm-date,.nm-cta,
  .nm-clock-caption,.nm-clock,.nm-clock-hint,.nm-portrait-stage,.nm-system-marks,.nm-dust,.nm-calendar){opacity:0}

/* ── The intro's own layers. They exist only while the sequence runs. ── */
.nm-intro{position:absolute;inset:var(--pane-top) var(--pane-side) 24px;z-index:4;pointer-events:none;opacity:0}
html.js-intro .nm-hero.is-booting .nm-intro{opacity:1}
.nm-intro span{position:absolute;display:block}
.nm-intro-line{left:0;right:0;top:50%;height:1px;transform:scaleX(0);opacity:0;
  background:linear-gradient(90deg,transparent,#8fe6ff 14%,#eafcff 50%,#8fe6ff 86%,transparent);
  box-shadow:0 0 10px #7fe0ffaa,0 0 26px #4fb8ff55}
.nm-intro-seed{left:50%;top:50%;width:7px;height:7px;margin:-3.5px 0 0 -3.5px;border-radius:50%;opacity:0;
  background:radial-gradient(circle,#ffffff 0 34%,#d7f7ff 62%,#7fe0ff00 100%);
  box-shadow:0 0 12px #eafcffcc,0 0 30px #7fe0ff99;transform:scale(.2)}
.nm-intro-flash{inset:0;opacity:0;clip-path:var(--intro-pane);
  background:linear-gradient(180deg,#cdf3ff5c,#ffffffb3 48%,#cdf3ff5c)}

@keyframes nmIntroLine{0%{opacity:0;transform:scaleX(0)}10%{opacity:1}64%{opacity:1;transform:scaleX(1)}100%{opacity:0;transform:scaleX(1)}}
@keyframes nmIntroSeed{0%{opacity:0;transform:scale(.2)}20%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(2.8)}}
@keyframes nmIntroFlash{from{opacity:.5}to{opacity:0}}
html.js-intro .nm-hero.is-booting .nm-intro-line{animation:nmIntroLine .55s cubic-bezier(.16,.84,.3,1) both}
html.js-intro .nm-hero.is-booting .nm-intro-seed{animation:nmIntroSeed .45s cubic-bezier(.2,.7,.2,1) both}
/* forwards, not both: a backwards fill would hold the flash's opening 50% white
   over the whole window for the first 0.82s. */
html.js-intro .nm-hero.is-booting .nm-intro-flash{animation:nmIntroFlash .12s linear .82s forwards}

/* ── 2. The window opens from the line and its frame is drawn. ── */
@keyframes nmIntroOpen{from{clip-path:var(--intro-shut)}to{clip-path:var(--intro-pane)}}
@keyframes nmIntroDraw{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
html.js-intro .nm-hero.is-booting::before,
html.js-intro .nm-hero.is-booting::after,
html.js-intro .nm-hero.is-booting .nm-glass-optics{animation:nmIntroOpen .6s cubic-bezier(.16,.84,.3,1) .3s both}
html.js-intro .nm-hero.is-booting .nm-window-frame path{animation:nmIntroDraw .6s cubic-bezier(.3,.8,.3,1) .34s both}
/* path. keeps the specificity level of the rule above, so the later source order wins. */
html.js-intro .nm-hero.is-booting path.nm-window-corners{animation:nmIntroDraw .3s ease-out .62s both}
/* The corner brackets light one step brighter, then ease back when the boot class
   drops. A transition, because glow must never be a keyframe here. */
html.js-intro .nm-hero .nm-window-corners{transition:filter .55s ease-out}
html.js-intro .nm-hero.is-booting .nm-window-corners{filter:drop-shadow(0 0 9px #dffaffcc) drop-shadow(-.7px -.5px 0 #5ff2ff77) drop-shadow(.7px .5px 0 #ff6ad577)}

/* ── 3. The scene loads: circle, silhouette, then the heading letter by letter. ── */
@keyframes nmIntroFade{from{opacity:0}to{opacity:1}}
@keyframes nmIntroShow{from{opacity:0}to{opacity:1}}
@keyframes nmIntroRise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes nmIntroCircle{from{opacity:0;transform:translate(-50%,-50%) rotate(-40deg) scale(.6)}
  to{opacity:1;transform:translate(-50%,-50%) rotate(0) scale(1)}}
@keyframes nmIntroPortrait{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
@keyframes nmIntroHalo{0%{opacity:0}42%{opacity:1}100%{opacity:0}}
@keyframes nmIntroLetter{from{opacity:0;transform:perspective(950px) rotateX(40deg) translateY(10px)}
  to{opacity:1;transform:perspective(950px) rotateX(0) translateY(0)}}

html.js-intro .nm-hero.is-booting .nm-portrait-stage{animation:nmIntroFade .35s linear .78s both}
html.js-intro .nm-hero.is-booting .nm-circle{animation:nmIntroCircle .7s cubic-bezier(.16,.84,.3,1) .8s both}
html.js-intro .nm-hero.is-booting .nm-portrait-frame{animation:nmIntroPortrait .8s cubic-bezier(.16,.84,.3,1) .82s both}
html.js-intro .nm-hero.is-booting .nm-intro-halo{animation:nmIntroHalo 1.1s ease-in-out .85s both}
html.js-intro .nm-hero.is-booting .nm-event{animation:nmIntroRise .3s ease-out .72s both}
/* The glyphs carry the reveal; the heading box only stops hiding them. */
html.js-intro .nm-hero.is-booting .nm-copy h1{animation:nmIntroShow .01s linear .8s both}
html.js-intro .nm-hero.is-booting .nm-copy h1 .nm-letter{animation:nmIntroLetter .45s cubic-bezier(.2,.8,.3,1) calc(.8s + var(--i,0) * 28ms) both}
html.js-intro .nm-hero.is-booting .nm-title-jp{animation:nmIntroRise .3s ease-out 1.06s both}
html.js-intro .nm-hero.is-booting .nm-date{animation:nmIntroRise .3s ease-out 1.18s both}
html.js-intro .nm-hero.is-booting .nm-cta{animation:nmIntroRise .3s ease-out 1.3s both}
html.js-intro .nm-hero.is-booting .nm-clock-caption{animation:nmIntroRise .3s ease-out 1.42s both}

/* Halo of our own: .nm-portrait-light breathes on opacity and .nm-portrait-stage::after
   belongs to the spell layer, so neither can carry a one-shot flare. */
.nm-intro-halo{position:absolute;inset:5% -14% 3%;z-index:1;pointer-events:none;opacity:0;
  background:radial-gradient(ellipse at 50% 46%,#d3e9ff6b 0%,#a8b8ff42 30%,transparent 66%);filter:blur(26px)}

/* Eight lilac sparks, our own set, so the spell layer's .nm-spark stays untouched. */
.nm-intro-sparks{position:absolute;left:50%;top:47%;width:0;height:0;z-index:3;pointer-events:none}
.nm-intro-sparks i{position:absolute;left:0;top:0;width:var(--s,10px);height:var(--s,10px);
  margin:calc(var(--s,10px) / -2) 0 0 calc(var(--s,10px) / -2);opacity:0;
  background:radial-gradient(circle,#f4ecff 0 16%,#dccdff 48%,#b79bff 80%,#b79bff00 100%);
  clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%);
  filter:drop-shadow(0 0 6px #c9b3ffcc);
  transform:rotate(var(--a,0deg)) translateX(10px) scale(.2)}
.nm-intro-sparks i:nth-child(1){--a:-108deg;--d:126px;--s:11px}
.nm-intro-sparks i:nth-child(2){--a:-58deg;--d:104px;--s:9px}
.nm-intro-sparks i:nth-child(3){--a:-14deg;--d:132px;--s:10px}
.nm-intro-sparks i:nth-child(4){--a:36deg;--d:112px;--s:12px}
.nm-intro-sparks i:nth-child(5){--a:82deg;--d:120px;--s:9px}
.nm-intro-sparks i:nth-child(6){--a:128deg;--d:100px;--s:11px}
.nm-intro-sparks i:nth-child(7){--a:166deg;--d:128px;--s:10px}
.nm-intro-sparks i:nth-child(8){--a:-152deg;--d:108px;--s:9px}
@keyframes nmIntroSpark{
  0%{opacity:0;transform:rotate(var(--a,0deg)) translateX(10px) scale(.2)}
  16%{opacity:1}
  68%{opacity:1}
  100%{opacity:0;transform:rotate(var(--a,0deg)) translateX(var(--d,116px)) scale(.55)}
}
html.js-intro .nm-hero.is-booting .nm-intro-sparks i{animation:nmIntroSpark .8s cubic-bezier(.15,.7,.3,1) 1.45s both}

/* ── 4. The display powers up. The end pose equals nmDisplayFloat's first frame,
      so the float simply takes over when the boot class drops. ── */
@keyframes nmIntroClock{
  0%{opacity:0;transform:translateY(0) rotateX(2deg) rotateY(-1.5deg) scale(.96)}
  40%{opacity:1}
  100%{opacity:1;transform:translateY(0) rotateX(2deg) rotateY(-1.5deg) scale(1)}
}
html.js-intro .nm-hero.is-booting .nm-clock{animation:nmIntroClock .7s cubic-bezier(.16,.84,.3,1) 1.2s both}
html.js-intro .nm-hero.is-booting :is(.nm-hud-depth,.nm-hud-back,.nm-hud-front){animation:nmIntroDraw .6s cubic-bezier(.3,.8,.3,1) 1.3s both}
html.js-intro .nm-hero.is-booting :is(.nm-hud-corners,.nm-hud-rules,.nm-hud-accent){animation:nmIntroDraw .34s ease-out 1.72s both}

/* ── 5. The status marks, the dust and the calendar come up last. ── */
html.js-intro .nm-hero.is-booting :is(.nm-system-marks,.nm-dust,.nm-calendar,.nm-clock-hint){animation:nmIntroFade .34s ease-out 1.9s both}

/* ── Phones: the same beats, six sparks, a shorter rise. ── */
@media(max-width:800px){
  .nm-intro-sparks i:nth-child(n+7){display:none}
  .nm-intro-sparks i{--s:9px}
  .nm-intro-sparks i:nth-child(1){--d:92px}.nm-intro-sparks i:nth-child(2){--d:78px}
  .nm-intro-sparks i:nth-child(3){--d:96px}.nm-intro-sparks i:nth-child(4){--d:84px}
  .nm-intro-sparks i:nth-child(5){--d:88px}.nm-intro-sparks i:nth-child(6){--d:76px}
  .nm-intro-halo{inset:0 -15% 0}
  @keyframes nmIntroPortrait{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
}

/* ── Reduced motion: the inline script never adds js-intro, but if the setting is
      turned on after load the scene must still be whole rather than hidden. ── */
@media(prefers-reduced-motion:reduce){
  .nm-intro,.nm-intro-halo,.nm-intro-sparks{display:none}
  html.js-intro .nm-hero::before,
  html.js-intro .nm-hero::after,
  html.js-intro .nm-hero .nm-glass-optics{clip-path:var(--intro-pane)}
  html.js-intro .nm-hero .nm-window-frame path,
  html.js-intro .nm-hero .nm-hud-frame path{stroke-dasharray:none;stroke-dashoffset:0}
  html.js-intro .nm-hero :is(.nm-event,.nm-copy h1,.nm-title-jp,.nm-date,.nm-cta,
    .nm-clock-caption,.nm-clock,.nm-clock-hint,.nm-portrait-stage,.nm-system-marks,.nm-dust,.nm-calendar){opacity:1}
  html.js-intro .nm-hero .nm-window-corners{transition:none}
}
