/* ==========================================================================
   NEWTECHWOOD // KINETIC — choreography layer
   ==========================================================================
   Ported from mockups/kinetic/. This file adds MOTION ONLY: it never changes
   layout, colour or type, so the site looks identical with JS off and
   identical again under prefers-reduced-motion.

   Contract with the existing theme:
     - js/motion.js owns gsap.ticker + Lenis and adds `.has-motion` to <html>
       ONLY when motion is actually running. Every pre-animation state here is
       gated on `.has-motion`, so a no-JS or reduced-motion visitor never sees
       a hidden element.
     - The nav keeps its existing markup and open/close logic untouched;
       js/kinetic.js observes `.is-open` and animates what is already there.
   ========================================================================== */

:root {
  --kin-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --kin-dur-ui: 240ms;
}


/* ==========================================================================
   1. CURTAIN — injected by js/kinetic.js, removed after the intro.
   ========================================================================== */
.kin-curtain { position: fixed; inset: 0; z-index: 9999; display: flex; pointer-events: none; }
.kin-curtain__panel { flex: 1; background: var(--color-ink, #101312); }
.kin-curtain__mark {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-family: var(--font-primary); font-weight: 700;
  font-size: clamp(1rem, 2.2vw, 1.75rem); letter-spacing: .52em;
  color: #fff; text-indent: .52em;
}
/* Clips to the line box, so the wordmark's ±110% exit actually leaves frame.
   Descender room keeps the glyph tails from being shaved while it sits still. */
.kin-curtain__mark-clip { display: block; overflow: hidden; padding-bottom: .12em; }
.kin-curtain__mark-text { display: block; will-change: transform; }
/* Scroll is locked only while the curtain is up. */
html.kin-intro, html.kin-intro body { overflow: hidden; }


/* ==========================================================================
   2. CURSOR — desktop pointers only.
   ========================================================================== */
.kin-cursor { position: fixed; inset: 0; pointer-events: none; z-index: 9000; display: none; }
@media (hover: hover) and (pointer: fine) {
  .has-motion .kin-cursor { display: block; }
}
.kin-cursor__dot, .kin-cursor__ring { position: absolute; top: 0; left: 0; border-radius: 50%; }
.kin-cursor__dot {
  width: 6px; height: 6px; margin: -3px 0 0 -3px;
  background: var(--color-ink, #101312);
  transition: opacity 200ms ease;
}
.kin-cursor__ring {
  width: 42px; height: 42px; margin: -21px 0 0 -21px;
  border: 1px solid rgba(16, 19, 18, .38);
  transition: border-color 260ms ease, background-color 260ms ease;
}

/* Interactive targets: the ring takes the brand green as an OUTLINE and
   thickens slightly. No fill and no label — a solid disc with uppercase
   micro-type is the loudest thing on an otherwise restrained page. */
.kin-cursor.is-hot .kin-cursor__ring {
  border-color: var(--color-primary, #007A33);
  border-width: 2px;
}

/* Colour chips get the opposite treatment. The cursor must never cover the
   sample being judged, so over a swatch the ring contracts to a fine
   reticle and the dot steps out of the way entirely. */
.kin-cursor.is-precise .kin-cursor__ring {
  border-color: rgba(16, 19, 18, .55);
  border-width: 1px;
}
.kin-cursor.is-precise .kin-cursor__dot { opacity: 0; }

/* Over photography the ring needs to read light. */
.kin-cursor.is-dark .kin-cursor__ring { border-color: rgba(255,255,255,.6); }
.kin-cursor.is-dark .kin-cursor__dot { background: #fff; }
.kin-cursor.is-dark.is-hot .kin-cursor__ring { border-color: #fff; }


/* ==========================================================================
   3. MASKED LINE REVEALS
   SplitText wraps each line in .kin-line; the inner span is what moves.
   ========================================================================== */
.has-motion .kin-line { overflow: hidden; display: block; }
.has-motion .kin-mask-pending { visibility: hidden; }


/* ==========================================================================
   4. HEADER — both rows, always.
   ==========================================================================
   Previously two rules fought over the utility bar: style.css:1408 folds it
   away over a hero and unfolds it at 40px of scroll, and an earlier KINETIC
   `condensed` state collapsed it again past 80px. Between those thresholds
   sat a narrow band — roughly 40-80px down — where both rows appeared and
   then vanished again, which read as a bug.

   The bar now simply stays. Over a hero it goes transparent and its text
   turns white so it sits on the film; once the header settles it picks up
   its normal surface. Nothing folds, nothing collapses, no thresholds.
   ========================================================================== */
.has-overlay-header .header-utility {
  transition: background-color 400ms ease, border-color 400ms ease, color 400ms ease;
}

/* Override the fold-away: keep full height and opacity at the top. */
.has-overlay-header .site-header:not(.is-scrolled) .header-utility {
  max-height: 80px;
  opacity: 1;
  background: transparent;
  border-bottom-color: transparent;
}

/* The header's own top gradient (style.css:1396) supplies the darkening
   these need to stay legible over bright photography. */
.has-overlay-header .site-header:not(.is-scrolled) .header-utility__menu a,
.has-overlay-header .site-header:not(.is-scrolled) .header-utility__phone {
  color: var(--color-white);
}
.has-overlay-header .site-header:not(.is-scrolled) .header-utility__menu a:hover,
.has-overlay-header .site-header:not(.is-scrolled) .header-utility__phone:hover {
  color: var(--color-white);
  opacity: 0.78;
}

/* Utility icons are dark artwork; invert them while the bar is transparent. */
.has-overlay-header .site-header:not(.is-scrolled) .header-utility__menu img,
.has-overlay-header .site-header:not(.is-scrolled) .header-utility__menu svg {
  filter: brightness(0) invert(1);
}


/* ==========================================================================
   5. MEGA PANEL — structure and behaviour unchanged; contents now arrive.
   ========================================================================== */
.has-motion .mega-panel__cell,
.has-motion .mega-panel__column { will-change: transform, opacity; }

/* Thumbnails settle rather than snap. */
.mega-panel__thumb img { transition: transform 620ms var(--kin-ease-out); }
.mega-panel__item:hover .mega-panel__thumb img { transform: scale(1.06); }
.mega-panel__item, .mega-panel__column-link { transition: transform 380ms var(--kin-ease-out); }
.mega-panel__column-link:hover { transform: translateX(6px); }


/* ==========================================================================
   6. TICKER
   ========================================================================== */
/* Template-declared insertion point (js/kinetic.js). Collapses to nothing when
   the bar is never built — no motion, or no GSAP. */
.kin-ticker-slot:empty { display: none; }

.kin-ticker {
  background: var(--color-ink, #101312); color: #fff;
  overflow: hidden; padding: .9rem 0;
}
.kin-ticker__row { display: flex; align-items: center; gap: 2.2rem; white-space: nowrap; width: max-content; }
.kin-ticker__row span {
  font-size: var(--fs-meta, .8125rem); text-transform: uppercase; letter-spacing: .18em;
}
.kin-ticker__row i { color: var(--color-primary, #007A33); font-style: normal; font-size: .6rem; }


/* ==========================================================================
   7. BUTTONS — the fill wipes instead of cross-fading.
   Scoped to existing button classes; colours are inherited, not redefined.
   ========================================================================== */
.has-motion .btn,
.has-motion .button,
.has-motion .wp-block-button__link { position: relative; overflow: hidden; z-index: 0; }
.has-motion .btn > *,
.has-motion .button > * { position: relative; z-index: 2; }
.has-motion .btn::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: currentColor; opacity: .14;
  transform: scaleX(0); transform-origin: left center;
  transition: transform 520ms var(--kin-ease-out);
}
.has-motion .btn:hover::after { transform: scaleX(1); }


/* ==========================================================================
   8. SAMPLER — the swatch chips and the scene stage.
   The scene crossfade (a 0.5s opacity transition in style.css) is handed
   over to GSAP, which wipes it along the boards instead.
   ========================================================================== */
.has-motion .home-sampler__scene { transition: none; }
.has-motion .home-sampler__stage { will-change: transform; }

/* The bright edge that rides the wipe. */
.kin-sweep {
  position: absolute; top: 0; bottom: 0; width: 90px; left: 0;
  opacity: 0; pointer-events: none; z-index: 5;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.7), transparent);
}


/* ==========================================================================
   9. LINEUP TABS — a rule that travels between tabs.
   ========================================================================== */
/* Positioned from the top and driven by the active tab's own box, so it
   still lands correctly if the strip wraps onto a second row. */
.kin-tab-ink {
  position: absolute; top: 0; left: 0; height: 3px; width: 0;
  background: var(--color-primary, #007A33);
  pointer-events: none; z-index: 2;
}

/* home-lab.js fades panels with a 180ms CSS opacity transition and an
   .is-entering pre-state. GSAP takes the movement; leaving the transition on
   would double-animate the swap. */
.has-motion .lab-panel { transition: none; }


/* ==========================================================================
   10. NO HORIZONTAL SCROLLING
   ==========================================================================
   Three controls hid their own options behind a sideways swipe on a phone.
   Nothing signals that content continues off-screen, so options simply go
   unseen — and this audience is the least likely to go hunting for them.
   Measured at 375px before the fix:
     .home-lineup__strip   335px visible / 1242px content →  907px hidden
     .section-nav__inner   375px visible /  827px content →  452px hidden
   Everything below trades the swipe for wrapping. Nothing is ever hidden.
   ========================================================================== */

/* Let the tab strip wrap at ANY width rather than clip. On desktop the six
   tabs already fit one row, so this changes nothing there. */
.home-lineup__strip {
  overflow-x: visible;
  flex-wrap: wrap;
}

@media (max-width: 900px) {
  /* Phones get a two-up grid of pills: every option on screen at once,
     each a full-height tap target instead of a thin underlined word. */
  .home-lineup__strip {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.5rem;
    border-bottom: 0;
    margin-bottom: var(--space-md, 2rem);
  }

  .home-lineup__strip .lab-tab {
    min-width: 0;
    padding: 0.9rem 0.85rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm, 6px);
    text-align: center;
    white-space: normal;      /* long labels wrap instead of forcing width */
    font-size: 1.0625rem;
    line-height: 1.25;
    background-color: var(--color-white);
  }

  .home-lineup__strip .lab-tab.is-active {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-white);
  }

  /* The travelling rule is a one-row idea; the filled pill carries state. */
  .kin-tab-ink { display: none; }
}

/* Section nav (category, series and colors pages) wraps to as many rows
   as it needs on TABLETS ONLY. The links are already pills, so wrapped
   rows read fine, and static beats a 203px permanent sticky block.

   Phones (≤768px) are handled by the Mobile Port block in style.css
   instead: a sticky "On this page ▾" dropdown built by js/site.js.
   These wrapped-pill rules must not reach that range — position:static
   here would un-stick the dropdown. */
@media (min-width: 769px) and (max-width: 900px) {
  .section-nav {
    position: static;
    top: auto;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--color-bg-alt);
  }

  .section-nav__inner { overflow-x: visible; }

  .section-nav__list {
    flex-wrap: wrap;
    gap: 0.4rem;
    justify-content: flex-start;
    padding-block: 0.75rem;
  }

  /* Tighter pills so six options land in two rows rather than four. */
  .section-nav__link {
    padding: 0.45rem 0.8rem;
    line-height: 1.2;
  }
}


/* ==========================================================================
   11. MOBILE NAV — thumbnails on one axis.
   .mobile-nav__sublink sets justify-content:center, and the --tile variant
   only overrode flex-direction — so every row centred itself and the
   thumbnails stepped in and out with each label's width. Left-justify the
   tiles so the images form a single clean column.
   ========================================================================== */
.mobile-nav__sublink--tile { justify-content: flex-start; }


/* ==========================================================================
   12. REDUCED MOTION — everything above is inert.
   motion.js already refuses to add .has-motion under reduced motion, so most
   of this file simply never applies. These are the belt-and-braces cases.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .kin-curtain, .kin-cursor, .kin-sweep { display: none !important; }
  html.kin-intro, html.kin-intro body { overflow: auto; }
  .kin-ticker__row { animation: none !important; transform: none !important; }
  .mega-panel__thumb img,
  .mega-panel__item,
  .mega-panel__column-link { transition: none !important; }
}
