/* ══════════════════════════════════════════════════════════════════════════
   AI PROJECTS — DELTA over the AI Directory design system
   --------------------------------------------------------------------------
   /ai-projects, /ai-projects/categories and the three hub contexts
   (category · technology · tag) 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 /ai-projects. Check all five.

   This file holds ONLY what a catalogue of buildable open-source PROJECTS
   needs and a catalogue of tools has no concept of:

     §PLATE   the icon plate — a project has no logo, but inherits its
              category's colour
     §FLAG    the featured / trending ribbon on the card
     §STRIP   the tech-stack + licence strip
     §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 anywhere in the stack
     §HERE    the "you are here" marker on the category rail
     §ABOUT   the hub pages' about panel
     §CATGRID /ai-projects/categories — the same cards, a browse layout
     §IOS     the 16px floor that stops iOS zooming on search focus
     §RESP    the handful of 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

   ⚠ NO `:has()` ANYWHERE. It has zero precedent in the directory sheet
   (grep it: 0 hits) and Safari <15.4 drops the entire selector, not just the
   unsupported part.
   ══════════════════════════════════════════════════════════════════════════ */


/* ═══ §PLATE — the icon plate ═══════════════════════════════════════════════
   A project carries no logo (`ai_projects.logo` is NULL on every row) but
   does inherit an icon + colour from its category, which is a richer plate
   than the first letter of its name.

   ⚠ THE ACCENT IS THE PLATE, NEVER THE GLYPH, AND THIS MUST NOT BE
   "SIMPLIFIED" BACK. `--apx-accent` is whatever hex an admin typed on the
   category. The seeded set alone includes #F59E0B, #14B8A6, #06B6D4, #EC4899
   and #F97316, which as a glyph on a light plate measure ~2.2–2.9: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-supplied 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 is used 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.

   ⚠ ANY AUDIT THAT READS `backgroundColor` WILL MISREAD THIS. The shorthand
   sets background-image (the scrim) AND background-color (the raw accent
   underneath). What is painted is the composite. Composite the
   backgroundImage before judging a plate — see the false-positive note on
   the /workflows pass, which reported 6.14:1 for a plate measuring 16:1. */
.v2x.apx .apx-plate{
  background:linear-gradient(rgba(255,255,255,.88),rgba(255,255,255,.88)),var(--apx-accent,#3680ED);
  color:var(--v2-ink);
  display:grid;place-items:center;overflow:hidden}
body.theme-dark .v2x.apx .apx-plate{
  background:linear-gradient(rgba(16,20,28,.82),rgba(16,20,28,.82)),var(--apx-accent,#3680ED);
  color:#EAF0FA}

/* Glyph sizing per placement. The plate BOXES come from the directory sheet
   (66px card, 52px list row, 34px rail); only the glyph inside them is ours.
   These are Lucide SVGs rendered through v2.public.partials.icon, not <i>
   glyphs, so the lever is width/height — a font-size rule here would do
   nothing at all and the icon would sit at its intrinsic 24px everywhere. */
.v2x.apx .dir-tc-logo.apx-plate svg{width:27px;height:27px}
.v2x.apx .dir-lc-logo.apx-plate svg{width:21px;height:21px}
.v2x.apx .dir-tr-lg.apx-plate   svg{width:15px;height:15px}
.v2x.apx .apx-plate i{line-height:1}
.v2x.apx .dir-tc-logo.apx-plate i{font-size:26px}
.v2x.apx .dir-lc-logo.apx-plate i{font-size:20px}
.v2x.apx .dir-tr-lg.apx-plate   i{font-size:14px}

/* Hero tiles get the same treatment at a lighter scrim — they sit on the
   hero's tinted ground rather than on a card, so they can afford more hue. */
.v2x.apx .dir-hh-tile.apx-tile{
  background:linear-gradient(rgba(255,255,255,.9),rgba(255,255,255,.9)),var(--apx-accent,#3680ED);
  color:var(--v2-ink)}
.v2x.apx .dir-hh-tile.apx-tile svg{width:30px;height:30px}
.v2x.apx .dir-hh-tile.apx-tile i{font-size:29px;line-height:1}
body.theme-dark .v2x.apx .dir-hh-tile.apx-tile{
  background:linear-gradient(rgba(20,25,34,.86),rgba(20,25,34,.86)),var(--apx-accent,#3680ED);
  color:#EAF0FA}

/* The category rail card's icon is already tone-cycled by the directory
   sheet, so it is deliberately NOT re-painted here — only sized, because the
   directory's cards carry Font Awesome <i> and ours carry Lucide <svg>. */
.v2x.apx .dir-cat-card-ico svg{width:22px;height:22px}


/* ═══ §FLAG — featured / trending ribbon ════════════════════════════════════
   Absolute in the card's top-right. The directory has no equivalent: its
   cards lead with a rating, and this catalogue has none to show. */
.v2x.apx .apx-flag{
  position:absolute;top:12px;right:12px;z-index:3;
  display:inline-flex;align-items:center;gap:5px;
  padding:4px 9px 4px 7px;border-radius:999px;
  font-size:.66rem;font-weight:800;letter-spacing:.03em;text-transform:uppercase;
  line-height:1;pointer-events:none}
.v2x.apx .apx-flag svg{width:11px;height:11px;flex:0 0 auto}
/* Both tones are measured, not picked: #7A4A05 on #FEF3C7 is 7.62:1 and
   #9A2C10 on #FFEDD5 is 7.09:1, so the uppercase 10.5px text clears AA by a
   wide margin at a size where it matters most. */
.v2x.apx .apx-flag.is-star{background:#FEF3C7;color:#7A4A05}
.v2x.apx .apx-flag.is-fire{background:#FFEDD5;color:#9A2C10}
body.theme-dark .v2x.apx .apx-flag.is-star{background:rgba(245,158,11,.2);color:#FCD34D}
body.theme-dark .v2x.apx .apx-flag.is-fire{background:rgba(249,115,22,.2);color:#FDBA74}

/* The rank chip and the flag both want the card's top-right. The rank moves
   left so the two never stack — the directory's card has no flag, so it
   parks the rank where ours needs to sit. */
.v2x.apx .dir-tc .apx-flag ~ .dir-tc-rank,
.v2x.apx .dir-tc-rank{right:auto;left:12px}


/* ═══ §STRIP — the tech-stack strip ════════════════════════════════════════
   The card's real signal. A visitor deciding whether to open a project asks
   "can I build this with what I already know" long before they ask how many
   stars it has — and stars are 0 on every row here anyway. */
.v2x.apx .apx-strip{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  margin:2px 0 10px}
.v2x.apx .apx-tech{
  display:inline-flex;align-items:center;
  padding:3px 8px;border-radius:6px;
  background:var(--v2-soft,#F1F5F9);border:1px solid var(--v2-line,#E2E8F0);
  font-size:.7rem;font-weight:650;color:var(--v2-ink-2,#475569);
  line-height:1.5;white-space:nowrap;max-width:100%;
  overflow:hidden;text-overflow:ellipsis}
.v2x.apx .apx-fig{
  display:inline-flex;align-items:center;gap:4px;
  font-size:.7rem;font-weight:600;color:var(--v2-ink-3,#64748B);line-height:1.5}
.v2x.apx .apx-fig svg{width:12px;height:12px;flex:0 0 auto;opacity:.75}
.v2x.apx .apx-fig b{font-weight:750;color:var(--v2-ink-2,#475569)}
body.theme-dark .v2x.apx .apx-tech{
  background:rgba(148,163,184,.12);border-color:rgba(148,163,184,.22);color:#CBD5E1}
body.theme-dark .v2x.apx .apx-fig{color:#94A3B8}
body.theme-dark .v2x.apx .apx-fig b{color:#CBD5E1}

/* In list mode the strip's chips join the meta row rather than forming their
   own line — a 92px-tall row has no space for a second band. */
.v2x.apx .dir-lc-meta .apx-tech,
.v2x.apx .dir-lc-meta .apx-fig{align-self:center}


/* ═══ §CHIP — active-filter chips ══════════════════════════════════════════
   One-tap removal without opening the rail. Taxonomy ids are resolved to
   names in the blade: a chip reading "7" would be worse than no chip. */
.v2x.apx .apx-chips{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  margin:0 0 16px}
.v2x.apx .apx-chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 6px 5px 12px;border-radius:999px;
  background:rgba(54,128,237,.09);border:1px solid rgba(54,128,237,.22);
  font-size:.78rem;font-weight:650;color:var(--brand-blue-ink,#1D4ED8);line-height:1.6}
.v2x.apx .apx-chip button{
  display:inline-flex;align-items:center;justify-content:center;
  width:17px;height:17px;border:0;border-radius:50%;cursor:pointer;
  background:rgba(54,128,237,.18);color:inherit;opacity:.75;
  transition:opacity .15s ease,background .15s ease}
.v2x.apx .apx-chip button svg{width:10px;height:10px}
.v2x.apx .apx-chip button:hover{opacity:1;background:rgba(54,128,237,.3)}
.v2x.apx .apx-chip-clear{
  border:0;background:none;cursor:pointer;padding:5px 4px;
  font-size:.78rem;font-weight:650;color:var(--v2-ink-3,#64748B);
  text-decoration:underline;text-underline-offset:3px;
  transition:color .15s ease}
.v2x.apx .apx-chip-clear:hover{color:var(--brand-blue,#3680ED)}
body.theme-dark .v2x.apx .apx-chip{
  background:rgba(96,164,245,.14);border-color:rgba(96,164,245,.3);color:#BFDBFE}
body.theme-dark .v2x.apx .apx-chip button{background:rgba(96,164,245,.2)}
body.theme-dark .v2x.apx .apx-chip button:hover{background:rgba(96,164,245,.36)}
body.theme-dark .v2x.apx .apx-chip-clear{color:#94A3B8}


/* ═══ §BUSY — dim while filtering ══════════════════════════════════════════
   `wire:loading.class="is-busy"` lands a class that NO sheet in the stack
   defines — verified by grep against both the directory sheet and the token
   layer, and the fourth module in a row to hit it. Mid-filter the rows on
   screen are the OLD set, so they are dimmed AND made inert rather than left
   looking interactive and current. */
.v2x.apx .apx-results{transition:opacity .18s ease,filter .18s ease}
.v2x.apx .apx-results.is-busy{opacity:.45;filter:saturate(.6);pointer-events:none}


/* ═══ §HERE — "you are here" on the category rail ══════════════════════════
   The rail renders on the hub pages too, so on /ai-projects/category/ai-agents
   one of its cards IS the current page. Marked with a ring rather than a
   colour change, so the tone cycle stays readable. */
.v2x.apx .dir-cat-card.is-here{
  box-shadow:inset 0 0 0 2px currentColor,0 10px 30px -14px rgba(16,24,40,.3)}
/* The ring is currentColor and therefore already theme-correct; only the drop
   shadow needs a twin — a near-black shadow on a dark ground is invisible,
   which loses the lift that separates the current card. */
body.theme-dark .v2x.apx .dir-cat-card.is-here{
  box-shadow:inset 0 0 0 2px currentColor,0 10px 30px -14px rgba(0,0,0,.7)}
.v2x.apx .dir-cat-card.is-here .dir-cat-card-cnt{font-weight:800}


/* ═══ §ABOUT — hub about panel ═════════════════════════════════════════════
   Built from the taxonomy row's own about_intro / about_points, on the same
   card language as the rest of the page. */
.v2x.apx .apx-about{
  max-width:var(--dir-shell,1280px);
  margin:0 auto;padding:0 clamp(16px,4vw,40px) 8px}
.v2x.apx .apx-about-box{
  background:var(--v2-surface,#fff);
  border:1px solid var(--v2-line,#E2E8F0);
  border-radius:18px;padding:clamp(20px,3vw,32px)}
.v2x.apx .apx-about-box h2{
  font-size:clamp(1.15rem,2.4vw,1.5rem);font-weight:800;
  letter-spacing:-.02em;color:var(--v2-ink);margin:0 0 12px}
.v2x.apx .apx-about-box p{
  font-size:.95rem;line-height:1.75;color:var(--v2-ink-2,#475569);margin:0 0 14px}
.v2x.apx .apx-about-box ul{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.v2x.apx .apx-about-box li{
  display:flex;align-items:flex-start;gap:9px;
  font-size:.9rem;line-height:1.6;color:var(--v2-ink-2,#475569)}
.v2x.apx .apx-about-box li svg{
  width:17px;height:17px;flex:0 0 auto;margin-top:2px;color:var(--brand-blue,#3680ED)}
body.theme-dark .v2x.apx .apx-about-box{
  background:var(--v2-surface,#141922);border-color:rgba(148,163,184,.16)}
body.theme-dark .v2x.apx .apx-about-box p,
body.theme-dark .v2x.apx .apx-about-box li{color:#B6C2D4}


/* ═══ §CATGRID — /ai-projects/categories ═══════════════════════════════════
   THE CARD IS THE SHARED SHEET'S `.dir-cat-card`; only the CONTAINER is
   local. On the listing page those cards live in `.dir-cat-rail`, a
   horizontal snap rail — right for a six-card teaser, wrong for a
   browse-everything index where the visitor wants all of them at once.

   `auto-fit` + a track RANGE + a capped, centred track keeps the card WIDTH
   matching the rail's rather than the column COUNT — the /gpts pass shipped
   the column-count version and the same component rendered 50% wider a few
   hundred pixels above its twin. */
.v2x.apx .apx-sect{margin-top:clamp(28px,5vw,56px)}
.v2x.apx .apx-catgrid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:18px;max-width:1240px;margin:0 auto;justify-content:center}
/* The rail card is `flex:0 0 <width>` inside the rail; in a grid track that
   fixed basis would fight the track, so it is released here and only here. */
.v2x.apx .apx-catgrid .dir-cat-card{flex:1 1 auto;width:auto;min-width:0;scroll-snap-align:none}

/* Technology rows — a technology has a name, a kind and a count, and nothing
   else worth a 240px card. This is the trending rail's row density, which is
   the right one for the data. */
.v2x.apx .apx-txgrid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:10px;max-width:1240px;margin:0 auto}
.v2x.apx .apx-txrow{
  position:relative;display:flex;align-items:center;gap:11px;
  padding:11px 12px;border-radius:13px;text-decoration:none;
  background:var(--v2-surface,#fff);border:1px solid var(--v2-line,#E2E8F0);
  transition:border-color .18s ease,box-shadow .18s ease,transform .18s ease}
.v2x.apx .apx-txrow:hover{
  border-color:rgba(54,128,237,.4);transform:translateY(-2px);
  box-shadow:0 10px 26px -16px rgba(16,24,40,.4)}
.v2x.apx .apx-txrow-ic{
  width:34px;height:34px;border-radius:9px;flex:0 0 auto}
.v2x.apx .apx-txrow-ic svg{width:16px;height:16px}
.v2x.apx .apx-txrow-mid{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1 1 auto}
.v2x.apx .apx-txrow-nm{
  font-size:.88rem;font-weight:700;color:var(--v2-ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.v2x.apx .apx-txrow-kind{
  font-size:.7rem;font-weight:600;color:var(--v2-ink-3,#64748B);
  text-transform:uppercase;letter-spacing:.04em}
.v2x.apx .apx-txrow-cnt{
  font-size:.8rem;font-weight:800;color:var(--v2-ink-2,#475569);
  flex:0 0 auto;transition:opacity .18s ease}
.v2x.apx .apx-txrow-arr{
  position:absolute;right:12px;flex:0 0 auto;
  opacity:0;transform:translateX(-4px);
  transition:opacity .18s ease,transform .18s ease;
  color:var(--brand-blue,#3680ED)}
.v2x.apx .apx-txrow-arr svg{width:15px;height:15px}
/* The count and the arrow share one slot and swap on hover — the same trick
   `.dir-tr-rt`/`.dir-tr-arr` uses in the trending rail. Without the count
   fading out, the arrow lands on top of it. */
.v2x.apx .apx-txrow:hover .apx-txrow-cnt{opacity:0}
.v2x.apx .apx-txrow:hover .apx-txrow-arr{opacity:1;transform:translateX(0)}
body.theme-dark .v2x.apx .apx-txrow{
  background:var(--v2-surface,#141922);border-color:rgba(148,163,184,.16)}
body.theme-dark .v2x.apx .apx-txrow:hover{border-color:rgba(96,164,245,.45)}
body.theme-dark .v2x.apx .apx-txrow-kind{color:#94A3B8}
body.theme-dark .v2x.apx .apx-txrow-cnt{color:#CBD5E1}
body.theme-dark .v2x.apx .apx-txrow-arr{color:#60A4F5}

/* Tag cloud. The accent is a DOT, never the text — same reasoning as §PLATE:
   these hexes are admin-supplied and several measure under 3:1 as ink. A 8px
   dot is decoration, so it is exempt from the text floor by definition. */
.v2x.apx .apx-tagcloud{
  display:flex;flex-wrap:wrap;gap:9px;justify-content:center;
  max-width:1000px;margin:0 auto}
.v2x.apx .apx-tag{
  display:inline-flex;align-items:center;gap:8px;
  padding:8px 13px;border-radius:999px;text-decoration:none;
  background:var(--v2-surface,#fff);border:1px solid var(--v2-line,#E2E8F0);
  transition:border-color .18s ease,transform .18s ease,box-shadow .18s ease}
.v2x.apx .apx-tag:hover{
  border-color:rgba(54,128,237,.4);transform:translateY(-2px);
  box-shadow:0 8px 20px -14px rgba(16,24,40,.45)}
.v2x.apx .apx-tag-dot{
  width:8px;height:8px;border-radius:50%;flex:0 0 auto;
  background:var(--apx-accent,#3680ED)}
.v2x.apx .apx-tag-nm{font-size:.84rem;font-weight:680;color:var(--v2-ink)}
.v2x.apx .apx-tag-cnt{
  font-size:.72rem;font-weight:750;color:var(--v2-ink-3,#64748B);
  padding:1px 6px;border-radius:999px;background:var(--v2-soft,#F1F5F9)}
body.theme-dark .v2x.apx .apx-tag{
  background:var(--v2-surface,#141922);border-color:rgba(148,163,184,.16)}
body.theme-dark .v2x.apx .apx-tag:hover{border-color:rgba(96,164,245,.45)}
body.theme-dark .v2x.apx .apx-tag-cnt{background:rgba(148,163,184,.14);color:#94A3B8}

/* "View all categories" / "Browse all projects" footer link. */
.v2x.apx .apx-catmore{
  display:flex;justify-content:center;
  margin-top:clamp(20px,3vw,32px)}
.v2x.apx .apx-catmore .dir-tr-more{max-width:320px}


/* ═══ §IOS — the 16px focus-zoom floor ═════════════════════════════════════
   `.dir-hh-search input` is 15.5px in the SHARED sheet (14px under 820px),
   and iOS Safari zooms the viewport on focus for anything under 16px. That
   affects /ai-directory, /browser-extensions, /gpts and /workflows too — the
   miss is real and wants its own pass on the shared sheet. Fixed here scoped
   to this page only, because raising it in the shared sheet would reflow four
   other pages that have not been re-verified.

   16px exactly: larger would visibly disagree with the sibling pages. */
.v2x.apx .dir-hh-search input,
.v2x.apx .dir-hh-search-field input{font-size:16px}


/* ═══ §RESP — responsive ═══════════════════════════════════════════════════
   ⚠ ALIGNED TO THE SHARED SHEET'S OWN LADDER, NOT TO BOOTSTRAP'S. Measured
   off the deployed sheet 2026-08-14, by frequency:
     820px ×8 · 520px ×5 · 1180px ×5 · 640px ×3 · 900px ×2 · 1100px ×2
   plus single uses at 1500 · 1024 · 700 · 680 · 560 · 480 · 420 · 400 · 380.
   The /workflows pass shipped on 991.98/767.98/479.98 and every one of its
   breakpoints fell BETWEEN the shared sheet's, so its CTA went column-wise
   140px after the page already had. Do not assume Bootstrap here. */

@media (max-width:1180px){
  /* Matches the point at which the shared sheet narrows its cards. */
  .v2x.apx .apx-catgrid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}
  .v2x.apx .apx-txgrid{grid-template-columns:repeat(auto-fit,minmax(215px,1fr))}
}

@media (max-width:900px){
  .v2x.apx .apx-strip{gap:5px}
  .v2x.apx .apx-tech{font-size:.68rem;padding:3px 7px}
}

@media (max-width:820px){
  /* The shared sheet's big one: single column + the facet accordion. */
  .v2x.apx .apx-catgrid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px}
  .v2x.apx .apx-txgrid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
  .v2x.apx .apx-chips{gap:6px;margin-bottom:13px}
  .v2x.apx .apx-about{padding-bottom:4px}
  /* The arrow's hover swap is meaningless without a pointer — on touch the
     count is the useful half, so it stays put. */
  .v2x.apx .apx-txrow-arr{display:none}
  .v2x.apx .apx-txrow:hover .apx-txrow-cnt{opacity:1}
}

@media (max-width:640px){
  .v2x.apx .apx-catgrid{grid-template-columns:1fr 1fr;gap:12px}
  .v2x.apx .apx-txgrid{grid-template-columns:1fr 1fr;gap:9px}
  .v2x.apx .apx-flag{top:10px;right:10px;font-size:.62rem;padding:3px 8px 3px 6px}
  .v2x.apx .apx-flag svg{width:10px;height:10px}
  .v2x.apx .dir-tc-rank{left:10px}
  /* Three chips is the most a 640px card can carry without wrapping into a
     third line and pushing the CTA below the fold of the card. */
  .v2x.apx .apx-strip{max-height:26px;overflow:hidden}
}

@media (max-width:520px){
  /* Single column — the shared sheet's narrowest common breakpoint. */
  .v2x.apx .apx-catgrid{grid-template-columns:1fr}
  .v2x.apx .apx-txgrid{grid-template-columns:1fr}
  .v2x.apx .apx-tagcloud{gap:7px}
  .v2x.apx .apx-tag{padding:7px 11px}
  .v2x.apx .apx-tag-nm{font-size:.8rem}
  .v2x.apx .apx-about-box{border-radius:14px}
  /* The flag's word is dropped below 520px; the icon alone still reads and
     the card's title has no room to share the line. */
  .v2x.apx .apx-flag span{display:none}
  .v2x.apx .apx-flag{padding:5px;border-radius:50%}
}

@media (max-width:380px){
  .v2x.apx .apx-strip{max-height:none}
  .v2x.apx .apx-tech{max-width:100%}
}


/* ═══ REDUCED MOTION ═══════════════════════════════════════════════════════
   Every transition above is decorative; none carries information that the
   end state does not. Honour the preference rather than easing it. */
@media (prefers-reduced-motion:reduce){
  .v2x.apx .apx-results,
  .v2x.apx .apx-txrow,
  .v2x.apx .apx-txrow-cnt,
  .v2x.apx .apx-txrow-arr,
  .v2x.apx .apx-tag,
  .v2x.apx .apx-chip button{transition:none}
  .v2x.apx .apx-txrow:hover,
  .v2x.apx .apx-tag:hover{transform:none}
}
