/* ============================================================================
   AIToolsay — /news and /blog listing DELTA
   Scope: .v2x.nwx (news) · .v2x.blx (blog)
   ----------------------------------------------------------------------------
   /news and /blog were rebuilt on 2026-08-26 on /ai-directory's design
   system, to the recipe /guides was rebuilt to on 2026-08-14. Both wear FOUR
   sheets, in this order, and the order is load-bearing:

     custom.*.css
       -> public-partials-styles.css      (the .v2x TOKEN layer)
       -> v2-public-directory-listing.css (the .dir-* design, SHARED — an edit
                                           there reaches twelve public pages)
       -> public-guides.css               (the SHARED listing delta: breadcrumb
                                           strip, active-filter chips, the
                                           .gdx-fact meta line, the card line,
                                           the is-busy dim. All three wear the
                                           `gdx` class to reach it.)
       -> public-feed-listing.css         (this file — what is genuinely new)

   WHY THIS FILE IS SHORT, AND MUST STAY SHORT.
   Almost everything these three need already exists two sheets up. The
   temptation is to re-declare a `.dir-*` rule here to "fix" it; do not. If the
   directory is wrong it is wrong on twelve pages and belongs upstream. The
   only thing that belongs here is what a NEWS, BLOG or STORY card needs and a
   tool card does not.

   RULE: every colour rule needs a dark twin. The convention in the shared
   sheet is `body.theme-dark .v2x .x`, so the twin here is
   `body.theme-dark .v2x.nwx .x` — one specificity step higher, which is what
   makes it win against the shared dark rule it is paired with.
   Dark tokens resolve to: --white:#171922 · --v2-bg:#0E0F14 · --v2-ink:#ECEDF3
   · --v2-muted:#9CA2B3. Compose alpha against those, not against black, or
   every measured ratio is wrong.
   ========================================================================== */


/* ============================================================================
   §THUMB — RETIRED 2026-08-26
   ----------------------------------------------------------------------------
   This block re-sized the image inside the directory's 66px/52px square plate
   (`.dir-tc-logo img` / `.dir-lc-logo img`, which the shared sheet sets to
   60%/70% `contain` for a tool LOGO) up to `100% cover`, so a press photo
   filled the plate instead of floating in it as a postage stamp.

   Both halves are gone because the plate is gone. Cards now open with a
   full-width 16:9 `.gdx-cover` band and rows carry a landscape
   `.dir-lc-logo.gdx-rowcover` — see §COVER and §ROWMEDIA in public-guides.css,
   which is where they belong now that all THREE pages (/guides too) share the
   treatment rather than only the two feed pages.

   The `.nwx-thumb` / `.blx-thumb` classes are no longer emitted by any partial.
   ========================================================================== */

/* ============================================================================
   §BYLINE — the author line on a blog row

   A guide has no author on its card; a post does, and the byline is a LINK to
   that author's other posts. `.gdx-fact.is-link` upstream already paints a
   linked fact, so this only handles the avatar that sits in front of it.
   ========================================================================== */
.v2x.blx .blx-byline      { display: inline-flex; align-items: center; gap: 6px; }
.v2x.blx .blx-byline img  { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; display: block; flex: 0 0 auto; box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .12); }
body.theme-dark .v2x.blx .blx-byline img { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14); }


/* ============================================================================
   §TAGROW — the tag strip under a blog card

   `pages.tags` is a free-text list on the TRANSLATION row, not a taxonomy, so
   these are labels rather than links: there is no /blog/tag/{slug} route to
   send a reader to, and minting one out of a free-text string is how a listing
   ends up full of 404s. They earn their place by telling a reader what a post
   covers before they open it.
   ========================================================================== */
.v2x.blx .blx-tags        { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; }
.v2x.blx .blx-tag         { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; background: rgba(15, 23, 42, .05); color: var(--v2-muted); font-size: 10.5px; font-weight: 700; letter-spacing: .01em; line-height: 1.6; white-space: nowrap; }
body.theme-dark .v2x.blx .blx-tag { background: rgba(255, 255, 255, .07); color: var(--v2-muted); }


/* ============================================================================
   §BUSY — `wire:loading.class="is-busy"` on the results grid

   public-guides.css defines this for `.v2x.gdx`, which both pages wear,
   so the grid dim already works. Repeated here ONLY for `.dir-lx` under
   `.nwx`/`.blx` so the rule survives if a future page drops the `gdx`
   class — it is idempotent with the upstream one, not a competing value.

   ⚠ Do not measure this in a CDP-driven tab: a hidden tab freezes every
     animated property, so `opacity` reads 1 while `pointer-events` applies.
     Strip the transition first, or instrument the call.
   ========================================================================== */
.v2x.nwx .dir-cards.is-busy, .v2x.nwx .dir-lx.is-busy,
.v2x.blx .dir-cards.is-busy, .v2x.blx .dir-lx.is-busy {
    opacity: .45;
    filter: saturate(.6);
    pointer-events: none;
    transition: opacity .18s ease, filter .18s ease;
}

@media (prefers-reduced-motion: reduce) {
    .v2x.nwx .dir-cards.is-busy, .v2x.nwx .dir-lx.is-busy,
    .v2x.blx .dir-cards.is-busy, .v2x.blx .dir-lx.is-busy { transition: none; }
}


/* ============================================================================
   §FLAG — the inline badge the guides row emits but no sheet defines

   `.gdx-flag` is rendered by `livewire/public/guides/_dir-row.blade.php` for
   its "Updated" badge and has NO rule in ANY sheet in the stack, so it prints
   as bare inline text. The news and blog rows deliberately use `.dir-tc-pill`
   instead. Defined here anyway, scoped to these three pages only, so a row
   copied across from /guides degrades to something deliberate rather than to
   unstyled text. Fixing it for /guides itself is an upstream change to
   public-guides.css and is NOT made here — it would repaint a page this pass
   was not asked to touch.
   ========================================================================== */
.v2x.nwx .gdx-flag, .v2x.blx .gdx-flag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(16, 185, 129, .12);
    color: #047857;
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .02em;
    line-height: 1.6;
    white-space: nowrap;
}
.v2x.nwx .gdx-flag svg, .v2x.blx .gdx-flag svg { width: 11px; height: 11px; flex: 0 0 auto; }
body.theme-dark .v2x.nwx .gdx-flag,
body.theme-dark .v2x.blx .gdx-flag { background: rgba(16, 185, 129, .18); color: #6EE7B7; }


/* ============================================================================
   §GPSBTN — MOVED 2026-08-26 to public-guides.css §TBRESP-GPS
   ----------------------------------------------------------------------------
   The Google "Add as a preferred source" badge used to be styled here, scoped
   `.v2x.nwx` / `.v2x.blx`. /guides carries the same badge now and does NOT load
   this sheet, so a second copy would have been the only way to dress it — and
   two copies of a third-party mark is how the two drift apart.

   It lives in the shared delta instead, under `.v2x.gdx`, which all three pages
   already link. The phone layout moved with it: the plate and ring are now on
   the `img` rather than the `a`, because below 520px the link is stretched to a
   full-width row so the badge can centre in it.
   ========================================================================== */


/* ============================================================================
   §NOPAGER — REMOVED 2026-08-26 (deliberately, on request)
   ----------------------------------------------------------------------------
   A rule here used to hide the injected Pages / Infinite switch on a listing
   that has only one page:

       .v2x.nwx .dir-main:not(:has(.dir-pg)) [data-dir-loadmode-group] { … }

   The reasoning was that a switch which cannot change anything is worse than
   no switch: /news has 5 stories against a 12 per-page setting and /blog has
   2 posts against 6, so neither paginates today and picking "Infinite" has
   nothing to fetch.

   It is gone because the control is wanted on both surfaces regardless — these
   two should carry the same toolbar as the other nineteen verticals, and the
   moment either catalogue outgrows its page size the switch is already there
   and already correct. §LOADMODE itself was fixed the same day (it used to
   stop after one appended page on EVERY vertical), so Infinite is now
   genuinely functional here rather than present-but-broken.

   ⚠ DO NOT RE-ADD THIS WITHOUT ASKING. Hiding the control is a product call,
     not a bug fix, and it has already been made the other way.
   ========================================================================== */


/* ============================================================================
   §CHIPSLOT — the active-filter row is ALWAYS in the DOM (2026-08-26)
   ----------------------------------------------------------------------------
   It used to be wrapped in `@if (count($chips))`, so the element appeared the
   moment a filter went on and vanished when it came off. That made its slot
   MOVE, and morphdom has to reconcile a moving slot:

     • unkeyed, it paired the outgoing results <div> with the incoming chip row,
       recycled the node and stripped its `wire:loading.class` — Livewire then
       threw on `null.split(' ')` in startLoading() and ABORTED the DOM patch,
       so filters applied server-side with no repaint;
     • keyed, it stopped recycling but started RELOCATING — the chip row ended
       up rendered BELOW the results, showing stale chips.

   Both disappear if the node simply never moves. The element is now permanent
   and only its CONTENT is conditional; this class hides it when it is empty.

   ⚠ `:empty` would NOT work here — Blade leaves indentation whitespace inside
     the div, and a whitespace text node defeats `:empty`. The state is decided
     server-side and shipped as a class instead, which is also what keeps the
     first paint correct with no flash.
   ========================================================================== */
.v2x.nwx .gdx-chiprow.is-hidden,
.v2x.blx .gdx-chiprow.is-hidden { display: none; }
