/* ══════════════════════════════════════════════════════════════════════════
   TEMPLATE LIBRARY — DELTA over the AI Directory design system
   --------------------------------------------------------------------------
   /templates, /templates/categories and /templates/categories/{slug} wear
   /ai-directory's sheet — 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 pages from drifting: /browser-extensions tried a
   snapshot first and it rotted in two days.

   ⚠ AN EDIT TO THE DIRECTORY SHEET NOW REACHES FIVE PAGES — /ai-directory,
     /browser-extensions, /gpts, /workflows and /templates*. Check all five.

   This file holds ONLY what a catalogue of editable DESIGN FILES needs and a
   catalogue of tools has no concept of:

     §PLATE  the icon plate — a template has no logo, but its category has a
             colour, and that colour must never become the glyph
     §COVER  the card's media area, which breaks out of `.dir-tc`'s padding
     §FMT    the file-format chips (Canva · Figma · PSD …)
     §FLAG   the featured ribbon on the cover
     §CHIP   the active-filter chip row above the results
     §BUSY   the dim-while-filtering state the directory keys on a class it
             does not define
     §HERE   the "you are here" marker on the category rail
     §GRID   the categories PAGE grid (the listing keeps the snap rail)
     §STRIP  the featured strip on /templates/categories
     §CTA    the submit band (admin-gated, module-specific)
     §MISC   small things: the see-all link, empty category cards
     §RESP   the responsive fixes the above need

   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 a delta is that it stays small
   enough to read in one sitting.

   ⚠ THE TONE VOCABULARY IS THE DIRECTORY'S, NOT A NEW ONE. An unmatched
   `data-tone` falls back to blue SILENTLY with nothing reporting an error.
   Verified ranges, read off the DEPLOYED directory sheet on 2026-08-14:
     .dir-hh-stat     12  amber blue cyan emerald green indigo orange pink
                          rose slate teal violet
     .dir-tc-pill     10  amber blue cyan emerald indigo orange rose slate
                          teal violet
     .dir-cat-card     8  amber blue cyan emerald indigo orange rose violet
     .dir-fx-dot       6  amber blue cyan emerald rose violet  ← NO indigo
     .dir-why-card     6  amber blue cyan emerald rose violet
     .dir-ts-ic /
     .dir-ts-opt-ic    5  amber blue cyan indigo violet        ← the tight one

   ⚠ BREAKPOINTS ARE THE SHARED SHEET'S, NOT BOOTSTRAP'S. Measured off the
   DEPLOYED sheet on 2026-08-14, its full ladder is
     1500 · 1180 · 1100 · 1024 · 900 · 820 · 700 · 680 · 640 · 560 · 520 ·
     480 · 420 · 400 · 380
   1500 stacks the sidebars, 820 goes single-column + filter accordion, 680
   goes one card per row AND drops `.dir-tc`'s top padding 42px → 20px (which
   §COVER's negative margin has to follow, or the cover gutters). This file
   uses 900 · 820 · 680 · 520 · 400, all on that ladder. Shipping on
   991.98/767.98 puts a break 140px from one the page already has, and the
   layout then changes twice in a row for no reason.
   Re-measure with:
     grep -o '@media[^{]*' <sheet> | grep -o '[0-9]\+px' | sort -un

   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 cannot slip through review.

   `:has()` has ZERO precedent in the shared sheet (grep it: 0 hits) and is
   not used here — Safari below 15.4 drops the whole selector, not just the
   clause.
   ══════════════════════════════════════════════════════════════════════════ */


/* ═══ §LINK — the one ink token this sheet adds ════════════════════════════
   `--brand-blue` (#3680ED by default) is a FILL colour, tuned so white sits
   on it in a button. As INK it measures 3.61:1 on the page ground and 3.84:1
   on a white card — both under the 4.5 text floor. Every link and every
   small filled control in this sheet therefore reads `--tplx-link` instead.

   #2060C0 is NOT invented: it is the directory sheet's own `--dtc-ink-dark`
   for the blue tone, so the hue family is unchanged and the value already
   ships in the stack. Measured: 5.65:1 on #f6f8fc · 6.01:1 on #ffffff · and
   6.01:1 for white sitting ON it.

   It deliberately does NOT fall back through `var(--brand-blue)`: an admin
   can set that token to any hex, and an arbitrary hue cannot be trusted as
   ink for exactly the reason §PLATE spells out below. Dark mode keeps
   #7FB0F7, which measures 8.62:1 on the dark ground. */
.v2x.tplx{--tplx-link:#2060C0}
body.theme-dark .v2x.tplx{--tplx-link:#7FB0F7}

/* ═══ §PLATE — the accent is the PLATE, never the glyph ════════════════════
   A template has no logo. What it does have is a CATEGORY, and every category
   carries `color` — any hex an admin typed. The seeded twelve alone include
   #F08C00, #2F9E44, #0CA678, #1098AD and #D6336C, which as a GLYPH on a light
   plate measure ~2.2–3.0:1 — under even the 3:1 non-text floor, and the glyph
   is the plate's only content. Saturation is not luminance, which is exactly
   why an arbitrary admin hue can never be trusted as ink.

   The fix needs no per-hue table: a white scrim is painted OVER the accent, so
   whatever the hue the plate lands light, and the glyph is drawn in the
   sheet's own guaranteed ink. Dark mode paints a dark scrim and flips the ink.
   Every hue passes in both themes by construction.

   `linear-gradient(rgba(),rgba())` over a colour rather than color-mix(),
   which Safari did not ship until 16.2 — a plate that vanishes on an older
   iPhone is not a trade worth making for shorter CSS.

   ⚠ A CONTRAST SWEEP WILL MISREAD THIS. The `background` shorthand sets
   background-image (the scrim) AND background-color (the raw accent
   underneath). Anything reading `backgroundColor` measures the invisible
   base. Composite the backgroundImage scrim before judging the plate. */
.v2x.tplx .tplx-plate,
.v2x.tplx .dir-hh-tile.tplx-tile{
  background:linear-gradient(rgba(255,255,255,.88),rgba(255,255,255,.88)),var(--tplx-accent,#3680ED);
  color:var(--v2-ink);
  display:grid;place-items:center;overflow:hidden}
body.theme-dark .v2x.tplx .tplx-plate,
body.theme-dark .v2x.tplx .dir-hh-tile.tplx-tile{
  background:linear-gradient(rgba(16,20,28,.82),rgba(16,20,28,.82)),var(--tplx-accent,#3680ED);
  color:#EAF0FA}

/* Glyph sizing per placement. The plate BOXES (78px hero tile, 34px rail)
   come from the directory sheet — only the glyph inside them is ours. */
.v2x.tplx .dir-hh-tile.tplx-tile svg{width:30px;height:30px}
.v2x.tplx .dir-tr-lg.tplx-plate svg{width:17px;height:17px}
.v2x.tplx .dir-tr-lg.tplx-plate img{width:100%;height:100%;object-fit:cover;border-radius:inherit}

/* The category rail card's icon is already tone-cycled by the directory sheet
   (it sets --dir-plate-ink from the card's data-tone), so this only sizes the
   SVG. No colour is set on purpose — inheriting keeps the rail identical to
   /ai-directory's. */
.v2x.tplx .dir-cat-card-ico svg{width:27px;height:27px}


/* ═══ §COVER — the card media area ════════════════════════════════════════
   `.dir-tc` is `padding:42px 16px 18px` with `overflow:hidden` and a 20px
   radius. The cover breaks out of that padding with a negative margin, so the
   card's OWN overflow clips it to the top corners — no second radius, and no
   risk of the two disagreeing when the shared sheet changes its radius.

   Why a cover at all when a tool card has a 66px logo plate: a template is a
   VISUAL artefact and the thing a visitor scans for is what it looks like. A
   66px monogram in the middle of a template grid tells them nothing.

   When `thumbnail` is NULL the cover renders a tone-washed field with the
   category glyph. That is deliberately NOT a fake preview: it says what the
   template is FOR without pretending to show artwork that has not been
   uploaded. A real upload replaces it with no CSS change. */
.v2x.tplx .tplx-cover{
  position:relative;z-index:2;
  display:block;width:calc(100% + 32px);margin:-42px -16px 14px;
  aspect-ratio:16 / 10;overflow:hidden;
  background:var(--dtc-bg);
  border-bottom:1px solid var(--v2-line)}
body.theme-dark .v2x.tplx .tplx-cover{border-bottom-color:rgba(255,255,255,.08)}

/* Older Safari / Firefox ESR without aspect-ratio: a padding box keeps the
   proportion. Modern engines ignore this because aspect-ratio wins. */
@supports not (aspect-ratio: 16 / 10){
  .v2x.tplx .tplx-cover{height:0;padding-bottom:62.5%}
}

.v2x.tplx .tplx-cover img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform .5s var(--ease-out)}
.v2x .tplx-tc:hover .tplx-cover img{transform:scale(1.045)}

/* The generated field. `--dtc-ink` is the card's own cycled tone, so the
   cover matches the CTA below it and the grid reads as one system. */
.v2x.tplx .tplx-cover-art{
  position:absolute;inset:0;display:grid;place-items:center;
  background:
    radial-gradient(120% 90% at 50% 8%, rgba(255,255,255,.55) 0%, rgba(255,255,255,0) 60%),
    var(--dtc-bg)}
body.theme-dark .v2x.tplx .tplx-cover-art{
  background:
    radial-gradient(120% 90% at 50% 8%, rgba(255,255,255,.06) 0%, rgba(255,255,255,0) 60%),
    var(--dtc-bg)}

/* A faint page grid behind the glyph — the visual shorthand for "a layout".
   Drawn with two repeating-linear-gradients rather than an SVG so it costs no
   request and scales with the card. */
.v2x.tplx .tplx-cover-grid{
  position:absolute;inset:0;
  background-image:
    repeating-linear-gradient(0deg, rgba(16,24,40,.055) 0 1px, transparent 1px 22px),
    repeating-linear-gradient(90deg, rgba(16,24,40,.055) 0 1px, transparent 1px 22px);
  -webkit-mask-image:radial-gradient(80% 70% at 50% 45%, #000 30%, transparent 78%);
          mask-image:radial-gradient(80% 70% at 50% 45%, #000 30%, transparent 78%)}
body.theme-dark .v2x.tplx .tplx-cover-grid{
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,.055) 0 1px, transparent 1px 22px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.055) 0 1px, transparent 1px 22px)}

.v2x.tplx .tplx-cover-ico{
  position:relative;display:grid;place-items:center;
  width:56px;height:56px;border-radius:17px;
  background:#fff;color:var(--dtc-ink-dark);
  box-shadow:0 2px 6px rgba(16,24,40,.09),0 10px 24px -14px rgba(16,24,40,.4);
  transition:transform .34s var(--ease-spring)}
.v2x.tplx .tplx-cover-ico svg{width:26px;height:26px}
.v2x .tplx-tc:hover .tplx-cover-ico{transform:translateY(-2px) scale(1.05)}
body.theme-dark .v2x.tplx .tplx-cover-ico{
  background:rgba(255,255,255,.09);color:var(--dtc-ink-dark);
  box-shadow:0 2px 6px rgba(0,0,0,.4),0 10px 24px -14px rgba(0,0,0,.8)}

/* File size, bottom-right of the cover.
   NO DARK TWIN, deliberately: this is a scrim badge over an image-or-wash
   surface, the same pattern as a video duration chip. A near-black scrim
   with white ink is correct against BOTH the light tone wash and the dark
   one — measured 8.29–8.48:1 light, and higher in dark because the wash
   underneath is already dark. Making it theme-reactive would make it WORSE
   in dark, not better.
   Ink measured on its own fill:
   #FFFFFF on rgba(9,14,24,.72) over the cover = 12.4:1 worst case (the
   lightest cover wash the tone cycle produces is #ffedd5 / amber). */
/* NO DARK TWIN, DELIBERATELY. The badge is a dark scrim sitting on the cover,
   which is tone-washed in BOTH themes. White on rgba(9,14,24,.72) measures
   8.29–8.48:1 over the four light washes and higher still over the dark ones,
   because the scrim only gets darker. A theme-reactive version would be a
   second value that never reads differently. */
.v2x.tplx .tplx-size{
  position:absolute;right:10px;bottom:9px;z-index:2;
  padding:3px 8px;border-radius:8px;
  background:rgba(9,14,24,.72);color:#fff;
  font-size:10.5px;font-weight:700;line-height:1.5;letter-spacing:.01em;
  font-variant-numeric:tabular-nums;
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}

/* The list row's cover reuses `.dir-lc-logo`'s box (the directory sizes it),
   so only the fill and the glyph are ours. */
.v2x.tplx .tplx-lc-cover{overflow:hidden;background:var(--dtc-bg);color:var(--dtc-ink-dark)}
.v2x.tplx .tplx-lc-cover img{width:100%;height:100%;object-fit:cover}
.v2x.tplx .tplx-lc-cover svg{width:22px;height:22px}
.v2x.tplx .tplx-lc-size{
  font-size:11px;font-weight:650;color:var(--v2-muted);font-variant-numeric:tabular-nums}


/* ═══ §FMT — file-format chips ═════════════════════════════════════════════
   Which apps a template opens in is the single most-used filter in a template
   library, so it earns a row on the card rather than a line in the
   description. Neutral by design: ten branded colours on a card that already
   carries a tone-cycled CTA and a licence pill is three colour systems
   arguing. The chips read as metadata; the pill reads as status.

   Ink: #475467 on #F2F4F7 = 7.53:1 · #C3CAD6 on rgba(255,255,255,.07)
   composited over the dark card (#1C1F2A) = 9.12:1. */
.v2x.tplx .tplx-fmts{
  display:flex;align-items:center;justify-content:center;gap:5px;
  flex-wrap:wrap;margin-top:10px;max-width:100%}
.v2x.tplx .tplx-fmt{
  display:inline-flex;align-items:center;
  padding:2px 7px;border-radius:7px;
  background:#F2F4F7;color:#475467;
  font-size:10px;font-weight:700;line-height:1.6;letter-spacing:.02em;
  text-transform:uppercase;white-space:nowrap;
  box-shadow:inset 0 0 0 1px rgba(16,24,40,.05)}
.v2x.tplx .tplx-fmt.is-more{background:transparent;color:var(--v2-muted);box-shadow:none}
body.theme-dark .v2x.tplx .tplx-fmt{
  background:rgba(255,255,255,.07);color:#C3CAD6;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}
body.theme-dark .v2x.tplx .tplx-fmt.is-more{background:transparent;box-shadow:none}

/* The two Google formats spell out in full and would wrap the row; they are
   the only tokens longer than five characters. */
.v2x.tplx .tplx-fmt[data-fmt^="google-"]{text-transform:none;letter-spacing:0}

/* In a list row the chips sit inline with the pills, left-aligned. */
.v2x .tplx-lc .dir-lc-meta{flex-wrap:wrap;row-gap:7px}
.v2x .tplx-lc .dir-lc-meta .tplx-fmts{margin-top:0;justify-content:flex-start}


/* ═══ §FLAG — the featured ribbon ══════════════════════════════════════════
   Sits on the cover, opposite the bookmark button. Inks measured on their own
   fills, both themes:
     #92400E on #FEF3C7 = 8.31:1   ·   #FBBF24 on #3B2A08 = 8.94:1 */
.v2x.tplx .tplx-flag{
  position:absolute;left:10px;top:10px;z-index:3;
  display:inline-flex;align-items:center;gap:5px;
  padding:4px 9px;border-radius:999px;
  background:#FEF3C7;color:#92400E;
  box-shadow:inset 0 0 0 1px rgba(146,64,14,.16);
  font-size:10px;font-weight:800;letter-spacing:.03em;text-transform:uppercase;
  line-height:1.5;pointer-events:none}
.v2x.tplx .tplx-flag svg{width:11px;height:11px;flex:0 0 auto}
body.theme-dark .v2x.tplx .tplx-flag{
  background:#3B2A08;color:#FBBF24;box-shadow:inset 0 0 0 1px rgba(251,191,36,.22)}

/* In a list row there is no cover to pin to, so it flows in the name row. */
.v2x.tplx .tplx-flag.is-inline{position:static;flex:0 0 auto}

/* The bookmark button sits ON the cover, where the directory has it on a flat
   card. Give it a surface so it stays legible over any cover. */
.v2x .tplx-tc .dir-tc-bk{
  z-index:4;background:rgba(255,255,255,.86);color:#667085;
  box-shadow:0 1px 3px rgba(16,24,40,.14);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.v2x .tplx-tc .dir-tc-bk:hover{background:#fff;color:var(--dtc-ink-dark)}
.v2x .tplx-tc .dir-tc-bk.is-on{background:#fff;color:var(--dtc-ink)}
body.theme-dark .v2x .tplx-tc .dir-tc-bk{
  background:rgba(18,22,30,.78);color:#A9B2C3;box-shadow:0 1px 3px rgba(0,0,0,.5)}
body.theme-dark .v2x .tplx-tc .dir-tc-bk:hover,
body.theme-dark .v2x .tplx-tc .dir-tc-bk.is-on{background:rgba(28,33,44,.94);color:var(--dtc-ink-dark)}


/* ═══ §CHIP — the active-filter row ════════════════════════════════════════
   Lets a visitor back out of a five-facet query one step at a time. The
   facet rail can already do this, but on ≤820px it is a collapsed accordion,
   so without these chips the only way out on a phone is Clear all.

   Ink: #344054 on #EEF2F7 = 9.36:1 · #D3D9E4 on rgba(255,255,255,.06) over
   the page ground = 11.1:1. */
.v2x.tplx .tplx-chips{
  display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:0 0 14px}
.v2x.tplx .tplx-chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 6px 5px 11px;border-radius:999px;
  background:#EEF2F7;color:#344054;
  font-size:12px;font-weight:650;line-height:1.5;
  box-shadow:inset 0 0 0 1px rgba(16,24,40,.06)}
.v2x.tplx .tplx-chip button{
  display:inline-grid;place-items:center;
  width:17px;height:17px;padding:0;border:0;border-radius:50%;
  background:rgba(16,24,40,.08);color:inherit;
  font-size:13px;line-height:1;cursor:pointer;font-family:inherit;
  transition:background .16s ease,color .16s ease}
.v2x.tplx .tplx-chip button:hover{background:var(--tplx-link);color:#fff}
/* ⚠ --tplx-link is a LIGHT blue in dark mode, so white on it is 2.22:1.
   Dark keeps the same fill and flips the INK: #0E1420 on #7FB0F7 = 8.30:1. */
body.theme-dark .v2x.tplx .tplx-chip button:hover{background:var(--tplx-link);color:#0E1420}
/* ⚠ `--tplx-link` flips to a LIGHT blue in dark mode, so the inherited white
   × measured 2.22:1 — all but invisible on hover, and only a per-theme sweep
   catches it because the light theme reads 6.01:1. A light fill takes dark
   ink: #0E1420 on #7FB0F7 = 8.30:1. */
body.theme-dark .v2x.tplx .tplx-chip button:hover{color:#0E1420}
.v2x.tplx .tplx-chip-clear{
  padding:5px 11px;border:0;border-radius:999px;
  background:transparent;color:var(--tplx-link);
  font-size:12px;font-weight:700;cursor:pointer;font-family:inherit;
  text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(32,96,192,.38);
  transition:text-decoration-color .16s ease}
.v2x.tplx .tplx-chip-clear:hover{text-decoration-color:currentColor}
body.theme-dark .v2x.tplx .tplx-chip-clear{text-decoration-color:rgba(127,176,247,.42)}
body.theme-dark .v2x.tplx .tplx-chip{
  background:rgba(255,255,255,.06);color:#D3D9E4;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}
body.theme-dark .v2x.tplx .tplx-chip button{background:rgba(255,255,255,.1)}
/* dark ink comes from the --tplx-link token above; nothing to restate */


/* ═══ §BUSY — dim while filtering ══════════════════════════════════════════
   `wire:loading.class="is-busy"` lands a DEAD class otherwise: no sheet in
   the stack defines `.is-busy`. Fourth module in a row to hit this — see the
   /workflows, /gpts and /browser-extensions notes.

   `pointer-events:none` is the point, not the dim: mid-filter the rows on
   screen are the OLD set, so a click lands on a card that is about to be
   replaced by a different one in the same position. */
.v2x.tplx .tplx-results{transition:opacity .16s ease,filter .16s ease}
.v2x.tplx .tplx-results.is-busy{opacity:.45;filter:saturate(.7);pointer-events:none}


/* ═══ §HERE — "you are here" on the category rail ══════════════════════════
   On /templates/categories/{slug} the rail still renders every category, so
   the current one needs to be identifiable. Uses a ring rather than a fill so
   the card's own `data-tone` keeps working. */
.v2x.tplx .dir-cat-card.is-here{
  box-shadow:inset 0 0 0 2px var(--brand-blue,#3680ED),0 10px 26px -18px rgba(16,24,40,.4)}
body.theme-dark .v2x.tplx .dir-cat-card.is-here{
  box-shadow:inset 0 0 0 2px #60A4F5,0 10px 26px -18px rgba(0,0,0,.8)}


/* ═══ §GRID — the categories PAGE grid ═════════════════════════════════════
   The listing keeps the directory's horizontal snap RAIL: there the cards are
   a secondary band under a result set. On /templates/categories the cards ARE
   the page, and hiding two thirds of them behind a horizontal scroll is the
   wrong call, so they lay out as a grid instead.

   `auto-fit` + a track RANGE rather than a fixed column count, because the
   directory's four-column `.dir-cards` is sized for the lab's ~1056px centre
   column; used full-bleed it makes cards ~385px — the same component 50%
   wider than its twin a few hundred pixels above. Capping the track keeps the
   card WIDTH matching, not the column count. */
.v2x.tplx .dir-cat-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(228px,268px));
  justify-content:center;
  gap:16px;max-width:1240px;margin:0 auto;padding:0 16px}

/* A category with nothing published still lists here (this page is the
   taxonomy). It is dimmed rather than hidden, and rather than being made
   unclickable — the hub renders a designed empty state. */
.v2x.tplx .dir-cat-grid .dir-cat-card.is-empty{opacity:.62}
.v2x.tplx .dir-cat-grid .dir-cat-card.is-empty:hover{opacity:1}


/* ═══ §STRIP — featured strip on /templates/categories ═════════════════════
   The listing's third grid column has nowhere to live on a page with no
   result set, so the same content becomes a horizontal strip under the grid. */
.v2x.tplx .tplx-strip{max-width:1240px;margin:44px auto 0;padding:0 16px}
.v2x.tplx .tplx-strip-head{
  display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin-bottom:14px}
.v2x.tplx .tplx-strip-head h2{
  margin:0;font-size:19px;font-weight:780;letter-spacing:-.02em;color:var(--v2-ink)}
.v2x.tplx .tplx-strip-head a{
  display:inline-flex;align-items:center;gap:6px;
  font-size:13px;font-weight:700;color:var(--tplx-link);text-decoration:none;
  transition:gap .18s ease}
.v2x.tplx .tplx-strip-head a:hover{gap:9px}
.v2x.tplx .tplx-strip-head a svg{width:15px;height:15px}
/* dark ink comes from the --tplx-link token above; nothing to restate */

.v2x.tplx .tplx-strip-rail{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
.v2x.tplx .tplx-strip-card{
  display:flex;align-items:center;gap:12px;
  padding:12px 14px;border-radius:16px;
  background:#fff;border:1px solid var(--v2-line);
  text-decoration:none;color:inherit;min-width:0;
  box-shadow:0 1px 2px rgba(16,24,40,.04);
  transition:transform .24s var(--ease-out),border-color .2s ease,box-shadow .24s ease}
.v2x.tplx .tplx-strip-card:hover{
  transform:translateY(-2px);border-color:rgba(54,128,237,.4);
  box-shadow:0 10px 24px -16px rgba(16,24,40,.4)}
body.theme-dark .v2x.tplx .tplx-strip-card:hover{
  border-color:rgba(96,164,245,.42);
  box-shadow:0 10px 24px -16px rgba(0,0,0,.85)}
body.theme-dark .v2x.tplx .tplx-strip-card:hover{
  border-color:rgba(96,164,245,.45);
  box-shadow:0 10px 24px -16px rgba(0,0,0,.85)}
.v2x.tplx .tplx-strip-ico{
  display:grid;place-items:center;flex:0 0 auto;
  width:42px;height:42px;border-radius:13px;overflow:hidden;
  background:linear-gradient(rgba(255,255,255,.88),rgba(255,255,255,.88)),var(--tplx-accent,#3680ED);
  color:var(--v2-ink)}
.v2x.tplx .tplx-strip-ico svg{width:20px;height:20px}
.v2x.tplx .tplx-strip-ico img{width:100%;height:100%;object-fit:cover}
.v2x.tplx .tplx-strip-tx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}
.v2x.tplx .tplx-strip-tx b{
  font-size:13.5px;font-weight:700;color:var(--v2-ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.v2x.tplx .tplx-strip-tx span{
  font-size:11.5px;color:var(--v2-muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.v2x.tplx .tplx-strip-arr{width:16px;height:16px;flex:0 0 auto;color:var(--v2-muted);transition:transform .2s ease}
.v2x.tplx .tplx-strip-card:hover .tplx-strip-arr{transform:translateX(3px)}
body.theme-dark .v2x.tplx .tplx-strip-card{
  background:rgba(28,31,42,.92);border-color:rgba(255,255,255,.08);
  box-shadow:0 1px 2px rgba(0,0,0,.4)}
body.theme-dark .v2x.tplx .tplx-strip-ico{
  background:linear-gradient(rgba(16,20,28,.82),rgba(16,20,28,.82)),var(--tplx-accent,#3680ED);
  color:#EAF0FA}


/* ═══ §CTA — the submit band ═══════════════════════════════════════════════
   ⚠ A GRADIENT MUST BE MEASURED AT EVERY STOP AND AT THE INTERPOLATED
   MIDDLE, not on an average. The obvious brand ramp
   (--brand-blue-dark → --brand-blue → a light blue) measured 3.84:1 at the
   mid stop and 2.82:1 at the light stop against a 4.5 floor on the /workflows
   pass — legible at one end of the band and not the other, which an average
   hides completely.

   These three stops are that pass's corrected set, re-measured here against
   rgba(255,255,255,.92) (the body copy, which is worse than the pure-white
   heading) at 0 / 10 / 25 / 40 / 58 / 70 / 85 / 100%:
     #1B4FB3 → #2F63D1 → #6127C4      worst white = 5.49:1
   It ends violet because darkening the light stop in place turned it slate
   (#416FAF) and killed the band. ONE set serves both themes — the band is a
   solid fill, so it does not need to react to the page ground. */
/* NO DARK TWINS BELOW, deliberately: the band is a SOLID gradient fill, so
   it does not sit on the page ground and has nothing to react to. One set
   serves both themes — the same call /browser-extensions made for its
   hero monogram tiles. Every stop is measured above. */
.v2x.tplx .tplx-cta{
  position:relative;overflow:hidden;isolation:isolate;
  display:flex;align-items:center;justify-content:space-between;gap:24px;
  max-width:1240px;margin:52px auto 0;padding:30px 34px;
  border-radius:24px;
  background:linear-gradient(115deg,#1B4FB3 0%,#2F63D1 52%,#6127C4 100%);
  box-shadow:0 18px 42px -28px rgba(27,79,179,.9)}
.v2x.tplx .tplx-cta-dots{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:radial-gradient(rgba(255,255,255,.22) 1px, transparent 1px);
  background-size:18px 18px;
  -webkit-mask-image:radial-gradient(90% 120% at 88% 20%, #000 0%, transparent 68%);
          mask-image:radial-gradient(90% 120% at 88% 20%, #000 0%, transparent 68%)}
.v2x.tplx .tplx-cta-tx{min-width:0}
.v2x.tplx .tplx-cta-tx h2{
  margin:0 0 6px;font-size:21px;font-weight:800;letter-spacing:-.024em;color:#fff}
.v2x.tplx .tplx-cta-tx p{
  margin:0;font-size:13.5px;line-height:1.6;color:rgba(255,255,255,.92);max-width:56ch}
.v2x.tplx .tplx-cta-btn{
  display:inline-flex;align-items:center;gap:9px;flex:0 0 auto;
  padding:12px 20px;border-radius:14px;
  background:#fff;color:#1B4FB3;
  font-size:13.5px;font-weight:750;text-decoration:none;
  box-shadow:0 8px 20px -12px rgba(0,0,0,.6);
  transition:transform .22s var(--ease-out),gap .2s ease,box-shadow .22s ease}
.v2x.tplx .tplx-cta-btn:hover{transform:translateY(-2px);gap:12px;color:#1B4FB3}
.v2x.tplx .tplx-cta-btn svg{width:16px;height:16px}


/* ═══ §MISC ════════════════════════════════════════════════════════════════ */

/* "See all categories" under the rail on the listing — the rail is capped at
   what fits a horizontal scroll, so the full taxonomy needs a way in. */
.v2x.tplx .tplx-cat-all{display:flex;justify-content:center;margin-top:20px}
.v2x.tplx .tplx-cat-all a{
  display:inline-flex;align-items:center;gap:8px;
  padding:10px 18px;border-radius:13px;
  border:1px solid var(--v2-line);background:#fff;
  color:var(--v2-ink);font-size:13px;font-weight:700;text-decoration:none;
  transition:transform .2s var(--ease-out),border-color .2s ease,gap .18s ease}
.v2x.tplx .tplx-cat-all a:hover{
  transform:translateY(-2px);gap:11px;border-color:rgba(54,128,237,.45);color:var(--tplx-link)}
.v2x.tplx .tplx-cat-all a svg{width:16px;height:16px}
body.theme-dark .v2x.tplx .tplx-cat-all a{
  background:rgba(28,31,42,.92);border-color:rgba(255,255,255,.1);color:#E7ECF5}
body.theme-dark .v2x.tplx .tplx-cat-all a:hover{border-color:rgba(96,164,245,.5);color:var(--tplx-link)}

/* The hero tile tooltip carries two lines here (name + count) where the
   directory's carries name + maker; only the count needs tabular figures. */
.v2x.tplx .dir-hh-tile.tplx-tile .dir-hh-tip b{font-variant-numeric:tabular-nums}



/* ═══ §RESP — on the SHARED sheet's ladder ═════════════════════════════════
   1500 · 1180 · 900 · 820 · 680 · 640 · 520 · 400 · 380. Only the
   breakpoints this delta actually needs are declared. */

/* 900 — the CTA's two halves stop fitting side by side before the page goes
   single-column, because the button is a fixed-width block. */
@media (max-width: 900px){
  .v2x.tplx .tplx-cta{flex-direction:column;align-items:flex-start;gap:18px;padding:26px 24px}
  .v2x.tplx .tplx-strip-rail{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* 820 — the page goes single-column and the facet rail becomes an accordion. */
@media (max-width: 820px){
  .v2x.tplx .dir-cat-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));padding:0 14px}
  .v2x.tplx .tplx-strip{margin-top:34px}

  /* ⚠ iOS zooms a focused input whose font-size is under 16px. The SHARED
     sheet sets `.dir-hh-search input` to 15.5px (14px small-screen), so
     /ai-directory, /browser-extensions, /gpts and /workflows ALL trigger it
     — tap the search box on an iPhone and the page jumps. Fixed here, scoped
     to this module only: the shared miss is real and wants its own pass
     rather than a fifth page-scoped patch pretending to be the fix. */
  .v2x.tplx .dir-hh-search input{font-size:16px}
}

/* 680 — one card per row. The cover's negative margin must follow the
   card's own padding, which the shared sheet drops to 20px 16px at 680. */
@media (max-width: 680px){
  .v2x.tplx .tplx-cover{margin:-20px -16px 12px}
  .v2x.tplx .tplx-strip-rail{grid-template-columns:1fr}
  .v2x.tplx .tplx-cta-tx h2{font-size:19px}
}

/* 520 — chips and format rows are the first things to run out of room. */
@media (max-width: 520px){
  .v2x.tplx .tplx-chips{gap:6px}
  .v2x.tplx .tplx-chip{font-size:11.5px;padding:4px 5px 4px 10px}
  .v2x.tplx .dir-cat-grid{grid-template-columns:1fr;max-width:420px}
  .v2x.tplx .tplx-cta{padding:22px 18px;border-radius:20px}
  .v2x.tplx .tplx-cta-btn{width:100%;justify-content:center}
}

/* 400 — the file-size badge and the featured ribbon start to collide on the
   narrowest phones, so the ribbon loses its label and keeps its star. */
@media (max-width: 400px){
  .v2x.tplx .tplx-flag{font-size:0;gap:0;padding:5px}
  .v2x.tplx .tplx-flag svg{width:12px;height:12px}
  .v2x.tplx .tplx-flag.is-inline{font-size:0;padding:4px}
}

/* Motion: every transform above is decorative. */
@media (prefers-reduced-motion: reduce){
  .v2x.tplx .tplx-cover img,
  .v2x.tplx .tplx-cover-ico,
  .v2x.tplx .tplx-strip-card,
  .v2x.tplx .tplx-strip-arr,
  .v2x.tplx .tplx-cta-btn,
  .v2x.tplx .tplx-cat-all a{transition:none}
  .v2x .tplx-tc:hover .tplx-cover img,
  .v2x .tplx-tc:hover .tplx-cover-ico,
  .v2x.tplx .tplx-strip-card:hover,
  .v2x.tplx .tplx-cta-btn:hover,
  .v2x.tplx .tplx-cat-all a:hover{transform:none}
}
