/* ==========================================================================
   motion-fx.css — homepage motion refinements, round 2 (after scroll-fx).

   Adds: hero text entrance, cursor-entry button fills, cursor-aware image
   pan/zoom, the footer reveal, and the drifting SVG backdrops. Same ground
   rules as scroll-fx.css: no library, transform/opacity/filter only (no
   layout → no CLS), pointer effects only on (hover:hover)+(pointer:fine)
   devices, everything behind prefers-reduced-motion: no-preference.
   pointer-fx.js supplies --fx-x/--fx-y (button entry point) and
   --fx-mx/--fx-my (normalised cursor position over an image frame).

   Image pan/zoom uses the individual translate/scale properties, NOT
   transform — scroll-fx.css's scroll-driven animations own `transform` on
   the same images, and the two compose instead of fighting.
   ========================================================================== */

/* ---- Hero text entrance ---------------------------------------------------
   Each title line rises out of its own clip box; the "trichology" ornament
   drifts in from the right and un-blurs (a transition from the
   .js:not(.is-ready) state — pointer-fx.js stamps .is-ready post-paint —
   so with JS off the ornament simply stays put). */
.hero-line { display: block; }
.hero-line-in { display: block; }

@media (prefers-reduced-motion: no-preference) {
  /* negative margin + equal padding grows the clip box so descenders and
     the comma survive overflow:hidden at line-height 1.02 */
  .hero-line { overflow: hidden; margin: -0.16em; padding: 0.16em; }
  .hero-line-in { animation: fx-line-rise 800ms cubic-bezier(0.22, 1, 0.36, 1) both 80ms; }
  .hero-line:nth-child(2) .hero-line-in { animation-delay: 220ms; }

  .js .hero-ornament {
    transition: opacity 1100ms ease 500ms,
                translate 1100ms cubic-bezier(0.22, 1, 0.36, 1) 500ms,
                filter 1100ms ease 500ms;
  }
  .js:not(.is-ready) .hero-ornament { opacity: 0; translate: 30px 0; filter: blur(8px); }
}

@keyframes fx-line-rise { from { transform: translateY(118%); } }

/* ---- Buttons: fill sweeps out from the cursor's entry point ---------------
   The ::after disc sits at the pointer's entry coordinates and scales up on
   hover; on leave pointer-fx.js re-anchors it to the exit point so it
   retreats the way the cursor left. The old flat hover bg-swaps stand down
   (the disc now supplies the hover colour); label/border colours keep their
   existing transitions. Touch devices keep the original hover styles. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .btn { position: relative; overflow: hidden; isolation: isolate; }
  .btn::after {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    left: var(--fx-x, 50%); top: var(--fx-y, 50%);
    width: max(250%, 140px); aspect-ratio: 1; border-radius: 50%;
    translate: -50% -50%; scale: 0;
    transition: scale 480ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .btn:hover::after, .btn:focus-visible::after { scale: 1; }

  .btn--primary:hover { background: var(--cypress); }
  .btn--primary::after { background: var(--cypress-deep); }
  .btn--jet:hover { background: var(--jet); }
  .btn--jet::after { background: #000; }
  .btn--outline:hover { background: transparent; }
  .btn--outline::after { background: var(--jet); }
  .btn--outline-light:hover { background: transparent; }
  .btn--outline-light::after { background: var(--paper); }
  .btn--whatsapp:hover { background: #6e7450; }
  .btn--whatsapp::after { background: #5c6242; }
  /* let the disc cover most of the button before the label flips colour */
  .btn--outline, .btn--outline-light {
    transition: background-color var(--t-hover), color 240ms ease 80ms,
                border-color var(--t-hover), transform var(--t-hover);
  }
}

/* ---- Images: cursor-aware pan + settle zoom ------------------------------
   The image leans toward the cursor (magnetic look-around) and eases back on
   leave. Travel budgets stay inside the overdraw scroll-fx's parallax scale
   already provides, so no frame edge is ever revealed. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .hero-img, .hero-collage__main img, .texture-panel > img, .divider-panel > img {
    --fx-pan: 8px;
    translate: calc(var(--fx-mx, 0) * var(--fx-pan))
               calc(var(--fx-my, 0) * var(--fx-pan));
    scale: var(--fx-zoom, 1);
    transition: translate 340ms cubic-bezier(0.2, 0.8, 0.2, 1),
                scale 700ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* the hero plate is its own frame (no clipping parent) — whole-element
     drift, so keep it smaller and barely zoomed */
  .hero-img, .hero-collage__main img { --fx-pan: 6px; }
  .hero-figure:hover .hero-img,
  .hero-collage:hover .hero-collage__main img { --fx-zoom: 1.02; }
  .texture-panel:hover > img, .divider-panel:hover > img { --fx-zoom: 1.04; }
}

/* ---- Footer reveal ---------------------------------------------------------
   Two geometries:
   - Base (mobile / short viewports): the colophon content rises softly as
     the footer enters — native scroll-driven animation, with the .sfx-js
     custom-property fallback riding scroll-fx.js's --sfx-cover.
   - Wide+tall viewports (footer < viewport): the classic curtain — the page
     lifts away over a footer pinned behind it. Pure positioning, no JS. */
@media (prefers-reduced-motion: no-preference) and (max-width: 1099.98px),
       (prefers-reduced-motion: no-preference) and (max-height: 699.98px) {
  @supports (animation-timeline: view()) {
    :root:not(.sfx-js) .site-footer { view-timeline: --fx-foot block; }
    :root:not(.sfx-js) .site-footer > .wrap {
      animation: fx-foot-rise linear both;
      animation-timeline: --fx-foot;
      animation-range: entry 0% entry 45%;
    }
  }
  .sfx-js .site-footer > .wrap {
    opacity: calc(0.55 + min(var(--sfx-cover, 1) / 0.3, 1) * 0.45);
    transform: translateY(calc(max(0, 1 - var(--sfx-cover, 1) / 0.3) * 36px));
  }
}
@media (prefers-reduced-motion: no-preference) and (min-width: 1100px) and (min-height: 700px) {
  main {
    position: relative; z-index: 1;
    background: var(--paper);
    box-shadow: 0 30px 70px rgba(33, 35, 34, 0.28);
  }
  .site-footer { position: sticky; bottom: 0; }
}
@keyframes fx-foot-rise { from { transform: translateY(36px); opacity: 0.55; } }

/* ---- Drifting SVG backdrops (hero + booking) -------------------------------
   motion.dev-style ambient shapes in brand tones: soft gradient orbs, dashed
   measurement rings, a specimen dot grid. Each shape is its own positioned
   <svg> animated at the element level (guaranteed compositor layer). Under
   reduced motion the shapes stay as a static composition. */
.hero, .booking { position: relative; }
.hero > .wrap, .booking > .wrap { position: relative; z-index: 1; }

/* The shapes deliberately overflow their sections and wash into neighbours
   (only the thin opaque toc strip interrupts them); the horizontal excess is
   clipped at the root so it can never cause horizontal panning. (clip on
   body alone does NOT propagate to the viewport — html must carry it; clip
   creates no scroll container, so sticky header/footer keep working.) */
html, body { overflow-x: clip; }
.fx-bg { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.fx-bg svg { position: absolute; height: auto; }

.fx-orb--a { width: clamp(340px, 54vw, 780px); top: -20%; right: -12%; color: var(--sage); }
.fx-orb--b { width: clamp(280px, 40vw, 600px); bottom: -18%; left: -14%; color: var(--stucco); }
.fx-ring--a { width: clamp(160px, 20vw, 320px); top: 6%; left: 4%; color: var(--cypress); opacity: 0.3; }

.fx-orb--book { width: clamp(320px, 44vw, 640px); top: -20%; left: -10%; color: var(--sage); }
.fx-ring--book { width: clamp(150px, 18vw, 280px); bottom: 8%; right: 3%; color: var(--cypress); opacity: 0.3; }

@media (prefers-reduced-motion: no-preference) {
  .fx-orb--a { animation: fx-drift-a 22s ease-in-out infinite alternate; }
  .fx-orb--b { animation: fx-drift-b 28s ease-in-out infinite alternate; }
  .fx-orb--book { animation: fx-drift-b 26s ease-in-out infinite alternate; }
  .fx-ring--a, .fx-ring--book { animation: fx-spin 60s linear infinite; }
}

@keyframes fx-drift-a {
  from { transform: translate3d(-5%, 6%, 0) scale(1); }
  to   { transform: translate3d(6%, -6%, 0) scale(1.12); }
}
@keyframes fx-drift-b {
  from { transform: translate3d(5%, -4%, 0) scale(1.08); }
  to   { transform: translate3d(-6%, 5%, 0) scale(1); }
}
@keyframes fx-spin { to { transform: rotate(360deg); } }
