/* ==========================================================================
   VELOCITY — Page & interactive-module styles
   Each interactive module is self-contained (own class namespace) so it can
   be lifted into a WordPress block or template part unchanged.
   ========================================================================== */

/* ======================= HOME : CINEMATIC HERO =========================== */
/* The approach film is the one place the brand is allowed to be atmospheric.
   Everything after it is structural. */
.hero { position: relative; height: 100svh; min-height: 560px; overflow: hidden; background: var(--midnight); }
.hero__media { position: absolute; inset: 0; }
.hero__media video,
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* Both hero films are decorative and are never operated by the visitor.
   Making them non-interactive stops the browser attaching its own hover
   overlay to them — the "picture in picture" and "enhance" chips Chrome and
   Edge float over large playing video. */
.hero video { pointer-events: none; }
.hero video::-webkit-media-controls,
.hero video::-webkit-media-controls-enclosure,
.hero video::-webkit-media-controls-panel,
.hero video::-webkit-media-controls-overlay-play-button,
.hero video::-internal-media-controls-overlay-cast-button { display: none !important; }
/* Midnight grade so white type always clears the footage */
.hero__grade {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(15,23,42,0.72) 0%, rgba(15,23,42,0.30) 34%, rgba(15,23,42,0.86) 100%);
}
/* Two-column composition: the message is anchored hard left, and the right
   half is deliberately held empty as the stage for a future scene. It is
   declared in the markup rather than left to chance, so the asymmetry reads
   as a decision instead of an accident. */
.hero__inner {
  position: relative; z-index: 2; height: 100%;
  display: grid; align-items: center;
  /* The second column is deliberately empty. With scene 2 now covering the
     whole frame there is nothing to put in it, and it is what still holds the
     copy to its own half rather than letting it run across the film. */
  grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
  gap: clamp(1.6rem, 4vw, 3.6rem);
  max-width: var(--maxw); margin-inline: auto; padding-inline: var(--pad);
}
/* No cap of its own. The copy column is 52% of the content box, so it already
   ends within a few pixels of the middle of the page at every width — the
   grid is the measure, and a 34rem cap on top of it only stopped the text
   two-fifths of the way across. */
.hero__copy { max-width: none; }
/* No bleed of its own any more. The page container reaches --pad of the
   viewport at every width up to 1920px, so the copy starts on the same
   vertical as the nav logo and every section below it, and the stage still
   runs out to the opposite edge — the composition is edge to edge because the
   whole page is, not because the hero was pulled out of it. Above 1920px the
   hero centres with everything else instead of stranding itself. */
.hero__eyebrow { color: var(--gold); }
.hero h1 {
  font-size: clamp(2.2rem, 4.6vw, 4.15rem); color: var(--white);
  /* Was 13ch, which broke a nine-word headline over three lines with most of
     the column empty beside it. Left to the column it sets to about 27
     characters at 1920px — a proper display measure — and breaks in two. */
  max-width: none; letter-spacing: -0.03em; line-height: 1.05;
}
.hero__lead { margin-top: 1.4rem; max-width: 72ch; color: var(--sky-80); font-size: var(--fs-lead); }
.hero__actions { margin-top: 2.1rem; display: flex; flex-wrap: wrap; gap: 0.85rem; }
/* Centred on the page, under the composition rather than beside it */
.hero__scroll {
  position: absolute; bottom: clamp(20px, 4vh, 38px);
  left: 50%; transform: translateX(-50%);
  z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 0.55rem;
  font-family: var(--ff-display); font-size: var(--fs-micro); font-weight: 600;
  letter-spacing: 0.28em; color: var(--sky-58);
  transition: opacity var(--dur) var(--ease);
}
.hero__scrollline { width: 1px; height: 40px; background: linear-gradient(var(--gold), transparent); }
.hero.is-scrolled .hero__scroll { opacity: 0; }

/* ------------------- HOME : THE OPENING SEQUENCE ------------------------- */
/* City film → cut to black → intelligence animation, twice, then hold.
   The copy sits above every layer, so it never flickers through the cut. */

/* The cut itself. Pure black, above the footage and below the type. Fast
   enough to read as a cut rather than a dissolve — and because it is #000
   throughout, there is no grey midpoint and no last-frame flash. */
.hero__black {
  position: absolute; inset: 0; z-index: 2;
  background: #000; opacity: 0; pointer-events: none;
  transition: opacity 220ms linear;
}
.hero.is-black .hero__black { opacity: 1; }
.hero__inner, .hero__scroll { z-index: 3; }

/* Once the sequence is past the cut the hero is a black canvas: the city
   layers stop painting entirely rather than sitting behind an opaque plate. */
.hero.is-phase2 { background: #000; }
.hero.is-phase2 .hero__media,
.hero.is-phase2 .hero__grade { visibility: hidden; }

/* Scene 2, full bleed. It covers the frame the way the city film does —
   object-fit: cover, so it fills any viewport shape without letterboxing and
   without distortion. z-index 2 puts it above the black plate (which stays
   opaque for the whole of phase 2), and it is the opacity below, not the
   plate, that hides it during the cut. The copy sits above it at z-index 3.

   No edge feather any more. The mask existed because the film used to be a
   small picture floating on a black field and its edges had to dissolve into
   that field; a film that reaches the edge of the screen has nothing to
   dissolve into, and feathering it would just fade the corners of the page. */
.hero__anim {
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transform: scale(1.03);
  transition: opacity 760ms var(--ease-out), transform 1500ms var(--ease-out);
}
.hero.is-phase2 .hero__anim { opacity: 1; transform: none; }
/* Closing the cycle: the film leaves while the plate is still black, so the
   handover back to the city happens entirely unseen. */
.hero.is-returning .hero__anim { opacity: 0; transition: opacity 380ms var(--ease); }

/* Scene 2's grade, confined to the left half of the frame.

   One layer doing two things. The gradient is the vertical wash that lets
   white type sit on footage — heaviest at the top and bottom, where the
   eyebrow, the headline and the actions are. The mask is what keeps it on
   the copy side: fully on down the left edge, easing off across the column
   and reaching zero at exactly 50%. Past the middle the mask is transparent,
   so nothing is painted there at all — the right half of the film is the raw
   picture, not a lighter version of the shaded one.

   Doing it as a mask rather than as a second horizontal gradient is what
   makes that absolute. Stacking two washes leaves the vertical one still
   covering the whole frame, so the right half is never actually clean; masking
   the single wash removes it from that half outright.

   The falloff is stepped rather than linear because a two-stop ramp across
   half a screen creases at both ends, and the alphas are set for the left
   edge — the mask only ever takes away from them, so full strength has to be
   what the copy needs. */
.hero__scene2 {
  position: absolute; inset: 0; z-index: 2;
  opacity: 0; pointer-events: none;
  transition: opacity 760ms var(--ease-out);
  background:
    linear-gradient(180deg,
      rgba(15,23,42,0.86) 0%,
      rgba(15,23,42,0.56) 34%,
      rgba(15,23,42,0.90) 100%);
  -webkit-mask-image:
    linear-gradient(90deg,
      rgba(0,0,0,1) 0%,
      rgba(0,0,0,1) 10%,
      rgba(0,0,0,0.92) 18%,
      rgba(0,0,0,0.76) 26%,
      rgba(0,0,0,0.54) 34%,
      rgba(0,0,0,0.30) 41%,
      rgba(0,0,0,0.12) 46%,
      rgba(0,0,0,0) 50%);
          mask-image:
    linear-gradient(90deg,
      rgba(0,0,0,1) 0%,
      rgba(0,0,0,1) 10%,
      rgba(0,0,0,0.92) 18%,
      rgba(0,0,0,0.76) 26%,
      rgba(0,0,0,0.54) 34%,
      rgba(0,0,0,0.30) 41%,
      rgba(0,0,0,0.12) 46%,
      rgba(0,0,0,0) 50%);
}
.hero.is-phase2 .hero__scene2 { opacity: 1; }
.hero.is-returning .hero__scene2 { opacity: 0; transition: opacity 300ms var(--ease); }

/* Mobile: a deliberate composition rather than a squeezed desktop one.
   The copy and the animation stack as one centred pair, and the stage is
   present from the first frame so the cut introduces no layout shift. */
@media (max-width: 940px) {
  .hero { height: auto; min-height: 100svh; }
  .hero__inner {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    align-content: center;
    gap: clamp(0.9rem, 2.6vh, 1.5rem);
    padding-block: calc(var(--nav-h) + 0.5rem) clamp(3.4rem, 9vh, 4.4rem);
  }
  .hero__copy { max-width: none; }
  /* Nothing to size here any more: scene 2 covers the frame at every width,
     so the mobile composition is the copy over the film rather than the copy
     stacked above a picture. */
  .hero__scroll { bottom: 14px; }
  .hero__scrollline { height: 22px; }
}

/* No opening sequence when motion is reduced: the hero simply holds the city
   film still, and scene 2 never arrives. */
@media (prefers-reduced-motion: reduce) {
  .hero__black, .hero__anim, .hero__scene2 { transition: none; }
}

/* ======================= HOME : CLIENT FEEDBACK RAIL ===================== */
/* A narrow band of proof between two dark sections. No heading and no framing
   copy — the reviews are the whole argument, so the section is only as tall as
   they are. The gold is the section's own frame, a hairline top and bottom,
   rather than a box drawn around every card. */
.proof {
  background: var(--white);
  border-top: 3px solid var(--gold);
  border-bottom: 3px solid var(--gold);
  /* Tightened by about a fifth overall. The saving is taken from spacing
     only — the band's padding here, and the internal rhythm of the card
     below. No type size changes, so the reviews read exactly as before in a
     shallower strip. */
  padding-block: clamp(13px, 1.7vw, 21px);
}

/* --- The marquee ---
   Two identical sets sit end to end and the track travels exactly -50%, which
   is one whole set: when the loop restarts the second set is standing exactly
   where the first was, so there is no jump to see. All spacing is padding on
   the cards, never a flex gap on the track — a gap between the two sets would
   put -50% half a gap out of register and the loop would stutter. */
.ticker {
  position: relative; overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 4%, #000 96%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 4%, #000 96%, transparent 100%);
}
.ticker__track {
  display: flex; width: max-content;
  animation: tickerRun var(--tick-dur, 64s) linear infinite;
  will-change: transform;
}
.ticker__set { display: flex; align-items: stretch; margin: 0; padding: 0; list-style: none; }
@keyframes tickerRun {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
/* Pointer devices only: let a reader stop the rail to finish a quotation.
   Pausing rather than slowing, because changing the duration mid-run jumps the
   track to a different point on the timeline. */
@media (hover: hover) {
  .ticker:hover .ticker__track,
  .ticker:focus-within .ticker__track { animation-play-state: paused; }
}

/* --- One review ---
   No box. Items are divided by a hairline the way a broadsheet divides
   columns, which keeps the rail reading as one continuous strip. */
.tcard {
  box-sizing: border-box;
  flex: 0 0 auto;
  width: clamp(318px, 33vw, 480px);
  padding-inline: clamp(20px, 2.4vw, 38px);
  display: flex; flex-direction: column;
  border-right: 1px solid var(--silver);
}
.tcard__stars { color: var(--gold); font-size: 1.02rem; letter-spacing: 0.14em; line-height: 1; }
.tcard__quote {
  margin: 0.58rem 0 0; padding: 0; border: 0;
  font-size: clamp(0.94rem, 1.02vw, 1.05rem); line-height: 1.46; color: var(--deep-text);
}
/* Quotation marks come from the stylesheet, so the text itself stays clean
   for whoever swaps in the real feedback. */
.tcard__quote::before { content: "“"; }
.tcard__quote::after  { content: "”"; }
.tcard__who {
  margin-top: auto; padding-top: 0.6rem;
  font-family: var(--ff-display); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--midnight);
}
/* The sector takes its own line in sentence case. Set inline it wrapped at
   different points on every card and the row lost its footing; on its own
   line every attribution is built the same way. */
.tcard__sector {
  display: block; margin-top: 0.22rem;
  font-size: 0.76rem; font-weight: 500; letter-spacing: 0.02em;
  text-transform: none; color: var(--ink-62);
}

/* No motion: the rail becomes a strip the reader moves themselves, and the
   duplicate set is dropped so nothing is announced twice. */
@media (prefers-reduced-motion: reduce) {
  .ticker { overflow-x: auto; -webkit-mask-image: none; mask-image: none; }
  .ticker__track { animation: none; width: auto; }
  .ticker__set + .ticker__set { display: none; }
}

/* ======================= METHOD (5-step process) ========================= */
.method { position: relative; }


/* The progress rule that fills as the section enters view */
/* ------------------- HOME : TRANSFORMATION STUDY LAYOUT -----------------
   Three columns, reading left to right as one sentence: what the study is,
   how it runs, and what it leaves you with. Named areas rather than bare
   columns, so each breakpoint can re-place the note and the button without
   the markup being reordered — the DOM order stays the reading order for
   screen readers and keyboard users at every width.

     wide    copy | steps | note      the button under the copy
     ≤1180   copy | steps             note becomes a full-width footing
     ≤940    stacked                  note before the steps, button last

   Top-aligned, not centred. With three columns of very different heights,
   centring leaves every one of them floating at a different offset; aligning
   the tops is what makes it read as a built layout. */
.method__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr) minmax(0, 0.7fr);
  grid-template-areas:
    "copy  steps note"
    "cta   steps note";
  grid-template-rows: auto 1fr;
  /* Split, because they are different decisions: the column gap separates
     three columns, the row gap is the space under the lead before the button
     and wants to stay at the 1.9rem the block had before. */
  column-gap: clamp(1.8rem, 3.6vw, 3.4rem);
  row-gap: 1.9rem;
  align-items: start;
}
.method__copy  { grid-area: copy; }
.method__steps { grid-area: steps; }
.method__note  { grid-area: note; }

/* Pinned to the bottom of the grid rather than hung under the copy. The steps
   column is the tallest of the three and spans both rows, so the bottom of
   the grid is the bottom of the steps list — which puts the button exactly
   level with the last step. Aligning it to the top instead left it floating
   at whatever height the copy happened to end at, which is what made the
   section look unresolved. */
.method__cta { grid-area: cta; align-self: end; }

/* No rules over the columns. The three of them now line up on the type
   itself: each opens on an eyebrow at the same size, on the same baseline,
   with the steps list closed at the top so its first row starts level with
   the other two. Alignment carried by a drawn line is the easy version of
   this; alignment carried by the text is the one that looks composed. */
.method .next { border-top: 0; }
.method .next__step:first-child { padding-top: 0; }

.method__copy .lead { margin-top: 1.2rem; }

/* The note is the third column's whole content, so it is set as a statement
   rather than a caption. Its head is a plain .eyebrow — same size, same gold,
   same left-to-right wipe as "Where every engagement starts" on the far side
   of the section, so the two outer columns open identically.

   The body is set large and loose on purpose. At --fs-small it filled barely
   half its column and read as a footnote left in the margin; at this size and
   leading the eight or so lines it sets to run from the top of the column
   down to about the last step, which is what makes the three columns look
   like one block rather than one tall thing between two short ones. The
   column stretches to the full height so the text has that room to use, and
   no measure cap — the column is the measure. */
.method__note { align-self: stretch; }
.method__note-body {
  font-size: clamp(1.1rem, 1.34vw, 1.45rem);
  line-height: 1.75;
  color: var(--sky-80);
  max-width: none;
}

/* Medium: three columns would put the note under 260px. It drops to a
   full-width footing beneath both, which suits a closing qualification
   better than a cramped sidebar would. */
@media (max-width: 1180px) {
  .method__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "copy  steps"
      "cta   steps"
      "note  note";
    grid-template-rows: auto auto auto;
  }
  .method__note { margin-top: 0.4rem; }
  .method__note-body { max-width: 68ch; }
}

/* Narrow: one column, and the order changes to suit reading rather than
   layout — the qualification belongs with the description it qualifies, and
   the call to action belongs at the end, after the steps have been read. */
@media (max-width: 940px) {
  .method__grid {
    grid-template-columns: 1fr;
    grid-template-areas: "copy" "note" "steps" "cta";
    grid-template-rows: auto;
    row-gap: clamp(1.4rem, 4vw, 2rem);
  }
}

/* --- The four study steps ---
   Colours first: these were inline in the markup, which meant nothing in a
   stylesheet could override them. Moved here so the hover state below works
   at all. */
/* Top rule comes from the shared hairline above. */
.method .next__step { border-color: var(--sky-08); }
.method .next__t { color: var(--white); }
.method .next__d { color: var(--sky-58); }

/* Then the hover. The same vocabulary the solutions index already uses — a
   gold rule at the left edge, a faint tint, and the row stepping in — so the
   list reads as something to move through rather than a static block. The
   negative inline margin lets the tint and the rule sit outside the text
   column, so nothing reflows when it comes in.

   Pointer devices only, and no pointer cursor: the rows respond to being
   read, they are not links, and inviting a click that goes nowhere would be
   worse than leaving them flat. */
.method .next__step {
  padding-inline: 0.75rem;
  margin-inline: -0.75rem;
  transition: background 280ms var(--ease),
              box-shadow 280ms var(--ease),
              transform 280ms var(--ease);
}
@media (hover: hover) {
  .method .next__step:hover {
    background: rgba(255, 255, 255, 0.035);
    box-shadow: inset 2px 0 0 var(--gold);
    transform: translateX(4px);
  }
  /* The numeral is deliberately left alone. Gold is what identifies it, and
     the row already announces itself with the rule, the tint and the step. */
  .method .next__step:hover .next__t { color: var(--gold); }
  .method .next__step:hover .next__d { color: var(--sky-80); }
}

/* ======================= SOLUTION MODULES (interactive) ================== */


/* Shared "device" frame that holds every live demo */
.demo {
  position: relative; background: var(--midnight);
  border: 1px solid var(--silver); border-radius: 6px;
  overflow: hidden; box-shadow: 0 24px 60px rgba(15, 23, 42, 0.13);
}
.demo__bar {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.65rem 0.9rem; border-bottom: 1px solid var(--sky-08);
  background: rgba(255,255,255,0.03);
}
.demo__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--sky-16); }
.demo__label {
  margin-left: auto; font-family: var(--ff-display); font-size: 0.63rem;
  font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--sky-38);
}
.demo__body { padding: clamp(0.9rem, 1.6vw, 1.3rem); min-height: 292px; }

/* --- Demo: AI agent conversation --- */
.chat { display: flex; flex-direction: column; gap: 0.6rem; }
.chat__msg {
  max-width: 82%; padding: 0.7rem 0.95rem; border-radius: 12px;
  font-size: var(--fs-small); line-height: 1.5;
  opacity: 0; transform: translateY(8px);
  animation: chatIn 460ms var(--ease-out) forwards;
}
@keyframes chatIn { to { opacity: 1; transform: none; } }
.chat__msg--in  { align-self: flex-start; background: var(--sky-08); color: var(--sky-80); border-bottom-left-radius: 3px; }
.chat__msg--out { align-self: flex-end; background: var(--gold); color: var(--midnight); border-bottom-right-radius: 3px; font-weight: 500; }
.chat__typing { display: flex; gap: 4px; align-self: flex-start; padding: 0.85rem 0.95rem; background: var(--sky-08); border-radius: 12px; border-bottom-left-radius: 3px; }
.chat__typing span { width: 5px; height: 5px; border-radius: 50%; background: var(--sky-38); animation: blink 1.3s infinite; }
.chat__typing span:nth-child(2) { animation-delay: 0.18s; }
.chat__typing span:nth-child(3) { animation-delay: 0.36s; }
@keyframes blink { 0%,60%,100% { opacity: 0.28; } 30% { opacity: 1; } }

/* --- Demo: workflow automation --- */
.flow { display: flex; flex-direction: column; gap: 0.55rem; }
.flow__row {
  display: grid; grid-template-columns: 26px 1fr auto; align-items: center; gap: 0.8rem;
  padding: 0.72rem 0.9rem; border: 1px solid var(--sky-08); border-radius: 4px;
  background: rgba(255,255,255,0.02);
  transition: border-color 460ms var(--ease), background 460ms var(--ease);
}
.flow__row.is-done { border-color: var(--gold-40); background: var(--gold-14); }
.flow__tick {
  width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--sky-16);
  display: grid; place-items: center; transition: all 460ms var(--ease);
}
.flow__row.is-done .flow__tick { background: var(--gold); border-color: var(--gold); }
.flow__tick svg { width: 11px; height: 11px; color: var(--midnight); opacity: 0; transition: opacity 300ms var(--ease); }
.flow__row.is-done .flow__tick svg { opacity: 1; }
.flow__label { font-size: var(--fs-small); color: var(--sky-58); }
.flow__row.is-done .flow__label { color: var(--white); }
.flow__meta { font-family: var(--ff-display); font-size: 0.66rem; letter-spacing: 0.1em; color: var(--sky-38); }

/* --- Demo: intelligent dashboard --- */
.dash { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.7rem; }
.dash__kpi { border: 1px solid var(--sky-08); border-radius: 4px; padding: 0.85rem; background: rgba(255,255,255,0.02); }
.dash__k { font-family: var(--ff-display); font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--sky-38); }
.dash__v { font-family: var(--ff-display); font-size: 1.5rem; font-weight: 600; color: var(--white); margin-top: 0.3rem; letter-spacing: -0.02em; }
.dash__d { font-size: 0.68rem; color: var(--gold); margin-top: 0.15rem; }
.dash__chart { grid-column: 1 / -1; border: 1px solid var(--sky-08); border-radius: 4px; padding: 0.9rem; background: rgba(255,255,255,0.02); }
.dash__bars { display: flex; align-items: flex-end; gap: 5px; height: 92px; margin-top: 0.7rem; }
.dash__bar { flex: 1; background: var(--sky-16); border-radius: 2px 2px 0 0; height: 0; transition: height 900ms var(--ease-out); }
.dash__bar.is-peak { background: var(--gold); }
@media (max-width: 520px) { .dash { grid-template-columns: repeat(2, 1fr); } }

/* ============ CUSTOM BUSINESS SYSTEMS : THE OFFICE AND THE SCREEN ========
   This area does not show a demonstration, it is somewhere you go. The
   photograph is the room, the monitor standing on the desk is the product,
   and the interface below is ordinary markup laid on to the glass of that
   monitor. The office is a still; only the screen is alive, and the contrast
   between the two is the whole idea.

   Everything hangs off one measurement. The screen's inner rectangle was read
   off the photograph rather than eyeballed — x 370 to 1162 and y 213 to 621
   of 1536 by 1024 — and the four percentages below are that rectangle. The
   scene keeps the source image's exact 3:2, so those percentages land on the
   glass at every width without the image ever being cropped. */
/* Doubled on purpose. .solx__panel carries the padding and scrolling every
   other interior needs and is written later in this file, so a single class
   here loses the tie and the scene gets a 40px frame it must not have. */
.solx__panel.solx__panel--scene { padding: 0; overflow: hidden; background: var(--midnight); }

/* --- The unit a room is written in ---------------------------------------
   Everything inside an interior used to be measured in container widths, and
   for a long time that was right: the room is as wide as the window, so the
   caption and the demonstration scaled together and kept their proportion to
   the scene whatever size the screen was.

   It stops being right when the window gets wider without getting any deeper.
   A 21:9 screen is a third wider than a 16:9 one of the same height, so every
   width-measured thing in the room grew by a third while the room itself
   stayed where it was — and the caption, which is the tallest of them, walked
   straight up into the demonstration above it.

   So the room is written in whichever of the two is smaller. One unit is one
   per cent of the width, or one per cent of the height at the proportion the
   rooms were drawn to — 1904 by 985, which is 1.933 — whichever is less. On
   any window of that shape or taller the first term wins and nothing changes
   at all, which is every ordinary desktop; only a window wider than its
   drawing takes the second, and then the whole room comes down together
   rather than one part of it outgrowing the rest. */
.solx__panel--scene {
  /* One per cent of the room's width, which is 1.5% of its depth, because the
     room is two thirds of its own width again. Kept as a name rather than
     written out, because it is the one measure everything in here shares. */
  --u: 1cqw;
}

/* Anchored to the foot of the panel rather than centred. On a desktop the
   panel is already 3:2 and it fills exactly; on a narrow screen, where the
   heading sits above the plate and the panel is taller, the scene stays with
   the plate and the strip left above it becomes the bar the way out sits in. */
/* It clips, now that the picture inside it is dropped: the foot that hangs
   past the room is cropped by the room rather than left hanging off the
   panel, where it was quietly making the panel a scrolling region. The way
   out, the demonstration line and the caption are all outside this box, so
   none of them is touched by it. */
.erps__room { position: absolute; inset: 0; overflow: hidden; }
/* Dropped far enough that the monitor clears the way out.

   The office is a 3:2 photograph in a room that is nearer 2:1, so about a
   fifth of it is cropped, and standing it on the floor took every bit of that
   off the top — which is exactly where the monitor is. The glass was starting
   20px above the room and the corner of it was coming up underneath BACK TO
   WHAT WE DO.

   So the picture is pushed down by however much it takes and no more. The
   screen's top edge is 20.8% down the photograph, which is 52.8 container
   widths from its foot, and the line below asks for that edge to land 78px
   into the room — clear of the way out at every size, from a short laptop to
   an ultrawide. min() keeps it at zero when the picture is already low
   enough, so the foot of the room can never be left uncovered. */
.erps {
  /* Stood on the foot of the room, at the photograph's own proportions. With
     the room back to three by two the plate fills it exactly, so the monitor
     sits where it was drawn to sit: clear of the way out above it and well
     clear of the caption below. */
  position: absolute; left: 0; right: 0; top: auto; bottom: 0;
  aspect-ratio: 1536 / 1024;
  container-type: inline-size;
}
.erps__img { width: 100%; height: 100%; object-fit: cover; }

/* Past about two to one the room is so shallow that the second term above
   goes to nothing and the monitor comes back up under the way out — and the
   way out is a control, which matters more than a caption does. On a window
   that shape the picture holds its full drop and the caption is the thing
   that gives, which is what it already does in the other four rooms at this
   ratio. */
/* Below about 1100px the monitor would be under 570px across, and an ERP
   rendered that small is a picture of an ERP rather than one you can use. So
   the camera moves in on the desk instead of the interface shrinking: the
   scene scales 1.85 about the centre of the screen, which puts the monitor at
   95% of the window and leaves just enough of the room around it to say where
   you are. The screen keeps its exact place on the glass because the scale is
   struck about that point and the scene is positioned by it.

   27.15vw is where the centre of the screen sits below the top of the scene
   (40.72% of a 3:2 box), so this is what lands it in the middle of the panel. */
@media (max-width: 1100px) {
  /* The room becomes a band and the panel scrolls: the monitor first, at a
     size worth reading, then the words. The scale is still a transform rather
     than a width, because the interface inside the screen sizes itself off
     the screen's own layout width — widening it would give the ERP a bigger
     box and the same tiny type, which is the opposite of what is wanted. */
  /* Inside, on a narrow screen, the interior is the page rather than a box
     sitting on it. The plate and the heading come out of the flow so they
     stop dictating the height (they keep their boxes, so the way in and the
     way out still animate), and the stage takes whatever its content needs.
     Applies to all six interiors: a fixed-height panel with its own scrollbar
     inside a page that also scrolls is the worst of both. */
  .eco.is-inside .eco__frame { position: absolute; inset: 0; }
  .eco.is-inside .eco__head { position: absolute; inset: 0 auto auto 0; }
  .eco.is-inside .solx__stage { position: relative; height: auto; }
  .eco.is-inside .solx__panel { position: relative; inset: auto; }
  .erps__room {
    position: relative; inset: auto;
    height: 76vw; overflow: hidden;
  }
  .erps {
    bottom: auto; top: 50%;
    margin-top: -27.15vw;
    transform: scale(1.85);
    transform-origin: 49.87% 40.72%;
  }
  .erps__grade { display: none; }
}

.erps__screen {
  position: absolute;
  left: 24.089%; top: 20.801%;
  width: 51.562%; height: 39.844%;
  container-type: inline-size;
  overflow: hidden;
  border-radius: 0.35cqw;
  background: #0B1424;
  /* A lit panel throws a little light into the room it is in. Two stops of it
     only, or the office starts to look like it is on fire. */
  box-shadow: 0 0 4cqw rgba(140, 175, 225, 0.10),
              0 0 1.2cqw rgba(140, 175, 225, 0.07);
}
/* The glass. A single soft diagonal at four percent: enough that the screen
   reads as a surface being looked at rather than a rectangle cut out of the
   photograph, faint enough that nothing under it is lost. */
.erps__screen::after {
  content: ""; position: absolute; inset: 0; z-index: 5;
  pointer-events: none;
  background: linear-gradient(114deg,
    rgba(255, 255, 255, 0.055) 0%, rgba(255, 255, 255, 0.018) 26%,
    rgba(255, 255, 255, 0) 46%);
}

/* --- Saying that it runs ---
   The one thing the screen cannot say about itself: at this size its own
   labels are unreadable across a room, and a photograph of an interface and
   a working one look exactly alike until somebody touches them. So it is
   said at the room's scale, on the desk directly under the monitor and
   aligned to the screen's left edge, and it is withdrawn the moment it has
   been acted on rather than sitting there for the rest of the visit. */
.erps__hint {
  position: absolute; z-index: 6;
  /* Directly above the monitor, on the wall the photograph leaves empty
     there. Hung from the bottom edge, which is the edge the photograph
     itself is hung from, so the gap to the glass is the same however tall
     the window turns out to be: the plate is 66.667 container-widths deep
     and the screen starts 20.801% down it, which puts the top of the glass
     52.8 up from the foot, and the pill sits 1.2 clear of that. */
  left: 50%; top: auto; bottom: calc(54 * var(--u));
  transform: translate(-50%, 0);
  display: inline-flex; align-items: center; gap: calc(0.66 * var(--u));
  padding: calc(0.46 * var(--u)) calc(1 * var(--u)) calc(0.46 * var(--u)) calc(0.84 * var(--u));
  border: 1px solid rgba(201, 168, 106, 0.38);
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.42);
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.78 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9); max-width: none;
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.8);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}
.erps__hint-dot {
  width: calc(0.46 * var(--u)); height: calc(0.46 * var(--u)); border-radius: 50%;
  background: var(--gold);
  animation: erpsBeacon 2.6s var(--ease) infinite;
}
/* A ring leaving the dot, not the dot itself moving. Nothing in the room
   should appear to twitch. */
@keyframes erpsBeacon {
  0%   { box-shadow: 0 0 0 0 rgba(201, 168, 106, 0.45); }
  70%  { box-shadow: 0 0 0 0.72cqw rgba(201, 168, 106, 0); }
  100% { box-shadow: 0 0 0 0 rgba(201, 168, 106, 0); }
}
.erps__hint.is-gone { opacity: 0; transform: translate(-50%, calc(0.5 * var(--u))); pointer-events: none; }

/* --- The caption in the room ---
   The lower third, and nothing above it: the monitor holds y 21% to 61% of
   the frame and this starts well below that, so the demonstration is never
   competing with the words about it.

   The grade is not a panel. It is the same thing a title card on a film is
   laid over: the photograph's own darkness deepened towards the bottom edge,
   starting exactly where the screen ends so it can never touch it. The chair
   and the desk front are already the darkest part of the picture, so this
   only has to finish the job. */
.erps__grade {
  position: absolute; left: 0; right: 0;
  top: 60.645%; bottom: 0;
  pointer-events: none;
  /* The desk top is the brightest thing in the lower half of the picture, a
     polished marble at about 150, and the caption has to cross it. So the
     ramp does most of its work early: by the time the type reaches the desk
     the ground under it is down near 80, which is where white holds. */
  background: linear-gradient(180deg,
    rgba(15, 23, 42, 0) 0%,
    rgba(15, 23, 42, 0.34) 12%,
    rgba(15, 23, 42, 0.62) 35%,
    rgba(15, 23, 42, 0.85) 70%,
    rgba(15, 23, 42, 0.92) 100%);
}

.erpc {
  position: absolute;
  left: 5.2%; right: 5.2%; bottom: 3.4%;
  color: var(--white);
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.8);
}
/* Sized against the scene, so the caption keeps its proportion to the room
   rather than to the window. */
.erpc__eyebrow { font-size: calc(0.82 * var(--u)); margin-bottom: calc(0.9 * var(--u)); }
.erpc__h {
  font-size: calc(2.1 * var(--u)); font-weight: 500; letter-spacing: -0.025em;
  color: var(--white); margin-bottom: calc(0.7 * var(--u));
}
.erpc__lead {
  font-size: calc(0.95 * var(--u)); line-height: 1.55;
  color: rgba(255, 255, 255, 0.66);
  max-width: 76ch;
  margin-bottom: calc(1.5 * var(--u));
}
/* Three, in a row, across the foot of the room. Stacked they would have run
   up the picture and into the desk. */
.erpc__pts {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: calc(2.4 * var(--u));
  max-width: 74%;
}
.erpc__n {
  display: block;
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.8 * var(--u)); letter-spacing: 0.16em; color: var(--gold);
  margin-bottom: calc(0.55 * var(--u));
}
.erpc__t {
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.86 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--white); margin-bottom: calc(0.4 * var(--u)); max-width: none;
}
.erpc__d {
  font-size: calc(0.84 * var(--u)); line-height: 1.6;
  color: rgba(255, 255, 255, 0.58); max-width: none;
}

/* Narrow: the caption leaves the photograph and is set on the panel below it,
   at the page's own sizes rather than the room's. It has to come after the
   rules above rather than travel with the rest of the narrow-screen block,
   because those are container units on the same selectors and whichever is
   written last wins. */
@media (max-width: 1100px) {
  /* The room is a cropped band here and everything in it is scaled up, so the
     cue leaves the photograph the way the caption does and is set on the page
     instead, immediately under the band and above the words. */
  .erps__hint {
    position: static; transform: none;
    margin: clamp(1.3rem, 4vw, 1.9rem) var(--pad) 0;
    gap: 0.55rem; padding: 0.44rem 0.85rem 0.44rem 0.7rem;
    font-size: clamp(0.62rem, 2.4vw, 0.72rem);
    text-shadow: none;
  }
  .erps__hint-dot { width: 0.4rem; height: 0.4rem; }
  @keyframes erpsBeacon {
    0%   { box-shadow: 0 0 0 0 rgba(201, 168, 106, 0.45); }
    70%  { box-shadow: 0 0 0 0.42rem rgba(201, 168, 106, 0); }
    100% { box-shadow: 0 0 0 0 rgba(201, 168, 106, 0); }
  }
  .erps__hint.is-gone { transform: translateY(0.3rem); }
  .erpc {
    position: static;
    padding: clamp(1.6rem, 5vw, 2.6rem) var(--pad) clamp(2rem, 6vw, 3rem);
    text-shadow: none;
  }
  .erpc__eyebrow { font-size: clamp(0.72rem, 2.6vw, 0.86rem); margin-bottom: 0.9rem; }
  .erpc__h { font-size: clamp(1.35rem, 5.4vw, 1.9rem); margin-bottom: 0.7rem; }
  .erpc__lead { font-size: clamp(0.86rem, 3.4vw, 1rem); margin-bottom: 1.8rem; }
  .erpc__pts { grid-template-columns: 1fr; gap: 1.4rem; max-width: none; }
  .erpc__n { font-size: 0.7rem; margin-bottom: 0.35rem; }
  .erpc__t { font-size: 0.78rem; margin-bottom: 0.3rem; }
  .erpc__d { font-size: 0.82rem; }
}

/* The way out, over the office rather than over the screen. The office is
   dark, so it inverts here — the same control, read against a photograph
   instead of against the ice the other five interiors are laid on.

   It keeps its column. Taking the caption's edge at 5.2% would have lined the
   two up, but the way out sits at the top of a room that the fixed bar floats
   over, and a tenth of the way in is exactly where the wordmark is: the two
   ran into each other the moment the room came level with the top of the
   window. The column it has is empty bar, so it stays there. */
.solx__stage:has(.solx__panel--scene:not([hidden])) .eco__back {
  color: rgba(255, 255, 255, 0.70);
  /* The office has a lit ceiling strip exactly where this sits, so it needs
     the same halo the labels on the map do. */
  text-shadow: 0 1px 2px rgba(15, 23, 42, 0.85), 0 0 8px rgba(15, 23, 42, 0.6);
}
.solx__stage:has(.solx__panel--scene:not([hidden])) .eco__back:hover { color: var(--white); }

/* --- The system on the screen ---
   Sized in em against a base of 1.55% of the screen's own width, so the
   interface holds one set of proportions whatever the monitor is rendered at:
   the layout is always about 64 characters of it across, the way a real
   application would be at any resolution. The clamp is the floor and ceiling
   for the type itself. */
.erp {
  position: absolute; inset: 0;
  display: grid;
  grid-template-columns: 11.6em 1fr;
  grid-template-rows: 2.9em 1fr;
  font-size: clamp(6.5px, 1.55cqw, 16px);
  font-family: var(--ff-text);
  line-height: 1.45;
  color: var(--sky-80);
  background: linear-gradient(180deg, #101B2E 0%, #0B1424 100%);
}

/* --- Top bar --- */
.erp__bar {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 1em;
  padding: 0 1.15em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.025);
}
.erp__brand {
  display: inline-flex; align-items: center; gap: 0.55em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.86em; letter-spacing: 0.02em; color: var(--white);
}
.erp__mark {
  width: 0.62em; height: 0.62em; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 0.24em rgba(201, 168, 106, 0.16);
}
.erp__search {
  flex: 1; max-width: 20em;
  padding: 0.34em 0.8em; border-radius: 0.25em;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.03);
  font-size: 0.76em; color: rgba(255, 255, 255, 0.34);
}
/* Said plainly and kept on screen at all times: these are made-up records
   chosen to look like a real operation, and none of them are anybody's. */
.erp__tag {
  margin-left: auto;
  padding: 0.26em 0.7em; border-radius: 999px;
  border: 1px solid var(--gold-40); color: var(--gold);
  font-family: var(--ff-display); font-size: 0.62em;
  font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
}
.erp__who {
  width: 1.75em; height: 1.75em; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.07);
  font-family: var(--ff-display); font-size: 0.68em;
  font-weight: 600; letter-spacing: 0.06em; color: var(--white);
}

/* --- Modules --- */
.erp__side {
  display: flex; flex-direction: column; gap: 0.1em;
  padding: 0.9em 0.6em;
  border-right: 1px solid rgba(255, 255, 255, 0.07);
}
.erp__nav {
  text-align: left; font: inherit; font-size: 0.84em;
  padding: 0.46em 0.7em;
  border: 0; border-left: 2px solid transparent; border-radius: 0.2em;
  background: none; color: rgba(255, 255, 255, 0.55); cursor: pointer;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.erp__nav {
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
/* Hovering has to answer, or the list reads as a printed table of contents.
   The gold edge is the same one the open module carries, at a quarter of the
   strength: the row says what it would become. */
.erp__nav:hover {
  color: rgba(255, 255, 255, 0.86); background: rgba(255, 255, 255, 0.05);
  border-left-color: var(--gold-40);
}
.erp__nav:focus-visible {
  outline: 1px solid var(--gold-40); outline-offset: -1px;
  color: var(--white); background: rgba(255, 255, 255, 0.05);
}
.erp__nav.is-active {
  color: var(--white); background: rgba(255, 255, 255, 0.07);
  border-left-color: var(--gold);
}
/* Until the first click, the open module breathes. It is the only moving
   thing in the interface and it is where the interface can be operated from,
   so the eye goes to the one place worth putting a cursor. It stops for good
   once that has happened, because a system that keeps asking to be used after
   it is being used is a system nobody trusts. */
.erp:not(.is-used) .erp__nav.is-active { animation: erpBeat 2.6s var(--ease) infinite; }
@keyframes erpBeat {
  0%, 100% { background: rgba(255, 255, 255, 0.07); }
  50%      { background: rgba(201, 168, 106, 0.16); }
}
.erp__sidefoot {
  margin-top: auto; padding: 0.7em;
  font-size: 0.62em; line-height: 1.5;
  color: rgba(255, 255, 255, 0.26);
}

/* --- The module on show --- */
.erp__stage { position: relative; overflow: hidden; }
.erp__panel {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: 0.75em;
  padding: 1em 1.15em 1.15em;
  animation: erpIn 320ms var(--ease-out) both;
}
.erp__panel[hidden] { display: none; }
@keyframes erpIn { from { opacity: 0; transform: translateY(0.5em); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .erp__panel { animation: none; }
  .erps__hint-dot, .erp:not(.is-used) .erp__nav.is-active { animation: none; }
  /* Without the beat the dot still has to read as lit rather than printed. */
  .erps__hint-dot { box-shadow: 0 0 0 0.28cqw rgba(201, 168, 106, 0.22); }
}

.erp__phead { display: flex; align-items: baseline; gap: 1em; flex-wrap: wrap; }
.erp__ptitle {
  font-family: var(--ff-display); font-size: 0.9em; font-weight: 600;
  /* Not a heading any more. These are the screen titles of a simulated
     application, and offering "Dashboard, Operations, Sales" to a screen
     reader as document structure said this page had an outline it does not
     have — it also put an h4 above the room's own h3. The line-height is
     carried here because it used to come from the h1..h4 rule. */
  line-height: 1.12; letter-spacing: 0.02em; color: var(--white);
}
.erp__pnote {
  flex: 1; min-width: 14em; max-width: none;
  font-size: 0.68em; line-height: 1.5; color: rgba(255, 255, 255, 0.42);
}
.erp__chips { display: flex; gap: 0.35em; margin-left: auto; }
.erp__chip {
  font: inherit; font-size: 0.66em;
  padding: 0.24em 0.7em; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: none; color: rgba(255, 255, 255, 0.5); cursor: pointer;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.erp__chip:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.28); }
.erp__chip.is-on { color: var(--midnight); background: var(--gold); border-color: var(--gold); }

/* --- Cards --- */
.erp__card {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  padding: 0.85em 0.95em;
  border: 1px solid rgba(255, 255, 255, 0.07); border-radius: 0.3em;
  background: rgba(255, 255, 255, 0.022);
}
.erp__card--flush { padding: 0; overflow: hidden; }
.erp__ctitle {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--ff-display); font-size: 0.66em; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
  margin-bottom: 0.9em;
}
.erp__ctitle span { letter-spacing: 0.06em; text-transform: none; font-weight: 400; color: rgba(255, 255, 255, 0.3); }
.erp__ctitle--sub { margin-top: 1.1em; }
.erp__split { flex: 1; min-height: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0.75em; }
.erp__split--wide { grid-template-columns: 2.05fr 1fr; }
.erp__split--half { grid-template-columns: 1fr 1.25fr; }

/* --- Numbers --- */
.erp__kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.6em; }
.erp__kpi {
  padding: 0.7em 0.85em;
  border: 1px solid rgba(255, 255, 255, 0.07); border-radius: 0.3em;
  background: rgba(255, 255, 255, 0.022);
}
.erp__kpi-k {
  font-family: var(--ff-display); font-size: 0.6em; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.38); max-width: none;
}
.erp__kpi-v {
  font-family: var(--ff-display); font-size: 1.35em; font-weight: 600;
  letter-spacing: -0.02em; color: var(--white); margin-top: 0.12em; max-width: none;
}
.erp__kpi-n { font-size: 0.62em; color: var(--gold); margin-top: 0.1em; max-width: none; }
.erp__fact {
  font-family: var(--ff-display); font-size: 0.95em; font-weight: 600;
  color: var(--white); margin-top: 0.1em; max-width: none;
}
.erp__facts { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75em 1em; }

/* --- Charts --- */
.erp__chart {
  flex: 1; min-height: 0;
  display: flex; align-items: flex-end; gap: 0.4em;
}
.erp__col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.erp__col i {
  display: block; height: var(--h);
  background: linear-gradient(180deg, var(--gold) 0%, rgba(201, 168, 106, 0.45) 100%);
  border-radius: 0.12em 0.12em 0 0;
}
.erp__col em {
  font-style: normal; text-align: center;
  font-size: 0.58em; color: rgba(255, 255, 255, 0.3); margin-top: 0.4em;
}

.erp__meter {
  display: block; flex: 1; height: 0.4em; border-radius: 999px;
  background: rgba(255, 255, 255, 0.08); overflow: hidden;
}
.erp__meter i { display: block; width: var(--w); height: 100%; background: var(--gold); }
.erp__meter i.erp__meter--low { background: #C97A6A; }

.erp__meters { display: flex; flex-direction: column; gap: 0.7em; justify-content: center; flex: 1; }
.erp__meters li, .erp__list li, .erp__feed li {
  display: flex; align-items: center; gap: 0.7em;
  font-size: 0.72em;
}
.erp__meters .erp__f { flex: 0 0 8.5em; color: rgba(255, 255, 255, 0.72); }
.erp__meters .erp__m { flex: 0 0 4.4em; text-align: right; color: var(--white); font-variant-numeric: tabular-nums; }

.erp__feed { display: flex; flex-direction: column; gap: 0.62em; }
.erp__feed .erp__t { flex: 0 0 4.4em; white-space: nowrap; color: rgba(255, 255, 255, 0.34); font-variant-numeric: tabular-nums; }
.erp__feed .erp__f { flex: 1; color: rgba(255, 255, 255, 0.78); }
.erp__feed .erp__m { color: rgba(255, 255, 255, 0.34); }

.erp__list { display: flex; flex-direction: column; gap: 0.1em; overflow: hidden; }
.erp__list li {
  justify-content: space-between; padding: 0.34em 0.5em; border-radius: 0.2em;
  color: rgba(255, 255, 255, 0.72); cursor: default;
}
.erp__list li.is-on { background: rgba(255, 255, 255, 0.06); color: var(--white); }
.erp__list li.is-on .erp__f { color: var(--gold); }
.erp__list .erp__m { color: rgba(255, 255, 255, 0.32); }

/* Aged receivables: one bar, four bands, because the question a finance lead
   asks is what share is late rather than what each bucket is worth. */
.erp__ages { display: flex; height: 0.55em; border-radius: 999px; overflow: hidden; gap: 1px; }
.erp__seg { display: block; width: var(--w); }
.erp__seg--1, .erp__dot--1 { background: var(--gold); }
.erp__seg--2, .erp__dot--2 { background: rgba(201, 168, 106, 0.58); }
.erp__seg--3, .erp__dot--3 { background: rgba(201, 168, 106, 0.3); }
.erp__seg--4, .erp__dot--4 { background: #C97A6A; }
.erp__agekeys { display: grid; grid-template-columns: 1fr 1fr; gap: 0.35em 0.8em; margin-top: 0.9em; }
.erp__agekeys li { display: flex; align-items: center; gap: 0.45em; font-size: 0.66em; color: rgba(255, 255, 255, 0.5); }
.erp__agekeys b { color: var(--white); font-weight: 600; margin-left: auto; }
.erp__dot { width: 0.5em; height: 0.5em; border-radius: 50%; flex: 0 0 auto; }
.erp__total {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: auto; padding-top: 0.8em;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  font-size: 0.68em; color: rgba(255, 255, 255, 0.42); max-width: none;
}
.erp__total b { font-family: var(--ff-display); font-size: 1.15em; color: var(--white); }

/* --- Tables --- */
.erp__table { width: 100%; border-collapse: collapse; font-size: 0.72em; }
.erp__table th {
  position: sticky; top: 0;
  text-align: left; font-family: var(--ff-display); font-weight: 600;
  font-size: 0.86em; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.36);
  padding: 0.9em 1.2em; background: rgba(255, 255, 255, 0.03);
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.erp__table td {
  padding: 0.95em 1.2em;
  color: rgba(255, 255, 255, 0.76);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
/* A record is one line. Left to wrap, a customer name takes two and the row
   heights stop matching, which is the fastest way to make a table look like a
   web page rather than an application. */
.erp__table th, .erp__table td { white-space: nowrap; }
.erp__table tr:last-child td { border-bottom: 0; }
.erp__table tbody tr { transition: background var(--dur-fast) var(--ease); }
.erp__table tbody tr:hover { background: rgba(255, 255, 255, 0.035); }
.erp__table td:first-child { color: var(--white); }
.erp__num { text-align: right; font-variant-numeric: tabular-nums; }
.erp__mono { font-variant-numeric: tabular-nums; color: rgba(255, 255, 255, 0.6); }
.erp__prog { display: flex; align-items: center; gap: 0.6em; min-width: 7em; }
.erp__prog b { font-weight: 600; color: var(--white); font-variant-numeric: tabular-nums; }

/* Eight of thirty four, page one of five. It is the line that says this is a
   window on to a set of records rather than the whole of them. */
.erp__tfoot {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: auto; padding: 0.85em 1.2em;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.02);
  font-size: 0.64em; color: rgba(255, 255, 255, 0.34); max-width: none;
}
.erp__tfoot b { font-weight: 400; color: rgba(255, 255, 255, 0.55); }

.erp__pill {
  display: inline-block;
  font-size: 0.86em; padding: 0.14em 0.6em; border-radius: 999px;
  border: 1px solid transparent; white-space: nowrap;
}
.erp__pill--live { color: var(--gold); border-color: var(--gold-40); background: rgba(201, 168, 106, 0.10); }
.erp__pill--wait { color: rgba(255, 255, 255, 0.6); border-color: rgba(255, 255, 255, 0.14); }
.erp__pill--done { color: #8FBF9F; border-color: rgba(143, 191, 159, 0.34); background: rgba(143, 191, 159, 0.08); }
.erp__pill--stop { color: #D89080; border-color: rgba(216, 144, 128, 0.38); background: rgba(216, 144, 128, 0.10); }

/* Small monitor: the same system, fewer columns. An interface that keeps all
   six columns and shrinks the type instead is one nobody can read. */
@container (max-width: 430px) {
  .erp { grid-template-columns: 7.6em 1fr; }
  /* Stacked into a screen this short, a module can run past the bottom of the
     glass. It scrolls there, the way an application does in a small window,
     rather than being cut off by it. */
  .erp__panel { overflow-y: auto; }
  .erp__search, .erp__who, .erp__sidefoot { display: none; }
  .erp__pnote { display: none; }
  /* Two across. Four columns at this width gives each tile about sixty pixels,
     which turns "Revenue, month to date" into three lines and a figure into
     two; two columns costs a second row and buys back far more than it
     spends. The figure never wraps either way. */
  .erp__kpis { grid-template-columns: 1fr 1fr; }
  .erp__kpi-v { white-space: nowrap; }
  .erp__kpi { padding: 0.55em 0.7em; }
  /* A chart with no height left is a row of invisible bars, so it keeps a
     floor and the module scrolls instead. */
  .erp__chart { min-height: 5.5em; }
  .erp__feed { min-height: 5.5em; }
  /* The splits stay side by side. This screen is 1.94:1 whatever size it is
     rendered at, so stacking them is fighting the shape of the glass: it runs
     the module off the bottom while leaving the right half empty. */
  .erp__table th:nth-child(3), .erp__table td:nth-child(3),
  .erp__table th:nth-child(4), .erp__table td:nth-child(4) { display: none; }
  .erp__facts { grid-template-columns: 1fr; }
}

/* --- Demo: digital experience (depth) --- */
/* --- Demo: branding & content ---
   Three columns, and the order is the argument: the identity, the book it is
   written into, and the agents that work from that book. An agent is only
   ever as on-brand as the document it was given, so the book sits physically
   between the identity and the things consuming it.

   All three are the same width and stretch to the same height. They are three
   parts of one deliverable, and unequal cards would have implied a hierarchy
   between them that does not exist — the hierarchy in this panel is inside
   the third column, not across the row.

   Only the middle one is paper. The outer two take the interface's own panel
   treatment, so the row reads as: the system applied, the system written
   down, the system operated. */
.brand {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 0.8rem; align-items: stretch;
}
.brand__card,
.brand__book {
  display: flex; flex-direction: column;
  border-radius: 4px; padding: 0.75rem 0.8rem;
}
.brand__card {
  border: 1px solid var(--sky-08);
  background: rgba(255, 255, 255, 0.02);
}
.brand__k {
  font-family: var(--ff-display); font-size: 0.58rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--sky-38);
}

/* Identity. The mark takes whatever height the row settles at rather than a
   fixed size, so it stays optically centred against the other two columns. */
.brand__logo { flex: 1; display: grid; place-items: center; padding-block: 0.9rem; }
.brand__mark { width: 82%; max-width: 148px; }
.brand__swatches { display: flex; gap: 5px; }
.brand__swatches span { flex: 1; height: 24px; border-radius: 2px; }

/* The book. Paper on a midnight panel — the same device the invoice module
   uses, and the reason a rectangle reads as a document rather than a card. */
.brand__book {
  background: var(--white);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.38);
}
.brand__booktag {
  font-family: var(--ff-display); font-size: 0.56rem; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--midnight);
  padding-bottom: 0.45rem; margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--silver);
}
.brand__toc { flex: 1; display: grid; gap: 0.34rem; align-content: start; }
.brand__toc li {
  display: flex; gap: 0.5rem; align-items: baseline;
  font-size: 0.62rem; color: var(--deep-text);
}
.brand__toc span {
  font-family: var(--ff-display); font-weight: 600; color: var(--gold);
  font-size: 0.54rem; letter-spacing: 0.06em;
}
.brand__bookfoot {
  margin-top: 0.5rem; padding-top: 0.4rem; border-top: 1px solid var(--silver);
  font-family: var(--ff-display); font-size: 0.5rem;
  letter-spacing: 0.08em; color: var(--ink-40);
}

/* The AI agent, drawn as a distribution. One agent built on the book beside it,
   a stem down, a bar, and every application the brand appears in hanging off
   it.

   Deliberately not an org chart of several agents. The claim is not that we
   own a fleet of them — it is that you get one, built on your material, and
   it serves everywhere. A stem meeting a bar is the diagram idiom for exactly
   that, and unlike per-item connectors it holds its meaning however many
   applications there are and however they wrap.

   Every line is a pseudo-element on something that had to exist anyway, so
   the diagram costs no markup beyond the nodes. */
.brand__agents { justify-content: center; }
.brand__map { display: grid; justify-items: center; margin-top: 0.9rem; }

.brand__node {
  display: flex; align-items: center; gap: 0.5rem;
  border: 1px solid var(--sky-16); border-radius: 3px;
  padding: 0.4rem 0.6rem;
  font-family: var(--ff-display); font-size: 0.66rem; font-weight: 600;
  color: var(--sky-80); line-height: 1.2;
}
.brand__node--lead {
  border-color: var(--gold-40); background: var(--gold-14);
  color: var(--white);
}
.brand__nodedot {
  flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%;
  background: var(--gold);
}
.brand__leadtext { display: grid; gap: 0.12rem; text-align: left; }
/* The second line is what makes it custom rather than generic — it names the
   thing the agent was built from, which is sitting in the column beside it. */
.brand__leadsub {
  font-style: normal; font-size: 0.5rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--sky-58);
}

/* Stem and bar. The bar runs the full width of the applications below it,
   because they all come from the one agent above. */
.brand__fan { position: relative; display: block; width: 100%; height: 20px; }
.brand__fan::before {
  content: ""; position: absolute; left: 50%; top: 0;
  width: 1px; height: 12px; background: var(--sky-16);
}
.brand__fan::after {
  content: ""; position: absolute; top: 12px; left: 4%; right: 4%;
  height: 1px; background: var(--sky-16);
}

/* The applications. Pills rather than boxes, so they read as a set of places
   the agent is used rather than as a second tier of things. They wrap freely
   — the number is meant to look like "and so on", not like a fixed list. */
.brand__apps {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 0.3rem; width: 100%;
}
.brand__apps li {
  border: 1px solid var(--sky-16); border-radius: 999px;
  padding: 0.22rem 0.55rem;
  font-family: var(--ff-display); font-size: 0.58rem; font-weight: 500;
  color: var(--sky-80);
}
.brand__mapnote {
  margin-top: 0.9rem; font-size: 0.6rem; color: var(--sky-38); text-align: center;
}
.brand__note { margin-top: 0.85rem; font-size: 0.66rem; color: var(--sky-38); }

/* Between 941px and 1180px the stage column is at its narrowest — three
   columns there put each one under 170px, which is not enough for the book's
   contents. The agents drop to a full-width row beneath the other two. */
@media (min-width: 941px) and (max-width: 1180px) {
  .brand { grid-template-columns: 1fr 1fr; }
  .brand__agents { grid-column: 1 / -1; }
  }
@media (max-width: 520px) {
  .brand { grid-template-columns: 1fr; }
  .brand__logo { padding-block: 0.6rem; }
  }

/* --- Demo: digital experiences ---
   The frame holds this page rather than a photograph of a screen. A picture
   of a laptop would only ever be a picture of the claim; the claim is that
   the site you are on is the sample, so the demonstration is the site.

   It also fits. The stage frame is roughly 1420 by 292, near enough five to
   one, and the only photograph in the project is 16:9 — cover would have
   sliced it to a horizontal band with the screens cut off. A browser window
   is the one thing that belongs in a shape that wide and that short.

   The push runs on the page inside the window, not on the window, which is
   the difference between a camera moving through a scene and someone zooming
   a screenshot. It is also exactly what the caption claims. */
.depth {
  position: relative; height: 292px; overflow: hidden; border-radius: 4px;
  background: var(--midnight);
}
.sitemini { position: absolute; inset: 0; display: flex; flex-direction: column; }

/* Browser chrome, held deliberately quiet: it is a frame around the subject,
   not part of it. */
.sitemini__chrome {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 5px;
  padding: 0.42rem 0.7rem;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid var(--sky-08);
}
.sitemini__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--sky-16); }
.sitemini__url {
  margin-left: 0.8rem; padding: 0.1rem 0.7rem;
  border-radius: 999px; background: rgba(255, 255, 255, 0.05);
  font-family: var(--ff-display); font-size: 0.55rem;
  letter-spacing: 0.06em; color: var(--sky-38);
}

/* The perspective lives on the viewport, so the object inside gets real
   depth rather than a flat drawing of it. */
.sitemini__view { position: relative; flex: 1; overflow: hidden; perspective: 760px; }
.sitemini__scene { position: absolute; inset: 0; padding: 0.9rem clamp(0.9rem, 2vw, 1.8rem); }

/* --- The object ---
   A wireframe globe assembled in 3D space: six rings standing on end at 30°
   to each other, and five lying flat at the latitudes where a sphere of that
   radius would cut them. Nothing here is a picture of a sphere — the rings
   are ordinary circles placed in space, and the sphere is what the browser
   works out when it renders them.

   That is the point of using it as the example. A flat graphic could imitate
   the look; only real geometry keeps its silhouette correct through a full
   turn, which is what the caption is claiming. It replaced the camera push
   that used to run here: two kinds of motion in one small frame competed, and
   the rotation is the one that demonstrates something. */
.globe {
  position: absolute; right: 8%; top: 50%;
  width: clamp(112px, 13vw, 178px); aspect-ratio: 1;
  transform-style: preserve-3d;
  animation: globeSpin 18s linear infinite;
}
@keyframes globeSpin {
  from { transform: translateY(-50%) rotateX(-16deg) rotateY(0deg); }
  to   { transform: translateY(-50%) rotateX(-16deg) rotateY(360deg); }
}
.globe__lon,
.globe__lat {
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 1px solid var(--gold-40);
}
.globe__lon { transform: rotateY(var(--r)); }
/* Flat rings: turned into the horizontal plane, lifted to their latitude,
   then narrowed to the radius a sphere actually has at that height. */
.globe__lat {
  border-color: var(--sky-16);
  transform: rotateX(90deg) translateZ(calc(var(--z) * 50%)) scale(var(--s));
}

@media (prefers-reduced-motion: reduce) {
  .globe { animation: none; transform: translateY(-50%) rotateX(-16deg) rotateY(24deg); }
}

.sitemini__nav {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: clamp(0.7rem, 2vw, 1.4rem);
}
.sitemini__mark {
  font-family: var(--ff-display); font-size: 0.62rem; font-weight: 700;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--white);
}
.sitemini__pill {
  width: 46px; height: 11px; border-radius: 2px; background: var(--gold);
}
.sitemini__eyebrow {
  font-family: var(--ff-display); font-size: 0.5rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--gold);
  margin-bottom: 0.45rem;
}
.sitemini__h1 {
  font-family: var(--ff-display); font-weight: 600;
  font-size: clamp(0.95rem, 1.5vw, 1.45rem);
  line-height: 1.08; letter-spacing: -0.03em;
  color: var(--white); max-width: 11ch;
}
.sitemini__btns { display: flex; gap: 6px; margin-top: clamp(0.6rem, 1.6vw, 1.1rem); }
.sitemini__btn {
  width: 62px; height: 15px; border-radius: 2px;
  border: 1px solid var(--sky-16);
}
.sitemini__btn--gold { background: var(--gold); border-color: var(--gold); }

.depth__cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 1rem;
  background: linear-gradient(transparent, rgba(15,23,42,0.9));
  font-size: var(--fs-small); color: var(--sky-80);
}

/* ======================= INSIGHTS ======================================== */


.filter {
  font-size: var(--fs-small); font-weight: 500; color: var(--ink-55);
  background: none; border: 1px solid var(--silver); border-radius: 999px;
  padding: 0.45rem 1rem; cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.filter:hover { border-color: var(--ink-40); color: var(--midnight); }
.filter.is-active { background: var(--midnight); border-color: var(--midnight); color: var(--white); }


.next { display: grid; gap: 0; border-top: 1px solid var(--ink-14); }
.next__step { display: grid; grid-template-columns: 34px 1fr; gap: 1rem; padding-block: 1.1rem; border-bottom: 1px solid var(--ink-14); }
.next__n {
  font-family: var(--ff-display); font-weight: 600; color: var(--gold);
  font-size: clamp(1.02rem, 1.15vw, 1.22rem);
  /* A length, not a ratio: this is the line box the title beside it gets
     (0.875rem of text at the body's 1.62), so the numeral keeps sitting level
     with the title no matter how much larger its own type is. */
  line-height: 1.42rem;
}
.next__t { font-family: var(--ff-display); font-weight: 600; font-size: var(--fs-small); color: var(--midnight); margin-bottom: 0.2rem; }
.next__d { font-size: var(--fs-small); color: var(--ink-55); }

/* ======================= HOME : LET’S TALK (closing) ==================== */
/* One question, one action, one number. The section carries no form because a
   form is a second decision: which fields matter, what to write, whether the
   message ever arrived. WhatsApp answers all three before the visitor has
   typed anything, and it is the channel this business actually replies on.

   White rather than ice or midnight. The Transformation Study above closes on
   midnight and the footer below opens on it, so a dark closer would run the
   last third of the page into one unbroken block; the white band is the beat
   of silence before the end. */
.talk {
  background: var(--white);
  /* More air than --sec-y gives. This is the only block on the page whose job
     is to be uncrowded: the space around the button is what makes it read as
     the conclusion rather than as one more row. */
  padding-block: clamp(96px, 12vw, 190px);
  text-align: center;
}
/* Contained, and centred, on a page that is otherwise full-bleed and
   left-aligned. Both breaks are deliberate: the layout visibly closes in at
   the end, which is the difference between a page that finishes and a page
   that stops. */
.talk__inner {
  max-width: 820px;
  margin-inline: auto;
  display: flex; flex-direction: column; align-items: center;
}

/* A hairline that draws itself from the middle out as the block arrives. The
   restrained gold accent for the section: it opens the close the way a rule
   opens a chapter, and it is the only thing here that moves on its own. */
.talk__rule {
  position: relative; overflow: hidden;
  width: 72px; height: 1px;
  background: var(--ink-14);
  margin-bottom: clamp(1.6rem, 2.6vw, 2.2rem);
}
.talk__rule::after {
  content: ""; position: absolute; inset: 0;
  background: var(--gold);
  transform: scaleX(0); transform-origin: center;
  transition: transform 1100ms var(--ease-out) 260ms;
}
.talk__rule.is-in::after { transform: scaleX(1); }

/* Larger than --fs-h2. Every other heading on the page is one of several;
   this one is the last thing said, and it is set to be read as such. The line
   break is authored rather than left to the wrap, so the two halves stay
   balanced at every width instead of the second line orphaning a word. */
.talk__h {
  font-size: clamp(1.95rem, 4.6vw, 4rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  margin-bottom: clamp(1.1rem, 1.8vw, 1.5rem);
}
.talk__lead {
  max-width: 58ch;
  margin-inline: auto;
  font-size: var(--fs-lead);
  line-height: 1.6;
  color: var(--ink-70);
  margin-bottom: clamp(2.2rem, 3.6vw, 3rem);
}

/* --- The one action --- */
/* Midnight, not gold. Gold is the site’s button colour, so a gold slab here
   would read as the seventh instance of a pattern rather than as the end of
   the page; midnight makes it the single dark object on a white field, which
   is unmistakable at a glance and leaves gold as the detail the brand book
   asks it to be. Hovering swaps the two — the accent arrives as the reward
   for reaching — which is also why the glyph inverts with it.

   The size is a decision, not a flourish: 62px of height and a full-width
   block on small screens put it far past any tap target it needs to clear. */
.talk__cta {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.85rem;
  min-height: 62px;
  padding: 0.95rem clamp(1.5rem, 3vw, 2.4rem);
  background: var(--midnight);
  color: var(--white);
  border: 1px solid var(--midnight);
  border-radius: var(--radius);
  font-family: var(--ff-display);
  font-size: clamp(0.9rem, 1.05vw, 1.02rem);
  font-weight: 600; letter-spacing: 0.01em; line-height: 1.2;
  box-shadow: 0 14px 34px rgba(15, 23, 42, 0.16);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform var(--dur-fast) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.talk__cta:hover {
  background: var(--gold); border-color: var(--gold); color: var(--midnight);
  transform: translateY(-2px);
  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.20);
}
.talk__cta:active { transform: translateY(0); }
.talk__mark { width: 22px; height: 22px; flex: 0 0 auto; }
/* The glyph is painted, not knocked out, so it survives the colour swap: the
   bubble takes the accent and the handset takes the ground, and on hover the
   two trade places along with the button. */
.talk__markBubble { fill: var(--gold); transition: fill var(--dur) var(--ease); }
.talk__markPhone  { fill: var(--midnight); transition: fill var(--dur) var(--ease); }
.talk__cta:hover .talk__markBubble { fill: var(--midnight); }
.talk__cta:hover .talk__markPhone  { fill: var(--gold); }
.talk__arrow { transition: transform var(--dur) var(--ease); }
.talk__cta:hover .talk__arrow { transform: translateX(4px); }

/* The destination, shown so the button is not a leap of faith. Deliberately
   not a tel: link: a second tappable contact would be a second path, and the
   section is built to have one. */
.talk__num {
  margin-top: clamp(1.3rem, 2.2vw, 1.8rem);
  font-family: var(--ff-display); font-weight: 600;
  font-size: var(--fs-small); letter-spacing: 0.12em;
  color: var(--ink-70);
}
@media (max-width: 560px) {
  .talk__cta { width: 100%; }
  .talk__act { width: 100%; }
}

/* ======================= HOME : THE ECOSYSTEM MAP ======================== */
/* The six areas are shown as one place rather than six rows. The photograph
   is the interface: the visitor sees the whole estate first, then finds the
   districts by moving over them, and choosing one runs it on the stage below.

   Nothing here edits the image. The exploring state is two translucent layers
   over it — one that drops the whole plate back, one that puts the light
   returned on a single island — so the source is used exactly as supplied. */
section[id] { scroll-margin-top: calc(var(--nav-h) + 14px); }
/* Except the estate, which is exactly the height of the window. Leaving the
   usual bar's worth of margin on it would have pushed the scene down by that
   much and taken the same off its foot, so the one section that is meant to
   fill the screen lands flush with the top of it and the bar floats over its
   sky — which is what the title is set to clear. */
#what-we-build { scroll-margin-top: 0; }

.eco {
  /* One box, two states. The estate and the six interiors occupy exactly the
     same rectangle, so going into a building replaces the view instead of
     adding another panel underneath it — which is the whole difference
     between a section with a picture on it and a place you can walk into.

     It clips, because entering pushes the photograph up past two and a half
     times its size and that has to happen inside the frame you are looking
     through. It is also the container the interior sizes itself against, so
     the type inside scales with the plate rather than with the window. */
  position: relative;
  container-type: inline-size;
  /* The viewport is the composition.

     Fitting the whole 3:2 photograph inside a 16:9 screen always costs the
     width, and any width it costs shows up as a frame down both sides. There
     is no version of "show every pixel" that does not put the scene in a box,
     so the scene stops trying: it takes the full width and the full height of
     the window, and the photograph is cropped to cover it.

     Which edge gets cropped is the whole decision, and it is not centred. The
     six districts are not spread evenly down the plate: the buildings finish
     at 86% of it and the shoreline they stand on at 94%, so everything worth
     keeping is in the top nine tenths. The foot is cropped to exactly that
     line and no further, which leaves the two front districts standing on a
     visible piece of ground rather than on the edge of the screen. What
     floats is the top: nothing at all on a window of 3:2 or taller, and about
     a sixteenth on a 16:9 one, which takes the tip of the Burj's needle at
     the widest ratios and nothing that can be pointed at, at any of them.

     And the plate is never allowed to be shorter than the window. On a 4:3
     screen a full-width plate does not reach the bottom, so the plate grows
     by height instead and the crop moves to the sides — the least of it that
     covers, taken evenly off both, because the estate is symmetrical.

     Every marker is still a percentage of the plate rather than of the window,
     so the districts and their labels move together underneath the crop and
     cannot come apart. */
  width: 100%;
  height: 100svh;
  overflow: hidden;
  scroll-margin-top: calc(var(--nav-h) + 8px);
}
/* --- The room is not the window ------------------------------------------
   The estate is one window tall, because the estate is a photograph and the
   window is its frame. An interior is not a photograph: it is a room with a
   demonstration in it, a way out above and a caption below, and all five were
   drawn against a box of the picture's own proportions — three by two, which
   at 1920 is 1269px deep, not 985.

   Making the estate fill the window took 284px out of every one of those
   rooms, and they have been colliding ever since: headings across charts,
   screens under the way out, a caption meeting the demonstration. Everything
   inside a room is measured in container widths precisely because the box was
   two thirds of its own width, which kept the type, the screens and the
   caption in fixed proportion to each other at every size.

   So the estate keeps the window and the interior takes its proportions back.
   It is taller than the window on a wide desktop, which is what it always
   was — the way out is at the top, and the caption is read on the way down. */
@media (min-width: 1101px) {
  .eco.is-inside { height: max(100svh, 66.67cqw); }
}

/* The scene brings its own top edge, so the section does not add one. */
.section--flush { padding-top: 0; }

/* The plate. The aspect ratio is the source image's own, exactly, because
   every marker below is placed as a percentage of this box: crop the frame
   and the buildings slide out from under their labels. So the frame keeps 3:2
   and overflows the window it sits in, rather than being squeezed to fit it —
   the coordinate space stays the photograph's own and the clipping happens
   one level up. isolation keeps the illumination blending against the
   photograph rather than the page.

   Pinned by its foot, not its head, and the foot is where the measuring was
   done. The two front buildings meet their own ground at 90% of the plate and
   the island they stand on runs out into the water at about 94%. The plate is
   1.5 times as wide as it is tall, so 7% of its height is 4.67% of its width:
   hang it that far below the window and the visible band ends at 93% — the
   buildings whole, standing on three points of promenade rather than on the
   edge of the screen, with only the last of the water lost. The markers sit
   at 82%, so they are never near the edge.

   The min() is what stops that hanging foot from opening a gap at the top.
   The second term is the whole of the overhang the plate can afford before
   its head leaves the window, so on a tall screen the foot simply stops
   hanging and the plate sits flush top and bottom instead. Which leaves the
   width: at least the window, and at least 1.5 window-heights, so there is
   always enough plate to cover in both directions. It is centred by its own
   half-width rather than by transform, because transform is the camera. */
.eco__frame {
  --plate-w: max(100vw, 150svh);
  position: absolute;
  top: auto;
  bottom: calc(0px - min(var(--plate-w) * 0.0466667,
                         var(--plate-w) / 1.5 - 100svh));
  left: 50%;
  margin-left: calc(var(--plate-w) / -2);
  width: var(--plate-w);
  isolation: isolate;
  aspect-ratio: 1536 / 1024;
  background: var(--midnight);
  /* The camera. Choosing a district pushes the scene past the edge of the
     frame towards it, from an origin taken from that building's own
     coordinates — which is what makes it read as going to that building
     rather than as a zoom. */
  transform-origin: var(--ox, 50%) var(--oy, 50%);
  transition: transform 880ms var(--ease-out),
              opacity 560ms var(--ease-out),
              filter 700ms var(--ease-out),
              visibility 0s;
}
.eco__img { width: 100%; height: 100%; object-fit: cover; }

/* Past about two to one there is no sky left to put a title in. A window that
   shape takes a quarter of the photograph's height away, and the photograph
   only has a quarter of sky, so the crop arrives at the top row of labels and
   the title comes down on top of them: on a maximised 1280 by 720 laptop the
   heading was running straight through Transformation Lab and the line under
   it through Custom Business Systems.

   Nothing can be gained back from the picture — the arithmetic is the same
   whichever edge it is taken from — so the two things that can give, do. The
   foot gives up its three points of promenade, which puts the whole label
   band a little lower while still keeping all six buildings whole; and the
   title gives up its second line, which is the only part of the block that
   is not the name of the section. Both come back the moment the window is a
   normal shape again. */
@media (min-width: 1101px) and (min-aspect-ratio: 39/20) {
  .eco__frame {
    bottom: calc(0px - min(var(--plate-w) * 0.0666667,
                           var(--plate-w) / 1.5 - 100svh));
  }
  .eco__head .lead { display: none; }
  /* And the heading stops being sized by width alone. On an ultrawide the
     scene is 2500 across and 1000 down: two and a half per cent of the width
     is a 66px heading standing in a sliver of sky, and it reached the labels
     again with the second line already gone. Whichever of the two is smaller
     wins, so the block is bounded by the sky it has rather than by how wide
     the window happens to be. */
  .eco__head h2 { font-size: max(1.5rem, min(2.6cqw, 3.8svh)); }
  .eco__head .eyebrow {
    font-size: max(0.625rem, min(0.8cqw, 1.22svh));
    margin-bottom: max(0.4rem, min(1.07cqw, 1.6svh));
  }
}

/* --- The title, in the sky ---
   Set straight on to the photograph with no card, panel or wash behind it:
   the left quarter of the image is open sky and distant shoreline, which is
   dark enough to carry white type on a halo alone. Sized in container units
   so it scales with the plate, not the window — a heading that grew while its
   sky stayed the same size would climb off the top of it. */
.eco__head {
  position: absolute; z-index: 4;
  /* Under the bar, and measured from the top of the window rather than from
     the plate. The plate's own foot now moves with the shape of the window —
     hanging on a wide one, flush on a tall one — so a place fixed to it would
     have carried the title up and down the sky with it. The top of the window
     does not move, and on a scene that covers the window the top of the
     window is sky at every ratio. */
  left: 4.5%;
  top: calc(var(--nav-h) + 0.25rem);
  /* Type over a picture, and nothing in it to press. On a wide, short window
     the sky is mostly cropped away and the block comes down over the middle
     of the estate, where its invisible box was taking the clicks meant for the
     Transformation Lab and, on the shortest, for Custom Business Systems too.
     Same arrangement the markers already use one level down: the layer lets
     the pointer through and only the things worth pressing catch it. */
  pointer-events: none;
  /* Both lines hold on one line each, so the block is as wide as its widest
     line and no wider: no column to wrap inside, and nothing to set a width
     to. nowrap guarantees it; the sizes below are what keep that promise from
     running off the side of the photograph.

     Sized against the scene rather than the window, and set so the longest
     line — the heading, at 44 characters — finishes around 58% of the frame
     even in the widest fallback face the stack can land on.
     That leaves the Burj and the dense half of the skyline clear at every
     width, and holds the whole block inside the sky band. */
  white-space: nowrap;
  width: auto; max-width: none;
  color: var(--white);
  /* Three shadows, not one. The sky itself is an even mid-tone and needs
     almost nothing, but the block is taller than the sky is deep, so the last
     two lines always land on the far shoreline — dark on average and full of
     window lights that would otherwise cut into the letters. The tight pair
     handles the specks; the wide one seats the whole block. */
  /* The block now sits entirely on open sky, which is the brightest ground on
     the plate — an even 120 to 140, with cloud highlights reaching 200. White
     type survives that on the average and not on the highlights, so the halo
     is what actually carries it: two tight shadows to cut an edge against the
     bright cloud, one wide one to seat the block on the scene. */
  text-shadow: 0 1px 2px rgba(15, 23, 42, 0.92),
               0 0 7px rgba(15, 23, 42, 0.72),
               0 2px 26px rgba(15, 23, 42, 0.55);
  transition: opacity 520ms var(--ease-out), transform 760ms var(--ease-out);
}
.eco__head h2 {
  color: var(--white);
  /* Sized against the scene, with a floor under it. The scene is capped by
     height now, so on a short wide laptop the container is a third narrower
     than the window and everything measured in cqw came down with it: at
     1366 by 768 the eyebrow was landing at 7px and the lead at 11.8px, which
     is a heading nobody can read on the one section the whole page is built
     around. max() keeps the proportional scaling exactly as it was wherever
     there is room for it, and simply stops it going below what type needs to
     stay type. The floors are set so the block still finishes inside the 58%
     of the plate the sky band allows. */
  font-size: max(1.5rem, 2.6cqw);
  letter-spacing: -0.025em;
}
.eco__head .eyebrow { font-size: max(0.625rem, 0.8cqw); margin-bottom: max(0.55rem, 1.07cqw); }
.eco__head .lead {
  color: rgba(255, 255, 255, 0.82);
  font-size: max(0.8125rem, 1.35cqw);
  max-width: none;
  /* The gaps inside this block scale with the scene as well, and for a
     sharper reason than the type did: held in rem they stayed the same
     number of pixels while the plate shrank, so on a short laptop the block
     grew taller relative to the photograph and its last line came down on
     the Transformation Lab's label. In cqw the block keeps its proportions,
     and 1.07cqw is exactly the 0.9rem it used to be at the widest size. */
  margin-top: max(0.55rem, 1.07cqw);
}
/* The tilt is the whole of the trick: a few degrees on to the façade plane
   and the mark sits on the tower instead of on the glass of the screen. */
.eco__core {
  position: absolute; left: 50%; top: 60%;
  width: 3.4%; height: auto;
  transform: translate(-50%, -50%) perspective(340px) rotateX(-9deg);
  opacity: 0.94;
  filter: drop-shadow(0 0 7px rgba(255, 246, 228, 0.45))
          drop-shadow(0 2px 3px rgba(15, 23, 42, 0.80));
  pointer-events: none;
}

/* --- The six hotspots ---
   Each button covers the whole plate and takes no pointer itself; only its
   marker and its label do. That is what lets six of them overlap without one
   sitting on top of the image and swallowing every hover, and it means both
   the dot and the words belong to the same control rather than being two
   things a visitor has to aim at separately. */
.eco__pts { position: absolute; inset: 0; pointer-events: none; }
.eco__pt {
  position: absolute; inset: 0;
  background: none; border: 0; padding: 0;
  font: inherit; color: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 700ms var(--ease-out) var(--pt-delay, 0ms);
}
/* The districts come up one after another as the plate arrives, on the
   stagger the rest of the page already uses. */
.eco.is-in .eco__pt { opacity: 1; }

/* The building itself, not the dot on it. An ellipse over each island's
   footprint, invisible and doing all the work: the marker says a place is
   here, the footprint is what you actually point at and press. */
.eco__zone {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--zw); height: var(--zh);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  pointer-events: auto; cursor: pointer;
}

.eco__node {
  position: absolute;
  left: var(--x); top: var(--y);
  width: 44px; height: 44px;              /* the tap target, centred on the roof */
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  pointer-events: auto; cursor: pointer;
}
.eco__node::after {
  content: "";
  width: 11px; height: 11px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.90);
  background: rgba(15, 23, 42, 0.42);
  /* Two shadows: a dark halo so the marker holds against a white roof, and a
     soft drop so it holds against dark water. It has to read on both. */
  box-shadow: 0 0 0 5px rgba(15, 23, 42, 0.24), 0 2px 8px rgba(15, 23, 42, 0.55);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}

/* Every label sits below its marker and over water. That is not a layout
   rule, it is where the photograph has room: the labels were placed on the
   dark parts of the image so they need a halo rather than a panel to stay
   readable, and the architecture is never covered. */
.eco__label {
  position: absolute;
  left: var(--x); top: var(--ly);
  transform: translate(-50%, -50%);
  pointer-events: auto; cursor: pointer;
  white-space: nowrap;
  font-family: var(--ff-display);
  font-size: clamp(0.7rem, 0.82cqw, 1.05rem);
  font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.74);
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.95), 0 2px 14px rgba(15, 23, 42, 0.80);
  /* Padding it does not appear to need at rest: with no background there is
     nothing to see, but it is what the gold plate is made of when one is
     pointed at. Symmetrical, so growing it does not shift the label off the
     building it names. */
  padding: 0.36em 0.72em;
  border-radius: 3px;
  background: rgba(201, 168, 106, 0);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              text-shadow var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* Pointing at a district. This is the whole of it: the marker fills and the
   name goes gold. Nothing is laid over the photograph, nothing is taken off
   it, and the scene the visitor is reading does not move. */
.eco__pt.is-hot .eco__node::after {
  background: var(--gold); border-color: var(--gold);
  transform: scale(1.18);
  box-shadow: 0 0 0 7px rgba(201, 168, 106, 0.20), 0 2px 12px rgba(15, 23, 42, 0.60);
}
.eco__pt.is-hot .eco__label {
  background: var(--gold);
  color: var(--midnight);
  box-shadow: 0 3px 12px rgba(15, 23, 42, 0.34);
  /* The same two shadows at zero alpha rather than `none`: a shadow list only
     interpolates against another list of the same shape, so this is what lets
     the halo fade out as the plate fades in instead of snapping off it. */
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0), 0 2px 14px rgba(15, 23, 42, 0);
}

/* Nothing marks the "chosen" district on the estate. It used to: the first
   area is selected from the start so its panel has something to be, and that
   selection showed here as a filled marker — which, once the stage moved
   behind the buildings, meant one building sat permanently gold with nothing
   to explain it. Selection is still tracked for the panels and for ARIA; it
   just has nothing to say out here, where every building is equally a place
   you have not been yet. */

/* --- A building that is not open yet ---
   Dimmer than the five that are, and inert: no pointer, no gold, no hover.
   The marker still says a place is here, because a place is here; it just
   does not answer yet, and a dot that lights up under the cursor and then
   does nothing is worse than no dot at all. */
.eco__pt--soon .eco__zone,
.eco__pt--soon .eco__node,
.eco__pt--soon .eco__label { pointer-events: none; cursor: default; }
.eco__pt--soon .eco__label {
  color: rgba(255, 255, 255, 0.44);
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.9), 0 2px 14px rgba(15, 23, 42, 0.7);
}
.eco__pt--soon .eco__node::after {
  border-color: rgba(255, 255, 255, 0.44);
  background: rgba(15, 23, 42, 0.30);
  box-shadow: 0 0 0 5px rgba(15, 23, 42, 0.18), 0 2px 8px rgba(15, 23, 42, 0.45);
}

/* The focus ring belongs on the marker, not on the button: the button is the
   whole plate, and an outline around the photograph says nothing about which
   district you are on. */
.eco__pt:focus-visible { outline: none; }
.eco__pt:focus-visible .eco__node::after {
  outline: 2px solid var(--gold); outline-offset: 5px;
}

/* --- Going in ---
   The photograph pushes past the edge of the frame towards the building that
   was chosen and blurs out of focus, and the interior arrives settling back
   from slightly too close. Neither is a cross-fade: one is the camera
   continuing the move it started on hover, the other is what is behind the
   door. Coming out plays it backwards, so leaving is the same movement in
   reverse rather than a different animation. */
/* visibility, not just opacity, here too. The heading used to be nothing but
   type, so fading it was enough; it holds the weather switch now, and a
   transparent button is still a tab stop — a keyboard inside an open interior
   was landing on "Prefer rainy Dubai?" with nothing on screen to explain it.
   Delayed to the end of the block's own move so the exit still plays in full. */
.eco.is-inside .eco__head {
  opacity: 0; transform: translateY(-14px);
  visibility: hidden;
  transition: opacity 520ms var(--ease-out),
              transform 760ms var(--ease-out),
              visibility 0s linear 760ms;
}
/* visibility, not just opacity: a transparent button is still a tab stop, and
   six invisible districts sitting in the tab order behind an open interior is
   a keyboard trap in all but name. Delayed to the end of the move so it plays
   out in full first. */
.eco.is-inside .eco__frame {
  transform: scale(2.5);
  opacity: 0;
  filter: blur(6px);
  pointer-events: none;
  visibility: hidden;
  transition: transform 880ms var(--ease-out),
              opacity 560ms var(--ease-out),
              filter 700ms var(--ease-out),
              visibility 0s linear 880ms;
}

/* ==========================================================================
   RAINY DUBAI

   An environment, not a theme. The photograph is never replaced and never
   touched: everything below is a wash, a mask or a drifting gradient laid
   over it, so the estate underneath is the same estate, the six buildings sit
   under the same markers, and switching back is a matter of taking the
   opacity away again.

   The stack, from the photograph up: the cool grade, the mist over the sky,
   the distant glow, the sheen on the wet ground, the shimmer on the water,
   the tower's mark, the rain, and then the labels — which stay on top of all
   of it, because weather that makes a word harder to read has stopped being
   worth having.
   ========================================================================== */

/* No z-index anywhere in here, deliberately. The markers keep the layer they
   were already being composited on, and the order comes from the document:
   photograph, weather, rain, then the tower's mark and the labels over all
   of it. */
.wx { position: absolute; inset: 0; pointer-events: none; }
.wx > * {
  position: absolute; display: block; opacity: 0;
  transition: opacity 1500ms var(--ease-out);
}
.eco.is-rain .wx > * { opacity: 1; }

/* The grade. Cooler and a little darker towards the top, where the weather
   is coming from, and darker again at the foot where the ground is wet. */
.wx__cool {
  inset: 0;
  background: linear-gradient(180deg,
    rgba(51, 65, 85, 0.46) 0%,
    rgba(37, 51, 74, 0.30) 34%,
    rgba(15, 23, 42, 0.24) 62%,
    rgba(15, 23, 42, 0.44) 100%);
}
/* The photograph's own colour, pulled back rather than repainted. */
.eco__img { transition: filter 1500ms var(--ease-out); }
.eco.is-rain .eco__img { filter: saturate(0.68) brightness(0.82) contrast(1.05); }

/* Cloud coming in over the sky band, masked away before it reaches the
   skyline so the city stays legible. Two layers at different speeds, which is
   what stops it reading as one moving object. */
.wx__mist {
  left: -32%; right: -32%; top: 0; height: 58%;
  will-change: transform;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 52%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 52%, transparent 100%);
}
.wx__mist--a {
  background:
    radial-gradient(58% 100% at 18% 42%, rgba(203, 213, 225, 0.22), rgba(203, 213, 225, 0) 70%),
    radial-gradient(46% 92% at 54% 20%, rgba(226, 232, 240, 0.18), rgba(226, 232, 240, 0) 72%),
    radial-gradient(56% 100% at 86% 48%, rgba(203, 213, 225, 0.2), rgba(203, 213, 225, 0) 70%);
  animation: wxDrift 96s linear infinite;
}
.wx__mist--b {
  height: 46%;
  background:
    radial-gradient(64% 100% at 34% 30%, rgba(148, 163, 184, 0.2), rgba(148, 163, 184, 0) 72%),
    radial-gradient(52% 96% at 72% 54%, rgba(203, 213, 225, 0.16), rgba(203, 213, 225, 0) 70%);
  animation: wxDrift 152s linear infinite reverse;
}
@keyframes wxDrift {
  from { transform: translate3d(-7%, 0, 0); }
  to   { transform: translate3d(7%, 0, 0); }
}

/* Lightning a long way off, behind the cloud. It never flashes: it swells
   and goes, twice, seventeen seconds apart, and never gets past a quarter. */
.wx__glow {
  left: 6%; right: 6%; top: -16%; height: 54%;
  background: radial-gradient(50% 60% at 63% 72%,
    rgba(226, 232, 240, 0.55), rgba(226, 232, 240, 0) 68%);
  mix-blend-mode: screen;
}
.eco.is-rain .wx__glow { animation: wxGlow 17s var(--ease) infinite; }
@keyframes wxGlow {
  0%, 88%, 100% { opacity: 0; }
  91.5% { opacity: 0.22; }
  93.5% { opacity: 0.08; }
  95.5% { opacity: 0.18; }
  99%   { opacity: 0; }
}

/* Wet ground: a sheen lifted out of the lower half rather than painted on to
   it, so what comes back is the light already in the photograph. */
.wx__wet {
  left: 0; right: 0; bottom: 0; height: 54%;
  background: linear-gradient(180deg,
    rgba(148, 163, 184, 0) 0%,
    rgba(148, 163, 184, 0.09) 44%,
    rgba(203, 213, 225, 0.15) 100%);
  mix-blend-mode: screen;
}
/* The water. Fine horizontal light, moving one repeat per cycle so it never
   seams, and kept far enough down that it reads as surface rather than as
   stripes across the city. */
.wx__ripple {
  left: 0; right: 0; bottom: 0; height: 42%;
  background: repeating-linear-gradient(180deg,
    rgba(226, 232, 240, 0) 0 5px,
    rgba(226, 232, 240, 0.05) 5px 6px,
    rgba(226, 232, 240, 0) 6px 11px);
  mix-blend-mode: screen;
  will-change: transform;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 58%, #000 100%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 58%, #000 100%);
  animation: wxRipple 9s linear infinite;
}
@keyframes wxRipple {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, 11px, 0); }
}

/* The rain itself is drawn, not built: three hundred elements in the document
   would cost more than the whole rest of the page put together. */
.wx__rain {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none; opacity: 0;
  transition: opacity 1400ms var(--ease-out);
}
.eco.is-rain .wx__rain { opacity: 1; }

/* --- the invitation ---------------------------------------------------- */
.wxsw {
  /* Across the sky from the title, on the same line as it. The two of them
     hold the top corners of the scene between them, which is what stops the
     invitation reading as a fourth line of the copy. Its own tab stop comes
     after the heading in the document, so nothing about the reading order
     changes.

     It brings its own halo: it used to inherit one from the heading block and
     the corner it sits in now is the brightest part of the photograph, with
     the sun in it. */
  position: absolute; z-index: 4;
  /* Measured from the top of the window, for the same reason the title is. */
  top: calc(var(--nav-h) + 0.25rem);
  right: 4.5%;
  display: inline-flex; align-items: center; gap: 0.8em;
  padding: 0.2em 0;
  background: none; border: 0; cursor: pointer;
  font-family: var(--ff-display); font-weight: 600;
  /* Floored for the same reason as the heading opposite it: this was rendering
     at 6.8px on a 1366-wide laptop, which is an invitation nobody can read. */
  font-size: max(0.625rem, 0.78cqw); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--white);
  /* Four shadows rather than the heading's three, and tighter. The corner it
     sits in has the sun in it: the ground behind these letters measures 2.1:1
     against white on average and 1.4:1 on the brightest tenth of it, which no
     amount of opacity would fix. The tight pair cut an edge on the blown-out
     cloud, the wide pair seat the whole control on the sky. */
  text-shadow: 0 1px 2px rgba(15, 23, 42, 0.98),
               0 0 4px rgba(15, 23, 42, 0.95),
               0 0 11px rgba(15, 23, 42, 0.85),
               0 2px 24px rgba(15, 23, 42, 0.65);
  transition: color var(--dur) var(--ease),
              opacity 520ms var(--ease-out),
              transform 760ms var(--ease-out),
              visibility 0s linear 760ms;
}
/* It left the heading block, so it no longer goes with it when a room opens.
   Same treatment, same reason: a transparent button is still a tab stop. */
.eco.is-inside .wxsw {
  opacity: 0; transform: translateY(-14px);
  visibility: hidden; pointer-events: none;
}
.wxsw:hover { color: var(--white); }
.wxsw:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 5px; }
.wxsw__sw {
  position: relative; flex: none;
  width: 2.7em; height: 1.3em; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.52);
  background: rgba(15, 23, 42, 0.52);
  /* Its own seat on the sky, for the same reason as the letters beside it. */
  box-shadow: 0 1px 10px rgba(15, 23, 42, 0.55);
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.wxsw__sw i {
  position: absolute; left: 0.17em; top: 50%;
  width: 0.84em; height: 0.84em; margin-top: -0.42em;
  border-radius: 50%; background: rgba(255, 255, 255, 0.82);
  transition: transform 340ms var(--ease-out), background-color 340ms var(--ease);
}
.eco.is-rain .wxsw__sw {
  border-color: rgba(201, 168, 106, 0.6); background: rgba(201, 168, 106, 0.16);
}
.eco.is-rain .wxsw__sw i { transform: translateX(1.36em); background: var(--gold); }
/* The label says what you can do next, not what is on: it changes to the
   name of the weather for a moment first, so the switch confirms itself. */
.wxsw__t { transition: opacity 200ms var(--ease); }
.wxsw.is-swap .wxsw__t { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .wx__mist, .wx__ripple { animation: none; }
  .eco.is-rain .wx__glow { animation: none; opacity: 0.06; }
  .wx > *, .wx__rain, .eco__img { transition-duration: 600ms; }
}

/* ==========================================================================
   NARROW
   The heading comes out of the sky and on to the page above the plate, so the
   invitation comes with it and has to be dark on light instead.
   ========================================================================== */
@media (max-width: 1100px) {
  .wxsw {
    /* No corner to put it in out here, so it goes back under the heading —
       which is where it sits in the document anyway. The heading's own gap
       below it becomes the space above the switch, and the switch carries the
       gap down to the plate. */
    position: static; right: auto; top: auto;
    padding-inline: var(--pad);
    text-shadow: none;
    font-size: clamp(0.68rem, 2.3vw, 0.78rem);
    margin-top: 0; margin-bottom: clamp(1.5rem, 4vw, 2.2rem);
    color: var(--ink-70);
  }
  .eco__head { margin-bottom: 1.2rem; }
  .wxsw:hover { color: var(--midnight); }
  .wxsw__sw {
    border-color: rgba(15, 23, 42, 0.26); background: rgba(15, 23, 42, 0.05);
  }
  .wxsw__sw i { background: rgba(15, 23, 42, 0.5); }
  .eco.is-rain .wxsw__sw i { background: var(--gold); }
  /* Less weather on a small screen, and none of it animated twice over. */
  .wx__mist--b, .wx__ripple { display: none; }
}

.solx__stage {
  position: absolute; inset: 0;
  background: var(--ice);
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: scale(1.06);
  transition: opacity 520ms var(--ease-out),
              transform 780ms var(--ease-out),
              visibility 0s linear 780ms;
}
.eco.is-inside .solx__stage {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: none;
  transition: opacity 520ms var(--ease-out) 200ms,
              transform 780ms var(--ease-out) 140ms,
              visibility 0s;
}
/* The global reduce rule zeroes durations but not delays, and both states
   here carry one. Without this the swap arrives, then waits. */
@media (prefers-reduced-motion: reduce) {
  .solx__stage, .eco.is-inside .solx__stage,
  .eco__frame, .eco.is-inside .eco__frame { transition-delay: 0s !important; }
}

/* The way out. Quiet, in the corner, and the only chrome the interior has. */
.eco__back {
  position: absolute; z-index: 3;
  top: clamp(0.9rem, 1.9cqw, 1.5rem);
  /* Held to the same column as everything else in the interior, so it does
     not drift off to the far edge of a wide screen on its own. */
  left: max(clamp(1.1rem, 2.6cqw, 2.6rem), calc(50% - 620px));
  display: inline-flex; align-items: center; gap: 0.55rem;
  background: none; border: 0; padding: 0.45rem 0; cursor: pointer;
  font-family: var(--ff-display); font-size: var(--fs-micro);
  font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-55);
  transition: color var(--dur) var(--ease);
}
.eco__back:hover { color: var(--midnight); }
.eco__back-a { transition: transform var(--dur) var(--ease); }
.eco__back:hover .eco__back-a { transform: translateX(-4px); }

/* Touch. Not the desktop version made small: six labels cannot sit on a
   350px-wide photograph and stay readable, so they come off it and only the
   chosen one names itself. The markers grow into proper thumb targets and
   stay the way in, and the caption under the plate carries the name for the
   area on stage. */
/* Narrow: the title cannot live in the sky. Partly because at a phone's width
   there is barely any sky, and partly because holding both lines to one line
   each costs width — below about 1100px the type would have to shrink past
   the point of being worth reading to keep that promise. It comes out above
   the plate instead, wraps normally and takes the page's own sizes. */
@media (max-width: 1100px) {
  .eco { container-type: normal; }
  /* The heading is above the plate out here rather than in the sky, so the
     cap goes on the plate by itself: capping the block would narrow the
     heading with it, and a heading that wraps takes back exactly the height
     the smaller plate just gave up. On a portrait tablet or a phone the width
     is the smaller limit anyway and none of this comes into play; it is here
     for the short landscape ones. */
  /* No crop out here. The heading has come out of the sky and on to the page,
     so the plate no longer has to hold it and there is nothing to gain by
     trimming the photograph: the window goes back to being the plate, whole. */
  .eco {
    max-width: none; box-shadow: none; clip-path: none;
    width: 100%; aspect-ratio: auto; height: auto;
  }
  .eco__frame {
    position: relative; top: auto; bottom: auto; left: auto;
    width: auto;
    /* Sixty-eight per cent of the window height was holding the plate to about
       three quarters of the width on a landscape iPad, which left it floating
       in white margins — a picture on a page rather than a place. Eighty-one
       per cent is the most the scene can take there and still keep all six
       markers above the fold: the lowest pair sit at 82% of the plate, and
       with the heading above them that is what the arithmetic allows. It puts
       the scene at nine tenths of the width instead of three quarters, with
       only the water at the foot of the photograph below the fold. Portrait
       tablets were already at 100% and do not move; the cap still exists to
       stop a landscape phone being handed a plate taller than its screen. */
    max-width: min(100%, calc(81svh * 1.5));
    margin-inline: auto;
  }
  .eco__head {
    position: static; white-space: normal;
    width: auto; max-width: var(--measure-head);
    padding-inline: var(--pad);
    color: inherit; text-shadow: none;
    margin-bottom: clamp(1.5rem, 4vw, 2.2rem);
    /* Out here it is ordinary copy above the plate with nothing underneath it
       to protect, so it takes the pointer back and stays selectable. */
    pointer-events: auto;
  }
  .eco__head h2 { color: var(--midnight); font-size: var(--fs-h2); }
  .eco__head .lead { font-size: var(--fs-lead); }
  .eco__head .eyebrow { font-size: clamp(0.82rem, 0.95vw, 0.94rem); }
  .eco__head .lead { color: var(--ink-70); font-size: var(--fs-lead); }
  /* It stays put while a district is being pointed at, because out here it is
     a heading above the plate rather than something in the sky. Going inside
     is different: the interior is the page then, and the heading goes with
     the estate it belonged to. */
  .eco.is-inside .eco__head { opacity: 0; visibility: hidden; }
  /* The interior covers the whole block here, heading included: with the
     title out of the sky and above the plate, there is no sky left to keep. */
  .solx__panel { padding-top: clamp(3rem, 9vw, 3.6rem); }
}

/* --- Tablets ---
   Between the phone, where all but the chosen label is hidden, and the
   desktop, where the heading is in the sky, there is a band where all seven
   labels are on the plate at once and the plate is small. At the desktop's
   own tracking they start to touch each other, so here they are set a size
   down and tracked a little tighter: the same seven words, still legible at
   arm's length, and no two of them overlapping. */
@media (min-width: 761px) and (max-width: 1100px) {
  .eco__label {
    font-size: clamp(0.55rem, 1.1vw, 0.64rem);
    letter-spacing: 0.1em;
  }
  /* A finger, not a pointer. */
  .eco__node { width: 40px; height: 40px; }
}

/* A landscape tablet has the least height of anything the site runs on, and
   the heading was taking a third of it before the estate began. Held to a
   narrower measure and set down a size, it gives that third back. */
@media (max-width: 1100px) and (orientation: landscape) and (min-width: 761px) {
  /* Edge to edge here as well. A landscape tablet is wide enough that any cap
     on the plate shows up as a margin down both sides, and a 3:2 source is no
     reason to put one there. The heading is above the scene at this width
     rather than in its sky, so the plate is free to take the whole width; what
     it costs is the foot of the photograph sitting just under the fold, which
     is water. All six markers stay above it. */
  .eco__frame { max-width: 100%; }
  .eco__head {
    max-width: 44rem;
    margin-bottom: clamp(0.7rem, 1.6vw, 1rem);
  }
  /* Small enough that the heading holds one line again, which is the whole
     of the difference between the estate fitting here and not. */
  .eco__head h2 { font-size: clamp(1.3rem, 2.8vw, 1.75rem); }
  .eco__head .lead { font-size: clamp(0.88rem, 1.7vw, 1rem); margin-top: 0.7rem; }
  .wxsw { margin-bottom: clamp(0.7rem, 1.6vw, 1rem); }
  .eco__head { margin-bottom: 1rem; }
  /* The plate is sized by the height here and the labels by the width, so on
     a wide short screen they are the two things that can disagree. This is
     the size at which they stop. */
  .eco__label { font-size: clamp(0.5rem, 0.9vw, 0.56rem); }
}

@media (max-width: 760px) {
  /* The measure comes off on a phone. --measure-head is 56% of the column,
     which was written as a composition rule for a wide page — the note above
     assumes the phone's own width binds first, but a percentage never lets it:
     at 390px the cap was still 56%, so the heading was breaking into four
     ragged lines down the left-hand half of the screen with the other half
     empty, and the weather switch under it was being squeezed into two lines
     with it. Every other heading on the page already takes the full column
     here; this one now does the same. */
  .eco__head { max-width: none; }

  .eco__label { display: none; }
  /* Every label is off at this width and only the district being pointed at
     brings one back, which the closed building never is. Left as a marker
     alone it would be an unexplained dot that does nothing, and shown as the
     only label on the map it would be the loudest thing on the estate. So on
     a phone that island simply has nothing on it. */
  .eco__pt--soon { display: none; }
  .eco__pt.is-active .eco__label,
  .eco__pt.is-hot .eco__label {
    display: block;
    font-size: 0.7rem;
    /* Held at the top of the plate rather than at its own marker. A name is
       around 210px of a 390px photograph, so wherever it is centred on the
       island it names it reaches the middle of the estate and lands on the
       tower's marker — "Custom Business Systems" was closing its last letter
       inside the Transformation Lab's ring and opening flush against the left
       edge. Only one name is ever shown at this width, so it can have one
       place to be: across the open sky, clear of all six markers, the same
       place every time. */
    left: 50%; top: 8%;
  }
  .eco__node { width: 52px; height: 52px; }
  .eco__node::after { width: 13px; height: 13px; }
  .eco__core { width: 5%; }
}

/* The stage is often a screen below the district that opened it, so it is
   brought up on choosing — and it has to clear the fixed nav when it lands. */
.solx__stage { scroll-margin-top: calc(var(--nav-h) + 20px); }

.solx__panel[hidden] { display: none; }
/* Each interior is the whole view, and scrolls inside it: the plate is the
   window, and going into a building does not change the size of the window. */
.solx__panel {
  position: absolute; inset: 0;
  overflow-y: auto;
  padding: clamp(3.1rem, 5.4cqw, 4.4rem) clamp(1.1rem, 2.6cqw, 2.6rem)
           clamp(1.4rem, 2.6cqw, 2.4rem);
  animation: solxIn 520ms var(--ease-out) both;
}
@keyframes solxIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .solx__panel { animation: none; } }

/* --- The caption ---
   It names itself: the heading repeats the area own title, so the stage says
   what it is showing rather than leaving the visitor to look back at which
   card is lit. That matters more because the section advances on its own, and
   on mobile, where the index is a rail that may be scrolled away from the
   active pill.

   And it is joined to the demonstration. The caption is the top half of the
   same card: it carries the border and the top corners, gives up its bottom
   edge, and the demo below gives up its top corners, so the two read as one
   object rather than as text that happens to sit above a box. It is lifted a
   layer as well, so the demo drop shadow cannot smudge the join. */
/* The view is edge to edge; its contents are not. Everything inside an
   interior holds a column of its own, because a demonstration stretched to
   the full width of a 1920 screen stops looking like a product. */
.solx__head, .solx__panel .demo { max-width: 1240px; margin-inline: auto; }
.solx__head {
  position: relative; z-index: 1;
  padding: 0 0 clamp(0.95rem, 1.7cqw, 1.35rem);
}
.solx__title {
  font-size: clamp(1.15rem, 1.6vw, 1.5rem);
  color: var(--midnight); letter-spacing: -0.015em;
  margin-bottom: 0.55rem;
}
/* A gold node against the title, the same marker the card in the index
   carries, so the lit card and the thing on stage are visibly the same object
   seen twice. */
.solx__title::before {
  content: ""; display: inline-block; vertical-align: 0.22em;
  width: 8px; height: 8px; margin-right: 0.6rem; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 4px var(--gold-14);
}
/* This is the panel copy, not a footnote to it. The floor holds the
   demonstration at one height across all six, so the stage does not jump as
   the section moves through them. */
.solx__desc {
  color: var(--ink-70);
  max-width: 68ch;
}

/* Wide: the title and the description sit side by side rather than stacked.
   Stacked, a 66ch paragraph left most of a 1300px card empty to its right and
   spent height the demonstration could have had, about 45px of it, since the
   head becomes as tall as the description alone rather than the title plus
   the description. Below 1400px the description column drops under 500px,
   which is where these paragraphs take an extra line, so it stacks instead. */
@container (min-width: 900px) {
  .solx__head {
    display: grid;
    grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
    gap: 0.4rem clamp(1.6rem, 2.6cqw, 2.8rem);
    align-items: start;
  }
  .solx__title { font-size: clamp(1.3rem, 1.85cqw, 1.85rem); margin-bottom: 0; }
}

/* This line is the route for anyone who cannot place themselves in the six
   areas, so it is set as a statement rather than a footnote. */
.solx__foot {
  /* Trimmed with the section around it. There is no rule above this line any
     more, so the space is doing the separating on its own: the two values
     below are what the gap was when the rule was in it, kept as they were so
     nothing else in the section shifts. */
  margin-top: clamp(1.6rem, 2.4vw, 2.2rem);
  padding-top: clamp(1.2rem, 2vw, 1.7rem);
  /* No measure cap. --measure-head holds display type to about the middle of
     the page, which is right for a heading with a column of content under it
     — but this is a single sentence with nothing beneath it, and the cap was
     the reason it broke over two lines. It takes the full width instead.

     The size is then set to fit that width on one line. At roughly 80
     characters including the arrow, the line needs about a fortieth of the
     available width per character; 2vw sits comfortably under that from
     768px up, so it holds one line across every desktop width while still
     being the largest type in the section.

     Below that it is allowed to wrap — one line on a phone would mean type
     too small to read, which is a worse outcome than two lines. */
  max-width: none;
  /* Centred. It is the one line in the section that is not attached to
     anything — not a heading over a block, not a caption under one — and set
     to the left it read as the start of something that never arrived. In the
     middle it reads as what it is: the section signing off. */
  text-align: center;
  font-family: var(--ff-display);
  font-size: clamp(1.05rem, 2vw, 2.3rem);
  line-height: 1.35; letter-spacing: -0.015em;
  color: var(--ink-40);
}
.solx__foot-em { color: var(--midnight); }

/* --- The marked name ---
   "Transformation Study" is the offer in this sentence, so it is set apart
   from it: gold, a size up, and underscored by hand rather than by a rule.

   The underline is a single SVG stroke carried as a background image — an
   uneven path with a slight bow and a bit of overshoot at each end, drawn in
   one movement the way a real one would be. A CSS border here would give a
   dead-straight machine line, which is exactly what the gesture is meant not
   to be. It sits at the foot of the box, sized to the text, so it stretches
   with the phrase instead of tiling under it. */
.solx__mark {
  color: var(--gold);
  font-size: 1.12em;
  white-space: nowrap;
  padding-bottom: 0.26em;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 14' preserveAspectRatio='none'%3E%3Cpath d='M4.5 9.9C42 6.1 96 4.3 149 5.1c34 .5 71 1.9 107 3.1' fill='none' stroke='%23C9A86A' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0.36em;
}

/* The arrow is drawn rather than typed. A ↓ is a straight character in
   whatever face happens to be resolving, which sits stiffly at the end of a
   line that is already half handwriting; this one leaves horizontally, bends
   through the turn and arrives pointing down at the section below — the shape
   of the movement it describes. Two strokes: the shaft and the head, both
   round-capped, so it reads as drawn in one go.

   currentColor, so it takes the gold from the rule below and darkens with the
   link on hover along with everything else. */
.solx__foot-arrow {
  display: inline-block; vertical-align: -0.62em;
  width: 1.05em; height: auto;
  margin-left: 0.35em; color: var(--gold);
  transition: transform var(--dur) var(--ease);
}
a.solx__foot-em:hover .solx__foot-arrow { transform: translateY(4px); }
a.solx__foot-em:hover .solx__mark { color: var(--midnight); }


/* ==========================================================================
   INTELLIGENT REPORTING & DASHBOARDS
   A boardroom photograph and five screens in it. Same principle as the office
   next door: the room is the environment, the interface is on the glass, and
   nothing at all is laid over the picture.

   One difference of consequence. The estate plate is 3:2 and so is every
   panel on this stage, but this photograph is 16:9, which leaves a sixteenth
   of the panel unspent at the foot. It is not letterboxed away — the scene is
   hung from the top, the picture's own darkness is deepened into it, and the
   caption crosses the join. Which is what a title card on a film is.
   ========================================================================== */

/* Clips, like the office: the plate is hung by its screens now, so its foot
   hangs past the room and would otherwise make the panel a scrolling region
   nobody can see. */
.bir__room { position: absolute; inset: 0; overflow: hidden; }
/* Stood on the foot of the room, not hung from its head. A 1.78 photograph in
   a 1.93 window is taller than the window by about 90px, and hanging it from
   the top put all of that past the foot: the screens came down into the
   caption, the demonstration line landed on the chart, and the room carried a
   scrolling region nobody could see. Standing it on the floor puts the crop
   in the ceiling, which is where a boardroom can spare it, and the rest of
   the room then measures against a box the size of the window it is in. */
.bir {
  position: absolute; left: 0; right: 0; top: 0; bottom: auto;
  aspect-ratio: 1672 / 941;
  container-type: inline-size;
}
.bir__img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* --- The glass ---
   Five rectangles, measured rather than judged: a screen in this photograph
   carries a blue cast the warm room does not, and these are the bounds of the
   five regions that have it. Every one is welded to the picture by
   percentage, so they hold at any width the room is rendered at. */
.bir__screen {
  position: absolute;
  container-type: inline-size;
  overflow: hidden;
  background: linear-gradient(180deg, #101B2E 0%, #0B1424 100%);
  border-radius: 0.25cqw;
}
/* A wall of lit screens throws light into the room it is in. Barely, or the
   boardroom starts to look like it is on fire. */
.bir__screen--main {
  left: 26.675%; top: 15.197%; width: 46.651%; height: 42.083%;
  box-shadow: 0 0 3.4cqw rgba(140, 175, 225, 0.11),
              0 0 1cqw rgba(140, 175, 225, 0.07);
}
.bir__screen--tl { left: 12.380%; top: 14.772%; width: 13.397%; height: 21.041%; }
.bir__screen--tr { left: 74.163%; top: 14.772%; width: 13.517%; height: 21.041%; }
.bir__screen--bl { left: 12.380%; top: 37.301%; width: 13.397%; height: 20.085%; }
.bir__screen--br { left: 74.163%; top: 37.301%; width: 13.517%; height: 20.085%; }
.bir__screen--tl, .bir__screen--tr, .bir__screen--bl, .bir__screen--br {
  box-shadow: 0 0 1.6cqw rgba(140, 175, 225, 0.08);
}
/* The same single soft diagonal the office monitor has: enough that each one
   reads as a surface being looked at rather than a hole cut in the picture. */
.bir__screen::after {
  content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background: linear-gradient(114deg,
    rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.016) 26%,
    rgba(255, 255, 255, 0) 46%);
}

/* Starts below the lowest screen, so it can never touch one, and arrives at
   very nearly solid midnight by the picture's bottom edge — which is where
   the panel's own midnight begins. That is the join, and it is why there is
   no visible seam to find. */
.bir__grade {
  position: absolute; left: 0; right: 0; top: 58.5%; bottom: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(15, 23, 42, 0) 0%,
    rgba(15, 23, 42, 0.30) 22%,
    rgba(15, 23, 42, 0.58) 50%,
    rgba(15, 23, 42, 0.86) 80%,
    rgba(15, 23, 42, 0.99) 100%);
}

/* --- Saying that it runs ---
   Directly above the dashboard, on the dark wall over the glass, where the
   room has nothing in it and the eye is already on its way to the screen.
   Same cue, same withdrawal as the office. */
.bir__hint {
  position: absolute; z-index: 6;
  /* Hung from the top edge of the main screen rather than from the foot of
     the panel, so the gap between the two is fixed however tall the window
     turns out to be. The glass starts 15.197% down a plate that is
     941/1672 of the room's width, which is 8.553 container-widths; the pill
     is pulled fully above that line and then a further 1.2 clear of it. */
  left: 50%; top: calc(8.553 * var(--u)); bottom: auto;
  transform: translate(-50%, calc(-100% - 1.2 * var(--u)));
  display: inline-flex; align-items: center; gap: calc(0.66 * var(--u));
  padding: calc(0.46 * var(--u)) calc(1 * var(--u)) calc(0.46 * var(--u)) calc(0.84 * var(--u));
  border: 1px solid rgba(201, 168, 106, 0.38);
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.42);
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.78 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9); max-width: none;
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.8);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}
.bir__hint-dot {
  width: calc(0.46 * var(--u)); height: calc(0.46 * var(--u)); border-radius: 50%;
  background: var(--gold);
  animation: erpsBeacon 2.6s var(--ease) infinite;
}
.bir__hint.is-gone {
  opacity: 0; pointer-events: none;
  transform: translate(-50%, calc(-100% - 0.7 * var(--u)));
}

/* --- The caption, across the join ---
   Same proportions as the office caption, because they are the same kind of
   thing said in the same size of room. */
.birc {
  position: absolute;
  left: 5.2%; right: 5.2%; bottom: 3.4%;
  color: var(--white);
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.8);
}
.birc__eyebrow { font-size: calc(0.82 * var(--u)); margin-bottom: calc(0.9 * var(--u)); }
.birc__h {
  font-size: calc(2.1 * var(--u)); font-weight: 500; letter-spacing: -0.025em;
  color: var(--white); margin-bottom: calc(0.7 * var(--u));
}
.birc__lead {
  font-size: calc(0.95 * var(--u)); line-height: 1.55;
  color: rgba(255, 255, 255, 0.66);
  max-width: 76ch; margin-bottom: calc(1.5 * var(--u));
}
.birc__pts {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: calc(2.4 * var(--u)); max-width: 74%;
}
.birc__n {
  display: block;
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.8 * var(--u)); letter-spacing: 0.16em; color: var(--gold);
  margin-bottom: calc(0.55 * var(--u));
}
.birc__t {
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.86 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--white); margin-bottom: calc(0.4 * var(--u)); max-width: none;
}
.birc__d {
  font-size: calc(0.84 * var(--u)); line-height: 1.6;
  color: rgba(255, 255, 255, 0.58); max-width: none;
}

/* ==========================================================================
   THE WALL SCREEN
   Sized in em against 1.42% of the glass's own width, so the dashboard holds
   one set of proportions whatever the room is rendered at.
   ========================================================================== */
.bid {
  position: absolute; inset: 0;
  display: grid; grid-template-rows: 2.5em 1fr;
  font-size: clamp(5.4px, 1.42cqw, 15px);
  font-family: var(--ff-text); line-height: 1.45;
  color: var(--sky-80);
}
.bid__bar {
  display: flex; align-items: center; gap: 1em;
  padding: 0 1em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.025);
}
.bid__brand {
  display: inline-flex; align-items: center; gap: 0.55em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.86em; letter-spacing: 0.02em; color: var(--white);
}
.bid__mark {
  width: 0.6em; height: 0.6em; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 0.24em rgba(201, 168, 106, 0.16);
}
.bid__mark--sm { width: 0.5em; height: 0.5em; box-shadow: 0 0 0 0.2em rgba(201, 168, 106, 0.16); }
.bid__crumb {
  font-size: 0.72em; color: rgba(255, 255, 255, 0.34);
  padding-left: 1em; border-left: 1px solid rgba(255, 255, 255, 0.10);
}
.bid__range { margin-left: auto; display: inline-flex; gap: 0.25em; }
.bid__chip {
  font: inherit; font-size: 0.68em; font-family: var(--ff-display); font-weight: 600;
  letter-spacing: 0.08em;
  padding: 0.3em 0.7em; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: none; color: rgba(255, 255, 255, 0.5);
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.bid__chip:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.28); }
.bid__chip.is-on {
  color: var(--midnight); background: var(--gold); border-color: var(--gold);
}
.bid__tag {
  padding: 0.26em 0.7em; border-radius: 999px;
  border: 1px solid var(--gold-40); color: var(--gold);
  font-family: var(--ff-display); font-size: 0.6em;
  font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
}

.bid__body {
  display: grid; grid-template-columns: 1fr 15.4em;
  gap: 1em; padding: 0.9em 1em 0.8em;
  min-height: 0;
}
.bid__main { display: flex; flex-direction: column; gap: 0.8em; min-height: 0; min-width: 0; }

/* --- The four readings --- */
.bid__kpis { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.5em; }
.bid__kpi {
  display: block; text-align: left; font: inherit; cursor: pointer;
  padding: 0.6em 0.75em; border-radius: 0.25em;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left: 2px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.03);
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.bid__kpi:hover { background: rgba(255, 255, 255, 0.06); border-left-color: var(--gold-40); }
.bid__kpi.is-on { background: rgba(201, 168, 106, 0.10); border-color: rgba(201, 168, 106, 0.30); border-left-color: var(--gold); }
.bid__kpi:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 1px; }
.bid__k {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: 0.62em; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42); margin-bottom: 0.25em;
}
.bid__v {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: 1.32em; letter-spacing: -0.01em; color: var(--white);
  white-space: nowrap;
}
.bid__d { display: block; font-size: 0.64em; color: rgba(255, 255, 255, 0.38); white-space: nowrap; }
.bid__d.is-up { color: #8FBF9F; }
.bid__d.is-down { color: #D89080; }

/* --- The chart --- */
.bid__chartwrap {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column; gap: 0.5em;
  padding: 0.75em 0.85em 0.6em;
  border: 1px solid rgba(255, 255, 255, 0.07); border-radius: 0.25em;
  background: rgba(255, 255, 255, 0.02);
}
.bid__chead { display: flex; align-items: baseline; gap: 1em; }
.bid__ctitle {
  font-family: var(--ff-display); font-weight: 600; font-size: 0.78em;
  letter-spacing: 0.02em; color: var(--white); max-width: none;
}
.bid__legend {
  display: inline-flex; align-items: center; gap: 0.5em;
  font-size: 0.6em; color: rgba(255, 255, 255, 0.36);
}
.bid__key { width: 1.1em; height: 0.16em; border-radius: 1px; margin-right: 0.15em; }
.bid__key--act { background: var(--gold); }
.bid__key--fc { background: linear-gradient(90deg, var(--gold) 45%, transparent 45%); opacity: 0.7; }
.bid__key--pat { background: rgba(201, 168, 106, 0.28); height: 0.5em; }
/* The readout is the only line in the interface that changes as you point at
   things, so it is given the width to change in without shifting anything. */
.bid__read {
  margin-left: auto; text-align: right; white-space: nowrap;
  font-size: 0.66em; color: rgba(255, 255, 255, 0.5); max-width: none;
}
.bid__read b { color: var(--white); font-weight: 600; }
/* A gutter for the scale, then the drawing. The numbers are placed against
   the gridlines they belong to rather than spread down the side, which is the
   difference between a chart and a shape. */
.bid__chart { flex: 1; min-height: 0; display: flex; gap: 0.5em; }
.bid__scale {
  position: relative; flex: none; width: 2.8em;
  font-size: 0.62em; color: rgba(255, 255, 255, 0.34);
}
.bid__scale i {
  position: absolute; right: 0; transform: translateY(-50%);
  font-style: normal; white-space: nowrap;
}
.bid__plot { position: relative; flex: 1; min-width: 0; }
.bid__chart svg { display: block; width: 100%; height: 100%; }
.bid__axis {
  display: flex; justify-content: space-between;
  padding-left: 3.3em;
  font-size: 0.62em; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.30);
}
/* --- Data, patterns, forecast, recommendation --- */
.bid__chain {
  display: flex; align-items: center; gap: 0.55em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.6em; letter-spacing: 0.16em; text-transform: uppercase;
}
.bid__step {
  padding: 0.4em 0.8em; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.34);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.bid__step + .bid__step { position: relative; }
.bid__step + .bid__step::before {
  content: ""; position: absolute; left: -0.55em; top: 50%;
  width: 0.55em; height: 1px; background: rgba(255, 255, 255, 0.12);
}
.bid__step.is-on {
  color: var(--gold); border-color: var(--gold-40); background: rgba(201, 168, 106, 0.10);
}

/* --- The rail --- */
.bid__rail {
  display: flex; flex-direction: column; gap: 0.5em;
  padding-left: 1em; border-left: 1px solid rgba(255, 255, 255, 0.07);
  min-height: 0;
}
.bid__rhead {
  display: flex; align-items: center; gap: 0.55em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.66em; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5); max-width: none;
}
.bid__ins {
  display: block; text-align: left; font: inherit; cursor: pointer;
  padding: 0.6em 0.7em; border-radius: 0.25em;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left: 2px solid var(--gold-40);
  background: rgba(255, 255, 255, 0.03);
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.bid__ins:hover { background: rgba(255, 255, 255, 0.06); }
.bid__ins:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 1px; }
.bid__ins.is-open { background: rgba(201, 168, 106, 0.10); border-color: rgba(201, 168, 106, 0.30); border-left-color: var(--gold); }
.bid__it {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: 0.7em; letter-spacing: 0.01em; color: var(--white); margin-bottom: 0.2em;
}
.bid__ib { display: block; font-size: 0.66em; line-height: 1.5; color: rgba(255, 255, 255, 0.5); }
/* The reasoning is folded away until it is asked for: an insight you cannot
   interrogate is a slogan. */
.bid__iw {
  display: block; font-size: 0.64em; line-height: 1.5;
  color: rgba(255, 255, 255, 0.62);
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height var(--dur) var(--ease), opacity var(--dur) var(--ease),
              margin-top var(--dur) var(--ease);
}
.bid__ins.is-open .bid__iw { max-height: 6em; opacity: 1; margin-top: 0.45em; }
.bid__rfoot {
  margin-top: auto; font-size: 0.6em; line-height: 1.5;
  color: rgba(255, 255, 255, 0.26); max-width: none;
}

/* ==========================================================================
   THE FOUR BESIDE IT
   A fifth of the width of the wall screen, so a fifth of the content: a
   heading, two readings, one picture and two lines. Anything more at this
   size is a smudge.
   ========================================================================== */
.bis {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: 0.55em;
  padding: 0.85em 0.9em;
  font-size: clamp(5.4px, 4.4cqw, 13px);
  font-family: var(--ff-text); line-height: 1.4;
  color: var(--sky-80);
}
.bis__h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.78em; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--white); max-width: none;
  padding-bottom: 0.5em; border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.bis__h span {
  font-size: 0.72em; letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.32); white-space: nowrap;
}
.bis__kpis { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5em; }
.bis__k {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: 0.58em; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.40);
}
.bis__v {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: 1.3em; color: var(--white); white-space: nowrap;
}
.bis__cap {
  font-size: 0.6em; letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32); max-width: none;
}
.bis__bars { display: flex; align-items: flex-end; gap: 0.16em; height: 2.6em; }
.bis__bars i {
  flex: 1; height: var(--h, 40%); border-radius: 1px 1px 0 0;
  background: linear-gradient(180deg, rgba(201, 168, 106, 0.85), rgba(201, 168, 106, 0.34));
}
.bis__bars i.is-low { background: linear-gradient(180deg, rgba(255, 255, 255, 0.30), rgba(255, 255, 255, 0.10)); }
/* A proportion, drawn. Three quarters of a year's target is a thing you
   should be able to see without reading a number. */
.bis__meter {
  height: 0.34em; border-radius: 999px;
  background: rgba(255, 255, 255, 0.10); overflow: hidden;
}
.bis__meter i { display: block; height: 100%; width: var(--w, 50%); background: var(--gold); }
.bis__spark { height: 2.6em; }
.bis__chart { flex: 1; min-height: 3.2em; }
.bis__spark svg, .bis__chart svg { display: block; width: 100%; height: 100%; }
.bis__rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.34em; }
.bis__rows li {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5em;
  font-size: 0.68em; color: rgba(255, 255, 255, 0.5);
}
.bis__rows b { font-weight: 600; color: var(--white); }
.bis__rows b.is-up { color: #8FBF9F; }
.bis__rows--alert li { justify-content: flex-start; }
.bis__dot {
  flex: none; width: 0.44em; height: 0.44em; border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
}
.bis__dot--gold { background: var(--gold); box-shadow: 0 0 0 0.18em rgba(201, 168, 106, 0.18); }
.bis__dot--warn { background: #D8B080; box-shadow: 0 0 0 0.18em rgba(216, 176, 128, 0.16); }
.bis__dot--stop { background: #D89080; box-shadow: 0 0 0 0.18em rgba(216, 144, 128, 0.16); }
.bis__note {
  display: flex; align-items: baseline; gap: 0.45em;
  font-size: 0.66em; line-height: 1.45; color: rgba(255, 255, 255, 0.55); max-width: none;
}
.bis__note .bis__dot { position: relative; top: 0.1em; }
.bis__ins {
  display: flex; align-items: baseline; gap: 0.45em; text-align: left;
  font: inherit; font-size: 0.68em; line-height: 1.45; cursor: pointer;
  padding: 0.4em 0.45em; border: 0; border-radius: 0.25em;
  border-left: 2px solid transparent;
  background: rgba(255, 255, 255, 0.03); color: rgba(255, 255, 255, 0.62);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.bis__ins:hover { background: rgba(255, 255, 255, 0.07); color: var(--white); border-left-color: var(--gold-40); }
.bis__ins.is-open { background: rgba(201, 168, 106, 0.12); color: var(--white); border-left-color: var(--gold); }
.bis__ins:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 1px; }
.bis__ins .bis__dot { position: relative; top: 0.15em; }
.bis__foot {
  margin-top: auto; font-size: 0.58em; line-height: 1.45;
  color: rgba(255, 255, 255, 0.26); max-width: none;
}

/* --- The drawing itself ---
   Strokes are told not to scale with the box, which is what lets one SVG be
   stretched to any screen on this wall and still draw a one pixel line. */
.bidc__band { fill: rgba(201, 168, 106, 0.10); }
.bidc__pat { fill: rgba(201, 168, 106, 0.12); }
.bidc__area { fill: url(#bidGrad); }
.bidc__line { fill: none; stroke: var(--gold); stroke-width: 1.6; stroke-linejoin: round; }
.bidc__fc { fill: none; stroke: var(--gold); stroke-width: 1.4; stroke-dasharray: 4 3; opacity: 0.75; }
.bidc__grid { stroke: rgba(255, 255, 255, 0.07); stroke-width: 1; }
/* The line where measurement stops and projection begins. */
.bidc__fcline { stroke: rgba(255, 255, 255, 0.16); stroke-dasharray: 3 3; }
.bidc__cur { stroke: rgba(255, 255, 255, 0.34); transition: opacity 120ms var(--ease); }
.bidc__cdot { fill: var(--gold); stroke: rgba(15, 23, 42, 0.9); stroke-width: 1; transition: opacity 120ms var(--ease); }

/* The system saying, on the chart itself, what it found there. It is put over
   the last cycle actually observed rather than over the projection of it,
   because the claim is about what happened, not about what is expected. */
.bid__ann {
  position: absolute; top: 0.1em; transform: translateX(-50%);
  padding: 0.22em 0.6em; border-radius: 999px;
  border: 1px solid rgba(201, 168, 106, 0.34);
  background: rgba(15, 23, 42, 0.72);
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.68em; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72); white-space: nowrap; pointer-events: none;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.bid__ann b { color: var(--gold); font-weight: 600; }
/* While a recommendation is open, the thing it was drawn from is brought up. */
.bid.is-insight .bidc__pat { fill: rgba(201, 168, 106, 0.20); }
.bid.is-insight .bid__ann { border-color: var(--gold-40); color: var(--white); }

/* ==========================================================================
   NARROW
   The wall does not survive a phone: four supporting screens rendered at
   ninety pixels across are four smudges, and the one that matters is the
   large one. So the room becomes a band holding the wall screen alone, and
   the caption is set on the page beneath it.
   ========================================================================== */
@media (max-width: 1100px) {
  .bir__room { position: relative; inset: auto; }
  /* The picture becomes the room and nothing else: the screens leave the wall
     rather than shrink on it, because a reading rendered sixty pixels wide is
     not a reading. */
  .bir {
    position: relative; aspect-ratio: auto;
    display: grid; grid-template-columns: 1fr 1fr;
    gap: clamp(0.5rem, 2vw, 0.9rem);
  }
  .bir picture { grid-column: 1 / -1; }
  .bir__img { height: auto; }
  .bir__grade { display: none; }

  .bir__screen {
    position: relative; left: auto; top: auto; width: auto; height: auto;
    border-radius: 0; box-shadow: none;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
  .bir__screen--main { grid-column: 1 / -1; margin-top: clamp(0.4rem, 1.6vw, 0.8rem); }
  /* Off the wall they are panels rather than glass, so they take the height
     their content needs and the row levels them. */
  .bir__screen--tl, .bir__screen--tr,
  .bir__screen--bl, .bir__screen--br { aspect-ratio: auto; }
  .bid { position: relative; inset: auto; }

  .bir__hint {
    position: static; transform: none;
    margin: clamp(1.3rem, 4vw, 1.9rem) var(--pad) 0;
    gap: 0.55rem; padding: 0.44rem 0.85rem 0.44rem 0.7rem;
    font-size: clamp(0.62rem, 2.4vw, 0.72rem);
    text-shadow: none;
  }
  .bir__hint-dot { width: 0.4rem; height: 0.4rem; }
  .bir__hint.is-gone { transform: translateY(0.3rem); }

  .birc {
    position: static;
    padding: clamp(1.6rem, 5vw, 2.6rem) var(--pad) clamp(2rem, 6vw, 3rem);
    text-shadow: none;
  }
  .birc__eyebrow { font-size: clamp(0.72rem, 2.6vw, 0.86rem); margin-bottom: 0.9rem; }
  .birc__h { font-size: clamp(1.35rem, 5.4vw, 1.9rem); margin-bottom: 0.7rem; }
  .birc__lead { font-size: clamp(0.86rem, 3.4vw, 1rem); margin-bottom: 1.8rem; }
  .birc__pts { grid-template-columns: 1fr; gap: 1.4rem; max-width: none; }
  .birc__n { font-size: 0.7rem; margin-bottom: 0.35rem; }
  .birc__t { font-size: 0.78rem; margin-bottom: 0.3rem; }
  .birc__d { font-size: 0.82rem; }
}

/* A wall screen this narrow is a phone screen: the rail goes under the chart,
   the readings go two by two, and the chain of four keeps only its words. */
@container (max-width: 520px) {
  /* A screen this narrow is a phone screen, and a phone screen is read from
     a foot away rather than across a room: the type stops shrinking with the
     box and is set for the hand instead. */
  .bid {
    font-size: clamp(8.5px, 2.7cqw, 13px);
    grid-template-rows: auto 1fr;
  }
  .bid__crumb { display: none; }
  .bid__bar { padding: 0.5em 0.9em; flex-wrap: wrap; gap: 0.6em; }
  .bid__body { grid-template-columns: 1fr; gap: 0.9em; overflow: visible; }
  .bid__kpis { grid-template-columns: 1fr 1fr; }
  .bid__chartwrap { min-height: 13em; }
  .bid__rail {
    padding-left: 0; border-left: 0;
    padding-top: 0.8em; border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
  .bid__ann, .bid__legend { display: none; }
  .bid__chain { flex-wrap: wrap; row-gap: 0.4em; }
  .bid__rfoot { margin-top: 0.4em; }
}

@media (prefers-reduced-motion: reduce) {
  .bir__hint-dot { animation: none; box-shadow: 0 0 0 0.28cqw rgba(201, 168, 106, 0.22); }
}


/* ==========================================================================
   DIGITAL EXPERIENCES
   A studio at night with two blank monitors, and a website living on the
   larger one. Third room in the same building as the office and the
   boardroom, built the same way: photograph as environment, HTML as the
   digital layer, nothing floating in between.

   The difference here is the second monitor. It is turned towards the room,
   which the measurements say plainly: its left edge stands 317 pixels tall
   and its right edge 290, over a width of 423. A flat rectangle laid on that
   would sit on the picture rather than in it, so the HTML is turned by the
   same sixteen degrees the monitor is.
   ========================================================================== */

/* Clips, like the office: the plate is hung by its screens now, so its foot
   hangs past the room and would otherwise make the panel a scrolling region
   nobody can see. */
.dxs__room { position: absolute; inset: 0; overflow: hidden; }
/* Stood on the foot of the room, for the reason the boardroom is. Here it
   bought the most: the monitors were sitting 90px lower than the room thought
   they were, which is why the caption was crossing the desk. */
.dxs {
  position: absolute; left: 0; right: 0; top: 0; bottom: auto;
  aspect-ratio: 1672 / 941;
  container-type: inline-size;
}
.dxs__img { display: block; width: 100%; height: 100%; object-fit: cover; }

.dxs__screen {
  position: absolute;
  container-type: inline-size;
  overflow: hidden;
  background: linear-gradient(180deg, #101B2E 0%, #0B1424 100%);
}
/* Square to the camera, so it needs nothing but its four numbers. */
.dxs__screen--main {
  left: 37.679%; top: 29.968%; width: 38.397%; height: 38.257%;
  border-radius: 0.2cqw;
  box-shadow: 0 0 3.2cqw rgba(140, 175, 225, 0.13),
              0 0 1cqw rgba(140, 175, 225, 0.08);
}
/* Not square to the camera. A sixteen degree turn about the vertical seen
   through a perspective of about four fifths of the picture's width is what
   makes a flat plate land as a keystone 300 pixels tall on its near edge and
   274 on its far one, which is the shape the glass actually is. These five
   numbers were not derived: the plate was rendered, its corners measured
   against the photograph's, and the numbers moved until the two agreed to
   within a pixel.

   One detail is deliberately not corrected. The real monitor sits a degree
   nose down, so its far edge's centre is seven pixels above its near edge's.
   Rolling the plate to match shears the vertical edges into diagonals, which
   reads far worse than the error it fixes, so the fit is symmetric and the
   remaining four pixels sit under the bezel. */
.dxs__screen--side {
  left: 9.3372%; top: 34.1941%; width: 26.1344%; height: 31.8812%;
  transform: perspective(81.51cqw) rotateY(16.00deg);
  box-shadow: 0 0 2cqw rgba(140, 175, 225, 0.10);
}
.dxs__screen::after {
  content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background: linear-gradient(114deg,
    rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.016) 26%,
    rgba(255, 255, 255, 0) 46%);
}

.dxs__grade {
  position: absolute; left: 0; right: 0; top: 69%; bottom: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(15, 23, 42, 0) 0%,
    rgba(15, 23, 42, 0.34) 24%,
    rgba(15, 23, 42, 0.62) 52%,
    rgba(15, 23, 42, 0.88) 82%,
    rgba(15, 23, 42, 0.99) 100%);
}

.dxs__hint {
  position: absolute; z-index: 6;
  /* Directly above the monitors, on the wall the photograph leaves empty
     there. The plate is hung from the top of the panel and is 56.280
     container-widths deep; the main screen starts 29.968% down it, which
     puts the top of the glass 16.866 down from the head. The near monitor
     starts lower still, so one line clears both.

     Centred on the browser rather than on the room: this room has two
     monitors and the line is about the one running the site, so at the
     room's centre it hangs in the gap between them and belongs to neither.
     37.679% plus half of 38.397% is 56.878%. */
  left: 56.878%; top: calc(16.866 * var(--u)); bottom: auto;
  transform: translate(-50%, calc(-100% - 1.2 * var(--u)));
  display: inline-flex; align-items: center; gap: calc(0.66 * var(--u));
  padding: calc(0.46 * var(--u)) calc(1 * var(--u)) calc(0.46 * var(--u)) calc(0.84 * var(--u));
  border: 1px solid rgba(201, 168, 106, 0.38);
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.42);
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.78 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9); max-width: none;
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.8);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}
.dxs__hint-dot {
  width: calc(0.46 * var(--u)); height: calc(0.46 * var(--u)); border-radius: 50%;
  background: var(--gold);
  animation: erpsBeacon 2.6s var(--ease) infinite;
}
.dxs__hint.is-gone {
  opacity: 0; pointer-events: none;
  transform: translate(-50%, calc(-100% - 0.7 * var(--u)));
}

.dxc {
  position: absolute;
  left: 5.2%; right: 5.2%; bottom: 3.4%;
  color: var(--white);
  text-shadow: 0 1px 3px rgba(15, 23, 42, 0.8);
}
.dxc__eyebrow { font-size: calc(0.82 * var(--u)); margin-bottom: calc(0.9 * var(--u)); }
.dxc__h {
  font-size: calc(2.1 * var(--u)); font-weight: 500; letter-spacing: -0.025em;
  color: var(--white); margin-bottom: calc(0.7 * var(--u));
}
.dxc__lead {
  font-size: calc(0.95 * var(--u)); line-height: 1.55;
  color: rgba(255, 255, 255, 0.66);
  max-width: 76ch; margin-bottom: calc(1.5 * var(--u));
}
.dxc__pts { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(2.4 * var(--u)); max-width: 74%; }
.dxc__n {
  display: block;
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.8 * var(--u)); letter-spacing: 0.16em; color: var(--gold);
  margin-bottom: calc(0.55 * var(--u));
}
.dxc__t {
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.86 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--white); margin-bottom: calc(0.4 * var(--u)); max-width: none;
}
.dxc__d { font-size: calc(0.84 * var(--u)); line-height: 1.6; color: rgba(255, 255, 255, 0.58); max-width: none; }

/* ==========================================================================
   THE WEBSITE ON THE GLASS
   Not a picture of a site and not a page of this one: a separate site, with
   its own chrome, its own scroll, its own navigation and its own object to
   turn. The visitor is inside a Velocity site while they use it, which is
   the entire point and the reason nothing here says so.
   ========================================================================== */
.dxw {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  font-size: clamp(5.6px, 1.62cqw, 15px);
  font-family: var(--ff-text); line-height: 1.5;
  color: var(--sky-80);
  background: linear-gradient(180deg, #0F172A 0%, #0A101F 100%);
}
.dxw__chrome {
  flex: none; display: flex; align-items: center; gap: 0.4em;
  padding: 0 0.8em; height: 2em;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.dxw__dot { width: 0.42em; height: 0.42em; border-radius: 50%; background: rgba(255, 255, 255, 0.16); }
.dxw__url {
  margin-left: 0.6em; padding: 0.2em 1.2em; border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  font-size: 0.62em; color: rgba(255, 255, 255, 0.44);
}
.dxw__tag {
  margin-left: auto;
  padding: 0.22em 0.7em; border-radius: 999px;
  border: 1px solid var(--gold-40); color: var(--gold);
  font-family: var(--ff-display); font-size: 0.55em;
  font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
}

/* The window the site is in. Everything inside it is another document, so
   there is nothing here to style but the box and the scale. */
.dxw__view {
  position: relative; flex: 1; min-height: 0; overflow: hidden;
  background: var(--midnight);
}
/* Loaded wide and shrunk to fit rather than loaded narrow: the first shows
   the site as it was designed, the second shows the phone layout on a
   desktop monitor, which is not what is being claimed. Rendering at 1440 and
   compositing at 42% also means every glyph is drawn from more pixels than
   it is shown with, which is why this reads sharper than type set at the
   size it lands. */
.dxw__frame {
  position: absolute; left: 0; top: 0; border: 0;
  width: calc(100% / var(--s, 0.42));
  height: calc(100% / var(--s, 0.42));
  transform: scale(var(--s, 0.42));
  transform-origin: 0 0;
}
/* Two windows deep, where a third copy is refused. */
.dxw__fb {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1.2em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.7em; letter-spacing: 0.24em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}
.dxw__fbmark { width: 12%; opacity: 0.5; }

/* ==========================================================================
   THE SECOND MONITOR
   Four things the large screen is doing, each said once, each moving so that
   the claim and the demonstration are the same object.
   ========================================================================== */
.dxt {
  position: absolute; inset: 0;
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  gap: 1px; background: rgba(255, 255, 255, 0.07);
  /* Bigger than it wants to be, because this screen is being read across a
     studio and through sixteen degrees of turn. Nothing on it is under ten
     pixels. */
  font-size: clamp(7px, 3.6cqw, 15px);
  font-family: var(--ff-text); color: var(--sky-80);
}
.dxt__tile {
  display: flex; flex-direction: column; gap: 0.45em;
  padding: 0.7em 0.75em;
  background: linear-gradient(180deg, #101B2E 0%, #0B1424 100%);
}
.dxt__h {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.76em; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gold); max-width: none;
}
.dxt__art { flex: 1; min-height: 2.4em; position: relative; overflow: hidden; }
.dxt__d { font-size: 0.68em; line-height: 1.4; color: rgba(255, 255, 255, 0.58); max-width: none; }

/* one: an object in space */
.dxt__art--spatial { perspective: 14em; }
.dxt__cube {
  position: absolute; left: 50%; top: 50%; width: 3.4em; height: 3.4em;
  margin: -1.7em 0 0 -1.7em; transform-style: preserve-3d;
  animation: dxtSpin 9s linear infinite;
}
.dxt__cube i {
  position: absolute; inset: 0; border: 1px solid var(--gold-40); border-radius: 6%;
  transform: rotateY(calc(var(--f) * 45deg));
}
@keyframes dxtSpin {
  from { transform: rotateX(-16deg) rotateY(0deg); }
  to   { transform: rotateX(-16deg) rotateY(360deg); }
}

/* two: one build, three widths */
.dxt__art--resp { display: grid; place-items: center; }
.dxt__frame {
  display: flex; flex-direction: column; gap: 0.3em; justify-content: center;
  width: 100%; height: 80%; padding: 0.4em;
  border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 0.2em;
  animation: dxtWidth 7s var(--ease) infinite;
}
.dxt__frame i { display: block; height: 0.3em; border-radius: 1px; background: rgba(226, 232, 240, 0.26); }
.dxt__frame i:first-child { background: var(--gold-40); width: 60%; }
@keyframes dxtWidth {
  0%, 26%   { width: 100%; }
  40%, 60%  { width: 62%; }
  74%, 100% { width: 34%; }
}

/* three: the curve itself */
.dxt__art--motion svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.dxt__curve { fill: none; stroke: rgba(255, 255, 255, 0.2); stroke-width: 1; }
.dxt__runner {
  position: absolute; left: 2%; top: 84%;
  width: 0.42em; height: 0.42em; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 0.2em rgba(201, 168, 106, 0.18);
  animation: dxtRun 3.4s var(--ease) infinite;
}
@keyframes dxtRun {
  0%   { left: 2%;  top: 84%; }
  30%  { left: 32%; top: 80%; }
  55%  { left: 48%; top: 34%; }
  100% { left: 95%; top: 10%; }
}

/* four: in an order */
.dxt__art--story { display: flex; flex-direction: column; justify-content: center; gap: 0.34em; }
.dxt__pane {
  height: 0.62em; border-radius: 1px; background: rgba(226, 232, 240, 0.18);
  transform-origin: left;
  animation: dxtTell 4.2s var(--ease) infinite;
  animation-delay: calc(var(--i) * 0.5s);
}
@keyframes dxtTell {
  0%, 10%  { transform: scaleX(0.1); background: rgba(226, 232, 240, 0.10); }
  32%, 78% { transform: scaleX(1);   background: rgba(201, 168, 106, 0.42); }
  100%     { transform: scaleX(1);   background: rgba(226, 232, 240, 0.14); }
}

@media (prefers-reduced-motion: reduce) {
  .dxs__hint-dot { animation: none; box-shadow: 0 0 0 0.28cqw rgba(201, 168, 106, 0.22); }
  .dxt__cube, .dxt__frame, .dxt__runner, .dxt__pane { animation: none; }
  .dxt__frame { width: 72%; }
  .dxt__runner { left: 60%; top: 26%; }
  .dxt__pane { transform: scaleX(1); background: rgba(201, 168, 106, 0.3); }
}

/* ==========================================================================
   NARROW
   Same as the boardroom: the screens come off the wall rather than shrink on
   it. The website goes full width, the four tiles follow it, and the
   photograph stays a photograph.
   ========================================================================== */
@media (max-width: 1100px) {
  .dxs__room { position: relative; inset: auto; }
  .dxs {
    position: relative; aspect-ratio: auto;
    display: grid; grid-template-columns: 1fr;
    gap: clamp(0.5rem, 2vw, 0.9rem);
  }
  .dxs__img { height: auto; }
  .dxs__grade { display: none; }

  .dxs__screen {
    position: relative; left: auto; top: auto; width: auto; height: auto;
    transform: none; border-radius: 0; box-shadow: none;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
  /* Taller than the glass it came off: a phone holds a window, not a
     monitor, and the site inside it needs room to be a site. */
  .dxs__screen--main { aspect-ratio: 3 / 4; margin-top: clamp(0.4rem, 1.6vw, 0.8rem); }
  .dxs__screen--side { aspect-ratio: 440 / 330; }

  .dxs__hint {
    position: static; transform: none;
    margin: clamp(1.3rem, 4vw, 1.9rem) var(--pad) 0;
    gap: 0.55rem; padding: 0.44rem 0.85rem 0.44rem 0.7rem;
    font-size: clamp(0.62rem, 2.4vw, 0.72rem);
    text-shadow: none;
  }
  .dxs__hint-dot { width: 0.4rem; height: 0.4rem; }
  .dxs__hint.is-gone { transform: translateY(0.3rem); }

  .dxc {
    position: static;
    padding: clamp(1.6rem, 5vw, 2.6rem) var(--pad) clamp(2rem, 6vw, 3rem);
    text-shadow: none;
  }
  .dxc__eyebrow { font-size: clamp(0.72rem, 2.6vw, 0.86rem); margin-bottom: 0.9rem; }
  .dxc__h { font-size: clamp(1.35rem, 5.4vw, 1.9rem); margin-bottom: 0.7rem; }
  .dxc__lead { font-size: clamp(0.86rem, 3.4vw, 1rem); margin-bottom: 1.8rem; }
  .dxc__pts { grid-template-columns: 1fr; gap: 1.4rem; max-width: none; }
  .dxc__n { font-size: 0.7rem; margin-bottom: 0.35rem; }
  .dxc__t { font-size: 0.78rem; margin-bottom: 0.3rem; }
  .dxc__d { font-size: 0.82rem; }
}

/* The chrome around a window read from a foot away. */
@container (max-width: 560px) {
  .dxw { font-size: clamp(8.5px, 2.4cqw, 13px); }
}
@container (max-width: 300px) {
  .dxt { grid-template-columns: 1fr; grid-template-rows: repeat(4, 1fr); }
}


/* ==========================================================================
   AI AGENTS
   The fourth room, and the only one that is not a photograph. There was no
   plate to measure, so the room is made out of light: a wash above, two
   faint verticals where the structure would be, a horizon, and a display
   standing in the dark casting down onto the floor in front of it.

   The display is given by four percentages exactly as the glass in the other
   three rooms is, which is deliberate. If a photograph of an operations room
   arrives, the interface moves onto its screen by changing those four
   numbers and deleting the light.
   ========================================================================== */

.agn__room { position: absolute; inset: 0; }
.agn {
  position: absolute; inset: 0;
  container-type: inline-size; overflow: hidden;
  background:
    linear-gradient(180deg, #0C1424 0%, #111C30 42%, #0A1120 70%, #070B14 100%);
}
/* The cove above, doing what the cove in the boardroom photograph does. */
.agn__amb {
  position: absolute; left: 50%; top: -34%;
  width: 128%; aspect-ratio: 2 / 1; transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 50%,
    rgba(201, 168, 106, 0.11), rgba(201, 168, 106, 0) 62%);
}
.agn__pillar {
  position: absolute; top: 0; bottom: 30%; width: 1px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0));
}
.agn__pillar--l { left: 7%; }
.agn__pillar--r { right: 7%; }
.agn__horizon {
  position: absolute; left: 0; right: 0; top: 70%; height: 1px;
  background: linear-gradient(90deg, transparent,
    rgba(255, 255, 255, 0.10) 18%, rgba(255, 255, 255, 0.10) 82%, transparent);
}
/* What a lit screen does to the floor in front of it. */
/* Light falls off towards the corners, which is the whole reason a display
   in a dark room reads as a display. Under the screen rather than over it. */
.agn::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse at 50% 38%,
    rgba(0, 0, 0, 0) 26%, rgba(0, 0, 0, 0.42) 74%, rgba(0, 0, 0, 0.62) 100%);
}
.agn__cast {
  position: absolute; left: 8%; right: 28%; top: 60%; height: 26%;
  background: radial-gradient(ellipse at 50% 0%,
    rgba(150, 180, 225, 0.18), rgba(150, 180, 225, 0) 72%);
}
/* The phone's own pool, under the phone rather than the wall. Smaller and
   dimmer, because a phone puts out less light than a wall does. */
.agn__cast--r {
  left: 68%; right: 4%; top: 60%; height: 18%;
  background: radial-gradient(ellipse at 50% 0%,
    rgba(150, 180, 225, 0.13), rgba(150, 180, 225, 0) 70%);
}

.agn__screen {
  position: absolute;
  left: 12.34%; top: 12%; width: 57%; height: 50%;
  z-index: 2;
  container-type: inline-size; overflow: hidden;
  border-radius: 0.4cqw;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: linear-gradient(180deg, #16233A 0%, #0D1729 100%);
  /* A bezel, then the room: the first two rings are the housing the glass is
     set into, and the rest is the light it puts into the air around it. */
  box-shadow: 0 0 0 0.5cqw #080D18,
              0 0 0 0.56cqw rgba(255, 255, 255, 0.05),
              0 0 6cqw rgba(140, 175, 225, 0.16),
              0 0 2cqw rgba(140, 175, 225, 0.09),
              0 2.6cqw 5cqw rgba(0, 0, 0, 0.55);
}
.agn__screen::after {
  content: ""; position: absolute; inset: 0; z-index: 9; pointer-events: none;
  background: linear-gradient(114deg,
    rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.016) 26%,
    rgba(255, 255, 255, 0) 46%);
}

/* ==========================================================================
   THE PHONE
   The wall display is the back of the agent: what it can reach, what it is
   doing, what it produced. This is the front: the same worker, seen from the
   only place a customer ever sees it from.

   It is a device rather than a second panel because the argument is about
   where the work arrives. Its height is given as a percentage of the room and
   its width follows from the aspect ratio, so it stays a phone whatever the
   room turns out to be, and it stands on the same baseline as the display.
   ========================================================================== */

.agn__pcap {
  position: absolute; z-index: 3;
  left: 68.28%; width: 24%; top: 10.4%;
  text-align: center;
}
.agn__ptitle {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.78cqw; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--gold); max-width: none; margin-bottom: 0.62cqw;
}

.agn__phone {
  position: absolute; z-index: 2;
  left: 72.9%; top: 14%; height: 48%;
  aspect-ratio: 9 / 19.5;
  padding: 0.4cqw;
  container-type: inline-size;
  border-radius: 2.1cqw;
  background: linear-gradient(158deg, #1E293D 0%, #10192B 46%, #080D18 100%);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07),
              0 0 4.4cqw rgba(140, 175, 225, 0.13),
              0 0 1.6cqw rgba(140, 175, 225, 0.08),
              0 2.2cqw 4cqw rgba(0, 0, 0, 0.55);
}
/* The same sheet of glass the wall display has, at the phone's angle. */
.agn__phone::after {
  content: ""; position: absolute; inset: 0; z-index: 9; pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(146deg,
    rgba(255, 255, 255, 0.07) 0%, rgba(255, 255, 255, 0.02) 24%,
    rgba(255, 255, 255, 0) 44%);
}

/* Just under the phone, on the same line the wall display's own footer sits
   on, so the two demonstrations read as one composition rather than one
   being an afterthought. */
.agn__preplay {
  position: absolute; z-index: 3;
  left: 80.28%; top: 63.8%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 0.5em;
  padding: 0.44em 0.9em;
  border: 1px solid rgba(255, 255, 255, 0.22); border-radius: 999px;
  background: transparent; cursor: pointer;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.72cqw; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.agn__preplay::before {
  content: ""; width: 0.42em; height: 0.42em; border-radius: 50%;
  background: var(--gold);
}
.agn__preplay:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.42); }
.agn__preplay:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 2px; }

/* --- the glass -------------------------------------------------------- */
/* The wall display says this of itself in its own footer; the phone is a
   separate object across the room, so it has to say it too. */
.agn__pnote {
  position: absolute; z-index: 3;
  left: 68.28%; width: 24%; top: 67.1%;
  text-align: center;
  font-size: 0.68cqw; line-height: 1.5;
  color: rgba(255, 255, 255, 0.34); max-width: none;
}

.wag {
  position: absolute; inset: 0.4cqw;
  display: grid; grid-template-rows: auto auto 1fr auto;
  border-radius: 1.75cqw; overflow: hidden;
  background: linear-gradient(180deg, #0B1220 0%, #080D18 100%);
  font-family: var(--ff-text);
  font-size: clamp(9.5px, 5.8cqw, 14px); line-height: 1.42;
  color: var(--sky-80);
}

/* The strip above the app, which is most of what makes a rectangle read as a
   phone rather than as a small window. */
.wag__sb {
  display: flex; align-items: center; gap: 0.3em;
  padding: 0.42em 1em 0.12em;
  font-size: 0.6em; letter-spacing: 0.02em; color: rgba(255, 255, 255, 0.5);
}
.wag__sb b { font-weight: 600; margin-right: auto; }
.wag__sbi {
  width: 0.4em; height: 0.4em; border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
}
.wag__sbi--b {
  position: relative; width: 0.95em; height: 0.5em;
  margin-left: 0.14em; border-radius: 0.14em;
  background: none; border: 1px solid rgba(255, 255, 255, 0.36);
}
.wag__sbi--b::after {
  content: ""; position: absolute; right: -0.18em; top: 0.11em;
  width: 0.09em; height: 0.2em; border-radius: 0 1px 1px 0;
  background: rgba(255, 255, 255, 0.36);
}

/* --- the header ------------------------------------------------------- */
.wag__top {
  display: flex; align-items: center; gap: 0.5em;
  padding: 0.5em 0.7em 0.6em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.03);
}
.wag__back {
  width: 0.42em; height: 0.42em; flex: none; margin: 0 0.1em 0 0.05em;
  border-left: 1.2px solid rgba(255, 255, 255, 0.45);
  border-bottom: 1.2px solid rgba(255, 255, 255, 0.45);
  transform: rotate(45deg);
}
.wag__av {
  width: 1.85em; height: 1.85em; flex: none;
  display: grid; place-items: center; border-radius: 50%;
  background: rgba(201, 168, 106, 0.12);
  border: 1px solid rgba(201, 168, 106, 0.3);
  color: var(--gold);
}
/* Gold rather than the colour the mark is usually painted in, exactly as the
   floating button elsewhere on this site is: the shape and the word carry the
   recognition, and the palette stays the one it is supposed to be. */
.wag__av svg { width: 1.05em; height: 1.05em; }
.wag__gp { fill: #0B1220; }
.wag__id { display: flex; flex-direction: column; min-width: 0; }
.wag__name {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.74em; color: var(--white);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wag__sub {
  font-style: normal; font-size: 0.6em; color: rgba(255, 255, 255, 0.45);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color var(--dur) var(--ease);
}
.wag.is-typing .wag__sub { color: var(--gold); }
/* Who is holding the conversation. It is a chip rather than a sentence so
   that it can change without anything else moving. */
.wag__who {
  margin-left: auto; flex: none;
  display: inline-flex; align-items: center; gap: 0.32em;
  padding: 0.24em 0.5em;
  border: 1px solid rgba(201, 168, 106, 0.35); border-radius: 999px;
  background: rgba(201, 168, 106, 0.1);
  transition: border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.wag__who i {
  width: 0.34em; height: 0.34em; border-radius: 50%; background: var(--gold);
}
.wag__who b {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.54em; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gold);
}
.wag__who.is-human {
  border-color: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.07);
}
.wag__who.is-human i { background: var(--white); }
.wag__who.is-human b { color: var(--white); }

/* --- the conversation -------------------------------------------------- */
.wag__thread {
  display: flex; flex-direction: column; gap: 0.29em;
  padding: 0.55em 0.7em 0.5em;
  overflow-y: auto; min-height: 0;
  scrollbar-width: none;
}
.wag__thread::-webkit-scrollbar { width: 0; }
.wag__day {
  align-self: center; margin-top: auto; margin-bottom: 0.2em;
  padding: 0.2em 0.6em; border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  font-size: 0.6em; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
}
/* Nothing is in the thread until it has been said. */
.wag__row { display: none; }
.wag__row.is-in { display: flex; animation: wagIn 260ms var(--ease-out) both; }
@keyframes wagIn {
  from { opacity: 0; transform: translateY(0.5em) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
.wag__row--in  { justify-content: flex-start; }
.wag__row--out { justify-content: flex-end; }
.wag__row--act { justify-content: center; }

.wag__b {
  position: relative; max-width: 84%;
  padding: 0.4em 0.58em 0.3em;
  border-radius: 0.62em;
  font-size: 0.68em; line-height: 1.45;
}
.wag__row--in .wag__b {
  background: rgba(255, 255, 255, 0.1);
  border-top-left-radius: 0.14em;
  color: rgba(255, 255, 255, 0.82);
}
.wag__row--out .wag__b {
  background: rgba(201, 168, 106, 0.15);
  border: 1px solid rgba(201, 168, 106, 0.24);
  border-top-right-radius: 0.12em;
  color: var(--white);
}
/* Every bubble here starts its own group, since a chip or the other party
   always sits between two of them, so every bubble gets a tail. */
.wag__b::after {
  content: ""; position: absolute; top: 0;
  border-style: solid; border-color: transparent;
}
.wag__row--in .wag__b::after {
  left: -0.42em;
  border-width: 0 0.44em 0.4em 0;
  border-right-color: rgba(255, 255, 255, 0.1);
}
.wag__row--out .wag__b::after {
  right: -0.44em; top: -1px;
  border-width: 0 0 0.4em 0.44em;
  border-left-color: rgba(201, 168, 106, 0.26);
}
/* The time sits on the last line of the bubble the way it does in a real
   thread, which is why it is floated rather than given a row of its own. */
.wag__t {
  float: right; margin: 0.5em 0 0 0.55em;
  display: inline-flex; align-items: center; gap: 0.3em;
  font-size: 0.82em; color: rgba(255, 255, 255, 0.42);
}
.wag__row--out .wag__t { color: rgba(201, 168, 106, 0.8); }
.wag__tk { width: 1.05em; height: 0.63em; }

/* What the agent did between one message and the next. This is the line that
   separates a worker from a chatbot, so it is drawn rather than described. */
.wag__act {
  display: inline-flex; align-items: center; gap: 0.4em;
  max-width: 92%; padding: 0.28em 0.62em;
  border: 1px solid rgba(255, 255, 255, 0.09); border-radius: 999px;
  background: rgba(255, 255, 255, 0.035);
  font-size: 0.62em; letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.62); text-align: center;
}
/* A tick inside a disc this small is a smudge, so it is a disc. */
.wag__act i {
  width: 0.46em; height: 0.46em; flex: none; border-radius: 50%;
  background: var(--gold);
}

/* --- the bar at the foot, which is scenery ---------------------------- */
.wag__bar {
  display: flex; align-items: center; gap: 0.45em;
  padding: 0.42em 0.6em 0.5em;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.wag__field {
  flex: 1; padding: 0.42em 0.7em;
  border-radius: 999px; background: rgba(255, 255, 255, 0.05);
  font-size: 0.62em; color: rgba(255, 255, 255, 0.3);
}
.wag__send {
  width: 1.5em; height: 1.5em; flex: none; border-radius: 50%;
  background: rgba(201, 168, 106, 0.22); position: relative;
}
.wag__send::after {
  content: ""; position: absolute; left: 0.5em; top: 0.46em;
  width: 0; height: 0;
  border-left: 0.5em solid var(--gold);
  border-top: 0.3em solid transparent; border-bottom: 0.3em solid transparent;
}

.agn__hint {
  position: absolute; z-index: 6;
  /* Directly above the demonstration, on the dark wall over the display.
     The room is drawn rather than photographed, so the screen's own 12% is
     the number to hang this from; the pill is pulled fully above that line
     and then 1.2 container-widths clear of it. The phone stands 2% lower,
     so one line clears both. */
  left: 50%; top: 12%; bottom: auto;
  transform: translate(-50%, calc(-100% - 1.2 * var(--u)));
  display: inline-flex; align-items: center; gap: calc(0.66 * var(--u));
  padding: calc(0.46 * var(--u)) calc(1 * var(--u)) calc(0.46 * var(--u)) calc(0.84 * var(--u));
  border: 1px solid rgba(201, 168, 106, 0.38); border-radius: 999px;
  background: rgba(15, 23, 42, 0.42);
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.78 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9); max-width: none;
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}
.agn__hint-dot {
  width: calc(0.46 * var(--u)); height: calc(0.46 * var(--u)); border-radius: 50%;
  background: var(--gold); animation: erpsBeacon 2.6s var(--ease) infinite;
}
.agn__hint.is-gone {
  opacity: 0; pointer-events: none;
  transform: translate(-50%, calc(-100% - 0.7 * var(--u)));
}

.agc {
  position: absolute; left: 5.2%; right: 5.2%; bottom: 3.4%;
  color: var(--white);
}
.agc__eyebrow { font-size: calc(0.82 * var(--u)); margin-bottom: calc(0.9 * var(--u)); }
.agc__h {
  font-size: calc(2.1 * var(--u)); font-weight: 500; letter-spacing: -0.025em;
  color: var(--white); margin-bottom: calc(0.7 * var(--u));
}
.agc__lead {
  font-size: calc(0.95 * var(--u)); line-height: 1.55;
  color: rgba(255, 255, 255, 0.66); max-width: 76ch; margin-bottom: calc(1.5 * var(--u));
}
.agc__pts { display: grid; grid-template-columns: repeat(4, 1fr); gap: calc(2 * var(--u)); max-width: 94%; }
.agc__n {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.8 * var(--u)); letter-spacing: 0.16em; color: var(--gold); margin-bottom: calc(0.55 * var(--u));
}
.agc__t {
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.86 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--white); margin-bottom: calc(0.4 * var(--u)); max-width: none;
}
.agc__d { font-size: calc(0.84 * var(--u)); line-height: 1.6; color: rgba(255, 255, 255, 0.58); max-width: none; }

/* ==========================================================================
   THE AGENT AT WORK
   Three columns, and the argument of the whole room is in their order: what
   it can reach, what it is doing, what it has produced. A chat window has
   only the middle one, which is why a chat window cannot make this claim.
   ========================================================================== */
.aga {
  position: absolute; inset: 0;
  display: grid; grid-template-rows: 2.6em 1fr;
  /* The screen is half the room's height whatever the room is, but its width
     follows the window, so past a point the type inside it kept growing while
     the glass did not and the last line of the work produced was cut off. The
     second term holds the type to the glass. */
  font-size: clamp(6px, 1.42cqw, 16px);
  font-family: var(--ff-text); line-height: 1.45;
  color: var(--sky-80);
}
.aga__bar {
  display: flex; align-items: center; gap: 1em; padding: 0 1em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.025);
}
.aga__brand {
  display: inline-flex; align-items: center; gap: 0.55em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.86em; letter-spacing: 0.02em; color: var(--white);
}
.aga__mark {
  width: 0.6em; height: 0.6em; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 0.24em rgba(201, 168, 106, 0.16);
}
.aga__task {
  font-size: 0.72em; color: rgba(255, 255, 255, 0.34);
  padding-left: 1em; border-left: 1px solid rgba(255, 255, 255, 0.10);
}
/* Idle, working, done. Three words and a colour, which is all a status needs. */
.aga__status {
  padding: 0.24em 0.7em; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.14); color: rgba(255, 255, 255, 0.5);
  font-family: var(--ff-display); font-size: 0.6em;
  font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.aga.is-running .aga__status { color: var(--gold); border-color: var(--gold-40); background: rgba(201, 168, 106, 0.10); }
.aga.is-done .aga__status { color: var(--midnight); background: var(--gold); border-color: var(--gold); }
.aga__ctrls { margin-left: auto; display: inline-flex; gap: 0.4em; }
.aga__btn {
  font: inherit; font-family: var(--ff-display); font-weight: 600;
  font-size: 0.64em; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.42em 0.95em; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.16); background: none;
  color: rgba(255, 255, 255, 0.72);
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease), opacity var(--dur) var(--ease);
}
.aga__btn:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.4); }
.aga__btn:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 2px; }
.aga__btn--go { background: var(--gold); border-color: var(--gold); color: var(--midnight); }
.aga__btn--go:hover { background: #D8BA80; border-color: #D8BA80; color: var(--midnight); }
.aga.is-running .aga__btn--go { opacity: 0.4; pointer-events: none; }
.aga__tag {
  padding: 0.24em 0.7em; border-radius: 999px;
  border: 1px solid var(--gold-40); color: var(--gold);
  font-family: var(--ff-display); font-size: 0.56em;
  font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
}

.aga__body {
  display: grid; grid-template-columns: 11.4em 1fr 17.4em;
  gap: 1.1em; padding: 1em 1.1em; min-height: 0;
}
.aga__rh {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.62em; letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42); margin-bottom: 0.8em; max-width: none;
}
.aga__rf {
  margin-top: auto; padding-top: 0.8em;
  font-size: 0.58em; line-height: 1.5; color: rgba(255, 255, 255, 0.26); max-width: none;
}

/* --- what it can reach --- */
.aga__rail { display: flex; flex-direction: column; min-height: 0;
  padding-right: 1.1em; border-right: 1px solid rgba(255, 255, 255, 0.07); }
/* Spread down the rail rather than stacked at the top of it: this is a
   panel of systems, and a panel is the shape of its housing. */
.aga__sysl {
  list-style: none; margin: 0; padding: 0; flex: 1; min-height: 0;
  display: flex; flex-direction: column; justify-content: space-around; gap: 0.3em;
}
.aga__sys {
  display: flex; align-items: center; gap: 0.55em;
  padding: 0.32em 0.45em; border-radius: 0.25em;
  border-left: 2px solid transparent;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.aga__ico {
  width: 1.5em; height: 1.5em; flex: none; display: grid; place-items: center;
  border-radius: 0.2em; border: 1px solid rgba(255, 255, 255, 0.10);
  color: rgba(255, 255, 255, 0.42);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.aga__ico svg { width: 0.95em; height: 0.95em; }
.aga__sysn { font-size: 0.68em; color: rgba(255, 255, 255, 0.5); transition: color var(--dur) var(--ease); }
.aga__state {
  margin-left: auto; width: 0.36em; height: 0.36em; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  transition: background-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* Reaching into a system, and having reached into it. */
.aga__sys.is-live { background: rgba(201, 168, 106, 0.10); border-left-color: var(--gold); }
.aga__sys.is-live .aga__ico { color: var(--gold); border-color: var(--gold-40); background: rgba(201, 168, 106, 0.10); }
.aga__sys.is-live .aga__sysn { color: var(--white); }
.aga__sys.is-live .aga__state { background: var(--gold); animation: agaPing 1.1s var(--ease) infinite; }
.aga__sys.is-touched { background: rgba(201, 168, 106, 0.05); border-left-color: rgba(201, 168, 106, 0.45); }
.aga__sys.is-touched .aga__ico {
  color: var(--gold); border-color: rgba(201, 168, 106, 0.34);
  background: rgba(201, 168, 106, 0.07);
}
.aga__sys.is-touched .aga__sysn { color: rgba(255, 255, 255, 0.82); }
.aga__sys.is-touched .aga__state { background: var(--gold); }
@keyframes agaPing {
  0%   { box-shadow: 0 0 0 0 rgba(201, 168, 106, 0.45); }
  70%  { box-shadow: 0 0 0 0.5em rgba(201, 168, 106, 0); }
  100% { box-shadow: 0 0 0 0 rgba(201, 168, 106, 0); }
}

/* --- the work --- */
.aga__main { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.aga__req {
  padding: 0.7em 0.85em; border-radius: 0.25em;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.03);
}
.aga__reqh {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: 0.56em; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 0.35em;
}
.aga__reqt { font-size: 0.82em; color: var(--white); max-width: none; min-height: 1.5em; }
.aga__caret {
  display: inline-block; width: 1px; height: 0.95em; margin-left: 1px;
  background: var(--gold); vertical-align: -0.1em;
  animation: agaBlink 1s steps(2, start) infinite;
}
@keyframes agaBlink { to { opacity: 0; } }
.aga:not(.is-typing) .aga__caret { display: none; }

.aga__track { height: 1px; margin: 0.9em 0 0.9em; background: rgba(255, 255, 255, 0.08); }
.aga__track i { display: block; height: 100%; width: 0%; background: var(--gold);
  transition: width 420ms var(--ease-out); }

.aga__steps { list-style: none; margin: 0; padding: 0; flex: 1; min-height: 0;
  display: flex; flex-direction: column; gap: 0.05em; }
.aga__step {
  display: grid; grid-template-columns: 1.5em 1fr; align-items: start;
  padding: 0.42em 0; opacity: 0.34;
  transition: opacity var(--dur) var(--ease);
}
.aga__step.is-active, .aga__step.is-done { opacity: 1; }
.aga__tick {
  width: 0.62em; height: 0.62em; margin-top: 0.42em; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.28); position: relative;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
/* The line down the left is drawn by the ticks themselves. */
.aga__step + .aga__step .aga__tick::before {
  content: ""; position: absolute; left: 50%; bottom: 100%;
  width: 1px; height: 0.85em; transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.12);
}
.aga__step.is-active .aga__tick { border-color: var(--gold); box-shadow: 0 0 0 0.22em rgba(201, 168, 106, 0.16); }
.aga__step.is-done .aga__tick { background: var(--gold); border-color: var(--gold); }
/* Both of these belong beside the tick rather than under it: three children
   in a two column grid puts the third back in the first column. */
.aga__st {
  grid-column: 2;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.74em; letter-spacing: 0.02em; color: var(--white);
}
.aga__step.is-active .aga__st { color: var(--gold); }
.aga__sd {
  grid-column: 2;
  display: block; font-size: 0.68em; line-height: 1.5;
  color: rgba(255, 255, 255, 0.46); max-width: 52ch;
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height var(--dur) var(--ease), opacity var(--dur) var(--ease),
              margin-top var(--dur) var(--ease);
}
.aga__step.is-active .aga__sd, .aga__step.is-done .aga__sd {
  max-height: 4em; opacity: 1; margin-top: 0.15em;
}

/* --- what it produced --- */
.aga__out { display: flex; flex-direction: column; gap: 0.7em; min-height: 0;
  padding-left: 1.1em; border-left: 1px solid rgba(255, 255, 255, 0.07); }
.aga__art {
  opacity: 0; transform: translateY(0.6em);
  transition: opacity 520ms var(--ease-out), transform 520ms var(--ease-out);
}
.aga__art.is-in { opacity: 1; transform: none; }
.aga__arth {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.62em; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5); margin-bottom: 0.5em; max-width: none;
}
.aga__arth span { color: var(--gold); }
.aga__draft {
  display: block; width: 100%; text-align: left; font: inherit; cursor: pointer;
  padding: 0.5em 0.6em; margin-bottom: 0.3em; border-radius: 0.25em;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left: 2px solid var(--gold-40);
  background: rgba(255, 255, 255, 0.03);
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.aga__draft:hover { background: rgba(255, 255, 255, 0.06); }
.aga__draft:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 1px; }
.aga__draft.is-open { background: rgba(201, 168, 106, 0.08); border-left-color: var(--gold); }
.aga__dto {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: 0.6em; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.44); margin-bottom: 0.15em;
}
.aga__dsub { display: block; font-size: 0.68em; color: var(--white); }
.aga__dbody {
  display: block; font-size: 0.64em; line-height: 1.55; color: rgba(255, 255, 255, 0.52);
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height var(--dur) var(--ease), opacity var(--dur) var(--ease),
              margin-top var(--dur) var(--ease);
}
.aga__draft.is-open .aga__dbody { max-height: 9em; opacity: 1; margin-top: 0.4em; }
.aga__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3em; }
.aga__list li {
  display: flex; justify-content: space-between; gap: 0.6em;
  font-size: 0.66em; color: rgba(255, 255, 255, 0.44);
}
.aga__list b { font-weight: 400; color: rgba(255, 255, 255, 0.72); }
.aga__art--done {
  padding: 0.7em 0.8em; border-radius: 0.25em;
  border: 1px solid rgba(201, 168, 106, 0.3); background: rgba(201, 168, 106, 0.08);
}
.aga__doneh {
  display: flex; align-items: center; gap: 0.5em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.7em; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 0.35em; max-width: none;
}
.aga__doneh i {
  width: 0.85em; height: 0.85em; border-radius: 50%; background: var(--gold);
  position: relative; flex: none;
}
.aga__doneh i::after {
  content: ""; position: absolute; left: 0.26em; top: 0.13em;
  width: 0.22em; height: 0.42em; border: solid var(--midnight);
  border-width: 0 1.5px 1.5px 0; transform: rotate(42deg);
}
.aga__donet { font-size: 0.66em; line-height: 1.55; color: rgba(255, 255, 255, 0.66); max-width: none; }

@media (prefers-reduced-motion: reduce) {
  .agn__hint-dot { animation: none; box-shadow: 0 0 0 0.28cqw rgba(201, 168, 106, 0.22); }
  .aga__caret, .aga__sys.is-live .aga__state { animation: none; }
  .wag__row.is-in { animation: none; }
}

/* ==========================================================================
   NARROW
   The room is light rather than a photograph, so on a phone it simply stops
   being a room: the display becomes the page, and the three columns of the
   workspace become three sections of it.
   ========================================================================== */
@media (max-width: 1100px) {
  /* The other three rooms have a photograph for the way out to sit over. This
     one does not, so it is given the space instead. */
  .agn__room { position: relative; inset: auto; padding-top: clamp(2.6rem, 8vw, 3.4rem); }
  .agn { position: relative; inset: auto; }
  .agn__amb, .agn__pillar, .agn__horizon, .agn__cast { display: none; }
  .agn__screen {
    position: relative; left: auto; top: auto; width: auto; height: auto;
    border-radius: 0; border-left: 0; border-right: 0; box-shadow: none;
  }
  .aga { position: relative; inset: auto; grid-template-rows: auto 1fr; }

  .agn__hint {
    position: static; transform: none;
    margin: clamp(1.3rem, 4vw, 1.9rem) var(--pad) 0;
    gap: 0.55rem; padding: 0.44rem 0.85rem 0.44rem 0.7rem;
    font-size: clamp(0.62rem, 2.4vw, 0.72rem);
  }
  .agn__hint-dot { width: 0.4rem; height: 0.4rem; }
  .agn__hint.is-gone { transform: translateY(0.3rem); }

  /* The phone stops being an object in a room and becomes what it
     already is on a phone: the thing you are holding. */
  .agn__pcap {
    position: static; width: auto;
    margin: clamp(2rem, 6vw, 2.8rem) auto 0;
    max-width: 34rem; padding: 0 var(--pad);
  }
  .agn__ptitle {
    font-size: clamp(0.66rem, 2.5vw, 0.78rem); margin-bottom: 0.7rem;
  }
  /* relative rather than static: the glass inside is positioned against it,
     and a static phone would let it escape to the room. */
  .agn__phone {
    position: relative; left: auto; top: auto; height: auto;
    width: min(310px, 74vw); aspect-ratio: 9 / 19.5;
    margin: clamp(0.9rem, 3vw, 1.2rem) auto 0;
    padding: 6px; border-radius: 30px; box-shadow: none;
    border: 1px solid rgba(255, 255, 255, 0.08);
  }
  /* Held in the hand rather than seen across a room, so the type in it can
     be the size it would really be. */
  .wag { inset: 6px; border-radius: 25px; font-size: clamp(12.5px, 5.1cqw, 15px); }
  .agn__pnote {
    position: static; width: auto; margin: 0.9rem var(--pad) 0;
    font-size: clamp(0.68rem, 2.6vw, 0.76rem);
  }
  .agn__preplay {
    position: static; transform: none;
    display: flex; width: fit-content;
    margin: clamp(1.1rem, 3.6vw, 1.5rem) auto 0;
    font-size: 0.68rem;
  }

  .agc {
    position: static;
    padding: clamp(1.6rem, 5vw, 2.6rem) var(--pad) clamp(2rem, 6vw, 3rem);
  }
  .agc__eyebrow { font-size: clamp(0.72rem, 2.6vw, 0.86rem); margin-bottom: 0.9rem; }
  .agc__h { font-size: clamp(1.35rem, 5.4vw, 1.9rem); margin-bottom: 0.7rem; }
  .agc__lead { font-size: clamp(0.86rem, 3.4vw, 1rem); margin-bottom: 1.8rem; }
  .agc__pts { grid-template-columns: 1fr; gap: 1.4rem; max-width: none; }
  .agc__n { font-size: 0.7rem; margin-bottom: 0.35rem; }
  .agc__t { font-size: 0.78rem; margin-bottom: 0.3rem; }
  .agc__d { font-size: 0.82rem; }
}

@container (max-width: 620px) {
  .aga { font-size: clamp(8.5px, 2.2cqw, 13px); }
  .aga__bar { flex-wrap: wrap; padding: 0.6em 0.9em; gap: 0.6em; }
  .aga__task, .aga__tag { display: none; }
  .aga__body { grid-template-columns: 1fr; gap: 1.2em; padding: 1em 0.9em 1.2em; }
  .aga__rail {
    padding-right: 0; border-right: 0; order: 3;
    padding-top: 1em; border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
  .aga__sysl { display: grid; grid-template-columns: 1fr 1fr; }
  .aga__out {
    padding-left: 0; border-left: 0; order: 2;
    padding-top: 1em; border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
  .aga__rail .aga__rf { display: none; }
}


/* ==========================================================================
   BRANDING & CONTENT
   The fifth room. Built light again, like the agents next door, but turned
   and warmed: the key comes from the left rather than overhead, there is a
   seam of light down the far wall, and the floor becomes a table. Same
   construction, different room, which is what a studio is compared to an
   operations floor.
   ========================================================================== */

.bsn__room { position: absolute; inset: 0; }
.bsn {
  position: absolute; inset: 0;
  container-type: inline-size; overflow: hidden;
  background:
    linear-gradient(180deg, #0E1626 0%, #131D31 40%, #0B1220 72%, #080D18 100%);
}
.bsn::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse at 46% 38%,
    rgba(0, 0, 0, 0) 26%, rgba(0, 0, 0, 0.40) 74%, rgba(0, 0, 0, 0.60) 100%);
}
/* A lamp, off to the left, warm. */
.bsn__key {
  position: absolute; left: -14%; top: -22%;
  width: 74%; aspect-ratio: 1 / 1;
  background: radial-gradient(circle at 50% 50%,
    rgba(201, 168, 106, 0.16), rgba(201, 168, 106, 0) 58%);
}
/* A seam of light down the far wall. */
.bsn__seam {
  position: absolute; right: 9%; top: 6%; bottom: 34%; width: 2px;
  background: linear-gradient(180deg, rgba(201, 168, 106, 0),
    rgba(201, 168, 106, 0.30), rgba(201, 168, 106, 0));
}
/* Not a horizon: a table, which is what a studio has. */
.bsn__table {
  position: absolute; left: 0; right: 0; top: 72%; bottom: 0;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.085) 0, rgba(255, 255, 255, 0.03) 1px,
    rgba(8, 13, 24, 0.34) 24%, rgba(6, 10, 18, 0.72) 100%);
}
.bsn__cast {
  position: absolute; left: 6%; right: 30%; top: 58%; height: 24%;
  background: radial-gradient(ellipse at 50% 0%,
    rgba(190, 200, 225, 0.16), rgba(190, 200, 225, 0) 72%);
}
/* The page is a lit white rectangle, so what it throws down is warmer and
   brighter than what the operations display does. */
.bsn__cast--r {
  position: absolute; left: 70%; right: 8%; top: 58%; height: 18%;
  background: radial-gradient(ellipse at 50% 0%,
    rgba(232, 236, 245, 0.2), rgba(232, 236, 245, 0) 70%);
}

.bsn__screen {
  position: absolute;
  left: 11%; top: 12%; width: 60%; height: 50%;
  z-index: 2;
  container-type: inline-size; overflow: hidden;
  border-radius: 0.4cqw;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: linear-gradient(180deg, #16233A 0%, #0D1729 100%);
  box-shadow: 0 0 0 0.5cqw #080D18,
              0 0 0 0.56cqw rgba(255, 255, 255, 0.05),
              0 0 6cqw rgba(160, 180, 220, 0.15),
              0 0 2cqw rgba(160, 180, 220, 0.08),
              0 2.6cqw 5cqw rgba(0, 0, 0, 0.55);
}
.bsn__screen::after {
  content: ""; position: absolute; inset: 0; z-index: 9; pointer-events: none;
  background: linear-gradient(114deg,
    rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.016) 26%,
    rgba(255, 255, 255, 0) 46%);
}

.bsn__hint {
  position: absolute; z-index: 6;
  /* Directly above the demonstration, on the dark wall over the display.
     The room is drawn rather than photographed, so the screen's own 12% is
     the number to hang this from; the pill is pulled fully above that line
     and then 1.2 container-widths clear of it. The page stands 2% lower,
     so one line clears both. */
  left: 50%; top: 12%; bottom: auto;
  transform: translate(-50%, calc(-100% - 1.2 * var(--u)));
  display: inline-flex; align-items: center; gap: calc(0.66 * var(--u));
  padding: calc(0.46 * var(--u)) calc(1 * var(--u)) calc(0.46 * var(--u)) calc(0.84 * var(--u));
  border: 1px solid rgba(201, 168, 106, 0.38); border-radius: 999px;
  background: rgba(15, 23, 42, 0.42);
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.78 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9); max-width: none;
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}
.bsn__hint-dot {
  width: calc(0.46 * var(--u)); height: calc(0.46 * var(--u)); border-radius: 50%;
  background: var(--gold); animation: erpsBeacon 2.6s var(--ease) infinite;
}
.bsn__hint.is-gone {
  opacity: 0; pointer-events: none;
  transform: translate(-50%, calc(-100% - 0.7 * var(--u)));
}

/* ==========================================================================
   THE BRAND IN PUBLIC

   Everything else in this room is machinery. This is the one thing a customer
   ever actually sees, which is why it is the only light surface anywhere in
   the estate: a white page standing in a dark room reads as published, and
   the operations display beside it reads as the thing that published it.

   Twelve tiles, no two alike, all unmistakably one brand. That sentence is
   the entire argument of the use case, and it is easier to see than to say.
   ========================================================================== */

.bsn__ptitle {
  position: absolute; z-index: 3;
  left: 72.3%; width: 18.5%; top: 10.4%;
  text-align: center;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.78cqw; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--gold); max-width: none;
}

.bsn__phone {
  position: absolute; z-index: 2;
  left: 74%; top: 14%; height: 48%;
  aspect-ratio: 9 / 19.5;
  padding: 0.4cqw;
  container-type: inline-size;
  border-radius: 2.1cqw;
  background: linear-gradient(158deg, #1E293D 0%, #10192B 46%, #080D18 100%);
  /* A brighter halo than the dark screens get, because the thing inside it
     is white. */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1),
              0 0 5cqw rgba(226, 232, 240, 0.16),
              0 0 1.8cqw rgba(226, 232, 240, 0.1),
              0 2.2cqw 4cqw rgba(0, 0, 0, 0.6);
}
.bsn__phone::after {
  content: ""; position: absolute; inset: 0; z-index: 9; pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(146deg,
    rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.03) 24%,
    rgba(255, 255, 255, 0) 44%);
}

.bsn__pnote {
  position: absolute; z-index: 3;
  left: 72.3%; width: 18.5%; top: 63.4%;
  text-align: center;
  font-size: 0.72cqw; line-height: 1.55;
  color: rgba(255, 255, 255, 0.46); max-width: none;
}

/* --- the page ---------------------------------------------------------- */
.bsg {
  position: absolute; inset: 0.4cqw;
  display: flex; flex-direction: column;
  border-radius: 1.75cqw; overflow: hidden;
  background: #FFFFFF;
  font-family: var(--ff-text);
  font-size: clamp(8px, 5.6cqw, 13px); line-height: 1.4;
  color: var(--deep-text, #111827);
}

.bsg__sb {
  display: flex; align-items: center; gap: 0.3em;
  padding: 0.5em 0.9em 0.2em;
  font-size: 0.6em; color: rgba(17, 24, 39, 0.55);
}
.bsg__sb b { font-weight: 600; margin-right: auto; }
.bsg__sbi {
  width: 0.4em; height: 0.4em; border-radius: 50%;
  background: rgba(17, 24, 39, 0.4);
}
.bsg__sbi--b {
  position: relative; width: 0.95em; height: 0.5em;
  margin-left: 0.14em; border-radius: 0.14em;
  background: none; border: 1px solid rgba(17, 24, 39, 0.38);
}
.bsg__sbi--b::after {
  content: ""; position: absolute; right: -0.18em; top: 0.11em;
  width: 0.09em; height: 0.2em; border-radius: 0 1px 1px 0;
  background: rgba(17, 24, 39, 0.38);
}

.bsg__top {
  display: flex; align-items: center; gap: 0.6em;
  padding: 0.5em 0.9em 0.3em;
}
.bsg__av {
  width: 2.4em; height: 2.4em; flex: none;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--midnight); color: var(--gold);
  border: 1px solid rgba(201, 168, 106, 0.5);
  font-family: var(--ff-display); font-weight: 600; font-size: 0.9em;
  letter-spacing: 0.02em;
}
.bsg__id { display: flex; flex-direction: column; min-width: 0; }
.bsg__name {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.82em; color: var(--midnight);
}
.bsg__handle {
  font-style: normal; font-size: 0.62em; color: rgba(17, 24, 39, 0.5);
}
.bsg__bio {
  padding: 0 0.9em; font-size: 0.62em; line-height: 1.45;
  color: rgba(17, 24, 39, 0.68); max-width: none;
}
.bsg__pills {
  display: flex; flex-wrap: wrap; gap: 0.26em;
  padding: 0.55em 0.9em 0.7em; max-width: none;
}
.bsg__pills span {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.5em; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.3em 0.55em; border-radius: 999px;
  border: 1px solid rgba(15, 23, 42, 0.16); color: rgba(15, 23, 42, 0.62);
}

/* Full bleed, two pixel gutters: the grid is the only part of this that has
   to be recognised at a glance from across a room. */
/* The fold. Whatever does not fit is simply below it, which is what makes
   this read as a page rather than as a picture of one. */
.bsg__feed { flex: 1; min-height: 0; overflow: hidden; }
.bsg__grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px;
  background: rgba(15, 23, 42, 0.1);
  border-top: 1px solid rgba(15, 23, 42, 0.1);
}
.bsg__tile {
  position: relative; aspect-ratio: 1 / 1;
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: 0.25em; padding: 0.5em;
  overflow: hidden;
}
.bsg__tile--l { background: var(--ice, #F8FAFC); }
.bsg__tile--d { background: var(--midnight); }
.bsg__tile--a { background: var(--gold); }

.bsg__k {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.5em; letter-spacing: 0.13em; text-transform: uppercase;
  color: rgba(15, 23, 42, 0.55); order: -1;
}
.bsg__tile--d .bsg__k { color: rgba(201, 168, 106, 0.9); }
.bsg__t {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.62em; line-height: 1.22; letter-spacing: -0.005em;
  color: var(--midnight);
}
.bsg__tile--d .bsg__t { color: var(--white); }

.bsg__tile--q { justify-content: center; }
.bsg__q {
  font-family: var(--ff-display); font-weight: 500;
  font-size: 0.6em; line-height: 1.3; color: var(--midnight);
}
.bsg__tile--q::before {
  content: ""; position: absolute; left: 0.5em; top: 0.5em;
  width: 1.1em; height: 1px; background: rgba(15, 23, 42, 0.5);
}

/* The three drawn marks. A brand's grid is never all headlines, and a tile
   that is only a shape is what stops this reading as a wall of text. */
.bsg__mk { position: absolute; inset: 0; display: grid; place-items: center; }
.bsg__mk--rules {
  align-content: center; justify-items: center; gap: 0.34em;
}
.bsg__mk--rules i {
  display: block; height: 1px; background: rgba(255, 255, 255, 0.55);
}
.bsg__mk--rules i:nth-child(1) { width: 58%; }
.bsg__mk--rules i:nth-child(2) { width: 40%; background: var(--gold); }
.bsg__mk--rules i:nth-child(3) { width: 24%; }
.bsg__mk--nodes { color: rgba(255, 255, 255, 0.6); }
.bsg__mk--nodes svg { width: 52%; height: auto; }
/* place-items:center from the base rule collapses cells that have no
   content of their own, which is exactly what these four are. */
.bsg__mk--grid {
  grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  place-items: stretch; gap: 0.24em;
  width: auto; height: auto; inset: 26%;
}
.bsg__mk--grid i {
  border: 1.4px solid rgba(255, 255, 255, 0.5); border-radius: 1px;
}
.bsg__mk--grid i:nth-child(2) { background: var(--gold); border-color: var(--gold); }

.bsg__pal { display: flex; height: 1.5em; border-radius: 0.14em; overflow: hidden; }
.bsg__pal i { flex: 1; }
.bsg__pal i:last-child { box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.12); }
.bsg__tile--n { justify-content: center; align-items: flex-start; gap: 0.1em; }
.bsg__num {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 2em; line-height: 1; color: var(--gold); order: -2;
}
.bsg__aa {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 1.5em; line-height: 1; color: var(--midnight);
}

.bsg__nav {
  margin-top: auto;
  display: grid; grid-template-columns: repeat(4, 1fr);
  align-items: center; justify-items: center;
  padding: 0.5em 0 0.55em;
  border-top: 1px solid rgba(15, 23, 42, 0.1);
}
.bsg__nav i {
  width: 0.75em; height: 0.75em; border-radius: 0.14em;
  border: 1.2px solid rgba(17, 24, 39, 0.38);
}
.bsg__nav i:first-child { background: rgba(17, 24, 39, 0.38); }
.bsg__nav i:nth-child(3) { border-radius: 50%; }

.bsc { position: absolute; left: 5.2%; right: 5.2%; bottom: 3.4%; color: var(--white); }
.bsc__eyebrow { font-size: calc(0.82 * var(--u)); margin-bottom: calc(0.9 * var(--u)); }
.bsc__h {
  font-size: calc(2.1 * var(--u)); font-weight: 500; letter-spacing: -0.025em;
  color: var(--white); margin-bottom: calc(0.7 * var(--u));
}
.bsc__lead {
  font-size: calc(0.95 * var(--u)); line-height: 1.55;
  color: rgba(255, 255, 255, 0.66); max-width: 76ch; margin-bottom: calc(1.5 * var(--u));
}
.bsc__pts { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(2.4 * var(--u)); max-width: 74%; }
.bsc__n {
  display: block; font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.8 * var(--u)); letter-spacing: 0.16em; color: var(--gold); margin-bottom: calc(0.55 * var(--u));
}
.bsc__t {
  font-family: var(--ff-display); font-weight: 600;
  font-size: calc(0.86 * var(--u)); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--white); margin-bottom: calc(0.4 * var(--u)); max-width: none;
}
.bsc__d { font-size: calc(0.84 * var(--u)); line-height: 1.6; color: rgba(255, 255, 255, 0.58); max-width: none; }

/* --- One caption, five rooms ---------------------------------------------
   The five interiors were each built against their own photograph, and it
   showed the moment you moved between them: the eyebrow, the heading and the
   line under it landed at three different heights, because the block was hung
   from its foot and grew upward by however many lines its own copy happened
   to take. Two rooms have a three line lead, one has a description that takes
   a third line, and each of those pushed its own heading up by about 30px.

   So the block is given one height for all five and the numbered row is
   pushed to the foot of it. The heading now starts in the same place in every
   room and the row still finishes in the same place; what absorbs the
   difference is the gap between the two, which is empty and which nobody can
   see. The height is in container widths like everything else inside a room,
   so it holds at any size: the copy wraps at the same word at every width,
   because the type and the column scale together. */
.erpc, .agc, .birc, .dxc, .bsc {
  display: flex; flex-direction: column;
  height: calc(17.9 * var(--u));
}
.erpc__pts, .agc__pts, .birc__pts, .dxc__pts, .bsc__pts { margin-top: auto; }
/* Out here every caption is ordinary page copy under its own plate, set to
   its own length, with the whole page free to be as tall as it needs. There
   is nothing to line up against, so the one height is given back. This sits
   after the rule above rather than in the block each caption is restyled in,
   because those blocks come earlier in the file and would lose the tie. */
@media (max-width: 1100px) {
  .erpc, .agc, .birc, .dxc, .bsc { display: block; height: auto; }
  .erpc__pts, .agc__pts, .birc__pts, .dxc__pts, .bsc__pts { margin-top: 0; }
}

/* ==========================================================================
   THE BRAND AS A SYSTEM

   The old interior walked a chain of stages, which is how an agency describes
   a project. This one is laid out as a system a business owns: the knowledge
   on the left because it is the thing that is bought, the ring in the middle
   because everything else only borrows from it, and the work on the right
   because that is the part that arrives every week afterwards.

   Nothing here is a flowchart. The only arrow in the room is the spine at the
   foot, and that is the order of the run rather than the shape of the idea.
   ========================================================================== */

.bis {
  position: absolute; inset: 0;
  display: grid; grid-template-rows: 2.6em 1fr;
  font-size: clamp(8px, 1.36cqw, 15px);
  font-family: var(--ff-text); line-height: 1.45;
  color: var(--sky-80);
}

/* --- the bar ---------------------------------------------------------- */
.bis__bar {
  display: flex; align-items: center; gap: 1em; padding: 0 1.1em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.02);
}
.bis__brand {
  display: inline-flex; align-items: center; gap: 0.5em;
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.76em; letter-spacing: 0.04em; color: var(--white);
}
.bis__mark {
  width: 0.5em; height: 0.5em; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 0.22em rgba(201, 168, 106, 0.16);
}
.bis__subject {
  font-size: 0.66em; color: rgba(255, 255, 255, 0.42);
  padding-left: 1em; border-left: 1px solid rgba(255, 255, 255, 0.1);
}
.bis__status {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.58em; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 0.3em 0.7em; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.6);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.bis.is-running .bis__status {
  color: var(--gold); border-color: var(--gold-40);
  background: rgba(201, 168, 106, 0.1);
}
.bis.is-done .bis__status {
  color: var(--midnight); background: var(--gold); border-color: var(--gold);
}
.bis__ctrls { margin-left: auto; display: inline-flex; gap: 0.4em; }
.bis__btn {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.58em; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 0.44em 0.9em; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: transparent; color: rgba(255, 255, 255, 0.72);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.bis__btn:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.4); }
.bis__btn:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 2px; }
.bis__btn--go { background: var(--gold); border-color: var(--gold); color: var(--midnight); }
.bis__btn--go:hover { background: #D8BA80; border-color: #D8BA80; color: var(--midnight); }
.bis.is-running .bis__btn--go { opacity: 0.4; pointer-events: none; }
.bis__tag {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.55em; letter-spacing: 0.15em; text-transform: uppercase;
  padding: 0.36em 0.7em; border-radius: 999px;
  border: 1px solid rgba(201, 168, 106, 0.3);
  color: rgba(201, 168, 106, 0.85);
}

.bis__body {
  display: grid; grid-template-columns: 0.235fr 0.45fr 0.315fr;
  gap: 1.2em; padding: 0.95em 1.1em 1em; min-height: 0;
}
.bis__h {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.6em; letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5); margin-bottom: 0.5em; max-width: none;
}
.bis__sub {
  font-size: 0.62em; line-height: 1.5;
  color: rgba(255, 255, 255, 0.4); max-width: none; margin-bottom: 0.9em;
}

/* --- the knowledge layer ---------------------------------------------- */
.bis__know {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  padding-right: 1.2em; border-right: 1px solid rgba(255, 255, 255, 0.07);
}
.bis__kl {
  list-style: none; margin: 0; padding: 0;
  min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 0.24em;
  scrollbar-width: none;
}
.bis__kl::-webkit-scrollbar { width: 0; }
.bis__ki {
  border-left: 2px solid transparent;
  background: rgba(255, 255, 255, 0.02);
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.bis__ki.is-read { background: rgba(201, 168, 106, 0.08); border-left-color: var(--gold); }
.bis__ki.is-open { background: rgba(255, 255, 255, 0.05); border-left-color: rgba(201, 168, 106, 0.5); }
.bis__kb {
  width: 100%; display: grid; align-items: center;
  grid-template-columns: 1fr auto auto; gap: 0.5em;
  padding: 0.5em 0.6em; cursor: pointer;
  background: none; border: 0; text-align: left; font: inherit; color: inherit;
}
.bis__kb:focus-visible { outline: 1px solid var(--gold-40); outline-offset: -1px; }
.bis__kn {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.68em; color: var(--white);
}
.bis__km { font-size: 0.58em; color: rgba(255, 255, 255, 0.38); }
/* A chevron, and a plain arrow for the one entry that hands over instead of
   opening. The difference in the mark is the difference in the behaviour. */
.bis__kc {
  width: 0.32em; height: 0.32em;
  border-right: 1.2px solid rgba(255, 255, 255, 0.42);
  border-bottom: 1.2px solid rgba(255, 255, 255, 0.42);
  transform: rotate(45deg) translate(-0.06em, -0.06em);
  transition: transform var(--dur) var(--ease);
}
.bis__ki.is-open .bis__kc { transform: rotate(-135deg) translate(-0.1em, -0.1em); }
.bis__kj {
  width: 0.5em; height: 0.5em; position: relative;
}
.bis__kj::after {
  content: ""; position: absolute; inset: 0;
  border-right: 1.2px solid var(--gold); border-top: 1.2px solid var(--gold);
  transform: rotate(45deg) scale(0.7);
}
.bis__kd {
  max-height: 0; opacity: 0; overflow: hidden;
  padding: 0 0.6em;
  transition: max-height 420ms var(--ease), opacity 280ms var(--ease),
              padding 420ms var(--ease);
}
.bis__ki.is-open .bis__kd { max-height: 14em; opacity: 1; padding: 0 0.6em 0.7em; }
.bis__chips { display: flex; flex-wrap: wrap; gap: 0.26em; max-width: none; }
.bis__chips span {
  font-size: 0.58em; padding: 0.24em 0.5em; border-radius: 999px;
  background: rgba(201, 168, 106, 0.1); color: rgba(201, 168, 106, 0.9);
  border: 1px solid rgba(201, 168, 106, 0.22);
}
.bis__sw { display: flex; gap: 0.3em; max-width: none; }
.bis__sw i {
  width: 1.3em; height: 1.3em; border-radius: 0.2em;
  border: 1px solid rgba(255, 255, 255, 0.14);
}
.bis__rows { margin: 0; display: flex; flex-direction: column; gap: 0.3em; }
.bis__rows div { display: grid; grid-template-columns: 3.6em 1fr; gap: 0.5em; }
.bis__rows dt {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.57em; letter-spacing: 0.11em; text-transform: uppercase;
  color: rgba(201, 168, 106, 0.8); padding-top: 0.15em;
}
.bis__rows dd { margin: 0; font-size: 0.6em; color: rgba(255, 255, 255, 0.7); }
.bis__ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.28em; }
.bis__ul li {
  position: relative; padding-left: 0.8em;
  font-size: 0.6em; line-height: 1.45; color: rgba(255, 255, 255, 0.68);
}
.bis__ul li::before {
  content: ""; position: absolute; left: 0; top: 0.5em;
  width: 0.28em; height: 0.28em; border-radius: 50%; background: var(--gold-40);
}
.bis__kt {
  font-size: 0.56em; line-height: 1.5; margin-top: 0.5em;
  color: rgba(255, 255, 255, 0.38); max-width: none;
}
.bis__pin {
  margin-top: auto; padding-top: 0.9em;
  font-family: var(--ff-display); font-weight: 500;
  font-size: 0.72em; line-height: 1.35; color: rgba(255, 255, 255, 0.82);
  max-width: none;
}
.bis__pinl {
  display: block; font-weight: 600;
  font-size: 0.72em; letter-spacing: 0.13em; text-transform: uppercase;
  color: rgba(201, 168, 106, 0.85); margin-bottom: 0.45em;
}
.bis__kf {
  font-size: 0.56em; line-height: 1.5; margin-top: 0.8em;
  padding-top: 0.7em; border-top: 1px solid rgba(255, 255, 255, 0.07);
  color: rgba(255, 255, 255, 0.36); max-width: none;
}

/* --- the system ------------------------------------------------------- */
.bis__sys { display: flex; flex-direction: column; min-height: 0; min-width: 0; gap: 0.8em; }
.bis__ask { display: flex; align-items: center; gap: 0.7em; flex-wrap: wrap; }
.bis__askh {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.58em; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42); max-width: none;
}
.bis__objs { display: flex; gap: 0.35em; flex-wrap: wrap; }
.bis__obj {
  font-family: var(--ff-text); font-size: 0.6em;
  padding: 0.36em 0.72em; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.03); color: rgba(255, 255, 255, 0.62);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.bis__obj:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.36); }
.bis__obj:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 2px; }
.bis__obj.is-on {
  color: var(--midnight); background: var(--gold); border-color: var(--gold);
}

.bis__map { position: relative; flex: 1; min-height: 0; }
.bis__links { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; }
.bis__links line {
  stroke: rgba(255, 255, 255, 0.1); stroke-width: 1;
  transition: stroke 420ms var(--ease);
}
.bis__links line.is-done { stroke: rgba(201, 168, 106, 0.26); }
/* A dashed line running towards the module is the only way to show, without
   words, that the knowledge is what is moving. */
.bis__links line.is-live {
  stroke: rgba(201, 168, 106, 0.75); stroke-dasharray: 3 5;
  animation: bisFlow 900ms linear infinite;
}
@keyframes bisFlow { to { stroke-dashoffset: -16; } }

.bis__core {
  position: absolute; left: 50%; top: 50%; z-index: 2;
  transform: translate(-50%, -50%);
  width: 8.6em; height: 8.6em; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  border: 1px solid rgba(201, 168, 106, 0.42);
  background:
    radial-gradient(circle at 50% 36%, rgba(201, 168, 106, 0.14), rgba(201, 168, 106, 0) 68%),
    linear-gradient(180deg, #16233A, #0D1729);
  box-shadow: 0 0 0 0.5em rgba(201, 168, 106, 0.05),
              0 0 2.4em rgba(201, 168, 106, 0.14);
  transition: box-shadow 420ms var(--ease), border-color 420ms var(--ease);
}
.bis__core.is-live {
  border-color: var(--gold);
  box-shadow: 0 0 0 0.62em rgba(201, 168, 106, 0.1),
              0 0 3.4em rgba(201, 168, 106, 0.26);
}
.bis__corek {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.52em; letter-spacing: 0.17em; text-transform: uppercase;
  color: rgba(201, 168, 106, 0.8); margin-bottom: 0.5em;
}
.bis__coret {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.95em; letter-spacing: 0.02em; color: var(--white); line-height: 1.1;
}
.bis__coreb {
  font-family: var(--ff-display); font-weight: 500;
  font-size: 0.72em; color: rgba(255, 255, 255, 0.72); line-height: 1.1;
}
.bis__corem {
  font-size: 0.55em; color: rgba(255, 255, 255, 0.34);
  margin-top: 0.6em; padding-top: 0.5em;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.bis__mod {
  position: absolute; left: var(--x); top: var(--y); z-index: 2;
  transform: translate(-50%, -50%);
  width: 7.4em; padding: 0.44em 0.5em;
  display: flex; flex-direction: column; align-items: center; gap: 0.24em;
  border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 0.4em;
  background: linear-gradient(180deg, rgba(22, 35, 58, 0.92), rgba(13, 23, 41, 0.92));
  cursor: pointer; text-align: center;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.bis__mod:hover { border-color: rgba(255, 255, 255, 0.32); }
.bis__mod:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 2px; }
.bis__moddot {
  width: 0.3em; height: 0.3em; border-radius: 50%;
  background: rgba(255, 255, 255, 0.24);
  transition: background-color var(--dur) var(--ease);
}
.bis__modn {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.58em; letter-spacing: 0.05em; line-height: 1.25;
  color: rgba(255, 255, 255, 0.68);
  transition: color var(--dur) var(--ease);
}
.bis__mod.is-done { border-color: rgba(201, 168, 106, 0.4); }
.bis__mod.is-done .bis__moddot { background: var(--gold); }
.bis__mod.is-done .bis__modn { color: rgba(255, 255, 255, 0.86); }
.bis__mod.is-live {
  border-color: var(--gold); background: rgba(201, 168, 106, 0.14);
  box-shadow: 0 0 1.6em rgba(201, 168, 106, 0.22);
}
.bis__mod.is-live .bis__moddot { background: var(--gold); animation: agaPing 1.1s var(--ease) infinite; }
.bis__mod.is-live .bis__modn { color: var(--white); }
.bis__mod.is-picked { border-color: rgba(255, 255, 255, 0.42); }

.bis__note {
  font-size: 0.6em; line-height: 1.5; min-height: 2.9em;
  padding-top: 0.6em; border-top: 1px solid rgba(255, 255, 255, 0.07);
  color: rgba(255, 255, 255, 0.5); max-width: none;
  transition: color var(--dur) var(--ease);
}
.bis__note.is-hot { color: rgba(255, 255, 255, 0.78); }

.bis__spine {
  position: relative; list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(6, 1fr);
}
.bis__rail {
  position: absolute; left: 8.34%; right: 8.34%; top: 0.31em; height: 1px;
  background: rgba(255, 255, 255, 0.1);
}
.bis__rail i {
  display: block; height: 100%; width: 0%; background: var(--gold);
  transition: width 420ms var(--ease);
}
.bis__stg {
  display: flex; flex-direction: column; align-items: center; gap: 0.5em;
  opacity: 0.42; transition: opacity var(--dur) var(--ease);
}
.bis__stg.is-on, .bis__stg.is-done { opacity: 1; }
.bis__stgd {
  width: 0.62em; height: 0.62em; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.28); background: #0D1729;
  position: relative; z-index: 1;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.bis__stg.is-on .bis__stgd { border-color: var(--gold); box-shadow: 0 0 0 0.24em rgba(201, 168, 106, 0.16); }
.bis__stg.is-done .bis__stgd { background: var(--gold); border-color: var(--gold); }
.bis__stgn {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.57em; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
}
.bis__stg.is-on .bis__stgn { color: var(--gold); }

/* --- the work --------------------------------------------------------- */
.bis__work {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  padding-left: 1.2em; border-left: 1px solid rgba(255, 255, 255, 0.07);
}
.bis__tabs { display: flex; gap: 1em; margin-bottom: 0.8em; }
.bis__tab {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.58em; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 0 0 0.5em; cursor: pointer;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: rgba(255, 255, 255, 0.4);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.bis__tab:hover { color: rgba(255, 255, 255, 0.7); }
.bis__tab:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 2px; }
.bis__tab.is-on { color: var(--white); border-bottom-color: var(--gold); }
/* display:flex would otherwise win against the hidden attribute, and both
   panels would sit on top of each other. */
.bis__pane[hidden] { display: none; }
.bis__pane {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 0.6em;
  scrollbar-width: none;
}
.bis__pane::-webkit-scrollbar { width: 0; }
.bis__ph {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.58em; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5); max-width: none;
}
.bis__pf {
  font-size: 0.58em; line-height: 1.5;
  color: rgba(255, 255, 255, 0.36); max-width: none; margin-top: 0.3em;
}
.bis__recs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.42em; }
.bis__rec {
  display: grid; grid-template-columns: auto 1fr; gap: 0.5em; align-items: start;
  padding: 0.5em 0.6em; border-radius: 0.3em;
  border-left: 2px solid rgba(201, 168, 106, 0.4);
  background: rgba(255, 255, 255, 0.03);
}
.bis__rtag {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.54em; letter-spacing: 0.11em; text-transform: uppercase;
  color: rgba(201, 168, 106, 0.9); padding-top: 0.22em;
}
.bis__rtx { font-size: 0.6em; line-height: 1.45; color: rgba(255, 255, 255, 0.7); }

.bis__card {
  opacity: 0; transform: translateY(0.5em);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}
.bis__card.is-in { opacity: 1; transform: none; }
.bis__ch {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.55em; letter-spacing: 0.13em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45); margin-bottom: 0.45em; max-width: none;
}
.bis__brief { margin: 0; display: flex; flex-direction: column; gap: 0.25em;
  padding: 0.55em 0.7em; border-radius: 0.3em;
  background: rgba(255, 255, 255, 0.03);
  border-left: 2px solid rgba(255, 255, 255, 0.12);
}
.bis__brief div { display: grid; grid-template-columns: 5.4em 1fr; gap: 0.5em; }
.bis__brief dt {
  font-size: 0.57em; letter-spacing: 0.1em; text-transform: uppercase;
  font-family: var(--ff-display); font-weight: 600;
  color: rgba(255, 255, 255, 0.36); padding-top: 0.1em;
}
.bis__brief dd { margin: 0; font-size: 0.6em; color: rgba(255, 255, 255, 0.78); }

.bis__card--out {
  padding: 0.7em 0.8em; border-radius: 0.3em;
  background: linear-gradient(180deg, rgba(201, 168, 106, 0.08), rgba(201, 168, 106, 0.03));
  border: 1px solid rgba(201, 168, 106, 0.24);
}
.bis__ctype {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.55em; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 0.4em; max-width: none;
}
.bis__ctitle {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.78em; line-height: 1.25; color: var(--white);
  margin-bottom: 0.35em; max-width: none;
}
.bis__cbody { font-size: 0.62em; line-height: 1.5; color: rgba(255, 255, 255, 0.72); max-width: none; }

.bis__rev { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3em; }
.bis__rev li {
  display: grid; grid-template-columns: auto 4.2em 1fr; gap: 0.45em; align-items: baseline;
}
.bis__rev i {
  width: 0.6em; height: 0.6em; border-radius: 50%; background: var(--gold);
  position: relative; align-self: center;
}
.bis__rev i::after {
  content: ""; position: absolute; left: 0.19em; top: 0.11em;
  width: 0.13em; height: 0.26em;
  border-right: 1.2px solid #0D1729; border-bottom: 1.2px solid #0D1729;
  transform: rotate(42deg);
}
.bis__rev b {
  font-family: var(--ff-display); font-weight: 600;
  font-size: 0.57em; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
}
.bis__rev span { font-size: 0.6em; color: rgba(255, 255, 255, 0.52); }

.bis__types { display: flex; flex-wrap: wrap; gap: 0.3em; }
.bis__type {
  font-family: var(--ff-text); font-size: 0.58em;
  padding: 0.34em 0.62em; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.03); color: rgba(255, 255, 255, 0.6);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.bis__type:hover { color: var(--white); border-color: rgba(255, 255, 255, 0.36); }
.bis__type:focus-visible { outline: 1px solid var(--gold-40); outline-offset: 2px; }
.bis__type.is-on {
  color: var(--gold); border-color: var(--gold-40); background: rgba(201, 168, 106, 0.12);
}

@media (prefers-reduced-motion: reduce) {
  .bsn__hint-dot { animation: none; box-shadow: 0 0 0 0.28cqw rgba(201, 168, 106, 0.22); }
  .bis__links line.is-live { animation: none; stroke-dasharray: none; }
  .bis__mod.is-live .bis__moddot { animation: none; }
  .bis__card { opacity: 1; transform: none; transition: none; }
  .bis__kd { transition: none; }
}

/* ==========================================================================
   NARROW
   No photograph to keep, so the room becomes the page. The ring cannot
   survive at this width, so it stops being a ring: the core goes to the top
   and the seven modules become a grid under it, which is the same statement
   with the geometry taken out.
   ========================================================================== */
@media (max-width: 1100px) {
  .bsn__room { position: relative; inset: auto; padding-top: clamp(2.6rem, 8vw, 3.4rem); }
  .bsn { position: relative; inset: auto; }
  .bsn__key, .bsn__seam, .bsn__table, .bsn__cast, .bsn__cast--r { display: none; }
  .bsn::after { display: none; }
  .bsn__screen {
    position: relative; left: auto; top: auto; width: auto; height: auto;
    border-radius: 0; border-left: 0; border-right: 0; box-shadow: none;
  }
  .bis { position: relative; inset: auto; grid-template-rows: auto 1fr; }

  .bsn__hint {
    position: static; transform: none;
    margin: clamp(1.3rem, 4vw, 1.9rem) var(--pad) 0;
    gap: 0.55rem; padding: 0.44rem 0.85rem 0.44rem 0.7rem;
    font-size: clamp(0.62rem, 2.4vw, 0.72rem);
  }
  .bsn__hint-dot { width: 0.4rem; height: 0.4rem; }
  .bsn__hint.is-gone { transform: translateY(0.3rem); }

  /* The page comes off the wall and becomes what it already is. */
  .bsn__ptitle {
    position: static; width: auto;
    margin: clamp(2rem, 6vw, 2.8rem) var(--pad) 0;
    font-size: clamp(0.66rem, 2.5vw, 0.78rem); text-align: center;
  }
  .bsn__phone {
    position: relative; left: auto; top: auto; height: auto;
    width: min(310px, 74vw); aspect-ratio: 9 / 19.5;
    margin: clamp(0.9rem, 3vw, 1.2rem) auto 0;
    padding: 6px; border-radius: 30px; box-shadow: none;
    border: 1px solid rgba(255, 255, 255, 0.1);
  }
  .bsg { inset: 6px; border-radius: 25px; font-size: clamp(11px, 4.6cqw, 14px); }
  .bsn__pnote {
    position: static; width: auto;
    margin: clamp(1rem, 3.4vw, 1.4rem) auto 0;
    max-width: 30rem; padding: 0 var(--pad);
    font-size: clamp(0.78rem, 3vw, 0.88rem);
  }

  .bsc { position: static; padding: clamp(1.6rem, 5vw, 2.6rem) var(--pad) clamp(2rem, 6vw, 3rem); }
  .bsc__eyebrow { font-size: clamp(0.72rem, 2.6vw, 0.86rem); margin-bottom: 0.9rem; }
  .bsc__h { font-size: clamp(1.35rem, 5.4vw, 1.9rem); margin-bottom: 0.7rem; }
  .bsc__lead { font-size: clamp(0.86rem, 3.4vw, 1rem); margin-bottom: 1.8rem; }
  .bsc__pts { grid-template-columns: 1fr; gap: 1.4rem; max-width: none; }
  .bsc__n { font-size: 0.7rem; margin-bottom: 0.35rem; }
  .bsc__t { font-size: 0.78rem; margin-bottom: 0.3rem; }
  .bsc__d { font-size: 0.82rem; }
}

/* The display is 60% of the room, so at the narrowest desktop it is about
   650px; this has to sit below that or the three columns collapse while the
   room is still a room. */
@container (max-width: 620px) {
  .bis { font-size: clamp(9px, 2.15cqw, 13px); }
  .bis__bar { flex-wrap: wrap; padding: 0.6em 0.9em; gap: 0.6em; }
  .bis__subject, .bis__tag { display: none; }
  .bis__body { grid-template-columns: 1fr; gap: 1.3em; padding: 1em 0.9em 1.2em; }

  .bis__sys { order: 1; }
  .bis__know {
    order: 2; padding-right: 0; border-right: 0;
    padding-top: 1.1em; border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
  .bis__work {
    order: 3; padding-left: 0; border-left: 0;
    padding-top: 1.1em; border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
  .bis__kl { overflow: visible; }

  .bis__map { position: static; display: grid; grid-template-columns: 1fr 1fr; gap: 0.5em; }
  .bis__links { display: none; }
  .bis__core {
    position: static; transform: none;
    grid-column: 1 / -1; width: auto; height: auto;
    border-radius: 0.5em; padding: 1em; margin-bottom: 0.3em;
    box-shadow: none;
  }
  .bis__mod {
    position: static; transform: none; width: auto;
    flex-direction: row; justify-content: center; gap: 0.45em;
    padding: 0.6em 0.5em;
  }
  /* The two line labels exist to keep the chips narrow on the ring; in a
     grid they can just be sentences again. */
  .bis__mod br { display: none; }
  .bis__mod:last-of-type { grid-column: 1 / -1; }
  .bis__note { min-height: 0; }
  .bis__spine { grid-template-columns: repeat(3, 1fr); row-gap: 0.9em; }
  .bis__rail { display: none; }
  .bis__pane { overflow: visible; }
}
