/* ODE · Seoul Encore hanging words — ALIVE monograph tokens */

:root {
  color-scheme: light;
  --ink: #0f0d0b;
  --ink-soft: #2a241c;
  --ink-60: rgba(15, 13, 11, 0.62);
  --ink-40: rgba(15, 13, 11, 0.4);
  --ink-18: rgba(15, 13, 11, 0.18);
  --paper: #f5f0e4;
  --paper-warm: #ebe3d1;
  --paper-hi: #fbf7ee;
  --terracotta: #c4714a;
  --warm-amber: #e2a820;
  --sage: #7a9464;
  --signal: #d8291d;
  --ultramarine: #2a46c8;
  --font-display: "Newsreader", "Times New Roman", serif;
  --font-wordmark: "Archivo Black", "Inter", sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
  --font-kr: "Noto Sans KR", "Apple SD Gothic Neo", sans-serif;
  --font-kid: "Indie Flower", "Segoe Print", "Comic Sans MS", cursive;
  --easing: cubic-bezier(0.2, 0.8, 0.2, 1);
  /*
   * Vertical composition reserves — the building box is centered in the band
   * left between the fixed header (top) and the fixed score + footer (bottom).
   * Tuned per breakpoint below. Keeping the building sized to this band (rather
   * than a fixed pixel lift) is what prevents top-clipping on short/landscape
   * screens and the dead void on tall/wide screens.
   */
  --top-reserve: 84px;
  --bottom-reserve: 196px;
  font-synthesis: none;
  text-rendering: optimizeLegibility;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  min-height: 100%;
  background: var(--paper);
  color: var(--ink);
}

body {
  min-height: 100svh;
  overflow: hidden;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  background:
    radial-gradient(ellipse 55vw 50vh at 78% 42%, rgba(226, 168, 32, 0.09), transparent 55%),
    radial-gradient(ellipse 45vw 55vh at 12% 70%, rgba(196, 113, 74, 0.07), transparent 50%),
    linear-gradient(160deg, var(--paper-hi) 0%, var(--paper) 48%, var(--paper-warm) 100%);
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: 0;
  background: transparent;
}

.grain {
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  opacity: 0.42;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='280' height='280'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.06  0 0 0 0 0.05  0 0 0 0 0.04  0 0 0 0.38 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

/* Floating butterflies — same paper-cut flock as ALIVE flower.html.
   Sit in the air above the building, under grain / chrome; never capture pointer. */
.butterfly-field {
  position: fixed;
  inset: 0;
  z-index: 7;
  pointer-events: none;
  overflow: hidden;
}
.bfly {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}
.bfly svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  filter: drop-shadow(0 8px 10px rgba(176, 81, 63, 0.10));
}
.bfly .wing {
  transform-box: view-box;
  transform-origin: 50% 50%;
  animation: bfly-flap var(--flap, 0.9s) ease-in-out infinite alternate;
  animation-delay: var(--flap-delay, 0s);
}
@keyframes bfly-flap {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0.24); }
}
@media (prefers-reduced-motion: reduce) {
  .bfly .wing { animation: none; }
}

/* —— top bar —— */
.top-bar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 20;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  padding: 18px clamp(16px, 3vw, 36px) 14px;
  pointer-events: none;
}

.meta-left,
.meta-right {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-60);
}

.meta-left .kr,
.meta-right .kr {
  font-family: var(--font-kr);
  letter-spacing: 0.04em;
  text-transform: none;
}

.meta-right { text-align: right; }
.dot { opacity: 0.45; margin: 0 0.35em; }

.tagline {
  font-family: var(--font-kid);
  font-weight: 400;
  font-style: normal;
  font-size: clamp(17px, 2.35vw, 28px);
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  text-align: center;
  white-space: nowrap;
}

/* —— stage —— */
.stage {
  position: relative;
  width: 100%;
  height: 100dvh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Center the building in the band between header and the fixed score/footer */
  justify-content: center;
  gap: 0;
  /* Reserve header (top) + score/footer (bottom); building fits between */
  padding: var(--top-reserve) 0 var(--bottom-reserve);
  isolation: isolate;
}

.stage .installation {
  margin-top: 0;
  /* Allow the box to shrink to fit the band on short screens (no overlap) */
  flex-shrink: 1;
  min-height: 0;
  /* No fixed lift — centering + band sizing places it on every viewport */
  transform: none;
}

.stage .installation .building-wrap {
  /* Desktop: building sit 10px lower than prior -50px lift; curtain stays put */
  transform: translateY(-40px);
}

/* Full-stage atmosphere — diffuse sky + warm evening haze (no hard oval blobs) */
.sky {
  position: absolute;
  inset: -12% -25% 18% -25%;
  pointer-events: none;
  background:
    /* Cool daylight field — very wide, soft falloff */
    radial-gradient(ellipse 130% 100% at 50% -5%,
      rgba(198, 216, 234, 0.58) 0%,
      rgba(214, 226, 236, 0.32) 38%,
      rgba(232, 228, 218, 0.1) 62%,
      transparent 78%),
    /* Warm evening haze — broad horizontal veil, not a spotlight oval */
    radial-gradient(ellipse 160% 70% at 48% 12%,
      rgba(255, 244, 220, 0.34) 0%,
      rgba(255, 228, 180, 0.14) 28%,
      rgba(255, 214, 150, 0.05) 48%,
      transparent 68%),
    /* Gentle top wash (sunlight through paper) */
    linear-gradient(185deg,
      rgba(255, 250, 236, 0.28) 0%,
      rgba(255, 242, 210, 0.1) 14%,
      transparent 36%),
    /* Faint cool lift on the left so it doesn’t feel flat */
    radial-gradient(ellipse 70% 80% at 12% 30%,
      rgba(245, 250, 255, 0.18) 0%,
      transparent 55%);
  /* Soft vertical dissolve into the page — no circular mask */
  mask-image: linear-gradient(
    180deg,
    #000 0%,
    #000 42%,
    rgba(0, 0, 0, 0.55) 62%,
    transparent 88%
  );
  -webkit-mask-image: linear-gradient(
    180deg,
    #000 0%,
    #000 42%,
    rgba(0, 0, 0, 0.55) 62%,
    transparent 88%
  );
}

/* Foreground plaza — flat plane that dissolves into paper (no disc/oval) */
.ground {
  position: absolute;
  inset: 46% 0 -20% 0;
  /* Match building + flower floor nudge */
  transform: translateY(10px);
  pointer-events: none;
  background:
    /* Horizontal band of pavement tone */
    linear-gradient(180deg,
      transparent 0%,
      rgba(165, 160, 150, 0.07) 8%,
      rgba(155, 150, 140, 0.14) 22%,
      rgba(148, 144, 134, 0.18) 40%,
      rgba(160, 154, 142, 0.12) 58%,
      rgba(180, 172, 158, 0.05) 75%,
      transparent 92%),
    /* Barely-there center emphasis so it still feels grounded under the building */
    radial-gradient(ellipse 100% 55% at 50% 28%,
      rgba(170, 165, 155, 0.1) 0%,
      transparent 70%);
  /* Fade only top/bottom into paper — full width, no side “egg” */
  mask-image: linear-gradient(
    180deg,
    transparent 0%,
    #000 14%,
    #000 58%,
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    180deg,
    transparent 0%,
    #000 14%,
    #000 58%,
    transparent 100%
  );
}

.installation {
  position: relative;
  z-index: 4;
  /*
   * Uniform 720/900 box (building proportions untouched — object-fit: contain).
   * Size is driven by the SHORTER of: the available vertical band (height 100%
   * of the stage content box), the width cap expressed as a height, and an
   * absolute cap. min() keeps the building whole on every viewport while the
   * aspect-ratio guarantees the scale stays uniform.
   */
  height: min(100%, calc(88vw * 900 / 720), 792px);
  width: auto;
  aspect-ratio: 720 / 900;
  max-width: 92vw;
  margin-inline: auto;
  flex-shrink: 1;
  min-height: 0;
  overflow: visible;
  touch-action: none;
  cursor: crosshair;
  user-select: none;
  -webkit-user-select: none;
}

.building-wrap {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
  overflow: visible;
}

.building-svg,
.building {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  object-position: center center;
  /* Critical: default SVG overflow is hidden and hard-clips soft shadow */
  overflow: visible;
  pointer-events: none;
  user-select: none;
  display: block;
  margin: 0 auto;
}

/* Code-drawn facade — crown light pulse (evening ref) */
@media (prefers-reduced-motion: no-preference) {
  .building-svg .crown-core {
    animation: crown-breathe 4.5s ease-in-out infinite;
  }
}

/* Interactive room lights — panel by panel, gentle on / off */
.building-svg .panel-glow,
.building-svg .panel-led {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.75s cubic-bezier(0.22, 0.8, 0.25, 1);
}

.building-svg .room-panel.is-lit .panel-glow {
  opacity: 0.62;
}

.building-svg .room-panel.is-lit .panel-led {
  opacity: 0.95;
}

@media (prefers-reduced-motion: reduce) {
  .building-svg .panel-glow,
  .building-svg .panel-led {
    transition-duration: 0.12s;
  }
}

@keyframes crown-breathe {
  0%, 100% { opacity: 0.82; }
  50% { opacity: 1; }
}

#curtain {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 2;
  /* Canvas still has its own pixel bounds, but no CSS box paint */
  background: transparent;
  overflow: visible;
}

/* Full-stage bloom layer — can drift into sky / ground beyond the building card */
#fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 6;
  pointer-events: none;
}

.hint {
  /* Fixed above score — must clear full score block (~6rem) + gap */
  position: fixed;
  left: 50%;
  bottom: calc(12.25rem + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 18;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-60);
  pointer-events: none;
  transition: opacity 480ms var(--easing);
}

.hint.is-hidden { opacity: 0; }

.hint-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--terracotta);
  box-shadow: 0 0 0 4px rgba(196, 113, 74, 0.18);
  animation: pulse 1.8s var(--easing) infinite;
}

@keyframes pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.25); opacity: 0.7; }
}

/* —— live score —— */
.score {
  position: fixed;
  left: 50%;
  /* Clear multi-line mobile footer + home indicator */
  bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  width: min(88vw, 560px);
  z-index: 18;
  pointer-events: none;
  text-align: center;
  flex-shrink: 0;
}

.score-label {
  margin-bottom: 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.16em;
  color: var(--ink-40);
}

#staff {
  width: 100%;
  height: auto;
  max-height: 72px;
  opacity: 0.92;
}

/* —— footer —— */
.bottom-bar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 20;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: end;
  gap: 12px;
  padding: 10px clamp(16px, 3vw, 36px) 16px;
  pointer-events: none;
  border-top: 1px solid var(--ink-18);
  background: color-mix(in srgb, var(--paper) 78%, transparent);
  backdrop-filter: blur(14px);
}

.credit {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.04em;
  color: var(--ink-40);
  max-width: 36ch;
}

.venue {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-40);
  text-align: right;
  justify-self: end;
  white-space: nowrap;
}

.venue .kr {
  font-family: var(--font-kr);
  letter-spacing: 0.04em;
  text-transform: none;
}

.venue .dot {
  opacity: 0.45;
  margin: 0 0.35em;
}

.dates {
  display: flex;
  gap: 14px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* —— responsive —— */
@media (max-width: 720px) {
  body { overflow: hidden; }

  :root {
    /* Mobile chrome is taller: stacked header + multi-line footer + score */
    --top-reserve: calc(4.4rem + env(safe-area-inset-top, 0px));
    --bottom-reserve: calc(13.25rem + env(safe-area-inset-bottom, 0px));
  }

  .top-bar {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 2px;
    padding: max(6px, env(safe-area-inset-top, 0px)) 10px 4px;
  }
  .meta-left, .meta-right { font-size: 8px; }
  .meta-right { text-align: center; }
  .tagline {
    font-size: clamp(15px, 4vw, 19px);
    white-space: normal;
    line-height: 1.25;
    max-width: 20ch;
  }

  .stage {
    height: 100dvh;
    min-height: 100dvh;
    /* Centered in the band; reserves above clear the mobile chrome */
    padding: var(--top-reserve) 0 var(--bottom-reserve);
    justify-content: center;
    gap: 0;
  }

  .stage .installation {
    transform: none;
    /* Fill the band, but let width drive on wide/short phones. Ratio preserved. */
    height: min(100%, calc(94vw * 900 / 720));
    width: auto;
    max-width: 96vw;
    aspect-ratio: 720 / 900;
    margin-inline: auto;
  }

  .stage .installation .building-wrap {
    transform: translateY(10px);
  }

  /* score clears tall multi-line footer; hint clears score */
  .hint {
    bottom: calc(13.5rem + env(safe-area-inset-bottom, 0px));
    font-size: 9px;
    letter-spacing: 0.12em;
  }

  .score {
    bottom: calc(6.85rem + env(safe-area-inset-bottom, 0px));
    width: min(92vw, 400px);
  }

  .score-label {
    font-size: 9px;
    margin-bottom: 4px;
  }

  #staff {
    height: 58px;
    max-height: 58px;
  }

  .bottom-bar {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    gap: 4px;
    padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px));
  }
  .credit {
    max-width: 42ch;
    text-align: center;
    font-size: 9px;
    justify-self: center;
  }
  .venue {
    text-align: center;
    justify-self: center;
    font-size: 9px;
  }
  .dates { font-size: 9px; }
}

/*
 * —— short / landscape ——
 * Little vertical room: the building must shrink to the band and the score
 * must stay compact so the two never collide (the old fixed-lift layout let
 * the building clip the top and overrun the staff here).
 */
@media (max-height: 560px) {
  :root {
    --top-reserve: calc(2.6rem + env(safe-area-inset-top, 0px));
    --bottom-reserve: calc(3.4rem + env(safe-area-inset-bottom, 0px));
  }

  .stage {
    height: 100dvh;
    min-height: 100dvh;
    padding: var(--top-reserve) 0 var(--bottom-reserve);
    justify-content: center;
  }

  .stage .installation {
    transform: none;
    height: min(100%, calc(64vw * 900 / 720));
    width: auto;
    max-width: 82vw;
    aspect-ratio: 720 / 900;
  }

  /* Keep the wrap/curtain registration but drop the desktop 10px nudge */
  .stage .installation .building-wrap { transform: none; }

  /* Hide the live score in landscape — no room, and it fought the building */
  .score { display: none; }
  .hint { display: none; }

  .bottom-bar {
    padding: 4px clamp(10px, 3vw, 28px) calc(4px + env(safe-area-inset-bottom, 0px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .hint-dot { animation: none; }
  * { scroll-behavior: auto !important; }
}
