/* ═══════════════════════════════════════════════════════════════
   CRAFTS GALLERY — isolated styles (gallery.css)
   ═══════════════════════════════════════════════════════════════
   Loaded ONLY by /gallery/. Strict isolation:
   - Every selector is prefixed `.cg-`.
   - Every design token is `--cg-*`, declared on the `.cg-body` scope
     as an alias of the existing Roxetta `--rxs-*` value (same value,
     so the gallery is visually identical to the Roxetta system while
     staying self-contained — it does not depend on roxetta-fix.css).
   Nothing here may affect any other page.

   This file is a scaffold: it ships the token system, the
   prefers-contrast override, and minimal base layout for the section
   containers that exist today. Component styles (wall grid, cards,
   heatmap, lightbox chrome, …) are added by their own later tasks.
   ═══════════════════════════════════════════════════════════════ */

/* ── Tokens: --cg-* aliases of --rxs-* values, scoped to .cg-body ── */
.cg-body {
    /* Backgrounds: depth ladder (near-black violet, never pure black) */
    --cg-bg-base:        #0B0716;
    --cg-bg-card:        #16102B;
    --cg-bg-card-hi:     #1F1838;

    /* Accents (desaturated base for large fills, per Material dark-theme
       guidance) + a stronger "vivid" violet used ONLY as a deliberate accent
       (section headers, dividers, active states, glows) so the page reads as
       distinctly violet without flooding saturated color over big surfaces. */
    --cg-violet:         #B49BE8;
    --cg-violet-strong:  #9D7FE5;
    --cg-violet-vivid:   #8B5CF6;  /* strong accent — headers, dividers, focus */
    --cg-indigo:         #6D5CF0;  /* bridges to the home page's #5B4FE8 */
    --cg-magenta-soft:   #E66BB1;
    --cg-violet-glow:    rgba(139, 92, 246, 0.30);

    /* Borders */
    --cg-border:         rgba(255, 255, 255, 0.08);
    --cg-border-warm:    rgba(180, 140, 255, 0.18);
    --cg-border-violet:  rgba(139, 92, 246, 0.42);  /* visible violet hairline */

    /* Text. Contrast verified by the Roxetta token set:
       text 17.8:1 (AAA), text-2 9.5:1 (AAA), text-3 ≥4.88:1 (AA body),
       text-4 3.5:1 (AA large only — decorative captions). */
    --cg-text:           rgba(255, 255, 255, 0.94);
    --cg-text-2:         rgba(220, 210, 255, 0.78);
    --cg-text-3:         rgba(180, 165, 230, 0.75);
    --cg-text-4:         rgba(180, 165, 230, 0.55);
    --cg-text-link:      #D4B8FF;

    /* Status (always paired with a text label, never color alone) */
    --cg-success:        #88E8B4;
    --cg-danger:         #FF6E8A;

    /* Type families: Inter only, matching the rest of the site */
    --cg-font-display:   'Inter', system-ui, -apple-system, sans-serif;
    --cg-font-body:      'Inter', system-ui, -apple-system, sans-serif;

    /* Easing */
    --cg-ease:           cubic-bezier(0.25, 0.46, 0.45, 0.94);
    --cg-ease-out-expo:  cubic-bezier(0.16, 1, 0.3, 1);

    /* Radius: cells/controls vs large cards */
    --cg-radius:         10px;
    --cg-radius-lg:      16px;

    /* Apply the base tokens to the gallery body */
    background: var(--cg-bg-base);
    color: var(--cg-text);
    font-family: var(--cg-font-body);
}

/* ── [hidden] reset (must win over component display rules) ─────
   Many gallery components set an explicit `display: flex|grid|…`. By the
   cascade, that overrides the `[hidden]` attribute's default `display:none`,
   so JS toggling `el.hidden = true` would NOT hide them. This guarantees any
   `.cg-` element the controllers hide actually disappears. *(bug: a hidden
   "Load more" footer stayed visible with a stale count)* */
.cg-body [hidden] {
    display: none !important;
}

/* ── prefers-contrast: more ─────────────────────────────────────
   Mirrors the Roxetta override: bumps tertiary/quaternary text and
   borders for users who request increased contrast. text and text-2
   already pass AAA, so they are left untouched. */
@media (prefers-contrast: more) {
    .cg-body {
        --cg-text-3:      rgba(220, 200, 255, 0.95);
        --cg-text-4:      rgba(210, 195, 250, 0.82);
        --cg-border:      rgba(255, 255, 255, 0.20);
        --cg-border-warm: rgba(180, 140, 255, 0.45);
    }
}

/* ── Page header ────────────────────────────────────────────────
   Roxetta-page header rhythm (eyebrow + H1 + subtitle), centered. */
.cg-page-header {
    text-align: center;
    margin: 2.4rem auto 1.6rem;
}

.cg-eyebrow {
    font-family: var(--cg-font-body);
    font-size: clamp(1.05rem, 2.4vw, 1.25rem);
    font-weight: 600;
    line-height: 1.5;
    color: var(--cg-text-2);
    max-width: 640px;
    margin: 0 auto 1.4rem;
}

.cg-page-h1 {
    font-family: var(--cg-font-display);
    font-size: clamp(2.6rem, 7vw, 4.6rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.05;
    margin: 0 0 0.8rem;
    /* Violet→magenta gradient wordmark, setting the page's accent tone up top
       (mirrors the home page's violet identity). Falls back to solid text. */
    color: var(--cg-text);
    background: linear-gradient(120deg, var(--cg-text) 30%, var(--cg-violet) 70%, var(--cg-magenta-soft));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.cg-page-subtitle {
    font-family: var(--cg-font-body);
    font-size: clamp(1rem, 2.4vw, 1.2rem);
    font-weight: 450;
    line-height: 1.45;
    color: var(--cg-text-2);
    max-width: 580px;
    margin: 0 auto;
}

/* ── KPI band (top-line stats) ──────────────────────────────────
   The "big idea" first (NN/g visual hierarchy; USWDS: lead with a central
   theme). A compact row of large figures: total crafts, five-rox count,
   lowest float, countries represented. Pure summary — each number is a
   real aggregate, large numeral over a quiet label, no chartjunk. Wraps to
   2x2 then 1-col as the viewport narrows (no overflow). Hidden until the
   data resolves so it never shows empty placeholders. */
.cg-kpi-band {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.75rem;
    margin: 0 auto 1.6rem;
}
.cg-kpi {
    position: relative;
    background:
        linear-gradient(180deg, color-mix(in srgb, var(--cg-violet-vivid) 8%, var(--cg-bg-card)), var(--cg-bg-card));
    border: 1px solid var(--cg-border-violet);
    border-radius: var(--cg-radius-lg);
    padding: 1rem 0.9rem;
    text-align: center;
}
.cg-kpi-value {
    font-family: var(--cg-font-display);
    font-size: clamp(1.5rem, 5vw, 2.3rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.01em;
    /* Vivid violet→magenta gradient numerals (deliberate accent, not a fill). */
    background: linear-gradient(135deg, var(--cg-violet), var(--cg-magenta-soft));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--cg-violet); /* fallback where background-clip:text is unsupported */
    font-variant-numeric: tabular-nums;
}
.cg-kpi-label {
    margin-top: 0.4rem;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--cg-text-3);
    text-transform: uppercase;
}
@media (max-width: 600px) {
    .cg-kpi-band { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 360px) {
    .cg-kpi-band { grid-template-columns: 1fr; }
}

/* ── Search panel (top-of-page primary interactive surface) ─────
   The most interactive element, placed first: a prominent free-text
   search, a full set of facet chip-toggles (weapon/wear/rox/origin),
   a sort control, a live result count, clear-all, and a jump to the
   wall. Quiet card surface so the controls — not chrome — lead. */
.cg-search {
    background: var(--cg-bg-card);
    border: 1px solid var(--cg-border-warm);
    border-radius: var(--cg-radius-lg);
    padding: 1.4rem 1.4rem 1.2rem;
    margin: 0 0 1.6rem;
}
.cg-search-title {
    font-family: var(--cg-font-display);
    font-size: clamp(1.3rem, 3.5vw, 1.8rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 0.3rem;
    color: var(--cg-text);
}
.cg-search-sub {
    margin: 0 0 1.1rem;
    font-size: 0.92rem;
    color: var(--cg-text-2);
}

/* Free-text search + sort row */
.cg-search-row {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 1.1rem;
}
.cg-search-input-wrap {
    position: relative;
    flex: 1 1 320px;
    min-width: 0;
}
.cg-search-input {
    width: 100%;
    box-sizing: border-box;
    padding: 0.8rem 1rem 0.8rem 2.4rem;
    font-family: var(--cg-font-body);
    font-size: 1rem;
    color: var(--cg-text);
    background: var(--cg-bg-base);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius);
    transition: border-color 0.18s var(--cg-ease), box-shadow 0.18s var(--cg-ease);
}
.cg-search-input::placeholder { color: var(--cg-text-4); }
.cg-search-input:focus {
    outline: none;
    border-color: var(--cg-violet-strong);
    box-shadow: 0 0 0 3px var(--cg-violet-glow);
}

/* ── Search autocomplete suggestions ────────────────────────────
   A dropdown of matching skin names beneath the search box. Anchored to
   the input wrap (position:relative); a hairline violet border ties it to
   the search's accent. Scrolls if it ever exceeds a few rows. */
.cg-ac-list {
    position: absolute;
    z-index: 40;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 280px;
    overflow-y: auto;
    background: var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border-violet);
    border-radius: var(--cg-radius);
    box-shadow: 0 14px 34px -12px rgba(0, 0, 0, 0.65);
    padding: 0.3rem;
}
.cg-ac-list[hidden] { display: none; }
.cg-ac-opt {
    padding: 0.55rem 0.7rem;
    border-radius: 8px;
    font-size: 0.92rem;
    line-height: 1.3;
    color: var(--cg-text-2);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cg-ac-opt:hover,
.cg-ac-opt.cg-active {
    background: color-mix(in srgb, var(--cg-violet-vivid) 18%, var(--cg-bg-card));
    color: var(--cg-text);
}
/* Search glyph inside the input (decorative, pure CSS) */
.cg-search-input-wrap::before {
    content: '';
    position: absolute;
    left: 0.85rem;
    top: 50%;
    width: 1rem;
    height: 1rem;
    transform: translateY(-50%);
    background: var(--cg-text-3);
    -webkit-mask: no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 5 1.49-1.5-5-5zm-6 0A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14z'/%3E%3C/svg%3E");
    mask: no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 5 1.49-1.5-5-5zm-6 0A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14z'/%3E%3C/svg%3E");
    pointer-events: none;
}
.cg-search-sort {
    flex: 0 0 auto;
    padding: 0.8rem 0.9rem;
    font-family: var(--cg-font-body);
    font-size: 0.9rem;
    color: var(--cg-text);
    background: var(--cg-bg-base);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius);
    cursor: pointer;
}
.cg-search-sort:focus-visible { outline: 2px solid var(--cg-violet-strong); outline-offset: 2px; }

/* Facet groups: a label over a wrapping row of toggle chips */
.cg-search-groups {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}
.cg-search-group-label {
    display: block;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--cg-text-3);
    margin-bottom: 0.45rem;
}
.cg-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
.cg-filter-chip {
    padding: 0.4rem 0.8rem;
    font-family: var(--cg-font-body);
    font-size: 0.83rem;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    color: var(--cg-text-2);
    background: var(--cg-bg-base);
    border: 1px solid var(--cg-border);
    border-radius: 999px;
    transition: color 0.16s var(--cg-ease), background 0.16s var(--cg-ease), border-color 0.16s var(--cg-ease);
}
.cg-filter-chip:hover { color: var(--cg-text); border-color: var(--cg-border-warm); }
.cg-filter-chip:focus-visible { outline: 2px solid var(--cg-violet-strong); outline-offset: 2px; }
.cg-filter-chip.cg-on {
    color: var(--cg-bg-base);
    background: var(--cg-violet);
    border-color: var(--cg-violet);
}

/* ── Searchable combobox (large facets: Weapon, Origin) ─────────
   Keeps the box compact: type to filter a dropdown, or press the caret
   to browse the full list. Selected values appear as removable chips
   below the field, preserving multi-select. */
.cg-combo {
    position: relative;
    max-width: 420px;
}
.cg-combo-field {
    display: flex;
    align-items: stretch;
    background: var(--cg-bg-base);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius);
    overflow: hidden;
    transition: border-color 0.18s var(--cg-ease), box-shadow 0.18s var(--cg-ease);
}
.cg-combo.cg-open .cg-combo-field,
.cg-combo-field:focus-within {
    border-color: var(--cg-violet-strong);
    box-shadow: 0 0 0 3px var(--cg-violet-glow);
}
.cg-combo-input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.6rem 0.75rem;
    font-family: var(--cg-font-body);
    font-size: 0.92rem;
    color: var(--cg-text);
    background: transparent;
    border: 0;
    outline: none;
}
.cg-combo-input::placeholder { color: var(--cg-text-4); }
.cg-combo-caret {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.2rem;
    background: transparent;
    border: 0;
    border-left: 1px solid var(--cg-border);
    color: var(--cg-text-3);
    cursor: pointer;
    transition: color 0.16s var(--cg-ease), transform 0.18s var(--cg-ease);
}
.cg-combo-caret svg { width: 18px; height: 18px; fill: currentColor; }
.cg-combo-caret:hover { color: var(--cg-text); }
.cg-combo.cg-open .cg-combo-caret { transform: rotate(180deg); }

/* Dropdown listbox */
.cg-combo-list {
    position: absolute;
    z-index: 30;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 260px;
    overflow-y: auto;
    background: var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border-warm);
    border-radius: var(--cg-radius);
    box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.6);
    padding: 0.3rem;
}
.cg-combo-list[hidden] { display: none; }
.cg-combo-opt {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.6rem;
    border-radius: 8px;
    font-size: 0.9rem;
    color: var(--cg-text-2);
    cursor: pointer;
}
.cg-combo-opt:hover,
.cg-combo-opt.cg-active {
    background: var(--cg-bg-card);
    color: var(--cg-text);
}
.cg-combo-opt.cg-on { color: var(--cg-text); }
.cg-combo-opt-box {
    flex: 0 0 auto;
    width: 1.05rem;
    height: 1.05rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    line-height: 1;
    color: var(--cg-bg-base);
    border: 1px solid var(--cg-border-warm);
    border-radius: 4px;
    background: transparent;
}
.cg-combo-opt.cg-on .cg-combo-opt-box {
    background: var(--cg-violet);
    border-color: var(--cg-violet);
}
.cg-combo-empty {
    padding: 0.6rem;
    font-size: 0.88rem;
    color: var(--cg-text-3);
}

/* Selected-value chips below the field */
.cg-combo-selected {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}
.cg-combo-selected:not(:empty) { margin-top: 0.5rem; }
.cg-combo-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.28rem 0.3rem 0.28rem 0.65rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--cg-bg-base);
    background: var(--cg-violet);
    border-radius: 999px;
}
.cg-combo-chip-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.1rem;
    height: 1.1rem;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    color: var(--cg-bg-base);
    background: rgba(11, 7, 22, 0.22);
    border: 0;
    border-radius: 50%;
}
.cg-combo-chip-x:hover { background: rgba(11, 7, 22, 0.4); }
.cg-combo-chip-x:focus-visible { outline: 2px solid var(--cg-bg-base); outline-offset: 1px; }

/* Actions row: StatTrak toggle, live count, clear-all, jump-to-wall */
.cg-search-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.9rem;
    margin-top: 1.2rem;
    padding-top: 1rem;
    border-top: 1px solid var(--cg-border);
}
.cg-search-st {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.88rem;
    color: var(--cg-text-2);
    cursor: pointer;
}
.cg-search-result {
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--cg-violet);
    font-variant-numeric: tabular-nums;
}
.cg-search-clear {
    padding: 0.45rem 0.9rem;
    font-size: 0.83rem;
    font-weight: 600;
    cursor: pointer;
    color: var(--cg-text-2);
    background: transparent;
    border: 1px solid var(--cg-border);
    border-radius: 999px;
    transition: color 0.16s var(--cg-ease), border-color 0.16s var(--cg-ease);
}
.cg-search-clear:hover { color: var(--cg-text); border-color: var(--cg-border-warm); }
.cg-search-clear:focus-visible { outline: 2px solid var(--cg-violet-strong); outline-offset: 2px; }
.cg-search-jump {
    margin-left: auto;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--cg-text-link);
    text-decoration: none;
}
.cg-search-jump:hover { text-decoration: underline; }
@media (max-width: 520px) {
    .cg-search-jump { margin-left: 0; }
}

/* ── Results header (announces the active search, above the wall) ──
   Appears only when a search/filter is active: a heading naming the query
   plus a "N skins found" line (or a clear no-match line), so the user sees
   what their search returned right where the results begin. */
.cg-results-header {
    margin: 0 0 1rem;
    padding: 1rem 1.2rem;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--cg-violet-vivid) 14%, var(--cg-bg-card-hi)),
        color-mix(in srgb, var(--cg-bg-card) 92%, transparent));
    border: 1px solid var(--cg-border-violet);
    border-left: 4px solid var(--cg-violet-vivid);
    border-radius: var(--cg-radius);
    box-shadow: 0 0 0 1px rgba(139, 92, 246, 0.08), 0 6px 20px -12px var(--cg-violet-glow);
}
.cg-results-header[hidden] { display: none; }
.cg-results-title {
    margin: 0;
    font-family: var(--cg-font-display);
    font-size: clamp(1.1rem, 3vw, 1.4rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    line-height: 1.25;
    color: var(--cg-text);
}
.cg-results-term {
    color: var(--cg-violet);
    word-break: break-word; /* a long query can never overflow the box */
}
.cg-results-count {
    margin: 0.3rem 0 0;
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--cg-violet);
    font-variant-numeric: tabular-nums;
}
.cg-results-count--empty {
    color: var(--cg-danger);
}

/* ── In-page section navigation (sticky table of contents) ──────
   NN/g in-page links + scroll-spy: on a long page, a compact sticky
   bar lets users jump to a section and see where they are. It sits
   directly under the site topbar; the filter bar stacks below it when
   both are stuck. Horizontal-scrollable on narrow screens (no overflow).
   Shown by gallery.js only when the enhancement is active (the [hidden]
   attribute is removed); without JS the page is a plain anchored stack. */
.cg-section-nav {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    flex-wrap: nowrap;
    gap: 0.4rem;
    align-items: center;
    margin: 0 0 1.25rem;
    padding: 0.5rem 0.55rem;
    overflow-x: auto;
    scrollbar-width: none; /* Firefox: hide the chrome, keep scrollability */
    /* A stronger, glassy violet rail so the bar reads as a distinct control
       strip rather than faint text floating over the page. */
    background:
        linear-gradient(180deg,
            color-mix(in srgb, var(--cg-bg-card-hi) 92%, transparent),
            color-mix(in srgb, var(--cg-bg-card) 92%, transparent));
    -webkit-backdrop-filter: blur(12px) saturate(1.2);
    backdrop-filter: blur(12px) saturate(1.2);
    border: 1px solid var(--cg-border-warm);
    border-radius: 999px;
    box-shadow:
        0 6px 22px -12px rgba(0, 0, 0, 0.7),
        inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.cg-section-nav::-webkit-scrollbar { display: none; } /* WebKit: same */
.cg-section-nav-link {
    flex: 0 0 auto;
    padding: 0.5rem 1rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    /* Brighter default ink + a hairline chip so each item reads as a tappable
       target, not plain text. */
    color: var(--cg-text-2);
    text-decoration: none;
    background: color-mix(in srgb, var(--cg-bg-base) 45%, transparent);
    border: 1px solid var(--cg-border);
    transition: color 0.18s var(--cg-ease), background 0.18s var(--cg-ease),
                border-color 0.18s var(--cg-ease), box-shadow 0.18s var(--cg-ease),
                transform 0.18s var(--cg-ease);
}
.cg-section-nav-link:hover {
    color: var(--cg-text);
    background: var(--cg-bg-card-hi);
    border-color: var(--cg-violet-strong);
}
.cg-section-nav-link:focus-visible {
    outline: 2px solid var(--cg-violet-strong);
    outline-offset: 2px;
}
.cg-section-nav-link.cg-active {
    color: #fff;
    background: linear-gradient(135deg, var(--cg-violet-vivid), var(--cg-magenta-soft));
    border-color: transparent;
    box-shadow: 0 4px 14px -4px var(--cg-violet-glow);
}
@media (prefers-reduced-motion: no-preference) {
    .cg-section-nav-link.cg-active { transform: translateY(-1px); }
}

/* Anchor offset so a sticky-bar jump never hides the section heading
   beneath the section nav. Applied to every in-page jump target. */
.cg-anchor { scroll-margin-top: 4.5rem; }

/* Smooth in-page scrolling for section-nav jumps, disabled when the
   user prefers reduced motion (the site-wide convention). */
@media (prefers-reduced-motion: no-preference) {
    .cg-body { scroll-behavior: smooth; }
}

/* ── Insights: tabbed group of the seven data visualizations ────
   NN/g tabs: independent panels the user views one at a time. When
   gallery.js enhances the group it shows the tablist and reveals one
   panel at a time; until then (or without JS / in tests) every panel
   is just a visible stacked section. */
.cg-insights { margin: 0 0 1.25rem; }
.cg-tablist {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.4rem;
    margin: 0 0 1rem;
    padding-bottom: 0.4rem;
    overflow-x: auto;
    scrollbar-width: none;
}
.cg-tablist::-webkit-scrollbar { display: none; }
.cg-tab {
    flex: 0 0 auto;
    padding: 0.5rem 0.95rem;
    border-radius: 999px;
    font-family: var(--cg-font-body);
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    color: var(--cg-text-2);
    background: var(--cg-bg-card);
    border: 1px solid var(--cg-border);
    transition: color 0.18s var(--cg-ease), background 0.18s var(--cg-ease), border-color 0.18s var(--cg-ease);
}
.cg-tab:hover { color: var(--cg-text); border-color: var(--cg-border-warm); }
.cg-tab:focus-visible { outline: 2px solid var(--cg-violet-strong); outline-offset: 2px; }
.cg-tab[aria-selected="true"] {
    color: var(--cg-bg-base);
    background: var(--cg-violet);
    border-color: var(--cg-violet);
}
/* When the group is enhanced into tabs, the inactive panels are hidden
   via this attribute (set by gallery.js); the active panel drops its
   bottom margin since the group provides the rhythm. */
.cg-insights[data-cg-tabs="on"] .cg-section { margin-bottom: 0; }

/* ── Section container base ─────────────────────────────────────
   Each showcase is a clearly-bounded GROUP (NN/g IA: proximity + a shared
   container + a labeled header signal "new section"). Elevation is surface
   lightness + a hairline border, topped by a thin violet accent rule so the
   start of every section is unmistakable — even when consecutive sections
   hold visually similar card grids (the reported "where did search end and
   Hall of Fame begin?" problem). The accent is a thin line, not a fill, so
   it adds structure without chartjunk (Tufte). */
.cg-section {
    position: relative;
    background: var(--cg-bg-card);
    border: 1px solid var(--cg-border);
    border-radius: 12px;
    padding: 1.4rem;
    margin: 0 0 2rem; /* more air BETWEEN sections than within them (proximity) */
    overflow: hidden; /* clip the top accent rule to the rounded corners */
}
/* Violet accent rule pinned to the top edge of every section. */
.cg-section::before {
    content: '';
    position: absolute;
    left: 0; right: 0; top: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--cg-violet-vivid), var(--cg-magenta-soft) 70%, transparent);
}

/* ── Filter / sort bar (sticky controls introducing the wall) ──── */
.cg-filter-bar {
    position: sticky;
    /* Sits just below the sticky section-nav when both are pinned. */
    top: 3.25rem;
    z-index: 9;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0;
    background: var(--cg-bg-card);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius);
    padding: 0.8rem 1rem;
    margin: 0 0 1.25rem;
}
/* In compact mode the search panel owns the controls, so the wall's bar
   is empty — collapse it entirely (no blank sticky strip). */
.cg-filter-bar:empty {
    display: none;
}

/* ── Craft wall container + paginated card grid ─────────────────
   The wall is a responsive CSS grid (auto-fill minmax tracks) rendered
   in pages: the controller mounts WALL_PAGE_SIZE cards at a time behind
   a "Load more" button (conscious control over a disorienting infinite
   scroll), so first paint stays light and only requested thumbnails load
   (lazy). No horizontal overflow at any breakpoint. */
.cg-wall {
    margin: 0 0 2.25rem;
}

/* Responsive card grid: auto-fill tracks with a wide min so cards stay large
   (gaming-storefront convention); columns drop many→one as width shrinks with
   no horizontal overflow in portrait or landscape. A wider min (≈360px) keeps
   each weapon big and detailed — closer to the home-page hero presentation —
   instead of many tiny cells. */
.cg-wall-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
    gap: 1rem;
    width: 100%;
    max-width: 100%;
}
@media (max-width: 520px) {
    /* Single, large card per row on phones so the weapon reads clearly. */
    .cg-wall-grid { grid-template-columns: 1fr; }
}

/* A craft card: media (full uncropped weapon) above an info panel. A real
   <button> so it is keyboard-activatable; surface-lightness elevation + a
   hairline border (no heavy shadow). */
.cg-cell {
    display: flex;
    flex-direction: column;
    padding: 0;
    margin: 0;
    text-align: left;
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius-lg);
    background: var(--cg-bg-card-hi);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 140ms var(--cg-ease), transform 140ms var(--cg-ease);
}

.cg-cell:hover,
.cg-cell:focus-visible {
    border-color: var(--cg-violet-vivid);
    transform: translateY(-2px);
    box-shadow: 0 10px 30px -16px var(--cg-violet-glow);
    outline: 2px solid var(--cg-violet-vivid); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

/* Media box: a fixed landscape frame matching the REAL weapon-panorama aspect
   (~3.31:1, e.g. 1024×309) so the craft fills the box edge-to-edge with no
   empty letterbox bands. The image is shown WHOLE (contain) — never cropped —
   over an atmospheric violet glow (mirroring the home-page hero) so the weapon
   pops with depth instead of sitting on a flat panel. Fixed ratio = zero CLS. */
.cg-cell-media {
    width: 100%;
    aspect-ratio: 1024 / 309;
    background:
        radial-gradient(ellipse at 25% 50%, rgba(157, 127, 229, 0.20), transparent 65%),
        radial-gradient(ellipse at 75% 50%, rgba(230, 107, 177, 0.13), transparent 65%),
        radial-gradient(ellipse at 50% 85%, rgba(79, 143, 232, 0.07), transparent 60%),
        var(--cg-bg-base);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

/* The weapon image: full, uncropped, centered, filling the media box. A small
   inset lets the glow breathe around the edges. */
.cg-thumb {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: transparent;
}

/* A thumbnail that 404'd: the factory swaps in a flat placeholder and
   adds this class so the broken cell reads as an intentional empty box
   rather than a broken-image glyph, leaving siblings untouched. */
.cg-thumb-broken {
    object-fit: contain;
    opacity: 0.6;
}

/* Info panel: the craft's name + a meta line of labeled chips. */
.cg-cell-info {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.7rem 0.85rem 0.85rem;
}

.cg-cell-name {
    font-family: var(--cg-font-display);
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--cg-text);
    /* Two-line clamp so long names never blow the card height. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cg-cell-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
}

/* A labeled data chip (wear, float, rox, StatTrak). Quiet by default; the
   float is emphasized (it is the headline collectors care about) and
   StatTrak gets its signature warm accent — paired with the text label so
   color is never the only signal (colorblind-safe). */
.cg-cell-chip {
    font-size: 0.74rem;
    font-weight: 600;
    line-height: 1;
    padding: 0.28em 0.55em;
    border-radius: 999px;
    border: 1px solid var(--cg-border);
    color: var(--cg-text-2);
    background: var(--cg-bg-card);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.cg-cell-float {
    color: var(--cg-text);
    border-color: var(--cg-border-warm);
    font-weight: 700;
}
.cg-cell-st {
    color: #F5B95C;
    border-color: rgba(245, 185, 92, 0.4);
}

/* Empty-state / data-unavailable message shown instead of an empty grid. */
.cg-wall-empty {
    margin: 0;
    padding: 2rem 1rem;
    text-align: center;
    color: var(--cg-text-2);
    font-size: 1rem;
}

/* "Load more" footer: a centered button + a "showing X of N" hint, so the
   user keeps conscious control over how much loads (NN/g: better than a
   disorienting infinite scroll). */
.cg-wall-more {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    margin: 1.4rem 0 0.4rem;
}
.cg-wall-more-btn {
    font-family: var(--cg-font-body);
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--cg-text);
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--cg-violet-vivid) 22%, var(--cg-bg-card-hi)),
        var(--cg-bg-card-hi));
    border: 1px solid var(--cg-border-violet);
    border-radius: 999px;
    padding: 0.6rem 1.6rem;
    cursor: pointer;
    transition: border-color 140ms var(--cg-ease), background 140ms var(--cg-ease), box-shadow 140ms var(--cg-ease);
}
.cg-wall-more-btn:hover,
.cg-wall-more-btn:focus-visible {
    border-color: var(--cg-violet-vivid);
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--cg-violet-vivid) 34%, var(--cg-bg-card-hi)),
        var(--cg-bg-card));
    box-shadow: 0 6px 20px -10px var(--cg-violet-glow);
    outline: 2px solid var(--cg-violet-vivid); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}
.cg-wall-more-info {
    font-size: 0.8rem;
    color: var(--cg-text-3);
    font-variant-numeric: tabular-nums;
}

/* ── Filter / sort controls (minimal; full panel is a later task) ── */
.cg-control {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-right: 1rem;
    color: var(--cg-text-2);
    font-size: 0.95rem;
}

.cg-sort {
    background: var(--cg-bg-card-hi);
    color: var(--cg-text);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius);
    padding: 0.3rem 0.5rem;
    font-family: var(--cg-font-body);
}

.cg-match-count {
    color: var(--cg-text-3);
    font-size: 0.95rem;
    font-variant-numeric: tabular-nums;
}

/* ── Showcase sections: Hall of Fame & Five-Rox Room ────────────
   Large trading-card grids rendered above the wall. Elevation is surface
   lightness + a hairline border only — no heavy shadows, no decorative
   gradients competing with the imagery (Tufte: no chartjunk). Cards reflow
   to fewer columns as the viewport narrows (auto-fill with a min track), so
   there is never horizontal overflow in portrait or landscape. */

/* Section heading: a strong, unmistakable label so the eye registers a new
   group. A violet accent bar sits to its left and a gradient divider runs
   beneath, giving every section a clear "this is where it starts" marker
   (NN/g IA grouping + hierarchy). Type scale + weight carry the hierarchy;
   the violet is a deliberate accent, not a fill. */
.cg-section-title {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin: 0 0 1.1rem;
    padding: 0 0 0.7rem;
    font-family: var(--cg-font-display);
    font-size: clamp(1.5rem, 4vw, 2.1rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    line-height: 1.1;
    color: var(--cg-text);
    border-bottom: 1px solid var(--cg-border-violet);
}
/* The accent bar (a short, bold violet→magenta stroke before the label). */
.cg-section-title::before {
    content: '';
    flex: 0 0 auto;
    width: 5px;
    align-self: stretch;
    min-height: 1.4em;
    border-radius: 999px;
    background: linear-gradient(180deg, var(--cg-violet-vivid), var(--cg-magenta-soft));
}

.cg-section-msg {
    margin: 0;
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--cg-text-2);
    font-size: 1rem;
}

/* Responsive card grid: tracks are at least 240px, so columns drop from
   many → one as width shrinks with no overflow (Req 13.1, 13.2). */
.cg-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 1rem;
}

/* A large card: an anchor to the craft page. Surface-lightness elevation +
   a warm hairline border; the only motion is a quiet border/translate on
   hover, so the craft image stays the loudest voice on the page. */
.cg-card {
    display: flex;
    flex-direction: column;
    background: var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border-warm);
    border-radius: var(--cg-radius-lg);
    overflow: hidden;
    text-decoration: none;
    color: var(--cg-text);
    transition: border-color 140ms var(--cg-ease), transform 140ms var(--cg-ease);
}

.cg-card:hover,
.cg-card:focus-visible {
    border-color: var(--cg-violet-strong);
    transform: translateY(-2px);
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

/* Media box: a fixed landscape frame matching the weapon panorama aspect
   (~3.3:1) so every card frames the image uniformly (NN/g) with zero CLS. */
.cg-card-media {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 6;
    background: var(--cg-bg-base);
    overflow: hidden;
}

/* Show the weapon WHOLE (contain) — never cropped — centered in the frame,
   matching the craft wall and the homepage hero. */
.cg-card-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* A card image that 404'd (Five-Rox per-card placeholder): a flat box rather
   than a broken-image glyph. (The Hall of Fame omits the whole card instead.) */
.cg-card-img-broken {
    object-fit: contain;
    opacity: 0.6;
}

/* Card body: name, metadata, and (Hall of Fame) the reason badge. */
.cg-card-body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.9rem 1rem 1.1rem;
}

/* Reason badge: a labeled pill (text, never color alone — colorblind safe). */
.cg-card-badge {
    align-self: flex-start;
    padding: 0.2rem 0.6rem;
    border: 1px solid var(--cg-border-warm);
    border-radius: 999px;
    background: var(--cg-bg-card);
    color: var(--cg-violet);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}

.cg-card-name {
    margin: 0;
    font-family: var(--cg-font-display);
    font-size: clamp(1rem, 2.4vw, 1.2rem);
    font-weight: 700;
    line-height: 1.25;
    color: var(--cg-text);
}

.cg-card-meta {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem 1rem;
}

.cg-card-meta-item {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    font-size: 0.88rem;
}

.cg-card-meta-label {
    color: var(--cg-text-3);
}

.cg-card-meta-value {
    color: var(--cg-text);
    font-variant-numeric: tabular-nums;
}

/* Reduced motion: drop the hover lift, keep the border cue. (Req: honor
   prefers-reduced-motion on every transition.) */
@media (prefers-reduced-motion: reduce) {
    .cg-card {
        transition: border-color 140ms var(--cg-ease);
    }
    .cg-card:hover,
    .cg-card:focus-visible {
        transform: none;
    }
}

/* ── Lightbox + Flip View (hidden until invoked) ────────────────
   A full-viewport modal overlay isolated in `.cg-` chrome (no
   dependency on the app.js lightbox). The image fits the viewport in
   BOTH orientations via `object-fit: contain` + viewport-relative max
   sizing (Req 13.4). Caption text sits on a scrim so it clears WCAG
   1.4.3 over any image. The flip crossfades two stacked layers that
   share one reserved box (zero CLS, Req 23.7); under reduced-motion the
   swap is instant (Req 23.8). */
.cg-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
}

.cg-lightbox[hidden] {
    display: none;
}

/* Backdrop: dim the page behind the dialog with a centered violet glow that
   makes the weapon pop, mirroring the home-page hero gallery's atmospheric
   radial gradients. The glow sits on the backdrop (never transformed), so it
   stays fixed behind the image even while zooming/panning. Clicking closes. */
.cg-lb-backdrop {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 50% 44%, rgba(157, 127, 229, 0.22), transparent 60%),
        radial-gradient(ellipse at 30% 60%, rgba(230, 107, 177, 0.12), transparent 62%),
        radial-gradient(ellipse at 72% 64%, rgba(79, 143, 232, 0.10), transparent 60%),
        #0B0716;
    backdrop-filter: blur(2px);
}

/* Dialog: a centered column holding the stage, flanked by nav controls. */
.cg-lb-dialog {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    height: 100%;
    max-width: 1200px;
    padding: clamp(0.5rem, 2vw, 1.5rem);
    box-sizing: border-box;
}

/* Stage: the image box stacked above the scrimmed caption. */
.cg-lb-stage {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    max-width: 100%;
    max-height: 100%;
    min-width: 0;
}

/* Reserved image box: both layers occupy the same area so the flip never
   shifts layout (zero CLS). Sized to FILL the viewport like the home-page
   hero (max 90vw / 80vh) so a clicked craft is shown large, not in a small
   square. The weapon panorama (~3.31:1) sits inside via object-fit: contain. */
.cg-lb-image-wrap {
    position: relative;
    width: 90vw;
    height: 80vh;
    max-width: 90vw;
    max-height: 80vh;
    cursor: zoom-in;
    transform-origin: center center;
    transition: transform 0.2s var(--cg-ease);
    will-change: transform;
    touch-action: none;
}

/* Fullres (zoom) mode: the engine drives a translate()+scale() transform on
   the wrap so both layers zoom/pan together (the flip still works). Drop the
   transition so pan tracks the pointer 1:1; switch the cursor to grab. */
.cg-lightbox.cg-lb--fullres .cg-lb-image-wrap {
    cursor: grab;
    transition: none;
}
.cg-lightbox.cg-lb--dragging .cg-lb-image-wrap {
    cursor: grabbing;
    transition: none;
}

/* Both full-res layers fill the reserved box and fit by contain. The back
   layer is hidden by default; the active layer is opacity-faded in. */
.cg-lb-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    transition: opacity 260ms var(--cg-ease-out-expo);
    -webkit-user-select: none;
    user-select: none;
    -webkit-user-drag: none;
}

/* Playside visible by default; backside visible when the stage is flipped. */
.cg-lb-img-play { opacity: 1; }
.cg-lb--backside .cg-lb-img-play { opacity: 0; }
.cg-lb--backside .cg-lb-img-back { opacity: 1; }

/* A full-res image that 404'd: the controller swaps in a flat placeholder. */
.cg-lb-img-broken {
    opacity: 0.6;
    object-fit: contain;
}

/* Scrimmed caption block (Req text-on-image rule + 7.4/7.5). */
.cg-lb-caption {
    width: 90vw;
    max-width: 900px;
    box-sizing: border-box;
    padding: 0.9rem 1rem;
    border-radius: var(--cg-radius);
    background: linear-gradient(to top, rgba(11, 7, 22, 0.92), rgba(11, 7, 22, 0.7));
    border: 1px solid var(--cg-border);
}
/* In zoom (fullres) mode the caption would obscure the panned image; fade it
   out so the weapon has the whole stage, mirroring the hero. */
.cg-lightbox.cg-lb--fullres .cg-lb-caption {
    opacity: 0;
    pointer-events: none;
    transition: opacity 160ms var(--cg-ease);
}
@media (prefers-reduced-motion: reduce) {
    .cg-lb-image-wrap { transition: none; }
}

.cg-lb-name {
    margin: 0 0 0.5rem;
    font-family: var(--cg-font-display);
    font-size: clamp(1.05rem, 2.6vw, 1.4rem);
    font-weight: 700;
    line-height: 1.2;
    color: var(--cg-text);
}

.cg-lb-meta {
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.1rem;
}

.cg-lb-meta-item {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    font-size: 0.92rem;
}

.cg-lb-meta-label {
    color: var(--cg-text-3);
}

.cg-lb-meta-value {
    color: var(--cg-text);
    font-variant-numeric: tabular-nums;
}

.cg-lb-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
}

/* Flip control + craft-page link share a button-ish affordance. */
.cg-lb-flip {
    background: var(--cg-bg-card-hi);
    color: var(--cg-text);
    border: 1px solid var(--cg-border-warm);
    border-radius: var(--cg-radius);
    padding: 0.45rem 0.9rem;
    font-family: var(--cg-font-body);
    font-size: 0.9rem;
    cursor: pointer;
    transition: border-color 120ms var(--cg-ease);
}

.cg-lb-flip[hidden] { display: none; }

.cg-lb-link {
    color: var(--cg-text-link);
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
}

.cg-lb-link:hover,
.cg-lb-link:focus-visible {
    text-decoration: underline;
}

/* Close + nav controls: chunky tap targets, visible focus ring. */
.cg-lb-close,
.cg-lb-nav {
    flex: 0 0 auto;
    background: var(--cg-bg-card-hi);
    color: var(--cg-text);
    border: 1px solid var(--cg-border);
    border-radius: 50%;
    width: 44px;
    height: 44px;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    transition: border-color 120ms var(--cg-ease), opacity 120ms var(--cg-ease);
}

.cg-lb-close {
    position: absolute;
    top: clamp(0.5rem, 2vw, 1.25rem);
    right: clamp(0.5rem, 2vw, 1.25rem);
    z-index: 2;
}

.cg-lb-nav:disabled {
    opacity: 0.35;
    cursor: default;
}

.cg-lb-close:hover,
.cg-lb-nav:not(:disabled):hover,
.cg-lb-close:focus-visible,
.cg-lb-nav:focus-visible,
.cg-lb-flip:focus-visible {
    border-color: var(--cg-border-warm);
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

/* Phone portrait: stack nav controls below the stage so the image keeps
   maximum width, and let the image use more vertical space. */
@media (max-width: 600px) {
    .cg-lb-dialog {
        flex-wrap: wrap;
    }
    .cg-lb-image-wrap {
        width: 96vw;
        height: 70vh;
        max-width: 96vw;
        max-height: 70vh;
    }
    .cg-lb-caption {
        width: 96vw;
    }
}

/* Reduced motion: the flip becomes an instant swap, no crossfade. (Req 23.8) */
@media (prefers-reduced-motion: reduce) {
    .cg-lb-img {
        transition: none;
    }
}

/* ═══════════════════════════════════════════════════════════════
   SHOWCASE VISUALIZATIONS
   ═══════════════════════════════════════════════════════════════
   Six data panels (Float Podium, Rarest Combos, Wear Heatmap,
   Companion Constellation, Discovery Timeline, World Map). All share
   the same discipline as the rest of the gallery: elevation by surface
   lightness + a hairline border only (no chartjunk / fake 3D / drop-
   shadow overload), a single-hue violet sequential ramp for ordered
   magnitude, tabular-nums for every count/float, tap-not-hover
   interaction, reduced-motion fallbacks, and no horizontal page overflow
   at any breakpoint (wide matrices scroll inside their own block). */

/* ── Float Podium ───────────────────────────────────────────────
   A vertical ranked list, lowest float first. Rank is communicated by
   order + the bare number — no decorative podium 3D (Tufte). */
.cg-podium {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.cg-podium-row {
    margin: 0;
}

.cg-podium-entry {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.7rem 0.9rem;
    background: var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius);
    text-decoration: none;
    color: var(--cg-text);
    transition: border-color 140ms var(--cg-ease);
}

a.cg-podium-entry:hover,
a.cg-podium-entry:focus-visible {
    border-color: var(--cg-violet-strong);
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

/* A Stats_Only_Card: no image, no link — distinguished by a warm edge. */
.cg-podium-entry--stats {
    border-style: dashed;
    border-color: var(--cg-border-warm);
}

.cg-podium-rank {
    flex: 0 0 auto;
    min-width: 2.2rem;
    font-family: var(--cg-font-display);
    font-size: 1.1rem;
    font-weight: 800;
    color: var(--cg-violet);
    font-variant-numeric: tabular-nums;
}

.cg-podium-media {
    flex: 0 0 auto;
    width: 108px;
    aspect-ratio: 16 / 6;
    border-radius: 8px;
    background: var(--cg-bg-base);
    overflow: hidden;
}

.cg-podium-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.cg-podium-skin {
    margin: 0;
    font-family: var(--cg-font-display);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--cg-text);
}

/* ── Rarest Combos carousel ─────────────────────────────────────
   One dramatic focal entry at a time over a quiet surface, prev/next
   flanking the stage. */
.cg-combo-carousel {
    display: flex;
    align-items: stretch;
    gap: 0.6rem;
}

.cg-combo-stage {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    justify-content: center;
}

.cg-combo-slide {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    width: 100%;
    max-width: 420px;
    padding: 1rem;
    background: var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border-warm);
    border-radius: var(--cg-radius-lg);
    text-decoration: none;
    color: var(--cg-text);
    transition: border-color 140ms var(--cg-ease);
}

a.cg-combo-slide:hover,
a.cg-combo-slide:focus-visible {
    border-color: var(--cg-violet-strong);
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

.cg-combo-slide--stats {
    border-style: dashed;
}

.cg-combo-media {
    width: 100%;
    aspect-ratio: 16 / 6;
    border-radius: var(--cg-radius);
    background: var(--cg-bg-base);
    overflow: hidden;
}

.cg-combo-skin {
    margin: 0;
    font-family: var(--cg-font-display);
    font-size: clamp(1.05rem, 2.6vw, 1.35rem);
    font-weight: 700;
    line-height: 1.2;
    color: var(--cg-text);
}

.cg-combo-nav {
    flex: 0 0 auto;
    align-self: center;
    background: var(--cg-bg-card-hi);
    color: var(--cg-text);
    border: 1px solid var(--cg-border);
    border-radius: 50%;
    width: 44px;
    height: 44px;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    transition: border-color 120ms var(--cg-ease), opacity 120ms var(--cg-ease);
}

.cg-combo-nav:disabled {
    opacity: 0.35;
    cursor: default;
}

.cg-combo-nav:not(:disabled):hover,
.cg-combo-nav:focus-visible {
    border-color: var(--cg-border-warm);
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

.cg-combo-position {
    margin: 0.8rem 0 0;
    text-align: center;
    color: var(--cg-text-3);
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
}

/* ── Wear Heatmap ───────────────────────────────────────────────
   A 5×5 matrix, single-hue violet intensity proportional to count via
   the `--cg-heat` alpha (0..1) the controller stamps per cell. On small
   screens the matrix scrolls horizontally inside its block rather than
   collapsing to a list (Req 13.1). */
.cg-heat-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin: 0 0 1rem;
}

.cg-heat-matrix {
    display: grid;
    grid-template-columns: 4.5rem repeat(5, minmax(70px, 1fr)) 3.4rem;
    gap: 4px;
    min-width: 520px;
}

.cg-heat-corner {
    font-size: 0.7rem;
    color: var(--cg-text-3);
    display: flex;
    align-items: center;
    padding: 0.3rem;
}

.cg-heat-colhead,
.cg-heat-rowhead {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--cg-text-2);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0.3rem;
    line-height: 1.15;
}

.cg-heat-rowhead {
    justify-content: flex-start;
    font-variant-numeric: tabular-nums;
}

/* A heatmap cell: a real button (tap target), filled by a single-hue
   violet sequential ramp whose LIGHTNESS tracks the count (`--cg-heat`,
   0..1). Tap selects it.

   Encoding rationale (Tufte graphical integrity + perceptual uniformity,
   europa.eu #EndRainbow, Kovesi "Good Colour Maps"): human vision is
   dominated by LIGHTNESS, not hue or alpha. Earlier this cell varied only
   alpha over the dark surface, which compresses low/medium counts into the
   background and makes them hard to tell apart. We now drive perceptual
   lightness from ~22% (near-empty) to ~72% (the grid maximum) on a fixed
   violet hue via OKLCH, so equal count steps read as equal visual steps.
   The chroma also rises slightly so high-count cells feel "denser" without
   the hue ever shifting (single-hue sequential, no rainbow). */
.cg-heat-cell {
    position: relative;
    aspect-ratio: 3 / 2;
    min-height: 44px;
    border: 1px solid var(--cg-border);
    border-radius: 8px;
    /* Fallback for engines without OKLCH: HSL lightness ramp 26%→70%. */
    background: hsl(263, 55%, calc(26% + var(--cg-heat, 0) * 44%));
    /* Perceptually-uniform ramp: OKLCH lightness 0.30→0.86, chroma 0.05→0.17. */
    background: oklch(
        calc(0.30 + var(--cg-heat, 0) * 0.56)
        calc(0.05 + var(--cg-heat, 0) * 0.12)
        300
    );
    /* High-count cells get dark text for legibility on the light end; the
       JS stamps --cg-heat-ink to pick the readable ink color per cell. */
    color: var(--cg-heat-ink, var(--cg-text));
    font-size: 0.85rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: transform 0.15s var(--cg-ease), border-color 0.15s var(--cg-ease);
}

.cg-heat-cell:hover {
    border-color: var(--cg-border-warm);
}

.cg-heat-cell:focus-visible {
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

.cg-heat-cell--selected {
    border-color: var(--cg-violet-strong);
    box-shadow: inset 0 0 0 1px var(--cg-violet-strong);
}

/* Marginal totals: a row-edge and column-edge tally (Tufte: more
   information, same ink). NOT .cg-heat-cell, so they are not part of the
   5x5 selectable matrix; they are quiet, unfilled, tabular figures. */
.cg-heat-total,
.cg-heat-total-corner {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--cg-text-2);
    font-variant-numeric: tabular-nums;
    padding: 0.3rem;
    border-radius: 6px;
    background: var(--cg-bg-card);
    border: 1px dashed var(--cg-border);
}
.cg-heat-total-corner {
    color: var(--cg-text-3);
    font-weight: 600;
}
.cg-heat-total-head {
    font-size: 0.66rem;
    font-weight: 600;
    color: var(--cg-text-3);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0.3rem 0.1rem;
    line-height: 1.1;
}

/* Scale legend: the key that turns intensity into a number range
   (a sequential gradient bar from 0 to the grid maximum). Every serious
   sequential encoding needs this so a color reads as a value. */
.cg-scale-legend {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 1rem;
    flex-wrap: wrap;
}
.cg-scale-label {
    font-size: 0.72rem;
    color: var(--cg-text-3);
    font-variant-numeric: tabular-nums;
}
.cg-scale-bar {
    flex: 0 1 220px;
    height: 12px;
    border-radius: 6px;
    border: 1px solid var(--cg-border);
    /* Same OKLCH lightness ramp as the cells, with an HSL fallback. */
    background: linear-gradient(to right,
        hsl(263, 55%, 26%), hsl(263, 55%, 70%));
    background: linear-gradient(to right,
        oklch(0.30 0.05 300), oklch(0.86 0.17 300));
}
.cg-scale-caption {
    font-size: 0.72rem;
    color: var(--cg-text-3);
    width: 100%;
}

/* Example panel surfaced on cell selection (works on tap, not hover). */
.cg-heat-examples {
    border-top: 1px solid var(--cg-border);
    padding-top: 0.9rem;
}

.cg-heat-examples-title {
    margin: 0 0 0.3rem;
    font-family: var(--cg-font-display);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--cg-text);
}

.cg-heat-examples-note {
    margin: 0 0 0.6rem;
    color: var(--cg-text-3);
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
}

.cg-heat-examples-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.cg-heat-example {
    color: var(--cg-text-link);
    font-size: 0.9rem;
    text-decoration: none;
}

.cg-heat-example:hover,
.cg-heat-example:focus-visible {
    text-decoration: underline;
}

/* ── Companion Constellation ────────────────────────────────────
   Rox holo centered, top-10 companions placed radially; each bubble's
   AREA is proportional to frequency (radius set inline by the JS). */
.cg-const-field {
    position: relative;
    width: 100%;
    max-width: 560px;
    margin: 0 auto;
    aspect-ratio: 1 / 1;
}

.cg-const-center {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 96px;
    height: 96px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border-warm);
    overflow: hidden;
    z-index: 2;
}

.cg-const-holo {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.cg-const-center--label {
    font-size: 0.7rem;
    font-weight: 700;
    text-align: center;
    color: var(--cg-violet);
    padding: 0.3rem;
}

/* A companion bubble: a positioned wrapper centred on its orbit point,
   the disc sized by the JS (area ∝ count), caption below. */
.cg-const-bubble {
    position: absolute;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
    max-width: 9rem;
    text-align: center;
}

.cg-const-disc {
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background:
        radial-gradient(circle at 35% 30%, hsla(258, 70%, 62%, 0.45), hsla(268, 75%, 56%, 0.28)),
        var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border-warm);
    overflow: hidden;
}

.cg-const-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.cg-const-disc--label {
    font-size: 0.62rem;
    font-weight: 600;
    color: var(--cg-text);
    padding: 0.2rem;
    line-height: 1.1;
}

.cg-const-caption {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 0.3rem;
    font-size: 0.74rem;
    line-height: 1.2;
}

.cg-const-name {
    color: var(--cg-text-2);
}

.cg-const-count {
    color: var(--cg-violet);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* ── Discovery Timeline ─────────────────────────────────────────
   A horizontally scrollable track of monthly buckets; bar height encodes
   the bucket's craft count (honest density). Markers mount only within
   the viewport + buffer (windowed by the JS). */
.cg-tl-track {
    position: relative;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin: 0 0 1rem;
    padding-bottom: 0.5rem;
}

.cg-tl-rail {
    position: relative;
    height: 150px;
    min-width: 100%;
    border-bottom: 1px solid var(--cg-border);
}

/* Timeline scale caption: states what bar height means and the peak count,
   so the height channel reads as a real quantity rather than a vague shape. */
.cg-tl-scale {
    margin: 0 0 0.6rem;
    font-size: 0.74rem;
    color: var(--cg-text-3);
    font-variant-numeric: tabular-nums;
}

/* A bucket marker: an absolutely-positioned button on the rail holding a
   count-proportional bar, a dot, and a month label. */
.cg-tl-marker {
    position: absolute;
    bottom: 0;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 0.2rem;
    width: 48px;
    height: 100%;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
}

.cg-tl-bar {
    width: 10px;
    min-height: 2px;
    border-radius: 4px 4px 0 0;
    /* Bar height already encodes the bucket count; a subtle lightness ramp
       (via --cg-heat, 0..1) reinforces it as a redundant channel so tall
       bars also read as "denser". Single hue, HSL fallback then OKLCH. */
    background: hsl(263, 55%, calc(40% + var(--cg-heat, 0.5) * 26%));
    background: oklch(calc(0.50 + var(--cg-heat, 0.5) * 0.30) 0.13 300);
    transition: width 0.15s var(--cg-ease);
}

.cg-tl-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--cg-violet);
}

.cg-tl-label {
    font-size: 0.62rem;
    color: var(--cg-text-3);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.cg-tl-marker:hover .cg-tl-bar,
.cg-tl-marker--selected .cg-tl-bar {
    width: 14px;
}

.cg-tl-marker:focus-visible {
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
    border-radius: 6px;
}

.cg-tl-marker--selected .cg-tl-label {
    color: var(--cg-violet);
    font-weight: 700;
}

/* Selection panel: the chosen bucket's crafts, each a craft link. */
.cg-tl-panel {
    border-top: 1px solid var(--cg-border);
    padding-top: 0.9rem;
}

.cg-tl-panel-title {
    margin: 0 0 0.4rem;
    font-family: var(--cg-font-display);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--cg-text);
}

.cg-tl-panel-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.cg-tl-craft {
    color: var(--cg-text-link);
    font-size: 0.9rem;
    text-decoration: none;
}

.cg-tl-craft:hover,
.cg-tl-craft:focus-visible {
    text-decoration: underline;
}

/* ── World Map ──────────────────────────────────────────────────
   A lightweight inline equirectangular SVG (no paid tiles): proportional
   markers placed by lon/lat, single-hue intensity ∝ count (`--cg-heat`),
   beside an unknown-origin count + a ranked, selectable legend. */
.cg-map-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(220px, 1fr);
    gap: 1.2rem;
    align-items: start;
}

.cg-map-canvas {
    min-width: 0;
}

.cg-map-svg {
    width: 100%;
    height: auto;
    display: block;
    background: var(--cg-bg-base);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-radius);
}

.cg-map-ocean {
    fill: var(--cg-bg-base);
}

/* Continent silhouettes: a quiet raised landmass tone (lighter than the
   ocean) with a faint violet edge, so land reads clearly behind the markers
   without competing with them for attention. */
.cg-map-land {
    fill: var(--cg-bg-card-hi);
    stroke: var(--cg-border-warm);
    stroke-width: 0.4;
    stroke-linejoin: round;
}

.cg-map-grid {
    stroke: var(--cg-border);
    stroke-width: 0.3;
}

/* Proportional-symbol marker: radius (set inline) encodes count; the fill
   adds a redundant single-hue lightness ramp so denser origins also read
   lighter. HSL fallback then OKLCH (perceptually uniform). */
.cg-map-marker {
    fill: hsl(263, 60%, calc(34% + var(--cg-heat, 0) * 40%));
    fill: oklch(calc(0.40 + var(--cg-heat, 0) * 0.42) 0.13 300);
    stroke: var(--cg-violet);
    stroke-width: 0.5;
    cursor: pointer;
    transition: stroke-width 0.12s var(--cg-ease);
}

.cg-map-marker:hover,
.cg-map-marker:focus-visible {
    stroke: var(--cg-violet-strong);
    stroke-width: 1.2;
    outline: none;
}

.cg-map-side {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    min-width: 0;
}

.cg-map-unknown {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.6rem;
    margin: 0;
    padding: 0.6rem 0.8rem;
    background: var(--cg-bg-card-hi);
    border: 1px dashed var(--cg-border-warm);
    border-radius: var(--cg-radius);
}

.cg-map-unknown-label {
    color: var(--cg-text-2);
    font-size: 0.9rem;
}

.cg-map-unknown-value {
    color: var(--cg-text);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.cg-map-status {
    margin: 0;
    color: var(--cg-text-3);
    font-size: 0.9rem;
    min-height: 1.2em;
}

.cg-map-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    max-height: 320px;
    overflow-y: auto;
}

.cg-map-legend-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.3rem 0.4rem;
    background: none;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--cg-text);
    font-size: 0.85rem;
    text-align: left;
    cursor: pointer;
}

.cg-map-legend-row:hover,
.cg-map-legend-row:focus-visible {
    border-color: var(--cg-border-warm);
    outline: none;
}

.cg-map-swatch {
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid var(--cg-border);
    background: hsl(263, 60%, calc(34% + var(--cg-heat, 0) * 40%));
    background: oklch(calc(0.40 + var(--cg-heat, 0) * 0.42) 0.13 300);
}

.cg-map-legend-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cg-map-legend-count {
    flex: 0 0 auto;
    color: var(--cg-text-2);
    font-variant-numeric: tabular-nums;
}

/* ── Sticker Evolution box ──────────────────────────────────────
   Crafts that gained rox stickers over time, as small multiples: each rox
   level side by side in one row (Tufte eye-span comparison). Row header has
   the "1x -> 3x" summary; the strip shows the path. Surface-lightness
   elevation + hairline borders only (no chartjunk). The strip scrolls
   horizontally inside its block on small screens (never collapses/overflows). */
.cg-evo-intro {
    margin: 0 0 1.1rem;
    color: var(--cg-text-2);
    font-size: 0.92rem;
}

.cg-evo-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.cg-evo-row {
    background: var(--cg-bg-card-hi);
    border: 1px solid var(--cg-border-warm);
    border-radius: var(--cg-radius-lg);
    padding: 0.9rem 1rem 1rem;
}

.cg-evo-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem 0.8rem;
    margin: 0 0 0.8rem;
}

.cg-evo-name {
    font-family: var(--cg-font-display);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--cg-text-link);
    text-decoration: none;
}
.cg-evo-name:hover,
.cg-evo-name:focus-visible {
    text-decoration: underline;
    outline: 2px solid var(--cg-violet-strong); /* visible focus ring (WCAG 2.4.7) */
    outline-offset: 2px;
}

/* The "1x -> 3x" headline: the conclusion first, in tabular figures. */
.cg-evo-summary {
    font-family: var(--cg-font-display);
    font-size: 1rem;
    font-weight: 800;
    color: var(--cg-violet);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
}

.cg-evo-meta {
    color: var(--cg-text-3);
    font-size: 0.82rem;
}

/* Horizontal scroll wrapper: the strip stays intact on small screens. */
.cg-evo-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* The small-multiples strip: frames + connectors in document order. */
.cg-evo-strip {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    min-width: min-content;
}

.cg-evo-frame {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    width: 140px;
}

.cg-evo-media {
    width: 100%;
    aspect-ratio: 16 / 6;
    border-radius: var(--cg-radius);
    border: 1px solid var(--cg-border);
    background: var(--cg-bg-base);
    overflow: hidden;
}

/* The current (latest) state reads as "now" via a stronger edge — not by
   color alone (the "now" label + last position also encode it). */
.cg-evo-frame--now .cg-evo-media {
    border-color: var(--cg-violet-strong);
    box-shadow: inset 0 0 0 1px var(--cg-violet-strong);
}

.cg-evo-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}
.cg-evo-img-broken {
    object-fit: contain;
    opacity: 0.6;
}

.cg-evo-badge {
    font-family: var(--cg-font-display);
    font-size: 0.85rem;
    font-weight: 800;
    color: var(--cg-violet);
    font-variant-numeric: tabular-nums;
}

.cg-evo-step-label {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--cg-text-3);
}
.cg-evo-frame--now .cg-evo-step-label {
    color: var(--cg-violet);
}

/* Connector arrow between consecutive states (decorative; aria-hidden). */
.cg-evo-connector {
    flex: 0 0 auto;
    align-self: center;
    color: var(--cg-text-3);
    font-size: 1.1rem;
    line-height: 1;
    padding-top: 1.5rem; /* visually centers it against the media box */
}

/* ── Responsive: stack showcase layouts, keep matrices scrollable ── */
@media (max-width: 720px) {
    .cg-map-layout {
        grid-template-columns: 1fr;
    }
    .cg-const-field {
        max-width: 420px;
    }
    .cg-const-bubble {
        max-width: 6.5rem;
    }
    .cg-podium-media {
        width: 84px;
    }
}

@media (max-width: 480px) {
    .cg-combo-carousel {
        gap: 0.3rem;
    }
    .cg-combo-nav {
        width: 38px;
        height: 38px;
        font-size: 1.25rem;
    }
    .cg-const-caption {
        font-size: 0.66rem;
    }
    .cg-evo-frame {
        width: 116px;
    }
    /* Phone portrait: shrink the card min track so the grid is always a
       single, full-width column with no horizontal overflow. */
    .cg-wall-grid {
        grid-template-columns: 1fr;
    }
}

/* ── Reduced motion: drop every showcase transition ─────────────
   (Req: honor prefers-reduced-motion on every transition/animation.) */
@media (prefers-reduced-motion: reduce) {
    .cg-podium-entry,
    .cg-combo-slide,
    .cg-combo-nav,
    .cg-heat-cell,
    .cg-tl-bar,
    .cg-map-marker,
    .cg-cell,
    .cg-wall-more-btn {
        transition: none;
    }
    /* No hover lift when the user prefers reduced motion. */
    .cg-cell:hover,
    .cg-cell:focus-visible {
        transform: none;
    }
}
