/* ============================================================================
   motion.css - the site's single motion layer.

   Loaded LAST on every page (after chrome.css), so it can correct the motion
   behaviour baked into the exported Elementor/ElementsKit CSS without touching
   those large generated files.

   Contents
     1. Motion tokens (durations + easings) - one place to retune the feel
     2. Scroll-reveal system   (paired with js/scroll-reveal.js)
     3. Navigation motion      (off-canvas sheet, dropdowns, submenus, icons)
     4. Accordion / FAQ motion (paired with js/nested-accordion.js)
     5. In-page transitions the exported CSS never had (catalogue filter pills)
     6. prefers-reduced-motion kill switch

   What is deliberately NOT here: buttons, links, cards and form fields, which
   already own their transitions elsewhere - see the notes in section 4.

   RULE OF THUMB: motion here is short (0.2-0.7s), uses opacity/transform only,
   and never gates content - if a script fails, everything is still visible
   (see the safety net in js/scroll-reveal.js).
   ========================================================================== */

:root {
  /* Easings */
  --motion-ease-out: cubic-bezier(0.22, 1, 0.36, 1);   /* decelerate - entrances */
  --motion-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); /* symmetric - open/close */

  /* Durations */
  --motion-fast: 0.18s;
  --motion-quick: 0.28s;
  --motion-base: 0.38s;
  --motion-slow: 0.62s;

  /* Distance a revealing block travels */
  --motion-rise: 26px;
}

/* ============================================================================
   1. SCROLL REVEAL
   js/scroll-reveal.js adds .reveal-init (hidden start state) then .reveal-in
   (animate to rest). Direction comes from data-reveal, per-item stagger from
   the --reveal-delay custom property. These rules intentionally override the
   simpler pair that still lives in main.css.
   ========================================================================== */
.reveal-init {
  opacity: 0;
  transform: translate3d(var(--reveal-x, 0px), var(--reveal-y, var(--motion-rise)), 0)
             scale(var(--reveal-scale, 1));
}

.reveal-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--motion-slow) ease var(--reveal-delay, 0s),
              transform 0.72s var(--motion-ease-out) var(--reveal-delay, 0s);
}

/* Direction variants (js sets data-reveal per group) */
[data-reveal="fade"]  { --reveal-y: 0px; }
[data-reveal="up"]    { --reveal-y: var(--motion-rise); }
[data-reveal="left"]  { --reveal-x: -28px; --reveal-y: 0px; }
[data-reveal="right"] { --reveal-x: 28px;  --reveal-y: 0px; }
[data-reveal="zoom"]  { --reveal-y: 12px;  --reveal-scale: 0.96; }

/* Already on screen when the page loaded - show it, don't animate it. */
.reveal-instant {
  transition: none;
}

/* A revealing block nested inside another one travels less, so a section and
   the cards inside it don't stack into one oversized jump. */
.reveal-init .reveal-init { --motion-rise: 12px; }
.reveal-init .reveal-init[data-reveal="left"]  { --reveal-x: -14px; }
.reveal-init .reveal-init[data-reveal="right"] { --reveal-x: 14px; }

/* A block that has not been scrolled to yet must still exist on paper. */
@media print {
  .reveal-init {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* The catalogue gallery is an absolutely-positioned masonry whose item
   geometry is measured by js/gallery-filter.js. Fade those in only - never
   move them - so a reveal in flight can't disturb the measured layout. */
.addon-filterable-gallery-item-wrap.reveal-init {
  transform: none;
}

/* ============================================================================
   2. NAVIGATION
   ========================================================================== */

/* --- 2a. Off-canvas sheet (tablet + mobile) -------------------------------
   main.css opens the sheet by animating `left` from -100vw to 0, and the
   exported CSS paired that with a `transform 4s` transition that could never
   fire - so the menu snapped open. Park the sheet with a transform instead and
   animate THAT (compositor-only, no layout work per frame). */
@media (max-width: 1024px) {
  .navmenu-navbar-nav-default.navmenu-menu-offcanvas-elements {
    left: 0 !important;
    transform: translate3d(-100%, 0, 0);
    transition: transform 0.42s var(--motion-ease-out) !important;
  }

  .navmenu-navbar-nav-default.navmenu-menu-offcanvas-elements.active {
    transform: translate3d(0, 0, 0);
  }

  /* Backdrop: cross-fade instead of sliding in from -100% with a 0.4s delay.
     visibility is delayed to the end of the fade on close so it stops
     swallowing taps only once it is actually invisible. */
  .navmenu-menu-overlay.navmenu-menu-offcanvas-elements {
    left: 0 !important;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.35s ease, visibility 0s linear 0.35s !important;
  }

  .navmenu-menu-overlay.navmenu-menu-offcanvas-elements.active {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.35s ease, visibility 0s !important;
  }

  /* Menu rows drift in behind the sheet, top to bottom. */
  .navmenu-menu-offcanvas-elements > .navmenu-navbar-nav > li {
    opacity: 0;
    transform: translate3d(-16px, 0, 0);
    transition: opacity 0.25s ease, transform 0.3s var(--motion-ease-out);
  }

  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li {
    opacity: 1;
    transform: none;
  }

  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li:nth-child(1) { transition-delay: 0.10s; }
  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li:nth-child(2) { transition-delay: 0.15s; }
  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li:nth-child(3) { transition-delay: 0.20s; }
  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li:nth-child(4) { transition-delay: 0.25s; }
  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li:nth-child(5) { transition-delay: 0.30s; }
  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li:nth-child(6) { transition-delay: 0.35s; }
  .navmenu-menu-offcanvas-elements.active > .navmenu-navbar-nav > li:nth-child(n+7) { transition-delay: 0.40s; }

  /* The "Menu" label + close button sit in their own panel. */
  .navmenu-menu-offcanvas-elements > .navmenu-nav-identity-panel {
    opacity: 0;
    transition: opacity 0.25s ease;
  }

  .navmenu-menu-offcanvas-elements.active > .navmenu-nav-identity-panel {
    opacity: 1;
    transition: opacity 0.3s ease 0.08s;
  }

  /* --- 2b. Mobile submenus: the drill-down slide --------------------------
     A submenu is a full-width page parked just off the right edge of the sheet
     (chrome.css lays it out). Opening one slides it in while the root rows step
     aside to the left; backing out reverses both.

     Everything here is !important because the exported CSS drives these same
     panels from several competing rules - display:none/block per breakpoint, a
     max-height accordion, and a tablet-only :hover rule that would otherwise
     pull a parked page into view on a stray hover after a tap. */
  .ekit_menu_responsive_tablet .navmenu-navbar-nav-default .navmenu-dropdown {
    display: block !important;
    transform: translate3d(100%, 0, 0) !important;
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
    transition: transform 0.4s var(--motion-ease-out),
                opacity 0.26s ease,
                visibility 0s linear 0.4s !important;
  }

  .ekit_menu_responsive_tablet .navmenu-navbar-nav-default .navmenu-dropdown.navmenu-dropdown-open {
    transform: translate3d(0, 0, 0) !important;
    opacity: 1 !important;
    visibility: visible !important;
    pointer-events: auto !important;
    transition: transform 0.42s var(--motion-ease-out),
                opacity 0.3s ease,
                visibility 0s !important;
  }

  /* The root list gets out of the way. This hides each row's <a>, not its
     <li>: a dropdown parent's <li> also wraps the page that is opening. */
  .navmenu-menu-container.navmenu-submenu-view > .navmenu-navbar-nav > li > a {
    opacity: 0;
    transform: translate3d(-24px, 0, 0);
    pointer-events: none;
    transition: opacity 0.22s ease,
                transform 0.32s var(--motion-ease-out);
  }

  /* Page rows arrive just behind their page. */
  .navmenu-submenu-panel > li {
    opacity: 0;
    transform: translate3d(12px, 0, 0);
    transition: opacity 0.2s ease, transform 0.26s var(--motion-ease-out);
  }

  .navmenu-submenu-panel.navmenu-dropdown-open > li {
    opacity: 1;
    transform: none;
  }

  .navmenu-submenu-panel.navmenu-dropdown-open > li:nth-child(1) { transition-delay: 0.10s; }
  .navmenu-submenu-panel.navmenu-dropdown-open > li:nth-child(2) { transition-delay: 0.14s; }
  .navmenu-submenu-panel.navmenu-dropdown-open > li:nth-child(3) { transition-delay: 0.18s; }
  .navmenu-submenu-panel.navmenu-dropdown-open > li:nth-child(4) { transition-delay: 0.22s; }
  .navmenu-submenu-panel.navmenu-dropdown-open > li:nth-child(5) { transition-delay: 0.26s; }
  .navmenu-submenu-panel.navmenu-dropdown-open > li:nth-child(n+6) { transition-delay: 0.30s; }
}

/* --- 2c. Desktop dropdowns ------------------------------------------------
   Base state already sets opacity:0 + translateY(-10px), but only `transform`
   was transitioned, so the panel blinked in at full opacity. */
@media (min-width: 1025px) {
  .navmenu-navbar-nav-default .navmenu-dropdown {
    transition: opacity 0.22s ease,
                transform 0.28s var(--motion-ease-out),
                visibility 0s linear 0.28s;
  }

  .navmenu-nav-dropdown-hover .navmenu-dropdown-has:hover > .navmenu-dropdown {
    transition: opacity 0.22s ease,
                transform 0.28s var(--motion-ease-out),
                visibility 0s;
  }

  /* Rows cascade as the panel opens. */
  .navmenu-nav-dropdown-hover .navmenu-dropdown-has > .navmenu-dropdown > li {
    opacity: 0;
    transform: translate3d(0, -6px, 0);
    transition: opacity 0.18s ease, transform 0.24s var(--motion-ease-out);
  }

  .navmenu-nav-dropdown-hover .navmenu-dropdown-has:hover > .navmenu-dropdown > li {
    opacity: 1;
    transform: none;
  }

  .navmenu-nav-dropdown-hover .navmenu-dropdown-has:hover > .navmenu-dropdown > li:nth-child(1) { transition-delay: 0.06s; }
  .navmenu-nav-dropdown-hover .navmenu-dropdown-has:hover > .navmenu-dropdown > li:nth-child(2) { transition-delay: 0.10s; }
  .navmenu-nav-dropdown-hover .navmenu-dropdown-has:hover > .navmenu-dropdown > li:nth-child(3) { transition-delay: 0.14s; }
  .navmenu-nav-dropdown-hover .navmenu-dropdown-has:hover > .navmenu-dropdown > li:nth-child(4) { transition-delay: 0.18s; }
  .navmenu-nav-dropdown-hover .navmenu-dropdown-has:hover > .navmenu-dropdown > li:nth-child(n+5) { transition-delay: 0.22s; }
}

@media (min-width: 1025px) and (hover: hover) {
  .navmenu-dropdown-has:hover > a .navmenu-submenu-indicator {
    transform: rotate(180deg);
  }
}

/* --- 2d. Nav chrome ------------------------------------------------------- */
.navmenu-submenu-indicator {
  transition: transform 0.3s var(--motion-ease-out),
              background-color var(--motion-quick) ease,
              border-color var(--motion-quick) ease;
}

.navmenu-menu-nav-link,
.navmenu-menu-container .dropdown-item {
  transition: background-color var(--motion-quick) ease,
              color var(--motion-quick) ease,
              border-radius var(--motion-quick) ease;
}

/* Icons nudge with their row. */
.navmenu-menu-nav-link .nav-menu-icon,
.dropdown-item .submenu-icon {
  transition: transform var(--motion-quick) var(--motion-ease-out);
}

.navmenu-menu-nav-link:hover .nav-menu-icon,
.dropdown-item:hover .submenu-icon {
  transform: translateX(2px);
}

/* button-hover.css deliberately excludes these two from its global rise, so
   they get their own gestures here. */
.navmenu-menu-hamburger,
button.navmenu-menu-close {
  transition: transform 0.25s var(--motion-ease-out),
              background-color var(--motion-quick) ease,
              color var(--motion-quick) ease,
              opacity var(--motion-fast) ease;
}

.navmenu-menu-hamburger:hover,
.navmenu-menu-hamburger:focus-visible {
  transform: scale(1.08);
}

button.navmenu-menu-close:hover,
button.navmenu-menu-close:focus-visible {
  transform: rotate(90deg);
}

/* ============================================================================
   3. ACCORDIONS / FAQ
   js/nested-accordion.js animates the panel height; everything else that reads
   as "the FAQ feels smooth" is here.
   ========================================================================== */
.e-n-accordion-item-title {
  transition: background-color var(--motion-base) ease,
              color var(--motion-base) ease,
              border-color var(--motion-base) ease;
}

.e-n-accordion-item-title-icon {
  transition: transform 0.35s var(--motion-ease-out);
}

/* Plus rotates into the minus rather than swapping on the spot. */
.e-n-accordion-item[open] > .e-n-accordion-item-title .e-n-accordion-item-title-icon {
  transform: rotate(180deg);
}

.e-n-accordion-item-title-icon span > svg {
  transition: fill var(--motion-base) ease;
}

/* Answer copy settles in just behind the opening panel. */
.e-n-accordion-item[open] > .e-con > * {
  animation: ma-accordion-copy-in 0.42s var(--motion-ease-out) 0.1s both;
}

@keyframes ma-accordion-copy-in {
  from { opacity: 0; transform: translate3d(0, 8px, 0); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================================
   4. IN-PAGE TRANSITIONS
   ========================================================================== */

/* Catalogue category filter pills */
.addon-filter-gallery-control ul li.control {
  transition: background-color var(--motion-quick) ease,
              color var(--motion-quick) ease,
              border-color var(--motion-quick) ease,
              transform var(--motion-fast) var(--motion-ease-out);
}

.addon-filter-gallery-control ul li.control:hover {
  transform: translateY(-1px);
}

/* --- Product lightbox -----------------------------------------------------
   js/lightbox.js swaps display:none for display:flex, so this has to be a
   keyframe animation - a transition cannot run across a display change. The
   close is animated too: lightbox.js keeps .is-open on while .is-closing plays,
   then drops both (it skips the wait entirely under reduced motion). */
.mesh-lightbox.is-open {
  animation: ma-lightbox-in 0.22s ease forwards;
}

.mesh-lightbox.is-open .mesh-lightbox__inner {
  animation: ma-lightbox-pop-in 0.3s var(--motion-ease-out) forwards;
}

.mesh-lightbox.is-closing {
  animation: ma-lightbox-out 0.18s ease forwards;
}

.mesh-lightbox.is-closing .mesh-lightbox__inner {
  animation: ma-lightbox-pop-out 0.18s ease forwards;
}

/* Paging with the arrows re-triggers this, so the new photo fades in rather
   than popping the moment it decodes. */
.mesh-lightbox__img {
  animation: ma-lightbox-img-in 0.26s ease forwards;
}

@keyframes ma-lightbox-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes ma-lightbox-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

@keyframes ma-lightbox-pop-in {
  from { opacity: 0; transform: scale(0.96) translate3d(0, 10px, 0); }
  to   { opacity: 1; transform: none; }
}

@keyframes ma-lightbox-pop-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: scale(0.97); }
}

@keyframes ma-lightbox-img-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* NOTE ON BODY COPY, LINKS, FORM FIELDS AND BUTTONS: those already carry their
   own transitions - css/button-hover.css for every button, page-blog.css and
   page-sportswear.css for article links, form.css for inputs. Restating them
   here would replace those transition lists with a narrower one (the shorthand
   is not additive), so this file leaves them to the sheets that own them.

   NOTE ON THE TOOL PAGES: the fabric encyclopedia (#fenc) and the consumption
   calculator (#fcalc) are self-contained apps whose scoped CSS already carries
   `transition: all 0.2s` on their tabs, filters, cards and buttons, and whose
   panels are swapped with display toggles driven by their own scripts. Adding
   rules here would narrow those transitions and fight their show/hide logic, so
   this file deliberately leaves them alone - they inherit only the shared nav,
   accordion and reduced-motion behaviour above. */

/* ============================================================================
   5. REDUCED MOTION
   One switch: no entrances, no travel, no cascades. State changes still apply
   instantly, so every control keeps working.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .reveal-init,
  .reveal-in {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .e-n-accordion-item[open] > .e-con > *,
  .mesh-lightbox.is-open,
  .mesh-lightbox.is-open .mesh-lightbox__inner,
  .mesh-lightbox.is-closing,
  .mesh-lightbox.is-closing .mesh-lightbox__inner,
  .mesh-lightbox__img {
    animation: none !important;
  }

  .navmenu-menu-offcanvas-elements > .navmenu-navbar-nav > li,
  .navmenu-menu-offcanvas-elements > .navmenu-nav-identity-panel,
  .navmenu-nav-dropdown-hover .navmenu-dropdown-has > .navmenu-dropdown > li {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    transition-delay: 0s !important;
  }

  .navmenu-menu-hamburger:hover,
  .navmenu-menu-hamburger:focus-visible,
  button.navmenu-menu-close:hover,
  button.navmenu-menu-close:focus-visible,
  .navmenu-menu-nav-link:hover .nav-menu-icon,
  .dropdown-item:hover .submenu-icon,
  .addon-filter-gallery-control ul li.control:hover {
    transform: none !important;
  }

  .e-n-accordion-item[open] > .e-n-accordion-item-title .e-n-accordion-item-title-icon {
    transform: none !important;
  }

  /* Desktop only: the chevron's flip is motion, but off-canvas its rotation is
     just which way the arrow points - killing that would aim it down again. */
  @media (min-width: 1025px) {
    .navmenu-dropdown-has:hover > a .navmenu-submenu-indicator {
      transform: none !important;
    }
  }

  @media (max-width: 1024px) {
    .navmenu-navbar-nav-default.navmenu-menu-offcanvas-elements {
      transition: none !important;
    }

    /* The drill-down page still swaps in, it just doesn't travel. Both states
       are listed: the open one re-declares its own transition at a higher
       weight, so silencing the closed state alone still leaves it sliding. */
    .ekit_menu_responsive_tablet .navmenu-navbar-nav-default .navmenu-dropdown,
    .ekit_menu_responsive_tablet .navmenu-navbar-nav-default .navmenu-dropdown.navmenu-dropdown-open {
      transition: none !important;
    }

    .navmenu-menu-container.navmenu-submenu-view > .navmenu-navbar-nav > li > a {
      transform: none !important;
      transition: none !important;
    }
  }
}
