/* ============================================================
   NOVA BOOT — the arrival animation (nova-boot.css)

   WHAT THIS REPLACES
   ------------------
   Nova Assistant's first load used to run the shared shell's first-load
   reveal: layout.css gates `.rise` / `.stagger > *` to "first load only" (they
   are neutralised once `body.nav-ready` lands), so on arrival every element in
   the view animated in on its own staggered delay. On a dense three-pane chat —
   sidebar rows, pinned chats, project rows, greeting, chips, composer — that is
   dozens of independently-timed pop-ins firing over each other while data is
   still streaming in and re-rendering rows mid-animation. Vincent: "instead of
   this weird glitching animation — because I think it's coming from something
   else". He was right that it wasn't the chat view: it was the shell.

   So on this product that cascade is switched OFF (app.js marks the body
   nav-ready before first paint) and this ONE deliberate animation runs instead.

   THE ANIMATION — the wordmark, and nothing else
   ---------------------------------------------
   Three rounds of subtraction (see nova-boot.js for the quotes): the nine
   opening slices went, then the spark icon went. What is left is the Nova
   wordmark coming up out of nothing in the middle of the screen, with a single
   soft light passing over it.

   Every value here is tuned around ONE idea: nothing should look like it is
   *starting*. No bounce, no overshoot, no spring. It enters already most of the
   way there on a long decelerating curve, so the eye reads it as arriving
   rather than as being animated.

   Transform/opacity/filter only — GPU-cheap, no layout thrash.
   ============================================================ */

/* ---- the timings, in one place ----------------------------------------
   These are NOT the app's --mo-dur-* rungs and must not be snapped onto them:
   the numbers below are the tuning this whole file is about (see the note
   above), and 260/420/520 sit deliberately between 200 and 480. They live
   here so the arrival can be retimed as a set rather than line by line. */
:root {
  --dur-nvb-exit: 260ms;    /* overlay fade + stage lift on the way out */
  --dur-nvb-word: 420ms;    /* the wordmark coming up out of nothing    */
  --dur-nvb-sheen: 520ms;   /* the single light pass across the mark    */
  --delay-nvb-sheen: 120ms;
  --ease-nvb-settle: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-nvb-sweep: cubic-bezier(0.35, 0, 0.2, 1);
}

.nvb {
  position: fixed;
  inset: 0;
  z-index: var(--z-boot);
  display: grid;
  place-items: center;
  background: var(--bg);
  /* The overlay owns the screen while it plays; nothing behind it is clickable
     and nothing behind it is announced. */
  pointer-events: all;
  opacity: 1;
  /* The exit is the longest curve in the file. A quick cut at the end undoes the
     calm the entrance just bought. */
  transition: opacity var(--dur-nvb-exit) var(--mo-ease-standard);
}
.nvb.is-out { opacity: 0; pointer-events: none; }

.nvb-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  /* The stage lifts a few pixels as it leaves, so the overlay reads as pulling
     away from the app rather than simply switching off. */
  transition: transform var(--dur-nvb-exit) var(--mo-ease-standard);
}
.nvb.is-out .nvb-stage { transform: translateY(-6px); }

/* ---- the wordmark ---- */
.nvb-wordwrap { position: relative; display: block; color: var(--text-100); }

.nvb-word {
  display: block;
  height: 34px;
  width: auto;
  opacity: 0;
  /* 0.16/1/0.3/1 — close to a pure ease-out with a very early peak velocity. It
     arrives fast and spends most of its time settling, which is what reads as
     "smooth" rather than "animated". */
  animation: nvb-word-in var(--dur-nvb-word) var(--ease-nvb-settle) both;
}
@keyframes nvb-word-in {
  from {
    opacity: 0;
    /* Up out of nothing: a small rise plus a scale that starts near-final.
       0.94, not 0.6 — a big scale jump is a pop, and this is a settle. */
    transform: translateY(10px) scale(0.94);
    filter: blur(7px);
  }
  55% { opacity: 1; }
  to {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}
/* One wordmark per theme — the same pair the rail lockup uses, so the intro and
   the app agree about which mark this product wears. The classes are named after
   the INK the file carries (white/black), not after the theme it belongs to: an
   earlier build called them -light/-dark, read as theme names, and painted black
   ink on the dark background — an invisible wordmark. */
[data-theme='light'] .nvb-word-white { display: none; }
[data-theme='dark'] .nvb-word-black,
:root:not([data-theme='light']) .nvb-word-black { display: none; }

/* The light sweep: one soft highlight crossing the wordmark once.
   mix-blend-mode:plus-lighter keeps it additive on both themes — a plain white
   overlay would wash the mark out on light. */
.nvb-sheen {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  mix-blend-mode: plus-lighter;
  opacity: 0;
  animation: nvb-sheen-on var(--dur-nvb-sheen) linear var(--delay-nvb-sheen) both;
}
.nvb-sheen::after {
  content: "";
  position: absolute;
  top: -40%;
  bottom: -40%;
  width: 34%;
  left: -50%;
  background: linear-gradient(100deg, transparent, color-mix(in srgb, currentColor 46%, transparent), transparent);
  filter: blur(6px);
  animation: nvb-sheen var(--dur-nvb-sheen) var(--ease-nvb-sweep) var(--delay-nvb-sheen) both;
}
@keyframes nvb-sheen-on { 0%, 100% { opacity: 0; } 20%, 74% { opacity: 1; } }
@keyframes nvb-sheen { from { left: -50%; } to { left: 120%; } }

/* ---- reduced motion ----
   Not "a faster animation" — no animation. The overlay still appears so the
   arrival is not a bare flash of an unpainted shell, but everything is in its
   final state immediately and nova-boot.js shortens the hold to match. */
@media (prefers-reduced-motion: reduce) {
  .nvb-word { animation: none; opacity: 1; transform: none; filter: none; }
  .nvb-sheen { display: none; }
  .nvb, .nvb-stage { transition: none; }
}
