/* ═══════════════════════════════════════════════════════════════════
   SHIRAUME LODGE · CINEMATIC SPLASH  ("the gate at dawn")
   Drop-in pair: this file + shiraume-splash.js

   The sequence, in one sentence: a torii is painted in wet ink on dark
   paper, lacquer floods up it, dawn breaks over the paper, the name is
   sealed with a hanko — and then the camera walks through the gateway.

   All timing lives in the --sp2-* custom properties at the top of
   #shiraume-splash so it can be retuned from one place.
   ═══════════════════════════════════════════════════════════════════ */

@property --sp2-flood { syntax: '<percentage>'; inherits: false; initial-value: 0%; }

#shiraume-splash {
  --sp2-ink:        #efe7d6;   /* wet ink while the paper is still dark   */
  --sp2-ink-day:    #4a3a2c;   /* the same ink once dawn has arrived      */
  --sp2-paper:      #b0a389;   /* dawn stops well short of white          */
  --sp2-paper-night:#17130d;
  --sp2-vermilion:  #5e2521;   /* aged urushi, not a saturated red        */
  --sp2-gold:       #b8956a;

  --sp2-draw-in:    0.35s;     /* first stroke lands                      */
  --sp2-dawn:       3.2s;      /* light starts to come up                 */
  --sp2-persp:      780px;

  position: fixed; inset: 0; z-index: 9500;
  overflow: hidden;
  background: #0b0b11;
  opacity: 1;
  transition: opacity 0.55s ease;
}
#shiraume-splash.sp2-gone { opacity: 0; pointer-events: none; }

/* ─── SKY · the dawn happens here ─────────────────────────────────
   Two stacked gradients cross-fade, because a gradient cannot tween. */
.sp2-sky { position: absolute; inset: -10%; }
.sp2-sky-night {
  background:
    radial-gradient(120% 90% at 50% 96%, #1d2233 0%, #0d0f18 55%, #08080d 100%);
}
.sp2-sky-dawn {
  background:
    radial-gradient(130% 95% at 50% 88%, #d9bd96 0%, #bfa07c 34%, #8f7960 62%, #55503f 100%);
  opacity: 0;
  animation: sp2-dawn 2.1s var(--sp2-dawn) cubic-bezier(0.4, 0, 0.4, 1) forwards;
}
@keyframes sp2-dawn { to { opacity: 1; } }

/* The warm flash at the moment of passing through. Sits above the
   whole stage, so it covers the gate crossing the camera plane. */
.sp2-flash {
  position: absolute; inset: 0;
  background: radial-gradient(70% 60% at 50% 46%, rgba(255, 243, 222, 0.95), rgba(255, 231, 197, 0.35) 60%, rgba(255, 226, 178, 0) 100%);
  opacity: 0; pointer-events: none;
  mix-blend-mode: screen;
  z-index: 3;
}

/* ─── STAGE · the only place perspective is declared ────────────── */
.sp2-stage {
  position: absolute; inset: 0;
  perspective: var(--sp2-persp);
  perspective-origin: 50% 46%;
}
.sp2-world {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}

/* ─── THE FAR PLANE · photograph + light ──────────────────────────
   Deliberately OUTSIDE .sp2-world, and so outside the dolly. The photo
   is a bitmap: 3D magnification resamples it, and the old setup — held
   at −1500px, pre-scaled 2.6× to compensate, then dollied forward —
   pushed it past 4× and turned it to mush. Here it renders at its
   natural size and does its own shallow push-in instead. */
.sp2-far {
  position: absolute; inset: 0;
  overflow: hidden;
}
.sp2-photo {
  position: absolute; inset: -1%;
  background-image: var(--sp2-photo);
  background-size: cover;
  background-position: 50% 52%;
  transform-origin: 50% 46%;
  filter: brightness(0.16) saturate(0.3) blur(18px);
  opacity: 0;
  animation: sp2-photo-wake 2.6s var(--sp2-dawn) cubic-bezier(0.3, 0, 0.28, 1) forwards;
  will-change: transform, filter;
}
/* Mist clearing: it arrives hazy and soft-focus, and resolves. */
@keyframes sp2-photo-wake {
  0%   { opacity: 0; transform: scale(1.07); filter: brightness(0.16) saturate(0.3) blur(18px); }
  22%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1);    filter: brightness(1) saturate(1) blur(0px); }
}

/* Warm light spilling through the opening once it is open. */
.sp2-bloom {
  position: absolute; inset: -8%;
  background: radial-gradient(38% 44% at 50% 44%, rgba(255, 232, 190, 0.5), rgba(255, 226, 178, 0) 70%);
  opacity: 0; mix-blend-mode: screen;
  animation: sp2-bloom 2.6s calc(var(--sp2-dawn) + 0.7s) ease-out forwards;
}
@keyframes sp2-bloom { 0% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 0.45; } }

/* ─── THE PAPER · the plane the camera passes through ─────────────
   A field of paper with the gateway cut out of it. Overscanned by 12%
   so no camera move can ever expose its edge against the photograph. */
.sp2-paper-plane {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
}
/* The paper sheet itself is overscanned past the viewport (with its
   viewBox extended to match, so the gate is not distorted) — that way
   the dolly can never expose the sheet's edge against the photograph. */
.sp2-gate {
  position: absolute; left: -14%; top: -14%; right: auto; bottom: auto;
  width: 128%; height: 128%; display: block;
  max-width: none; max-height: none;  /* host stylesheets clamp svg to 100% */
}

#sp2-fill {
  fill: var(--sp2-paper-night);
  animation: sp2-paper-day 2.3s var(--sp2-dawn) cubic-bezier(0.4, 0, 0.4, 1) forwards;
}
@keyframes sp2-paper-day {
  0%   { fill: #17130d; }
  50%  { fill: #4d3f2c; }
  100% { fill: var(--sp2-paper); }
}

/* Paper grain, so the field reads as washi and not as a colour. */
.sp2-grain {
  position: absolute; inset: 0; pointer-events: none;
  opacity: 0.42; mix-blend-mode: overlay;
  background-image: var(--sp2-grain);
}

/* The gateway itself. It does NOT scale open — a growing aperture reads
   as the photograph sprouting from one corner. The cutout fades instead
   (mask luminance), so the paper dissolves and the view is simply there. */
#sp2-hole {
  opacity: 0;
  animation: sp2-open 1.9s calc(var(--sp2-dawn) + 0.1s) cubic-bezier(0.42, 0, 0.4, 1) forwards;
}
@keyframes sp2-open { to { opacity: 1; } }

/* ─── INK · the gate paints itself ────────────────────────────────
   Each member traces in the order a gate is raised. pathLength="1"
   lets one rule serve pieces of wildly different length. The brush
   wobble and the bleed are the two turbulence filters in the markup. */
#sp2-strokes path,
#sp2-bleed path {
  fill: none;
  stroke: var(--sp2-ink);
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation:
    sp2-trace var(--dd, 0.6s) cubic-bezier(0.24, 0.9, 0.32, 1) calc(var(--sp2-draw-in) + var(--dl, 0s)) forwards,
    sp2-ink-day 2.3s var(--sp2-dawn) cubic-bezier(0.4, 0, 0.4, 1) forwards;
}
@keyframes sp2-trace  { to { stroke-dashoffset: 0; } }
@keyframes sp2-ink-day { to { stroke: var(--sp2-ink-day); } }

/* The plaque is gilded, so it is laid in gold from the first stroke
   rather than drawn in ink and gilded afterwards. */
#sp2-strokes path.sp2-gold-stroke {
  stroke: #d9b878;
  animation:
    sp2-trace var(--dd, 0.6s) cubic-bezier(0.24, 0.9, 0.32, 1) calc(var(--sp2-draw-in) + var(--dl, 0s)) forwards,
    sp2-gold-day 2.3s var(--sp2-dawn) cubic-bezier(0.4, 0, 0.4, 1) forwards;
}
@keyframes sp2-gold-day { to { stroke: #8a6a3c; } }

/* The wet bleed: the same strokes at three times the width, low opacity,
   traced on the same clock. It belongs to the wet phase — as dawn comes
   the ink dries and it goes. Widened geometry, not a blur, so it costs
   nothing per frame. */
.sp2-bleed {
  opacity: 0.16;
  animation: sp2-dry 1.6s var(--sp2-dawn) ease forwards;
}
@keyframes sp2-dry { to { opacity: 0; } }

/* ─── LACQUER · vermilion floods up the gate ──────────────────────
   Filled copies of the closed members, revealed by a soft edge that
   climbs from the plinths to the lintel. */
#sp2-lacquer {
  fill: url(#sp2-lac);
  opacity: 0;
  --sp2-flood: 0%;
  -webkit-mask-image: linear-gradient(to top, #000 0%, #000 var(--sp2-flood), transparent calc(var(--sp2-flood) + 9%));
  mask-image: linear-gradient(to top, #000 0%, #000 var(--sp2-flood), transparent calc(var(--sp2-flood) + 9%));
  animation: sp2-flood 1.5s 2.85s cubic-bezier(0.42, 0, 0.4, 1) forwards;
}
@keyframes sp2-flood {
  0%   { opacity: 0.68; --sp2-flood: 0%; }
  100% { opacity: 0.68; --sp2-flood: 112%; }
}
/* The plinths are stone, not lacquer. */
#sp2-stone {
  fill: #8d8271; opacity: 0;
  animation: sp2-stone 1.2s 3.1s ease-out forwards;
}
@keyframes sp2-stone { to { opacity: 0.5; } }

/* The board is not lacquered — it is gilded, and it catches last. */
#sp2-gilt {
  fill: var(--sp2-gold); opacity: 0;
  animation: sp2-gilt 0.9s 3.95s ease-out forwards;
}
@keyframes sp2-gilt { 0% { opacity: 0; } 100% { opacity: 0.72; } }

/* ─── THE NAME ────────────────────────────────────────────────────
   Stacked, not set beside the mark: the opening of this gate is
   narrow, and a horizontal lockup would have to cross the posts.

   The lockup sits over the photograph, which ends up bright sunlit
   gravel — so cream type needs a real ground, not just a soft glow.
   The veil is a contained dark wash that follows the type. */
.sp2-veil {
  position: absolute; left: 50%; top: 0;
  transform: translate(-50%, -14%) translateZ(5px);
  pointer-events: none;
  background: radial-gradient(78% 50% at 50% 50%,
    rgba(18, 14, 9, 0.66) 0%, rgba(18, 14, 9, 0.5) 42%,
    rgba(18, 14, 9, 0.2) 70%, rgba(18, 14, 9, 0) 100%);
  opacity: 0;
  animation: sp2-veil-in 1.6s 1.7s ease forwards;
}
@keyframes sp2-veil-in { to { opacity: 1; } }

.sp2-word {
  position: absolute; left: 50%; top: 0;
  transform: translate(-50%, 0) translateZ(6px);
  display: flex; flex-direction: column; align-items: center; gap: 0.55rem;
  text-align: center; pointer-events: none;
}
.sp2-mark {
  width: var(--sp2-mark-size, 78px); height: var(--sp2-mark-size, 78px);
  object-fit: contain; display: block;
  filter: brightness(0) invert(0.94) drop-shadow(0 1px 14px rgba(20, 16, 10, 0.5));
  opacity: 0;
  animation: sp2-rise 1.1s 1.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.sp2-name {
  font-family: var(--font-display, 'Cormorant Garamond', Georgia, serif);
  font-weight: 500; line-height: 1;
  font-size: var(--sp2-name-size, 2.1rem);
  letter-spacing: 0.02em;
  color: #f6f1e6;
  /* A tight, high-alpha shadow does the legibility work; the wide blur
     is only atmosphere. Cream on sunlit gravel needs both. */
  text-shadow:
    0 1px 2px rgba(16, 12, 7, 0.85),
    0 2px 8px rgba(16, 12, 7, 0.7),
    0 1px 30px rgba(16, 12, 7, 0.5);
  opacity: 0;
  animation: sp2-rise 1.1s 2.15s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.sp2-sub {
  font-family: var(--font-body, 'Work Sans', 'Helvetica Neue', sans-serif);
  font-size: var(--sp2-sub-size, 0.62rem);
  letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--sp2-gold);
  text-shadow: 0 1px 2px rgba(16, 12, 7, 0.85), 0 1px 16px rgba(16, 12, 7, 0.6);
  opacity: 0;
  animation: sp2-rise 1.1s 2.35s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
@keyframes sp2-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* ─── HANKO · the seal that ends the painting ─────────────────────
   Struck, not faded: it overshoots, squashes, and settles. */
.sp2-hanko {
  position: absolute; left: 50%; top: 0;
  margin-left: calc(var(--sp2-hanko-size, 46px) / -2);
  width: var(--sp2-hanko-size, 46px); height: var(--sp2-hanko-size, 46px);
  border-radius: 4px;
  background: var(--sp2-vermilion);
  color: #f7ece4;
  font-family: var(--jpfont, 'Noto Serif JP', serif); font-weight: 400;
  font-size: calc(var(--sp2-hanko-size, 46px) * 0.36);
  line-height: 1.05; letter-spacing: 0.04em;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  opacity: 0;
  transform: translateZ(6px) rotate(-4deg) scale(2.1);
  animation: sp2-stamp 0.62s 4.35s cubic-bezier(0.2, 1.5, 0.4, 1) forwards;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12) inset;
  pointer-events: none;
}
@keyframes sp2-stamp {
  0%   { opacity: 0;    transform: translateZ(6px) rotate(-9deg) scale(2.1); }
  45%  { opacity: 0.95; transform: translateZ(6px) rotate(-4deg) scale(0.9)  skewX(2deg); }
  70%  { opacity: 0.95; transform: translateZ(6px) rotate(-4deg) scale(1.06); }
  100% { opacity: 0.95; transform: translateZ(6px) rotate(-4deg) scale(1); }
}

/* ─── KANJI · 白梅, held far behind the drawing ──────────────────── */
.sp2-kanji {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  gap: 0.04em;
  font-family: var(--jpfont, 'Noto Serif JP', serif); font-weight: 400;
  font-size: clamp(150px, 27vw, 300px);
  line-height: 1; letter-spacing: -0.05em;
  color: rgba(184, 149, 106, 0.055);
  transform: translateZ(-120px);
  pointer-events: none; user-select: none;
}
.sp2-kanji span { opacity: 0; animation: sp2-kanji-in 2.4s ease forwards; }
.sp2-kanji span:nth-child(1) { animation-delay: 0.5s; }
.sp2-kanji span:nth-child(2) { animation-delay: 0.9s; }
@keyframes sp2-kanji-in { from { opacity: 0; } to { opacity: 1; } }

/* ─── TAGLINE ─────────────────────────────────────────────────────
   Set below the gate, on the path in front of it. */
.sp2-tag {
  position: absolute; left: 50%; top: 0;
  transform: translate(-50%, 0) translateZ(6px);
  font-family: var(--jpfont, 'Noto Serif JP', serif); font-weight: 300;
  font-size: var(--sp2-tag-size, 1rem);
  letter-spacing: 0.22em; white-space: nowrap;
  color: rgba(248, 244, 235, 0.94);
  text-shadow:
    0 1px 2px rgba(16, 12, 7, 0.9),
    0 2px 10px rgba(16, 12, 7, 0.7),
    0 1px 26px rgba(16, 12, 7, 0.5);
  opacity: 0;
  animation: sp2-rise-c 1.2s 4.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  pointer-events: none;
}
@keyframes sp2-rise-c {
  from { opacity: 0; transform: translate(-50%, 14px) translateZ(6px); }
  to   { opacity: 1; transform: translate(-50%, 0) translateZ(6px); }
}

/* ─── PETALS ──────────────────────────────────────────────────────
   Outer node holds the position in depth (and later the gust);
   inner node holds the drift, so the two never fight.

   The whole layer is held back until the gate has finished drawing: the
   trace is the one genuinely expensive stretch (it re-rasterizes an SVG
   filter every frame) and should not share the frame with 22
   independently animating elements. */
.sp2-petals {
  opacity: 0;
  animation: sp2-petals-in 1.4s 3.05s ease forwards;
}
@keyframes sp2-petals-in { to { opacity: 1; } }
.sp2-petal {
  position: absolute; left: 0; top: 0;
  transform: translate3d(var(--px), var(--py), var(--pz)) translate(var(--gx, 0px), var(--gy, 0px));
  transition: transform 1.5s cubic-bezier(0.2, 0.7, 0.25, 1), opacity 1.3s ease;
  pointer-events: none;
}
.sp2-petal i {
  display: block;
  width: var(--ps, 7px); height: var(--ps, 7px);
  border-radius: 50% 0 50% 50%;
  background: rgba(242, 232, 214, 0.8);
  opacity: 0;
  animation: sp2-drift var(--pd, 9s) var(--pdl, 0s) linear infinite;
}
/* Roughly one in five is a whole blossom rather than a fleck — the
   brand's five-petal plum, masked so it stays crisp at any size. */
.sp2-petal i.sp2-bloom-petal {
  border-radius: 0;
  background: rgba(246, 238, 224, 0.72);
  -webkit-mask-image: var(--sp2-ume); mask-image: var(--sp2-ume);
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
@keyframes sp2-drift {
  0%   { opacity: 0;    transform: translate(0, -14px) rotate(0deg); }
  12%  { opacity: 0.85; }
  88%  { opacity: 0.7; }
  100% { opacity: 0;    transform: translate(var(--pdx, 40px), var(--pdy, 130px)) rotate(320deg); }
}

/* ─── UME BRANCHES ──────────────────────────────────────
   The lodge's own branch artwork: pale silver against the dark paper,
   settling to ink once the light is up. Two reaching branches and one
   very large ghost printed under the whole gate.

   Three nested elements, each owning exactly one job — outer positions
   and orients, <span> sways, and the two tint layers cross-fade. The ink
   change is deliberately NOT an animated background-color: that repaints
   the whole masked area every frame, and on a 118vh ghost carrying a
   large mask bitmap it pegs the renderer on first load. Two pre-tinted
   layers cross-fading run on the compositor instead. */
/* The branches likewise wait for the trace to finish. */
.sp2-branch {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  animation: sp2-branch-in 1.8s 2.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
@keyframes sp2-branch-in { to { opacity: 1; } }

.sp2-branch span {
  display: block; position: absolute; inset: 0;
  animation: sp2-sway var(--sway, 11s) ease-in-out infinite;
  will-change: transform;
}
.sp2-branch i,
.sp2-branch b {
  display: block; position: absolute; inset: 0;
  -webkit-mask-image: var(--sp2-branch); mask-image: var(--sp2-branch);
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
.sp2-branch i { background: #e3d8c6; }
.sp2-branch b {
  background: #4a3a2c;
  opacity: 0;
  animation: sp2-branch-ink 2.4s var(--sp2-dawn) cubic-bezier(0.4, 0, 0.4, 1) forwards;
  will-change: opacity;
}
@keyframes sp2-branch-ink { to { opacity: 1; } }
@keyframes sp2-sway {
  0%, 100% { transform: rotate(-1.2deg); }
  50%      { transform: rotate(1.2deg); }
}

.sp2-branch-tr {
  top: -7%; right: -9%;
  width: 36vw; height: 37.8vw;
  transform: rotate(170deg);
}
.sp2-branch-tr span { --sway: 13s; transform-origin: 20% 85%; }

.sp2-branch-bl {
  left: -5%; bottom: -4%;
  width: 18vw; height: 19vw;
  transform: rotate(-7deg);
}
.sp2-branch-bl span { --sway: 9.5s; transform-origin: 15% 90%; animation-delay: -3.2s; }

/* The ghost: large enough that only a few strokes read, and faint enough
   to sit under the gate without competing with it — so it masks with a
   downscaled copy of the art rather than the full-detail one. */
.sp2-branch-ghost {
  left: 50%; top: 47%;
  width: 118vh; height: 118vh;
  transform: translate(-50%, -50%) rotate(6deg);
  opacity: 0;
  animation: sp2-ghost-in 2.6s 2.7s ease forwards;
}
@keyframes sp2-ghost-in { to { opacity: 0.085; } }
.sp2-branch-ghost span { --sway: 19s; transform-origin: 50% 60%; }
.sp2-branch-ghost i,
.sp2-branch-ghost b {
  -webkit-mask-image: var(--sp2-branch-ghost); mask-image: var(--sp2-branch-ghost);
}

/* ─── ENTER ───────────────────────────────────────────────────────
   The only affordance on screen, and it is quiet. */
.sp2-skip {
  position: absolute; left: 50%; bottom: 2.2rem;
  transform: translateX(-50%);
  appearance: none; border: 0; background: none;
  font-family: var(--font-body, 'Work Sans', sans-serif);
  font-size: 0.6rem; letter-spacing: 0.28em; text-transform: uppercase;
  color: rgba(240, 234, 222, 0.55);
  text-shadow: 0 1px 16px rgba(20, 16, 10, 0.7);
  cursor: pointer; z-index: 4;
  /* Its own keyframes, because sp2-rise ends on `transform: none` and this
     is the one element that carries its centring in a transform of its
     own. Sharing them threw the translateX(-50%) away the moment the
     animation started: the button jumped right by exactly half its width,
     sat there, and jumped back when the walk-through set animation:none
     and the base rule returned. .sp2-tag already has the same fix. */
  opacity: 0; animation: sp2-rise-skip 1s 2.8s ease forwards;
  transition: color 0.25s;
}
@keyframes sp2-rise-skip {
  from { opacity: 0; transform: translateX(-50%) translateY(14px); }
  to   { opacity: 1; transform: translateX(-50%); }
}
.sp2-skip:hover { color: var(--sp2-gold); }

/* ═══ THE WALK-THROUGH ════════════════════════════════════════════
   Not a fade and not a zoom: a move with weight. The camera holds for a
   beat, then accelerates hard through the opening — the paper plane and
   the gate on it rush past the viewer and out of frame — while the
   photograph behind pushes in only slightly, so it never magnifies
   enough to resample. A warm flash marks the frame the gate passes. */
#shiraume-splash.sp2-exit { pointer-events: none; }
#shiraume-splash.sp2-exit .sp2-world {
  animation: sp2-dolly 1.35s cubic-bezier(0.62, 0, 0.86, 0.34) forwards;
}
/* The camera only ever travels forward — any pull-back would shrink the
   paper plane and reveal the photograph around its edges. The travel
   stops short of --sp2-persp, past which CSS clips the plane. */
@keyframes sp2-dolly {
  0%   { transform: translateZ(0); }
  100% { transform: translateZ(700px); }
}

/* The photograph's own push-in: shallow, and easing the opposite way to
   the gate, so the two moves read as separate depths rather than one
   scale. It also brightens, as if stepping out of the gate's shadow. */
/* NB: this replaces sp2-photo-wake, so it must restate opacity — without
   it the photo falls back to the base rule's opacity: 0 and the dawn sky
   shows through the gateway instead of the photograph. */
#shiraume-splash.sp2-exit .sp2-photo {
  animation: sp2-arrive 1.9s cubic-bezier(0.3, 0, 0.4, 1) forwards;
}
@keyframes sp2-arrive {
  0%   { opacity: 1; transform: scale(1);     filter: brightness(1) saturate(1); }
  100% { opacity: 1; transform: scale(1.075); filter: brightness(1.1) saturate(1.06); }
}
/* The words do not fly at the viewer — only the gate does. */
#shiraume-splash.sp2-exit .sp2-word,
#shiraume-splash.sp2-exit .sp2-veil,
#shiraume-splash.sp2-exit .sp2-tag,
#shiraume-splash.sp2-exit .sp2-hanko,
#shiraume-splash.sp2-exit .sp2-skip {
  animation: none;
  opacity: 0;
  transition: opacity 0.34s ease;
}
#shiraume-splash.sp2-exit .sp2-kanji { opacity: 0; transition: opacity 0.5s ease; }

/* The flash: brief, warm, and gone — it hides the instant the gate's
   geometry crosses the camera, which is the one ugly frame. */
#shiraume-splash.sp2-exit .sp2-flash {
  animation: sp2-flash 0.72s 0.52s ease-out forwards;
}
@keyframes sp2-flash {
  0%   { opacity: 0; }
  34%  { opacity: 0.5; }
  100% { opacity: 0; }
}

/* The paper thins out only once it is past the viewer. */
#shiraume-splash.sp2-exit .sp2-paper-plane {
  animation: sp2-paper-pass 1.35s cubic-bezier(0.62, 0, 0.86, 0.34) forwards;
}
@keyframes sp2-paper-pass {
  0%   { opacity: 1; }
  58%  { opacity: 1; }
  100% { opacity: 0; }
}
#shiraume-splash.sp2-exit .sp2-petal { opacity: 0; }
#shiraume-splash.sp2-exit .sp2-grain { opacity: 0; transition: opacity 1s ease; }

/* ─── HELD STATE (reduced motion, or a visitor who has been here) ── */
#shiraume-splash.sp2-static .sp2-sky-dawn,
#shiraume-splash.sp2-static .sp2-photo { opacity: 1; animation: none; }
#shiraume-splash.sp2-static .sp2-photo { filter: none; }
#shiraume-splash.sp2-static #sp2-fill { fill: var(--sp2-paper); animation: none; }
#shiraume-splash.sp2-static #sp2-stone { opacity: 0.5; animation: none; }
#shiraume-splash.sp2-static .sp2-bleed { opacity: 0; animation: none; }
#shiraume-splash.sp2-static #sp2-hole { opacity: 1; animation: none; }
#shiraume-splash.sp2-static .sp2-branch { opacity: 1; animation: none; }
#shiraume-splash.sp2-static .sp2-branch-ghost { opacity: 0.085; animation: none; }
#shiraume-splash.sp2-static .sp2-branch span { animation: none; }
#shiraume-splash.sp2-static .sp2-branch b { opacity: 1; animation: none; }
#shiraume-splash.sp2-static #sp2-strokes path,
#shiraume-splash.sp2-static #sp2-bleed path { stroke-dashoffset: 0; stroke: var(--sp2-ink-day); animation: none; }
#shiraume-splash.sp2-static #sp2-strokes path.sp2-gold-stroke { stroke: #8a6a3c; }
#shiraume-splash.sp2-static #sp2-lacquer { opacity: 0.68; --sp2-flood: 112%; animation: none; -webkit-mask-image: none; mask-image: none; }
#shiraume-splash.sp2-static #sp2-gilt { opacity: 0.72; animation: none; }
#shiraume-splash.sp2-static .sp2-word *,
#shiraume-splash.sp2-static .sp2-veil,
#shiraume-splash.sp2-static .sp2-tag,
#shiraume-splash.sp2-static .sp2-skip,
#shiraume-splash.sp2-static .sp2-kanji span { opacity: 1; transform: none; animation: none; }
#shiraume-splash.sp2-static .sp2-mark { filter: brightness(0) invert(0.94); }
#shiraume-splash.sp2-static .sp2-tag { color: rgba(246, 241, 230, 0.86); transform: translate(-50%, 0) translateZ(6px); }
#shiraume-splash.sp2-static .sp2-hanko { opacity: 0.95; transform: translateZ(6px) rotate(-4deg) scale(1); animation: none; }
#shiraume-splash.sp2-static .sp2-petals { opacity: 1; animation: none; }
#shiraume-splash.sp2-static .sp2-petal i { animation: none; opacity: 0; }

@media (max-width: 560px) {
  .sp2-kanji { font-size: clamp(120px, 42vw, 220px); }
  .sp2-skip { bottom: 1.4rem; }
  .sp2-branch-tr { width: 56vw; height: 58vw; }
  .sp2-branch-bl { width: 30vw; height: 32vw; }
}

/* ═══════════════════════════════════════════════════════════════════
   LOCAL FIX · sp2-lite — the same sequence, on a machine that is
   struggling. Set by the frame watch in the JS after three quarters of a
   second of measuring, never by guessing at the device.

   What goes is decoration only. The gate still paints, the lacquer still
   floods, dawn still comes and the camera still walks through — those are
   the sequence. Grain over a full-screen sheet, an 18px blur resolving on
   a full-screen bitmap, and two dozen independently transformed petals
   are the three things that cost the most and are missed the least.
   ═══════════════════════════════════════════════════════════════════ */
#shiraume-splash.sp2-lite .sp2-grain,
#shiraume-splash.sp2-lite .sp2-paper-grain { display: none; }

/* The photograph arrives sharp rather than resolving out of mist. */
#shiraume-splash.sp2-lite .sp2-photo { filter: brightness(0.16) saturate(0.3); }
#shiraume-splash.sp2-lite .sp2-photo,
#shiraume-splash.sp2-lite.sp2-exit .sp2-photo { animation-name: sp2-photo-lite; }
@keyframes sp2-photo-lite {
  0%   { opacity: 0; transform: scale(1.07); filter: brightness(0.16) saturate(0.3); }
  100% { opacity: 1; transform: scale(1);    filter: brightness(1) saturate(1); }
}

/* A few petals still read as wind; twenty-two do not read as more. */
#shiraume-splash.sp2-lite .sp2-petal:nth-child(n + 7) { display: none; }

/* The brush wobble is a per-frame filter over the whole drawing. */
#shiraume-splash.sp2-lite #sp2-strokes { filter: none; }
