/* =========================================================================
 * Testimonial Carousel (Coverflow) — flat, single-screen rebuild.
 *
 * Replaces the old CSS-3D "corridor" walkthrough entirely. No 3D rooms,
 * no translateZ depth-scroll, no preserve-3d plane geometry — just a flat
 * row of cards, offset/scaled/dimmed by distance from the centre via plain
 * 2D transforms (translateX + scale) and opacity, computed in JS from
 * scroll progress (corridor-cards-widget.js). That removes the entire
 * class of flicker/repaint-lag bug the old 3D version had: there's no
 * heavy background-image plane being pushed through 3D space every scroll
 * frame, so there's nothing to visibly lag behind or flicker.
 *
 * The one 3D touch kept from the old version is the "Look Around" mouse/
 * touch tilt — a single subtle perspective rotation on .atc-stage (the
 * whole carousel), driven only by pointer movement, never by scroll. It's
 * cheap (one element, one transform, updates only on pointermove) and
 * fully decoupled from the scroll-driven coverflow logic below it.
 *
 * "Room Backdrop" (2.1.0) — an OPTIONAL, purely flat/2D decorative layer
 * behind the cards: a hologram-style full-bleed background plus ceiling/
 * floor/wall panel images, each just a positioned <div> with a
 * background-image, faded into the scene with a CSS mask-image gradient.
 * No translateZ, no perspective, nothing re-painted on scroll or pointer
 * move — it's static once laid out, so it can't reintroduce the old
 * corridor's flicker/repaint-lag bug. Markup renders nothing for this
 * layer unless the widget's "Enable Room Backdrop" switch is on AND at
 * least one image is set, so existing instances are unaffected.
 * ========================================================================= */

/* Elementor's Flexbox containers (flex-direction:column + a non-"stretch"
 * align-items) size a flex child to its own in-flow content. Every card
 * here is position:absolute (so the coverflow transforms can offset them
 * freely), which means the widget has zero in-flow content and would
 * otherwise collapse to 0 width before GSAP's ScrollTrigger pins it and
 * bakes that 0px into an inline style. Forcing the wrapper to stretch/fill
 * here, ahead of the pin, is what stops that collapse at its source. */
.elementor-widget-aidem_corridor_testimonials {
  width: 100%;
  align-self: stretch;
}
.elementor-widget-aidem_corridor_testimonials > .elementor-widget-container {
  width: 100%;
}

.atc-scene {
  --atc-card-bg: #11151c;
  --atc-quote-color: #b7d4e8;
  --atc-name-color: #eaf6ff;
  --atc-role-color: #eaf6ff;
  --atc-company-color: #8C5FF5;
  --atc-dot-color: rgba(255, 255, 255, 0.3);
  --atc-dot-active-color: #8C5FF5;
  --atc-perspective-px: 1400px;
  /* Room Backdrop defaults — only ever visible when the widget actually
     renders a .atc-room layer (markup-gated in PHP), but declared here so
     the Style tab's sliders always have something sane to override. */
  --atc-room-hologram-opacity: 0.5;
  --atc-room-wall-width: 16%;
  --atc-room-wall-opacity: 0.55;
  /* svh keeps this fixed as a mobile browser's address bar shows/hides
     mid-scroll — plain vh visibly jumps/resizes in that situation. The
     second declaration overrides the first only where svh is supported
     and is simply invalid (ignored) where it isn't — a safe fallback
     chain, not a browser check. */
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: #0a0b0e;
  /* Added for the optional Section Heading & Subtitle block below. Safe
     with no visual effect on .atc-room/.atc-stage: both are
     position:absolute; inset:0, and an absolutely-positioned element
     takes no part in its parent's flex layout at all (per spec) — they
     keep covering the full scene exactly as before. This only affects
     .atc-heading-wrap, the one new element that's actually in normal
     flow, pushing it to the top instead of overlapping row 1 of nothing. */
  display: flex;
  flex-direction: column;
}

/* When this widget sits inside the theme's sticky-header-clearance wrapper
   (.hero-behind-header-pinned / .pin-hero-header-safe — same class the
   pin-offset fix in corridor-cards-widget.js reads via --aidem-header-h /
   --aidem-header-live-h / --aidem-adminbar-h), that wrapper adds a
   padding-top equal to the header's height so the heading doesn't render
   behind the fixed header. But .atc-scene is ALSO a fixed 100vh/100svh
   tall box, so with that padding added on top of it, the scene's total
   rendered height (padding + 100vh) becomes taller than the viewport —
   its bottom edge (and the dots 6% up from that bottom, see .atc-dots
   below) gets pushed below the fold, invisible until the user scrolls
   further into the pin.
   Fix: shrink the scene's own height by exactly the same header-clearance
   amount the ancestor's padding-top already added, so "padding-top +
   this height" always equals exactly 100vh/100svh again — the scene's
   bottom (and the dots) line up flush with the actual viewport bottom,
   with nothing hidden below the fold. Scoped to ONLY this ancestor
   (rather than changing the base .atc-scene rule above) so a placement of
   this widget NOT inside that header-clearance wrapper is unaffected and
   keeps its full 100vh/100svh height exactly as before. */
.hero-behind-header-pinned .atc-scene,
.pin-hero-header-safe .atc-scene {
  height: calc(100vh - (max(var(--aidem-header-h, 0px), var(--aidem-header-live-h, 0px)) + var(--aidem-adminbar-h, 0px)));
  height: calc(100svh - (max(var(--aidem-header-h, 0px), var(--aidem-header-live-h, 0px)) + var(--aidem-adminbar-h, 0px)));
}

/* ── Header underlay mode (frontend pin only) ──────────────────────────
   corridor-cards-widget.js adds .atc-room-underlay and sets
   --atc-pin-offset (= the fixed header's height) when this scene is the
   first thing on the page. The pin holds the scene that many px below the
   viewport top so the heading and cards clear the header; this mode makes
   the page look the way the Elementor editor (no pin, scene flush with the
   top) shows it:

   1. The scene is shortened to (100svh - header) so, pinned at the header's
      bottom edge, its bottom meets the bottom of the screen exactly — no
      overhang below the fold, so no flat-colour band appears under the
      backdrop when the pin releases.
   2. The Room Backdrop is stretched UP behind the header (top: -header,
      bottom: 0), i.e. exactly one viewport tall (100svh), so the image is
      framed the same as in the editor: size it for the viewport
      (e.g. 2560x1440). overflow:hidden is swapped for a clip-path that is
      identical on the left/right/bottom and only opens the top edge by the
      header height. background-color:inherit gives the extension the
      scene's own dark fill so the hologram's "screen" blend is unchanged.
   3. Heading, cards and dots fold the pin offset into the same Vertical
      Offsets you set in the editor, so they land where the editor shows
      them at EVERY breakpoint (set once on desktop, inherited everywhere,
      overridable per breakpoint). The scene is now (header) lower but
      (header) shorter, so its centre is only header/2 lower than the
      editor's — hence the cards/dots use pin/2, the heading (top-anchored)
      uses the full pin. Horizontal offsets are untouched. */
.atc-scene.atc-room-underlay {
  overflow: visible;
  clip-path: inset(calc(-1 * var(--atc-pin-offset, 0px)) 0 0 0);
  height: calc(100vh - var(--atc-pin-offset, 0px));
  height: calc(100svh - var(--atc-pin-offset, 0px));
}

.atc-scene.atc-room-underlay > .atc-room {
  top: calc(-1 * var(--atc-pin-offset, 0px));
  bottom: 0;
  background-color: inherit;
}

.atc-scene.atc-room-underlay .atc-heading-wrap {
  transform: translate(
    var(--atc-heading-offset-x, 0px),
    calc(var(--atc-heading-offset-y, 0px) - var(--atc-pin-offset, 0px))
  );
}

.atc-scene.atc-room-underlay .atc-card {
  top: calc(50% + var(--atc-card-offset-y, 0px) - (var(--atc-pin-offset, 0px) / 2));
}

.atc-scene.atc-room-underlay .atc-dots {
  top: calc(50% + var(--atc-card-offset-y, 0px) + (var(--atc-cards-h, 580px) * 0.53) + var(--atc-dots-gap, 14px) - (var(--atc-pin-offset, 0px) / 2));
}

/* ── Section Heading & Subtitle (optional, off by default) ──────────────
   The only in-flow child of .atc-scene — everything else (.atc-room,
   .atc-stage) is position:absolute and ignores this box entirely. Needs
   its own stacking context (position:relative + z-index) specifically
   because .atc-room/.atc-stage, being positioned elements, would
   otherwise paint ON TOP of this plain in-flow block regardless of DOM
   order (that's how CSS stacking works for positioned vs. static
   elements) — without this it would render, just invisibly, behind the
   cards. */
.atc-heading-wrap {
  position: relative;
  z-index: 5;
  flex: 0 0 auto;
  width: 100%;
  box-sizing: border-box;
  /* Same architecture as the proven-working Text Overlay widget's
     .ato-content: a flex column with `gap` for the space BETWEEN the
     heading and subtitle. Flex children never margin-collapse with each
     other or with this container, so there is nothing left to fight —
     no !important, no flow-root hack needed. subtitle_gap (Style →
     Section Subtitle) now writes this `gap`, not a margin-bottom. */
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: clamp(24px, 6vh, 56px) 24px 0;
  gap: 12px;
  /* heading_gap (Style → Section Heading → Space Below Heading Block)
     writes margin-bottom directly on THIS element — the space between
     the whole heading+subtitle block and the cards below it. 32px here
     is just the pre-Elementor-CSS fallback. */
  margin-bottom: 32px;
  text-align: center;
  pointer-events: none;
  /* Per-breakpoint Horizontal/Vertical Offset controls (Style tab) write
     these two vars. A transform (not margin/top/left) so nudging this
     never changes the space it reserves in .atc-scene's flex column —
     .atc-stage below still gets exactly the gap set by heading_gap,
     regardless of how far this is visually shifted. */
  transform: translate(var(--atc-heading-offset-x, 0px), var(--atc-heading-offset-y, 0px));
}

.atc-heading-wrap { position: relative; z-index: 3; }

.atc-heading {
  margin: 0;
  font-weight: 800;
  font-size: clamp(2rem, 1.4rem + 3vw, 4.5rem);
  /* !important: the site's global Kit CSS (.elementor-kit-7703 h2) also
     targets every <h2>, including this one, with a line-height tuned for
     16-38px body headings (currently a "1.9lh" fluid value). That rule is
     MORE specific than our plain .atc-heading class selector, so without
     !important it silently wins for just this one property, leaving the
     glyphs far taller than the line box at our much larger display sizes
     and making the heading visually bleed into its own bottom margin. */
  line-height: 0.95 !important;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  /* !important: same leak as line-height above, different property. The
     site's global Kit CSS (.elementor-kit-7703 h2 { color: var(--e-global-
     color-primary); }) is more specific (tag+class, 0,1,1) than our plain
     .atc-heading class selector (0,1,0), so it silently wins the `color`
     property — the Fill Colour control (heading_color) writes the
     --atc-heading-color variable correctly, but the Kit rule's own color
     value was rendering instead of it. Confirmed live via cascade
     inspection: computed color was the Kit's black/primary, not the
     control's value, even though the CSS var itself was set correctly. */
  color: var(--atc-heading-color, #8C5FF5) !important;
  -webkit-text-stroke-width: 0;
  -webkit-text-stroke-color: var(--atc-heading-stroke-color, #8855ff);
}

/* Stroke mode: transparent fill so only the outline is visible — same
   technique as the site's Stroke Title widget (.ast-title--stroke). */
.atc-heading--stroke {
  -webkit-text-fill-color: transparent;
  -webkit-text-stroke-width: var(--atc-heading-stroke-width, 2px);
}

.atc-subtitle {
  margin: 0;
  font-size: clamp(1rem, 0.85rem + 0.6vw, 1.35rem);
  font-weight: 400;
  /* !important for the same reason as .atc-heading above: nothing here
     previously set line-height at all, so this element was inheriting a
     mismatched value from elsewhere on the page rather than scaling with
     its own font-size. 1.3 is a normal, readable ratio for body/subtitle
     text and is pinned so no future global style change can reintroduce
     the same silent mismatch. */
  line-height: 1.3 !important;
  color: var(--atc-subtitle-color, #b7d4e8);
}

/* ── Subtitle as a HUD label (Style → Section Subtitle → Subtitle Style) ──
   A compact, glowing monospace tag in the style of the Brand Strip HUD
   labels: uppercase Courier, glow text-shadow, hairline border with optional
   corner brackets. Single-class
   selectors on purpose, so Elementor's own Typography / Alignment controls
   (higher specificity) still override them. */
.atc-subtitle--hud {
  font-family: "Courier New", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--atc-hl-ls, 0.18em);
}
.atc-subtitle--hud .atc-subtitle__box {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  width: var(--atc-hl-w, auto);
  max-width: 100%;
  box-sizing: border-box;
  font-size: 13px;
  line-height: 1.1;
  color: var(--atc-hl-color, #60ff18);
  background: var(--atc-hl-bg, rgba(0, 0, 0, 0.38));
  border: var(--atc-hl-bw, 2px) solid var(--atc-hl-border, #60ff18);
  border-radius: var(--atc-hl-radius, 0px);
  padding: 8px 18px;
  /* Mirrors the Brand Strip HUD terminal: green text glow + inset line + outer glow */
  text-shadow: 0 0 var(--atc-hl-glow, 8px) color-mix(in srgb, var(--atc-hl-color, #60ff18) 50%, transparent);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--atc-hl-color, #60ff18) 24%, transparent),
    0 0 14px color-mix(in srgb, var(--atc-hl-color, #60ff18) 22%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.atc-subtitle--hud .atc-subtitle__text { min-width: 0; overflow-wrap: anywhere; }
.atc-subtitle--hud .atc-subtitle__box.has-brackets::before,
.atc-subtitle--hud .atc-subtitle__box.has-brackets::after {
  content: "";
  position: absolute;
  width: 9px;
  height: 9px;
  pointer-events: none;
  display: var(--atc-hl-brk, block);
  border: 0 solid var(--atc-hl-color, #60ff18);
}
.atc-subtitle--hud .atc-subtitle__box.has-brackets::before {
  top: -4px; left: -4px;
  border-top-width: 2px; border-left-width: 2px;
}
.atc-subtitle--hud .atc-subtitle__box.has-brackets::after {
  bottom: -4px; right: -4px;
  border-bottom-width: 2px; border-right-width: 2px;
}
/* CRT typing */
.atc-subtitle--hud .atc-type-rest { visibility: hidden; }
.atc-subtitle--hud .atc-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Room Backdrop ────────────────────────────────────────────────────── */
/* All panels are plain position:absolute 2D layers, stacked below
   .atc-stage purely by DOM order (this block is written before .atc-stage
   in the widget's markup — see class-aidem-corridor-testimonials-widget.php
   — so with neither element setting z-index, .atc-stage simply paints on
   top). No transform, no animation, nothing JS ever touches here: it's
   laid out once by the browser and left alone, which is what keeps it
   free of the old 3D corridor's per-frame repaint cost. */
.atc-room {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.atc-room > div {
  position: absolute;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.atc-room-hologram {
  inset: 0;
  opacity: var(--atc-room-hologram-opacity);
  /* "screen" blend lets a dark hologram/grid graphic's black areas
     disappear into .atc-scene's own dark background instead of showing
     as a hard-edged rectangle. */
  mix-blend-mode: screen;
}

/* ── Card Backdrop (Style → Card Backdrop) ─────────────────────────────
   A single STATIC panel behind the centred card: either an accent-colour
   panel with blurred speech-bubble icons (same idea as the Testimonial
   Carousel's coloured back card) or a blurred "HUD" activity window. It sits
   at the cards' centre, is painted below .atc-stage purely by DOM order,
   never zooms or moves, and its optional animation is a slow opacity fade
   only, disabled under prefers-reduced-motion. Colour follows the active
   card's accent (--atc-active-accent, set by JS) unless a custom colour is set. */
.atc-backing {
  --atc-c: var(--atc-backing-color, var(--atc-active-accent, #8C5FF5));
  position: absolute;
  z-index: 0;
  top: calc(50% + var(--atc-card-offset-y, 0px) + var(--atc-backing-y, 0px));
  left: calc(50% + var(--atc-card-offset-x, 0px) + var(--atc-backing-x, 0px));
  width: var(--atc-backing-w, calc(min(80vw, var(--atc-card-w, 380px)) * 1.08));
  height: var(--atc-backing-h, calc(var(--atc-cards-h, 560px) * 1.08));
  transform: translate(-50%, -50%);
  border-radius: var(--atc-backing-radius, 28px);
  opacity: var(--atc-backing-opacity, 0.8);
  overflow: hidden;
  pointer-events: none;
  transition: background-color 0.6s ease;
}

.atc-scene.atc-room-underlay .atc-backing {
  top: calc(50% + var(--atc-card-offset-y, 0px) + var(--atc-backing-y, 0px) - (var(--atc-pin-offset, 0px) / 2));
}

/* Colour Panel Pulse: accent-coloured glowing panel behind the card.
   The pulse (opacity) is applied by .atc-backing--anim below. */
.atc-backing--speech {
  overflow: visible;
  background:
    linear-gradient(145deg,
      color-mix(in srgb, var(--atc-c) 85%, transparent),
      color-mix(in srgb, var(--atc-c) 35%, #05060a));
  box-shadow:
    0 0 var(--atc-backing-glow, 40px) color-mix(in srgb, var(--atc-c) 55%, transparent),
    inset 0 0 calc(var(--atc-backing-glow, 40px) * 0.6) color-mix(in srgb, var(--atc-c) 30%, transparent);
}

/* HUD: blurred glow window with grid, corner brackets and data bars */
.atc-backing--hud {
  overflow: visible;
  border: 1px solid color-mix(in srgb, var(--atc-c) 55%, transparent);
  background:
    radial-gradient(ellipse at 50% 50%, color-mix(in srgb, var(--atc-c) 38%, transparent), transparent 72%),
    repeating-linear-gradient(0deg, color-mix(in srgb, var(--atc-c) 16%, transparent) 0 1px, transparent 1px 16px),
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--atc-c) 16%, transparent) 0 1px, transparent 1px 16px),
    color-mix(in srgb, var(--atc-c) 8%, transparent);
  box-shadow:
    0 0 var(--atc-backing-glow, 40px) color-mix(in srgb, var(--atc-c) 45%, transparent),
    inset 0 0 calc(var(--atc-backing-glow, 40px) * 0.8) color-mix(in srgb, var(--atc-c) 22%, transparent);
  filter: blur(var(--atc-backing-hud-blur, 2px));
}
.atc-backing--hud::before {
  content: "";
  position: absolute;
  inset: 12px;
  background:
    linear-gradient(var(--atc-c), var(--atc-c)) 0 0 / 22px 2px no-repeat,
    linear-gradient(var(--atc-c), var(--atc-c)) 0 0 / 2px 22px no-repeat,
    linear-gradient(var(--atc-c), var(--atc-c)) 100% 0 / 22px 2px no-repeat,
    linear-gradient(var(--atc-c), var(--atc-c)) 100% 0 / 2px 22px no-repeat,
    linear-gradient(var(--atc-c), var(--atc-c)) 0 100% / 22px 2px no-repeat,
    linear-gradient(var(--atc-c), var(--atc-c)) 0 100% / 2px 22px no-repeat,
    linear-gradient(var(--atc-c), var(--atc-c)) 100% 100% / 22px 2px no-repeat,
    linear-gradient(var(--atc-c), var(--atc-c)) 100% 100% / 2px 22px no-repeat;
  opacity: 0.85;
}
.atc-backing--hud::after {
  content: "";
  position: absolute;
  left: 9%;
  right: 9%;
  bottom: 9%;
  height: 22%;
  background:
    linear-gradient(90deg, var(--atc-c) 0 62%, transparent 62%) 0 0 / 100% 5px no-repeat,
    linear-gradient(90deg, var(--atc-c) 0 38%, transparent 38%) 0 50% / 100% 5px no-repeat,
    linear-gradient(90deg, var(--atc-c) 0 78%, transparent 78%) 0 100% / 100% 5px no-repeat;
  opacity: 0.5;
}

/* Backdrop pulse (speech + HUD): whole-panel opacity breathes in place.
   Speed / depth / timing / start delay are Elementor controls. */
@keyframes atc-backing-fade {
  0%, 100% { opacity: var(--atc-backing-opacity, 0.8); }
  50%      { opacity: calc(var(--atc-backing-opacity, 0.8) * (1 - var(--atc-backing-depth, 0.5))); }
}
.atc-backing--anim {
  animation: atc-backing-fade var(--atc-backing-dur, 4s) var(--atc-backing-ease, ease-in-out) var(--atc-backing-delay, 0s) infinite;
}

/* HUD border light: a glowing comet that runs all the way round the border.
   A conic-gradient is masked down to a thin ring; the registered angle
   property is animated for the lap, opacity for the pulse. */
@property --atc-orbit-a {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.atc-backing-orbit {
  --oc: var(--atc-orbit-color, var(--atc-backing-color, var(--atc-active-accent, #8C5FF5)));
  position: absolute;
  z-index: 0;
  top: calc(50% + var(--atc-card-offset-y, 0px) + var(--atc-backing-y, 0px));
  left: calc(50% + var(--atc-card-offset-x, 0px) + var(--atc-backing-x, 0px));
  width: var(--atc-backing-w, calc(min(80vw, var(--atc-card-w, 380px)) * 1.08));
  height: var(--atc-backing-h, calc(var(--atc-cards-h, 560px) * 1.08));
  transform: translate(-50%, -50%);
  box-sizing: border-box;
  border-radius: var(--atc-backing-radius, 28px);
  padding: var(--atc-orbit-w, 3px);
  pointer-events: none;
  background: conic-gradient(from var(--atc-orbit-a),
    transparent 0,
    transparent calc(100% - var(--atc-orbit-len, 35%)),
    var(--oc) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  filter: drop-shadow(0 0 var(--atc-orbit-glow, 12px) var(--oc));
}
.atc-scene.atc-room-underlay .atc-backing-orbit {
  top: calc(50% + var(--atc-card-offset-y, 0px) + var(--atc-backing-y, 0px) - (var(--atc-pin-offset, 0px) / 2));
}
@keyframes atc-orbit-spin  { to { --atc-orbit-a: 360deg; } }
@keyframes atc-orbit-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: var(--atc-orbit-pulse-min, 0.4); }
}
.atc-backing-orbit--spin {
  animation: atc-orbit-spin var(--atc-orbit-speed, 8s) linear infinite;
  animation-direction: var(--atc-orbit-dir, normal);
}
.atc-backing-orbit--pulse {
  animation: atc-orbit-pulse var(--atc-orbit-pulse-dur, 2s) ease-in-out infinite;
}
.atc-backing-orbit--spin.atc-backing-orbit--pulse {
  animation:
    atc-orbit-spin var(--atc-orbit-speed, 8s) linear infinite var(--atc-orbit-dir, normal),
    atc-orbit-pulse var(--atc-orbit-pulse-dur, 2s) ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .atc-backing--anim,
  .atc-backing-orbit--spin,
  .atc-backing-orbit--pulse { animation: none !important; }
}

.atc-room-wall {
  top: 0;
  bottom: 0;
  width: var(--atc-room-wall-width);
  opacity: var(--atc-room-wall-opacity);
}

.atc-room-wall--left {
  left: 0;
  -webkit-mask-image: linear-gradient(to right, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
  mask-image: linear-gradient(to right, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
}

.atc-room-wall--right {
  right: 0;
  -webkit-mask-image: linear-gradient(to left, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
  mask-image: linear-gradient(to left, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
}

.atc-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: var(--atc-perspective-px);
  /* The tilt transform (rotateX/rotateY) is set directly here by JS on
     pointermove only — no CSS transition, so it never fights a continuous
     stream of updates; JS already lerps toward the target itself. */
}

.atc-track {
  position: relative;
  width: 100%;
  height: 100%;
}

/* ── Cards ────────────────────────────────────────────────────────────── */

.atc-card {
  position: absolute;
  /* Style → Card Style → Cards Horizontal/Vertical Offset write
     --atc-card-offset-x/-y on .atc-scene. Deliberately applied to top/left
     (the anchor point), NOT transform: corridor-cards-widget.js's
     applyCoverflow() sets this element's inline `transform` fresh on every
     scroll-progress tick (translate(-50%,-50%) translateX(...) scale(...)),
     which would instantly stomp any transform-based offset set here. top/
     left are never touched by that JS, so the offset always sticks. */
  top: calc(50% + var(--atc-card-offset-y, 0px));
  left: calc(50% + var(--atc-card-offset-x, 0px));
  width: min(80vw, 380px);
  /* Was a fixed `aspect-ratio: 3/4`, which forces every card to exactly
     the same height regardless of how long its quote is — a short quote
     left empty space, a long one got hard-clipped by overflow:hidden
     below (and by -webkit-line-clamp, now removed from .atc-card-quote).
     min-height keeps short-quote cards looking like a proper card at the
     old 3:4 proportions; height:auto then lets the card grow taller for
     a longer quote instead of truncating it; max-height is just a safety
     ceiling so one freak extra-long quote can't blow the card off-screen. */
  /* Fit-to-screen: the card (x1.08 active-card scale) plus the dots row
     below it must always fit inside the scene, which is one screen tall
     minus the sticky header. Without this, on phones/tablets the bottom of
     the card (name / role / company) and the dots were cut off.
     min-height follows the per-breakpoint Card Width (--atc-card-w) and is
     capped by the same fit-to-screen limit, so min can never beat max. */
  --atc-fit-h: calc((100vh - var(--aidem-header-h, 80px) - 76px) / 1.08);
  --atc-fit-h: calc((100svh - var(--aidem-header-h, 80px) - 76px) / 1.08);
  min-height: min(calc(min(80vw, var(--atc-card-w, 380px)) * 4 / 3), var(--atc-fit-h));
  height: auto;
  max-height: var(--atc-fit-h);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* flex-start, not center: when aspect-ratio + max-height make the card
     shorter than its content needs, centering clips the overflow off BOTH
     the top and bottom equally — on a short/wide viewport that silently
     chops off the logo and quote (the top of the stack) while leaving
     name/role/company (the bottom) visible, which is exactly the "no
     quote, blank logo" bug this replaces. Top-aligning means any overflow
     is confined to the bottom, and the quote area below (flex: 1 1 auto;
     min-height: 0) is the one piece designed to shrink/clip first. */
  justify-content: flex-start;
  text-align: center;
  /* NOT a percentage: .atc-card is position:absolute, and percentage
     padding on an absolutely-positioned element resolves against its
     CONTAINING BLOCK's width (the full-width .atc-stage, ~1900px+ on a
     desktop monitor) — never against the card's own width (capped at
     380px above). "padding: 8%" was computing to ~150px+ per side on
     wide screens, crushing the card's content column down to ~80px
     wide, which is what was really starving the logo/quote/company of
     space (not a flex-shrink issue). clamp() with vw is viewport-wide
     too, but it's bounded, so it can only ever land in the 14–30px
     range this design wants, matching roughly what 8% of a 380px-wide
     card looked like at the sizes this was designed and tested at. */
  padding: clamp(14px, 8vw, 30px);
  border-radius: 14px;
  background: var(--atc-card-bg);
  border: 1px solid color-mix(in srgb, var(--atc-accent, #8C5FF5) 35%, transparent);
  box-shadow:
    0 20px 60px rgba(0, 0, 0, 0.45),
    inset 0 0 0 1px rgba(255, 255, 255, 0.03);
  overflow: hidden;
  /* translateX/scale/opacity/z-index are all set inline by JS every
     tick — no CSS transition here either, for the same reason as
     .atc-stage above: it needs to track scroll progress exactly. */
}

.atc-card.is-active {
  border-color: color-mix(in srgb, var(--atc-accent, #8C5FF5) 70%, transparent);
  box-shadow:
    0 24px 70px rgba(0, 0, 0, 0.55),
    0 0 50px color-mix(in srgb, var(--atc-accent, #8C5FF5) 25%, transparent),
    inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}

/* ── Apple-style "Liquid Glass" card (Style → Card Style → Apple Liquid
   Glass, off by default) ─────────────────────────────────────────────────
   Swaps the flat solid .atc-card-bg background for a translucent, blurred
   "glass" material in the current Apple (iOS/visionOS) design language:
   a frosted backdrop-blur + saturation boost so whatever's behind the card
   (other coverflow cards, the Room Backdrop layer) reads as softly diffused
   colour through the card rather than a flat tint; a faint white tint
   gradient (brighter top-left, the way light catches curved glass) instead
   of one flat colour; a bright hairline rim border so the glass edge
   actually reads against a dark page; and a much larger border-radius —
   Apple's liquid glass language is characterised by very generous, almost
   pill-like rounding, not the 14px our flat cards use. ::before adds the
   soft diagonal specular "sheen" highlight real glass/metal catches near
   its top edge; mix-blend-mode: overlay lets it brighten without ever
   fully whiting-out the content or the glass tint beneath it. -webkit-
   backdrop-filter is required for Safari (no un-prefixed support yet as of
   writing); where backdrop-filter isn't supported at all, @supports not
   falls back to a flat translucent tint so the card still reads instead of
   going invisible. */
.atc-card.apple-liquid-glass {
  background: linear-gradient(
    165deg,
    color-mix(in srgb, white 16%, transparent),
    color-mix(in srgb, white 5%, transparent)
  );
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  backdrop-filter: blur(24px) saturate(180%);
  /* Border + glow follow the card's accent colour exactly like the default
     (no-class) card. !important is needed because the theme/kit global
     .apple-liquid-glass rule sets border and box-shadow with !important. */
  border: 1px solid color-mix(in srgb, var(--atc-accent, #8C5FF5) 35%, transparent) !important;
  box-shadow:
    0 20px 60px rgba(0, 0, 0, 0.45),
    inset 0 0 0 1px rgba(255, 255, 255, 0.03) !important;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .atc-card.apple-liquid-glass {
    background: linear-gradient(
      165deg,
      color-mix(in srgb, var(--atc-card-bg, #11151c) 80%, white 16%),
      var(--atc-card-bg, #11151c)
    );
  }
}

/* The theme/kit global .apple-liquid-glass rule forces
   position: relative !important and z-index: 1 !important, which would drop
   the cards out of the absolute coverflow stack. Re-assert them here with
   higher specificity (also !important). z-index is set inline by JS with
   !important too. */
.atc-scene .atc-track .atc-card.apple-liquid-glass,
.atc-scene .atc-card.apple-liquid-glass {
  position: absolute !important;
}

.atc-card.apple-liquid-glass::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    120deg,
    rgba(255, 255, 255, 0.35),
    rgba(255, 255, 255, 0) 40%
  );
  mix-blend-mode: overlay;
  pointer-events: none;
}

.atc-scene .atc-card.apple-liquid-glass.is-active {
  border-color: color-mix(in srgb, var(--atc-accent, #8C5FF5) 70%, transparent) !important;
  box-shadow:
    0 24px 70px rgba(0, 0, 0, 0.55),
    0 0 50px color-mix(in srgb, var(--atc-accent, #8C5FF5) 25%, transparent),
    inset 0 0 0 1px rgba(255, 255, 255, 0.05) !important;
}

/* White rounded "chip" behind the logo — most client logos are drawn in
   dark/colour ink on a transparent background, so they need a light
   backing to read clearly against this dark card. */
.atc-card-logo {
  /* Shows the uploaded image exactly as-is (pre-made circular logos): no
     background, no crop, no shadow. Shape / fit / background / border are
     optional overrides in Style → Card Logo. */
  display: block;
  width: 72px;
  height: 72px;
  object-fit: contain;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  box-sizing: border-box;
  padding: 0;
  margin: 0 auto 1em;
  flex-shrink: 0;
}

/* .atc-card-quote-wrap exists only so the clamped <p> below is NOT a
   direct child of .atc-card's flex container. Chrome "blockifies" a flex
   item's own display value — an element whose CSS says
   `display: -webkit-box` (required for -webkit-line-clamp to do
   anything) silently computes to `display: flow-root` instead when it's
   a direct flex child, which makes the clamp a no-op and lets the text
   grow to its full unclamped height, pushed out of the visible card by
   .atc-card's overflow:hidden. A plain block wrapper (default
   display:block, already "block-level" so it isn't blockified) absorbs
   being the flex item instead, and the <p> inside it keeps its
   -webkit-box display untouched. */
.atc-card-quote-wrap {
  width: 100%;
  overflow: hidden;
  /* The one flexible element in the card's flex column: grows to fill
     whatever space is left after the fixed-size logo/name/role/company,
     and can shrink when the card is too short to fit everything.
     BUT: logo/name/role/company are all flex-shrink:0 (locked), so when
     their own combined height already exceeds the card (e.g. a long name
     wraps to 2 lines AND a long company name wraps to 4-5 lines at this
     card width), flexbox has nowhere else to take the deficit from and
     squeezes this element all the way down to min-height:0 — the quote
     disappears completely even though there's quote text to show.
     min-height: 4.5em is a floor (~3 lines at this element's own
     font-size/line-height) that flexbox is not allowed to shrink past, so
     the quote always shows at least a few lines. Past that floor, any
     remaining overflow clips at the card's own bottom edge instead
     (justify-content: flex-start above), which in practice means the
     company text (the most space-hungry element — see the 2-line clamp
     below) is what gives way, never the quote. */
  flex: 1 1 auto;
  min-height: 4.5em;
}

.atc-card-quote {
  margin: 0 0 0.8em;
  font-size: clamp(1rem, 0.85rem + 0.6vw, 1.35rem);
  font-style: italic;
  line-height: 1.5;
  color: var(--atc-quote-color);
  /* No more -webkit-line-clamp: the card above now grows (height: auto)
     to fit however many lines the quote actually needs, so there's
     nothing left to truncate. This is a plain wrapped paragraph again. */
}

.atc-card-quote::before { content: "\201C"; }
.atc-card-quote::after  { content: "\201D"; }

.atc-card-name {
  margin: 0 0 0.15em;
  font-size: clamp(0.95rem, 0.85rem + 0.3vw, 1.1rem);
  font-weight: 600;
  font-style: normal;
  letter-spacing: 0.02em;
  color: var(--atc-name-color);
  flex-shrink: 0;
}

.atc-card-role {
  margin: 0 0 0.1em;
  font-size: clamp(0.8rem, 0.72rem + 0.2vw, 0.9rem);
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--atc-role-color);
  opacity: 0.8;
  flex-shrink: 0;
}

/* .atc-card-company-wrap exists for the same reason as
   .atc-card-quote-wrap above: the clamped <p> inside needs to NOT be a
   direct flex child of .atc-card, or Chrome blockifies its
   display:-webkit-box and the clamp silently stops working. This wrap
   is what caps company text at 2 lines instead of the 4-5 lines a long
   name like "THINKTANK / BIRMINGHAM SCIENCE MUSEUM" can wrap to at
   narrow card widths — that excess was the biggest single cause of
   .atc-card-quote-wrap being squeezed to 0px (see the comment on
   min-height above). flex-shrink:0 is unchanged: company still keeps
   its fixed 2-line allowance, it's just a much smaller allowance now. */
.atc-card-company-wrap {
  width: 100%;
  overflow: hidden;
  flex-shrink: 0;
}

.atc-card-company {
  margin: 0;
  font-size: clamp(0.72rem, 0.66rem + 0.15vw, 0.8rem);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--atc-company-color, #8C5FF5);
  opacity: 0.9;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Phone sizing ─────────────────────────────────────────────────────
   Cards were too big on phones: 30px padding, 16px quote text on a theme
   25-30px line-height. These are plain (low-specificity) defaults, so any
   Typography / Padding you set in the Style tab for Mobile still wins. */
@media (max-width: 767px) {
  .atc-card {
    padding: 16px 14px;
    border-radius: 12px;
  }
  .atc-card .atc-card-quote {
    font-size: 0.8125rem;
    line-height: 1.5;
    min-height: 3em;
  }
  .atc-card .atc-card-name {
    font-size: 0.875rem;
    line-height: 1.3;
  }
  .atc-card .atc-card-role {
    font-size: 0.72rem;
    line-height: 1.3;
  }
  .atc-card .atc-card-company {
    font-size: 0.64rem;
    line-height: 1.3;
  }
  .atc-card .atc-card-logo {
    margin-bottom: 0.6em;
  }
}

/* ── Dot indicators ───────────────────────────────────────────────────── */

.atc-dots {
  position: absolute;
  /* Anchored to the card stack, not the scene bottom, so the dots move
     with Cards Vertical/Horizontal Offset automatically. --atc-cards-h is
     the tallest card's height, measured by corridor-cards-widget.js; 0.53
     is half of it times the active card's ~1.05 coverflow scale;
     --atc-dots-gap is the space under the card. */
  top: calc(50% + var(--atc-card-offset-y, 0px) + (var(--atc-cards-h, 580px) * 0.53) + var(--atc-dots-gap, 14px));
  left: calc(50% + var(--atc-card-offset-x, 0px));
  z-index: 10;
  transform: translateX(-50%);
  display: flex;
  gap: 0.6em;
}

/* Specificity + !important: the Elementor kit / theme style every <button>
   (min-width, padding, border, line-height — and bigger at tablet/mobile),
   which turned the 8px dots into fat ovals. These dots are fixed circles. */
.atc-scene .atc-dots .atc-dot {
  position: relative;
  box-sizing: border-box !important;
  flex: 0 0 auto !important;
  display: block !important;
  width: 8px !important;
  height: 8px !important;
  min-width: 0 !important;
  min-height: 0 !important;
  max-width: 8px !important;
  max-height: 8px !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 50% !important;
  background: var(--atc-dot-color) !important;
  box-shadow: none !important;
  font-size: 0 !important;
  line-height: 0 !important;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: background-color 0.3s ease, transform 0.3s ease;
}
/* Larger invisible tap target (44px) without changing the visible dot. */
.atc-scene .atc-dots .atc-dot::after {
  content: "";
  position: absolute;
  inset: -18px -9px;
}
.atc-scene .atc-dots .atc-dot.atc-dot--active {
  background: var(--atc-dot-active-color) !important;
  transform: scale(1.3);
}
.atc-scene .atc-dots .atc-dot:hover,
.atc-scene .atc-dots .atc-dot:focus {
  background: var(--atc-dot-active-color) !important;
  box-shadow: none !important;
}
.atc-scene .atc-dots .atc-dot:focus-visible {
  outline: 2px solid var(--atc-dot-active-color);
  outline-offset: 4px;
}
.atc-dots { align-items: center; }

/* ── Reduced motion / no-JS fallback ──────────────────────────────────── */
/* If JS never runs at all (disabled, or failed to load), show every card
   as a plain stacked list rather than a pile of overlapping absolute
   cards with no positioning applied. */
.atc-scene.atc-no-js .atc-stage { display: block; position: relative; height: auto; overflow: visible; padding: 4em 0; }
.atc-scene.atc-no-js .atc-track { position: static; display: flex; flex-direction: column; align-items: center; gap: 2em; }
.atc-scene.atc-no-js .atc-card { position: static; transform: none !important; opacity: 1 !important; }
.atc-scene.atc-no-js .atc-dots { display: none; }
.atc-scene.atc-no-js .atc-room { display: none; }

@media (prefers-reduced-motion: reduce) {
  .atc-scene .atc-dots .atc-dot { transition: none; }
}
