/* Home intro (home page only, first visit per tab; see intro.js).
   This file holds the 2D version (no WebGL, slow device, or the 3D files late) and the frame
   the 3D one (intro3d.js) plays in. Same story as the 3D: paste, slap, brush, rip.
   A wet paste line glints across a concrete wall, the show's red poster is slapped onto it,
   one brush pass of light runs over it, then it is ripped down the middle: the left half is
   yanked at the viewer and fills the screen, and behind it the wall is gone and the red hero
   is there. The show's own poster, never an ad (Ian, 9 Oct). Nothing here shows unless
   intro.js puts .intro-on on <html>; reduced motion never gets it.
   2D timeline (20% quicker since 18 Oct, matching the 3D pace): paste line 0.08-0.48s, slap 0.36-0.76s,
   brush 0.92-1.4s, tear 1.6s, left half fills the screen 1.96s (wall gone underneath it), hero
   released 1.96s, removed 2.44s (intro.js holds the matching timers). */

.intro{display:none}
.intro-on{overflow:hidden}
.intro-on .intro{display:block;position:fixed;inset:0;z-index:100}

/* the wall: concrete; it goes at once while the yanked half covers the screen */
.intro::before{content:"";position:absolute;inset:0;
  background:url("img/grain.webp") center/520px,var(--concrete) url("img/concrete.webp") center/420px;
  background-blend-mode:multiply;animation:intro-wall 0s linear 1.96s forwards}
@keyframes intro-wall{to{opacity:0}}

.intro-art{position:absolute;inset:0;overflow:hidden}
/* the wet paste line: a glint drawn across the wall by the brush */
.intro-art::before{content:"";position:absolute;left:0;top:47%;width:100%;height:3px;border-radius:2px;
  background:linear-gradient(90deg,transparent,rgba(255,226,180,.25) 60%,#fff6e6 98%,transparent);
  box-shadow:0 0 14px 3px rgba(255,214,160,.45);transform-origin:0 50%;transform:scaleX(0) rotate(-2deg);
  animation:intro-line .4s cubic-bezier(.65,0,.35,1) .08s forwards,intro-gone .2s linear .56s forwards}
@keyframes intro-line{to{transform:scaleX(1) rotate(-2deg)}}
@keyframes intro-gone{to{opacity:0}}

/* the slap: thrown in curled from below the viewer, lands, a short knock */
.intro-sheet{position:absolute;inset:4vmin;transform:rotate(-.8deg);opacity:0;
  animation:intro-slap .4s cubic-bezier(.3,.05,.6,1) .36s forwards,intro-knock .2s ease-out .76s}
@keyframes intro-slap{
  0%{opacity:0;transform:translate(-8%,55%) rotate(-14deg) scale(1.6)}
  25%{opacity:1}
  100%{opacity:1;transform:rotate(-.8deg)}}
@keyframes intro-knock{0%{transform:rotate(-.8deg) scale(1.012)}100%{transform:rotate(-.8deg)}}

/* the whole sheet sits on top of the two torn halves until the moment it tears */
.intro-whole{position:absolute;inset:0;background:var(--paper);animation:intro-hide 0s linear 1.6s forwards}
@keyframes intro-hide{to{visibility:hidden}}
/* a shadow under each piece so it reads as paper coming off the wall */
.intro-piece{position:absolute;inset:0;filter:drop-shadow(0 20px 26px rgba(0,0,0,.5))}

/* each half: white paper with the red print on it; clip-paths come from build_site.py */
.intro-half{position:absolute;inset:0;background:var(--paper)}
.intro-print{position:absolute;inset:0;background:var(--red);display:flex;flex-direction:column;justify-content:center;
  padding:0 clamp(1.2rem,7vw,7rem)}
.intro-print::after{content:"";position:absolute;inset:0;background:url("img/grain.webp") center/700px;opacity:.6;mix-blend-mode:multiply}
.intro-lock{position:relative;z-index:1;margin:0;font-family:var(--display);color:var(--ink);
  font-size:min(15vw,24vh);line-height:.86;letter-spacing:-.01em}
.intro-lock span{display:block}
.intro-sub{position:relative;z-index:1;margin:1.2em 0 0;font:800 clamp(.95rem,1.6vw,1.4rem)/1.2 var(--text);color:var(--ink)}

.intro-roll{display:none} /* the old paste roller; the 2D version no longer uses it */

/* the brush pass: one band of light over the wet sheet */
.intro-sheen{position:absolute;inset:0;pointer-events:none;opacity:0;
  background:linear-gradient(115deg,transparent 38%,rgba(255,240,220,.5) 48%,rgba(255,255,255,.1) 53%,transparent 60%) no-repeat;
  background-size:250% 100%;background-position:120% 0;
  animation:intro-sheen .48s ease-in-out .92s forwards}
@keyframes intro-sheen{0%{opacity:1;background-position:120% 0}100%{opacity:1;background-position:-20% 0}}

/* the rip: the left half is yanked at the viewer and fills the screen; the right half flies off */
.intro-piece.a{transform-origin:30% 50%;animation:intro-off-a .44s cubic-bezier(.55,0,.9,.3) 1.6s forwards}
.intro-piece.b{animation:intro-off-b .68s cubic-bezier(.5,0,.75,0) 1.64s forwards}
@keyframes intro-off-a{
  0%{transform:none;opacity:1}
  20%{transform:translate(-1%,-1%) rotate(-1.5deg)}
  82%{transform:translate(18%,4%) rotate(-6deg) scale(4.2);opacity:1}
  100%{transform:translate(30%,6%) rotate(-8deg) scale(7);opacity:0}}
@keyframes intro-off-b{
  0%{transform:none}
  18%{transform:translate(1.5%,1%) rotate(1.5deg)}
  100%{transform:translate(110%,-26%) rotate(14deg)}}

/* 3D first (intro3d.js): while it loads only the concrete wall shows and the 2D sheet waits,
   unstarted, in case it is needed. Once the 3D scene runs the 2D sheet is never shown. At the
   tear the wall (here and in the scene) dissolves, so the halves fly off over the page itself. */
.intro-wait .intro-art{visibility:hidden}
.intro-wait .intro::before,.intro-wait .intro *{animation-play-state:paused!important}
/* the 3D scene opens in low raking light, so the wall waits dimmed; the 2D version brightens it */
.intro-wait .intro::before{filter:brightness(.32)}
.intro::before{transition:filter .28s ease-out}
.intro-gl{position:absolute;inset:0;z-index:1;display:block;width:100%;height:100%;opacity:0;transition:opacity .28s ease-out}
.intro-gl.on{opacity:1}
.intro-3d .intro-art{display:none}
.intro-3d .intro::before{animation:none}
.intro-3d.intro-bare .intro::before{opacity:0}
.intro-gl.out{opacity:0;transition:opacity .2s ease-in}
.intro-bare .intro,.intro-bare .intro-gl,.intro-out .intro,.intro-out .intro-gl{pointer-events:none}

/* late fallback from 3D skips straight to the tear so slow devices are not penalized twice */
.intro-fast .intro::before{animation-delay:.44s}
.intro-fast .intro-art::before,.intro-fast .intro-sheen{display:none}
.intro-fast .intro-sheet{opacity:1;animation:none}
.intro-fast .intro-whole,.intro-fast .intro-piece.a{animation-delay:.1s}
.intro-fast .intro-piece.b{animation-delay:.13s}

/* keep the white header masked while on the nocturnal wall, then slide it in as the wipe clears */
.intro-on .head,.intro-on .ribbon{opacity:0;transform:translateY(-100%);
  transition:transform .36s cubic-bezier(.16,1,.3,1),opacity .28s ease-out}
.intro-bare .head,.intro-bare .ribbon,.intro-out .head,.intro-out .ribbon{
  opacity:1;transform:translateY(0);transition-delay:.12s}

/* the hero piece waits for the wall, then is made in front of the visitor */
.intro-hold .hero .patch,.intro-hold .hero .spray,.intro-hold .hero .sticker,.intro-hold .hero .drip{animation-play-state:paused}

.intro-skip{position:absolute;right:max(4vmin,1rem);bottom:max(4vmin,1rem);z-index:2;min-height:44px;
  font:800 var(--s-1)/1 var(--text);padding:.85rem 1.1rem .75rem;cursor:pointer;
  background:var(--ink);color:var(--paper);border:3px solid var(--ink);border-radius:2px}
.intro-skip:hover{background:var(--paper);color:var(--ink)}
.intro-skip:focus-visible{outline:3px solid var(--paper);outline-offset:3px}
.intro-bare .intro-skip,.intro-out .intro-skip{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .16s,visibility 0s .16s}

/* tall, narrow screens: four lines, bigger */
@media (max-aspect-ratio:3/4){
  .intro-lock{font-size:min(25vw,13vh)}
}

@media (prefers-reduced-motion:reduce){
  .intro-on .intro{display:none}
  .intro-on{overflow:visible}
  .intro-on .head,.intro-on .ribbon{opacity:1;transform:none;transition:none}
  .intro-hold .hero .patch,.intro-hold .hero .spray,.intro-hold .hero .sticker,.intro-hold .hero .drip{animation-play-state:running}
}

/* generated by build_site.py (intro_tear_css): the tear line */
.intro-half.a{clip-path:polygon(0% 0%,68% 0%,68.3% 3.6%,64% 8.2%,64.9% 12.6%,62.1% 16.3%,59.2% 20.2%,58.7% 24.1%,58.1% 27.8%,56.4% 30.3%,58.7% 33.6%,56.7% 35.7%,54.7% 39.9%,55.6% 42.6%,51.9% 44.4%,50.2% 49.5%,51% 54%,46.7% 57.5%,47% 60.1%,44.6% 64.2%,46% 66%,46.9% 68.5%,44% 72.1%,44.6% 75.1%,42% 79.2%,40.5% 83.6%,39.5% 87.6%,38.1% 91.5%,36.9% 95.7%,35.8% 99.2%,34% 100%,0% 100%)}.intro-half.a .intro-print{clip-path:polygon(0% 0%,calc(68% + -5px) 0%,calc(68.3% + -5px) 3.6%,calc(64% + -5px) 8.2%,calc(64.9% + -5px) 12.6%,calc(62.1% + -5px) 16.3%,calc(59.2% + -5px) 20.2%,calc(58.7% + -5px) 24.1%,calc(58.1% + -5px) 27.8%,calc(56.4% + -5px) 30.3%,calc(58.7% + -5px) 33.6%,calc(56.7% + -5px) 35.7%,calc(54.7% + -5px) 39.9%,calc(55.6% + -5px) 42.6%,calc(51.9% + -5px) 44.4%,calc(50.2% + -5px) 49.5%,calc(51% + -5px) 54%,calc(46.7% + -5px) 57.5%,calc(47% + -5px) 60.1%,calc(44.6% + -5px) 64.2%,calc(46% + -5px) 66%,calc(46.9% + -5px) 68.5%,calc(44% + -5px) 72.1%,calc(44.6% + -5px) 75.1%,calc(42% + -5px) 79.2%,calc(40.5% + -5px) 83.6%,calc(39.5% + -5px) 87.6%,calc(38.1% + -5px) 91.5%,calc(36.9% + -5px) 95.7%,calc(35.8% + -5px) 99.2%,calc(34% + -5px) 100%,0% 100%)}
.intro-half.b{clip-path:polygon(34% 100%,35.8% 99.2%,36.9% 95.7%,38.1% 91.5%,39.5% 87.6%,40.5% 83.6%,42% 79.2%,44.6% 75.1%,44% 72.1%,46.9% 68.5%,46% 66%,44.6% 64.2%,47% 60.1%,46.7% 57.5%,51% 54%,50.2% 49.5%,51.9% 44.4%,55.6% 42.6%,54.7% 39.9%,56.7% 35.7%,58.7% 33.6%,56.4% 30.3%,58.1% 27.8%,58.7% 24.1%,59.2% 20.2%,62.1% 16.3%,64.9% 12.6%,64% 8.2%,68.3% 3.6%,68% 0%,100% 0%,100% 100%)}.intro-half.b .intro-print{clip-path:polygon(calc(34% + 5px) 100%,calc(35.8% + 5px) 99.2%,calc(36.9% + 5px) 95.7%,calc(38.1% + 5px) 91.5%,calc(39.5% + 5px) 87.6%,calc(40.5% + 5px) 83.6%,calc(42% + 5px) 79.2%,calc(44.6% + 5px) 75.1%,calc(44% + 5px) 72.1%,calc(46.9% + 5px) 68.5%,calc(46% + 5px) 66%,calc(44.6% + 5px) 64.2%,calc(47% + 5px) 60.1%,calc(46.7% + 5px) 57.5%,calc(51% + 5px) 54%,calc(50.2% + 5px) 49.5%,calc(51.9% + 5px) 44.4%,calc(55.6% + 5px) 42.6%,calc(54.7% + 5px) 39.9%,calc(56.7% + 5px) 35.7%,calc(58.7% + 5px) 33.6%,calc(56.4% + 5px) 30.3%,calc(58.1% + 5px) 27.8%,calc(58.7% + 5px) 24.1%,calc(59.2% + 5px) 20.2%,calc(62.1% + 5px) 16.3%,calc(64.9% + 5px) 12.6%,calc(64% + 5px) 8.2%,calc(68.3% + 5px) 3.6%,calc(68% + 5px) 0%,100% 0%,100% 100%)}
