/*
 * Archive shell: shop, category and (via ArchiveScreen — see its docblock)
 * product-search-results all share this markup.
 *
 * Only loaded on the shop/category route: Assets::screen() checks
 * is_search() before is_shop(), so a product search resolves to the
 * separate 'search' screen and this file is not enqueued there — Task 10's
 * own search.css is where the search-specific grid track (1fr / 320px,
 * global-constraints.md) belongs.
 */

.st-archive {
  display: grid;
  grid-template-columns: 268px 1fr;
  gap: 32px;
  align-items: start;
}

.st-archive__aside,
.st-archive__main {
  /*
   * A grid item defaults to min-width: auto, which refuses to shrink below
   * its content's intrinsic width. card.css hit exactly this on
   * .st-card-item (its own comment: a 23px sideways scroll at 360px); the
   * same fix is needed one level up here, or the aside's fixed 268px track
   * plus an unshrinkable .st-archive__main would push this grid — and the
   * whole page — wider than the viewport at narrow widths.
   *
   * Not provable by a test today: at this task's stage the aside is empty
   * (Tasks 4-6 populate it) and the product grid already carries its own
   * fix at the .st-card-item level, so nothing currently forces either
   * track wider than its share — see task-2-report.md.
   */
  min-width: 0;
}

/*
 * Task 9's real responsive design, replacing Task 2's interim
 * "grid-template-columns: 1fr below 899px" safety net (that rule only
 * existed to stop the fixed 268px column forcing horizontal overflow —
 * task-2-report.md — before this task's own breakpoints existed to refine
 * it).
 *
 * 900-1199px: same two-column shell, sidebar narrowed to 240px
 * (global-constraints.md) — .st-filters keeps rendering inline here, just
 * in a narrower track.
 */
@media (max-width: 1199px) {
  .st-archive {
    grid-template-columns: 240px 1fr;
  }
}

/*
 * <900px (600-899px AND the "mobile layout" below 600px — global-constraints.md
 * draws no further distinction for the sidebar under 600px, and there is no
 * separate spec for it there): .st-archive__aside now holds only the
 * "Filtros" toggle button in normal flow (initFilterSheet() in archive.js)
 * plus the sheet itself, which renders `position: fixed` and out of flow —
 * so the two-column grid is no longer the right shape; .st-archive__main
 * needs the full row, with the toggle's own row above it.
 */
@media (max-width: 899px) {
  .st-archive {
    grid-template-columns: 1fr;
  }
}

/*
 * Archive header: title, result counter and ordering form (Task 3).
 * .st-archive__title needs no font rule of its own — base.css's bare `h1`
 * selector already sets font-size: var(--st-size-h1) (34px, the handoff
 * value for this screen) plus the matching weight/tracking/line-height, so
 * duplicating that here would only risk the two drifting apart.
 */
.st-archive__header {
  margin-bottom: 24px;
}

.st-archive__title {
  margin-bottom: 16px;
}

.st-archive__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.st-archive__count {
  margin: 0;
  color: var(--st-muted);
  font-size: var(--st-size-body-sm);
}

.st-archive__orderby {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.st-archive__orderby-label {
  margin-bottom: 0;
  white-space: nowrap;
}

/*
 * archive.js hides this button with the plain `hidden` attribute once (and
 * only once) it has bound the ordering select's auto-submit — but `.st-btn`
 * (button.css) already sets `display: inline-flex` on it, and an AUTHOR
 * stylesheet rule beats the browser's own `[hidden] { display: none }` UA
 * rule regardless of selector specificity or source order (cascade origin
 * ranks above specificity). Confirmed live: without this rule the button
 * stayed fully visible with `hidden` set to `true` on the element. This is
 * the fix, not a reason to stop setting `hidden` in JS — `hidden` still
 * correctly drops the button from the accessibility tree and tab order.
 */
.st-archive__orderby-submit[hidden] {
  display: none;
}

.st-archive__orderby-select {
  width: auto;
  min-width: 180px;
}

@media (max-width: 599px) {
  .st-archive__meta {
    flex-direction: column;
    align-items: flex-start;
  }

  .st-archive__orderby {
    width: 100%;
  }

  .st-archive__orderby-select {
    flex: 1 1 auto;
    min-width: 0;
  }
}

/*
 * Filter sidebar shell (Task 4): "FILTROS"/"Limpar" head and the size
 * filter group, at `sleeptime_archive_sidebar`. White card, 2px ink
 * border — handoff, screen 03 ("Sidebar de filtros (card branco, borda 2 px)").
 *
 * Below 900px this same node becomes the bottom sheet's own content —
 * archive.js's initFilterSheet() moves it (not a copy) inside the
 * `#st-archive-filters-sheet` dialog built below; without JavaScript no
 * such wrapping ever happens, so it stays exactly this inline card, stacked
 * full-width under .st-archive's own <900px single-column rule above — a
 * real, always-usable fallback, not a broken control waiting on a script.
 */
.st-filters {
  background: var(--st-surface);
  border: var(--st-rule);
  padding: 20px;
}

.st-filters__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 16px;
  margin-bottom: 20px;
  border-bottom: var(--st-rule-thin);
}

.st-filters__title {
  margin: 0;
  color: var(--st-ink);
  font-size: var(--st-size-label);
  font-weight: var(--st-weight-bold);
  letter-spacing: var(--st-track-eyebrow);
  text-transform: uppercase;
}

/*
 * .st-filters__clear is a plain <a>: base.css's own `a`/`a:hover,a:active`
 * rules already give it exactly the handoff's "Link de lista (mega-menu,
 * rodapé, filtros): cor vai para #ae1800" behaviour (--st-ink at rest,
 * --st-accent-deep on hover/active) — restating either colour here would
 * only risk the two drifting apart.
 */
.st-filters__clear {
  /* Measured 44 x 21.7 at 360px — a text link is still a tap target, and the
     constraint is both axes, not just the one the text happens to fill. */
  display: inline-flex;
  align-items: center;
  min-height: var(--st-h-touch);
  font-size: var(--st-size-body-sm);
  font-weight: var(--st-weight-medium);
  text-decoration: underline;
}

.st-filters__form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Reset the native <fieldset>/<legend> box model before laying it out as a list. */
.st-filters__group {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  padding: 0;
  border: 0;
}

.st-filters__group-title {
  padding: 0 0 8px;
  color: var(--st-muted);
  font-size: var(--st-size-label);
  font-weight: var(--st-weight-bold);
  letter-spacing: var(--st-track-button);
  text-transform: uppercase;
}

/*
 * The tap target is the whole row, not the native checkbox alone —
 * min-height: var(--st-h-touch) (44px) on the <label> is what makes a
 * checkbox row satisfy "touch targets >= 44px on both axes"
 * (global-constraints.md); the row's own width is already the full sidebar
 * column, well past 44px.
 */
.st-filters__option {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--st-h-touch);
  cursor: pointer;
}

.st-filters__option:hover,
.st-filters__option:active {
  color: var(--st-accent-deep);
}

.st-filters__checkbox {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
}

.st-filters__option-label {
  color: var(--st-ink-2);
  font-size: var(--st-size-body-sm);
}

.st-filters__submit {
  align-self: flex-start;
}

/*
 * Firmeza: a 1/1/1 grid of toggle buttons, not checkboxes — task-5-brief.md
 * and bin/seed.sh's own comment ("screen 03's own filter buttons"). Active
 * state is a server-rendered `.st-filters__button--active` modifier
 * (ArchiveScreen::term_filter_options()'s own `checked` boolean), not a
 * `:checked` CSS selector: the native `<input type="radio">` is visually
 * hidden (.st-filters__button-input below), so no plain CSS selector could
 * reach the ANCESTOR button chrome from the checked DESCENDANT input
 * without `:has()` — driving the state from PHP, which already computes it
 * for the "checked" attribute, avoids that dependency entirely and keeps a
 * single source of truth.
 */
.st-filters__buttons {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.st-filters__button {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--st-h-touch);
  padding: 8px 4px;
  border: var(--st-border-width) solid var(--st-ink);
  background: var(--st-surface);
  color: var(--st-ink);
  font-size: var(--st-size-body-sm);
  font-weight: var(--st-weight-medium);
  text-align: center;
  cursor: pointer;
  transition:
    background-color var(--st-transition),
    color var(--st-transition),
    border-color var(--st-transition);
}

.st-filters__button:hover,
.st-filters__button:active {
  border-color: var(--st-accent-deep);
  color: var(--st-accent-deep);
}

/* --st-ink background, white text — global-constraints.md's exact wording for the active firmeza button. */
.st-filters__button--active {
  background: var(--st-ink);
  border-color: var(--st-ink);
  color: var(--st-surface);
}

.st-filters__button--active:hover,
.st-filters__button--active:active {
  background: var(--st-ink);
  border-color: var(--st-ink);
  color: var(--st-surface);
}

/*
 * Visually hidden, not display:none — the input stays in the accessibility
 * tree and the tab order (so toHaveAccessibleName() and keyboard use both
 * still work) while every visible cue moves to the label it sits inside,
 * which the browser still toggles it via on click.
 */
.st-filters__button-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.st-filters__button:focus-within {
  outline: var(--st-focus-width) solid var(--st-accent);
  outline-offset: var(--st-focus-offset);
}

/*
 * Price filter (Task 6): two accessible number fields (always present,
 * always functional) plus a JS-enhanced dual-thumb slider — rendered
 * `hidden` by templates/archive/filters.php until archive.js finishes
 * wiring it up (see that file's own docblock on why: a JS failure must
 * never leave a half-built control on screen).
 */
.st-filters__price-fields {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.st-filters__price-field {
  flex: 1 1 0;
  min-width: 0;
}

/* Same shape as .st-field__label (field.css), duplicated rather than
   shared: that class carries a 6px bottom margin tuned for a full-width
   field, and this task is barred from touching card.css/product.js but
   NOT from a small, scoped rule of its own here for the sidebar's own
   narrower fields. */
.st-filters__price-label {
  display: block;
  margin-bottom: 6px;
  color: var(--st-muted);
  font-size: 12px;
  font-weight: var(--st-weight-bold);
  letter-spacing: var(--st-track-button);
  text-transform: uppercase;
}

.st-filters__price-input {
  padding: 0 10px;
  font-size: var(--st-size-body-sm);
}

.st-filters__price-sep {
  padding-bottom: 12px;
  color: var(--st-muted);
}

/*
 * 22px side/top padding = half of --st-h-touch (44px): the exact clearance
 * a thumb centred at 0% or 100% (translate(-50%, -50%)) needs so its own
 * 44x44 hit box never spills past this container's edges, which would
 * otherwise read as a right-edge overflow at 360px.
 */
.st-filters__price-slider {
  margin-top: 20px;
  padding: 22px 22px 0;
}

.st-filters__price-track {
  position: relative;
  height: 4px;
  background: var(--st-line);
}

.st-filters__price-range {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--st-accent);
}

/*
 * The interactive element (role="slider", tabindex, aria-value*) IS the
 * 44x44 touch target itself — not a wrapper around a smaller one — so a
 * bounding-box measurement of this exact element is the accessible
 * control's own hit area, not an adjacent decorative box
 * (global-constraints.md's own defect class: "an assertion on an adjacent
 * property"). The visible 16x18 --st-ink mark (global-constraints.md's
 * own price-slider spec) is the child .st-filters__price-thumb-mark below,
 * centred inside it — same "visual size and touch-target size deliberately
 * differ" pattern .st-filters__option already uses for its checkbox row.
 */
.st-filters__price-thumb {
  position: absolute;
  top: 50%;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--st-h-touch);
  height: var(--st-h-touch);
  transform: translate(-50%, -50%);
  cursor: pointer;
  touch-action: none;
}

.st-filters__price-thumb-mark {
  display: block;
  width: 16px;
  height: 18px;
  background: var(--st-ink);
  pointer-events: none;
}

.st-filters__price-thumb:focus-visible {
  outline: var(--st-focus-width) solid var(--st-accent);
  outline-offset: var(--st-focus-offset);
}

/*
 * Active filter chips (Task 7), above the grid. `.st-chip`/`.st-chip--active`/
 * `.st-chip__remove` already exist in components/chip.css (loaded on every
 * page — Assets::COMPONENTS) with exactly this row's own colours
 * (global-constraints.md: "background --st-accent-wash, border 2px
 * --st-accent, text --st-accent-ink" — chip.css's own `.st-chip--active`
 * already reads var(--st-accent-tint)/var(--st-accent)/var(--st-accent-ink),
 * tokens.css's own name for that wash colour); `.st-chips` (the row itself)
 * is this task's only new class.
 */
.st-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 16px;
}

/*
 * chip.css's own .st-chip__remove is an 18x18 visual button; a 44px hit area
 * is added there only for a coarse (touch) pointer, via an absolutely
 * positioned ::after overlay that does not grow the element's own box —
 * deliberately, so a plain mouse click still targets a small, precise ×.
 * global-constraints.md's "touch targets >= 44px on both axes" is
 * unconditional for this specific control though (task-7-brief.md's own
 * verification bar names it: "the × is a tap target"), and an overlay
 * invisible to a real element measurement cannot prove that — the same
 * "an assertion on an adjacent property proves nothing" trap
 * global-constraints.md warns about, applied to a bounding-box check
 * instead of a colour. Scoped to .st-chips specifically, not chip.css
 * itself: product-card.php's own plain, non-removable .st-chip (a
 * measurement pill with no .st-chip__remove at all) is untouched, and nothing
 * else in this theme uses .st-chip--active/.st-chip__remove yet.
 */
.st-chips .st-chip--active {
  padding: 0 6px 0 12px;
}

.st-chips .st-chip__remove {
  width: var(--st-h-touch);
  height: var(--st-h-touch);
  font-size: var(--st-size-body);
}

.st-chips .st-chip__remove:hover,
.st-chips .st-chip__remove:active {
  color: var(--st-accent-deep);
}

.st-chips .st-chip__remove:focus-visible {
  outline: var(--st-focus-width) solid var(--st-accent);
  outline-offset: var(--st-focus-offset);
}

/*
 * Pagination (Task 8), at `sleeptime_archive_after_loop`
 * (ArchiveScreen::render_pagination() — see its own docblock: this task
 * also unhooks WooCommerce's own `woocommerce_pagination`, replacing it
 * here so the handoff's own shell — a solid 40x40 --st-ink current-page
 * square, the rest outline, plus a pt-BR "Próxima" button — renders instead
 * of core's default markup).
 *
 * global-constraints.md: "Active firmeza button and current pagination
 * square: --st-ink with white text, 40x40." The interactive element
 * (.st-pagination__link — an <a>, or a non-interactive <span> for the
 * current page) is its own 44x44 touch target (--st-h-touch) —
 * global-constraints.md's unconditional "touch targets >= 44px on both
 * axes" — with the visible 40x40 square centred inside it as
 * .st-pagination__mark, the same "visual size and touch-target size
 * deliberately differ" split .st-filters__price-thumb/-thumb-mark already
 * uses (see that rule's own docblock above for why measuring the mark
 * alone, not its 44x44 wrapper, is what proves the exact 40x40 handoff
 * spec, and measuring the wrapper is what proves the touch floor).
 */
.st-pagination {
  margin-top: 32px;
}

.st-pagination__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.st-pagination__link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--st-h-touch);
  height: var(--st-h-touch);
  color: var(--st-ink);
  text-decoration: none;
}

.st-pagination__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: var(--st-border-width) solid var(--st-ink);
  color: var(--st-ink);
  font-size: var(--st-size-body-sm);
  font-weight: var(--st-weight-medium);
  transition:
    background-color var(--st-transition),
    color var(--st-transition),
    border-color var(--st-transition);
}

/* --st-ink background, white text, 40x40 — global-constraints.md's exact wording for the current pagination square. */
.st-pagination__link--current .st-pagination__mark {
  background: var(--st-ink);
  border-color: var(--st-ink);
  color: var(--st-surface);
}

.st-pagination__link:hover .st-pagination__mark,
.st-pagination__link:active .st-pagination__mark {
  border-color: var(--st-accent-deep);
  color: var(--st-accent-deep);
}

.st-pagination__link:focus-visible {
  outline: var(--st-focus-width) solid var(--st-accent);
  outline-offset: var(--st-focus-offset);
}

.st-pagination__next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--st-h-touch);
  padding: 0 16px;
  margin-left: 8px;
  border: var(--st-border-width) solid var(--st-ink);
  color: var(--st-ink);
  font-size: var(--st-size-body-sm);
  font-weight: var(--st-weight-medium);
  letter-spacing: var(--st-track-button);
  text-decoration: none;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background-color var(--st-transition),
    color var(--st-transition),
    border-color var(--st-transition);
}

.st-pagination__next:hover,
.st-pagination__next:active {
  background: var(--st-ink);
  color: var(--st-surface);
}

.st-pagination__next:focus-visible {
  outline: var(--st-focus-width) solid var(--st-accent);
  outline-offset: var(--st-focus-offset);
}

@media (max-width: 599px) {
  .st-pagination__list {
    gap: 6px;
  }
}

/*
 * Task 9: below 900px, the filter sidebar becomes a "Filtros" button that
 * opens .st-filters as a bottom-sheet dialog (global-constraints.md:
 * "600-899px filters become a button + bottom sheet").
 *
 * The dialog itself reuses components/drawer.css's own `.st-drawer` shell
 * and header.js's `window.stDrawer` open()/close() — the same shared focus
 * trap, Escape handling, backdrop-click-to-close and scroll lock
 * mini-cart.js already reuses for its own `.st-drawer` instance (see that
 * file's own docblock: "Task 19's mini-cart reuses open()/close() on its
 * own element") — rather than a second, independent implementation of any
 * of that. archive.js's initFilterSheet() builds the wrapper markup once,
 * around the EXISTING .st-filters node (moved into place, not duplicated),
 * because this screen has no PHP template seam of its own to add one to
 * without going outside this task's own archive.css/archive.js scope.
 */
.st-archive__filters-toggle {
  width: 100%;
  justify-content: center;
}

/*
 * `.st-btn` (button.css) sets `display: inline-flex`, an AUTHOR rule that
 * beats base.css's own `[hidden] { display: none }` on specificity ties by
 * source order (base.css loads first) — the exact defect
 * `.st-archive__orderby-submit[hidden]` above already documents and fixes
 * the same way. archive.js only ever un-hides this button below 900px
 * (initFilterSheet()'s own syncMode()), so without this override it would
 * stay visible above 900px too, sitting uselessly above the always-visible
 * inline sidebar.
 */
.st-archive__filters-toggle[hidden] {
  display: none;
}

/*
 * >=900px: the sheet wrapper carries none of `.st-drawer`'s own chrome.
 * archive.js keeps `#st-archive-filters-sheet` un-hidden unconditionally at
 * this width (so .st-filters — its grandchild — keeps rendering as the
 * plain inline sidebar card it always was), which means drawer.css's own
 * unscoped `.st-drawer { position: fixed; inset: 0; z-index: 90 }` would
 * otherwise turn it into a second, full-viewport layer sitting behind the
 * visible sidebar. These rules are what actually neutralise that, not the
 * `hidden` attribute — the same "an adjacent rule alone isn't the effective
 * one" trap global-constraints.md warns about, applied to CSS specificity
 * rather than a test assertion.
 */
@media (min-width: 900px) {
  #st-archive-filters-sheet {
    position: static;
    inset: auto;
    z-index: auto;
  }

  #st-archive-filters-sheet .st-drawer__backdrop {
    display: none;
  }

  #st-archive-filters-sheet .st-drawer__panel {
    position: static;
    inset: auto;
    width: auto;
    background: none;
    border: 0;
    box-shadow: none;
    max-height: none;
    overflow: visible;
  }
}

/*
 * <900px: the real bottom sheet. `.st-drawer__panel` (drawer.css) is built
 * for a LEFT-edge slide-in (`inset-inline-start: 0`, a fixed max-width) —
 * overridden here, scoped to this one wrapper's own id so it wins on
 * specificity regardless of source order, to anchor to the bottom edge
 * instead, full width, capped height with its own internal scroll (a tall
 * sheet — Tamanho + Firmeza + Marca + Entrega + Preço all at once — must
 * not run off the top of a short viewport the way .st-mega already guards
 * against for the same reason, nav.css's own docblock). `--st-shadow-sheet`
 * (tokens.css) exists for exactly this edge — the one now facing open page
 * content instead of the viewport edge drawer.css's own border assumes.
 */
@media (max-width: 899px) {
  #st-archive-filters-sheet .st-drawer__panel {
    inset-inline: 0;
    inset-block: auto 0;
    width: 100%;
    max-height: 85vh;
    border-inline-end: 0;
    border-top: var(--st-rule);
    box-shadow: var(--st-shadow-sheet);
    overflow-y: auto;
  }

  /* The panel above already supplies the surface/border/shadow; .st-filters
     keeping its own 2px border too would read as a doubled box inside it. */
  #st-archive-filters-sheet .st-filters {
    border: 0;
  }
}

/*
 * "Limpar" and the sheet's own close × share one flex row so both stay
 * grouped at the right edge against the "FILTROS" title —
 * `.st-filters__head`'s own `justify-content: space-between` only pins the
 * FIRST and LAST child to each edge; a third child would land between them
 * instead of beside "Limpar". archive.js always builds both elements once
 * it runs, at every width; only the close button's own display is
 * media-gated below, so at 900px+ this wrapper holds "Limpar" alone and is
 * visually identical to it never having been wrapped at all.
 */
.st-filters__head-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.st-filters__sheet-close {
  display: none;
}

@media (max-width: 899px) {
  .st-filters__sheet-close {
    display: inline-flex;
    font-size: 20px;
  }
}
