/* Porch motion kit 0.1.0 (MIG-WO-3). First-party code. README.md has the markup contract.
   Rules this file keeps:
   - Every timing, easing and distance is a --pm-* token. A theme overrides them in its own tokens.css.
   - No color or font literals (PorchOS token contract): colors come from theme roles, shades are color-mix().
   - Hidden start states apply only under html.pm-ready, which porch-motion.js adds after it has marked
     everything already on screen as shown. With JS off or failed, nothing is hidden.
   - Only opacity and transform move, so motion causes no layout shift.
   - prefers-reduced-motion: reduce stops all of it (bottom of this file, and in the JS). */

:root {
  /* Durations */
  --pm-dur-micro: 160ms;      /* button and link hover, press */
  --pm-dur-ui: 240ms;         /* header state, menu panel */
  --pm-dur-reveal: 560ms;     /* scroll reveal of one item */
  --pm-dur-enter: 640ms;      /* hero entry, once on load */
  --pm-dur-image: 420ms;      /* gallery image hover */
  --pm-dur-lightbox: 280ms;   /* PhotoSwipe open and close */

  /* Easings */
  --pm-ease-out: cubic-bezier(0.22, 1, 0.36, 1);      /* reveals, entries, image hover */
  --pm-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);   /* menu panel, header hide */
  --pm-ease-micro: cubic-bezier(0.2, 0, 0, 1);        /* buttons, links */

  /* Distances and amounts */
  --pm-reveal-distance: 16px;
  --pm-reveal-stagger: 80ms;
  --pm-reveal-stagger-max: 6;     /* items after the 6th start together */
  --pm-reveal-offset: 12%;        /* item starts when it is this far inside the bottom of the viewport */
  --pm-enter-distance: 12px;
  --pm-enter-stagger: 90ms;
  --pm-menu-distance: 8px;
  --pm-menu-item-stagger: 30ms;
  --pm-image-hover-scale: 1.03;   /* only inside links (gallery items). Never on a non-link image. */
  --pm-btn-icon-shift: 3px;
  --pm-press-shift: 1px;          /* pressed buttons move down, they never change size */
  --pm-header-offset: 24;         /* px scrolled before the header gets its scrolled state (unitless, read by JS) */
  --pm-header-shadow: 0 2px 10px color-mix(in srgb, var(--c-ink, currentColor) 10%, transparent);
  --pm-anchor-offset: 96px;       /* sticky header height plus a gap, for anchor jumps */
  --pm-smooth-lerp: 0.1;          /* Lenis smoothing, only with data-pm-smooth="lenis" (unitless, read by JS) */
  --pm-focus-ring: 2px solid var(--color-focus, currentColor);
  --pm-focus-offset: 3px;
  --pm-gsap-ease: power3.out;     /* only with data-pm-engine="gsap" (read by JS) */
}

/* ---- Anchors and native smooth scroll -------------------------------- */
html { scroll-padding-top: var(--pm-anchor-offset); }
html:not([data-pm-smooth="off"]) { scroll-behavior: smooth; }

/* ---- Scroll reveal ----------------------------------------------------- */
.pm-ready [data-pm-reveal]:not([data-pm-reveal="group"]),
.pm-ready [data-pm-reveal="group"] > * {
  transition:
    opacity var(--pm-dur-reveal) var(--pm-ease-out),
    transform var(--pm-dur-reveal) var(--pm-ease-out);
  transition-delay: calc(min(var(--pm-i, 0), var(--pm-reveal-stagger-max)) * var(--pm-reveal-stagger));
}
.pm-ready [data-pm-reveal="rise"]:not(.pm-in),
.pm-ready [data-pm-reveal=""]:not(.pm-in),
.pm-ready [data-pm-reveal="group"]:not(.pm-in) > * {
  opacity: 0;
  transform: translate3d(0, var(--pm-reveal-distance), 0);
}
.pm-ready [data-pm-reveal="fade"]:not(.pm-in) { opacity: 0; }

/* First frame after start: hidden states switch on without animating (no fade-out of off-screen items). */
.pm-init [data-pm-reveal],
.pm-init [data-pm-reveal] > * { transition: none !important; }

/* GSAP engine: GSAP owns the inline styles, so CSS transitions step aside. */
.pm-engine-gsap [data-pm-reveal],
.pm-engine-gsap [data-pm-reveal="group"] > * { transition: none; }

/* ---- Hero entry (CSS only, runs once on load, no JS needed) ------------ */
[data-pm-enter] > * {
  animation: pm-enter var(--pm-dur-enter) var(--pm-ease-out) both;
  animation-delay: calc(var(--pm-i, 0) * var(--pm-enter-stagger));
}
[data-pm-enter] > :nth-child(2) { --pm-i: 1; }
[data-pm-enter] > :nth-child(3) { --pm-i: 2; }
[data-pm-enter] > :nth-child(4) { --pm-i: 3; }
[data-pm-enter] > :nth-child(n + 5) { --pm-i: 4; }
/* The main heading never waits: it is visible on the first frame. */
[data-pm-enter] > h1,
[data-pm-enter] > :has(h1) { animation: none; }
@keyframes pm-enter {
  from { opacity: 0; transform: translate3d(0, var(--pm-enter-distance), 0); }
}

/* ---- Header states ----------------------------------------------------- */
[data-pm-header] {
  transition:
    box-shadow var(--pm-dur-ui) var(--pm-ease-out),
    background-color var(--pm-dur-ui) var(--pm-ease-out),
    transform var(--pm-dur-ui) var(--pm-ease-in-out);
}
[data-pm-header][data-pm-scrolled] { box-shadow: var(--pm-header-shadow); }
[data-pm-header][data-pm-hidden]:not(:focus-within) { transform: translate3d(0, -100%, 0); }

/* ---- Menu (overlay mode is set by JS only while the toggle is visible) - */
[data-pm-menu-toggle] { cursor: pointer; }
html:not(.pm-ready) [data-pm-menu-toggle] { display: none; }
[data-pm-menu-toggle] .pm-menu-icon { display: inline-grid; width: 20px; height: 14px; position: relative; }
[data-pm-menu-toggle] .pm-menu-icon::before,
[data-pm-menu-toggle] .pm-menu-icon::after {
  content: ""; position: absolute; left: 0; right: 0; height: 2px; border-radius: 1px; background: currentColor;
  transition: transform var(--pm-dur-ui) var(--pm-ease-in-out), top var(--pm-dur-ui) var(--pm-ease-in-out);
}
[data-pm-menu-toggle] .pm-menu-icon::before { top: 3px; }
[data-pm-menu-toggle] .pm-menu-icon::after { top: 9px; }
[data-pm-menu-toggle][aria-expanded="true"] .pm-menu-icon::before { top: 6px; transform: rotate(45deg); }
[data-pm-menu-toggle][aria-expanded="true"] .pm-menu-icon::after { top: 6px; transform: rotate(-45deg); }

[data-pm-menu][data-pm-menu-mode="overlay"] {
  position: fixed;
  inset: var(--pm-menu-top, 0px) 0 0 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 90;
  transition:
    opacity var(--pm-dur-ui) var(--pm-ease-in-out),
    transform var(--pm-dur-ui) var(--pm-ease-in-out),
    visibility 0s linear var(--pm-dur-ui);
}
[data-pm-menu][data-pm-menu-mode="overlay"]:not([data-open]) {
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, calc(-1 * var(--pm-menu-distance)), 0);
}
[data-pm-menu][data-pm-menu-mode="overlay"][data-open] { transition-delay: 0s; }
[data-pm-menu][data-pm-menu-mode="overlay"] li {
  transition: opacity var(--pm-dur-ui) var(--pm-ease-out), transform var(--pm-dur-ui) var(--pm-ease-out);
}
[data-pm-menu][data-pm-menu-mode="overlay"]:not([data-open]) li { opacity: 0; transform: translate3d(0, var(--pm-menu-distance), 0); }
[data-pm-menu][data-pm-menu-mode="overlay"][data-open] li { transition-delay: calc(var(--pm-i, 0) * var(--pm-menu-item-stagger)); }
html.pm-menu-open { overflow: hidden; }

/* ---- Buttons and links ------------------------------------------------- */
[data-pm-btn] {
  transition:
    background-color var(--pm-dur-micro) var(--pm-ease-micro),
    border-color var(--pm-dur-micro) var(--pm-ease-micro),
    color var(--pm-dur-micro) var(--pm-ease-micro),
    box-shadow var(--pm-dur-micro) var(--pm-ease-micro),
    transform var(--pm-dur-micro) var(--pm-ease-micro);
}
[data-pm-btn]:active { transform: translate3d(0, var(--pm-press-shift), 0); }
[data-pm-btn] .pm-btn__icon { display: inline-block; transition: transform var(--pm-dur-micro) var(--pm-ease-micro); }
[data-pm-btn]:hover .pm-btn__icon,
[data-pm-btn]:focus-visible .pm-btn__icon { transform: translate3d(var(--pm-btn-icon-shift), 0, 0); }
[data-pm-btn]:focus-visible,
[data-pm-gallery] a:focus-visible,
[data-pm-menu-toggle]:focus-visible { outline: var(--pm-focus-ring); outline-offset: var(--pm-focus-offset); }

/* One soft ring, once, when the button first enters the viewport. Never a loop. */
.pm-ready [data-pm-btn="attention"].pm-in { animation: pm-attention 1200ms var(--pm-ease-out) 300ms 1; }
@keyframes pm-attention {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-accent, currentColor) 45%, transparent); }
  100% { box-shadow: 0 0 0 12px color-mix(in srgb, var(--color-accent, currentColor) 0%, transparent); }
}

[data-pm-link] {
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--pm-dur-micro) var(--pm-ease-micro), text-decoration-color var(--pm-dur-micro) var(--pm-ease-micro), text-decoration-thickness var(--pm-dur-micro) var(--pm-ease-micro);
}
[data-pm-link]:hover { text-decoration-thickness: 2px; }

/* ---- Gallery (each image is a link to the large file: hover is allowed) - */
[data-pm-gallery] a { display: block; overflow: hidden; border-radius: inherit; cursor: zoom-in; }
[data-pm-gallery] a img {
  display: block;
  transition: transform var(--pm-dur-image) var(--pm-ease-out), filter var(--pm-dur-image) var(--pm-ease-out);
}
@media (hover: hover) {
  [data-pm-gallery] a:hover img,
  [data-pm-gallery] a:focus-visible img { transform: scale(var(--pm-image-hover-scale)); }
}

/* ---- Reduced motion: no movement, nothing hidden ------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  .pm-ready [data-pm-reveal],
  .pm-ready [data-pm-reveal] > *,
  [data-pm-enter] > *,
  [data-pm-menu] li {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
    transition: none !important;
  }
  [data-pm-header],
  [data-pm-menu],
  [data-pm-btn],
  [data-pm-btn] .pm-btn__icon,
  [data-pm-gallery] a img { transition-duration: 1ms !important; animation: none !important; }
  [data-pm-header][data-pm-hidden] { transform: none; }
  [data-pm-btn]:active,
  [data-pm-btn]:hover .pm-btn__icon,
  [data-pm-gallery] a:hover img,
  [data-pm-gallery] a:focus-visible img { transform: none; }
}
