/* LIMM / Material futures. Shared motion; cinematic Home composition. */
:root {
  --motion-ease: cubic-bezier(.22, 1, .36, 1);
  --midnight: #061820;
  --mint: #b4ead8;
}

/* Cross-document transitions are an enhancement; normal links always work. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: 260ms ease both page-out; }
::view-transition-new(root) { animation: 600ms var(--motion-ease) both page-in; }
@keyframes page-out { to { opacity: 0; } }
@keyframes page-in { from { opacity: 0; transform: translateY(18px); } }

.reading-progress {
  position: fixed; inset: 0 0 auto; height: 2px; z-index: 150;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  pointer-events: none;
}
/* Scroll reveal — the single definition; tokens.css no longer carries one.
   main.js adds .is-in from an IntersectionObserver, so the hidden starting
   state is gated on the `js` class every page writes onto <html> in its head.
   With scripting off nothing ever adds .is-in and the reader would otherwise
   be left with a blank page, so the plain .reveal is fully visible.
   Both halves of the gate sit inside :where(), which keeps this rule at the
   same (0,1,0) weight the bare .reveal had, so the .motion-paused and
   reduced-motion overrides further down still win on source order alone. */
.reveal {
  transition: opacity 900ms var(--motion-ease), transform 1100ms var(--motion-ease);
}
:where(html.js) .reveal:where(:not(.is-in)) {
  opacity: 0;
  transform: translateY(32px);
}
.motion-heading { overflow: clip; }
.motion-heading.is-seen { animation: heading-arrive 1100ms var(--motion-ease) both; }
@keyframes heading-arrive {
  from { opacity: .15; transform: translateY(22px); clip-path: inset(100% 0 0); }
  to { opacity: 1; transform: none; clip-path: inset(0); }
}
.motion-image { overflow: hidden; }
.motion-image img {
  transition: transform 1400ms var(--motion-ease), filter 1000ms var(--motion-ease);
}
@media (hover: hover) and (pointer: fine) {
  .motion-image:hover img { transform: scale(1.055); }
  .btn:hover, .pill:hover { transform: translateY(-2px); }
}
.btn, .pill { transition-duration: 450ms; transition-timing-function: var(--motion-ease); }
.menu { transition-duration: 700ms; transition-timing-function: var(--motion-ease); }
.menu__link { transform: translateY(28px); opacity: 0; transition: opacity 450ms, transform 700ms var(--motion-ease); }
.menu.is-open .menu__link { transform: none; opacity: 1; }
.menu.is-open .menu__link:nth-child(2) { transition-delay: 50ms; }
.menu.is-open .menu__link:nth-child(3) { transition-delay: 100ms; }
.menu.is-open .menu__link:nth-child(4) { transition-delay: 150ms; }
.menu.is-open .menu__link:nth-child(5) { transition-delay: 200ms; }
.menu.is-open .menu__link:nth-child(6) { transition-delay: 250ms; }
/* The motion switch sits in the Home hero foot and in every inner-page
   chapter foot, so its base styling belongs with the shared motion rules. */
.motion-toggle { display: inline-flex; align-items: center; gap: 8px; padding: 10px 0 10px 15px; color: #dbe9e4; border-left: 1px solid #b7d8d540; font-size: 8px; letter-spacing: .07em; text-transform: uppercase; }
.motion-toggle[hidden] { display: none; }
.motion-toggle__icon { font-size: 14px; }

@media (max-width: 700px) {
  .motion-toggle { font-size: 7px; }
}

/* User controls override all decorative motion, including existing effects. */
html.motion-paused { scroll-behavior: auto; }
.motion-paused *, .motion-paused *::before, .motion-paused *::after { animation: none !important; transition: none !important; }
.motion-paused .reveal { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
  .motion-heading { animation: none !important; }
  .reveal { opacity: 1; transform: none; }
  .motion-image:hover img { transform: none; }
}
