/* ============================================================
   FragSearcher - Liquid Glass UI (iOS-inspired)
   Rewritten for a translucent, layered "liquid glass" look.
   Class names preserved so markup/JS stay compatible.
   ============================================================ */

/* Pjax navigation: a subtle "loading" cue while the next page's <main> is
   fetched and swapped in. Kept light so quick hops don't flicker. */
body.pjax-loading { cursor: progress; }
body.pjax-loading main { opacity: 0.6; transition: opacity 0.12s ease; }

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Consistent interface icon system, sourced from Lucide. User-authored emoji
   remain untouched in forum posts and the message emoji picker. */
.ui-icon {
  --ui-icon: none;
  display: inline-block;
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  vertical-align: -0.14em;
  background-color: currentColor;
  -webkit-mask: var(--ui-icon) center / contain no-repeat;
  mask: var(--ui-icon) center / contain no-repeat;
}
.ui-icon[data-icon="archive"] { --ui-icon: url('/static/ui-icons/archive.svg'); }
.ui-icon[data-icon="badge-check"] { --ui-icon: url('/static/ui-icons/badge-check.svg'); }
.ui-icon[data-icon="badge-dollar-sign"] { --ui-icon: url('/static/ui-icons/badge-dollar-sign.svg'); }
.ui-icon[data-icon="bell"] { --ui-icon: url('/static/ui-icons/bell.svg'); }
.ui-icon[data-icon="chart"] { --ui-icon: url('/static/ui-icons/chart-no-axes-column.svg'); }
.ui-icon[data-icon="chart-up"] { --ui-icon: url('/static/ui-icons/chart-no-axes-column-increasing.svg'); }
.ui-icon[data-icon="check"] { --ui-icon: url('/static/ui-icons/circle-check.svg'); }
.ui-icon[data-icon="circle-x"] { --ui-icon: url('/static/ui-icons/circle-x.svg'); }
.ui-icon[data-icon="clock"] { --ui-icon: url('/static/ui-icons/clock-3.svg'); }
.ui-icon[data-icon="flame"] { --ui-icon: url('/static/ui-icons/flame.svg'); }
.ui-icon[data-icon="grip"] { --ui-icon: url('/static/ui-icons/grip-vertical.svg'); }
.ui-icon[data-icon="hand"] { --ui-icon: url('/static/ui-icons/hand.svg'); }
.ui-icon[data-icon="handshake"] { --ui-icon: url('/static/ui-icons/handshake.svg'); }
.ui-icon[data-icon="heart"] { --ui-icon: url('/static/ui-icons/heart.svg'); }
.ui-icon[data-icon="image"] { --ui-icon: url('/static/ui-icons/image.svg'); }
.ui-icon[data-icon="user"] { --ui-icon: url('/static/ui-icons/circle-user.svg'); }
.ui-icon[data-icon="home"] { --ui-icon: url('/static/ui-icons/house.svg'); }
.ui-icon[data-icon="heading"] { --ui-icon: url('/static/ui-icons/heading.svg'); }
.ui-icon[data-icon="paragraph"] { --ui-icon: url('/static/ui-icons/align-left.svg'); }
.ui-icon[data-icon="button"] { --ui-icon: url('/static/ui-icons/rectangle-horizontal.svg'); }
.ui-icon[data-icon="divider"] { --ui-icon: url('/static/ui-icons/minus.svg'); }
.ui-icon[data-icon="spacer"] { --ui-icon: url('/static/ui-icons/move-vertical.svg'); }
.ui-icon[data-icon="link"] { --ui-icon: url('/static/ui-icons/link.svg'); }
.ui-icon[data-icon="lock"] { --ui-icon: url('/static/ui-icons/lock-keyhole.svg'); }
.ui-icon[data-icon="map-pin"] { --ui-icon: url('/static/ui-icons/map-pin.svg'); }
.ui-icon[data-icon="message"] { --ui-icon: url('/static/ui-icons/message-circle.svg'); }
.ui-icon[data-icon="messages"] { --ui-icon: url('/static/ui-icons/messages-square.svg'); }
.ui-icon[data-icon="package"] { --ui-icon: url('/static/ui-icons/package.svg'); }
.ui-icon[data-icon="party"] { --ui-icon: url('/static/ui-icons/party-popper.svg'); }
.ui-icon[data-icon="pencil"] { --ui-icon: url('/static/ui-icons/pencil.svg'); }
.ui-icon[data-icon="pin"] { --ui-icon: url('/static/ui-icons/pin.svg'); }
.ui-icon[data-icon="search"] { --ui-icon: url('/static/ui-icons/search.svg'); }
.ui-icon[data-icon="share"] { --ui-icon: url('/static/ui-icons/share-2.svg'); }
.ui-icon[data-icon="shield-ban"] { --ui-icon: url('/static/ui-icons/shield-ban.svg'); }
.ui-icon[data-icon="shopping-bag"] { --ui-icon: url('/static/ui-icons/shopping-bag.svg'); }
.ui-icon[data-icon="sliders"] { --ui-icon: url('/static/ui-icons/sliders-horizontal.svg'); }
.ui-icon[data-icon="smile-plus"] { --ui-icon: url('/static/ui-icons/smile-plus.svg'); }
.ui-icon[data-icon="sparkles"] { --ui-icon: url('/static/ui-icons/sparkles.svg'); }
.ui-icon[data-icon="spray-can"] { --ui-icon: url('/static/ui-icons/spray-can.svg'); }
.ui-icon[data-icon="warning"] { --ui-icon: url('/static/ui-icons/triangle-alert.svg'); }
.ui-icon[data-icon="x"] { --ui-icon: url('/static/ui-icons/x.svg'); }
.ui-icon[data-icon="zap"] { --ui-icon: url('/static/ui-icons/zap.svg'); }

:root {
  /* ── Palette ── */
  --bg:          #eef0f8;
  --bg-2:        #e7e9f6;
  --ink:         #1a1a20;
  --ink-2:       #5c5c6b;
  /* Darkened from #9a9aab (only ~2.4:1 on --bg) to meet WCAG AA 4.5:1 for the
     hint / label / metadata text that uses this token. */
  /* Measured on the glass panels this mostly sits on: #6b6b7a came to
     4.38:1 there, under the floor for the 11-13px it is set in. */
  --ink-3:       #65657a;

  /* Fill shades are dark enough for white button text at normal text sizes. */
  --accent:      #c92534;
  --accent-2:    #d93444;
  --accent-ink:  #b01722;
  /* The deep end of the accent, for gradients and fills. --accent-ink is
     re-pointed to a LIGHT red in the dark theme because it is mostly text
     there, so it cannot double as the dark end of a ground. */
  --accent-deep: #b01722;
  --accent-soft: rgba(226,55,68,0.12);
  --accent-glow: rgba(226,55,68,0.34);

  --gold:        #c8961e;
  --gold-2:      #e0b34a;
  --success:     #08783a;
  --danger:      #bd2530;

  /* ── Liquid glass tokens ──
     Backgrounds are more opaque than a true glass look so that
     backdrop-filter is only needed on ONE element (the hero search box).
     Dozens of blurred layers (every card/chip/button) forced continuous
     GPU compositing and made the whole page laggy. */
  --glass:        rgba(255,255,255,0.78);
  --glass-strong: rgba(255,255,255,0.9);
  --glass-hi:     rgba(255,255,255,0.95);   /* specular highlight */
  --glass-edge:   rgba(255,255,255,0.65);
  --glass-line:   rgba(17,17,34,0.06);
  /* ── Form controls ── single source of truth for every input / select /
     textarea surface, so fields read as one family site-wide. See the
     "Unified form controls" block near the end of this file. */
  --input-bg:     rgba(255,255,255,0.85);
  --input-border: rgba(17,17,34,0.14);
  --r-input:      var(--r-ctrl);
  --blur:         blur(30px) saturate(190%);
  --blur-sm:      blur(16px) saturate(170%);

  /* ── Geometry ── */
  --r-card:  26px;
  --r-ctrl:  17px;
  --r-sm:    12px;
  --r-pill:  999px;

  /* ── Spacing scale ── */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s8: 32px; --s10: 40px;

  /* ── Elevation (soft, layered → the "floating glass" feel) ── */
  --e-1:
    0 1px 2px rgba(20,20,50,0.05),
    0 4px 14px rgba(20,20,50,0.05),
    inset 0 1px 0 var(--glass-hi);
  --e-2:
    0 2px 6px rgba(20,20,50,0.05),
    0 10px 30px rgba(20,20,50,0.08),
    0 1px 0 rgba(255,255,255,0.4),
    inset 0 1px 0 var(--glass-hi),
    inset 0 -1px 0 rgba(20,20,50,0.03);
  --e-3:
    0 6px 18px rgba(20,20,50,0.09),
    0 24px 60px rgba(20,20,50,0.14),
    inset 0 1px 0 var(--glass-hi);

  --t:      .2s cubic-bezier(.3,.5,.35,1);
  --spring: .34s cubic-bezier(.34,1.4,.5,1);
}

/* `clip` rather than `hidden`: hidden turns html/body into scroll containers,
   which silently breaks every position: sticky element on the page. */
html { scroll-behavior: smooth; overflow-x: clip; }

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Inter', system-ui, sans-serif;
  color: var(--ink);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: var(--bg);
  letter-spacing: -0.01em;
  overflow-x: clip;
}

/* Reusable specular sheen for glass surfaces */
.glass-sheen { position: relative; }
.glass-sheen::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(150deg,
    rgba(255,255,255,0.55) 0%,
    rgba(255,255,255,0.10) 22%,
    rgba(255,255,255,0) 46%);
  mix-blend-mode: screen;
}

/* ============================================================
   Header / hero
   ============================================================ */
.header {
  position: relative;
  color: #fff;
  padding: 56px 24px 30px;
  text-align: center;
  overflow: hidden;
  background:
    radial-gradient(60% 120% at 50% -10%,
      rgba(255,90,106,0.55) 0%,
      rgba(255,90,106,0.30) 30%,
      rgba(255,90,106,0.10) 48%,
      rgba(255,90,106,0) 66%),
    linear-gradient(165deg, #2a0e13 0%, #351319 48%, #200a0e 100%);
  box-shadow: 0 20px 60px rgba(40,12,18,0.38);
}
.header::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(50% 60% at 15% 20%,
      rgba(226,55,68,0.30) 0%, rgba(226,55,68,0.16) 28%,
      rgba(226,55,68,0.05) 45%, rgba(226,55,68,0) 62%),
    radial-gradient(46% 50% at 88% 30%,
      rgba(255,120,120,0.20) 0%, rgba(255,120,120,0.11) 28%,
      rgba(255,120,120,0.04) 45%, rgba(255,120,120,0) 62%);
}
.header-inner { position: relative; z-index: 1; }

.addon-banner {
  position: relative;
  z-index: 20;
  color: #fff;
  /* The same material, carrying the accent. The highlight fades to white at
     zero alpha rather than to `transparent`, which is transparent BLACK and
     leaves a dirty ring where it ends. */
  background:
    radial-gradient(70% 160% at 10% 0%,
      rgba(255,255,255,0.22) 0%,
      rgba(255,255,255,0.10) 28%,
      rgba(255,255,255,0.04) 46%,
      rgba(255,255,255,0) 64%),
    linear-gradient(135deg, rgba(206,40,54,0.92) 0%, rgba(150,18,30,0.92) 100%);
  -webkit-backdrop-filter: saturate(170%) blur(18px);
  backdrop-filter: saturate(170%) blur(18px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.28),
    inset 0 -1px 0 rgba(0,0,0,0.22),
    0 8px 26px rgba(150,18,30,0.26);
}
.addon-banner[hidden] { display: none; }
.addon-banner-inner {
  max-width: 1180px;
  margin: 0 auto;
  min-height: 44px;
  padding: 8px 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: center;
}
.addon-banner-copy {
  font-size: 0.92rem;
  line-height: 1.35;
  color: #fff;
}
.addon-banner-copy strong { color: #fff; }
.addon-banner-link {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  color: #b01722;
  background: rgba(255,255,255,0.94);
  text-decoration: none;
  font-size: 0.82rem;
  font-weight: 800;
  box-shadow: 0 6px 16px rgba(64,0,8,0.16);
  transition: transform var(--t), background var(--t), box-shadow var(--t);
}
.addon-banner-link:hover {
  transform: translateY(-1px);
  background: #fff;
  box-shadow: 0 8px 20px rgba(64,0,8,0.22);
}
.addon-banner-close {
  flex: none;
  width: 28px;
  height: 28px;
  border: 1px solid rgba(255,255,255,0.34);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: rgba(255,255,255,0.12);
  font: inherit;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--t), border-color var(--t), transform var(--t);
}
.addon-banner-close:hover,
.addon-banner-close:focus-visible {
  background: rgba(255,255,255,0.22);
  border-color: rgba(255,255,255,0.6);
  transform: translateY(-1px);
  outline: none;
}

.logo { display: inline-flex; align-items: center; gap: 10px; }
.logo-word {
  width:250px
}
.logo-icon {
  width: 38px;
  height: auto;
  flex: none;
}
.tagline {
  font-size: 0.9rem;
  color: rgba(255,255,255,0.5);
  font-weight: 400;
}

/* Home intro: a light strip beneath the sticky nav (no dark banner), so the page
   reads like the internal pages - glass nav straight onto the light surface. */
.home-hero {
  position: relative;
  text-align: center;
  padding: 30px 24px 4px;
  background: transparent;
}
.home-hero .tagline {
  font-size: 1.08rem;
  color: var(--ink-2);
  max-width: 660px;
  margin: 0 auto;
  line-height: 1.55;
}

/* ============================================================
   Search
   ============================================================ */
.search-section {
  position: relative;
  padding: 12px 24px 26px;
  background: transparent;
}
.search-container { max-width: 740px; margin: 0 auto; }
.search-form { margin-bottom: 18px; position: relative; }

/* ── Search autocomplete dropdown ── */
.search-suggest {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  z-index: 40;
  padding: 6px;
  border-radius: var(--r-ctrl);
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--e-3);
  max-height: 340px;
  overflow-y: auto;
}
.search-suggest-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.search-suggest-item:hover,
.search-suggest-item.is-active {
  background: rgba(127, 127, 160, 0.16);
}
.search-suggest-img {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  border-radius: 9px;
  object-fit: contain;
  background: rgba(127, 127, 160, 0.10);
}
.search-suggest-img--empty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.55;
  font-size: 15px;
}
.search-suggest-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.search-box {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 7px 7px 20px;
  border-radius: var(--r-pill);
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--e-2);
  transition: border-color var(--t), box-shadow var(--t), background var(--t);
}
.search-box:focus-within {
  background: var(--glass-strong);
  border-color: rgba(226,55,68,0.5);
  box-shadow: var(--e-2), 0 0 0 4px var(--accent-soft);
}
.search-icon { color: var(--ink-3); flex-shrink: 0; display: flex; }
.search-input {
  flex: 1;
  border: none;
  outline: none;
  font: inherit;
  font-size: 1.02rem;
  color: var(--ink);
  background: transparent;
  min-width: 0;
}
.search-input::placeholder { color: var(--ink-3); }

.search-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  border: 1px solid rgba(255,255,255,0.25);
  border-radius: var(--r-pill);
  padding: 12px 24px;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  background: linear-gradient(135deg, var(--accent-2) 0%, var(--accent) 60%, var(--accent-deep) 100%);
  box-shadow:
    0 6px 20px var(--accent-glow),
    inset 0 1px 0 rgba(255,255,255,0.35);
  transition: transform var(--t), box-shadow var(--t), filter var(--t);
}
.search-btn:hover { transform: translateY(-1px); filter: brightness(1.06);
  box-shadow: 0 10px 30px rgba(226,55,68,0.55), inset 0 1px 0 rgba(255,255,255,0.4); }
.search-btn:active { transform: translateY(0) scale(0.98); }
.btn-icon { font-size: 1.05rem; }

/* Rate-limit countdown: the Search button is disabled and shows "Wait Ns"
   between searches so the stores aren't pelted with back-to-back scrapes. */
.search-btn--cooldown,
.search-btn:disabled {
  filter: grayscale(0.5);
  opacity: 0.72;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.25);
}
/* Cooldown only rate-limits fresh scrapes - the button stays clickable so a
   still-cached fragrance can be pulled up instantly (pointer, not not-allowed). */
.search-btn--cooldown { cursor: pointer; }
.search-btn:disabled  { cursor: not-allowed; }
.search-btn:disabled:hover { transform: none; filter: grayscale(0.5); }
.search-btn--cooldown .btn-text { font-variant-numeric: tabular-nums; }

/* Cancel button (shown while a search is streaming) - a neutral slate variant
   so it reads as "stop", not another primary action. */
.search-btn--cancel {
  background: linear-gradient(135deg, #6b7280 0%, #4b5563 60%, #374151 100%);
  box-shadow: 0 6px 20px rgba(55,65,81,0.4), inset 0 1px 0 rgba(255,255,255,0.25);
}
.search-btn--cancel:hover {
  box-shadow: 0 10px 30px rgba(55,65,81,0.5), inset 0 1px 0 rgba(255,255,255,0.3);
}

/* Brief shake when a search is attempted during the cooldown window. */
@keyframes searchNudge {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}
.search-btn.nudge { animation: searchNudge 0.4s ease; }

/* Suggestion rails */
.suggestions { display: flex; flex-direction: column; gap: 8px; }
.suggest-row { display: flex; align-items: center; gap: 12px; min-width: 0; }
.suggest-gender-label {
  flex-shrink: 0;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--ink-2);
  text-transform: uppercase;
  letter-spacing: 0.9px;
  width: 74px;
  text-align: right;
}
.suggest-scroll {
  display: flex; flex-wrap: nowrap; gap: 7px;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none;
  padding: 4px 0 14px;
  flex: 1; min-width: 0; cursor: default;
  touch-action: pan-x pan-y;
}
.suggest-scroll--dragging,
.suggest-scroll--dragging .suggest-chip { cursor: grabbing; user-select: none; }
.suggest-scroll::-webkit-scrollbar { display: none; }

.suggest-scroll--loading {
  cursor: default;
  pointer-events: none;
}
.suggest-scroll--loading .suggest-skel {
  animation:
    latestSkelShimmer 1.3s ease-in-out infinite,
    suggestSkelMascLoop 18s linear infinite;
}
#suggestFem.suggest-scroll--loading .suggest-skel {
  animation:
    latestSkelShimmer 1.3s ease-in-out infinite,
    suggestSkelFemLoop 18s linear infinite;
}
#suggestUnisex.suggest-scroll--loading .suggest-skel {
  animation:
    latestSkelShimmer 1.3s ease-in-out infinite,
    suggestSkelUnisexLoop 18s linear infinite;
}
.suggest-skel {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 30px;
  box-sizing: border-box;
  padding: 6px 15px;
  border-radius: var(--r-pill);
  border: 1px solid var(--glass-line);
  background: linear-gradient(100deg,
    rgba(20,20,50,0.06) 30%, rgba(20,20,50,0.13) 50%, rgba(20,20,50,0.06) 70%);
  background-size: 200% 100%;
  box-shadow: var(--e-1);
  animation: latestSkelShimmer 1.3s ease-in-out infinite;
  overflow: hidden;
  position: relative;
}
.suggest-skel::after {
  content: "";
  color: rgba(20,20,50,0.34);
  filter: blur(4px);
  font-size: 0.78rem;
  font-weight: 650;
  line-height: 1;
  opacity: 0.7;
  white-space: nowrap;
  transform: translateZ(0);
  animation: suggestSkelTextPulse 1.55s ease-in-out infinite;
}
@keyframes suggestSkelTextPulse {
  0%, 100% {
    filter: blur(5px);
    opacity: 0.48;
  }
  50% {
    filter: blur(3px);
    opacity: 0.82;
  }
}
#suggestMasc .suggest-skel:nth-child(6n + 1)::after { content: "Dior Sauvage"; }
#suggestMasc .suggest-skel:nth-child(6n + 2)::after { content: "Bleu de Chanel"; }
#suggestMasc .suggest-skel:nth-child(6n + 3)::after { content: "Creed Aventus"; }
#suggestMasc .suggest-skel:nth-child(6n + 4)::after { content: "Y EDP"; }
#suggestMasc .suggest-skel:nth-child(6n + 5)::after { content: "Azzaro Wanted"; }
#suggestMasc .suggest-skel:nth-child(6n)::after { content: "Spicebomb"; }

#suggestFem .suggest-skel:nth-child(6n + 1)::after { content: "Burberry Her"; }
#suggestFem .suggest-skel:nth-child(6n + 2)::after { content: "Libre"; }
#suggestFem .suggest-skel:nth-child(6n + 3)::after { content: "Black Opium"; }
#suggestFem .suggest-skel:nth-child(6n + 4)::after { content: "Good Girl"; }
#suggestFem .suggest-skel:nth-child(6n + 5)::after { content: "Delina"; }
#suggestFem .suggest-skel:nth-child(6n)::after { content: "Flowerbomb"; }

#suggestUnisex .suggest-skel:nth-child(6n + 1)::after { content: "Baccarat Rouge"; }
#suggestUnisex .suggest-skel:nth-child(6n + 2)::after { content: "Santal 33"; }
#suggestUnisex .suggest-skel:nth-child(6n + 3)::after { content: "Another 13"; }
#suggestUnisex .suggest-skel:nth-child(6n + 4)::after { content: "Mojave Ghost"; }
#suggestUnisex .suggest-skel:nth-child(6n + 5)::after { content: "Angels' Share"; }
#suggestUnisex .suggest-skel:nth-child(6n)::after { content: "Oud Wood"; }
@keyframes suggestSkelMascLoop {
  0%   { transform: translateX(-681px); }
  100% { transform: translateX(0); }
}
@keyframes suggestSkelFemLoop {
  0%   { transform: translateX(0); }
  100% { transform: translateX(-676px); }
}
@keyframes suggestSkelUnisexLoop {
  0%   { transform: translateX(-721px); }
  100% { transform: translateX(0); }
}

.suggest-chip {
  background: var(--glass);
  border: 1px solid var(--glass-line);
  color: var(--ink-2);
  border-radius: var(--r-pill);
  padding: 6px 15px;
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  box-shadow: var(--e-1);
  transition: background var(--t), color var(--t), border-color var(--t), transform var(--t);
}
.suggest-chip:hover {
  background: var(--glass-hi);
  border-color: var(--glass-edge);
  color: var(--ink);
  transform: translateY(-1px);
}

/* Marquee arrows - hover to steer the auto-scroll */
.suggest-arrow {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--glass);
  border: 1px solid var(--glass-line);
  color: var(--ink-2);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--e-1);
  transition: background var(--t), color var(--t), border-color var(--t), transform var(--t);
  user-select: none;
}
.suggest-arrow:hover {
  background: var(--glass-hi);
  border-color: var(--glass-edge);
  color: var(--ink);
  transform: scale(1.08);
}

/* ============================================================
   Main
   ============================================================ */
.main { flex: 1; max-width: 1300px; margin: 0 auto; width: 100%; padding: 26px 24px 56px; }

.deal-feed-strip {
  position: relative;
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  padding: 16px 18px;
  margin-bottom: var(--s4);
  box-shadow: var(--e-2);
  overflow: hidden;
}
.deal-feed-head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
}
.deal-feed-title { font-size: 1rem; font-weight: 800; letter-spacing: -0.2px; margin: 0; }
.deal-feed-sub { font-size: 0.8rem; color: var(--ink-3); margin-top: 3px; }
.deal-feed-list {
  position: relative;
  z-index: 1;
  list-style: none;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(190px, 230px);
  gap: 12px;
  overflow-x: auto;
  padding: 2px 2px 10px;
  scrollbar-width: thin;
}
.deal-card {
  position: relative;
  width: 100%;
  min-height: 196px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: left;
  border: 1px solid var(--glass-edge);
  border-radius: 12px;
  background: rgba(255,255,255,0.48);
  color: inherit;
  cursor: pointer;
  font: inherit;
  overflow: hidden;
  box-shadow: var(--e-1);
  transition: transform var(--spring), box-shadow var(--t), background var(--t);
}
.deal-card:hover { transform: translateY(-2px); box-shadow: var(--e-2); background: rgba(255,255,255,0.74); }
.deal-card-img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 96px;
  object-fit: contain;
  background: #fff;
  border-bottom: 1px solid var(--glass-edge);
}
.deal-card-img--ph {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  font-weight: 800;
}
.deal-card-body { position: relative; z-index: 3; display: flex; flex-direction: column; gap: 4px; padding: 10px 11px 12px; min-width: 0; }
.deal-card-save {
  align-self: flex-start;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(34,197,94,0.10);
  color: var(--success);
  border: 1px solid rgba(34,197,94,0.20);
  font-size: 0.68rem;
  font-weight: 800;
}
.deal-card-name {
  font-size: 0.83rem;
  font-weight: 700;
  line-height: 1.2;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.deal-card-meta { font-size: 0.72rem; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.deal-card-price { color: var(--accent); font-size: 1rem; font-weight: 800; margin-top: 2px; }
.deal-feed-empty {
  grid-column: 1 / -1;
  padding: 14px 4px 4px;
  color: var(--ink-3);
  font-size: 0.84rem;
}

.deal-card-actions { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.deal-card-actions button { border: 1px solid var(--glass-line); border-radius: 999px; background: var(--glass-strong); color: var(--ink-2); padding: 5px 9px; font: inherit; font-size: .72rem; cursor: pointer; }
.deal-card-actions .deal-feed-item { border-color: var(--accent); color: var(--accent); font-weight: 750; }
.deal-card-actions button:hover { background: color-mix(in srgb, var(--accent) 11%, var(--glass-strong)); }

/* Idle - no top padding so the cards line up with the top of the latest-searches rail */
.idle-state { padding: 0; }
.idle-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  align-items: stretch;
  gap: var(--s4);
}

.idle-card {
  min-width: 0;
  position: relative;
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  padding: 24px 22px;
  box-shadow: var(--e-2);
  overflow: hidden;
  height: 100%;
  transition: transform var(--spring), box-shadow var(--t);
}
.idle-card--discount {
  grid-column: 1 / -1;
}
.idle-card--feature {
  grid-column: span 3;
}
.idle-grid--retail-active .idle-card--retail,
.idle-grid--retail-active .idle-card--feature:nth-of-type(3),
.idle-grid--retail-active .idle-card--feature:nth-of-type(4) {
  grid-column: span 2;
}
.idle-grid--retail-active .idle-card--feature:nth-of-type(5),
.idle-grid--retail-active .idle-card--feature:nth-of-type(6) {
  grid-column: span 3;
}
.idle-card:hover { transform: translateY(-3px); box-shadow: var(--e-3); }
.idle-icon { font-size: 1.55rem; display: block; margin-bottom: 10px; }
.idle-card h3 { font-size: 0.92rem; font-weight: 700; margin-bottom: 10px; letter-spacing: -0.2px; }
.idle-list { list-style: none; display: flex; flex-direction: column; gap: 5px; margin-bottom: 10px; }
.idle-list li { font-size: 0.83rem; color: var(--ink-2); display: flex; align-items: center; gap: 7px; }
.idle-list li::before { content: ''; width: 4px; height: 4px; border-radius: 50%; background: var(--accent); opacity: 0.6; flex-shrink: 0; }
.idle-list--ranked {
  counter-reset: discount-rank;
  display: block;
  column-count: 3;
  column-gap: 16px;
}
.idle-list--ranked li {
  counter-increment: discount-rank;
  align-items: center;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  column-gap: 8px;
  break-inside: avoid;
  margin-bottom: 7px;
}
.idle-list--ranked li::before {
  content: counter(discount-rank);
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-ink);
  opacity: 1;
  font-size: 0.72rem;
  font-weight: 800;
}
.ranked-site-main {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
}
.ranked-site-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: 0 0 auto;
}
.ranked-site-name {
  color: var(--ink);
  font-weight: 700;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ranked-site-tip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid var(--glass-edge);
  background: var(--glass-hi);
  color: var(--ink-3);
  font-size: 0.75rem;
  font-weight: 800;
  line-height: 0;
  cursor: help;
}
.idle-note {
  font-size: 0.7rem; background: var(--gold-lt, rgba(224,179,74,0.16)); color: #8a5f00;
  border: 1px solid rgba(224,179,74,0.32); border-radius: 7px; padding: 1px 7px; font-weight: 600;
}
.idle-sub { font-size: 0.8rem; color: var(--ink-3); line-height: 1.5; margin-top: 4px; }
.idle-card:first-child .idle-sub { margin-top: 12px; }
#storeCountText { display: contents; }
.extension-link { color: var(--accent-ink); font-weight: 650; }
.extension-link:hover { color: var(--accent); }
.extension-installed-note { display: none; font-weight: 700; color: var(--accent); }
.sf-extension-installed .extension-link { display: none; }
.sf-extension-installed .extension-installed-note { display: inline; }
.extension-page {
  width: min(100%, 960px);
  margin: 0 auto;
  padding: 28px 18px 56px;
}
.extension-hero {
  padding: 32px 0 26px;
  border-bottom: 1px solid var(--glass-line);
}
.extension-hero h1 {
  margin: 8px 0 10px;
  font-size: clamp(1.9rem, 4vw, 2.4rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0;
}
.extension-hero p {
  max-width: 680px;
  color: var(--ink-2);
  line-height: 1.6;
}
.extension-download { margin-top: 16px; display: inline-flex; }
.extension-install-note { margin: 14px 0 0; color: var(--ink-2); font-size: 0.9rem; line-height: 1.6; }
.extension-actions { display: flex; flex-wrap: wrap; gap: 4px 12px; }
.extension-download[hidden], .extension-status[hidden] { display: none; }
.extension-status {
  display: flex;
  align-items: center;
  gap: 10px;
  width: fit-content;
  max-width: 100%;
  margin-top: 18px;
  padding: 10px 12px;
  border: 1px solid var(--glass-line);
  border-radius: 8px;
  background: var(--glass);
  color: var(--ink-2);
}
.extension-status strong,
.extension-status small {
  display: block;
}
.extension-status strong {
  color: var(--ink);
  font-size: 0.9rem;
}
.extension-status small {
  margin-top: 1px;
  font-size: 0.78rem;
  line-height: 1.35;
}
.extension-status-dot {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: #9aa4b2;
  box-shadow: 0 0 0 4px rgba(154,164,178,0.14);
}
.extension-status--ready .extension-status-dot,
.extension-mini-status--ready .extension-status-dot {
  background: #0d9f58;
  box-shadow: 0 0 0 4px rgba(13,159,88,0.14);
}
.extension-status--running .extension-status-dot,
.extension-mini-status--running .extension-status-dot {
  background: #1d7ff0;
  box-shadow: 0 0 0 4px rgba(29,127,240,0.15);
  animation: extPulse 1.1s ease-in-out infinite;
}
.extension-status--missing .extension-status-dot,
.extension-mini-status--missing .extension-status-dot {
  background: #c47a17;
  box-shadow: 0 0 0 4px rgba(196,122,23,0.14);
}
.extension-status--disabled .extension-status-dot,
.extension-mini-status--disabled .extension-status-dot {
  background: #64748b;
  box-shadow: 0 0 0 4px rgba(100,116,139,0.14);
}
.extension-mini-status {
  display: flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  max-width: 100%;
  margin: 10px auto 14px;
  padding: 7px 10px;
  border: 1px solid var(--glass-line);
  border-radius: 999px;
  background: var(--glass);
  color: var(--ink-2);
  font-size: 0.78rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  appearance: none;
}
.extension-mini-status:hover {
  border-color: color-mix(in srgb, var(--accent) 42%, var(--glass-line));
  color: var(--ink);
}
@keyframes extPulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.25); opacity: 0.72; }
}
.extension-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  margin-top: 22px;
}
.extension-panel {
  background: var(--glass-strong);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  box-shadow: var(--e-2);
  padding: 20px;
}
.extension-panel h2 {
  margin: 0 0 12px;
  font-size: 1rem;
}
.extension-steps,
.extension-list {
  margin: 0;
  padding-left: 20px;
  color: var(--ink-2);
  line-height: 1.7;
}
@media (max-width: 760px) {
  .extension-grid { grid-template-columns: 1fr; }
}
.copy-url {
  font: inherit;
  color: var(--accent);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.copy-url:hover { opacity: 0.82; }
.copy-url.copied { color: #2e9e5b; text-decoration: none; }
.copy-url-hint { color: var(--ink-2); }

/* Main layout: content column on the left, latest-searches rail on the right.
   The rail lives outside the idle/results panels so it stays visible on both. */
/* gap matches the idle-grid gap (--s4) so the rail sits the same distance from
   the last card as the cards sit from each other. */
.main-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  align-items: flex-start;
  gap: var(--s4);
}
.main-col { flex: 1 1 auto; min-width: 0; }

.latest-searches {
  width: 300px;
  position: sticky;
  top: 90px;
  /* Never taller than the viewport - the list inside scrolls instead. */
  max-height: calc(100vh - 106px);
  display: flex;
  flex-direction: column;
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  padding: 20px 18px;
  box-shadow: var(--e-2);
}
.latest-searches--idle,
.latest-searches.is-loading {
  position: static;
  align-self: stretch;
  height: auto;
  max-height: none;
}
.latest-title { font-size: 0.92rem; font-weight: 700; letter-spacing: -0.2px; display: flex; align-items: center; gap: 7px; }
.latest-icon { font-size: 1.1rem; }
.latest-sub { font-size: 0.78rem; color: var(--ink-3); line-height: 1.45; margin: 6px 0 12px; }
/* Header stays put; only this list scrolls. min-height:0 lets it shrink inside
   the flex column. The list is a scroll container, so it clips at its padding
   box - the generous padding (cancelled by matching negative margins, so the
   items stay aligned) gives the item hover shadow room instead of clipping it. */
.latest-list {
  list-style: none; display: flex; flex-direction: column; gap: 6px;
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
  margin: 0 -14px -14px; padding: 4px 14px 14px;
  scrollbar-width: thin;
  scrollbar-color: rgba(20,20,50,0.22) transparent;
}
.latest-list::-webkit-scrollbar { width: 8px; }
.latest-list::-webkit-scrollbar-track { background: transparent; }
.latest-list::-webkit-scrollbar-thumb {
  background: rgba(20,20,50,0.2); border-radius: 999px;
  border: 2px solid transparent; background-clip: padding-box;
}
.latest-list::-webkit-scrollbar-thumb:hover { background: rgba(20,20,50,0.34); background-clip: padding-box; }

.latest-item {
  display: flex; align-items: flex-start; gap: 11px;
  width: 100%; text-align: left;
  background: rgba(255,255,255,0.45);
  border: 1px solid var(--glass-edge);
  border-radius: 12px;
  padding: 9px 10px;
  cursor: pointer;
  font: inherit; color: inherit;
  transition: transform var(--spring), box-shadow var(--t), background var(--t);
}
.latest-item:hover { transform: translateY(-2px); box-shadow: var(--e-1); background: rgba(255,255,255,0.72); }
.latest-thumb {
  flex-shrink: 0; width: 40px; height: 40px; border-radius: 9px; object-fit: contain;
  background: #fff; border: 1px solid var(--glass-edge);
}
.latest-thumb--ph { display: flex; align-items: center; justify-content: center; font-size: 1.1rem; }
.latest-info { min-width: 0; flex: 1; }
.latest-name {
  display: block;
  font-size: 0.82rem; font-weight: 600; line-height: 1.25;
  text-transform: capitalize;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Own line, under the name */
.latest-meta { display: block; font-size: 0.72rem; color: var(--ink-3); margin-top: 2px; }

/* Per-size lowest prices - each size on its own row, split into Normal (retail
   bottle) vs Tester so a cheap tester doesn't misrepresent the real bottle. */
.latest-sizes { display: flex; flex-direction: column; gap: 3px; margin-top: 6px; }
.latest-size {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 0.7rem; line-height: 1.25;
}
.latest-size-ml { color: var(--ink-2); font-weight: 700; min-width: 42px; flex-shrink: 0; }
/* Prices stack in a column to the right of the size label, so a Tester price
   lines up directly under the Normal price (same x) and reads as indented. */
.latest-size-prices { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lsp { display: inline-flex; align-items: baseline; gap: 4px; white-space: nowrap; font-weight: 700; }
.lsp-tag {
  display: inline-block; min-width: 50px; text-align: center;
  font-size: 0.56rem; text-transform: uppercase; letter-spacing: 0.3px; font-weight: 700;
  padding: 1px 4px; border-radius: 4px;
}
.lsp--normal { color: var(--accent); }
.lsp--normal .lsp-tag { background: var(--accent-soft); color: var(--accent-ink); }
.lsp--tester { color: var(--ink-3); }
.lsp--tester .lsp-tag { background: rgba(20,20,50,0.07); color: var(--ink-2); }
.latest-price { color: var(--accent); font-weight: 700; }

/* Skeleton loading state - mirrors the item layout so the rail holds its shape
   while /api/recent-searches is in flight, then script.js drops .is-loading. */
.latest-skeleton { display: none; }
.latest-searches.is-loading .latest-list { display: none; }
/* Fill and clip exactly like .latest-list so the loading card takes the height
   fitLatestRail() gives it - aligned to the idle grid / results column on the
   left - instead of sizing to a fixed row count. */
.latest-searches.is-loading .latest-skeleton {
  display: flex; flex-direction: column; gap: 6px;
  list-style: none; flex: 1 1 auto; min-height: 0; overflow: hidden;
  margin: 0 -14px -14px; padding: 4px 14px 14px;
}
.latest-skel-item {
  flex: 1 1 0;
  min-height: 58px;
  display: flex; align-items: flex-start; gap: 11px;
  border: 1px solid var(--glass-edge);
  border-radius: 12px;
  padding: 9px 10px;
  background: rgba(255,255,255,0.45);
}
.skel-thumb { flex-shrink: 0; width: 40px; height: 40px; border-radius: 9px; }
.skel-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; padding-top: 2px; }
.skel-line { display: block; height: 9px; border-radius: 5px; }
.skel-line--name  { width: 80%; }
.skel-line--meta  { width: 45%; height: 8px; }
.skel-line--price { width: 60%; }
/* Shimmer sweep shared by every skeleton block. */
.skel-thumb, .skel-line {
  background: linear-gradient(100deg,
    rgba(20,20,50,0.06) 30%, rgba(20,20,50,0.13) 50%, rgba(20,20,50,0.06) 70%);
  background-size: 200% 100%;
  animation: latestSkelShimmer 1.3s ease-in-out infinite;
}
@keyframes latestSkelShimmer {
  0%   { background-position: 180% 0; }
  100% { background-position: -80% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skel-thumb, .skel-line, .suggest-skel, .suggest-skel::after { animation: none; }
}

/* Stack the rail below the main column once the three idle cards can no longer
   sit beside a 300px rail in one row (~1160px, allowing for scrollbar variance).
   Kept in sync with the matchMedia guard in fitLatestRail(). */
@media (max-width: 1160px) {
  .main-layout { grid-template-columns: 1fr; }
  .latest-searches { position: static; width: 100%; max-height: 560px; }
  /* Stack the cards full-width so they never overflow the rail on mobile. */
  .latest-list { flex-direction: column; flex-wrap: nowrap; overflow-y: auto; }
  .latest-item { flex: 0 0 auto; width: 100%; }
  /* Let long titles wrap instead of being clipped to a single line. */
  .latest-name { white-space: normal; overflow: visible; text-overflow: clip; }
}

/* ============================================================
   Controls bar
   ============================================================ */
.controls-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s4); margin-bottom: var(--s4); flex-wrap: wrap;
}
.results-meta { font-size: 0.9rem; color: var(--ink-2); }
.results-meta strong { color: var(--ink); font-weight: 600; }
.controls-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* "Save search" - one favorite per search (tracks the lowest price). */
.save-search-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 15px; border-radius: var(--r-ctrl); cursor: pointer;
  font: inherit; font-size: 0.83rem; font-weight: 600; color: var(--ink-2);
  background: var(--glass); border: 1px solid var(--glass-edge);
  box-shadow: var(--e-1);
  transition: background var(--t), color var(--t), border-color var(--t), box-shadow var(--t);
}
.save-search-btn[hidden] { display: none; }
.save-search-btn .ssb-heart { font-size: 1rem; line-height: 1; width: 1em; height: 1em; color: var(--accent); }
.save-search-btn:hover { color: var(--accent); border-color: var(--accent); }
.save-search-btn:disabled { opacity: 0.55; cursor: default; }
.save-search-btn.saved {
  background: linear-gradient(135deg, var(--accent-2), var(--accent));
  color: #fff; border-color: transparent;
  box-shadow: 0 3px 12px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.3);
}
.save-search-btn.saved .ssb-heart { color: #fff; }

/* Shelf and search utilities are separate segmented controls in the results bar. */
.search-actions {
  display: inline-flex; align-items: center; flex-wrap: wrap; gap: 8px;
}
.search-actions[hidden] { display: none; }
.search-utility-actions,
.shelf-actions {
  display: inline-flex; align-items: center; gap: 3px; padding: 3px;
  background: var(--glass); border: 1px solid var(--glass-line);
  border-radius: var(--r-ctrl); box-shadow: var(--e-1);
}
.search-utility-actions {
  border-left-color: var(--glass-edge);
}
.search-actions .save-search-btn {
  background: transparent; border-color: transparent; box-shadow: none;
  border-radius: calc(var(--r-ctrl) - 4px); padding: 6px 12px;
  text-decoration: none;
}
.search-actions .save-search-btn:hover { background: var(--glass-line); border-color: transparent; }
.search-actions .save-search-btn.saved:hover { color: #fff; }
.shelf-actions {
  padding-left: 6px;
}
.shelf-actions[hidden] { display: none; }
.shelf-actions-label {
  padding: 0 4px;
  color: var(--ink-3);
  font-size: 0.76rem;
  font-weight: 700;
}
.search-actions .shelf-action {
  padding-inline: 9px;
}

/* ── Share popover ─────────────────────────────────────────────────────────
   Custom share menu (popular networks + copy link), opened by any [data-share]
   trigger. Built and positioned by static/share.js. */
.share-backdrop { position: fixed; inset: 0; z-index: 1400; background: transparent; }
.share-backdrop[hidden], .share-pop[hidden] { display: none; }
.share-pop {
  position: fixed; z-index: 1401; width: 384px; max-width: calc(100vw - 24px);
  padding: 18px; border-radius: 22px; color: var(--ink);
  background: var(--glass-strong);
  background: color-mix(in srgb, var(--glass-strong) 96%, var(--bg));
  border: 1px solid rgba(255,255,255,0.48);
  box-shadow: 0 20px 54px rgba(15,18,40,0.22), 0 3px 12px rgba(15,18,40,0.1), inset 0 1px 0 rgba(255,255,255,0.68);
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  animation: sharePopIn 0.16s cubic-bezier(0.3, 0.5, 0.35, 1);
}
@keyframes sharePopIn {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
.share-pop-head {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px;
}
.share-pop-title { font-weight: 750; font-size: 1rem; letter-spacing: -0.015em; }
.share-pop-close {
  border: 0; background: transparent; color: var(--ink-2); cursor: pointer;
  font-size: 1.25rem; line-height: 1; width: 30px; height: 30px;
  border-radius: var(--r-pill); display: inline-flex; align-items: center;
  justify-content: center; transition: background var(--t), color var(--t);
}
.share-pop-close:hover { background: rgba(127,127,145,0.12); color: var(--ink); }
.share-pop-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px 6px;
  margin: 0 -2px 16px;
}
.share-net {
  min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 3px 1px 5px; border-radius: 14px; text-decoration: none;
  color: var(--ink-2); font-size: 0.72rem; line-height: 1.2; font-weight: 650;
  cursor: pointer; background: transparent; border: 0;
  transition: transform var(--t), background var(--t), color var(--t);
}
.share-net:hover { transform: translateY(-2px); background: rgba(127,127,145,0.08); color: var(--ink); }
.share-net:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.share-net svg {
  width: 44px; height: 44px; display: block; padding: 11px; border-radius: 50%;
  box-shadow: 0 5px 14px rgba(18,22,42,0.14), inset 0 1px 0 rgba(255,255,255,0.25);
}
.share-net--x svg { fill: #fff; background: #17171c; }
.share-net--fb svg { fill: #fff; background: #1877f2; }
.share-net--messenger svg { fill: #fff; background: linear-gradient(145deg, #00b2ff 0%, #006aff 55%, #a033ff 100%); }
.share-net--reddit svg { fill: #fff; background: #ff4500; }
.share-net--wa svg { fill: #fff; background: #20ba5a; }
.share-net--tg svg { fill: #fff; background: #229ed9; }
.share-net--email svg { color: #fff; background: linear-gradient(145deg, #f25463, var(--accent)); }
.share-net--sms svg { color: #fff; background: linear-gradient(145deg, #32d36b, #099347); }
.share-pop-copy {
  display: flex; gap: 8px; align-items: center; padding: 5px;
  border: 1px solid var(--glass-line); border-radius: 15px;
  background: rgba(127,127,145,0.08);
}
.share-pop-url {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 0.8rem; color: var(--ink-2);
  padding: 8px 7px; border-radius: 10px; outline: none;
  background: transparent; border: 0;
}
.share-pop-url:focus { color: var(--ink); }
.share-pop-copybtn {
  flex: 0 0 auto; font: inherit; font-size: 0.8rem; font-weight: 600; cursor: pointer;
  padding: 9px 15px; border-radius: 11px; color: #fff; border: 1px solid transparent;
  background: linear-gradient(135deg, var(--accent-2), var(--accent));
  box-shadow: 0 2px 8px var(--accent-glow); transition: filter var(--t), background var(--t);
}
.share-pop-copybtn:hover { filter: brightness(1.05); }
.share-pop-copybtn.is-copied { background: #16a34a; box-shadow: none; }
/* Bottom sheet on small screens */
.share-pop--sheet {
  left: 12px !important; right: 12px; top: auto !important; bottom: 12px;
  width: auto; max-width: none; padding: 18px 16px max(18px, env(safe-area-inset-bottom));
}

/* iOS segmented control */
.filter-group {
  display: flex; gap: 2px; padding: 3px;
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-ctrl);
  box-shadow: var(--e-1);
}
.extension-status--outdated .extension-status-dot,
.extension-mini-status--outdated .extension-status-dot {
  background: #d35400;
  box-shadow: 0 0 0 4px rgba(211,84,0,0.16);
}
.extension-status--outdated,
.extension-mini-status--outdated {
  border-color: rgba(211,84,0,0.45);
}
.filter-group[hidden] { display: none !important; }
.filter-btn {
  border: none; background: transparent; border-radius: 13px;
  padding: 7px 16px; font: inherit; font-size: 0.83rem; font-weight: 550;
  cursor: pointer; color: var(--ink-2);
  transition: background var(--t), color var(--t), box-shadow var(--t);
}
.filter-btn:hover { color: var(--accent); }
.filter-btn.active {
  background: linear-gradient(135deg, var(--accent-2), var(--accent));
  color: #fff;
  box-shadow: 0 3px 12px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.3);
}

.sort-group { display: flex; align-items: center; gap: 8px; }
.sort-label { font-size: 0.83rem; color: var(--ink-2); white-space: nowrap; }
.sort-select {
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-ctrl);
  padding: 8px 13px; font: inherit; font-size: 0.83rem; color: var(--ink);
  cursor: pointer; outline: none; box-shadow: var(--e-1);
  transition: border-color var(--t), box-shadow var(--t);
}
.sort-select:focus { border-color: rgba(226,55,68,0.5); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ── Size / type / gender filter bars ── */
.size-filter { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-bottom: var(--s3); }
/* 11px uppercase: --ink-3 sits right on the floor here, as it does on the
   suggestion dropdown's matching labels. */
.size-filter-label {
  font-size: 0.72rem; font-weight: 700; color: var(--ink-2);
  text-transform: uppercase; letter-spacing: 0.6px; margin-right: 2px; white-space: nowrap;
}
.size-btn {
  border: 1px solid var(--glass-edge);
  background: var(--glass);
  color: var(--ink-2);
  border-radius: var(--r-pill);
  padding: 6px 15px; font: inherit; font-size: 0.79rem; font-weight: 550;
  cursor: pointer; user-select: none;
  box-shadow: var(--e-1);
  transition: transform var(--t), color var(--t), border-color var(--t), background var(--t), box-shadow var(--t);
}
.size-btn:hover { border-color: rgba(226,55,68,0.4); color: var(--accent); transform: translateY(-1px); }
.size-btn.active {
  background: linear-gradient(135deg, var(--accent-2), var(--accent));
  border-color: transparent; color: #fff;
  box-shadow: 0 3px 12px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.3);
}
.filter-sep { display: inline-block; width: 1px; height: 16px; background: var(--glass-line); margin: 0 5px; flex-shrink: 0; }

/* ── Top progress bar ── */
.search-progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; background: transparent; z-index: 9999; }
.search-progress-bar {
  height: 100%;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
  border-radius: 0 3px 3px 0;
  transition: width 0.3s ease;
  box-shadow: 0 0 12px var(--accent-glow);
}

/* ============================================================
   Site status chips
   ============================================================ */
.site-statuses-bar { margin-bottom: var(--s6); }
.site-statuses { display: flex; flex-direction: column; gap: 11px; }
.site-section { display: flex; flex-direction: column; gap: 7px; }
.site-section-hd { display: flex; align-items: center; gap: 8px; }
.site-section-lbl { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.7px; color: var(--ink-3); }
.site-chips-row { display: flex; flex-wrap: wrap; gap: 6px; }

.section-toggle-btn {
  flex-shrink: 0; display: inline-flex; align-items: center;
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  color: var(--ink-2); border-radius: var(--r-pill);
  padding: 3px 12px; font: inherit; font-size: 0.7rem; font-weight: 600;
  cursor: pointer; white-space: nowrap; box-shadow: var(--e-1);
  transition: color var(--t), border-color var(--t), transform var(--t);
}
.section-toggle-btn:hover { border-color: rgba(226,55,68,0.4); color: var(--accent); transform: translateY(-1px); }

.site-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 13px; border-radius: var(--r-pill);
  font-size: 0.76rem; font-weight: 550; cursor: pointer; user-select: none;
  border: 1px solid var(--glass-edge);
  background: var(--glass);
  box-shadow: var(--e-1);
  color: var(--ink-2);
  transition: opacity var(--t), filter var(--t), transform var(--t), box-shadow var(--t);
}
.site-chip:hover { transform: translateY(-1px); box-shadow: var(--e-2); }
.site-chip.off { opacity: 0.4; filter: grayscale(1); text-decoration: line-through; }
.site-chip.success { background: rgba(220,247,232,0.7); color: #0d7a3e; border-color: rgba(150,220,180,0.6); }
.site-chip.failed  { background: rgba(253,232,232,0.7); color: #b53434; border-color: rgba(240,180,180,0.6); }
.site-chip.cached  { background: rgba(255,244,214,0.78); color: #8a5a00; border-color: rgba(224,179,74,0.5); }
.site-chip.loading { background: rgba(252,231,232,0.7); color: var(--accent-ink); border-color: rgba(226,55,68,0.22); }

.chip-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.chip-dot.success { background: var(--success); }
.chip-dot.failed  { background: var(--danger); }
.site-chip.cached .chip-dot { background: #d49a21; }
@keyframes chip-spin { to { transform: rotate(360deg); } }
.site-chip.loading .chip-dot {
  background: transparent;
  border: 2px solid rgba(226,55,68,0.25);
  border-top-color: var(--accent);
  animation: chip-spin 0.7s linear infinite;
}

.loading-text { color: var(--accent); font-weight: 550; display: inline-flex; align-items: center; gap: 5px; }
@keyframes pulse-dot { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }
.loading-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); animation: pulse-dot 1s ease-in-out infinite; flex-shrink: 0; }

/* ============================================================
   Advertisement preview slots
   ============================================================ */
.ad-slot {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 92px;
  width: 100%;
  margin: 22px auto;
  padding: 18px 20px;
  border: 1px solid var(--glass-line);
  border-radius: var(--r-ctrl);
  background:
    linear-gradient(135deg, rgba(255,255,255,0.7), rgba(255,255,255,0.34)),
    var(--glass);
  box-shadow: var(--e-1);
  color: var(--ink-3);
  overflow: hidden;
}
.ad-slot::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    repeating-linear-gradient(135deg,
      rgba(17,17,34,0.028) 0,
      rgba(17,17,34,0.028) 1px,
      transparent 1px,
      transparent 11px);
}
.ad-slot-label {
  position: absolute;
  top: 7px;
  left: 12px;
  z-index: 1;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-3);
  opacity: 0.76;
}
.ad-slot-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  text-align: center;
}
.ad-slot-kicker { font-size: 0.88rem; font-weight: 700; color: var(--ink); }
.ad-slot-copy { font-size: 0.76rem; color: var(--ink); }
.ad-slot-link { color: inherit; text-decoration: none; }
.ad-slot-img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  max-height: 220px;
  object-fit: cover;
}
.ad-slot--sidebar .ad-slot-img { min-height: 250px; }
.ad-slot-caption {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px 14px 10px;
  text-align: center;
}
.ad-slot-html {
  position: relative;
  z-index: 1;
  width: 100%;
}
.ad-slot--home { max-width: 740px; min-height: 88px; margin-top: 18px; margin-bottom: 0; }
.ad-slot--results, .ad-slot--forum-wide { max-width: none; min-height: 96px; margin: 16px 0 18px; }
.ad-slot--sidebar { min-height: 250px; margin: 0 0 var(--s5); }
.ad-slot--admin-preview { max-width: 520px; margin: 0; }

/* ============================================================
   Skeletons
   ============================================================ */
.loading-grid, .results-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(264px, 1fr)); gap: var(--s4);
}

.comparison-tabs { grid-column: 1 / -1; display: flex; gap: 8px; overflow-x: auto; padding: 3px 2px 9px; scrollbar-width: thin; }
.comparison-tab { flex: 0 0 auto; display: grid; gap: 2px; min-width: 132px; padding: 10px 13px; border: 1px solid var(--glass-line); border-radius: 12px; background: var(--glass); color: var(--ink-2); text-align: left; cursor: pointer; }
.comparison-tab span { color: var(--ink-3); font-size: .78rem; }
.comparison-tab.active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--glass)); color: var(--ink); box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent); }
.comparison-tab.active span { color: var(--accent); }
.comparison-tab { transition: background-color var(--t), border-color var(--t), box-shadow var(--t), transform var(--t); }
.comparison-tab:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 20%, var(--glass));
  color: var(--ink);
  box-shadow: 0 3px 12px color-mix(in srgb, var(--accent) 25%, transparent);
  transform: translateY(-2px);
}
.comparison-tab:hover span { color: var(--accent); }
.comparison-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .comparison-tab { transition: none; }
  .comparison-tab:hover { transform: none; }
}
.comparison-group { grid-column: 1 / -1; border: 1px solid var(--glass-line); border-radius: 16px; background: var(--glass); overflow: clip; }
.comparison-panel-head { display: flex; justify-content: space-between; gap: 12px; padding: 12px 15px; color: var(--ink-3); font-size: .82rem; }
.comparison-panel-head strong { color: var(--accent); font-size: 1rem; }
.comparison-value { color: var(--ink-2); font-size: .8rem; }
.comparison-offers { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; padding: 14px; border-top: 1px solid var(--glass-line); }

@media (max-width: 620px) {
  .comparison-tab { min-width: 118px; }
  .comparison-panel-head { align-items: flex-start; flex-direction: column; }
  .comparison-offers { grid-template-columns: 1fr; padding: 10px; }
}

/* ── Fragrance pages (product / brand / directory) - shared styles.
     Width comes from base.html's .acct-main--wide tier; page h1s sit on the
     site-wide 1.7rem/700 title rail. ── */
.product-crumbs { display: flex; gap: 8px; color: var(--ink-3); margin-bottom: 18px; font-size: .86rem; }
.product-hero { display: grid; grid-template-columns: minmax(180px, 280px) 1fr; gap: 34px; padding: 28px; }
.product-hero-img { width: 100%; max-height: 330px; object-fit: contain; border-radius: 14px; background: #fff; }
.product-hero-body { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; }
.product-brand { color: var(--accent); font-weight: 800; text-transform: uppercase; letter-spacing: .08em; }
.product-hero h1 { margin: 4px 0 12px; font-size: 1.7rem; font-weight: 700; }
.product-tags { display: flex; flex-wrap: wrap; gap: 7px; }
.product-tags span { border: 1px solid var(--glass-line); border-radius: 999px; padding: 5px 10px; color: var(--ink-2); font-size: .8rem; }
.product-from { margin: 24px 0 2px; font-size: 1.05rem; }
.product-from strong { color: var(--accent); font-size: 1.35rem; }
.product-offers { color: var(--ink-3); margin: 3px 0 20px; }
.product-eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--accent); font-weight: 750; margin: 0; }
.product-related { list-style: none; padding: 0; }
.product-related li { display: flex; justify-content: space-between; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--glass-line); }
.product-related span { font-size: 12px; color: var(--ink-3); }
.brand-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.brand-card { display: flex; align-items: center; gap: 14px; padding: 14px; text-decoration: none; transition: border-color .15s, transform .15s; }
.brand-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.brand-card img { width: 56px; height: 70px; object-fit: contain; flex: 0 0 auto; }
.brand-card-ph { flex: 0 0 auto; display: grid; place-items: center; width: 56px; height: 70px; border-radius: 10px; background: var(--glass); border: 1px solid var(--glass-line); color: var(--ink-3); font-weight: 700; font-size: 1.3rem; }
.brand-card > span { min-width: 0; }
.brand-card small, .brand-card strong { display: block; }
.brand-card strong { overflow-wrap: anywhere; }
.brand-card small { font-size: 12px; color: var(--ink-3); }
.brands-chip { transition: border-color .15s, transform .15s; }
.brands-chip:hover { border-color: var(--accent); transform: translateY(-1px); }
/* Numbered pager shared by the fragrance/brand directories (_pager.html). */
.dir-pager { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
.dir-pager-nums { display: flex; align-items: center; gap: 4px; }
.dir-pager-btn, .dir-pager-num { padding: 6px 11px; border: 1px solid var(--glass-line); border-radius: var(--r-sm); text-decoration: none; font-size: 13px; font-weight: 600; color: var(--ink-2); background: var(--glass); }
a.dir-pager-btn:hover, a.dir-pager-num:hover { border-color: var(--accent); color: var(--ink); }
.dir-pager-num.is-current { background: var(--accent); border-color: var(--accent); color: #fff; }
.dir-pager-gap { padding: 0 3px; color: var(--ink-3); }
@media (max-width: 680px) { .product-hero { grid-template-columns: 1fr; padding: 20px; } .product-hero-img { max-height: 240px; } .brand-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .brand-grid { grid-template-columns: 1fr; gap: 10px; } .brand-card { padding: 12px; } }
.skeleton-card {
  background: rgba(255,255,255,0.5);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  overflow: hidden; padding: 0 0 14px; box-shadow: var(--e-1);
}
.sk-img { width: 100%; aspect-ratio: 4/3; }
.sk-img, .sk-line {
  background: linear-gradient(90deg, rgba(238,238,246,0.85) 25%, rgba(226,226,238,0.85) 50%, rgba(238,238,246,0.85) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s ease infinite;
}
.sk-lines { padding: 13px 15px 0; display: flex; flex-direction: column; gap: 8px; }
.sk-line { height: 11px; border-radius: 6px; }
.sk-w80 { width: 80%; } .sk-w50 { width: 50%; } .sk-w40 { width: 40%; }
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ============================================================
   Product card
   ============================================================ */
.product-card {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--glass-strong);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  overflow: hidden;
  box-shadow: var(--e-2);
  transition: transform var(--spring), box-shadow var(--t);
}
.product-card:hover { transform: translateY(-5px); box-shadow: var(--e-3); }
.product-card.best-price {
  border-color: rgba(200,150,30,0.45);
  box-shadow: var(--e-2), 0 0 0 1.5px rgba(200,150,30,0.35);
}

.best-badge {
  position: absolute; top: 11px; left: 11px; z-index: 4;
  background: linear-gradient(135deg, var(--gold-2), var(--gold));
  color: #fff; font-size: 0.67rem; font-weight: 700; letter-spacing: 0.4px;
  text-transform: uppercase; padding: 4px 11px; border-radius: var(--r-pill);
  box-shadow: 0 3px 12px rgba(200,150,30,0.45), inset 0 1px 0 rgba(255,255,255,0.35);
}
.site-badge {
  position: absolute; top: 11px; right: 11px; z-index: 4;
  font-size: 0.66rem; font-weight: 600; padding: 4px 11px; border-radius: var(--r-pill);
  color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.25);
  box-shadow: 0 3px 10px rgba(0,0,0,0.22), inset 0 1px 0 rgba(255,255,255,0.25);
}

.card-img-wrap {
  width: 100%; aspect-ratio: 4/3;
  background: linear-gradient(180deg, rgba(255,255,255,0.5), rgba(246,246,252,0.35));
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.card-img { width: 100%; height: 100%; object-fit: contain; padding: 14px; transition: transform 0.34s cubic-bezier(.25,.46,.45,.94); }
.product-card:hover .card-img { transform: scale(1.05); }
.card-img-placeholder { font-size: 2.8rem; opacity: 0.18; }

.card-body { padding: 13px 16px 15px; display: flex; flex-direction: column; flex: 1; gap: 6px; position: relative; z-index: 4; }
.card-site { font-size: 0.71rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.65px; color: var(--ink-3); display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }

.site-type-tag, .size-tag {
  display: inline-flex; align-items: center;
  font-size: 0.63rem; font-weight: 600; padding: 2px 7px;
  border-radius: 7px; vertical-align: middle; border: 1px solid transparent;
}
.site-type-tag.discount { background: rgba(224,179,74,0.16); color: #8a5f00; border-color: rgba(224,179,74,0.28); }
.site-type-tag.retail   { background: var(--accent-soft); color: var(--accent-ink); border-color: rgba(226,55,68,0.2); }
.site-type-tag.sample   { background: rgba(18,161,80,0.12); color: #0d7a3e; border-color: rgba(18,161,80,0.2); }

.size-tag { background: rgba(20,20,50,0.05); color: var(--ink-2); border-color: rgba(20,20,50,0.08); letter-spacing: 0.2px; }
.size-tag.sample  { background: rgba(229,72,77,0.1);  color: #b02a2f; border-color: rgba(229,72,77,0.18); }
.size-tag.travel  { background: rgba(0,122,255,0.1);  color: #1a58b5; border-color: rgba(0,122,255,0.16); }
.size-tag.refill  { background: rgba(116,72,190,0.12); color: #5b35a3; border-color: rgba(116,72,190,0.18); }
.size-tag.unknown { background: var(--accent-soft);   color: var(--accent-ink); border-color: rgba(226,55,68,0.16); }
.size-tag.tester  { background: rgba(255,159,10,0.12); color: #7a5000; border-color: rgba(255,159,10,0.18); }
.size-tag.gender-men   { background: rgba(0,122,255,0.1); color: #1a58b5; border-color: rgba(0,122,255,0.15); }
.size-tag.gender-women { background: rgba(255,45,85,0.1); color: #9a1040; border-color: rgba(255,45,85,0.15); }

.product-card.is-sold-out { opacity: 0.62; }
.sold-out-overlay {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 4;
  background: rgba(0,0,0,0.62);
  color: #fff; font-size: 0.75rem; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
  padding: 6px 14px; border-radius: 10px; pointer-events: none;
}

.card-name {
  font-size: 0.89rem; font-weight: 500; color: var(--ink); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card-price { font-size: 1.6rem; font-weight: 700; color: var(--ink); letter-spacing: -0.7px; }
.card-price sup { font-size: 0.86rem; font-weight: 500; vertical-align: super; letter-spacing: 0; }
.price-from { font-size: 0.62rem; font-weight: 400; color: var(--ink-2); margin-right: 2px; }
.price-range-sep { font-size: 0.8em; color: var(--ink-2); font-weight: 400; margin: 0 1px; }
.price-range-max { font-size: 0.85em; color: var(--ink-2); font-weight: 500; }
.card-size-info { font-size: 0.77rem; color: var(--ink-2); margin-top: 2px; }
.card-price-meta { display: flex; flex-wrap: wrap; gap: 5px 10px; margin-top: 5px; color: var(--ink-3); font-size: .7rem; }
.card-verified::before {
  content: '';
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  margin-right: 0.25em;
  vertical-align: -0.08em;
  background: var(--success);
  -webkit-mask: url('/static/ui-icons/circle-check.svg') center / contain no-repeat;
  mask: url('/static/ui-icons/circle-check.svg') center / contain no-repeat;
}
.card-delivery--unknown { opacity: .82; }
.card-ppm { color: var(--accent); font-weight: 600; }
.card-coupon { font-size: 0.74rem; color: var(--success); font-weight: 500; margin-top: 4px; }
.deal-score {
  align-self: flex-start;
  display: inline-flex;
  margin: 2px 0 8px;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(34,197,94,0.10);
  color: var(--success);
  border: 1px solid rgba(34,197,94,0.20);
  font-size: 0.72rem;
  font-weight: 700;
}
.currency-tag { font-size: 0.66rem; font-weight: 600; color: var(--ink-3); margin-left: 4px; vertical-align: middle; letter-spacing: 0.5px; }

.card-mini-actions {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: auto;
  padding-top: 10px;
}
.card-footer { padding: 0 16px 16px; position: relative; z-index: 4; }

/* Watchlist is now saved per-search from the results bar (#saveSearchBtn), so
   the card footer holds just the View/Buy link, which fills the row. */
.card-footer .view-btn { flex: 1; }
.mini-action {
  border: 1px solid var(--glass-edge);
  background: var(--glass);
  color: var(--ink-2);
  border-radius: 999px;
  padding: 4px 9px;
  font: inherit;
  font-size: 0.72rem;
  line-height: 1.1;
  font-weight: 700;
  cursor: pointer;
}
.mini-action.saved {
  background: rgba(34,197,94,0.10);
  border-color: rgba(34,197,94,0.24);
  color: var(--success);
}
.mini-action:hover { color: var(--accent); border-color: rgba(108,58,214,0.35); }
.mini-action:disabled { opacity: .65; cursor: default; }
.latest-image-editor:not([hidden]) { display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin:0 0 14px; padding:10px 12px; border:1px solid var(--glass-line); border-radius:10px; }
.latest-image-editor p { margin:2px 0 0; color:var(--ink-2); font-size:.8rem; }
.latest-image-editor img { width:42px; height:42px; object-fit:contain; background:#fff; border-radius:6px; }
.latest-image-editor button { margin-left:auto; }
.latest-image-editor .mini-action, .latest-image-pick { width:auto; padding:0 8px; font-size:.74rem; }
.view-btn {
  display: block; width: 100%; text-align: center;
  background: linear-gradient(135deg, rgba(255,90,106,0.95), rgba(226,55,68,0.98));
  border: 1px solid rgba(226,55,68,0.35);
  color: #fff; text-decoration: none; border-radius: var(--r-ctrl);
  padding: 12px 16px; font: inherit; font-size: 0.87rem; font-weight: 600;
  box-shadow: 0 5px 18px rgba(226,55,68,0.28), inset 0 1px 0 rgba(255,255,255,0.28);
  transition: transform var(--t), box-shadow var(--t), filter var(--t);
}
.view-btn:hover { transform: translateY(-1px); filter: brightness(1.05); box-shadow: 0 9px 26px rgba(226,55,68,0.42), inset 0 1px 0 rgba(255,255,255,0.3); }
.best-price .view-btn {
  background: linear-gradient(135deg, var(--gold-2), var(--gold));
  border-color: rgba(200,150,30,0.4);
  box-shadow: 0 5px 18px rgba(200,150,30,0.32), inset 0 1px 0 rgba(255,255,255,0.28);
}

/* ============================================================
   Empty / error
   ============================================================ */
.empty-state, .error-state { text-align: center; padding: 64px 24px; }
.empty-icon, .error-icon { font-size: 3rem; display: block; margin: 0 auto 14px; }
.empty-state h3, .error-state h3 { font-size: 1.2rem; font-weight: 600; margin-bottom: 8px; }
.empty-state p, .error-state p { font-size: 0.9rem; color: var(--ink-2); max-width: 460px; margin: 0 auto; line-height: 1.5; }

/* ── Cache banner ── */
.cache-info {
  display: flex; align-items: center; gap: 8px; padding: 10px 16px;
  border-radius: var(--r-ctrl); font-size: 0.8rem; margin-bottom: var(--s4);
  border: 1px solid transparent; flex-wrap: wrap;
  box-shadow: var(--e-1);
}
.cache-info--cached { background: rgba(255,248,224,0.8); border-color: rgba(232,208,130,0.6); color: #7a5800; }
.cache-info--fresh  { background: rgba(224,248,235,0.8); border-color: rgba(160,220,185,0.6); color: #0d7a3e; }
.ci-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.ci-dot--cached { background: var(--gold); } .ci-dot--fresh { background: var(--success); }
.cache-info strong { font-weight: 600; }
.ci-refresh {
  margin-left: auto; border: 1.5px solid currentColor; background: transparent; color: inherit;
  border-radius: var(--r-pill); padding: 4px 14px; font: inherit; font-size: 0.76rem; font-weight: 600;
  cursor: pointer; transition: background var(--t); white-space: nowrap;
}
.ci-refresh:hover { background: rgba(0,0,0,0.05); }

/* Info icon; its data-tip is rendered by the single shared tooltip in theme.js. */
.ci-info {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; font-size: 0.85rem; line-height: 1;
  color: inherit; opacity: 0.65; cursor: help; flex-shrink: 0;
  transition: opacity var(--t);
}
.ci-info:hover, .ci-info:focus-visible { opacity: 1; outline: none; }

.delivery-winner,.sticker-winner{display:inline-flex;width:max-content;margin-top:4px;padding:2px 7px;border-radius:999px;font-size:.68rem;font-weight:750}.delivery-winner{background:#e8f7ef;color:#167347}.sticker-winner{background:var(--accent-soft);color:var(--accent-ink)}.card-delivery-note{display:block;font-size:.69rem;color:var(--ink-3);margin-top:2px}
/* ── Price-history mini chart ── */
.card-sparkline { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--glass-line); }
.sparkline-header { display: flex; justify-content: space-between; align-items: center; gap: 5px; flex-wrap: wrap; margin-bottom: 2px; }

/* Per-card graph range buttons (override the global Graph filter) */
.spark-range-local { display: inline-flex; gap: 2px; }
.spark-range-btn {
  border: 1px solid var(--glass-line);
  background: transparent;
  color: var(--ink-3);
  border-radius: 6px;
  padding: 0 5px;
  font: inherit; font-size: 0.6rem; font-weight: 600; line-height: 1.6;
  cursor: pointer;
  transition: color var(--t), border-color var(--t), background var(--t);
}
.spark-range-btn:hover { color: var(--accent); border-color: rgba(226,55,68,0.4); }
.spark-range-btn.active {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: rgba(226,55,68,0.3);
}
.spark-empty { font-size: 0.72rem; color: var(--ink-3); text-align: center; padding: 10px 0 6px; }
.sparkline-label { font-size: 0.68rem; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.4px; }
.sparkline-trend { position: relative; font-size: 0.7rem; font-weight: 600; cursor: help; }
.sparkline-trend.trend-down { color: var(--success); }
.sparkline-trend.trend-up { color: var(--danger); }
.sparkline-trend.trend-flat { color: var(--ink-3); }

.spark-svg { display: block; width: 100%; height: auto; overflow: visible; cursor: crosshair; }
.spark-grid { stroke: rgba(20,20,50,0.07); stroke-width: 1; vector-effect: non-scaling-stroke; }
.spark-grid--mid { stroke-dasharray: 2 3; }
.spark-axis { stroke: rgba(20,20,50,0.16); stroke-width: 1; vector-effect: non-scaling-stroke; }
.spark-ylab, .spark-xlab { fill: var(--ink-3); font-size: 8px; font-family: inherit; }
.spark-area { stroke: none; }
.spark-line { fill: none; stroke-width: 1.3; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.spark-dot { stroke: var(--glass-strong); stroke-width: 0.6; transition: r 0.12s ease; }
.spark-hit { fill: transparent; pointer-events: all; cursor: crosshair; }
.spark-tip { opacity: 0; transition: opacity 0.12s ease; pointer-events: none; }
.spark-pt:hover .spark-tip { opacity: 1; }
.spark-pt:hover .spark-dot { r: 3; }
.spark-tip-bg { fill: rgba(22,22,32,0.94); }
.spark-tip-tx { fill: #fff; font-size: 7.5px; font-weight: 600; font-family: inherit; }

/* Price alert modal */
body.modal-open { overflow: hidden; }
.site-modal[hidden] { display: none; }
.site-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: grid;
  place-items: center;
  padding: 22px;
  background: rgba(18,18,28,0.34);
}
.site-modal-card {
  position: relative;
  width: min(440px, 100%);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  padding: 24px;
  box-shadow: var(--e-3);
  background: var(--glass-strong);
}
.site-modal-card h2 {
  margin: 0 34px 6px 0;
  font-size: 1.25rem;
  letter-spacing: -0.2px;
}
.site-modal-sub {
  margin: 0 0 18px;
  color: var(--ink-2);
  font-size: 0.9rem;
  overflow-wrap: anywhere;
}
.site-modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 32px;
  height: 32px;
  border: 1px solid var(--glass-line);
  border-radius: 999px;
  background: var(--glass);
  color: var(--ink-2);
  font: inherit;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}
.site-modal-close:hover { color: var(--accent); border-color: rgba(226,55,68,0.35); }
.price-alert-form { display: grid; gap: 13px; }
.modal-field {
  display: grid;
  gap: 7px;
  color: var(--ink-2);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.35px;
}
.money-input {
  display: flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--glass-line);
  border-radius: var(--r-ctrl);
  background: rgba(255,255,255,0.7);
  padding: 0 12px;
  color: var(--ink-3);
}
.money-input input,
.modal-field select {
  width: 100%;
  border: 1px solid var(--glass-line);
  border-radius: var(--r-ctrl);
  background: rgba(255,255,255,0.7);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  outline: none;
}
.money-input input {
  border: 0;
  background: transparent;
  padding: 11px 0;
}
.modal-field select { padding: 11px 12px; }
.money-input:focus-within,
.modal-field select:focus {
  border-color: rgba(226,55,68,0.45);
  box-shadow: 0 0 0 3px rgba(226,55,68,0.1);
}
.modal-hint {
  color: var(--ink-3);
  font-size: 0.8rem;
  line-height: 1.45;
}
.modal-error {
  min-height: 1.2em;
  color: var(--danger);
  font-size: 0.82rem;
  font-weight: 600;
}
.modal-error[hidden] { display: none; }
.site-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 9px;
  margin-top: 4px;
}
.modal-secondary,
.modal-primary {
  border-radius: var(--r-ctrl);
  padding: 10px 15px;
  font: inherit;
  font-size: 0.86rem;
  font-weight: 700;
  cursor: pointer;
}
.modal-secondary {
  border: 1px solid var(--glass-line);
  background: var(--glass);
  color: var(--ink-2);
}
.modal-primary {
  border: 1px solid rgba(226,55,68,0.35);
  background: linear-gradient(135deg, rgba(255,90,106,0.95), rgba(226,55,68,0.98));
  color: #fff;
  box-shadow: 0 5px 18px rgba(226,55,68,0.24);
}
.modal-primary:disabled { opacity: 0.68; cursor: default; }

/* Custom dialogs (uiAlert / uiConfirm / uiPrompt) - reuse the .site-modal
   shell above; only the message wrapping, text input, and the destructive
   primary variant need their own rules. */
.ui-dialog { z-index: 2400; }
.ui-dialog-card { width: min(420px, 100%); }
.ui-dialog-title[hidden], .ui-dialog-msg[hidden], .ui-dialog-field[hidden],
.ui-dialog-cancel[hidden] { display: none; }
.ui-dialog-msg { white-space: pre-wrap; margin-bottom: 18px; }
.ui-dialog-title + .ui-dialog-msg { margin-top: 0; }
.ui-dialog-field { margin-bottom: 16px; }
.modal-input {
  width: 100%;
  border: 1px solid var(--glass-line);
  border-radius: var(--r-ctrl);
  background: rgba(255,255,255,0.7);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  padding: 11px 12px;
  outline: none;
}
textarea.modal-input { resize: vertical; min-height: 84px; line-height: 1.45; }
.modal-input:focus {
  border-color: rgba(226,55,68,0.45);
  box-shadow: 0 0 0 3px rgba(226,55,68,0.1);
}
.modal-primary.ui-dialog-danger {
  border-color: rgba(226,55,68,0.5);
  background: linear-gradient(135deg, rgba(226,55,68,0.98), rgba(190,32,44,0.98));
}

/* Footer */
.footer {
  padding: 44px 24px calc(24px + env(safe-area-inset-bottom, 0px));
  color: var(--ink-3);
  border-top: 1px solid rgba(255,255,255,0.5);
  background: rgba(255,255,255,0.62);
}
.footer-inner {
  max-width: 1120px;
  margin: 0 auto;
}
.footer-main {
  display: grid;
  grid-template-columns: minmax(220px, 1.15fr) minmax(480px, 2fr);
  gap: clamp(36px, 7vw, 96px);
  align-items: start;
}
.footer-brand-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  text-decoration: none;
}
.footer-brand-link img { object-fit: contain; }
.footer-word-logo { height: 25px; width: auto; }
.footer-note {
  font-size: 0.8rem;
  line-height: 1.65;
  color: var(--ink-3);
  margin: 12px 0 0;
  max-width: 320px;
}
.footer-nav-grid {
  display: grid;
  grid-template-columns: .7fr 1.15fr 1fr;
  gap: clamp(24px, 4vw, 56px);
}
.footer-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 9px;
}
.footer-heading {
  margin: 0 0 5px;
  color: var(--ink);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.footer-group a,
.footer .footer-cookie-settings {
  display: inline-block;
  padding: 2px 0;
  border: 0;
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: 0.8rem;
  line-height: 1.4;
  text-decoration: none;
  cursor: pointer;
  transition: color .15s ease, transform .15s ease;
}
.footer-group a:hover,
.footer .footer-cookie-settings:hover {
  color: var(--ink);
  transform: translateX(2px);
}
.footer-group a:focus-visible,
.footer .footer-cookie-settings:focus-visible { color: var(--ink); }
.footer-bottom {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  margin-top: 36px;
  padding-top: 18px;
  border-top: 1px solid rgba(20,20,40,.09);
  font-size: .72rem;
  line-height: 1.5;
}
@media (max-width: 900px) {
  .footer { padding: 34px 20px calc(22px + env(safe-area-inset-bottom, 0px)); }
  .footer-main { grid-template-columns: 1fr; gap: 30px; }
  .footer-note { max-width: 520px; }
  .footer-nav-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ============================================================
   Responsive
   ============================================================ */
/* Tablet: the result count pushes the filter + sort onto their own line -
   spread them across it (control left / sort right) and centre the pill rows
   so the mid-width layout stays balanced instead of bunching to the left. */
@media (min-width: 601px) and (max-width: 900px) {
  .idle-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .idle-card--discount { grid-column: 1 / -1; }
  .idle-card--feature,
  .idle-grid--retail-active .idle-card--retail,
  .idle-grid--retail-active .idle-card--feature:nth-of-type(3),
  .idle-grid--retail-active .idle-card--feature:nth-of-type(4),
  .idle-grid--retail-active .idle-card--feature:nth-of-type(5),
  .idle-grid--retail-active .idle-card--feature:nth-of-type(6) {
    grid-column: span 1;
  }
  .idle-list--ranked { column-count: 2; }
  .controls-bar { align-items: flex-start; }
  .controls-right { width: 100%; justify-content: space-between; }
  .size-filter { justify-content: center; }
  .site-chips-row { justify-content: center; }
  .site-section-hd { justify-content: space-between; }
}

@media (max-width: 600px) {
  .addon-banner-inner {
    justify-content: flex-start;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 12px;
    text-align: left;
  }
  .addon-banner-copy {
    flex: 1 1 auto;
    font-size: 0.84rem;
  }
  .addon-banner-link {
    align-self: center;
    padding: 5px 10px;
    font-size: 0.76rem;
    white-space: nowrap;
  }
  .addon-banner-close {
    width: 26px;
    height: 26px;
    font-size: 1.1rem;
  }
  .header { padding: 42px 20px 26px; }
  .logo-text { font-size: 1.95rem; }
  .main { padding: 18px 16px 42px; }
  .home-hero { padding: 24px 16px 4px; }
  .home-hero .tagline { font-size: 0.98rem; }
  .search-section { padding: 12px 16px 22px; }
  .idle-grid { grid-template-columns: 1fr; }
  .idle-card--discount,
  .idle-card--feature,
  .idle-grid--retail-active .idle-card--retail,
  .idle-grid--retail-active .idle-card--feature:nth-of-type(3),
  .idle-grid--retail-active .idle-card--feature:nth-of-type(4),
  .idle-grid--retail-active .idle-card--feature:nth-of-type(5),
  .idle-grid--retail-active .idle-card--feature:nth-of-type(6) {
    grid-column: 1 / -1;
  }
  .idle-list--ranked {
    column-count: 2;
    column-gap: 12px;
  }
  .idle-card { padding: 20px 18px; }
  .latest-searches { max-height: 520px; }

  .footer { padding-inline: 18px; }
  .footer-nav-grid { grid-template-columns: 1fr 1fr; gap: 28px 20px; }
  .footer-group:last-child { grid-column: 1 / -1; }
  .footer-bottom { flex-direction: column; gap: 5px; margin-top: 28px; }
  .search-btn .btn-text { display: none; }
  .search-btn { padding: 12px 16px; }
  .loading-grid, .results-grid { grid-template-columns: 1fr; gap: 12px; }
  .card-price { font-size: 1.35rem; }
  .suggest-gender-label { width: 60px; font-size: 0.61rem; }

  /* Controls stack full-width; result count centered above them */
  .controls-bar { flex-direction: column; align-items: stretch; gap: 12px; }
  .results-meta { text-align: center; }
  .controls-right { width: 100%; flex-direction: column; align-items: stretch; gap: 10px; }

  /* Segmented control spans the row with equal segments (iOS style) */
  .filter-group { width: 100%; }
  .filter-btn { flex: 1 1 0; text-align: center; }

  /* Sort: label left, dropdown fills the rest of the row */
  .sort-group { width: 100%; }
  .sort-select { flex: 1; }

  /* Filter pill rows: centered label header, pills centered beneath it */
  .size-filter { justify-content: center; gap: 8px; }
  .size-filter-label { width: 100%; text-align: center; margin: 2px 0 0; }
  .filter-sep { display: none; }

  /* Site sections: header label left / toggle right, chips centered */
  .site-section-hd { justify-content: space-between; }
  .site-chips-row { justify-content: center; }
}
@media (max-width: 400px) {
  .loading-grid, .results-grid { grid-template-columns: 1fr; }
  .suggest-gender-label { display: none; }
  .idle-list--ranked { column-count: 1; }
}

/* ── Presence dot (online / offline indicator next to usernames) ── */
.presence-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;             /* centre with the avatar + name */
  flex: none;
  background: var(--ink-3);            /* offline: muted grey */
}
.presence-dot--on {
  background: var(--success);          /* online: green */
  box-shadow: 0 0 0 1.5px rgba(18,161,80,0.20);
}
.presence-dot--off {
  background: var(--ink-3);
}

/* ============================================================
   Theme toggle button (lives in the always-dark header, so the
   icon colour is inherited from .acct-link in both modes). Show
   the moon in light mode, the sun in dark mode.
   ============================================================ */
.theme-toggle { background: none; border: none; cursor: pointer; }
/* Scoped under .theme-toggle so these beat dashboard.css's .acct-icon
   { display: block } (same specificity, but that file loads later). */
.theme-toggle .theme-icon--sun { display: none; }
.theme-toggle .theme-icon--moon { display: block; }
:root[data-theme="dark"] .theme-toggle .theme-icon--sun { display: block; }
:root[data-theme="dark"] .theme-toggle .theme-icon--moon { display: none; }

/* ============================================================
   Dark theme
   Activated by data-theme="dark" on <html> (set pre-paint by the
   inline script in base.html, toggled by /static/theme.js). It
   mostly re-points the design tokens; every surface built on the
   --glass / --ink tokens then adapts automatically. Only the few
   hardcoded light surfaces need explicit overrides below.
   ============================================================ */
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg:          #131219;
  --bg-2:        #191824;
  --ink:         #ecebf3;
  --ink-2:       #a9a7bb;
  /* Lightened from #6f6d82 (~3.6:1) so hint/metadata text clears WCAG AA
     even where it sits over the lighter translucent glass panels. #8f8da1
     still came to 4.35:1 on a card face, under the 4.5 floor for the 11px
     it is mostly set in; this is 5.0:1 there. */
  --ink-3:       #9a98ac;

  --accent-soft: rgba(226,55,68,0.22);
  /* --accent-ink is a DARK red meant for text on light surfaces. It's used as
     text on the translucent --accent-soft background in ~30 chips/tags/links
     across the forum, dashboard and results. On dark that dark-on-dark pairing
     is barely legible, so re-point it to a light red here. Fixes them all at
     once. (The two hover states that use it as a *background* are overridden
     back to a mid red further down so their white text stays readable.) */
  --accent-ink:  #ff8a94;

  /* Leaned into real glass: surfaces are much more translucent so the
     coloured mesh refracts through them, with brighter rim + specular
     highlights to catch the light. The blur that makes this read as glass
     (rather than flat tint) is added on the key surfaces further down,
     dark-mode only, so light mode's perf profile is untouched. */
  --glass:        rgba(34,33,49,0.52);
  --glass-strong: rgba(44,43,61,0.60);
  --glass-hi:     rgba(255,255,255,0.12);   /* specular highlight */
  --glass-edge:   rgba(255,255,255,0.20);   /* rim light */
  --glass-line:   rgba(255,255,255,0.10);
  --input-bg:     rgba(255,255,255,0.06);
  --input-border: rgba(255,255,255,0.20);

  /* Fallback vars consumed via var(--panel,...) / var(--surface,...) etc. */
  --panel:   rgba(32,31,43,0.62);
  --surface: rgba(32,31,43,0.62);
  --glass-2: rgba(255,255,255,0.08);
  --gold-lt: rgba(224,179,74,0.18);

  --e-1:
    0 1px 2px rgba(0,0,0,0.40),
    0 4px 14px rgba(0,0,0,0.35),
    inset 0 1px 0 rgba(255,255,255,0.10);
  --e-2:
    0 2px 6px rgba(0,0,0,0.40),
    0 10px 30px rgba(0,0,0,0.50),
    inset 0 1px 0 rgba(255,255,255,0.12),
    inset 0 -1px 0 rgba(0,0,0,0.20);
  --e-3:
    0 6px 18px rgba(0,0,0,0.50),
    0 24px 60px rgba(0,0,0,0.60),
    inset 0 1px 0 rgba(255,255,255,0.14),
    inset 0 -1px 0 rgba(0,0,0,0.22);
}

/* ── Real glass blur (dark mode only) ──
   In light mode blur is limited to the hero search box for perf (see the note
   by the glass tokens up top). In dark mode we lean into the glass look: the
   surfaces above are now translucent, so we add backdrop blur on the handful
   of large, mostly-static surfaces that carry the aesthetic - the search box
   already blurs, these join it. The mesh is static (no drift animation), so
   these compose once and only re-blur on scroll. */
:root[data-theme="dark"] .latest-searches,
:root[data-theme="dark"] .idle-card,
:root[data-theme="dark"] .deal-feed-strip,
:root[data-theme="dark"] .product-card {
  -webkit-backdrop-filter: var(--blur-sm);
  backdrop-filter: var(--blur-sm);
}
/* The card image well is a hardcoded light gradient - make it a dark
   translucent pane so the glass reads through the whole card. */
:root[data-theme="dark"] .card-img-wrap {
  background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02));
}

/* Hardcoded light surfaces in this file that bypass the glass tokens */
:root[data-theme="dark"] .latest-item        { background: rgba(255,255,255,0.04); }
:root[data-theme="dark"] .latest-item:hover  { background: rgba(255,255,255,0.08); }
:root[data-theme="dark"] .deal-card          { background: rgba(255,255,255,0.04); }
:root[data-theme="dark"] .deal-card:hover    { background: rgba(255,255,255,0.08); }
:root[data-theme="dark"] .deal-card-img      { background: rgba(255,255,255,0.06); }
:root[data-theme="dark"] .skeleton-card      { background: rgba(255,255,255,0.04); }
:root[data-theme="dark"] .latest-skel-item   { background: rgba(255,255,255,0.04); }
:root[data-theme="dark"] .skel-thumb,
:root[data-theme="dark"] .skel-line,
:root[data-theme="dark"] .suggest-skel {
  background: linear-gradient(100deg,
    rgba(255,255,255,0.05) 30%, rgba(255,255,255,0.12) 50%, rgba(255,255,255,0.05) 70%);
  background-size: 200% 100%;
}
:root[data-theme="dark"] .suggest-skel::after {
  color: rgba(255,255,255,0.42);
}
:root[data-theme="dark"] .footer {
  border-top-color: var(--glass-line);
  background: rgba(255,255,255,0.03);
}
:root[data-theme="dark"] .footer-bottom { border-top-color: var(--glass-line); }

/* Dashboard / auth / forms hardcoded light surfaces (dashboard.css) */
:root[data-theme="dark"] .magic-input,
:root[data-theme="dark"] .username-input,
:root[data-theme="dark"] .contact-textarea { background: rgba(255,255,255,0.06); color: var(--ink); }
:root[data-theme="dark"] .site-modal-card { background: rgba(28,28,38,0.96); }
:root[data-theme="dark"] .money-input,
:root[data-theme="dark"] .money-input input { background: rgba(255,255,255,0.06); color: var(--ink); }
:root[data-theme="dark"] textarea.modal-input,
:root[data-theme="dark"] input.modal-input { background: rgba(255,255,255,0.06); color: var(--ink); }
/* .modal-field select intentionally omitted above: like every other <select>
   it needs the SOLID dark background (see the dropdown-legibility block below)
   so its native option popup stays readable in dark mode. */
:root[data-theme="dark"] .fav-item,
:root[data-theme="dark"] .seg-opt,
:root[data-theme="dark"] .msg-item,
:root[data-theme="dark"] .friend-item     { background: rgba(255,255,255,0.04); }
:root[data-theme="dark"] .fav-card:hover  { background: rgba(255,255,255,0.08); }
:root[data-theme="dark"] .msg-item.unread { background: rgba(226,55,68,0.14); }

/* Google/generic OAuth button keeps a light chip for logo legibility */
.oauth-form { margin: 18px 0; }
.oauth-btn {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  width: 100%; min-height: 44px; padding: 10px 16px;
  border: 1px solid #747775; border-radius: 8px;
  background: #fff; color: #1f1f1f; font: inherit; font-weight: 600;
  cursor: pointer; transition: box-shadow var(--t), background-color var(--t);
}
.oauth-btn:hover { background: #f2f2f2; box-shadow: 0 2px 6px rgba(0,0,0,.14); }
.oauth-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.oauth-btn.is-disabled { opacity: .6; cursor: not-allowed; }
:root[data-theme="dark"] .oauth-btn { background: #fff; color: #1f1f1f; }
:root[data-theme="dark"] .oauth-btn:hover { background: #e8e8e8; }

/* Custom scrollbars use dark thumbs that vanish on dark panels - flip them to
   light translucent thumbs in dark mode. Covers the Latest Searches rail and
   the messaging scroll areas; the page's native scrollbar follows color-scheme. */
:root[data-theme="dark"] .latest-list,
:root[data-theme="dark"] .dm-messages,
:root[data-theme="dark"] .dm-list,
:root[data-theme="dark"] .dm-emoji-panel {
  scrollbar-color: rgba(255,255,255,0.3) transparent;
}
:root[data-theme="dark"] .latest-list::-webkit-scrollbar-thumb,
:root[data-theme="dark"] .dm-messages::-webkit-scrollbar-thumb,
:root[data-theme="dark"] .dm-list::-webkit-scrollbar-thumb,
:root[data-theme="dark"] .dm-emoji-panel::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,0.26); background-clip: padding-box;
}
:root[data-theme="dark"] .latest-list::-webkit-scrollbar-thumb:hover,
:root[data-theme="dark"] .dm-messages:hover::-webkit-scrollbar-thumb,
:root[data-theme="dark"] .dm-list:hover::-webkit-scrollbar-thumb,
:root[data-theme="dark"] .dm-emoji-panel:hover::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,0.42); background-clip: padding-box;
}

/* ── Staff name colouring ──
   Admins and moderators are highlighted wherever their @username appears
   (forum authors, DMs, user cards, profiles, the admin list) so members can
   tell staff apart at a glance. Admins render red, moderators amber. The
   `uname_class()` template global and the JSON `role` fields both resolve to
   these two classes. `!important` wins over the link/heading colours these
   names usually inherit. */
.uname--admin {
  color: #d21f2b !important;    /* admin: strong red */
  font-weight: 700;
}
/* That red measures 2.9:1 on the dark theme's panels. The amber the
   moderators get clears it at 5:1 either way; the red needs its own value. */
:root[data-theme="dark"] .uname--admin { color: #ff6a76 !important; }
.uname--mod {
  color: #e07b00 !important;    /* moderator: visible amber-orange */
  font-weight: 700;
}

/* ============================================================
   ACCESSIBILITY (WCAG / ADA)
   Global rules that apply on every page (style.css is loaded
   site-wide from base.html). Kept last so they win over the
   per-page stylesheets that come before them.
   ============================================================ */

/* ── Keyboard focus ──
   Every interactive element gets a clearly visible focus ring when
   reached with the keyboard. :focus-visible means mouse clicks don't
   show the ring, so the visual design is untouched for pointer users
   while keyboard users always get an unmistakable indicator. The ring
   is drawn as an outline PLUS a contrasting halo so it stands out on
   both light glass and dark surfaces. */
:root a:focus-visible,
:root button:focus-visible,
:root select:focus-visible,
:root input:focus-visible,
:root textarea:focus-visible,
:root summary:focus-visible,
:root [tabindex]:focus-visible,
:root [role="button"]:focus-visible,
:root [role="tab"]:focus-visible,
:root [contenteditable="true"]:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
  box-shadow: 0 0 0 5px rgba(255,255,255,0.9), 0 0 0 8px var(--accent-soft);
}
:root[data-theme="dark"] a:focus-visible,
:root[data-theme="dark"] button:focus-visible,
:root[data-theme="dark"] select:focus-visible,
:root[data-theme="dark"] input:focus-visible,
:root[data-theme="dark"] textarea:focus-visible,
:root[data-theme="dark"] summary:focus-visible,
:root[data-theme="dark"] [tabindex]:focus-visible,
:root[data-theme="dark"] [role="button"]:focus-visible,
:root[data-theme="dark"] [role="tab"]:focus-visible,
:root[data-theme="dark"] [contenteditable="true"]:focus-visible {
  outline-color: var(--accent-2);
  box-shadow: 0 0 0 5px rgba(0,0,0,0.6), 0 0 0 8px var(--accent-soft);
}

/* ── Links in page prose ──
   A link written in a sentence - the privacy policy's contact address, the
   terms' cross-references, the note on /contact - had no colour of its own, so
   it fell back to the browser's default link blue (#0000ee) on every page that
   contains one. Anything with a class of its own (a button, a card, a nav pill)
   styles itself and is left alone. The underline stays: in a wall of legal text
   colour alone should not be what marks a link.
   Written inside :where() so it carries no specificity at all: it is the
   fallback for a link nothing else styles, and every rule that does have
   something to say about a link - a contents rail, a jump-nav pill, a
   breadcrumb - still wins without having to fight an id selector. */
:where(#main-content) :where(a:not([class])) { color: var(--accent-ink); }
:where(#main-content) :where(a:not([class]):hover) { color: var(--accent); }
/* Crumbs are a quiet trail, not prose: muted until pointed at. */
:where(#main-content) :where(.product-crumbs a) { color: var(--ink-2); text-decoration: none; }
:where(#main-content) :where(.product-crumbs a:hover) { color: var(--accent); text-decoration: underline; }

/* ── Skip to main content ──
   First tab stop on every page; lets keyboard/screen-reader users jump
   past the header nav straight to the page content. Off-screen until
   focused. Pairs with id="main-content" on <main> in base.html. */
.skip-link {
  position: absolute;
  left: 50%;
  top: -60px;
  transform: translateX(-50%);
  z-index: 1000;
  padding: 10px 20px;
  border-radius: 0 0 12px 12px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  transition: top .18s ease;
}
/* The shadow belongs to the link only while the link is on screen. Parked at
   top: -60px it still cast a 30px-blur shadow downwards, which showed as a
   dark smudge across the middle of the very top of the page -- the width of
   this link, centred -- over whatever sat there. */
.skip-link:focus {
  top: 0;
  box-shadow: var(--e-2);
  outline: 3px solid #fff;
  outline-offset: -6px;
}

/* Screen-reader-only helper: available for visually-hidden labels. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── Dark-mode dropdown legibility ──
   The problem: selects styled with the translucent glass tokens
   (--glass / --glass-hi) render an almost-white native <option> popup
   with light text over it in dark mode - effectively invisible. Browsers
   also composite the closed control's translucent-white background into a
   pale strip that light text can't sit on. Fix: give the select controls a
   SOLID dark background, and force the <option>/<optgroup> popup to solid
   dark-on-light-text. Specificity (root+attr+element+class) intentionally
   beats the per-page .form-input / .deal-input / .mod-move rules regardless
   of stylesheet load order. */
:root[data-theme="dark"] select,
:root[data-theme="dark"] select.form-input,
:root[data-theme="dark"] select.modal-input,
:root[data-theme="dark"] select.sort-select,
:root[data-theme="dark"] select.deal-input,
:root[data-theme="dark"] select.mod-move {
  background-color: #211f2d;
  color: var(--ink);
  border-color: var(--glass-edge);
  /* Lighter chevron so it reads on the solid dark control. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%238f8da1' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] select option,
:root[data-theme="dark"] select optgroup {
  background-color: #211f2d;
  color: #ecebf3;
}
:root[data-theme="dark"] select option:checked,
:root[data-theme="dark"] select option:hover {
  background-color: #33314a;
  color: #fff;
}

/* ══ Unified form controls ═══════════════════════════════════════════════════
   One coherent look for every text input, select, and textarea across the
   site - home, dashboard, forum, admin, and the fragrance directory / detail
   pages. Lives at the end of the file and uses element-level selectors so it
   reaches fields regardless of which per-page class they carry (and even
   fields with no class at all, like the admin proxy numbers or the price-alert
   modal). The whole point is that the fragrance pages use `.form-input`, whose
   definition lives in forum.css - which those pages don't load - so before
   this block their inputs/selects fell back to raw browser defaults.

   SPECIFICITY IS LOad-BEARING here, so note the exact tiers (a,b,c = id,
   class/attr/pseudo-class, element). The exclusion selectors deliberately use
   a *single grouped* `:not(...)`, whose specificity is that of its single most
   specific argument - one attribute selector, (0,1,0) - NOT the sum of ten
   chained `:not()`s. Getting that wrong is what makes the bare wrapper fields
   (below) lose.

   Three tiers, lowest-wins-least first:
   1. SIZING - `input, select, textarea` (0,0,1). Comfortable padding/font.
      Loses to any per-class rule (.form-input, .deal-input … 0,1,0), so
      compact controls keep their density; but reaches classless / unstyled
      fields. Button/checkbox/etc. input types are restored to UA sizing just
      below so it never bloats a checkbox.
   2. SURFACE - `:root input:not(…), :root select, :root textarea`
      (input branch 0,2,1; select/textarea 0,1,1). Beats per-class rules so
      every field shares one background / border / radius / focus ring, plus a
      custom chevron on selects.
   3. BARE WRAPPER - the three controls that sit inside a bordered wrapper
      (.search-input, .money-input input, .friends-add-input). Matched at
      (0,2,1) and placed last so source order settles the tie with the surface
      input branch - they stay transparent and border-less. */

/* Tier 1 - default sizing (low specificity; per-class rules win) */
input, select, textarea {
  padding: 10px 14px;
  font-size: 15px;
  font-family: inherit;
  line-height: 1.4;
}
/* …but keep non-text control types at their native sizing. */
input[type="checkbox"], input[type="radio"], input[type="range"],
input[type="file"], input[type="color"], input[type="submit"],
input[type="button"], input[type="reset"], input[type="image"] {
  padding: revert; font-size: revert; line-height: revert;
}

/* Tier 2 - shared surface (beats per-class rules). Grouped :not() keeps the
   input branch at (0,2,1); non-text input types are excluded so they never get
   a field background/border. */
:root input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="submit"], [type="button"], [type="reset"], [type="image"], [type="hidden"]),
:root select,
:root textarea {
  background-color: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: var(--r-input);
  color: var(--ink);
  box-sizing: border-box;
  transition: border-color var(--t), box-shadow var(--t);
}
:root input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="submit"], [type="button"], [type="reset"], [type="image"], [type="hidden"]):focus,
:root select:focus,
:root textarea:focus {
  outline: none;
  border-color: var(--accent-glow);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
:root input::placeholder,
:root textarea::placeholder { color: var(--ink-3); }

/* Selects: strip the native arrow and draw one consistent chevron so every
   dropdown looks identical. padding-right (longhand) beats the per-class
   `padding` shorthand, so the label never runs under the chevron. */
:root select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%236b6b7a' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  background-size: 11px 8px;
  padding-right: 34px;
  cursor: pointer;
}

/* Tier 3 - controls that live *inside* a bordered wrapper stay bare: the
   wrapper owns the border, background, and focus ring. Selectors match the
   surface input branch at (0,2,1) and come last, so source order wins. */
:root input.search-input,
:root .money-input input,
:root input.friends-add-input {
  background-color: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
/* The hero search field owns no padding of its own - keep it flush inside the
   pill wrapper. (.money-input input / .friends-add-input set their own.) */
:root input.search-input { padding: 0; }
:root input.search-input:focus,
:root .money-input input:focus,
:root input.friends-add-input:focus { box-shadow: none; border: 0; }

/* ── Reduced motion ──
   Honour the OS "reduce motion" setting: kill the drifting gradient mesh,
   smooth-scroll, and transition/animation flourishes for users who get
   motion sick or distracted by movement. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================
   DARK-MODE SEMANTIC COLOUR CORRECTIONS
   Many status chips / tags / messages pair a saturated *dark* text
   colour with a translucent light-tint background. In light mode that
   reads fine; in dark mode the tint composites dark while the text stays
   dark → poor contrast. These overrides lighten the text (and, where the
   background was baked light, darken it too) so every semantic colour
   stays legible and on-theme. Light mode is completely untouched.
   (Accent-red text is handled globally by re-pointing --accent-ink above.)
   ============================================================ */

/* Danger / error → light red */
:root[data-theme="dark"] .size-tag.sample,
:root[data-theme="dark"] .danger-btn,
:root[data-theme="dark"] .dash-danger .danger-btn,
:root[data-theme="dark"] .pill--admin,
:root[data-theme="dark"] .msg-cat--bug,
:root[data-theme="dark"] .reddit-rejected,
:root[data-theme="dark"] .reddit-link .username-msg.is-error,
:root[data-theme="dark"] .friends-add-msg.err,
:root[data-theme="dark"] .ban-pill { color: #ff9ba1; }

/* Women / pink → light pink */
:root[data-theme="dark"] .size-tag.gender-women { color: #ff8ab0; }

/* Success (green) → light green */
:root[data-theme="dark"] .site-type-tag.sample,
:root[data-theme="dark"] .ok-pill,
:root[data-theme="dark"] .friends-add-msg.ok,
:root[data-theme="dark"] .reddit-check,
:root[data-theme="dark"] .deal-status--ok { color: #5cd897; }

/* Info (blue) → light blue */
:root[data-theme="dark"] .size-tag.travel,
:root[data-theme="dark"] .size-tag.gender-men { color: #84b6ff; }

/* Warn / discount / tester (amber) → light amber */
:root[data-theme="dark"] .site-type-tag.discount,
:root[data-theme="dark"] .size-tag.tester,
:root[data-theme="dark"] .idle-note { color: #e8b866; }

/* Baked-light alert surfaces → dark tint + light text so they read as dark-mode
   cards instead of glaring white boxes on the dark page. */
:root[data-theme="dark"] .flash--info,
:root[data-theme="dark"] .flash--success,
:root[data-theme="dark"] .site-chip.success,
:root[data-theme="dark"] .cache-info--fresh,
:root[data-theme="dark"] .banned-appealed {
  background: rgba(40,170,90,0.16); color: #5cd897; border-color: rgba(60,180,110,0.32);
}
:root[data-theme="dark"] .flash--error,
:root[data-theme="dark"] .site-chip.failed {
  background: rgba(229,72,77,0.16); color: #ff9ba1; border-color: rgba(229,72,77,0.4);
}
:root[data-theme="dark"] .cache-info--cached {
  background: rgba(224,179,74,0.16); color: #e8b866; border-color: rgba(224,179,74,0.32);
}
:root[data-theme="dark"] .site-chip.loading {
  background: rgba(226,55,68,0.16); border-color: rgba(226,55,68,0.3);
}

/* Own DM bubble was a baked light #f4f4f7 → light text on light in dark mode. */
:root[data-theme="dark"] .dm-msg--mine .dm-bubble {
  background: rgba(255,255,255,0.10);
}

/* Two hover states use --accent-ink as a *background* (white text on top). Since
   --accent-ink is now light in dark mode, force these back to a mid red so the
   white label keeps its contrast and the hover still reads as "darker". */
:root[data-theme="dark"] .rte-pop-ok:hover,
:root[data-theme="dark"] .user-card-btn--msg:hover,
:root[data-theme="dark"] .user-card-btn--friend.is-primary:hover {
  background: #c62531;
}

/* ── Username popup card ──────────────────────────────────────────────────────
   The floating card shown when a username is clicked anywhere on the site
   (built by user-card.js). Identity header + two rows of quick actions. */
.user-card {
  position: absolute; z-index: 60;
  width: 264px; max-width: calc(100vw - 16px);
  display: flex; flex-direction: column; gap: 10px;
  padding: 14px; border: 1px solid var(--glass-line);
  border-radius: var(--r-md, 14px); background: var(--glass-strong);
  box-shadow: var(--e-3, 0 18px 44px rgba(17,17,34,0.22));
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  backdrop-filter: saturate(1.4) blur(12px);
  animation: user-card-in 0.13s ease-out;
}
@keyframes user-card-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .user-card { animation: none; } }

.user-card-id {
  display: flex; align-items: center; gap: 12px;
  text-decoration: none; border-radius: var(--r-sm); margin: -6px -6px 2px; padding: 6px;
  transition: var(--t);
}
.user-card-id:hover { background: var(--glass-hi); }
.user-card-av-wrap { position: relative; flex: 0 0 auto; line-height: 0; }
.user-card-av {
  width: 52px; height: 52px;
  border: 2px solid var(--glass-edge, rgba(255,255,255,0.5));
  box-shadow: var(--e-1, 0 4px 12px rgba(17,17,34,0.12));
}
.user-card-meta {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.user-card-name {
  font-size: 15px; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.user-card-handle { font-size: 12.5px; font-weight: 500; color: var(--ink-3); }
.user-card-rep {
  display: inline-flex; gap: 6px; margin-top: 3px; font-size: 11px; font-weight: 700;
}
.user-card-rep-b, .user-card-rep-s {
  padding: 1px 7px; border-radius: 999px; letter-spacing: 0.02em;
}
.user-card-rep-b { background: rgba(41,140,72,0.16); color: #1f7d40; }
.user-card-rep-s { background: rgba(59,110,214,0.16); color: #2f5fce; }

.user-card-actions { display: flex; gap: 8px; }
.user-card-btn {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  text-align: center; text-decoration: none; cursor: pointer;
  border: 1px solid var(--glass-line); background: var(--glass-hi); color: var(--ink-2);
  border-radius: var(--r-ctrl); padding: 8px 12px; font: inherit; font-size: 13px;
  font-weight: 600; line-height: 1.1; transition: var(--t); white-space: nowrap;
}
.user-card-btn svg { flex: 0 0 auto; }
.user-card-btn:hover { border-color: var(--accent-glow); color: var(--accent-ink); }
.user-card-btn:disabled { opacity: 0.55; cursor: default; }
.user-card-btn--wide { flex: 1 1 100%; }
.user-card-btn--msg { background: var(--accent); color: #fff; border-color: transparent; }
.user-card-btn--msg:hover { background: var(--accent-ink); color: #fff; }
.user-card-btn--friend.is-primary { background: var(--accent); color: #fff; border-color: transparent; }
.user-card-btn--friend.is-primary:hover { background: var(--accent-ink); color: #fff; }
.user-card-btn--friend.is-on, .user-card-btn--follow.is-on {
  background: transparent; color: var(--ink-3);
}
.user-card-btn--follow.is-on::before {
  content: "";
  width: 0.9em;
  height: 0.9em;
  background: var(--accent);
  -webkit-mask: url('/static/ui-icons/circle-check.svg') center / contain no-repeat;
  mask: url('/static/ui-icons/circle-check.svg') center / contain no-repeat;
}

/* Floating tooltip renderer used by theme.js. This avoids clipping inside cards,
   mod panels, and other overflow-hidden surfaces. */
.site-tooltip {
  position: fixed;
  z-index: 10000;
  max-width: min(280px, calc(100vw - 24px));
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(22,22,32,0.94);
  color: #fff;
  box-shadow: 0 10px 28px rgba(0,0,0,0.24);
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0;
  text-align: left;
  text-transform: none;
  pointer-events: none;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 0.12s ease, transform 0.12s ease;
}
.site-tooltip.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.affiliate-disclosure { display:block; margin:0 0 7px; color:var(--ink-2); font-size:11px; line-height:1.35; text-align:center; }
.card-footer .affiliate-disclosure { font-size: 0.625rem; letter-spacing: -0.01em; }

/* WCAG 2.2 AA hardening. These rules intentionally live last so page-specific
   styles cannot remove keyboard focus or shrink essential controls below the
   24 CSS pixel target-size floor. */
:where(p, li, dd, dt, figcaption, label, .card-name, .forum-body) {
  overflow-wrap: anywhere;
}
:root[data-theme="dark"] .site-chip.cached {
  background: rgba(224,179,74,0.16); color: #e8b866; border-color: rgba(224,179,74,0.32);
}
.seg-fieldset {
  min-width: 0;
  border: 0;
  padding: 0;
}
.seg-fieldset > legend {
  float: left;
  width: 100%;
}
.seg-fieldset > legend + * { clear: both; }

:where(button, input[type="button"], input[type="submit"], input[type="reset"],
       [role="button"], [role="tab"], .acct-link--icon, .share-pop-close,
       .notif-pop-close, .site-modal-close, .suggest-arrow, .mini-action) {
  min-width: 24px;
  min-height: 24px;
}

/* Reassert focus after the unified form-control block above. */
:root :where(a[href], button, select, input:not([type="hidden"]), textarea,
             summary, [tabindex]:not([tabindex="-1"]), [role="button"],
             [role="tab"], [contenteditable="true"]):focus-visible {
  outline: 3px solid #9b1421;
  outline-offset: 3px;
  box-shadow: 0 0 0 2px #fff;
}
:root[data-theme="dark"] :where(a[href], button, select, input:not([type="hidden"]),
             textarea, summary, [tabindex]:not([tabindex="-1"]), [role="button"],
             [role="tab"], [contenteditable="true"]):focus-visible {
  outline-color: #ff9ba5;
  box-shadow: 0 0 0 2px #111;
}

/* Accent-colored text needs a lighter shade on dark glass; fill colors stay
   dark enough to retain white-text contrast on buttons. */
:root[data-theme="dark"] :where(
  .deal-card-price, .deal-card-actions .deal-feed-item, .extension-installed-note,
  .copy-url, .latest-price, .lsp--normal, .share-net--email, .loading-text,
  .comparison-tab.active span, .comparison-panel-head strong, .product-brand,
  .product-from strong, .product-eyebrow, .card-ppm, .mini-action:hover,
  .spark-range-btn.active, .sparkline-trend, .user-card-btn:hover,
  .user-card-btn--follow.is-on::before,
  /* Links and labels that take the accent straight: #c92534 on a dark panel
     measures 2.8:1, so every one of these was under the floor. */
  .feature-card a, .cms-card a, .features-hero .features-eyebrow,
  .admin-table a, .legal-region-note a, .msg-from a, .profile-stat dd a,
  .forum-empty a, .cms-rich-editor a
) { color: #ff9ba5; }
:root[data-theme="dark"] .ranked-site-tip { color: #c8c6d5; }

/* Windows High Contrast / forced-colors mode must retain boundaries and state. */
@media (forced-colors: active) {
  *, *::before, *::after { forced-color-adjust: auto; }
  :where(button, a, input, select, textarea, [role="button"], [role="tab"]) {
    border-color: ButtonText;
  }
  :where(.active, .is-active, .is-on, [aria-pressed="true"], [aria-selected="true"]) {
    outline: 2px solid Highlight;
    outline-offset: 1px;
  }
  .chip-dot, .presence-dot, .live-dot { border: 1px solid CanvasText; }
}
/* Scraper health is split by execution source so client-only failures do not
   get mistaken for server scraper outages. */
.scraper-source-summary {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .75rem;
  margin: 1rem 0 1.25rem;
}
.scraper-source-stat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .8rem 1rem;
  border: 1px solid var(--glass-line);
  border-left: 4px solid #8090a8;
  border-radius: 10px;
  background: var(--surface, rgba(255,255,255,.035));
}
.scraper-source-stat--extension { border-left-color: #6f9cff; }
.scraper-source-stat--desktop { border-left-color: #b782e8; }
.scraper-source-stat strong { font-size: 1.25rem; }
.scraper-source-groups { display: grid; gap: 1.25rem; }
.scraper-source-group {
  padding: 1rem;
  border: 1px solid var(--glass-line);
  border-radius: 12px;
}
.scraper-source-heading .dash-mini-title { margin: 0 0 5px; }
.scraper-source-heading .dash-note { display: block; margin: 0; }
.scraper-source-group .dash-subtitle { margin: 18px 0 8px; }
@media (max-width: 700px) {
  .scraper-source-summary { grid-template-columns: 1fr; }
}

/* ── Marketing blocks (hero / feature_group / cta) ────────────────────────────
   Used by the CMS blocks of the same name (see templates/_cms_blocks.html) and
   by the /features page, which is built entirely from those blocks. Loaded
   globally so the admin CMS preview renders them the same as the live page. */
.features-page { max-width: 1080px; margin: 0 auto; }

.features-hero {
  text-align: center;
  max-width: 760px;
  margin: 4px auto 34px;
}
.features-hero.cms-hero--left { text-align: left; margin-left: 0; margin-right: auto; }
.features-hero .features-eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 750;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--accent);
  margin: 0 0 10px;
}
/* This rule comes after the dark accent-text list and matches as tightly, so
   the eyebrow needs its own light red rather than a place on that list. */
:root[data-theme="dark"] .features-hero .features-eyebrow {
  color: #ff9ba5;
}
.features-hero h1 { font-size: 1.9rem; font-weight: 700; line-height: 1.15; margin: 0 0 12px; }
.features-hero p { color: var(--ink-2); font-size: 1rem; line-height: 1.6; margin: 0 auto; max-width: 640px; }
.features-hero.cms-hero--left p { margin-left: 0; }

.features-toc {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 22px auto 0;
  max-width: 760px;
}
.features-hero.cms-hero--left .features-toc { justify-content: flex-start; }
.features-toc a {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-2);
  text-decoration: none;
  padding: 6px 13px;
  border: 1px solid var(--glass-line);
  border-radius: var(--r-pill);
  background: var(--glass);
  transition: color var(--t, .18s), border-color var(--t, .18s), transform var(--t, .18s);
}
.features-toc a:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-1px); }

.features-section { margin: 0 0 20px; scroll-margin-top: 90px; }
.features-section-head, .cms-section-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 4px;
  padding: 0 4px;
}
.features-section-head .features-badge, .cms-section-head .cms-section-badge {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 12px;
  background: var(--accent-soft);
  color: var(--accent);
}
.features-section-head .features-badge .ui-icon, .cms-section-head .cms-section-badge .ui-icon { width: 20px; height: 20px; }
.features-section-head h2, .cms-section-head h2 { font-size: 1.25rem; font-weight: 700; margin: 0; }
.features-section-lede, .cms-lede { color: var(--ink-2); font-size: 0.92rem; line-height: 1.55; margin: 0 0 16px; padding: 0 4px; }

.features-grid, .cms-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  gap: 16px;
}
.feature-card, .cms-card {
  background: var(--glass-strong);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  box-shadow: var(--e-1);
  padding: 20px 22px;
}
.feature-card h3, .cms-card h3 {
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.feature-card h3 .ui-icon, .cms-card h3 .ui-icon { width: 17px; height: 17px; color: var(--accent); flex-shrink: 0; }
.feature-card p, .cms-card p { color: var(--ink-2); font-size: 0.88rem; line-height: 1.55; margin: 0 0 10px; }
.feature-card p:last-child, .cms-card p:last-child { margin-bottom: 0; }
.feature-list, .cms-card-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.feature-list li, .cms-card-list li {
  position: relative;
  padding-left: 18px;
  color: var(--ink-2);
  font-size: 0.86rem;
  line-height: 1.5;
}
.feature-list li::before, .cms-card-list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 8px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.7;
}
.feature-list li strong, .cms-card-list li strong { color: var(--ink); font-weight: 650; }
.feature-card a, .cms-card a { color: var(--accent); font-weight: 600; text-decoration: none; }
.feature-card a:hover, .cms-card a:hover { text-decoration: underline; }

/* A section built from plain blocks - an icon heading, an intro paragraph, a
   card grid - needs the breathing room the old one-piece section wrapper gave
   it, so the pieces carry it themselves. */
.cms-section-head { scroll-margin-top: 90px; }
.features-page > .cms-cards { margin-bottom: 20px; }
.features-page > .cms-cards + .cms-section-head,
.features-page > p + .cms-section-head { margin-top: 20px; }
.cms-cards--2 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.cms-cards--3 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.cms-cards--4 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
@media (min-width: 900px) {
  .cms-cards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cms-cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cms-cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* A row of buttons. Left by default; centred is what a closing call to action
   wants. In a guide's hero panel it sits where the page-actions row used to. */
.cms-buttons { display: flex; flex-wrap: wrap; gap: 10px; }
.cms-buttons--center { justify-content: center; }
.partner-hero > .cms-buttons { margin-top: 18px; }
.features-divider { border: 0; border-top: 1px solid var(--glass-line); margin: 26px 4px; }
.features-page > .cms-divider { margin: 26px 4px; }

/* A panel: a box with ordinary blocks inside it. `card` is the raised surface
   the closing call-to-action has always used, `soft` a quieter tinted note, and
   `plain` a bare group that only sets the alignment. */
.features-cta, .cms-box--card {
  background: var(--glass-strong);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  box-shadow: var(--e-1);
  padding: 30px 24px;
  margin-top: 6px;
}
.cms-box--soft {
  background: var(--accent-soft);
  border: 1px solid var(--glass-line);
  border-radius: var(--r-card);
  padding: 26px 24px;
  margin-top: 6px;
}
.cms-box--plain { padding: 0; }
.features-cta, .cms-box--center { text-align: center; }
.cms-box--center .cms-buttons, .cms-box--center .features-cta-actions { justify-content: center; }
.features-cta h2,
.cms-box > h2, .cms-box > .cms-section-head h2 { font-size: 1.3rem; font-weight: 700; margin: 0 0 8px; }
.features-cta p, .cms-box > p { color: var(--ink-2); font-size: 0.95rem; line-height: 1.55; margin: 0 auto 18px; max-width: 520px; }
.cms-box--left > p { margin-left: 0; }
.cms-box > *:last-child { margin-bottom: 0; }
.cms-box > .cms-section-head { justify-content: center; }
.cms-box--left > .cms-section-head { justify-content: flex-start; }
.features-cta-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.features-cta-actions .acct-btn, .cms-box .acct-btn { text-decoration: none; }

@media (max-width: 560px) {
  .features-hero h1 { font-size: 1.55rem; }
  .feature-card, .cms-card { padding: 18px; }
}

/* â”€â”€ Partner Shopify setup (/partners/shopify-setup) â”€â”€
   A merchant-facing handoff page: contents rail on the left, numbered setup
   steps on the right. Sits on the shared glass surface and the site-wide
   1.7rem/700 h1 rail, plus a print stylesheet so a store can save it as a PDF
   and forward it to their developer. â”€â”€ */
.partner-page { display: flex; flex-direction: column; gap: 20px; }

.partner-hero {
  background: var(--glass-strong);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  box-shadow: var(--e-2);
  padding: 30px 28px;
}
/* --accent-ink rather than --accent on every small red text run here: the flat
   accent is a fill colour and drops under 4.5:1 as text on the dark surface,
   while --accent-ink is re-pointed per theme for exactly this. */
.partner-eyebrow {
  color: var(--accent-ink); font-weight: 700; font-size: 0.76rem;
  text-transform: uppercase; letter-spacing: 0.09em; margin-bottom: 8px;
}
.partner-hero h1 { font-size: 1.7rem; font-weight: 700; margin: 0 0 10px; }
.partner-lede {
  color: var(--ink-2); font-size: 1rem; line-height: 1.6; max-width: 62ch; margin: 0;
}
.partner-lede strong { color: var(--ink); font-weight: 650; }
.partner-facts {
  list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 0; padding: 0;
}
.partner-facts li {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--glass-line); border-radius: var(--r-pill);
  padding: 6px 13px; color: var(--ink-2); font-size: 0.84rem;
}
.partner-facts .ui-icon { color: var(--accent); font-size: 0.95rem; }
.partner-hero-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }

.partner-layout {
  display: grid; grid-template-columns: 208px minmax(0, 1fr); gap: 32px; align-items: start;
}

.partner-toc {
  position: sticky; top: calc(var(--sticky-header-h, 0px) + 22px);
  border-left: 2px solid var(--glass-line); padding-left: 14px;
}
.partner-toc-hd {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 10px;
}
.partner-toc ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.partner-toc a {
  display: block; padding: 5px 0; color: var(--ink-2); font-size: 0.85rem;
  text-decoration: none; line-height: 1.35; transition: color var(--t);
}
.partner-toc a:hover { color: var(--ink); }
.partner-toc a.is-current { color: var(--accent-ink); font-weight: 650; }

.partner-body { display: flex; flex-direction: column; gap: 18px; min-width: 0; }

.partner-section {
  background: var(--glass-strong);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-card);
  box-shadow: var(--e-1);
  padding: 26px;
  scroll-margin-top: calc(var(--sticky-header-h, 0px) + 20px);
}
.partner-section h2 { font-size: 1.18rem; font-weight: 700; margin: 0 0 12px; }
.partner-section > p { color: var(--ink-2); font-size: 0.93rem; line-height: 1.65; margin: 0 0 10px; }
.partner-section > p:last-child { margin-bottom: 0; }
.partner-section strong { color: var(--ink); font-weight: 650; }
.partner-section code {
  background: var(--accent-soft); color: var(--accent-ink);
  padding: 1px 6px; border-radius: 6px; font-size: 0.85em;
  word-break: break-word;
}
.partner-tag {
  display: inline-block; vertical-align: 3px; margin-left: 8px;
  background: var(--accent); color: #fff; border-radius: var(--r-pill);
  padding: 3px 10px; font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase;
}
.partner-note, .partner-hint {
  color: var(--ink-3); font-size: 0.85rem; line-height: 1.55; margin: 10px 0 0;
}
.partner-next { margin-top: 16px; font-size: 0.93rem; color: var(--ink-2); }
.partner-next a, .partner-contact a { color: var(--accent-ink); font-weight: 600; text-decoration: none; }
.partner-next a:hover, .partner-contact a:hover { text-decoration: underline; }
.partner-contact { font-size: 0.95rem; line-height: 1.7; }

.partner-list { margin: 8px 0 0; padding-left: 20px; color: var(--ink-2); font-size: 0.92rem; line-height: 1.7; }
.partner-list li + li { margin-top: 4px; }

/* What we read / never touch */
.partner-split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.partner-panel { border: 1px solid var(--glass-line); border-radius: var(--r-ctrl); padding: 18px; }
.partner-panel h3 {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.92rem; font-weight: 700; margin: 0 0 10px;
}
.partner-panel ul { margin: 0; padding-left: 20px; color: var(--ink-2); font-size: 0.88rem; line-height: 1.65; }
.partner-panel--yes { background: rgba(8,120,58,0.07); border-color: rgba(8,120,58,0.22); }
.partner-panel--yes h3 { color: var(--success); }
.partner-panel--no { background: rgba(189,37,48,0.06); border-color: rgba(189,37,48,0.20); }
.partner-panel--no h3 { color: var(--danger); }

/* Numbered setup steps */
.partner-steps { list-style: none; counter-reset: partner-step; margin: 14px 0 0; padding: 0; }
.partner-steps > li {
  counter-increment: partner-step;
  position: relative; padding: 0 0 20px 46px;
}
.partner-steps > li::before {
  content: counter(partner-step);
  position: absolute; left: 0; top: 0;
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; font-size: 0.85rem; font-weight: 700;
}
/* Rail joining one step to the next, so the sequence reads as a single flow. */
.partner-steps > li::after {
  content: ''; position: absolute; left: 14px; top: 34px; bottom: 4px;
  width: 2px; background: var(--glass-line);
}
.partner-steps > li:last-child { padding-bottom: 0; }
.partner-steps > li:last-child::after { display: none; }
.partner-steps h3 { font-size: 0.98rem; font-weight: 650; margin: 4px 0 6px; }
.partner-steps p { color: var(--ink-2); font-size: 0.92rem; line-height: 1.65; margin: 0 0 8px; }
.partner-steps p:last-child { margin-bottom: 0; }
.partner-steps--compact > li { padding-bottom: 14px; }

.partner-callout {
  display: flex; gap: 10px; align-items: flex-start;
  border-radius: var(--r-ctrl); padding: 12px 14px; margin: 10px 0 0;
  font-size: 0.88rem; line-height: 1.6;
}
.partner-callout .ui-icon { flex: 0 0 auto; margin-top: 2px; font-size: 1rem; }
.partner-callout--warn {
  background: rgba(200,150,30,0.12); border: 1px solid rgba(200,150,30,0.32); color: var(--ink-2);
}
.partner-callout--warn .ui-icon { color: var(--gold); }

/* Copy affordances */
.copy-chip {
  font: inherit; color: var(--accent-ink); background: var(--accent-soft);
  border: 1px solid transparent; border-radius: 6px; padding: 1px 7px;
  cursor: pointer; transition: background var(--t);
}
.copy-chip:hover { background: var(--accent-glow); }
.copy-chip.copied { color: var(--success); background: rgba(8,120,58,0.14); }
.partner-copyblock { position: relative; margin: 12px 0 0; }
.partner-copyblock pre {
  background: var(--input-bg); border: 1px solid var(--input-border);
  border-radius: var(--r-ctrl); padding: 16px; margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.82rem; line-height: 1.7; color: var(--ink-2);
  overflow-x: auto; white-space: pre;
}
.partner-copyblock .copy-block { position: absolute; top: 10px; right: 10px; }
.partner-copyblock .copy-block.copied { color: var(--success); }

/* What happens next */
.partner-timeline { list-style: none; margin: 4px 0 0; padding: 0; }
.partner-timeline li {
  position: relative; padding: 0 0 14px 22px;
  color: var(--ink-2); font-size: 0.92rem; line-height: 1.65;
}
.partner-timeline li::before {
  content: ''; position: absolute; left: 0; top: 8px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--accent); opacity: 0.75;
}
.partner-timeline li:last-child { padding-bottom: 0; }

/* Collapsible options and FAQ */
.partner-details {
  border: 1px solid var(--glass-line); border-radius: var(--r-ctrl);
  margin-top: 10px; background: var(--glass);
}
.partner-details summary {
  cursor: pointer; list-style: none; padding: 14px 40px 14px 16px; position: relative;
}
.partner-details summary::-webkit-details-marker { display: none; }
.partner-details summary::after {
  content: ''; position: absolute; right: 16px; top: 20px;
  width: 8px; height: 8px; border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3);
  transform: rotate(45deg); transition: transform var(--t);
}
.partner-details[open] summary::after { transform: rotate(-135deg); top: 23px; }
.partner-details summary:hover { background: var(--glass-line); border-radius: var(--r-ctrl); }
.partner-details-title { display: block; font-size: 0.95rem; font-weight: 650; color: var(--ink); }
.partner-details-sub { display: block; font-size: 0.84rem; color: var(--ink-3); margin-top: 3px; }
.partner-details-body { padding: 0 16px 16px; }
.partner-details-body p { color: var(--ink-2); font-size: 0.9rem; line-height: 1.65; margin: 0 0 8px; }
.partner-details-body p:last-child { margin-bottom: 0; }
.partner-faq { display: flex; flex-direction: column; }

/* Tables (scopes, troubleshooting) */
.partner-table-wrap { overflow-x: auto; margin: 12px 0 0; }
.partner-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.partner-table th, .partner-table td {
  text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--glass-line);
  vertical-align: top; line-height: 1.55;
}
.partner-table th { color: var(--ink); font-weight: 650; white-space: nowrap; }
.partner-table td { color: var(--ink-2); }
.partner-table tr:last-child td { border-bottom: 0; }

/* CMS guide blocks (steps / timeline / compare / copy block / facts).
   They reuse the partner-page section pieces above so a guide built in the
   Pages CMS is indistinguishable from a hand-written one. */
/* Their heading is a section heading like any other, so it deliberately keeps
   the same size as a Heading block rather than the smaller one the panelled
   .partner-section layout uses. */
.cms-steps > h2, .cms-timeline > h2, .cms-compare > h2 { margin: 0 0 12px; }
.cms-steps .partner-steps li ul, .cms-steps .partner-steps li ol {
  color: var(--ink-2); font-size: 0.92rem; line-height: 1.65;
  margin: 0 0 8px; padding-left: 20px;
}
.cms-compare-split--1 { grid-template-columns: 1fr; }
.cms-compare-split--3 { grid-template-columns: repeat(3, 1fr); }
.cms-compare > .partner-note { margin-top: 12px; }
.partner-panel--neutral { background: var(--glass); }
/* Accordion bodies hold rich text, so their lists need the same treatment the
   hand-written .partner-list got. */
.partner-details-body ul, .partner-details-body ol {
  margin: 8px 0; padding-left: 20px;
  color: var(--ink-2); font-size: 0.9rem; line-height: 1.65;
}
.partner-details-body li + li { margin-top: 4px; }
/* Native page content sits in a marked wrapper so the live-text editor knows
   what it may rewrite; it still reads as part of the card around it. */
.cms-native > p {
  color: var(--ink-2); font-size: 0.93rem; line-height: 1.65; margin: 0 0 10px;
}
.cms-native > p:last-child { margin-bottom: 0; }
.cms-copyblock figcaption {
  color: var(--ink); font-size: 0.92rem; font-weight: 650; margin: 0 0 8px;
}
.cms-copyblock figcaption + pre + .copy-block { top: 40px; }

@media (max-width: 940px) {
  .partner-layout { grid-template-columns: 1fr; }
  .partner-toc { display: none; }
  .cms-compare-split--3 { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .partner-hero { padding: 24px 20px; }
  .partner-hero h1 { font-size: 1.45rem; }
  .partner-section { padding: 20px 18px; }
  .partner-split { grid-template-columns: 1fr; }
  .partner-steps > li { padding-left: 40px; }
  .partner-copyblock .copy-block { position: static; margin-top: 8px; width: 100%; }
}

/* Dark theme: the green/red/gold tints above are mixed for a light surface, so
   re-point them to the same dark-mode alert palette the flashes and site chips
   already use (see the alert-surface overrides higher up). */
:root[data-theme="dark"] .partner-panel--yes {
  background: rgba(40,170,90,0.14); border-color: rgba(60,180,110,0.30);
}
:root[data-theme="dark"] .partner-panel--yes h3 { color: #5cd897; }
:root[data-theme="dark"] .partner-panel--no {
  background: rgba(229,72,77,0.13); border-color: rgba(229,72,77,0.32);
}
:root[data-theme="dark"] .partner-panel--no h3 { color: #ff9ba1; }
:root[data-theme="dark"] .partner-callout--warn {
  background: rgba(224,179,74,0.14); border-color: rgba(224,179,74,0.32);
}
:root[data-theme="dark"] .partner-callout--warn .ui-icon { color: #e8b866; }
:root[data-theme="dark"] .copy-chip.copied,
:root[data-theme="dark"] .partner-copyblock .copy-block.copied { color: #5cd897; }
:root[data-theme="dark"] .copy-chip.copied { background: rgba(40,170,90,0.18); }

/* Stores print this page or save it as a PDF to forward internally, so strip
   the site chrome and force every collapsed section open. */
@media print {
  .header, .addon-banner, .cookie-banner, .footer,
  .partner-toc, .partner-hero-actions, .cms-toc, .skip-link { display: none !important; }
  /* A button that acts on the page being read has nothing to do on paper; an
     ordinary link button is part of the content and stays. */
  .cms-buttons [data-copy-link], .cms-buttons [data-partner-print] { display: none !important; }
  /* Same idea for the CMS blocks the guides are built from: a collapsed
     section must still print, and a copy button must not. */
  .cms-accordion-item, .cms-faq-item { break-inside: avoid; }
  .cms-accordion-item > *:not(summary),
  .cms-faq-item > *:not(summary) { display: block !important; }
  .cms-copyblock .copy-block { display: none !important; }
  .partner-layout { grid-template-columns: 1fr; }
  .partner-hero, .partner-section {
    box-shadow: none; border: 1px solid #ddd; break-inside: avoid; background: #fff;
  }
  .partner-details { break-inside: avoid; }
  .partner-details > *:not(summary) { display: block !important; }
  .partner-details summary::after { display: none; }
  .partner-copyblock .copy-block, .copy-chip { border: 0; background: none; }
}

/* ============================================================
   Liquid glass, light mode
   ------------------------------------------------------------
   The glass tokens up top are nearly opaque white over a flat
   --bg, and the coloured mesh the dark-mode rules refer to was
   never actually painted. Glass with nothing behind it reads as
   a grey gradient, which is exactly how it looked.

   Three things make it read as glass instead:
     1. something to refract  → a fixed, static mesh on <body>
     2. a translucent, *graded* fill → --glass-panel
     3. a specular rim + sheen that catches that mesh

   --glass / --glass-strong keep their existing opacity: they are
   consumed by hundreds of small chips and controls whose text
   contrast depends on them. Only the large surfaces opt into
   --glass-panel, so only a handful of layers ever blur.
   ============================================================ */
:root {
  /* The face: what the pane is made of. One value, used by every surface.
     It carries its own body. A face thin enough to read the washes through
     takes their hue, so two panes side by side come out different colours
     and the text on them loses its ground. */
  --glass-panel: linear-gradient(152deg,
    rgba(255,255,255,0.82) 0%,
    rgba(255,255,255,0.64) 46%,
    rgba(255,255,255,0.72) 100%);
  --glass-rim: rgba(255,255,255,0.78);
  /* The specular sweep across the top-left corner, the way light catches a
     real pane. It is a background layer and not an overlay, because an
     overlay has to be lifted above the pane's own content, and the rule
     that lifted it flattened every absolutely-positioned child. */
  --glass-sweep: linear-gradient(142deg,
    rgba(255,255,255,0.34) 0%,
    rgba(255,255,255,0.19) 12%,
    rgba(255,255,255,0.09) 24%,
    rgba(255,255,255,0.03) 36%,
    rgba(255,255,255,0) 52%);
  /* The two rims plus the inner wall, which is what gives a pane thickness
     rather than printing it flat on the page. */
  --glass-core:
    inset 0 1px 0 rgba(255,255,255,0.95),
    inset 0 -1px 0 rgba(17,17,34,0.10),
    inset 0 0 24px rgba(255,255,255,0.22);
  --glass-drop: 0 14px 40px rgba(17,17,34,0.12);

  /* The washes behind the content. Each fades to its OWN hue at zero alpha
     through several stops: a ramp that ends at `transparent` ends at
     transparent BLACK, which darkens as it fades and leaves a visible ring.
     They are centred on the content band, not the page edges, because glass
     over a flat middle is just a grey card. */
  /* Light has to stay light. The same washes at dark-theme strength turn a
     pale page grey, and anything translucent over them reads as a dirty slab
     rather than as glass. These are half the strength and warmer, enough to
     give a pane something to show without tinting the paper. */
  --page-wash:
    radial-gradient(58% 46% at 22% 22%,
      rgba(214,44,60,0.13) 0%, rgba(214,44,60,0.07) 34%,
      rgba(214,44,60,0.02) 62%, rgba(214,44,60,0) 84%),
    radial-gradient(54% 44% at 84% 14%,
      rgba(96,110,235,0.13) 0%, rgba(96,110,235,0.07) 36%,
      rgba(96,110,235,0.02) 64%, rgba(96,110,235,0) 86%),
    radial-gradient(52% 42% at 66% 56%,
      rgba(168,96,220,0.09) 0%, rgba(168,96,220,0.05) 38%,
      rgba(168,96,220,0.02) 66%, rgba(168,96,220,0) 86%),
    radial-gradient(90% 64% at 36% 106%,
      rgba(255,168,120,0.14) 0%, rgba(255,168,120,0.07) 40%,
      rgba(255,168,120,0.02) 70%, rgba(255,168,120,0) 90%);
}
:root[data-theme="dark"] {
  --glass-panel: linear-gradient(152deg,
    rgba(52,50,72,0.68) 0%,
    rgba(36,35,52,0.58) 46%,
    rgba(46,44,64,0.64) 100%);
  --glass-rim: rgba(255,255,255,0.26);
  --glass-sweep: linear-gradient(142deg,
    rgba(255,255,255,0.13) 0%,
    rgba(255,255,255,0.08) 12%,
    rgba(255,255,255,0.04) 24%,
    rgba(255,255,255,0.015) 36%,
    rgba(255,255,255,0) 52%);
  --glass-core:
    inset 0 1px 0 rgba(255,255,255,0.50),
    inset 0 -1px 0 rgba(0,0,0,0.35),
    inset 0 0 24px rgba(255,255,255,0.05);
  --glass-drop: 0 18px 48px rgba(0,0,0,0.46);

  /* Half the strength these were set to. Behind an opaque-enough pane a
     wash is a ground; at full strength it is the page, and it turned the
     middle of every screen into a red-to-violet bloom. */
  --page-wash:
    radial-gradient(58% 46% at 22% 26%,
      rgba(214,44,60,0.22) 0%, rgba(214,44,60,0.13) 34%,
      rgba(214,44,60,0.045) 62%, rgba(214,44,60,0) 84%),
    radial-gradient(54% 44% at 82% 18%,
      rgba(88,78,220,0.22) 0%, rgba(88,78,220,0.13) 36%,
      rgba(88,78,220,0.045) 64%, rgba(88,78,220,0) 86%),
    radial-gradient(52% 42% at 62% 60%,
      rgba(150,70,210,0.15) 0%, rgba(150,70,210,0.08) 38%,
      rgba(150,70,210,0.03) 66%, rgba(150,70,210,0) 86%),
    radial-gradient(90% 64% at 40% 104%,
      rgba(40,34,86,0.30) 0%, rgba(40,34,86,0.15) 40%,
      rgba(40,34,86,0.05) 70%, rgba(40,34,86,0) 90%);
}

/* The mesh is painted as body background layers rather than a
   pseudo-element: a negative-z pseudo would sit behind body's own
   background colour and never show. `fixed` attachment keeps it
   viewport-sized, so it composites once and never re-paints on
   scroll or as the page grows. */
body {
  background: var(--page-wash), linear-gradient(170deg, var(--bg) 0%, var(--bg-2) 100%);
  background-attachment: fixed;
}

/* Large, mostly-static surfaces: translucent graded fill, bright
   rim, and the blur that turns a tint into glass. */
.glass-card,
.latest-searches,
.idle-card,
.deal-feed-strip,
.user-card,
.search-suggest {
  background: var(--glass-sweep), var(--glass-panel);
  border: 1px solid var(--glass-rim);
  box-shadow: var(--glass-core), var(--glass-drop);
  -webkit-backdrop-filter: var(--blur-sm);
  backdrop-filter: var(--blur-sm);
}

/* Result cards are a grid of many instances, so they get the glass
   fill and rim but no blur - dozens of blurred layers is what made
   the page composite continuously in the first place. The sweep is a
   background layer here too: as an overlay it lay across the top-left of
   every product photo and washed it out. */
.product-card,
.deal-card {
  background: var(--glass-sweep), var(--glass-panel);
  border: 1px solid var(--glass-rim);
  box-shadow: var(--glass-core), var(--glass-drop);
  transition: box-shadow var(--t), transform var(--t);
}
/* Only .glass-card needs this; .idle-card and .deal-feed-strip already
   declare it themselves, and .latest-searches declares its own position --
   sticky on a results page, and deliberately static on an idle one so the
   rail lines up with the top of the cards. Naming it here overrode that
   static with `relative`, which turned the sticky rule's `top: 90px` into a
   90px shove down the page. */
.glass-card { position: relative; }
/* There is deliberately no `> *` lift here. The sweep is a background layer
   now, so a panel's content already paints above it, and forcing every direct
   child to `position: relative` overrode `absolute` on the ones that need it
   -- the modal close button landed in the flow on top of the dialog title. */

/* ── Size / type / gender filters read as buttons ──
   They were flat translucent pills that looked like inert labels.
   Give them a raised edge, a graded face and a press response so
   it is obvious they can be clicked. */
.size-btn {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.95), rgba(255,255,255,0.72));
  border: 1.5px solid rgba(17,17,34,0.16);
  color: var(--ink);
  font-weight: 600;
  padding: 7px 16px;
  box-shadow:
    0 1px 2px rgba(20,20,50,0.08),
    0 2px 8px rgba(20,20,50,0.06),
    inset 0 1px 0 rgba(255,255,255,0.9);
}
.size-btn:hover {
  border-color: rgba(226,55,68,0.55);
  color: var(--accent);
  background: linear-gradient(180deg, #fff, rgba(255,255,255,0.86));
  box-shadow:
    0 2px 4px rgba(20,20,50,0.10),
    0 6px 16px rgba(226,55,68,0.14),
    inset 0 1px 0 rgba(255,255,255,0.95);
}
.size-btn:active { transform: translateY(1px); box-shadow: inset 0 2px 5px rgba(20,20,50,0.16); }
.size-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.size-btn.active {
  border: 1.5px solid transparent;
  color: #fff;
  box-shadow:
    0 2px 5px rgba(226,55,68,0.30),
    0 6px 18px var(--accent-glow),
    inset 0 1px 0 rgba(255,255,255,0.38);
}
.size-btn.active:hover { color: #fff; }
:root[data-theme="dark"] .size-btn {
  background: linear-gradient(180deg, rgba(255,255,255,0.13), rgba(255,255,255,0.05));
  border-color: rgba(255,255,255,0.26);
  color: var(--ink);
  box-shadow:
    0 1px 2px rgba(0,0,0,0.35),
    inset 0 1px 0 rgba(255,255,255,0.14);
}
:root[data-theme="dark"] .size-btn:hover {
  background: linear-gradient(180deg, rgba(255,255,255,0.20), rgba(255,255,255,0.09));
  border-color: rgba(255,138,148,0.6);
  color: var(--accent-ink);
}
:root[data-theme="dark"] .size-btn:active { box-shadow: inset 0 2px 6px rgba(0,0,0,0.45); }

/* The OS reduce-motion / reduce-transparency path keeps the page
   cheap: no blur, flat fills. */
@media (prefers-reduced-transparency: reduce) {
  .glass-card, .latest-searches, .idle-card,
  .deal-feed-strip, .product-card, .deal-card {
    background: var(--glass-strong);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body { background: var(--bg); }
}

.ship-badge--manual{background:rgba(90,110,160,.14);color:#39496b}
:root[data-theme="dark"] .ship-badge--manual{background:rgba(140,165,220,.18);color:#c3d0ee}
.ed-upload{margin-bottom:10px}
.ed-upload button{width:100%}
.ed-upload-msg{margin:6px 0 0;font-size:.82rem;color:var(--ink-2)}
.ed-upload-msg.is-bad{color:#b02a2f}

/* Collapsible search filters (phones only) */
.filters-toggle{display:none}
@media (max-width:600px){
  .filters-toggle{
    display:inline-flex;align-items:center;gap:8px;
    margin:0 0 var(--s3);padding:10px 16px;
    font:inherit;font-weight:600;font-size:.92rem;
    color:var(--ink);background:var(--glass-panel,rgba(255,255,255,.72));
    border:1px solid var(--glass-rim,rgba(0,0,0,.1));border-radius:999px;
    cursor:pointer;
  }
  .filters-toggle[hidden]{display:none}
  .filters-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .filters-toggle .ui-icon{font-size:1.05em}
  /* Closed by default: the results are what the visitor came for. */
  .filter-panel{display:none}
  .filter-panel.is-open{display:block}
  /* Store chips read as a list rather than one tall column of pills. */
  .site-statuses{gap:8px}
}
.extension-unsupported{margin:14px 0 0;padding:12px 14px;border-radius:12px;font-size:.92rem;line-height:1.5;background:var(--glass-panel,rgba(255,255,255,.7));border:1px solid var(--glass-rim,rgba(0,0,0,.1))}
/* Borrowed-view bar */
.viewas-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:12px;padding:9px 16px;background:#2d2a66;color:#f2f1ff;font-size:.9rem;line-height:1.4}
.viewas-bar strong{color:#fff}
.viewas-stop{padding:6px 14px;font:inherit;font-weight:600;color:#2d2a66;background:#f2f1ff;border:0;border-radius:999px;cursor:pointer}
.viewas-stop:hover{background:#fff}
.viewas-stop:focus-visible{outline:2px solid #fff;outline-offset:2px}
@media (max-width:600px){.viewas-bar{font-size:.84rem;padding:8px 12px;gap:8px}}

/* Phone layout for the search controls.
   Each control used to take a full-width row of its own - results sat roughly
   300px down the page. Sort and Filters now share a row, the graph range is a
   compact strip above them, and the filter panel reads as a left-aligned list
   rather than a centred scatter. */
@media (max-width: 600px) {
  .controls-right { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }
  .sort-group--graph { width: 100%; gap: 6px; }
  .sort-group--graph .sort-label { font-size: .78rem; }
  #sparkRange { flex: 1; }
  #sparkRange .filter-btn { padding: 6px 0; font-size: .8rem; }
  .sort-group--sort { flex: 1 1 140px; min-width: 0; width: auto; gap: 6px; }
  .sort-group--sort .sort-label { font-size: .78rem; }
  .sort-group--sort .sort-select { flex: 1; min-width: 0; padding-top: 8px; padding-bottom: 8px; }
  .filters-toggle { margin: 0; flex: 0 0 auto; padding: 9px 14px; }

  /* The cache notice fits on one line; the information icon still carries the
     24-hour explanation that used to wrap onto a line of its own. */
  .cache-info { padding: 8px 12px; gap: 6px; font-size: .76rem; flex-wrap: nowrap; }
  .ci-secondary { display: none; }
  .rm-hint { display: none; }

  /* Inside the panel: one labelled row per filter, aligned left. */
  .filter-panel .size-filter { justify-content: flex-start; gap: 6px; margin-bottom: 10px; }
  .filter-panel .size-filter-label { width: 100%; text-align: left; margin: 0 0 4px; }
  .filter-panel .size-btn { flex: 0 0 auto; padding: 7px 12px; font-size: .82rem; }
  /* The rails scroll by swiping on a touch screen, which is the gesture
     people reach for anyway, and the arrows depend on hovering, which a
     phone cannot do. Hiding them gives the chips the full width. */
  .suggest-arrow { display: none; }
  .suggest-scroll { -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity; }
  .suggest-scroll .suggest-chip { scroll-snap-align: start; }

  .filter-panel .site-statuses { gap: 6px; }
  .filter-panel .site-chips-row { justify-content: flex-start; }
  .filter-panel .site-chip { font-size: .78rem; padding: 6px 10px; }
  /* The dot already carries the state; the word doubles the chip width. */
  .chip-suffix--state { display: none; }
  .filter-panel .site-statuses-bar { margin-bottom: var(--s3); }
}

/* ───────────────────────────────────────────────────────────────────────────
   Phone app shell

   On a phone this stops being a narrow web page and behaves like an app: the
   sections live in a bottom bar within thumb reach, the filters arrive as a
   sheet that can be swiped away, and everything that responds to a finger
   answers it immediately rather than waiting for a hover that never comes.
   None of it applies above 600px, where the header already does the job.
   ─────────────────────────────────────────────────────────────────────────── */

.app-tabs { display: none; }
.sheet-grip { display: none; }
.sheet-backdrop { display: none; }

@media (max-width: 600px) {
  .app-tabs {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 60;
    display: flex;
    justify-content: space-around;
    gap: 2px;
    padding: 6px 6px calc(6px + env(safe-area-inset-bottom, 0px));
    background: var(--glass-panel, rgba(255, 255, 255, .88));
    border-top: 1px solid var(--glass-rim, rgba(0, 0, 0, .09));
    backdrop-filter: saturate(140%) blur(18px);
    -webkit-backdrop-filter: saturate(140%) blur(18px);
  }
  .app-tab {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    /* A comfortable thumb target rather than a link you have to aim at. */
    min-height: 48px;
    padding: 4px 2px;
    border-radius: 12px;
    color: var(--ink-2, #5d5f66);
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .01em;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: color .15s ease, background-color .15s ease, transform .12s ease;
  }
  .app-tab .ui-icon { font-size: 1.35rem; }
  /* The brand red is a mid tone: legible on a light bar, not on a dark one.
     The dark theme already keeps a lighter accent for text on dark grounds. */
  .app-tab.is-active { color: var(--accent, #e23744); }
  :root[data-theme="dark"] .app-tab.is-active { color: var(--accent-ink, #ff8a94); }
  .app-tab:active { transform: scale(.94); background: var(--accent-soft, rgba(226, 55, 68, .1)); }
  .app-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .app-tab-badge {
    position: absolute; top: 2px; right: 50%; margin-right: -18px;
    min-width: 8px; height: 8px; border-radius: 999px;
    background: var(--accent, #e23744);
  }
  .app-tab-badge[hidden] { display: none; }

  /* Keep the last of the page clear of the bar. */
  body { padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)); }

  /* ── Filters as a bottom sheet ──────────────────────────────────────────
     The panel used to push the results down the page while it was open. As a
     sheet it sits over them, can be flicked away, and leaves the results
     where they were. */
  .filter-panel.is-open {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 70;
    display: block;
    max-height: 78vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 6px 16px calc(20px + env(safe-area-inset-bottom, 0px));
    /* The sheet sits over the results, and its ground is translucent, so it
       needs the blur of its own: without it the listing underneath reads
       straight through the filter labels. */
    background: var(--panel, #fff);
    -webkit-backdrop-filter: var(--blur-sm);
    backdrop-filter: var(--blur-sm);
    border-radius: 20px 20px 0 0;
    box-shadow: 0 -12px 40px rgba(0, 0, 0, .22);
    transform: translateY(var(--sheet-drag, 0px));
    animation: sheet-rise .22s cubic-bezier(.22, 1, .36, 1);
  }
  .filter-panel.is-dragging { animation: none; transition: none; }
  .filter-panel.is-settling { transition: transform .18s ease-out; }
  @keyframes sheet-rise { from { transform: translateY(100%); } to { transform: translateY(0); } }

  /* The grab handle, and a heading so the sheet says what it is. */
  .sheet-grip {
    position: sticky; top: 0; z-index: 1;
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    margin: 0 -16px 10px; padding: 10px 16px 8px;
    background: var(--panel, #fff);
    cursor: grab; touch-action: none; -webkit-tap-highlight-color: transparent;
  }
  .sheet-grip::before {
    content: ""; width: 42px; height: 5px; border-radius: 999px;
    background: var(--glass-rim, rgba(0, 0, 0, .18));
  }
  .sheet-grip-row { display: flex; align-items: center; justify-content: space-between; width: 100%; }
  .sheet-title { font-size: .95rem; font-weight: 700; }
  .sheet-done {
    padding: 7px 16px; font: inherit; font-size: .85rem; font-weight: 600;
    color: #fff; background: var(--accent, #e23744);
    border: 0; border-radius: 999px; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .sheet-done:active { transform: scale(.96); }

  .sheet-backdrop {
    display: block;
    position: fixed; inset: 0; z-index: 69;
    background: rgba(12, 10, 20, .42);
    animation: sheet-fade .22s ease-out;
  }
  .sheet-backdrop[hidden] { display: none; }
  @keyframes sheet-fade { from { opacity: 0; } to { opacity: 1; } }
  /* While a sheet is up the page behind it should not scroll with it. */
  body.sheet-open { overflow: hidden; }

  /* ── Touch manners ─────────────────────────────────────────────────────
     Press states instead of hover states, and no 300ms grey flash. */
  a, button, .size-btn, .filter-btn, .site-chip, .suggest-chip {
    -webkit-tap-highlight-color: transparent;
  }
  .size-btn:active, .filter-btn:active, .site-chip:active, .suggest-chip:active,
  .acct-btn:active, .filters-toggle:active { transform: scale(.97); }
  .site-chip:hover, .suggest-chip:hover { transform: none; box-shadow: none; }
  /* Rails and tables flick properly and stop at a chip. */
  .table-scroll, .ship-table-wrap { overscroll-behavior-x: contain; }
}

@media (max-width: 600px) and (prefers-reduced-motion: reduce) {
  .filter-panel.is-open { animation: none; }
  .sheet-backdrop { animation: none; }
  .app-tab:active, .size-btn:active, .filter-btn:active,
  .site-chip:active, .suggest-chip:active, .sheet-done:active { transform: none; }
}

/* ── A filter toggle says whether it is on ─────────────────────────────────
   These were telling you their state with colour alone: a red fill for on, a
   pale face for off. On a phone, in daylight, or to anyone who reads red and
   grey the same way, "Tester" on and "Tester" off looked much alike, and
   nothing said the pale ones were toggles at all.

   Every one of them now carries a marker: an empty ring when it is off and a
   tick when it is on. The marker occupies the same space either way, so the
   label never shifts as it is pressed, and it rides on top of the colour
   rather than replacing it. */
.size-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
/* ── Under construction ──────────────────────────────────────────────────
   The holding page is the only page most people will see while the site is
   closed, so it is built from the same parts as the rest: one glass pane, the
   accent, and the icon set. */
.uc { position: relative; max-width: 620px; margin: 8px auto 32px; }
/* A soft bloom behind the pane, so it is not a card floating on a flat page.
   The mask is what keeps it soft: a radial ramp is still part-way up its
   alpha where the element's own box ends, which drew a hard vertical seam
   down each side of the page. The layer now fades out before its edge
   whatever the ramps underneath are doing. */
.uc::before {
  content: "";
  position: absolute;
  inset: -40% -45% -45%;
  z-index: 0;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(closest-side, #000 42%, rgba(0,0,0,0) 100%);
  mask-image: radial-gradient(closest-side, #000 42%, rgba(0,0,0,0) 100%);
  background:
    radial-gradient(52% 44% at 24% 16%,
      rgba(226,55,68,0.22) 0%, rgba(226,55,68,0.10) 38%, rgba(226,55,68,0) 72%),
    radial-gradient(48% 42% at 80% 32%,
      rgba(120,110,235,0.18) 0%, rgba(120,110,235,0.08) 40%, rgba(120,110,235,0) 74%);
}
.uc-card { position: relative; z-index: 1; padding: 34px 32px 30px; text-align: center; }

.uc-badge {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0 0 18px; padding: 6px 14px 6px 11px;
  border: 1px solid rgba(226,55,68,0.32); border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-deep);
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
}
.uc-dot {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--accent);
  box-shadow: 0 0 0 0 rgba(226,55,68,0.55);
  animation: uc-pulse 2s ease-out infinite;
}
@keyframes uc-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(226,55,68,0.5); }
  70%  { box-shadow: 0 0 0 7px rgba(226,55,68,0); }
  100% { box-shadow: 0 0 0 0 rgba(226,55,68,0); }
}

.uc-title { margin: 0 0 10px; font-size: 2rem; font-weight: 700; line-height: 1.15; letter-spacing: -0.5px; }
.uc-title em { font-style: normal; color: var(--accent-deep); }
.uc-lede { margin: 0 auto; max-width: 44ch; color: var(--ink-2); font-size: 1rem; line-height: 1.6; }

/* Indeterminate: a stripe that keeps travelling, because there is no honest
   percentage to show. */
.uc-bar {
  position: relative; overflow: hidden;
  height: 6px; margin: 24px auto 26px; max-width: 320px;
  border-radius: var(--r-pill);
  background: rgba(20,20,50,0.10);
}
.uc-bar span {
  position: absolute; inset: 0 auto 0 0; width: 42%;
  border-radius: inherit;
  background: linear-gradient(90deg,
    rgba(226,55,68,0) 0%, var(--accent) 45%, var(--accent-2) 65%, rgba(226,55,68,0) 100%);
  animation: uc-slide 2.4s cubic-bezier(.45,0,.35,1) infinite;
}
@keyframes uc-slide {
  0%   { transform: translateX(-110%); }
  100% { transform: translateX(260%); }
}

.uc-list { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 12px; text-align: left; }
.uc-list li {
  display: flex; align-items: flex-start; gap: 13px;
  padding: 13px 15px;
  border: 1px solid var(--glass-line); border-radius: var(--r-sm);
  background: var(--glass);
}
.uc-ico {
  flex: none; width: 19px; height: 19px; margin-top: 2px;
  color: var(--accent-deep);
}
.uc-item { display: grid; gap: 2px; min-width: 0; }
.uc-item strong { font-size: 0.92rem; font-weight: 650; color: var(--ink); }
.uc-item span { font-size: 0.86rem; line-height: 1.5; color: var(--ink-2); }

.uc-actions { display: flex; gap: .6rem; justify-content: center; flex-wrap: wrap; margin: 0; }
.uc-actions form { margin: 0; }

:root[data-theme="dark"] .uc::before {
  background:
    radial-gradient(52% 44% at 24% 16%,
      rgba(255,90,106,0.20) 0%, rgba(255,90,106,0.09) 38%, rgba(255,90,106,0) 72%),
    radial-gradient(48% 42% at 80% 32%,
      rgba(120,110,235,0.20) 0%, rgba(120,110,235,0.09) 40%, rgba(120,110,235,0) 74%);
}
:root[data-theme="dark"] .uc-badge { color: #ff9ba5; border-color: rgba(255,155,165,0.34); }
:root[data-theme="dark"] .uc-title em { color: #ff9ba5; }
:root[data-theme="dark"] .uc-ico { color: #ff9ba5; }
:root[data-theme="dark"] .uc-bar { background: rgba(255,255,255,0.10); }

@media (max-width: 600px) {
  .uc-card { padding: 26px 18px 24px; }
  .uc-title { font-size: 1.6rem; }
  .uc-lede { font-size: 0.94rem; }
  .uc-actions .acct-btn { width: 100%; justify-content: center; }
  .uc-actions form { width: 100%; }
}

/* Movement is decoration here; the page reads the same without it. */
@media (prefers-reduced-motion: reduce) {
  .uc-dot { animation: none; }
  .uc-bar span { animation: none; transform: none; width: 55%; }
}

/* The switch that closes the whole site reads differently from the ones that
   hide a single feature. */
.proxy-row--danger { border-left: 3px solid var(--accent); padding-left: 13px; }
.proxy-row--danger .proxy-lbl { color: var(--accent); }
:root[data-theme="dark"] .proxy-row--danger .proxy-lbl { color: #ff9ba5; }

.idle-soon {
  font: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--ink-2);
  background: var(--glass);
  border: 1px dashed var(--glass-edge);
  border-radius: var(--r-pill);
  padding: 7px 16px;
  cursor: not-allowed;
}
.idle-soon[disabled] { opacity: 1; }

.size-btn::before {
  content: "";
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.6px solid currentColor;
  opacity: .42;
  transition: opacity var(--t), border-color var(--t), background-color var(--t);
}
.size-btn.active::before {
  opacity: 1;
  border-color: transparent;
  background-color: currentColor;
  -webkit-mask: url('/static/ui-icons/circle-check.svg') center / contain no-repeat;
  mask: url('/static/ui-icons/circle-check.svg') center / contain no-repeat;
}
/* Off should read as off: quieter than the page, not as loud as an on one. */
.size-btn:not(.active) { color: var(--ink-2); }
.size-btn:not(.active)::before { border-style: dashed; }
/* Hovering one you are not on should show you what picking it would do: the
   face lifts towards the active fill, the ring firms up from its dashed
   "off" state, and the label takes the accent. */
.size-btn:not(.active):hover {
  color: var(--accent-deep);
  border-color: rgba(226,55,68,0.55);
  background: linear-gradient(180deg, rgba(255,235,236,0.96), rgba(255,224,226,0.82));
  box-shadow:
    0 2px 6px rgba(226,55,68,0.18),
    inset 0 1px 0 rgba(255,255,255,0.9);
}
.size-btn:not(.active):hover::before { border-style: solid; opacity: .85; }

/* The same treatment for the dark theme's version of these buttons. */
:root[data-theme="dark"] .size-btn:not(.active) { color: var(--ink-2); }
:root[data-theme="dark"] .size-btn:not(.active):hover {
  color: #ff9ba5;
  border-color: rgba(255,155,165,0.55);
  background: linear-gradient(180deg, rgba(255,155,165,0.20), rgba(255,155,165,0.08));
  box-shadow:
    0 2px 8px rgba(0,0,0,0.35),
    inset 0 1px 0 rgba(255,255,255,0.14);
}

@media (prefers-reduced-motion: reduce) {
  .size-btn::before { transition: none; }
}
