/* ================= ARIADNA — pantalla de inicio (splash) ================
   Se reproduce una sola vez al entrar al agente y luego se desvanece,
   revelando la app debajo. Mismo motor que el reproductor de marca
   (hilo de Ariadna azul->dorado + formacion de letras por particulas). */
.as-overlay{
  position:fixed; inset:0; z-index:99999;
  display:flex; align-items:center; justify-content:center;
  /* Large, slow, multi-stop falloffs (instead of the previous tighter two-stop
     blobs) so the glow reads as one continuous atmosphere with no perceptible
     ring where a gradient "ends" -- a fast falloff against a large flat dark
     field is exactly what made the content read as a separate tinted shape
     sitting ON the background instead of blended INTO it. */
  background:
    radial-gradient(115% 105% at 50% 40%, rgba(87,217,255,0.22) 0%, rgba(87,217,255,0.10) 32%, rgba(87,217,255,0.03) 58%, transparent 80%),
    radial-gradient(105% 95% at 8% 95%, rgba(124,123,255,0.17) 0%, rgba(124,123,255,0.07) 32%, rgba(124,123,255,0.02) 58%, transparent 78%),
    radial-gradient(95% 88% at 96% 90%, rgba(255,184,92,0.10) 0%, rgba(255,184,92,0.04) 32%, transparent 75%),
    var(--bg);
  transition: opacity 576ms ease;
}
.as-overlay.as-hide{ opacity:0; }
.as-overlay.as-gone{ display:none; }
.as-overlay{ overflow:hidden; }
.as-overlay::before{
  content:"";
  position:absolute; inset:-15%;
  /* Same position/hue family as the main top blob above -- this pulses that
     existing glow's intensity rather than adding a second, differently-shaped
     glow on top of it (which was reading as its own separate ring). */
  background: radial-gradient(68% 60% at 50% 42%, rgba(120,195,255,0.15) 0%, rgba(120,195,255,0.06) 40%, transparent 78%);
  animation: asAmbientPulse 3.8s ease-in-out infinite;
  pointer-events:none;
}
@keyframes asAmbientPulse{
  0%, 100%{ transform: scale(1) translate(0,0); opacity:.65; }
  50%{ transform: scale(1.22) translate(2%, -2.6%); opacity:1; }
}
@media (prefers-reduced-motion: reduce){
  .as-overlay::before{ animation:none; }
}
.as-screen{
  position:relative;
  /* Sized to dominate the viewport rather than sit as a small centered card:
     bound mainly by viewport height (screens are almost always wider than
     tall), with a much higher cap than before so it isn't artificially
     capped on large/desktop displays — that capped-at-820px box is what made
     the reveal read as "a framed animation" instead of filling the screen's
     own environment. Kept at 94vw / a modest cap floor so phone-width
     portrait viewports are unaffected (they were already vw-bound). */
  width:min(94vw, 96vh, 1400px);
  aspect-ratio:248/247;
}
.as-seq-wrap{
  width:100%; height:100%; position:relative; transform-origin:50% 45%; mix-blend-mode:screen;
  transition: opacity 760ms cubic-bezier(.4,0,.2,1); will-change: opacity;
}
.as-seq-wrap.as-dissolve{ opacity:0; }
.as-seq-wrap.reset-snap{ transition:none !important; }

/* ---- Real reference-frame sequence -> robot handoff ----
   The 51 motion-interpolated frames (see build script) are pre-decoded
   into bitmaps and blitted onto this canvas every SPRITE_FRAME_MS (a raw
   drawImage, not an <img>.src swap -- reassigning src on a large data-URI
   ~20x/sec forces a re-parse each time and is what produced the visible
   stutter). Each frame carries a real alpha channel (background luminance
   keyed out to transparent, a soft ramp rather than a hard cut) so the
   glowing logo/shatter/particle content composites cleanly over the
   splash's own background with no visible rectangle edge -- more reliable
   than relying on a blend mode, which does not isolate consistently
   across ancestor stacking contexts. */
#spriteCanvas{
  position:absolute; inset:0; width:100%; height:100%;
}
/* Pantalla de inicio del agente: mismo fondo atmosferico del splash,
   para que la transicion no se sienta como un corte a otra pieza. */
.view[data-view="inicio"]{
  background:
    radial-gradient(60% 50% at 50% 8%, rgba(58,169,255,0.14), transparent 60%),
    radial-gradient(70% 60% at 85% 90%, rgba(124,123,255,0.09), transparent 60%),
    var(--bg);
}

.wm-scene{ position:absolute; inset:0; z-index:2; pointer-events:none; }
.robot-top{ position:absolute; left:25.4%; top:13.8%; width:50%; height:47%; opacity:0; transform:scale(.99); transform-origin:50% 55%; transition:opacity 760ms cubic-bezier(.22,.61,.36,1), transform 900ms cubic-bezier(.22,.61,.36,1); will-change:opacity,transform; }
.robot-top img{ width:100%; height:100%; display:block; filter:brightness(1.005) saturate(1.05) drop-shadow(0 0 .7vmin rgba(87,217,255,.18)); }
.wm-scene.building .robot-top, .wm-scene.settled .robot-top{ opacity:1; transform:scale(1); animation:asRobotBreathe 2.1s ease-in-out infinite; }
@keyframes asRobotBreathe{ 0%, 100%{ filter:brightness(1) saturate(1); } 50%{ filter:brightness(1.09) saturate(1.08); } }
.robot-shine{
  position:absolute; inset:0;
  -webkit-mask-size:100% 100%; mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  background:
    radial-gradient(34% 28% at 32% 24%, rgba(255,255,255,.95), transparent 72%),
    linear-gradient(115deg, transparent 28%, rgba(255,255,255,.5) 45%, rgba(255,255,255,.88) 50%, rgba(255,255,255,.5) 55%, transparent 72%);
  background-repeat:no-repeat, no-repeat;
  background-size:100% 100%, 260% 260%;
  background-position:0 0, 140% -35%;
  mix-blend-mode:screen;
  opacity:.92;
  animation:asGlossSweep 3.18s ease-in-out infinite;
  pointer-events:none;
}
@keyframes asGlossSweep{
  0%, 100%{ background-position:0 0, 140% -35%; }
  50%{ background-position:0 0, -45% 140%; }
}
.thread-layer{ position:absolute; inset:0; width:100%; height:100%; opacity:0; transition:opacity 507ms ease; }
.wm-scene.building .thread-layer, .wm-scene.settled .thread-layer{ opacity:1; }

#threadBlue, #threadBlueHi{ stroke-dasharray:1; stroke-dashoffset:1; opacity:1; transition:stroke-dashoffset 1085ms cubic-bezier(.3,.8,.3,1), opacity 1139ms ease 1085ms; }
.wm-scene.building #threadBlue, .wm-scene.building #threadBlueHi{ stroke-dashoffset:0; }
.wm-scene.building.handoff #threadBlue, .wm-scene.building.handoff #threadBlueHi,
.wm-scene.settled #threadBlue, .wm-scene.settled #threadBlueHi{ opacity:0; transition-delay:0ms; }
#threadPath, #threadHighlight{ stroke-dasharray:1; stroke-dashoffset:1; opacity:0; transition:opacity 441ms ease, stroke-dashoffset 1139ms cubic-bezier(.3,.8,.3,1); }
.wm-scene.building.handoff #threadPath, .wm-scene.building.handoff #threadHighlight,
.wm-scene.settled #threadPath, .wm-scene.settled #threadHighlight{ opacity:1; }
.spark{ fill:#ffe6b0; filter:drop-shadow(0 0 4px rgba(255,225,170,1)) drop-shadow(0 0 10px rgba(255,190,110,.75)) drop-shadow(0 0 20px rgba(255,170,90,.4)); opacity:0; transition:opacity 441ms ease 1139ms; }
.wm-scene.building .spark, .wm-scene.settled .spark{ opacity:1; }

/* Fondo en movimiento entre azules + destellos alrededor del avatar, mientras
   se arman las letras del wordmark (y hasta que se cierra la pantalla de inicio).
   El fondo va en .as-screen ANTES del canvas del logo, o sea DETRAS de todo, y
   se enciende con los mismos estados building/settled de .wm-scene (via :has,
   asi no hace falta tocar el JavaScript). Sin :has el fondo simplemente no se ve. */
/* Moving blue background: drawn on a small canvas (see the script) with the geometry, periods and easing of the
   original CSS animation; it always covers the whole screen. */
.as-bg-canvas{ position:fixed; inset:0; width:100%; height:100%; opacity:0; transition:opacity 700ms ease; pointer-events:none; }
.as-screen:has(.wm-scene.building) ~ .as-bg-canvas, .as-screen:has(.wm-scene.settled) ~ .as-bg-canvas{ opacity:1; }
.as-overlay.as-prewarm .as-bg-canvas, .as-overlay.as-prewarm .wm-scene{ opacity:.012 !important; transition:none !important; }
.as-overlay:has(.wm-scene.building) .as-bg-canvas, .as-overlay:has(.wm-scene.settled) .as-bg-canvas{ opacity:1; }
.as-overlay:has(.wm-scene.resetting) .as-bg-canvas{ transition:none !important; }
.avatar-glints{ position:absolute; left:25.4%; top:13.8%; width:50%; height:47%; pointer-events:none; }
.glint{
  position:absolute; width:5px; height:5px; border-radius:50%;
  background:#eaf7ff;
  box-shadow:0 0 6px 1px rgba(135,222,255,.95), 0 0 14px 4px rgba(46,167,255,.6);
  opacity:0; transform:scale(.4);
}
.wm-scene.building .glint, .wm-scene.settled .glint{ animation:asGlintTwinkle 1.7s ease-in-out infinite; }
@keyframes asGlintTwinkle{
  0%, 100%{ opacity:0; transform:scale(.4); }
  50%{ opacity:1; transform:scale(1); }
}
/* El avatar flota sobre el fondo: sube y baja apenas. Usa la propiedad `translate`
   (independiente de `transform`) para no pisar la entrada con escala del robot;
   conserva la animacion de brillo asRobotBreathe de la regla de arriba. */
.wm-scene.building .robot-top, .wm-scene.settled .robot-top{ animation:asRobotBreathe 2.1s ease-in-out infinite, asRobotFloat 4.4s ease-in-out infinite; }
@keyframes asRobotFloat{
  0%, 100%{ translate:0 0; }
  50%{ translate:0 -6%; }
}

.wm-wrap{ position:absolute; left:10%; width:80%; top:62%; height:15%; display:flex; align-items:center; justify-content:center; z-index:3; }
.wordmark{ position:relative; display:flex; align-items:flex-end; justify-content:center; line-height:1; white-space:nowrap; font:800 calc(min(94vw, 90vh, 820px) * 0.122) 'Inter',sans-serif; letter-spacing:-0.015em; }
.letter-fx{ position:absolute; inset:0; width:100%; height:100%; z-index:3; pointer-events:none; }
.ch{
  position:relative; z-index:2; display:inline-block; color:#eef5ff;
  background:linear-gradient(180deg, #ffffff 0%, #d9ecff 55%, #9fd8ff 100%);
  -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent;
  filter:drop-shadow(0 0 5px rgba(135,222,255,.85)) drop-shadow(0 0 14px rgba(87,217,255,.5)) drop-shadow(0 0 26px rgba(255,196,130,.28));
  opacity:0; transform:scale(.92); transition:opacity 279ms ease, transform 355ms cubic-bezier(.2,1.3,.4,1);
}
.wm-scene.building .ch.on, .wm-scene.settled .ch{ opacity:1; transform:scale(1); }
.wm-scene.resetting .ch, .wm-scene.resetting .ch.on, .wm-scene.resetting .idot,
.wm-scene.resetting .idot::before, .wm-scene.resetting .idot::after,
.wm-scene.resetting .wm-reflect, .wm-scene.resetting .tagline-live, .wm-scene.resetting .wm-wrap,
.wm-scene.resetting .robot-top, .wm-scene.resetting .robot-shine, .wm-scene.resetting .thread-layer, .wm-scene.resetting #threadPath,
.wm-scene.resetting #threadHighlight, .wm-scene.resetting #threadBlue, .wm-scene.resetting #threadBlueHi,
.wm-scene.resetting .spark, .wm-scene.resetting .glint{ transition:none !important; animation:none !important; }
.as-screen:has(.wm-scene.resetting) .as-bg-flux{ transition:none !important; animation:none !important; }
.ch-i{ position:relative; padding-top:.30em; }
.idot{ position:absolute; left:50%; top:-0.03em; width:.44em; height:.44em; transform:translateX(-50%) scale(.4); opacity:0; transition:opacity 405ms ease 77ms, transform 532ms cubic-bezier(.2,1.5,.35,1) 77ms; filter:drop-shadow(0 0 6px rgba(243,198,117,.95)) drop-shadow(0 0 14px rgba(243,198,117,.62)) drop-shadow(0 0 26px rgba(255,205,135,.38)); }
/* Backup halo painted with a plain radial-gradient (not a filter) so the glow
   stays present on engines that render stacked drop-shadow filters much weaker
   (notably iOS Safari) — a gradient paints identically everywhere. Kept small
   and soft: this is a subtle assist behind the drop-shadow filter above, not
   the main glow, so it doesn't read as a solid blob/smudge. */
.idot::before{
  content:""; position:absolute; left:50%; top:50%;
  width:170%; height:170%; transform:translate(-50%,-50%);
  background:radial-gradient(circle, rgba(255,224,170,.5) 0%, rgba(255,205,135,.28) 32%, rgba(255,190,110,.12) 56%, transparent 74%);
  border-radius:50%; pointer-events:none; z-index:-1;
}
.idot img{ width:100%; height:100%; display:block; position:relative; z-index:1; }
.wm-scene.building .ch-i.on .idot, .wm-scene.settled .idot{ opacity:1; transform:translateX(-50%) scale(1); }
/* One-shot "ignition" beat: once the wordmark is fully settled, the globe over
   the i doesn't just sit there having faded in with the other letters — it
   flares up like it's switching on (brightness + scale pop on the glow, plus
   a quick flash-burst ring through the ::after pseudo) and settles back to its
   normal glow, so it reads as a deliberate closing highlight/protagonist beat
   rather than just another letter appearing. Plays once (no loop). */
.idot::after{
  content:""; position:absolute; left:50%; top:50%; width:100%; height:100%;
  transform:translate(-50%,-50%) scale(.3); border-radius:50%;
  background:radial-gradient(circle, rgba(255,255,255,.95) 0%, rgba(255,224,170,.55) 42%, transparent 74%);
  opacity:0; pointer-events:none; z-index:2; mix-blend-mode:screen;
}
.wm-scene.settled .idot{
  animation: asIdotIgnite 830ms cubic-bezier(.16,.9,.25,1) 158ms both;
}
.wm-scene.settled .idot::before{
  animation: asIdotHaloFlash 830ms cubic-bezier(.16,.9,.25,1) 158ms both;
}
.wm-scene.settled .idot::after{
  animation: asIdotFlashBurst 830ms cubic-bezier(.1,.8,.2,1) 158ms both;
}
@keyframes asIdotIgnite{
  0%{ transform:translateX(-50%) scale(1); filter:drop-shadow(0 0 6px rgba(243,198,117,.95)) drop-shadow(0 0 14px rgba(243,198,117,.62)) drop-shadow(0 0 26px rgba(255,205,135,.38)); }
  35%{ transform:translateX(-50%) scale(1.32); filter:brightness(2.3) drop-shadow(0 0 10px rgba(255,244,214,1)) drop-shadow(0 0 26px rgba(255,214,140,.92)) drop-shadow(0 0 46px rgba(255,190,110,.66)); }
  60%{ transform:translateX(-50%) scale(.95); filter:brightness(1.45) drop-shadow(0 0 8px rgba(255,230,180,.98)) drop-shadow(0 0 18px rgba(255,205,135,.72)) drop-shadow(0 0 34px rgba(255,190,110,.46)); }
  100%{ transform:translateX(-50%) scale(1); filter:drop-shadow(0 0 6px rgba(243,198,117,.95)) drop-shadow(0 0 14px rgba(243,198,117,.62)) drop-shadow(0 0 26px rgba(255,205,135,.38)); }
}
@keyframes asIdotHaloFlash{
  0%{ opacity:1; transform:translate(-50%,-50%) scale(1); }
  35%{ opacity:1; transform:translate(-50%,-50%) scale(2.1); }
  60%{ opacity:.85; transform:translate(-50%,-50%) scale(1.25); }
  100%{ opacity:1; transform:translate(-50%,-50%) scale(1); }
}
@keyframes asIdotFlashBurst{
  0%{ opacity:0; transform:translate(-50%,-50%) scale(.3); }
  18%{ opacity:1; transform:translate(-50%,-50%) scale(1.1); }
  45%{ opacity:.55; transform:translate(-50%,-50%) scale(2.7); }
  100%{ opacity:0; transform:translate(-50%,-50%) scale(3.8); }
}

.wm-reflect{ position:absolute; left:0; right:0; top:100%; height:.34em; overflow:hidden; display:flex; align-items:flex-start; justify-content:center; line-height:1; font:800 calc(min(94vw, 90vh, 820px) * 0.122) 'Inter',sans-serif; letter-spacing:-0.015em; color:rgba(159,216,255,.4); transform:scaleY(-1); -webkit-mask-image:linear-gradient(rgba(0,0,0,.35), transparent 55%); mask-image:linear-gradient(rgba(0,0,0,.35), transparent 55%); filter:blur(1.5px); opacity:0; transition:opacity 633ms ease 152ms; }
.wm-scene.settled .wm-reflect{ opacity:1; }
.tagline-live{ position:absolute; left:8%; right:8%; top:84%; text-align:center; font:500 calc(min(94vw, 90vh, 820px) * 0.032) 'Inter',sans-serif; letter-spacing:.02em; color:rgba(210,232,255,.85); text-shadow:0 0 10px rgba(87,217,255,.35); opacity:0; transform:translateY(6px); transition:opacity 658ms ease, transform 658ms ease; }
.wm-scene.settled .tagline-live{ opacity:1; transform:translateY(0); }
