/* ============================================================================
   HERO — "The Vault"
   The DDB B is two stacked D's. A D is a door: flat hinge edge left, rounded
   swing right. Both doors hinge on the shared left edge, swing open, and the
   camera dollies through into the credentials.

   NOTE ON BRAND: this treatment knowingly departs from the DDB logo rules
   (Angle / Distortion / Effects / Combination, guidelines p.14). Approved by
   Ziyad for pitch use. Keep it contained to this hero — everywhere else the
   logo must appear flat, unmodified and with correct clear space.
   ============================================================================ */

.vault-track { position: relative; display: grid; grid-template-columns: 1fr; }
.vault-steps { grid-area: 1 / 1; pointer-events: none; }
.vault-step  { height: 100vh; height: 100dvh; }

.vault-stage {
  grid-area: 1 / 1; align-self: start;
  position: sticky; top: 0;
  height: 100vh; height: 100dvh;
  display: grid; place-items: center;
  overflow: hidden;
  background: #0B0B0C;          /* the room the vault sits in */
  perspective: 1500px;
  perspective-origin: 50% 50%;
}

/* Everything that travels with the camera */
.vault-world {
  position: relative;
  transform-style: preserve-3d;
  will-change: transform;
}

/* ---- the shaft behind the doors: receding rings imply real depth ---- */
.vault-shaft {
  position: absolute; left: 50%; top: 50%;
  width: 150%; aspect-ratio: 1;
  transform: translate3d(-50%, -50%, -60px);
  transform-style: preserve-3d;
  pointer-events: none;
}
.vault-ring {
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(238, 41, 58, .07);
}

/* ---- the door frame: proportioned to the B (169 × 283) ---- */
.vault-frame {
  position: relative;
  width: min(42vmin, 340px);
  aspect-ratio: 169 / 283;
  transform-style: preserve-3d;
}

/* ---- a door ---- */
.vault-door {
  position: absolute; left: 0;
  transform-style: preserve-3d;
  transform-origin: 0% 50%;        /* the shared hinge edge */
  will-change: transform;
}
/* geometry lifted from the master logo (see js/vault.js) */
.vault-door--top    { top: 0;      width: 90.06%; height: 45.01%; }
.vault-door--bottom { top: 50.32%; width: 99.87%; height: 49.52%; }

.vault-layer { position: absolute; inset: 0; }
.vault-layer svg { width: 100%; height: 100%; overflow: visible; }

/* ---- copy revealed through the opening ---- */
.vault-reveal {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  text-align: center; padding-inline: var(--gutter);
  opacity: 0; pointer-events: none;
  will-change: opacity, transform;
}
.vault-reveal .t-eyebrow { display: block; margin-bottom: var(--space-md); color: #EE293A; }
.vault-reveal h1 { max-width: 17ch; margin-inline: auto; color: #fff; }
.vault-reveal p  { margin-top: var(--space-md); max-width: 48ch; margin-inline: auto; color: rgba(255,255,255,.66); }

.vault-caption {
  position: absolute; left: 50%; translate: -50% 0;
  bottom: clamp(28px, 6vh, 64px); text-align: center; pointer-events: none;
}
.vault-caption .k {
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
  color: rgba(255,255,255,.42);
}
.vault-caption .v {
  margin-top: 5px; font-size: 14px; font-weight: 700; letter-spacing: .01em;
  color: #fff;
}

/* ---- reduced motion: no vault, no travel — the logo, flat and correct ---- */
@media (prefers-reduced-motion: reduce) {
  .vault-steps { display: none; }
  .vault-stage { position: static; height: auto; padding-block: var(--space-3xl); }
  .vault-world, .vault-door { transform: none !important; }
  .vault-shaft { display: none; }
  .vault-reveal { position: static; opacity: 1; }
  .vault-caption { display: none; }
}

/* ============================================================================
   THE EXIT — the vault must open onto SAB, not onto nothing.
   Travelling through, we pass their tessellated pattern receding in Z, then
   flood to white so the hero lands on the light site instead of hard-cutting.
   ============================================================================ */
.vault-depth {
  position: absolute; left: 50%; top: 50%;
  width: 260%; aspect-ratio: 1;
  transform: translate3d(-50%, -50%, 0);
  transform-style: preserve-3d;
  pointer-events: none;
}
.vault-depth i {
  position: absolute; inset: 0; display: block;
  background-repeat: repeat;   /* image set per-plane in js/vault.js */
  /* Soft elliptical falloff, no hard edge — a tight radial cutoff meeting the
     tile diagonals is what produced the star artefact. */
  -webkit-mask-image: radial-gradient(58% 52% at 50% 50%, #000 0%, rgba(0,0,0,.55) 42%, transparent 88%);
          mask-image: radial-gradient(58% 52% at 50% 50%, #000 0%, rgba(0,0,0,.55) 42%, transparent 88%);
}

/* a single warm core so the eye has somewhere to land instead of scanning
   a field of triangles */
.vault-depth::after {
  content: ''; position: absolute; inset: 0;
  transform: translateZ(-620px) scale(2.2);
  background: radial-gradient(circle at 50% 50%,
              rgba(255,120,130,.30) 0%, rgba(238,41,58,.16) 26%, transparent 62%);
  pointer-events: none;
}

/* the daylight we emerge into — matches --bg-page, so the next section joins */
.vault-exit {
  position: absolute; inset: 0; z-index: 3;
  background: var(--bg-page);
  opacity: 0; pointer-events: none;
}

/* copy resolves on white, in the SAB system, not on black */
.vault-reveal { z-index: 4; }
.vault-reveal h1 { color: var(--text-primary); }
.vault-reveal p  { color: var(--text-muted); }
.vault-reveal .t-eyebrow { color: var(--accent); }

/* ---- material: the door casts into its own recess ---- */
/* No drop-shadow here: it is a filter on an element that rotates every frame,
   and the doors already read as solid from the baked extrusion. */
.vault-door { will-change: transform; }

/* a pool of shadow behind the closed B, so it sits in a frame rather than
   floating in space. Fades out as the doors swing away from it. */
.vault-contact {
  position: absolute; left: 50%; top: 50%;
  width: 128%; height: 112%;
  transform: translate3d(-50%, -46%, -34px);
  background: radial-gradient(60% 52% at 50% 52%, rgba(0,0,0,.92), rgba(0,0,0,0) 72%);
  filter: blur(12px);
  pointer-events: none;
}

/* the rim of the aperture the doors seat into */
.vault-jamb {
  position: absolute; inset: -2% -2.5% -2% -1.5%;
  transition: opacity 120ms linear;
  transform: translateZ(-40px);
  background: linear-gradient(148deg, #1C1C20 0%, #0E0E11 42%, #070709 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.07);
  /* feather the edges — a hard rectangle behind the mark reads as a mistake */
  -webkit-mask-image: radial-gradient(58% 48% at 50% 50%, #000 22%, transparent 92%);
          mask-image: radial-gradient(58% 48% at 50% 50%, #000 22%, transparent 92%);
  pointer-events: none;
}

/* The inside face is mirrored, so it must only be visible from behind —
   otherwise it sits on top of the lit face while the door is still shut. */
.vault-face { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.vault-back { backface-visibility: hidden; -webkit-backface-visibility: hidden; }

/* The inside face is placed with rotateY(180deg), which mirrors its content
   horizontally — so the hinge edge ended up on the wrong side and the union of
   a D and a mirrored D read as a rectangle. Pre-mirror the artwork so the flip
   cancels it out: two mirrors = the same silhouette as the front, which is
   what a real slab has. */
.vault-back svg { transform: scaleX(-1); transform-origin: 50% 50%; }

/* ============================================================================
   KINETIC TYPE
   Two moments, both earning their place:

   1. THE CONTENTS — words sitting at depth inside the shaft. They rush past
      the camera on the way in because they live in .vault-world and inherit
      its travel; no separate animation, so they can never drift out of sync
      with the dolly.

   2. THE LANDING — the headline arrives line by line from behind a mask.
      Type that slides up out of nothing reads as mechanical; type revealed
      by a moving edge reads as deliberate.
   ============================================================================ */
.vault-words {
  position: absolute; left: 50%; top: 50%;
  width: 0; height: 0;
  transform-style: preserve-3d;
  pointer-events: none; opacity: 0;
}
.vault-words b {
  position: absolute;
  display: block;
  white-space: nowrap;
  font-weight: 700;
  letter-spacing: -.02em;
  color: rgba(255,255,255,.9);
  text-transform: none;
  transform-origin: 50% 50%;
}
.vault-words b.is-red { color: #EE293A; }
.vault-words b.is-ghost { color: rgba(255,255,255,.22); font-weight: 300; }

/* ---- the landing ---- */
.vault-reveal .line {
  display: block;
  overflow: hidden;          /* the mask */
  padding-bottom: .08em;     /* descenders must not be clipped */
}
.vault-reveal .line > span {
  display: block;
  transform: translateY(105%);
  transition: transform 900ms var(--ease-out);
  transition-delay: var(--line-delay, 0ms);
}
.vault-reveal.is-landed .line > span { transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .vault-words { display: none; }
  .vault-reveal .line > span { transform: none; transition: none; }
}

/* ============================================================================
   THE COMBINATION
   A vault opens with one. Three tumblers spin and lock in sequence during the
   sealed phase — which was previously dead scroll with only the wheel turning.
   The words they land on are the argument.
   ============================================================================ */
.vault-combo {
  position: absolute;
  left: var(--gutter);
  top: 50%; translate: 0 -50%;
  display: grid; gap: clamp(6px, 1.1vh, 14px);
  pointer-events: none;
  z-index: 2;
}
.vault-combo .tumbler {
  --lh: clamp(40px, 6.6vh, 82px);
  position: relative;
  height: var(--lh);
  overflow: hidden;             /* the mask the words spin behind */
}
.vault-combo .strip {
  display: block;
  will-change: transform;
}
.vault-combo .strip span {
  display: block;
  height: var(--lh); line-height: var(--lh);
  font-size: calc(var(--lh) * 0.80);
  font-weight: 700; letter-spacing: -.02em;
  color: rgba(255,255,255,.42);
  white-space: nowrap;
}
/* the word it settles on */
.vault-combo .strip span:last-child { color: #FFF; }
.vault-combo .tumbler.is-locked .strip span:last-child { color: #FFF; }

/* the lock indicator — a rule that draws itself when the tumbler seats */
.vault-combo .tumbler::after {
  content: ''; position: absolute; left: 0; bottom: 2px;
  height: 3px; width: 100%;
  background: #EE293A;
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 260ms var(--ease-out);
}
.vault-combo .tumbler.is-locked::after { transform: scaleX(1); }

.vault-combo .combo-label {
  font-size: 13px; font-weight: 700; letter-spacing: .03em;
  color: rgba(255,255,255,.55);
  margin-bottom: 10px;
}

/* Below the point where the mark and the type would collide, the combination
   is the thing that goes — the vault is the hero, not the copy. */
@media (max-width: 1100px) { .vault-combo { display: none; } }
@media (prefers-reduced-motion: reduce) { .vault-combo { display: none; } }
