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

body {
  background: #211307;
  font-family: system-ui, -apple-system, sans-serif;
  overflow: hidden;
}

.wrap {
  height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/*
 * 1920x1080 comp from the Figma prototype. All layer geometry below is that
 * frame's coordinates expressed as percentages of the stage.
 * --tear is the tear layer's left edge; app.js drives it from scroll.
 */
.stage {
  --tear: 37.1354%;
  position: relative;
  aspect-ratio: 1920 / 1080;
  width: min(100vw, 177.78dvh);
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
}

.layer {
  position: absolute;
  display: block;
  pointer-events: none;
}

.bg-bronze          { left: 0;        top: 0;       width: 100%;      height: 100%; }
.bg-right-building  { left: 25.6771%; top: 4.6296%; width: 73.2813%;  height: 95.3704%; }
.bg-right-halftones { left: 0.0521%;  top: 0;       width: 99.9479%;  height: 100%; }
.bg-gold            { left: 0.0521%;  top: 0;       width: 51.25%;    height: 100%; }
.bg-left-building   { left: 0;        top: 0;       width: 50.6771%;  height: 100%; }
.bg-left-halftones  { left: 0;        top: 0;       width: 51.25%;    height: 100%; }
.pace-bond          { left: 18.2292%; top: 0.0926%; width: 55.2604%;  height: 99.9074%; }
.pace-homeboy       { left: 20.3125%; top: 0.0926%; width: 48.8021%;  height: 99.9074%; }
.tear               { left: var(--tear); top: 0;    width: 15.4688%;  height: 100%; }
.title              { left: 30.8333%; top: 1.1111%; width: 34.2188%;  height: 30.3704%; }

/* Full-stage wrappers so the ragged clip-path resolves in stage coordinates. */
.figure-wrap {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Comic caption cards that pull in from the edges as each Pace is revealed. */
.caption {
  position: absolute;
  top: 36%;
  width: 20.5%;
  padding: 1.1% 1.3%;
  background: #f3e9d4;
  color: #201206;
  border: 3px solid #16100a;
  box-shadow: 7px 7px 0 rgba(22, 16, 10, 0.55);
  pointer-events: none;
  opacity: 0;
  transition: transform 0.5s cubic-bezier(0.22, 1.1, 0.36, 1), opacity 0.35s ease;
}

.caption .kicker {
  display: inline-block;
  background: #16100a;
  color: #f3e9d4;
  padding: 0.2em 0.7em;
  font-size: clamp(8px, 1.1vw, 15px);
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 0.55em;
}

.caption h2 {
  font-size: clamp(11px, 1.9vw, 30px);
  font-weight: 900;
  line-height: 1.02;
  text-transform: uppercase;
  transform: skewX(-4deg);
  margin-bottom: 0.4em;
}

.caption p {
  font-size: clamp(9px, 1.25vw, 19px);
  line-height: 1.4;
  font-weight: 600;
}

.caption-bond {
  left: 2.2%;
  transform: translateX(-140%) rotate(-2deg);
}

.caption-homeboy {
  right: 2.2%;
  transform: translateX(140%) rotate(2deg);
}

.stage.show-bond .caption-bond {
  transform: translateX(0) rotate(-2deg);
  opacity: 1;
}

.stage.show-homeboy .caption-homeboy {
  transform: translateX(0) rotate(2deg);
  opacity: 1;
}

/* Concept tagline, visible around the split-face center state. */
.tagline {
  position: absolute;
  bottom: 11%;
  left: 50%;
  transform: translateX(-50%) translateY(12px);
  color: #f3e9d4;
  background: rgba(22, 16, 10, 0.72);
  border: 2px solid rgba(243, 233, 212, 0.35);
  padding: 0.5em 1.4em;
  font-size: clamp(10px, 1.4cqw, 21px);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s ease, transform 0.4s ease;
}

.stage.show-center .tagline {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Narrow screens (phones): captions become bottom-anchored sheets that grow
 * upward, so long copy can't run past the bottom edge of the stage. */
@media (max-width: 700px) {
  .caption {
    top: auto;
    bottom: 3.5%;
    width: 46%;
    padding: 2% 2.4%;
    box-shadow: 4px 4px 0 rgba(22, 16, 10, 0.55);
  }

  .caption .kicker { font-size: clamp(7px, 2.4vw, 12px); }
  .caption h2      { font-size: clamp(10px, 4.2vw, 22px); }
  .caption p       { font-size: clamp(8px, 3vw, 15px); line-height: 1.32; }

  .tagline {
    font-size: clamp(8px, 3vw, 16px);
    white-space: normal;
    text-align: center;
    max-width: 88%;
  }
}

.hint {
  position: absolute;
  bottom: 4%;
  left: 50%;
  transform: translateX(-50%);
  color: #fdf6e3;
  background: rgba(24, 12, 3, 0.55);
  padding: 8px 18px;
  border-radius: 999px;
  font-size: clamp(12px, 1.6vw, 16px);
  letter-spacing: 0.04em;
  white-space: nowrap;
  transition: opacity 0.6s;
  animation: hint-pulse 2.4s ease-in-out infinite;
}

.hint.seen {
  opacity: 0;
  animation: none;
}

@keyframes hint-pulse {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(-6px); }
}

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

/* Portrait: fill the height instead of the width.
 *
 * The stage is a 16:9 frame, so sizing it to the viewport WIDTH leaves it 26%
 * of the height on a 414x896 phone — 414x233, a strip across the middle with
 * two thirds of the screen empty. Widening it to 178vw and letting `.wrap`
 * crop the overflow makes it ~46% instead, at the cost of the outer ~22% a
 * side: the two outer buildings, which carry no interaction.
 *
 * That crop budget is set by two things and cannot grow much:
 *
 *   1. The figures span 18.2%-73.5% of the frame (`.pace-bond` / `.pace-homeboy`
 *      above), so 56% is the narrowest window that still holds both.
 *   2. `follow()` in app.js maps pointer x through the stage's client rect, so
 *      the reachable tear range shrinks with the visible window. The caption
 *      reveals fire at a 0.62 ratio of TEAR_CENTER->TEAR_RIGHT / ->TEAR_LEFT;
 *      below 43.6% visible the homeboy threshold stops being reachable by
 *      touch and that caption simply never appears. At 56.2% the reveals peak
 *      at 0.81 (bond) and 0.90 (homeboy) against that 0.62 threshold, so there
 *      is real headroom — but it is 12.6 percentage points of width, not the
 *      whole gap to zero.
 *
 * The frame is nudged 2% right so the crop does not eat the bond figure's
 * shoulder. That is a trade against touch-target size, measured in the table
 * on `.stage` below — and it also moves everything positioned on the frame's
 * centre (the hint pill, the tagline, the title) 2% right of screen centre,
 * which is why the tagline cap below is 48% and not 50%.
 *
 * No new assets, and the tear is untouched: the crack clip paths are all
 * percentages of the stage, so they scale with it.
 */
@media (orientation: portrait) {
  .stage {
    /* Height is width x 0.5625, so 177.78dvh is exactly the width at which the
       stage is 100dvh tall. In portrait 178vw always loses, except on a
       viewport within 0.1% of square — the clamp guards that edge, not tablets
       (a 768x1024 iPad takes 178vw and lands at 75% of the height). */
    width: min(178vw, 177.78dvh);
    /* `.wrap` is a flex row and every layer inside the stage is absolutely
       positioned, so the stage has no intrinsic width to hold it open: without
       this it shrinks straight back to the 426px container and the width above
       does nothing. This is the whole fix — the width alone is a no-op. */
    flex-shrink: 0;
    /* The artwork centres on 45.9% of the frame, not 50%, so an uncentred crop
       shaves the bond figure's left shoulder. Nudging right fixes that but
       costs touch target: `follow()` maps pointer x through the stage rect, so
       moving the frame right pushes the screen region that trips the bond
       caption toward the edge. Measured on a 390px viewport:

         nudge   bond zone   homeboy zone   figure clipped
         0%        61px         43px            25px
         2%        47px         57px            12px
         4%        33px         71px             0px

       4% centres the artwork perfectly and leaves a 33px target that overlaps
       the Android gesture-nav strip (~24dp) and the iOS interactive-pop edge.
       2% keeps both zones at roughly twice that strip and halves the clipping.
       Re-measure this table before changing the width above. */
    transform: translateX(2%);
  }

  /* The captions are anchored to the frame edges — exactly what the crop
     removes. Re-anchor them inside the visible window (19.9%-76.1% at this
     nudge), with margin for the card's offset box-shadow and its 2deg
     rotation, which sit outside the box and would otherwise clip. */
  .caption-bond    { left: 22%; }
  .caption-homeboy { right: 26%; }

  /* 88% of the frame is wider than the window. The tagline centres on the
     frame's 50%, which the nudge puts 2% right of the window's centre, so cap
     it at 48% rather than 50% — at 50% its right edge would clip. */
  .tagline {
    max-width: 48%;
    /* `white-space: normal` only arrives from the max-width:700px block, which
       does not match a portrait tablet. Without it the base `nowrap` survives
       and long copy lays out past the capped box, rendering outside its own
       background. */
    white-space: normal;
    text-align: center;
  }
}
