/* ═══════════════════════════════════════════════════════════════════════════
   §DCX — /ai-directory/categories, the browse-every-category index.
   ---------------------------------------------------------------------------
   Scope: `.v2x.dcx`. Loaded AFTER v2-public-directory-listing.css and after
   public-dir-bands.css (which rides in on the hh-orbit partial), so this sheet
   is the last word on source order for equal-specificity ties. Everything the
   page needs that ALREADY exists is taken, not rebuilt:

     · the hero            `.dir-hh*`        — v2-public-directory-listing.css
     · the band heads      `.dir-cat-head`   — public-dir-bands.css §HEAD
     · the category card   `.dir-cat-card`   — public-dir-bands.css §CATPRM
     · the FAQ + Why bands `.dir-why-*`      — both sheets

   This file adds only what has no home yet: the spotlight row (§DCXSPOT), the
   sort + letter toolbar (§DCXBAR / §DCXAZ), the browse-everything grid that
   re-lays the shared card (§DCXGRID), the tag cloud (§DCXTAG) and the closing
   CTA (§DCXCTA).

   ── Three cascade rules this sheet obeys, all of them learned the hard way ──

   1. EVERY SURFACE PROPERTY GETS A `body.theme-dark` TWIN, even when the value
      is identical. The base sheets set card surfaces with the `background`
      SHORTHAND at (0,3,1); the shorthand resets `background-image`, so a wash
      written once renders in light mode and silently vanishes at night. That
      is also why nothing here restyles `.dir-cat-card` itself — §DCXGRID only
      re-lays it, and layout properties have no dark twin to lose to.

   2. HEADINGS ARE QUALIFIED WITH THEIR PARENT. `custom.ltr.css` carries
      `body:not(.admin-shell):not(.theme-dark) h2` — (0,2,2), light mode only —
      which out-ranks any `.v2x .x-title` at (0,2,0) and takes its
      `line-height` and `letter-spacing` with it. Every heading rule below is
      written parent-qualified so it lands at (0,3,0) or better.

   3. GRID TRACKS CAP WITH `1fr`, NEVER A PX MAX. `repeat(auto-fill,
      minmax(min(100%, Npx), Mpx))` picks its repetition count from the MAX
      when that max is definite, so a px cap silently collapses the row to one
      column. Where a real per-item cap is needed the row is flex, not grid.

   ── Colour ────────────────────────────────────────────────────────────────
   The spotlight cards wear each category's OWN `directory_categories.color`.
   It arrives as three inline custom properties set by the blade:

     --dcs-rgb   the raw hue as an "r,g,b" triplet, for alpha ramps
     --dcs-ink   the same hue darkened until it clears 4.5:1 on white
     --dcs-inkd  the same hue lightened until it clears 4.5:1 on the dark card

   A triplet rather than a hex because a wash, a bloom, an edge and a shadow
   all need to vary ALPHA along the same hue — and because a composited hex
   picked for light mode goes pale and unreadable on a night surface. Text
   never uses `--dcs-rgb` directly: it uses the ink pair, which is computed to
   pass contrast in the theme it is used in.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXSHELL — page rhythm
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-sect { margin-top: clamp(38px, 5vw, 66px); }
.v2x.dcx .dcx-sect:first-child { margin-top: clamp(26px, 3.4vw, 44px); }

/* The hero already ends on the stat rail's own bottom margin; the marquee
   under it supplies the next beat. Only the lab needs pulling up. */
.v2x.dcx .dir-lab { margin-top: clamp(22px, 3vw, 38px); }


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXSPOT — the spotlight row
   ---------------------------------------------------------------------------
   Six large cards for the categories that actually hold tools, and the one
   band on the page that is not a variation of something else. The shared
   `.dir-cat-card` is a 220px portrait tile built for a rail of ten; at three
   across it reads as an oversized icon with a caption. This is the landscape
   answer: hue-washed surface, real tool logos from inside the category, and a
   CTA that fills on hover.

   Suppressed while searching — see the component. A "start here" band that
   ignores the query reads as a broken filter.
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-spotgrid {
    display: grid;
    /* A FIXED three, not `auto-fill`. The band is capped at six cards in the
       component, and six over an auto-fill track fitted four-then-two on a
       1500px shell — a full row and a stub, which reads as a layout that ran
       out rather than as a deliberate six. Three by two is the only balanced
       split of six that also leaves each card wide enough for the logo stack
       and the CTA to sit on one line. `minmax(0, 1fr)` and not `1fr`: a bare
       `1fr` is `minmax(auto, 1fr)`, so a long unbreakable string in a
       description would push the track past its share. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
}

/* ── The card shell ──────────────────────────────────────────────────────
   `background-color` + `background-image` as SEPARATE properties, never the
   shorthand: the shorthand resets the other slot, and the dark twin below
   has to be able to swap the colour while keeping the wash. */
.v2x.dcx .dcx-spot {
    --dcs-rgb: 54, 128, 237;
    --dcs-ink: #1B5BB5;
    --dcs-inkd: #8CBEFA;
    /* The ink actually in use, and the text that sits ON it once that ink
       becomes a FILL. Both flip once, in the dark block below, so every rule
       downstream reads one property and there is no second twin to keep in
       step.

       ⚠ `--dcs-on` is not decoration. `--dcs-ink` is darkened until it clears
       4.5:1 on white, which by symmetry makes WHITE text on it clear 4.5:1
       too — but `--dcs-inkd` is LIGHTENED until it clears 4.5:1 on the night
       card, so white text on that one is around 1.5:1. A hard-coded `#fff`
       on the filled CTA would therefore be near-invisible after dark on
       every card here. The pair is what makes one fill rule right in both
       themes. */
    --dcs-now: var(--dcs-ink);
    --dcs-on: #fff;

    /* The RECESS inside a filled pill — the arrow disc once the CTA has
       filled. It has to move AWAY from the text, not toward the hue: a
       `rgba(hue, .32)` overlay lightens the fill, which is the wrong
       direction under white text and measured 3.91:1 on the amber card. So
       the well is a neutral scrim whose direction flips with the theme —
       black over a dark fill carrying white text, white over a light fill
       carrying dark text. Either way contrast strictly IMPROVES over the
       fill it sits on, so no card can fail it. */
    --dcs-well: rgba(0, 0, 0, .2);

    position: relative;
    isolation: isolate;
    display: flex;
    flex-direction: column;
    min-height: 100%;
    padding: 22px 22px 20px;
    border: 1px solid var(--v2-line);
    border-radius: 22px;
    background-color: #fff;
    background-image: linear-gradient(152deg, rgba(var(--dcs-rgb), .075) 0%, rgba(var(--dcs-rgb), 0) 48%, rgba(var(--dcs-rgb), .055) 100%);
    color: var(--v2-ink);
    text-decoration: none;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 14px 30px -24px rgba(16, 24, 40, .26);
    transition: transform .3s var(--ease-out), border-color .24s ease, box-shadow .3s ease;
}

body.theme-dark .v2x.dcx .dcx-spot {
    --dcs-now: var(--dcs-inkd);
    --dcs-on: var(--dk-surface,#131317);
    --dcs-well: rgba(255, 255, 255, .26);
    border-color: var(--dk-line,rgba(255,255,255,.10));
    background-color: rgba(29,29,34,.92);
    background-image: linear-gradient(152deg, rgba(var(--dcs-rgb), .16) 0%, rgba(var(--dcs-rgb), 0) 52%, rgba(var(--dcs-rgb), .1) 100%);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .42), 0 14px 30px -24px rgba(0, 0, 0, .7);
}

/* Corner bloom. Its own pseudo rather than a second background layer so the
   hover can change its opacity without touching the wash underneath. */
.v2x.dcx .dcx-spot::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background-image: radial-gradient(240px 210px at calc(100% + 30px) -56px, rgba(var(--dcs-rgb), .22) 0%, rgba(var(--dcs-rgb), 0) 70%);
    opacity: .85;
    transition: opacity .3s ease;
    pointer-events: none;
    z-index: 0;
}

body.theme-dark .v2x.dcx .dcx-spot::before {
    background-image: radial-gradient(240px 210px at calc(100% + 30px) -56px, rgba(var(--dcs-rgb), .3) 0%, rgba(var(--dcs-rgb), 0) 70%);
}

/* Foot bar — the tone tab along the bottom edge. A pseudo, because the third
   background layer is already spent on the wash and the card has no spare
   span in the blade to hang it on. `width` animates via a custom property so
   the hover rule never has to out-rank the dark surface rule (cascade rule 1:
   a `:hover` at (0,3,1) still loses to `body.theme-dark …` at (0,4,1)). */
.v2x.dcx .dcx-spot::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 0;
    width: var(--dcs-bar, 46%);
    height: var(--dcs-barh, 3px);
    transform: translateX(-50%);
    border-radius: 3px 3px 0 0;
    background-image: linear-gradient(90deg, rgba(var(--dcs-rgb), 0) 0%, rgba(var(--dcs-rgb), .95) 50%, rgba(var(--dcs-rgb), 0) 100%);
    transition: width .32s var(--ease-out), height .32s var(--ease-out);
    pointer-events: none;
    z-index: 2;
}

/* Content sits above both pseudos. */
.v2x.dcx .dcx-spot > * { position: relative; z-index: 1; }

/* ── Hover / focus ───────────────────────────────────────────────────────
   Every state change that touches a SURFACE goes through a custom property,
   for the reason spelled out on `::after` above. Geometry and shadow are
   safe to set directly — the dark twin restates the shadow, and both are
   listed here so the two themes lift identically. */
@media (hover: hover) {
    .v2x.dcx .dcx-spot:hover {
        --dcs-bar: 100%;
        --dcs-barh: 5px;
        transform: translateY(-6px);
        border-color: rgba(var(--dcs-rgb), .34);
        box-shadow: 0 28px 52px -22px rgba(var(--dcs-rgb), .45), 0 6px 14px rgba(16, 24, 40, .07);
        color: var(--v2-ink);
        text-decoration: none;
    }

    body.theme-dark .v2x.dcx .dcx-spot:hover {
        border-color: rgba(var(--dcs-rgb), .48);
        box-shadow: 0 28px 52px -22px rgba(0, 0, 0, .72), 0 0 0 1px rgba(var(--dcs-rgb), .22);
    }

    .v2x.dcx .dcx-spot:hover::before { opacity: 1; }
    .v2x.dcx .dcx-spot:hover .dcx-spot-ico { transform: translateY(-2px) scale(1.06); }
    .v2x.dcx .dcx-spot:hover .dcx-spot-nm { color: var(--dcs-now); }
    .v2x.dcx .dcx-spot:hover .dcx-spot-rank { transform: scale(1.08); }
}

/* Keyboard parity. `:focus-visible` gets the SAME lift as hover plus a ring,
   because a keyboard user has no pointer to tell them where they are. */
.v2x.dcx .dcx-spot:focus-visible {
    --dcs-bar: 100%;
    --dcs-barh: 5px;
    outline: none;
    border-color: rgba(var(--dcs-rgb), .5);
    box-shadow: 0 0 0 3px rgba(var(--dcs-rgb), .3), 0 24px 46px -20px rgba(var(--dcs-rgb), .4);
}

.v2x.dcx .dcx-spot:active { transform: translateY(-2px) scale(.995); }

/* ── Top row: icon plate + count chip ────────────────────────────────────── */
.v2x.dcx .dcx-spot-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.v2x.dcx .dcx-spot-ico {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 54px;
    height: 54px;
    border-radius: 16px;
    background-color: rgba(var(--dcs-rgb), .12);
    color: var(--dcs-now);
    box-shadow: inset 0 0 0 1px rgba(var(--dcs-rgb), .22);
    transition: transform .3s var(--ease-spring);
}

body.theme-dark .v2x.dcx .dcx-spot-ico {
    background-color: rgba(var(--dcs-rgb), .2);
    box-shadow: inset 0 0 0 1px rgba(var(--dcs-rgb), .32);
}

.v2x.dcx .dcx-spot-ico svg { width: 26px; height: 26px; }
.v2x.dcx .dcx-spot-ico i   { font-size: 22px; line-height: 1; }

/* The count. Ink is the contrast-checked pair, never the raw hue — an amber
   or a lime category would fail on white otherwise. */
.v2x.dcx .dcx-spot-cnt {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    padding: 6px 12px;
    border-radius: 999px;
    background-color: rgba(var(--dcs-rgb), .1);
    color: var(--dcs-now);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: -.002em;
    white-space: nowrap;
    box-shadow: inset 0 0 0 1px rgba(var(--dcs-rgb), .2);
}

body.theme-dark .v2x.dcx .dcx-spot-cnt {
    background-color: rgba(var(--dcs-rgb), .18);
    box-shadow: inset 0 0 0 1px rgba(var(--dcs-rgb), .3);
}

.v2x.dcx .dcx-spot-cnt-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: currentColor;
    flex: 0 0 auto;
}

/* ── Rank medal ──────────────────────────────────────────────────────────
   ⚠ THIS WAS A 34px WATERMARK IN THE TOP-RIGHT CORNER AND IT COLLIDED. The
   count chip is `justify-content: space-between`'s right-hand item, which
   puts it in exactly that corner — so "01" rendered UNDER "6 tools" on all
   six cards and read as a rendering fault rather than as a rank. Moving the
   chip was not the answer either: the count is the card's one piece of hard
   information and it belongs beside the icon, not buried in the footer.

   So the rank becomes a MEDAL notched onto the icon plate's top-left corner,
   which is the one part of the card nothing else claims. Small, solid, and
   legible in both themes because it takes the same contrast-checked ink pair
   as everything else that fills. `aria-hidden` in the blade — the order is
   already carried by the DOM. */
.v2x.dcx .dcx-spot-rank {
    position: absolute;
    top: 14px;
    inset-inline-start: 14px;
    display: grid;
    place-items: center;
    min-width: 24px;
    height: 24px;
    padding: 0 6px;
    border-radius: 999px;
    background-color: var(--dcs-now);
    color: var(--dcs-on);
    font-family: var(--font-mono, 'JetBrains Mono', monospace);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.02em;
    box-shadow: 0 0 0 2.5px #fff, 0 3px 8px -2px rgba(var(--dcs-rgb), .5);
    transition: transform .26s var(--ease-spring);
    pointer-events: none;
    z-index: 3;
}

/* The white keyline that lifts the medal off the plate has to become the CARD
   colour at night, or it draws a bright ring on a dark surface. */
body.theme-dark .v2x.dcx .dcx-spot-rank {
    box-shadow: 0 0 0 2.5px var(--dk-surface-3,#1D1D22), 0 3px 8px -2px rgba(0, 0, 0, .6);
}

/* ── Name + description ──────────────────────────────────────────────────
   `min-height` on the clamp, not just `-webkit-line-clamp`: a two-line and a
   one-line description in the same row would otherwise hold their CTAs at
   different heights, which reads as the cards being stretched. */
.v2x.dcx .dcx-spot-nm {
    margin: 16px 0 0;
    font-size: 18px;
    font-weight: 750;
    line-height: 1.28;
    letter-spacing: -.018em;
    color: var(--v2-ink);
    transition: color .2s ease;
}

.v2x.dcx .dcx-spot-desc {
    margin: 8px 0 0;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--v2-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: calc(2 * 1.6em);
}

/* ── Foot: logo stack + CTA ──────────────────────────────────────────────
   `margin-top: auto` on the foot, and the clear space above it is PADDING,
   not a margin — a sibling margin in the same axis is exactly what beat an
   `auto` once before and left two cards in a row holding their buttons at
   different heights. */
.v2x.dcx .dcx-spot-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: auto;
    padding-top: 18px;
}

/* Real logos from inside the category. The stack overlaps by default and
   fans out on hover — the one motion on this page that is pure delight, and
   it is `transform` only, so it is free. */
.v2x.dcx .dcx-spot-stack {
    display: flex;
    align-items: center;
    flex: 0 1 auto;
    min-width: 0;
}

.v2x.dcx .dcx-spot-av {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    margin-inline-start: -9px;
    border-radius: 10px;
    background-color: #fff;
    color: var(--dcs-now);
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1;
    overflow: hidden;
    box-shadow: 0 0 0 2px #fff, 0 2px 6px rgba(16, 24, 40, .16);
    transition: transform .3s var(--ease-spring), margin .3s var(--ease-spring);
}

.v2x.dcx .dcx-spot-av:first-child { margin-inline-start: 0; }

body.theme-dark .v2x.dcx .dcx-spot-av {
    background-color: var(--dk-surface-4,#24242A);
    box-shadow: 0 0 0 2px var(--dk-surface-3,#1D1D22), 0 2px 6px rgba(0, 0, 0, .5);
}

.v2x.dcx .dcx-spot-av img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 4px;
    display: block;
}

/* The initial-only fallback. A tool with no logo renders its first letter,
   and on `background-color: #fff` inside a white ring on a white card that is
   a letter floating in space — which is what eighteen of the twenty-seven
   avatars in the live band actually were. Tinting it gives the letter a chip
   to sit in, so the row reads as one set whether or not a logo exists. */
.v2x.dcx .dcx-spot-av.is-txt {
    background-color: rgba(var(--dcs-rgb), .12);
    box-shadow: 0 0 0 2px #fff, inset 0 0 0 1px rgba(var(--dcs-rgb), .22), 0 2px 6px rgba(16, 24, 40, .14);
}

body.theme-dark .v2x.dcx .dcx-spot-av.is-txt {
    background-color: rgba(var(--dcs-rgb), .24);
    box-shadow: 0 0 0 2px var(--dk-surface-3,#1D1D22), inset 0 0 0 1px rgba(var(--dcs-rgb), .34), 0 2px 6px rgba(0, 0, 0, .5);
}

/* The "+N" tail. Tinted rather than white so it reads as a summary and not
   as a seventh logo. */
.v2x.dcx .dcx-spot-av.is-more {
    background-color: rgba(var(--dcs-rgb), .14);
    color: var(--dcs-now);
    font-size: 11px;
    letter-spacing: -.01em;
}

body.theme-dark .v2x.dcx .dcx-spot-av.is-more { background-color: rgba(var(--dcs-rgb), .26); }

@media (hover: hover) {
    .v2x.dcx .dcx-spot:hover .dcx-spot-av { margin-inline-start: -3px; }
    .v2x.dcx .dcx-spot:hover .dcx-spot-av:first-child { margin-inline-start: 0; }
}

/* The CTA. Tinted at rest, brand-filled on hover — the same two-state
   language `.dir-cat-cta` uses in the band head above it, so the page has
   one button idea rather than two. */
.v2x.dcx .dcx-spot-go {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    padding: 8px 9px 8px 15px;
    border-radius: 999px;
    background-color: rgba(var(--dcs-rgb), .12);
    color: var(--dcs-now);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: -.004em;
    white-space: nowrap;
    box-shadow: inset 0 0 0 1px rgba(var(--dcs-rgb), .22);
    transition: background-color .22s ease, color .2s ease, box-shadow .22s ease;
}

body.theme-dark .v2x.dcx .dcx-spot-go {
    background-color: rgba(var(--dcs-rgb), .2);
    box-shadow: inset 0 0 0 1px rgba(var(--dcs-rgb), .32);
}

.v2x.dcx .dcx-spot-go-arr {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background-color: var(--dcs-now);
    color: var(--dcs-on);
    transition: transform .24s var(--ease-spring), background-color .22s ease, color .18s ease;
}

.v2x.dcx .dcx-spot-go-arr svg { width: 12px; height: 12px; }
[dir="rtl"] .v2x.dcx .dcx-spot-go-arr svg { transform: scaleX(-1); }

/* The filled state — the tinted pill becomes a solid one in the category's
   own hue, with `--dcs-on` supplying the text. See the token-pair note at the
   top of §DCXSPOT for why that text colour cannot be a literal. The arrow
   disc inverts to a translucent well of the hue, keeping the glyph on
   `--dcs-on` alongside the label. */
@media (hover: hover) {
    .v2x.dcx .dcx-spot:hover .dcx-spot-go {
        background-color: var(--dcs-now);
        color: var(--dcs-on);
        box-shadow: inset 0 0 0 1px transparent, 0 10px 20px -8px rgba(var(--dcs-rgb), .55);
    }

    .v2x.dcx .dcx-spot:hover .dcx-spot-go-arr {
        background-color: var(--dcs-well);
        color: var(--dcs-on);
        transform: translateX(2px);
    }

    [dir="rtl"] .v2x.dcx .dcx-spot:hover .dcx-spot-go-arr { transform: translateX(-2px); }
}

.v2x.dcx .dcx-spot:focus-visible .dcx-spot-go {
    background-color: var(--dcs-now);
    color: var(--dcs-on);
    box-shadow: inset 0 0 0 1px transparent;
}

.v2x.dcx .dcx-spot:focus-visible .dcx-spot-go-arr {
    background-color: var(--dcs-well);
    color: var(--dcs-on);
}


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXTILE — the hero orbit tiles
   ---------------------------------------------------------------------------
   The listing puts four MODEL LOGOS on the hero ring — ChatGPT, Claude,
   Gemini, Grok — as `<img>`. A page about categories puts the four busiest
   CATEGORIES there instead, so the ring says what the page is about rather
   than repeating the vertical's mascots. That swaps an image for an inline
   SVG, and `.dir-hh-tile img { width: 100% }` does not reach an `<svg>`, so
   the glyph arrives at its intrinsic size in the inherited ink. These four
   rules give it the tile's box and the category's own hue.
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-hh-tile {
    --dcs-now: var(--dcs-ink);
    color: var(--dcs-now);
    background-image: linear-gradient(150deg, rgba(var(--dcs-rgb), .1) 0%, rgba(var(--dcs-rgb), 0) 62%);
}

body.theme-dark .v2x.dcx .dcx-hh-tile {
    --dcs-now: var(--dcs-inkd);
    background-image: linear-gradient(150deg, rgba(var(--dcs-rgb), .2) 0%, rgba(var(--dcs-rgb), 0) 62%);
}

/* The two small tiles (t3 / t4) are 66px with 11px padding against the large
   pair's 78px and 14px, so the glyph is sized off the box rather than fixed —
   otherwise the ring reads as four icons at two different weights. */
.v2x.dcx .dcx-hh-tile svg { width: 100%; height: 100%; }
.v2x.dcx .dcx-hh-tile i   { font-size: 26px; line-height: 1; }

@media (hover: hover) {
    .v2x.dcx .dcx-hh-tile:hover { box-shadow: 0 20px 42px -14px rgba(var(--dcs-rgb), .5); }
    body.theme-dark .v2x.dcx .dcx-hh-tile:hover { box-shadow: 0 20px 42px -14px rgba(0, 0, 0, .7); }
}

.v2x.dcx .dcx-hh-tile:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(var(--dcs-rgb), .35), 0 14px 30px -14px rgba(var(--dcs-rgb), .45);
}


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXBAR — the toolbar above the browse-everything grid
   ---------------------------------------------------------------------------
   Result count on the left, a two-option segmented control on the right. The
   control is a real pair of buttons, not a `<select>`: two options do not
   earn a menu, and a segmented pair shows the alternative without a click.
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    margin-bottom: 18px;
    padding: 12px 14px;
    border: 1px solid var(--v2-line);
    border-radius: 16px;
    background-color: #fff;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
}

body.theme-dark .v2x.dcx .dcx-bar {
    border-color: var(--dk-line,rgba(255,255,255,.10));
    background-color: rgba(29,29,34,.9);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .4);
}

.v2x.dcx .dcx-bar-count {
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
    min-width: 0;
    font-size: 14px;
    color: var(--v2-muted);
}

.v2x.dcx .dcx-bar-count b {
    font-size: 16px;
    font-weight: 750;
    color: var(--v2-ink);
    letter-spacing: -.012em;
}

/* ── Segmented sort control ────────────────────────────────────────────── */
.v2x.dcx .dcx-seg {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    flex: 0 0 auto;
    padding: 3px;
    border-radius: 999px;
    background-color: var(--v2-bg);
    box-shadow: inset 0 0 0 1px var(--v2-line);
}

body.theme-dark .v2x.dcx .dcx-seg {
    background-color: rgba(255, 255, 255, .05);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}

.v2x.dcx .dcx-seg-b {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border: 0;
    border-radius: 999px;
    background-color: transparent;
    color: var(--v2-muted);
    font-family: inherit;
    font-size: 13px;
    font-weight: 650;
    letter-spacing: -.004em;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .2s ease, color .18s ease, box-shadow .2s ease, transform .18s ease;
}

.v2x.dcx .dcx-seg-b svg { width: 14px; height: 14px; flex: 0 0 auto; }

@media (hover: hover) {
    .v2x.dcx .dcx-seg-b:hover { color: var(--brand-blue); transform: translateY(-1px); }
    body.theme-dark .v2x.dcx .dcx-seg-b:hover { color: var(--brand-blue-light); }
}

.v2x.dcx .dcx-seg-b:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(54, 128, 237, .3);
}

/* ── The brand FILL, and why it is three hexes and not two tokens ─────────
   Every white-on-blue surface in this sheet — the ON segment, the letter
   chip's hover, the primary CTA and the empty-state button — uses the SAME
   measured ramp, because the brand tokens fail under white text:

     #60A4F5 brand-blue-light   2.58:1   ✗
     #3680ED brand-blue         3.84:1   ✗
     #2060C0 brand-blue-dark    6.01:1   ✓

   The first version of this sheet used `var(--brand-blue) → var(--brand-blue-dark)`
   and measured 3.84:1 at the light end on the live page — the exact defect
   `assets/css/ai-contrast-fix.css` exists to correct sitewide, whose header
   states the rule outright: brand blue is fine for ink, borders and tints,
   and must never sit under white text.

   The stops are that file's own `--aa-fill-1/2/3`, which `public-dir-bands.css`
   §3230 already reuses for the same reason:

     #2E6FD0  4.88:1   #2762C2  5.81:1   #1B4E9E  7.98:1

   Worst point 4.88:1 — AA at EVERY step of the gradient, which is what
   matters, because a reader sees all three stops and not an average.

   ⚠ LITERALS, NOT `var(--aa-fill-*)`. Those tokens are declared inside a
   `body.theme-dark` block in that file and are undefined in light mode, so a
   bare `var()` reference paints nothing by day. The ramp is identical in both
   themes, which is also why there is no dark twin below: `background-image`
   here is not competing with a dark surface rule.

   The tokens stay in use everywhere they are correct — the glow, the focus
   ring and every shadow below are still brand blue, because none of those
   sits under text. */
.v2x.dcx .dcx-seg-b.is-on {
    background-color: #2762C2;
    background-image: linear-gradient(135deg, #2E6FD0 0%, #2762C2 46%, #1B4E9E 100%);
    color: #fff;
    box-shadow: 0 6px 14px -6px rgba(54, 128, 237, .6);
}

body.theme-dark .v2x.dcx .dcx-seg-b.is-on {
    background-color: #2762C2;
    background-image: linear-gradient(135deg, #2E6FD0 0%, #2762C2 46%, #1B4E9E 100%);
    color: #fff;
}

@media (hover: hover) {
    .v2x.dcx .dcx-seg-b.is-on:hover { color: #fff; transform: translateY(-1px); }
    body.theme-dark .v2x.dcx .dcx-seg-b.is-on:hover { color: #fff; }
}


/* §DCXBAR-ALT — the link across to the other index (categories ↔ tags), a
   quiet pill between the count and the sort. Pushed to the right of the
   count with `margin-inline-start: auto`; the sort segment follows it. */
.v2x.dcx .dcx-bar-alt {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-inline-start: auto;
    padding: 8px 12px 8px 10px;
    border: 1px solid var(--v2-line);
    border-radius: 999px;
    background-color: #fff;
    color: var(--v2-ink);
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: -.004em;
    text-decoration: none;
    white-space: nowrap;
    transition: border-color .2s ease, color .18s ease, transform .2s var(--ease-spring), box-shadow .24s ease;
}

.v2x.dcx .dcx-bar-alt svg { width: 14px; height: 14px; flex: 0 0 auto; }
.v2x.dcx .dcx-bar-alt > svg:first-child { color: var(--brand-blue); }
[dir="rtl"] .v2x.dcx .dcx-bar-alt > svg:last-child { transform: scaleX(-1); }

body.theme-dark .v2x.dcx .dcx-bar-alt {
    background-color: rgba(255, 255, 255, .05);
    border-color: var(--dk-line, rgba(255, 255, 255, .12));
}

@media (hover: hover) {
    .v2x.dcx .dcx-bar-alt:hover {
        border-color: var(--brand-blue);
        color: var(--brand-blue-dark, #1B5BB5);
        transform: translateY(-1px);
        box-shadow: 0 10px 20px -12px rgba(54, 128, 237, .5);
    }

    body.theme-dark .v2x.dcx .dcx-bar-alt:hover { border-color: var(--brand-blue-light); color: var(--brand-blue-light); }
}

.v2x.dcx .dcx-bar-alt:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(54, 128, 237, .32); }

@media (max-width: 575.98px) {
    .v2x.dcx .dcx-bar-alt { margin-inline-start: 0; }
    .v2x.dcx .dcx-bar-alt span { display: none; }
    .v2x.dcx .dcx-bar-alt { padding: 8px 10px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   §DCXAZ — the letter rail
   ---------------------------------------------------------------------------
   Only rendered in A–Z mode, and only for letters that HAVE a group — a rail
   offering "Q" that scrolls nowhere is worse than no rail. Plain anchors, so
   it works with JS off and the browser owns the scroll.
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-az {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 22px;
}

.v2x.dcx .dcx-az-lbl {
    margin-inline-end: 4px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--v2-muted);
}

.v2x.dcx .dcx-az-l {
    display: grid;
    place-items: center;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    border-radius: 10px;
    background-color: #fff;
    color: var(--v2-ink);
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    text-decoration: none;
    box-shadow: inset 0 0 0 1px var(--v2-line);
    transition: background-color .2s ease, color .18s ease, box-shadow .2s ease, transform .2s var(--ease-spring);
}

body.theme-dark .v2x.dcx .dcx-az-l {
    background-color: rgba(255, 255, 255, .05);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .09);
}

@media (hover: hover) {
    .v2x.dcx .dcx-az-l:hover {
        /* The measured AA ramp, not the brand tokens — see the note at
           §DCXBAR. */
        background-color: #2762C2;
        background-image: linear-gradient(135deg, #2E6FD0 0%, #2762C2 46%, #1B4E9E 100%);
        color: #fff;
        text-decoration: none;
        transform: translateY(-2px);
        box-shadow: 0 8px 16px -6px rgba(54, 128, 237, .55);
    }

    body.theme-dark .v2x.dcx .dcx-az-l:hover { color: #fff; }
}

.v2x.dcx .dcx-az-l:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 1px var(--brand-blue), 0 0 0 3px rgba(54, 128, 237, .3);
}


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXGRID — the browse-everything grid
   ---------------------------------------------------------------------------
   ⚠ THE CARD IS THE SHARED SHEET'S `.dir-cat-card` AND IS NOT RESTYLED HERE.
   On the listing page those cards live in `.dir-cat-rail`, a horizontal snap
   rail — right for a ten-card teaser, wrong for a browse-everything index
   where the visitor wants the whole set at once. This container re-lays the
   SAME card into a wrapping grid and touches nothing else about it, so the
   hub and the listing stay identical card-for-card and the §CATPRM surface,
   the tone tokens and the hover all come along for free.

   Layout properties only. Anything that painted a surface here would need a
   `body.theme-dark` twin at (0,4,1) to survive the night — see cascade rule 1.
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 232px), 1fr));
    gap: 18px;
}

/* The rail sets `scroll-snap-align` and a fixed track width on the card; in a
   grid both are noise. `min-width: 0` lets a long category name wrap instead
   of forcing the track wider than its share. */
.v2x.dcx .dcx-grid .dir-cat-card {
    width: auto;
    min-width: 0;
    scroll-snap-align: none;
}

/* ── Empty categories ────────────────────────────────────────────────────
   `data-soon="1"` — no tools published yet. The card is DIMMED, not hidden
   and not de-linked: the category page has a real empty state, already ships
   noindex under three tools, and hiding 32 of 41 would make a "browse
   everything" index that browses a quarter of the catalogue.

   Only the tone chrome fades. The name and the description keep full ink —
   this card still has to be readable, and greying the words is how a
   "coming soon" state turns into an accessibility bug. */
.v2x.dcx .dcx-grid .dir-cat-card[data-soon="1"] { opacity: .82; }
.v2x.dcx .dcx-grid .dir-cat-card[data-soon="1"] .dir-cat-card-nm { color: var(--v2-ink); }

@media (hover: hover) {
    .v2x.dcx .dcx-grid .dir-cat-card[data-soon="1"]:hover { opacity: 1; }
}

/* The count chip becomes a neutral "Coming soon" tag rather than a tone pill,
   so a reader can tell an empty category from a full one without reading the
   number. Both themes declared — the chip's own tone rule is (0,2,0) light /
   (0,3,1) dark, and this pair clears both at (0,4,1) / (0,5,1). */
.v2x.dcx .dcx-grid .dir-cat-card[data-soon="1"] .dir-cat-card-cnt {
    background-color: var(--v2-bg);
    color: var(--v2-muted);
    box-shadow: inset 0 0 0 1px var(--v2-line);
}

body.theme-dark .v2x.dcx .dcx-grid .dir-cat-card[data-soon="1"] .dir-cat-card-cnt {
    background-color: rgba(255, 255, 255, .06);
    color: var(--v2-muted);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1);
}

/* ── Letter group heads ──────────────────────────────────────────────────
   A chip and a rule, not a heading: these are navigation furniture inside one
   section, and promoting 20 of them to `<h3>` would bury the real headings in
   the document outline. `scroll-margin-top` keeps the anchor jump clear of
   the site header. */
.v2x.dcx .dcx-lgroup { scroll-margin-top: 90px; }
.v2x.dcx .dcx-lgroup + .dcx-lgroup { margin-top: 32px; }

.v2x.dcx .dcx-lhead {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}

.v2x.dcx .dcx-lhead-ch {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    min-width: 34px;
    height: 34px;
    padding: 0 10px;
    border-radius: 11px;
    background-color: var(--v2-accent-soft);
    color: var(--brand-blue-dark);
    font-size: 15px;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.01em;
    box-shadow: inset 0 0 0 1px #CFE0FA;
}

body.theme-dark .v2x.dcx .dcx-lhead-ch {
    background-color: rgba(54, 128, 237, .16);
    color: var(--brand-blue-light);
    box-shadow: inset 0 0 0 1px rgba(96, 164, 245, .28);
}

.v2x.dcx .dcx-lhead-n {
    flex: 0 0 auto;
    font-size: 12.5px;
    font-weight: 650;
    color: var(--v2-muted);
}

.v2x.dcx .dcx-lhead-rule {
    flex: 1 1 auto;
    height: 1px;
    min-width: 12px;
    border: 0;
    margin: 0;
    background-image: linear-gradient(90deg, var(--v2-line) 0%, rgba(231, 234, 240, 0) 100%);
}

body.theme-dark .v2x.dcx .dcx-lhead-rule {
    background-image: linear-gradient(90deg, rgba(255, 255, 255, .12) 0%, rgba(255, 255, 255, 0) 100%);
}

/* Back-to-top from a letter group. Small, quiet, and only where it helps. */
.v2x.dcx .dcx-lhead-top {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border-radius: 999px;
    color: var(--v2-muted);
    font-size: 11.5px;
    font-weight: 650;
    text-decoration: none;
    transition: background-color .2s ease, color .18s ease;
}

.v2x.dcx .dcx-lhead-top svg { width: 12px; height: 12px; }

@media (hover: hover) {
    .v2x.dcx .dcx-lhead-top:hover {
        background-color: var(--v2-accent-soft);
        color: var(--brand-blue-dark);
        text-decoration: none;
    }

    body.theme-dark .v2x.dcx .dcx-lhead-top:hover {
        background-color: rgba(54, 128, 237, .16);
        color: var(--brand-blue-light);
    }
}

.v2x.dcx .dcx-lhead-top:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(54, 128, 237, .3);
}


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXFAM — one main category and its subcategories (§CATTREE)
   ---------------------------------------------------------------------------
   REBUILT 2026-09-16 on the homepage's promo-quad card (`.hpx-promo`, the
   AI Courses / Prompt Marketplace / AI Projects / AI Deals quartet), which
   the owner pointed at as the reference. Same three zones in the same
   order: a tone-washed header with a solid plate icon, the subcategories as
   link rows (tone bar + arrow arrive on hover), one full-width tinted action
   at the foot. Re-expressed here in the directory's own tokens rather than
   linking homepage.css — see hpx-kit-outside-homepage: `.hpx` on a page
   root is tokens only, never the sheet.

   Tones: the same eight hexes the shared `.dir-cat-card` carries in
   v2-public-directory-listing.css, declared on the family so the header,
   plate, rows and button all agree. Four values per tone — ink (text on
   white), plate (a fill that takes white text), bg (the wash), line (the
   ring) — and the dark twins LIGHTEN the ink and DARKEN the plate, so a
   white glyph on a plate stays legible after dark.

   Cascade rule 1 applies throughout: every surface has its `body.theme-dark`
   twin; `background-color`, never the shorthand, wherever an image may
   follow (see dark-background-shorthand-trap).
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-fam[data-tone="blue"]    { --fam-ink:#1B5BB5; --fam-plate:#1B5BB5; --fam-bg:#EAF2FD; --fam-line:#CFE0FA; --fam-glow:rgba(54,128,237,.4); }
.v2x.dcx .dcx-fam[data-tone="violet"]  { --fam-ink:#0369A1; --fam-plate:#0369A1; --fam-bg:#E0F2FE; --fam-line:#BAE6FD; --fam-glow:rgba(14,165,233,.42); }
.v2x.dcx .dcx-fam[data-tone="indigo"]  { --fam-ink:#3540B0; --fam-plate:#3540B0; --fam-bg:#EBEEFE; --fam-line:#D3D9FB; --fam-glow:rgba(99,102,241,.42); }
.v2x.dcx .dcx-fam[data-tone="rose"]    { --fam-ink:#B31D3C; --fam-plate:#B31D3C; --fam-bg:#FEECEF; --fam-line:#FBD2DA; --fam-glow:rgba(236,72,153,.42); }
.v2x.dcx .dcx-fam[data-tone="amber"]   { --fam-ink:#A85B08; --fam-plate:#A85B08; --fam-bg:#FEF4E4; --fam-line:#FBE3C0; --fam-glow:rgba(245,158,11,.42); }
.v2x.dcx .dcx-fam[data-tone="emerald"] { --fam-ink:#08795A; --fam-plate:#08795A; --fam-bg:#E6F8F1; --fam-line:#C6EEDF; --fam-glow:rgba(16,185,129,.42); }
.v2x.dcx .dcx-fam[data-tone="cyan"]    { --fam-ink:#0A6E88; --fam-plate:#0A6E88; --fam-bg:#E4F6FB; --fam-line:#C2E9F4; --fam-glow:rgba(6,182,212,.42); }
.v2x.dcx .dcx-fam[data-tone="orange"]  { --fam-ink:#B4500C; --fam-plate:#B4500C; --fam-bg:#FEF0E6; --fam-line:#FBD9C2; --fam-glow:rgba(234,88,12,.42); }

body.theme-dark .v2x.dcx .dcx-fam[data-tone="blue"]    { --fam-ink:#8CBEFA; --fam-plate:#2572DF; --fam-bg:rgba(54,128,237,.16);  --fam-line:rgba(96,164,245,.28); }
body.theme-dark .v2x.dcx .dcx-fam[data-tone="violet"]  { --fam-ink:#7DD3FC; --fam-plate:#0284C7; --fam-bg:rgba(1,150,253,.18);   --fam-line:rgba(56,189,248,.3); }
body.theme-dark .v2x.dcx .dcx-fam[data-tone="indigo"]  { --fam-ink:#A9B2FB; --fam-plate:#616BCF; --fam-bg:rgba(79,70,229,.18);   --fam-line:rgba(129,140,248,.3); }
body.theme-dark .v2x.dcx .dcx-fam[data-tone="rose"]    { --fam-ink:#FB9BB0; --fam-plate:#DD2C51; --fam-bg:rgba(244,63,94,.18);   --fam-line:rgba(251,113,133,.3); }
body.theme-dark .v2x.dcx .dcx-fam[data-tone="amber"]   { --fam-ink:#FBC97A; --fam-plate:#B16008; --fam-bg:rgba(245,158,11,.18);  --fam-line:rgba(251,191,36,.3); }
body.theme-dark .v2x.dcx .dcx-fam[data-tone="emerald"] { --fam-ink:#6EE7BE; --fam-plate:#098563; --fam-bg:rgba(16,185,129,.18);  --fam-line:rgba(52,211,153,.3); }
body.theme-dark .v2x.dcx .dcx-fam[data-tone="cyan"]    { --fam-ink:#7CD9EE; --fam-plate:#0C7F9D; --fam-bg:rgba(6,182,212,.18);   --fam-line:rgba(34,211,238,.3); }
body.theme-dark .v2x.dcx .dcx-fam[data-tone="orange"]  { --fam-ink:#FBB07A; --fam-plate:#BF550D; --fam-bg:rgba(249,115,22,.18);  --fam-line:rgba(251,146,60,.3); }

/* ── The grid ─────────────────────────────────────────────────────────────
   Four across at the 1180px band cap — the homepage quartet's rhythm — two
   on a tablet, one on a phone. `align-items: start`: a card with twelve
   rows and one with two must not stretch to the same height. */
.v2x.dcx .dcx-grid.is-fam {
    /* `max(262px, 22%)`: never narrower than 262px, and never more than four
       across — a fifth would need 5 × 22% of the row. On the 2560px screen
       this page is also read on, 262px alone gave six cramped columns. */
    grid-template-columns: repeat(auto-fill, minmax(min(100%, max(262px, 22%)), 1fr));
    gap: 18px;
    align-items: start;
}

/* §DCXMAS — masonry. The script at the foot of the hub view measures each card
   and writes `grid-row-end: span <height + gap>` while this class is on;
   1px rows plus `dense` packing put the next card under the shortest column,
   so a two-row card no longer leaves a hole under it. Row gap must be 0 here —
   the span already includes the gap — and only the column gap survives. */
.v2x.dcx .dcx-grid.is-fam.is-masonry {
    grid-auto-rows: 1px;
    grid-auto-flow: row dense;
    row-gap: 0;
    column-gap: 18px;
}

/* ── The card ───────────────────────────────────────────────────────────── */
.v2x.dcx .dcx-fam {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    background-color: #fff;
    border: 1px solid var(--v2-line);
    border-radius: 20px;
    /* The homepage's three-layer recipe: a glass hairline along the top inner
       edge, a contact shadow, a wide soft one. */
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .7),
        0 1px 2px rgba(16, 24, 40, .04),
        0 12px 26px -20px rgba(16, 24, 40, .30);
    transition: transform .24s var(--ease-spring), box-shadow .26s ease, border-color .22s ease;
}

body.theme-dark .v2x.dcx .dcx-fam {
    background-color: rgba(29, 29, 34, .92);
    border-color: var(--dk-line, rgba(255, 255, 255, .10));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .4),
        0 12px 26px -20px rgba(0, 0, 0, .7);
}

/* ── The header — the main category, itself a link ──────────────────────── */
.v2x.dcx .dcx-fam-top {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 18px 18px 16px;
    background-image:
        linear-gradient(180deg, var(--fam-bg) 0%, transparent 100%),
        radial-gradient(120% 130% at 100% 0%, var(--fam-bg) 0%, transparent 64%);
    border-bottom: 1px solid var(--v2-line);
    color: var(--v2-ink);
    text-decoration: none;
}

body.theme-dark .v2x.dcx .dcx-fam-top { border-bottom-color: rgba(255, 255, 255, .06); }

/* A solid tone plate with a white glyph — a soft tint would disappear into
   the tinted header it is sitting on. */
.v2x.dcx .dcx-fam-ico {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 46px; height: 46px;
    border-radius: 14px;
    background-color: var(--fam-plate);
    background-image: linear-gradient(155deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, 0) 62%);
    color: #fff;
    box-shadow: 0 8px 16px -8px var(--fam-plate);
    transition: transform .28s var(--ease-spring), box-shadow .26s ease;
}

.v2x.dcx .dcx-fam-ico svg { width: 22px; height: 22px; }
.v2x.dcx .dcx-fam-ico i   { font-size: 19px; }

body.theme-dark .v2x.dcx .dcx-fam-ico { box-shadow: none; }

.v2x.dcx .dcx-fam-copy { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }

.v2x.dcx .dcx-fam-title {
    font-size: 17px;
    font-weight: 760;
    line-height: 1.25;
    letter-spacing: -.018em;
    color: var(--v2-ink);
}

.v2x.dcx .dcx-fam-sub {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 3px;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--v2-muted);
}

/* An empty family (rolled-up count 0 — §CATTREE) says so beside its name, in
   neutral, rather than printing a zero in the tone. The live count itself
   rides on the action ("Explore 8 tools"). */
.v2x.dcx .dcx-fam-soon {
    display: inline-block;
    vertical-align: 2px;
    margin-inline-start: 6px;
    padding: 2px 7px;
    border-radius: 999px;
    background-color: #fff;
    color: var(--v2-muted);
    font-size: 10.5px;
    font-weight: 750;
    letter-spacing: .01em;
    line-height: 1.4;
    white-space: nowrap;
    box-shadow: inset 0 0 0 1px var(--v2-line);
}

body.theme-dark .v2x.dcx .dcx-fam-soon {
    background-color: rgba(255, 255, 255, .06);
    box-shadow: inset 0 0 0 1px var(--dk-line, rgba(255, 255, 255, .12));
}

/* ── The rows — one subcategory each ────────────────────────────────────── */
.v2x.dcx .dcx-fam-links {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1 1 auto;
    margin: 0;
    /* 14px at the foot is what guarantees air above the button: its
       `margin-top: auto` only pays out when the card has slack, and the
       twelve-row card has none. */
    padding: 10px 10px 14px;
    list-style: none;
}

.v2x.dcx .dcx-fam-links li { margin: 0; padding: 0; }

.v2x.dcx .dcx-fam-links a {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 9px;
    border-radius: 10px;
    color: var(--v2-ink);
    text-decoration: none;
    transition: background-color .16s ease;
}

/* The tone bar that grows on hover, so a row reads as selected rather than
   merely tinted. */
.v2x.dcx .dcx-fam-links a::before {
    content: '';
    position: absolute;
    inset-inline-start: 0;
    top: 50%;
    width: 2px; height: 0;
    border-radius: 2px;
    background-color: var(--fam-ink);
    transform: translateY(-50%);
    transition: height .22s var(--ease-spring);
}

.v2x.dcx .dcx-fam-lico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 28px; height: 28px;
    border-radius: 9px;
    background-color: var(--fam-bg);
    color: var(--fam-ink);
    transition: transform .2s ease;
}

.v2x.dcx .dcx-fam-lico svg { width: 14px; height: 14px; }

.v2x.dcx .dcx-fam-ltitle {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13px;
    font-weight: 640;
    line-height: 1.35;
    transition: color .18s ease;
}

/* The row's own count — small, tabular, out of the way; a zero goes quiet. */
.v2x.dcx .dcx-fam-ln {
    flex: 0 0 auto;
    min-width: 18px;
    color: var(--v2-muted);
    font-size: 11.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: end;
}

.v2x.dcx .dcx-fam-links a[data-soon="1"] .dcx-fam-ln { opacity: .55; }

/* The affordance that says these rows go somewhere: hidden at rest on a
   pointer device, revealed on hover; always faintly there on touch. */
.v2x.dcx .dcx-fam-lgo {
    flex: 0 0 auto;
    width: 14px; height: 14px;
    color: var(--fam-ink);
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity .18s ease, transform .2s var(--ease-spring);
}

[dir="rtl"] .v2x.dcx .dcx-fam-lgo { transform: scaleX(-1) translateX(-4px); }

/* ── The expander — rows past `maxRows` stay in the DOM, hidden ────────── */
.v2x.dcx .dcx-fam-links li.is-extra { display: none; }
.v2x.dcx .dcx-fam.is-open .dcx-fam-links li.is-extra { display: block; }

.v2x.dcx .dcx-fam-more {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    align-self: flex-start;
    margin: -6px 14px 4px;
    padding: 6px 10px;
    border: 0;
    border-radius: 999px;
    background-color: transparent;
    color: var(--fam-ink);
    font: inherit;
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    transition: background-color .18s ease;
}

.v2x.dcx .dcx-fam-more svg { width: 13px; height: 13px; transition: transform .25s var(--ease-spring); }
.v2x.dcx .dcx-fam.is-open .dcx-fam-more svg { transform: rotate(180deg); }

@media (hover: hover) {
    .v2x.dcx .dcx-fam-more:hover { background-color: var(--fam-bg); }
}

.v2x.dcx .dcx-fam-more:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--fam-line); }

/* ── The action ─────────────────────────────────────────────────────────── */
.v2x.dcx .dcx-fam-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin: auto 14px 16px;
    padding: 9px 10px 9px 19px;
    border-radius: 999px;
    background-color: var(--fam-bg);
    color: var(--fam-ink);
    font-size: 14px;
    font-weight: 650;
    letter-spacing: -.004em;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    box-shadow: inset 0 0 0 1px var(--fam-line);
    transition: transform .18s ease, box-shadow .22s ease, background-color .18s ease, color .18s ease;
}

.v2x.dcx .dcx-fam-btn-arrow {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 24px; height: 24px;
    border-radius: 50%;
    background-color: var(--fam-plate);
    color: #fff;
    transition: background-color .2s ease, transform .22s var(--ease-spring);
}

.v2x.dcx .dcx-fam-btn-arrow svg { width: 13px; height: 13px; }
[dir="rtl"] .v2x.dcx .dcx-fam-btn-arrow svg { transform: scaleX(-1); }

.v2x.dcx .dcx-fam-btn:focus-visible {
    outline: none;
    background-color: var(--fam-plate);
    color: #fff;
    box-shadow: 0 0 0 3px var(--fam-line);
}

.v2x.dcx .dcx-fam-top:focus-visible,
.v2x.dcx .dcx-fam-links a:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px var(--fam-line);
}

.v2x.dcx .dcx-fam-links a:focus-visible::before { height: 62%; }
.v2x.dcx .dcx-fam-links a:focus-visible .dcx-fam-lgo { opacity: 1; transform: translateX(0); }

/* ── Hover ──────────────────────────────────────────────────────────────── */
@media (hover: hover) {
    .v2x.dcx .dcx-fam:hover {
        transform: translateY(-4px);
        border-color: var(--fam-line);
        box-shadow:
            inset 0 1px 0 rgba(255, 255, 255, .7),
            0 1px 2px rgba(16, 24, 40, .05),
            0 26px 46px -30px var(--fam-glow, rgba(16, 24, 40, .4));
    }

    body.theme-dark .v2x.dcx .dcx-fam:hover {
        box-shadow:
            inset 0 1px 0 rgba(255, 255, 255, .06),
            0 26px 46px -30px rgba(0, 0, 0, .85);
    }

    .v2x.dcx .dcx-fam:hover .dcx-fam-ico {
        transform: translateY(-2px) scale(1.04);
        box-shadow: 0 14px 22px -10px var(--fam-plate);
    }

    body.theme-dark .v2x.dcx .dcx-fam:hover .dcx-fam-ico { box-shadow: none; }

    .v2x.dcx .dcx-fam-top:hover .dcx-fam-title { color: var(--fam-ink); }

    .v2x.dcx .dcx-fam-links a:hover { background-color: var(--fam-bg); }
    .v2x.dcx .dcx-fam-links a:hover::before { height: 62%; }
    .v2x.dcx .dcx-fam-links a:hover .dcx-fam-ltitle { color: var(--fam-ink); }
    .v2x.dcx .dcx-fam-links a:hover .dcx-fam-lico { transform: scale(1.08); }
    .v2x.dcx .dcx-fam-links a:hover .dcx-fam-lgo { opacity: 1; transform: translateX(0); }
    [dir="rtl"] .v2x.dcx .dcx-fam-links a:hover .dcx-fam-lgo { transform: scaleX(-1) translateX(0); }

    .v2x.dcx .dcx-fam-btn:hover {
        background-color: var(--fam-plate);
        background-image: linear-gradient(160deg, rgba(255, 255, 255, .2) 0%, rgba(255, 255, 255, 0) 58%);
        color: #fff;
        transform: translateY(-1px);
        box-shadow: 0 12px 24px -10px var(--fam-plate);
    }

    body.theme-dark .v2x.dcx .dcx-fam-btn:hover { box-shadow: 0 12px 24px -12px rgba(0, 0, 0, .9); }

    .v2x.dcx .dcx-fam-btn:hover .dcx-fam-btn-arrow { background-color: rgba(255, 255, 255, .24); }
}

@media (hover: none) {
    .v2x.dcx .dcx-fam-lgo { opacity: .4; transform: none; }
    [dir="rtl"] .v2x.dcx .dcx-fam-lgo { transform: scaleX(-1); }
}

/* ── Narrow ─────────────────────────────────────────────────────────────── */
@media (max-width: 575.98px) {
    .v2x.dcx .dcx-grid.is-fam { gap: 14px; }
    .v2x.dcx .dcx-fam-top { padding: 15px 15px 14px; }
    .v2x.dcx .dcx-fam-ico { width: 42px; height: 42px; border-radius: 13px; }
    .v2x.dcx .dcx-fam-title { font-size: 16px; }
    .v2x.dcx .dcx-fam-links a { padding: 8px; gap: 8px; }
    .v2x.dcx .dcx-fam-btn { margin: auto 12px 12px; }
}

@media (prefers-reduced-motion: reduce) {
    .v2x.dcx .dcx-fam, .v2x.dcx .dcx-fam-ico, .v2x.dcx .dcx-fam-links a, .v2x.dcx .dcx-fam-lgo,
    .v2x.dcx .dcx-fam-btn, .v2x.dcx .dcx-fam-btn-arrow, .v2x.dcx .dcx-fam-lico { transition: none; }
    .v2x.dcx .dcx-fam:hover, .v2x.dcx .dcx-fam:hover .dcx-fam-ico, .v2x.dcx .dcx-fam-btn:hover { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   §DCXTAG — the tag cloud
   ---------------------------------------------------------------------------
   Tags carry a name and a count and nothing else worth a card. A pill row is
   the right density, and it lets thirteen of them occupy the space two cards
   would. Each pill wears its own tag colour as a dot; the LABEL stays in the
   ink token, because thirteen differently-coloured words is a ransom note.
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-tagcloud {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
}

.v2x.dcx .dcx-tag {
    /* Raw hue for the dot and the glow; the contrast-checked pair for the
       hover FILL. Same two-token shape, same reason, as §DCXSPOT's. */
    --dct-rgb: 54, 128, 237;
    --dct-ink: #1B5BB5;
    --dct-inkd: #8CBEFA;
    --dct-now: var(--dct-ink);
    --dct-on: #fff;
    /* The count well once the pill has filled — same neutral scrim, same
       reason, as §DCXSPOT`s `--dcs-well`. */
    --dct-well: rgba(0, 0, 0, .2);
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 9px 9px 9px 14px;
    border: 1px solid var(--v2-line);
    border-radius: 999px;
    background-color: #fff;
    color: var(--v2-ink);
    font-size: 13.5px;
    font-weight: 650;
    letter-spacing: -.006em;
    text-decoration: none;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
    transition: transform .22s var(--ease-spring), border-color .2s ease, box-shadow .24s ease, background-color .2s ease, color .18s ease;
}

body.theme-dark .v2x.dcx .dcx-tag {
    --dct-now: var(--dct-inkd);
    --dct-on: var(--dk-surface,#131317);
    --dct-well: rgba(255, 255, 255, .26);
    border-color: var(--dk-line,rgba(255,255,255,.10));
    background-color: rgba(29,29,34,.9);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .4);
}

.v2x.dcx .dcx-tag-dot {
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background-color: rgb(var(--dct-rgb));
    box-shadow: 0 0 0 3px rgba(var(--dct-rgb), .18);
    transition: box-shadow .24s ease, background-color .2s ease;
}

.v2x.dcx .dcx-tag-nm { white-space: nowrap; }

.v2x.dcx .dcx-tag-cnt {
    display: inline-grid;
    place-items: center;
    flex: 0 0 auto;
    min-width: 24px;
    height: 24px;
    padding: 0 7px;
    border-radius: 999px;
    background-color: var(--v2-bg);
    color: var(--v2-muted);
    font-size: 11.5px;
    font-weight: 700;
    line-height: 1;
    transition: background-color .2s ease, color .18s ease;
}

body.theme-dark .v2x.dcx .dcx-tag-cnt {
    background-color: rgba(255, 255, 255, .07);
    color: var(--v2-muted);
}

/* Hover fills with the tag's own hue, in its theme-safe form. The dot, the
   count well and the label invert TOGETHER — inverting only the label is how
   a filled pill ends up showing a white dot on white. */
@media (hover: hover) {
    .v2x.dcx .dcx-tag:hover {
        transform: translateY(-2px);
        border-color: transparent;
        background-color: var(--dct-now);
        color: var(--dct-on);
        text-decoration: none;
        box-shadow: 0 12px 24px -10px rgba(var(--dct-rgb), .6);
    }

    body.theme-dark .v2x.dcx .dcx-tag:hover {
        border-color: transparent;
        background-color: var(--dct-now);
        color: var(--dct-on);
        box-shadow: 0 12px 24px -10px rgba(0, 0, 0, .7);
    }

    .v2x.dcx .dcx-tag:hover .dcx-tag-dot {
        background-color: var(--dct-on);
        box-shadow: 0 0 0 3px rgba(var(--dct-rgb), .34);
    }

    .v2x.dcx .dcx-tag:hover .dcx-tag-cnt {
        background-color: var(--dct-well);
        color: var(--dct-on);
    }
}

.v2x.dcx .dcx-tag:focus-visible {
    outline: none;
    border-color: var(--dct-now);
    box-shadow: 0 0 0 3px rgba(var(--dct-rgb), .3);
}

.v2x.dcx .dcx-tag:active { transform: translateY(0) scale(.97); }

/* §DCXTAG · grouped (§TAGTREE, 2026-09-15) — one card per MAIN tag: a linked
   head wearing the group's hue on its icon plate and carrying the rolled-up
   count, then that group's sub-tag pills, left-aligned beneath it. The pills
   are the SAME .dcx-tag; only the container changes. Flat while searching.
   Tone tokens ride on the card (`--dct-*`, set inline by $dcxTone) so the head
   and its pills agree; every pill still carries its own, so a recoloured sub
   tag wins on its own pill. */
.v2x.dcx .dcx-taggroups {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.v2x.dcx .dcx-taggrp {
    --dct-rgb: 54, 128, 237;
    --dct-ink: #1B5BB5;
    --dct-inkd: #8CBEFA;
    --dct-now: var(--dct-ink);
    padding: 16px 18px 18px;
    border: 1px solid var(--v2-line);
    border-radius: 18px;
    background-color: #fff;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
}

body.theme-dark .v2x.dcx .dcx-taggrp {
    --dct-now: var(--dct-inkd);
    border-color: var(--dk-line,rgba(255,255,255,.10));
    background-color: rgba(29,29,34,.9);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .4);
}

.v2x.dcx .dcx-taggrp-hd {
    display: inline-flex;
    align-items: center;
    gap: 11px;
    margin: 0 0 12px;
    color: var(--v2-ink);
    font-size: 15px;
    font-weight: 800;
    letter-spacing: -.012em;
    text-decoration: none;
    transition: color .18s ease;
}

/* Icon plate: alpha .14 by day is the very tint `--dct-ink` was walked
   against, and .22 by night sits under the .26 `--dct-inkd` was, so the glyph
   clears 4.5:1 on its plate in both themes. */
.v2x.dcx .dcx-taggrp-ic {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 10px;
    background-color: rgba(var(--dct-rgb), .14);
    color: var(--dct-now);
}

body.theme-dark .v2x.dcx .dcx-taggrp-ic { background-color: rgba(var(--dct-rgb), .22); }

.v2x.dcx .dcx-taggrp-ic svg,
.v2x.dcx .dcx-taggrp-ic i { width: 16px; height: 16px; font-size: 15px; }

.v2x.dcx .dcx-taggrp-nm { min-width: 0; }

.v2x.dcx .dcx-taggrp-cnt {
    flex: 0 0 auto;
    padding: 3px 9px;
    border-radius: 999px;
    background-color: var(--v2-bg);
    color: var(--v2-muted);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0;
    white-space: nowrap;
}

body.theme-dark .v2x.dcx .dcx-taggrp-cnt {
    background-color: rgba(255, 255, 255, .07);
}

@media (hover: hover) {
    .v2x.dcx .dcx-taggrp-hd:hover { color: var(--dct-now); text-decoration: none; }
}

.v2x.dcx .dcx-taggrp-hd:focus-visible {
    outline: none;
    border-radius: 8px;
    box-shadow: 0 0 0 3px rgba(var(--dct-rgb), .3);
}

.v2x.dcx .dcx-tagcloud.is-sub {
    justify-content: flex-start;
    gap: 8px;
}

@media (max-width: 640px) {
    .v2x.dcx .dcx-taggrp { padding: 14px 14px 15px; border-radius: 14px; }
    .v2x.dcx .dcx-taggrp-hd { font-size: 14px; gap: 9px; }
    .v2x.dcx .dcx-taggrp-ic { width: 28px; height: 28px; border-radius: 8px; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXEMPTY — no search results
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 10px;
    padding: 54px 24px;
    border: 1px dashed var(--v2-line);
    border-radius: 22px;
    background-color: #fff;
}

body.theme-dark .v2x.dcx .dcx-empty {
    border-color: var(--dk-line,rgba(255,255,255,.10));
    background-color: rgba(29,29,34,.72);
}

.v2x.dcx .dcx-empty-ic {
    display: grid;
    place-items: center;
    width: 62px;
    height: 62px;
    border-radius: 20px;
    background-color: var(--v2-accent-soft);
    color: var(--brand-blue);
    margin-bottom: 4px;
}

body.theme-dark .v2x.dcx .dcx-empty-ic {
    background-color: rgba(54, 128, 237, .16);
    color: var(--brand-blue-light);
}

.v2x.dcx .dcx-empty-ic svg { width: 28px; height: 28px; }

.v2x.dcx .dcx-empty .dcx-empty-t {
    margin: 0;
    font-size: 19px;
    font-weight: 750;
    line-height: 1.3;
    letter-spacing: -.018em;
    color: var(--v2-ink);
}

.v2x.dcx .dcx-empty p {
    margin: 0;
    max-width: 46ch;
    font-size: 14.5px;
    line-height: 1.6;
    color: var(--v2-muted);
}

.v2x.dcx .dcx-empty-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 11px 22px;
    border: 0;
    border-radius: 999px;
    /* AA ramp — see §DCXBAR. */
    background-color: #2762C2;
    background-image: linear-gradient(135deg, #2E6FD0 0%, #2762C2 46%, #1B4E9E 100%);
    color: #fff;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 10px 22px -10px rgba(54, 128, 237, .6);
    transition: transform .2s var(--ease-spring), box-shadow .22s ease;
}

@media (hover: hover) {
    .v2x.dcx .dcx-empty-btn:hover { transform: translateY(-2px); box-shadow: 0 16px 30px -12px rgba(54, 128, 237, .7); color: #fff; }
}

.v2x.dcx .dcx-empty-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(54, 128, 237, .35); }
.v2x.dcx .dcx-empty-btn:active { transform: scale(.97); }


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXCTA — the closing panel (v2, 2026-09-16)
   ---------------------------------------------------------------------------
   A wayfinding index must not be a dead end for someone who wanted the whole
   catalogue. v2 is a two-column "finder": the copy, the two exits and the
   directory's own filters as one-tap chips with live counts on the left; on
   the right a decorative filter deck — a typed query, three fanned filter
   cards, a match count — that shows what the click leads to. The art is
   aria-hidden throughout and stacks under the copy below 900px.

   Tokens are the page's own (`--v2-*`, brand blue); the deck's cards use
   `--dcx-glass` for their surface so both themes paint them once. Every
   surface has its `body.theme-dark` twin (cascade rule 1); backgrounds that
   carry an image use `background-color` + `background-image`, never the
   shorthand (dark-background-shorthand-trap).
   ═══════════════════════════════════════════════════════════════════════════ */

.v2x.dcx .dcx-cta {
    --dcx-glass: rgba(255, 255, 255, .86);
    --dcx-glass-line: rgba(255, 255, 255, .9);
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(300px, .85fr);
    align-items: center;
    gap: clamp(24px, 4vw, 56px);
    margin-top: clamp(38px, 5vw, 62px);
    padding: clamp(28px, 4vw, 48px) clamp(22px, 4vw, 52px);
    border: 1px solid var(--v2-line);
    border-radius: 28px;
    background-color: #fff;
    background-image:
        radial-gradient(640px 320px at 8% -20%, rgba(54, 128, 237, .14) 0%, rgba(54, 128, 237, 0) 70%),
        radial-gradient(560px 300px at 96% 120%, rgba(1, 150, 253, .14) 0%, rgba(1, 150, 253, 0) 70%),
        linear-gradient(180deg, #fff 0%, #F7FAFF 100%);
    overflow: hidden;
    isolation: isolate;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 24px 54px -34px rgba(16, 24, 40, .35);
    transition: box-shadow .3s ease, border-color .3s ease;
}

body.theme-dark .v2x.dcx .dcx-cta {
    --dcx-glass: rgba(29, 29, 34, .78);
    --dcx-glass-line: rgba(255, 255, 255, .12);
    border-color: var(--dk-line, rgba(255, 255, 255, .10));
    background-color: #17181D;
    background-image:
        radial-gradient(640px 320px at 8% -20%, rgba(54, 128, 237, .26) 0%, rgba(54, 128, 237, 0) 70%),
        radial-gradient(560px 300px at 96% 120%, rgba(1, 150, 253, .22) 0%, rgba(1, 150, 253, 0) 70%),
        linear-gradient(180deg, #1B1C22 0%, #15161B 100%);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .42), 0 24px 54px -34px rgba(0, 0, 0, .85);
}

/* Two slow-drifting orbs behind everything — the hero's glow language.
   Blurred colour only; they never carry text, so contrast is not in play. */
.v2x.dcx .dcx-cta-orb {
    position: absolute;
    z-index: -1;
    width: 340px; height: 340px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 35%, rgba(54, 128, 237, .28) 0%, rgba(54, 128, 237, 0) 62%);
    filter: blur(6px);
    left: -120px; top: -140px;
    pointer-events: none;
    animation: dcx-orb 14s ease-in-out infinite alternate;
}

.v2x.dcx .dcx-cta-orb.is-2 {
    left: auto; top: auto;
    right: -110px; bottom: -160px;
    width: 300px; height: 300px;
    background: radial-gradient(circle at 60% 60%, rgba(1, 150, 253, .26) 0%, rgba(1, 150, 253, 0) 62%);
    animation-duration: 18s;
    animation-delay: -6s;
}

body.theme-dark .v2x.dcx .dcx-cta-orb      { background: radial-gradient(circle at 35% 35%, rgba(54, 128, 237, .38) 0%, rgba(54, 128, 237, 0) 62%); }
body.theme-dark .v2x.dcx .dcx-cta-orb.is-2 { background: radial-gradient(circle at 60% 60%, rgba(1, 150, 253, .32) 0%, rgba(1, 150, 253, 0) 62%); }

@keyframes dcx-orb {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to   { transform: translate3d(40px, 26px, 0) scale(1.08); }
}

/* ── Copy ─────────────────────────────────────────────────────────────── */
.v2x.dcx .dcx-cta-copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
}

.v2x.dcx .dcx-cta-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 12px 6px 9px;
    border-radius: 999px;
    background-color: rgba(54, 128, 237, .10);
    color: var(--brand-blue-dark, #1B5BB5);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    box-shadow: inset 0 0 0 1px rgba(54, 128, 237, .22);
}

.v2x.dcx .dcx-cta-eyebrow svg { width: 13px; height: 13px; color: var(--brand-blue); }

body.theme-dark .v2x.dcx .dcx-cta-eyebrow {
    background-color: rgba(54, 128, 237, .18);
    color: var(--brand-blue-light, #8CBEFA);
    box-shadow: inset 0 0 0 1px rgba(96, 164, 245, .3);
}

.v2x.dcx .dcx-cta .dcx-cta-t {
    margin: 16px 0 0;
    font-size: clamp(26px, 2.2vw + 10px, 40px);
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -.03em;
    color: var(--v2-ink);
    text-wrap: balance;
}

/* The accent word: the site's blue→sky gradient, with a soft underline that
   draws in on hover of the panel. `-webkit-text-fill-color` is the part that
   actually paints the gradient; `color` is the fallback. */
.v2x.dcx .dcx-cta-accent {
    position: relative;
    display: inline-block;
    color: var(--brand-blue);
    background-image: linear-gradient(92deg, #3680ED 0%, #0196FD 55%, #5CCBFF 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.v2x.dcx .dcx-cta-accent::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: .04em;
    height: .14em;
    border-radius: 999px;
    background: linear-gradient(90deg, rgba(54, 128, 237, .55), rgba(1, 150, 253, .55));
    transform: scaleX(.35);
    transform-origin: left center;
    opacity: .6;
    transition: transform .55s var(--ease-spring), opacity .3s ease;
}

.v2x.dcx .dcx-cta-p {
    margin: 14px 0 0;
    max-width: 52ch;
    font-size: 15.5px;
    line-height: 1.65;
    color: var(--v2-muted);
}

/* ── Buttons ──────────────────────────────────────────────────────────── */
.v2x.dcx .dcx-cta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 24px;
}

.v2x.dcx .dcx-cta-b {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 12px 22px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: 14.5px;
    font-weight: 700;
    letter-spacing: -.006em;
    text-decoration: none;
    overflow: hidden;
    isolation: isolate;
    transition: transform .2s var(--ease-spring), box-shadow .24s ease, background-color .2s ease, color .18s ease, border-color .2s ease;
}

.v2x.dcx .dcx-cta-b > svg { width: 16px; height: 16px; flex: 0 0 auto; }

.v2x.dcx .dcx-cta-b.is-primary {
    padding-inline-end: 8px;
    /* AA ramp — see §DCXBAR. */
    background-color: #2762C2;
    background-image: linear-gradient(135deg, #3680ED 0%, #2762C2 52%, #1B4E9E 100%);
    color: #fff;
    box-shadow: 0 12px 26px -10px rgba(54, 128, 237, .65), inset 0 1px 0 rgba(255, 255, 255, .22);
}

/* The sheen that sweeps across on hover — its own layer so the gradient
   underneath never moves. */
.v2x.dcx .dcx-cta-b.is-primary::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(115deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, .28) 50%, rgba(255, 255, 255, 0) 70%);
    transform: translateX(-120%);
    transition: transform .7s ease;
}

.v2x.dcx .dcx-cta-b-arrow {
    display: grid;
    place-items: center;
    width: 26px; height: 26px;
    margin-inline-start: 4px;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, .2);
    color: #fff;
    transition: transform .22s var(--ease-spring), background-color .2s ease;
}

.v2x.dcx .dcx-cta-b-arrow svg { width: 13px; height: 13px; }
[dir="rtl"] .v2x.dcx .dcx-cta-b-arrow svg { transform: scaleX(-1); }

.v2x.dcx .dcx-cta-b.is-ghost {
    background-color: #fff;
    border-color: var(--v2-line);
    color: var(--v2-ink);
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
}

body.theme-dark .v2x.dcx .dcx-cta-b.is-ghost {
    background-color: rgba(255, 255, 255, .05);
    border-color: var(--dk-line-strong, rgba(255, 255, 255, .16));
    color: var(--v2-ink);
}

/* ── Quick filters ────────────────────────────────────────────────────── */
.v2x.dcx .dcx-cta-quick {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid var(--v2-line);
    width: 100%;
}

body.theme-dark .v2x.dcx .dcx-cta-quick { border-top-color: rgba(255, 255, 255, .08); }

.v2x.dcx .dcx-cta-quick-lbl {
    margin-inline-end: 4px;
    color: var(--v2-muted);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    white-space: nowrap;
}

.v2x.dcx .dcx-cta-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 34px;
    padding: 0 11px 0 9px;
    border: 1px solid var(--v2-line);
    border-radius: 999px;
    background-color: #fff;
    color: var(--v2-ink);
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: -.004em;
    text-decoration: none;
    white-space: nowrap;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
    transition: transform .2s var(--ease-spring), border-color .2s ease, background-color .2s ease, color .18s ease, box-shadow .24s ease;
}

body.theme-dark .v2x.dcx .dcx-cta-chip {
    background-color: rgba(255, 255, 255, .05);
    border-color: var(--dk-line, rgba(255, 255, 255, .12));
}

.v2x.dcx .dcx-cta-chip-ico {
    display: inline-grid;
    place-items: center;
    width: 20px; height: 20px;
    border-radius: 7px;
    background-color: rgba(54, 128, 237, .10);
    color: var(--brand-blue-dark, #1B5BB5);
    transition: background-color .2s ease, color .2s ease;
}

.v2x.dcx .dcx-cta-chip-ico svg { width: 13px; height: 13px; }

body.theme-dark .v2x.dcx .dcx-cta-chip-ico { background-color: rgba(54, 128, 237, .2); color: var(--brand-blue-light, #8CBEFA); }

.v2x.dcx .dcx-cta-chip-n {
    display: inline-grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background-color: var(--v2-bg, #F4F6FA);
    color: var(--v2-muted);
    font-size: 10.5px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    transition: background-color .2s ease, color .2s ease;
}

body.theme-dark .v2x.dcx .dcx-cta-chip-n { background-color: rgba(255, 255, 255, .08); }

/* ── The art: typed query, filter deck, match pill ────────────────────── */
.v2x.dcx .dcx-cta-art {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    min-width: 0;
    padding: 18px 12px 8px;
    perspective: 1200px;
}

/* Two thin orbit rings, the hero's motif, turning very slowly. */
.v2x.dcx .dcx-cta-ring {
    position: absolute;
    z-index: 0;
    top: 50%; left: 50%;
    width: min(420px, 118%);
    aspect-ratio: 1;
    border: 1px dashed rgba(54, 128, 237, .28);
    border-radius: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    animation: dcx-ring 60s linear infinite;
}

.v2x.dcx .dcx-cta-ring.is-2 {
    width: min(300px, 86%);
    border-style: solid;
    border-color: rgba(54, 128, 237, .14);
    animation-direction: reverse;
    animation-duration: 45s;
}

body.theme-dark .v2x.dcx .dcx-cta-ring      { border-color: rgba(96, 164, 245, .3); }
body.theme-dark .v2x.dcx .dcx-cta-ring.is-2 { border-color: rgba(96, 164, 245, .16); }

@keyframes dcx-ring {
    from { transform: translate(-50%, -50%) rotate(0deg); }
    to   { transform: translate(-50%, -50%) rotate(360deg); }
}

.v2x.dcx .dcx-cta-search {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 10px;
    width: min(360px, 100%);
    padding: 11px 12px 11px 14px;
    border: 1px solid var(--dcx-glass-line);
    border-radius: 16px;
    background-color: var(--dcx-glass);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 18px 36px -22px rgba(16, 24, 40, .35);
    transition: transform .4s var(--ease-spring), box-shadow .3s ease;
}

body.theme-dark .v2x.dcx .dcx-cta-search { box-shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 18px 36px -22px rgba(0, 0, 0, .8); }

.v2x.dcx .dcx-cta-search-ico {
    display: grid;
    place-items: center;
    width: 30px; height: 30px;
    border-radius: 10px;
    background-color: #2762C2;
    background-image: linear-gradient(135deg, #3680ED 0%, #1B4E9E 100%);
    color: #fff;
    box-shadow: 0 8px 16px -8px rgba(54, 128, 237, .7);
}

.v2x.dcx .dcx-cta-search-ico svg { width: 15px; height: 15px; }

.v2x.dcx .dcx-cta-search-q {
    display: inline-flex;
    align-items: center;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    color: var(--v2-ink);
    font-size: 14.5px;
    font-weight: 600;
    letter-spacing: -.006em;
    white-space: nowrap;
}

.v2x.dcx .dcx-cta-caret {
    display: inline-block;
    width: 2px; height: 1.1em;
    margin-inline-start: 2px;
    border-radius: 1px;
    background-color: var(--brand-blue);
    animation: dcx-caret 1s steps(1) infinite;
}

@keyframes dcx-caret { 50% { opacity: 0; } }

.v2x.dcx .dcx-cta-search-kbd { display: inline-flex; gap: 3px; flex: 0 0 auto; }

.v2x.dcx .dcx-cta-search-kbd kbd {
    display: inline-grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border-radius: 6px;
    background-color: var(--v2-bg, #F4F6FA);
    color: var(--v2-muted);
    font: 700 10.5px/1 inherit;
    font-family: inherit;
    box-shadow: inset 0 0 0 1px var(--v2-line), 0 1px 0 var(--v2-line);
}

body.theme-dark .v2x.dcx .dcx-cta-search-kbd kbd {
    background-color: rgba(255, 255, 255, .06);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
}

/* The deck: three cards stacked with a vertical stagger, so every card's
   header line — Pricing, Features, Rating — stays readable above the one in
   front of it (a sideways fan hid two of the three behind the front card).
   Each has its own resting tilt and its own hover target, so the stack
   spreads a little as the pointer arrives — the "shuffle" that gives the
   panel its motion. */
.v2x.dcx .dcx-cta-deck {
    position: relative;
    z-index: 1;
    width: min(360px, 100%);
    height: 214px;
}

.v2x.dcx .dcx-cta-fcard {
    position: absolute;
    left: 50%;
    top: 0;
    display: flex;
    flex-direction: column;
    gap: 9px;
    width: min(292px, 88%);
    padding: 12px 14px 13px;
    border: 1px solid var(--dcx-glass-line);
    border-radius: 16px;
    background-color: var(--dcx-glass);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 22px 40px -26px rgba(16, 24, 40, .4);
    transform-origin: 50% 0;
    transition: transform .55s var(--ease-spring), box-shadow .3s ease;
}

body.theme-dark .v2x.dcx .dcx-cta-fcard { box-shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 22px 40px -26px rgba(0, 0, 0, .85); }

.v2x.dcx .dcx-cta-fcard.is-1 { transform: translate(calc(-50% - 10px), 0)   rotate(-2.5deg); z-index: 1; }
.v2x.dcx .dcx-cta-fcard.is-2 { transform: translate(-50%, 62px)             rotate(0deg);    z-index: 2; }
.v2x.dcx .dcx-cta-fcard.is-3 { transform: translate(calc(-50% + 10px), 132px) rotate(2.5deg); z-index: 3; }

.v2x.dcx .dcx-cta-fcard-h {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--v2-muted);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.v2x.dcx .dcx-cta-fcard-h svg { width: 13px; height: 13px; color: var(--brand-blue); }

.v2x.dcx .dcx-cta-fcard-pills { display: flex; flex-wrap: wrap; gap: 6px; }

.v2x.dcx .dcx-cta-fcard-pills span {
    padding: 4px 9px;
    border-radius: 999px;
    background-color: var(--v2-bg, #F4F6FA);
    color: var(--v2-muted);
    font-size: 11.5px;
    font-weight: 700;
    box-shadow: inset 0 0 0 1px var(--v2-line);
}

.v2x.dcx .dcx-cta-fcard-pills span.is-on {
    background-color: #2762C2;
    background-image: linear-gradient(135deg, #3680ED 0%, #1B4E9E 100%);
    color: #fff;
    box-shadow: 0 6px 12px -6px rgba(54, 128, 237, .7);
}

body.theme-dark .v2x.dcx .dcx-cta-fcard-pills span { background-color: rgba(255, 255, 255, .06); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12); }
body.theme-dark .v2x.dcx .dcx-cta-fcard-pills span.is-on { background-color: #2572DF; box-shadow: none; }

.v2x.dcx .dcx-cta-fcard-rows { display: flex; flex-direction: column; gap: 6px; }

.v2x.dcx .dcx-cta-fcard-row {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--v2-ink);
    font-size: 12px;
    font-weight: 650;
}

/* A toggle switch drawn in CSS: a track and a knob. */
.v2x.dcx .dcx-cta-tog {
    position: relative;
    flex: 0 0 auto;
    width: 26px; height: 15px;
    border-radius: 999px;
    background-color: var(--v2-line);
    transition: background-color .2s ease;
}

.v2x.dcx .dcx-cta-tog::after {
    content: '';
    position: absolute;
    top: 2px; left: 2px;
    width: 11px; height: 11px;
    border-radius: 50%;
    background-color: #fff;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .3);
    transition: transform .25s var(--ease-spring);
}

.v2x.dcx .dcx-cta-tog.is-on { background-color: var(--brand-blue); }
.v2x.dcx .dcx-cta-tog.is-on::after { transform: translateX(11px); }

body.theme-dark .v2x.dcx .dcx-cta-tog { background-color: rgba(255, 255, 255, .16); }
body.theme-dark .v2x.dcx .dcx-cta-tog.is-on { background-color: #2572DF; }

.v2x.dcx .dcx-cta-fcard-stars { display: flex; align-items: center; gap: 2px; }
.v2x.dcx .dcx-cta-fcard-stars svg { width: 15px; height: 15px; color: #F59E0B; }
.v2x.dcx .dcx-cta-fcard-stars svg.is-half { opacity: .45; }

.v2x.dcx .dcx-cta-fcard-stars b {
    margin-inline-start: 6px;
    color: var(--v2-ink);
    font-size: 12.5px;
    font-weight: 800;
}

/* The match count — a live pill, pulsing dot, sitting on the deck's foot. */
.v2x.dcx .dcx-cta-hit {
    position: relative;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 12px 7px 10px;
    border-radius: 999px;
    background-color: var(--dcx-glass);
    color: var(--v2-ink);
    font-size: 12px;
    font-weight: 750;
    box-shadow: inset 0 0 0 1px var(--dcx-glass-line), 0 10px 22px -16px rgba(16, 24, 40, .4);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.v2x.dcx .dcx-cta-hit-dot {
    position: relative;
    width: 8px; height: 8px;
    border-radius: 50%;
    background-color: #0CA678;
    box-shadow: 0 0 0 3px rgba(12, 166, 120, .2);
}

.v2x.dcx .dcx-cta-hit-dot::after {
    content: '';
    position: absolute;
    inset: -3px;
    border-radius: 50%;
    border: 1.5px solid rgba(12, 166, 120, .6);
    animation: dcx-pulse 2.2s ease-out infinite;
}

@keyframes dcx-pulse {
    0%   { transform: scale(.8); opacity: 1; }
    100% { transform: scale(2.1); opacity: 0; }
}

/* ── Hover — the whole panel wakes up ─────────────────────────────────── */
@media (hover: hover) {
    .v2x.dcx .dcx-cta:hover {
        border-color: rgba(54, 128, 237, .35);
        box-shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 30px 64px -34px rgba(54, 128, 237, .45);
    }

    body.theme-dark .v2x.dcx .dcx-cta:hover { box-shadow: 0 1px 2px rgba(0, 0, 0, .42), 0 30px 64px -34px rgba(54, 128, 237, .35); }

    .v2x.dcx .dcx-cta:hover .dcx-cta-accent::after { transform: scaleX(1); opacity: 1; }

    .v2x.dcx .dcx-cta:hover .dcx-cta-fcard.is-1 { transform: translate(calc(-50% - 18px), -8px)  rotate(-4deg); }
    .v2x.dcx .dcx-cta:hover .dcx-cta-fcard.is-2 { transform: translate(-50%, 60px)               rotate(0deg); }
    .v2x.dcx .dcx-cta:hover .dcx-cta-fcard.is-3 { transform: translate(calc(-50% + 18px), 138px) rotate(4deg); box-shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 28px 48px -26px rgba(54, 128, 237, .5); }
    .v2x.dcx .dcx-cta:hover .dcx-cta-search     { transform: translateY(-3px); box-shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 24px 44px -22px rgba(54, 128, 237, .45); }

    .v2x.dcx .dcx-cta-b.is-primary:hover {
        transform: translateY(-2px);
        color: #fff;
        text-decoration: none;
        box-shadow: 0 18px 34px -12px rgba(54, 128, 237, .75), inset 0 1px 0 rgba(255, 255, 255, .22);
    }

    .v2x.dcx .dcx-cta-b.is-primary:hover::after { transform: translateX(120%); }
    .v2x.dcx .dcx-cta-b.is-primary:hover .dcx-cta-b-arrow { transform: translateX(3px); background-color: rgba(255, 255, 255, .3); }

    .v2x.dcx .dcx-cta-b.is-ghost:hover {
        transform: translateY(-2px);
        border-color: var(--brand-blue);
        color: var(--brand-blue-dark, #1B5BB5);
        text-decoration: none;
        box-shadow: 0 12px 24px -12px rgba(54, 128, 237, .4);
    }

    body.theme-dark .v2x.dcx .dcx-cta-b.is-ghost:hover { border-color: var(--brand-blue-light); color: var(--brand-blue-light); }

    .v2x.dcx .dcx-cta-chip:hover {
        transform: translateY(-2px);
        border-color: var(--brand-blue);
        color: var(--brand-blue-dark, #1B5BB5);
        text-decoration: none;
        box-shadow: 0 10px 20px -12px rgba(54, 128, 237, .5);
    }

    .v2x.dcx .dcx-cta-chip:hover .dcx-cta-chip-ico { background-color: var(--brand-blue); color: #fff; }
    .v2x.dcx .dcx-cta-chip:hover .dcx-cta-chip-n   { background-color: rgba(54, 128, 237, .14); color: var(--brand-blue-dark, #1B5BB5); }

    body.theme-dark .v2x.dcx .dcx-cta-chip:hover { border-color: var(--brand-blue-light); color: var(--brand-blue-light); }
    body.theme-dark .v2x.dcx .dcx-cta-chip:hover .dcx-cta-chip-n { color: var(--brand-blue-light); }
}

.v2x.dcx .dcx-cta-b:focus-visible,
.v2x.dcx .dcx-cta-chip:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(54, 128, 237, .35); }
.v2x.dcx .dcx-cta-b:active, .v2x.dcx .dcx-cta-chip:active { transform: scale(.97); }

/* ── Responsive ───────────────────────────────────────────────────────── */
@media (max-width: 899.98px) {
    .v2x.dcx .dcx-cta { grid-template-columns: 1fr; gap: 26px; }
    .v2x.dcx .dcx-cta-copy { align-items: center; text-align: center; }
    .v2x.dcx .dcx-cta-row, .v2x.dcx .dcx-cta-quick { justify-content: center; }
    .v2x.dcx .dcx-cta-art { padding-top: 6px; }
    .v2x.dcx .dcx-cta-deck { height: 214px; }
}

@media (max-width: 575.98px) {
    .v2x.dcx .dcx-cta { padding: 24px 16px 22px; border-radius: 22px; }
    .v2x.dcx .dcx-cta-p { font-size: 14.5px; }
    .v2x.dcx .dcx-cta-b { padding: 11px 18px; font-size: 14px; }
    .v2x.dcx .dcx-cta-quick-lbl { width: 100%; text-align: center; margin: 0 0 2px; }
    .v2x.dcx .dcx-cta-fcard { width: 92%; }
    .v2x.dcx .dcx-cta-ring { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .v2x.dcx .dcx-cta-orb, .v2x.dcx .dcx-cta-ring, .v2x.dcx .dcx-cta-caret, .v2x.dcx .dcx-cta-hit-dot::after { animation: none; }
    .v2x.dcx .dcx-cta-fcard, .v2x.dcx .dcx-cta-search, .v2x.dcx .dcx-cta-b, .v2x.dcx .dcx-cta-chip,
    .v2x.dcx .dcx-cta-accent::after, .v2x.dcx .dcx-cta-b.is-primary::after { transition: none; }
    .v2x.dcx .dcx-cta-accent::after { transform: scaleX(1); opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   §DCXRESP — the responsive ladder
   ---------------------------------------------------------------------------
   Steps match the base sheet's (1180 / 980 / 820 / 640 / 420) so a viewport
   that reflows the hero reflows this page's bands in the same breath.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 1180px) {
    .v2x.dcx .dcx-spotgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
    .v2x.dcx .dcx-grid     { grid-template-columns: repeat(auto-fill, minmax(min(100%, 214px), 1fr)); gap: 16px; }

    /* The medal shrinks with the plate it is notched onto — see §DCXRESP's
       980px step for the plate itself. It is never hidden: at two-up and at
       one-up the cards are WIDER than at three-up, so there is more room for
       it here, not less. */
    .v2x.dcx .dcx-spot-rank { top: 12px; inset-inline-start: 12px; }
}

@media (max-width: 980px) {
    .v2x.dcx .dcx-spot      { padding: 20px 18px 18px; }
    .v2x.dcx .dcx-spot-ico  { width: 48px; height: 48px; border-radius: 14px; }
    .v2x.dcx .dcx-spot-ico svg { width: 23px; height: 23px; }
    .v2x.dcx .dcx-spot-nm   { font-size: 17px; margin-top: 14px; }
}

@media (max-width: 820px) {
    .v2x.dcx .dcx-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 196px), 1fr)); gap: 14px; }

    .v2x.dcx .dcx-bar { padding: 11px 12px; gap: 10px; }
    .v2x.dcx .dcx-bar-count { font-size: 13px; }
    .v2x.dcx .dcx-bar-count b { font-size: 15px; }

    .v2x.dcx .dcx-lgroup { scroll-margin-top: 74px; }
    .v2x.dcx .dcx-lgroup + .dcx-lgroup { margin-top: 26px; }
}

@media (max-width: 640px) {
    /* One column for the spotlight: at 320px min the two-up would be 150px
       wide, which is narrower than the logo stack it has to carry. */
    .v2x.dcx .dcx-spotgrid { grid-template-columns: 1fr; gap: 14px; }

    /* Two-up for the small tiles all the way down. `.dir-cat-card` is a
       portrait tile with a 3-line description clamp, so a single column of
       them is a very long scroll for very little information. */
    .v2x.dcx .dcx-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

    /* The toolbar stacks: the count reads first, the control gets the full
       row so both segments keep their labels rather than truncating. */
    .v2x.dcx .dcx-bar { flex-direction: column; align-items: stretch; }
    .v2x.dcx .dcx-seg { width: 100%; }
    .v2x.dcx .dcx-seg-b { flex: 1 1 0; justify-content: center; }

    .v2x.dcx .dcx-az { gap: 5px; margin-bottom: 18px; }
    .v2x.dcx .dcx-az-l { min-width: 30px; height: 30px; font-size: 12.5px; }

    .v2x.dcx .dcx-spot-desc { -webkit-line-clamp: 3; min-height: 0; }
    .v2x.dcx .dcx-tagcloud { gap: 8px; }
    .v2x.dcx .dcx-tag { padding: 8px 8px 8px 12px; font-size: 13px; }
}

@media (max-width: 420px) {
    /* Single column at last. Two 150px tracks cannot hold "AI Transcription &
       Subtitles" on fewer than four lines. */
    .v2x.dcx .dcx-grid { grid-template-columns: 1fr; }

    .v2x.dcx .dcx-spot { padding: 18px 16px 16px; }
    .v2x.dcx .dcx-spot-nm { font-size: 16.5px; }

    /* The foot wraps rather than squeezing the CTA out of its label. */
    .v2x.dcx .dcx-spot-foot { flex-wrap: wrap; gap: 10px; }
    .v2x.dcx .dcx-spot-go { flex: 1 1 auto; justify-content: center; }

    .v2x.dcx .dcx-lhead-n { display: none; }
    .v2x.dcx .dcx-cta-row { flex-direction: column; align-items: stretch; }
    .v2x.dcx .dcx-cta-b { justify-content: center; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §DCXMOTION — reduced motion
   ---------------------------------------------------------------------------
   Transforms and transitions go; COLOUR and shadow changes stay, because they
   are what tells a reader which card is under the pointer. Removing those too
   is how a reduced-motion page loses its hover affordance entirely.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
    .v2x.dcx .dcx-spot,
    .v2x.dcx .dcx-spot::after,
    .v2x.dcx .dcx-spot-ico,
    .v2x.dcx .dcx-spot-av,
    .v2x.dcx .dcx-spot-go-arr,
    .v2x.dcx .dcx-seg-b,
    .v2x.dcx .dcx-az-l,
    .v2x.dcx .dcx-tag,
    .v2x.dcx .dcx-cta-b,
    .v2x.dcx .dcx-empty-btn {
        transition-property: background-color, color, border-color, box-shadow, opacity;
        transform: none !important;
    }

    .v2x.dcx .dcx-spot:hover,
    .v2x.dcx .dcx-spot:hover .dcx-spot-av,
    .v2x.dcx .dcx-spot:hover .dcx-spot-ico,
    .v2x.dcx .dcx-tag:hover,
    .v2x.dcx .dcx-az-l:hover,
    .v2x.dcx .dcx-cta-b:hover { transform: none !important; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   §CHX — the eight module hubs (2026-09-17)
   /glossary, /browser-extensions, /ai-projects, /ai-skills, /workflows,
   /gpts, /prompts, /templates + /categories all wear this sheet through
   App\Http\Livewire\Public\V2\CategoryHub. Two things differ from the
   directory hubs and they live here: a family card's rows can be ITEMS
   (logo, name, no count) rather than subcategories, and a peek that is not
   showing everything ends in a "+N more" tail row.
   ═══════════════════════════════════════════════════════════════════════════ */

/* An item's logo in the row slot: white plate so a transparent mark reads on
   both themes, the tone line as its edge, the image inset like the spotlight
   stack's. */
.v2x.dcx .dcx-fam-lico.is-img {
    overflow: hidden;
    background-color: #fff;
    border: 1px solid var(--fam-line);
}

.v2x.dcx .dcx-fam-lico.is-img img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 3px;
}

body.theme-dark .v2x.dcx .dcx-fam-lico.is-img { background-color: rgba(255,255,255,.92); }

/* An item with no logo: its initial on the tone plate. */
.v2x.dcx .dcx-fam-lico.is-txt {
    font-size: 12px;
    font-weight: 800;
    letter-spacing: .02em;
    line-height: 1;
}

/* The tail row's "+N" chip. Muted rather than toned: it is the rest of the
   list, not one more entry in it. */
.v2x.dcx .dcx-fam-lico.is-more {
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .01em;
    background-color: rgba(100, 116, 139, .14);
    color: var(--v2-muted);
}

body.theme-dark .v2x.dcx .dcx-fam-lico.is-more { background-color: rgba(148, 163, 184, .18); }

.v2x.dcx .dcx-fam-tail .dcx-fam-ltitle {
    color: var(--v2-muted);
    font-weight: 600;
}

.v2x.dcx .dcx-fam-tail a:hover .dcx-fam-ltitle,
.v2x.dcx .dcx-fam-tail a:focus-visible .dcx-fam-ltitle { color: var(--fam-ink); }

/* A row without a count keeps its title on one line and lets the arrow sit
   where the count would have. */
.v2x.dcx .dcx-fam-links a > .dcx-fam-ltitle:nth-last-child(2) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A Font Awesome glyph in a plate — HubIcon's last resort for a name with no
   Lucide twin — sized to the SVG it stands in for. */
.v2x.dcx .dcx-fam-ico i,
.v2x.dcx .dcx-spot-ico i,
.v2x.dcx .dcx-hh-tile > i { font-size: 20px; line-height: 1; }
.v2x.dcx .dcx-fam-lico i  { font-size: 12px; line-height: 1; }
