
/* Placeholder shown instead of a <video> whose file does not exist yet. */
.clip__ph {
  display: grid; place-content: center; gap: var(--s-2); text-align: center;
  aspect-ratio: 9/16; padding: var(--s-6);
  border: 2px dashed var(--surface-line); border-radius: var(--radius);
  background: var(--surface-2);
}
.clip__ph-note { font-size: var(--fs-xs); color: var(--text-lo); }

/* Placeholders shown instead of an <img> whose file does not exist yet. */
.studio-card__ph, .scene__ph {
  display: grid; place-items: center; text-align: center; padding: var(--s-4);
  border: 2px dashed var(--surface-line); border-radius: var(--radius);
  background: var(--surface-2);
}
.studio-card__ph { aspect-ratio: 4 / 5; }
.scene__ph { aspect-ratio: 16 / 9; }

/* --------------------------------------------------------------------------
   Studio range — compact cards.

   The cards were built around a 4/5 placeholder box that filled most of the
   viewport height, so two avatars filled a screen and the range read as short.
   Capping the image and tightening the spec fits the whole roster in one view,
   which is the only way a catalogue communicates "we have a range".
   -------------------------------------------------------------------------- */
.studio-grid { --studio-card: 15rem; }
.studio-card { padding: var(--s-4); }
.studio-card__img {
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: 15rem;          /* the cap that does the actual work */
  object-fit: cover;
  /* Portrait stills in a shorter frame: hold the face, not the torso. */
  object-position: 50% 14%;
  border-radius: var(--radius-sm);
  display: block;
}
.studio-card__code {
  font-size: var(--fs-body-lg);
  margin: var(--s-3) 0 var(--s-2);
  letter-spacing: -0.01em;
}
.studio-card .spec { font-size: var(--fs-xs); gap: var(--s-1) var(--s-3); }
.studio-card .spec dd { margin: 0; }

.scene__img {
  width: 100%; aspect-ratio: 16 / 9; max-height: 9rem;
  object-fit: cover; border-radius: var(--radius-sm); display: block;
}

/* ==========================================================================
   HERO STACK (/ai/) — three roster faces beside the pitch.

   The right half of this hero was empty, which on a page selling avatars
   wastes the argument: the product is a face that talks, and the hero was
   making that case in words only.

   Three cards in depth. Each drifts on its own cycle so the group never
   marches in step — synchronised float is the tell that turns a "cool" effect
   into an obviously canned one.
   ========================================================================== */
.hero__inner--split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: clamp(var(--s-8), 4vw, var(--s-16));
  align-items: center;
}
.hero__copy { min-width: 0; }

.herostack {
  position: relative;
  min-height: clamp(22rem, 38vw, 34rem);   /* room for the lower front card */
  perspective: 1200px;
  transform-style: preserve-3d;
}

.herostack__card {
  position: absolute;
  margin: 0;
  width: clamp(9rem, 16vw, 13rem);
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--surface-line);
  background: var(--surface-1);
  box-shadow: var(--shadow-card);
  will-change: transform;
}
.herostack__card img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* These are full-length portraits of dark subjects on dark backdrops. Fitted
     whole into a 220px card they average 44/255 — the face is a small bright
     patch lost in black, so the cards read as empty rectangles. Brightening
     does not fix that; it just makes grey rectangles.
     So: crop INTO the head. The image is scaled past the frame with the origin
     near the top, which turns a full-length shot into a headshot — which is
     what a card this size can actually show. */
  /* Mixed sources: two portraits and one 16:9 video thumbnail. A plain cover
     with the focal point above centre suits all three; the face-zoom crop this
     had before mangled anything that was not a full-length portrait. */
  object-position: 50% 34%;
}
/* A scrim only under the caption, so the picture itself stays bright. */
.herostack__card figcaption {
  position: absolute; inset: auto 0 0 0;
  padding: var(--s-6) var(--s-3) var(--s-3);
  display: grid; gap: 2px;
  background: linear-gradient(to top, rgb(13 13 15 / 0.92), transparent);
}
.herostack__name { font-size: var(--fs-sm); color: var(--y-white); font-weight: 500; }
.herostack__role {
  font-size: 0.6875rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--y-yellow);
}

/* Placement: a front card, one behind-left, one behind-right. Rotations are
   small — past about 8deg the cards read as fallen over rather than stacked.

   The dimming on the two rear cards is gentle on purpose. These portraits are
   already dark subjects on dark backdrops, and the first pass at 0.5/0.62
   crushed them to black rectangles — a depth cue that erases the thing it is
   supposed to be adding depth to.

   Offsets are tuned so all three FACES clear the card in front of them. The
   first arrangement had the front card sitting squarely over the rear-right
   one, so a third of the stack was an empty rounded rectangle — the point of
   showing three is that a visitor sees a range. */
.herostack__card--1 {
  left: 0;   top: 16%;
  transform: rotate(-6deg) translateZ(-80px) scale(0.9);
  filter: brightness(0.95) saturate(1);
  animation: stack-float-a 9s var(--ease-inout) infinite;
}
.herostack__card--2 {
  right: 0;  top: 0;
  transform: rotate(5deg) translateZ(-140px) scale(0.84);
  filter: brightness(0.85) saturate(0.95);
  animation: stack-float-b 11s var(--ease-inout) infinite;
}
.herostack__card--wide { aspect-ratio: 16 / 10; width: clamp(11rem, 19vw, 15rem); }
.herostack__card--3 {
  left: 44%; top: 46%;
  translate: -50% 0;
  transform: rotate(-1deg) translateZ(0) scale(1.06);
  z-index: 2;
  box-shadow: var(--glow-yellow), var(--shadow-card);
  animation: stack-float-c 7.5s var(--ease-inout) infinite;
}
@keyframes stack-float-a { 50% { transform: rotate(-6deg) translateZ(-80px)  scale(0.9)  translateY(-14px); } }
@keyframes stack-float-b { 50% { transform: rotate(5deg)  translateZ(-140px) scale(0.84) translateY(10px); } }
@keyframes stack-float-c { 50% { transform: rotate(-1deg) translateZ(0)      scale(1.06) translateY(-9px); } }

.herostack__badge {
  position: absolute; z-index: 3;
  left: 50%; bottom: 2%; translate: -50% 0;
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-4);
  border-radius: var(--radius-pill);
  background: rgb(13 13 15 / 0.78);
  border: 1px solid var(--surface-line);
  backdrop-filter: blur(10px);
  font-size: var(--fs-xs); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--y-white); white-space: nowrap;
}
.herostack__dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--y-red);
  animation: stack-pulse 1.8s var(--ease-inout) infinite;
}
@keyframes stack-pulse { 50% { opacity: .3; transform: scale(.7); } }

/* Below ~62rem the copy needs the full width, and three absolutely-positioned
   cards in a short row would collide. The stack is decorative — it goes. */
@media (max-width: 62rem) {
  .hero__inner--split { grid-template-columns: 1fr; }
  .herostack { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .herostack__card, .herostack__dot { animation: none; }
}

/* --------------------------------------------------------------------------
   FAQ column (/ai/).
   The intro sits beside eight collapsed questions, so its column was mostly
   empty canvas. Sticking it keeps the heading in view while the list is read,
   which is the only thing that column can usefully do.
   -------------------------------------------------------------------------- */
@media (min-width: 60rem) {
  #faq .grid--75 > :first-child { position: sticky; top: calc(var(--s-20) + var(--s-4)); align-self: start; }
}

/* ==========================================================================
   FUTURISTIC LAYER (/ai/avatar/)

   The page sold real-time digital humans in plain editorial type — correct,
   but it read like an essay about the future rather than a thing from it.
   Three reusable pieces do the work, and all three are pure decoration layered
   OVER content that is already complete and readable without them:

     .hud       corner brackets + a scanline sweep on any media
     .readout   mono spec rows, terminal-styled
     .pipeline  a numbered rail for the build steps

   Nothing here carries information of its own. If the CSS never arrives the
   page loses its atmosphere and keeps every word.
   ========================================================================== */

/* --- HUD frame ---------------------------------------------------------- */
.hud { position: relative; isolation: isolate; }
.hud__frame {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid rgb(240 198 74 / 0.22);
  background: var(--surface-1);
  box-shadow: 0 0 0 1px rgb(13 13 15 / 0.6), 0 24px 70px -30px rgb(240 198 74 / 0.28);
}
.hud__frame > img,
.hud__frame > video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Four corner brackets, drawn with borders on two pseudo-elements per corner
   pair — cheaper than four extra elements and impossible to get out of sync. */
.hud__frame::before,
.hud__frame::after {
  content: ""; position: absolute; z-index: 3;
  width: 22px; height: 22px; pointer-events: none;
  border-color: var(--y-yellow); border-style: solid; border-width: 0;
}
.hud__frame::before {
  top: 10px; left: 10px; border-top-width: 2px; border-left-width: 2px;
  border-top-left-radius: 4px;
}
.hud__frame::after {
  bottom: 10px; right: 10px; border-bottom-width: 2px; border-right-width: 2px;
  border-bottom-right-radius: 4px;
}
.hud__corners { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.hud__corners::before,
.hud__corners::after {
  content: ""; position: absolute; width: 22px; height: 22px;
  border-color: var(--y-yellow); border-style: solid; border-width: 0;
}
.hud__corners::before {
  top: 10px; right: 10px; border-top-width: 2px; border-right-width: 2px;
  border-top-right-radius: 4px;
}
.hud__corners::after {
  bottom: 10px; left: 10px; border-bottom-width: 2px; border-left-width: 2px;
  border-bottom-left-radius: 4px;
}

/* Scanline sweep. One translated gradient — no repaint of the media beneath. */
.hud__scan {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(to bottom,
              transparent 0%, rgb(240 198 74 / 0.07) 46%,
              rgb(240 198 74 / 0.16) 50%, rgb(240 198 74 / 0.07) 54%, transparent 100%);
  background-size: 100% 42%;
  background-repeat: no-repeat;
  animation: hud-scan 5.5s var(--ease-inout) infinite;
  mix-blend-mode: screen;
}
@keyframes hud-scan {
  0%, 100% { background-position: 0 -50%; }
  50%      { background-position: 0 150%; }
}

/* A faint horizontal raster over the whole frame — the thing that reads as
   "signal" rather than "photograph". Kept very low or it dirties skin tones. */
.hud__frame > .hud__grain {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: repeating-linear-gradient(to bottom,
              rgb(255 255 255 / 0.035) 0 1px, transparent 1px 3px);
}

.hud__tag {
  position: absolute; z-index: 4; top: var(--s-3); left: var(--s-3);
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--radius-pill);
  background: rgb(13 13 15 / 0.78);
  border: 1px solid rgb(240 198 74 / 0.3);
  backdrop-filter: blur(10px);
  font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--y-white);
}
.hud__tag::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--y-red); animation: hud-pulse 1.8s var(--ease-inout) infinite;
}
@keyframes hud-pulse { 50% { opacity: .25; transform: scale(.65); } }

/* --- Readout ------------------------------------------------------------ */
.readout {
  display: grid; gap: 0;
  margin: var(--s-6) 0 0;
  border-top: 1px solid var(--surface-line);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
}
.readout__row {
  display: grid; grid-template-columns: 1fr auto; gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--surface-line);
}
.readout__k { color: var(--text-lo); letter-spacing: 0.1em; text-transform: uppercase; }
.readout__v { color: var(--y-yellow); text-align: right; }

/* --- Pipeline ----------------------------------------------------------- */
.pipeline { display: grid; gap: 0; counter-reset: step; }
.pipeline__step {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(var(--s-4), 2.5vw, var(--s-8));
  padding: var(--s-6) 0;
  border-bottom: 1px solid var(--surface-line);
}
.pipeline__step:first-child { border-top: 1px solid var(--surface-line); }
.pipeline__n {
  counter-increment: step;
  display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem;
  border-radius: 50%;
  border: 1px solid rgb(240 198 74 / 0.4);
  background: rgb(240 198 74 / 0.06);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--y-yellow);
}
.pipeline__n::before { content: counter(step, decimal-leading-zero); }
.pipeline__h { font-size: var(--fs-body-lg); color: var(--text-hi); margin: 0 0 var(--s-2); }
.pipeline__p { color: var(--text-mid); font-size: var(--fs-sm); line-height: var(--lh-body); margin: 0; max-width: 60ch; }

@media (prefers-reduced-motion: reduce) {
  .hud__scan, .hud__tag::before { animation: none; }
}

/* --------------------------------------------------------------------------
   Avatar hero — copy beside a framed showreel.

   `.avatar-hero__grid` was referenced in the markup and never written, so the
   hero was a plain block: the copy stacked, then a 9:16 clip ran at full
   container width and Hanna filled the entire screen. A showreel on a page
   selling avatars is evidence, not a billboard — she is framed here at the
   same scale as the roster cards further down.
   -------------------------------------------------------------------------- */
.avatar-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
  gap: clamp(var(--s-8), 4vw, var(--s-16));
  align-items: center;
}
.avatar-hero__copy { min-width: 0; }

.avatar-hero__media { margin: 0; min-width: 0; }
.avatar-hero__media .hud__frame { aspect-ratio: 3 / 4; }
.avatar-hero__media video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* 9:16 source in a 3:4 frame — hold the face, drop the torso. */
  object-position: 50% 16%;
}
.avatar-hero__cap {
  margin-top: var(--s-4);
  font-size: var(--fs-sm);
  color: var(--text-lo);
  line-height: var(--lh-body);
}

@media (max-width: 62rem) {
  .avatar-hero__grid { grid-template-columns: 1fr; }
  .avatar-hero__media { max-width: 22rem; }
}

/* --------------------------------------------------------------------------
   Scene packs — 2×2 grid with pointer-driven depth.

   Four plates stacked in one column read as an afterthought running down the
   gutter. In a grid they read as a range you pick from, which is what a scene
   pack is. The tilt is the same one the capability cards use, so the page has
   one motion vocabulary rather than a new trick per section.
   -------------------------------------------------------------------------- */
.scene-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(var(--s-4), 2vw, var(--s-6));
}
@media (max-width: 40rem) { .scene-grid { grid-template-columns: 1fr; } }

.scene {
  min-width: 0;
  transform: perspective(900px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transform-style: preserve-3d;
  transition: transform var(--dur) var(--ease-out);
}
.scene__frame {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--surface-line);
  background: var(--surface-1);
  transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.scene:hover .scene__frame {
  border-color: rgb(240 198 74 / 0.45);
  box-shadow: var(--glow-yellow);
}
.scene__img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform var(--dur-slow) var(--ease-out);
}
.scene:hover .scene__img { transform: scale(1.05); }

/* A light sweep that follows the pointer — the surface catching a light source
   rather than a decorative shine that plays on a loop. */
.scene__sheen {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
              rgb(255 255 255 / 0.16), transparent 62%);
  opacity: 0; transition: opacity var(--dur) var(--ease-out);
}
.scene:hover .scene__sheen { opacity: 1; }

.scene__body { padding-top: var(--s-3); }
.scene__name { color: var(--text-hi); font-weight: 500; margin: 0 0 var(--s-1); }
.scene__detail { color: var(--text-mid); font-size: var(--fs-sm); line-height: var(--lh-snug); margin: 0; }

@media (hover: none) { .scene { transform: none; } .scene__sheen { display: none; } }
@media (prefers-reduced-motion: reduce) { .scene, .scene__img { transition: none; } }

/* ── STUDIO HERO FAN ────────────────────────────────────────────────────────
   The studio hero was a single centred column with a large empty right side.
   It now carries the roster itself as a 3D fan, because "a shelf of AI avatars
   you can pick from" is a claim best answered with the shelf.

   The fan is built from --i on each card, so adding a sixth avatar to the
   roster needs no CSS change — the angles and offsets are computed from the
   index. Cards spread on hover; the transform is one property so it composites
   on the GPU. */
.stHero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(var(--s-8), 5vw, var(--s-14));
  align-items: center;
}
@media (max-width: 64rem) {
  .stHero { grid-template-columns: 1fr; }
  .stFan { order: -1; }
}

.stFan { position: relative; perspective: 1500px; display: grid; place-items: center; }
.stFan__stage {
  position: relative;
  width: 100%; height: clamp(20rem, 34vw, 27rem);
  display: grid; place-items: center;
  transform-style: preserve-3d;
  transform: rotateX(var(--ax, 0deg)) rotateY(var(--ay, 0deg));
  transition: transform .5s cubic-bezier(.22,1,.36,1);
}
.stFan__glow {
  position: absolute; width: 78%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, rgb(240 198 74 / .2), transparent 64%);
  filter: blur(30px);
}
.stFan__card {
  position: absolute; margin: 0;
  width: clamp(9rem, 15vw, 11.5rem); aspect-ratio: 3 / 4;
  border-radius: var(--radius-lg); overflow: hidden;
  border: 1px solid rgb(255 255 255 / .12);
  background: var(--surface-1);
  box-shadow: 0 26px 70px -26px rgb(0 0 0 / .9);
  /* Centred fan: --i - 2 puts the middle card at 0 for a five-card roster and
     stays symmetrical for any odd count. */
  --o: calc(var(--i) - 2);
  transform:
    translate3d(calc(var(--o) * 2.6rem), calc(abs(var(--o)) * 0.9rem), calc(abs(var(--o)) * -60px))
    rotateY(calc(var(--o) * -13deg))
    rotate(calc(var(--o) * 3deg));
  transition: transform .65s cubic-bezier(.22,1,.36,1), box-shadow .4s, border-color .3s;
  z-index: calc(10 - abs(var(--o)));
}
.stFan__stage:hover .stFan__card {
  transform:
    translate3d(calc(var(--o) * 4.3rem), calc(abs(var(--o)) * 0.4rem), calc(abs(var(--o)) * -24px))
    rotateY(calc(var(--o) * -17deg))
    rotate(calc(var(--o) * 2deg));
}
.stFan__card:hover { border-color: rgb(240 198 74 / .6); box-shadow: 0 0 0 1px rgb(240 198 74 / .4), 0 30px 80px -24px rgb(0 0 0 / .95); z-index: 20; }
.stFan__card img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 18%; display: block; }
.stFan__card figcaption {
  position: absolute; inset: auto 0 0 0; display: grid; gap: 1px;
  padding: var(--s-6) var(--s-3) var(--s-3);
  background: linear-gradient(to top, rgb(6 6 8 / .92), transparent);
}
.stFan__card figcaption b { color: #fff; font-size: var(--fs-sm); }
.stFan__card figcaption span { color: rgb(255 255 255 / .7); font-size: .6rem; letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }
.stFan__hint {
  margin: var(--s-4) 0 0; text-align: center;
  font-size: var(--fs-xs); color: var(--text-lo);
}

@media (max-width: 40rem) {
  .stFan__stage { height: 16rem; }
  .stFan__card { width: 7.5rem; --o: calc(var(--i) - 2); }
  .stFan__card { transform: translate3d(calc(var(--o) * 1.9rem), calc(abs(var(--o)) * .6rem), calc(abs(var(--o)) * -50px)) rotateY(calc(var(--o) * -11deg)); }
  .stFan__hint { display: none; }   /* no hover on touch, so the hint lies */
}
@media (prefers-reduced-motion: reduce) {
  .stFan__stage, .stFan__card { transition: none; }
  .stFan__stage:hover .stFan__card { transform: translate3d(calc(var(--o) * 2.6rem), calc(abs(var(--o)) * .9rem), calc(abs(var(--o)) * -60px)) rotateY(calc(var(--o) * -13deg)) rotate(calc(var(--o) * 3deg)); }
}
