/* =====================================================================
   Be Virtual — the interactive room

   CSS 3D, no library. Every object is a .bx with five .fc faces. Sizes
   are written in metres by the template and multiplied by --u here, so
   one variable rescales the entire scene for a phone.

   Axes, as the template writes them:
     --x  metres east from the north-west floor corner
     --z  metres south
     --h  height of the box
     --lift  metres the box floats above the floor

   Loaded only on pages that draw the room.
   ===================================================================== */

.room-scope {
  /* Pixels per metre, and the camera. JS writes --ry / --rx on the
     stage; these are the still-life values a visitor sees with
     JavaScript switched off, and they are a decent angle in their
     own right. */
  --u: 62;
  --ry: -26deg;
  --rx: 27deg;

  /* Surfaces. Fixed values, not role tokens: the room is a dark
     object in both themes, the way the masthead is. */
  --room-void: #101010;
  --room-floor: #1f1f1f;
  --room-grid: rgba(120, 169, 255, 0.17);
  --room-wall: #232323;
  --room-wall-2: #1c1c1c;
  --room-edge: rgba(255, 255, 255, 0.09);
  --room-object: #484848;
  --room-object-2: #383838;
  --room-accent: #78a9ff;
  --room-accent-dim: rgba(120, 169, 255, 0.35);
}

/* ---------------------------------------------------------------------
   Layout: the stage on the left, the notes on the right
   --------------------------------------------------------------------- */
.room {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: var(--sp-9);
  align-items: start;
  margin-top: var(--sp-9);
}

.room__viewer {
  min-width: 0;
}

.room__stage {
  position: relative;
  height: 30rem;
  background:
    radial-gradient(120% 90% at 50% 12%, #1a1a1a 0%, var(--room-void) 68%);
  border: 1px solid var(--ink-line);
  overflow: hidden;
  perspective: 1500px;
  perspective-origin: 50% 40%;
  cursor: grab;
  touch-action: pan-y;
  /* The engineering grid the rest of the site uses, as a backdrop. */
  background-image:
    linear-gradient(var(--room-edge) 1px, transparent 1px),
    linear-gradient(90deg, var(--room-edge) 1px, transparent 1px),
    radial-gradient(120% 90% at 50% 12%, #1a1a1a 0%, var(--room-void) 68%);
  background-size: 48px 48px, 48px 48px, 100% 100%;
}

.room__stage:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.room__stage.is-dragging {
  cursor: grabbing;
}

/* A notch in the top-left corner, matching the rest of the site. */
.room__stage::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
  border-top: 1px solid var(--room-accent-dim);
  clip-path: polygon(0 0, 14px 0, 14px 1px, 0 1px);
}

.room__world {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  /* --rx is written as a positive "how far above the floor the camera
     sits" angle, which is the way the controls and the admin think about
     it. The scene has to rotate the other way to produce that view, so
     the sign is flipped here and nowhere else. */
  transform:
    rotateX(calc(-1 * var(--rx)))
    rotateY(var(--ry))
    translate3d(calc(var(--u) * -5px), calc(var(--u) * 1.15px), calc(var(--u) * -3px));
  transition: transform 480ms cubic-bezier(0.2, 0, 0.15, 1);
}

.room__stage.is-dragging .room__world {
  transition: none;
}

/* ---------------------------------------------------------------------
   Boxes
   --------------------------------------------------------------------- */
.bx {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  transform: translate3d(
    calc(var(--x) * var(--u) * 1px),
    calc(var(--lift, 0) * var(--u) * -1px),
    calc(var(--z) * var(--u) * 1px)
  );
}

.bx > .fc {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  background: var(--room-object);
  box-shadow: inset 0 0 0 1px var(--room-edge);
  display: block;
}

/* Top: the box's lid, dropped to its height then laid flat. */
.bx > .fc--top {
  width: calc(var(--w) * var(--u) * 1px);
  height: calc(var(--d) * var(--u) * 1px);
  transform: translate3d(0, calc(var(--h) * var(--u) * -1px), 0) rotateX(90deg);
  background: color-mix(in srgb, var(--room-object) 100%, white 12%);
}

.bx > .fc--north,
.bx > .fc--south {
  width: calc(var(--w) * var(--u) * 1px);
  height: calc(var(--h) * var(--u) * 1px);
}

.bx > .fc--north {
  transform: translate3d(0, calc(var(--h) * var(--u) * -1px), 0);
  background: var(--room-object-2);
}

.bx > .fc--south {
  transform: translate3d(0, calc(var(--h) * var(--u) * -1px), calc(var(--d) * var(--u) * 1px));
}

.bx > .fc--west,
.bx > .fc--east {
  width: calc(var(--d) * var(--u) * 1px);
  height: calc(var(--h) * var(--u) * 1px);
  background: color-mix(in srgb, var(--room-object) 100%, black 18%);
}

.bx > .fc--west {
  transform: translate3d(0, calc(var(--h) * var(--u) * -1px), 0) rotateY(-90deg);
}

.bx > .fc--east {
  transform: translate3d(calc(var(--w) * var(--u) * 1px), calc(var(--h) * var(--u) * -1px), 0) rotateY(-90deg);
}

/* A box with no height still needs its lid drawn (the floor). */
.bx--floor > .fc--top {
  background:
    linear-gradient(var(--room-grid) 1px, transparent 1px) 0 0 / calc(var(--u) * 1px) calc(var(--u) * 1px),
    linear-gradient(90deg, var(--room-grid) 1px, transparent 1px) 0 0 / calc(var(--u) * 1px) calc(var(--u) * 1px),
    var(--room-floor);
  box-shadow: inset 0 0 0 1px rgba(120, 169, 255, 0.22);
}

.bx--floor > .fc:not(.fc--top) { background: #141414; }

/* ---------------------------------------------------------------------
   Materials
   --------------------------------------------------------------------- */
.bx--wall > .fc { background: var(--room-wall); }
.bx--wall > .fc--top { background: #2b2b2b; }
.bx--wall > .fc--west,
.bx--wall > .fc--east { background: var(--room-wall-2); }
.bx--wall-low > .fc--top { background: var(--room-accent-dim); }

.bx--glass > .fc {
  background: rgba(120, 169, 255, 0.07);
  box-shadow: inset 0 0 0 1px rgba(120, 169, 255, 0.3);
}
.bx--glass > .fc--top { background: rgba(120, 169, 255, 0.22); }

.bx--desk > .fc--top,
.bx--table > .fc--top { background: #6a6a6a; }
.bx--desk > .fc,
.bx--table > .fc { background: #3f3f3f; }

.bx--reception > .fc { background: #3b3b3b; }
.bx--reception > .fc--top { background: #6e6e6e; }
.bx--counter > .fc { background: var(--room-accent-dim); }

.bx--sign > .fc { background: rgba(120, 169, 255, 0.16); box-shadow: inset 0 0 0 1px var(--room-accent-dim); }
.bx--sign > .fc--north { background: rgba(120, 169, 255, 0.3); }

.bx--screen > .fc,
.bx--display > .fc { background: #0d0d0d; box-shadow: inset 0 0 0 1px #4a4a4a; }
.bx--screen > .fc--north,
.bx--display > .fc--north { background: rgba(120, 169, 255, 0.5); }

.bx--chair > .fc,
.bx--chair-back > .fc { background: #343434; }
.bx--chair > .fc--top { background: #4f4f4f; }

.bx--partition > .fc { background: rgba(255, 255, 255, 0.06); box-shadow: inset 0 0 0 1px var(--room-edge); }
.bx--partition > .fc--top { background: rgba(120, 169, 255, 0.2); }

.bx--rack > .fc { background: #202020; }
.bx--rack > .fc--top { background: #333; }
.bx--rack-face > .fc { background: repeating-linear-gradient(
  180deg, #2a2a2a 0 4px, #151515 4px 7px); }
.bx--rack-face > .fc--north { background: repeating-linear-gradient(
  180deg, rgba(120, 169, 255, 0.5) 0 2px, #151515 2px 8px); }

.bx--camera > .fc { background: #0f0f0f; }
.bx--camera > .fc--top { background: #2a2a2a; }
.bx--camera > .fc--south { background: rgba(255, 92, 92, 0.55); }

.bx--light > .fc { background: rgba(255, 255, 255, 0.5); box-shadow: 0 0 22px rgba(180, 210, 255, 0.28); }
.bx--light > .fc--top { background: rgba(255, 255, 255, 0.16); }

.bx--plant > .fc { background: #262626; }
.bx--leaf > .fc { background: rgba(66, 190, 101, 0.32); box-shadow: inset 0 0 0 1px rgba(66, 190, 101, 0.5); }
.bx--leaf > .fc--top { background: rgba(66, 190, 101, 0.5); }

.bx--locker > .fc { background: #262626; }
.bx--locker > .fc--south { background: repeating-linear-gradient(
  90deg, #303030 0 26px, #1c1c1c 26px 28px); }

.bx--bench > .fc { background: #2c2c2c; }
.bx--door > .fc { background: var(--room-accent-dim); }

/* ---------------------------------------------------------------------
   Hotspot pins — counter-rotated so they always face the camera
   --------------------------------------------------------------------- */
.room__pin {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  transform:
    translate3d(
      calc(var(--x) * var(--u) * 1px),
      calc(var(--y) * var(--u) * -1px),
      calc(var(--z) * var(--u) * 1px)
    )
    rotateY(calc(-1 * var(--ry)))
    rotateX(var(--rx));
  text-decoration: none;
  z-index: 3;
}

.room__pin-dot,
.room__pin-label {
  position: absolute;
  display: block;
  white-space: nowrap;
}

.room__pin-dot {
  left: -13px;
  top: -13px;
  width: 26px;
  height: 26px;
  line-height: 24px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--ink-text);
  background: rgba(16, 16, 16, 0.92);
  border: 1px solid var(--room-accent-dim);
  transition: background 120ms linear, border-color 120ms linear, color 120ms linear;
}

.room__pin-label {
  left: -12px;
  top: -42px;
  padding: 3px var(--sp-3);
  font-size: var(--type-caption);
  letter-spacing: 0.32px;
  text-transform: uppercase;
  color: var(--ink-text-2);
  background: rgba(16, 16, 16, 0.9);
  border: 1px solid var(--ink-line);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 140ms linear, transform 140ms linear;
  pointer-events: none;
}

.room__pin:hover .room__pin-dot,
.room__pin:focus-visible .room__pin-dot,
.room__pin.is-active .room__pin-dot {
  background: var(--room-accent);
  border-color: var(--room-accent);
  color: #001141;
}

/* The label appears on hover and focus only. Leaving it up for the
   selected pin looked tidy in isolation and collided with the next
   marker along as soon as the room turned. */
.room__pin:hover .room__pin-label,
.room__pin:focus-visible .room__pin-label {
  opacity: 1;
  transform: translateY(0);
}

.room__pin:focus-visible .room__pin-dot {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* A thin stalk from the pin down to the floor reads as depth. */
.room__pin.is-active .room__pin-dot::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  width: 1px;
  height: 26px;
  background: linear-gradient(var(--room-accent), transparent);
}

/* ---------------------------------------------------------------------
   Controls
   --------------------------------------------------------------------- */
.room__controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  flex-wrap: wrap;
  margin-top: var(--sp-5);
}

.room__hint {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  color: var(--text-03);
  font-size: var(--type-caption);
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

.room__hint svg { flex: none; }

.room__buttons {
  display: flex;
  gap: var(--sp-2);
}

.room__btn {
  min-height: 32px;
  padding: 0 var(--sp-4);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: inherit;
  font-size: var(--type-caption);
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: var(--text-02);
  background: transparent;
  border: 1px solid var(--ui-03);
  cursor: pointer;
  transition: color 120ms linear, border-color 120ms linear, background 120ms linear;
}

.room__btn:hover {
  color: var(--text-01);
  border-color: var(--ui-04);
  background: var(--ui-01);
}

.room__btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------
   The notes beside the room. <details> so they work without JS.
   --------------------------------------------------------------------- */
.room__notes {
  border-top: 1px solid var(--ui-03);
}

.room__note {
  border-bottom: 1px solid var(--ui-03);
}

.room__note > summary {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  padding: var(--sp-5) 0;
  cursor: pointer;
  list-style: none;
  transition: color 120ms linear;
}

.room__note > summary::-webkit-details-marker { display: none; }

.room__note > summary:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.room__note-n {
  flex: none;
  width: 22px;
  font-family: var(--font-mono);
  font-size: var(--type-caption);
  color: var(--text-03);
}

.room__note-title {
  font-size: var(--type-body);
  color: var(--text-01);
}

.room__note[open] > summary .room__note-n,
.room__note.is-active > summary .room__note-n {
  color: var(--interactive);
}

.room__note-body {
  padding: 0 0 var(--sp-6) 38px;
}

.room__note-body p {
  margin: 0;
  color: var(--text-02);
  font-size: var(--type-body);
  line-height: var(--leading-body);
}

.room__note-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  font-size: var(--type-caption);
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

.room__caveat {
  margin-top: var(--sp-7);
  max-width: 62ch;
}

/* ---------------------------------------------------------------------
   Smaller screens: shrink the scene, drop the small props, stack.
   --------------------------------------------------------------------- */
@media (max-width: 1080px) {
  .room-scope { --u: 46; }
  .room { grid-template-columns: 1fr; gap: var(--sp-7); }
  .room__stage { height: 24rem; }
}

@media (max-width: 700px) {
  .room-scope { --u: 33; --rx: 32deg; }
  .room__stage { height: 17rem; }
  .bx--detail { display: none; }
  .room__pin-label { display: none; }
  .room__note-body { padding-left: 0; }
}

/* A visitor who has asked for less movement gets the room without the
   camera easing between angles. It still turns; it just does not glide. */
@media (prefers-reduced-motion: reduce) {
  .room__world { transition: none; }
  .room__pin-dot,
  .room__pin-label { transition: none; }
}

/* Browsers without color-mix still need a face colour, not transparency. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .bx > .fc--top { background: #4a4a4a; }
  .bx > .fc--west,
  .bx > .fc--east { background: #2c2c2c; }
}
