/* -------------- Intro timeline -------------- */
/* --------------
The entrance a page plays when it shows the character: the face drops in, winks
once, and an emphasized word takes the accent on the way out of the wink.

Every delay is the previous step's start plus its duration, and the sequence only
reads right while that holds. The wink starts at 500 and runs 700, so the
emphasis waits 1200 — the exact frame the wink ends. Those three numbers are now
named by their value rather than by their part in the sequence, so the arithmetic
lives here in the comment instead of in the token names. Retiming a step means checking
the one after it.

The scope class stays because the emphasis color still travels through it: the
character and the word sit in different branches of the page, and a custom
property is how one declaration reaches both. The hero section is that element on
the home page; the centering wrapper is that element on the login page.
-------------- */
.intro {
  --nn-anima-color-var3: var(--nn-color-typo-primary);
}

/* -------------- Intro entrance -------------- */
/* --------------
The drop and the lean, hung off a modifier so the entrance is something a page
opts into rather than a property of the drawing. It also gives the script an
honest thing to read: a character with this class has an animation coming and is
worth waiting on before the eyes start tracking, one without it is not.
-------------- */
.character--intro {
  animation:
    character-enter var(--nn-anima-time-400ms) var(--nn-anima-ease-out) backwards,
    character-tilt var(--nn-anima-time-700ms) var(--nn-anima-ease-in-out) var(--nn-anima-time-500ms) 1
    backwards;
}

@keyframes character-enter {
  from {
    opacity: 0;
    translate: 0 calc(var(--nn-space-4x8) * -1);
  }

  to {
    opacity: 1;
    translate: 0 0;
  }
}

@keyframes character-tilt {
  0% {
    rotate: 0deg;
  }

  30%,
  55% {
    rotate: 5deg;
  }

  100% {
    rotate: 0deg;
  }
}

/* -------------- Intro wink -------------- */
/* --------------
One eye closes, once, after the character has landed, and the whole head leans
into it on the same curve so the wink reads as a gesture rather than as a lid
moving on its own. The eye squashes on the block axis and stretches on the
inline axis, because a lid closing gets wider as it flattens rather than
shrinking to a stub. Each moving part takes a separate transform property — the
head rotates, the entrance translates, the eye scales, the gaze translates — so
four pieces of motion sit on two elements without contending for one property or
having to be composed by hand.

The rule stands down once the script marks the character awake, and that is
load-bearing rather than tidiness. The blink in global-character.css claims the
same property on both eyes at the same specificity, so whichever file is linked
second would otherwise decide which eye is allowed to blink — and this one is
linked second, which left the winking eye holding a spent animation and blinking
alone. Excluding the awake state means the two rules never both apply, so the
outcome no longer depends on link order.
-------------- */
.character--intro:not(.character--awake) .character__eye--wink {
  animation: character-wink var(--nn-anima-time-700ms) var(--nn-anima-ease-in-out)
    var(--nn-anima-time-500ms) 1 backwards;
}

@keyframes character-wink {
  0% {
    transform: scale(1, 1);
  }

  30%,
  55% {
    transform: scale(1.35, 0.07);
  }

  80% {
    transform: scale(0.95, 1.08);
  }

  100% {
    transform: scale(1, 1);
  }
}

/* -------------- Intro emphasis -------------- */
/* --------------
The word the sequence lands on. It reads as ordinary sentence text until the
wink finishes, then takes the accent color and its wash. The animation does not
fill forwards on purpose: its end state is the same pair of tokens the nn-color
utilities already set on the element, so the utilities take the value back the
moment it ends and the resting state has one definition rather than two.

The color it starts from is a property rather than a literal because the text
around it differs per page — the hero sentences sit a step off the darkest ink,
a login heading does not — and the word has to begin as whatever its own
sentence is.
-------------- */
.intro__emphasis {
  animation: intro-emphasis-in var(--nn-anima-time-400ms) var(--nn-anima-ease-out)
    var(--nn-anima-time-1200ms) backwards;
}

@keyframes intro-emphasis-in {
  from {
    color: var(--nn-anima-color-var3);
    background-color: transparent;
  }

  to {
    color: var(--nn-color-accent-strong);
    background-color: var(--nn-color-accent-surface);
  }
}

/* -------------- Reduced motion -------------- */
/* --------------
Every step of the sequence is an animation onto a resting state the element
already declares, so switching them all off lands the page in its finished form
with nothing missing.
-------------- */
@media (prefers-reduced-motion: reduce) {
  .character--intro,
  .character--intro:not(.character--awake) .character__eye--wink,
  .intro__emphasis {
    animation: none;
  }
}
