/* ==========================================================================
   OSTUGRUPP — MOTION
   One rhythm for the whole shop: press feedback, honest loading, and a hover
   layer that stops lying on touch screens.

   WHY THIS FILE EXISTS
   Before it, the theme had ~190 `:hover` rules and exactly THREE `:active`
   rules across 36 stylesheets (cart-sticky-bar.css:153, woocommerce.css:324,
   woocommerce.css:723). 73% of this shop's traffic is phones, where `:hover`
   is not a state a finger can produce — so for three quarters of the shop,
   almost nothing acknowledged a tap. A control that does not answer a press
   feels broken even when it works perfectly.

   Durations were scattered too: .2s (195×), .18s (59×), .15s (31×), .25s,
   .3s, .16s, .28s, .22s, .4s, .35s, .12s, .5s — no system behind any of it.
   Meanwhile the design pack already ships --dur-fast, --dur and --ease
   (assets/css/tokens.css:295-297) and NOTHING referenced them.

   HOW IT IS SCOPED — read this before adding a selector
   • This file must load LAST. It wins by source order, not by specificity
     inflation: nearly every rule here is the same weight as the `:hover` rule
     it sits beside. If it is enqueued before another stylesheet that declares
     a `:hover` transform on the same element, the press state loses.
   • Payment is untouchable (CLAUDE.md invariant 1). No rule here may reach
     the checkout's right-hand order column. The generic WooCommerce-button
     nets below are fenced with a two-clause `body:not(...):not(...)` — one
     clause for the checkout and pay-for-order page, one for the account page
     that adds a saved method (see 2h for why one class is not enough). The
     checkout's own coupon and login forms are named explicitly instead,
     because they sit OUTSIDE `#customer_details` (documented in
     checkout-fields.css:24-26) and would otherwise be left with no press
     feedback at all.
   • Animate transform and opacity only. Nothing here animates width, height,
     top or left, so no rule in this file can trigger a layout pass.
   • Press = 120ms in, release = 200ms out. That is deliberately the opposite
     of the usual "exit shorter than enter" rule, and the deviation is on
     purpose: that rule is about things that appear and dismiss. A press is
     not an appearance — a physical button snaps down and settles back up, and
     every native platform models it that way. This file animates no
     dismissal, so nothing here is governed by the other convention.

   ONE RULE LIVES IN THE ORDER COLUMN, ON PURPOSE
   The parcel-machine picker (`.og-pickup__*`) renders inside `#order_review`
   (inc/pickup-points.php:394). It is a theme-owned class emitted by exactly
   one file, so it cannot match markup produced by any gateway — and on a
   phone it is the most-tapped control on the whole checkout. It is called out
   here so an auditor finds it in one search rather than by accident.
   ========================================================================== */


/* ==========================================================================
   0 · THE RHYTHM
   Four names, all aliases onto the pack tokens. Aliasing rather than copying
   means the reduced-motion override in tokens.css:303-306 — which sets
   --dur-fast and --dur to 0ms — flows through this file for free.
   ========================================================================== */
:root {
  --og-press: var(--dur-fast, 120ms);                     /* finger down    */
  --og-move:  var(--dur, 200ms);                          /* release, hover */
  --og-ease:  var(--ease, cubic-bezier(.2, .6, .3, 1));
}
/* There is no --og-exit here. "Exit shorter than enter" governs things that
   appear and then dismiss — drawers, modals, toasts — and every one of those
   is owned by another stylesheet. This file animates no dismissal, so an
   exit duration would be a token nothing consumes. */


/* ==========================================================================
   1 · THE FOCUS RING IS INSTANT, EVERYWHERE
   a11y.css:41-47 draws the keyboard ring with `outline` + `box-shadow`. Five
   rules in the theme declare `transition: all` — main.css:166 (.btn-primary,
   .btn-secondary), main.css:177 (.card-premium), blog.css:114, blog.css:151,
   blog.css:229 — and `all` covers outline-width, outline-color and
   box-shadow. On those five the ring GROWS over 200ms while it snaps
   instantly everywhere else. A focus ring that arrives late is the one piece
   of motion in a shop that is never an improvement.

   Every group below that keeps `box-shadow` in its transition list repeats
   this `transition-duration: 0s` line, so the ring never fades anywhere.
   Zeroing the duration is used instead of rewriting five property lists, so
   no element silently loses a transition it relied on.
   ========================================================================== */
.btn-primary:focus-visible,
.btn-secondary:focus-visible,
.card-premium:focus-visible,
.card-premium a:focus-visible,
.blog-tags__chip:focus-visible,
.blog-cats__chip:focus-visible,
.blog-postnav__link:focus-visible,
.blog-pagination .page-numbers:focus-visible {
  transition-duration: 0s;
}


/* ==========================================================================
   2 · PRESS FEEDBACK
   Four scales, chosen by target size so the movement reads as the same
   physical depth on a 44px icon as on a 320px full-width CTA:

     .97   large solid CTA        .96   neutral / outline control
     .90   small icon button      .985  card-sized tap target

   Text links get opacity instead of transform: `transform` does nothing on a
   non-replaced inline element, so a scale on an inline link is a rule that
   looks applied in DevTools and moves nothing on screen.

   Every base rule declares `transition-property` explicitly. Several targets
   (.ostu-searchform__btn at pages.css:37, .header-account at main.css:215)
   transition `background` ONLY, so retiming alone would have left their press
   scale to jump with no animation at all.
   ========================================================================== */

/* --- 2a · Solid brand CTAs -------------------------------------------------
   The pressed colour is --brand-active (tokens.css:13) — the token the pack
   added for exactly this state, labelled "VAJUTATUD. Seni puudus täielikult",
   and which nothing in the theme had used yet.
   NOTE: .og-mega__promo-cta:hover animates `gap` (nav.css). That property is
   not carried over here on purpose — animating gap animates layout. The gap
   change still happens, it just no longer eases. */
.btn-primary,
.single-product form.cart .button,
.single-product .single_add_to_cart_button,
.product-card__actions .button,
.product-card__actions a.add_to_cart_button,
.product-card .button,
.product-card a.add_to_cart_button,
.wc-proceed-to-checkout a.checkout-button,
.woocommerce-cart .return-to-shop .button,
.og-cartbar__btn,
.sticky-atc__btn,
.ostu-qv-product__buy .button,
.ostu-cs-card .ostu-cs-card__add,
.ostu-fbt-card .ostu-fbt-card__add,
.ostu-bundle__add,
.ostu-wl-card__actions .button,
.ostu-cmp-table__add,
.og-mega__promo-cta,
.ostu-price-apply {
  transition-property: transform, background-color, border-color, color, box-shadow;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.btn-primary:focus-visible,
.single-product form.cart .button:focus-visible,
.single-product .single_add_to_cart_button:focus-visible,
.product-card__actions .button:focus-visible,
.product-card__actions a.add_to_cart_button:focus-visible,
.product-card .button:focus-visible,
.product-card a.add_to_cart_button:focus-visible,
.wc-proceed-to-checkout a.checkout-button:focus-visible,
.woocommerce-cart .return-to-shop .button:focus-visible,
.og-cartbar__btn:focus-visible,
.sticky-atc__btn:focus-visible,
.ostu-qv-product__buy .button:focus-visible,
.ostu-cs-card .ostu-cs-card__add:focus-visible,
.ostu-fbt-card .ostu-fbt-card__add:focus-visible,
.ostu-bundle__add:focus-visible,
.ostu-wl-card__actions .button:focus-visible,
.ostu-cmp-table__add:focus-visible,
.og-mega__promo-cta:focus-visible,
.ostu-price-apply:focus-visible {
  transition-duration: 0s;
}

.btn-primary:active,
.single-product form.cart .button:active,
.single-product .single_add_to_cart_button:active,
.product-card__actions .button:active,
.product-card__actions a.add_to_cart_button:active,
.product-card .button:active,
.product-card a.add_to_cart_button:active,
.og-cartbar__btn:active,
.sticky-atc__btn:active,
.ostu-qv-product__buy .button:active,
.ostu-cs-card .ostu-cs-card__add:active,
.ostu-fbt-card .ostu-fbt-card__add:active,
.ostu-bundle__add:active,
.ostu-wl-card__actions .button:active,
.ostu-cmp-table__add:active,
.og-mega__promo-cta:active,
.ostu-price-apply:active {
  transform: scale(.97);
  background-color: var(--brand-active, #024430);
  transition-duration: var(--og-press, 120ms);
}

/* The two cart CTAs whose base AND hover backgrounds are !important
   (woocommerce.css:958-959, 1111-1117). Same weight, later file — so the
   press colour needs the same flag or the hover colour simply stays put. */
.wc-proceed-to-checkout a.checkout-button:active,
.woocommerce-cart .return-to-shop .button:active {
  transform: scale(.97);
  background: var(--brand-active, #024430) !important;
  transition-duration: var(--og-press, 120ms);
}

/* --- 2b · Neutral, outline and secondary controls --------------------------
   No solid brand fill to darken, so the pressed cue is the pack's own
   secondary-surface tint --brand-a2 (tokens.css:80, documented as "teisese
   nupu hover, kiip"). It is also the cue that SURVIVES prefers-reduced-motion
   once the scale is removed. */
.btn-secondary,
.ostu-chip,
.ostu-gc__chip,
.blog-tags__chip,
.blog-cats__chip,
.ostu-filters-mobile-trigger,
.ostu-wl-btn--single,
.ostu-cmp-btn--single,
.ostu-psec-nav__link,
.ostu-share__btn,
.ostu-searchform__btn,
.home-seasonal__cta,
.product-card .added_to_cart,
.product-card.outofstock .button,
.single-product .woocommerce-product-gallery__trigger,
.error-404__chips a,
.blog-pagination a.page-numbers,
.woocommerce-pagination a.page-numbers,
.search-results__pagination a.page-numbers {
  transition-property: transform, background-color, border-color, color, box-shadow;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.btn-secondary:focus-visible,
.ostu-chip:focus-visible,
.ostu-gc__chip:focus-visible,
.ostu-filters-mobile-trigger:focus-visible,
.ostu-wl-btn--single:focus-visible,
.ostu-cmp-btn--single:focus-visible,
.ostu-psec-nav__link:focus-visible,
.ostu-share__btn:focus-visible,
.ostu-searchform__btn:focus-visible,
.home-seasonal__cta:focus-visible,
.product-card .added_to_cart:focus-visible,
.product-card.outofstock .button:focus-visible,
.single-product .woocommerce-product-gallery__trigger:focus-visible,
.error-404__chips a:focus-visible,
.woocommerce-pagination a.page-numbers:focus-visible,
.search-results__pagination a.page-numbers:focus-visible {
  transition-duration: 0s;
}

.btn-secondary:active,
.ostu-chip:active,
.ostu-gc__chip:active,
.blog-tags__chip:active,
.blog-cats__chip:active,
.ostu-filters-mobile-trigger:active,
.ostu-wl-btn--single:active,
.ostu-cmp-btn--single:active,
.ostu-psec-nav__link:active,
.ostu-share__btn:active,
.ostu-searchform__btn:active,
.home-seasonal__cta:active,
.product-card .added_to_cart:active,
.product-card.outofstock .button:active,
.single-product .woocommerce-product-gallery__trigger:active,
.error-404__chips a:active,
.blog-pagination a.page-numbers:active,
.woocommerce-pagination a.page-numbers:active,
.search-results__pagination a.page-numbers:active {
  transform: scale(.96);
  background-color: var(--brand-a3, rgb(4 120 87/.20));
  transition-duration: var(--og-press, 120ms);
}

/* The pack's alpha ladder gives hover = --brand-a2 (.12, tokens.css:80,
   "teisese nupu hover, kiip") but names no pressed step. Pressed must read as
   MORE than hover or the press disappears the moment a latched hover is also
   on the element — which on a phone is always. Hence --brand-a3 (.20) above:
   the chips in filters.css:88 already sit at .08 with a .14 hover, so a .12
   press would have been LIGHTER than hovering. */

/* The two frosted-glass icon buttons that float over a product photo
   (wishlist.css:12, and the compare twin in woocommerce.css). Their rest
   background is rgba(255,255,255,.92); replacing that with a translucent
   green tint would drop them to near-invisible over a dark photo, so these
   press with scale + a border that darkens instead. 38px control, so .90. */
.ostu-wl-btn--card,
.ostu-cmp-btn--card {
  transition-property: transform, background-color, border-color, color, box-shadow;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.ostu-wl-btn--card:focus-visible,
.ostu-cmp-btn--card:focus-visible {
  transition-duration: 0s;
}
.ostu-wl-btn--card:active,
.ostu-cmp-btn--card:active {
  transform: scale(.90);
  border-color: var(--brand-active, #024430);
  transition-duration: var(--og-press, 120ms);
}

/* Variation swatches are split in two, because a colour swatch carries the
   PRODUCT's colour as an inline style on the button itself and the chip
   inside mirrors it with `background: inherit` (swatches.css:73-84). A tint
   there would either lose to the inline style (silently doing nothing) or
   win and paint the real product colour green. Colour swatches dim instead. */
.ostu-swatch:active {
  transform: scale(.96);
  transition-duration: var(--og-press, 120ms);
}
.ostu-swatch--pill:active {
  background-color: var(--brand-a3, rgb(4 120 87/.20));
}
.ostu-swatch--colour:active {
  opacity: .78;
}

/* Cart-page secondary buttons. woocommerce.css:1026-1081 sets their hover
   background !important; on a phone the latched :hover and the live :active
   both match, so without the flag the press cue is swallowed by the hover
   colour and the tap reads as unanswered. */
.woocommerce-cart table.cart td.actions .ostu-continue-shopping:active,
.woocommerce-cart table.cart td.actions button[name="apply_coupon"]:active,
.woocommerce button[name="update_cart"]:not([disabled]):not([aria-disabled="true"]):active {
  transform: scale(.96);
  background: var(--brand-a3, rgb(4 120 87/.20)) !important;
  transition-duration: var(--og-press, 120ms);
}

/* The cart's remove "×". woocommerce.css:855-856 flips it to solid red on
   hover, also !important. Pressed = one shade deeper, so the tap that deletes
   a line from the basket confirms itself before the page reloads. */
.woocommerce a.remove {
  transition-property: transform, background-color, border-color, color;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.woocommerce a.remove:active {
  background: var(--state-error-active, #7f1d1d) !important;
  color: #fff !important;
  transition-duration: var(--og-press, 120ms);
}

/* --- 2c · Small icon-only buttons ------------------------------------------
   44px squares: closes, drawer toggle, mini-cart controls, back-to-top.
   A .90 scale on a 44px box moves ~4px — enough to read at arm's length,
   small enough not to look like a bounce. */
.og-drawer-toggle,
.og-drawer__close,
.og-drawer__search button,
.header-search button,
.mini-cart__close,
.mini-cart__item-remove,
.og-popup__close,
.ostu-qv__close,
.og-sproof__close,
.ostu-filters__close,
.ostu-cmp-bar__slot-remove,
.ostu-wl-card__remove,
.ostu-cmp-table__remove,
.site-footer__social-link {
  transition-property: transform, background-color, border-color, color;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}

.og-drawer-toggle:active,
.og-drawer__close:active,
.og-drawer__search button:active,
.header-search button:active,
.mini-cart__close:active,
.og-popup__close:active,
.ostu-qv__close:active,
.og-sproof__close:active,
.ostu-filters__close:active,
.ostu-cmp-bar__slot-remove:active,
.ostu-wl-card__remove:active,
.ostu-cmp-table__remove:active,
.site-footer__social-link:active {
  transform: scale(.90);
  transition-duration: var(--og-press, 120ms);
}

/* Press colour, by SURFACE family. The scale is the cue that reduced motion
   removes, so every one of these carries a colour as well — and because the
   colour is declared out here rather than inside the reduced-motion block, a
   user who turns motion off loses the movement and keeps the answer. */
.og-drawer-toggle:active,
.mini-cart__close:active,
.mini-cart__item-remove:active,
.og-popup__close:active,
.ostu-qv__close:active,
.og-sproof__close:active,
.ostu-wl-card__remove:active,
.ostu-cmp-table__remove:active {
  background-color: var(--brand-a3, rgb(4 120 87/.20));
}

/* Solid green search buttons (main.css:211, nav.css) take the pressed-brand
   token, not a tint — a translucent green over solid green is not a state. */
.header-search button:active,
.og-drawer__search button:active {
  background: var(--brand-active, #024430);
}

/* The drawer close and the filter close already hover to a light red
   (nav.css, filters.css). A green press on top of a latched red hover reads
   as mud, so these deepen the red they are already speaking. */
.og-drawer__close:active,
.ostu-filters__close:active {
  background: var(--danger-a3, rgb(185 28 28/.20));
  color: var(--state-error, #b91c1c);
}

/* The footer sits on --surface-inverse, where a brand tint at .20 is close to
   invisible. tokens.css:110 ships the on-dark ladder for exactly this. */
.site-footer__social-link:active {
  background: var(--on-dark-a3, rgb(255 255 255/.20));
}

/* ⚠ .mini-cart__item-remove is centred BY a transform — cart-widget.css gives
   it `position:absolute; top:50%; transform:translateY(-50%)`. A bare
   `scale(.90)` replaces that translate and drops the × 12px down its own row
   on every press. `transform` is one declaration, not a list; a press state on
   any element already carrying a transform must COMPOSE, never overwrite.
   (a11y.css:178-186 records the last time this button was reset by a rule
   that did not know about its positioning — it shipped, and the × landed on
   top of the thumbnail.) */
.mini-cart__item-remove:active {
  transform: translateY(-50%) scale(.90);
  transition-duration: var(--og-press, 120ms);
}

/* .ostu-qv__close rotates 90° on hover (quickview.css). With a pointer, hover
   and active are both live during a click, so the press has to carry the
   rotation with it or the × visibly un-rotates under the finger. On touch the
   hover transform is already cancelled in section 3, so the plain scale above
   is the correct one there. */
@media (hover: hover) {
  .ostu-qv__close:active {
    transform: rotate(90deg) scale(.90);
  }
}

/* The quantity stepper is the most repeatedly tapped control in the cart, and
   the only one a shopper fires four times in a row. It gets colour AS WELL AS
   scale so each individual tap lands as its own event rather than a blur of
   movement. A disabled stepper answers nothing — an unresponsive control must
   not pretend otherwise (cart-widget.css:270 already dims it). */
.qty-stepper .qty-stepper__btn {
  transition-property: transform, background-color, color;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.qty-stepper .qty-stepper__btn:not(:disabled):active {
  transform: scale(.90);
  background: var(--brand-active, #024430);
  color: #fff;
  transition-duration: var(--og-press, 120ms);
}

/* --- 2d · Header account / cart / wishlist ---------------------------------
   main.css:215 transitions `background` only, so `transform` has to be named
   here or the scale would jump instead of animating. */
.header-account,
.header-cart,
.header-wishlist {
  transition-property: transform, background-color, color;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.header-account:active,
.header-cart:active,
.header-wishlist:active {
  transform: scale(.94);
  background-color: var(--brand-a3, rgb(4 120 87/.20));
  transition-duration: var(--og-press, 120ms);
}

/* --- 2e · Card-sized tap targets -------------------------------------------
   `:active` propagates up the activation chain, so a card whose button is
   pressed would otherwise scale TOO — a double press, one nested inside the
   other. The `:has()` guard hands the press to whichever control was actually
   touched. `:has()` is already used in this theme (checkout-review.css:313);
   where it is unsupported the whole rule is dropped and the card simply has
   no press state, which is the behaviour that exists today. */
.product-card,
.home-cat,
.home-prop,
.home-mini-card,
.blog-postnav__link,
.ostu-cs-card,
.ostu-fbt-card,
.ostu-rev-photos__item,
.woocommerce ul.products li.product.product-category > a {
  transition-property: transform, background-color, border-color, box-shadow;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.blog-postnav__link:focus-visible,
.ostu-rev-photos__item:focus-visible,
.woocommerce ul.products li.product.product-category > a:focus-visible {
  transition-duration: 0s;
}

.product-card:active:not(:has(.button:active, button:active, a.added_to_cart:active, .product-card__tools a:active)),
.home-cat:active:not(:has(button:active)),
.home-prop:active,
.home-mini-card:active,
.blog-postnav__link:active,
.ostu-cs-card:active:not(:has(.ostu-cs-card__add:active)),
.ostu-fbt-card:active:not(:has(.ostu-fbt-card__add:active)),
.ostu-rev-photos__item:active,
.woocommerce ul.products li.product.product-category > a:active {
  transform: scale(.985);
  transition-duration: var(--og-press, 120ms);
}

/* --- 2f · Rows and text links ----------------------------------------------
   Opacity, not transform: these are inline links or full-bleed list rows,
   where a scale either does nothing at all (inline boxes are not
   transformable) or makes the row look detached from its list. */
.site-nav__menu a,
/* :not() is load-bearing, not tidiness. `.site-footer a` is (0,1,1) and beats
   `.site-footer__social-link` (0,1,0) from 2c — so without the exclusion this
   property list, which names no `transform`, would win on that button and its
   press scale would jump with no animation at all.
   `.mini-cart__item` is absent for a different reason: it is the ROW, not a
   link. `:active` propagates up, so pressing the name link inside it would
   fade the row to .55 and the link to .55 on top of that — .30 compounded. */
.site-footer a:not(.site-footer__social-link),
.og-drawer__links li a,
.og-drawer__subcats li a,
.og-drawer__cat-row a,
.og-mega__rail-item,
.og-mega__parent,
a.mini-cart__item-name,
.og-bottomnav__item,
.og-ls-item a,
.search-result__title a,
.blog-card__title a,
.woocommerce-MyAccount-navigation li a,
.woocommerce-breadcrumb a,
.woo-breadcrumbs a,
.breadcrumb-trail a,
.page-breadcrumb a,
.blog-breadcrumb a,
.shop-widget li a,
.ostu-filter-option label,
.single-product .product_meta a,
.og-steps__step--done .og-steps__link {
  transition-property: color, background-color, opacity;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}

.site-nav__menu a:active,
.site-footer a:not(.site-footer__social-link):active,
.og-drawer__links li a:active,
.og-drawer__subcats li a:active,
.og-drawer__cat-row a:active,
.og-mega__rail-item:active,
.og-mega__parent:active,
a.mini-cart__item-name:active,
.og-bottomnav__item:active,
.og-ls-item a:active,
.search-result__title a:active,
.blog-card__title a:active,
.woocommerce-MyAccount-navigation li a:active,
.woocommerce-breadcrumb a:active,
.woo-breadcrumbs a:active,
.breadcrumb-trail a:active,
.page-breadcrumb a:active,
.blog-breadcrumb a:active,
.shop-widget li a:active,
.ostu-filter-option label:active,
.single-product .product_meta a:active,
.og-steps__step--done .og-steps__link:active {
  opacity: .55;
  transition-duration: var(--og-press, 120ms);
}

/* --- 2g · Floating and dark-surface controls -------------------------------
   back-to-top carries its own show/hide transform (cart-widget.css:346-370),
   so its press state is written against the VISIBLE class only; the hidden
   state is pointer-events:none, so there is nothing there to press.
   .ogmb-cta sits on the dark mega-banner, where a green tint would read as
   dirt — it dims instead, which is also its reduced-motion cue. */
.back-to-top.is-visible:active {
  transform: scale(.90);
  background: var(--brand-active, #024430);
  transition-duration: var(--og-press, 120ms);
}
/* Sits on the dark compare bar over a solid red dot — a green tint would read
   as mud, so it dims. Opacity is also its reduced-motion cue. */
.ostu-cmp-bar__slot-remove:active {
  opacity: .75;
}
.ogmb-cta:active {
  transform: scale(.97);
  opacity: .88;
  transition-duration: var(--og-press, 120ms);
}

/* --- 2h · Generic WooCommerce button net -----------------------------------
   Everything the enumerated lists above miss: account pages, order tracking,
   downloads, forms inside page content.

   THE FENCE, and why it has two clauses:
   `body.woocommerce-checkout` covers the checkout AND the pay-for-order page.
   It does NOT cover the account page that adds a saved method — WooCommerce
   decides that class from is_checkout(), which is false there, while the page
   still renders a gateway list. That page is almost certainly unreachable on
   this shop (Montonio/ESTO do not tokenise), but "almost certainly" is not a
   guarantee and invariant 1 does not take probabilities. The second clause
   names it, so the fence is closed by construction rather than by luck.
   Naming a body class is not payment styling: this is the one place in the
   file where the word appears, and it appears in order to EXCLUDE. */
body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce .button:active,
body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce button.button:active,
body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce input.button:active {
  transform: scale(.97);
  transition-duration: var(--og-press, 120ms);
}

/* The checkout's coupon and login forms are the exception that fence creates.
   They sit outside #customer_details (checkout-fields.css:24-26) and are the
   only two buttons a shopper touches on that page before the order column.
   Each is named by its own form class, so neither can match anything a
   gateway renders. */
form.checkout_coupon button.button:active,
form.woocommerce-form-login button.button:active {
  transform: scale(.97);
  transition-duration: var(--og-press, 120ms);
}

/* Parcel-machine picker — the one rule in this file inside #order_review.
   See the header note. On a phone this is a searchable list of hundreds of
   machines and it is the most-tapped control on the checkout; leaving it as
   the only silent control in the shop was not defensible. */
.og-pickup__item,
.og-pickup__change {
  transition-property: transform, background-color, border-color, color;
  transition-duration: var(--og-move, 200ms);
  transition-timing-function: var(--og-ease, cubic-bezier(.2, .6, .3, 1));
}
.og-pickup__item:active,
.og-pickup__change:active {
  transform: scale(.98);
  background-color: var(--brand-a3, rgb(4 120 87/.20));
  transition-duration: var(--og-press, 120ms);
}


/* ==========================================================================
   3 · HOVER IS A DESKTOP CLAIM
   The theme has ~55 `:hover` rules that set a transform and NOT ONE is fenced
   by pointer capability — there is no `@media (hover: ...)` query anywhere in
   the 36 stylesheets. On a touch screen the browser applies :hover on tap and
   KEEPS it until the finger lands somewhere else, so a shopper who taps a
   product card and comes back from the product page finds that card still
   lifted 4px with a hover shadow, out of line with the eleven cards around
   it. That is the "hover fights the rest state" bug, and it is visible on the
   shop grid, the homepage and the blog.

   Only decorative lifts and zooms are cancelled here. Hover rules that REVEAL
   something — the category rail's dropdown panels, the mega menu's panes, the
   live-search arrow — are deliberately left alone: on touch they are the only
   thing opening those panels, and neutralising their transform would break
   navigation rather than polish it.
   ========================================================================== */
@media (hover: none) {
  .btn-primary:hover:not(:active),
  .btn-secondary:hover:not(:active),
  .card-premium:hover:not(:active),
  .product-card:hover:not(:active),
  .product-card:hover:not(:active) .product-card__media img,
  .product-card__actions .button:hover:not(:active),
  .product-card__actions a.add_to_cart_button:hover:not(:active),
  .product-card .button:hover:not(:active),
  .product-card a.add_to_cart_button:hover:not(:active),
  .product-card.outofstock .button:hover:not(:active),
  .woocommerce ul.products li.product.product-category > a:hover:not(:active),
  .woocommerce ul.products li.product.product-category > a:hover:not(:active) img,
  body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce .button:hover:not(:active),
  .single-product .single_add_to_cart_button:hover:not(:active),
  .single-product .woocommerce-product-gallery__trigger:hover:not(:active),
  .single-product .flex-control-thumbs img:hover:not(:active),
  .home-cat:hover:not(:active),
  .home-cat:hover:not(:active) .home-cat__media img,
  .home-cat:hover:not(:active) .home-cat__arrow,
  .home-mini-card:hover:not(:active),
  .home-prop:hover:not(:active),
  .home-seasonal__cta:hover:not(:active),
  .ostu-chip:hover:not(:active),
  .ostu-gc__chip:hover:not(:active),
  .ostu-swatch:hover:not(:active),
  .ostu-filters-mobile-trigger:hover:not(:active),
  .ostu-cs-card:hover:not(:active),
  .ostu-cs-card .ostu-cs-card__add:hover:not(:active),
  .ostu-fbt-card:hover:not(:active),
  .ostu-fbt-card .ostu-fbt-card__add:hover:not(:active),
  .ostu-wl-btn--card:hover:not(:active),
  .ostu-wl-btn--single:hover:not(:active),
  .ostu-cmp-btn--single:hover:not(:active),
  .ostu-wl-card__actions .button:hover:not(:active),
  .ostu-cmp-table__add:hover:not(:active),
  .ostu-psec-nav__link:hover:not(:active),
  .ostu-share__btn:hover:not(:active),
  .ostu-rev-photos__item:hover:not(:active),
  .ostu-qv__close:hover:not(:active),
  .ostu-qv-product__thumb:hover:not(:active),
  .ostu-qv-product__buy .button:hover:not(:active),
  .blog-share__link:hover:not(:active),
  .blog-postnav__link:hover:not(:active),
  .blog-pagination a.page-numbers:hover:not(:active),
  .blog-card:hover:not(:active) .blog-card__image,
  .search-result:hover:not(:active) .search-result__media img,
  .search-results__pagination a.page-numbers:hover:not(:active),
  .error-404__chips a:hover:not(:active),
  .site-footer__social-link:hover:not(:active),
  .site-footer__links a:hover:not(:active),
  .site-footer__col .footer-widget a:hover:not(:active),
  .og-mega__trigger:hover:not(:active),
  .og-mega__promo-cta:hover:not(:active),
  .ogmb-cta:hover:not(:active),
  .back-to-top:hover:not(:active) {
    transform: none;
  }

  /* back-to-top's REST position is itself a transform once visible
     (translateY(0) scale(1), cart-widget.css:369), so the blanket
     `transform: none` above would drop it back toward its hidden offset while
     a stale hover is still latched. Restore it explicitly. */
  .back-to-top.is-visible:hover:not(:active) {
    transform: translateY(0) scale(1);
  }
}


/* ==========================================================================
   4 · HONEST LOADING
   Two async paths were effectively silent. Neither gets a progress bar — a
   bar that measures nothing is a lie about how long the wait will be. Both
   get a state that says "working" and stops when the work stops.
   ========================================================================== */

/* 4a · Cart update. WooCommerce blocks `form.woocommerce-cart-form` and
   `div.cart_totals` while it recalculates, injecting `.blockUI.blockOverlay`.
   The overlay lands at full strength in a single frame, which reads as a
   flicker rather than as work; fading it in turns the same event into a
   deliberate pause. Scoped to the cart page — on the checkout the equivalent
   overlay covers the order column, and this file does not go there.
   The keyframe ends at .6 because that is the opacity jQuery blockUI writes
   INLINE. A CSS animation outranks an inline style, so the end frame has to
   match that value or the overlay would jump on its last frame. */
@keyframes og-motion-veil-in { from { opacity: 0; } to { opacity: .6; } }

.woocommerce-cart .blockUI.blockOverlay {
  animation: og-motion-veil-in var(--og-move, 200ms) var(--og-ease, cubic-bezier(.2, .6, .3, 1));
  cursor: progress;
}

/* 4b · The theme's own in-flight buttons. interactions.js:318, bundles.js:66,
   giftcards.js:155 and filters.js:411 each add `.is-loading` / `.is-busy` for
   the exact lifetime of a fetch(). Today that only dims the button to .8
   (main.css:589, cart-widget.css:336, filters.css:535), which on a phone in
   daylight is not a signal. A slow opacity breath is honest: it says "still
   working", claims no percentage, and stops the moment the class is removed.
   Element-qualified on purpose — `.ostu-shop-main.is-loading` (filters.css:463)
   is a CONTAINER with its own skeleton treatment and must not breathe. */
@keyframes og-motion-breathe { 0%, 100% { opacity: .55; } 50% { opacity: .9; } }

button.is-loading,
a.is-loading,
.button.is-loading,
button.is-busy,
a.is-busy,
.button.is-busy {
  animation: og-motion-breathe 1.4s var(--og-ease, cubic-bezier(.2, .6, .3, 1)) infinite;
  cursor: progress;
}


/* ==========================================================================
   5 · prefers-reduced-motion — COMPLETE, NOT PARTIAL
   main.css:146-148 and a11y.css:241-248 already crush every duration to
   ~0.01ms, and tokens.css:303-306 zeroes --dur-fast/--dur. That handles
   TIMING but not DISPLACEMENT: a `transform: scale(.9)` with a 0ms transition
   is still an instant 4px jump — exactly what a vestibular-sensitive user
   asked the OS to stop. a11y.css:250-256 cancels five hover lifts; it cancels
   no :active state, because until now there were almost none to cancel.

   So every transform this file introduces is cancelled here, and every one of
   them is replaced by something that is still SEEN. The cues that survive are
   colour and opacity: --brand-active on solid CTAs, --brand-a2 on secondary
   controls and cards, opacity on links and on dark surfaces. This section
   removes movement, never feedback.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {

  /* 5a · Every pressed transform introduced in section 2, in one list. */
  .btn-primary:active,
  .btn-secondary:active,
  .single-product form.cart .button:active,
  .single-product .single_add_to_cart_button:active,
  .single-product .woocommerce-product-gallery__trigger:active,
  .product-card__actions .button:active,
  .product-card__actions a.add_to_cart_button:active,
  .product-card .button:active,
  .product-card a.add_to_cart_button:active,
  .product-card .added_to_cart:active,
  .product-card.outofstock .button:active,
  .product-card:active,
  .wc-proceed-to-checkout a.checkout-button:active,
  .woocommerce-cart .return-to-shop .button:active,
  .woocommerce-cart table.cart td.actions .ostu-continue-shopping:active,
  .woocommerce-cart table.cart td.actions button[name="apply_coupon"]:active,
  .woocommerce button[name="update_cart"]:active,
  .woocommerce a.remove:active,
  .woocommerce ul.products li.product.product-category > a:active,
  .og-cartbar__btn:active,
  .sticky-atc__btn:active,
  .ostu-qv-product__buy .button:active,
  .ostu-cs-card .ostu-cs-card__add:active,
  .ostu-fbt-card .ostu-fbt-card__add:active,
  .ostu-bundle__add:active,
  .ostu-wl-card__actions .button:active,
  .ostu-cmp-table__add:active,
  .og-mega__promo-cta:active,
  .ostu-price-apply:active,
  .ostu-chip:active,
  .ostu-gc__chip:active,
  .blog-tags__chip:active,
  .blog-cats__chip:active,
  .ostu-swatch:active,
  .ostu-filters-mobile-trigger:active,
  .ostu-wl-btn--card:active,
  .ostu-wl-btn--single:active,
  .ostu-cmp-btn--card:active,
  .ostu-cmp-btn--single:active,
  .ostu-psec-nav__link:active,
  .ostu-share__btn:active,
  .ostu-searchform__btn:active,
  .home-seasonal__cta:active,
  .error-404__chips a:active,
  .blog-pagination a.page-numbers:active,
  .woocommerce-pagination a.page-numbers:active,
  .search-results__pagination a.page-numbers:active,
  .og-drawer-toggle:active,
  .og-drawer__close:active,
  .og-drawer__search button:active,
  .header-search button:active,
  .mini-cart__close:active,
  .og-popup__close:active,
  .ostu-qv__close:active,
  .og-sproof__close:active,
  .ostu-filters__close:active,
  .ostu-cmp-bar__slot-remove:active,
  .ostu-wl-card__remove:active,
  .ostu-cmp-table__remove:active,
  .qty-stepper .qty-stepper__btn:not(:disabled):active,
  .site-footer__social-link:active,
  .header-account:active,
  .header-cart:active,
  .header-wishlist:active,
  .home-cat:active,
  .home-prop:active,
  .home-mini-card:active,
  .blog-postnav__link:active,
  .ostu-cs-card:active,
  .ostu-fbt-card:active,
  .ostu-rev-photos__item:active,
  .back-to-top.is-visible:active,
  .ogmb-cta:active,
  .og-pickup__item:active,
  .og-pickup__change:active,
  body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce .button:active,
  body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce button.button:active,
  body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce input.button:active,
  form.checkout_coupon button.button:active,
  form.woocommerce-form-login button.button:active {
    transform: none !important;
  }

  /* Two exceptions to the blanket `transform: none` above. Both are positioned
     BY a transform at rest, so "no motion" here means "hold the rest
     transform", not "drop it" — `none` would move them, which is the opposite
     of what the user asked the OS for. */
  .mini-cart__item-remove:active {
    transform: translateY(-50%) !important;
  }
  .back-to-top.is-visible:active {
    transform: translateY(0) scale(1) !important;
  }
}

/* Third exception, and it needs its own query. .ostu-qv__close is rotated 90°
   by its hover (quickview.css). With a pointer AND reduced motion, the plain
   `transform: none` above would UN-rotate it under the finger — a press that
   produces movement, which is precisely what this section exists to prevent.
   Holding the hover transform means the press moves nothing at all; the
   background tint from 2c is the cue. */
@media (prefers-reduced-motion: reduce) and (hover: hover) {
  .ostu-qv__close:active {
    transform: rotate(90deg) !important;
  }
}

@media (prefers-reduced-motion: reduce) {

  /* 5b · The short list of controls whose ONLY cue was the scale: the card
     tiles and the generic WooCommerce net. Everything else already carries a
     colour or an opacity change declared OUTSIDE this media query — the icon
     buttons in 2c, the solid CTAs in 2a, the swatches, the remove ×, the
     stepper, .ogmb-cta and the compare-bar dot — so those need nothing here
     and are deliberately absent rather than forgotten. */
  .product-card:active,
  .home-cat:active,
  .home-prop:active,
  .home-mini-card:active,
  .blog-postnav__link:active,
  .ostu-cs-card:active,
  .ostu-fbt-card:active,
  .ostu-rev-photos__item:active,
  .woocommerce ul.products li.product.product-category > a:active,
  body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce .button:active,
  form.checkout_coupon button.button:active,
  form.woocommerce-form-login button.button:active {
    background-color: var(--brand-a3, rgb(4 120 87/.20));
  }

  /* 5c · The loading states keep saying "working" — they just stop moving.
     The veil lands at its final opacity in one step; the breathing button
     holds a single dimmed value instead of cycling. */
  .woocommerce-cart .blockUI.blockOverlay {
    animation: none;
  }

  button.is-loading,
  a.is-loading,
  .button.is-loading,
  button.is-busy,
  a.is-busy,
  .button.is-busy {
    animation: none;
    opacity: .6;
  }
}


/* ==========================================================================
   6 · forced-colors — the press must survive an OS colour override.
   In Windows High Contrast every background this file sets is discarded, so
   the tint-based cues in section 5 would silently vanish for exactly the
   users least able to spare a missing signal. A system-keyword outline is one
   of the few things forced-colors keeps.
   ========================================================================== */
@media (forced-colors: active) {
  .btn-primary:active,
  .btn-secondary:active,
  .product-card:active,
  .qty-stepper .qty-stepper__btn:not(:disabled):active,
  .woocommerce a.remove:active,
  .og-pickup__item:active,
  .og-cartbar__btn:active,
  .sticky-atc__btn:active,
  body:not(.woocommerce-checkout):not(.woocommerce-add-payment-method) .woocommerce .button:active {
    outline: 2px solid Highlight;
    outline-offset: 2px;
  }
}
