/* Rebuild the Block: the interactive street hero. Everything is scoped to
   #rebuild-story -- the bundle shipped with its own :root, html and body rules,
   which would have repainted the page navy and lowered --ca-focus to gold-500
   (2.61 on white). */
#rebuild-story {
  color-scheme: dark;
  --ca-red-50: #fcecec;
  --ca-red-300: #e4666c;
  --ca-red-500: #b3030d;
  --ca-red-700: #8c0209;
  --ca-red-900: #5c0105;
  --ca-navy-50: #eef2f8;
  --ca-navy-100: #d8e0ee;
  --ca-navy-300: #8a9cc4;
  --ca-navy-500: #1e4278;
  --ca-navy-700: #02204f;
  --ca-navy-900: #01132f;
  --ca-gold-50: #fdf6e3;
  --ca-gold-300: #e8c267;
  --ca-gold-500: #d1952b;
  --ca-gold-700: #8f5e00;
  --ca-gold-900: #5e3d00;
  --ca-ink: #121826;
  --ca-charcoal: #2e3547;
  --ca-slate: #5a6377;
  --ca-steel: #8b93a6;
  --ca-limestone: #c9cfdb;
  --ca-fog: #e6e9f0;
  --ca-cream: #f6f4ec;
  --ca-paper: #f8f8f8;
  --ca-white: #ffffff;
  --ca-forest: #2a541e;
  --ca-plum: #362454;
  --ca-focus: #d1952b;
  --display: "Alfa Slab One", Rockwell, "Roboto Slab", serif;
  --text: "Barlow", "Helvetica Neue", Arial, sans-serif;
  --accent: "Barlow Condensed", "Arial Narrow", sans-serif;
  --p: 0;
  --travel: 0;
  --top-ui: 320px;
}
#rebuild-story *,
#rebuild-story *::before,
#rebuild-story *::after {
  box-sizing: border-box;
}
#rebuild-story {
  background: var(--inverse-deep);
  color: var(--ink-inverse);
  font-family: var(--text);
  font-size: var(--t-6);
  line-height: 1.5;
}
#rebuild-story button,
#rebuild-story a {
  font: inherit;
}
#rebuild-story button {
  cursor: pointer;
}
#rebuild-story img {
  max-width: 100%;
}
#rebuild-story .sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}
#rebuild-story :focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 3px;
}
#rebuild-story {
  /* 0 = a block is one screen wide. 1 = as wide as the plate needs to fill the
     hero top to bottom, and the overflow is pannable. rebuild.js reads this and
     writes back --block-w in pixels. */
  --block-fill: 0;
  height: 300vh;
  min-height: 1500px;
  background: var(--inverse-deep);
}
#rebuild-story .hero {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  min-height: 620px;
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(180deg, #69798c 0%, #9ea4aa 54%, #6b675f 100%);
  touch-action: pan-y;
}
#rebuild-story .sky-clear,
#rebuild-story .sky-overcast,
#rebuild-story .sky-glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
#rebuild-story .sky-clear {
  z-index: -8;
  background: linear-gradient(180deg, #6fa8ec 0%, #b9daf5 58%, #f5d2a8 100%);
}
#rebuild-story .sky-overcast {
  z-index: 18;
  background: linear-gradient(
    180deg,
    rgba(39, 50, 65, 0.82),
    rgba(91, 93, 96, 0.64) 56%,
    rgba(44, 43, 44, 0.32)
  );
  opacity: calc(1 - var(--p));
  mix-blend-mode: multiply;
}
#rebuild-story .sky-glow {
  z-index: 17;
  background:
    radial-gradient(
      circle at 16% 10%,
      rgba(255, 240, 192, 0.7),
      transparent 25%
    ),
    linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.06),
      rgba(255, 188, 105, 0.12)
    );
  opacity: var(--p);
  mix-blend-mode: screen;
}
#rebuild-story .sun {
  position: absolute;
  z-index: -6;
  width: clamp(70px, 8vw, 120px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(
    circle at 40% 38%,
    #fff9cf 0 12%,
    #ffd466 38%,
    rgba(255, 184, 55, 0.35) 66%,
    transparent 72%
  );
  filter: blur(0.2px);
  opacity: calc(0.08 + var(--p) * 0.92);
  pointer-events: none;
  transform: translate3d(8vw, 52vh, 0);
}
#rebuild-story .cloud {
  position: absolute;
  z-index: -5;
  width: 170px;
  height: 46px;
  border-radius: 50%;
  background: rgba(248, 248, 248, 0.72);
  filter: blur(2px);
  box-shadow:
    38px -18px 0 4px rgba(248, 248, 248, 0.65),
    78px 2px 0 -4px rgba(248, 248, 248, 0.7);
  animation: cloud-drift 38s linear infinite;
  pointer-events: none;
}
#rebuild-story .cloud.one {
  left: 13vw;
  top: 12vh;
}
#rebuild-story .cloud.two {
  left: 74vw;
  top: 18vh;
  transform: scale(0.72);
  animation-duration: 51s;
  animation-delay: -22s;
}
@keyframes cloud-drift {
  0% {
    translate: -12vw 0;
  }
  50% {
    translate: 7vw 8px;
  }
  100% {
    translate: -12vw 0;
  }
}
#rebuild-story .horizon {
  position: absolute;
  z-index: -4;
  left: -10vw;
  right: -90vw;
  bottom: 24vh;
  height: 27vh;
  opacity: 0.42;
  filter: blur(8px);
  background: linear-gradient(
    90deg,
    rgba(29, 45, 76, 0.76) 0 9%,
    transparent 9% 11%,
    rgba(33, 49, 78, 0.72) 11% 17%,
    transparent 17% 19%,
    rgba(24, 42, 71, 0.68) 19% 25%,
    transparent 25% 43%,
    rgba(70, 112, 60, 0.64) 55%,
    rgba(101, 143, 73, 0.76) 70%,
    rgba(80, 126, 61, 0.72)
  );
  clip-path: polygon(
    0 100%,
    0 48%,
    4% 48%,
    4% 17%,
    7% 17%,
    7% 55%,
    10% 55%,
    10% 3%,
    14% 3%,
    14% 48%,
    17% 48%,
    17% 30%,
    22% 30%,
    22% 63%,
    27% 63%,
    27% 34%,
    31% 34%,
    31% 62%,
    40% 62%,
    46% 80%,
    51% 66%,
    57% 83%,
    63% 55%,
    70% 82%,
    78% 60%,
    86% 77%,
    93% 50%,
    100% 69%,
    100% 100%
  );
  transform: translate3d(0, 0, 0);
  will-change: transform;
}
#rebuild-story .top-scrim {
  position: absolute;
  z-index: 20;
  inset: 0 0 auto;
  height: min(54vh, 430px);
  background: linear-gradient(
    180deg,
    rgba(1, 19, 47, 0.97),
    rgba(1, 19, 47, 0.82) 57%,
    rgba(1, 19, 47, 0.18) 88%,
    transparent
  );
  pointer-events: none;
}
#rebuild-story .topbar {
  position: absolute;
  z-index: 35;
  left: clamp(16px, 3vw, 46px);
  right: clamp(16px, 3vw, 46px);
  top: max(12px, env(safe-area-inset-top));
  display: grid;
  grid-template-columns: minmax(180px, 1fr) auto;
  gap: 18px;
  align-items: center;
}
#rebuild-story .meter-wrap {
  max-width: 520px;
}
#rebuild-story .meter-label {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: var(--s-2);
  color: var(--ink-inverse-2);
  font: 600 var(--t-2)/1 var(--accent);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
#rebuild-story .meter {
  height: 10px;
  border: 1px solid rgba(248, 248, 248, 0.48);
  background: rgba(1, 19, 47, 0.74);
  overflow: hidden;
}
#rebuild-story .meter-fill {
  width: 100%;
  height: 100%;
  transform: scaleX(var(--p));
  transform-origin: left center;
  background: linear-gradient(90deg, var(--ca-gold-500), #f3c758);
  will-change: transform;
}
#rebuild-story .utility {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
}
#rebuild-story .btn {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  border-radius: var(--r-1);
  padding: 0 var(--s-5);
  border: 0;
  font: 600 var(--t-6)/1 var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
#rebuild-story .btn-small {
  min-height: 36px;
  padding: 0 var(--s-4);
  font-size: var(--t-3);
}
#rebuild-story .btn-primary {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
}
#rebuild-story .btn-primary:hover {
  background: var(--ca-gold-300);
}
#rebuild-story .btn-secondary {
  background: rgba(1, 19, 47, 0.56);
  color: var(--ca-paper);
  border: 2px solid var(--ca-paper);
}
#rebuild-story .btn-secondary:hover {
  background: rgba(248, 248, 248, 0.12);
}
#rebuild-story .btn-tertiary {
  min-height: 36px;
  background: rgba(1, 19, 47, 0.78);
  color: var(--ca-paper);
  border: 1px solid rgba(248, 248, 248, 0.42);
  padding: 0 0.8rem;
}
#rebuild-story .intro {
  position: absolute;
  z-index: 32;
  left: clamp(18px, 4vw, 64px);
  top: 76px;
  width: min(620px, calc(100% - 36px));
  pointer-events: none;
}
#rebuild-story .eyebrow {
  color: var(--ca-gold-300);
  font: 600 var(--t-3)/1.2 var(--accent);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
#rebuild-story .intro h1 {
  max-width: 12ch;
  margin: 0.16em 0 0.12em;
  color: var(--ink-inverse);
  font: 400 clamp(2.65rem, 5.8vw, 4.75rem)/1.1 var(--display);
  letter-spacing: -0.005em;
  text-wrap: balance;
}
#rebuild-story .intro p {
  max-width: 54ch;
  margin: 0;
  color: var(--ink-inverse-2);
  font-size: clamp(17px, 1.55vw, 20px);
  line-height: 1.45;
  text-shadow: 0 1px 14px rgba(1, 19, 47, 0.8);
}
#rebuild-story .tabs {
  position: absolute;
  z-index: 34;
  top: min(49vh, 430px);
  left: 50%;
  display: flex;
  max-width: calc(100vw - 32px);
  transform: translateX(-50%);
  gap: 4px;
  padding: var(--s-1);
  background: rgba(1, 19, 47, 0.88);
  border: 1px solid rgba(248, 248, 248, 0.3);
  box-shadow: 0 8px 30px rgba(1, 19, 47, 0.32);
  overflow-x: auto;
  scrollbar-width: none;
}
#rebuild-story .tabs::-webkit-scrollbar {
  display: none;
}
#rebuild-story .tab {
  flex: none;
  min-height: 40px;
  border: 0;
  border-radius: var(--r-1);
  padding: 0 var(--s-3);
  background: transparent;
  color: var(--ink-inverse-2);
  font: 600 var(--t-4)/1 var(--accent);
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
#rebuild-story .tab:hover {
  background: rgba(248, 248, 248, 0.1);
  color: var(--ca-paper);
}
#rebuild-story .tab[aria-selected="true"] {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
}
#rebuild-story .scroll-hint {
  position: absolute;
  z-index: 33;
  top: min(56vh, 490px);
  left: 50%;
  transform: translate(-50%, -6px);
  margin: 0;
  padding: var(--s-1) var(--s-3);
  color: var(--ca-paper);
  background: rgba(1, 19, 47, 0.78);
  font: 600 var(--t-3)/1.2 var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0;
  transition:
    opacity 0.25s,
    transform 0.25s;
  pointer-events: none;
}
#rebuild-story .scroll-hint.show {
  opacity: 1;
  transform: translate(-50%, 0);
}
#rebuild-story .viewport {
  position: absolute;
  z-index: 2;
  inset: 0;
  overflow: hidden;
  touch-action: pan-y;
  cursor: grab;
}
#rebuild-story .viewport.dragging {
  cursor: grabbing;
}
#rebuild-story .viewport.painting {
  cursor: crosshair;
  touch-action: none;
}
#rebuild-story .street-track {
  position: absolute;
  inset: 0 auto 0 0;
  width: 300vw;
  height: 100%;
  display: flex;
  transform: translate3d(0, 0, 0);
  will-change: transform;
}
#rebuild-story .block {
  position: relative;
  flex: 0 0 var(--block-w, 100vw);
  height: 100%;
  overflow: hidden;
}
#rebuild-story .plate-layer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  aspect-ratio: 2880/1607;
  overflow: hidden;
}
#rebuild-story .plate-image,
#rebuild-story .decline-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  pointer-events: none;
  user-select: none;
}
#rebuild-story .plate-image {
  z-index: 1;
}
#rebuild-story .decline-image {
  z-index: 2;
  will-change: opacity, filter;
}
#rebuild-story .simulated-decline {
  filter: grayscale(0.82) sepia(0.1) brightness(0.58) contrast(1.04)
    saturate(0.55);
}
#rebuild-story .damage-film {
  position: absolute;
  z-index: 3;
  inset: 0;
  opacity: 0.75;
  pointer-events: none;
  background:
    linear-gradient(
      168deg,
      transparent 0 45%,
      rgba(27, 25, 29, 0.38) 46% 47%,
      transparent 48% 72%,
      rgba(60, 50, 40, 0.34) 73% 74%,
      transparent 75%
    ),
    repeating-linear-gradient(
      92deg,
      transparent 0 8%,
      rgba(14, 26, 34, 0.09) 8.2% 8.6%,
      transparent 8.8% 15%
    );
  mix-blend-mode: multiply;
}
#rebuild-story .patch {
  position: absolute;
  z-index: 4;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  will-change: clip-path, opacity, filter, transform;
}
#rebuild-story .patch img {
  position: absolute;
  max-width: none;
  pointer-events: none;
  user-select: none;
}
#rebuild-story .patch.settled[data-reveal="light-on"] {
  animation: neon-breathe 2.8s ease-in-out infinite;
}
#rebuild-story .patch.flicker {
  animation: neon-flicker 0.78s steps(1) 1;
}
@keyframes neon-flicker {
  0%,
  12%,
  32%,
  50%,
  70%,
  100% {
    opacity: 1;
  }
  7%,
  24%,
  42%,
  61%,
  79% {
    opacity: 0.16;
  }
}
/* Brightness alone. The drop-shadow it used to carry was drawn from the
   patch's rectangular alpha, so it glowed as a yellow box, not around the sign. */
@keyframes neon-breathe {
  0%,
  100% {
    filter: brightness(1);
    transform: scale(1);
  }
  50% {
    filter: brightness(1.06);
    transform: scale(1.003);
  }
}
#rebuild-story .brush-canvas {
  position: absolute;
  z-index: 5;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* The seam between scenes
   ==========================================================================
   Blocks butt edge to edge in the track, so two different photographs meet on
   a hard vertical line at every boundary and the line is what you see when you
   walk between scenes. Each block feathers its inner edges: a narrow strip
   that blurs what is behind it, masked so the strip has no edge of its own,
   over a faint navy haze that carries the softening where backdrop-filter is
   not supported. The two neighbours each contribute one, so the seam dissolves
   across about twice the strip.

   Only the inner edges -- :not(:first-child) and :not(:last-child) -- so the
   two ends of the street are not vignetted for no reason.

   z-index 7: above the plates, the damage film, the patches and the brush
   canvas, below the hotspots at 8. The visible pins are in .pin-layer above
   the whole viewport, so nothing of theirs is covered. pointer-events none, or
   it would eat the drag that walks the street. */
#rebuild-story .block:not(:first-child)::before,
#rebuild-story .block:not(:last-child)::after {
  content: "";
  position: absolute;
  z-index: 7;
  top: 0;
  bottom: 0;
  width: clamp(32px, 5vw, 84px);
  pointer-events: none;
  background: linear-gradient(90deg, rgba(1, 19, 47, 0.26), rgba(1, 19, 47, 0));
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
  mask-image: linear-gradient(90deg, #000, rgba(0, 0, 0, 0));
  -webkit-mask-image: linear-gradient(90deg, #000, rgba(0, 0, 0, 0));
}
#rebuild-story .block:not(:first-child)::before {
  left: 0;
}
/* The trailing strip is the same figure, turned round. */
#rebuild-story .block:not(:last-child)::after {
  right: 0;
  background: linear-gradient(270deg, rgba(1, 19, 47, 0.26), rgba(1, 19, 47, 0));
  mask-image: linear-gradient(270deg, #000, rgba(0, 0, 0, 0));
  -webkit-mask-image: linear-gradient(270deg, #000, rgba(0, 0, 0, 0));
}
@media (prefers-reduced-motion: reduce) {
  /* Nothing moves here, but a blur that follows a dragged strip is the most
     expensive thing on the page; the haze alone still softens the seam. */
  #rebuild-story .block::before,
  #rebuild-story .block::after {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

#rebuild-story .hotspot {
  position: absolute;
  z-index: 8;
  display: block;
  min-width: 24px;
  min-height: 24px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: transparent;
  color: transparent;
  box-shadow: none;
}
#rebuild-story .hotspot::after {
  content: "";
  position: absolute;
  width: 13px;
  height: 13px;
  right: 4px;
  top: 4px;
  border-radius: 50%;
  background: var(--ca-gold-500);
  border: 2px solid var(--ca-navy-900);
  box-shadow:
    0 0 0 2px var(--ca-paper),
    0 3px 9px rgba(1, 19, 47, 0.55);
  opacity: 0;
  transform: scale(0.4);
  transition:
    opacity 0.2s,
    transform 0.2s;
}
#rebuild-story .debug .hotspot.user-fixed::after {
  opacity: 1;
}
#rebuild-story .hotspot:focus-visible {
  outline: 4px solid var(--ca-gold-500);
  outline-offset: 2px;
  background: rgba(209, 149, 43, 0.14);
}
#rebuild-story .chevron {
  position: absolute;
  z-index: 34;
  top: 64%;
  width: 52px;
  height: 68px;
  border: 2px solid var(--ca-paper);
  background: rgba(1, 19, 47, 0.84);
  color: var(--ca-paper);
  font-size: var(--t-10);
  line-height: 1;
  border-radius: 3px;
  box-shadow: 0 6px 18px rgba(1, 19, 47, 0.3);
}
#rebuild-story .chevron:hover {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
}
#rebuild-story .chevron.left {
  left: 12px;
}
#rebuild-story .chevron.right {
  right: 12px;
}
#rebuild-story .chevron:disabled {
  opacity: 0.26;
  cursor: not-allowed;
}
#rebuild-story .tooltip {
  position: fixed;
  z-index: 80;
  max-width: min(340px, calc(100vw - 24px));
  padding: var(--s-3) var(--s-3) var(--s-3);
  background: var(--inverse);
  color: var(--ink-inverse);
  border-top: 4px solid var(--ca-gold-500);
  border-radius: 3px;
  box-shadow: 0 12px 32px rgba(1, 19, 47, 0.4);
  font: 600 var(--t-5)/1.25 var(--text);
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
  transition:
    opacity 0.12s,
    transform 0.12s;
}
#rebuild-story .tooltip.show {
  opacity: 1;
  transform: none;
}
#rebuild-story .lens {
  position: fixed;
  z-index: 75;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  border: 4px solid var(--ca-gold-500);
  box-shadow:
    0 0 0 2px var(--ca-paper),
    0 12px 30px rgba(1, 19, 47, 0.48);
  background-repeat: no-repeat;
  opacity: 0;
  pointer-events: none;
  transform: scale(0.92);
  transition:
    opacity 0.12s,
    transform 0.12s;
}
#rebuild-story .lens.show {
  opacity: 1;
  transform: scale(1);
}
#rebuild-story dialog.card-dialog {
  width: min(660px, calc(100vw - 24px));
  max-height: min(88vh, 780px);
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: var(--inverse);
  color: var(--ink-inverse);
  box-shadow: 0 24px 80px rgba(1, 19, 47, 0.65);
  overflow: auto;
}
#rebuild-story dialog.card-dialog::backdrop {
  background: rgba(1, 19, 47, 0.76);
  backdrop-filter: blur(5px);
}
#rebuild-story .card-inner {
  padding: clamp(22px, 4vw, 40px);
}
#rebuild-story .close-card {
  float: right;
  width: 44px;
  height: 44px;
  margin: -8px -8px var(--s-2) var(--s-3);
  border: 2px solid var(--ink-inverse);
  border-radius: 3px;
  background: transparent;
  color: var(--ink-inverse);
  font-size: var(--t-9);
  line-height: 1;
}
#rebuild-story .card-office {
  margin: 0 52px var(--s-2) 0;
  color: var(--ca-gold-300);
  font: 600 var(--t-3)/1.2 var(--accent);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
#rebuild-story .card-dialog h2 {
  clear: both;
  margin: 0 0 var(--s-3);
  font: 400 clamp(1.75rem, 4vw, 2.25rem)/1.1 var(--display);
  letter-spacing: -0.005em;
  text-wrap: balance;
}
#rebuild-story .card-does {
  margin: 0 0 var(--s-4);
  color: var(--ink-inverse-2);
  font-size: var(--t-6);
  line-height: 1.6;
}
#rebuild-story .chips {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: 0 0 var(--s-5);
}
#rebuild-story .chip {
  display: inline-flex;
  min-height: 30px;
  align-items: center;
  padding: 0 var(--s-2);
  border-radius: 3px;
  font: 600 var(--t-2)/1 var(--accent);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
#rebuild-story .chip.level-open {
  background: var(--ca-forest);
  color: white;
}
#rebuild-story .chip.level-statutory {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
}
#rebuild-story .chip.level-license {
  background: var(--ca-red-500);
  color: white;
  border: 1px solid white;
}
#rebuild-story .chip.level-experience {
  background: var(--ca-navy-500);
  color: white;
  border: 1px solid var(--ca-paper);
}
#rebuild-story .chip.level-appointed {
  background: var(--ca-plum);
  color: white;
}
#rebuild-story .chip.level-varies {
  background: var(--ca-charcoal);
  color: white;
}
#rebuild-story .chip.fact {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
}
#rebuild-story .card-actions {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  flex-wrap: wrap;
}
#rebuild-story .card-note {
  margin: var(--s-4) 0 0;
  color: var(--ink-inverse-2);
  font-size: var(--t-2);
}
#rebuild-story .payoff-wrap {
  position: absolute;
  z-index: 36;
  right: clamp(16px, 3vw, 44px);
  bottom: clamp(18px, 3vw, 38px);
  width: min(520px, calc(100vw - 32px));
  pointer-events: none;
}
#rebuild-story .payoff {
  position: relative;
  z-index: 1;
  width: 100%;
  padding: var(--s-5);
  background: var(--ca-red-500);
  color: white;
  border: 1px solid white;
  border-radius: 3px;
  box-shadow: 0 18px 55px rgba(1, 19, 47, 0.48);
  opacity: 0;
  transform: translateY(120%);
  pointer-events: none;
  will-change: transform, opacity;
}
#rebuild-story .payoff.show {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
#rebuild-story .payoff::before {
  content: "";
  display: block;
  width: 64px;
  height: 5px;
  margin-bottom: var(--s-4);
  background: var(--ca-gold-500);
}
#rebuild-story .payoff h2 {
  margin: 0 0 var(--s-2);
  font: 400 clamp(1.65rem, 3vw, 2rem)/1.1 var(--display);
}
#rebuild-story .payoff p {
  margin: 0 0 var(--s-4);
  font-size: var(--t-6);
}
#rebuild-story .payoff .btn-primary {
  background: white;
  color: var(--ca-red-500);
}
#rebuild-story .payoff .btn-secondary {
  background: transparent;
}
#rebuild-story .after {
  background: var(--cream);
  color: var(--ink-deep);
  padding: clamp(58px, 8vw, 110px) max(24px, calc((100vw - 1180px) / 2));
  border-top: 8px solid var(--ca-gold-500);
}
#rebuild-story .after .eyebrow {
  color: var(--gold-ink);
}
#rebuild-story .after h2 {
  margin: 0.25em 0 0.3em;
  color: var(--ink);
  font: 400 clamp(2.1rem, 5vw, 3.5rem)/1.1 var(--display);
  letter-spacing: -0.005em;
}
#rebuild-story .after p {
  font-size: var(--t-6);
  line-height: 1.65;
}
#rebuild-story .after .btn-primary {
  background: var(--ca-red-500);
  color: white;
}
#rebuild-story .after .btn-primary:hover {
  background: var(--ca-red-700);
}
#rebuild-story .after .btn-secondary {
  border-color: var(--ink);
  color: var(--ink);
  background: transparent;
}
#rebuild-story .sources {
  margin-top: 70px;
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule);
}
#rebuild-story .sources h3 {
  margin: 0 0 var(--s-3);
  color: var(--ink);
  font-size: var(--t-7);
}
@media (max-width: 800px) {
  #rebuild-story {
    --top-ui: 310px;
  }
  #rebuild-story .hero {
    min-height: 620px;
  }
  #rebuild-story .topbar {
    grid-template-columns: 1fr;
    gap: 7px;
    right: 14px;
    left: 14px;
  }
  #rebuild-story .meter-wrap {
    max-width: none;
  }
  #rebuild-story .utility {
    position: absolute;
    right: 0;
    top: 35px;
    gap: 5px;
  }
  #rebuild-story .utility .btn {
    font-size: var(--t-2);
    min-height: 34px;
    padding: 0 0.7rem;
  }
  #rebuild-story .intro {
    top: 86px;
    left: 18px;
    width: calc(100% - 36px);
  }
  #rebuild-story .intro h1 {
    font-size: clamp(2.55rem, 12vw, 3.55rem);
    max-width: 10ch;
  }
  #rebuild-story .intro p {
    max-width: 38ch;
    font-size: var(--t-6);
    line-height: 1.38;
  }
  #rebuild-story .tabs {
    top: 332px;
    left: 12px;
    right: 12px;
    max-width: none;
    transform: none;
    justify-content: flex-start;
  }
  #rebuild-story .tab {
    padding: 0 var(--s-3);
  }
  #rebuild-story .scroll-hint {
    top: 384px;
    white-space: nowrap;
  }
  #rebuild-story .chevron {
    top: auto;
    bottom: 16px;
    width: 46px;
    height: 52px;
  }
  #rebuild-story .chevron.left {
    left: 10px;
  }
  #rebuild-story .chevron.right {
    right: 10px;
  }
  #rebuild-story .payoff-wrap {
    bottom: 78px;
  }
  #rebuild-story .payoff .card-actions {
    display: grid;
  }
  #rebuild-story .payoff .btn {
    width: 100%;
  }
    #rebuild-story .lens {
    display: none;
  }
}
@media (max-width: 480px) {
  #rebuild-story .intro h1 {
    margin-top: 0.12em;
  }
  #rebuild-story .intro p {
    font-size: var(--t-5);
  }
  #rebuild-story .tabs {
    top: 330px;
  }
  #rebuild-story .tab {
    padding: 0 var(--s-2);
    font-size: var(--t-1);
  }
  #rebuild-story .scroll-hint {
    top: 382px;
    font-size: var(--t-1);
  }
  #rebuild-story .utility {
    top: 34px;
  }
    #rebuild-story .plate-layer {
    bottom: 68px;
  }
  #rebuild-story .card-actions {
    display: grid;
  }
  #rebuild-story .card-actions .btn {
    width: 100%;
  }
  #rebuild-story .chips {
    gap: 6px;
  }
  #rebuild-story .card-inner {
    padding: var(--s-5) var(--s-4) var(--s-5);
  }
  #rebuild-story .card-dialog h2 {
    font-size: var(--t-9);
  }
}
@media (prefers-reduced-motion: reduce) {
  #rebuild-story {
    scroll-behavior: auto;
  }
  #rebuild-story {
    height: auto;
    min-height: 0;
  }
  #rebuild-story .hero {
    position: relative;
    height: 100svh;
  }
  #rebuild-story *,
  #rebuild-story *::before,
  #rebuild-story *::after {
    scroll-behavior: auto !important;
    animation: none !important;
    transition: none !important;
  }
  #rebuild-story .sky-overcast {
    display: none;
  }
  #rebuild-story .sun {
    opacity: 1;
  }
  #rebuild-story .cloud {
    display: none;
  }
  #rebuild-story .payoff.show {
    transform: none;
  }
  #rebuild-story .street-track {
    transition: none;
  }
}

/* Hero layout revisions
   ==========================================================================
   The walk controls, the block names and the meter sit together at the foot,
   so the sky above the street stays clear. */

/* The top bar keeps only the utility buttons now the meter has moved out. */
#rebuild-story .topbar {
  grid-template-columns: minmax(0, 1fr);
}
#rebuild-story .meter-wrap {
  max-width: none;
}

/* 5. Hero copy ranges left, rather than centring inside its column. */
#rebuild-story .intro {
  text-align: left;
}
#rebuild-story .intro h1,
#rebuild-story .intro p {
  margin-left: 0;
  margin-right: auto;
  text-align: left;
}

/* 7. Walk controls and block names, one row, centred at the foot. */
#rebuild-story .street-controls {
  position: absolute;
  z-index: 34;
  left: 50%;
  bottom: clamp(74px, 11vh, 104px);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  max-width: calc(100vw - 24px);
}
#rebuild-story .street-controls .tabs {
  position: static;
  transform: none;
  left: auto;
  top: auto;
  max-width: min(60vw, 540px);
  overflow-x: auto;
  scrollbar-width: none;
}

/* SVG arrows, not the ‹ › characters: those carry heavy, uneven side bearing,
   so no amount of flex centring put them in the middle of the box. */
#rebuild-story .chevron {
  position: static;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  top: auto;
  bottom: auto;
  left: auto;
  right: auto;
  width: var(--ctrl-h);
  height: var(--ctrl-h);
  padding: 0;
  line-height: 1;
}
#rebuild-story .chevron svg {
  width: 22px;
  height: 22px;
  display: block;
}
#rebuild-story .chevron.left,
#rebuild-story .chevron.right {
  position: static;
  left: auto;
  right: auto;
}

/* 2. The meter, centred beneath the controls. */
#rebuild-story .street-meter {
  position: absolute;
  z-index: 34;
  left: 50%;
  bottom: clamp(20px, 4.5vh, 40px);
  transform: translateX(-50%);
  width: min(520px, calc(100vw - 32px));
}
#rebuild-story .street-meter .meter-label {
  justify-content: center;
  gap: var(--s-2);
}

/* 4. A pulsing arrow under the scroll note. */
#rebuild-story .scroll-hint {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
#rebuild-story .hint-arrow {
  width: 15px;
  height: 15px;
  flex: none;
  animation: hint-bob 1.6s ease-in-out infinite;
}
@keyframes hint-bob {
  0%,
  100% {
    transform: translateY(-2px);
    opacity: 0.55;
  }
  50% {
    transform: translateY(3px);
    opacity: 1;
  }
}

@media (max-width: 760px) {
  #rebuild-story .street-controls {
    bottom: auto;
    top: min(52vh, 404px);
    gap: var(--s-1);
  }

  #rebuild-story .street-meter {
    bottom: 14px;
    width: calc(100vw - 24px);
  }
}

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

/* ==========================================================================
   Hero behaviour revisions
   ========================================================================== */

/* The pinned height buys the scroll distance that drives the rebuild and a
   tail so the payoff card is read before the page moves on. PIN_TAIL splits
   the two. */
#rebuild-story {
  height: 380vh;
  min-height: 1900px;
}

/* Everything has to be on screen at once. Short viewports get a tighter stack
   rather than a scrollbar. */
/* Pins below the sticky header and takes exactly what is left of the
   viewport, so the controls and the meter are up on load rather than 66px
   under the fold. */
#rebuild-story .hero {
  top: var(--hdr);
  min-height: 0;
  height: calc(100svh - var(--hdr));
  max-height: calc(100svh - var(--hdr));
}
#rebuild-story .intro {
  top: clamp(64px, 9vh, 96px);
}
#rebuild-story .street-controls {
  bottom: clamp(66px, 9.5vh, 96px);
}
#rebuild-story .street-meter {
  bottom: clamp(16px, 3.5vh, 32px);
}
#rebuild-story .scroll-hint {
  top: auto;
  bottom: clamp(126px, 17vh, 166px);
  transform: translate(-50%, 0);
}
#rebuild-story .scroll-hint.show {
  transform: translate(-50%, 0);
}

@media (max-height: 720px) {
  #rebuild-story .intro h1 {
    font-size: clamp(2rem, 4.4vw, 3rem);
  }
  #rebuild-story .intro p {
    font-size: var(--t-5);
  }
  #rebuild-story .street-controls {
    bottom: 62px;
  }

  #rebuild-story .scroll-hint {
    bottom: 114px;
  }
}

@media (max-height: 600px) {
  #rebuild-story .intro p {
    display: none;
  }
  #rebuild-story .scroll-hint {
    display: none;
  }
}

/* Reduced motion keeps the scene static and lets the page scroll. It has to
   undo the pin completely -- position, top, height, max-height -- or the
   fitted rule above wins on source order. */
@media (prefers-reduced-motion: reduce) {
  #rebuild-story {
    height: auto;
    min-height: 0;
  }
  #rebuild-story .hero {
    position: relative;
    top: auto;
    height: auto;
    min-height: 560px;
    max-height: none;
  }
}

/* Hotspot mode
   ==========================================================================
   Every clickable tile at once. Red sits directly on the navy street
   furniture, so a red outline broke the badge rule and read as an error state.
   Gold is the badge's marker colour, so the tiles wash gold. */

/* The pin: centred in its tile, and shown for every hotspot rather than only
   the ones already repaired. */
/* The tile itself stays invisible: no fill, no outline, no label chip. A
   single gold pin marks each hotspot, centred in its region. */

/* The two hero toggles carry no wording change any more, so their on-state has
   to be visible. Gold fill, navy label: the same inversion the buttons use on
   a navy ground elsewhere. */
#rebuild-story .btn-tertiary[aria-pressed="true"] {
  background: var(--ca-gold-500);
  border-color: var(--ca-gold-500);
  color: var(--ca-navy-900);
}

/* The tooltip now carries the office and what it does, not just the hook. */
#rebuild-story .tooltip {
  display: grid;
  gap: var(--s-1);
}
#rebuild-story .tip-hover {
  font: 600 var(--t-5)/1.25 var(--text);
  color: var(--ink-inverse);
}
#rebuild-story .tip-office {
  font: 600 var(--t-2)/1.2 var(--accent);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ca-gold-500);
}
#rebuild-story .tip-does {
  font: 400 var(--t-3)/1.4 var(--text);
  color: var(--ink-inverse-2);
}

/* The plates sit edge to edge, so a shadow on each drew a dark seam at every
   100vw boundary. One shadow on the strip has no internal edges. */
#rebuild-story .street-track {
  filter: drop-shadow(0 12px 16px rgba(1, 19, 47, 0.22));
}

/* Tooltip copy ranges left; it was inheriting the centred alignment of the
   scene around it. */
#rebuild-story .tooltip {
  text-align: left;
  justify-items: start;
}
#rebuild-story .tip-hover,
#rebuild-story .tip-office,
#rebuild-story .tip-does {
  text-align: left;
}

/* The pitch a finger opened
   ==========================================================================
   A cursor closes this by leaving. A finger cannot, so a tap-opened pitch
   carries its own close. The sheet stays transparent to a tap -- only the
   button is live -- so a pitch lying over the street does not swallow the
   taps meant for the pins under it. */
#rebuild-story .tooltip.is-stuck {
  padding-right: 44px;
}
#rebuild-story .tip-close {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 2.5.5's 44, which is the whole reason this exists. */
  width: 44px;
  height: 44px;
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  font: 400 22px/1 var(--text);
  color: var(--ink-inverse-3);
  pointer-events: auto;
  cursor: pointer;
}
#rebuild-story .tip-close:hover {
  color: var(--ca-gold-500);
}
#rebuild-story .tip-close:focus-visible {
  outline: 3px solid var(--ca-focus-dark);
  outline-offset: -3px;
}

/* Payoff rays
   ==========================================================================
   The badge's rays at a fraction of the strength, masked to a ring so the
   spokes only appear around the card. Gold over Torch Red would muddy both,
   and the badge never lets them touch. */
#rebuild-story .payoff-rays {
  position: absolute;
  z-index: 0;
  left: 50%;
  top: 50%;
  width: 210%;
  height: 260%;
  transform: translate(-50%, -50%) scale(0.88);
  background: repeating-conic-gradient(
    from 0deg at 50% 50%,
    var(--ca-gold-500) 0deg 0.45deg,
    transparent 0.45deg 7.5deg
  );
  /* An ellipse, not a circle: the card is far wider than it is tall, so a
     circular hole clears its top and bottom but cuts across its sides. */
  -webkit-mask-image: radial-gradient(
    ellipse 60% 52% at 50% 50%,
    transparent 46%,
    #000 53%,
    transparent 69%
  );
  mask-image: radial-gradient(
    ellipse 60% 52% at 50% 50%,
    transparent 46%,
    #000 53%,
    transparent 69%
  );
  opacity: 0;
  pointer-events: none;
}

/* A burst rather than a fade: the spokes throw out past their resting size,
   then settle back. :has() drives them off the card's own show state. */
@keyframes payoff-rays-in {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.5);
  }
  40% {
    opacity: 0.92;
    transform: translate(-50%, -50%) scale(1.13);
  }
  70% {
    opacity: 0.66;
    transform: translate(-50%, -50%) scale(0.97);
  }
  100% {
    opacity: 0.58;
    transform: translate(-50%, -50%) scale(1);
  }
}

#rebuild-story .payoff-wrap:has(.payoff.show) .payoff-rays {
  animation: payoff-rays-in 1200ms cubic-bezier(0.2, 0.75, 0.3, 1) 220ms both;
}

@media (prefers-reduced-motion: reduce) {
  #rebuild-story .payoff-wrap:has(.payoff.show) .payoff-rays {
    animation: none;
    opacity: 0.58;
    transform: translate(-50%, -50%) scale(1);
  }
}

/* "Shape what's next." holds on one line once the hero is wide enough.
   Forcing it below that pushes the headline past the edge. */
@media (min-width: 1100px) {
  #rebuild-story .intro {
    width: min(860px, calc(100% - 36px));
  }
  #rebuild-story .intro h1 {
    max-width: none;
  }
}

/* Hero calls to action. The intro block is pointer-events:none so the street
   behind it stays clickable, so the buttons have to opt back in. */
#rebuild-story .intro-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-5);
  pointer-events: auto;
}

@media (max-height: 720px) {
  #rebuild-story .intro-cta {
    margin-top: var(--s-4);
  }
  #rebuild-story .intro-cta .btn {
    min-height: 40px;
    padding: 0 var(--s-4);
  }
}

@media (max-width: 560px) {
  #rebuild-story .intro-cta {
    gap: var(--s-2);
  }
  #rebuild-story .intro-cta .btn {
    width: 100%;
  }
}

/* Patches are rectangles cut from the restored plate and laid over the
   decline, so their edges showed as boxes. Two linear masks intersected
   feather all four sides while keeping the shape rectangular. */
#rebuild-story .patch {
  -webkit-mask-image:
    linear-gradient(
      to right,
      transparent 0,
      #000 9%,
      #000 91%,
      transparent 100%
    ),
    linear-gradient(
      to bottom,
      transparent 0,
      #000 9%,
      #000 91%,
      transparent 100%
    );
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(
      to right,
      transparent 0,
      #000 9%,
      #000 91%,
      transparent 100%
    ),
    linear-gradient(
      to bottom,
      transparent 0,
      #000 9%,
      #000 91%,
      transparent 100%
    );
  mask-composite: intersect;
}

/* Hotspot pins
   ==========================================================================
   .viewport carries z-index:2, so nothing inside it rises above the atmosphere
   layers after it. The overcast at z-18 is a multiply wash, which turned the
   gold pins olive. In hotspot mode the street lifts above it and the glow, and
   stays below the top scrim, which is still doing legibility work. */
/* The street stays under the overcast, as it should. The pins live in
   their own layer above it instead. */

/* A ring of short gold spokes, thrown out from behind the pin on hover. Same
   idea as the payoff rays, at a fifteenth of the size. */

@media (prefers-reduced-motion: reduce) {
}

/* Pin layer
   ==========================================================================
   The street sits under the overcast and keeps its night hue; the pins do not.
   Drawn here, a sibling of .viewport above the weather, mirroring the street
   track's transform so they travel with their blocks. */
#rebuild-story .pin-layer {
  position: absolute;
  inset: 0;
  z-index: 21;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 200ms ease;
}

#rebuild-story .debug .pin-layer {
  opacity: 1;
  visibility: visible;
}

#rebuild-story .pin-track {
  position: absolute;
  inset: 0 auto 0 0;
  height: 100%;
  display: flex;
}

#rebuild-story .pin-block {
  position: relative;
  flex: 0 0 var(--block-w, 100vw);
  height: 100%;
}
#rebuild-story .pin-plate {
  overflow: visible;
  background: none;
}

#rebuild-story .pin {
  position: absolute;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  background: var(--ca-gold-300);
  border: 2px solid var(--ca-navy-900);
  box-shadow:
    0 0 0 2px var(--ca-paper),
    0 3px 9px rgba(1, 19, 47, 0.55);
  transition:
    transform 160ms ease,
    background 160ms ease;
}

#rebuild-story .pin.is-hover {
  background: var(--ca-gold-300);
  transform: scale(1.12);
}

/* Rays: 16 spokes at 5.5deg, which measures roughly 1.3px rising to 2.4px at
   this radius. Anything thinner renders as a haze rather than as lines. */
#rebuild-story .pin::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 54px;
  height: 54px;
  transform: translate(-50%, -50%) scale(0.55);
  background: repeating-conic-gradient(
    from 0deg at 50% 50%,
    var(--ca-gold-500) 0deg 5.5deg,
    transparent 5.5deg 22.5deg
  );
  -webkit-mask-image: radial-gradient(
    circle,
    transparent 50%,
    #000 58%,
    #000 74%,
    transparent 94%
  );
  mask-image: radial-gradient(
    circle,
    transparent 50%,
    #000 58%,
    #000 74%,
    transparent 94%
  );
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 240ms ease,
    transform 420ms cubic-bezier(0.2, 0.8, 0.3, 1);
}

#rebuild-story .pin.is-hover::before {
  opacity: 0.9;
  transform: translate(-50%, -50%) scale(1);
}

@media (prefers-reduced-motion: reduce) {
  #rebuild-story .pin,
  #rebuild-story .pin::before {
    transition: none;
  }
  #rebuild-story .pin.is-hover::before {
    transform: translate(-50%, -50%) scale(1);
  }
}

/* The section is class="hero", the same name the site's own component uses, so
   site.css's .hero{text-align:center} was leaking in. Reset once for the
   whole scene rather than chased element by element. */
#rebuild-story .hero {
  text-align: left;
  padding-block: 0;
}

/* Right-hand progress rail
   ==========================================================================
   A vertical rail at the right edge, titled with whichever block the reader is
   standing in, so the scene is always named. Appended last, so it supersedes
   the earlier bottom-centre placement. */
#rebuild-story {
  --rail-gap: clamp(16px, 3vw, 46px);
  --rail-w: 42px;
  --rail-mid: 46%;
}

#rebuild-story .street-meter {
  left: auto;
  right: var(--rail-gap);
  top: var(--rail-mid);
  bottom: auto;
  width: auto;
  transform: translateY(-50%);
}

/* The label's two spans belong in different cells of the rail, so the wrapper
   steps out of the box tree and lets the grid place them. Type and colour
   still inherit through. */
#rebuild-story .street-meter .meter-label {
  display: contents;
}
#rebuild-story .street-meter .meter-wrap {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-areas:
    "pct pct"
    "bar name";
  align-items: center;
  justify-items: center;
  gap: 10px 9px;
  max-width: none;
}
#rebuild-story .street-meter #meter-percent {
  grid-area: pct;
  color: var(--ca-gold-300);
  font-variant-numeric: tabular-nums;
}
#rebuild-story .street-meter #meter-scene {
  grid-area: name;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  letter-spacing: 0.18em;
  white-space: nowrap;
}
#rebuild-story .street-meter .meter {
  grid-area: bar;
  width: 10px;
  height: min(38vh, 300px);
}
/* Fills downward: empty at the top, complete at the foot, so the rail reads
   the same direction as the scroll that drives it. */
#rebuild-story .street-meter .meter-fill {
  /* --bp is the active block's own tally; --p stays the global scroll, which
     the sky and the sun still ride on. */
  transform: scaleY(var(--bp, 0));
  transform-origin: top center;
  background: linear-gradient(180deg, var(--ca-gold-500), #f3c758);
}

#rebuild-story .scroll-hint {
  left: auto;
  bottom: auto;
  top: var(--rail-mid);
  right: calc(var(--rail-gap) + var(--rail-w) + 12px);
  white-space: nowrap;
  transform: translate(6px, -50%);
}
#rebuild-story .scroll-hint.show {
  transform: translate(0, -50%);
}

/* Short viewports: lift the rail and shorten the bar so it stays clear of the
   payoff card and the Quick Book tab, which both sit in the bottom-right. */
@media (max-height: 780px) {
  #rebuild-story {
    --rail-mid: 40%;
  }
}
@media (max-height: 640px) {
  #rebuild-story {
    --rail-mid: 34%;
  }
  #rebuild-story .street-meter .meter {
    height: min(30vh, 300px);
  }
}

/* Hero intro panel
   ==========================================================================
   The headline, lead and calls to action sit over a busy photograph that keeps
   changing as the reader walks, so they get a navy panel rather than a
   text-shadow. Same vocabulary as .tabs, so the furniture reads as one set. */
#rebuild-story .intro {
  padding: clamp(18px, 2.4vw, 30px) clamp(20px, 2.6vw, 34px);
  background: rgba(1, 19, 47, 0.86);
  border: 1px solid rgba(248, 248, 248, 0.26);
  border-radius: var(--r-2);
  box-shadow: 0 14px 40px rgba(1, 19, 47, 0.42);
}
/* The panel carries the contrast now. */
#rebuild-story .intro p {
  text-shadow: none;
}

/* Intro collapse
   ==========================================================================
   LEAD_IN in rebuild.js reserves the head of the pinned scroll for this: the
   lead and the buttons fold away, leaving the eyebrow and the headline, and
   only then does the first repair start. Heights come from measureIntro(),
   which reads the real line box, so the panel never holds empty space. */
#rebuild-story .intro p,
#rebuild-story .intro-cta {
  overflow: hidden;
  /* rebuild.js sets these in whole line boxes, so each step is one line leaving:
     quick enough to keep up with the scroll, slow enough not to blink out. */
  transition:
    max-height 150ms ease,
    margin-top 150ms ease,
    opacity 150ms ease;
}
/* Once folded the buttons are invisible, so take them out of the tab order
   and out of the way of the street behind them. */
#rebuild-story .hero.intro-collapsed .intro-cta {
  pointer-events: none;
  visibility: hidden;
}

@media (prefers-reduced-motion: reduce) {
  #rebuild-story .intro p,
  #rebuild-story .intro-cta {
    transition: none;
  }
}

/* Dismissing the intro
   ==========================================================================
   The scroll fold leaves the eyebrow and the headline; the X takes the panel
   entirely. Fade, lift and a slight squash rather than an animated height: the
   headline wraps to a different number of lines at different widths, so any
   max-height would be wrong somewhere. */
#rebuild-story .intro {
  transform-origin: top left;
  transition:
    opacity 260ms ease,
    transform 300ms cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 300ms;
}
#rebuild-story .hero.intro-dismissed .intro {
  opacity: 0;
  transform: translateY(-14px) scaleY(0.92);
  visibility: hidden;
  pointer-events: none;
}

#rebuild-story .intro-close {
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: 1px solid rgba(248, 248, 248, 0.3);
  border-radius: var(--r-1);
  color: var(--ink-inverse-2);
  cursor: pointer;
  /* .intro is pointer-events:none so the street stays draggable behind it. */
  pointer-events: auto;
  transition:
    background-color 140ms ease,
    color 140ms ease,
    border-color 140ms ease;
}
#rebuild-story .intro-close svg {
  width: 16px;
  height: 16px;
}
#rebuild-story .intro-close:hover {
  background: rgba(248, 248, 248, 0.14);
  border-color: var(--ca-paper);
  color: var(--ca-paper);
}
#rebuild-story .intro-close:focus-visible {
  outline: 3px solid var(--ca-gold-500);
  outline-offset: 2px;
}
/* Keep the eyebrow clear of the button. */
#rebuild-story .intro .eyebrow {
  padding-right: 52px;
}

@media (prefers-reduced-motion: reduce) {
  #rebuild-story .intro {
    transition: none;
  }
  #rebuild-story .hero.intro-dismissed .intro {
    transform: none;
  }
}

/* At full collapse the panel holds only the eyebrow and the headline, so the
   headline gets the whole width and the break comes out: one compact line. */
#rebuild-story .hero.intro-collapsed .intro h1 {
  max-width: none;
}

/* Frozen regions
   ==========================================================================
   Same crop geometry as .patch but never animated: above the decline image for
   the whole sequence. Feathered harder, because the plates are lit
   differently and the crop is small. */
#rebuild-story .frozen {
  position: absolute;
  /* Above the patches and the brush canvas, which both paint the restored plate
     and would bring the garbled lettering back; below the hotspots at 8, so
     nothing is stolen from the pins. */
  z-index: 6;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image:
    linear-gradient(
      to right,
      transparent 0,
      #000 6%,
      #000 94%,
      transparent 100%
    ),
    linear-gradient(
      to bottom,
      transparent 0,
      #000 5%,
      #000 95%,
      transparent 100%
    );
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(
      to right,
      transparent 0,
      #000 6%,
      #000 94%,
      transparent 100%
    ),
    linear-gradient(
      to bottom,
      transparent 0,
      #000 5%,
      #000 95%,
      transparent 100%
    );
  mask-composite: intersect;
}
#rebuild-story .frozen img {
  position: absolute;
  max-width: none;
  pointer-events: none;
  user-select: none;
}

/* Payoff calls to action
   ==========================================================================
   Rays first, then the two buttons one after the other. `both` holds them at
   the 0% frame through the delay, so nothing flashes before its turn. */
@keyframes payoff-btn-pop {
  0% {
    opacity: 0;
    transform: translateY(10px) scale(0.9);
  }
  62% {
    opacity: 1;
    transform: translateY(0) scale(1.05);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
#rebuild-story .payoff-wrap:has(.payoff.show) .card-actions .btn {
  animation: payoff-btn-pop 380ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}
#rebuild-story .payoff-wrap:has(.payoff.show) .card-actions .btn:first-child {
  animation-delay: 820ms;
}
#rebuild-story .payoff-wrap:has(.payoff.show) .card-actions .btn:last-child {
  animation-delay: 980ms;
}

@media (prefers-reduced-motion: reduce) {
  #rebuild-story .payoff-wrap:has(.payoff.show) .card-actions .btn {
    animation: none;
  }
}

/* Walk controls: one row, one height
   ==========================================================================
   The arrows and the block list are one control group, so they share a height
   token and the same 2px paper outline. The list's 1px 30% white border read
   as a different weight between two solid ones. */
#rebuild-story {
  --ctrl-h: 52px;
}

#rebuild-story .street-controls .tabs {
  height: var(--ctrl-h);
  align-items: center;
  padding: var(--s-1);
  border: 2px solid var(--ink-inverse);
  border-radius: 3px;
}
#rebuild-story .street-controls .tab {
  min-height: 40px;
}

@media (max-width: 760px) {
  #rebuild-story {
    --ctrl-h: 44px;
  }
  #rebuild-story .street-controls .tabs {
    padding: var(--s-0);
  }
  #rebuild-story .street-controls .tab {
    min-height: 34px;
  }
  #rebuild-story .chevron svg {
    width: 19px;
    height: 19px;
  }
}
@media (max-height: 720px) {
  #rebuild-story {
    --ctrl-h: 44px;
  }
  #rebuild-story .street-controls .tabs {
    padding: var(--s-0);
  }
  #rebuild-story .street-controls .tab {
    min-height: 34px;
  }
  #rebuild-story .chevron svg {
    width: 19px;
    height: 19px;
  }
}

/* The meter moved to the right-hand rail, which freed the foot of the hero, so
   the walk controls drop into it rather than floating in mid-air. */
#rebuild-story .street-controls {
  bottom: clamp(20px, 4vh, 40px);
}
@media (max-height: 720px) {
  #rebuild-story .street-controls {
    bottom: 18px;
  }
}

/* At full collapse only the headline's descender reaches the bottom padding,
   so equal padding reads as a deeper gap below: 51px from the baseline
   against 34px above the eyebrow's caps. */
#rebuild-story .hero.intro-collapsed .intro {
  padding-bottom: clamp(11px, 1.75vw, 22px);
}
#rebuild-story .hero.intro-collapsed .intro h1 {
  margin-bottom: 0;
  white-space: nowrap;
  /* Alfa Slab One sets "Shape What's Next." in 10.4em, so under a tenth of the
     panel per em the line lands inside it. Measured against the panel, not the
     viewport, so it holds at every width rather than at guessed steps. */
  font-size: min(clamp(2.65rem, 5.8vw, 4.75rem), 9.2cqi);
}
#rebuild-story .hero.intro-collapsed .intro h1 br {
  display: none;
}
/* The panel is the query container the headline is sized against. It has an
   explicit width at every breakpoint, so containing its inline size changes
   nothing about the layout. */
#rebuild-story .intro {
  container-type: inline-size;
}
/* So the size settles rather than snapping as the fold completes. */
#rebuild-story .intro h1 {
  transition: font-size 220ms var(--ca-ease);
}
@media (prefers-reduced-motion: reduce) {
  #rebuild-story .intro h1 {
    transition: none;
  }
}

/* A clear 25px above the headline, rather than the .16em it inherited, which
   scaled with the type and closed up as the h1 shrank on narrow screens. */
#rebuild-story .intro h1 {
  margin-top: var(--s-5);
}

/* Folding the intro by hand
   ==========================================================================
   Quieter than the dismiss X beside it: a chevron that turns over, no border
   until reached for. The X removes the panel; this only closes the text. */
#rebuild-story .intro-fold {
  position: absolute;
  top: var(--s-2);
  right: calc(var(--s-2) + 40px + var(--s-1));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-1);
  color: var(--ink-inverse-2);
  cursor: pointer;
  /* .intro is pointer-events:none so the street stays draggable behind it. */
  pointer-events: auto;
  transition:
    background-color 140ms ease,
    color 140ms ease,
    border-color 140ms ease;
}
#rebuild-story .intro-fold svg {
  width: 18px;
  height: 18px;
  transition: rotate 260ms cubic-bezier(0.4, 0, 0.2, 1);
}
#rebuild-story .intro-fold:hover {
  background: rgba(248, 248, 248, 0.12);
  border-color: rgba(248, 248, 248, 0.3);
  color: var(--ca-paper);
}
#rebuild-story .intro-fold:focus-visible {
  outline: 3px solid var(--ca-gold-500);
  outline-offset: 2px;
}
/* Points down to close, up to open, so the chevron always shows the way out. */
#rebuild-story .intro-fold[aria-expanded="false"] svg {
  rotate: 180deg;
}

/* Two controls now sit in the corner, so the eyebrow needs the room for both. */
#rebuild-story .intro .eyebrow {
  padding-right: 104px;
}

@media (prefers-reduced-motion: reduce) {
  #rebuild-story .intro-fold svg {
    transition: none;
  }
}

/* The payoff card clears the walk controls
   ==========================================================================
   Positioned independently, nothing held them apart: card bottom-right,
   controls bottom-centre, and on a narrow viewport the card is nearly full
   width, so it covered the scene tabs. The card's foot is derived from where
   the controls actually are. */
#rebuild-story{--ctrl-bottom:clamp(20px,4vh,40px)}
#rebuild-story .street-controls{bottom:var(--ctrl-bottom)}
#rebuild-story .payoff-wrap{
  bottom:calc(var(--ctrl-bottom) + var(--ctrl-h) + var(--s-4));
}

/* Above 1220 they sit on one line: the card's foot drops to the controls' own
   and the controls come off centre. Below that they cannot both fit -- 520
   plus 575 needs 1180 before the gaps -- so the stacking above stands. */
@media (min-width: 1220px){
  #rebuild-story .hero:has(.payoff.show) .payoff-wrap{
    bottom:var(--ctrl-bottom);
  }
  #rebuild-story .hero:has(.payoff.show) .street-controls{
    left:clamp(16px,3vw,44px);
    transform:none;
  }
}
@media (max-height:720px){
  #rebuild-story{--ctrl-bottom:18px}
}

/* Phone landscape
   ==========================================================================
   844x390 leaves the hero 324px. The portrait layout stacks the intro above
   the payoff card, which needs height between them and there is none, so they
   sit side by side and the card is inset past the meter rail. */
@media (orientation: landscape) and (max-height: 520px) {
  #rebuild-story .intro{
    top: clamp(28px, 6vh, 52px);
    width: min(40%, 400px);
    padding: var(--s-3) var(--s-4);
  }
  #rebuild-story .intro h1{
    font-size: clamp(1.375rem, 3vw, 1.875rem);
    margin-top: var(--s-3);
  }
  #rebuild-story .intro .eyebrow{ font-size: var(--t-1) }

  #rebuild-story .payoff-wrap{
    width: min(38%, 360px);
    /* clear of the rail, the same offset the scroll note uses */
    right: calc(var(--rail-gap) + var(--rail-w) + var(--s-4));
  }
  #rebuild-story .payoff{ padding: var(--s-4) }
  #rebuild-story .payoff h2{ font-size: var(--t-7) }
  #rebuild-story .payoff p{ font-size: var(--t-3); margin-bottom: var(--s-3) }

  /* The rail keeps its column but stops reaching for the full height. */
  #rebuild-story{ --rail-mid: 42% }
  #rebuild-story .street-meter .meter{ height: min(34vh, 150px) }
}

/* Phone portrait
   ==========================================================================
   The intro panel is 91% of a 430px screen, so anything else over the scene
   lands on it. Not a z-index problem: the meter rail, the scroll note and the
   utility row were simply put in the same place. */
@media (orientation: portrait) and (max-width: 640px) {
  #rebuild-story{
    /* The plate is scaled to fill the hero, which makes it wider than the
       phone: the street runs off both sides and is dragged into view. */
    --block-fill: 1;

    --meter-h: 44px;
    --stack-ctrl: calc(var(--s-3) + env(safe-area-inset-bottom, 0px));
    --stack-meter: calc(var(--stack-ctrl) + var(--ctrl-h) + var(--s-3));
    --stack-hint: calc(var(--stack-meter) + var(--meter-h) + var(--s-2));
  }

  /* The art now runs to the top of the hero, so everything at the foot sits on
     street rather than on sky. A scrim to read against, matched to the top. */
  #rebuild-story .hero::after{
    content: "";
    position: absolute;
    z-index: 3;
    inset: auto 0 0;
    height: min(36vh, 280px);
    background: linear-gradient(
      0deg,
      rgba(1, 19, 47, .92),
      rgba(1, 19, 47, .60) 46%,
      transparent
    );
    pointer-events: none;
  }

  /* The rail lies down and runs the width: name, bar, percentage. */
  #rebuild-story .street-meter{
    left: 50%; right: auto; top: auto;
    bottom: var(--stack-meter);
    transform: translateX(-50%);
    width: calc(100vw - 2 * var(--gutter));
  }
  #rebuild-story .street-meter .meter-wrap{
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "name bar pct";
    align-items: center;
    gap: var(--s-3);
  }
  #rebuild-story .street-meter #meter-scene{
    writing-mode: horizontal-tb;
    letter-spacing: .12em;
  }
  #rebuild-story .street-meter .meter{ width: auto; height: 10px }
  #rebuild-story .street-meter .meter-fill{
    transform: scaleX(var(--bp, 0));
    transform-origin: left center;
    background: linear-gradient(90deg, var(--ca-gold-500), #f3c758);
  }

  #rebuild-story .street-controls{
    top: auto;
    bottom: var(--stack-ctrl);
  }
  /* The tabs get the width between the arrows rather than 60vw of a phone. */
  #rebuild-story .street-controls .tabs{ max-width: none; flex: 1 1 auto }

  #rebuild-story .scroll-hint{
    left: 50%; right: auto; top: auto;
    bottom: var(--stack-hint);
    transform: translate(-50%, 6px);
  }
  #rebuild-story .scroll-hint.show{ transform: translate(-50%, 0) }

  /* Clear of the whole stack, not just the controls. */
  #rebuild-story .payoff-wrap{
    bottom: calc(var(--stack-hint) + var(--s-6));
    width: calc(100vw - 2 * var(--gutter));
    right: var(--gutter);
  }

  /* Below the utility row, which sits under the notch and wraps on a phone. */
  #rebuild-story .intro{ top: clamp(150px, 19vh, 190px) }
}

/* On a shorter phone the panel is taller than its space: at 375x667 it wants
   457px of a 295px gap. The lead scales worst, six lines of it, and the scroll
   fold drops it first anyway. The headline comes down with it; the eyebrow,
   headline and both buttons stay. */
@media (orientation: portrait) and (max-width: 640px) and (max-height: 860px) {
  #rebuild-story .intro{
    top: clamp(140px, 17vh, 170px);
    padding: var(--s-3) var(--s-4);
  }
  #rebuild-story .intro h1{ font-size: clamp(1.75rem, 9vw, 2.5rem) }
  #rebuild-story .intro p{ display: none }
}

/* The floor: 320x568 leaves the hero 502px and the panel still wants more.
   Eyebrow down a step, headline eased again, buttons to 36px -- above the 24px
   target minimum. */
@media (orientation: portrait) and (max-width: 640px) and (max-height: 620px) {
  #rebuild-story .intro{ top: clamp(118px, 15vh, 140px) }
  #rebuild-story .intro .eyebrow{ font-size: var(--t-1) }
  #rebuild-story .intro h1{ font-size: clamp(1.5rem, 8vw, 2rem) }
  #rebuild-story .intro-cta{ margin-top: var(--s-4) }
  #rebuild-story .intro-cta .btn{ min-height: 36px }
}
