/* ======================================
   ZON PERFORMANCE — premium.css
   Animations, reveals, premium interactions
   ====================================== */

/* ======================================
   SCROLL REVEAL
   ====================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 0.7s ease,
    transform 0.7s cubic-bezier(0.16, 0.84, 0.34, 1);
}
[data-reveal].is-revealed {
  opacity: 1;
  transform: translateY(0);
}

/* ======================================
   CARD REVEAL — softer settle + reticle "lock-on"
   Cards (credentials, testimonials, modes) ease and
   scale into place instead of snapping up. As each
   credential / testimonial settles, an amber sight-line
   sweeps across its top edge and vanishes — a scope
   confirming a target. Transform + opacity only.
   ====================================== */
.cred[data-reveal],
.mode[data-reveal],
.testimonial[data-reveal],
.testimonial-featured[data-reveal] {
  transform: translateY(22px) scale(0.985);
  transition:
    opacity 0.95s cubic-bezier(0.22, 1, 0.36, 1),
    transform 1.05s cubic-bezier(0.22, 1, 0.36, 1);
}
.cred[data-reveal].is-revealed,
.mode[data-reveal].is-revealed,
.testimonial[data-reveal].is-revealed,
.testimonial-featured[data-reveal].is-revealed {
  transform: translateY(0) scale(1);
}

/* Lock-on sweep */
.cred,
.testimonial,
.testimonial-featured {
  position: relative;
}
.cred[data-reveal]::after,
.testimonial[data-reveal]::after,
.testimonial-featured[data-reveal]::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: var(--c-accent);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  pointer-events: none;
}
.cred[data-reveal].is-revealed::after,
.testimonial[data-reveal].is-revealed::after,
.testimonial-featured[data-reveal].is-revealed::after {
  animation: lockOnSweep 1.15s cubic-bezier(0.22, 1, 0.36, 1) 0.18s both;
}

@keyframes lockOnSweep {
  0%   { transform: scaleX(0); opacity: 0; }
  35%  { opacity: 1; }
  65%  { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; }
}

/* ======================================
   KEYFRAME ANIMATIONS
   ====================================== */
@keyframes reticlePulse {
  0%, 100% { opacity: 0.06; transform: translateY(-50%) scale(1); }
  50%       { opacity: 0.10; transform: translateY(-50%) scale(1.04); }
}
@keyframes dotPulse {
  0%, 100% { box-shadow: 0 0 10px rgba(234,88,12,0.8); }
  50%       { box-shadow: 0 0 18px rgba(234,88,12,1); }
}
@keyframes countUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Dot pulse on hero caption */
.caption-dot {
  animation: dotPulse 2.4s ease-in-out infinite;
}

/* ======================================
   NAV LOGO — assemble on first visit
   JS adds .is-assembling once per session; without it the mark
   rests fully drawn, so no-JS and repeat visits see the normal
   static logo. Keyframes omit `to` so every part settles on its
   natural computed style (e.g. the inner ring's 0.3 opacity).
   ====================================== */
.nav-logo.is-assembling .logo-o > circle:first-of-type {
  stroke-dasharray: 176; /* 2π × r28 */
  animation: logoRingDraw 0.7s cubic-bezier(0.16, 0.84, 0.34, 1) both;
}
.nav-logo.is-assembling .logo-o > circle:nth-of-type(2) {
  animation: logoPartIn 0.4s ease-out 0.45s both;
}
.nav-logo.is-assembling .logo-o > g:first-of-type {
  animation: logoPartIn 0.35s ease-out 0.5s both;
}
.nav-logo.is-assembling .logo-o > g:nth-of-type(2) {
  transform-box: view-box;
  transform-origin: center;
  animation: logoBellIn 0.55s cubic-bezier(0.34, 1.42, 0.5, 1) 0.55s both;
}
@keyframes logoRingDraw {
  from { stroke-dashoffset: 176; }
  to   { stroke-dashoffset: 0; }
}
@keyframes logoPartIn {
  from { opacity: 0; }
}
@keyframes logoBellIn {
  from { opacity: 0; transform: scale(0.55); }
}

/* ======================================
   NAV CTA HOVER STATE
   ====================================== */
.nav-cta {
  position: relative;
  overflow: hidden;
}
.nav-cta::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--c-light);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.3s cubic-bezier(0.16, 0.84, 0.34, 1);
  z-index: -1;
}
.nav-cta:hover::after { transform: scaleX(1); }

/* ======================================
   DOOR HOVER — diagonal grid reveal
   ====================================== */
.door--tactical .door-inner::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    58deg,
    rgba(244,239,230,0.04) 0 1px,
    transparent 1px 60px
  );
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
}
.door--tactical:hover .door-inner::before { opacity: 1; }

.door--performance .door-inner::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    58deg,
    rgba(26,24,21,0.04) 0 1px,
    transparent 1px 60px
  );
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
}
.door--performance:hover .door-inner::before { opacity: 1; }

/* Door CTA arrow nudge on hover */
.door:hover .door-cta { gap: 14px; transition: gap 0.3s ease; }

/* ======================================
   CHOOSE YOUR PATH — intent-sensing doors
   One normalized signal drives every effect:
     --it   tactical activation      0..1
     --ip   performance activation   0..1
     --is   global intensity knob (dial the whole
            interaction up or down from one place)
   JS writes --it / --ip on #doors from cursor
   proximity (desktop) or focus state (mobile).
   Everything below is CSS easing off those vars —
   no per-frame styling, transitions do the damping.
   ====================================== */
#doors {
  position: relative;
  overflow: hidden;
  --it: 0;
  --ip: 0;
  /* --is: global interaction intensity. 1 = full-strength build.
     Base magnitudes below were already raised for presence — this
     knob is the fine-tune on top of that, not the primary lever.
     Raise toward 1 for more; drop toward 0.6 to soften. */
  --is: 0.85;
  transition: background-color 1.3s cubic-bezier(0.22, 1, 0.36, 1);
  /* Wash toward Tactical's ember on --it, then further toward
     Performance's steel blue on --ip — each door tints the room
     in its own color rather than a single shared accent. */
  background-color: color-mix(
    in srgb,
    color-mix(in srgb, var(--c-dark), var(--c-accent) calc(var(--it) * var(--is) * 7%)),
    var(--c-accent-perf) calc(var(--ip) * var(--is) * 9%)
  );
}
#doors .container {
  position: relative;
  z-index: 1;
}

/* The reveal lives on a wrapper cell so .door is free to
   own the intent transform without colliding with it. */
.door-cell { display: grid; }

/* Registered as <number> so the signal computes to real values
   and invalidates correctly — including on pseudo-elements
   (an inherited calc()-defined property would not repaint them). */
@property --it    { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --ip    { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --is    { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --own   { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --other { syntax: "<number>"; inherits: true; initial-value: 0; }

/* Resolve, per card, which signal is "mine" vs "the other".
   Consumers inline var(--own) * var(--is) — plain-number vars,
   no calc-defined intermediate. */
.door--tactical    { --own: var(--it); --other: var(--ip); }
.door--performance { --own: var(--ip); --other: var(--it); }

/* Card lift + settle. */
.door {
  transform: translateY(calc(var(--own) * var(--is) * -10px)) scale(calc(1 + var(--own) * var(--is) * 0.013));
  box-shadow: 0 calc(var(--own) * var(--is) * 30px) calc(var(--own) * var(--is) * 60px) rgba(8, 6, 4, calc(var(--own) * var(--is) * 0.45));
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.6s ease,
              border-color 0.5s ease;
  will-change: transform;
}
@media (hover: hover) and (pointer: fine) {
  /* let intent own the transform — neutralise the old static lift */
  .door--tactical:hover,
  .door--performance:hover {
    transform: translateY(calc(var(--own) * var(--is) * -10px)) scale(calc(1 + var(--own) * var(--is) * 0.013));
  }
}

/* Full-card wash — the cards are opaque, so the section-level
   ambient glow behind them barely reads. This paints the reaction
   on the card surface itself (over the image AND the text half),
   which is what actually makes the whole tile feel like it's
   waking up rather than just a corner accent. */
.door::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  mix-blend-mode: overlay;
  opacity: calc(var(--own) * var(--is) * 0.7 - var(--other) * var(--is) * 0.3);
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.door--tactical::after {
  /* overlay reads as a warm glow against this card's dark base */
  background: linear-gradient(165deg, color-mix(in srgb, var(--c-accent) 60%, transparent), color-mix(in srgb, var(--c-accent) 12%, transparent) 55%, transparent 85%);
  mix-blend-mode: overlay;
}
.door--performance::after {
  /* overlay is nearly a no-op on a near-white base — multiply is
     the one that actually tints a light surface visibly */
  background: linear-gradient(165deg, color-mix(in srgb, var(--c-accent-perf) 48%, white), color-mix(in srgb, var(--c-accent-perf) 14%, white) 55%, white 85%);
  mix-blend-mode: multiply;
}

/* Video wakes: a scrim flattens it toward a still at rest,
   clears as the card activates, and deepens a touch when the
   OTHER side is chosen — the inactive card relaxes, never disables. */
.door-image-placeholder::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(13, 11, 9, 0.22), rgba(13, 11, 9, 0.44));
  opacity: calc(0.32 - var(--own) * var(--is) * 0.42 + var(--other) * var(--is) * 0.28);
  transition: opacity 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}
.door-video {
  transform: scale(calc(1 + var(--own) * var(--is) * 0.055));
  filter: grayscale(calc(100% - var(--own) * var(--is) * 22%))
          contrast(calc(1.08 + var(--own) * var(--is) * 0.1))
          brightness(calc(1 + var(--own) * var(--is) * 0.08));
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1),
              filter 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Ambient corner glow strengthens on the active side. */
.door--tactical::before,
.door--performance::before {
  opacity: calc(0.5 + var(--own) * var(--is) * 0.9 - var(--other) * var(--is) * 0.38);
  transition: opacity 0.65s ease;
}

/* CTA gains quiet emphasis. */
.door-cta {
  transform: translateX(calc(var(--own) * var(--is) * 10px));
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Environment: light migrates across the whole section toward the
   active side and settles slower than the cards (1.3s vs 0.6s) —
   this is a section-wide wash, not a corner accent, so the pane
   behind both cards visibly shifts as intent builds. */
.doors-ambient {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.doors-ambient::before,
.doors-ambient::after {
  content: '';
  position: absolute;
  top: -45%;
  bottom: -45%;
  width: 105%;
  opacity: 0;
  transition: opacity 1.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.doors-ambient::before {
  left: -8%;
  background: radial-gradient(closest-side at center, color-mix(in srgb, var(--c-accent) 32%, transparent), transparent 75%);
  opacity: calc(var(--it) * var(--is));
}
.doors-ambient::after {
  right: -8%;
  background: radial-gradient(closest-side at center, color-mix(in srgb, var(--c-accent-perf) 42%, transparent), transparent 75%);
  opacity: calc(var(--ip) * var(--is));
}

/* Mobile two-step: first tap focuses (JS blocks navigation),
   a second tap on the focused card follows the link. JS drives
   --it/--ip directly on #doors for the focused side, so --own/
   --other (and everything built on them, above) fall out of the
   same mapping desktop hover uses — no separate override needed. */

/* Immersive focus: while a door is focused on touch, everything
   outside it — nav, the hero, every other section, this section's
   own heading/footnote, and the other door — fades back so the
   focused door reads as the sole centerpiece. Tapping anywhere in
   that faded field (handled in JS as "outside the door") drops
   the class and restores normal view. */
body.is-door-immersive #nav,
body.is-door-immersive .hero-wrapper,
body.is-door-immersive .site-main > section:not(#doors),
body.is-door-immersive .site-main > footer {
  opacity: 0.02;
  pointer-events: none;
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
body.is-door-immersive #doors .two-doors-header,
body.is-door-immersive #doors .doors-footnote {
  opacity: 0.05;
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.door.is-relaxed {
  /* left faintly present (not 0) so it's still tappable to switch
     focus to the other door — everything else goes near-invisible */
  opacity: 0.12;
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Exit hint — a quiet pill that only appears once a door is locked
   in, telling the user how to back out. This is a deliberate,
   narrow exception to the project's "no fixed positioning outside
   nav/progress-bar" rule: sticky can't do this job here (it only
   catches an element while scrolling would carry it past its
   anchored edge, which never happens for an element that starts
   near the top of a ~9000px document — tested and confirmed).
   Fixed is the only way to keep it pinned to the viewport
   regardless of scroll position, and it's gated to opacity/
   pointer-events: none outside the immersive state, so it never
   intrudes otherwise. */
.doors-exit-hint {
  position: fixed;
  bottom: clamp(16px, 4vh, 32px);
  left: 0;
  right: 0;
  z-index: 40;
  display: flex;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.doors-exit-hint span {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-light);
  background-color: color-mix(in srgb, var(--c-base) 82%, transparent);
  border: 1px solid color-mix(in srgb, var(--c-light) 18%, transparent);
  padding: 10px 20px;
  border-radius: 999px;
  backdrop-filter: blur(6px);
}
body.is-door-immersive .doors-exit-hint {
  opacity: 0.9;
  pointer-events: auto;
}

/* ======================================
   CREDENTIALS GRID — hover lift
   ====================================== */
.cred {
  transition: background 0.3s ease;
}
.cred:hover { background-color: #161310; }

/* ======================================
   ABOUT IMAGE — subtle parallax
   ====================================== */
.about-image {
  will-change: transform;
}

/* ======================================
   TESTIMONIAL HOVER
   ====================================== */
.testimonial {
  transition: border-color 0.3s ease, background 0.3s ease;
}
.testimonial:hover {
  border-color: rgba(244,239,230,0.16);
  background: rgba(244,239,230,0.06);
}

/* ======================================
   BUTTON HOVER — border expand
   ====================================== */
.btn-primary.btn-lg {
  position: relative;
}
.btn-primary.btn-lg::before {
  content: '';
  position: absolute;
  inset: -2px;
  border: 2px solid var(--c-accent);
  border-radius: calc(var(--radius) + 2px);
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.btn-primary.btn-lg:hover::before {
  opacity: 1;
  transform: scale(1);
}

/* ======================================
   VIDEO — fade in on load
   ====================================== */
.hero-video {
  opacity: 0;
  transition: opacity 1.2s ease;
}
.hero-video.is-loaded { opacity: 1; }

/* ======================================
   SCROLL PROGRESS — amber glow
   ====================================== */
.scroll-progress {
  box-shadow: 0 0 8px rgba(234,88,12,0.6);
}

/* ======================================
   REDUCED MOTION — kill all non-essential
   ====================================== */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .cred[data-reveal],
  .mode[data-reveal],
  .testimonial[data-reveal],
  .testimonial-featured[data-reveal] {
    transform: none;
    transition: none;
  }
  .cred[data-reveal]::after,
  .testimonial[data-reveal]::after,
  .testimonial-featured[data-reveal]::after {
    display: none;
    animation: none;
  }
  .hero-reticle-bg { animation: none; }
  .caption-dot { animation: none; }
  #doors,
  .door,
  .door::after,
  .door--tactical .door-inner::before,
  .door--performance .door-inner::before,
  .door-image-placeholder::after,
  .door-video,
  .door--tactical::before,
  .door--performance::before,
  .door-cta,
  .doors-ambient::before,
  .doors-ambient::after,
  .door.is-relaxed,
  #nav,
  .hero-wrapper,
  .site-main > section,
  .site-main > footer,
  .two-doors-header,
  .doors-footnote,
  .doors-exit-hint {
    transition: none;
  }
  .nav-logo.is-assembling .logo-o > circle:first-of-type,
  .nav-logo.is-assembling .logo-o > circle:nth-of-type(2),
  .nav-logo.is-assembling .logo-o > g {
    animation: none;
  }
  .hero-video {
    opacity: 1;
    transition: none;
  }
}
