/* ============================================================
   AIKO — boot sequence, "she's coming"
   The first version was "a single big eye opening"; it didn't fit the product
   (an AI girl companion) — too abstract, and not good-looking either.
   This version brings the protagonist herself on stage: the girl emerges from
   the dark → light sweeps across → she speaks a greeting → lands on the brand name.

   The timeline is driven by CSS animation-delay (see the end of the file); JS
   only handles: building nodes, typewriter, particles, skip, exit, fallback.
   Cover and animation nodes are separate: html.aiko-run::before is the pure CSS
   cover, the animation overlay is appended at runtime by boot.js, and on exit
   the cover is lifted first, then the lights dim out.

   Girl asset: assets/hero-app.jpg — note that url() in CSS resolves relative to
   **this file**, and this file lives at the root, so "assets/hero-app.jpg" works
   for both the landing page and the app page; no per-page prefix needed.
   ============================================================ */

html.aiko-run { background: #07040e; }
html.aiko-run::before {
  content: ""; position: fixed; inset: 0; background: #07040e;
  z-index: 2147483600; pointer-events: none;
}
html.aiko-lock, html.aiko-lock body { overflow: hidden !important; }

#aikoBoot {
  position: fixed; inset: 0; z-index: 2147483601;
  background: radial-gradient(120% 100% at 50% 58%, #1a0b30 0%, #0c0619 48%, #06030e 100%);
  display: grid; place-items: center;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  color: #f6f0ff; overflow: hidden;
}
/* Exit: a warm bloom then a full fade-out — closer to the "she's coming" mood than the first version's iris closing */
#aikoBoot.ab-out { transition: opacity .55s ease; opacity: 0; }
#aikoBoot.ab-out::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at 50% 52%, rgba(255, 214, 236, .5), transparent 55%);
  animation: abBloom .55s ease forwards;
}
@keyframes abBloom { from { opacity: 0; } 40% { opacity: 1; } to { opacity: 0; } }

/* ---------- Stage ---------- */
.ab-stage {
  position: relative;
  width: min(940px, 92vw);
  height: min(600px, 74vh);
}

/* ---------- Girl ----------
   Cropped from assets/hero-app.jpg (source image 1280×720).
   ⚠ The crop region must avoid the chat panel in the bottom-left corner: the
     panel's top edge is at y≈357 and its right edge at x≈570 in the source.
     The first version started at x420 and cropped the panel in too — the Send
     button was visible on screen.
   Now using x 440–860 / y 0–345: only her head and shoulders, fully clear of the panel.
   Scale 1.1 → element 462×380, full image becomes 1408×792, offset -440*1.1 = -484.
   A feathered mask blends the rectangle edges into the dark scene instead of
   cutting the subject out the hard way (she already sits on a dark background). */
.ab-girl {
  position: absolute; left: 62%; top: 40%;
  width: 462px; height: 380px; margin: -190px 0 0 -231px;
  background: url("assets/hero-app.jpg") -484px 0 / 1408px 792px no-repeat;
  opacity: 0; transform: translateY(20px) scale(1.045);
  filter: brightness(.32) saturate(.8);
  /* Feathered mask: must intersect two linear gradients (mask-composite: intersect)
     so all four edges **truly fade to 0**. A single radial layer won't do — as long
     as the ellipse radius is larger than the element, opacity at the element's edges
     is still 60-70% and the rectangle's backdrop stays visible (that's how the first
     version failed). */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0%, #000 26%, #000 74%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000 12%, #000 64%, transparent 100%);
  mask-image:
    linear-gradient(to right, transparent 0%, #000 26%, #000 74%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000 12%, #000 64%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
  will-change: opacity, transform, filter;
}

/* Warm halo behind her: spreads out from her chest */
.ab-glow {
  position: absolute; left: 62%; top: 33%;
  width: 700px; height: 560px; margin: -280px 0 0 -350px;
  background: radial-gradient(ellipse at 50% 50%, rgba(255, 107, 157, .40) 0%, rgba(168, 85, 247, .22) 42%, transparent 72%);
  filter: blur(26px); opacity: 0;
}
.ab-glow.tight {
  left: 62%; top: 33%;
  width: 220px; height: 220px; margin: -110px 0 0 -110px;
  background: radial-gradient(circle, rgba(255, 214, 236, .85) 0%, rgba(255, 107, 157, .35) 40%, transparent 70%);
  filter: blur(18px);
}

/* Light sweep: a soft band of light passes down over her */
.ab-sweep {
  position: absolute; left: 44%; right: 6%; top: 0; height: 46%;
  background: linear-gradient(180deg, transparent, rgba(255, 214, 236, .16) 45%, rgba(255, 255, 255, .30) 62%, transparent);
  filter: blur(14px); opacity: 0; pointer-events: none;
}

/* ---------- Speech bubble ----------
   The product is a "companion", so let her **speak** — that's more direct than
   any abstract graphic. Anchored to her left, vertically centered at her chest height. */
.ab-bubble {
  position: absolute; left: 1%; top: 44%; margin-top: -34px;
  max-width: min(336px, 36vw);
  background: rgba(24, 12, 44, .82);
  border: 1px solid rgba(255, 214, 236, .22);
  border-radius: 18px 18px 18px 6px;
  padding: 16px 20px;
  backdrop-filter: blur(10px);
  box-shadow: 0 10px 40px rgba(0, 0, 0, .5), 0 0 30px rgba(168, 85, 247, .18);
  opacity: 0; transform: translateX(-16px);
}
.ab-bubble:after {                       /* little tail pointing at her */
  content: ""; position: absolute; right: -8px; bottom: 10px;
  width: 14px; height: 14px; background: inherit;
  border-right: 1px solid rgba(255, 214, 236, .22);
  border-bottom: 1px solid rgba(255, 214, 236, .22);
  transform: rotate(-45deg); border-radius: 0 0 4px 0;
}
.ab-say {
  display: block; font-size: 17px; line-height: 1.6; color: #fdf2ff;
  letter-spacing: .01em; min-height: 1.6em;
}
.ab-say .ab-caret {
  display: inline-block; width: 2px; height: 1.05em; margin-left: 3px;
  background: #ff6b9d; vertical-align: -2px;
  animation: abCaret .7s steps(1, end) infinite;
}
@keyframes abCaret { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }

/* typing dots */
.ab-dots { display: inline-flex; gap: 5px; align-items: center; }
.ab-dots i {
  width: 7px; height: 7px; border-radius: 50%; background: #d8b4fe; display: block;
  animation: abDot 1.05s ease-in-out infinite;
}
.ab-dots i:nth-child(2) { animation-delay: .16s; }
.ab-dots i:nth-child(3) { animation-delay: .32s; }
@keyframes abDot { 0%, 60%, 100% { opacity: .28; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-4px); } }

/* ---------- Branding ---------- */
.ab-hud {
  position: absolute; left: 0; right: 0; top: 2%;
  display: flex; justify-content: space-between;
  font-size: 11px; letter-spacing: .32em; text-transform: uppercase;
  color: rgba(216, 180, 254, .62); opacity: 0;
}
.ab-hud b { color: #ff6b9d; font-weight: 600; }

.ab-word {
  position: absolute; left: 0; right: 0; bottom: 9%;
  text-align: center;
  font-size: clamp(36px, 5.8vw, 70px); font-weight: 800; letter-spacing: .22em; line-height: 1;
  text-indent: .22em;
  background: linear-gradient(105deg, #ffd6ec 4%, #ff6b9d 42%, #c084fc 78%, #a855f7 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 26px rgba(168, 85, 247, .5));
  opacity: 0;
}
.ab-sub {
  position: absolute; left: 0; right: 0; bottom: 3.5%;
  text-align: center;
  font-size: 11px; letter-spacing: .46em; text-transform: uppercase; text-indent: .46em;
  color: rgba(216, 180, 254, .7);
  opacity: 0;
}
.ab-bar {
  position: absolute; left: 50%; bottom: 0; width: min(360px, 54vw); height: 1.5px;
  transform: translateX(-50%); background: rgba(168, 85, 247, .22); overflow: hidden;
}
.ab-bar i { display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, #a855f7, #ff6b9d);
  box-shadow: 0 0 12px rgba(255, 107, 157, .8); }
.ab-skip {
  position: absolute; right: 4px; bottom: 2%;
  font-size: 10px; letter-spacing: .22em; text-transform: uppercase;
  color: rgba(216, 180, 254, .40); opacity: 0;
}

/* Waiting state: the animation has finished, the character is still loading.
   Required — otherwise the frame sits still for those seconds and looks frozen. */
.ab-waiting {
  position: absolute; left: 0; right: 0; bottom: 3.5%;
  display: none; align-items: center; justify-content: center; gap: 10px;
  font-size: 11px; letter-spacing: .3em; text-transform: uppercase;
  color: rgba(216, 180, 254, .8);
}
#aikoBoot.ab-wait .ab-waiting { display: flex; }
#aikoBoot.ab-wait .ab-sub { opacity: 0; }
#aikoBoot.ab-wait .ab-bar i { width: 100%; opacity: .45; }
#aikoBoot.ab-wait .ab-girl { animation: abBreathe 2.4s ease-in-out infinite; }
@keyframes abBreathe {
  0%, 100% { filter: brightness(1) saturate(1.02); transform: translateY(0) scale(1); }
  50% { filter: brightness(1.1) saturate(1.06); transform: translateY(-4px) scale(1.008); }
}

.ab-dust { position: absolute; inset: 0; pointer-events: none; }

/* ============================================================
   Timeline — to adjust the timings, change only this block
   (AB_TOTAL in boot.js must be kept in sync)
   ============================================================ */
#aikoBoot.ab-play .ab-hud { animation: abFade .6s ease .25s both; }
#aikoBoot.ab-play .ab-glow.tight { animation: abSparkPulse 1.5s ease .05s both, abFadeOut .5s ease 1.35s both; }
#aikoBoot.ab-play .ab-girl { animation: abGirlIn 1.5s cubic-bezier(.22, .8, .25, 1) .45s both; }
#aikoBoot.ab-play .ab-sweep { animation: abSweep 1.15s cubic-bezier(.4, .1, .3, 1) 1.0s both; }
#aikoBoot.ab-play .ab-glow { animation: abGlowIn 1.4s ease 1.55s both; }
#aikoBoot.ab-play .ab-bubble { animation: abBubbleIn .55s cubic-bezier(.2, .9, .25, 1) 1.85s both; }
#aikoBoot.ab-play .ab-word { animation: abWordIn .8s cubic-bezier(.2, .9, .25, 1) 3.05s both; }
#aikoBoot.ab-play .ab-sub { animation: abFade .55s ease 3.45s both; }
#aikoBoot.ab-play .ab-bar i { animation: abBarFill 3.75s cubic-bezier(.35, .75, .3, 1) .15s both; }
#aikoBoot.ab-play .ab-skip { animation: abFade .4s ease 1.1s both; }

@keyframes abFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes abFadeOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes abSparkPulse {
  0% { opacity: 0; transform: scale(.25); }
  35% { opacity: 1; transform: scale(1); }
  60% { opacity: .82; transform: scale(.9); }
  100% { opacity: 1; transform: scale(1.08); }
}
/* Girl appears: brightness lifts out of the dark + a slight upward drift; no
   exaggerated movement, so it doesn't look like a "sprite flying in" */
@keyframes abGirlIn {
  0% { opacity: 0; transform: translateY(20px) scale(1.045); filter: brightness(.32) saturate(.8) blur(6px); }
  55% { opacity: 1; filter: brightness(.92) saturate(1) blur(0); }
  100% { opacity: 1; transform: translateY(0) scale(1); filter: brightness(1) saturate(1.02) blur(0); }
}
@keyframes abSweep {
  0% { opacity: 0; transform: translateY(-60%); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: translateY(240%); }
}
@keyframes abGlowIn {
  0% { opacity: 0; transform: scale(.7); }
  70% { opacity: .86; transform: scale(1.04); }
  100% { opacity: .68; transform: scale(1); }
}
@keyframes abBubbleIn {
  0% { opacity: 0; transform: translateX(-16px) scale(.96); }
  100% { opacity: 1; transform: translateX(0) scale(1); }
}
@keyframes abWordIn {
  0% { opacity: 0; transform: scale(1.28); filter: blur(14px); }
  60% { opacity: 1; transform: scale(.985); filter: blur(0); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes abBarFill { from { width: 0; } to { width: 100%; } }

@media (prefers-reduced-motion: reduce) {
  #aikoBoot { display: none; }
}
/* Narrow screens: move the bubble below the frame and step the font size down, otherwise it covers her */
@media (max-width: 860px), (max-height: 620px) {
  /* No room to place the bubble beside her on narrow screens, so center her and put the bubble below her */
  .ab-girl { left: 50%; top: 38%; width: 300px; height: 247px; margin: -123px 0 0 -150px;
    background-position: -314px 0; background-size: 914px 514px; }
  .ab-glow { left: 50%; top: 40%; }
  .ab-glow.tight { left: 50%; top: 40%; }
  .ab-sweep { left: 18%; right: 18%; }
  .ab-bubble { left: 50%; top: auto; bottom: 24%; margin-top: 0;
    transform: translateX(-50%); max-width: 84vw; border-radius: 16px 16px 16px 16px; }
  .ab-bubble:after { display: none; }
  .ab-word { bottom: 12%; }
}
