/* Living Comic — prototype styles.
   Mobile-first. GPU-friendly transforms only. No background-attachment: fixed. */

:root {
  --page-bg: #1a1714;
  --bubble-fill: #FBF6EA;   /* warm cream paper (bubble-demo.html) */
  --bubble-ink: #1B1612;    /* near-black ink for text + outline */
  --bubble-outline: #1B1612;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: #0d0b09;
  color: #f6efe0;
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;        /* breakout layers may spill past the page edges */
}

.stage {
  display: flex;
  justify-content: center;
  align-items: center;
  /* fit one screen (svh = stable across the iOS URL-bar show/hide), small
     room for the breakout to spill above/below the page; no extra scroll.
     In PWA standalone the content draws under the status bar / Dynamic Island,
     so keep a safe zone top & bottom (env() resolves only with viewport-fit=cover). */
  min-height: 100svh;
  padding: max(5vh, env(safe-area-inset-top, 0px)) 0 max(6vh, env(safe-area-inset-bottom, 0px));
}

/* The page is a fixed-aspect column; width clamps so it reads on phone and desktop.
   overflow: visible so breakout subjects + bubbles spill into the gutters. */
.page {
  position: relative;
  width: 100vw;                 /* full viewport width */
  aspect-ratio: var(--page-aspect, 0.72);
  background: var(--page-bg);
  overflow: visible;
}

/* ---- Snap layout: one full-screen panel per scroll, snaps into place ---- */

/* iOS Safari is unreliable at scroll-snapping the document/body. The robust
   pattern is a dedicated scroll CONTAINER with its own height + overflow — the
   .stage becomes the scroller, the document itself doesn't scroll. */
body.snap-mode {
  height: 100svh;
  overflow: hidden;           /* lock document scroll; .stage scrolls instead */
}
body.snap-mode .stage {
  display: block;
  padding: 0;
  /* PWA standalone: keep the whole scroller inside the safe viewport — offset
     below the status bar / Dynamic Island and above the home indicator, so no
     panel (image edge or top bubble) is ever clipped by the island. */
  margin-top: env(safe-area-inset-top, 0px);
  height: calc(100svh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  overflow: hidden scroll;    /* x clipped (breakout is vertical), y scrolls */
  scroll-snap-type: y mandatory;
  -webkit-overflow-scrolling: touch;
}
.snap-root { width: 100vw; }

.snap {
  position: relative;
  width: 100vw;
  /* matches the (safe-area-reduced) scroller height so one panel == one screen */
  height: calc(100svh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  scroll-snap-align: start;   /* 'start' snaps more reliably than 'center' on iOS */
  scroll-snap-stop: always;   /* don't skip past a panel in one flick */
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;          /* breakout subject spills into the screen margins */
}

/* ---- Panels ---------------------------------------------------------- */

.panel {
  position: absolute;
  overflow: visible;          /* breakout subject extends past the frame */
  will-change: transform;
}

.panel__clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* clip-path polygon injected inline by renderer.js */
}

.layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
  /* slightly oversize so parallax drift never reveals an empty edge */
  transform: translate3d(0, 0, 0);
}

.layer--background {
  scale: 1.12;
}

/* breakout subject is a sibling of __clip, higher z, NOT clipped */
.layer--subject {
  position: absolute;
  z-index: 3;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  will-change: transform;
}

.layer--subject.is-shadow {
  filter: drop-shadow(0 14px 18px rgba(0, 0, 0, 0.55));
}

/* subject rendered inside the clip when breakout:false */
.panel__clip .layer--subject {
  z-index: 2;
}

/* wrapper that clips a breakout subject's bottom to the bg's bottom line
   (open at the top so the head still breaks out); panel-coord, untransformed */
.layer--clipwrap {
  position: absolute;
  inset: 0;
}

.panel__border {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
}
.panel__border polygon {
  fill: none;
  vector-effect: non-scaling-stroke;
}

/* ---- Speech bubbles -------------------------------------------------- */

/* The bubble is a transparent, shrink-to-fit box; the SVG draws the balloon
   (cream fill + ink outline + soft shadow) behind the serif text — the
   bubble-demo.html look, made parametric in renderer.js. */
.bubble {
  position: absolute;
  z-index: 10;
  display: inline-block;       /* shrink-wrap the text so the SVG can size to it */
}

/* SVG balloon: sits behind the text, top-left aligned to the text box; overflow
   visible lets the teardrop tail + thought lobes spill past the box edge. The
   soft drop-shadow replaces the old hard comic offset. */
.bubble__shape {
  position: absolute;
  top: 0;
  left: 0;
  overflow: visible;
  pointer-events: none;
  filter: drop-shadow(0 4px 5px rgba(0, 0, 0, 0.34));
}

.bubble__text {
  position: relative;
  z-index: 1;
  display: block;
  font-family: "Cormorant Garamond", Georgia, serif;
  font-weight: 600;
  font-size: 18px;
  line-height: 1.18;
  letter-spacing: 0.005em;
  color: var(--bubble-ink);
  text-align: center;
}
.bubble__text em { font-style: italic; }

/* Narration = dark film-subtitle plate: light text, smaller italic, bottom of
   the panel (positioned via the manifest). */
.bubble[data-kind="narration"] .bubble__text {
  font-weight: 500;
  font-style: italic;
  font-size: 15px;
  line-height: 1.3;
  text-align: left;
  color: #F4ECDA;
}
.bubble[data-kind="thought"] .bubble__text { font-style: italic; }

/* Title = bare serif caps over the cover, no balloon. */
.bubble[data-kind="title"] .bubble__text {
  font-weight: 600;
  font-size: 40px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #FBF6EA;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.75);
}

/* (Removed the scroll-driven view() fade-in: on a snapped full-screen panel the
   per-element view timeline left lower bubbles stuck mid-animation — partially
   transparent and soft. Bubbles now render at full opacity always.) */

/* ---- Temporary review labels (?labels) ------------------------------ */

.panel-label {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #fff;
  background: rgba(0, 0, 0, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  padding: 4px 11px;
  pointer-events: none;
  white-space: nowrap;
}

/* ---- Debug HUD (?debug): live tilt state painted on-screen ---------- */

#tilt-hud {
  position: fixed;
  left: 6px;
  bottom: 6px;
  z-index: 200;
  font: 11px/1.4 ui-monospace, Menlo, monospace;
  color: #7CFC7C;
  background: rgba(0, 0, 0, 0.82);
  padding: 6px 9px;
  border-radius: 6px;
  max-width: 72vw;
  white-space: pre;
  pointer-events: none;
}

/* ---- Enable-motion button ------------------------------------------- */

.motion-btn {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 100;
  font-family: "Patrick Hand", cursive;
  font-size: 16px;
  padding: 10px 18px;
  color: var(--bubble-ink);
  background: var(--bubble-fill);
  border: 2px solid var(--bubble-outline);
  border-radius: 999px;
  box-shadow: 0 4px 0 rgba(0, 0, 0, 0.25);
  cursor: pointer;
}
.motion-btn:active { transform: translateX(-50%) translateY(2px); box-shadow: 0 2px 0 rgba(0,0,0,0.25); }

/* ---- Reduced motion: kill all parallax/tilt, keep it legible --------- */

@media (prefers-reduced-motion: reduce) {
  .layer, .panel, .layer--background { transform: none !important; scale: 1 !important; will-change: auto; }
  .bubble { opacity: 1 !important; transform: none !important; animation: none !important; }
  .motion-btn { display: none !important; }
}
