/* "Vault" entrance to the study section, played when a signed-out reader solves the home page's
   brain teaser.
   Home (.vault.closing): two doors slide shut over the page and a seam of light glows where they meet.
   Study (.vault.opening), about 3.1s:
     0.0s  doors shut; the seam brightens and light streaks rush out of it (assets/vault.js draws them),
           so it feels like flying forward into the light
     0.9s  boom: a flash and a shockwave ring on the shut doors, and STUDY slams in
     2.1s  the title lifts away and the doors slide apart; the page settles in behind them
     3.1s  the overlay is removed
   Nothing plays under prefers-reduced-motion, and the overlay never takes input. */
.vault{ position:fixed; inset:0; z-index:9999; pointer-events:none; overflow:hidden; }
.vault-door{
  position:absolute; top:0; bottom:0; width:50.5%; will-change:transform;
  background-color:#0B0E13; background-size:48px 48px, 48px 48px, 100% 100%;
}
.vault-door.l{ left:0;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.028) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.028) 1px, transparent 1px),
    radial-gradient(ellipse 120% 80% at 100% 50%, #121a26 0%, #0B0E13 70%);
  box-shadow:inset -1px 0 0 rgba(74,222,128,.6), 14px 0 44px rgba(74,222,128,.18); }
.vault-door.r{ right:0;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.028) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.028) 1px, transparent 1px),
    radial-gradient(ellipse 120% 80% at 0% 50%, #121a26 0%, #0B0E13 70%);
  box-shadow:inset 1px 0 0 rgba(74,222,128,.6), -14px 0 44px rgba(74,222,128,.18); }

/* Seam of light where the doors meet. */
.vault-seam{ position:absolute; left:50%; top:0; bottom:0; width:3px; margin-left:-1.5px;
  background:linear-gradient(to bottom, transparent, #d9ffe8 30%, #ffffff 50%, #d9ffe8 70%, transparent);
  box-shadow:0 0 18px 4px rgba(74,222,128,.75), 0 0 60px 14px rgba(74,222,128,.35); opacity:0; will-change:transform, opacity; }
/* No mix-blend-mode: over the dark doors "screen" looks the same and a full-screen blend is costly to composite. */
.vault-warp{ position:absolute; inset:0; width:100%; height:100%; }
.vault-flash{ position:absolute; inset:0; opacity:0; will-change:opacity;
  background:radial-gradient(circle at 50% 50%, rgba(235,255,242,.95) 0%, rgba(74,222,128,.55) 28%, rgba(11,14,19,0) 70%); }
.vault-ring{ position:absolute; left:50%; top:50%; width:60px; height:60px; margin:-30px 0 0 -30px; border-radius:50%;
  border:2px solid #4ADE80; box-shadow:0 0 24px rgba(74,222,128,.8), inset 0 0 24px rgba(74,222,128,.5); opacity:0; will-change:transform, opacity; }

.vault-title{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); opacity:0; will-change:transform, opacity;
  display:flex; flex-direction:column; align-items:center; gap:16px; text-align:center;
  font-family:'Space Grotesk',sans-serif; color:#ECEEF2; white-space:nowrap;
}
.vault-word{ font-size:clamp(48px, 13vw, 120px); font-weight:700; letter-spacing:.28em; margin-right:-.28em; line-height:1;
  text-shadow:0 0 24px rgba(74,222,128,.55), 0 0 70px rgba(74,222,128,.3); }
.vault-sub{ font-family:'JetBrains Mono',monospace; font-size:12px; letter-spacing:.24em; text-transform:uppercase; color:#4ADE80;
  display:flex; align-items:center; gap:10px; }
.vault-sub::before{ content:""; width:7px; height:7px; border-radius:50%; background:#4ADE80; box-shadow:0 0 10px #4ADE80; }

/* Home: the doors meet, then the seam lights up. */
.vault.closing .vault-door.l{ animation:vault-in-l .5s cubic-bezier(.6,0,.3,1) both; }
.vault.closing .vault-door.r{ animation:vault-in-r .5s cubic-bezier(.6,0,.3,1) both; }
.vault.closing .vault-seam{ animation:vault-seam-on .3s ease-out .45s both; }

/* Study */
.vault.opening .vault-seam{ opacity:1; animation:vault-seam-charge .9s ease-in both, vault-seam-off .35s ease-out .9s forwards; }
.vault.opening .vault-flash{ animation:vault-flash .75s ease-out .85s both; }
/* forwards, not both: "both" would show the ring's first frame (a small bright dot) during the delay. */
.vault.opening .vault-ring{ animation:vault-ring .9s cubic-bezier(.1,.6,.3,1) .9s forwards; }
.vault.opening .vault-title{ animation:vault-boom .55s cubic-bezier(.2,1.35,.35,1) .92s both, vault-title-out .4s ease-in 2.1s forwards; }
.vault.opening .vault-door.l{ animation:vault-out-l .85s cubic-bezier(.7,0,.2,1) 2.2s both; }
.vault.opening .vault-door.r{ animation:vault-out-r .85s cubic-bezier(.7,0,.2,1) 2.2s both; }
/* The page behind waits while the doors are shut (html.vault-hold: its own load animations are
   paused too, and study-home.js holds its count-ups). The hold is released at 2.0s, still behind the
   shut doors, so that restyle doesn't land on the frames where the doors start to move (2.2s). */
html.vault-reveal .sh-wrap{ animation:vault-page .9s cubic-bezier(.2,.7,.2,1) both; }
html.vault-hold .sh-wrap, html.vault-hold .sh-wrap *{ animation-play-state:paused !important; }

@keyframes vault-in-l{ from{ transform:translateX(-101%); } to{ transform:none; } }
@keyframes vault-in-r{ from{ transform:translateX(101%); } to{ transform:none; } }
@keyframes vault-out-l{ from{ transform:none; } to{ transform:translateX(-101%); } }
@keyframes vault-out-r{ from{ transform:none; } to{ transform:translateX(101%); } }
@keyframes vault-seam-on{ from{ opacity:0; transform:scaleY(.2); } to{ opacity:.8; transform:none; } }
@keyframes vault-seam-charge{ from{ opacity:.8; transform:scaleX(1); } to{ opacity:1; transform:scaleX(2.2); } }
@keyframes vault-seam-off{ to{ opacity:0; transform:scaleX(6); } }
@keyframes vault-flash{ 0%{ opacity:0; } 14%{ opacity:1; } 100%{ opacity:0; } }
@keyframes vault-ring{ 0%{ opacity:1; transform:scale(.2); } 100%{ opacity:0; transform:scale(28); } }
/* Scale + fade only: an animated blur on large glowing text is repainted every frame. */
@keyframes vault-boom{ from{ opacity:0; transform:translate(-50%,-50%) scale(2.6); }
  to{ opacity:1; transform:translate(-50%,-50%) scale(1); } }
@keyframes vault-title-out{ from{ opacity:1; transform:translate(-50%,-50%) scale(1); }
  to{ opacity:0; transform:translate(-50%,-56%) scale(1.04); } }
/* Fade only: scaling the whole page while its own animations run re-rasterises it every frame. */
@keyframes vault-page{ from{ opacity:.35; } to{ opacity:1; } }

@media (prefers-reduced-motion: reduce){ .vault{ display:none; } html.vault-reveal .sh-wrap{ animation:none; } html.vault-hold .sh-wrap *{ animation-play-state:running !important; } }
