/**
 * sections.css — layout for each page section.
 */

/* ===================== intro banner ===================== */

.intro-banner {
  display: flex; align-items: flex-start; gap: 16px;
  background: var(--tile); border-radius: var(--radius-lg);
  padding: 20px 22px; margin-bottom: 32px; position: relative;
}
.intro-banner p { font-size: 14px; color: var(--navy-deep); line-height: 1.6; max-width: 640px; }
.intro-banner p strong { display: block; font-size: 15px; margin-bottom: 4px; }
.intro-close {
  position: absolute; top: 14px; right: 16px;
  background: none; border: none; color: var(--text-faint);
  font-size: 18px; cursor: pointer; line-height: 1; padding: 4px;
}
.intro-close:hover { color: var(--navy-deep); }

/* ===================== lab photo card =====================
   The overhead shot used to render at its natural aspect at full page
   width — ~660px tall, so you had to scroll to see the room. Here the
   STAGE owns the height (capped against the viewport) and the photo is
   sized to fit inside it, with a blurred, scaled copy of itself filling
   whatever space is left over. Nothing is cropped, nothing overflows,
   and the frame still reads as a lit space rather than a letterbox.

   Hotspots keep working because .lab-image is given the photo's exact
   aspect ratio: its box and the picture are the same rectangle, so the
   x/y percentages in data.js still land where they did.              */

.lab-photo-card {
  margin-bottom: 28px; border-radius: var(--radius-lg);
  overflow: hidden; border: 1px solid var(--border);
  background: var(--chrome);
  box-shadow: var(--shadow-md);
  /* scroll-linked depth (data-depth, js/vocab.js); resting values are an
     identity transform, and the vars are only ever written with motion on */
  transform: translate3d(0, var(--depth-y, 0px), 0) scale(var(--depth-s, 1));
}
/* full screen must sit exactly where it's put — no scroll offset */
.lab-photo-card.is-full { transform: none; }

.lab-stage {
  position: relative; width: 100%;
  aspect-ratio: 1870 / 841;               /* the photo's own ratio: no side gutters */
  min-height: 260px;
  overflow: hidden;
  perspective: 1400px; perspective-origin: 50% 45%;
  background: var(--fw-s90);
  display: flex; align-items: center; justify-content: center;
}

/* same image, scaled and blurred: fills the side gutters with light
   that matches the photo instead of a flat letterbox bar */
.lab-backdrop {
  position: absolute; inset: -8%;
  background: var(--lab-shot) center / cover no-repeat;
  filter: blur(34px) saturate(1.25) brightness(.55);
  /* --par-x/--par-y are written by lab.js: the backdrop drifts against
     the plate, which is what makes the photo sit *in* a space */
  /* --scroll-y (#lab-stage's data-parallax, js/vocab.js): the room lags the photo
     as the deck crosses the viewport. Its own layer, so the blur is
     rasterised once and only moved. */
  transform: scale(1.12) translate(var(--par-x, 0px), calc(var(--par-y, 0px) + var(--scroll-y, 0px)));
  will-change: transform;
  opacity: 0; transition: opacity var(--dur-slow) var(--ease-out-quart);
}
.lab-stage.is-ready .lab-backdrop { opacity: 1; }

/* pannellum mode (CONFIG.panoramaUrl): the viewer takes the whole stage
   and the still-photo plate simply never unhides */
.panorama-viewer { position: absolute; inset: 0; width: 100%; height: 100%; display: none; z-index: 5; }

/* the tilting plate: photo + gloss, lifted in 3D by lab.js */
.lab-plate {
  position: relative; height: 100%; width: auto; max-width: 100%;
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform var(--dur-base) var(--ease-out-expo);
}
.lab-stage.is-tilting .lab-plate { transition: none; }   /* pointer drives it directly */

.lab-image.image-wrap {
  height: 100%; width: auto; aspect-ratio: 1870 / 841; max-width: 100%;
  overflow: hidden; background: transparent;
  border-radius: 0;
  transform-style: preserve-3d;
  box-shadow: 0 30px 70px rgba(0, 0, 0, .55), 0 2px 0 rgba(255, 255, 255, .06) inset;
  opacity: 0; transform: translateZ(0) scale(.97);
  transition: opacity var(--dur-slow) var(--ease-out-quart), transform var(--dur-slow) var(--ease-out-expo);
}
.lab-stage.is-ready .lab-image.image-wrap { opacity: 1; transform: translateZ(0) scale(1); }
.lab-image.image-wrap img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }

/* a moving highlight across the glass — the cue that this is a surface
   being looked at, not a flat image on a page */
.lab-gloss {
  position: absolute; inset: 0; pointer-events: none; border-radius: 8px;
  background: linear-gradient(115deg, rgba(255,255,255,.16) 0%, rgba(255,255,255,0) 32%, rgba(255,255,255,0) 68%, rgba(255,255,255,.07) 100%);
  transform: translateZ(40px);
  opacity: .9; mix-blend-mode: screen;
}

/* ── light layers ──────────────────────────────────────────────────
   torch   — a highlight under the pointer, so the surface feels lit
   spot    — everything but the cued pin falls into shadow
   Both live inside the plate, so they tilt and zoom with the photo.  */
.lab-torch, .lab-spot {
  position: absolute; inset: 0; pointer-events: none; border-radius: 8px;
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out-quart);
}
.lab-torch {
  z-index: 2; mix-blend-mode: soft-light;
  background: radial-gradient(circle at var(--tx, 50%) var(--ty, 50%),
              rgba(255,255,255,.55) 0%, rgba(255,255,255,.14) 16%, transparent 38%);
}
/* the hover torch is retired with the lens: the floor photo stays as it is under the pointer */
.lab-stage.is-lit .lab-torch { opacity: 0; }
.lab-spot {
  z-index: 3;
  background: radial-gradient(circle at var(--sx, 50%) var(--sy, 50%),
              transparent 0%, transparent 9%, rgba(var(--fw-s90-rgb), .74) 34%, rgba(var(--fw-s90-rgb), .86) 100%);
  transition: opacity var(--dur-base) var(--ease-out-quart), background var(--dur-slow) var(--ease-out-expo);
}
.lab-stage.is-spotlit .lab-spot { opacity: 1; }

/* ── inspect mode ── */
.lab-stage.is-zoomed { cursor: zoom-out; }
.lab-stage.is-zoomed .lab-gloss { opacity: .35; }
.lab-stage.is-zoomed .lab-image.image-wrap { box-shadow: 0 50px 110px rgba(0, 0, 0, .7); }

.lab-hint {
  position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%);
  z-index: 6; white-space: nowrap; pointer-events: none;
  font-size: 10.5px; font-weight: 600; letter-spacing: .03em;
  color: rgba(255,255,255,.82);
  background: rgba(var(--fw-s90-rgb), .46); border-radius: var(--radius-pill); padding: 6px 14px;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out-quart);
}
.lab-stage.is-ready .lab-hint { opacity: 1; }
.lab-stage.is-lit .lab-hint, .lab-stage.is-zoomed .lab-hint, .lab-stage.is-spotlit .lab-hint { opacity: 0; }

/* hotspots float above the photo so the depth reads on the pins too */
.lab-image .hotspot { transform: translateZ(34px); z-index: 4; }
/* they arrive after the room does — delay per pin is set in lab.js */
.lab-image.pins-in .hotspot {
  animation: lab-pin-in var(--dur-slow) var(--ease-out-expo) both;
  animation-delay: var(--pin-delay, 0ms);
}
@keyframes lab-pin-in {
  from { opacity: 0; transform: translateZ(34px) scale(.3); }
  to   { opacity: 1; transform: translateZ(34px) scale(1); }
}
@media (prefers-reduced-motion: reduce) { .lab-image.pins-in .hotspot { animation: none; } }
.lab-image .hotspot:hover, .lab-image .hotspot:focus-visible { transform: translateZ(52px) scale(1.18); }
.lab-image .hotspot.is-cued {
  transform: translateZ(60px) scale(1.25);
  box-shadow: 0 0 0 4px var(--blue-dim), 0 6px 18px rgba(0, 0, 0, .5);
}
.lab-image .hotspot-tip { transform: translate(-50%, 8px) translateZ(60px); }
.lab-image .hotspot[aria-expanded="true"] .hotspot-tip { transform: translate(-50%, 0) translateZ(60px); }

/* ── overlay chrome ── */
.lab-overlay {
  position: absolute; inset: 12px 14px auto 14px; z-index: 6;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  pointer-events: none;
}
.lab-overlay > * { pointer-events: auto; }
.lab-badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 10px; font-weight: 800; letter-spacing: .1em; color: rgba(255,255,255,.92);
  background: rgba(var(--fw-s90-rgb), .5); border-radius: var(--radius-pill); padding: 6px 12px;
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
}
.lab-tools { display: flex; gap: 6px; }
.lab-tool {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font); font-size: 11.5px; font-weight: 700; color: #fff;
  background: rgba(var(--fw-s90-rgb), .5); border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--radius-pill); padding: 7px 13px; cursor: pointer;
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  /* hover lift and press compose into one transform (see components.css
     "micro-interactions"): press is fast in, spring out */
  --lift: 0px; --press: 1;
  transform: translate3d(0, var(--lift), 0) scale(var(--press));
  transition: background var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart), transform var(--dur-base) var(--ease-spring);
}
.lab-tool:hover { background: rgba(var(--fw-s10-rgb), .72); border-color: transparent; --lift: -1px; }
.lab-tool:active {
  --press: .96;
  transition: background var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart), transform var(--dur-instant) var(--ease-out-quart);
}
.lab-tool:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.lab-tool[aria-pressed="true"] { background: var(--blue); border-color: transparent; }
.lab-tool.primary { background: var(--blue); border-color: transparent; box-shadow: 0 6px 18px rgba(var(--fw-s10-rgb), .38); }
.lab-tool.primary:hover { background: var(--blue); filter: brightness(1.08); }
.lab-tool.icon { padding: 7px; width: 32px; justify-content: center; }
.lab-tool.icon svg { width: 16px; height: 16px; }
.lab-tool-glyph { font-size: 9px; }

/* ── loading state ── */
.lab-placeholder {
  position: absolute; inset: 0; z-index: 7;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  background: var(--fw-s90); color: rgba(255,255,255,.6);
}
.lab-placeholder p { font-size: 12px; font-weight: 600; letter-spacing: .04em; }
.lab-skeleton {
  width: min(62%, 420px); height: 6px; border-radius: var(--radius-pill);
  background: linear-gradient(90deg, rgba(255,255,255,.08) 0%, rgba(var(--fw-t30-rgb), .45) 50%, rgba(255,255,255,.08) 100%);
  background-size: 220% 100%; animation: skeleton-sheen 1.5s var(--ease-in-out-smooth) infinite;
}
/* (sheen keyframes now shared with every media frame: components.css .skeleton-shimmer) */

/* ── points-of-interest rail ── */
.lab-rail {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  padding: 12px 14px; background: var(--surface); border-top: 1px solid var(--border);
}
.lab-poi {
  display: inline-flex; align-items: center; gap: 9px; text-align: left;
  background: var(--tile); border: 1px solid transparent; border-radius: var(--radius-pill);
  padding: 7px 14px 7px 8px; cursor: pointer; font-family: var(--font);
  transition: border-color var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart), background var(--dur-fast) var(--ease-out-quart);
}
.lab-poi:hover, .lab-poi.is-cued { border-color: var(--blue); transform: translateY(-2px); }
.lab-poi:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.lab-poi-num {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  background: var(--blue); color: var(--on-blue); font-size: 10px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.lab-poi.jump .lab-poi-num { background: var(--accent); }
.lab-poi-label { font-size: 12px; font-weight: 700; color: var(--navy-deep); }
.lab-poi-go { font-size: 10.5px; font-weight: 700; color: var(--text-faint); }
.lab-rail-hint { font-size: 10.5px; font-weight: 600; color: var(--text-faint); margin-left: auto; }

/* full screen: the stage drops its viewport cap and takes the display,
   the rail stays docked underneath as the legend */
.lab-photo-card.is-full { display: flex; flex-direction: column; border: none; border-radius: 0; }
.lab-photo-card.is-full .lab-stage { flex: 1 1 auto; max-height: none; aspect-ratio: auto; }
.lab-photo-card.is-full .lab-rail { background: rgba(var(--fw-s90-rgb), .92); border-top-color: rgba(255,255,255,.1); }
.lab-photo-card.is-full .lab-poi { background: rgba(255,255,255,.08); }
.lab-photo-card.is-full .lab-poi-label { color: #fff; }

@media (prefers-reduced-motion: reduce) {
  .lab-plate, .lab-image.image-wrap, .lab-backdrop { transition: opacity var(--dur-fast) var(--ease-out-quart); }
  .lab-skeleton { animation: none; }
}

/* ===================== 360° virtual tour =====================
   A body-level overlay (see panorama.js for why it cannot live inside
   #page-stations). The chrome is deliberately sparse: a title block, an
   exit, fullscreen, station shortcuts and zoom — everything else is the
   room. Colours come from the same tokens as the rest of the app, but
   the surfaces are fixed dark because they sit over a photograph.     */

.pano {
  position: fixed; inset: 0; z-index: 900;
  background: var(--fw-s90);
  opacity: 0; transform: scale(1.04);
  transition: opacity var(--dur-base) var(--ease-out-quart), transform var(--dur-slow) var(--ease-out-expo);
  pointer-events: none;
}
.pano.is-open { opacity: 1; transform: scale(1); pointer-events: auto; }
.pano-stage { position: absolute; inset: 0; cursor: grab; }
.pano-stage:active { cursor: grabbing; }

/* the page behind stops scrolling and settles back a step, so exiting
   the tour lands you where you were rather than somewhere new */
.tour-open body { overflow: hidden; }
.tour-open .wrap { transform: scale(.985); filter: blur(2px); transition: transform var(--dur-base) var(--ease-out-quart), filter var(--dur-base) var(--ease-out-quart); }

/* ── loading / error ── */
.pano-loader {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
  background: radial-gradient(70% 70% at 50% 45%, var(--fw-s80) 0%, var(--fw-s90) 100%);
  transition: opacity var(--dur-base) var(--ease-out-quart), visibility var(--dur-base) var(--ease-out-quart);
}
.pano.is-ready .pano-loader { opacity: 0; visibility: hidden; }
.pano-ring {
  width: 38px; height: 38px; border-radius: 50%;
  border: 2.5px solid rgba(255,255,255,.16); border-top-color: var(--blue);
  animation: pano-spin .9s var(--ease-linear) infinite;
}
@keyframes pano-spin { to { transform: rotate(360deg); } }
.pano-loader-text { font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,.7); letter-spacing: .02em; text-align: center; max-width: 320px; }
.pano-loader.is-error .pano-loader-text { color: #FFC9D3; }

/* ── top bar ── */
.pano-topbar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 4;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 18px 20px;
  background: linear-gradient(to bottom, rgba(var(--fw-s90-rgb), .72) 0%, transparent 100%);
  pointer-events: none;
}
.pano-topbar > * { pointer-events: auto; }
.pano-identity { display: flex; flex-direction: column; gap: 2px; }
.pano-eyebrow { font-size: 9.5px; font-weight: 800; letter-spacing: .18em; color: var(--blue); }
.pano-title { font-size: 17px; font-weight: 800; color: #fff; letter-spacing: -.01em; }
.pano-scene { font-size: 11.5px; font-weight: 600; color: rgba(255,255,255,.55); }
.pano-actions { display: flex; gap: 8px; align-items: center; }

.pano-btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font); font-size: 12px; font-weight: 700; color: #fff;
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.16);
  border-radius: var(--radius-pill); padding: 9px 14px; cursor: pointer;
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  transition: background var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart);
}
.pano-btn svg { width: 16px; height: 16px; fill: currentColor; }
.pano-btn:hover { background: rgba(255,255,255,.16); transform: translateY(-1px); }
.pano-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.pano-btn.small { padding: 9px; width: 38px; height: 38px; justify-content: center; }
.pano-exit { background: rgba(var(--fw-s10-rgb), .9); border-color: transparent; }
.pano-exit:hover { background: var(--blue); }
.pano-btn-ico { display: inline-flex; }

/* ── bottom dock ── */
.pano-dock {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 4;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 20px; flex-wrap: wrap;
  background: linear-gradient(to top, rgba(var(--fw-s90-rgb), .72) 0%, transparent 100%);
  pointer-events: none;
}
.pano-dock > * { pointer-events: auto; }
.pano-scenes { display: flex; gap: 8px; flex-wrap: wrap; }
.pano-scene-btn {
  font-family: var(--font); font-size: 11.5px; font-weight: 700; color: rgba(255,255,255,.86);
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.16);
  border-radius: var(--radius-pill); padding: 8px 15px; cursor: pointer;
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  transition: background var(--dur-fast) var(--ease-out-quart), color var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart);
}
.pano-scene-btn:hover { background: var(--blue); color: var(--on-blue); transform: translateY(-2px); }
.pano-scene-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.pano-view-tools { display: flex; gap: 6px; margin-left: auto; }

.pano-hint {
  position: absolute; left: 50%; bottom: 76px; transform: translateX(-50%);
  z-index: 4; white-space: nowrap; pointer-events: none;
  font-size: 11px; font-weight: 600; color: rgba(255,255,255,.75);
  background: rgba(var(--fw-s90-rgb), .5); border-radius: var(--radius-pill); padding: 7px 16px;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  opacity: 0; transition: opacity var(--dur-slow) var(--ease-out-quart);
}
.pano.is-ready .pano-hint { opacity: 1; }
.pano.is-touched .pano-hint { opacity: 0; }

/* ── hotspots ──
   Pannellum positions the element; everything inside it is ours.      */
.pano-hotspot { cursor: pointer; }
.pano-pin {
  position: relative; display: flex; align-items: center; gap: 10px;
  background: none; border: none; padding: 0; white-space: nowrap;
}
.pano-pin-dot {
  width: 15px; height: 15px; flex: none; border-radius: 50%;
  background: var(--blue); border: 2px solid #fff;
  box-shadow: 0 2px 10px rgba(0,0,0,.5);
}
.pano-pin-dot::after {
  content: ""; position: absolute; left: -6px; top: 50%; margin-top: -13px;
  width: 27px; height: 27px; border-radius: 50%;
  border: 1.5px solid var(--blue); animation: pano-pulse 2.4s var(--ease-out-quart) infinite;
}
@keyframes pano-pulse { 0% { transform: scale(.55); opacity: .65; } 100% { transform: scale(1.5); opacity: 0; } }
.pano-hotspot.is-scene .pano-pin-dot { background: var(--accent); }
.pano-hotspot.is-scene .pano-pin-dot::after { border-color: var(--accent); }

.pano-pin-card {
  display: flex; flex-direction: column; gap: 1px;
  background: rgba(var(--fw-s90-rgb), .82); border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--radius-md); padding: 9px 14px;
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  opacity: 0; transform: translateX(-6px) scale(.96); transform-origin: left center;
  transition: opacity var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-expo);
}
.pano-pin-card b { font-size: 12.5px; font-weight: 700; color: #fff; }
.pano-pin-card i { font-style: normal; font-size: 11px; color: rgba(255,255,255,.62); white-space: normal; max-width: 220px; line-height: 1.45; }
.pano-pin-card u { text-decoration: none; font-size: 10.5px; font-weight: 700; color: var(--blue); margin-top: 3px; }
.pano-hotspot:hover .pano-pin-card,
.pano-hotspot:focus-visible .pano-pin-card,
.pano-pin.is-open .pano-pin-card { opacity: 1; transform: translateX(0) scale(1); }
.pano-hotspot:focus-visible { outline: 2px solid #fff; outline-offset: 6px; border-radius: 50%; }

@media (prefers-reduced-motion: reduce) {
  .pano { transition: opacity var(--dur-fast) var(--ease-out-quart); transform: none; }
  .pano-pin-dot::after, .pano-ring { animation: none; }
  .tour-open .wrap { transition: none; }
}

/* ===================== batch journey ===================== */

.journey-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 20px; margin-bottom: 32px;
  box-shadow: var(--shadow-sm), var(--surface-hi);   /* elevation level 1 */
}
.journey-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 18px; flex-wrap: wrap; gap: 8px; }
.journey-head h2 { font-size: 15px; font-weight: 700; color: var(--navy-deep); }
.journey-batch-id {
  font-size: 11px; font-weight: 600; color: var(--blue); font-family: var(--font-mono); letter-spacing: 0;
  background: var(--blue-dim); padding: 4px 10px; border-radius: var(--radius-pill);
}
.journey-rail { display: flex; align-items: flex-start; gap: 2px; margin-bottom: 16px; overflow-x: auto; position: relative; }
.journey-marker {
  position: absolute; top: 20px; left: 0; width: 10px; height: 10px;
  border-radius: 50%; background: var(--blue); pointer-events: none; z-index: 3;
  box-shadow: 0 0 0 4px var(--blue-dim), 0 0 14px 2px var(--blue-dim);
  transition: transform .5s var(--ease-out-quart);
}
@media (prefers-reduced-motion: reduce) { .journey-marker { transition: none; } }
.journey-stage {
  flex: 1; min-width: 90px; text-align: center; cursor: pointer;
  padding: 6px 2px; background: none; border: none;
}
.journey-dot {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--tile); border: 2px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 8px; font-size: 11px; font-weight: 700;
  color: var(--text-faint); transition: all var(--dur-fast) var(--ease-out-quart);
}
.journey-stage[aria-current="true"] .journey-dot { border-color: var(--blue); color: var(--blue); background: var(--blue-dim); }
.journey-line { height: 2px; background: var(--border); flex: .4; margin-top: 20px; position: relative; overflow: hidden; }
.journey-line::after {
  content: ""; position: absolute; top: 0; left: -40%; width: 40%; height: 100%;
  background: linear-gradient(90deg, transparent, var(--blue), transparent);
  animation: journey-flow 2.8s var(--ease-linear) infinite;
}
@keyframes journey-flow { 0% { left: -40%; } 100% { left: 100%; } }
.journey-label { font-size: 10.5px; font-weight: 700; color: var(--text-muted); line-height: 1.3; }
.journey-stage[aria-current="true"] .journey-label { color: var(--navy-deep); }
.journey-detail { background: var(--tile); border-radius: var(--radius-md); padding: 16px 18px; }
.journey-detail p { font-size: 13px; color: var(--text); line-height: 1.6; margin-bottom: 10px; }
.journey-open {
  font-size: 12.5px; font-weight: 700; color: var(--blue);
  background: none; border: none; cursor: pointer; padding: 0;
}

/* ===================== progress rail ===================== */

.rail { display: flex; align-items: center; margin-bottom: 26px; max-width: 640px; }
.rail-step { display: flex; align-items: center; gap: 8px; flex: 1; }
.rail-dot {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--border); color: var(--text-faint);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; flex-shrink: 0; transition: all var(--dur-fast) var(--ease-out-quart);
}
.rail-step.active .rail-dot { border-color: var(--blue); color: var(--blue); background: var(--blue-dim); }
.rail-line { height: 2px; background: var(--border); flex: 1; }
.rail-step:last-child .rail-line { display: none; }
.rail-name { font-size: 12px; color: var(--text-muted); font-weight: 600; white-space: nowrap; display: none; }
@media (min-width: 720px) { .rail-name { display: inline; } }

/* ===================== detail view ===================== */

.detail-title-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }
.detail-title-row h2 { font-size: 26px; font-weight: 800; color: var(--navy-deep); }
.detail-tagline { font-size: 12px; color: var(--blue); font-weight: 700; margin-bottom: 6px; }
.detail-body { display: grid; grid-template-columns: 1.2fr 1fr; gap: 28px; }

.detail-footer-nav {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--border);
  flex-wrap: wrap; gap: 14px;
}
.detail-cta-line {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin-top: 20px; padding: 18px; background: var(--tile);
  border-radius: var(--radius-md); flex-wrap: wrap; text-align: center;
}
.detail-cta-line span { font-size: 13.5px; color: var(--navy-deep); font-weight: 600; }

/* ===================== story ===================== */

.story-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 40px; }
.story-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 22px; box-shadow: var(--shadow-sm);
  transform-style: preserve-3d;
}
.story-card h3 { font-size: 15px; font-weight: 700; color: var(--navy-deep); margin-bottom: 10px; }
.story-card p { font-size: 13.5px; color: var(--text-muted); line-height: 1.65; }

.story-closing {
  background: var(--tile); border-radius: var(--radius-lg); padding: 28px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
}
.story-closing p { font-size: 15px; font-weight: 600; color: var(--navy-deep); max-width: 420px; }

/* ===================== track record ===================== */

.notice-banner {
  background: var(--warn-dim); border: 1px dashed var(--warn); border-radius: var(--radius-md);
  padding: 12px 16px; font-size: 12.5px; color: var(--warn);
  margin-bottom: 24px; max-width: 680px; line-height: 1.6;
}
.notice-banner code { background: var(--surface); padding: 1px 5px; border-radius: 4px; font-size: 11.5px; }

.kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 46px; }
.kpi-tile {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 24px 16px; text-align: center; box-shadow: var(--shadow-sm);
}
.kpi-value { font-size: 32px; font-weight: 700; color: var(--blue); line-height: 1; margin-bottom: 8px; font-family: var(--font-mono); letter-spacing: -.01em; }
.kpi-label { font-size: 12px; color: var(--text-muted); font-weight: 600; line-height: 1.4; }

.client-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.client-tile {
  background: var(--tile); border-radius: var(--radius-md); padding: 22px 14px;
  text-align: center; font-weight: 700; color: var(--navy-deep); font-size: 14px;
}

.partner-row { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 8px; }
.partner-chip {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 9px 18px;
  font-size: 13px; font-weight: 700; color: var(--navy-deep);
}

/* ===================== partner success orbit ===================== */

.orbit-lead { color: var(--text-muted); font-size: 13.5px; line-height: 1.6; max-width: 560px; margin: -4px 0 20px; }

/* No card, no border, no background: the spheres float directly on the
   page so the site's own mesh/grain background stays visible behind and
   between them. The only atmosphere is a soft, edgeless bloom. */
.orbit {
  position: relative;
  margin-bottom: 8px;
  isolation: isolate;
}
.orbit::before {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  /* vertical bleed only — horizontal bleed pushed past the wrap padding
     and added document-level horizontal overflow below ~1240px. The
     gradients fade to transparent well inside the box, so the soft
     edge survives without it. */
  left: 0; right: 0; top: -6%; bottom: -6%;
  background:
    radial-gradient(60% 55% at 32% 42%, var(--sphere-halo), transparent 70%),
    radial-gradient(45% 45% at 76% 62%, var(--sphere-halo), transparent 72%);
  filter: blur(26px); opacity: .85;
  /* the halo lags the constellation as the section scrolls past
     (#orbit's data-parallax, js/vocab.js); promoted, so the blur only moves */
  transform: translateY(var(--scroll-y, 0px));
  will-change: transform;
}
.orbit-stage {
  position: relative; z-index: 1;
  height: 470px;                 /* JS sizes this to the year's story count */
  perspective: 1100px;
  touch-action: pan-y;           /* vertical scrolling stays the browser's; horizontal is ours */
}

/* ── year navigation: part of the field, not a toolbar above it ── */
.orbit-yearnav {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: center; gap: 22px;
  padding: 4px 0 2px;
}
.orbit-year-arrow {
  width: 38px; height: 38px; border-radius: 50%;
  background: none; border: 1px solid var(--border); color: var(--text-muted);
  font-size: 15px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: border-color var(--dur-fast) var(--ease-out-quart), color var(--dur-fast) var(--ease-out-quart), opacity var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart);
}
.orbit-year-arrow:hover:not(:disabled) { border-color: var(--blue); color: var(--blue); transform: scale(1.06); }
.orbit-year-arrow:disabled { opacity: .28; cursor: default; }
.orbit-year-display { text-align: center; min-width: 132px; }
.orbit-year-label {
  font-size: 9.5px; font-weight: 800; letter-spacing: .14em;
  color: var(--text-faint); margin-bottom: 2px;
}
.orbit-year-value {
  font-size: 30px; font-weight: 800; line-height: 1.05; color: var(--navy-deep);
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.orbit-year-meta { font-size: 11.5px; font-weight: 600; color: var(--text-muted); margin-top: 1px; }

/* the year itself travels with the constellation */
@keyframes orbit-year-in-right {
  from { opacity: 0; transform: translateX(16px) scale(.94); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: none; }
}
@keyframes orbit-year-in-left {
  from { opacity: 0; transform: translateX(-16px) scale(.94); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: none; }
}
.orbit-year-value.shift-in-right { animation: orbit-year-in-right .44s var(--ease-out-expo) both; }
.orbit-year-value.shift-in-left  { animation: orbit-year-in-left .44s var(--ease-out-expo) both; }

.orbit-hint {
  position: relative; z-index: 2; text-align: center;
  font-size: 11px; font-weight: 600; color: var(--text-faint);
  margin-top: 2px;
}

/* spheres leaving on a year change — the loop hands them to CSS, which is
   why transform is transitioned here and nowhere else on .orbit-bubble */
.orbit-bubble.is-leaving {
  opacity: 0;
  transition: transform var(--dur-base) var(--ease-standard), opacity .38s var(--ease-out-quart);
}

.orbit-bubble {
  position: absolute; left: var(--bx); top: var(--by);
  /* --bsize is computed in orbit.js from the measured stage and the
     number of case studies in view, so it is already responsive */
  width: var(--bsize); height: var(--bsize);
  margin: calc(var(--bsize) / -2) 0 0 calc(var(--bsize) / -2);
  z-index: calc(1 + var(--d, .5) * 10);
  background: none; border: none; padding: 0; cursor: pointer;
  transition: opacity var(--dur-base) var(--ease-out-quart), filter var(--dur-base) var(--ease-out-quart);
  will-change: transform;
}
.orbit-bubble:focus-visible { outline: none; } /* ring is drawn on the sphere — a square outline would sit off the circle */

/* ── the sphere itself ──────────────────────────────────────────
   Four stacked layers, all circular:
     media    — the portrait (or placeholder silhouette)
     refract  — edge-only backdrop blur: refraction is strongest at
                grazing angles, and masking it to the rim keeps the
                portrait itself perfectly sharp
     glass    — specular highlights + rim light, fixed light source
     index    — a small story indicator, not the sphere's content
   Depth (--d) drives size, shadow, contrast and parallax response.     */
.orbit-sphere {
  position: relative; display: block; width: 100%; height: 100%;
  border-radius: 50%;
  background: var(--sphere-tint);
  box-shadow:
    0 calc(var(--d, .5) * 26px) calc(var(--d, .5) * 46px) calc(var(--d, .5) * -6px) var(--sphere-shadow),
    inset 0 0 0 1px var(--sphere-rim);
  transition: transform .38s var(--ease-out-expo), box-shadow .38s var(--ease-out-quart);
  transform: translateZ(0);
}

.orbit-sphere-media {
  position: absolute; inset: 6%; border-radius: 50%; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(168deg, var(--sphere-fill) 0%, var(--sphere-fill-2) 100%);
  /* the interior carries its own spherical shading, so its edge melts
     into the glass shell instead of ending on a hard ring */
  box-shadow:
    inset 0 6px 12px var(--sphere-spec-soft),
    inset 0 -10px 18px var(--sphere-shade);
  /* far spheres sit back in the haze; near ones read at full contrast */
  opacity: calc(.62 + var(--d, .5) * .38);
  transition: opacity .35s var(--ease-out-quart), filter .35s var(--ease-out-quart);
  will-change: transform;
}
.orbit-sphere-media img { width: 100%; height: 100%; object-fit: cover; object-position: center 28%; display: block; }

.orbit-sphere-placeholder { display: flex; width: 100%; height: 100%; align-items: flex-end; justify-content: center; }
.orbit-sphere-glyph { width: 76%; height: 76%; fill: var(--sphere-glyph); display: block; }
/* the case-study mark reads as an object inside the sphere, so it floats
   centred rather than sitting on the base line like the silhouette does */
.orbit-sphere-glyph.is-case {
  width: 48%; height: 48%; margin: auto;
  /* drawn in line rather than solid, so it stays legible in both themes */
  fill: none; stroke: var(--sphere-glyph); stroke-width: 3.2;
  stroke-linecap: round; stroke-linejoin: round;
}

.orbit-sphere-refract {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent 56%, #000 78%, #000 100%);
          mask-image: radial-gradient(circle at 50% 50%, transparent 56%, #000 78%, #000 100%);
}
@media (hover: hover) and (pointer: fine) {
  .orbit-sphere-refract { backdrop-filter: blur(4px) saturate(1.15); -webkit-backdrop-filter: blur(4px) saturate(1.15); }
}

.orbit-sphere-glass {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background:
    /* primary specular, upper-left */
    radial-gradient(circle at 31% 25%, var(--sphere-spec) 0%, var(--sphere-spec-soft) 16%, transparent 43%),
    /* small secondary catch-light */
    radial-gradient(circle at 67% 17%, var(--sphere-spec-soft) 0%, transparent 13%),
    /* bounce light off the lower-right */
    radial-gradient(circle at 72% 82%, var(--sphere-spec-soft) 0%, transparent 32%),
    /* rim brightening toward the silhouette edge */
    radial-gradient(circle at 50% 50%, transparent 60%, var(--sphere-spec-soft) 88%, transparent 100%);
  box-shadow:
    inset 0 2px 2px var(--sphere-spec-soft),
    inset 0 -14px 22px var(--sphere-shade);
  transition: opacity .35s var(--ease-out-quart);
}

.orbit-sphere-index {
  position: absolute; right: 4%; bottom: 6%;
  min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--surface); border: 1px solid var(--border);
  color: var(--text-faint); font-size: 9.5px; font-weight: 800; letter-spacing: .02em;
  display: flex; align-items: center; justify-content: center;
  opacity: .82; transition: opacity .3s var(--ease-out-quart), color .3s var(--ease-out-quart), border-color .3s var(--ease-out-quart);
}

/* ── hover / focus ── */
.orbit-bubble:hover .orbit-sphere,
.orbit-bubble:focus-visible .orbit-sphere {
  transform: scale(1.07) translateZ(0);
  box-shadow:
    0 calc(var(--d, .5) * 32px) calc(var(--d, .5) * 56px) calc(var(--d, .5) * -6px) var(--sphere-shadow),
    inset 0 0 0 1px var(--sphere-rim),
    0 0 0 1px var(--blue-dim);
}
.orbit-bubble:hover .orbit-sphere-media,
.orbit-bubble:focus-visible .orbit-sphere-media { opacity: 1; }
.orbit-bubble:focus-visible .orbit-sphere { outline: 2px solid var(--blue); outline-offset: 5px; }
.orbit-bubble:hover .orbit-sphere-index,
.orbit-bubble:focus-visible .orbit-sphere-index { opacity: 1; color: var(--blue); border-color: var(--blue); }

.orbit-bubble-caption {
  position: absolute; top: calc(100% + 10px); left: 50%;
  transform: translate(-50%, 4px);
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  max-width: 190px; text-align: center; pointer-events: none;
  opacity: 0; transition: opacity .28s var(--ease-out-quart), transform .28s var(--ease-out-quart);
}
.orbit-bubble-caption b {
  font-size: 12px; font-weight: 700; color: var(--navy-deep);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 190px;
}
.orbit-bubble-caption i {
  font-style: normal; font-size: 10.5px; font-weight: 600; color: var(--text-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 190px;
}
.orbit-bubble:hover .orbit-bubble-caption,
.orbit-bubble:focus-visible .orbit-bubble-caption { opacity: 1; transform: translate(-50%, 0); }

/* ── story open: the rest of the scene recedes ── */
.orbit-stage.story-open .orbit-bubble:not(.is-selected) { opacity: .22; filter: saturate(.6); pointer-events: none; }
.orbit-stage.story-open .orbit-bubble.is-selected { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .orbit-sphere, .orbit-sphere-media, .orbit-bubble-caption { transition: opacity var(--dur-fast) var(--ease-out-quart); }
  .orbit::before { display: none; }
}

/* story panel — a body-level element (see orbit.js for why), docked via
   JS-measured left/top/width/height so position:fixed always resolves
   against the true viewport rather than a transformed page ancestor.
   Expands from the clicked bubble's own rect via a transform+opacity
   flight, not a generic modal pop-up. */
.orbit-story {
  position: fixed; z-index: 500;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-md);
  display: grid; grid-template-columns: 220px 1fr; overflow: hidden;
  opacity: 0; pointer-events: none; transform-origin: center;
}
.orbit-story.visible { opacity: 1; pointer-events: auto; }
.orbit-story-portrait {
  position: relative; background: var(--tile);
  display: flex; align-items: center; justify-content: center;
}
.orbit-story-portrait img { width: 100%; height: 100%; object-fit: cover; }
.orbit-story-close {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border);
  color: var(--text-muted); font-size: 18px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.orbit-story-close::before { content: ""; position: absolute; inset: -7px; } /* 48px touch target without growing the visible chip */
.orbit-story-close:hover, .orbit-story-close:focus-visible { color: var(--navy-deep); border-color: var(--blue); }
/* The story is longer than the card on purpose, so it scrolls — but the
   platform scrollbar is loud next to this palette. Thin, tokenised, and
   `contain` so reaching the end never hands the scroll to the page. */
.orbit-story-body {
  padding: 26px 30px; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: var(--border) transparent;
}
.orbit-story-body::-webkit-scrollbar { width: 10px; }
.orbit-story-body::-webkit-scrollbar-track { background: transparent; }
.orbit-story-body::-webkit-scrollbar-thumb {
  background: var(--border); background-clip: content-box;
  border: 3px solid transparent; border-radius: var(--radius-pill);
}
.orbit-story-body:hover::-webkit-scrollbar-thumb { background: var(--text-faint); background-clip: content-box; }
.orbit-story-context {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
}
.orbit-story-year {
  background: var(--blue-dim); color: var(--blue);
  border-radius: var(--radius-pill); padding: 3px 9px; font-variant-numeric: tabular-nums;
}
.orbit-story-caseno { color: var(--text-faint); }
.orbit-story-position {
  font-size: 11px; font-weight: 700; color: var(--text-faint);
  font-variant-numeric: tabular-nums; align-self: center; padding: 0 4px;
}
.orbit-story-role { font-size: 11.5px; font-weight: 700; color: var(--blue); margin-bottom: 4px; letter-spacing: .02em; }
.orbit-story-name { font-size: 21px; font-weight: 800; color: var(--navy-deep); margin-bottom: 10px; }
.orbit-story-placeholder-tag {
  display: inline-block; margin-left: 8px; padding: 2px 8px; border-radius: var(--radius-pill);
  font-size: 9px; font-weight: 800; letter-spacing: .05em; color: var(--warn);
  background: var(--warn-dim); border: 1px solid var(--warn); vertical-align: middle;
}
.orbit-story-title { font-size: 15px; font-weight: 700; color: var(--navy-deep); margin: 10px 0 16px; line-height: 1.4; }
.orbit-story-field { margin-bottom: 14px; }
.orbit-story-field h4 { font-size: 10.5px; font-weight: 800; letter-spacing: .06em; color: var(--text-faint); text-transform: uppercase; margin-bottom: 5px; }
.orbit-story-field p { font-size: 13px; color: var(--text-muted); line-height: 1.6; }
.orbit-story-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.orbit-story-tag { font-size: 11px; font-weight: 700; color: var(--navy-deep); background: var(--tile); border-radius: var(--radius-pill); padding: 4px 10px; }
/* credits — the people behind the delivery, inside the case study */
.orbit-story-team { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.orbit-story-people { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 10px; }
.orbit-story-person {
  display: flex; align-items: center; gap: 8px;
  background: var(--tile); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 4px 12px 4px 4px;
}
.orbit-story-avatar {
  width: 28px; height: 28px; flex: none; border-radius: 50%; overflow: hidden;
  background: linear-gradient(168deg, var(--sphere-fill) 0%, var(--sphere-fill-2) 100%);
  display: flex; align-items: flex-end; justify-content: center;
}
.orbit-story-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: center 28%; display: block; }
.orbit-story-person-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.orbit-story-person-text b { font-size: 12px; font-weight: 700; color: var(--navy-deep); }
.orbit-story-person-text i { font-style: normal; font-size: 10.5px; font-weight: 600; color: var(--text-faint); }

.orbit-story-nav { display: flex; gap: 8px; margin-top: 20px; }
.orbit-story-nav button {
  flex: 1; background: var(--tile); border: 1px solid var(--border); color: var(--navy-deep);
  font-family: var(--font); font-size: 12px; font-weight: 700; padding: 9px; border-radius: var(--radius-md); cursor: pointer;
}
.orbit-story-nav button:hover, .orbit-story-nav button:focus-visible { border-color: var(--blue); color: var(--blue); }

@media (prefers-reduced-motion: reduce) {
  .orbit-story { transition: opacity var(--dur-fast) var(--ease-out-quart) !important; }
}

.case-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.case-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 20px; box-shadow: var(--shadow-sm);
}
.case-client { font-size: 12px; font-weight: 700; color: var(--blue); margin-bottom: 8px; }
.case-card h3 { font-size: 15px; font-weight: 700; color: var(--navy-deep); margin-bottom: 8px; line-height: 1.4; }
.case-card p { font-size: 13px; color: var(--text-muted); line-height: 1.6; }
.case-stat { font-size: 22px; font-weight: 800; color: var(--blue); margin-top: 10px; }

.testimonial-card {
  background: var(--chrome); color: var(--fw-t90);
  border-radius: var(--radius-lg); padding: 30px 32px; margin-top: 16px;
}
.testimonial-quote { font-size: 17px; line-height: 1.6; font-weight: 600; max-width: 640px; margin-bottom: 18px; }
.testimonial-name { font-size: 13px; font-weight: 700; }
.testimonial-role { font-size: 12px; opacity: .7; }

/* ===================== ROI calculator ===================== */

.roi-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 26px; align-items: start; }
.roi-inputs {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 22px; box-shadow: var(--shadow-sm);
}
.roi-inputs label { display: block; font-size: 12.5px; font-weight: 700; color: var(--text-muted); margin-bottom: 20px; }
.roi-inputs input[type="range"] { width: 100%; margin-top: 10px; accent-color: var(--blue); }
.roi-input-value { margin-top: 6px; font-size: 13px; font-weight: 600; color: var(--navy-deep); }
.roi-input-value span { font-family: var(--font-mono); font-weight: 600; }
.roi-disclaimer { font-size: 11.5px; color: var(--text-faint); line-height: 1.6; margin-top: 6px; }

.roi-output {
  background: var(--chrome); color: var(--fw-t90);
  border-radius: var(--radius-lg); padding: 26px; position: sticky; top: 20px;
}
.roi-output-label { font-size: 11px; font-weight: 700; letter-spacing: .04em; opacity: .7; margin-bottom: 14px; }
.roi-output-row { margin-bottom: 16px; }
.roi-output-value { font-size: 32px; font-weight: 700; line-height: 1; font-family: var(--font-mono); letter-spacing: -.01em; }
.roi-output-unit { font-size: 12px; opacity: .75; margin-top: 4px; }

/* ===================== booking ===================== */

.session-toggle { display: flex; gap: 10px; margin-bottom: 28px; flex-wrap: wrap; }
.session-opt {
  background: var(--surface); border: 1px solid var(--border); color: var(--text-muted);
  font-size: 13px; font-weight: 700; padding: 10px 16px;
  border-radius: var(--radius-pill); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out-quart), color var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart);
}
.session-opt[aria-pressed="true"] { background: var(--blue); color: var(--on-blue); border-color: var(--blue); }

.booking-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
.cal-card, .booking-form-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 20px;
  box-shadow: var(--shadow-sm), var(--surface-hi);   /* elevation level 1 */
  transition: box-shadow var(--dur-base) var(--ease-out-quart);
}
/* the card you're working in rises one level, so focus reads as depth too */
.cal-card:focus-within, .booking-form-card:focus-within {
  box-shadow: var(--shadow-md), var(--surface-hi);
}
.cal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.cal-month { font-weight: 700; color: var(--navy-deep); font-size: 14px; }
.cal-weekdays {
  display: grid; grid-template-columns: repeat(7, 1fr); text-align: center;
  font-size: 11px; color: var(--text-faint); font-weight: 700; margin-bottom: 8px;
}
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-day {
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; font-size: 13px; color: var(--text);
  cursor: pointer; border: 1px solid transparent; background: none;
  transition: background var(--dur-fast) var(--ease-out-quart), color var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart);
}
.cal-day.empty { visibility: hidden; cursor: default; }
.cal-day:disabled { color: var(--text-faint); cursor: default; opacity: .4; }
.cal-day:not(:disabled):not(.empty):hover { border-color: var(--blue); }
.cal-day[aria-pressed="true"] { background: var(--blue); color: var(--on-blue); font-weight: 700; }
.cal-note { margin-top: 12px; font-size: 11px; color: var(--text-faint); text-align: center; }

.slot-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; min-height: 38px; align-items: center; }
.slot-empty { font-size: 12.5px; color: var(--text-faint); }
.slot-pill {
  background: var(--tile); border: 1px solid var(--border); color: var(--navy-deep);
  font-size: 12.5px; font-weight: 700; padding: 8px 14px;
  border-radius: var(--radius-pill); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out-quart), color var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart);
}
.slot-pill[aria-pressed="true"] { background: var(--blue); color: var(--on-blue); border-color: var(--blue); }

/* ===================== plant ===================== */

.plant-viewport { height: 430px; }

/* ── walkthrough showcase ──────────────────────────────────────────
   Player and its context sit side by side: the video stops being a
   full-bleed banner and becomes one column of a composed block, which
   is what keeps it from dominating the top of the section.           */
.plant-showcase {
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(270px, 1fr);
  gap: 22px; align-items: start; margin: 8px 0 38px;
}

.plant-aside { display: flex; flex-direction: column; gap: 10px; padding-top: 2px; }
.plant-aside-eyebrow {
  font-size: 10.5px; font-weight: 800; letter-spacing: .12em; color: var(--blue);
}
.plant-aside h3 { font-size: 19px; font-weight: 800; color: var(--navy-deep); line-height: 1.3; }
.plant-aside > p { font-size: 13px; color: var(--text-muted); line-height: 1.6; }
.plant-aside-keys {
  font-size: 10.5px; color: var(--text-faint); font-weight: 600;
  margin-top: auto; padding-top: 4px;
}

.plant-stats { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.plant-stat {
  flex: 1 1 88px;
  background: var(--tile); border: 1px solid transparent;
  border-radius: var(--radius-md); padding: 10px 12px;
  display: flex; flex-direction: column; gap: 2px;
  transition: border-color var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart);
}
.plant-stat:hover { border-color: var(--blue); transform: translateY(-2px); }
.plant-stat-value { font-size: 20px; font-weight: 800; color: var(--blue); line-height: 1; font-variant-numeric: tabular-nums; }
.plant-stat-label { font-size: 10.5px; color: var(--text-muted); font-weight: 600; line-height: 1.3; white-space: pre-line; }

/* ── the player ────────────────────────────────────────────────────
   One soft shell: no inner 1px seams, no native control bar. The
   frame owns the radius and every layer inside is absolutely
   positioned against it, so nothing can produce a hard corner.       */
.vp {
  position: relative;
  /* scroll-linked depth, as the floor card (data-depth, js/vocab.js) */
  transform: translate3d(0, var(--depth-y, 0px), 0) scale(var(--depth-s, 1));
}
.vp.is-full, .vp:fullscreen { transform: none; }
.vp-frame {
  position: relative; aspect-ratio: 16 / 9; width: 100%; overflow: hidden;
  border-radius: var(--radius-lg);
  background: radial-gradient(120% 120% at 30% 10%, var(--tile) 0%, var(--tile-2) 60%, var(--tile-2) 100%);
  box-shadow: var(--shadow-md), inset 0 0 0 1px var(--border);
  isolation: isolate;
}
.vp-frame video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; background: var(--fw-s90); cursor: pointer;
}

/* bottom-weighted scrim: the control bar needs contrast over bright
   frames, the top of the picture does not */
.vp-scrim {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, rgba(var(--fw-s90-rgb), .62) 0%, rgba(var(--fw-s90-rgb), .18) 26%, transparent 52%);
  opacity: 0; transition: opacity .25s var(--ease-out-quart);
}
.vp:hover .vp-scrim, .vp:focus-within .vp-scrim, .vp:not(.is-playing) .vp-scrim { opacity: 1; }

.vp-empty {
  position: absolute; inset: 0; display: none;
  flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 28px; gap: 6px;
}
.vp-empty-glyph { font-size: 12px; font-weight: 800; letter-spacing: .06em; color: var(--blue); }
.vp-empty p { font-size: 12.5px; color: var(--text-muted); line-height: 1.6; max-width: 320px; }
.vp.is-empty .vp-empty { display: flex; }
.vp.is-empty .vp-bar, .vp.is-empty .vp-bigplay, .vp.is-empty video { display: none; }

/* ── big play ── */
.vp-bigplay {
  position: absolute; inset: 0; margin: auto;
  width: max-content; height: max-content;
  display: flex; align-items: center; gap: 12px;
  padding: 10px 20px 10px 10px; border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .92); border: none;
  box-shadow: 0 10px 30px rgba(var(--fw-s90-rgb), .28);
  color: var(--fw-s70); font-family: var(--font); cursor: pointer;   /* a white pill in both themes: fixed deep ink */
  transition: transform .28s var(--ease-out-expo), opacity .25s var(--ease-out-quart), box-shadow .25s var(--ease-out-quart);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.vp-bigplay-ring {
  width: 42px; height: 42px; border-radius: 50%; flex: none;
  background: var(--blue); color: var(--on-blue);
  display: flex; align-items: center; justify-content: center;
}
.vp-bigplay-ring svg { width: 20px; height: 20px; fill: currentColor; margin-left: 2px; }
.vp-bigplay-text { font-size: 13px; font-weight: 700; display: flex; flex-direction: column; align-items: flex-start; line-height: 1.25; }
.vp-bigplay-text b { font-size: 11px; font-weight: 600; color: var(--fw-s10); font-variant-numeric: tabular-nums; }
.vp-bigplay:hover, .vp-bigplay:focus-visible { transform: scale(1.04); box-shadow: 0 14px 38px rgba(var(--fw-s90-rgb), .34); }
.vp-bigplay:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
/* once running it gets out of the way entirely */
.vp.is-playing .vp-bigplay { opacity: 0; transform: scale(.9); pointer-events: none; }

.vp-spinner {
  position: absolute; inset: 0; margin: auto; width: 34px; height: 34px;
  border-radius: 50%; border: 2.5px solid rgba(255,255,255,.35); border-top-color: #fff;
  opacity: 0; pointer-events: none; transition: opacity var(--dur-fast) var(--ease-out-quart);
}
.vp.is-buffering .vp-spinner { opacity: 1; animation: vp-spin .8s var(--ease-linear) infinite; }
@keyframes vp-spin { to { transform: rotate(360deg); } }

/* ── control bar ── */
.vp-bar {
  position: absolute; left: 10px; right: 10px; bottom: 10px;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-radius: var(--radius-pill);
  background: rgba(var(--fw-s90-rgb), .52);
  backdrop-filter: blur(14px) saturate(1.3); -webkit-backdrop-filter: blur(14px) saturate(1.3);
  opacity: 0; transform: translateY(8px);
  transition: opacity .25s var(--ease-out-quart), transform .25s var(--ease-out-expo);
}
.vp:hover .vp-bar, .vp:focus-within .vp-bar, .vp:not(.is-playing) .vp-bar { opacity: 1; transform: translateY(0); }
.vp-btn {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: transparent; border: none; cursor: pointer;
  color: #fff; display: flex; align-items: center; justify-content: center;
  transition: background var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart);
}
.vp-btn svg { width: 17px; height: 17px; fill: currentColor; }
.vp-btn:hover { background: rgba(255,255,255,.16); }
.vp-btn:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
.vp-time { font-size: 11px; font-weight: 700; color: rgba(255,255,255,.88); font-variant-numeric: tabular-nums; flex: none; }

.vp-scrub {
  position: relative; flex: 1 1 auto; height: 18px; cursor: pointer;
  display: flex; align-items: center; touch-action: none;
}
.vp-rail, .vp-buffered, .vp-played {
  position: absolute; left: 0; height: 4px; border-radius: var(--radius-pill);
  transition: height var(--dur-fast) var(--ease-out-quart);
}
.vp-rail { width: 100%; background: rgba(255,255,255,.24); }
.vp-buffered { width: 0; background: rgba(255,255,255,.34); }
.vp-played { width: 0; background: var(--blue); }
.vp-played::after {
  content: ""; position: absolute; right: -5px; top: 50%;
  width: 10px; height: 10px; border-radius: 50%; background: #fff;
  transform: translateY(-50%) scale(0); transition: transform var(--dur-fast) var(--ease-out-expo);
  box-shadow: 0 1px 4px rgba(0,0,0,.4);
}
.vp-scrub:hover .vp-rail, .vp-scrub:hover .vp-buffered, .vp-scrub:hover .vp-played,
.vp-scrub:focus-visible .vp-rail, .vp-scrub:focus-visible .vp-buffered, .vp-scrub:focus-visible .vp-played { height: 6px; }
.vp-scrub:hover .vp-played::after, .vp-scrub:focus-visible .vp-played::after { transform: translateY(-50%) scale(1); }
.vp-scrub:focus-visible { outline: 2px solid #fff; outline-offset: 3px; border-radius: var(--radius-pill); }
.vp-ticks { position: absolute; left: 0; right: 0; height: 100%; pointer-events: none; }
.vp-tick {
  position: absolute; top: 50%; width: 2px; height: 9px; margin-left: -1px;
  transform: translateY(-50%); border-radius: 1px; background: rgba(255,255,255,.75);
}

/* ── chapters ── */
.vp-chapters { list-style: none; display: flex; flex-direction: column; gap: 4px; margin: 2px 0 0; padding: 0; }
.vp-chapters.is-empty { display: none; }
.vp-chapter {
  width: 100%; display: flex; align-items: baseline; gap: 10px; text-align: left;
  background: transparent; border: 1px solid transparent; border-radius: var(--radius-md);
  padding: 7px 10px; cursor: pointer; font-family: var(--font);
  transition: background var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart);
}
.vp-chapter:hover { background: var(--tile); transform: translateX(2px); }
.vp-chapter:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.vp-chapter-time { font-size: 11px; font-weight: 700; color: var(--text-faint); font-variant-numeric: tabular-nums; flex: none; }
.vp-chapter-label { font-size: 12.5px; font-weight: 600; color: var(--text-muted); line-height: 1.4; }
.vp-chapter.is-active { background: var(--blue-dim); border-color: var(--blue); }
.vp-chapter.is-active .vp-chapter-time,
.vp-chapter.is-active .vp-chapter-label { color: var(--blue); }

/* ── category filter ── */
.plant-filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.plant-filter {
  background: var(--surface); border: 1px solid var(--border); color: var(--text-muted);
  font-family: var(--font); font-size: 12px; font-weight: 700;
  padding: 7px 14px; border-radius: var(--radius-pill); cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  transition: color var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart), background var(--dur-fast) var(--ease-out-quart), transform var(--dur-fast) var(--ease-out-quart);
}
.plant-filter:hover { border-color: var(--blue); color: var(--blue); transform: translateY(-1px); }
.plant-filter:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.plant-filter b { font-size: 10.5px; font-weight: 700; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.plant-filter[aria-pressed="true"] { background: var(--blue); border-color: var(--blue); color: var(--on-blue); }
.plant-filter[aria-pressed="true"] b { color: rgba(255,255,255,.75); }
.plant-empty { text-align: center; font-size: 13px; color: var(--text-muted); padding: 20px 0; }

@media (prefers-reduced-motion: reduce) {
  .vp-bar, .vp-bigplay, .vp-scrim, .vp-chapter, .plant-filter, .plant-stat { transition: opacity var(--dur-fast) var(--ease-out-quart); }
  .vp.is-buffering .vp-spinner { animation-duration: 1.6s; }
}

/* ===================== view transitions (transitions.js) ===================== */
/* Progressive enhancement over the FLIP ghost: where the browser supports
   document.startViewTransition, the selected card and the detail kiosk share
   a view-transition-name and the browser morphs one into the other. The
   page's own .page transitions are suspended for the swap (the root
   cross-fade replaces them). Timing uses the same motion tokens. */
.vt-running .page { transition: none !important; }
::view-transition-group(fw-shared) {
  animation-duration: var(--dur-slow);
  animation-timing-function: var(--ease-out-expo);
}
::view-transition-old(fw-shared),
::view-transition-new(fw-shared) {
  height: 100%; object-fit: cover; overflow: clip;
  animation-duration: var(--dur-base);
  animation-timing-function: var(--ease-out-quart);
}
/* the outgoing page clears in --dur-fast while the incoming one arrives over
   --dur-base, so the two views never sit double-exposed behind the morph */
::view-transition-old(root) {
  animation-duration: var(--dur-fast);
  animation-timing-function: var(--ease-out-quart);
}
::view-transition-new(root) {
  animation-duration: var(--dur-base);
  animation-timing-function: var(--ease-out-quart);
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
