/* ==========================================================================
   pages/tours.css — the 360 viewer and the scene index
   ========================================================================== */

.crumbs { display: flex; gap: var(--s-3); align-items: center; color: var(--bone-mute); }
.crumbs a { transition: color var(--d-fast) var(--ease); }
.crumbs a:hover { color: var(--gold); }

/* ======================= Viewer ======================= */
/* The mount point is empty until tour.js builds the viewer into it. Without
   a reserved box the page collapsed and then jumped, measuring CLS 0.337.
   These reservations must stay in step with .tv__stage's aspect-ratio. */
.tv-mount {
  aspect-ratio: 16 / 9;
  min-height: 320px;
  border-radius: var(--r-lg);
  background: var(--ink-3);
}
@media (max-width: 700px) { .tv-mount { aspect-ratio: 4 / 5; } }
/* Once mounted, .tv sizes itself; drop the reservation so the chips and
   note below it are not pushed off the reserved box. */
.tv-mount:has(.tv) { aspect-ratio: auto; min-height: 0; background: none; }

.tv { display: flex; flex-direction: column; gap: var(--s-4); }

.tv__stage {
  position: relative;
  aspect-ratio: 16 / 9;
  min-height: 320px;
  border: 1px solid var(--line-firm);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ink-3);
  isolation: isolate;
  cursor: grab;
  touch-action: pan-y;      /* vertical page scroll still works on mobile */
  transition: opacity var(--d-base) var(--ease);
}
.tv__stage.is-grabbing { cursor: grabbing; }
.tv__stage.is-fading { opacity: 0; }
.tv__stage:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

@media (max-width: 700px) {
  .tv__stage { aspect-ratio: 4 / 5; }
}

/* --- WebGL canvas: the photograph projected onto curved geometry --- */
.tv__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: none;
  opacity: 0;
  transition: opacity var(--d-slow) var(--ease);
  touch-action: none;      /* we handle drag + pinch ourselves */
}
.tv--gl .tv__canvas { display: block; }
.tv__canvas.is-ready { opacity: 1; }

/* Flat fallback track: 300% wide, JS translates it. Only used when WebGL
   is unavailable — hidden entirely in GL mode. */
.tv__track {
  position: absolute;
  inset: 0;
  width: 300%;
  left: -100%;
  will-change: transform;
  opacity: 0;
  transition: opacity var(--d-slow) var(--ease);
}
.tv__track.is-ready { opacity: 1; }
.tv--gl .tv__track { display: none; }
.tv__img { width: 100%; height: 100%; object-fit: cover; }

/* --- Drag hint --- */
.tv__hint {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  padding: var(--s-3) var(--s-4);
  background: color-mix(in srgb, var(--ink) 62%, transparent);
  backdrop-filter: blur(6px);
  border-radius: var(--r-full);
  color: var(--bone);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-base) var(--ease);
}
.is-entered .tv__hint { opacity: 1; }
.is-entered .tv__hint.is-gone { opacity: 0; }

.tv__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to top, color-mix(in srgb, var(--ink) 90%, transparent) 4%, transparent 46%),
    linear-gradient(to right, color-mix(in srgb, var(--ink) 60%, transparent), transparent 55%);
}

/* Thin gold load bar — never blocks first paint. */
.tv__bar {
  position: absolute;
  top: 0; left: 0;
  height: 2px; width: 100%;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left;
  z-index: 5;
  transition: transform var(--d-slow) var(--ease), opacity var(--d-base) var(--ease);
}

/* ---------- Enter gate ---------- */
.tv__enter {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 6;
}
.tv__enter-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-6);
  background: color-mix(in srgb, var(--ink) 72%, transparent);
  backdrop-filter: blur(10px);
  border: 1px solid var(--line-gold);
  border-radius: var(--r-full);
  color: var(--bone);
  font-family: var(--font-mono);
  font-size: var(--step-util);
  letter-spacing: var(--tr-util-lg);
  text-transform: uppercase;
  transition: background-color var(--d-fast) var(--ease), color var(--d-fast) var(--ease), transform var(--d-fast) var(--ease);
}
.tv__enter-btn:hover { background: var(--gold); color: var(--on-accent); transform: scale(1.04); }

/* ---------- HUD ---------- */
.tv__hud {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 4;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-5);
  pointer-events: none;
}
.tv__hud > * { pointer-events: auto; }
.tv__meta { display: flex; flex-direction: column; gap: var(--s-2); max-width: 46ch; }
.tv__title {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 1rem + 1.6vw, 2.1rem);
  font-weight: 700;
  letter-spacing: var(--tr-display);
  line-height: 1.05;
}
.tv__blurb { color: var(--bone-dim); font-size: var(--step-small); }

@media (max-width: 620px) {
  .tv__blurb { display: none; }
  .tv__book { width: 100%; justify-content: center; }
}

/* ---------- Tools ---------- */
.tv__tools {
  position: absolute;
  top: var(--s-4); right: var(--s-4);
  z-index: 6;
  display: flex;
  gap: var(--s-2);
}
.tv__tool {
  width: 44px; height: 44px;      /* 44px tap target */
  display: grid; place-items: center;
  border: 1px solid var(--line-firm);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--ink) 66%, transparent);
  backdrop-filter: blur(8px);
  font-size: 1rem;
  line-height: 1;
  transition: border-color var(--d-fast) var(--ease), background-color var(--d-fast) var(--ease);
}
.tv__tool:hover { border-color: var(--gold); background: color-mix(in srgb, var(--ink) 88%, transparent); }
.tv__tool[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }

/* ---------- Hotspots ---------- */
.tv__hotspots {
  position: absolute;
  inset: 0;
  width: 300%;
  left: -100%;
  z-index: 3;
  pointer-events: none;
  will-change: transform;
}
/* In GL mode pins are re-projected each frame into stage-percentage space,
   so the wrapper must be exactly the stage with no transform of its own. */
.tv--gl .tv__hotspots {
  width: 100%;
  left: 0;
  transform: none !important;
}
.tv--gl .tv__pin { transition: none; }
.tv__pin {
  position: absolute;
  transform: translate(-50%, -50%);
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.tv__pin-dot {
  position: relative;
  width: 16px; height: 16px;
  flex: none;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--gold) 24%, transparent);
}
.tv__pin-dot::after {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  animation: pulse 2.4s var(--ease) infinite;
  animation-delay: calc(var(--i, 0) * 400ms);
}
@keyframes pulse {
  0%   { transform: scale(0.7); opacity: 0.9; }
  70%  { transform: scale(1.9); opacity: 0; }
  100% { transform: scale(1.9); opacity: 0; }
}
.tv__pin--scene .tv__pin-dot { background: var(--bone); box-shadow: 0 0 0 4px color-mix(in srgb, var(--bone) 20%, transparent); }
.tv__pin--scene .tv__pin-dot::after { border-color: var(--bone); }

.tv__pin-label {
  padding: var(--s-2) var(--s-3);
  background: color-mix(in srgb, var(--ink) 88%, transparent);
  backdrop-filter: blur(8px);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: var(--step-util);
  letter-spacing: var(--tr-util-lg);
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity var(--d-fast) var(--ease), transform var(--d-fast) var(--ease);
}
.tv__pin:hover .tv__pin-label,
.tv__pin:focus-visible .tv__pin-label { opacity: 1; transform: none; }

/* ---------- Caption panel ---------- */
.tv__caption {
  position: absolute;
  left: var(--s-5); bottom: 50%;
  z-index: 7;
  max-width: min(360px, 74vw);
  padding: var(--s-5) var(--s-6) var(--s-5) var(--s-5);
  background: color-mix(in srgb, var(--ink) 94%, transparent);
  backdrop-filter: blur(12px);
  border: 1px solid var(--line-gold);
  border-radius: var(--r-lg);
  font-size: var(--step-small);
}
.tv__caption-close {
  position: absolute;
  top: 6px; right: 6px;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--bone-dim);
}
.tv__caption-close:hover { color: var(--gold); }

/* ---------- Chips + note ---------- */
.tv__chips { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.tv__note { color: var(--bone-mute); }
.tv__fail { padding: var(--s-7); text-align: center; color: var(--bone-dim); }
.tv__fail a { color: var(--gold); text-decoration: underline; }

/* ======================= Scene index ======================= */
.scene {
  display: flex;
  flex-direction: column;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--d-base) var(--ease);
}
.scene:hover { border-color: var(--line-firm); }
.scene__media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: var(--ink-3); }
.scene__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 1100ms var(--ease); }
.scene:hover .scene__media img { transform: scale(1.06); }

.scene__tag {
  position: absolute;
  top: var(--s-3); left: var(--s-3);
  padding: var(--s-2) var(--s-3);
  background: color-mix(in srgb, var(--ink) 84%, transparent);
  backdrop-filter: blur(6px);
  border-radius: var(--r-sm);
  color: var(--bone-dim);
}
.scene__tag--360 { background: var(--gold); color: var(--on-accent); }

.scene__body { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-5); }
.scene__title { font-size: var(--step-h3); font-weight: 600; }
.scene__title a { transition: color var(--d-fast) var(--ease); }
.scene__title a:hover { color: var(--gold); }
.scene__blurb { color: var(--bone-dim); font-size: var(--step-small); }
.scene__label { margin-top: var(--s-2); }
.scene__tours { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.scene__tour {
  display: inline-block;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 0.8125rem;
  color: var(--bone-dim);
  transition: color var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease);
}
.scene__tour:hover { color: var(--gold); border-color: var(--gold); }

/* ======================= Reduced motion ======================= */
@media (prefers-reduced-motion: reduce) {
  .tv__pin-dot::after { animation: none !important; }
  .tv__stage.is-fading { opacity: 1 !important; }
  .scene__media img { transition: none !important; }
}
