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

   ⚠ AN EDIT TO THE DIRECTORY SHEET NOW REACHES SEVEN PAGES — /ai-directory,
     /browser-extensions, /gpts, /workflows, /ai-projects, /ai-courses and
     /glossary. Check all seven.

   LOAD ORDER (load-bearing):
     custom.*.css → public-partials-styles.css (the `.v2x` TOKEN layer) →
     v2-public-directory-listing.css → THIS FILE.
   The token layer is not optional: `linear-gradient(var(--brand-blue),…)`
   with the var unset is INVALID CSS, not a fallback colour.

   ⚠ `--v2-surface`, `--v2-soft`, `--v2-ink-2` and `--v2-ink-3` are NOT
   declared anywhere in the stack — grep the token layer, it has --v2-ink,
   --v2-line, --v2-muted, --v2-bg and no others in that family. So every
   `var(--v2-ink-2,#475569)` below paints its FALLBACK in BOTH themes, which is
   why each is paired with an explicit `body.theme-dark` twin. Removing a twin
   does not fall back to a dark value; it leaves slate-on-slate. This is the
   same arrangement /ai-projects and /ai-courses use — do not "tidy" it.

   This file holds ONLY what a GLOSSARY needs and a catalogue of tools has no
   concept of:

     §PLATE   the icon plate — an entry has no logo; it inherits its area's
              icon + colour, and the accent is the PLATE, never the glyph
     §AZ      the A–Z letter index — the control that makes this a glossary
     §ABBR    the acronym chip on the card
     §DEF     the definition body: this card leads with prose, not with metrics
     §CHIP    the active-filter chip row above the results
     §BUSY    the dim-while-filtering state the directory keys on a class it
              does not define anywhere in the stack
     §HERE    the "you are here" marker on the areas rail
     §ACRO    the alias decoder — gl_synonyms rendered as a lookup table
     §ABOUT   the hub pages' about panel
     §CATGRID /glossary/categories — the same cards, a browse layout
     §IOS     the 16px floor that stops iOS zooming on search focus
     §RESP    the handful of responsive fixes the above need

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

   ⚠ NO `:has()` ANYWHERE — zero precedent in the directory sheet, and Safari
   <15.4 drops the entire selector rather than the unsupported part.
   ══════════════════════════════════════════════════════════════════════════ */


/* ═══ §HIDE — per-band responsive visibility ════════════════════════════════
   `GlSection::hiddenClasses()` emits `glp-hide-desktop|tablet|mobile` from the
   Page Editor's "visible on" checkboxes. Those class NAMES belong to the old
   `.glp-` kit, and that kit is not loaded here — so without this block the
   switch would land a dead class and a band an editor hid on mobile would
   render anyway, with nothing reporting the mistake.

   The names are kept rather than renamed because the DETAIL page still emits
   them from the same PHP method; forking the method to emit `.glx-hide-*` here
   would leave two vocabularies for one setting.

   Breakpoints are the OLD kit's (1200 / 768), not the directory sheet's ladder
   — they have to be, or a band hidden "on tablet" would cover a different
   range on this page than on /glossary/{slug}. */
@media (min-width:1200px){ .v2x.glx .glp-hide-desktop{display:none !important} }
@media (min-width:768px) and (max-width:1199.98px){ .v2x.glx .glp-hide-tablet{display:none !important} }
@media (max-width:767.98px){ .v2x.glx .glp-hide-mobile{display:none !important} }


/* ═══ §PLATE — the icon plate ═══════════════════════════════════════════════
   A glossary entry carries no logo and, on this install, no per-entry
   `icon_name` either (0 of 32 rows have one). It inherits its AREA's icon and
   colour — a truer mark than the first letter of the term, and it makes the
   grid readable by subject at a glance.

   ⚠ THE ACCENT IS THE PLATE, NEVER THE GLYPH, AND THIS MUST NOT BE
   "SIMPLIFIED" BACK. Measured over all EIGHT accents stored on gl_categories,
   as glyph ink on white: worst #0891B2 at 3.68:1, i.e. under AA for the
   14px-equivalent glyph that is the plate's only content. Saturation is not
   luminance, which is why an admin-supplied hue can never be trusted as ink.

   A white scrim painted OVER the accent needs no per-hue table: whatever the
   hue, the plate lands light and the glyph is drawn in the sheet's own ink.
   Measured across the same eight: 15.62–16.60:1 light. Dark mode swaps to the
   row's stored `color_dark` twin under a dark scrim: 10.47–11.96:1.

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

   ⚠ ANY AUDIT THAT READS `backgroundColor` WILL MISREAD THIS. The shorthand
   sets background-image (the scrim) AND background-color (the raw accent
   underneath); what is painted is the composite. */
.v2x.glx .glx-plate{
  background:linear-gradient(rgba(255,255,255,.88),rgba(255,255,255,.88)),var(--glx-accent,#3680ED);
  color:var(--v2-ink);
  display:grid;place-items:center;overflow:hidden}
body.theme-dark .v2x.glx .glx-plate{
  background:linear-gradient(rgba(16,20,28,.82),rgba(16,20,28,.82)),var(--glx-accent-dark,var(--glx-accent,#3680ED));
  color:#EAF0FA}

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

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

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


/* ═══ §AZ — the A–Z letter index ════════════════════════════════════════════
   The one control that makes this page a glossary rather than a directory.
   It is a FILTER, not an anchor list: pressing R re-queries the catalogue, so
   the letter state round-trips through the URL and survives a share.

   Counts are honest and pre-computed with the letter itself lifted out of the
   filter set (GlCatalog::azCounts), so a letter's count is what pressing it
   will actually return. A letter with none is kept visible but inert: hiding
   it makes the row reflow every time a filter changes, and the gap is itself
   information — "nothing here starts with J".

   ⚠ The ACTIVE fill is --brand-blue-dark (#2060C0), NOT --brand-blue
   (#3680ED). White on #3680ED measures 3.84:1 — under AA for a 13px bold
   glyph. On #2060C0 it is 6.01:1. */
/* ⚠ NO max-width. `--dir-shell` is NOT declared anywhere in the stack, so
   `var(--dir-shell,1280px)` paints the 1280px FALLBACK — and the bands around
   this one (.dir-lab, .dir-cat-sect, .dir-why-sect) have no cap at all. On a
   2560px screen that rendered the A–Z block 1280px wide inside a 1872px
   column: measured in-browser, visibly inset from everything above and below
   it. The horizontal padding matches .dir-lab (0 4px) so the two line up. */
.v2x.glx .glx-az{
  margin:0 auto;padding:clamp(18px,3vw,30px) 4px 0}
.v2x.glx .glx-az-box{
  background:var(--v2-surface,#fff);
  border:1px solid var(--v2-line,#E2E8F0);
  border-radius:18px;
  padding:clamp(13px,2vw,18px);
  display:flex;flex-wrap:wrap;align-items:center;gap:clamp(10px,2vw,18px)}
.v2x.glx .glx-az-lbl{
  display:inline-flex;align-items:center;gap:8px;
  font-size:.72rem;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--v2-ink-3,#64748B);flex:0 0 auto;line-height:1}
.v2x.glx .glx-az-lbl svg{width:15px;height:15px;color:var(--brand-blue,#3680ED)}
/* A GRID, not a wrapping flex row. 26 letters cannot fit one line below
   ~1100px, so the row wraps regardless; `auto-fit` + `1fr` makes every wrapped
   line full-width and evenly divided instead of leaving a ragged last row that
   reads as a rendering fault. The track FLOOR is what controls how many rows
   the block takes:
     320px viewport → 232px of track → 6 columns → 5 rows
     390px          → 302px          → 8 columns → 4 rows
     820px+         → the row fits in 1–2 lines
   34px is above the 24px minimum target size with room to spare; the 30px
   floor at ≤520px (§RESP) still clears it. */
.v2x.glx .glx-az-row{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(34px,1fr));
  gap:5px;flex:1 1 320px;min-width:0}
/* "All" needs two tracks — its label is a word, not a glyph. */
.v2x.glx .glx-az-row .is-all{grid-column:span 2}

.v2x.glx .glx-az-k{
  --glx-k:34px;
  display:inline-flex;align-items:center;justify-content:center;
  min-width:var(--glx-k);height:var(--glx-k);padding:0 7px;
  border:1px solid var(--v2-line,#E2E8F0);border-radius:10px;
  background:var(--v2-surface,#fff);
  font-size:.82rem;font-weight:750;line-height:1;
  color:var(--v2-ink-2,#475569);            /* 7.58:1 on white */
  cursor:pointer;text-decoration:none;
  transition:border-color .16s ease,background .16s ease,color .16s ease,transform .16s ease}
.v2x.glx .glx-az-k:hover:not(:disabled){
  border-color:rgba(54,128,237,.45);color:var(--brand-blue-dark,#2060C0);transform:translateY(-1px)}
.v2x.glx .glx-az-k.is-on{
  background:var(--brand-blue-dark,#2060C0);border-color:var(--brand-blue-dark,#2060C0);
  color:#fff;                               /* 6.01:1 */
  box-shadow:0 6px 16px -8px rgba(32,96,192,.75)}
/* A letter with no entries. Disabled controls are exempt from the WCAG text
   minimum, but there are up to five of them in a row here and a row of ghosts
   reads as a rendering fault — so it is held at 4.51:1 rather than greyed to
   the usual ~2.5:1. */
.v2x.glx .glx-az-k:disabled{
  color:#6E7787;background:var(--v2-soft,#F8FAFC);
  border-color:var(--v2-line,#E2E8F0);cursor:default;box-shadow:none}
.v2x.glx .glx-az-k.is-all{min-width:auto;padding:0 6px;font-size:.76rem;letter-spacing:.02em}

body.theme-dark .v2x.glx .glx-az-box{
  background:var(--v2-surface,#141922);border-color:rgba(148,163,184,.16)}
body.theme-dark .v2x.glx .glx-az-lbl{color:#94A3B8}
body.theme-dark .v2x.glx .glx-az-lbl svg{color:#60A4F5}
body.theme-dark .v2x.glx .glx-az-k{
  background:rgba(148,163,184,.08);border-color:rgba(148,163,184,.18);color:#CBD5E1}
body.theme-dark .v2x.glx .glx-az-k:hover:not(:disabled){
  border-color:rgba(96,164,245,.5);color:#BFDBFE}
/* ⚠ DARK FLIPS THE POLARITY. Measured in-browser: white on --brand-blue
   (#3680ED) is 3.84:1 — under AA for a 12px bold glyph, and the same figure
   that made the LIGHT rule use --brand-blue-dark. Going darker is not an
   option on a dark ground, so the fill goes LIGHTER and the ink goes dark:
   #0B1220 on #60A4F5 measures 7.25:1. #60A4F5 is the brand blue's dark twin
   already used across this stack, so the key still reads as "selected, brand". */
body.theme-dark .v2x.glx .glx-az-k.is-on{
  background:#60A4F5;border-color:#60A4F5;color:#0B1220;
  box-shadow:0 6px 16px -8px rgba(96,164,245,.55)}
body.theme-dark .v2x.glx .glx-az-k:disabled{
  color:#7C8798;background:rgba(148,163,184,.05);border-color:rgba(148,163,184,.12)}


/* ═══ §ABBR — the acronym chip ══════════════════════════════════════════════
   Seven of the 32 entries carry an abbreviation and 22 aliases point at them,
   so "RAG" and "CNN" are how a visitor arrives. The chip is monospaced
   because it is a token, not a word — and it is dropped by the blade when the
   abbreviation equals the term rather than printed twice. */
.v2x.glx .glx-abbr{
  display:inline-flex;align-items:center;
  padding:2px 7px;border-radius:6px;
  font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:.68rem;font-weight:700;letter-spacing:.01em;line-height:1.6;
  background:#EFF6FF;color:#1D4ED8;         /* 6.16:1 */
  white-space:nowrap;flex:0 0 auto}
body.theme-dark .v2x.glx .glx-abbr{
  background:rgba(96,164,245,.16);color:#93C5FD}   /* 7.45:1 */

/* On the card the term and its acronym share one baseline row. `min-width:0`
   is what lets the term truncate instead of shoving the chip off the card. */
.v2x.glx .glx-nmrow{
  display:flex;align-items:center;gap:8px;min-width:0;margin:0 0 2px}
.v2x.glx .glx-nmrow .dir-tc-nm{margin:0;min-width:0}


/* ═══ §DEF — the definition body ════════════════════════════════════════════
   The directory's card gives its description one clamped line because the
   product NAME is the payload. Here the DEFINITION is the payload: a visitor
   who can read it on the card never needs to open the entry. So it gets three
   lines and a taller line-height, and the card's fixed metric strip is gone. */
.v2x.glx .dir-tc-desc.glx-def{
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;
  overflow:hidden;font-size:.855rem;line-height:1.62;min-height:calc(.855rem * 1.62 * 3)}
.v2x.glx .dir-lc-desc.glx-def{
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
  overflow:hidden;line-height:1.6}


/* ═══ §CHIP — active-filter chips ══════════════════════════════════════════
   One-tap removal without opening the rail. Taxonomy ids are resolved to
   names in the blade: a chip reading "7" would be worse than no chip. */
.v2x.glx .glx-chips{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  margin:0 0 16px}
.v2x.glx .glx-chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 6px 5px 12px;border-radius:999px;
  background:rgba(54,128,237,.09);border:1px solid rgba(54,128,237,.22);
  font-size:.78rem;font-weight:650;color:#1D4ED8;line-height:1.6}  /* 6.03:1 */
.v2x.glx .glx-chip button{
  display:inline-flex;align-items:center;justify-content:center;
  width:17px;height:17px;border:0;border-radius:50%;cursor:pointer;
  background:rgba(54,128,237,.18);color:inherit;opacity:.75;
  transition:opacity .15s ease,background .15s ease}
.v2x.glx .glx-chip button svg{width:10px;height:10px}
.v2x.glx .glx-chip button:hover{opacity:1;background:rgba(54,128,237,.3)}
.v2x.glx .glx-chip-clear{
  border:0;background:none;cursor:pointer;padding:5px 4px;
  font-size:.78rem;font-weight:650;color:var(--v2-ink-3,#64748B);
  text-decoration:underline;text-underline-offset:3px;
  transition:color .15s ease}
.v2x.glx .glx-chip-clear:hover{color:var(--brand-blue-dark,#2060C0)}
body.theme-dark .v2x.glx .glx-chip{
  background:rgba(96,164,245,.14);border-color:rgba(96,164,245,.3);color:#BFDBFE}  /* 11.01:1 */
body.theme-dark .v2x.glx .glx-chip button{background:rgba(96,164,245,.2)}
body.theme-dark .v2x.glx .glx-chip button:hover{background:rgba(96,164,245,.36)}
body.theme-dark .v2x.glx .glx-chip-clear{color:#94A3B8}
/* --brand-blue-dark is NOT remapped by the token layer's dark block (which
   touches --v2-ink/-muted/-line/-bg, the greys and the accent-softs, and
   nothing in the brand family). Left alone this hover measured 3.19:1 on the
   dark ground; #60A4F5 is 7.41:1 and is the twin the rest of the stack uses. */
body.theme-dark .v2x.glx .glx-chip-clear:hover{color:#60A4F5}


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


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


/* ═══ §ACRO — the alias decoder ═════════════════════════════════════════════
   The one band on this page that could not be borrowed from a sibling module.
   `gl_synonyms` is why searching "LLM" finds "Large Language Model", and the
   rows are real: 22 of them, every one routable to its canonical entry. Only
   aliases whose target is still LIVE are listed — a decoder pointing at a
   withdrawn entry is worse than no decoder.

   Two columns of one row: the alias as a mono token, the canonical term as
   prose, an arrow between them. Reads as a lookup table because it is one. */
.v2x.glx .glx-acro-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));
  gap:10px;max-width:1240px;margin:0 auto}
.v2x.glx .glx-acro{
  position:relative;display:flex;align-items:center;gap:10px;
  padding:10px 13px;border-radius:12px;text-decoration:none;
  background:var(--v2-surface,#fff);border:1px solid var(--v2-line,#E2E8F0);
  transition:border-color .18s ease,box-shadow .18s ease,transform .18s ease}
.v2x.glx .glx-acro:hover{
  border-color:rgba(54,128,237,.4);transform:translateY(-2px);
  box-shadow:0 10px 26px -16px rgba(16,24,40,.4)}
/* ⚠ THE TOKEN WRAPS AND IS NEVER TRUNCATED. It must not be
   `white-space:nowrap` with an ellipsis: most aliases are short (RAG, CoT,
   ConvNet) but the corpus also contains "Reinforcement Learning from Human
   Feedback" — 41 characters, ~290px of 12px mono, which cannot fit one line
   inside a 232–268px track at ANY viewport. Clipping it to "Reinforcement
   Le…" breaks the one job this row has: telling you what the short form
   expands to. So it wraps to as many lines as it needs and the row grows;
   grid equalises the rest of that row.

   ⚠ `break-word`, NOT `anywhere`. They look interchangeable and are not:
   `anywhere` also shrinks the element's MIN-CONTENT width to one character, so
   as a flex item it collapsed to the narrowest thing the row allowed and broke
   three-letter tokens mid-word — "GA/N", "RA/G", "ConvNe/t" were all visible
   in a live screenshot. `break-word` leaves min-content at the longest word
   ("Reinforcement", ~120px measured in DejaVu Sans Mono Bold at 11.5px, and
   the real face is no wider), which sits inside 60% of the narrowest track
   (139px at a 320px viewport). Short tokens therefore never break, and a
   longer word than any in the corpus still breaks rather than pushing the
   page sideways. */
.v2x.glx .glx-acro-k{
  font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:.72rem;font-weight:700;line-height:1.5;
  padding:3px 8px;border-radius:7px;flex:0 1 auto;max-width:60%;
  background:var(--v2-soft,#F1F5F9);color:#334155;   /* 9.45:1 */
  overflow-wrap:break-word}
.v2x.glx .glx-acro-arr{flex:0 0 auto;color:var(--v2-ink-3,#94A3B8);opacity:.8}
.v2x.glx .glx-acro-arr svg{width:14px;height:14px;display:block}
.v2x.glx .glx-acro-nm{
  font-size:.855rem;font-weight:680;color:var(--v2-ink);min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.theme-dark .v2x.glx .glx-acro{
  background:var(--v2-surface,#141922);border-color:rgba(148,163,184,.16)}
body.theme-dark .v2x.glx .glx-acro:hover{border-color:rgba(96,164,245,.45)}
body.theme-dark .v2x.glx .glx-acro-k{
  background:rgba(148,163,184,.12);color:#E2E8F0}    /* 11.69:1 */
body.theme-dark .v2x.glx .glx-acro-arr{color:#7C8798}


/* ═══ §ABOUT — hub about panel ═════════════════════════════════════════════
   Built from the area row's own description / about_intro / about_points, on
   the same card language as the rest of the page. */
/* Same reasoning as .glx-az — see the note there. */
.v2x.glx .glx-about{
  margin:0 auto;padding:0 4px 8px}
.v2x.glx .glx-about-box{
  background:var(--v2-surface,#fff);
  border:1px solid var(--v2-line,#E2E8F0);
  border-radius:18px;padding:clamp(20px,3vw,32px)}
.v2x.glx .glx-about-box h2{
  font-size:clamp(1.15rem,2.4vw,1.5rem);font-weight:800;
  letter-spacing:-.02em;color:var(--v2-ink);margin:0 0 12px}
.v2x.glx .glx-about-box p{
  font-size:.95rem;line-height:1.75;color:var(--v2-ink-2,#475569);margin:0 0 14px}
.v2x.glx .glx-about-box ul{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.v2x.glx .glx-about-box li{
  display:flex;align-items:flex-start;gap:9px;
  font-size:.9rem;line-height:1.6;color:var(--v2-ink-2,#475569)}
.v2x.glx .glx-about-box li svg{
  width:17px;height:17px;flex:0 0 auto;margin-top:2px;color:var(--brand-blue,#3680ED)}
body.theme-dark .v2x.glx .glx-about-box{
  background:var(--v2-surface,#141922);border-color:rgba(148,163,184,.16)}
body.theme-dark .v2x.glx .glx-about-box p,
body.theme-dark .v2x.glx .glx-about-box li{color:#B6C2D4}   /* 9.78:1 */
/* The tick icon is decoration at 17px, so the 3:1 non-text floor applies and
   #3680ED already clears it at 4.59:1 on the dark card — the twin is here for
   parity with the p/li ink beside it, not to fix a failure. */
body.theme-dark .v2x.glx .glx-about-box li svg{color:#60A4F5}


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

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

/* "View all areas" / "Browse every term" footer link. */
.v2x.glx .glx-more{
  display:flex;justify-content:center;
  margin-top:clamp(20px,3vw,32px)}
.v2x.glx .glx-more .dir-tr-more{max-width:340px}


/* ═══ §IOS — the 16px focus-zoom floor ═════════════════════════════════════
   `.dir-hh-search input` is 15.5px in the SHARED sheet (14px under 820px) and
   iOS Safari zooms the viewport on focus for anything under 16px. Pinned here
   rather than in the shared sheet, because raising it there would reflow six
   pages that have not been re-verified. The shared miss is real and still
   wants its own pass. */
.v2x.glx .dir-hh-search input{font-size:16px}
@media (max-width:820px){
  .v2x.glx .dir-hh-search input{font-size:16px}
}


/* ═══ §RESP — responsive fixes the above need ══════════════════════════════
   Every breakpoint here is one the SHARED sheet already uses, measured by
   frequency: 820 · 520 · 1180 · 640. Introducing a new stop (1100 was the
   temptation) makes the layout change twice within 80px. */
@media (max-width:1180px){
  .v2x.glx .glx-az-box{gap:12px}
}
@media (max-width:820px){
  .v2x.glx .glx-az{padding-top:16px}
  .v2x.glx .glx-az-lbl{flex:1 1 100%}
  .v2x.glx .glx-az-row{flex:1 1 100%}
  .v2x.glx .glx-az-k{--glx-k:32px;font-size:.78rem}
  .v2x.glx .glx-acro-grid{grid-template-columns:repeat(auto-fit,minmax(232px,1fr))}
}
@media (max-width:640px){
  .v2x.glx .glx-catgrid{grid-template-columns:1fr}
}
@media (max-width:520px){
  /* The grid track floor drops with the key, so the block keeps the same
     number of ROWS rather than growing one. 30px is still above the 24px
     minimum target size, and the same filter is reachable from the search box
     for anyone who cannot hit it. */
  .v2x.glx .glx-az-k{--glx-k:30px;padding:0 4px;border-radius:9px;font-size:.75rem}
  .v2x.glx .glx-az-row{gap:4px;grid-template-columns:repeat(auto-fit,minmax(30px,1fr))}
  .v2x.glx .glx-az-box{padding:12px}
  .v2x.glx .glx-acro-grid{grid-template-columns:1fr}
  .v2x.glx .glx-acro-k{max-width:50%}
}


/* ═══ Motion ═══════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  .v2x.glx .glx-az-k,
  .v2x.glx .glx-acro,
  .v2x.glx .glx-results{transition:none}
  .v2x.glx .glx-az-k:hover:not(:disabled),
  .v2x.glx .glx-acro:hover{transform:none}
}
