/* ==========================================
   IT-Impulse Reception Engine V1
   SVG silhouette hotspots + cinematic travel
   (loads with campus.css for panels / terminal)
   ========================================== */

/* Legacy white-dot / floor-map classes removed from CSS; guard if markup reappears */
.reception-hotspots,
.reception-hotspot,
.campus-map {
  display: none !important;
}

/* SR / keyboard failsafe — not a visual white-dot map */
.reception-skip-nav {
  position: absolute;
  z-index: 20;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
  padding: 0;
  margin: 0;
  border: 0;
}

.reception-skip-nav:focus-within {
  left: var(--nx-gutter, 16px);
  top: calc(72px + env(safe-area-inset-top, 0px));
  width: auto;
  height: auto;
  max-width: min(22rem, calc(100% - 32px));
  padding: 12px 14px;
  overflow: visible;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--campus-glass-strong, rgba(248, 250, 252, 0.92));
  border: 1px solid var(--nx-border-glass, rgba(255, 255, 255, 0.45));
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(10, 16, 24, 0.14);
}

.reception-skip-nav__title {
  margin: 0 0 4px;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.55;
}

.reception-skip-nav button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  min-height: 44px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.reception-skip-nav button:hover,
.reception-skip-nav button:focus-visible {
  background: rgba(255, 255, 255, 0.55);
  border-color: rgba(20, 24, 30, 0.18);
  outline: none;
}

body.is-in-room .reception-skip-nav,
body.is-traveling .reception-skip-nav {
  display: none;
}

/* ---- Stage: plate + SVG share one parallax group ---- */
.reception-stage {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background: #b8c2ca;
  transform-origin: var(--travel-x, 50%) var(--travel-y, 50%);
  transition: transform 1.05s cubic-bezier(0.22, 1, 0.36, 1);
  backface-visibility: hidden;
}

.reception-stage.is-zooming {
  transform: scale(1.08);
}

.reception-stage.is-approach-zoom {
  transform: scale(1.14);
}

.reception-stage.is-screen-dive-zoom {
  transform: scale(1.28);
}

.reception-parallax {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
}

.reception-plate {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Wide lobby (~21:9): cover crops side padding on 16:9, full scene on ultrawide */
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  user-select: none;
  -webkit-user-drag: none;
  image-rendering: auto;
}

/* Cloud Hall plate: keep racks centered in the frame */
.reception-plate[data-room="cloud"] {
  object-position: 50% 52%;
}

.reception-plate.is-active {
  opacity: 1;
}

.reception-stage__vignette {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 75% 65% at 50% 42%, transparent 30%, rgba(10, 16, 24, 0.18) 100%),
    linear-gradient(180deg, rgba(10, 16, 24, 0.1) 0%, transparent 32%, transparent 58%, rgba(10, 16, 24, 0.24) 100%);
  pointer-events: none;
  transition: background 0.8s ease;
  z-index: 1;
}

body.is-approaching .reception-stage__vignette,
body.is-screen-diving .reception-stage__vignette {
  background:
    radial-gradient(
      ellipse 55% 50% at var(--travel-x, 50%) var(--travel-y, 50%),
      transparent 0%,
      rgba(10, 16, 24, 0.1) 40%,
      rgba(10, 16, 24, 0.5) 100%
    );
}

/* ---- SVG hotspot overlay ---- */
.reception-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  pointer-events: none;
  overflow: visible;
}

/* Idle: impulse trace only (no dark charcoal bed — reads clean on bright lobby) */
.reception-svg .hotspot-path {
  fill: transparent;
  stroke: transparent;
  stroke-width: 2.6;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 9999;
  stroke-dashoffset: 0;
  pointer-events: none;
  outline: none;
  opacity: 1;
  transition:
    fill 520ms cubic-bezier(0.22, 1, 0.36, 1),
    stroke 520ms cubic-bezier(0.22, 1, 0.36, 1),
    stroke-width 520ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 520ms cubic-bezier(0.22, 1, 0.36, 1);
  filter: none;
  animation: none;
}

/* Rail off by default — was reading as a thick dark outline */
.reception-svg .hotspot-rail {
  fill: none;
  stroke: rgba(8, 10, 14, 0.35);
  stroke-width: 2.4;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
  opacity: 0;
  transition: opacity 280ms ease;
}

.reception-svg .hotspot-trace {
  fill: none;
  stroke: url(#rx-idle-flow);
  stroke-width: 2.6;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: var(--rx-segment, 120) var(--rx-gap, 840);
  stroke-dashoffset: 0;
  pointer-events: none;
  opacity: 1;
  filter: none;
  animation: none;
  transition:
    opacity 480ms cubic-bezier(0.22, 1, 0.36, 1),
    stroke 480ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: stroke-dashoffset, opacity;
}

/* Invisible fat-finger hit layer (≥ ~44px effective on coarse pointers) */
.reception-svg .hotspot-hit {
  fill: rgba(0, 0, 0, 0.001);
  stroke: rgba(0, 0, 0, 0.001);
  stroke-width: 18;
  vector-effect: non-scaling-stroke;
  cursor: pointer;
  pointer-events: visiblePainted;
  outline: none;
}

.reception-svg .hotspot-path.is-hot,
.reception-svg .hotspot-path.is-focus,
.reception-svg .hotspot-path.is-tour {
  fill: rgba(212, 196, 168, 0.06);
  stroke: url(#rx-hover-gradient);
  stroke-width: 2.4;
  stroke-dasharray: 9999;
  filter: none;
  animation: rx-breathe 3.8s ease-in-out infinite;
  animation-delay: 0.35s;
  opacity: 1;
}

.reception-svg .hotspot-path.is-focus {
  stroke: #d4c4a8;
  fill: rgba(212, 196, 168, 0.06);
}

.reception-svg .hotspot-path.is-hot + .hotspot-rail,
.reception-svg .hotspot-path.is-focus + .hotspot-rail {
  opacity: 0;
}

/* The solid outline takes over while an object is lit, so the travelling
   impulse steps aside rather than crawling across it. */
.reception-svg .hotspot-trace.is-hot,
.reception-svg .hotspot-trace.is-tour {
  opacity: 0.12;
}

.reception-svg .hotspot-path.is-tour + .hotspot-rail {
  opacity: 0;
}

.reception-svg .hotspot-hit:focus-visible {
  outline: 1.5px solid rgba(255, 255, 255, 0.7);
  outline-offset: 3px;
  stroke: rgba(255, 255, 255, 0.35);
  stroke-width: 3;
}

@keyframes rx-breathe {
  0%, 100% { opacity: 0.88; }
  50% { opacity: 1; }
}

@keyframes rx-outline-breathe {
  0%, 100% {
    opacity: 0.78;
    stroke-width: 2.3;
  }
  50% {
    opacity: 0.95;
    stroke-width: 2.7;
  }
}

body.is-traveling .reception-svg {
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none !important;
}

body.is-in-lobby:not(.is-traveling) .reception-svg {
  opacity: 1;
  transition: opacity 0.55s 0.08s ease;
}

body.is-in-room .reception-svg {
  visibility: hidden;
  pointer-events: none;
}

/* ---- Entrance copy over the lobby ----
   Top-left, over the wall above the server racks. Every marker in the lobby
   sits lower than this, so the copy never buries one — the first attempt was
   anchored to the floor and swallowed the racks and the NAS. The Cloud Hall
   plate does open into this corner, which is why the block steps aside
   whenever a plate is up. */
.rx-hero {
  position: absolute;
  left: clamp(20px, 4vw, 56px);
  top: clamp(76px, 11vh, 116px);
  z-index: 5;
  max-width: min(29rem, 62vw);
  padding: 22px 26px 20px;
  border-radius: var(--nx-radius-lg, 18px);
  background:
    linear-gradient(165deg, rgba(28, 34, 46, 0.74) 0%, rgba(14, 18, 26, 0.8) 100%),
    rgba(16, 22, 32, 0.74);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 22px 56px rgba(10, 16, 24, 0.4);
  backdrop-filter: blur(20px) saturate(1.15);
  -webkit-backdrop-filter: blur(20px) saturate(1.15);
  color: #f2f4f7;
  transition:
    opacity 360ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 360ms cubic-bezier(0.22, 1, 0.36, 1);
}

.rx-hero__eyebrow {
  margin: 0 0 10px;
  font-family: var(--nx-font-mono, ui-monospace, "SF Mono", monospace);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(232, 217, 184, 0.86);
}

.rx-hero__title {
  margin: 0 0 10px;
  font-family: var(--nx-font-display, Georgia, serif);
  font-size: clamp(1.6rem, 2.6vw, 2.3rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: #fbfcfd;
}

.rx-hero__lede {
  margin: 0 0 18px;
  font-size: 0.94rem;
  line-height: 1.5;
  color: rgba(226, 231, 238, 0.84);
}

.rx-hero__acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

.rx-hero__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 20px;
  border-radius: 999px;
  background: #e8d9b8;
  color: #14161b;
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid rgba(255, 255, 255, 0.24);
  transition: background-color 220ms ease, transform 220ms ease;
}

.rx-hero__cta:hover {
  background: #f4ead2;
  transform: translateY(-1px);
}

.rx-hero__ghost {
  font-size: 0.9rem;
  color: rgba(232, 237, 244, 0.9);
  text-decoration: none;
  border-bottom: 1px solid rgba(232, 217, 184, 0.42);
  padding-bottom: 2px;
  transition: color 220ms ease, border-color 220ms ease;
}

.rx-hero__ghost:hover {
  color: #fff;
  border-bottom-color: rgba(232, 217, 184, 0.9);
}

.rx-hero__hint {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.78rem;
  line-height: 1.4;
  color: rgba(206, 214, 224, 0.78);
}

.rx-hero__hint--narrow {
  display: none;
}

.rx-hero__hint-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #e8d9b8;
  box-shadow: 0 0 0 0 rgba(232, 217, 184, 0.55);
  animation: rx-hint-ping 2.8s ease-out infinite;
}

@keyframes rx-hint-ping {
  0% { box-shadow: 0 0 0 0 rgba(232, 217, 184, 0.5); }
  70%, 100% { box-shadow: 0 0 0 9px rgba(232, 217, 184, 0); }
}

.reception-root.has-portal .rx-hero {
  opacity: 0;
  transform: translateY(8px);
}

body.is-traveling .rx-hero,
body.is-in-room .rx-hero {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s 0.3s;
}

/* A phone crops the landscape lobby to a narrow slice and puts the tall mobile
   header where the copy sat, so the block moves to the floor at the bottom —
   the empty part of that crop — and the objects above it stay in view. */
@media (max-width: 720px) {
  .rx-hero {
    left: 12px;
    right: 12px;
    top: auto;
    bottom: 12px;
    max-width: none;
    padding: 16px 16px 14px;
  }

  .rx-hero__title {
    font-size: 1.45rem;
  }

  .rx-hero__lede {
    margin-bottom: 14px;
    font-size: 0.85rem;
  }

  .rx-hero__hint {
    margin-top: 14px;
    padding-top: 12px;
    font-size: 0.74rem;
  }

  .rx-hero__hint--wide {
    display: none;
  }

  .rx-hero__hint--narrow {
    display: inline;
  }

  /* Only the reception desk survives this crop; a lone marker floating over it
     teaches nothing, so the halls are reached from the buttons above instead. */
  .rx-pins {
    display: none;
  }
}

/* ---- Standing markers over the interactive objects ----
   Without these the lobby is a photograph with nothing to say: the silhouettes
   are transparent at rest and the impulse that travels along them is a 2.6px
   line lit for a twentieth of its own track, which nobody catches. A pin says
   "there is something here" and hands the explaining over to the plate on
   hover. Purely decorative — the SVG hit paths beneath own the clicks, the
   focus ring and the accessible names. */
.rx-pins {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  overflow: hidden;
}

.rx-pin {
  --rx-pin-x: 50%;
  --rx-pin-y: 50%;
  --rx-pin-depth: 1;
  --rx-pin-size: 30px;
  position: absolute;
  left: var(--rx-pin-x);
  top: var(--rx-pin-y);
  display: grid;
  place-items: center;
  width: var(--rx-pin-size);
  height: var(--rx-pin-size);
  border-radius: 50%;
  color: #f6f2e8;
  font-family: var(--nx-font-mono, ui-monospace, "SF Mono", monospace);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  background: rgba(18, 20, 26, 0.62);
  border: 1px solid rgba(232, 217, 184, 0.5);
  box-shadow:
    0 2px 10px rgba(8, 10, 14, 0.42),
    inset 0 1px 0 rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(7px) saturate(1.15);
  -webkit-backdrop-filter: blur(7px) saturate(1.15);
  opacity: 0;
  transform: translate(-50%, -50%) scale(var(--rx-pin-depth));
  transition:
    opacity 420ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 420ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 420ms ease,
    background-color 420ms ease;
}

/* Placed only once the silhouette has been measured, so a pin never flashes at
   the middle of the screen before it knows where it belongs. */
.rx-pin.is-placed {
  opacity: 0.92;
}

.rx-pin__mark {
  position: relative;
  z-index: 1;
  line-height: 1;
}

/* Briefing and the contact terminal are not catalogue services and carry no
   number, so they get a plain bead instead of a label. */
.rx-pin--plain {
  --rx-pin-size: 22px;
}

.rx-pin--plain .rx-pin__mark {
  display: none;
}

.rx-pin--plain .rx-pin__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #e8d9b8;
}

/* The halo, not the pin itself, carries the breathing: animating a blurred
   pseudo-element keeps the number crisp and the work off the main thread. */
.rx-pin::before {
  content: "";
  position: absolute;
  inset: -7px;
  border-radius: 50%;
  border: 1px solid rgba(232, 217, 184, 0.32);
  opacity: 0;
  transform: scale(0.82);
  transition:
    opacity 420ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.rx-pin.is-placed::before {
  animation: rx-pin-breathe 4.4s ease-in-out infinite;
}

.rx-pin:nth-of-type(2n)::before { animation-delay: 0.9s; }
.rx-pin:nth-of-type(3n)::before { animation-delay: 1.8s; }

.rx-pin.is-hot,
.rx-pin.is-tour {
  opacity: 1;
  background: rgba(232, 217, 184, 0.94);
  border-color: rgba(255, 255, 255, 0.85);
  color: #14161b;
  transform: translate(-50%, -50%) scale(calc(var(--rx-pin-depth) * 1.28));
}

.rx-pin.is-hot .rx-pin__dot,
.rx-pin.is-tour .rx-pin__dot {
  background: #14161b;
}

.rx-pin.is-hot::before,
.rx-pin.is-tour::before {
  animation: none;
  opacity: 1;
  transform: scale(1);
  border-color: rgba(232, 217, 184, 0.75);
}

@keyframes rx-pin-breathe {
  0%, 100% { opacity: 0; transform: scale(0.82); }
  45% { opacity: 0.75; transform: scale(1.06); }
  70% { opacity: 0; transform: scale(1.24); }
}

body.is-traveling .rx-pins,
body.is-in-room .rx-pins {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s 0.3s;
}

/* ---- Thematic hover portals (unique mini-windows per room) ---- */
.rx-portals {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  overflow: hidden;
}

.rx-portal {
  --rx-px: 50%;
  --rx-py: 50%;
  --rx-lift: 16px;
  --rx-ox: 0px;
  --rx-width: 244px;
  --rx-glass-edge: rgba(255, 255, 255, 0.16);
  --rx-accent: #d4c4a8;
  --rx-text: #f5f6f8;
  --rx-muted: rgba(200, 206, 214, 0.72);
  position: absolute;
  left: var(--rx-px);
  top: var(--rx-py);
  width: min(var(--rx-width), 72vw);
  transform:
    translate(calc(-50% + var(--rx-ox)), calc(-100% - 18px - var(--rx-lift)))
    translateY(6px);
  visibility: hidden;
  pointer-events: none;
  transform-origin: 50% 100%;
  /* slide only — opacity fade desyncs text vs backdrop-filter */
  transition:
    transform 0.42s cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s linear 0.42s;
}

.rx-portal.is-visible {
  visibility: visible;
  /* Informational only — click always goes to the hotspot */
  pointer-events: none;
  transform:
    translate(calc(-50% + var(--rx-ox)), calc(-100% - 18px - var(--rx-lift)))
    translateY(0);
  transition:
    transform 0.42s cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s;
}

.rx-portal.is-below {
  transform:
    translate(calc(-50% + var(--rx-ox)), calc(18px + var(--rx-lift) * 0.35))
    translateY(-5px);
  transform-origin: 50% 0%;
}

.rx-portal.is-below.is-visible {
  transform:
    translate(calc(-50% + var(--rx-ox)), calc(18px + var(--rx-lift) * 0.35))
    translateY(0);
}

.rx-portal__shell {
  position: relative;
  padding: 14px 18px 13px;
  color: var(--rx-text);
  overflow: visible;
  border-radius: 16px;
  background: transparent;
  border: none;
  box-shadow: none;
}

.rx-portal__shell::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background:
    linear-gradient(165deg, rgba(36, 38, 44, 0.62) 0%, rgba(14, 16, 20, 0.68) 100%);
  border: 1px solid var(--rx-glass-edge);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.08) inset,
    0 18px 40px rgba(6, 8, 12, 0.35);
  backdrop-filter: blur(14px) saturate(1.12);
  -webkit-backdrop-filter: blur(14px) saturate(1.12);
  transform: translateZ(0);
  pointer-events: none;
}

.rx-portal__head {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 9px;
}

/* The number is set as a door plate rather than loose text: on a sign the
   room number is the first thing you look for. */
.rx-portal__idx {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 19px;
  padding: 0 6px;
  border-radius: 5px;
  border: 1px solid rgba(232, 217, 184, 0.34);
  background: rgba(232, 217, 184, 0.12);
  font-family: var(--nx-font-mono, ui-monospace, monospace);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
  color: var(--rx-accent);
}

.rx-portal__glyph {
  display: inline-flex;
  width: 19px;
  height: 19px;
  color: rgba(232, 217, 184, 0.72);
}

.rx-portal__glyph svg {
  width: 100%;
  height: 100%;
}

.rx-portal__title {
  position: relative;
  z-index: 2;
  display: block;
  font-family: var(--nx-font-display, Georgia, serif);
  font-weight: 400;
  font-size: 1.2rem;
  line-height: 1.14;
  letter-spacing: -0.02em;
  color: var(--rx-text);
}

.rx-portal__sub {
  position: relative;
  z-index: 2;
  display: block;
  margin-top: 3px;
  font-size: 0.74rem;
  line-height: 1.4;
  color: rgba(220, 224, 230, 0.7);
}

/* Every hall gets the same 220x20 window of motion, so the panels keep one
   silhouette while each keeps its own character. */
.rx-portal__strip {
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  height: 20px;
  margin: 11px 0 9px;
  opacity: 0.85;
}

.rx-portal__foot {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-top: 9px;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
}

/* One line, always: a second line of tags would push the cue down and the
   panels would stop being the same height, which is the whole point of the
   redesign. */
.rx-portal__tags {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-family: var(--nx-font-mono, ui-monospace, monospace);
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--rx-muted);
}

/* A hint, not a button: the plate never takes the pointer, the object under it
   does. It says what a click will do, which is the one thing the old plates
   never told anybody — the copy for it existed in the engine all along and was
   switched off in the stylesheet. */
.rx-portal__cue {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  font-size: 0.68rem;
  font-weight: 500;
  white-space: nowrap;
  color: var(--rx-accent);
}

.rx-portal__cue svg {
  width: 12px;
  height: 12px;
  transform: translateX(-2px);
  transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.rx-portal.is-visible .rx-portal__cue svg {
  transform: translateX(0);
}

/* Leader line down to the object the sign names. */
.rx-portal__lead {
  position: absolute;
  left: 50%;
  top: 100%;
  width: 1px;
  height: calc(var(--rx-lift, 16px) + 12px);
  background: linear-gradient(180deg, rgba(232, 217, 184, 0.9), rgba(232, 217, 184, 0));
  transform: translateX(-50%);
  pointer-events: none;
  /* The lobby behind a sign can be a sunlit window; a hairline needs its own
     shadow to survive there. */
  filter: drop-shadow(0 0 2px rgba(8, 10, 14, 0.55));
}

.rx-portal__lead::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  border: 1px solid rgba(232, 217, 184, 0.85);
  background: rgba(232, 217, 184, 0.25);
  transform: translate(-50%, 50%);
}

/* When the sign sits under its object the line points the other way. */
.rx-portal.is-below .rx-portal__lead {
  top: auto;
  bottom: 100%;
  background: linear-gradient(0deg, rgba(232, 217, 184, 0.9), rgba(232, 217, 184, 0));
}

.rx-portal.is-below .rx-portal__lead::after {
  bottom: auto;
  top: 0;
  transform: translate(-50%, -50%);
}

/* Per-hall motion. The strips share one grammar; only the movement differs. */
.rx-p-node {
  transform-box: fill-box;
  transform-origin: center;
  animation: rx-node-pulse 2.4s ease-in-out infinite;
}

.rx-p-node:nth-of-type(2) { animation-delay: 0.35s; }
.rx-p-node:nth-of-type(3) { animation-delay: 0.7s; }
.rx-p-node:nth-of-type(4) { animation-delay: 1.05s; }

.rx-p-packet {
  stroke-dasharray: 8 110;
  animation: rx-packet-run 3.2s linear infinite;
}

.rx-p-queue {
  animation: rx-queue-run 2.6s linear infinite;
}

.rx-p-cursor {
  animation: rx-blink 1.05s steps(1) infinite;
}

.rx-p-sweep-x {
  animation: rx-sweep-x 3.4s ease-in-out infinite;
}

.rx-p-ring {
  transform-origin: 110px 10px;
  animation: rx-spin-slow 8s linear infinite;
}

.rx-p-bars rect {
  transform-box: fill-box;
  transform-origin: bottom;
  animation: rx-bar-pulse 1.8s ease-in-out infinite;
}

.rx-p-bars rect:nth-child(2) { animation-delay: 0.15s; }
.rx-p-bars rect:nth-child(3) { animation-delay: 0.3s; }
.rx-p-bars rect:nth-child(4) { animation-delay: 0.45s; }

.rx-p-scan {
  animation: rx-scanline 2.8s linear infinite;
}

@keyframes rx-queue-run {
  to { stroke-dashoffset: -48; }
}

@keyframes rx-sweep-x {
  0% { transform: translateX(0); }
  100% { transform: translateX(250px); }
}

body.is-traveling .rx-portals,
body.is-in-room .rx-portals {
  opacity: 0;
  visibility: hidden;
}

@keyframes rx-node-pulse {
  0%, 100% { transform: scale(0.85); opacity: 0.5; }
  50% { transform: scale(1.25); opacity: 1; }
}

@keyframes rx-packet-run {
  0% { stroke-dashoffset: 120; opacity: 0.25; }
  25% { opacity: 1; }
  75% { opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 0.25; }
}

@keyframes rx-spin-slow {
  to { transform: rotate(360deg); }
}

@keyframes rx-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@keyframes rx-bar-pulse {
  0%, 100% { transform: scaleY(0.55); opacity: 0.55; }
  50% { transform: scaleY(1); opacity: 1; }
}

@keyframes rx-scanline {
  0% { transform: translateY(-120%); }
  100% { transform: translateY(220%); }
}

@media (max-width: 720px) {
  .rx-portal {
    width: min(190px, 62vw);
  }

  .rx-portal__title {
    font-size: 1.05rem;
  }

  .rx-portal__cue {
    font-size: 0.64rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rx-portal,
  .rx-portal.is-visible,
  .rx-portal.is-below,
  .rx-portal.is-below.is-visible {
    transition: visibility 0s;
    transform: translate(-50%, calc(-100% - 12px - var(--rx-lift, 0px)));
  }

  .rx-portal.is-below,
  .rx-portal.is-below.is-visible {
    transform: translate(-50%, calc(14px + var(--rx-lift, 0px) * 0.25));
  }

  /* Everything that moves inside a strip, by class rather than by hall, so a
     new hall cannot quietly escape the preference. */
  .rx-portal__strip * {
    animation: none !important;
  }

  .rx-portal__cue svg,
  .rx-portal.is-visible .rx-portal__cue svg {
    transition: none;
    transform: none;
  }
}

/* ---- Room panels: dark glass overlay (readable on bright lobby) ---- */
.reception-panel {
  max-width: 32rem;
  padding: 22px 24px 20px;
  background:
    linear-gradient(165deg, rgba(28, 34, 46, 0.72) 0%, rgba(14, 18, 26, 0.78) 100%),
    rgba(16, 22, 32, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 18px 48px rgba(10, 16, 24, 0.35);
  color: #f2f4f7;
  backdrop-filter: blur(20px) saturate(1.15);
  -webkit-backdrop-filter: blur(20px) saturate(1.15);
}

.reception-panel .nx-eyebrow {
  color: rgba(242, 244, 247, 0.55);
}

.reception-panel .campus-panel__title {
  font-size: clamp(1.35rem, 2.6vw, 1.85rem);
  margin-bottom: 8px;
  color: #f2f4f7;
}

.reception-panel .campus-panel__body {
  margin-bottom: 14px;
  font-size: 0.94rem;
  line-height: 1.5;
  color: rgba(242, 244, 247, 0.72);
}

.reception-panel .campus-panel__body strong {
  color: #f2f4f7;
}

.reception-panel .campus-panel__list {
  margin-bottom: 14px;
  gap: 6px;
}

.reception-panel .campus-panel__list li {
  font-size: 0.88rem;
  color: rgba(242, 244, 247, 0.72);
}

.reception-panel .campus-panel__list li::before {
  background: rgba(242, 244, 247, 0.85);
}

.reception-panel .campus-panel__price {
  margin-bottom: 14px;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  color: #f2f4f7;
}

.reception-panel__kpis {
  justify-content: flex-start;
  gap: 16px 24px;
  margin: 4px 0 16px;
}

.reception-panel__kpis .campus-kpi .num {
  font-size: 1.2rem;
  color: #f2f4f7;
}

.reception-panel__kpis .campus-kpi .lbl {
  color: rgba(242, 244, 247, 0.55);
}

.reception-panel--briefing {
  max-width: 42rem;
}

.reception-compare .campus-compare__tag,
.reception-compare .campus-compare__col,
.reception-bars .campus-bar__top,
.reception-bars .campus-bar__top .val {
  color: rgba(242, 244, 247, 0.78);
}

/* ---- Mini-calc (Briefing) — dark chips, not white blanks ---- */
.mini-calc {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 4px;
  text-align: left;
  color: #f2f4f7;
}

.mini-calc__presets {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.mini-calc__preset {
  flex: 1 1 calc(33.333% - 8px);
  min-width: 7.5rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(8px);
  color: #f2f4f7;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease, transform 0.18s ease;
}

.mini-calc__preset:hover,
.mini-calc__preset:focus-visible {
  border-color: rgba(255, 255, 255, 0.28);
  background: rgba(255, 255, 255, 0.12);
  outline: none;
}

.mini-calc__preset.is-active {
  border-color: rgba(120, 190, 255, 0.55);
  background: rgba(80, 140, 220, 0.22);
  box-shadow: inset 0 0 0 1px rgba(120, 190, 255, 0.18);
}

.mini-calc__preset .ph {
  font-size: 1.1rem;
  opacity: 0.8;
  margin-bottom: 2px;
  color: #f2f4f7;
}

.mini-calc__preset-name {
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.25;
  color: #f2f4f7;
}

.mini-calc__preset-aud {
  font-size: 0.72rem;
  color: rgba(242, 244, 247, 0.55);
  line-height: 1.2;
}

.mini-calc__summary {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin-top: 4px;
  padding: 12px 14px 10px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(10, 14, 22, 0.72);
  backdrop-filter: blur(14px);
  box-shadow: 0 -8px 28px rgba(10, 16, 24, 0.25);
  color: #f2f4f7;
}

.mini-calc__summary--pulse .mini-calc__value {
  animation: mini-calc-pulse 0.45s ease;
}

@keyframes mini-calc-pulse {
  0% { transform: scale(1); }
  40% { transform: scale(1.04); }
  100% { transform: scale(1); }
}

.mini-calc__totals {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 28px;
  align-items: flex-end;
}

.mini-calc__total {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.mini-calc__label {
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: rgba(242, 244, 247, 0.5);
}

.mini-calc__hint {
  text-transform: none;
  letter-spacing: 0;
  color: rgba(242, 244, 247, 0.72);
}

.mini-calc__hint:empty {
  display: none;
}

.mini-calc__hint:not(:empty)::before {
  content: "· ";
}

.mini-calc__value {
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  color: #f2f4f7;
}

.mini-calc__value--sm {
  font-size: 1.05rem;
  font-weight: 600;
}

.mini-calc__meta {
  margin: 8px 0 0;
  font-size: 0.78rem;
  color: rgba(242, 244, 247, 0.55);
  line-height: 1.35;
}

.mini-calc__actions {
  margin: 12px 0 0;
}

@media (prefers-reduced-motion: reduce) {
  .mini-calc__summary--pulse .mini-calc__value {
    animation: none;
  }

  .mini-calc__preset {
    transition: none;
  }
}

.reception-room:not(.reception-room--terminal) {
  overflow: auto;
  overscroll-behavior: contain;
}

.reception-room:not(.reception-room--terminal) .reception-back {
  position: sticky;
  top: 0;
  z-index: 2;
  flex-shrink: 0;
  color: #f2f4f7;
  background:
    linear-gradient(165deg, rgba(28, 34, 46, 0.72) 0%, rgba(14, 18, 26, 0.78) 100%),
    rgba(16, 22, 32, 0.72);
  border-color: rgba(255, 255, 255, 0.14);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 10px 28px rgba(10, 16, 24, 0.28);
}

.reception-room:not(.reception-room--terminal) .reception-back:hover {
  background: rgba(28, 34, 46, 0.9);
  border-color: rgba(255, 255, 255, 0.22);
}

/* Removed room veil layer to prevent accidental interaction overlap. */

.reception-room > * {
  position: relative;
  z-index: 2;
}

/* Studio: explicit anchor so panel sits cleanly on right monitor area */
.reception-room--studio {
  align-items: flex-end;
}

.reception-panel--studio {
  width: min(33rem, calc(100vw - 2 * var(--nx-gutter, 16px)));
  margin-right: clamp(10px, 3vw, 48px);
  margin-top: clamp(8px, 2vh, 24px);
  margin-left: 0;
}

/* Cloud: back stays centered over racks; card sits left of center */
.reception-room--cloud {
  align-items: center;
}

.reception-room--cloud .reception-back--cloud {
  align-self: center;
  margin-left: -4vw;
}

.reception-panel--cloud {
  width: min(32rem, calc(100vw - 2 * var(--nx-gutter, 16px)));
  margin-left: auto;
  margin-right: auto;
  margin-top: clamp(8px, 2vh, 24px);
  /* Use left, not transform — room-panel-in animation ends at transform:none */
  position: relative;
  left: -1.25vw;
  text-align: left;
}

/* Vault / Backup: banner + back on the right — NAS stays readable on the left */
.reception-room--vault {
  align-items: flex-end;
}

.reception-room--vault .reception-back--vault {
  align-self: flex-end;
  margin-right: clamp(10px, 3vw, 48px);
}

.reception-panel--vault {
  width: min(32rem, calc(100vw - 2 * var(--nx-gutter, 16px)));
  margin-right: clamp(10px, 3vw, 48px);
  margin-top: clamp(8px, 2vh, 24px);
  margin-left: 0;
  text-align: left;
}

.reception-plate[data-room="vault"] {
  object-position: 38% 55%;
}

/* Desk / Service Desk: banner + back on the right — counter + TV stay in frame */
.reception-room--desk {
  align-items: flex-end;
}

.reception-room--desk .reception-back--desk {
  align-self: flex-end;
  margin-right: clamp(10px, 3vw, 48px);
}

.reception-panel--desk {
  width: min(32rem, calc(100vw - 2 * var(--nx-gutter, 16px)));
  margin-right: clamp(10px, 3vw, 48px);
  margin-top: clamp(8px, 2vh, 24px);
  margin-left: 0;
  text-align: left;
}

.reception-plate[data-room="desk"] {
  object-position: 42% 52%;
}

/* Briefing: wide pricing card on the left — wall screen stays readable on the right */
.reception-room--briefing {
  align-items: flex-start;
}

.reception-room--briefing .reception-back--briefing {
  align-self: flex-start;
  margin-left: 0;
}

.reception-panel--briefing {
  width: min(42rem, calc(100vw - 2 * var(--nx-gutter, 16px)));
  margin-left: 0;
  margin-right: auto;
  margin-top: clamp(8px, 2vh, 24px);
  text-align: left;
}

.reception-plate[data-room="briefing"] {
  /* Wall dashboard + desk; leave left free for pricing panel */
  object-position: 58% 42%;
}

/* Mobile / coarse: shorter dolly, larger hits, bottom sheet */
@media (max-width: 720px), (pointer: coarse) {
  .reception-stage {
    transition-duration: 0.65s;
  }

  .reception-stage.is-zooming {
    transform: scale(1.04);
  }

  .reception-stage.is-approach-zoom {
    transform: scale(1.07);
  }

  .reception-stage.is-screen-dive-zoom {
    transform: scale(1.14);
  }

  .reception-svg .hotspot-hit {
    stroke-width: 28;
  }
}

/* Mobile: bottom sheet; Back stays above content */
@media (max-width: 720px) {
  .reception-svg .hotspot-path {
    stroke-width: 2.2;
    stroke-dasharray: 9999;
  }

  .reception-svg .hotspot-trace {
    stroke-width: 2.8;
    stroke-dasharray: var(--rx-segment, 104) var(--rx-gap, 856);
  }

  .reception-svg .hotspot-path.is-hot,
  .reception-svg .hotspot-path.is-tour {
    stroke-width: 2.5;
  }

  .reception-room:not(.reception-room--terminal) {
    justify-content: flex-end;
    padding:
      calc(72px + env(safe-area-inset-top, 0px))
      max(12px, env(safe-area-inset-right, 0px))
      max(12px, env(safe-area-inset-bottom, 0px))
      max(12px, env(safe-area-inset-left, 0px));
    gap: 0;
  }

  .reception-room:not(.reception-room--terminal) .reception-back {
    position: sticky;
    top: 0;
    align-self: flex-start;
    margin-bottom: 10px;
    box-shadow: 0 8px 24px rgba(10, 16, 24, 0.12);
  }

  .reception-panel {
    max-width: none;
    width: 100%;
    margin: 0;
    padding: 18px 16px 16px;
    border-radius: 18px 18px 12px 12px;
    max-height: min(62vh, 520px);
    overflow: auto;
    -webkit-overflow-scrolling: touch;
  }

  .reception-panel--studio,
  .reception-panel--cloud,
  .reception-panel--vault,
  .reception-panel--desk,
  .reception-panel--briefing {
    width: 100%;
    margin: 0;
    transform: none;
    left: 0;
  }

  .reception-room--cloud .reception-back--cloud,
  .reception-room--vault .reception-back--vault,
  .reception-room--desk .reception-back--desk,
  .reception-room--briefing .reception-back--briefing {
    align-self: flex-start;
    margin-left: 0;
    margin-right: 0;
  }

  .reception-panel--briefing {
    max-height: min(72vh, 620px);
  }

  .reception-plate[data-room="cloud"] {
    object-position: 50% 55%;
  }

  .reception-plate[data-room="vault"] {
    object-position: 42% 58%;
  }

  .reception-plate[data-room="desk"] {
    object-position: 45% 55%;
  }

  .reception-plate[data-room="briefing"] {
    object-position: 54% 48%;
  }

  .mini-calc__preset {
    flex: 1 1 calc(50% - 8px);
    min-width: 0;
  }

  .mini-calc__summary {
    position: sticky;
    bottom: -2px;
  }

  .mini-calc__value {
    font-size: 1.25rem;
  }

  .reception-panel .campus-panel__title {
    font-size: 1.25rem;
  }

  .reception-compare {
    grid-template-columns: 1fr;
  }

  .reception-room--terminal {
    padding:
      calc(64px + env(safe-area-inset-top, 0px))
      12px
      max(12px, env(safe-area-inset-bottom, 0px));
    justify-content: flex-start;
    align-items: stretch;
    overflow: auto;
  }

  .reception-back--terminal {
    position: sticky;
    top: 0;
    z-index: 3;
    margin-bottom: 12px;
  }

  .terminal-shell {
    width: 100%;
    max-width: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .reception-svg .hotspot-path {
    animation: none;
    opacity: 1;
  }

  .reception-svg .hotspot-trace {
    animation: none;
    opacity: 0.4;
  }

  /* The pins stay — they are the only thing telling a visitor the objects can
     be opened. Only the breathing halo goes, replaced by a steady ring. */
  .rx-pin,
  .rx-pin.is-hot,
  .rx-pin.is-tour {
    transition: none;
  }

  .rx-hero {
    transition: none;
  }

  .rx-hero__hint-dot {
    animation: none;
    box-shadow: 0 0 0 3px rgba(232, 217, 184, 0.22);
  }

  .rx-pin.is-placed::before,
  .rx-pin.is-hot::before,
  .rx-pin.is-tour::before {
    animation: none;
    opacity: 0.6;
    transform: scale(1);
  }

  .reception-stage,
  .reception-plate {
    transition: none !important;
  }
}
