/* ══════════════════════════════════════════════════════════════════════════
   Browser Extensions — DELTA over the AI Directory design system
   --------------------------------------------------------------------------
   /browser-extensions wears /ai-directory's sheet
   (assets/css/ext/v2-public-directory-listing.css) by using that page's own
   `.v2x .dir-*` class names. Sharing the sheet rather than copying it is what
   keeps the two pages from drifting — a snapshot was tried first and rotted in
   two days.

   This file holds ONLY what a catalogue of browser extensions needs and a
   catalogue of AI tools has no concept of:

     §RISK   the risk meter — facet rail and trending rail only
     §CARD   the meta-row slot the extension card adds to `.dir-tc`
     §HERO   hero tiles carrying a monogram instead of a product logo
     §DECK   the sixth stat tile's tone, absent from the directory's cycle

   Loaded LAST of the three sheets, so it wins where it must. Everything it
   does not define is inherited — deliberately. If a rule here duplicates the
   directory's, delete it here: the point of the delta is that it is small
   enough to read.

   Tone vocabulary is the directory's, not a new one. Before adding a
   `data-tone` value, check it exists in the directory sheet for THAT component
   — an unmatched tone falls back to blue SILENTLY. Verified ranges:
     .dir-hh-stat      12 tones   .dir-tc-pill    10
     .dir-cat-card      8         .dir-why-card    6
     .dir-ts-ic / .dir-ts-opt-ic  5  ← amber blue cyan indigo violet ONLY

   Dark mode: the directory sheet keys dark off `body.theme-dark`. Every rule
   here that sets a colour declares its dark twin the same way, in the same
   block, so a light-only addition can't slip through review.
   ══════════════════════════════════════════════════════════════════════════ */

/* ═══ §RISK — permission risk ══════════════════════════════════════════════
   The module's whole editorial angle: what an extension ASKS FOR, not only
   what it does. The three-step meter states low/medium/high in a form a pill
   label alone has no room for.

   Two placements, both STANDALONE: the facet rail and the trending rail. The
   listing CARDS carried a third reading of this — a toned `.dir-tc-pill`
   wrapping the meter — until 2026-08-22, when the grid card and the list row
   both dropped it on request. Nothing wraps the meter in a pill any more.

   ⚠ THE SIGNAL IS FILLED-VS-HOLLOW, NOT COLOUR, AND NOT LUMINANCE.

   The first version lit the bars with flat tone colours (#0F9F6E green,
   #D97706 amber) over a light grey track. Measured against the composited
   track those came out at 2.53:1 and 2.38:1 — under the 3:1 floor for
   non-text UI, which means the difference between "one bar lit" and "no bars
   lit" was not reliably visible in light mode. The bars are the whole control:
   if lit and unlit are hard to separate, the meter reads as decoration.

   Two changes fix it and keep it fixed:

   1. A lit bar is SOLID, an unlit bar is an OUTLINE. That is a difference in
      form, so it survives any ground, either theme, and a viewer who cannot
      separate the green from the amber at all.
   2. Both states are drawn in `currentColor`, so the meter takes its ink from
      whatever wraps it rather than hardcoding one that has to be re-checked
      against every surface it might land on.

   Because both surviving placements are standalone, each sets that colour
   itself — measured against the page surface, not against the raw hue. If a
   toned wrapper is ever reintroduced, it can inherit instead. */

.v2x .cxr-meter{display:inline-flex;align-items:center;gap:4px;vertical-align:middle;color:inherit}
.v2x .cxr-meter i{display:block;width:13px;height:5px;border-radius:2.5px;
    background:transparent;box-shadow:inset 0 0 0 1.25px currentColor;opacity:.34;
    transition:opacity .18s ease,background-color .18s ease}
/* Lit bars: solid fill, full strength. nth-child rather than a class so the
   markup stays three identical <i>s and the level lives in one attribute. */
.v2x .cxr-meter[data-risk="low"]    i:nth-child(1),
.v2x .cxr-meter[data-risk="medium"] i:nth-child(-n+2),
.v2x .cxr-meter[data-risk="high"]   i{background:currentColor;opacity:1;box-shadow:none}

/* Standalone placements — no pill to inherit an ink from. Measured on the
   card/rail surface: light 4.9–6.3:1, dark 8.0–13:1, all well past the 3:1
   non-text floor.

   The colour is set on the WRAPPER, not on the meter, so the meter's bars
   (currentColor) and the trending rail's text level inherit the same ink from
   one declaration. Setting it on `.cxr-meter` would have coloured the bars and
   left the label beside them at the row's default grey. */
.v2x .dir-fx-chk .cxr-meter[data-risk="low"],
.v2x .dir-tr-rt[data-risk="low"]   {color:#0A7A54}
.v2x .dir-fx-chk .cxr-meter[data-risk="medium"],
.v2x .dir-tr-rt[data-risk="medium"]{color:#A85D00}
.v2x .dir-fx-chk .cxr-meter[data-risk="high"],
.v2x .dir-tr-rt[data-risk="high"]  {color:#BE123C}
body.theme-dark .v2x .dir-fx-chk .cxr-meter[data-risk="low"],
body.theme-dark .v2x .dir-tr-rt[data-risk="low"]   {color:#34D399}
body.theme-dark .v2x .dir-fx-chk .cxr-meter[data-risk="medium"],
body.theme-dark .v2x .dir-tr-rt[data-risk="medium"]{color:#FBBF24}
body.theme-dark .v2x .dir-fx-chk .cxr-meter[data-risk="high"],
body.theme-dark .v2x .dir-tr-rt[data-risk="high"]  {color:#FB7185}

/* The facet rail's risk rows carry the same meter, sized down to sit on one
   line with the label and the count without pushing the count off the edge. */
.v2x .dir-fx-chk .cxr-meter{margin-inline-end:7px;flex:0 0 auto}
.v2x .dir-fx-chk .cxr-meter i{width:11px;height:4px}

/* Trending rail: meter beside its own label, because there is no pill and no
   sentence around it there. An unlabelled three-bar gauge in a ranked list is
   a puzzle, not a datum. */
.v2x .dir-tr-rt{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.v2x .dir-tr-rt .cxr-lvl{font:600 10.5px/1 ui-sans-serif,system-ui,sans-serif;
    letter-spacing:.02em;text-transform:uppercase;color:currentColor}
.v2x .dir-tr-rt .cxr-meter i{width:9px;height:4px}

/* ═══ §BUSY — results dimmed while a filter is in flight ═══════════════════
   The toolbar already says "Updating…", but the results themselves are the
   thing the visitor is watching, and on a fast connection the grid swaps with
   no indication that anything was requested.

   This is a DELTA, not a copy: `is-busy` has no rule in the directory sheet,
   in cx-public.css, or anywhere else — `wire:loading.class="is-busy"` was
   landing a class nothing styled. The class also had to move off `.dir-lx`,
   which the directory sheet defines as the list-mode flex column rather than a
   generic results wrapper.

   Kept deliberately gentle: a heavy fade on every keystroke of a debounced
   search reads as flicker. Opacity only — no transform, no blur — so nothing
   reflows and the page does not appear to jump while typing. */
.v2x .cx-results{transition:opacity .18s ease}
.v2x .cx-results.is-busy{opacity:.45;pointer-events:none}
/* A visitor who has asked for less motion still gets the state, just without
   the fade animating. */
@media (prefers-reduced-motion:reduce){
    .v2x .cx-results{transition:none}
}

/* ═══ §BTN — card CTA: DO NOT override the tone ════════════════════════════
   ⚠ There was a `body:not(.theme-dark) .v2x .dir-tc-btn{background-color:#3174D8}`
   rule here. It is DELETED on purpose — do not re-add it.

   The directory's card button is TONE-CYCLED: its base rule is
   `.dir-tc-btn{background-color:var(--dtc-ink)}`, and `--dtc-ink` is set per
   card by `.dir-tc:nth-child(8n+N)` (blue, violet, emerald, amber, rose, cyan,
   indigo, orange). Every card's CTA is the card's own colour — that is the
   whole look of the section. Setting a flat `background-color` here overrode
   `var(--dtc-ink)` on EVERY card, so all ten buttons rendered the same blue and
   the section stopped matching /ai-directory. The user flagged exactly that.

   The rule had been added as a contrast fix — flat blue #3680ED is 3.84:1 with
   white. But the directory ships those same tone buttons at the same ratios
   (blue/emerald/cyan land 3.68–3.84 on their light stop), so "match the
   directory" and "flatten to one accessible blue" are in direct conflict, and
   the user chose the match. The button now inherits `var(--dtc-ink)` untouched
   and is pixel-identical to the directory's.

   If button contrast is ever raised, do it WITHOUT breaking the tone and do it
   on BOTH pages at once: switch the shared base rule from `var(--dtc-ink)` to
   `var(--dtc-ink-dark)` in the directory sheet (every dark tone clears 4.5 and
   stays tone-cycled). That is a shared-sheet decision, not a BE-only override. */

/* ═══ §CARD — the card slot the extension card adds ═══════════════════════ */

/* The directory card's meta row is one line of pills. The extension card can
   still put two there (badge · price), and a narrow column is where they would
   otherwise clip, so the row wraps. Kept after the risk chip was removed on
   2026-08-22: wrapping costs nothing when one pill fits. */
.v2x .dir-tc .dir-tc-meta{flex-wrap:wrap;row-gap:6px}

/* ═══ §HERO — monogram tiles ═══════════════════════════════════════════════
   The directory's hero tiles carry product logos. Every seeded extension has
   `icon` NULL, so a tile here would be an empty box. These render the same
   tile with a tone-tinted monogram, and swap to the image the moment a real
   icon is uploaded — `:has(img)` drops the fill so an uploaded logo is never
   painted over with a brand colour it does not own. */

.v2x .dir-hh-tile .cxt-mono{display:grid;place-items:center;width:100%;height:100%;
    border-radius:inherit;font:700 20px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:-.02em}
/* ⚠ THESE ARE NOT THE BRAND HUES AT FULL STRENGTH, AND MUST NOT BE PUT BACK.

   The first version of this block used the palette's display values —
   #3680ED, #7C3AED, #0F9F6E, #D97706 paired with a lighter stop. A gradient
   has to be measured at its LIGHTEST point, not its midpoint, and at that end
   white text came out at:

       blue 2.82:1 · violet 3.63:1 · emerald 2.48:1 · amber 2.12:1

   Three of the four fail even the 3:1 large-text floor, and the monogram is
   the tile's only content. It looked fine at a glance because a saturated
   fill reads as "strong" — saturation is not luminance, which is the whole
   reason this needs measuring rather than eyeballing.

   Each hue below is scaled toward black until white clears 4.5:1 at BOTH
   stops. Measured white-on-fill, lightest stop first:

       blue 4.53 / 4.55 · violet 4.56 / 5.70 · emerald 4.55 / 4.53 · amber 4.51 / 4.50

   ONE SET SERVES BOTH THEMES, and that is a measured result rather than an
   omission: the same fills sit at 4.23–5.36:1 against the light hero ground
   (#F6F8FC) and 3.29–4.16:1 against the dark one (#0B1220), so the plate is
   clear of the 3:1 non-text floor either way. A `body.theme-dark` twin here
   would change numbers that already pass in both directions. The header's
   "every colour declares its dark twin" rule is satisfied by this note: the
   twin was considered and is deliberately absent, not forgotten. */
.v2x .dir-hh-tile[data-tone="blue"]    .cxt-mono{background:linear-gradient(145deg,#3174D8,#4677BD);color:#fff}
.v2x .dir-hh-tile[data-tone="violet"]  .cxt-mono{background:linear-gradient(145deg,#7C3AED,#885ED5);color:#fff}
.v2x .dir-hh-tile[data-tone="emerald"] .cxt-mono{background:linear-gradient(145deg,#0D875D,#258563);color:#fff}
.v2x .dir-hh-tile[data-tone="amber"]   .cxt-mono{background:linear-gradient(145deg,#B36205,#A06C1F);color:#fff}

/* An uploaded icon wins over the monogram treatment entirely. */
.v2x .dir-hh-tile:has(img) .cxt-mono{display:none}

/* ═══ §DECK — sixth stat tone ══════════════════════════════════════════════
   The directory cycles six stat tones; this page's sixth figure is "open
   source", which reads green. `emerald` is already spent on "verified", so the
   tile uses `teal` — present in the directory sheet's 12-tone stat range, so
   this is a selection, not a new colour. Left as a comment rather than a rule
   precisely because no rule is needed; the note stops the next person adding
   one. */

