/* ==========================================================================
   GENESIS shop - search results + filter rail
   Design source: "Nuova proposta grafica.dc.html" -> data-screen-label="Web — Risultati" (Turn 4)

   Scoped under .gns-shop, which also carries `gns-scope` so gns-base.css
   neutralises the parent theme's legacy globals. Loaded only on shop and
   product-archive screens.
   ========================================================================== */

.gns-shop {
  --rail-w: 270px;
  /* ⚠️ The site header is `position: fixed` (121px, or 143px with the beta
     banner). The theme exposes its height as --top-margin and the parent offsets
     `.shop-container` by it. This layout replaces that container, so it has to
     carry the same offset - without it the filter rail and the results header
     render underneath the header and are invisible. */
  --gns-header-h: var(--top-margin, 113px);

  display: grid;
  grid-template-columns: var(--rail-w) 1fr;
  align-items: start;
  background: var(--gns-bg);
  color: var(--gns-text);
  min-height: 70vh;
  margin-top: var(--gns-header-h);
}

/* ⚠️ The legacy class names stay on these elements because the parent's JS
   binds to them - `.custom-sidebar` is the mobile filter drawer (open/close)
   and `.shop-main-content` scopes the pagination click handler. But their
   parent-theme widths were written for the old float layout:
   `.shop-main-content { width: calc(100% - 290px) }` subtracts the sidebar a
   second time inside this grid, collapsing the results column. Neutralise the
   sizing, keep the hooks. */
.gns-shop .shop-main-content,
.gns-shop .custom-sidebar {
  width: auto;
  max-width: none;
  float: none;
}

/* ============================================================ filter rail === */

.gns-rail {
  border-right: 1px solid var(--gns-border-faint);
  padding: 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  position: sticky;
  /* Stick below the fixed site header, not under it. */
  top: var(--gns-header-h);
  align-self: start;
  max-height: calc(100vh - var(--gns-header-h));
  overflow-y: auto;
}

.gns-rail__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.gns-rail__head b { font-size: 15px; font-weight: 700; }
.gns-rail__reset {
  font-size: 11.5px;
  color: var(--gns-cyan-ink);
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0;
}
.gns-rail__reset:hover { text-decoration: underline; }

/* The groups live inside <form id="shop-filters">, so the rail's own gap does
   not separate them - the form is a single flex child. Space them here. */
.gns-rail #shop-filters {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin: 0;
}

.gns-group { display: flex; flex-direction: column; gap: 9px; }
.gns-group__label {
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted);
}

/* ------------------------------------------------------ option lists ------ */

.gns-options {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-size: 12.5px;
  max-height: 210px;
  overflow-y: auto;
  padding-right: 4px;
}

/* Long lists (264 printers) need a scrollbar, but the native one is a bright
   slab against the dark rail. */
.gns-rail,
.gns-options { scrollbar-width: thin; scrollbar-color: var(--gns-border-heavy) transparent; }
.gns-rail::-webkit-scrollbar,
.gns-options::-webkit-scrollbar { width: 6px; }
.gns-rail::-webkit-scrollbar-track,
.gns-options::-webkit-scrollbar-track { background: transparent; }
.gns-rail::-webkit-scrollbar-thumb,
.gns-options::-webkit-scrollbar-thumb {
  background: var(--gns-border-heavy);
  border-radius: 3px;
}
.gns-rail::-webkit-scrollbar-thumb:hover,
.gns-options::-webkit-scrollbar-thumb:hover { background: var(--gns-secondary); }

/* The design shows checkboxes. The filter backend takes ONE value per group, so
   these are radios wearing a checkbox's clothes - see sidebar-shop.php. */
.gns-option {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--gns-secondary-2);
  cursor: pointer;
  line-height: 1.35;
}
.gns-option input { position: absolute; opacity: 0; width: 0; height: 0; }
.gns-option i {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  border-radius: 4px;
  border: 1.5px solid var(--gns-muted);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  font-style: normal;
  font-size: 9px;
  color: transparent;
  transition: background .15s ease, border-color .15s ease;
}
.gns-option input:checked + i {
  background: var(--gns-cyan);
  border-color: var(--gns-cyan);
  color: var(--gns-on-accent);
}
.gns-option input:checked ~ span { color: var(--gns-text); }
.gns-option input:focus-visible + i { box-shadow: 0 0 0 3px var(--gns-cyan-tint-2); }

/* ------------------------------------------------------------- pills ------ */

.gns-pills { display: flex; flex-wrap: wrap; gap: 7px; }
.gns-pill {
  height: 28px;
  padding: 0 12px;
  border-radius: var(--gns-r-pill);
  border: 1px solid var(--gns-border-strong);
  background: none;
  display: inline-flex;
  align-items: center;
  font-size: 11.5px;
  color: var(--gns-secondary-2);
  cursor: pointer;
  white-space: nowrap;
}
.gns-pill:hover { color: var(--gns-text); border-color: var(--gns-border-heavy); }
.gns-pill.selected {
  background: var(--gns-text);
  color: var(--gns-bg);
  border-color: var(--gns-text);
  font-weight: 700;
}

/* -------------------------------------------------------- price range ----- */

.gns-range { display: flex; flex-direction: column; gap: 11px; }
.gns-range__track {
  position: relative;
  height: 4px;
  border-radius: 2px;
  background: var(--gns-tint-strong);
  margin: 7px 0;
}
.gns-range__fill {
  position: absolute;
  top: 0;
  bottom: 0;
  border-radius: 2px;
  background: var(--gns-gradient);
}
/* Two overlaid native range inputs give real keyboard and touch behaviour;
   the visible track above is drawn from their values. */
.gns-range input[type="range"] {
  position: absolute;
  left: 0;
  top: -7px;
  width: 100%;
  height: 18px;
  margin: 0;
  padding: 0;
  background: none !important;
  border: 0;
  appearance: none;
  -webkit-appearance: none;
  pointer-events: none;
}
.gns-range input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--gns-text);
  border: 0;
  cursor: pointer;
  pointer-events: auto;
}
.gns-range input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--gns-text);
  border: 0;
  cursor: pointer;
  pointer-events: auto;
}
.gns-range__values {
  display: flex;
  justify-content: space-between;
  font: 500 11px var(--gns-font-mono);
  color: var(--gns-secondary-2);
}

/* ------------------------------------------------------------ toggles ----- */

.gns-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 13px;
  border-radius: var(--gns-r-input);
  border: 1px solid var(--gns-border-faint);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.gns-toggle__text { display: flex; flex-direction: column; gap: 2px; }
.gns-toggle__text b { font-size: 12.5px; font-weight: 400; color: var(--gns-text); }
.gns-toggle__text span { font-size: 10.5px; color: var(--gns-muted); }
.gns-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.gns-toggle i {
  flex: 0 0 auto;
  width: 34px;
  height: 20px;
  border-radius: var(--gns-r-pill);
  background: var(--gns-tint-strong-2);
  position: relative;
  transition: background .15s ease;
}
.gns-toggle i::after {
  content: "";
  position: absolute;
  left: 2px;
  top: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gns-secondary-2);
  transition: transform .15s ease, background .15s ease;
}
.gns-toggle input:checked + i { background: var(--gns-cyan); }
.gns-toggle input:checked + i::after {
  transform: translateX(14px);
  background: var(--gns-on-accent);
}
.gns-toggle:has(input:checked) {
  border-color: var(--gns-border-cyan);
  background: var(--gns-cyan-tint);
}
.gns-toggle input:focus-visible + i { box-shadow: 0 0 0 3px var(--gns-cyan-tint-2); }

/* ============================================================== results === */

.gns-results { display: flex; flex-direction: column; min-width: 0; }

.gns-results__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 28px;
  border-bottom: 1px solid var(--gns-border-faint);
}
.gns-results__title { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.gns-results__title h1 {
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -.02em;
  margin: 0;
}
.gns-results__count { font-size: 12.5px; color: var(--gns-secondary-2); }

.gns-results__tools { display: flex; align-items: center; gap: 10px; }
.gns-results__tools > span {
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-sort {
  height: 34px;
  padding: 0 32px 0 14px;
  border-radius: var(--gns-r-pill);
  border: 1px solid var(--gns-border-strong);
  background-color: transparent !important;
  color: var(--gns-text) !important;
  font-size: 12.5px;
  cursor: pointer;
  /* Native arrow is invisible on a dark pill; draw our own. */
  appearance: none;
  -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--gns-secondary-2) 50%),
                    linear-gradient(135deg, var(--gns-secondary-2) 50%, transparent 50%);
  background-position: right 15px center, right 10px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.gns-sort option { background: var(--gns-surface); color: var(--gns-text); }

/* --------------------------------------------------------- product grid --- */

/*
 * ⚠️ FLUID COLUMN COUNT, not a fixed four.
 *
 * The canvas draws `repeat(4, 1fr)` at 1440px, and four was read off that one
 * screen. But the canvas is a fixed-width artboard and this is a browser: at
 * 1440 the results area is ~1099px, so four cards land at the 264px the design
 * draws - and on a 1920 monitor that same rule stretched them to 380px, which
 * is not the design's card, it is the design's card blown up.
 *
 * `auto-fill` with a 240px floor holds the card near its drawn size and lets
 * the COUNT answer the screen instead: 4 at 1440, 5 at ~1600, 6 at ~1850,
 * more beyond. The `1fr` ceiling means a row is always exactly full, so the
 * grid stays tidy at every width rather than leaving a ragged tail.
 */
.gns-shop ul.products,
.gns-shop .products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  padding: 20px 28px 24px;
  margin: 0;
  list-style: none;
}

/*
 * ⚠️ THE EMPTY FIRST SLOT. WooCommerce clears its float layout with
 * `ul.products::before/::after { content: " "; display: table }`. Those were
 * written for a float grid, where they collapse to nothing - but in a GRID
 * container a pseudo-element is a grid ITEM, so `::before` was taking the whole
 * first cell (measured: 249.25px wide, the exact column width) and pushing the
 * first product into column two, with `::after` taking a second cell at the
 * end.
 *
 * archive.css already cancels these for the printers archive; the shop grid
 * never did, so every result page has been starting one slot late.
 */
.gns-shop ul.products::before,
.gns-shop ul.products::after,
.gns-shop .products::before,
.gns-shop .products::after {
  content: none;
}

/* The float/width reset that makes these grid items behave now lives in
   card.css, because the card renders from seven callers and only two of them
   are this file's screens. See the note there. */

/* Product card rules live in card.css - they are shared with every other
   template that runs the product loop (creator store, printers, sales,
   best-seller, favourites). See the note at the top of that file. */

.gns-empty { padding: 60px 28px; color: var(--gns-secondary); text-align: center; }
.gns-shop .gns-pagination { padding: 0 28px 32px; }

/* ------------------------------------------------------------ responsive -- */

/* No 1280px step any more: auto-fill drops to three columns on its own when
   the results area passes below ~3 x 254px, and to two below ~2 x 254. The
   fixed steps that remain are the small-screen floors, where a 240px card no
   longer fits the viewport at all and the count has to be forced. */
/* --------------------------------------------------- filter disclosure --- */
/*
 * The control rendered by archive-product.php just above the rail. It does not
 * exist on desktop, where the rail is a column of its own and always open.
 */
.gns-filter-btn { display: none; }

@media (max-width: 1024px) {
  .gns-shop { grid-template-columns: 1fr; }
  .gns-rail {
    position: static;
    max-height: none;
    border-right: 0;
    border-bottom: 1px solid var(--gns-border-faint);
  }

  /*
   * Collapsed by default. Stacked, the rail is six filter groups and ~40
   * controls, so on a phone the entire first screen was the filter form and the
   * first product sat below the fold - on the results page, whose job is to
   * show results. The rail is still the first thing in the column, just folded
   * into a 46px bar until it is asked for.
   */
  .gns-shop .gns-rail { display: none; }
  .gns-shop .gns-filter-toggle:checked ~ .gns-rail { display: flex; }

  .gns-filter-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 16px 16px 0;
    padding: 0 16px;
    min-height: 46px;
    border: 1px solid var(--gns-border-strong);
    border-radius: var(--gns-r-pill);
    color: var(--gns-text);
    font-size: 13.5px;
    font-weight: 500;
    cursor: pointer;
    user-select: none;
  }
  .gns-filter-btn:hover { border-color: var(--gns-border-cyan); }
  /* The checkbox is clipped, so its focus ring has to be drawn on the label. */
  .gns-shop .gns-filter-toggle:focus-visible ~ .gns-filter-btn {
    outline: 2px solid var(--gns-focus);
    outline-offset: 2px;
  }

  /* The chevron is the open/closed state, so it is the one thing that turns. */
  .gns-filter-btn__chev {
    margin-left: auto;
    font-size: 11px;
    color: var(--gns-secondary-2);
    transition: transform .15s ease;
  }
  .gns-shop .gns-filter-toggle:checked ~ .gns-filter-btn .gns-filter-btn__chev {
    transform: rotate(180deg);
  }
}
/*
 * The mobile filter drawer. Below 768px the parent slides `.custom-sidebar` in
 * from off-canvas and paints it `background: #fff` (style.css, inside
 * `@media (max-width: 767.98px)`) - a rule that never runs on desktop, which
 * is why a desktop-only audit reported this page clean while the drawer showed
 * the redesign's light text on white: 350 elements under 4.5:1 in dark, the
 * whole filter rail unreadable.
 *
 * Surface rather than the page ground: the drawer slides OVER the results, and
 * the parent's own drop shadow reads better against a panel that is a step
 * away from what is behind it.
 */
@media (max-width: 767.98px) {
  .gns-shop .custom-sidebar {
    background: var(--gns-surface) !important;
    border-right: 1px solid var(--gns-border);
  }
}

@media (max-width: 720px) {
  .gns-shop ul.products, .gns-shop .products {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    padding: 16px;
    gap: 12px;
  }
  .gns-results__head { padding: 16px; }
}
@media (max-width: 420px) {
  .gns-shop ul.products, .gns-shop .products { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------- sort select --- */
/*
 * The parent styles this control by ID - `#orderby-custom { border: 1px solid
 * var(--wp--preset--color--lightgrey) }` - and an ID (1,0,0) outranks the
 * `.gns-sort` rule above (0,1,0), so the redesign's border never applied and
 * the select kept a near-white outline on the dark ground.
 *
 * `#orderby-custom.gns-sort` is (1,1,0): the same ID plus the class, which is
 * the minimum needed to win. Repeating the token rather than reaching for
 * !important keeps the value in one place conceptually.
 */
#orderby-custom.gns-sort {
  border: 1px solid var(--gns-border-strong);
}

/* ========================================================= view toggle === */
/*
 * Canvas "Web - Risultati": the grid/list pair to the right of SORT BY.
 * Same shape as the appearance switch, so the two read as one family.
 */
.gns-view {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-pill);
  background: var(--gns-tint);
}
.gns-view__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--gns-r-pill);
  background: transparent;
  color: var(--gns-secondary);
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.gns-view__btn svg { fill: currentColor; }
.gns-view__btn:hover { color: var(--gns-text); }
.gns-view__btn.is-active {
  background: var(--gns-gradient);
  color: var(--gns-on-accent);
}

@media (pointer: coarse) {
  .gns-view__btn { width: 44px; height: 40px; }
}

/* ------------------------------------------------------------ list view -- */
/*
 * One row per result: the media block shrinks to a fixed thumbnail and the
 * body runs beside it. Only the grid template and the card's own axis change -
 * the card component itself is untouched, so both views stay in step.
 */
.gns-results.is-list ul.products,
.gns-results.is-list .products {
  grid-template-columns: 1fr;
  gap: 10px;
}
/*
 * ⚠️ The selector is this long on purpose. Both WooCommerce and the parent set
 * an explicit width on the list item for their float layout, and the parent's
 * lives in a media query:
 *
 *   @media (max-width: 1200px) .woocommerce ul.products[class*="columns-"]
 *     li.product { width: calc(33.33% - 10px) }        (0,3,2)
 *
 * which is why a shorter `.gns-results.is-list .gns-card` (0,3,0) left every
 * row at exactly a third of the track. `ul.products li.gns-card` under the two
 * state classes is (0,4,2) and clears all of them without !important.
 */
.gns-results.is-list ul.products li.gns-card,
.gns-results.is-list .products li.gns-card {
  flex-direction: row;
  align-items: stretch;
  width: auto;
  max-width: none;
  margin-inline: 0;
}
/*
 * ⚠️ The `li.gns-card >` in these two is what keeps list mode working. card.css
 * pins both children to `flex: 0 0 auto; width: 100%` so the grid card cannot
 * wrap into two columns (see the note there), at (0,3,0) - the same weight a
 * plain `.gns-results.is-list .gns-card__media` carries, leaving which one wins
 * to the order the stylesheets happen to load in. The child combinator takes
 * these to (0,4,1) and settles it.
 */
.gns-results.is-list ul.products li.gns-card > .gns-card__media,
.gns-results.is-list .products li.gns-card > .gns-card__media {
  flex: 0 0 132px;
  width: 132px;
  aspect-ratio: auto;
}
.gns-results.is-list ul.products li.gns-card > .gns-card__body,
.gns-results.is-list .products li.gns-card > .gns-card__body {
  flex: 1 1 auto;
  width: auto;
  justify-content: center;
  padding: 14px 16px;
}
.gns-results.is-list .gns-card__name {
  -webkit-line-clamp: 1;
  font-size: 14px;
}
/* With a full row to work in, the price can sit out at the end rather than
   under the name. */
.gns-results.is-list .gns-card__foot {
  justify-content: flex-start;
  gap: 16px;
}

@media (max-width: 560px) {
  .gns-results.is-list .gns-card__media { flex-basis: 96px; width: 96px; }
}

/* ========================================================== load more === */
/*
 * Canvas "Web - Risultati": "Altri 93 risultati" over a "Carica altri" button,
 * in place of page numbers. The numbered pagination is still in the document
 * underneath and is unhidden again whenever the button cannot do its job -
 * see the note in assets/js/shop-filters.js.
 */
.gns-more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 8px 28px 40px;
}
.gns-more__count {
  margin: 0;
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-more__btn {
  min-width: 190px;
  height: 44px;
  padding: 0 26px;
  border: 1px solid var(--gns-border-strong);
  border-radius: var(--gns-r-pill);
  background: var(--gns-tint);
  color: var(--gns-text);
  font-family: var(--gns-font);
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}
.gns-more__btn:hover:not([disabled]) {
  border-color: var(--gns-border-cyan);
  background: var(--gns-cyan-tint);
}
.gns-more__btn[disabled] { opacity: .55; cursor: default; }

/* ------------------------------------------ load more: scroll + states --- */
/*
 * The pieces assets/js/load-more.js builds. They are created in JS, not in the
 * templates, because none of them mean anything without it - with no script the
 * page falls back to the numbered pagination and none of this exists.
 *
 * Unscoped on purpose: shop.css is loaded by the secondary archives too (see
 * the note at the top of archive.css), and both surfaces run the same script.
 */

/* Where the observer watches for the fold. Never seen. */
.gns-more__sentinel { height: 1px; }

/*
 * The running commentary, for screen readers only. The visible count beside the
 * button already says how many results are left, so announcing it again on
 * screen would just be the same sentence twice.
 */
.gns-more__status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The end of the list is a statement, not a control - the button is gone. */
.gns-more.is-done { padding-top: 0; }
.gns-more.is-done .gns-more__count { color: var(--gns-secondary-2); }

/* Once the automatic batches are spent, the button is the way on: say so. */
.gns-more.is-manual .gns-more__btn { border-color: var(--gns-border-cyan); }

/* ------------------------------------------------------------ skeleton --- */
/*
 * Placeholders for the page being fetched. They sit in their own list AFTER the
 * grid rather than inside it: the parent's AJAX replaces the whole contents of
 * `.products`, so anything parked in there is wiped mid-flight.
 */
.gns-skeleton {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0 28px;
  list-style: none;
}
.gns-skeleton__card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px;
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-card);
  background: var(--gns-surface);
}
.gns-skeleton__media {
  display: block;
  aspect-ratio: 1 / 1;
  border-radius: calc(var(--gns-r-card) - 4px);
}
.gns-skeleton__line { display: block; height: 10px; border-radius: 999px; }
.gns-skeleton__line--short { width: 55%; }

.gns-skeleton__media,
.gns-skeleton__line {
  background-image: linear-gradient(
    90deg,
    var(--gns-tint) 25%,
    var(--gns-elevated) 37%,
    var(--gns-tint) 63%
  );
  background-size: 400% 100%;
  /* @keyframes gns-shimmer now lives in loading.css, which is global: the
     cart's line-subtotal placeholder uses the same animation, and one
     declaration is better than two identical ones. */
  animation: gns-shimmer 1.4s ease infinite;
}

/* Newly appended cards arrive rather than appearing. */
@keyframes gns-card-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.products .gns-card--in { animation: gns-card-in .32s ease both; }

@media (prefers-reduced-motion: reduce) {
  .gns-skeleton__media,
  .gns-skeleton__line,
  .products .gns-card--in { animation: none; }
}

