/* ============================================================
   app-new.css — incremental additions for the new catalog (live on /<cat>).
   Legacy catalog (/old/<cat>) uses only app.css.
   Loaded AFTER app.css in layout-new.html. Keep this file minimal —
   reuse design tokens (--si-*) and existing component classes from
   app.css. Add new rules here only when a /new-specific behavior
   diverges (e.g. Load Time pill, future floating helpers).
   ============================================================ */

/* Load Time pill — bottom-left, fixed, terminal-style with two-color
   palette: green labels (total/server) and amber numbers (45ms). Designed
   to "pop" so the Redis speed becomes the first thing anyone notices.
   Auto-shows on every render (initial + AJAX swap) and auto-hides after 3s
   via opacity+transform transition. mallistix-new.js manages the timer. */
.mxnew-load-time {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 1060;
  padding: .5rem .9rem;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .04em;
  color: #3ddc84;
  background: #0a0a0a;
  border: 1px solid #1f2937;
  border-radius: 8px;
  box-shadow:
    0 6px 16px rgba(0, 0, 0, .35),
    0 0 0 1px rgba(61, 220, 132, .08),
    inset 0 1px 0 rgba(255, 255, 255, .04);
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-variant-numeric: tabular-nums;
  user-select: none;
  pointer-events: none;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .22s ease, transform .22s ease;
}
.mxnew-load-time.mxnew-lt-visible {
  opacity: 1;
  transform: translateY(0);
}
.mxnew-load-time[hidden] { display: none; }
/* v360: hide load-time pill on mobile (< lg). Debug-only info, not relevant
   for end users on phones. Still shown on desktop for dev/QA visibility. */
@media (max-width: 991.98px) {
  .mxnew-load-time { display: none !important; }
}
/* Lightning bolt — speed cue, green like the labels. */
.mxnew-load-time .bi {
  color: #3ddc84;
  font-size: 1rem;
  filter: drop-shadow(0 0 4px rgba(61, 220, 132, .45));
}
/* Numbers + ms unit in pure yellow — sharp contrast against the green
   labels, no glow so each digit reads crisp on the dark background. */
.mxnew-load-time .mxnew-lt-num,
.mxnew-load-time .mxnew-lt-unit {
  color: #ffff00;
  font-weight: 500;
}
.mxnew-load-time .mxnew-lt-unit {
  opacity: .88;
  margin-left: 1px;
}
/* Mid-dot separator dimmed so it doesn't compete with the numbers. */
.mxnew-load-time .mxnew-lt-sep {
  color: #3ddc84;
  opacity: .35;
  margin: 0 .15rem;
}

/* Category title style — light typography, premium feel.
   App.css's .si-product-card etc. cover product cards already. */
.si-category-title {
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--si-text);
}

/* 5-columns grid override at xxl (>=1400px). Possible because the /new
   sidebar uses col-xl-2 (narrower than legacy col-xl-3), leaving the main
   column with 10/12 of viewport — enough for 5 cards/row at 20% each.
   Below 1400px Bootstrap defaults take over: col-sm-6 / col-xl-4. */
@media (min-width: 1400px) {
  .si-col-xxl-5 {
    flex: 0 0 auto;
    width: 20%;
  }
}

/* Disable Chrome's scroll anchoring on the new catalog. Otherwise the browser tries
   to keep "stable" content anchored during the AJAX swap, but the anchor
   it picks is unpredictable (often a product card that's about to be
   removed). We own scroll behavior via mallistix-new.js's captureScrollAnchor
   — it places the sidebar facet that the user clicked at the same viewport
   position as before, which is what the user expects. */
html {
  overflow-anchor: none;
}

/* Active filter chips — thicker, darker outline around the whole chip.
   Matches the visual weight the user liked on the X button's focus ring
   and extends it to surround the entire chip. Scoped to #mxnew-root so
   the legacy / catalog keeps its original thinner outline.
   X separator is removed — the toggle and X look like one continuous chip
   with no internal divider line, only the outer 2px border surrounds it. */
#mxnew-root .si-active-pill {
  border-width: 2px;
  border-color: var(--si-text-muted);
}
#mxnew-root .si-active-pill:hover {
  border-color: var(--si-accent);
}
#mxnew-root .si-active-pill-x {
  /* Reset native <button> defaults (border 2px outset + grey bg) which
     don't fire for legacy /'s <a> variant, then re-apply ONLY the
     left-side separator at the same 2px weight as the chip outline. */
  border: none;
  border-left: 2px solid var(--si-text-muted);
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
}
#mxnew-root .si-active-pill:hover .si-active-pill-x {
  border-left-color: var(--si-accent);
}

/* AJAX skeleton overlay during a filter swap. The .mxnew-loading state is
   added to #mxnew-root by mallistix-new.js for the duration of the fetch.
   Two effects compound: (1) content dims + becomes non-interactive, (2) a
   subtle progress bar pulses at the top edge so the user feels something
   is happening even on instant Redis-backed responses (~10-30ms). */
#mxnew-root {
  position: relative;
}
#mxnew-root.mxnew-loading {
  /* Non-interactive while waiting for swap, but NO global dim — we localize
     the visual "loading" effect to the products grid only (below). Sidebar,
     chip bar, banner, h1, trust bar all stay at full opacity — they're not
     stale, they're already correct for the in-flight selection. */
  pointer-events: none;
  cursor: progress;
}

/* Localized loading effect — tinted overlay PER PRODUCT CARD (not a
   single bar covering the whole grid). Each card gets its own ::after
   so the user sees individual cards transitioning, matching the visual
   metaphor of "cards being replaced one at a time". Theme-aware:
   light → dark tint (cards visibly darkened / glass-panel feel);
   dark  → light tint (cards visibly lifted from the near-black bg).
   Filter brightness() doesn't work on dark mode (multipliers can't lift
   true-black), so we use a tinted overlay which GUARANTEES visibility
   regardless of card content. Combined with the red pulse bar above
   the grid, the swap moment becomes obvious even on sub-200ms responses. */
#mxnew-root .si-product-card {
  position: relative;
}
#mxnew-root .si-product-card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s ease-out;
  z-index: 4;
  border-radius: inherit;
}
[data-bs-theme="light"] #mxnew-root .si-product-card::after {
  background: rgba(15, 20, 40, .45);
}
[data-bs-theme="dark"] #mxnew-root .si-product-card::after {
  background: rgba(220, 230, 255, .20);
}
#mxnew-root.mxnew-loading .si-product-card::after {
  opacity: 1;
}
/* Mild saturate drop on the whole grid during loading reinforces the
   "in transition" feel without competing with the per-card tints. */
#mxnew-products {
  transition: filter .15s ease-out;
}
#mxnew-root.mxnew-loading #mxnew-products {
  filter: saturate(.6);
}
/* Pulse bar — visible only while loading. Anchored to #mxnew-products
   so it appears RIGHT ABOVE the product grid (just below the active
   filter chip bar). Earlier it was on #mxnew-root::before (top of the
   whole layout) — user wanted it closer to the products area where
   their eye is already focused after a filter click. CSS animation,
   zero reflow cost. */
#mxnew-products {
  position: relative;
}
#mxnew-products::before {
  content: '';
  position: absolute;
  top: -3px;
  left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg,
    transparent 0%,
    var(--si-accent-text) 30%,
    var(--si-accent-text) 70%,
    transparent 100%);
  background-size: 200% 100%;
  background-position: 100% 0;
  opacity: 0;
  pointer-events: none;
  z-index: 5;
  transition: opacity .1s ease;
}
#mxnew-root.mxnew-loading #mxnew-products::before {
  opacity: 1;
  animation: mxnew-pulse 1.1s linear infinite;
}
@keyframes mxnew-pulse {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

/* CSS containment removed — measured negligible perf benefit (style
   recalc per task stayed at 410ms vs 368ms baseline) but caused two
   real bugs: (1) chip dropdowns landed off-screen because `contain:
   layout` makes the element a containing block for `position: fixed`
   descendants; (2) overlay pseudo-elements on the grid could not cover
   the cards because each card got its own stacking context. Not worth
   the trade-off. Left this comment as a "do not re-add" reminder. */

