/* ============================================================
   7COMPARE — "PRICE INTELLIGENCE"

   A price comparison site is a measuring instrument, so this is
   built to read like one: hairlines instead of shadows, tabular
   figures for anything comparable, one blue for the product and
   colour otherwise reserved for numbers that mean something
   (green = a saving we calculated, red = a rise we recorded).

   THE SEVEN MOTIF
   The brand mark is a 7, so the recurring device is a strip of
   seven segments — see `.seven`. It is not decoration: it shows
   where a price sits between the lowest and highest we have
   actually recorded. Seven segments is coarse on purpose. Our
   history is thin, and a smooth needle would imply a precision
   the data does not have.

   Every visual value comes from tokens.css.
   ============================================================ */

/* ============================================================
   1. RESET & BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* the mobile tab bar is fixed; content must be able to clear it */
  padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
}
@media (min-width: 861px) { body { padding-bottom: 0; } }

img, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; }
a { color: inherit; text-decoration: none; }

/* One focus treatment everywhere. Visible, never removed —
   keyboard users need to know where they are. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

::selection { background: var(--brand-100); color: var(--ink); }

/* Keyboard users land here first and can jump straight past the nav. */
.skip-link {
  position: absolute; left: var(--s3); top: -60px; z-index: 200;
  background: var(--brand); color: var(--brand-ink);
  padding: 10px 16px; border-radius: var(--r-sm); font-weight: 600;
  transition: top var(--dur-2) var(--ease);
}
.skip-link:focus { top: var(--s3); }

/* Numbers that sit in a column must line up. */
.num, .deal-price, .best-price, .store-price, .trend-price,
.card-price-row, .stat b, .drop-old, .deal-mrp, .store-mrp {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ============================================================
   2. LAYOUT
   ============================================================ */
.shell, .nav-inner, .section, .hero, .footer-inner {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--s4);
}
@media (min-width: 720px) {
  .shell, .nav-inner, .section, .hero, .footer-inner { padding-inline: var(--s5); }
}

.section { padding-block: var(--s7); }
@media (min-width: 720px) { .section { padding-block: var(--s8); } }

.hidden { display: none !important; }
.dimmed { opacity: .45; transition: opacity var(--dur-2) var(--ease); }

/* ============================================================
   3. TYPOGRAPHY
   ============================================================ */
h1, h2, h3, h4 { line-height: var(--lh-tight); font-weight: 600; letter-spacing: -.02em; }
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); letter-spacing: -.01em; }

/* Section label — the small monospace marker above every heading.
   It carries the seven motif as a leading rule. */
.section-label {
  display: flex; align-items: center; gap: var(--s2);
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s3);
}
.section-label::before {
  content: "";
  width: 22px; height: 2px; flex: none;
  background: var(--brand);
  /* seven ticks compressed into a rule */
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 2px, transparent 2px 3px);
  mask-image: repeating-linear-gradient(90deg, #000 0 2px, transparent 2px 3px);
}

.section-sub, .hero-sub, .about {
  color: var(--ink-2);
  max-width: 68ch;
  margin-top: var(--s3);
}
.section h2 + .section-sub { margin-top: var(--s3); }

.mono-note { font-family: var(--mono); font-size: var(--t-xs); letter-spacing: .04em; }
.dim { color: var(--ink-3); }
.hint { color: var(--ink-3); font-size: var(--t-sm); }

/* The old design used a gradient text fill for emphasis. Solid
   brand colour reads better at small sizes and stays legible in
   both themes. */
.grad-text { color: var(--brand); font-weight: 700; }

/* ============================================================
   4. THE SEVEN — signature component
   Seven segments showing where a price sits inside its recorded
   range. `--fill` is how many segments are lit (0–7).
   ============================================================ */
.seven { display: inline-flex; gap: 3px; align-items: center; }
.seven i {
  width: 6px; height: 14px;
  border-radius: 2px;
  background: var(--line-2);
  transition: background var(--dur-2) var(--ease);
}
.seven i.on { background: var(--brand); }
.seven.is-low  i.on { background: var(--save); }
.seven.is-high i.on { background: var(--rise); }
.seven.sm i { width: 4px; height: 10px; }

/* ============================================================
   5. NAVIGATION
   ============================================================ */
.nav {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--line);
}
.nav-inner {
  height: var(--nav-h);
  display: flex; align-items: center; gap: var(--s4);
}

.logo { display: inline-flex; align-items: center; gap: var(--s2); font-weight: 700; font-size: 1.05rem; letter-spacing: -.02em; flex: none; }
.logo-mark {
  width: 26px; height: 26px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-xs);
  background: var(--brand); color: var(--brand-ink);
  font-family: var(--mono); font-size: .8rem; font-weight: 700;
  position: relative;
  transform-style: preserve-3d;
  animation: logo-flip 7s var(--ease) infinite;
}

/* THE MARK — flips like a card being checked, then settles.
   On a 7-second cycle, which is both long enough to stay out of the way
   and a small joke about the name. */
@keyframes logo-flip {
  0%, 74%, 100% { transform: rotateY(0deg); }
  82%           { transform: rotateY(180deg); }
  90%           { transform: rotateY(0deg); }
}

/* a soft ring that expands out of the mark as it lands */
.logo-mark::after {
  content: ""; position: absolute; inset: 0;
  border-radius: inherit;
  border: 2px solid var(--brand);
  opacity: 0;
  animation: logo-ring 7s var(--ease) infinite;
}
@keyframes logo-ring {
  0%, 88%, 100% { opacity: 0; transform: scale(1); }
  92%           { opacity: .5; transform: scale(1.35); }
  100%          { opacity: 0; transform: scale(1.6); }
}

/* THE WORD — a light sweeps across the letters, left to right, like a
   scan pass comparing them. Two markup variants exist across the site
   (a bare span on the homepage, a <b class="grad-text"> everywhere
   else) and both are covered; the small grey suffix some pages append
   is deliberately excluded. */
.logo > span:not(.logo-mark):not(.dim),
.logo > b.grad-text {
  position: relative;
  color: var(--ink);
}

/* Gated: without background-clip:text the transparent fill would make
   the wordmark invisible rather than merely unanimated. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .logo > span:not(.logo-mark):not(.dim),
  .logo > b.grad-text {
    background-image: linear-gradient(100deg,
      var(--ink) 42%, var(--brand) 50%, var(--ink) 58%);
    background-size: 260% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: logo-scan 7s var(--ease) infinite;
  }
}
@keyframes logo-scan {
  0%, 58%  { background-position: 100% 0; }
  84%, 100% { background-position: 0 0; }
}

@media (prefers-reduced-motion: reduce) {
  .logo-mark, .logo-mark::after,
  .logo > span:not(.logo-mark):not(.dim),
  .logo > b.grad-text { animation: none !important; }
  .logo > span:not(.logo-mark):not(.dim),
  .logo > b.grad-text { -webkit-text-fill-color: currentColor; }
}

.nav-links { display: none; align-items: center; gap: var(--s1); margin-left: var(--s3); }
@media (min-width: 861px) { .nav-links { display: flex; } }
.nav-links a {
  padding: 7px 11px; border-radius: var(--r-sm);
  font-size: var(--t-sm); font-weight: 500; color: var(--ink-2);
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  white-space: nowrap;
}
.nav-links a:hover { background: var(--raised); color: var(--ink); }
.nav-links a[aria-current="page"] { color: var(--brand); background: var(--brand-50); }

.nav-right { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }

.nav-menu-btn { display: grid; place-items: center; width: 38px; height: 38px; border-radius: var(--r-sm); color: var(--ink-2); }
.nav-menu-btn:hover { background: var(--raised); }
@media (min-width: 861px) { .nav-menu-btn { display: none; } }

.theme-btn {
  width: 38px; height: 38px; display: grid; place-items: center;
  border-radius: var(--r-sm); border: 1px solid var(--line);
  color: var(--ink-2); background: var(--surface);
  transition: border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.theme-btn:hover { border-color: var(--line-2); color: var(--ink); }
.theme-btn .moon { display: none; }
[data-theme="dark"] .theme-btn .sun { display: none; }
[data-theme="dark"] .theme-btn .moon { display: block; }

.live-badge {
  display: none; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: .1em;
  color: var(--save); background: var(--save-bg);
  padding: 5px 10px; border-radius: var(--r-pill);
  white-space: nowrap;
}
@media (min-width: 980px) { .live-badge { display: inline-flex; } }
.live-badge .dot, .hero-badge .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: none;
  animation: pulse 2.4s var(--ease) infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

.nav-tg svg { width: 15px; height: 15px; }
.nav-links .nav-tg { display: inline-flex; align-items: center; gap: 6px; }

/* --- mobile: the wordmark sits centred --- */
@media (max-width: 860px) {
  .nav-inner { position: relative; }
  /* Absolute centring rather than flex, so the logo is centred against
     the VIEWPORT and not against whatever width the hamburger and theme
     button happen to occupy — those two are different sizes, which would
     otherwise push the wordmark permanently off-centre.
     Scoped to the header: the footer logo stays left-aligned. */
  .nav .logo {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%);
  }
  /* the buttons keep the ends; nothing else competes for the middle */
  .nav-right { margin-left: auto; }
}

/* --- mobile drawer --- */
@media (max-width: 860px) {
  .nav-links {
    position: fixed; inset: var(--nav-h) 0 auto 0;
    display: block; margin: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--e2);
    padding: var(--s2) var(--s4) var(--s4);
    transform: translateY(-8px);
    opacity: 0; pointer-events: none;
    /* `visibility` is deliberately NOT transitioned. It is a discrete
       property, and animating it alongside opacity is a classic way to
       end up with a panel that reports .open while staying invisible —
       which is exactly what this drawer did. display toggles instead. */
    display: none;
    transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
    max-height: calc(100dvh - var(--nav-h)); overflow-y: auto;
  }
  .nav-links.open { display: block; opacity: 1; pointer-events: auto; transform: none; }
  .nav-links a { display: block; padding: 13px 10px; font-size: 1rem; border-radius: var(--r-sm); }
}

/* --- mobile bottom tab bar ---
   Thumb-reachable primary navigation. Hidden on desktop, where the
   header already carries these destinations. */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
}
@media (min-width: 861px) { .tabbar { display: none; } }
.tabbar a {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  font-size: 10px; font-weight: 500; letter-spacing: .01em;
  color: var(--ink-3);
  min-height: 44px;                      /* touch target */
  transition: color var(--dur-1) var(--ease);
}
.tabbar a svg {
  width: 21px; height: 21px; stroke-width: 1.7;
  transition: transform var(--dur-2) var(--ease);
}

/* The active tab needs to be unmistakable at a glance on a phone, so it
   gets four cues rather than a colour change alone: a filled pill behind
   the icon, the icon lifted and slightly larger, the label in brand
   colour, and a short bar above it. */
.tabbar a::before {
  content: "";
  position: absolute; top: 6px; left: 50%;
  width: 34px; height: 30px; margin-left: -17px;
  border-radius: var(--r-sm);
  background: var(--brand-50);
  opacity: 0; transform: scale(.7);
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.tabbar a { position: relative; }
.tabbar a > svg, .tabbar a { z-index: 1; }

.tabbar a[aria-current="page"] { color: var(--brand); font-weight: 600; }
.tabbar a[aria-current="page"]::before { opacity: 1; transform: scale(1); }
.tabbar a[aria-current="page"] svg { transform: translateY(-1px) scale(1.06); }
.tabbar a[aria-current="page"]::after {
  content: "";
  position: absolute; top: 0; left: 50%; margin-left: -10px;
  width: 20px; height: 3px; border-radius: 0 0 3px 3px;
  background: var(--brand);
  animation: tab-bar-in var(--dur-3) var(--ease) both;
}
@keyframes tab-bar-in { from { transform: scaleX(.2); opacity: 0; } to { transform: none; opacity: 1; } }

.tabbar a:active svg { transform: scale(.9); }

/* Desktop nav gets the same certainty, in its own idiom. */
.nav-links a[aria-current="page"] { color: var(--brand); background: var(--brand-50); font-weight: 600; }

/* ============================================================
   6. HERO + COMMAND SEARCH
   ============================================================ */
.hero { padding-block: var(--s6) var(--s7); text-align: left; }
@media (min-width: 720px) { .hero { padding-block: var(--s8) var(--s7); } }

.hero-badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: .12em;
  color: var(--brand); background: var(--brand-50);
  border: 1px solid var(--brand-100);
  padding: 6px 12px; border-radius: var(--r-pill);
  margin-bottom: var(--s4);
}

.hero h1 { font-size: var(--t-display); font-weight: 700; letter-spacing: -.035em; max-width: 16ch; }
.hero-sub { font-size: 1.0625rem; margin-top: var(--s4); }

/* The command bar. One field that takes a product, a pasted link
   or a question — so a first-time visitor never has to work out
   which box they are supposed to use. */
.cmd {
  margin-top: var(--s6);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--e1);
  overflow: hidden;
  transition: border-color var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.cmd:focus-within { border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-50); }

.cmd-row { display: flex; align-items: center; gap: var(--s2); padding: var(--s2); }
.cmd-icon { width: 40px; flex: none; display: grid; place-items: center; color: var(--ink-3); }
.cmd-icon svg { width: 19px; height: 19px; }
.cmd input {
  flex: 1 1 auto; min-width: 0;
  border: 0; outline: 0; background: none;
  font-size: 1rem; padding: 13px 0;
}
.cmd input::placeholder { color: var(--ink-4); }
.cmd .btn { flex: none; }

/* Quick actions sit inside the same surface so they read as modes
   of one tool rather than four separate features. */
.cmd-actions {
  display: flex; gap: var(--s1); flex-wrap: wrap;
  padding: var(--s2) var(--s2) var(--s3) calc(40px + var(--s3));
  border-top: 1px solid var(--line);
}
@media (max-width: 560px) { .cmd-actions { padding-left: var(--s3); } }
.cmd-action {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-xs); font-weight: 500; color: var(--ink-2);
  padding: 7px 11px; border-radius: var(--r-pill);
  border: 1px solid transparent;
  transition: background var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.cmd-action:hover { background: var(--raised); color: var(--ink); }
.cmd-action.active { background: var(--brand-50); border-color: var(--brand-100); color: var(--brand); }

.quick-chips {
  display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin-top: var(--s4);
  transition: opacity var(--dur-2) var(--ease);
}
.quick-chips.is-swapping { opacity: .25; }

/* Placeholder cross-fade while the examples cycle. */
.cmd input, .paste-form input { transition: opacity var(--dur-2) var(--ease); }
.cmd input.ph-out::placeholder, .paste-form input.ph-out::placeholder { opacity: 0; }
.cmd input::placeholder, .paste-form input::placeholder { transition: opacity 200ms var(--ease); }

/* ---------- the two invitation rows ----------
   One confident icon each in a filled tile, a sheen that sweeps across
   on hover, and an arrow that travels. Enough motion to read as an
   invitation, little enough to sit above the fold without nagging. */
.tg-cta, .unique-cta { position: relative; overflow: hidden; isolation: isolate; }

.cta-icon {
  width: 42px; height: 42px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  color: #fff;
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.cta-icon svg { width: 21px; height: 21px; }
.cta-icon-tg { background: #229ED9; box-shadow: 0 4px 14px rgba(34,158,217,.30); }
.cta-icon-uq { background: var(--brand); box-shadow: 0 4px 14px rgba(15,79,232,.28); }

/* the plane takes off, the star twinkles — both on a slow idle loop */
.cta-icon-tg svg { animation: cta-fly 3.4s var(--ease) infinite; }
.cta-icon-uq svg { animation: cta-twinkle 3.4s var(--ease) infinite; }
@keyframes cta-fly { 0%, 62%, 100% { transform: translate(0,0) rotate(0deg); } 76% { transform: translate(3px,-3px) rotate(8deg); } }
@keyframes cta-twinkle { 0%, 62%, 100% { transform: scale(1) rotate(0deg); } 78% { transform: scale(1.16) rotate(18deg); } }

/* a sheen that crosses the row on hover */
.tg-cta::after, .unique-cta::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(105deg, transparent 35%,
              color-mix(in srgb, var(--brand) 10%, transparent) 50%, transparent 65%);
  transform: translateX(-100%);
  transition: transform 620ms var(--ease);
}
.tg-cta:hover::after, .unique-cta:hover::after { transform: translateX(100%); }

.tg-cta:hover .cta-icon, .unique-cta:hover .cta-icon { transform: scale(1.06) rotate(-3deg); }

/* The invitation badge — the thing that actually says "do this".
   It breathes on a slow loop so the eye catches it once, then settles;
   Telegram's carries a live dot because that channel really is posting. */
.cta-badge {
  margin-left: auto; flex: none;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .01em;
  padding: 6px 12px; border-radius: var(--r-pill);
  background: var(--brand); color: var(--brand-ink);
  white-space: nowrap;
  animation: badge-breathe 2.6s var(--ease) infinite;
}
.cta-badge-live { background: #229ED9; }
.cta-badge-live::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: #fff; animation: pulse 1.6s infinite;
}
@keyframes badge-breathe {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 40%, transparent); }
  50%      { transform: scale(1.045); box-shadow: 0 0 0 7px transparent; }
}
.tg-cta:hover .cta-badge, .unique-cta:hover .cta-badge { animation-duration: 1.2s; }

/* the arrow follows the badge, so it no longer takes the auto margin */
.tg-cta-arrow, .unique-cta-arrow { margin-left: 0; }

@media (max-width: 440px) {
  /* on the narrowest phones the badge would squeeze the subtitle, so the
     arrow goes and the badge keeps the call to action */
  .cta-badge { padding: 5px 10px; font-size: 11px; }
  .tg-cta-arrow, .unique-cta-arrow { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cta-badge, .cta-badge-live::before { animation: none !important; }
}

.tg-cta-arrow, .unique-cta-arrow { transition: transform var(--dur-2) var(--ease), color var(--dur-2) var(--ease); }
.tg-cta:hover .tg-cta-arrow, .unique-cta:hover .unique-cta-arrow { transform: translateX(5px); color: var(--brand); }

@media (prefers-reduced-motion: reduce) {
  .cta-icon svg { animation: none !important; }
  .tg-cta::after, .unique-cta::after { display: none; }
}

/* Paste-a-link keeps its own affordance but inherits the command
   surface, so it reads as part of the same instrument. */
.paste-box { margin-top: var(--s5); }
.paste-label { font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); margin-bottom: var(--s2); }
.paste-form { display: flex; gap: var(--s2); flex-wrap: wrap; }
.paste-form input {
  flex: 1 1 260px; min-width: 0;
  padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface);
  transition: border-color var(--dur-1) var(--ease);
}
.paste-form input:focus { outline: 0; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-50); }
.paste-result:not(:empty) { margin-top: var(--s4); }

/* --- paste-a-link result ---
   Rendered by app.js after a link is resolved: a verdict line, the
   product, then every store we found it at. */
.paste-verdict {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  padding: var(--s3) var(--s4); border-radius: var(--r-sm);
  font-size: var(--t-sm); font-weight: 600;
  margin-bottom: var(--s3);
}
.paste-save { background: var(--save-bg); color: var(--save); }
.paste-best { background: var(--brand-50); color: var(--brand); }
.paste-err {
  padding: var(--s3) var(--s4); border-radius: var(--r-sm);
  background: var(--rise-bg); color: var(--rise); font-size: var(--t-sm);
}
.paste-head { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s3); }
.paste-head img { width: 52px; height: 52px; flex: none; object-fit: contain; background: var(--raised); border-radius: var(--r-xs); }
.paste-rows { display: flex; flex-direction: column; gap: var(--s2); }

/* --- coupon "what you actually pay" --- */
.coupon-after {
  font-size: 1.0625rem; font-weight: 700;
  color: var(--save); display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.coupon-after-label { font-size: var(--t-xs); font-weight: 500; color: var(--ink-3); }
.coupon-after-code { font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); }

/* misc states emitted by app.js */
.live { color: var(--save); }
.unique-banner-inner { min-width: 0; }

/* --- hero stat strip --- */
.hero-stats {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 1px; margin-top: var(--s6);
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
@media (min-width: 720px) { .hero-stats { grid-template-columns: repeat(4, 1fr); } }
.stat { background: var(--surface); padding: var(--s4); }
.stat b { display: block; font-size: 1.375rem; font-weight: 700; letter-spacing: -.02em; }
.stat span { font-size: var(--t-xs); color: var(--ink-3); }
.stat-min { font-size: .75rem; font-weight: 500; color: var(--ink-3); }

/* --- promotional rows (Telegram, Unique) --- */
.tg-cta, .unique-cta {
  display: flex; align-items: center; gap: var(--s3);
  margin-top: var(--s3); padding: var(--s3) var(--s4);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
}
.tg-cta:hover, .unique-cta:hover { border-color: var(--brand-200); transform: translateY(-1px); }
.tg-cta-mark, .unique-cta-spark { width: 34px; height: 34px; flex: none; display: grid; place-items: center; border-radius: var(--r-sm); background: var(--raised); }
.tg-cta-mark svg { width: 19px; height: 19px; }
.tg-cta-text, .unique-cta-text { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.tg-cta-text b, .unique-cta-text b { font-size: var(--t-sm); }
.tg-cta-text small, .unique-cta-text small { font-size: var(--t-xs); color: var(--ink-3); }
.tg-cta-arrow, .unique-cta-arrow { margin-left: auto; color: var(--ink-3); flex: none; }

/* ============================================================
   7. CONTROLS
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font-size: var(--t-sm); font-weight: 600;
  padding: 11px 16px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  min-height: 42px;                  /* never below a comfortable tap */
  white-space: nowrap;
  transition: background var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease),
              color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
}
/* Press physics. A real surface compresses under a finger and the
   light moves with it; a rectangle that only changes colour does not.
   --px/--py are written by reveal.js from the pointer position. */
.btn { position: relative; overflow: hidden; isolation: isolate; }
.btn::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(120px circle at var(--px, 50%) var(--py, 50%),
              rgba(255,255,255,.18), transparent 60%);
  opacity: 0; transition: opacity var(--dur-2) var(--ease);
}
.btn:hover::after { opacity: 1; }
.btn-outline::after, .btn-ghost::after {
  background: radial-gradient(120px circle at var(--px, 50%) var(--py, 50%),
              color-mix(in srgb, var(--brand) 12%, transparent), transparent 60%);
}
.btn:active { transform: scale(.97) translateY(1px); }

/* The buy action moves toward the store it sends you to. */
.btn-primary { transition: background var(--dur-1) var(--ease), transform var(--dur-1) var(--ease); }
.btn-primary:hover { letter-spacing: .002em; }

.btn-primary { background: var(--brand); color: var(--brand-ink); }
.btn-primary:hover { background: var(--brand-600); }

.btn-outline { background: var(--surface); border-color: var(--line-2); color: var(--ink); }
.btn-outline:hover { border-color: var(--ink-4); background: var(--raised); }

.btn-ghost { color: var(--ink-2); }
.btn-ghost:hover { background: var(--raised); color: var(--ink); }

.btn-sm { padding: 7px 11px; min-height: 34px; font-size: var(--t-xs); }
.btn-lg { padding: 13px 22px; min-height: 48px; font-size: 1rem; }

/* Chips — category, price band, filter. One component, used
   everywhere a set of mutually exclusive options appears. */
.chips-row { display: flex; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s4); }
.chip-cat {
  font-size: var(--t-xs); font-weight: 500;
  padding: 8px 13px; border-radius: var(--r-pill);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  min-height: 36px;
  transition: border-color var(--dur-1) var(--ease), background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.chip-cat:hover { border-color: var(--line-2); color: var(--ink); }
.chip-cat.active { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }

/* Store status pills during a live search. */
.pills-row { display: flex; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s5); }
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: .04em;
  padding: 5px 10px; border-radius: var(--r-pill);
  border: 1px solid var(--line); color: var(--ink-3); background: var(--surface);
}
.pill-ok { color: var(--save); border-color: color-mix(in srgb, var(--save) 30%, transparent); background: var(--save-bg); }
.pill-fail { color: var(--ink-4); text-decoration: line-through; }
.pill-wait { color: var(--ink-3); }
.pill-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; animation: pulse 1.2s infinite; }

select, .feed-head-row select {
  padding: 10px 13px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font-size: var(--t-sm); min-height: 42px;
}
select:focus { outline: 0; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-50); }
.feed-head-row { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; margin-bottom: var(--s4); }

/* ============================================================
   8. CARDS
   Compact and information-dense rather than bulky. The price is
   the largest thing on the card because it is why the card exists.
   ============================================================ */
.deal-grid, .grid {
  display: grid; gap: var(--s3);
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
}
@media (min-width: 600px) { .deal-grid, .grid { gap: var(--s4); grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); } }
@media (min-width: 1100px) { .deal-grid, .grid { grid-template-columns: repeat(auto-fill, minmax(238px, 1fr)); } }

.card, .deal-card, .coupon-card, .trend-card, .blog-card {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  position: relative;
  text-align: left;
  transition: border-color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.card:hover, .deal-card:hover, .coupon-card:hover, .trend-card:hover, .blog-card:hover {
  border-color: var(--line-2);
  transform: translateY(-2px);
  box-shadow: var(--e2);
}

.card-thumb, .deal-thumb, .blog-thumb {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--raised);
  display: grid; place-items: center;
  overflow: hidden;
}
.card-thumb img, .deal-thumb img { width: 100%; height: 100%; object-fit: contain; padding: var(--s3); }
.blog-thumb { aspect-ratio: 16 / 9; font-size: 2rem; }
.thumb-fallback, .trend-fallback { font-size: 1.75rem; color: var(--ink-4); }

.card-body, .deal-body, .trend-body, .blog-card-body, .coupon-card > div:last-child {
  padding: var(--s3);
  display: flex; flex-direction: column; gap: 7px;
  flex: 1 1 auto;
}

.card-cat, .deal-store, .trend-title, .blog-meta {
  font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}
.deal-title, .card-body h3, .trend-title, .blog-card h3 {
  font-size: var(--t-sm); font-weight: 600; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.blog-card h3 { font-size: 1rem; -webkit-line-clamp: 3; }
.blog-excerpt { font-size: var(--t-xs); color: var(--ink-2); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

.card-price-row, .deal-price, .trend-price { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; margin-top: auto; }
.deal-price, .trend-price, .best-price { font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em; }
.deal-mrp, .store-mrp, .drop-old { font-size: var(--t-xs); color: var(--ink-4); text-decoration: line-through; }

/* ------------------------------------------------------------
   THE PRICE REVEAL
   Fired once per card as it scrolls into view (reveal.js). The MRP
   falls back and dims while the real price advances and the figure
   counts down onto it — the discount is performed rather than
   stamped on in a red badge.

   Deliberately small: 520ms, a few pixels of travel. This sits
   between a shopper and the number they came for, so it has to read
   as the price arriving, not as the page still loading.
   ------------------------------------------------------------ */
.card.is-revealing .deal-price, .card.is-revealing .best-price,
.deal-card.is-revealing .deal-price { animation: pr-advance 520ms var(--ease) both; }
.card.is-revealing .best-label { animation: pr-save 620ms var(--ease) 120ms both; }
.card.is-revealing .deal-mrp,
.deal-card.is-revealing .deal-mrp { animation: pr-recede 520ms var(--ease) both; }
.card.is-revealing .save-badge, .deal-card.is-revealing .save-badge,
.card.is-revealing .drop-saved, .deal-card.is-revealing .drop-saved { animation: pr-save 620ms var(--ease) 180ms both; }

@keyframes pr-advance {
  from { transform: translateY(6px) scale(.94); opacity: 0; }
  to   { transform: none; opacity: 1; }
}
@keyframes pr-recede {
  from { transform: translateX(-6px) scale(1.06); opacity: .9; }
  to   { transform: none; opacity: 1; }
}
@keyframes pr-save {
  from { transform: translateY(4px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* Layered depth on hover: the thumbnail lifts a little further than
   the card it sits in, so the object reads as sitting inside a frame
   rather than printed onto it. */
@media (hover: hover) {
  .card:hover .card-thumb img, .deal-card:hover .deal-thumb img {
    transform: scale(1.045);
  }
  .card-thumb img, .deal-thumb img { transition: transform var(--dur-3) var(--ease); }
}

/* These rows carry a rating, a review count and a "bought" note. At 132px
   of card width they were wider than their own card and got clipped by the
   card's overflow, silently losing the review count — so they wrap. */
.card-rating, .stars, .bought-note {
  font-size: var(--t-xs); color: var(--ink-3);
  display: flex; align-items: center; gap: 5px;
  flex-wrap: wrap; min-width: 0;
}
.card-body > *, .deal-body > *, .trend-body > * { min-width: 0; }
.card-actions, .deal-actions { display: flex; gap: var(--s2); padding: 0 var(--s3) var(--s3); flex-wrap: wrap; }
/* A flex item's default min-width is `auto`, which is its CONTENT width —
   so a nowrap label like "Compare 6 prices" refused to shrink and pushed
   11px past the card, where overflow:hidden sliced the text off. min-width:0
   lets it shrink; the ellipsis makes the truncation deliberate. */
.card-actions .btn, .deal-actions .btn {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis;
}

/* Badges. Deliberately few: an unmissable badge on every card
   means none of them are unmissable. */
.discount-badge, .save-badge, .drop-badge, .tag-lowest, .best-label, .coupon-chip, .cpn-chip, .drop-flag, .mrp-flag, .blog-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--mono); font-size: var(--t-label); font-weight: 500;
  letter-spacing: .04em;
  padding: 4px 8px; border-radius: var(--r-xs);
  white-space: nowrap;
}
.discount-badge, .drop-badge {
  position: absolute; top: var(--s2); left: var(--s2); z-index: 1;
  background: var(--rise); color: var(--brand-ink);
}
.save-badge, .drop-saved, .tag-lowest, .best-label { background: var(--save-bg); color: var(--save); }
.coupon-chip, .cpn-chip, .blog-tag { background: var(--raised); color: var(--ink-2); }
/* Unlike the short badges above, these two carry a short sentence
   ("was ₹1,299 on 2 Aug"). Holding them on one line overflowed a narrow
   card, so they are allowed to wrap and to sit on their own line. */
.mrp-flag, .drop-flag {
  background: var(--warn-bg); color: var(--warn);
  white-space: normal; line-height: 1.35; align-self: flex-start;
}

/* ------------------------------------------------------------
   MOBILE CARD — a different composition, not a smaller one.

   Two columns on a 360px phone left each card 158px wide. At that
   width the title truncated after three words, "2 STORES · SAME
   PRODUCT" wrapped onto two lines, the coupon note was sliced in
   half and the Compare button ran off the edge. Everything was
   technically present and none of it was readable.

   So on phones a card becomes a horizontal row: a fixed square
   thumbnail, the facts beside it with a full line to themselves,
   and the actions spanning the full width underneath where the
   buttons finally have room. Fewer cards per screen, but each one
   can actually be read and tapped.
   ------------------------------------------------------------ */
@media (max-width: 560px) {
  /* Two compact square cards per row, as asked. The clipped Compare
     button was never caused by the column count — it was a flex item
     that could not shrink below its own text (fixed with min-width:0
     above), so the tiles can stay small and still hold their buttons. */
  .deal-grid, .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }

  .card, .deal-card, .coupon-card { border-radius: var(--r-lg); }
  .card-thumb, .deal-thumb { border-radius: var(--r-lg) var(--r-lg) 0 0; }

  .card-body, .deal-body { padding: var(--s3) 11px; gap: 5px; }
  .deal-title, .card-body h3 { font-size: .8125rem; -webkit-line-clamp: 2; }
  .deal-price, .trend-price, .best-price { font-size: 1.0625rem; }
  .card-cat, .deal-store, .best-label { font-size: 10px; letter-spacing: .04em; }

  /* Buttons stack so each gets the full tile width instead of fighting
     for half of a 158px row. */
  .card-actions, .deal-actions { padding: 0 11px 11px; gap: 6px; }
  .card-actions .btn, .deal-actions .btn {
    flex: 1 1 100%; min-height: 40px; padding: 9px 10px; font-size: 12px;
  }
}

.blog-tags { display: flex; gap: 5px; flex-wrap: wrap; }
.blog-grid { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.trend-grid { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.trend-save { color: var(--save); font-size: var(--t-xs); font-weight: 600; }

/* ============================================================
   9. RESULTS LIST (the "more" list under the grid)
   ============================================================ */
.more-row, .store-row, .paste-row, .store-listing {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  margin-bottom: var(--s2);
  transition: border-color var(--dur-1) var(--ease);
}
.more-row:hover, .store-row:hover, .store-listing:hover { border-color: var(--line-2); }
.row-img { width: 46px; height: 46px; flex: none; border-radius: var(--r-xs); background: var(--raised); object-fit: contain; }
.row-title, .more-title, .store-name, .paste-title { font-size: var(--t-sm); font-weight: 600; min-width: 0; }
.row-meta, .store-info, .store-diff { font-size: var(--t-xs); color: var(--ink-3); }
.more-list { display: flex; flex-direction: column; }

/* ============================================================
   10. COMPARE MODAL — the price intelligence view
   ============================================================ */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: color-mix(in srgb, var(--ink) 45%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  display: none; align-items: flex-end; justify-content: center;
  opacity: 0; transition: opacity var(--dur-2) var(--ease);
}
.modal-overlay.open { display: flex; opacity: 1; }
@media (min-width: 720px) { .modal-overlay { align-items: center; padding: var(--s5); } }

/* On mobile this is a bottom sheet — reachable, familiar, and it
   keeps the page visible behind it. On desktop it becomes a
   centred dialog. */
.modal {
  position: relative;
  width: 100%; max-width: 760px;
  max-height: 92dvh; overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: var(--e3);
  padding: var(--s5) var(--s4) calc(var(--s6) + env(safe-area-inset-bottom));
  transform: translateY(14px);
  transition: transform var(--dur-3) var(--ease);
  overscroll-behavior: contain;
}
.modal-overlay.open .modal { transform: none; }
@media (min-width: 720px) { .modal { border-radius: var(--r-lg); padding: var(--s6); max-height: 88dvh; } }

/* the sheet grab handle, mobile only */
.modal::before {
  content: ""; position: absolute; top: 9px; left: 50%; transform: translateX(-50%);
  width: 38px; height: 4px; border-radius: 2px; background: var(--line-2);
}
@media (min-width: 720px) { .modal::before { display: none; } }

.modal-close {
  position: absolute; top: var(--s3); right: var(--s3);
  width: 36px; height: 36px; display: grid; place-items: center;
  border-radius: var(--r-sm); color: var(--ink-3); background: var(--raised);
  z-index: 2;
}
.modal-close:hover { color: var(--ink); }

.modal-head { display: flex; gap: var(--s4); margin-bottom: var(--s5); padding-right: 44px; }
.modal-head img { width: 84px; height: 84px; flex: none; object-fit: contain; background: var(--raised); border-radius: var(--r-sm); }
.modal-head h3 { font-size: 1.0625rem; }
.modal-tools { display: flex; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s5); }

/* Best-price block — the single loudest element in the dialog. */
.verdict {
  padding: var(--s4);
  border-radius: var(--r-md);
  background: var(--save-bg);
  border: 1px solid color-mix(in srgb, var(--save) 22%, transparent);
  margin-bottom: var(--s5);
}
.verdict-head { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; }
.best-price { font-size: 1.75rem; color: var(--save); }
.best-store { font-weight: 600; }
.verdict-why { font-size: var(--t-sm); color: var(--ink-2); margin-top: 6px; }
.compare-summary { font-size: var(--t-sm); color: var(--ink-2); margin-bottom: var(--s4); }

/* Store rows — the cheapest is visually dominant, everything else
   recedes so the eye lands on it first. */
.store-list { display: flex; flex-direction: column; gap: var(--s2); }
.store-row.is-best, .store-listing.is-best { border-color: var(--save); background: var(--save-bg); }
/* Rating column — a peer of price, so both can be read straight down
   the list. Right-aligned on the same baseline grid as the price. */
.store-rate {
  margin-left: auto; text-align: right; flex: none;
  display: flex; flex-direction: column; line-height: 1.25;
  min-width: 74px;
}
.store-rate b { font-size: var(--t-sm); font-weight: 700; color: var(--warn); font-variant-numeric: tabular-nums; }
.store-rate span { font-size: 10px; color: var(--ink-3); }
.store-rate .no-rate { font-size: var(--t-xs); color: var(--ink-4); font-style: italic; }

.store-price { font-size: 1.0625rem; font-weight: 700; flex: none; min-width: 92px; text-align: right; }

@media (max-width: 560px) {
  /* the row wraps rather than squeezing four columns onto a phone */
  .store-row { flex-wrap: wrap; }
  .store-info { flex: 1 1 100%; }
  .store-rate { margin-left: 0; text-align: left; min-width: 0; }
  .store-price { margin-left: auto; }
  .store-row .btn { flex: 1 1 100%; }
}
.store-row .btn, .store-listing .btn { flex: none; }

.modal-disclosure { font-size: var(--t-xs); color: var(--ink-3); margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--line); }

/* ============================================================
   11. PRICE HISTORY CHART
   ============================================================ */
.price-chart, .chart-box {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s4);
  margin-bottom: var(--s5);
  overflow-x: auto;                    /* never let a chart burst the layout */
}
.chart-title { font-size: var(--t-sm); font-weight: 600; margin-bottom: var(--s3); }
.chart-grid { stroke: var(--line); }
.chart-label { font-family: var(--mono); font-size: 10px; fill: var(--ink-3); }
.chart-legend { display: flex; gap: var(--s4); flex-wrap: wrap; margin-top: var(--s3); }
.legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-xs); color: var(--ink-3); }
.legend-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); flex: none; }
.chart-note { font-size: var(--t-xs); color: var(--ink-3); margin-top: var(--s2); }

.up { color: var(--rise); }
.down { color: var(--save); }
.flat { color: var(--ink-3); }

/* ============================================================
   12. ASK AI
   ============================================================ */
.ask-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 13px 18px; min-height: 46px;
  border-radius: var(--r-sm);
  background: var(--brand-50); border: 1px solid var(--brand-100); color: var(--brand);
  font-weight: 600; font-size: var(--t-sm);
  transition: background var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.ask-btn:hover { background: var(--brand-100); border-color: var(--brand-200); }
.spark { font-size: 1rem; }

.ask-panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s4);
  position: relative; overflow: hidden;
}
.ask-panel.is-loading::after {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 40%;
  background: linear-gradient(90deg, transparent, var(--brand-50), transparent);
  animation: askScan 1.1s linear infinite;
}
@keyframes askScan { from { transform: translateX(-100%); } to { transform: translateX(320%); } }

.ask-verdict { display: flex; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s3); }
.ask-pill {
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: .07em; text-transform: uppercase;
  padding: 5px 10px; border-radius: var(--r-pill);
  background: var(--raised); color: var(--ink-2);
}
.ask-buy     { background: var(--save-bg); color: var(--save); }
.ask-wait    { background: var(--warn-bg); color: var(--warn); }
.ask-steady  { background: var(--raised); color: var(--ink-2); }
.ask-neutral { background: var(--brand-50); color: var(--brand); }
.ask-unknown { background: var(--raised); color: var(--ink-3); }

.ask-headline { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.01em; }
.ask-detail { font-size: var(--t-sm); color: var(--ink-2); margin-top: 6px; }

.ask-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); gap: 1px; margin-top: var(--s4); background: var(--line); border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; }
.ask-fact { background: var(--surface); padding: var(--s3) var(--s2); text-align: center; }
.ask-fact b { display: block; font-size: 1rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.ask-fact span { font-size: 10px; color: var(--ink-3); text-transform: uppercase; letter-spacing: .05em; }

.ask-source { font-size: var(--t-xs); color: var(--ink-3); margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--line); }

/* ============================================================
   13. LOADING / EMPTY / ERROR
   ============================================================ */
.skeleton { pointer-events: none; }
.sk-thumb { aspect-ratio: 1 / 1; background: var(--raised); }
.sk-line { height: 11px; border-radius: var(--r-xs); background: var(--raised); margin-bottom: 8px; }
.sk-line.w70 { width: 70%; } .sk-line.w55 { width: 55%; } .sk-line.w40 { width: 40%; }
.sk-thumb, .sk-line {
  background: linear-gradient(90deg, var(--raised) 25%, var(--sunken) 37%, var(--raised) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* Empty and error states share one component — both need to say
   what happened and what to do next, and neither should look like
   a failure of the page. */
.empty {
  padding: var(--s7) var(--s4);
  text-align: center;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px dashed var(--line-2);
  border-radius: var(--r-md);
}
.empty b { display: block; color: var(--ink); font-size: 1.0625rem; margin-bottom: 6px; }
.empty .btn { margin-top: var(--s4); }

.feed-sentinel { display: flex; justify-content: center; margin-top: var(--s5); }
.drop-alert-close { margin-left: auto; color: var(--ink-3); }

/* ============================================================
   14. STEPS / STORES / FAQ / DISCLOSURE
   ============================================================ */
.steps { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); margin-top: var(--s5); }
.step { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s5); }
.step-num { font-family: var(--mono); font-size: var(--t-label); letter-spacing: .12em; color: var(--brand); margin-bottom: var(--s2); }
.step h3 { margin-bottom: var(--s2); }
.step p { font-size: var(--t-sm); color: var(--ink-2); }

.stores-strip { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s5); }
.store-chip { font-size: var(--t-sm); padding: 9px 14px; border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--line); }

.faq-list { margin-top: var(--s5); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; background: var(--surface); }
.faq-list details { border-bottom: 1px solid var(--line); }
.faq-list details:last-child { border-bottom: 0; }
.faq-list summary { padding: var(--s4); font-weight: 600; cursor: pointer; list-style: none; display: flex; justify-content: space-between; gap: var(--s3); align-items: center; }
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary::after { content: "+"; color: var(--ink-3); font-size: 1.25rem; flex: none; }
.faq-list details[open] summary::after { content: "−"; }
.faq-list p { padding: 0 var(--s4) var(--s4); font-size: var(--t-sm); color: var(--ink-2); }

.disclosure { max-width: var(--shell); margin: 0 auto; padding: 0 var(--s4) var(--s7); }
.disclosure-box, .unique-banner {
  background: var(--raised); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: var(--s4);
  font-size: var(--t-sm); color: var(--ink-2);
}
.unique-banner { padding: var(--s5); margin-bottom: var(--s5); }
.unique-banner-glow { display: none; }
.unique-badge { font-family: var(--mono); font-size: var(--t-label); letter-spacing: .12em; color: var(--brand); margin-bottom: var(--s2); }

/* ============================================================
   15. FOOTER
   ============================================================ */
.footer { border-top: 1px solid var(--line); background: var(--surface); margin-top: var(--s8); }
.footer-inner { display: grid; gap: var(--s5); padding-block: var(--s7); grid-template-columns: 1fr; }
@media (min-width: 640px) { .footer-inner { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .footer-inner { grid-template-columns: 2fr 1fr 1fr 1fr; } }
.footer h4 { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-3); margin-bottom: var(--s3); }
.footer a { display: block; padding: 5px 0; font-size: var(--t-sm); color: var(--ink-2); }
.footer a:hover { color: var(--brand); }
.footer .logo { display: inline-flex; padding: 0; }
.tg-foot { display: inline-flex !important; align-items: center; gap: 7px; }
.tg-foot svg { width: 16px; height: 16px; }
.footer-bottom {
  border-top: 1px solid var(--line);
  padding: var(--s4);
  display: flex; justify-content: space-between; gap: var(--s3); flex-wrap: wrap;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: .06em; color: var(--ink-3);
  max-width: var(--shell); margin-inline: auto;
}

/* ============================================================
   16. SHARED PAGE COMPONENTS
   Used by the pages that aren't the single-page app — cashback,
   reels, 404, the SSR templates and the admin tools. They live
   here rather than in each page's own <style> so the whole
   product stays one design system.
   ============================================================ */
.admin-wrap, .article {
  width: 100%; max-width: 940px;
  margin-inline: auto;
  padding: var(--s6) var(--s4) var(--s8);
}
.article { max-width: 760px; }

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s5);
  margin-bottom: var(--s4);
}
.panel h2 { margin-bottom: var(--s2); }
.panel > .hint { margin-bottom: var(--s4); }

.form-grid { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); margin-bottom: var(--s4); }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field label { font-size: var(--t-xs); font-weight: 600; color: var(--ink-2); }
.field input, .field textarea, .field select {
  padding: 11px 13px; min-height: 42px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); width: 100%;
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: 0; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-50);
}

.mono { font-family: var(--mono); }
.grow { flex: 1 1 auto; min-width: 0; }
.name { font-weight: 600; }
.meta { font-size: var(--t-xs); color: var(--ink-3); }

.btn-danger { background: var(--rise); color: var(--brand-ink); }
.btn-danger:hover { filter: brightness(.93); }

.admin-list { display: flex; flex-direction: column; gap: var(--s2); }
.admin-item {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  flex-wrap: wrap;
}

/* 404 */
.nav-cta { margin-left: auto; }
.hero-search { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s5); }
.hero-search input {
  flex: 1 1 260px; min-width: 0; padding: 13px 16px; min-height: 48px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
}
.hero-search input:focus { outline: 0; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-50); }

/* Blog article body — long-form reading measure. These two classes were
   the last unstyled ones on the site, which is why /blog fell back to
   browser-default serif with no layout at all. */
.back-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-2);
  margin-bottom: var(--s5);
}
.back-link:hover { color: var(--brand); }

.article-body { font-size: 1.0625rem; line-height: 1.75; color: var(--ink-2); }
.article-body > * + * { margin-top: var(--s4); }
.article-body h2 {
  font-size: var(--t-h2); color: var(--ink);
  margin-top: var(--s7); padding-top: var(--s5);
  border-top: 1px solid var(--line);
}
.article-body h3 { font-size: 1.125rem; color: var(--ink); margin-top: var(--s5); }
.article-body p { max-width: 68ch; }
.article-body ul, .article-body ol { padding-left: 1.25rem; max-width: 68ch; }
.article-body li + li { margin-top: var(--s2); }
.article-body a { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.article-body strong, .article-body b { color: var(--ink); font-weight: 600; }
.article-body blockquote {
  border-left: 3px solid var(--brand);
  padding: var(--s2) 0 var(--s2) var(--s4);
  color: var(--ink-2); font-style: italic;
}
.article-body table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); display: block; overflow-x: auto; }
.article-body th, .article-body td { padding: 10px 12px; border-bottom: 1px solid var(--line); text-align: left; }
.article-body th { font-weight: 600; color: var(--ink); background: var(--raised); }
.article-body img { border-radius: var(--r-md); }
.article-body code { font-family: var(--mono); font-size: .9em; background: var(--raised); padding: 2px 6px; border-radius: var(--r-xs); }

/* SSR SEO landing pages */
.seo-crumbs { font-size: var(--t-xs); color: var(--ink-3); margin-bottom: var(--s3); display: flex; gap: 6px; flex-wrap: wrap; }
.seo-crumbs a:hover { color: var(--brand); }
.seo-h1 { font-size: var(--t-h1); font-weight: 700; letter-spacing: -.03em; }
.seo-updated { font-family: var(--mono); font-size: var(--t-label); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); margin-top: var(--s2); }

/* ============================================================
   17. MOTION PREFERENCES
   Everything above is decoration on top of a working page; if the
   reader would rather it held still, it holds still.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .card:hover, .deal-card:hover, .tg-cta:hover, .unique-cta:hover { transform: none; }
}

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

   The star strip is two copies of the same five-star row, one grey
   and one gold, with the gold one clipped to a percentage width.
   That is the only way to draw a half star that stays a half star
   at every font size — the ★ character has no half, and rounding
   4.6 up to five stars on a filter chip would misstate the very
   thing the filter exists to be precise about.
   ============================================================ */
.rating-row { align-items: center; }

.chip-rate {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: var(--r-pill, 999px);
  border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-2); font-size: 13px; font-weight: 600;
  cursor: pointer; white-space: nowrap; line-height: 1;
  transition: border-color .15s, background .15s, color .15s;
}
.chip-rate:hover { border-color: var(--line-2); color: var(--ink); }
.chip-rate.active { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }

.stars-strip { position: relative; display: inline-block; height: 13px; line-height: 1; }
.stars-strip .base,
.stars-strip .fill { display: block; font-size: 13px; line-height: 1; letter-spacing: 1px; }
.stars-strip .base { color: var(--line-2); }
.stars-strip .fill {
  position: absolute; inset: 0; overflow: hidden; white-space: nowrap;
  color: #F5A623;                     /* the same amber on both themes — a
                                         star that changes colour with the
                                         interface stops reading as a star */
}
.chip-rate.active .stars-strip .base { color: rgba(255, 255, 255, .42); }
.chip-rate.active .stars-strip .fill { color: #FFD466; }

/* The two chips that are not a star level. They must not look like a
   low rating — "not yet rated" is an absence of information, not a bad
   review, and a shopper who reads it as one skips 21,000 products. */
.chip-rate.chip-plain { font-style: normal; }
.chip-rate.chip-plain .dotm {
  width: 6px; height: 6px; border-radius: 50%; background: var(--ink-3, var(--ink-2));
  display: inline-block; opacity: .5;
}

.rating-note {
  margin: 9px 2px 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.55;
  max-width: 62ch;
}
.rating-note b { color: var(--ink); font-weight: 700; }

/* Card ratings: the count is what tells a shopper whether the stars
   mean anything, so it is never dropped on small screens. */
.card-rating .thin-flag {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: .2px;
  background: var(--warn-bg, #FFF4E5); color: var(--warn, #A15C00);
  border: 1px solid var(--warn-line, #FFE0B2);
}

/* ============================================================
   BLOG / SUB-PAGE LOGO

   The blog wore a different mark from the rest of the site — a "7"
   typed into a gradient box, from before the real logo existed. Same
   SVG as the homepage now, so the two pages read as one product.
   ============================================================ */
.logo-img {
  width: 30px; height: 30px; flex: none; display: block;
  border-radius: 7px;
}
.logo { display: inline-flex; align-items: center; gap: 9px; }

/* ============================================================
   ACTIVE FILTERS + EMPTY STATE

   A filter you cannot see is a filter you cannot undo. Without these
   chips the usual outcome is a shopper who set 4.5+ three screens ago
   deciding the site has no stock.
   ============================================================ */
.active-filters {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0 2px;
}
.active-filters:empty { display: none; }
.af-label { font-size: 12.5px; font-weight: 700; color: var(--ink-2); margin-right: 2px; }
.af-chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 6px 10px 6px 12px;
  border-radius: var(--r-pill, 999px); background: var(--brand-50);
  border: 1px solid var(--brand-200); color: var(--brand-700);
  font-size: 12.5px; font-weight: 700; line-height: 1;
}
.af-chip button {
  display: grid; place-items: center; width: 17px; height: 17px; border-radius: 50%;
  background: transparent; border: 0; cursor: pointer; color: inherit;
  font-size: 15px; line-height: 1; opacity: .62; padding: 0;
}
.af-chip button:hover { opacity: 1; background: rgba(0, 0, 0, .07); }
.af-clear {
  font-size: 12.5px; font-weight: 700; color: var(--ink-2); background: none;
  border: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
  padding: 6px 4px;
}
.af-clear:hover { color: var(--brand-600); }

.empty-state {
  border: 1.5px dashed var(--line-2); border-radius: var(--r-md, 14px);
  padding: 34px 24px; text-align: center; margin-top: 6px;
}
.empty-state h3 { font-size: 1.05rem; font-weight: 800; margin: 0 0 6px; color: var(--ink); }
.empty-state p { font-size: 14px; color: var(--ink-2); margin: 0 auto 16px; max-width: 46ch; }
.empty-state ul {
  list-style: none; padding: 0; margin: 0 auto 18px; max-width: 40ch;
  text-align: left; display: inline-block;
}
.empty-state li {
  font-size: 13.5px; color: var(--ink-2); padding: 4px 0 4px 20px; position: relative;
}
.empty-state li::before {
  content: "\2192"; position: absolute; left: 0; color: var(--brand-600); font-weight: 700;
}
.empty-state .btn { margin-top: 2px; }

/* ============================================================
   VALUE SCORE, INSIGHTS, DECISION MODE AND COMPARE

   The score chip is a button, not a badge. A number on a shopping
   card that cannot be interrogated is indistinguishable from a paid
   ranking — which is what shoppers assume every score is — so the
   reasons are one tap away, and already in the markup rather than
   fetched when asked for.
   ============================================================ */
.vscore {
  position: absolute; left: 8px; bottom: 8px; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: 12px; border: 0; cursor: pointer;
  line-height: 1; color: #fff; box-shadow: 0 4px 12px rgba(20, 19, 43, .22);
  transition: transform .14s;
}
.vscore:hover { transform: translateY(-1px) scale(1.04); }
.vscore b { font-family: var(--mono, ui-monospace, monospace); font-size: 15px; font-weight: 800; }
.vscore span { font-size: 8px; text-transform: uppercase; letter-spacing: .6px; opacity: .85; margin-top: 2px; }
.vs-hi  { background: linear-gradient(140deg, #0E9F6E, #057A55); }
.vs-mid { background: linear-gradient(140deg, #7C4DFF, #5B7CFA); }
.vs-lo  { background: linear-gradient(140deg, #8A8AA3, #6B6B85); }

.vdetail {
  margin: 8px 0 2px; padding: 10px 11px; border-radius: 10px;
  background: var(--raised); border: 1px solid var(--line);
}
.vdetail h4 {
  margin: 0 0 7px; font-size: 11.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .5px; color: var(--ink-2);
}
.vdetail ul { list-style: none; margin: 0 0 7px; padding: 0; }
.vdetail li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: 12.5px; padding: 3px 0; color: var(--ink-2);
}
.vdetail li i {
  font-style: normal; font-family: var(--mono, monospace); font-size: 11px;
  color: var(--ink-3, var(--ink-2)); white-space: nowrap;
}
.vdetail .vd-good span::before { content: "\2713 "; color: var(--save, #0E9F6E); font-weight: 700; }
.vdetail .vd-weak span::before { content: "\00b7 "; color: var(--ink-3, var(--ink-2)); font-weight: 700; }
.vdetail p { margin: 0; font-size: 11.5px; color: var(--ink-3, var(--ink-2)); line-height: 1.5; }

.ins { display: flex; flex-wrap: wrap; gap: 5px; margin: 6px 0 2px; }
.ins-b {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px;
  border-radius: 999px; font-size: 10.5px; font-weight: 700; line-height: 1.4;
  background: var(--brand-50); color: var(--brand-700); border: 1px solid var(--brand-200);
}
.ins-b i { font-style: normal; font-size: 10px; }
.ins-warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-line); }

.deal-save { font-size: 12px; font-weight: 700; color: var(--save, #0E9F6E); margin-top: 2px; }

/* ---------- compare tick ---------- */
.cmp-tick { position: absolute; top: 8px; left: 8px; z-index: 3; cursor: pointer; }
.cmp-tick input { position: absolute; opacity: 0; width: 0; height: 0; }
.cmp-tick span {
  display: block; width: 22px; height: 22px; border-radius: 7px;
  background: rgba(255, 255, 255, .92); border: 1.5px solid var(--line-2);
  box-shadow: 0 2px 6px rgba(20, 19, 43, .14); transition: .14s;
}
.cmp-tick input:checked + span { background: var(--brand); border-color: var(--brand); }
.cmp-tick input:checked + span::after {
  content: "\2713"; display: block; text-align: center; color: #fff;
  font-size: 14px; font-weight: 800; line-height: 20px;
}
.cmp-tick input:focus-visible + span { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ---------- decision mode ---------- */
.dm { margin: 18px 0 6px; }
.dm h3 { font-size: 1.02rem; font-weight: 800; margin: 0 0 10px; letter-spacing: -.3px; }
.dm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: 9px; }
.dm-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 12px 13px; border-radius: 13px; text-align: left; cursor: pointer;
  background: var(--surface); border: 1.5px solid var(--line); transition: .15s;
}
.dm-card:hover { border-color: var(--brand-200); transform: translateY(-1px); }
.dm-card.active { border-color: var(--brand); background: var(--brand-50); }
.dm-card i { font-style: normal; font-size: 15px; color: var(--brand-600); margin-bottom: 3px; }
.dm-card b { font-size: 13.5px; font-weight: 800; color: var(--ink); }
.dm-card span { font-size: 11.5px; color: var(--ink-2); line-height: 1.45; }

/* ---------- compare tray ---------- */
.cmp-bar {
  position: fixed; left: 50%; transform: translateX(-50%); z-index: 60;
  bottom: calc(70px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; gap: 10px; max-width: min(94vw, 780px);
  padding: 10px 12px; border-radius: 16px;
  background: var(--surface); border: 1px solid var(--line-2);
  box-shadow: 0 10px 34px rgba(20, 19, 43, .2);
}
@media (min-width: 900px) { .cmp-bar { bottom: 20px; } }
.cmp-items { display: flex; gap: 7px; overflow-x: auto; flex: 1; scrollbar-width: none; }
.cmp-items::-webkit-scrollbar { display: none; }
.cmp-pill {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 6px 5px 5px;
  border-radius: 999px; background: var(--raised); border: 1px solid var(--line);
  font-size: 11.5px; font-weight: 600; white-space: nowrap; color: var(--ink-2);
}
.cmp-pill img { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; }
.cmp-pill button {
  border: 0; background: none; cursor: pointer; font-size: 14px;
  line-height: 1; color: var(--ink-3, var(--ink-2)); padding: 0 2px;
}
.cmp-pill button:hover { color: var(--bad, #D33); }
.cmp-clear {
  border: 0; background: none; cursor: pointer; font-size: 12.5px;
  font-weight: 700; color: var(--ink-2); text-decoration: underline; text-underline-offset: 3px;
}
.cmp-msg {
  position: absolute; left: 12px; right: 12px; top: -34px; padding: 6px 12px;
  border-radius: 10px; background: var(--ink); color: var(--page);
  font-size: 12px; font-weight: 600; text-align: center;
  opacity: 0; pointer-events: none; transition: opacity .2s;
}
.cmp-msg.show { opacity: 1; }

/* ---------- comparison modal ---------- */
.cmp-modal {
  position: fixed; inset: 0; z-index: 90; display: grid; place-items: center;
  background: rgba(14, 13, 30, .55); padding: 16px;
}
.cmp-sheet {
  width: min(94vw, 900px); max-height: 88vh; display: flex; flex-direction: column;
  background: var(--surface); border-radius: 18px; overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .3);
}
.cmp-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 15px 18px; border-bottom: 1px solid var(--line);
}
.cmp-head h3 { margin: 0; font-size: 1.05rem; font-weight: 800; }
.cmp-close {
  border: 0; background: none; font-size: 26px; line-height: 1; cursor: pointer;
  color: var(--ink-2); padding: 0 4px;
}
.cmp-close:hover { color: var(--ink); }
/* The table scrolls inside its own box: four columns will not fit a phone,
   and a page that scrolls sideways is a page that feels broken. */
.cmp-scroll { overflow: auto; padding: 4px 18px 14px; }
.cmp-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.cmp-table th, .cmp-table td {
  padding: 10px 11px; border-bottom: 1px solid var(--line);
  text-align: left; vertical-align: middle;
}
.cmp-table thead th {
  position: sticky; top: 0; background: var(--surface); z-index: 1; min-width: 130px;
}
.cmp-table thead img { display: block; width: 46px; height: 46px; object-fit: contain; margin-bottom: 6px; }
.cmp-table thead span { font-size: 12px; font-weight: 700; line-height: 1.35; display: block; }
.cmp-table tbody th {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--ink-2); font-weight: 800; white-space: nowrap;
}
.cmp-win { background: var(--save-bg, #E8F7F0); font-weight: 800; color: var(--ink); border-radius: 6px; }
.cmp-foot {
  margin: 0; padding: 12px 18px 16px; font-size: 11.5px; color: var(--ink-2);
  border-top: 1px solid var(--line); line-height: 1.5;
}

/* Keyboard users must be able to see where they are. The default outline
   is removed by resets far more often than it is replaced. */
.chip-rate:focus-visible, .dm-card:focus-visible, .vscore:focus-visible,
.af-chip button:focus-visible, .cmp-close:focus-visible, .hs-btn:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 2px;
}

/* ============================================================
   FILTER PANEL

   Six stacked chip rows pushed the products below the fold on every
   screen — the controls ended up more prominent than the thing being
   controlled. Wide screens get a column beside the grid. Phones get a
   sheet behind one button, because a permanent panel would eat the
   entire first screen on a 375px display.
   ============================================================ */
.browse-cols { display: block; }
.results { min-width: 0; }        /* or a wide product title stretches the grid */

/* ---------- the phone trigger ---------- */
.filters-open {
  display: inline-flex; align-items: center; gap: 8px; margin: 14px 0 4px;
  padding: 10px 16px; border-radius: var(--r-pill, 999px); cursor: pointer;
  background: var(--surface); border: 1.5px solid var(--line-2); color: var(--ink);
  font-size: 13.5px; font-weight: 700;
}
.filters-open svg { width: 16px; height: 16px; }
.filters-open b {
  font-family: var(--mono, monospace); font-size: 11.5px; font-weight: 800;
  background: var(--brand); color: var(--brand-ink); border-radius: 999px;
  padding: 2px 7px; line-height: 1.4;
}
.filters-open b:empty { display: none; }
.filters-head, .filters-foot { display: none; }

/* ---------- phone: a sheet ---------- */
@media (max-width: 1023px) {
  .filters {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
    max-height: 82vh; display: flex; flex-direction: column;
    background: var(--surface); border-radius: 20px 20px 0 0;
    box-shadow: 0 -14px 44px rgba(20, 19, 43, .26);
    transform: translateY(100%); transition: transform .24s ease;
    visibility: hidden;
  }
  .filters.open { transform: translateY(0); visibility: visible; }
  .filters-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 15px 18px 10px; border-bottom: 1px solid var(--line); flex: none;
  }
  .filters-head h3 { margin: 0; font-size: 1.05rem; font-weight: 800; }
  .filters-close {
    border: 0; background: none; font-size: 26px; line-height: 1; cursor: pointer;
    color: var(--ink-2); padding: 0 4px;
  }
  .filters-body { overflow-y: auto; padding: 4px 18px 8px; flex: 1; }
  .filters-foot {
    display: block; padding: 12px 18px calc(16px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--line); flex: none;
  }
  .filters-foot .btn { width: 100%; }
  .filters-scrim {
    position: fixed; inset: 0; z-index: 94; background: rgba(14, 13, 30, .5);
    opacity: 0; pointer-events: none; transition: opacity .24s;
  }
  .filters-scrim.open { opacity: 1; pointer-events: auto; }
}

/* ---------- desktop: a column ---------- */
@media (min-width: 1024px) {
  .filters-open { display: none; }
  .browse-cols {
    display: grid; grid-template-columns: 246px minmax(0, 1fr); gap: 26px;
    align-items: start;
  }
  .filters {
    position: sticky; top: 14px; max-height: calc(100vh - 28px); overflow-y: auto;
    padding: 4px 2px 8px; scrollbar-width: thin;
  }
  .filters .chips-row { flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
  .filters .chip-cat, .filters .chip-rate { font-size: 12px; padding: 6px 10px; }
  .filters .af-label {
    display: block; width: 100%; margin: 2px 0 6px;
    font-size: 11px; text-transform: uppercase; letter-spacing: .6px;
  }
  .filters .rating-note { font-size: 11.5px; }
}
