/* ==========================================================================
   Haus Hunduren — motion & texture layer
   Optional. Loads after hunduren-blocks.css. Everything here is additive:
   remove the file and the layout is unchanged.

   Principles
   - Nothing moves more than 24px or lasts longer than 1.1s.
   - Blur is used as an *arrival* state only, never a resting state.
   - Grain sits above the page at very low opacity; it never touches text sharpness.
   - Every effect is off under prefers-reduced-motion.
   ========================================================================== */

:root {
  --hd-ease-soft: cubic-bezier(0.22, 0.61, 0.36, 1);
  --hd-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --hd-dur-slow: 1.05s;
  --hd-dur-mid: 0.72s;
  --hd-dur-fast: 0.42s;
  --hd-rise: 22px;
  --hd-blur-in: 14px;
  --hd-grain-opacity: 0.035;
}

/* ==========================================================================
   1. Grain — a fixed film-grain plate over the whole page
   SVG fractal noise, so there is no image request and no canvas.
   ========================================================================== */

body::after {
  content: "";
  position: fixed;
  inset: -50%;
  z-index: 1;
  pointer-events: none;
  opacity: var(--hd-grain-opacity);
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  will-change: transform;
  animation: hd-grain-drift 6s steps(6) infinite;
}

@keyframes hd-grain-drift {
  0%   { transform: translate3d(0, 0, 0); }
  20%  { transform: translate3d(-3%, 2%, 0); }
  40%  { transform: translate3d(2%, -3%, 0); }
  60%  { transform: translate3d(-2%, -2%, 0); }
  80%  { transform: translate3d(3%, 1%, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* NOTE — do not add `body > * { position: relative; z-index: N }` here.
   Blocksy emits `.ct-drawer-canvas` on wp_body_open, BEFORE #main-container,
   and that canvas holds the offcanvas mobile menu (.ct-panel, z-index 999999)
   plus the Companion cookie banner. Giving body's children a z-index turns the
   drawer canvas into a stacking context, traps those 999999 children at the
   parent's level, and lets the later #main-container paint straight over both.
   The plate does not need it: it is fixed at z-index 1, so it already sits
   above static page content, while real overlays keep their own high z-index. */

/* Print / export never inherits the texture. */
@media print {
  body::after,
  .wp-block-group.has-background::before,
  .hd-hero::before { display: none !important; }

  /* Never print a mid-reveal state. */
  [data-hd-reveal],
  .hd-hero__line,
  .hd-hero__attribution,
  .hd-hero__media img {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
}

/* Heavier grain inside a colour band — the gold reads flat without it */
.wp-block-group.has-background,
.hd-hero {
  position: relative;
  isolation: isolate;
}
.wp-block-group.has-background::before,
.hd-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}
/* Lift content above the grain plate. Scoped with :not() so it never disturbs
   an absolutely-positioned child — `> *` would silently reset those to static
   flow, which cost the hero's scroll hint its anchoring. */
.wp-block-group.has-background > *:not([style*="position:absolute"]):not([style*="position: absolute"]),
.hd-hero > *:not(.hd-hero__scroll) {
  position: relative;
  z-index: 1;
}
/* Absolutely-positioned children just need the stacking level, not the mode. */
.wp-block-group.has-background > *,
.hd-hero > * { z-index: 1; }

/* Opt-out for a band that should stay perfectly clean */
.wp-block-group.is-style-hunduren-no-grain::before { display: none; }

/* ==========================================================================
   2. Reveal on scroll
   JS adds [data-hd-reveal] then .is-in. Elements are hidden ONLY when JS has
   marked the document (.hd-motion) — no-JS visitors see everything.
   ========================================================================== */

.hd-motion [data-hd-reveal] {
  opacity: 0;
  transform: translate3d(0, var(--hd-rise), 0);
  filter: blur(6px);
  transition:
    opacity var(--hd-dur-mid) var(--hd-ease-soft),
    transform var(--hd-dur-slow) var(--hd-ease-out),
    filter var(--hd-dur-mid) var(--hd-ease-soft);
  transition-delay: var(--hd-delay, 0ms);
  will-change: opacity, transform, filter;
}
.hd-motion [data-hd-reveal].is-in {
  opacity: 1;
  transform: none;
  filter: none;
}
.hd-motion [data-hd-reveal].is-in { will-change: auto; }

/* Softer, blur-led variant for images and media */
.hd-motion [data-hd-reveal="media"] {
  transform: translate3d(0, calc(var(--hd-rise) * 0.6), 0) scale(1.02);
  filter: blur(var(--hd-blur-in));
  transition:
    opacity var(--hd-dur-slow) var(--hd-ease-soft),
    transform 1.4s var(--hd-ease-out),
    filter var(--hd-dur-slow) var(--hd-ease-soft);
}
.hd-motion [data-hd-reveal="media"].is-in { transform: none; }

/* Headline lines cascade — set by JS as --hd-delay per line */
.hd-motion .hd-hero__line,
.hd-motion .hd-hero__attribution {
  opacity: 0;
  transform: translate3d(0, 0.42em, 0);
  filter: blur(10px);
  transition:
    opacity var(--hd-dur-slow) var(--hd-ease-soft),
    transform 1.15s var(--hd-ease-out),
    filter var(--hd-dur-slow) var(--hd-ease-soft);
  transition-delay: var(--hd-delay, 0ms);
}
.hd-motion .hd-hero.is-in .hd-hero__line,
.hd-motion .hd-hero.is-in .hd-hero__attribution {
  opacity: 1;
  transform: none;
  filter: none;
}

/* ==========================================================================
   3. Hero media — very slow settle, no looping pan
   ========================================================================== */

.hd-motion .hd-hero__media { overflow: hidden; }
.hd-motion .hd-hero__media img {
  transform: scale(1.06);
  filter: blur(10px) saturate(0.92);
  opacity: 0;
  transition:
    transform 2.4s var(--hd-ease-out),
    filter 1.4s var(--hd-ease-soft),
    opacity 1.2s var(--hd-ease-soft);
}
.hd-motion .hd-hero.is-in .hd-hero__media img {
  transform: scale(1);
  filter: none;
  opacity: 1;
}

/* Note box drifts up a touch later than the headline it belongs to */
.hd-motion .hd-hero__note,
.hd-motion .hd-hero__kicker { --hd-delay: 620ms; }

/* ==========================================================================
   4. Hover states — soft, slow, never bouncy
   ========================================================================== */

/* Every image tile clips its own image. Without this a hovered scale on a
   bleeding tile grows past the viewport edge, the document gains a horizontal
   scrollbar for the duration of the hover, and the page shifts under the
   pointer — the jump that made bleeds feel broken. */
.wp-block-image { overflow: hidden; }

/* The transition belongs on every image, not just the cropped ones. Bleeding
   tiles used to be excluded here while the :hover rule below still applied to
   them, so they snapped to the scaled size in one frame instead of easing. */
.wp-block-image img {
  transition: transform 1.4s var(--hd-ease-out), filter 0.8s var(--hd-ease-soft);
}
.wp-block-image:hover img { transform: scale(1.025); }

/* Collage tiles get the same slow zoom. They already clip, so the scale never
   reaches past the tile's own area. */
.hd-collage__img {
  transition: transform 1.4s var(--hd-ease-out), filter 0.8s var(--hd-ease-soft);
}
.hd-collage__item--image:hover .hd-collage__img { transform: scale(1.025); }

.wp-block-button__link,
.gform_wrapper .gform_button,
input[type="submit"] {
  transition:
    background-color 0.45s var(--hd-ease-soft),
    color 0.45s var(--hd-ease-soft),
    border-color 0.45s var(--hd-ease-soft),
    letter-spacing 0.45s var(--hd-ease-soft);
}
.wp-block-button__link:hover { letter-spacing: 0.08em; }

.wp-block-button.is-style-hunduren-link .wp-block-button__link {
  background-image: linear-gradient(var(--hd-text), var(--hd-text));
  background-repeat: no-repeat;
  background-size: 0% 1px;
  background-position: 0 100%;
  transition: background-size 0.55s var(--hd-ease-out), color 0.45s var(--hd-ease-soft);
}
.wp-block-button.is-style-hunduren-link .wp-block-button__link:hover { background-size: 100% 1px; }

.ct-header .ct-menu-link,
.is-style-hunduren-footer a {
  transition: opacity 0.35s var(--hd-ease-soft), color 0.35s var(--hd-ease-soft);
}
.is-style-hunduren-footer a:hover { opacity: 0.72; }

/* Form fields: the underline grows from the left on focus */
.gform_wrapper :is(input[type="text"], input[type="email"], input[type="tel"], input[type="url"], input[type="number"], select, textarea) {
  background-image: linear-gradient(var(--hd-gold), var(--hd-gold));
  background-repeat: no-repeat;
  background-size: 0% 1px;
  background-position: 0 100%;
  transition: background-size 0.6s var(--hd-ease-out), border-color 0.4s var(--hd-ease-soft);
}
.gform_wrapper :is(input, select, textarea):focus { background-size: 100% 1px; }

/* ==========================================================================
   5. Sticky header wash
   ========================================================================== */

body.hd-nav-scrolled .ct-header [data-row="middle"],
[data-sticky] .ct-header [data-row="middle"] {
  backdrop-filter: blur(10px) saturate(1.1);
  transition: background-color 0.5s var(--hd-ease-soft), backdrop-filter 0.5s var(--hd-ease-soft);
}

/* ==========================================================================
   6a. Hard off-switch
   Set by the script when it detects that the host's animation clock is frozen
   (see the outcome audit in hunduren-motion.js). Must out-specify anything a
   stalled transition is still holding, hence !important.
   ========================================================================== */

.hd-no-motion [data-hd-reveal],
.hd-no-motion .hd-hero__line,
.hd-no-motion .hd-hero__attribution,
.hd-no-motion .hd-hero__media img,
.hd-no-motion .hd-hero__note,
.hd-no-motion .hd-hero__kicker {
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
  transition: none !important;
  animation: none !important;
}

/* ==========================================================================
   6. Reduced motion — texture stays, movement goes
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  body::after { animation: none; }
  .hd-motion [data-hd-reveal],
  .hd-motion [data-hd-reveal="media"],
  .hd-motion .hd-hero__line,
  .hd-motion .hd-hero__attribution,
  .hd-motion .hd-hero__media img {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
  .wp-block-image:hover img,
  .wp-block-button__link:hover { transform: none; letter-spacing: inherit; }
}
