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

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

     §HERO   hero tiles carrying a monogram instead of a product logo
     §CAP    the capability row — what a GPT can DO once it is open
     §RAIL   the trending rail's access chip, in the rail's tight row
     §GRID   category / collection cards and the featured / popular shelves,
             laid out full-bleed without inheriting a column count sized for
             the results grid's narrower centre column
     §BUSY   the dim-while-filtering state the directory keys on a class it
             does not define
     §HERE   the "you are here" marker on the category rail

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

   ⚠ TONE VOCABULARY IS THE DIRECTORY'S, NOT A NEW ONE. Before adding a
   `data-tone` value, check it exists in the directory sheet for THAT
   component — an unmatched tone falls back to blue SILENTLY, with nothing
   reporting an error. Verified ranges as of 2026-08-14, read off the
   DEPLOYED sheet rather than remembered:
     .dir-hh-stat      12  amber blue cyan emerald green indigo orange pink
                           rose slate teal violet
     .dir-tc-pill      10  amber blue cyan emerald indigo orange rose slate
                           teal violet
     .dir-cat-card      8  amber blue cyan emerald indigo orange rose violet
     .dir-fx-dot        6  amber blue cyan emerald rose violet   ← NO indigo
     .dir-why-card      6  amber blue cyan emerald rose violet
     .dir-ts-ic /
     .dir-ts-opt-ic     5  amber blue cyan indigo violet         ← the tight one

   Two of those bit during this build and are worth stating plainly:

   · `.dir-ts-ic` has five tones and Settings ships SIX sort options, so one
     pair has to share. `newest` and `updated` share cyan — both answer "how
     recent", so the tone groups them correctly and the icon and label do the
     separating. See the note beside $sortMeta in listing.blade.php.
   · `.dir-fx-dot` has no `indigo`, unlike almost every other component here.
     The Builder facet was written with one and rendered in the fallback blue,
     indistinguishable from the Category group's dot directly above it, with
     nothing anywhere reporting it. It is `rose` now.

   Dark mode: the directory sheet keys dark off `body.theme-dark`. Every rule
   here that sets a colour declares its dark twin the same way, in the same
   block, so a light-only addition cannot slip through review. The one
   deliberate exception is documented where it occurs (§HERO).
   ══════════════════════════════════════════════════════════════════════════ */


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

   ⚠ THESE ARE NOT THE BRAND HUES AT FULL STRENGTH, AND MUST NOT BE "FIXED"
   BACK TO THEM. The palette's display values (#3680ED, #7C3AED, #0F9F6E,
   #D97706) were measured on /browser-extensions against WHITE at the
   gradient's lightest stop — where a gradient has to be measured, not at its
   midpoint — and came out at blue 2.82:1 · violet 3.63:1 · emerald 2.48:1 ·
   amber 2.12:1. Three of the four fail even the 3:1 large-text floor, and the
   monogram is the tile's only content. A saturated fill reads as "strong";
   saturation is not luminance, which is exactly why this needs measuring.

   The four fills below are that page's corrected set, reused verbatim rather
   than re-derived: each hue scaled toward black until white clears 4.5:1 at
   BOTH stops — a gradient has to pass at every stop, not on average.
   Re-measured here rather than copied on trust, white-on-fill, in the order
   the gradient declares them:

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

   The worst case is 4.50:1 against a 4.5:1 floor, so there is no headroom
   here at all: nudging any of these eight values lighter fails AA.

   ONE SET SERVES BOTH THEMES, and that is a measured result rather than an
   omission: the same fills sit at 4.23–5.36:1 against the light hero ground
   (#F6F8FC) and 3.29–4.16:1 against the dark one (#0B1220), so the plate
   clears the 3:1 non-text floor either way. A `body.theme-dark` twin would
   change numbers that already pass in both directions. The header's "every
   colour declares its dark twin" rule is satisfied by this note: the twin was
   considered and is deliberately absent, not forgotten. */

.v2x .dir-hh-tile .gptt-mono{display:grid;place-items:center;width:100%;height:100%;
    border-radius:inherit;font:700 20px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:-.02em}

.v2x .dir-hh-tile[data-tone="blue"]    .gptt-mono{background:linear-gradient(145deg,#3174D8,#4677BD);color:#fff}
.v2x .dir-hh-tile[data-tone="violet"]  .gptt-mono{background:linear-gradient(145deg,#7C3AED,#885ED5);color:#fff}
.v2x .dir-hh-tile[data-tone="emerald"] .gptt-mono{background:linear-gradient(145deg,#0D875D,#258563);color:#fff}
.v2x .dir-hh-tile[data-tone="amber"]   .gptt-mono{background:linear-gradient(145deg,#B36205,#A06C1F);color:#fff}

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


/* ═══ §CAP — capability row ════════════════════════════════════════════════
   What a GPT can do once it is open: browsing, image generation, code
   interpreter, file uploads, canvas, voice, actions, memory. This is the
   module's editorial angle and the thing the GPT store itself gives you no
   way to filter on, so it gets a slot of its own on the card rather than
   being folded into the meta row.

   DELIBERATELY NEUTRAL, NOT TONED. The meta row directly below already
   carries up to three toned pills (Official / Editor's Pick / access level).
   Four more colours above them turns the card into a paint chart and, worse,
   makes the two rows look like one taxonomy when they answer different
   questions. Neutral here reads as "specification"; toned below reads as
   "status".

   ICON **AND** LABEL. Eight glyphs with no text is a legend the visitor does
   not have, and the label is the same string the facet rail filters on — so
   the card and the filter teach each other.

   Contrast, measured not eyeballed. Ink is --v2-muted, surface is the tint
   below, both composited over the card ground the directory sheet declares
   (#fff light · rgba(28,31,42,.92) over #0E0F14 dark → ≈#1B1E28):
       light  #4A4A5A on #F4F6FA  →  8.03:1
       dark   #9CA2B3 on ≈#262933 →  5.69:1
   Both clear AA for the 11px text by a wide margin, which they need to: this
   is the smallest type on the card. */

.v2x .gptx-caprow{display:flex;flex-wrap:wrap;justify-content:center;gap:5px;
    width:100%;margin:8px 0 2px;padding:0 2px}

.v2x .gptx-cap{display:inline-flex;align-items:center;gap:4px;max-width:100%;
    padding:3px 8px;border-radius:8px;font-size:11px;font-weight:640;line-height:1.45;
    color:var(--v2-muted);background:#F4F6FA;box-shadow:inset 0 0 0 1px rgba(16,24,40,.06);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.theme-dark .v2x .gptx-cap{background:rgba(255,255,255,.05);box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}

.v2x .gptx-cap svg{width:12px;height:12px;flex:0 0 auto;opacity:.85}

/* In the LIST view the capability chips sit inside `.dir-lc-meta`, a row that
   already holds the rating and the pills. They keep the same shape there but
   lose the wrapper's centring, which belongs to the grid card. */
.v2x .dir-lc-meta .gptx-cap{margin:0}

/* The facet rail draws the same glyph beside the label. Sized to the rail's
   text rather than the card's, and never allowed to take the row's width from
   the label it annotates. */
.v2x .gptx-capico{display:inline-flex;align-items:center;justify-content:center;
    width:16px;height:16px;flex:0 0 auto;margin-inline-end:7px;opacity:.7}
.v2x .gptx-capico svg{width:100%;height:100%}
/* Inside a checked row the label goes to the accent ink; the glyph follows it
   rather than staying grey, or the row reads as half-selected. */
.v2x .dir-fx-chk.is-on .gptx-capico{opacity:1}


/* ═══ §RAIL — access chip in the trending rail ═════════════════════════════
   The directory shows a RATING in this slot. Every row in this catalogue has
   avg_rating 0.00, so a rating slot would print "0.0" five times and call it
   a ranking. The access level is the figure this module actually holds — and
   the one that decides whether a visitor can open the GPT at all.

   The element carries `.dir-tc-pill` as well as this class, so its colour and
   shape come from the directory sheet's ten-tone pill and NOT from a second
   palette defined here. This rule only places it in the rail's tight row.
   That is the whole reason there are no colour declarations in this section:
   a duplicated tone map is a tone map that drifts. */

.v2x .gptx-tr-acc{margin-inline-start:auto;flex:0 0 auto;font-size:10px;padding:2px 7px;
    transition:opacity .2s ease,transform .2s ease}

/* ⚠ IT MUST FADE OUT ON HOVER, and this is the only rule here that is not
   about placement.

   `.dir-tr-arr` is `position:absolute; right:10px; opacity:0` and fades IN on
   row hover; the chip it slides over — the directory's `.dir-tr-rt` — fades
   OUT in the same 200ms, in a rule two lines below it. They share one slot by
   swapping, not by sitting side by side.

   This element is NOT `.dir-tr-rt` (it is `.dir-tc-pill`, so that its colour
   comes from the directory's ten-tone pill rather than from a second palette
   defined here), so it does not inherit that swap. The first version left the
   chip up: hovering any row in the rail painted a blue arrow tile on top of a
   violet pill. Nothing errors, and it only shows up under a pointer.

   Wrapped in `@media (hover:hover)` to match the block it is pairing with —
   on a touch device `:hover` sticks after a tap and the chip would stay
   invisible on the row the visitor last touched. */
@media (hover:hover){
    .v2x .dir-tr-row:hover .gptx-tr-acc{opacity:0;transform:translateX(-6px)}
}

/* No width-based hiding. The three-column lab collapses at 1500px — below
   that the rail is full width and the chip has room to spare. Above it the
   rail column is 268px and `.dir-tr-nm` clamps to two lines, which is the
   directory's own answer to the same squeeze. A `display:none` here would
   have removed the row's only datum at exactly the widths where it fits. */


/* ═══ §GRID / §SHELF — CARD WIDTH IS THE THING BEING MATCHED ═══════════════
   Both of the containers below hold cards that ALSO appear inside
   `.dir-lab > .dir-g`, the directory's three-column results grid. That grid
   is `236px | 1fr | 268px`, so on a 1600px shell the centre column is about
   1056px and `.dir-cards`' four tracks make each card ≈252px.

   These containers are FULL-BLEED — there is no facet rail or trending rail
   beside them. Inheriting the same "four columns" would make each card ≈385px:
   the same component, 50% wider, a few hundred pixels above its twin. Column
   COUNT is not the thing to keep equal across the two contexts; card WIDTH is.

   So both use `auto-fit` with a track RANGE and a centred row:
     · auto-fit fits as many tracks as the width allows at the minimum, then
       collapses the empty ones — which is what stops three collections from
       sitting in a four-track grid with a hole on the right,
     · the max stops a short row from stretching its cards to fill the shell,
     · `justify-content:center` splits the leftover evenly instead of leaving
       it all at the end,
     · the 1240px cap is the site's `--container` width, so a full row lands at
       roughly the same card size as one in the results grid.

   No explicit breakpoints: a track range plus auto-fit already reflows at
   every width, and the four @media steps this replaced could only ever be a
   second, drifting copy of what the range says once.

   `.dir-cat-card` needs no change to sit here — it carries no width of its
   own, and its `scroll-snap-align` is inert outside a snap container. */

/* Category and collection cards. Range floor matches the directory rail's own
   `minmax(220px,1fr)`, so a category card is the same size on both pages. */
.v2x .gptx-catgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,260px));
    justify-content:center;gap:18px;max-width:1240px;margin-inline:auto}
@media (max-width:820px){ .v2x .gptx-catgrid{gap:14px} }
@media (max-width:680px){ .v2x .gptx-catgrid{grid-template-columns:minmax(0,1fr);gap:12px} }

/* GPT cards on the featured / popular shelves. The floor is 240px rather than
   220px because `.dir-tc` carries a 66px logo plate above a two-line clamp —
   it reads cramped below that, where `.dir-cat-card` does not. */
.v2x .gptx-shelf .dir-cards{grid-template-columns:repeat(auto-fit,minmax(240px,300px));
    justify-content:center;max-width:1240px;margin:4px auto 0}
@media (max-width:680px){ .v2x .gptx-shelf .dir-cards{grid-template-columns:minmax(0,1fr)} }
.v2x .gptx-shelf-more{display:flex;justify-content:center;margin-top:26px}
/* `.dir-tr-more` is built for the rail's full-width footer. In the middle of
   a page it should read as a button, so it stops growing at its content. */
.v2x .gptx-shelf-more .dir-tr-more{width:auto;padding-inline:22px}


/* ═══ §BUSY — dim while filtering ══════════════════════════════════════════
   `wire:loading.class="is-busy"` lands a class that NO sheet in this stack
   defines — /browser-extensions shipped that way and the results grid never
   dimmed. The rule lives here rather than on `.dir-lx`, which is the LIST
   mode's column flexbox and not a general results wrapper.

   `pointer-events:none` matters as much as the opacity: while a filter is in
   flight the rows on screen are the OLD result set, and a click on one of
   them navigates somewhere the visitor did not choose. */

.v2x .gptx-results{transition:opacity .18s ease}
.v2x .gptx-results.is-busy{opacity:.45;pointer-events:none}

/* Reduced motion, for everything this file adds. The directory sheet has its
   own block, but it lists components by name and cannot know about these.

   The rail chip keeps its OPACITY swap: that is not decoration, it is what
   stops the hover arrow being drawn on top of it (§RAIL). Only the 6px slide
   goes. */
@media (prefers-reduced-motion:reduce){
    .v2x .gptx-results,.v2x .gptx-cap{transition:none}
    .v2x .gptx-tr-acc{transition:opacity .01ms linear;transform:none !important}
}


/* ═══ §HERE — "you are here" on the category rail ══════════════════════════
   The rail renders on category pages too (matching /ai-directory), which puts
   the category you are already reading in a row of links to elsewhere.
   Marking it is the difference between a nav aid and a loop.

   `aria-current="page"` is on the element as well; this is the visual half of
   the same statement. The marker is a ring plus a lifted shadow rather than a
   colour change, so it survives a viewer who cannot separate the card's tone
   from its neighbours'. */

.v2x .dir-cat-card.is-current{border-color:var(--dtc-ink,var(--brand-blue));
    box-shadow:0 0 0 1px var(--dtc-ink,var(--brand-blue)),0 1px 2px rgba(16,24,40,.04),0 10px 24px -18px var(--dtc-shadow,rgba(54,128,237,.42))}
body.theme-dark .v2x .dir-cat-card.is-current{box-shadow:0 0 0 1px var(--dtc-ink,var(--brand-blue-light,#60A4F5)),0 1px 2px rgba(0,0,0,.4),0 10px 24px -18px rgba(0,0,0,.65)}


/* ═══ RESPONSIVE ═══════════════════════════════════════════════════════════
   The directory sheet already carries the page's breakpoints. Only the pieces
   defined ABOVE need their own, so this block stays short by construction. */

@media (max-width:820px){
    /* Tablet: the card narrows to a two-up grid and four capability chips
       start wrapping to three lines. Two is enough to say what kind of GPT
       this is; the rest are on the detail page, one tap away. */
    .v2x .dir-tc .gptx-cap:nth-child(n+3){display:none}
}

@media (max-width:680px){
    /* Phone: the card is full width again, so the third chip fits. The row
       stays single-line — `flex-wrap` is still on, but three chips at this
       width do not reach a second line. */
    .v2x .dir-tc .gptx-cap:nth-child(n+3){display:inline-flex}
    .v2x .dir-tc .gptx-cap:nth-child(n+4){display:none}

    /* In the list view the meta row is the first thing to crowd: rating,
       Official, access level and capabilities on one line. The capabilities
       go, because they are the only one of the four that is not a filter the
       visitor is likely to have just used. */
    .v2x .dir-lc-meta .gptx-cap{display:none}
}
