@layer animations {
  /* =========================================================
     Keyframes
     ========================================================= */
  @keyframes reveal-up {
    from { opacity: 0; translate: 0 28px; }
    to { opacity: 1; translate: 0 0; }
  }

  @keyframes reveal-fade {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  @keyframes reveal-scale {
    from { opacity: 0; translate: 0 24px; scale: 0.95; }
    to { opacity: 1; translate: 0 0; scale: 1; }
  }

  @keyframes reveal-left {
    from { opacity: 0; translate: -36px 0; }
    to { opacity: 1; translate: 0 0; }
  }

  @keyframes reveal-right {
    from { opacity: 0; translate: 36px 0; }
    to { opacity: 1; translate: 0 0; }
  }

  @keyframes intro-fade {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  @keyframes intro-down {
    from { opacity: 0; translate: 0 -14px; }
    to { opacity: 1; translate: 0 0; }
  }

  @keyframes intro-up {
    from { opacity: 0; translate: 0 18px; }
    to { opacity: 1; translate: 0 0; }
  }

  @keyframes intro-line {
    from { translate: 0 108%; }
    to { translate: 0 0; }
  }

  @keyframes intro-visual {
    from { opacity: 0; translate: 0 28px; scale: 0.92; }
    to { opacity: 1; translate: 0 0; scale: 1; }
  }

  @keyframes float-y {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-10px); }
  }

  @keyframes float-y-sm {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-6px); }
  }

  @keyframes float-tilt {
    0%, 100% { transform: translateY(0) rotate(0deg); }
    50% { transform: translateY(-8px) rotate(-2deg); }
  }

  @keyframes glow-pulse {
    0%, 100% { opacity: 0.75; transform: scale(0.97); }
    50% { opacity: 1; transform: scale(1.04); }
  }

  @keyframes screen-glow {
    0%, 100% { opacity: 0.35; }
    50% { opacity: 0.85; }
  }

  @keyframes drift {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(var(--dx, 14px), var(--dy, -18px), 0); }
  }

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

  @keyframes twinkle {
    0%, 100% { opacity: 0.25; transform: scale(0.7); }
    50% { opacity: 1; transform: scale(1); }
  }

  @keyframes type-line {
    from { clip-path: inset(0 100% 0 0); }
    to { clip-path: inset(0 0 0 0); }
  }

  @keyframes caret-blink {
    0%, 49% { opacity: 1; }
    50%, 100% { opacity: 0; }
  }

  @keyframes pop-in {
    from { opacity: 0; scale: 0.8; }
    to { opacity: 1; scale: 1; }
  }

  @keyframes ring-draw {
    from { stroke-dashoffset: 100; }
    to { stroke-dashoffset: 4; }
  }

  @keyframes status-ping {
    from { transform: scale(1); opacity: 0.7; }
    to { transform: scale(2.6); opacity: 0; }
  }

  @keyframes marquee {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(-50%, 0, 0); }
  }

  @keyframes assemble {
    from { opacity: 0; transform: translate(var(--from-x, 0), var(--from-y, 36px)) scale(0.96); }
    to { opacity: 1; transform: none; }
  }

  @keyframes bar-grow {
    from { transform: scaleY(0); }
    to { transform: scaleY(1); }
  }

  @keyframes bar-grow-x {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
  }

  @keyframes draw {
    from { stroke-dashoffset: var(--len, 24); }
    to { stroke-dashoffset: 0; }
  }

  @keyframes step-activate {
    0% { background-color: var(--surface); border-color: var(--color-line-strong); color: var(--text-muted); transform: scale(1); }
    60% { transform: scale(1.14); }
    100% { background-color: var(--color-blue-600); border-color: var(--color-blue-600); color: var(--color-white); transform: scale(1); }
  }

  @keyframes pulse-ring {
    from { opacity: 0.6; transform: scale(1); }
    to { opacity: 0; transform: scale(1.7); }
  }

  @keyframes icon-wiggle {
    0%, 100% { transform: rotate(0deg) scale(1); }
    30% { transform: rotate(-12deg) scale(1.15); }
    60% { transform: rotate(8deg) scale(1.05); }
  }

  @keyframes pointer-path {
    0%, 12% { transform: translate(120%, -260%); opacity: 0; }
    22% { opacity: 1; }
    48% { transform: translate(0, 0); }
    54% { transform: translate(0, 0) scale(0.82); }
    60%, 82% { transform: translate(0, 0) scale(1); opacity: 1; }
    100% { transform: translate(0, 0); opacity: 0; }
  }

  @keyframes cta-press {
    0%, 50% { transform: scale(1); box-shadow: 0 0 0 0 rgb(37 99 235 / 0.45); }
    55% { transform: scale(0.94); }
    62% { transform: scale(1); box-shadow: 0 0 0 0.6em rgb(37 99 235 / 0); }
    100% { transform: scale(1); box-shadow: 0 0 0 0 rgb(37 99 235 / 0); }
  }

  @keyframes trail-dash {
    to { stroke-dashoffset: -110; }
  }

  @keyframes bulb-glow {
    0%, 100% { opacity: 0.45; transform: scale(0.94); }
    50% { opacity: 1; transform: scale(1.06); }
  }

  @keyframes spin-quarter {
    from { transform: rotate(0deg); }
    to { transform: rotate(90deg); }
  }

  @keyframes heartbeat {
    0%, 100% { transform: scale(1); }
    20% { transform: scale(1.18); }
    40% { transform: scale(0.96); }
    60% { transform: scale(1.1); }
  }

  @keyframes bob {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-2.5px); }
  }

  @keyframes blink {
    0%, 42%, 58%, 100% { transform: scaleY(1); }
    50% { transform: scaleY(0.1); }
  }

  @keyframes spinner {
    to { rotate: 360deg; }
  }

  @keyframes success-pop {
    from { opacity: 0; scale: 0.6; }
    to { opacity: 1; scale: 1; }
  }

  @keyframes page-in {
    from { opacity: 0; translate: 0 10px; }
    to { opacity: 1; translate: 0 0; }
  }

  @keyframes vt-out {
    to { opacity: 0; translate: 0 -8px; }
  }

  @keyframes vt-in {
    from { opacity: 0; translate: 0 14px; }
  }

  /* =========================================================
     Scroll reveal system (JS toggles .is-visible)
     ========================================================= */
  .js [data-reveal]:not(.is-visible) {
    opacity: 0;
  }

  .js [data-reveal].is-visible {
    animation: reveal-up var(--dur-4) var(--ease-out) both;
    animation-delay: calc(var(--i, 0) * var(--stagger));
  }

  .js [data-reveal="fade"].is-visible { animation-name: reveal-fade; }
  .js [data-reveal="scale"].is-visible { animation-name: reveal-scale; }
  .js [data-reveal="left"].is-visible { animation-name: reveal-left; }
  .js [data-reveal="right"].is-visible { animation-name: reveal-right; }

  /* =========================================================
     First-visit intro (≈1.4s total)
     ========================================================= */
  .intro [data-intro="logo"] {
    animation: intro-fade 600ms var(--ease-out) both;
  }

  .intro [data-intro="nav"] {
    animation: intro-down 600ms var(--ease-out) 120ms both;
  }

  .js [data-intro="line"] {
    animation: intro-line 700ms var(--ease-out) both;
    animation-delay: calc(60ms + var(--line, 0) * 80ms);
  }

  .intro [data-intro="line"] {
    animation-duration: 800ms;
    animation-delay: calc(220ms + var(--line, 0) * 110ms);
  }

  .js [data-intro="text"] {
    animation: intro-up 600ms var(--ease-out) both;
    animation-delay: calc(280ms + var(--seq, 0) * 70ms);
  }

  .intro [data-intro="text"] {
    animation-delay: calc(560ms + var(--seq, 0) * 70ms);
  }

  .js [data-intro="actions"] {
    animation: intro-up 600ms var(--ease-out) 380ms both;
  }

  .intro [data-intro="actions"] {
    animation-delay: 740ms;
  }

  .js [data-intro="visual"] {
    animation: intro-visual 900ms var(--ease-out) 150ms both;
  }

  .intro [data-intro="visual"] {
    animation-duration: 1000ms;
    animation-delay: 350ms;
  }

  /* =========================================================
     Ambient motion
     ========================================================= */
  .hero__glyphs li {
    animation: drift var(--t, 16s) ease-in-out var(--d, 0s) infinite alternate;
  }

  .hero__nodes-drift {
    animation: drift 22s ease-in-out infinite alternate;
    --dx: -24px;
    --dy: 16px;
  }

  .hero__waves path {
    animation: drift 18s ease-in-out infinite alternate;
  }

  .hero__waves path:nth-child(2) {
    --dx: -18px;
    --dy: 10px;
    animation-duration: 14s;
  }

  .hero__waves path:nth-child(3) {
    --dx: 10px;
    --dy: 14px;
    animation-duration: 20s;
  }

  .scene__glow,
  .about-visual__glow,
  .contact-visual__glow {
    animation: glow-pulse 7s ease-in-out infinite;
  }

  .scene__mascot-body,
  .about-visual__mascot img,
  .contact-visual__mascot img,
  .cta-band__visual img {
    animation: float-y 6.5s ease-in-out infinite;
  }

  .scene__screen-glow {
    animation: screen-glow 3.2s ease-in-out infinite;
  }

  .scene__editor .editor {
    animation: float-y-sm 8s ease-in-out 0.8s infinite;
  }

  .float-card--score {
    animation: float-tilt 7s ease-in-out infinite;
  }

  .orbit-token {
    animation: orbit 9s linear infinite;
  }

  .scene__sparks span {
    animation: twinkle var(--t, 3.6s) ease-in-out var(--d, 0s) infinite;
  }

  .status-dot::after {
    animation: status-ping 1.8s var(--ease-out) infinite;
  }

  .fn-chip {
    animation: float-y-sm var(--t, 6s) ease-in-out var(--d, 0s) infinite;
  }

  .cta-band__bubble {
    animation: float-tilt 6s ease-in-out infinite;
  }

  .cta-band__bubble--code {
    animation-delay: -2.5s;
  }

  .assembly__chip {
    animation: float-y-sm 7s ease-in-out infinite;
  }

  .assembly__chip--code {
    animation-delay: -3s;
  }

  .about-visual__bulb .bulb__rays,
  .story__stage .bulb__rays {
    animation: bulb-glow 2.8s ease-in-out infinite;
  }

  .btn.is-loading .btn__spinner {
    animation: spinner 0.8s linear infinite;
  }

  /* Hero editor typing (timings set by JS from each line's length).
     The typed state is the base style and `backwards` only holds the hidden frame during the delay,
     so short steps() animations can't end one step short due to float rounding. */
  .js .code-line {
    animation: type-line var(--dur, 600ms) steps(var(--chars, 20), end) var(--delay, 0ms) backwards;
  }

  .editor__caret {
    opacity: 0;
  }

  .js .editor__caret {
    animation: caret-blink 1s steps(1) var(--caret-delay, 0ms) infinite;
  }

  .js .scene__deploy .float-card {
    opacity: 0;
    animation:
      pop-in 600ms var(--ease-spring) var(--deploy-delay, 2600ms) forwards,
      float-y-sm 7s ease-in-out calc(var(--deploy-delay, 2600ms) + 600ms) infinite;
  }

  .js .ring__value {
    animation: ring-draw 1.6s var(--ease-out) 1s both;
  }

  /* Services hero assembly */
  .js .assembly__piece {
    animation: assemble 800ms var(--ease-out) both;
    animation-delay: calc(350ms + var(--i, 0) * 110ms);
  }

  .assembly__pointer {
    animation: pointer-path 6s var(--ease-in-out) 2s infinite both;
  }

  .assembly__cta {
    animation: cta-press 6s var(--ease-out) 2s infinite;
  }

  /* Contact hero trail (the plane itself flies via SVG animateMotion) */
  .contact-visual__trail {
    animation: trail-dash 6s linear infinite;
  }

  /* Why section: UI stack assembles once visible */
  .js .ui-stack .ui-stack__part {
    opacity: 0;
  }

  .js .ui-stack.is-visible .ui-stack__part {
    animation: assemble 900ms var(--ease-out) both;
    animation-delay: calc(var(--i, 0) * 140ms + 150ms);
  }

  .js .ui-stack.is-visible .ui-chart__bars span {
    animation: bar-grow 900ms var(--ease-out) both;
    animation-delay: calc(700ms + var(--b, 0) * 90ms);
  }

  .js .feature-item.is-visible .feature-item__check svg {
    animation: draw 600ms var(--ease-out) both;
    animation-delay: calc(var(--i, 0) * var(--stagger) + 300ms);
  }

  /* Journey strip (home) — sequential activation */
  .js .journey-strip__progress {
    transform: scaleY(0);
  }

  .js .journey-strip.is-visible .journey-strip__progress {
    animation: bar-grow 1.9s var(--ease-in-out) 150ms both;
  }

  .js .journey-strip.is-visible .journey-strip__marker {
    animation: step-activate 650ms var(--ease-out) both;
    animation-delay: calc(150ms + var(--i, 0) * 340ms);
  }

  /* Journey (about) — scroll driven via JS state classes */
  .journey__step.is-active .journey__marker::after {
    animation: pulse-ring 1.6s var(--ease-out) infinite;
  }

  .journey__step.is-active .journey__marker .icon {
    animation: icon-wiggle 800ms var(--ease-spring);
  }

  /* Upcoming steps keep a readable title; the description appears as the step reaches the reading line. */
  @media (prefers-reduced-motion: no-preference) {
    .js [data-scroll-steps] .journey__step:not(.is-active, .is-past) .journey__text {
      opacity: 0;
      translate: 0 8px;
    }

    .journey__step.is-active .journey__content {
      transform: translateX(6px);
    }
  }

  /* Capability icons (hover) */
  .capability .p-core,
  .capability .p-bar,
  .capability .p-left,
  .capability .p-right,
  .capability .p-spark {
    transform-box: fill-box;
    transform-origin: center;
    transition: transform var(--dur-4) var(--ease-spring);
  }

  .capability .p-bar {
    transform-origin: bottom;
  }

  .capability:hover .p-core {
    transform: rotate(90deg) scale(1.15);
  }

  .capability:hover .p-bar {
    animation: bar-grow 600ms var(--ease-spring) both;
    animation-delay: calc(var(--b, 0) * 80ms);
  }

  .capability:hover .p-left {
    transform: translateX(-2px);
  }

  .capability:hover .p-right {
    transform: translateX(2px);
  }

  .capability:hover .p-spark {
    transform: rotate(90deg) scale(1.3);
  }

  .capability:hover .p-head {
    animation: bob 700ms ease-in-out 2;
  }

  /* Value icons: play once on reveal, again on hover */
  .value svg * {
    transform-box: fill-box;
    transform-origin: center;
  }

  .value .p-rays {
    transform-box: view-box;
    transform-origin: 12px 10px;
  }

  .value.is-visible .p-rays,
  .value:hover .p-rays {
    animation: bulb-glow 1.4s ease-in-out 2;
  }

  .value .p-check {
    stroke-dasharray: 14;
    --len: 14;
  }

  .value.is-visible .p-check {
    animation: draw 700ms var(--ease-out) 400ms both;
  }

  .value:hover .p-check {
    animation: draw 600ms var(--ease-out) both;
  }

  .value.is-visible .p-person2,
  .value:hover .p-person2 {
    animation: bob 800ms ease-in-out 2;
  }

  .value.is-visible .p-heart,
  .value:hover .p-heart {
    animation: heartbeat 1.1s ease-in-out;
  }

  /* Mission / vision icons */
  .mv-card:hover .p-ring-outer {
    animation: pulse-ring 1.2s var(--ease-out);
  }

  .mv-card .p-eye {
    transform-box: fill-box;
    transform-origin: center;
  }

  .mv-card:hover .p-eye {
    animation: blink 900ms ease-in-out;
  }

  .mv-card .p-ring-outer {
    transform-box: fill-box;
    transform-origin: center;
  }

  /* Success state */
  .contact-success:not([hidden]) .contact-success__icon {
    animation: success-pop 600ms var(--ease-spring) both;
  }

  .contact-success:not([hidden]) .contact-success__icon path {
    stroke-dasharray: 30;
    --len: 30;
    animation: draw 700ms var(--ease-out) 250ms both;
  }

  .contact-success:not([hidden]) > :not(.contact-success__icon) {
    animation: intro-up 600ms var(--ease-out) both;
    animation-delay: calc(300ms + var(--seq, 0) * 80ms);
  }

  /* Ambient loops stop while their section is off screen (JS toggles .is-offscreen) */
  [data-pause-offscreen].is-offscreen,
  [data-pause-offscreen].is-offscreen * {
    animation-play-state: paused;
  }

  /* Scroll-linked drift, compositor-driven where supported; static elsewhere */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) and (min-width: 48rem) {
      [data-parallax-scroll] {
        animation: scroll-drift linear both;
        animation-timeline: view();
        animation-range: cover;
      }
    }
  }

  @keyframes scroll-drift {
    from { translate: 0 calc(var(--speed, 1) * 40px); }
    to { translate: 0 calc(var(--speed, 1) * -40px); }
  }

  /* Marquee */
  .marquee__track {
    animation: marquee var(--marquee-duration, 48s) linear infinite;
  }

  .marquee:hover .marquee__track,
  .marquee:focus-within .marquee__track,
  .marquee.is-paused .marquee__track {
    animation-play-state: paused;
  }

  /* =========================================================
     Page transitions (opt-in rule lives outside the layer, below)
     ========================================================= */
  ::view-transition-old(root) {
    animation: vt-out 180ms var(--ease-in-out) both;
  }

  ::view-transition-new(root) {
    animation: vt-in 360ms var(--ease-out) both;
  }

  ::view-transition-group(site-header) {
    animation-duration: 300ms;
    animation-timing-function: var(--ease-out);
  }

  @supports not (view-transition-name: none) {
    .js main {
      animation: page-in 450ms var(--ease-out) both;
    }
  }

  /* =========================================================
     Reduced motion: no parallax, floating, transitions or cursor
     ========================================================= */
  @media (prefers-reduced-motion: reduce) {
    html {
      scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
      animation-duration: 0.01ms !important;
      animation-delay: 0ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      transition-delay: 0ms !important;
    }

    .js [data-reveal]:not(.is-visible),
    .js .ui-stack .ui-stack__part {
      opacity: 1;
    }

    .marquee__track {
      flex-wrap: wrap;
      justify-content: center;
      width: auto;
    }

    .marquee__group {
      flex-wrap: wrap;
      justify-content: center;
      padding-right: 0;
    }

    .marquee__group[aria-hidden="true"],
    .marquee__toggle,
    .assembly__pointer,
    .contact-visual__plane {
      display: none;
    }

    .marquee__viewport {
      -webkit-mask-image: none;
      mask-image: none;
    }

    .cursor {
      display: none;
    }
  }
}

/* Cross-document view transitions: Chromium & Safari 18.2+, ignored elsewhere. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}
