/* ==========================================================================
   vn.css — the scene engine: stage, sprite, HUD, transitions
   Spec §2 §5 §6 §7
     · animate ONLY transform/opacity (GPU compositing)
     · 100svh/100dvh, never 100vh
     · every hover has a tap twin — nothing is hover-only
   ========================================================================== */

.scene {
  position: relative;
  min-height: 100svh;
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 1fr;
  isolation: isolate;
  overflow: hidden;
}

.scene__stage { position: absolute; inset: 0; z-index: 0; overflow: hidden; }

.scene__bg {
  position: absolute; inset: -2%;
  background-image: var(--bg);
  background-size: cover; background-position: center;
  transform: scale(1.04);
  will-change: transform;
}
.scene__bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255,247,250,.28), transparent 62%),
    linear-gradient(180deg, rgba(255,240,247,.30) 0%, rgba(255,228,240,.52) 100%);
}

.scene__particles {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none; z-index: 1;
}

.scene__sprite {
  position: absolute; right: 2%; bottom: 0; z-index: 2;
  height: min(88svh, 78vh); width: auto; max-width: none;
  object-fit: contain; object-position: bottom center;
  filter: drop-shadow(0 26px 46px rgba(110,38,78,.34));
  transform-origin: bottom center;
  animation: sprite-in .78s var(--ease-out) both;
  pointer-events: none;
}
@keyframes sprite-in {
  from { opacity: 0; transform: scale(.985); }   /* no vertical lift: she stays flush to the bottom */
  to   { opacity: 1; transform: translate3d(0,0,0) scale(1); }
}

.scene__content {
  position: relative; z-index: 3;
  display: flex; flex-direction: column; gap: var(--s-4);
  width: min(680px, 100%);
  padding: calc(var(--hud-h) + var(--s-5)) var(--s-4) var(--s-6);
}

.panel {
  background: rgba(255,253,253,.93);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  box-shadow: var(--sh-panel);
  border: 1px solid rgba(255,255,255,.8);
  backdrop-filter: blur(9px) saturate(1.12);
  -webkit-backdrop-filter: blur(9px) saturate(1.12);
  animation: panel-in .56s var(--ease-out) both;
}
.panel:nth-child(2) { animation-delay: .07s; }
.panel:nth-child(3) { animation-delay: .13s; }
@keyframes panel-in {
  from { opacity: 0; transform: translate3d(0,16px,0); }
  to   { opacity: 1; transform: translate3d(0,0,0); }
}

.panel--hero { background: linear-gradient(155deg, rgba(255,253,253,.96), rgba(255,237,246,.94)); }
.panel--hero h1 {
  background: linear-gradient(120deg, var(--c-rose-deep), var(--c-rose) 46%, var(--c-gold));
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  margin: var(--s-2) 0;
}

.scene-nav { display: flex; flex-wrap: wrap; gap: var(--s-2); padding-top: var(--s-1); }

.hud {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  height: var(--hud-h);
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  padding-top: max(var(--s-2), env(safe-area-inset-top));
  background: linear-gradient(180deg, rgba(255,247,250,.92), rgba(255,247,250,.62) 70%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.hud__right { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }

.hud__btn {
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.82);
  border: 1px solid rgba(217,106,146,.28);
  color: var(--c-rose-deep);
  font-size: 1.05rem; text-decoration: none; font-weight: 700;
  transition: transform var(--dur) var(--ease-spring), background var(--dur) var(--ease-out);
}
.hud__btn:hover, .hud__btn:focus-visible {
  transform: translateY(-2px) scale(1.06);
  background: rgba(255, 255, 255, .34);
  border-color: rgba(201, 154, 83, .85);
  color: var(--c-brand-pri);
}
.hud__btn:active { transform: translateY(0) scale(.97); transition-duration: .08s; }
.hud__btn:active { transform: translateY(0) scale(.95); }
.hud__btn[aria-pressed="true"] { background: var(--c-rose-deep); color: #fff; border-color: var(--c-rose-deep); }
.hud__lang { font-size: var(--t-small); letter-spacing: .08em; }

.hud__charms {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: 0 var(--s-3); min-height: 44px;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.82);
  border: 1px solid rgba(201,154,83,.4);
  font-size: var(--t-small); font-weight: 700; color: var(--c-gold);
}
.hud__charms b { color: var(--c-rose-deep); font-size: 1.05rem; }

.scene-menu {
  position: fixed; top: var(--hud-h); left: var(--s-3); z-index: 59;
  min-width: 232px; padding: var(--s-3);
  border-radius: var(--r-md);
  background: rgba(255,253,253,.97);
  box-shadow: var(--sh-panel);
  border: 1px solid rgba(217,106,146,.22);
}
.scene-menu[hidden] { display: none; }
.scene-menu ul { display: grid; gap: var(--s-1); }
.scene-menu a {
  display: block; padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm); text-decoration: none;
  font-weight: 700; color: var(--c-ink);
  transition: background var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.scene-menu a:hover, .scene-menu a:focus-visible { background: var(--c-blush); transform: translate3d(3px,0,0); }
.scene-menu a[aria-current="page"] { background: var(--c-blush-deep); color: var(--c-rose-deep); }

.loader {
  position: fixed; top: 0; left: 0; right: 0; z-index: 120;
  height: 3px; background: rgba(255,255,255,.4);
}
.loader__bar {
  height: 100%; width: 0;
  background: linear-gradient(90deg, var(--c-gold), var(--c-rose));
  transition: width .34s var(--ease-out);
}

.charm {
  /* MUST sit outside .scene__stage: that element is its own stacking context
     (z-index:0), so anything inside it can never rise above .scene__content
     (z-index:3). The bell was ending up under the text panels, which made the
     Hint button look broken. It is now a direct child of .scene at z-index 6. */
  position: absolute; z-index: 6;
  left: var(--charm-x, 62%);
  top: var(--charm-y, 32%);
  width: 64px; height: 64px;
  opacity: .001;
  transition: opacity .32s var(--ease-out), transform .32s var(--ease-spring);
}
.charm img { width: 64px; height: 64px; }
.charm:hover, .charm:focus-visible, .charm.is-hinted {
  opacity: 1; transform: scale(1.18) rotate(-6deg);
}
.charm.is-found { opacity: 0; pointer-events: none; transform: scale(.4); }

.scene.is-entering { animation: scene-in .5s var(--ease-out) both; }
@keyframes scene-in {
  /* no transform: a transform on .scene would make it the containing block
     for the position:fixed bottom nav and clip it under overflow:hidden. */
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (min-width: 900px) {
  .scene { grid-template-columns: minmax(0,1fr) minmax(0,.92fr); align-items: center; }
  .scene__content {
    width: 100%;
    padding-left: clamp(var(--s-5), 6vw, var(--s-7));
    padding-right: var(--s-5);
  }
  .scene__sprite { right: clamp(2%, 6vw, 12%); height: min(92svh, 860px); }
}

@media (max-width: 899px) {
  /* She must be FULLY visible on a phone: centred, anchored to the bottom of
     the viewport, no negative offset. Content reserves space beneath her. */
  .scene__sprite {
    position: fixed;
    left: 0; right: 0;
    margin-inline: auto;
    bottom: 0;
    right: auto;
    height: min(58svh, 470px);
    width: auto;
    max-width: 100vw;
    object-fit: contain;
    object-position: bottom center;
  }
  .scene__content {
    width: 100%;
    padding-bottom: calc(58svh + var(--s-5));
  }
  .panel { padding: var(--s-4); }
  .scene-nav .btn { flex: 1 1 auto; }
}

@media (max-width: 420px) {
  .scene__sprite { height: min(52svh, 420px); }
}

@media (max-width: 420px) {
  .hud { gap: var(--s-1); padding-inline: var(--s-2); }
  .hud__btn { min-width: 40px; min-height: 40px; padding-inline: var(--s-2); }
  .hud__charms { padding-inline: var(--s-2); }
}

/* ==========================================================================
   Sprite / scene integration
   A keyed sprite pasted over scene art reads as "flat cutout, pasted on top"
   unless the two share light. These three treatments fix that without
   touching the pixels:
     1. warm grade on the sprite so her key light agrees with the scene
     2. a soft-light tint layer OVER the sprite, tinted per scene
     3. a grounding bloom where she meets the floor
   ========================================================================== */

.scene__sprite {
  position: absolute;
  z-index: 1;                 /* behind .scene__content (3) on desktop */
  filter: drop-shadow(0 26px 46px rgba(110, 38, 78, .34))
          saturate(1.03) sepia(.06) brightness(1.012)
          contrast(.985);
}

/* 2. scene-tinted light wrap sitting ABOVE the sprite, below the content.
   It is a real element (not .scene__stage::after) because .scene__stage is its
   own stacking context — a pseudo-element inside it could never sit above the
   sprite, which lives outside the stage. */
.scene__light {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  mix-blend-mode: soft-light;
  opacity: .72;
  background:
    radial-gradient(78% 62% at 18% 22%, var(--scene-key, rgba(255, 226, 190, .95)), transparent 68%),
    linear-gradient(200deg, var(--scene-warm, rgba(255, 214, 232, .55)), transparent 62%);
}

/* 3. grounding bloom where she meets the floor */
.scene__stage::before {
  content: "";
  position: absolute;
  z-index: 2;
  left: 0; right: 0;
  bottom: -6%;
  height: 34%;
  pointer-events: none;
  background: radial-gradient(58% 100% at 72% 100%,
              var(--scene-floor, rgba(120, 60, 90, .34)), transparent 72%);
  filter: blur(2px);
}

/* per-scene light so she belongs to THAT room */
.scene--home       { --scene-key: rgba(255, 224, 182, .98); --scene-warm: rgba(255, 210, 176, .58); --scene-floor: rgba(126, 74, 46, .32); }
.scene--title      { --scene-key: rgba(255, 216, 196, .95); --scene-warm: rgba(255, 198, 222, .52); --scene-floor: rgba(120, 52, 88, .30); }
.scene--profile    { --scene-key: rgba(255, 232, 206, .95); --scene-warm: rgba(255, 214, 230, .50); --scene-floor: rgba(112, 62, 76, .30); }
.scene--discography{ --scene-key: rgba(214, 202, 255, .92); --scene-warm: rgba(198, 182, 255, .48); --scene-floor: rgba(70, 52, 128, .32); }
.scene--mv         { --scene-key: rgba(255, 218, 172, .95); --scene-warm: rgba(255, 198, 214, .52); --scene-floor: rgba(118, 62, 52, .32); }
.scene--gallery    { --scene-key: rgba(255, 238, 216, .96); --scene-warm: rgba(255, 222, 222, .52); --scene-floor: rgba(122, 84, 70, .28); }
.scene--news       { --scene-key: rgba(255, 220, 190, .96); --scene-warm: rgba(255, 212, 196, .52); --scene-floor: rgba(124, 76, 56, .30); }
.scene--fanclub    { --scene-key: rgba(255, 198, 214, .95); --scene-warm: rgba(255, 176, 204, .52); --scene-floor: rgba(122, 44, 78, .34); }
.scene--connect    { --scene-key: rgba(255, 196, 186, .94); --scene-warm: rgba(214, 176, 226, .50); --scene-floor: rgba(72, 52, 110, .32); }
.scene--secret     { --scene-key: rgba(196, 190, 255, .92); --scene-warm: rgba(160, 158, 240, .46); --scene-floor: rgba(46, 38, 92, .36); }
.scene--music      { --scene-key: rgba(214, 202, 255, .92); --scene-warm: rgba(198, 182, 255, .48); --scene-floor: rgba(70, 52, 128, .32); }


.scene--home { --charm-x: 62%; --charm-y: 30%; }
.scene--title { --charm-x: 80%; --charm-y: 30%; }
.scene--profile { --charm-x: 66%; --charm-y: 34%; }
.scene--discography { --charm-x: 74%; --charm-y: 38%; }
.scene--mv { --charm-x: 60%; --charm-y: 32%; }
.scene--gallery { --charm-x: 82%; --charm-y: 30%; }
.scene--news { --charm-x: 64%; --charm-y: 36%; }
.scene--fanclub { --charm-x: 78%; --charm-y: 32%; }
.scene--connect { --charm-x: 62%; --charm-y: 34%; }
.scene--secret { --charm-x: 80%; --charm-y: 28%; }
.scene--music { --charm-x: 74%; --charm-y: 38%; }

@media (max-width: 899px) {
  .charm {
    left: var(--charm-mx, 14%);
    top: auto;
    bottom: calc(58svh - 6svh);
    width: 54px; height: 54px;
  }
  .charm img { width: 54px; height: 54px; }
}

@media (prefers-reduced-motion: reduce) {
  .scene__sprite { animation: none; }
}

/* HUD icon + label: text labels make the controls self-explanatory on
   desktop; below 720px they collapse to icons with the tooltip/aria-label
   carrying the meaning. */
.hud__icon { font-size: 1.02rem; line-height: 1; }
.hud__logo { width: 26px; height: 26px; border-radius: 50%; }
.hud__label {
  margin-left: var(--s-2);
  font-family: var(--f-display);
  font-size: .78rem;
  letter-spacing: .09em;
  white-space: nowrap;
}
.hud__charms .hud__label { margin-left: var(--s-1); }
.hud__charms b { margin-left: .1em; }

@media (max-width: 720px) {
  .hud__label { display: none; }
  .hud__charms b { margin-left: 0; }
}

/* tooltip affordance for the icon-only state */
.hud__btn { position: relative; }
@media (max-width: 720px) {
  .hud__btn::after {
    content: attr(title);
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    padding: 3px 9px;
    border-radius: 7px;
    background: var(--c-night);
    color: #fff;
    font-family: var(--f-body);
    font-size: .68rem;
    letter-spacing: .04em;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
    z-index: 80;
  }
  .hud__btn:hover::after, .hud__btn:focus-visible::after { opacity: 1; }
}

/* 「ヒント」 — pulses the hidden bell on demand (spec §8d, mandatory) */
.hint-btn {
  position: fixed;
  right: var(--s-3);
  bottom: calc(var(--s-3) + env(safe-area-inset-bottom));
  z-index: 55;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .9);
  border: 1px solid rgba(201, 154, 83, .45);
  color: var(--c-gold);
  font-family: var(--f-display);
  font-size: var(--t-small);
  font-weight: 700;
  letter-spacing: .06em;
  box-shadow: var(--sh-soft);
  transition: transform var(--dur) var(--ease-spring), background var(--dur) var(--ease-out);
}
.hint-btn:hover, .hint-btn:focus-visible {
  transform: translateY(-3px) scale(1.05);
  background: rgba(255, 255, 255, .34);
  border-color: rgba(201, 154, 83, .85);
  color: var(--c-brand-pri);
}
.hint-btn:active { transform: translateY(0) scale(.97); transition-duration: .08s; }
.hint-btn:active { transform: translateY(0) scale(.95); }
.hint-btn.is-used { opacity: .55; }

/* ==========================================================================
   ONE-SCREEN SECTION
   Master's rule: the whole home section must be visible on a 16:9 screen.
   Only the footer may fall below the fold. Every spacing decision below is
   budgeted against that — see the height budget in the commit message.
   ========================================================================== */
.scene__content {
  padding-block: calc(var(--hud-h) + 10px) 10px;
  gap: 0;
}

.panel {
  padding: 14px var(--s-4);
  margin-block: 12px;
  border-radius: 16px;
}

.panel--hero { padding: var(--s-3) var(--s-4); margin-block: 0 var(--s-2); }

.panel--hero h1 {
  font-size: var(--t-hero);
  line-height: 1.12;
  letter-spacing: .015em;
  margin-block: .12em .06em;
}

.eyebrow { margin-block: 0 .35em; font-size: clamp(.72rem, 1.25vw, .82rem); }
.romaji  { margin-block: .15em 0; font-size: .82rem; }

.scene-nav {
  margin-block: 10px 0;
  gap: 6px;
}
.scene-nav .btn {
  padding: .42em .88em;
  font-size: .78rem;
  min-height: 34px;
}

/* the dialogue block is the tallest element — keep its chrome small */
.dialogue {
  margin-block: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-radius: 16px;
}
.dialogue__name { margin-bottom: 5px; padding: 2px 10px; font-size: .66rem; }
.dialogue__nav  { margin-top: 8px; }
.dialogue__step { width: 30px; height: 30px; font-size: .76rem; }
.dialogue__page .dialogue__text {
  font-size: clamp(.95rem, 1.42vw, 1.06rem);
  line-height: 1.76;
}

.hint-note { margin-top: var(--s-2); padding: var(--s-2) var(--s-3); }
.hint-note p { line-height: 1.7; }

/* one-screen budget: the panel interiors must not eat the height */
.panel h2 { font-size: clamp(1.05rem, 2vw, 1.32rem); margin-block: 0 .3em; line-height: 1.3; }
.chips { gap: var(--s-2); margin-block: var(--s-2) 0; }
.chip { padding: .32em .92em; font-size: .78rem; min-height: 32px; }
.eyebrow + h1 + .romaji { margin-block: 0; }

/* the sprite crossfades between poses like a VN sprite swap */
/* Single source of truth: opacity ONLY. Master wants her to stay exactly
   where she is - the pose changes with a fade, she never moves. */
.scene__sprite { transition: opacity .22s ease; }
.scene__sprite.is-swapping { opacity: 0; }

/* ==========================================================================
   SECTION 1 — the dialogue room.
   .scene__lead is the box the sprite is anchored to. Before this existed the
   sprite was positioned against the WHOLE page, so adding the releases section
   below pushed her to the very bottom and cropped her head off. Master:
   "Keep Suzu-chan visible on the 1st section as intended."
   ========================================================================== */
.scene__lead {
  position: relative;
  min-height: 100svh;
  z-index: 2;
}
.scene__lead .scene__sprite {
  position: absolute;
  right: 2%;
  bottom: 0;
  height: min(86svh, 820px);
  width: auto;
  z-index: 1;
}
.scene__lead .scene__light { z-index: 2; }
.scene__lead .scene__content { z-index: 3; }

@media (max-width: 899px) {
  .scene__lead .scene__sprite {
    right: auto; left: 50%;
    transform: translateX(-50%);
    height: min(62svh, 520px);
    opacity: 1;
  }
}

/* ==========================================================================
   FIX: the two sections must span the WHOLE scene grid.
   .scene is a two-column grid on desktop (copy | sprite lane). Adding a second
   section below made .scene__lead and the releases section land one per column,
   side by side. Both now span every column, and .scene__lead inherits the
   copy|sprite grid so section 1 lays out exactly as it always did.
   ========================================================================== */
.scene__lead { grid-column: 1 / -1; }
.scene__section--releases { grid-column: 1 / -1; }

@media (min-width: 900px) {
  .scene__lead {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, .92fr);
    align-items: center;
    min-height: 100svh;
  }
}

/* ==========================================================================
   SHE STAYS AT HER POSITION.
   Master: "Suzu-chan suppose to stay at her position and the scroll craft
   change her pose, fade out, fade in." She is pinned to the right lane across
   BOTH sections; only the pose changes. The releases grid leaves her that lane.
   ========================================================================== */
@media (min-width: 900px) {
  .scene--discography > .scene__sprite {
    position: sticky;
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: start;
    top: calc(100svh - min(86svh, 820px));
    justify-self: end;
    margin-right: clamp(2%, 6vw, 12%);
    height: min(86svh, 820px);
    width: auto;
    z-index: 1;
    animation: none;
    opacity: 1;
  }
  /* the releases section must leave her the right lane */
  .scene__section--releases .scene__section-inner {
    max-width: min(1120px, 52%);
    margin-inline: clamp(var(--s-5), 6vw, var(--s-7)) auto;
  }
}

/* the releases panel paints BELOW her (z-index 1) so she stands in the room */
.scene__lead { z-index: auto; }
.scene__section--releases { z-index: auto; }

/* ==========================================================================
   MASTER'S CORRECTION (2026-10-13):
   1. The FIRST section is exactly one 16:9 screen tall - 100% of it.
   2. Suzu is NOT stuck to section 1. She stays at her position ON SCREEN, so
      she is visible in section 2 as well while you scroll.

   Why it was wrong: `.scene__lead` had only `min-height: 100svh` and, as a grid
   item, it resolved to its content height (measured 699px in a 900px viewport).
   And `grid-row: 1 / -1` does NOT span implicit rows - with no grid-template-rows
   set, -1 is line 1, so the span collapsed and she never reached section 2.
   ========================================================================== */
.scene__lead {
  height: 100svh;
  min-height: 100svh;
  box-sizing: border-box;
}

@media (min-width: 900px) {
  .scene--discography > .scene__sprite {
    position: fixed;              /* fixed to the SCREEN, not to section 1 */
    right: clamp(2%, 6vw, 12%);
    bottom: 0;
    height: min(86svh, 820px);
    width: auto;
    z-index: 1;
    grid-column: auto;
    grid-row: auto;
    top: auto;
    align-self: auto;
    justify-self: auto;
    margin-right: 0;
  }
}
