/*!
 * Search+ 3.0 — shopper-facing overlay styles (Phase 4a contract §1.8).
 * Hand-written, no framework, no webfont. Every selector is .sp--prefixed and
 * scoped to .sp-root, at most two classes deep (§1.8), so a theme overrides us
 * by setting the tokens below. Budget: this file <= 14336 bytes, unminified.
 * !important appears five times, each marked [!]: the [hidden] contract, the
 * body scroll lock, and three text-decoration declarations that hostile theme
 * link rules (higher specificity than two classes) would otherwise win.
 */

/* tokens */

/* Computed contrast, light: accent/bg 6.52, accent/tint 5.67, white/accent
   6.52, muted/bg 6.23, muted/tint 5.42, border-strong 4.25. Dark: 7.16, 7.16,
   7.11, 4.67. --sp-border is decorative, so 1.4.11 exempts it. */

.sp-root {
  color-scheme: light; /* or Chromium picks ::placeholder for the wrong scheme */
  --sp-bg: #fff;
  --sp-fg: #16181d;
  --sp-muted: #5a616e;
  --sp-border: #e2e5ea;
  --sp-border-strong: #767b85;
  --sp-accent: #0b53d6;
  --sp-accent-soft: rgba(11, 83, 214, .09);
  --sp-danger: #b4232a;
  --sp-skel: #e9ecf1;
  --sp-shine: rgba(255, 255, 255, .65);
  --sp-radius: 10px;
  --sp-shadow: 0 8px 28px rgba(16, 24, 40, .14), 0 1px 3px rgba(16, 24, 40, .08);
  --sp-row-h: 72px;
  --sp-font: inherit;
  --sp-z: 999999;
}

/* OS preference plus a .sp-dark hook, since themes force their own scheme. The
   dark accent is legible AS TEXT on dark, so it is a poor background for white:
   anything filled with it puts var(--sp-bg) on top. */
@media (prefers-color-scheme: dark) {
  .sp-root {
    color-scheme: dark;
    --sp-bg: #14161a;
    --sp-fg: #f2f4f7;
    --sp-muted: #9aa3b0;
    --sp-border: #2b3038;
    --sp-border-strong: #7b828d;
    --sp-accent: #6aa3ff;
    --sp-accent-soft: rgba(106, 163, 255, .14);
    --sp-danger: #ff8a8a;
    --sp-skel: #23262c;
    --sp-shine: rgba(255, 255, 255, .07);
    --sp-shadow: 0 10px 30px rgba(0, 0, 0, .55), 0 1px 2px rgba(0, 0, 0, .4);
  }
}

.sp-root.sp-dark,
html.sp-dark .sp-root,
body.sp-dark .sp-root {
  color-scheme: dark;
  --sp-bg: #14161a;
  --sp-fg: #f2f4f7;
  --sp-muted: #9aa3b0;
  --sp-border: #2b3038;
  --sp-border-strong: #7b828d;
  --sp-accent: #6aa3ff;
  --sp-accent-soft: rgba(106, 163, 255, .14);
  --sp-danger: #ff8a8a;
  --sp-skel: #23262c;
  --sp-shine: rgba(255, 255, 255, .07);
  --sp-shadow: 0 10px 30px rgba(0, 0, 0, .55), 0 1px 2px rgba(0, 0, 0, .4);
}

/* defensive resets (§1.8) */

/* Neutralises theme rules on OUR nodes only; `all: initial` is avoided so that
   font-family and direction still inherit. */
.sp-root,
.sp-root * {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: none;
  box-shadow: none;
  float: none;
  min-width: 0;
  max-width: none;
  font: inherit;
  font-family: var(--sp-font);
  color: inherit;
  letter-spacing: normal;
  text-transform: none;
  text-align: start;
  text-shadow: none;
  list-style: none;
  vertical-align: baseline;
  animation: none;
  transition: none;
}

/* [!] Regions toggle with `hidden`; a theme `div { display: block }` would
   otherwise reveal them. */
.sp-root [hidden] {
  display: none !important;
}

.sp-root button,
.sp-root input {
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  font: inherit;
}

.sp-root input {
  cursor: auto;
}

/* SR-only live region: it lives on document.body, so it carries .sp-root. */
.sp-root.sp-sr,
.sp-root .sp-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* panel */

.sp-root.sp-panel {
  position: absolute;
  top: 0;
  left: 0;
  z-index: var(--sp-z);
  display: flex;
  flex-direction: column;
  width: 320px;
  max-width: 100vw;
  max-height: 62vh;
  overflow: hidden;
  background: var(--sp-bg);
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius);
  box-shadow: var(--sp-shadow);
  color: var(--sp-fg);
  font-size: 15px;
  line-height: 1.35;
  text-align: start;
  direction: inherit;
}

/* result list */

.sp-root .sp-list {
  position: relative;
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--sp-border) transparent;
}

.sp-root .sp-list::-webkit-scrollbar {
  width: 8px;
}

.sp-root .sp-list::-webkit-scrollbar-thumb {
  background: var(--sp-border);
  border-radius: 8px;
}

/* Stale results are never blanked (§1.4.1); the hairline is now the ONLY
   staleness cue, because `opacity: .62` put the out-of-stock badge at 3.18:1 and
   muted text at 2.40:1. The iteration cap satisfies 2.2.2. */
.sp-root .sp-list[aria-busy]::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--sp-accent), transparent);
  animation: sp-shine 1.1s linear 4;
  pointer-events: none;
}

/* rows */

.sp-root .sp-row {
  position: relative;
  display: flex;
  gap: 12px;
  align-items: center;
  min-height: var(--sp-row-h);
  padding: 12px 14px;
  border-bottom: 1px solid var(--sp-border);
  color: var(--sp-fg);
  cursor: pointer;
  /* [!] Theme link rules (`.site a { text-decoration: underline }`) outrank our
     two-class selector, and an underlined row looks broken. */
  text-decoration: none !important;
}

.sp-root .sp-row:last-child {
  border-bottom: 0;
}

.sp-root .sp-row:hover,
.sp-root .sp-row.is-active {
  background: var(--sp-accent-soft);
}

/* Never colour alone (1.4.1): a 2 px inset bar and a bolder title too. */
.sp-root .sp-row.is-active::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 2px;
  background: var(--sp-accent);
}

/* Depth 2: our own pooled markup (§1.8). */
.sp-row.is-active .sp-title {
  font-weight: 700;
}

.sp-root .sp-thumb {
  position: relative;
  flex: 0 0 48px;
  width: 48px;
  height: 48px;
  overflow: hidden;
  background: var(--sp-skel);
  border-radius: 6px;
}

/* No image, or the image failed to load. */
.sp-root .sp-thumb.is-ph::after {
  content: "";
  position: absolute;
  top: 14px;
  left: 14px;
  width: 20px;
  height: 20px;
  border: 2px solid var(--sp-border);
  border-radius: 4px;
}

.sp-root .sp-img {
  display: block;
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 6px;
}

.sp-root .sp-body {
  display: block;
  flex: 1 1 auto;
  min-width: 0;
}

.sp-root .sp-title {
  display: -webkit-box;
  overflow: hidden;
  font-size: 15px;
  line-height: 1.35;
  word-break: break-word;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.sp-root .sp-meta {
  display: flex;
  gap: 8px;
  align-items: baseline;
  margin-top: 3px;
}

.sp-root .sp-price {
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

.sp-root .sp-oos {
  color: var(--sp-danger);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
}

/* suggestion note, footer, links */

.sp-root .sp-note {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: baseline;
  padding: 9px 14px;
  background: var(--sp-accent-soft);
  border-bottom: 1px solid var(--sp-border);
  font-size: 13px;
}

.sp-root .sp-note-h {
  font-weight: 600;
}

/* 2.5.8: 17.6 px passed only via the spacing exception, by 3-7 px, on
   translator-controlled strings. Padding makes it 25.6 px; the negative block
   margin keeps the line box unchanged. */
.sp-root .sp-note-btn,
.sp-root .sp-retry {
  padding: 4px 6px;
  margin: -4px 0;
  color: var(--sp-accent);
  font-size: 13px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.sp-root .sp-foot {
  flex: 0 0 auto;
  border-top: 1px solid var(--sp-border);
  background: var(--sp-bg);
}

.sp-root .sp-all {
  display: block;
  padding: 13px 14px;
  color: var(--sp-accent);
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  text-decoration: none !important; /* [!] same theme-link reason as .sp-row */
}

/* :hover alone: pairing it with :focus-visible would lose BOTH where that
   pseudo-class is unknown, and the ring already covers focus (A11Y-13). */
.sp-root .sp-all:hover {
  background: var(--sp-accent-soft);
}

/* empty / error / rate limited */

.sp-root .sp-msg {
  padding: 18px 16px;
}

.sp-root .sp-msg-h {
  font-size: 15px;
  font-weight: 600;
  word-break: break-word;
}

.sp-root .sp-msg-t {
  display: block;
  color: var(--sp-muted);
  font-size: 14px;
}

.sp-root .sp-alert {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: baseline;
  padding: 12px 14px;
}

.sp-root .sp-acts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin-top: 10px;
}

.sp-root .sp-link {
  padding: 4px 6px; /* 2.5.8, as .sp-note-btn above: 18.9 px -> 26.9 px */
  margin: -4px 0;
  color: var(--sp-accent);
  font-size: 14px;
  font-weight: 600;
  text-decoration: underline !important; /* [!] beats theme link resets */
  text-underline-offset: 2px;
}

/* skeleton (§1.4.1) */

/* Three shimmer rows drawn purely with background layers, so no throwaway DOM
   is built on every keystroke. */
.sp-root .sp-skel {
  position: relative;
  flex: 0 0 auto;
  height: calc(var(--sp-row-h) * 3);
  overflow: hidden;
  --sp-bar: linear-gradient(var(--sp-skel), var(--sp-skel));
  background-color: transparent;
  background-image:
    var(--sp-bar), var(--sp-bar), var(--sp-bar),
    var(--sp-bar), var(--sp-bar), var(--sp-bar),
    var(--sp-bar), var(--sp-bar), var(--sp-bar);
  background-repeat: no-repeat;
  background-size:
    48px 48px, 46% 13px, 26% 11px,
    48px 48px, 46% 13px, 26% 11px,
    48px 48px, 46% 13px, 26% 11px;
  background-position:
    14px 14px, 74px 20px, 74px 43px,
    14px 86px, 74px 92px, 74px 115px,
    14px 158px, 74px 164px, 74px 187px;
}

.sp-root .sp-skel::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, var(--sp-shine), transparent);
  animation: sp-shine 1.15s linear 4; /* 2.2.2: stops itself at ~4.6 s */
}

@keyframes sp-shine {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}

/* mobile sheet (§1.2, §1.8) */

.sp-root.sp-sheet {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: auto;
  max-width: none;
  max-height: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  /* Touches on the sheet padding must not chain to the page. */
  overscroll-behavior: none;
}

.sp-root .sp-head {
  display: flex;
  flex: 0 0 auto;
  gap: 8px;
  align-items: center;
  padding: 10px 10px 10px 12px;
  border-bottom: 1px solid var(--sp-border);
  background: var(--sp-bg);
}

.sp-root .sp-input {
  flex: 1 1 auto;
  height: 44px;
  padding: 0 12px;
  background: var(--sp-bg);
  /* Fully custom-styled, so 1.4.11 grants no user-agent exception and this 1 px
     border is the only boundary of the field: >= 3:1 required. */
  border: 1px solid var(--sp-border-strong);
  border-radius: 8px;
  color: var(--sp-fg);
  font-size: 16px; /* 16px keeps iOS from zooming the viewport on focus */
  line-height: 44px;
}

/* The only instruction in the full-screen mobile UI; Chromium's internal one
   measures 1.09:1 on the dark panel, this measures 6.23/7.11. */
.sp-root .sp-input::placeholder {
  color: var(--sp-muted);
  opacity: 1;
}

.sp-root .sp-input:focus {
  border-color: var(--sp-accent);
  box-shadow: 0 0 0 3px var(--sp-accent-soft);
}

.sp-root .sp-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
}

/* Glyph in CSS: the name comes from the aria-label. */
.sp-root .sp-close::before {
  content: "\00d7";
}

.sp-root .sp-close {
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  border-radius: 8px;
  color: var(--sp-muted);
  font-size: 18px;
  line-height: 44px;
  text-align: center;
}

.sp-root .sp-close:hover {
  background: var(--sp-accent-soft);
  color: var(--sp-fg);
}

.sp-sheet .sp-list {
  max-height: none;
  /* 2.4.11: the sticky footer overlays the end of this scroller and
     scrollIntoView({block:'nearest'}) ignores it, so the last active option
     would settle behind it. Reserve the footer height. */
  scroll-padding-block-end: 48px;
}

.sp-sheet .sp-row {
  min-height: 56px;
  padding: 14px;
}

.sp-sheet .sp-foot {
  position: sticky;
  bottom: 0;
}

/* [!] Body scroll lock while the sheet is open: themes commonly declare
   `body { overflow-x: hidden }`, which would defeat it. */
html.sp-lock,
html.sp-lock body {
  overflow: hidden !important;
  overscroll-behavior: none;
}

/* iOS Safari ignores `overflow: hidden` for touch, so the body also leaves flow;
   the JS sets body.style.top = -scrollY and restores it with scrollTo. */
html.sp-lock body {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
}

/* focus & reduced motion */

/* Ring drawn INSIDE the box: `overflow: hidden` on the panel and its scrollers
   clips an offset outline, costing the edge chips and the footer link part of
   their ring (2.4.7, 2.4.11). The transparent outline is what forced-colors
   repaints. Base rule is plain :focus so browsers without :focus-visible still
   get a ring; rule two withdraws it from pointer focus (A11Y-13). */
.sp-root :focus {
  outline: 2px solid transparent;
  outline-offset: -2px;
  box-shadow: inset 0 0 0 2px var(--sp-accent), inset 0 0 0 4px var(--sp-bg);
}

.sp-root :focus:not(:focus-visible) {
  outline: 0;
  box-shadow: none;
}

/* The reset already sets `transition: none`, so only the keyframes need it. */
@media (prefers-reduced-motion: reduce) {
  .sp-root .sp-skel::after,
  .sp-root .sp-list[aria-busy]::after {
    animation: none;
  }
}

/* Forced colours drop background and box-shadow, so the active row and the
   thumb lose their marks (the focus outline is repainted by the mode). */
@media (forced-colors: active) {
  .sp-root .sp-row.is-active {
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }

  .sp-root .sp-input,
  .sp-root .sp-thumb {
    border: 1px solid ButtonBorder;
  }
}

/* Very narrow desktop viewports. */
@media (max-width: 360px) {
  .sp-root.sp-panel {
    max-width: calc(100vw - 8px);
  }
}
