/* ==========================================================================
   QRBELL Store — Layout
   App shell, containers, section rhythm, grid helpers, sticky regions.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Containers
   Max width is capped so cards never sprawl on 1600px+ — spec §74.
   -------------------------------------------------------------------------- */

.qb-container,
.qb-container-wide,
.qb-container-narrow,
.qb-container-form {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.qb-container        { max-width: var(--container-max); }
.qb-container-wide   { max-width: var(--container-wide); }
.qb-container-narrow { max-width: var(--container-narrow); }
.qb-container-form   { max-width: var(--container-form); }

/* Full-bleed rail that still aligns its first card to the container edge */
.qb-bleed {
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
}


/* --------------------------------------------------------------------------
   Page shell
   -------------------------------------------------------------------------- */

.qb-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.qb-main { flex: 1 1 auto; }

/* Vertical rhythm between page sections */
.qb-section { padding-block: var(--section-gap); }
.qb-section--tight { padding-block: var(--space-8); }
.qb-section--flush-top { padding-top: 0; }
.qb-section--flush-bottom { padding-bottom: 0; }

.qb-section--alt    { background: var(--color-surface-alt); }
.qb-section--invert { background: var(--color-surface-invert); }

/* Section heading block */
.qb-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}

.qb-section-head__title { margin-bottom: var(--space-1); }

.qb-section-head__sub {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-base);
}

.qb-eyebrow {
  display: inline-block;
  margin-bottom: var(--space-2);
  color: var(--color-text-faint);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}


/* --------------------------------------------------------------------------
   Stacks — the workhorse spacing utilities
   -------------------------------------------------------------------------- */

.qb-stack   { display: flex; flex-direction: column; gap: var(--space-4); }
.qb-stack-1 { display: flex; flex-direction: column; gap: var(--space-1); }
.qb-stack-2 { display: flex; flex-direction: column; gap: var(--space-2); }
.qb-stack-3 { display: flex; flex-direction: column; gap: var(--space-3); }
.qb-stack-4 { display: flex; flex-direction: column; gap: var(--space-4); }
.qb-stack-5 { display: flex; flex-direction: column; gap: var(--space-5); }
.qb-stack-6 { display: flex; flex-direction: column; gap: var(--space-6); }
.qb-stack-8 { display: flex; flex-direction: column; gap: var(--space-8); }

.qb-row    { display: flex; align-items: center; gap: var(--space-3); }
.qb-row-2  { display: flex; align-items: center; gap: var(--space-2); }
.qb-row-4  { display: flex; align-items: center; gap: var(--space-4); }
.qb-row--between { justify-content: space-between; }
.qb-row--wrap    { flex-wrap: wrap; }
.qb-row--top     { align-items: flex-start; }

.qb-spacer { flex: 1 1 auto; }


/* --------------------------------------------------------------------------
   Auto grid
   Cards size themselves; no manual breakpoint column counts needed.
   Falls back to the explicit counts below where the spec dictates them (§86).
   -------------------------------------------------------------------------- */

.qb-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
}

.qb-grid--sm { grid-template-columns: repeat(auto-fill, minmax(min(100%, 180px), 1fr)); }
.qb-grid--lg { grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); }

/* Explicit product grid — 1 / 2 / 3 / 4 per spec §86 */
.qb-grid-products {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 400px) {
  /* Below 400px two columns get cramped; one full card reads better */
  .qb-grid-products { grid-template-columns: minmax(0, 1fr); }
}

@media (min-width: 768px) {
  .qb-grid-products { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-5); }
}

@media (min-width: 1200px) {
  .qb-grid-products { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-6); }
}


/* --------------------------------------------------------------------------
   Two-column work layouts
   Used by shop (filters + grid), checkout (form + summary), cart, product.
   Single column below lg; the aside becomes sticky at lg.
   -------------------------------------------------------------------------- */

.qb-split {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@media (min-width: 992px) {
  /* main + summary rail */
  .qb-split--summary { grid-template-columns: minmax(0, 1fr) 360px; gap: var(--space-8); }
  /* filter rail + main */
  .qb-split--filters { grid-template-columns: 264px minmax(0, 1fr); gap: var(--space-8); }
  /* gallery + info, product detail */
  .qb-split--product { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--space-8); }
}

@media (min-width: 1200px) {
  .qb-split--summary { grid-template-columns: minmax(0, 1fr) 380px; }
  .qb-split--product { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--space-10); }
}

/* Sticky aside, offset below the header, never taller than the viewport */
.qb-sticky-aside { position: static; }

@media (min-width: 992px) {
  .qb-sticky-aside {
    position: sticky;
    top: calc(var(--header-height-desktop) + var(--space-4));
    max-height: calc(100vh - var(--header-height-desktop) - var(--space-8));
    overflow-y: auto;
    scrollbar-width: thin;
  }
}


/* --------------------------------------------------------------------------
   Sticky bottom action bar (mobile) — spec §70
   Sits above the bottom nav, respects the home indicator, and is only
   rendered where a page declares it.
   -------------------------------------------------------------------------- */

.qb-stickybar {
  position: fixed;
  left: 0; right: 0;
  bottom: 0;
  z-index: var(--z-stickybar);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--gutter);
  padding-bottom: calc(var(--space-3) + var(--safe-bottom));
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  box-shadow: var(--shadow-bar-up);
}

/* When the bottom nav is present the bar stacks above it */
body.has-bottomnav .qb-stickybar {
  bottom: calc(var(--bottomnav-height) + var(--safe-bottom));
  padding-bottom: var(--space-3);
}

.qb-stickybar__info {
  flex: 0 0 auto;
  min-width: 0;
  line-height: var(--leading-tight);
}

.qb-stickybar__label {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

.qb-stickybar__value {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}

.qb-stickybar__action { flex: 1 1 auto; }

/* Desktop resolves the sticky bar into the page — spec §70 */
@media (min-width: 992px) {
  .qb-stickybar { display: none; }
}

.qb-stickybar--desktop-visible { display: flex; }


/* --------------------------------------------------------------------------
   Visibility helpers
   Named for intent rather than breakpoint, so the meaning survives a redesign.
   -------------------------------------------------------------------------- */

/* Hide-only, deliberately.
   These used to impose `display: block` when visible, which had two problems:
   the value was wrong for anything naturally flex or inline-flex, and at equal
   specificity a component's own display rule in a later stylesheet won. That
   is exactly what happened to `.qb-back` (inline-flex, components.css), which
   beat `.qb-mobile-only { display: none }` and left the breadcrumb and the
   back link both visible on desktop.

   Hiding only — and marking it important, as display utilities should be —
   lets every element keep its natural display when shown, and guarantees the
   hide wins regardless of stylesheet order. */

@media (max-width: 991.98px) { .qb-desktop-only { display: none !important; } }
@media (min-width: 992px)    { .qb-mobile-only  { display: none !important; } }

/* Tablet band gets its own treatment rather than inheriting desktop — spec §75 */
@media (min-width: 768px) and (max-width: 991.98px) {
  .qb-tablet-hide { display: none !important; }
}
