/* ============================================================
   Portal preview — the then/now scrub without the camera.
   Same layer order and gesture the live portal will use, so the
   feel can be reviewed before the camera work lands.
   ============================================================ */

.portal-page {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: #000;
  color: #fff;
}

.stage {
  position: absolute;
  inset: 0;
  touch-action: none;   /* the vertical drag is ours, not the scroller's */
  cursor: ew-resize;
}

.stage .layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-select: none;
  user-select: none;
}

#cam-feed { z-index: 1; background: #000; }
#now-img  { z-index: 1; }
#then-vid { z-index: 2; }

/* ---------- Camera gate ---------- */

.cam-gate {
  position: absolute;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  padding: max(24px, var(--safe-left));
  background: radial-gradient(120% 90% at 50% 30%, #241d16, #0b0907 70%);
  transition: opacity .45s ease;
}
.cam-gate.gone { opacity: 0; pointer-events: none; }

.cam-gate-inner {
  max-width: 340px;
  text-align: center;
  display: grid;
  gap: 14px;
  justify-items: center;
}

.cam-gate-mark {
  width: 52px; height: 52px;
  color: var(--brass);
}
.cam-gate-mark svg { width: 100%; height: 100%; }

.cam-gate-inner h1 {
  font-size: 25px;
  color: #f7f2e8;
}

.cam-gate-lede {
  font-size: 14.5px;
  line-height: 1.55;
  color: rgba(247, 242, 232, .72);
}

.cam-gate-note {
  font-size: 11.5px;
  color: rgba(247, 242, 232, .45);
}

.preview-flag.live {
  background: color-mix(in srgb, var(--teal) 38%, transparent);
  color: #baf5ec;
}

/* ---------- Top bar ---------- */

.portal-top {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: calc(10px + var(--safe-top)) max(12px, var(--safe-left)) 14px max(12px, var(--safe-right));
  background: linear-gradient(180deg, rgba(0,0,0,.62), transparent);
  transition: opacity .3s ease;
}

.portal-top .icon-btn { color: #fff; flex: none; }
.portal-top .icon-btn:active { background: rgba(255,255,255,.16); }

.portal-title {
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}
.portal-title .name {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.portal-title .era {
  font-size: 12px;
  color: rgba(255,255,255,.66);
}

.preview-flag {
  margin-left: auto;
  flex: none;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(255,255,255,.16);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* ---------- Scrub ---------- */

.portal-bottom {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 10;
  padding: 28px max(16px, var(--safe-left)) calc(16px + var(--safe-bottom)) max(16px, var(--safe-right));
  background: linear-gradient(0deg, rgba(0,0,0,.66), transparent);
  transition: opacity .3s ease;
}

.scrub-card {
  max-width: 460px;
  margin: 0 auto;
  padding: 13px 16px 8px;
  border-radius: var(--radius-lg);
  background: rgba(22, 19, 15, .52);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255,255,255,.13);
}

.scrub-labels {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 7px;
}
.scrub-labels .then { color: var(--brass-bright); }
.scrub-labels .now { color: rgba(255,255,255,.62); }

.scrub {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 26px;
  background: none;
}
.scrub::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brass), rgba(255,255,255,.3));
}
.scrub::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brass), rgba(255,255,255,.3));
}
.scrub::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px; height: 22px;
  margin-top: -9px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,.5);
}
.scrub::-moz-range-thumb {
  width: 22px; height: 22px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,.5);
}

.drag-hint {
  text-align: center;
  font-size: 11.5px;
  color: rgba(255,255,255,.5);
  margin-top: 2px;
  transition: opacity .4s ease;
}

.chrome-hidden { opacity: 0; pointer-events: none; }

/* ---------- Provenance ----------
   On the dark stage the chip needs its own light treatment; the shared
   .prov-chip colours are tuned for paper. */

.cam-gate-prov {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  max-width: 320px;
  font-size: 12.5px;
  line-height: 1.5;
  color: rgba(255, 255, 255, .62);
}

.portal-page .prov-chip {
  border-color: rgba(212, 171, 106, .55);
  background: rgba(212, 171, 106, .16);
  color: var(--brass-bright);
}

/* Anchored under the title block, top-left, so it is in the same glance as
   the building name and the Live/Photo flag. It rides the chrome fade: the
   visitor can clear the view deliberately, but nothing clears it for them. */
.prov-badge {
  position: absolute;
  z-index: 12;
  left: max(12px, var(--safe-left));
  top: calc(58px + var(--safe-top));
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 2px;
  transition: opacity .3s ease;
}
.prov-badge:active { transform: scale(.97); }

.prov-sheet {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: end center;
  padding: max(16px, var(--safe-left));
  padding-bottom: calc(24px + var(--safe-bottom));
  background: rgba(0, 0, 0, .55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.prov-sheet[hidden] { display: none; }

.prov-sheet-inner {
  display: grid;
  justify-items: start;
  gap: 12px;
  width: 100%;
  max-width: 420px;
  padding: 20px;
  border-radius: var(--radius-lg);
  background: #221d17;
  box-shadow: 0 -8px 40px rgba(0, 0, 0, .6);
}
.prov-sheet-inner p {
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, .8);
}
.prov-sheet-inner .btn-ghost {
  width: 100%;
  color: #fff;
  border-color: rgba(255, 255, 255, .28);
}

/* ---------- Collapsed scrub ----------
   The card sits right where the street life is in most of this footage,
   so it retreats on its own once you've seen it. Dragging on the picture
   still works while it's away — the ring tracks your position. */

/* The card doesn't slide away and back — it opens out of the circle.
   `clip-path` rather than a scale transform, because scaling would squash
   the label row and the slider on the way in and out; clipping reveals the
   control already at its final size, so the only thing that moves is the
   shape itself. The collapsed inset is a 44px round window pinned to the
   bottom-right, which is exactly the FAB's footprint — expanding therefore
   reads as that circle elongating leftward and growing open. */
.scrub-card {
  clip-path: inset(0 0 0 0 round var(--radius-lg));
  transition: clip-path .46s cubic-bezier(.32, .72, 0, 1),
              opacity .2s ease .06s;
}

body.scrub-collapsed .scrub-card {
  clip-path: inset(calc(100% - 44px) 0 0 calc(100% - 44px) round 22px);
  opacity: 0;
  pointer-events: none;
  transition: clip-path .4s cubic-bezier(.4, 0, .6, 1),
              opacity .18s ease .16s;
}
body.scrub-collapsed .portal-bottom {
  background: none;
  pointer-events: none;
}

/* Nothing to clip open on a viewport wide enough that the card stops
   touching the right edge — the two shapes would no longer be in the same
   place. Fall back to the plain slide there. */
@media (min-width: 520px) {
  .scrub-card,
  body.scrub-collapsed .scrub-card {
    clip-path: none;
    transition: transform .5s cubic-bezier(.32, .72, 0, 1), opacity .32s ease;
  }
  body.scrub-collapsed .scrub-card { transform: translateY(150%); }
}
/* Collapsed, the two controls read as one stacked pair in the corner:
   same size, same right edge, same treatment, 12px apart. */
body.scrub-collapsed .sound-btn {
  bottom: calc(74px + var(--safe-bottom));
}

.scrub-fab {
  position: absolute;
  z-index: 12;
  /* Deliberately the same edge offsets as .portal-bottom's padding, so the
     circle sits exactly on the card's bottom-right corner. The clip-path
     morph above depends on those two rectangles coinciding. */
  right: max(16px, var(--safe-right));
  bottom: calc(16px + var(--safe-bottom));
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(22, 19, 15, .5);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, .14);
  color: #fff;
  /* Leaving: fade out fast and hold its size. Shrinking away would fight the
     card growing out of the same spot — two things moving where the eye
     should read one. Arriving is a spring, handled by the keyframes below. */
  opacity: 0;
  pointer-events: none;
  transition: opacity .13s ease, background-color .2s ease;
}
body.scrub-collapsed .scrub-fab {
  /* The resting state is declared outright, and the spring is only an
     entrance on top of it. With `animation: … both` doing the work instead,
     a tab whose animations are frozen — backgrounded, or reduced-motion —
     held the keyframe's `from` value and left the button invisible at 35%
     scale with no way back. */
  opacity: 1;
  transform: scale(1);
  pointer-events: auto;
  animation: fab-pop .42s cubic-bezier(.34, 1.4, .64, 1);
}

@keyframes fab-pop {
  from { transform: scale(.35); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}
.scrub-fab:active { background: rgba(22, 19, 15, .72); }

/* The ring sits just outside the button's own border so the two controls
   still read as the same size. */
.scrub-fab .fab-ring {
  position: absolute;
  inset: -3px;
  width: calc(100% + 6px);
  height: calc(100% + 6px);
  transform: rotate(-90deg);
  overflow: visible;
}
.fab-track {
  fill: none;
  stroke: rgba(255, 255, 255, .18);
  stroke-width: 2;
}
.fab-fill {
  fill: none;
  stroke: var(--brass-bright);
  stroke-width: 2;
  stroke-linecap: round;
  /* r=19 → circumference ≈ 119.38 */
  stroke-dasharray: 119.38;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset .12s linear;
}

.scrub-fab .fab-glyph {
  position: relative;
  width: 20px;
  height: 20px;
}

/* ---------- Sound ---------- */

.sound-btn {
  position: absolute;
  z-index: 10;
  right: max(12px, var(--safe-right));
  bottom: calc(140px + var(--safe-bottom));
  width: 44px; height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(22,19,15,.5);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,.14);
  color: #fff;
  transition: opacity .3s ease;
}
.sound-btn svg { width: 20px; height: 20px; }
