/* ==========================================================================
   QRBELL Store — Components
   Every component declares all eight states where meaningful (spec §85):
   default · hover · focus · active · disabled · loading · error · success.
   No raw hex values — tokens only.
   ========================================================================== */

/* ==========================================================================
   BUTTONS — hierarchy per spec §7: primary, secondary, outline, ghost, danger
   ========================================================================== */

.qb-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--touch-min);
  padding: var(--space-3) var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-btn);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--transition-base),
    border-color var(--transition-base),
    color var(--transition-base),
    box-shadow var(--transition-base),
    transform var(--duration-fast) var(--ease-out);
}

.qb-btn:hover { text-decoration: none; }
.qb-btn:active { transform: translateY(0) scale(0.985); }

.qb-btn:disabled,
.qb-btn.is-disabled,
.qb-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  pointer-events: none;
}

/* -- Primary: gold. The buy action. ------------------------------------- */
.qb-btn--primary {
  background: var(--color-primary);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-primary);
}
.qb-btn--primary:hover {
  background: var(--color-primary-hover);
  color: var(--color-on-primary);
  transform: var(--lift);
  box-shadow: var(--shadow-primary-hover);
}
.qb-btn--primary:active { background: var(--color-primary-active); }

/* -- Secondary: navy. Structural actions. -------------------------------- */
.qb-btn--secondary {
  background: var(--qb-navy-900);
  color: var(--color-text-invert);
}
.qb-btn--secondary:hover {
  background: var(--qb-navy-800);
  color: var(--color-text-invert);
  transform: var(--lift);
  box-shadow: var(--shadow-md);
}

/* -- Accent: blue. Informational / secondary conversion. ----------------- */
.qb-btn--accent {
  background: var(--color-accent);
  color: var(--color-on-accent);
  box-shadow: var(--shadow-accent);
}
.qb-btn--accent:hover {
  background: var(--color-accent-hover);
  color: var(--color-on-accent);
  transform: var(--lift);
  box-shadow: var(--shadow-accent-hover);
}

/* -- Outline ------------------------------------------------------------- */
.qb-btn--outline {
  background: transparent;
  border-color: var(--color-border-strong);
  color: var(--color-text);
}
.qb-btn--outline:hover {
  background: var(--color-surface-alt);
  border-color: var(--qb-navy-900);
  color: var(--color-text);
}

/* -- Ghost --------------------------------------------------------------- */
.qb-btn--ghost {
  background: transparent;
  color: var(--color-text-muted);
}
.qb-btn--ghost:hover {
  background: var(--color-surface-alt);
  color: var(--color-text);
}

/* -- Danger -------------------------------------------------------------- */
.qb-btn--danger {
  background: var(--color-danger);
  color: #fff;
}
.qb-btn--danger:hover {
  background: var(--color-danger-strong);
  color: #fff;
  transform: var(--lift);
}

.qb-btn--danger-soft {
  background: var(--color-danger-soft);
  color: var(--color-danger-strong);
}
.qb-btn--danger-soft:hover { background: var(--color-danger); color: #fff; }

/* -- Sizes --------------------------------------------------------------- */
.qb-btn--sm {
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  border-radius: var(--radius-sm);
}
.qb-btn--lg {
  min-height: 52px;
  padding: var(--space-4) var(--space-8);
  font-size: var(--text-md);
}
.qb-btn--block { display: flex; width: 100%; }

/* Icon-only — square, still clears the touch minimum */
.qb-btn--icon {
  width: var(--touch-min);
  min-width: var(--touch-min);
  padding: 0;
  border-radius: var(--radius-sm);
}
.qb-btn--icon.qb-btn--sm { width: 36px; min-width: 36px; min-height: 36px; }

/* -- Loading: swap the label for a spinner without changing width -------- */
.qb-btn.is-loading { color: transparent !important; pointer-events: none; }
.qb-btn.is-loading::after {
  content: "";
  position: absolute;
  width: 18px; height: 18px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-circle);
  animation: qb-spin 0.7s linear infinite;
  /* Inherit the button's own text color, which was zeroed above */
  color: var(--color-on-primary);
  border-color: var(--color-on-primary);
  border-top-color: transparent;
}
.qb-btn--secondary.is-loading::after,
.qb-btn--accent.is-loading::after,
.qb-btn--danger.is-loading::after {
  color: #fff; border-color: #fff; border-top-color: transparent;
}
.qb-btn--outline.is-loading::after,
.qb-btn--ghost.is-loading::after {
  color: var(--color-text); border-color: var(--color-text); border-top-color: transparent;
}

@keyframes qb-spin { to { transform: rotate(360deg); } }


/* ==========================================================================
   FORMS — label + input + help + error, always. Never placeholder-as-label
   (spec §84).
   ========================================================================== */

.qb-field { display: flex; flex-direction: column; gap: var(--space-2); }

.qb-label {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
}

.qb-label__req { color: var(--color-danger); margin-left: 2px; }

.qb-label__optional {
  margin-left: var(--space-2);
  font-weight: var(--weight-regular);
  color: var(--color-text-faint);
  font-size: var(--text-xs);
}

.qb-input,
.qb-select,
.qb-textarea {
  width: 100%;
  min-height: var(--touch-min);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-input);
  color: var(--color-text);
  font-size: var(--text-md);
  transition:
    border-color var(--transition-base),
    box-shadow var(--transition-base),
    background-color var(--transition-base);
}

.qb-input::placeholder,
.qb-textarea::placeholder { color: var(--color-text-faint); }

.qb-input:hover,
.qb-select:hover,
.qb-textarea:hover { border-color: var(--qb-grey-400); }

.qb-input:focus,
.qb-select:focus,
.qb-textarea:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: var(--focus-ring);
}

.qb-input:disabled,
.qb-select:disabled,
.qb-textarea:disabled {
  background: var(--color-surface-alt);
  color: var(--color-text-faint);
  cursor: not-allowed;
}

.qb-textarea { min-height: 108px; padding-top: var(--space-3); }

.qb-select {
  appearance: none;
  padding-right: var(--space-10);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%237A8699' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
}

/* -- Validation states --------------------------------------------------- */
.qb-field.is-error .qb-input,
.qb-field.is-error .qb-select,
.qb-field.is-error .qb-textarea { border-color: var(--color-danger); }

.qb-field.is-error .qb-input:focus,
.qb-field.is-error .qb-select:focus,
.qb-field.is-error .qb-textarea:focus {
  box-shadow: 0 0 0 3px var(--color-danger-soft);
}

.qb-field.is-success .qb-input,
.qb-field.is-success .qb-select { border-color: var(--color-success); }

.qb-help {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  line-height: var(--leading-snug);
}

.qb-error-text {
  display: none;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--color-danger-strong);
  line-height: var(--leading-snug);
}
.qb-field.is-error .qb-error-text { display: flex; }

.qb-success-text {
  display: none;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--color-success-strong);
}
.qb-field.is-success .qb-success-text { display: flex; }

/* -- Input with a leading icon or prefix ---------------------------------- */
.qb-input-group { position: relative; display: flex; align-items: center; }

.qb-input-group__icon {
  position: absolute;
  left: var(--space-4);
  display: flex;
  color: var(--color-text-faint);
  pointer-events: none;
}
.qb-input-group__icon ~ .qb-input { padding-left: var(--space-10); }

.qb-input-group__suffix {
  position: absolute;
  right: var(--space-3);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

/* Country prefix for Indian mobile entry */
.qb-input-prefix {
  display: flex;
  align-items: center;
  /* The group centres its children, so the prefix would sit shorter than the
     input beside it. Stretching makes the two read as one control. */
  align-self: stretch;
  padding: 0 var(--space-3);
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border-strong);
  border-right: 0;
  border-radius: var(--radius-input) 0 0 var(--radius-input);
  color: var(--color-text-muted);
  font-size: var(--text-md);
  white-space: nowrap;
}
.qb-input-prefix + .qb-input { border-radius: 0 var(--radius-input) var(--radius-input) 0; }


/* --------------------------------------------------------------------------
   Compact desktop controls.
   --------------------------------------------------------------------------
   The base sizes are touch-first: 44px tall (WCAG 2.5.5) with 16px text, which
   is what stops iOS zooming the page on focus. Neither applies to a fine
   pointer, so above lg the controls step down.

   This lives here, once, rather than in each page's stylesheet. Page-scoped
   copies of it re-clobbered the icon clearance, the select chevron and the
   prefix radius on three separate occasions — because a `padding` or
   `border-radius` declaration on `.qb-input` silently resets whatever the
   group rules above had set up.
   -------------------------------------------------------------------------- */

@media (min-width: 992px) {
  .qb-input,
  .qb-select,
  .qb-textarea {
    min-height: 42px;
    padding-block: var(--space-2);
    padding-inline: var(--space-3);
    font-size: var(--text-base);
    border-radius: var(--radius-sm);
  }

  .qb-textarea { min-height: 96px; }

  /* Icon and its clearance move together */
  .qb-input-group__icon { left: var(--space-3); }
  .qb-input-group__icon ~ .qb-input { padding-left: var(--space-8); }

  /* The select's own chevron needs its room back */
  .qb-select { padding-right: var(--space-8); }

  /* Keep the prefix and input joined at the smaller radius */
  .qb-input-prefix { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
  .qb-input-prefix + .qb-input { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }

  .qb-label { font-size: var(--text-xs); }
}

/* -- Checkbox / radio ----------------------------------------------------- */
.qb-check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  min-height: var(--touch-min);
  padding: var(--space-2) 0;
  cursor: pointer;
}

.qb-check input[type="checkbox"],
.qb-check input[type="radio"] {
  flex: 0 0 auto;
  width: 20px; height: 20px;
  margin-top: 2px;
  accent-color: var(--color-accent);
  cursor: pointer;
}

.qb-check__label { font-size: var(--text-base); line-height: var(--leading-snug); }
.qb-check__hint { display: block; font-size: var(--text-xs); color: var(--color-text-muted); }

/* -- Selectable option card (variants, payment methods, addresses) -------- */
.qb-option {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  text-align: left;
  cursor: pointer;
  transition:
    border-color var(--transition-base),
    background-color var(--transition-base),
    box-shadow var(--transition-base);
}
.qb-option:hover { border-color: var(--qb-grey-400); background: var(--color-surface-alt); }

.qb-option.is-selected,
.qb-option[aria-pressed="true"],
.qb-option[aria-checked="true"] {
  border-color: var(--color-accent);
  background: var(--color-accent-subtle);
  box-shadow: inset 0 0 0 1px var(--color-accent);
}

.qb-option.is-disabled,
.qb-option:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  background: var(--color-surface-alt);
}

.qb-option__body { flex: 1 1 auto; min-width: 0; }
.qb-option__title { font-weight: var(--weight-semibold); font-size: var(--text-base); }
.qb-option__meta  { font-size: var(--text-xs); color: var(--color-text-muted); }
.qb-option__price { font-weight: var(--weight-bold); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* -- Toggle switch -------------------------------------------------------- */
.qb-switch { display: flex; align-items: center; gap: var(--space-3); cursor: pointer; min-height: var(--touch-min); }
.qb-switch input { position: absolute; opacity: 0; width: 0; height: 0; }

.qb-switch__track {
  position: relative;
  flex: 0 0 auto;
  width: 44px; height: 26px;
  background: var(--qb-grey-300);
  border-radius: var(--radius-pill);
  transition: background-color var(--transition-base);
}
.qb-switch__track::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 20px; height: 20px;
  background: var(--color-surface);
  border-radius: var(--radius-circle);
  box-shadow: var(--shadow-xs);
  transition: transform var(--transition-base);
}
.qb-switch input:checked + .qb-switch__track { background: var(--color-success); }
.qb-switch input:checked + .qb-switch__track::after { transform: translateX(18px); }
.qb-switch input:focus-visible + .qb-switch__track { box-shadow: var(--focus-ring); }
.qb-switch input:disabled + .qb-switch__track { opacity: 0.5; cursor: not-allowed; }

/* -- Quantity stepper ----------------------------------------------------- */
.qb-qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--color-surface);
}

.qb-qty__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--touch-min);
  height: var(--touch-min);
  color: var(--color-text);
  transition: background-color var(--transition-base);
}
.qb-qty__btn:hover:not(:disabled) { background: var(--color-surface-alt); }
.qb-qty__btn:disabled { color: var(--color-text-faint); cursor: not-allowed; }

.qb-qty__value {
  width: 48px;
  height: var(--touch-min);
  padding: 0;
  border: 0;
  border-inline: 1px solid var(--color-border);
  text-align: center;
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  background: transparent;
}
.qb-qty__value:focus { outline: none; background: var(--color-accent-subtle); }


/* ==========================================================================
   CARDS
   ========================================================================== */

.qb-card {
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  overflow: hidden;
  transition:
    border-color var(--transition-base),
    box-shadow var(--transition-base),
    transform var(--transition-base);
}

.qb-card--flat   { border-radius: var(--radius-section); }
.qb-card--pad    { padding: var(--space-5); }
.qb-card--pad-sm { padding: var(--space-4); }

/* Only cards that are actually clickable get the lift */
.qb-card--interactive { cursor: pointer; }
.qb-card--interactive:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-md);
  transform: var(--lift);
}
/* Touch devices have no hover; the lift would stick after a tap */
@media (hover: none) {
  .qb-card--interactive:hover { transform: none; box-shadow: none; }
}

.qb-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
}
.qb-card__title { margin: 0; font-size: var(--text-md); font-weight: var(--weight-bold); }
.qb-card__body { padding: var(--space-5); }
.qb-card__foot {
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--color-border);
  background: var(--color-surface-alt);
}


/* ==========================================================================
   BADGES & STATUS  — never color alone; each carries an icon or text (§52)
   ========================================================================== */

.qb-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 3px var(--space-2);
  border-radius: var(--radius-xs);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1.4;
}

.qb-badge--neutral { background: var(--color-surface-sunken); color: var(--color-text-muted); }
.qb-badge--primary { background: var(--color-primary-soft);   color: var(--qb-gold-700); }
.qb-badge--accent  { background: var(--color-accent-soft);    color: var(--color-accent-hover); }
.qb-badge--success { background: var(--color-success-soft);   color: var(--color-success-strong); }
.qb-badge--danger  { background: var(--color-danger-soft);    color: var(--color-danger-strong); }
.qb-badge--warning { background: var(--color-warning-soft);   color: #92600A; }
.qb-badge--solid   { background: var(--qb-navy-900);          color: var(--color-text-invert); }

/* Status dot pairs with a label — QR statuses per spec §95 */
.qb-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}
.qb-status__dot {
  width: 8px; height: 8px;
  border-radius: var(--radius-circle);
  flex: 0 0 auto;
  background: currentColor;
}
.qb-status--active   { color: var(--color-success-strong); }
.qb-status--pending  { color: var(--color-warning); }
.qb-status--inactive { color: var(--color-text-faint); }
.qb-status--suspended{ color: var(--color-danger-strong); }
.qb-status--replaced { color: var(--color-accent); }
.qb-status--retired  { color: var(--color-text-faint); }

/* Live pulse for an active QR */
.qb-status--active .qb-status__dot { animation: qb-pulse 2.4s ease-out infinite; }
@keyframes qb-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(43, 182, 115, 0.55); }
  50%      { box-shadow: 0 0 0 6px rgba(43, 182, 115, 0); }
}

/* Count bubble on cart / nav icons */
.qb-count {
  position: absolute;
  top: -4px; right: -6px;
  min-width: 18px; height: 18px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-danger);
  color: #fff;
  border-radius: var(--radius-pill);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.qb-count:empty,
.qb-count[data-count="0"] { display: none; }


/* ==========================================================================
   CHIPS — category rails, active filters
   ========================================================================== */

.qb-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 38px;
  padding: var(--space-2) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  color: var(--color-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition: all var(--transition-base);
}
.qb-chip:hover { border-color: var(--qb-navy-900); text-decoration: none; color: var(--color-text); }

.qb-chip.is-active,
.qb-chip[aria-pressed="true"] {
  background: var(--qb-navy-900);
  border-color: var(--qb-navy-900);
  color: var(--color-text-invert);
}

.qb-chip__remove { display: flex; opacity: 0.7; }
.qb-chip__remove:hover { opacity: 1; }


/* ==========================================================================
   ALERTS
   ========================================================================== */

.qb-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-size: var(--text-base);
  line-height: var(--leading-snug);
}
.qb-alert__icon  { flex: 0 0 auto; font-size: 1.15em; line-height: 1.2; }
.qb-alert__body  { flex: 1 1 auto; min-width: 0; }
.qb-alert__title { font-weight: var(--weight-semibold); margin-bottom: var(--space-1); }

.qb-alert--info    { background: var(--color-info-soft);    border-color: var(--qb-blue-100);  color: var(--qb-blue-700); }
.qb-alert--success { background: var(--color-success-soft); border-color: #BDE9D4;             color: var(--color-success-strong); }
.qb-alert--warning { background: var(--color-warning-soft); border-color: #F8DFA8;             color: #92600A; }
.qb-alert--danger  { background: var(--color-danger-soft);  border-color: #F5C6C6;             color: var(--color-danger-strong); }


/* ==========================================================================
   TABS
   ========================================================================== */

.qb-tabs {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--color-border);
  overflow-x: auto;
  scrollbar-width: none;
}
.qb-tabs::-webkit-scrollbar { display: none; }

.qb-tab {
  position: relative;
  flex: 0 0 auto;
  padding: var(--space-3) var(--space-4);
  min-height: var(--touch-min);
  color: var(--color-text-muted);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--transition-base), border-color var(--transition-base);
}
.qb-tab:hover { color: var(--color-text); text-decoration: none; }

.qb-tab.is-active,
.qb-tab[aria-selected="true"] {
  color: var(--color-text);
  font-weight: var(--weight-semibold);
  border-bottom-color: var(--color-primary);
}

.qb-tab__count {
  margin-left: var(--space-2);
  padding: 1px var(--space-2);
  background: var(--color-surface-sunken);
  border-radius: var(--radius-pill);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
}


/* ==========================================================================
   BREADCRUMBS — spec §90
   ========================================================================== */

.qb-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.qb-breadcrumb li { display: flex; align-items: center; gap: var(--space-2); }
.qb-breadcrumb li:not(:last-child)::after {
  content: "/";
  color: var(--color-text-faint);
}
.qb-breadcrumb a { color: var(--color-text-muted); }
.qb-breadcrumb a:hover { color: var(--color-text); }
.qb-breadcrumb [aria-current="page"] { color: var(--color-text); font-weight: var(--weight-medium); }

/* Mobile uses compact back navigation instead — spec §90 */
.qb-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--touch-min);
  color: var(--color-text-muted);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
}
.qb-back:hover { color: var(--color-text); text-decoration: none; }


/* ==========================================================================
   PAGINATION
   ========================================================================== */

.qb-pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
  margin: 0;
}

.qb-page-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 0 var(--space-2);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  transition: all var(--transition-base);
}
.qb-page-btn:hover:not(:disabled) { border-color: var(--qb-navy-900); text-decoration: none; color: var(--color-text); }
.qb-page-btn.is-active {
  background: var(--qb-navy-900);
  border-color: var(--qb-navy-900);
  color: var(--color-text-invert);
}
.qb-page-btn:disabled { opacity: 0.4; cursor: not-allowed; }


/* ==========================================================================
   EMPTY STATE — spec §47. Icon + explanation + primary CTA. Never blank space.
   ========================================================================== */

.qb-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-12) var(--space-5);
  text-align: center;
}

.qb-empty__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px; height: 72px;
  background: var(--color-surface-alt);
  border-radius: var(--radius-circle);
  color: var(--color-text-faint);
  font-size: 1.9rem;
}

.qb-empty__title { margin: 0; font-size: var(--text-xl); }
.qb-empty__text  { margin: 0; max-width: 42ch; color: var(--color-text-muted); font-size: var(--text-base); }
.qb-empty__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center; }


/* ==========================================================================
   SKELETON LOADERS — spec §48, pure CSS
   ========================================================================== */

.qb-skel {
  position: relative;
  overflow: hidden;
  background: var(--color-surface-alt);
  border-radius: var(--radius-xs);
}
.qb-skel::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.65),
    transparent
  );
  animation: qb-shimmer 1.4s infinite;
}
@keyframes qb-shimmer { to { transform: translateX(100%); } }

.qb-skel--text   { height: 12px; margin-bottom: var(--space-2); border-radius: var(--radius-pill); }
.qb-skel--title  { height: 18px; width: 65%; margin-bottom: var(--space-3); border-radius: var(--radius-pill); }
.qb-skel--line   { height: 10px; width: 100%; }
.qb-skel--line-sm{ height: 10px; width: 45%; }
.qb-skel--thumb  { aspect-ratio: 1 / 1; width: 100%; border-radius: var(--radius-sm); }
.qb-skel--avatar { width: 40px; height: 40px; border-radius: var(--radius-circle); }
.qb-skel--btn    { height: 40px; width: 110px; border-radius: var(--radius-btn); }

@media (prefers-reduced-motion: reduce) {
  .qb-skel::after { animation: none; }
}


/* ==========================================================================
   TOASTS — spec §50
   ========================================================================== */

.qb-toaster {
  position: fixed;
  z-index: var(--z-toast);
  left: var(--gutter);
  right: var(--gutter);
  bottom: calc(var(--bottomnav-height) + var(--safe-bottom) + var(--space-4));
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  pointer-events: none;
}

@media (min-width: 992px) {
  .qb-toaster {
    left: auto;
    right: var(--space-6);
    bottom: var(--space-6);
    width: 360px;
  }
}

.qb-toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--qb-navy-900);
  color: var(--color-text-invert);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  font-size: var(--text-base);
  pointer-events: auto;
  animation: qb-toast-in var(--duration-slow) var(--ease-out);
}
.qb-toast.is-leaving { animation: qb-toast-out var(--duration-normal) var(--ease-out) forwards; }

.qb-toast__icon  { flex: 0 0 auto; font-size: 1.1em; }
.qb-toast__body  { flex: 1 1 auto; min-width: 0; line-height: var(--leading-snug); }
.qb-toast__title { font-weight: var(--weight-semibold); }
.qb-toast__text  { color: var(--color-text-invert-muted); font-size: var(--text-sm); }
.qb-toast__close { flex: 0 0 auto; color: var(--color-text-invert-muted); }
.qb-toast__close:hover { color: var(--color-text-invert); }

.qb-toast--success .qb-toast__icon { color: var(--color-success); }
.qb-toast--danger  .qb-toast__icon { color: var(--color-danger); }
.qb-toast--warning .qb-toast__icon { color: var(--color-primary); }
.qb-toast--info    .qb-toast__icon { color: var(--qb-blue-400); }

@keyframes qb-toast-in  { from { opacity: 0; transform: translateY(16px); } }
@keyframes qb-toast-out { to   { opacity: 0; transform: translateY(8px); } }


/* ==========================================================================
   MODAL / BOTTOM SHEET — spec §51
   One component. Below lg it renders as a bottom sheet, above as a modal.
   ========================================================================== */

.qb-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-backdrop);
  background: rgba(7, 9, 28, 0.55);
  opacity: 0;
  transition: opacity var(--transition-base);
}
.qb-backdrop.is-open { opacity: 1; }

.qb-sheet {
  position: fixed;
  z-index: var(--z-sheet);
  left: 0; right: 0; bottom: 0;
  display: flex;
  flex-direction: column;
  max-height: 88vh;
  background: var(--color-surface);
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  box-shadow: var(--shadow-xl);
  transform: translateY(100%);
  transition: transform var(--duration-slow) var(--ease-out);
}
.qb-sheet.is-open { transform: translateY(0); }

/* Drag affordance, mobile only */
.qb-sheet__grip {
  flex: 0 0 auto;
  width: 40px; height: 4px;
  margin: var(--space-3) auto var(--space-1);
  background: var(--color-border-strong);
  border-radius: var(--radius-pill);
}

.qb-sheet__head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
}
.qb-sheet__title { margin: 0; font-size: var(--text-lg); }
.qb-sheet__body  { flex: 1 1 auto; overflow-y: auto; padding: var(--space-5); }
.qb-sheet__foot  {
  flex: 0 0 auto;
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  padding-bottom: calc(var(--space-4) + var(--safe-bottom));
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
}
.qb-sheet__foot > .qb-btn { flex: 1 1 auto; }

@media (min-width: 992px) {
  .qb-sheet {
    top: 50%;
    left: 50%;
    right: auto;
    bottom: auto;
    width: min(560px, calc(100vw - var(--space-10)));
    max-height: 86vh;
    border-radius: var(--radius-section);
    transform: translate(-50%, -46%) scale(0.98);
    opacity: 0;
    transition:
      transform var(--transition-base),
      opacity var(--transition-base);
  }
  .qb-sheet.is-open { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  .qb-sheet__grip { display: none; }
  .qb-sheet__foot { padding-bottom: var(--space-4); justify-content: flex-end; }
  .qb-sheet__foot > .qb-btn { flex: 0 0 auto; }

  .qb-sheet--lg { width: min(860px, calc(100vw - var(--space-10))); }
  .qb-sheet--sm { width: min(420px, calc(100vw - var(--space-10))); }
}


/* ==========================================================================
   STEPPER — checkout and bulk-order progress
   ========================================================================== */

.qb-stepper {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.qb-step {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1 1 0;
  min-width: 0;
}

.qb-step__num {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  background: var(--color-surface-sunken);
  color: var(--color-text-muted);
  border-radius: var(--radius-circle);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  transition: all var(--transition-base);
}

.qb-step__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.qb-step__bar {
  flex: 1 1 auto;
  height: 2px;
  min-width: var(--space-2);
  background: var(--color-border);
  border-radius: var(--radius-pill);
}

.qb-step.is-active .qb-step__num  { background: var(--color-primary); color: var(--color-on-primary); }
.qb-step.is-active .qb-step__label{ color: var(--color-text); font-weight: var(--weight-semibold); }
.qb-step.is-done   .qb-step__num  { background: var(--color-success); color: #fff; }
.qb-step.is-done   .qb-step__bar  { background: var(--color-success); }

/* Below md only the active step keeps its label, so 5 steps still fit 320px */
@media (max-width: 767.98px) {
  .qb-step__label { display: none; }
  .qb-step.is-active .qb-step__label { display: block; }
}


/* ==========================================================================
   TIMELINE — reusable across order detail, tracking, admin production (§94)
   ========================================================================== */

.qb-timeline { position: relative; margin: 0; padding: 0; list-style: none; }

.qb-tl-item {
  position: relative;
  display: flex;
  gap: var(--space-4);
  padding-bottom: var(--space-6);
}
.qb-tl-item:last-child { padding-bottom: 0; }

/* The connecting rail, drawn from each marker down to the next */
.qb-tl-item:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 13px;
  top: 28px;
  bottom: 0;
  width: 2px;
  background: var(--color-border);
}
.qb-tl-item.is-done:not(:last-child)::before { background: var(--color-success); }

.qb-tl-marker {
  position: relative;
  z-index: var(--z-base);
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-circle);
  color: var(--color-text-faint);
  font-size: var(--text-xs);
}

.qb-tl-item.is-done .qb-tl-marker {
  background: var(--color-success);
  border-color: var(--color-success);
  color: #fff;
}
.qb-tl-item.is-current .qb-tl-marker {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}

.qb-tl-body  { flex: 1 1 auto; min-width: 0; padding-top: 2px; }
.qb-tl-title { font-size: var(--text-base); font-weight: var(--weight-semibold); }
.qb-tl-item:not(.is-done):not(.is-current) .qb-tl-title { color: var(--color-text-muted); font-weight: var(--weight-medium); }
.qb-tl-meta  { font-size: var(--text-xs); color: var(--color-text-muted); }


/* ==========================================================================
   PRICE SUMMARY — cart, checkout, product
   ========================================================================== */

.qb-price-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
  font-size: var(--text-base);
}
.qb-price-row__label { color: var(--color-text-muted); }
.qb-price-row__value { font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; white-space: nowrap; }
.qb-price-row--discount .qb-price-row__value { color: var(--color-success-strong); }

.qb-price-row--total {
  margin-top: var(--space-2);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
  font-size: var(--text-lg);
}
.qb-price-row--total .qb-price-row__label { color: var(--color-text); font-weight: var(--weight-semibold); }
.qb-price-row--total .qb-price-row__value {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: var(--weight-extra);
}

/* Struck original price beside a discounted one */
.qb-price-strike {
  color: var(--color-text-faint);
  text-decoration: line-through;
  font-weight: var(--weight-regular);
  font-size: 0.85em;
}


/* ==========================================================================
   RATING
   ========================================================================== */

.qb-rating { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--text-xs); }
.qb-rating__stars { display: inline-flex; gap: 1px; color: var(--color-primary); }
.qb-rating__value { font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.qb-rating__count { color: var(--color-text-muted); }


/* ==========================================================================
   PRODUCT GRID + SHOWCASE CARD
   --------------------------------------------------------------------------
   The commercial, image-led card. Shared by the homepage, the shop grid and
   the product page's related rail, so it lives here rather than in any one
   page's stylesheet. Media occupies ~60% of card height; the body carries
   only what a shopper needs to decide.
   ========================================================================== */

.qb-pgrid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));   /* mobile: 2-up */
}

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

/* Inside a filtered layout the grid has a sidebar beside it, so it steps
   down one column at each breakpoint. */
.qb-pgrid--narrow { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 992px)  { .qb-pgrid--narrow { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .qb-pgrid--narrow { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1600px) { .qb-pgrid--narrow { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.qb-pcard {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  transition: border-color var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}
.qb-pcard:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}
@media (hover: none) { .qb-pcard:hover { transform: none; box-shadow: none; } }

.qb-pcard__media {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  background: var(--qb-grey-100);
  overflow: hidden;
}

.qb-pcard__img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-out);
}
.qb-pcard:hover .qb-pcard__img { transform: scale(1.03); }
@media (hover: none) { .qb-pcard:hover .qb-pcard__img { transform: none; } }

.qb-pcard__badge,
.qb-pcard__off {
  position: absolute;
  top: var(--space-2);
  padding: 3px var(--space-2);
  border-radius: var(--radius-xs);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  line-height: 1.4;
}

.qb-pcard__badge { left: var(--space-2); }
.qb-pcard__badge--primary { background: var(--color-primary); color: var(--color-on-primary); }
.qb-pcard__badge--solid   { background: var(--qb-navy-900);   color: var(--color-text-invert); }
.qb-pcard__badge--success { background: var(--color-success); color: #fff; }
.qb-pcard__badge--accent  { background: var(--color-accent);  color: #fff; }
.qb-pcard__badge--neutral { background: var(--qb-navy-900);   color: var(--color-text-invert); }
.qb-pcard__badge--danger  { background: var(--color-danger);  color: #fff; }

.qb-pcard__off {
  right: var(--space-2);
  background: var(--color-success);
  color: #fff;
  text-transform: none;
}

.qb-pcard__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  flex: 1 1 auto;
  padding: var(--space-3);
}

@media (min-width: 768px) { .qb-pcard__body { padding: var(--space-4); } }

.qb-pcard__cat {
  color: var(--color-text-faint);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.qb-pcard__name {
  margin: 0;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1.25;
}
.qb-pcard__name a { color: var(--color-text); }
.qb-pcard__name a:hover { color: var(--color-accent); text-decoration: none; }

.qb-pcard__benefit {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.qb-pcard__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
}

.qb-pcard__price { display: flex; flex-direction: column; line-height: 1.15; }
.qb-pcard__price-label { color: var(--color-text-faint); font-size: var(--text-2xs); }
.qb-pcard__price-value {
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: var(--weight-extra);
  font-variant-numeric: tabular-nums;
}
.qb-pcard__price-mrp {
  color: var(--color-text-faint);
  font-size: var(--text-2xs);
  text-decoration: line-through;
}

.qb-pcard__cta { width: 100%; margin-top: var(--space-3); }

/* Below 400px the two-up grid gets narrow — trim the card, keep the image */
@media (max-width: 400px) {
  .qb-pcard__benefit { display: none; }
  .qb-pcard__body { padding: var(--space-2) var(--space-3) var(--space-3); }
}



/* ==========================================================================
   STEP FLOW and CTA BAND
   --------------------------------------------------------------------------
   Both started life on the homepage and are now used by the business page
   too, so they live here rather than in one page's stylesheet — the same
   move the product card needed.
   ========================================================================== */

/* Borderless: the connected markers carry the flow, so card chrome would
   only fight it. The eye should travel along the row, not scan four boxes. */

.qb-flow {
  --step-gap: var(--space-4);
  --marker: 48px;

  display: grid;
  gap: var(--space-5) var(--step-gap);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

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

.qb-flow__item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.qb-flow__marker {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--marker);
  height: var(--marker);
  margin-bottom: var(--space-3);
  background: var(--color-surface);
  border: 2px solid var(--color-border-strong);
  border-radius: var(--radius-circle);
  color: var(--qb-navy-900);
  font-size: 1.15rem;
}

/* Activate is the payoff, not another step — so it lands filled. */
.qb-flow__item--final .qb-flow__marker {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}

/* Connector runs behind the markers, from this one to the next */
@media (min-width: 768px) {
  .qb-flow__item:not(:last-child)::after {
    content: "";
    position: absolute;
    top: calc(var(--marker) / 2 - 1px);
    left: var(--marker);
    right: calc(var(--step-gap) * -1);
    height: 2px;
    background: var(--color-border);
  }
}

.qb-flow__num {
  font-family: var(--font-heading);
  font-size: var(--text-2xs);
  font-weight: var(--weight-extra);
  color: var(--color-text-faint);
  letter-spacing: var(--tracking-caps);
}

.qb-flow__title { font-size: var(--text-base); font-weight: var(--weight-semibold); }
.qb-flow__text  { margin: 0; color: var(--color-text-muted); font-size: var(--text-xs); line-height: 1.35; }

/* Closing note + CTA — the section explains the journey, so it should also
   offer the way to begin it. */
.qb-flow-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

.qb-flow-foot__note {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

@media (max-width: 575.98px) {
  .qb-flow-foot { flex-direction: column; align-items: stretch; }
  .qb-flow-foot > .qb-btn { width: 100%; }
}



/* ==========================================================================
   HELP ME CHOOSE — one compact banner, questionnaire hidden behind the CTA
   Target: 120–180px tall.
   ========================================================================== */

.qb-cta-band {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5);
  background: var(--qb-navy-900);
  color: var(--color-text-invert);
  border-radius: var(--radius-section);
}

@media (min-width: 768px) {
  .qb-cta-band {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    padding: var(--space-6) var(--space-8);
  }
}

.qb-cta-band__icon {
  display: none;
  align-items: center;
  justify-content: center;
  width: 52px; height: 52px;
  flex: 0 0 auto;
  background: rgba(244, 180, 0, 0.14);
  color: var(--color-primary);
  border-radius: var(--radius-sm);
  font-size: 1.4rem;
}
@media (min-width: 992px) { .qb-cta-band__icon { display: flex; } }

.qb-cta-band__body { flex: 1 1 auto; min-width: 0; }

.qb-cta-band__title {
  margin: 0 0 var(--space-1);
  color: var(--color-text-invert);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
}

.qb-cta-band__text {
  margin: 0;
  color: var(--color-text-invert-muted);
  font-size: var(--text-sm);
}

.qb-cta-band__cta { flex: 0 0 auto; }

@media (max-width: 767.98px) { .qb-cta-band__cta { width: 100%; } }


/* ==========================================================================
   DIVIDER WITH LABEL — auth screens ("or continue with")
   ========================================================================== */

.qb-divider-text {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-text-faint);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}
.qb-divider-text::before,
.qb-divider-text::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--color-border);
}
