/* ==========================================================================
   OSTUGRUPP — DISAINIPAKI KOMPONENDIKIHT  (pack-components.css)
   Loaded by inc/pack-components.php behind one owner switch.

   WHY THIS FILE EXISTS
   The design pack (design_handoff_ostugrupp_system) specifies fourteen
   components, D1–D14. The theme adopted the pack's TOKENS (assets/css/tokens.css
   is a verbatim copy) and its ICONS, and then largely stopped. Tokens are
   numbers; components are what a shopper sees. The full specified-vs-built
   delta is written up in docs/DISAIN-KOMPONENDID.md — this file builds the
   three items from that delta with the best ratio of shopper impact to build
   cost that no other module already owns:

     1 · D14 kategooriaplaat  — the tile shell (4:3 media box, reserved title
         and count rows, the fallback ladder's visible half). ~200 categories,
         every category landing page.
     2 · D13 kleepuvad alaribad — the product page's LOCKED rule ("variant A",
         pack sample line 1859): the sticky Add-to-cart sits at bottom:0 and
         REPLACES the bottom nav instead of stacking on top of it. Today
         engagement.css:142 builds variant B, the one the designer explicitly
         rejected ("Kaks varju kohakuti. See variant ei lähe ehitusse.").
         Worth 64px of phone screen on every product page.
     3 · D5 kiibid — the active-filter chips: the deleted green removed, the
         missing :active and :focus-visible states added, tap zone widened.

   Everything here is an OVERRIDE of rules that already exist in
   woocommerce.css / engagement.css / cart-widget.css / filters.css. Not one of
   those files is edited. Each override therefore states its own specificity
   arithmetic against the rule it is beating, so the next reader can check the
   claim without a browser. ⚠️ Specificity arithmetic is NOT a measured computed
   value — CLAUDE.md Trap 1 exists because a rule can look live in DevTools and
   still lose to a plugin sheet. Every claim below is arithmetic; none of it has
   been read off a real browser, because this session had none.

   TOKENS. Every var() carries its literal as a fallback. Deploys here are a
   hand-built zip uploaded by hand and a custom property that cannot resolve
   does not fall back to its old value — it becomes the guaranteed-invalid
   value and takes every consumer of the declaration with it. The literals are
   the pack's own values (assets/css/tokens.css), so the day a token moves,
   nothing on screen moves with it.

   MOBILE FIRST. 73% of this shop's traffic is a phone, and hover does not
   exist there. Every interactive rule below states :active alongside :hover,
   and :focus-visible alongside both.
   ========================================================================== */


/* ==========================================================================
   1 · D14 · KATEGOORIAPLAAT — „Varuvariandi redel"
   ==========================================================================
   Pack: sample lines 1301–1424. Four rungs, ONE shell:
     1 the category has its own image      → cover, full bleed
     2 no image, one of the eight top-level → duotone icon on --brand-a1
     3 neither                              → first product photo, CONTAIN
     4 category is empty                    → neutral placeholder, count row blank
   "Kest on kõigil neljal identne: sama plaat, sama meediakasti mõõt ja
   proportsioon, sama pealkirja koht, sama arvurida." (sample 1310)

   WHAT THE THEME ALREADY HAS
   inc/woocommerce.php:694 `ostugrupp_subcategory_thumbnail()` already builds
   rungs 1, 3 and 4 in PHP (own thumbnail → first product image → placeholder,
   with a 6h transient). Rung 2 is not built; brand/icons/pack-categories.php
   and ostugrupp_category_icon() (inc/icons.php:217) are installed and waiting.

   WHAT WAS WRONG IN CSS — three measured mismatches against woocommerce.css:
     · line 268  `aspect-ratio: 1/1`      → pack says 4/3 on all four rungs
     · line 268  contain + 14px padding + `background: var(--muted)` applied to
                 EVERY rung, so a real category photograph is letterboxed onto
                 grey. Pack: rung 3 is contain on WHITE (sample 1345), only the
                 empty rung sits on --surface-muted (sample 1359).
     · line 272  title 15px with the count as an inline chip pushed right, and
                 no reserved height anywhere. Pack: name block 40px, count row
                 16px, "Ka ühesõnalise nime ja puuduva arvu korral.
                 Reserveeritud kõrgus hoiab read joondatuna." (sample 1383)

   WHAT CSS CANNOT DO HERE — stated, not hidden.
   Rung 1 and rung 3 come out of the PHP as byte-identical markup (both are
   wp_get_attachment_image( …, 'woocommerce_thumbnail' )), so no selector can
   tell "the owner's category photo" from "some product's photo". Only rung 4
   is distinguishable, because wc_placeholder_img() carries
   `.woocommerce-placeholder`. The default below is therefore rung 3's
   treatment — contain on white — which is the correct SAFE default on this
   shop: it is a dropship catalogue whose supplier photos are 1000×1000 on
   white, and "cover lõikaks toote pooleks" (sample 1353). The hook class for
   rung 1 is defined and inert until the PHP sets it; the one-line PHP edit is
   written out in docs/DISAIN-KOMPONENDID.md for the lead to apply.
   ========================================================================== */

/* ---- The tile shell ----------------------------------------------------- */
/* woocommerce.css:264 hovers the tile with `rgba(5,150,105,.3)` — that is
   #059669, a colour the pack DELETED ("Kustutatud, ei tohi tagasi tulla",
   README §6). Same alpha step, correct hue: --brand-a3 is rgb(4 120 87/.20).
   Specificity: theirs `.woocommerce ul.products li.product.product-category
   > a:hover` = 4 classes + :hover + 3 elements = (0,5,3). Adding `body`
   makes this (0,5,4). */
body.woocommerce ul.products li.product.product-category > a:hover {
  border-color: var(--brand-a3, rgb(4 120 87 / .20));
}

/* Pressed + keyboard focus did not exist on this tile at all. The pack's
   loudest single point is that a phone has no hover: "Telefonis hover'it ei
   ole — :active ei ole valikuline" (sample 840). (0,5,4) each. */
body.woocommerce ul.products li.product.product-category > a:active {
  border-color: var(--brand-a3, rgb(4 120 87 / .20));
  /* press movement intentionally omitted — motion.css owns it shop-wide as a
     scale(.985); a translateY here would give the shop two press languages
     depending on which list a control happens to sit in. Colour and shadow
     changes below stay: they are the other two press signals. */
}

body.woocommerce ul.products li.product.product-category > a:focus-visible {
  /* outline intentionally NOT reset — a11y.css owns the focus ring shop-wide
     and is the accessibility contract. Three different rings across three files
     is worse than one imperfect ring. */
  border-color: var(--brand, #047857);
  /* The pack's ring is a FULL-STRENGTH two-stop shadow, never an alpha: an
     alpha ring composites to 1,61:1 on white and fails WCAG 1.4.11 (README
     §5b, correction 1). */
  box-shadow: var(--focus-ring, 0 0 0 2px #ffffff, 0 0 0 5px #047857);
}

/* box-shadow is not painted in forced-colours mode, so that mode needs a real
   outline or the focus indicator vanishes completely. */
@media (forced-colors: active) {
  body.woocommerce ul.products li.product.product-category > a:focus-visible {
    outline: 2px solid;
    outline-offset: 2px;
  }
}

/* ---- The media box — 4:3, always ---------------------------------------- */
/* "Meediakast on alati 4:3. Kõrgus ei sõltu sellest, mis sees on. Nii ei hüppa
   võrestik, kui üks kategooria pildi saab." (sample 1382)

   Specificity: theirs `.woocommerce ul.products li.product.product-category
   img` = 4 classes + 3 elements = (0,4,3); this is (0,4,4). It also has to
   clear TWO core rules — Trap 1's originals:
     `.woocommerce img, .woocommerce-page img { height:auto; max-width:100% }`
     `.woocommerce ul.products li.product img { width:100%; height:auto; … }`
   at (0,1,1) and (0,3,3). Arithmetic only; not verified in a browser. */
body.woocommerce ul.products li.product.product-category img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  /* Default = rung 3. Supplier photography is 1000×1000 on white; cover would
     cut the product in half (sample 1353). */
  object-fit: contain;
  object-position: center;
  padding: var(--space-12, 12px);
  background: var(--surface, #ffffff);
  border-bottom: 1px solid var(--border, #e2e8f0);
  margin: 0;
}

/* Rung 1 — the owner uploaded a picture FOR the category. Full bleed, cropped
   from the centre (sample 1318: "täisserv, cover"). Inert until the PHP adds
   the class; see docs/DISAIN-KOMPONENDID.md § "Mida juht peab tegema". */
body.woocommerce ul.products li.product.product-category img.og-cat-media--own {
  object-fit: cover;
  padding: 0;
}

/* Rung 4 — nothing to show. "Neutraalne kohatäide, mitte katkine pilt ega tühi
   kast." (sample 1367) wc_placeholder_img() is the only rung CSS can identify
   on its own, because it is the only one carrying its own class.
   `.woocommerce-placeholder` adds one class → (0,5,4). */
body.woocommerce ul.products li.product.product-category img.woocommerce-placeholder {
  background: var(--surface-muted, #f1f5f9);
  /* A percentage padding on a replaced element resolves against its own width,
     so the glyph shrinks with the tile instead of filling it — it has to read
     as "nothing here yet", not as a photograph that failed to load. */
  padding: 22%;
}

/* ---- Title + count — reserved heights, always --------------------------- */
/* "Pealkiri 40px, arvurida 16px — alati. Ka ühesõnalise nime ja puuduva arvu
   korral." (sample 1383)

   WooCommerce prints `<h2 class="woocommerce-loop-category__title">Nimi
   <mark class="count">312</mark></h2>` — the name is a bare text node, so it
   cannot be given -webkit-line-clamp (that needs an element). A two-row grid
   with fixed track heights plus overflow:hidden on the container gets the same
   GEOMETRY: the name is auto-placed into the 40px row, the <mark> into the
   16px row, and a name that would run to a third line is clipped by the
   container rather than pushing the count down. What it does not get is the
   ellipsis and the `title` attribute the pack asks for (sample 1400); both
   need a PHP span, written out for the lead.

   Specificity: theirs (0,5,2), this (0,5,3). */
body.woocommerce ul.products li.product.product-category .woocommerce-loop-category__title {
  display: grid;
  grid-template-rows: 40px 16px; /* nimi · arvurida — reserveeritud */
  row-gap: var(--space-4, 4px);
  align-items: start;
  overflow: hidden;
  padding: var(--space-12, 12px);
  margin: 0;
  font: var(--text-sm, 400 14px/20px "DM Sans", system-ui, sans-serif);
  /* MUST come after the `font` shorthand — the shorthand resets weight. */
  font-weight: var(--fw-semibold, 600);
  letter-spacing: 0;
  color: var(--text, #0f172a);
  /* The chip layout in woocommerce.css:274 pushed the count to the right of
     the name on one line. It is its own row now. */
  justify-content: start;
  gap: var(--space-4, 4px);
}

/* The count row. It stops being a grey pill and becomes the quiet line the
   pack draws (sample 1322): --text-2xs, --text-subtle, no background.
   Specificity: theirs `… mark.count` = 5 classes + 3 elements = (0,5,3);
   this is (0,5,4). */
body.woocommerce ul.products li.product.product-category mark.count {
  align-self: center;
  justify-self: start;
  padding: 0;
  background: none;
  border-radius: 0;
  font: var(--text-2xs, 500 12px/16px "DM Sans", system-ui, sans-serif);
  letter-spacing: var(--text-2xs-tracking, .02em);
  color: var(--text-subtle, #64748b);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* Rung 4 reads one step quieter in the title too (sample 1363), so a category
   that is still being filled does not shout as loudly as one that is full.
   `:has()` is already an accepted pattern in this theme (woocommerce.css:1327).
   Where it is unsupported the tile simply keeps the normal title colour —
   a graceful loss, not a broken layout. */
@supports selector(:has(*)) {
  body.woocommerce ul.products li.product.product-category > a:has(img.woocommerce-placeholder) .woocommerce-loop-category__title {
    color: var(--text-muted, #475569);
  }
}


/* ==========================================================================
   2 · D13 · KLEEPUVAD ALARIBAD — tooteleht, otsustatud variant A
   ==========================================================================
   Pack: sample lines 1742–1908. "Ribad ei virna. Nad ASENDAVAD üksteist:
   korraga on ekraanil täpselt üks." (sample 1746)
   Locked rule (sample 1859): "tootelehel on kleepuv riba bottom: 0 ja
   alanavigatsioon peidus. […] see reegel kehtib ainult tootelehele ja ainult
   siis, kui riba on nähtaval."

   WHAT THE THEME BUILDS TODAY — variant B, the rejected one:
     engagement.css:142  `.sticky-atc { bottom: var(--og-bottomnav-h) }`
   so the Add-to-cart bar is parked 64px up, ON TOP of the bottom nav. That is
   the drawing the designer marked in red — "Kaks varju kohakuti. See variant
   ei lähe ehitusse." (sample 1854) — and it costs the shopper 144px, 22% of a
   667px screen, on every product page (sample 1852).

   THE MEASUREMENTS THIS FIXES
     · bar drops to bottom:0, nav hides while it is up → 72px used, not 136px
     · bar height 72px (--sticky-h), the one height all four bars share
       (sample 1763). Today: 10px + 46px + 10px = 66px.
     · button 52px — size M, "kleepuv „Lisa korvi" · nupp M (52px)"
       (sample 1883). Today 46px, which is also under the 44px+ comfort the
       pack asks of a bar's single action.

   SCOPE. Only the product page, only ≤1023.98px (the width at which
   cart-widget.css:339 already hides the bar), and only the GEOMETRY of the
   bar. Colour and state on the button itself belong to the button module.
   ========================================================================== */

/* ---- Geometry that is safe unconditionally ------------------------------ */

@media (max-width: 1023.98px) {

  /* Reserve the bar's height on the body, replacing engagement.css:139's 64px.
     Set unconditionally on the product page rather than toggled with the bar:
     a padding that changes on scroll is a layout shift, and CLS is exactly
     what a mobile PageSpeed of 91 cannot afford. When the bar is down the nav
     (64px) simply sits inside a 72px gap — 8px of slack, no movement.
     Specificity: `body` (0,0,1) vs `body.single-product` (0,1,1). Independent
     of load order, which matters — this file declares no dependency on
     engagement.css, and an unregistered dependency makes WordPress drop a
     stylesheet silently. */
  body.single-product {
    padding-bottom: calc(var(--sticky-h, 72px) + env(safe-area-inset-bottom, 0px));
  }

  /* 72px — the single height all four bars share (sample 1763).
     cart-widget.css:311 gives the inner `padding-block: 10px` around a 46px
     button; a min-height on the same element raises the bar without fighting
     that padding. Do NOT add safe-area padding here: cart-widget.css:299
     already puts env(safe-area-inset-bottom) on `.sticky-atc` itself, and
     stating it twice would inset the bar twice on a notched phone.
     `.sticky-atc__inner` (0,1,0) → (0,2,1). */
  body.single-product .sticky-atc__inner {
    min-height: var(--sticky-h, 72px);
  }

  /* Size M — "kleepuv „Lisa korvi" · nupp M (52px)" (sample 1883).

     This is the complement of an exclusion, not a contradiction of one:
     controls-d1-d2.css:119 deliberately keeps `.sticky-atc__btn` OUT of its
     52px rule, on the stated ground that the button "sits in a fixed-height
     bar whose height was measured around it". The bar's height is what this
     section changes — and 72px minus cart-widget.css:311's 10px+10px block
     padding is 52px exactly, which is why the pack can put an M button in a
     72px bar at all. The two files agree by construction.
     `.sticky-atc__btn` (0,1,0) → (0,2,1). */
  body.single-product .sticky-atc__btn {
    min-height: 52px;
    border-radius: var(--radius-12, 12px);
  }

  /* NOT stated here: the bar's shadow. D13's "üks vari, suunatud ÜLES"
     (sample 1764) is claimed by surfaces-d4-d12.css:226, which supersedes
     cart-widget.css:296 for every bar at once. Two authors on one shadow is
     how a value drifts; the material is that file's, the geometry is this
     one's.

     engagement.css:141 lifts the back-to-top button by the nav's 64px. On this
     page the reserved height is 72px. (0,1,0) → (0,2,1). */
  body.single-product .back-to-top {
    bottom: calc(var(--sticky-h, 72px) + var(--space-16, 16px) + env(safe-area-inset-bottom, 0px));
  }
}

/* ---- The replacement itself — PARKED, see the ⛔ note below -------------- */
/* Design notes for the reference block at the end of this section. NOTHING in
   the rest of this section is live CSS; it is all inside comments.

   ⚠️ THE WHOLE OF IT BELONGS BEHIND ONE @supports, INCLUDING `bottom: 0`, and
   that is deliberate rather than tidy. Moving the bar down and hiding the nav are
   ONE change, not two: ship the move without the hide and the two bars land on
   top of each other — and `.sticky-atc` ends up at z-index 1150 against the
   nav's 1100 (engagement.css:128), so the Add-to-cart bar would paint straight
   OVER the five navigation links instead of replacing them. A browser without
   :has() therefore keeps today's behaviour exactly, unimproved but unbroken.

   Z-INDEX — CORRECTED 2026-08-14. cart-widget.css declares `.sticky-atc` TWICE:
   :292 sets `z-index: 150`, and :448 sets `z-index: 1150`. Both selectors are
   the bare class (0,1,0), so the LATER declaration wins and the effective value
   on the page is 1150 — :448 says why in as many words ("the bottom nav sits at
   z-index 1100 and the sticky bar at 150 … The bar belongs above the nav — it
   is the one carrying the price"). cart-sticky-bar.css:18, which states that
   .sticky-atc in cart-widget.css is 1150, is therefore RIGHT and is left alone.
   An earlier revision of THIS comment read only the first of the two
   declarations, called 150 the live value, and reported cart-sticky-bar.css as
   carrying a wrong comment. This comment was the wrong one. Read a stylesheet
   to the END before quoting a value out of it — cart-widget.css:425-448 is a
   whole section of later corrections. (Arithmetic + source order only; no
   browser was available to read the computed value — CLAUDE.md Trap 1.)

   The bar and the nav are not siblings in the DOM, so no sibling combinator
   reaches from one to the other; :has() on <body> does, and this theme already
   relies on :has() (woocommerce.css:1327).

   `.is-visible` is the real class: interactions.js:282 toggles it and
   cart-widget.css:306 is what makes the bar appear.

   THE COOKIE-BAR GUARD. The pack is explicit that the external cookie bar
   outranks all of ours and that ours stay out of its way until it is answered
   (sample 1760: "meie kolm mahutavad end tema alla … Nii ei kordu see, et tema
   nupp istus hinna peal"). engagement.css:57 already lifts `.og-cookie` by the
   nav's height, so hiding the nav underneath it would leave the cookie bar
   floating over a gap with the Add-to-cart bar behind it. While the banner is
   up — `.og-cookie` without its `hidden` attribute (inc/engagement.php:119
   ships it hidden, assets/js/engagement.js removes the attribute to show it) —
   this whole change stands down and variant B stays.

   Specificity: :has() and :not() each take the specificity of their most
   specific argument.
   `body.single-product:not(:has(.og-cookie:not([hidden]))):has(.sticky-atc.is-visible) .og-bottomnav`
   = body(el) + .single-product + :not→(0,2,0) + :has→(0,2,0) + .og-bottomnav
   = (0,6,1), against engagement.css:136's `.og-bottomnav` (0,1,0). `display`
   is deliberately NOT touched — the nav keeps display:grid and is removed by
   visibility, which is what takes it out of the tab order. */
/* ⛔ D13 VARIANT A IS PARKED — NOT SHIPPED. The block below is left in place as
   reference text, because it is correct as far as it goes and will be wanted
   later.

   The pack’s decision has TWO halves: the product page’s buy bar moves to
   bottom:0 and hides the bottom nav, AND the cart count moves onto the bar
   itself. Only the first half exists. inc/ajax-cart.php renders name, price and
   one button — there is no cart control on that bar — and the count lives in
   .og-bottomnav__count (inc/engagement.php:294), i.e. in the very nav this block
   hides.

   Shipping half of it costs the shopper the cart count at the exact moment they
   have just added something. 64px of phone screen is not worth the confirmation
   that the thing they did worked. Owner’s call; until then, half is worse than
   none.

   ⚠️ HOW THIS BLOCK WAS "PARKED" BEFORE — AND WHY IT WAS NOT (2026-08-14).
   Until this edit the block was wrapped in a comment opened on its own line
   below and closed at the very bottom, with SEVEN ordinary comments still
   inside it. CSS COMMENTS DO NOT NEST: the wrapper ended at the FIRST inner
   closing marker, four lines in, and every rule from the `.sticky-atc`
   declaration onwards was LIVE CSS on the site. Worse, the two lines that
   opened `@supports selector(:has(*))` and `@media (max-width: 1023.98px)`
   were on the swallowed side of that boundary — so variant A was not merely
   shipped, it shipped with BOTH of its guards gone and applied at every
   viewport width.

   What that actually did on a phone: the rule below is (0,4,1) and beat
   engagement.css:142's `.sticky-atc { bottom: var(--og-bottomnav-h) }` (0,1,0),
   so the Add-to-cart bar sat on the screen edge, and `.og-bottomnav` went
   `visibility: hidden` whenever the bar was up — i.e. the shopper lost the cart
   count exactly as the three paragraphs above say must not happen without the
   owner deciding it. (Desktop was spared by luck, not design:
   cart-widget.css:339 hides `.sticky-atc` from 1024px up and engagement.css:135
   only shows the nav below 1024px.)

   tools/check-theme.sh check 5 could not catch it. It counts opening markers
   against closing ones, and both counts were equal — which is the exact failure
   mode that check's own comment warns about ("a stray closing marker … makes
   the CSS parser swallow the NEXT selector whole"). It also counts braces
   across the whole file, and the swallowed braces balanced too.

   The block is now ONE comment that contains NO comment marker of any kind —
   the only shape that cannot come apart again. The seven inner comments are
   kept as `·` lines. If this is ever un-parked, restore them as real comments
   only after the braces are real braces.

@supports selector(:has(*)) {
  @media (max-width: 1023.98px) {

    · THE decision (sample 1859). (0,4,1) against `.sticky-atc` (0,1,0).
    body.single-product:not(:has(.og-cookie:not([hidden]))) .sticky-atc {
      bottom: 0;
      · Above the nav's 1100, so the two can never trade places mid-transition
      ·   on the way in or out. The cookie bar's 1200 stays on top of both.
      ·   Redundant as written: cart-widget.css:448 already puts `.sticky-atc`
      ·   at 1150. Kept so the rule still reads on its own if it is un-parked.
      z-index: 1150;
    }

    body.single-product .og-bottomnav {
      · Showing must be instant, so no delay on the base state.
      transition:
        transform var(--dur, 200ms) var(--ease, cubic-bezier(.2, .6, .3, 1)),
        opacity var(--dur, 200ms) var(--ease, cubic-bezier(.2, .6, .3, 1)),
        visibility 0s linear 0s;
    }

    body.single-product:not(:has(.og-cookie:not([hidden]))):has(.sticky-atc.is-visible) .og-bottomnav {
      · transform + opacity only — never height, top or bottom.
      transform: translateY(100%);
      opacity: 0;
      · ⚠️ visibility is LOAD-BEARING, not decoration. transform alone slides
      ·   the nav off screen while leaving five links in the tab order, so a
      ·   keyboard user tabs into invisible navigation. This exact bug has been
      ·   paid for three times in this theme — see the note at
      ·   cart-widget.css:301 and cart-sticky-bar.css:43. The delay is what
      ·   keeps the slide intact: visibility flips only once it has finished.
      visibility: hidden;
      pointer-events: none;
      transition:
        transform var(--dur, 200ms) var(--ease, cubic-bezier(.2, .6, .3, 1)),
        opacity var(--dur, 200ms) var(--ease, cubic-bezier(.2, .6, .3, 1)),
        visibility 0s linear var(--dur, 200ms);
    }

    · Reduced motion, COMPLETE rather than partial: somebody who asked the OS
    ·   to stop animation still has to SEE that the nav is gone — otherwise the
    ·   Add-to-cart bar appears to be sitting on top of live navigation. So the
    ·   movement goes and the state change stays, instantly.
    ·   Both selectors repeat the ones above verbatim — same specificity, later
    ·   in the file, so they win on order.
    @media (prefers-reduced-motion: reduce) {
      body.single-product .og-bottomnav {
        transition: none;
      }
      body.single-product:not(:has(.og-cookie:not([hidden]))):has(.sticky-atc.is-visible) .og-bottomnav {
        transform: none;
        opacity: 0;
        visibility: hidden;
        transition: none;
      }
    }
  }
}
*/


/* ==========================================================================
   3 · D5 · KIIBID — aktiivsete filtrite kiibid
   ==========================================================================
   Pack: sample lines 1448–1482. "aktiivne filter · 36px · vaikimisi / hiirega /
   vajutatud / fookuses".

   WHAT WAS WRONG — filters.css:84–105:
     · `rgba(5,150,105,.08/.14/.18/.22/.4)` in five places. #059669 is on the
       pack's delete list (README §6) and none of those five is the brand.
     · :hover only. No :active — and 73% of this shop is a phone, where the
       only state that exists IS :active. No :focus-visible either, so a
       keyboard user removing a filter cannot see which chip they are on.
     · 18px × glyph inside a ~29px chip. The pack's own words: "Väike ristike,
       mida ei taba, on halvem kui ristikest üldse mitte." (sample 1467)

   THE TAP-ZONE TECHNIQUE — and why it is the ::after one.
   The pack gives two, and picking the wrong one makes a NEW bug (README rule
   4). Chips sit side by side, so horizontally they are the "neighbour closer
   than 44px" case and the box is what grows — which it does: the whole chip is
   the remove control (inc/ajax-filters.php:1079 renders it as a <button>), so
   its width is already 60px+. Vertically the neighbour is the chip on the next
   wrapped line, and there the ::after technique is safe ONLY if the rows are
   more than 44px apart. 36px chip + 8px row-gap = 44px exactly, which is the
   overlap the pack warns about — so the row-gap goes to 12px first, making the
   pitch 48px, and only then is a 44px ::after laid over each chip.

   Specificity: filters.css `.ostu-chip` is (0,1,0); every rule below is
   (0,2,0) or more via the container class, so none of this depends on load
   order.
   ========================================================================== */

.ostu-filters .ostu-filters__chips {
  /* 36 + 12 = 48px pitch, so two rows of 44px tap zones never overlap. */
  row-gap: var(--space-12, 12px);
  column-gap: var(--space-8, 8px);
}

.ostu-filters__chips .ostu-chip {
  position: relative;
  height: 36px;
  /* 6px on the right because the × is a 24px circle that needs to sit close to
     the edge; 14px on the left for the label (sample 1460). */
  padding: 0 6px 0 14px;
  gap: var(--space-8, 8px);
  border-radius: var(--radius-pill, 999px);
  border: 1.5px solid var(--brand-a3, rgb(4 120 87 / .20));
  background: var(--brand-a1, rgb(4 120 87 / .06));
  color: var(--brand, #047857);
  font: var(--text-sm, 400 14px/20px "DM Sans", system-ui, sans-serif);
  font-weight: var(--fw-semibold, 600); /* after the shorthand, which resets it */
  cursor: pointer;
  transition:
    background var(--dur-fast, 120ms) var(--ease, cubic-bezier(.2, .6, .3, 1)),
    border-color var(--dur-fast, 120ms) var(--ease, cubic-bezier(.2, .6, .3, 1)),
    transform var(--dur-fast, 120ms) var(--ease, cubic-bezier(.2, .6, .3, 1));
}

/* The invisible 44px tap zone. Vertical only — the chip is already wider than
   44px horizontally, and left/right:0 keeps the zone inside the chip's own
   column so it cannot steal a tap from the chip beside it. */
.ostu-filters__chips .ostu-chip::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--tap-min, 44px);
  transform: translateY(-50%);
}

.ostu-filters__chips .ostu-chip:hover {
  background: var(--brand-a2, rgb(4 120 87 / .12));
  border-color: var(--brand-a3, rgb(4 120 87 / .20));
  /* filters.css:98 lifts the chip 1px on hover. A chip is not a button that
     lifts — and on a phone a hover-only lift is a state nobody ever sees. */
  transform: none;
}

/* The state the pack calls the most important column of the whole sheet:
   "Vajutus vastab 120ms jooksul" (sample 840). Pressed = one step darker and
   the chip sinks 1px (sample 1462). */
.ostu-filters__chips .ostu-chip:active {
  background: var(--brand-a2, rgb(4 120 87 / .12));
  border-color: var(--brand-a3, rgb(4 120 87 / .20));
  color: var(--brand-active, #024430);
  /* press movement intentionally omitted — motion.css owns it shop-wide as a
     scale(.985); a translateY here would give the shop two press languages
     depending on which list a control happens to sit in. Colour and shadow
     changes below stay: they are the other two press signals. */
}

.ostu-filters__chips .ostu-chip:focus-visible {
  /* outline intentionally NOT reset — a11y.css owns the focus ring shop-wide
     and is the accessibility contract. Three different rings across three files
     is worse than one imperfect ring. */
  border-color: var(--brand, #047857);
  box-shadow: var(--focus-ring, 0 0 0 2px #ffffff, 0 0 0 5px #047857);
}

@media (forced-colors: active) {
  .ostu-filters__chips .ostu-chip:focus-visible {
    outline: 2px solid;
    outline-offset: 2px;
  }
}

/* The × — a 24px circle carrying a 12px glyph (sample 1461). It is a <span>
   with a &times; character, not an SVG, so the glyph is sized with font-size
   and centred with line-height rather than with a viewBox. */
.ostu-filters__chips .ostu-chip .ostu-chip__x {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-circle, 50%);
  background: var(--brand-a2, rgb(4 120 87 / .12));
  color: var(--brand, #047857);
  font-size: 15px;
  line-height: var(--lh-flat, 1);
  transition: background var(--dur-fast, 120ms) var(--ease, cubic-bezier(.2, .6, .3, 1));
}

.ostu-filters__chips .ostu-chip:hover .ostu-chip__x,
.ostu-filters__chips .ostu-chip:focus-visible .ostu-chip__x {
  background: var(--brand-a3, rgb(4 120 87 / .20));
  color: var(--brand, #047857);
}

.ostu-filters__chips .ostu-chip:active .ostu-chip__x {
  background: var(--brand-a3, rgb(4 120 87 / .20));
  color: var(--brand-active, #024430);
}

/* "Tühjenda kõik" is a secondary action, not an active filter, so it keeps the
   neutral family: surface + border-strong + muted text (sample 1460's first
   chip). Same height and same tap zone as its neighbours. */
.ostu-filters__chips .ostu-chip.ostu-chip--clear {
  background: var(--surface, #ffffff);
  border-color: var(--border-strong, #cbd5e1);
  color: var(--text-muted, #475569);
  padding: 0 14px;
}

.ostu-filters__chips .ostu-chip.ostu-chip--clear:hover {
  background: var(--surface-muted, #f1f5f9);
  border-color: var(--border-strong, #cbd5e1);
  color: var(--text, #0f172a);
}

.ostu-filters__chips .ostu-chip.ostu-chip--clear:active {
  background: var(--surface-muted, #f1f5f9);
  color: var(--text, #0f172a);
  /* press movement intentionally omitted — motion.css owns it shop-wide as a
     scale(.985); a translateY here would give the shop two press languages
     depending on which list a control happens to sit in. Colour and shadow
     changes below stay: they are the other two press signals. */
}

/* Reduced motion, COMPLETE: the press must still be legible without the sink,
   so the transform goes and the colour step stays. */
@media (prefers-reduced-motion: reduce) {
  .ostu-filters__chips .ostu-chip,
  .ostu-filters__chips .ostu-chip .ostu-chip__x {
    transition: none;
  }
  .ostu-filters__chips .ostu-chip:active,
  .ostu-filters__chips .ostu-chip.ostu-chip--clear:active {
    transform: none;
  }
}


/* ==========================================================================
   Print
   ========================================================================== */
@media print {
  .sticky-atc,
  .og-bottomnav,
  .ostu-filters__chips { display: none !important; }
}
