/**
 * Browse cards (/cards) — page chrome, 2026-08-26.
 *
 * Surface tokens, the .fselect shells and the card tile itself live in
 * ui-kit.css, which must load first (see $page_styles in controllers/cards.php).
 * This file is only what is specific to the browse page: its header band, the
 * filter panel layout, the applied-filter chips, the empty state and paging.
 *
 * Loaded last, so it wins ties against app/design/theme/polish/responsive
 * without !important. Every rule is scoped under .browse or .browse-head.
 */
/* ============================================================
   1. Page header — title, blurb and the live result count in one
      band. The filter panel below overlaps its lower edge so the
      two read as a single control surface and the grid starts
      ~90px higher than it did with the shared page hero.
   ============================================================ */
.browse-head {
    position: relative;
    padding: clamp(26px, 3.4vw, 44px) 0 clamp(52px, 6vw, 76px);
    background: var(--surf-head-wash);
    border-bottom: 1px solid var(--surf-border);
}
.browse-head__inner {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-5);
    flex-wrap: wrap;
}
.browse-head__text { min-width: 0; }
.browse-head__title {
    margin: 0;
    font-size: var(--step-4);
    font-weight: 800;
    letter-spacing: -0.035em;
    line-height: var(--leading-tight);
    color: var(--text-primary);
}
.browse-head__sub {
    margin: 8px 0 0;
    font-size: var(--step-0);
    color: var(--text-secondary);
}
/* Result count as a live pill — it changes on every filter keystroke, so it
   needs to look like a readout rather than a caption lost above the grid. */
.browse-head__count {
    margin: 0;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 9px 17px;
    border-radius: 999px;
    background: var(--surf-surface);
    border: 1px solid var(--surf-border-strong);
    box-shadow: var(--surf-shadow);
    font-size: 0.84rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.browse-head__count::before {
    content: '';
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 3px var(--surf-accent-ring);
}

.browse {
    position: relative;
    padding-bottom: clamp(48px, 6vw, 88px);
}

/* ============================================================
   2. Filter panel
   ============================================================ */
.browse .search-panel {
    position: relative;
    z-index: 3;
    margin: -38px 0 18px;
    padding: 14px;
    background: var(--surf-surface);
    border: 1px solid var(--surf-border-strong);
    border-radius: 18px;
    box-shadow: var(--surf-shadow-panel);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}
.browse .search-bar--advanced {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* —— Main search row —— */
.browse .search-bar__row--main {
    display: flex;
    gap: 10px;
    align-items: stretch;
}
.browse .search-submit {
    flex: 0 0 auto;
    padding: 0 26px;
    border-radius: 13px;
    font-size: 0.9rem;
    font-weight: 700;
}

/* —— Labelled filter shells ——
   The old bare selects all read as identical text boxes: "All Sets" gave no
   clue it was the set filter. Each control now carries its own caption and
   turns accent-coloured the moment it holds a value. */
.browse .search-bar__row--filters,
.browse .search-bar__row--advanced {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: stretch;
}
.browse .search-bar__row[hidden] { display: none; }
.browse .search-bar__row--advanced {
    padding-top: 12px;
    border-top: 1px solid var(--surf-border);
}

/* —— Has-image checkbox —— */
.browse .filter-check {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    flex: 0 1 auto;
    min-height: 52px;
    padding: 0 16px;
    background: var(--surf-input);
    border: 1px solid var(--surf-border);
    border-radius: 13px;
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color 0.18s, background 0.18s, color 0.18s;
}
.browse .filter-check:hover { border-color: var(--surf-border-strong); }
.browse .filter-check.is-active {
    background: var(--surf-accent-tint);
    border-color: var(--surf-accent-border);
    color: var(--text-primary);
}
.browse .filter-check input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--accent);
    cursor: pointer;
}

/* —— More filters toggle —— */
.browse .filter-toggle {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 52px;
    padding: 0 18px;
    background: var(--surf-input);
    border: 1px solid var(--surf-border);
    border-radius: 13px;
    color: var(--text-secondary);
    font-size: 0.84rem;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color 0.18s, background 0.18s, color 0.18s;
}
.browse .filter-toggle:hover {
    border-color: var(--surf-border-strong);
    color: var(--text-primary);
}
.browse .filter-toggle[aria-expanded="true"] {
    background: var(--surf-accent-tint);
    border-color: var(--surf-accent-border);
    color: var(--surf-accent-ink);
}

/* ============================================================
   3. Active filter chips — every applied filter is visible and
      individually removable, rebuilt by JS on each change.
   ============================================================ */
.browse-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 18px;
}
.browse-chips[hidden] { display: none; }
.chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 6px 6px 12px;
    border-radius: 999px;
    background: var(--surf-accent-tint);
    border: 1px solid var(--surf-accent-border);
    font-size: 0.8rem;
    color: var(--text-primary);
    text-decoration: none;
    max-width: 100%;
}
.chip__label {
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--surf-accent-ink);
}
.chip__value {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chip__x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-muted);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s, color 0.15s;
}
.chip__x:hover {
    background: var(--surf-accent-ring);
    color: var(--text-primary);
}
.chip--clear {
    padding: 7px 14px;
    background: transparent;
    border-color: var(--surf-border-strong);
    color: var(--text-muted);
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}
.chip--clear:hover {
    border-color: var(--surf-accent-border);
    color: var(--surf-accent-ink);
}

/* ============================================================
   5. Empty state, pagination, load more
   ============================================================ */
.browse .browse-empty {
    padding: 64px 24px;
    background: var(--surf-surface);
    border: 1px solid var(--surf-border);
    border-radius: 20px;
    box-shadow: var(--surf-shadow);
    color: var(--text-secondary);
}
.browse .empty-state__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 62px;
    height: 62px;
    margin-bottom: 18px;
    border-radius: 50%;
    background: var(--surf-accent-tint);
    color: var(--surf-accent-ink);
    font-size: 1.4rem;
}
.browse .empty-state__title {
    margin: 0 0 8px;
    font-size: var(--step-2);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--text-primary);
}

.browse .pagination { margin-top: 32px; }
.browse .page-btn {
    min-width: 40px;
    padding: 9px 14px;
    background: var(--surf-surface);
    border: 1px solid var(--surf-border);
    border-radius: 11px;
    color: var(--text-secondary);
    font-weight: 600;
    text-align: center;
}
.browse .page-btn:hover {
    border-color: var(--surf-accent-border);
    color: var(--surf-accent-ink);
    background: var(--surf-accent-tint);
}
.browse .page-btn.active {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.browse .load-more-wrap { margin: 30px 0 0; }
.browse #loadMore {
    min-width: 240px;
    padding: 13px 28px;
    border-radius: 13px;
    background: var(--surf-surface);
    border: 1px solid var(--surf-border-strong);
    color: var(--text-primary);
    font-weight: 700;
    box-shadow: var(--surf-shadow);
}
.browse #loadMore:hover:not(:disabled) {
    border-color: var(--surf-accent-border);
    color: var(--surf-accent-ink);
    background: var(--surf-accent-tint);
}
.browse #loadMore:disabled { opacity: 0.5; cursor: default; }

/* ============================================================
   6. Responsive
   ============================================================ */
/* ============================================================
   6. Responsive  (tile-side responsive rules live in ui-kit.css)
   ============================================================ */
@media (max-width: 900px) {
    .browse-head__count { order: 3; }
}

@media (max-width: 700.98px) {
    .browse-head {
        padding-top: 13px;
        padding-bottom: 40px;
    }
    .browse-head__sub { display: none; }
    .browse-head__inner {
        align-items: center;
        flex-wrap: nowrap;
    }
    /* The pill, not the h1, was setting this band's height. */
    .browse-head__count {
        order: 0;
        padding: 5px 11px;
        font-size: 0.72rem;
    }
    .browse .search-panel {
        margin: -28px 0 12px;
        padding: 11px;
        border-radius: 16px;
    }
    /* "Browse cards" at --step-4 ran ~34px on a phone and cost a third of the
       chrome above the first result; the bottom tab bar already labels the
       page, so the h1 stays for structure but stops shouting. */
    .browse-head__title { font-size: 1.4rem; letter-spacing: -0.02em; }
    /* The submit was eating 133px of a 348px row and clipping the placeholder
       mid-word ("…or r"). */
    .browse .search-input { padding: 12px 12px 12px 38px; font-size: 0.9rem; }
    .browse .search-submit { padding: 0 14px; font-size: 0.86rem; }

    /* One horizontally-scrollable rail instead of a wrapped block — keeps the
       panel around 130px tall so results stay above the fold. */
    .browse .search-bar__row--filters {
        flex-wrap: nowrap;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        margin: 0 -11px;
        padding: 0 11px 2px;
        scroll-padding-left: 11px;
    }
    .browse .search-bar__row--filters::-webkit-scrollbar { display: none; }
    /* The rail overflows silently — "All rarities" sits half-cut at the right
       edge with nothing to say it scrolls. A mask fades the last 26px so the
       clipped shell reads as "more this way" instead of as a layout bug.
       The fade is static, not scroll-linked: at the far right end the last
       shell carries a light fade it has not earned. Scroll-linked masking
       needs animation-timeline, which is not worth a progressive-enhancement
       block for 26px of gradient. */
    .browse .search-bar__row--filters {
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
        mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
    }
    .browse .search-bar__row--filters > * {
        flex: 0 0 auto;
        max-width: none;
        white-space: nowrap;
    }
    .browse .search-bar__row--advanced > * { flex: 1 1 150px; max-width: none; }
    .browse .filter-check { flex: 1 1 100%; justify-content: flex-start; }

}

@media (pointer: coarse) {
    .browse .chip__x { width: 26px; height: 26px; }
}

/* ── Infinite-scroll status ───────────────────────────────────────────
   Replaces the load-more button while the next page is in flight. The row
   keeps the button's height so the grid does not jump as pages append. */
.browse .load-more-status {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-height: 48px;
    color: var(--text-muted);
    font-size: 0.9rem;
    font-weight: 500;
}
.browse .load-more-status__ring {
    width: 17px;
    height: 17px;
    border-radius: 50%;
    border: 2px solid var(--surf-border-strong, rgba(255, 255, 255, 0.18));
    border-top-color: var(--accent);
    animation: browse-spin 0.7s linear infinite;
}
@keyframes browse-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    .browse .load-more-status__ring { animation-duration: 2.4s; }
}
