/* ==========================================================================
   SMAG — motion layer
   Easing + duration tokens, keyframes, reveal choreography, micro-interactions.
   Everything here degrades to "no motion" under prefers-reduced-motion,
   and to "fully visible" when JS is unavailable (see the :not(.js) guard).
   ========================================================================== */

:root {
  /* Easing — expo.out is the house curve: fast departure, long soft settle. */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);

  --dur-fast: 150ms;
  --dur-base: 260ms;
  --dur-slow: 520ms;
  --dur-reveal: 760ms;

  /* Set to 0 by the reduced-motion block below; multiplied into every
     JS-driven stagger so one switch disables the whole choreography. */
  --motion-scale: 1;
}

/* ==========================================================================
   1. Keyframes
   ========================================================================== */

/* -- Ambient background ---------------------------------------------------- */
@keyframes silkDrift {
  0%   { transform: translate3d(-2%, -1%, 0) rotate(-1.2deg) scale(1.12); }
  50%  { transform: translate3d(2%, 1.5%, 0) rotate(1.2deg) scale(1.2); }
  100% { transform: translate3d(-2%, -1%, 0) rotate(-1.2deg) scale(1.12); }
}

@keyframes blobDriftA {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(4%, 3%, 0) scale(1.1); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}

@keyframes blobDriftB {
  0%   { transform: translate3d(0, 0, 0) scale(1.06); }
  50%  { transform: translate3d(-4.5%, 3.5%, 0) scale(0.94); }
  100% { transform: translate3d(0, 0, 0) scale(1.06); }
}

/* -- Hero orbit ------------------------------------------------------------ */
@keyframes logoFloat {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(0, -18px, 0); }
}

@keyframes ringSpin    { to { transform: rotate(360deg); } }
@keyframes ringSpinRev { to { transform: rotate(-360deg); } }

@keyframes haloPulse {
  0%, 100% { opacity: .5; transform: scale(1); }
  50%      { opacity: .85; transform: scale(1.08); }
}

@keyframes orbit {
  from { transform: rotate(0deg) translateX(var(--r)) rotate(0deg); }
  to   { transform: rotate(360deg) translateX(var(--r)) rotate(-360deg); }
}

/* Signal rings radiating out of the mark — the "connection established" beat. */
@keyframes signalPulse {
  0%   { opacity: 0; transform: scale(.72); }
  12%  { opacity: .5; }
  100% { opacity: 0; transform: scale(1.5); }
}

@keyframes dotShift {
  0%, 100% { filter: brightness(1.02) saturate(1.05) contrast(1.02); transform: translateZ(0) scale(1); }
  50%      { filter: brightness(.82) saturate(.9) contrast(1.08); transform: translateZ(0) scale(.985); }
}

@keyframes dotGlow {
  0%, 100% { opacity: .92; transform: translate(-50%, -50%) scale(1.08); }
  50%      { opacity: .28; transform: translate(-50%, -50%) scale(.94); }
}

/* -- Utility --------------------------------------------------------------- */
@keyframes blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: .25; }
}

@keyframes shimmer {
  from { transform: translateX(-110%) skewX(-18deg); }
  to   { transform: translateX(320%) skewX(-18deg); }
}

/* ==========================================================================
   2. Reveal choreography
   Elements are hidden pre-reveal and released by IntersectionObserver, which
   adds .is-revealed. --i is the stagger index written by main.js.
   ========================================================================== */

[data-reveal] {
  --i: 0;
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition:
    opacity var(--dur-reveal) var(--ease-out-expo),
    transform var(--dur-reveal) var(--ease-out-expo);
  transition-delay: calc(var(--i) * 70ms * var(--motion-scale));
  will-change: opacity, transform;
}

[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* Free the compositor once the element has landed. */
[data-reveal].is-settled { will-change: auto; }

/* No JS: never leave content invisible. Beats sections.css's inline opacity:0
   via specificity, so it holds regardless of stylesheet load order. */
html:not(.js) [data-reveal],
html:not(.js) [data-reveal-child] {
  opacity: 1 !important;
  transform: none !important;
}

/* Hero entrance — plays on load rather than on scroll.
   Mirrors the critical copy in index.html's <style>; keep the two in sync. */
@media (prefers-reduced-motion: no-preference) {
  :root.js .hero-in {
    --i: 0;
    opacity: 0;
    transform: translate3d(0, 20px, 0);
  }

  :root.js .hero-in.is-revealed {
    opacity: 1;
    transform: none;
    transition:
      opacity 820ms var(--ease-out-expo),
      transform 820ms var(--ease-out-expo);
    transition-delay: calc(var(--i) * 90ms);
  }
}

/* ==========================================================================
   3. Micro-interactions
   ========================================================================== */

/* -- Focus: visible, branded, never removed --------------------------------- */
:where(a, button, [tabindex]):focus-visible {
  outline: 2.5px solid var(--accent);
  outline-offset: 3px;
  border-radius: 999px;
}

/* -- Buttons: lift + sheen -------------------------------------------------- */
.btn-fx {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
  transition:
    transform var(--dur-base) var(--ease-spring),
    box-shadow var(--dur-base) var(--ease-smooth),
    background var(--dur-base) var(--ease-smooth),
    border-color var(--dur-base) var(--ease-smooth);
}

.btn-fx::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 34%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .38), transparent);
  transform: translateX(-110%) skewX(-18deg);
  opacity: 0;
  pointer-events: none;
}

.btn-fx:hover  { transform: translateY(-2px); }
.btn-fx:active { transform: translateY(0) scale(.975); transition-duration: var(--dur-fast); }

.btn-fx:hover::after {
  opacity: 1;
  animation: shimmer 900ms var(--ease-out-quart);
}

/* -- Nav links: underline wipe ---------------------------------------------- */
.nav-fx {
  position: relative;
  transition: opacity var(--dur-base) var(--ease-smooth), color var(--dur-base) var(--ease-smooth);
}

.nav-fx::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -5px;
  height: 2px;
  width: 100%;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out-expo);
}

.nav-fx:hover,
.nav-fx.is-active { opacity: 1; }

.nav-fx:hover::after,
.nav-fx.is-active::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* -- Cards: tilt + cursor spotlight ----------------------------------------- */
.card-fx {
  position: relative;
  transform-style: preserve-3d;
  transition:
    transform var(--dur-slow) var(--ease-out-expo),
    box-shadow var(--dur-slow) var(--ease-smooth),
    border-color var(--dur-slow) var(--ease-smooth),
    opacity var(--dur-reveal) var(--ease-out-expo);
}

/* Spotlight tracks the pointer via --mx/--my written by main.js. */
.card-fx::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-smooth);
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 50%),
    rgba(239, 59, 52, .13),
    transparent 62%
  );
}

/* While the pointer drives the tilt, transform must follow instantly —
   transitioning it would lag a frame behind the cursor. It stays transitioned
   on enter/leave so the card eases in and springs back. */
.card-fx.is-tilting {
  transition:
    box-shadow var(--dur-slow) var(--ease-smooth),
    border-color var(--dur-slow) var(--ease-smooth);
}

.card-fx:hover::before { opacity: 1; }

.card-fx:hover {
  box-shadow:
    rgba(140, 20, 14, .58) 0 34px 74px -32px,
    rgba(255, 255, 255, .7) 0 1px 0 inset;
}

[data-theme="dark"] .card-fx::before {
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 90, 79, .16),
    transparent 62%
  );
}

/* Icon tile reacts to its parent card. */
.card-fx .icon-tile {
  transition: transform var(--dur-slow) var(--ease-spring), box-shadow var(--dur-slow) var(--ease-smooth);
}

.card-fx:hover .icon-tile {
  transform: translateZ(30px) scale(1.07) rotate(-4deg);
  box-shadow: rgba(184, 20, 14, .85) 0 16px 30px -10px;
}

/* ==========================================================================
   4. Chrome: scroll progress + header state
   ========================================================================== */

.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 2.5px;
  width: 100%;
  z-index: 200;
  transform: scaleX(var(--progress, 0));
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--accent-deep), var(--accent), var(--accent-soft));
  pointer-events: none;
  will-change: transform;
}

.page__root-01 {
  transition: padding var(--dur-slow) var(--ease-out-expo), box-shadow var(--dur-slow) var(--ease-smooth),
    background var(--dur-slow) var(--ease-smooth);
}

.page__root-01.is-stuck {
  box-shadow: rgba(12, 12, 13, .16) 0 10px 34px -18px;
}

.page__root-01.is-stuck .header__group-01 {
  padding-top: 9px;
  padding-bottom: 9px;
}

.header__group-01 {
  transition: padding var(--dur-slow) var(--ease-out-expo);
}

/* ==========================================================================
   5. Mobile navigation
   ========================================================================== */

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 999px;
  border: 1.5px solid rgba(12, 12, 13, .24);
  background: rgba(255, 255, 255, .34);
  color: var(--ink);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  transition: background var(--dur-base) var(--ease-smooth), border-color var(--dur-base) var(--ease-smooth);
}

[data-theme="dark"] .nav-toggle {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .18);
}

.nav-toggle__bar {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform var(--dur-base) var(--ease-out-expo), opacity var(--dur-fast) var(--ease-smooth);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; transform: scaleX(.4); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 6px;
  padding: 32px;
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(20px) saturate(1.15);
  -webkit-backdrop-filter: blur(20px) saturate(1.15);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-slow) var(--ease-out-expo), visibility var(--dur-slow);
}

.mobile-nav.is-open {
  opacity: 1;
  visibility: visible;
}

.mobile-nav__link {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(30px, 8vw, 46px);
  letter-spacing: -.03em;
  color: var(--ink);
  padding: 12px 20px;
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition:
    opacity var(--dur-slow) var(--ease-out-expo),
    transform var(--dur-slow) var(--ease-out-expo),
    color var(--dur-base) var(--ease-smooth);
}

.mobile-nav.is-open .mobile-nav__link {
  opacity: 1;
  transform: none;
  transition-delay: calc(90ms + var(--i, 0) * 60ms * var(--motion-scale));
}

.mobile-nav__link:hover { color: var(--accent); }

.mobile-nav__cta {
  margin-top: 18px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 17px;
  padding: 16px 34px;
  border-radius: 999px;
  background: var(--button-ink);
  color: var(--button-text);
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition: opacity var(--dur-slow) var(--ease-out-expo), transform var(--dur-slow) var(--ease-out-expo);
}

.mobile-nav.is-open .mobile-nav__cta {
  opacity: 1;
  transform: none;
  transition-delay: calc(90ms + var(--i, 0) * 60ms * var(--motion-scale));
}

/* Locks background scroll while the sheet is open. */
body.nav-open { overflow: hidden; }

/* The sheet sits above the sticky header (z-index 100), which would bury the
   burger and leave no way to tap it closed. Lift the header over the overlay
   so the control stays reachable and animates into its X state in place. */
body.nav-open .page__root-01 { z-index: 160; }

/* The sheet carries both CTAs, so hide the header's copies while it's open —
   otherwise they render twice in one viewport and crowd the burger. */
body.nav-open .header__link-04,
body.nav-open .header__link-05 {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-smooth), visibility var(--dur-base);
}

@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; }
}

@media (min-width: 901px) {
  .mobile-nav { display: none; }
}

/* ==========================================================================
   6. Theme toggle — View Transitions circular reveal
   The new theme is clipped in from the toggle button's position. Progressive
   enhancement: browsers without startViewTransition just swap instantly.
   ========================================================================== */

::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

::view-transition-old(root) { z-index: 1; }
::view-transition-new(root) { z-index: 2; }

/* ==========================================================================
   7. Reduced motion
   Kills ambient loops and choreography, keeps opacity so nothing is invisible.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  :root { --motion-scale: 0; }

  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  /* .hero-in needs no entry here: its hidden state is scoped to
     prefers-reduced-motion: no-preference, so it never applies. */
  [data-reveal],
  .mobile-nav__link,
  .mobile-nav__cta {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }

  .btn-fx::after,
  .card-fx::before { display: none; }

  .btn-fx:hover,
  .card-fx:hover { transform: none; }

  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none !important; }
}
