/* The product list (/products): filter sidebar, results bar, chips, grid, load more.
   On phones the filters become a bottom sheet, but only once JS is running (html.js);
   without JS they stay inline above the results and submit with the Apply button. */

@layer pages {
  .catalog { display: flex; flex-direction: column; gap: var(--space-6); }

  /* Only holds the hidden search input; no box, so no extra gap. */
  .catalog > [data-swap="query"] { display: contents; }

  /* Filters */
  .filters { display: flex; flex-direction: column; gap: var(--space-5); }

  .filters__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }

  .filters__title { font-size: var(--fs-xl); }

  .filters__clear { font-size: var(--fs-sm); font-weight: 600; }

  .filters__close { display: none; }

  .filters__body { display: flex; flex-direction: column; gap: var(--space-5); }

  .filter-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: var(--space-5);
    border-bottom: 1px solid var(--bp-line);
  }

  .filter-group:last-child { border-bottom: 0; padding-bottom: 0; }

  .filter-group__legend { margin-bottom: var(--space-2); font-size: var(--fs-xs); font-weight: 700; letter-spacing: var(--tracking-label); text-transform: uppercase; }

  .filter-option {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: var(--control-h);
    font-size: var(--fs-sm);
    cursor: pointer;
  }

  .filter-option input { width: 18px; height: 18px; margin: 0; accent-color: var(--bp-brand-600); flex: none; }
  .filter-option--depth-1 { padding-inline-start: 22px; }
  .filter-option--depth-2 { padding-inline-start: 44px; }
  .filter-option__label { flex: 1; }
  .filter-option__count { font-size: var(--fs-xs); color: var(--bp-ink-2); }

  /* Finding one artist in a long list. Needs script, so it only shows with it; it stays in view while
     the list scrolls under it. */
  .filter-search { display: none; }
  .js .filter-search {
    position: sticky;
    top: 0;
    z-index: 1;
    display: block;
    margin-bottom: var(--space-2);
    padding-block: 2px;
    background: var(--bp-paper);
  }

  .filter-search__icon { position: absolute; inset-inline-start: 12px; top: 50%; transform: translateY(-50%); font-size: 18px; color: var(--bp-ink-3); pointer-events: none; }
  .filter-search__input { min-height: 40px; padding-inline-start: 38px; font-size: var(--fs-sm); }
  .filter-search__none { font-size: var(--fs-sm); color: var(--bp-ink-2); }

  .filters__foot { display: none; }

  .js .filters__apply { display: none; }

  @media (min-width: 820px) {
    .catalog { flex-direction: row; align-items: flex-start; gap: var(--space-10); }

    /* Stays in view while the results scroll. Sticky only holds while the box fits the window, and
       the list of artists is long, so the box is capped at the window's height and its options scroll
       on their own; the heading and "Clear all" stay put. */
    .filters {
      position: sticky;
      top: var(--space-6);
      flex: 0 0 260px;
      max-height: calc(100dvh - 2 * var(--space-6));
      gap: var(--space-4);
    }

    .filters__body {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      scrollbar-width: thin;
      scrollbar-color: var(--bp-line-strong) transparent;
      scrollbar-gutter: stable;
      padding-inline-end: var(--space-2);
    }

    .filter-option { min-height: 36px; }
  }

  /* Phone bottom sheet */
  .is-scroll-locked body { overflow: hidden; }

  /* #main's view-transition name (page-transition.css) makes it a stacking layer of its own, painted
     under the header, so no z-index inside it can lift the sheet and its scrim above the header. While
     the sheet is open #main gives up the name, and both stack against the whole page. */
  html:has(.filters.is-open) #main { view-transition-name: none; }

  @media (max-width: 819.98px) {
    .js .filters {
      position: fixed;
      inset-inline: 0;
      bottom: 0;
      z-index: calc(var(--z-drawer) + 1);
      max-height: 88dvh;
      gap: 0;
      border-radius: var(--radius-xl) var(--radius-xl) 0 0;
      background: var(--bp-surface);
      box-shadow: var(--shadow-lg);
      transform: translateY(100%);
      visibility: hidden;
      transition: transform 200ms var(--ease), visibility 200ms;
    }

    .js .filters.is-open { transform: none; visibility: visible; }

    .js .filters__head { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--bp-line); }
    .js .filters__close { display: inline-grid; }
    .js .filters .filter-search { background: var(--bp-surface); }
    .js .filters__clear { display: none; }

    .js .filters__body {
      overflow-y: auto;
      overscroll-behavior: contain;
      padding: var(--space-3) var(--space-5);
    }

    .js .filters__foot {
      display: flex;
      gap: 10px;
      padding: 14px var(--space-5) calc(16px + env(safe-area-inset-bottom));
      border-top: 1px solid var(--bp-line);
    }

    .js .filters__foot > :first-child { flex: 1; }
    .js .filters__foot > :last-child { flex: 2; }

    .filters-scrim {
      position: fixed;
      inset: 0;
      z-index: var(--z-drawer);
      background: var(--bp-scrim);
      opacity: 0;
      visibility: hidden;
      transition: opacity 200ms, visibility 200ms;
    }

    .filters-scrim.is-open { opacity: 1; visibility: visible; }
  }

  @media (min-width: 820px) {
    .filters-scrim { display: none; }
  }

  /* Results */
  .results { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-5); }

  .results[aria-busy="true"] .product-grid { opacity: .55; transition: opacity var(--dur); }

  /* While a new list loads (products.js): the filters and results dim and take no input (they are
     inert), and a small pill says what is happening. It waits a moment, so a quick answer doesn't flash it. */
  .catalog.is-loading .filters,
  .catalog.is-loading .results { cursor: progress; }
  .catalog.is-loading .filters__body,
  .catalog.is-loading .results-bar,
  .catalog.is-loading .active-filters { opacity: .55; transition: opacity var(--dur); }

  .catalog-loading {
    position: fixed;
    left: 50%;
    bottom: calc(var(--space-6) + max(var(--tab-bar-h), env(safe-area-inset-bottom)));
    z-index: var(--z-toast);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 10px 18px;
    border-radius: var(--radius-pill);
    background: var(--bp-ink);
    color: var(--bp-paper);
    font-size: var(--fs-sm);
    font-weight: 600;
    box-shadow: var(--shadow-lg);
    transform: translateX(-50%);
    animation: catalog-loading-in var(--dur) 120ms both;
  }

  .catalog-loading__spinner {
    width: 16px;
    height: 16px;
    border: 2px solid currentColor;
    border-inline-end-color: transparent;
    border-radius: 50%;
    animation: catalog-spin .7s linear infinite;
  }

  @keyframes catalog-loading-in { from { opacity: 0; transform: translate(-50%, 8px); } }
  @keyframes catalog-spin { to { transform: rotate(360deg); } }

  .results-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 12px;
  }

  .results-bar__count { margin: 0; font-size: 15px; color: var(--bp-ink-2); }
  .results-bar__count strong { color: var(--bp-ink); }

  .results-bar__controls { display: flex; align-items: center; gap: 10px; }

  .results-bar__sort-label { font-size: var(--fs-sm); color: var(--bp-ink-2); }

  .select {
    min-width: 0;
    height: var(--control-h);
    padding: 0 14px;
    border: 0;
    border-bottom: 1px solid var(--bp-ink);
    border-radius: 0;
    background: transparent;
    color: var(--bp-ink);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
  }

  .filters-toggle { display: none; }

  .count-pill {
    display: inline-grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 10px;
    background: var(--bp-brand-600);
    color: var(--bp-on-primary);
    font-size: var(--fs-xs);
  }

  @media (max-width: 819.98px) {
    .results-bar {
      position: sticky;
      top: 0;
      z-index: var(--z-sticky);
      margin-inline: calc(var(--gutter) * -1);
      padding: 10px var(--gutter);
      background: var(--bp-paper);
      border-bottom: 1px solid var(--bp-line);
    }

    .results-bar__count { order: 2; }
    .results-bar__controls { flex: 1 1 100%; }
    .results-bar__sort-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
    .results-bar__controls .select { flex: 1; font-size: var(--fs-md); }

    .js .filters-toggle { display: inline-flex; flex: 1; }
  }

  /* Active filter chips */
  .active-filters { display: flex; flex-wrap: wrap; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }

  .chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 34px;
    padding: 0 8px 0 12px;
    border: 1px solid var(--bp-line-strong);
    border-radius: var(--radius-xs);
    background: var(--bp-surface);
    color: var(--bp-ink);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
  }

  .chip:hover { border-color: var(--bp-brand-600); color: var(--bp-brand-600); }
  .chip .icon { font-size: 18px; }

  /* Empty state */
  .empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: var(--space-12) var(--space-6);
    border: 1px dashed var(--bp-line-strong);
    background: transparent;
    text-align: center;
  }

  .empty-state__icon {
    display: grid;
    place-items: center;
    width: 64px;
    height: 64px;
    border-radius: 46% 54% 50% 50% / 55% 45% 55% 45%;
    background: var(--bp-brand-50);
    color: var(--bp-brand-600);
  }

  .empty-state__icon .icon { font-size: 32px; }
  .empty-state__title { font-family: var(--font-display); font-size: var(--fs-2xl); font-style: italic; font-weight: 300; color: var(--bp-heading); }
  .empty-state__text { color: var(--bp-ink-2); }
  .empty-state .button { margin-top: 6px; }

  /* Load more */
  .load-more { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); padding-top: var(--space-5); }
  .load-more__status { font-size: var(--fs-sm); color: var(--bp-ink-2); }

  .load-more__progress {
    width: 200px;
    height: 4px;
    border: 0;
    border-radius: 2px;
    background: var(--bp-paper-2);
    overflow: hidden;
    appearance: none;
  }

  .load-more__progress::-webkit-progress-bar { background: var(--bp-paper-2); }
  .load-more__progress::-webkit-progress-value { background: var(--bp-brand-600); }
  .load-more__progress::-moz-progress-bar { background: var(--bp-brand-600); }
}
