/* ==========================================================================
   THE INTRO
   A full screen layer that writes the welcome, then lifts away to reveal the
   hero underneath. It sits over a copy of the hero's own colour, so there is
   never a black frame, never a flash, and nothing to cut to: the layer simply
   rises and the page it was covering is already there.
   ========================================================================== */

.intro{
  position:fixed;inset:0;z-index:120;
  background:
    radial-gradient(ellipse 76% 64% at 12% 14%, #FFF0CE 0%, rgba(255,240,206,0) 62%),
    radial-gradient(ellipse 74% 62% at 88% 18%, #FFDCE9 0%, rgba(255,220,233,0) 64%),
    radial-gradient(ellipse 92% 74% at 50% 104%, #D6EAFB 0%, rgba(214,234,251,0) 68%),
    linear-gradient(158deg, #FFFDF7 0%, #FFF9FB 52%, #F6FBFF 100%);
  overflow:hidden;
  /* the lift: the layer travels up and fades, and the hero is already painted
     underneath, so the two are never separated by an empty frame */
  transition:transform 1.05s cubic-bezier(.7,0,.28,1), opacity .75s ease .3s}
/* No standing will-change: a full screen layer promoted for the whole
   performance gets rasterised once at a fixed scale, and on phones (Safari
   above all) the letters drawn into it came out soft and pixelated. The lift
   transition promotes the layer by itself, only for the second it moves. */

.intro.gone{transform:translateY(-102%);opacity:0;pointer-events:none}

/* The soft shadow under the letters is an SVG filter inside the drawing
   (#introShadow, sized by intro-write.js), not a CSS filter on the element.
   CSS filters on a whole SVG render at 1x on high density screens in Safari,
   and they re-raster the full screen on every stroke. */
.intro svg{position:absolute;inset:0;width:100%;height:100%}

.intro-pen{position:absolute;z-index:12;width:1.5%;min-width:13px;aspect-ratio:.2;
  left:0;top:0;will-change:transform;   /* placed by intro-write.js through transform */
  transform:translate(-14%,-96%) rotate(24deg);transform-origin:50% 100%;
  opacity:0;transition:opacity .18s linear;
  background:linear-gradient(180deg,#3E7CD9 0%,#3E7CD9 62%,#F3DCC0 74%,#F3DCC0 88%,#33284A 100%);
  border-radius:3px 3px 0 0;
  filter:drop-shadow(0 3px 5px rgba(51,40,74,.3))}

.intro-mascot{position:absolute;left:50%;bottom:2%;width:min(15%,150px);
  transform:translateX(-50%);z-index:14;opacity:0}
.intro-mascot img{width:100%;filter:drop-shadow(0 14px 20px rgba(51,40,74,.24))}
.intro.playing .intro-mascot{animation:intro-pop .9s 6.7s cubic-bezier(.2,1.6,.5,1) forwards}
@keyframes intro-pop{0%{opacity:0;transform:translateX(-50%) translateY(46px) scale(.72)}
  100%{opacity:1;transform:translateX(-50%) translateY(0) scale(1)}}

.intro-skip{position:absolute;right:1.2rem;top:1.2rem;z-index:20;
  font-family:var(--display);font-weight:600;font-size:.86rem;color:var(--ink);
  background:rgba(255,255,255,.92);border:0;border-radius:999px;padding:.62rem 1.2rem;
  cursor:pointer;box-shadow:0 4px 0 rgba(51,40,74,.12), 0 10px 22px rgba(51,40,74,.16);
  transition:transform .25s cubic-bezier(.34,1.56,.64,1)}
.intro-skip:hover{transform:translateY(-2px)}

/* The page underneath is held still while the intro runs, so nothing can shift
   or be half read behind it. It is painted, just not scrollable. */
body.intro-on{overflow:hidden}
/* ...and its loops wait. The breathing words, the bobbing bubble, the drifting
   shapes all kept animating under a layer that covers them completely, and on
   a phone that work was taken straight out of the pen's frames. They resume the
   moment the layer lifts; a loop picking up where it paused looks the same. */
body.intro-on > :not(.intro),
body.intro-on > :not(.intro) *,
body.intro-on > :not(.intro) *::before,
body.intro-on > :not(.intro) *::after{animation-play-state:paused !important}

/* Phones get the same sequence, just quicker to the point, and the words are
   sized off the viewport so they never crowd the edges. */
@media (max-width:720px){
  .intro-mascot{width:min(26%,120px);bottom:6%}
  .intro-skip{right:.8rem;top:.8rem;font-size:.8rem;padding:.55rem 1rem}
}

/* Nothing uninvited: with reduced motion the intro shows its finished frame and
   steps aside quickly instead of performing. */
@media (prefers-reduced-motion: reduce){
  .intro{transition:opacity .4s ease}
  .intro.gone{transform:none;opacity:0}
  .intro.playing .intro-mascot{animation:none;opacity:1}
}
