/* ACD motion engine (UPGRADE_PLAN_2026-10-05.md Phase 4d, Datum). One easing and three durations for every effect.
   Visible by default: nothing is hidden unless motion is allowed (prefers-reduced-motion: no-preference) and either
   scroll-driven animation is supported or assets/motion/motion.js has marked the page with .motion-on. Only opacity,
   transform and stroke-dashoffset move. Layered !important beats the legacy kill switch in website.css until
   Phase 6 removes it. Hooks: data-reveal on a block (fade and 12 px rise) and data-draw on an SVG whose shapes carry
   pathLength="1" (draw once). The hero image and the h1 never take a hook. */
@layer motion {
  :root { --ease-datum: cubic-bezier(.22,1,.36,1); --dur-quick: 160ms; --dur-base: 420ms; --dur-slow: 900ms; }
  @keyframes datum-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
  @keyframes datum-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  @keyframes datum-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
  @media (prefers-reduced-motion: no-preference) {
    @supports (animation-timeline: scroll()) {
      .scroll-progress { height: 1px !important; width: 100% !important; background: var(--spark, var(--warm)) !important; transform-origin: 0 50%; transition: none !important; animation: datum-progress linear both !important; animation-timeline: scroll(root) !important; }
    }
    /* Focus draw-in: the ring rests 6 px out and draws in to the legacy 2 px (important, unlayered) over 160 ms. */
    a, button, input, select, textarea, summary, [tabindex] { outline-offset: 6px; }
    :focus-visible { transition: outline-offset var(--dur-quick) var(--ease-datum); }
    @supports (animation-timeline: view()) {
      [data-reveal] { animation: datum-rise linear both !important; animation-timeline: view() !important; animation-range: entry 0% cover 25% !important; }
      [data-draw] [pathLength] { stroke-dasharray: 1; animation: datum-draw linear both !important; animation-timeline: view() !important; animation-range: entry 10% cover 40% !important; }
    }
    .motion-on [data-reveal] { transition: opacity var(--dur-base) var(--ease-datum), transform var(--dur-base) var(--ease-datum) !important; }
    .motion-on [data-reveal]:not([data-in]) { opacity: 0; transform: translateY(12px); }
    .motion-on [data-draw] [pathLength] { stroke-dasharray: 1; transition: stroke-dashoffset var(--dur-slow) var(--ease-datum) !important; }
    .motion-on [data-draw]:not([data-in]) [pathLength] { stroke-dashoffset: 1; }
  }
  @media (prefers-reduced-motion: reduce) { .scroll-progress { display: none !important; } }
  @media print { [data-reveal], [data-draw] [pathLength] { animation: none !important; opacity: 1 !important; transform: none !important; stroke-dashoffset: 0 !important; } }
}
/* Phase 5b hero drafting grid: the canvas hero-grid.js inserts sits behind the hero copy and under the render. */
@layer motion {
  .experience-hero:has(> .hero-grid) { position: relative; }
  .experience-hero:has(> .hero-grid) > :not(.hero-grid) { position: relative; }
  .hero-grid { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
  @media print { .hero-grid { display: none; } }
}
/* Phase 5c kinetic serif headlines below the fold (never the hero h1). Line spans (.kl) are in the HTML, so nothing is
   split at run time. Each line rises out of a clip on a view() timeline; the italic gets a Warm pen-stroke underline.
   Only transform and clip-path move. Without view() support, under reduced motion and in print, the final state shows. */
@layer motion {
  [data-kinetic] .kl { display: block; }
  /* A view() timeline binds to the nearest scroll container, and overflow: hidden makes one that never scrolls, so the
     headline's section clips instead: same paint, same formatting context (flow-root), no scroll container. */
  :is(.work, .immersive, .tech, .process, .services, .sectors, .contact):has([data-kinetic]) { overflow: clip !important; display: flow-root !important; }
  [data-kinetic] em { position: relative; }
  [data-kinetic] em::after { content: ''; position: absolute; left: 0; right: 0; bottom: .02em; height: 1px; background: var(--warm); transform-origin: 0 50%; pointer-events: none; }
  @keyframes datum-line { from { clip-path: inset(100% -10% -40% -10%); transform: translateY(.45em); } to { clip-path: inset(-40% -10% -40% -10%); transform: none; } }
  @keyframes datum-pen { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  @media (prefers-reduced-motion: no-preference) {
    @supports (animation-timeline: view()) {
      [data-kinetic] .kl { animation: datum-line linear both !important; animation-timeline: view() !important; animation-range: entry 10% cover 30% !important; }
      [data-kinetic] .kl + .kl { animation-range: entry 25% cover 35% !important; }
      [data-kinetic] em::after { animation: datum-pen linear both !important; animation-timeline: view() !important; animation-range: cover 12% cover 30% !important; }
    }
  }
  @media print { [data-kinetic] .kl, [data-kinetic] em::after { animation: none !important; clip-path: none; transform: none; } }
}
