/* =====================================================================
   PriceDrop.me — "The Deal Ledger"
   Editorial, paper-warm, monospace-anchored. Trust through restraint.
   ===================================================================== */

/* Fonts are loaded via a <link> in the HTML head (parallel with this stylesheet) — an @import
   here would serialize the fetch chain (html -> css -> font css -> woff2) and block first paint. */

:root {
  /* Paper palette */
  --paper:        #f5f0e6;
  --paper-deep:   #ece5d6;
  --paper-edge:   #e2dac6;
  --ink:          #14110d;
  --ink-soft:     #2a2620;
  --ink-mid:      #6b6760;
  --ink-faint:    #9a958b;
  --rule:         #1a1814;
  --rule-soft:    rgba(20,17,13,.12);
  --rule-hair:    rgba(20,17,13,.22);

  /* Single bold accent — used sparingly so it stays loud */
  --signal:       #c8281e;
  --signal-deep:  #9a1a14;
  --signal-soft:  rgba(200,40,30,.08);

  /* Secondary accent — for the "below typical" / trust signals */
  --gold:         #a17500;
  --gold-soft:    rgba(161,117,0,.10);

  /* Type */
  --serif:  'Instrument Serif', 'Iowan Old Style', 'Apple Garamond', Georgia, serif;
  --mono:   'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --sans:   'Inter', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;

  /* Rhythm */
  --col-max: 1240px;
  --col-text: 720px;
  --gutter: clamp(1rem, 3vw, 2rem);
  --rule-w: 1px;

  /* Shadows — editorial uses paper-shadow, not glow */
  --paper-lift: 0 1px 0 rgba(0,0,0,.04), 0 2px 6px -2px rgba(20,17,13,.06);
  --paper-lift-hover: 0 1px 0 rgba(0,0,0,.06), 0 14px 32px -16px rgba(20,17,13,.18);
}

/* ─── Reset / base ─── */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--paper);
  /* Subtle paper grain — purely decorative; falls back to flat color */
  background-image:
    radial-gradient(rgba(20,17,13,.025) 1px, transparent 1px),
    radial-gradient(rgba(20,17,13,.018) 1px, transparent 1px);
  background-size: 3px 3px, 7px 7px;
  background-position: 0 0, 1px 2px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "ss01", "cv11";
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }
button { font: inherit; color: inherit; cursor: pointer; }
a { color: inherit; }

/* ─── Overflow guard ───
   A third-party embed once rendered a fixed 1170px-wide iframe inside the deal grid, which made
   the whole document 1186px wide on a 375px phone and let every section scroll sideways. The ad
   is gone, but replaceable media must never be able to do that again: cap the intrinsic width of
   anything embedded, then clip (not `hidden` — `clip` doesn't create a scroll container, so the
   sticky filter bar keeps working) whatever still manages to stick out. */
img, svg, video, canvas, iframe, embed, object, table, pre { max-width: 100%; }
iframe, embed, object { max-width: 100% !important; }
body { overflow-x: clip; }

.container {
  width: 100%;
  max-width: var(--col-max);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* ─── Selection / focus ─── */
::selection { background: var(--ink); color: var(--paper); }
:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }

/* =====================================================================
   HEADER — newspaper nameplate
   ===================================================================== */
.app-header {
  position: relative;
  padding: clamp(.7rem, 1.6vw, 1rem) 0 0;
  border-bottom: var(--rule-w) solid var(--rule);
  background: var(--paper);
}
.app-header::before {
  /* hairline above the bottom rule = double-rule masthead trick */
  content: '';
  position: absolute; left: 0; right: 0; bottom: 4px;
  height: 1px; background: var(--rule); opacity: .5;
}

.header-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  padding-bottom: .55rem;
}

/* Logo / nameplate */
.site-logo { margin: 0; }

/* Homepage H1. The logo is no longer an <h1>, so this carries the page's heading weight for
   crawlers while staying visually secondary to the masthead. */
.home-h1 {
  /* Display serif, matching "Top Deals" / "Viral Finds" / the logo. Defaulting to the sans
     stack made the page's only H1 the one element that didn't belong to the masthead. */
  font-family: var(--serif);
  font-weight: 400;
  margin: 1rem 0 .3rem;
  font-size: clamp(1.4rem, 3.2vw, 2.1rem);
  line-height: 1.12;
  letter-spacing: -.015em;
}
.site-logo-link {
  display: inline-flex; align-items: baseline; gap: .55rem;
  text-decoration: none; color: inherit;
}
.logo-icon {
  display: inline-grid; place-items: center;
  width: 30px; height: 30px;
  align-self: center;
  background: var(--ink); color: var(--paper);
  border-radius: 2px;
  position: relative;
}
.logo-icon::after {
  /* corner notch — subtle stamp / mark */
  content: ''; position: absolute; top: -3px; right: -3px;
  width: 8px; height: 8px;
  background: var(--signal);
  border-radius: 50%;
}
.logo-icon svg { width: 18px; height: 18px; }
.logo-icon svg rect { fill: transparent; }
.logo-icon svg path { stroke: var(--paper); }

.logo-text {
  font-family: var(--serif);
  font-size: clamp(1.4rem, 2.6vw, 1.85rem);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -.01em;
  line-height: 1;
}
.logo-highlight {
  color: var(--signal);
}
.logo-dot {
  font-family: var(--mono);
  font-style: normal;
  font-size: .42em;
  font-weight: 500;
  letter-spacing: .04em;
  vertical-align: .55em;
  margin-left: .15em;
  color: var(--ink-mid);
}

/* Dateline — sits beneath logo, gives the masthead its newsroom feel */
.masthead-dateline {
  display: flex; align-items: center; gap: .9rem;
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-mid);
  margin-top: .35rem;
  padding-bottom: .55rem;
  border-bottom: var(--rule-w) solid var(--rule-soft);
  flex-wrap: wrap;
}
.masthead-dateline strong {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.15rem;
  letter-spacing: -.01em;
  color: var(--ink);
  text-transform: none;
}
.masthead-dateline strong.signal { color: var(--signal); }
.masthead-dateline > span { display: inline-flex; align-items: center; gap: .4rem; }
.masthead-dateline .pulse {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--signal);
  animation: pulse 1.6s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: .35; transform: scale(.85); }
  50%      { opacity: 1;   transform: scale(1.1); }
}
.masthead-dateline .sep { color: var(--ink-faint); }

/* Header actions (market switcher + social menu) */
.header-actions { display: inline-flex; align-items: center; gap: .75rem; }

/* Market switcher */
.market-switcher { display: inline-flex; align-items: center; }
.market-switcher select {
  appearance: none; -webkit-appearance: none;
  padding: .55rem .9rem;
  background: transparent;
  border: var(--rule-w) solid var(--rule);
  border-radius: 0;
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink);
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23333'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .6rem center;
  padding-right: 1.8rem;
}
.market-switcher select:hover { background-color: var(--ink); color: var(--paper); }

/* Social menu — restrained dropdown */
.social-menu { position: relative; }
.social-menu-btn {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .55rem .9rem;
  background: transparent;
  border: var(--rule-w) solid var(--rule);
  border-radius: 0;
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink);
  transition: background .18s ease, color .18s ease;
}
.social-menu-btn:hover { background: var(--ink); color: var(--paper); }
.social-menu-btn svg { width: 14px; height: 14px; }
.social-menu-dropdown[hidden] { display: none; }
.social-menu-dropdown {
  position: absolute; right: 0; top: calc(100% + 8px);
  display: flex; flex-direction: column;
  background: var(--paper);
  border: var(--rule-w) solid var(--rule);
  min-width: 180px;
  padding: .35rem 0;
  z-index: 50;
  box-shadow: 0 14px 32px -16px rgba(20,17,13,.25);
}
.social-menu-dropdown a {
  display: flex; align-items: center; gap: .65rem;
  padding: .55rem 1rem;
  text-decoration: none;
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .04em;
  color: var(--ink-soft);
  transition: background .15s, color .15s;
}
.social-menu-dropdown a:hover { background: var(--ink); color: var(--paper); }
.social-menu-dropdown a svg { width: 14px; height: 14px; flex-shrink: 0; }

/* =====================================================================
   FILTERS BAR — slim ledger row beneath masthead
   ===================================================================== */
.filters-bar {
  display: grid;
  /* The slider is the only control whose usability depends on track LENGTH — the selects
     just need to fit their label. At 1.4fr it got ~215px of track for a 0-90% range
     (~2.4px per point), which is too fine to aim. minmax() gives it a floor so it keeps a
     usable track while the selects absorb the difference. */
  grid-template-columns: 1.3fr 1fr 1fr 1.9fr 1fr;
  gap: 0;
  /* Constrain to the same width as the rest of the page content. Auto-margins center it,
     gutter padding keeps the side rules off the screen edge — same horizontal frame as
     `.container` without changing the global container itself. */
  width: 100%;
  max-width: var(--col-max);
  margin: 0 auto;
  padding: 0 var(--gutter);
  border-top: var(--rule-w) solid var(--rule);
  border-bottom: var(--rule-w) solid var(--rule);
  background: var(--paper);
  position: sticky; top: 0; z-index: 20;
  backdrop-filter: saturate(140%) blur(8px);
  background: rgba(245,240,230,.92);
}
/* The four filter controls live in a wrapper so they can collapse together on small screens.
   On desktop the wrapper is `display: contents`, so its children stay grid items of .filters-bar
   exactly as before — the cell rule below therefore skips the wrapper and targets them directly. */
.filters-bar > *:not(.filter-controls),
.filter-controls > * {
  border-right: var(--rule-w) solid var(--rule-soft);
  padding: .85rem 1rem;
  min-height: 56px;
  display: flex; align-items: center; gap: .55rem;
}
.filters-bar > *:not(.filter-controls):last-child,
.filter-controls > *:last-child { border-right: 0; }
/* After the cell rule above, so the wrapper itself stays layout-transparent. */
.filters-bar > .filter-controls { display: contents; }

/* Mobile-only drawer trigger (see the max-width: 720px block below). The child selector keeps
   this ahead of the generic `.filters-bar > *` cell rule, which sets display: flex. */
.filters-bar > .filters-toggle { display: none; }
.filters-toggle {
  justify-content: center;
  background: transparent;
  border: 0;
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
.filters-toggle svg { flex-shrink: 0; }
.filters-toggle::after {
  content: '+';
  font-family: var(--mono);
  font-size: .95rem;
  line-height: 1;
  color: var(--ink-mid);
}
.filters-bar.filters-open .filters-toggle::after { content: '–'; }
.filters-bar.filters-open .filters-toggle { color: var(--signal); }
.filters-toggle:focus-visible { outline: 2px solid var(--signal); outline-offset: -2px; }

.search-field {
  position: relative; gap: .55rem;
}
.search-icon { color: var(--ink-mid); flex-shrink: 0; }
#search {
  flex: 1; min-width: 0;
  background: transparent; border: 0; outline: 0;
  font-family: var(--mono);
  font-size: .85rem;
  color: var(--ink);
  letter-spacing: .01em;
  padding: 0;
}
#search::placeholder { color: var(--ink-faint); font-style: italic; font-family: var(--serif); font-size: 1rem; }
.search-clear-btn {
  background: transparent; border: 0; color: var(--ink-mid);
  font-size: 1.25rem; line-height: 1; padding: 0 .25rem;
  border-radius: 50%; width: 22px; height: 22px;
  display: inline-grid; place-items: center;
}
.search-clear-btn:hover { background: var(--ink); color: var(--paper); }

.filter-group {
  font-family: var(--mono); font-size: .78rem;
}
.filter-group select {
  flex: 1;
  appearance: none;
  background: transparent;
  border: 0; outline: 0;
  padding: 0 1.2rem 0 0;
  font-family: var(--mono);
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--ink);
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-mid) 50%), linear-gradient(135deg, var(--ink-mid) 50%, transparent 50%);
  background-position: calc(100% - 9px) 52%, calc(100% - 4px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

/* Grid items default to min-width:auto, so the two selects refused to shrink below their
   intrinsic width — at a 1009px viewport they claimed ~500px between them and the slider was
   left with a 78px track, which is unusable for a 0-90% range. Letting every cell shrink hands
   the distribution back to the fr ratios above, where the slider gets the largest share because
   it's the only control whose usability depends on track length. Deliberately no px floor here:
   a minmax() floor overflows the page at ~1000-1200px, which is what it replaced. */
.filters-bar > *,
.filter-controls > * { min-width: 0; }
.filters-bar select { min-width: 0; width: 100%; }

.filter-group-slider { flex-direction: column; align-items: stretch !important; gap: .35rem !important; padding-top: .5rem !important; padding-bottom: .5rem !important; }
.slider-label {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-mid);
  display: flex; justify-content: space-between;
}
.slider-label span { color: var(--signal); font-weight: 600; }
#drop-slider {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 2px;
  background: var(--rule); outline: 0;
  border-radius: 0;
}
#drop-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px;
  background: var(--signal);
  border-radius: 0;
  border: 2px solid var(--paper);
  box-shadow: 0 0 0 1px var(--signal);
  cursor: pointer;
}
#drop-slider::-moz-range-thumb {
  width: 14px; height: 14px;
  background: var(--signal);
  border-radius: 0;
  border: 2px solid var(--paper);
  box-shadow: 0 0 0 1px var(--signal);
  cursor: pointer;
}

.filter-group-price { gap: .35rem !important; }
.filter-group-price input {
  width: 100%; min-width: 0;
  background: transparent; border: 0;
  border-bottom: 1px solid var(--rule-soft);
  outline: 0;
  font-family: var(--mono);
  font-size: .82rem;
  color: var(--ink);
  padding: .25rem 0;
}
.filter-group-price input:focus { border-bottom-color: var(--signal); }
.filter-group-price input::placeholder { color: var(--ink-faint); }
.price-sep { color: var(--ink-faint); font-family: var(--mono); }

@media (max-width: 1000px) {
  .filters-bar { grid-template-columns: 1fr 1fr; }
  .filters-bar > *:not(.filter-controls),
  .filter-controls > * { border-bottom: var(--rule-w) solid var(--rule-soft); }
}

/* ─── Collapsed filters (small screens) ───
   Stacked, the five controls were ~300px of chrome: on a 390x844 phone the first deal card
   started below the fold, so the page opened on filters instead of on deals. Search stays out
   in the open (it's the control people actually reach for); the rest fold into a drawer. */
@media (max-width: 720px) {
  .filters-bar { grid-template-columns: minmax(0, 1fr) auto; }
  .filters-bar > .search-field { border-right: var(--rule-w) solid var(--rule-soft); border-bottom: 0; }
  .filters-bar > .filters-toggle { display: inline-flex; border-right: 0; border-bottom: 0; padding: .7rem 1rem; min-height: 48px; }
  .filters-bar > .filter-controls { display: none; }
  .filters-bar.filters-open > .filter-controls {
    display: grid;
    grid-template-columns: 1fr;
    grid-column: 1 / -1;
    border-top: var(--rule-w) solid var(--rule-soft);
  }
  .filters-bar.filters-open > .filter-controls > * { border-right: 0; min-height: 48px; }
  .filters-bar > .search-field { min-height: 48px; }
}

/* ─── Docked filter bar ───
   app.js adds body.filters-docked (and sets --filters-h to the bar's in-flow height) once the
   header scrolls out of view, so search/filtering stays reachable deep in the list. The header
   gets the bar's height back as padding so the content below never jumps. */
body.filters-docked .app-header { padding-bottom: var(--filters-h, 0px); }
body.filters-docked .filters-bar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 90;
  margin: 0 auto;
  background: var(--paper);
  border-top: 0;
  box-shadow: 0 3px 14px rgba(20, 17, 13, .14);
  animation: dock-slide .18s ease-out;
}
@keyframes dock-slide {
  from { transform: translateY(-100%); }
  to   { transform: translateY(0); }
}
/* On narrow screens the full filter grid stacks several rows tall — docked, it would cover
   half the viewport. Collapse to just the search field (the filter the user reaches for most). */
@media (max-width: 900px) {
  body.filters-docked .filters-bar > *:not(.search-field):not(.filters-toggle) { display: none; }
  body.filters-docked .filters-bar > .search-field { border-bottom: 0; }
}
/* …but the drawer trigger stays, and opening it still has to win over the rule above. */
@media (max-width: 720px) {
  body.filters-docked .filters-bar > .filters-toggle { display: inline-flex; }
  body.filters-docked .filters-bar.filters-open > .filter-controls { display: grid; }
}
@media (min-width: 721px) and (max-width: 900px) {
  body.filters-docked .filters-bar > .search-field { border-right: 0; }
}
@media (prefers-reduced-motion: reduce) {
  body.filters-docked .filters-bar { animation: none; }
}

.active-filters {
  padding: .65rem var(--gutter);
  display: flex; flex-wrap: wrap; gap: .5rem;
  border-bottom: var(--rule-w) solid var(--rule-soft);
}
.active-filter {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .25rem .6rem;
  background: var(--ink); color: var(--paper);
  font-family: var(--mono); font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.active-filter button {
  background: transparent; border: 0; color: inherit;
  padding: 0; line-height: 1; font-size: 1rem;
}
.clear-all-btn {
  margin-left: auto;
  background: transparent;
  border: var(--rule-w) solid var(--rule);
  padding: .25rem .65rem;
  font-family: var(--mono); font-size: .68rem;
  letter-spacing: .12em; text-transform: uppercase;
}
.clear-all-btn:hover { background: var(--ink); color: var(--paper); }

.results-summary {
  padding: .75rem var(--gutter);
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-mid);
  display: flex; align-items: center; gap: .6rem;
  border-bottom: var(--rule-w) solid var(--rule-soft);
  background: var(--paper);
}
/* Mobile: trim the ledger chrome between the filter bar and the first card. */
@media (max-width: 720px) {
  .results-summary { padding: .5rem var(--gutter); font-size: .66rem; }
  .active-filters { padding: .45rem var(--gutter); }
}

.results-summary::before {
  content: '§';
  font-family: var(--serif);
  font-size: 1.4rem;
  color: var(--signal);
  font-style: italic;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1;
}

/* =====================================================================
   SECTION HEADINGS — hairline rule + italic display
   ===================================================================== */
.section-heading,
.featured-heading,
.seasonal-heading,
.faq-heading {
  font-family: var(--serif);
  font-size: clamp(1.7rem, 3.6vw, 2.4rem);
  font-style: italic;
  font-weight: 400;
  color: var(--ink);
  margin: clamp(2rem, 4vw, 3rem) 0 .25rem;
  letter-spacing: -.015em;
  line-height: 1;
  display: flex; align-items: baseline; gap: .9rem;
}
.featured-heading::before,
.seasonal-heading::before,
.faq-heading::before {
  content: attr(data-num);
  font-family: var(--mono); font-style: normal;
  font-size: .65rem; font-weight: 600;
  letter-spacing: .2em;
  color: var(--signal);
  align-self: center;
  padding: .25rem .55rem;
  border: 1px solid var(--signal);
  text-transform: uppercase;
}
.featured-heading::before { content: '№ 01 · TOP DEALS'; }
.seasonal-heading::before { content: '№ 02 · SEASONAL'; }
.faq-heading::before { content: '§ FAQ'; }
.section-eyebrow {
  display: block;
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-mid);
  margin: 0 0 .65rem;
  padding-bottom: .65rem;
  border-bottom: var(--rule-w) solid var(--rule-soft);
}
.section-eyebrow .em { color: var(--signal); font-weight: 600; }

.featured-deals,
.seasonal-picks {
  margin-top: clamp(1.5rem, 3vw, 2.4rem);
}
.featured-deals { padding-bottom: 1rem; }

/* =====================================================================
   PRODUCT CARD — wide, ledger-line, number-dominant
   ===================================================================== */
.products-grid,
.featured-grid,
.seasonal-grid {
  display: grid;
  /* min(360px, 100%) so a track can never be wider than its container — a fixed 360px
     minimum overflowed the page by ~17px at 375px viewport. */
  grid-template-columns: repeat(auto-fill, minmax(min(360px, 100%), 1fr));
  gap: 0;
  margin: 1.2rem 0 0;
  border-top: var(--rule-w) solid var(--rule);
}

.product-card {
  position: relative;
  background: transparent;
  border-bottom: var(--rule-w) solid var(--rule-soft);
  border-right: var(--rule-w) solid var(--rule-soft);
  /* Tightened from 1.4rem — deal browsing is scanning, and the old rhythm fit barely four
     cards on a 1440x1000 screen. The rules between cards carry the separation now. */
  padding: 1.05rem 1.15rem 1rem;
  transition: background .25s ease, transform .25s ease;
  display: flex; flex-direction: column;
}
.product-card:hover {
  background: rgba(255,255,255,.45);
}
.product-card:hover .product-name { color: var(--signal); }
.product-card:hover .product-img { transform: scale(1.04) rotate(-.4deg); }

.product-link {
  display: grid;
  grid-template-columns: 124px 1fr;
  grid-template-rows: auto auto auto auto;
  gap: .8rem .95rem;
  text-decoration: none;
  color: inherit;
  align-items: start;
}
.product-img-col {
  grid-column: 1; grid-row: 1 / span 4;
  align-self: start;
  width: 124px; height: 124px;
  background: var(--paper-deep);
  border: 1px solid var(--rule-soft);
  display: grid; place-items: stretch;
  overflow: hidden;
  position: relative;
}
.product-img-col::after {
  /* hairline corners — gives the chip a printed-frame feel */
  content: ''; position: absolute; inset: 4px; pointer-events: none;
  background:
    linear-gradient(to right, var(--ink) 8px, transparent 8px) top left / 8px 1px no-repeat,
    linear-gradient(to bottom, var(--ink) 8px, transparent 8px) top left / 1px 8px no-repeat,
    linear-gradient(to left, var(--ink) 8px, transparent 8px) top right / 8px 1px no-repeat,
    linear-gradient(to bottom, var(--ink) 8px, transparent 8px) top right / 1px 8px no-repeat,
    linear-gradient(to right, var(--ink) 8px, transparent 8px) bottom left / 8px 1px no-repeat,
    linear-gradient(to top, var(--ink) 8px, transparent 8px) bottom left / 1px 8px no-repeat,
    linear-gradient(to left, var(--ink) 8px, transparent 8px) bottom right / 8px 1px no-repeat,
    linear-gradient(to top, var(--ink) 8px, transparent 8px) bottom right / 1px 8px no-repeat;
  opacity: .65;
}
.product-img {
  display: block;
  position: absolute;
  inset: 4px;
  width: calc(100% - 8px);
  height: calc(100% - 8px);
  object-fit: contain;
  object-position: center center;
  transition: transform .35s ease;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.08));
}

.product-info-col {
  grid-column: 2; grid-row: 1 / span 4;
  display: flex; flex-direction: column;
  min-width: 0;
}

.product-name {
  font-family: var(--serif);
  font-size: 1.16rem;
  line-height: 1.16;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 .35rem;
  letter-spacing: -.005em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color .18s ease;
}

.price-row {
  display: flex; align-items: baseline; gap: .55rem; flex-wrap: wrap;
  margin-bottom: .22rem;
}
.current-price {
  font-family: var(--mono);
  font-size: 1.55rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.original-price {
  font-family: var(--mono);
  font-size: .85rem;
  color: var(--ink-faint);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  font-variant-numeric: tabular-nums;
}
.original-price:empty { display: none; }

/* THE STAR: the drop badge as a typographic event, not a sticker */
.drop-badge {
  margin-left: auto;
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.6rem;
  font-weight: 400;
  color: var(--signal);
  letter-spacing: -.03em;
  position: relative;
  padding-left: .55rem;
  line-height: 1;
  white-space: nowrap;
}
.drop-badge::before {
  content: ''; position: absolute; left: 0; top: 50%;
  width: 4px; height: 4px;
  background: var(--signal);
  border-radius: 50%;
  transform: translateY(-50%);
}
.drop-badge[data-high="true"] {
  font-size: 1.85rem;
  font-weight: 400;
}
.drop-badge[data-high="true"]::after {
  content: '↓';
  position: absolute; left: -.85rem; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono); font-size: .9rem; font-style: normal;
  color: var(--signal);
  font-weight: 600;
}

/* One line: "TYPICAL  $59.99  [BELOW TYPICAL]". The label used to sit on its own row above the
   badge, which cost a whole line of card height for two words. */
.typical-price-row {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .04em;
  color: var(--ink-mid);
  margin: .1rem 0 .25rem;
  display: flex; align-items: center; gap: .45rem; flex-wrap: nowrap;
  min-width: 0;
}
.typical-label {
  font-size: .6rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  flex-shrink: 0;
}
/* The `hidden` attribute has to beat the display rules above (equal specificity otherwise), or a
   card with no TypicalPrice renders a bare "TYPICAL" label and — worse — an unearned
   "BELOW TYPICAL" badge beside it. Same fix as .rating-row[hidden]. */
.typical-price-row[hidden] { display: none; }
.below-typical-badge[hidden] { display: none; }
.typical-price {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-weight: 500;
  flex-shrink: 0;
}
.below-typical-badge {
  display: inline-flex; align-items: center; gap: .3rem;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  padding: .12rem .45rem .14rem;
  background: var(--gold-soft);
  border: 1px solid var(--gold);
  color: var(--gold);
  font-family: var(--mono);
  font-size: .6rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* Dollar savings next to the percent badge — concrete anchor beats an abstract percent */
.save-amount {
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .05em;
  color: var(--gold);
  white-space: nowrap;
}
.save-amount[hidden] { display: none; }

/* "Lowest we've seen" — same trust-signal family as .below-typical-badge */
.lowest-badge {
  display: inline-flex; align-items: center; gap: .3rem;
  align-self: flex-start;
  padding: .12rem .45rem .14rem;
  margin-top: .3rem;
  background: var(--gold-soft);
  border: 1px solid var(--gold);
  color: var(--gold);
  font-family: var(--mono);
  font-size: .6rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.lowest-badge[hidden] { display: none; }

/* Per-product editorial blurb (AI copy from the generator), clamped to keep cards tidy */
.product-desc {
  font-family: var(--sans);
  font-size: .78rem;
  line-height: 1.45;
  color: var(--ink-mid);
  margin: .3rem 0 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.product-desc[hidden] { display: none; }

/* Live deal-end countdown */
.deal-countdown {
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--signal);
  margin-top: .4rem;
}
.deal-countdown[hidden] { display: none; }

/* Empty-search state + tagged Amazon-search fallback (expired-deal traffic recovery) */
.status-message {
  grid-column: 1 / -1;
  text-align: center;
  padding: 3rem 1rem;
  font-family: var(--sans);
  font-size: .95rem;
  color: var(--ink-mid);
  line-height: 2;
}
.amazon-search-fallback {
  display: inline-block;
  margin-top: .75rem;
  padding: .55rem 1.1rem;
  font-family: var(--mono);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--paper);
  background: var(--signal);
  border: 1px solid var(--signal-deep);
}
.amazon-search-fallback:hover { background: var(--signal-deep); }

/* Monthly roundup pages */
.roundup-video {
  position: relative;
  max-width: var(--col-text);
  aspect-ratio: 16 / 9;
  margin: 1.25rem 0;
  border: 1px solid var(--rule-hair);
  background: var(--paper-deep);
}
.roundup-video iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0;
}
.roundup-as-of {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .05em;
  color: var(--ink-faint);
  margin: .25rem 0 0;
}
.roundup-links,
.roundup-live-link {
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .04em;
  color: var(--ink-mid);
  margin: .6rem 0 0;
}
.roundup-links a,
.roundup-live-link a {
  color: var(--signal);
  text-decoration: none;
  border-bottom: 1px solid var(--signal-soft);
}
.roundup-links a:hover,
.roundup-live-link a:hover { border-bottom-color: var(--signal); }

/* "View on Amazon" — the card's only explicit affordance. Solid ink, borrowing the black
   `★ TOP DEAL` ribbon's language so it reads as native rather than bolted on, and deliberately
   NOT red: the drop percentage owns the one red on the card and shouldn't compete with a button.
   Sits inside the card's own affiliate <a> (a nested link would be invalid HTML), so it inherits
   the same resolved ?tag= the card carries. Natural width, never a full-bleed bar. */
.card-cta {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  width: fit-content;
  align-self: flex-start;
  margin: .6rem 0 .1rem;
  padding: .62em 1.1em;
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #f5f1e8;
  background: #141414;
  border: 1px solid #141414;
  border-radius: 0;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.card-cta-arrow { line-height: 1; }
.product-card:hover .card-cta,
.product-link:focus-visible .card-cta {
  background: var(--signal);
  border-color: var(--signal);
  color: var(--paper);
}

.deal-date {
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: auto;
  padding-top: .55rem;
  border-top: 1px solid var(--rule-soft);
}

/* Urgency markers — purely typographic, no glow */
.product-card[data-fresh="true"] .deal-date::before {
  content: '● NEW · ';
  color: var(--signal);
  font-weight: 600;
  letter-spacing: .12em;
}
.product-card[data-recent="true"] .deal-date::before {
  content: '○ RECENT · ';
  color: var(--gold);
  font-weight: 600;
  letter-spacing: .12em;
}

/* Top-deal & seasonal — a corner mark, no fill */
.featured-card { padding-top: 1.6rem; }
.featured-card::before {
  content: '★ TOP DEAL';
  position: absolute; top: 0; left: 1.4rem;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: .62rem; font-weight: 600;
  letter-spacing: .2em;
  color: var(--paper);
  background: var(--ink);
  padding: .3rem .55rem .32rem;
}
.seasonal-card::before {
  content: '◆ SEASONAL';
  position: absolute; top: 0; left: 1.4rem;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: .62rem; font-weight: 600;
  letter-spacing: .2em;
  color: var(--paper);
  background: var(--gold);
  padding: .3rem .55rem .32rem;
}
.top-deal-badge,
.seasonal-badge { display: none; } /* legacy; replaced by ::before */

.category-badge {
  display: inline-block;
  align-self: flex-start;
  font-family: var(--mono);
  font-size: .58rem;
  letter-spacing: .18em;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--ink-mid);
  border: 1px solid var(--rule-soft);
  padding: .12rem .5rem;
  margin-top: .4rem;
}

/* Amazon-verified urgency badge (e.g. "Prime Day Deal", "Lightning Deal").
   Filled signal pill so it reads as time-sensitive, distinct from the muted category tag. */
.deal-badge {
  display: inline-flex;
  align-items: center;
  gap: .3em;
  align-self: flex-start;
  font-family: var(--mono);
  font-size: .58rem;
  letter-spacing: .14em;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--signal);
  padding: .16rem .5rem;
  margin-top: .45rem;
}
.deal-badge::before { content: '⚡'; font-size: .85em; }
.deal-badge[hidden] { display: none; }

.share-btn {
  position: absolute; top: 1rem; right: 1rem;
  width: 30px; height: 30px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--ink-faint);
  display: grid; place-items: center;
  border-radius: 0;
  transition: color .15s, border-color .15s, background .15s;
  z-index: 2;
  opacity: 0;
}
.product-card:hover .share-btn { opacity: 1; }
.share-btn:hover {
  color: var(--ink);
  border-color: var(--rule);
  background: var(--paper-deep);
}

/* Featured grid — slightly larger / 2-up */
.featured-grid {
  grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
}
.featured-card .current-price { font-size: 1.7rem; }
.featured-card .product-name { font-size: 1.3rem; }

@media (max-width: 600px) {
  /* Single column: the vertical rule has nothing to separate, and its 1px pushed the
     document 1px wider than the viewport. */
  .product-card { padding: .9rem 1rem .85rem; border-right: 0; }
  .product-link { grid-template-columns: 100px 1fr; gap: .7rem .8rem; }
  .product-img-col { width: 100px; height: 100px; }
  .product-name { font-size: 1.02rem; }
  .current-price { font-size: 1.3rem; }
  .drop-badge { font-size: 1.35rem; }
  /* Comfortable thumb target without stretching the button across the card. */
  .card-cta { min-height: 44px; padding: .5em 1.15em; letter-spacing: .12em; }
  .featured-grid, .products-grid, .seasonal-grid { grid-template-columns: 1fr; }
}

/* =====================================================================
   PRIME BANNER — editorial advertorial card
   ===================================================================== */
.prime-banner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 1.2rem;
  align-items: center;
  padding: 1.4rem 1.6rem;
  margin: 2rem 0 0;
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  background:
    repeating-linear-gradient(
      45deg,
      var(--paper-deep) 0,
      var(--paper-deep) 12px,
      var(--paper) 12px,
      var(--paper) 24px
    );
  text-decoration: none;
  color: inherit;
  position: relative;
  transition: transform .2s ease;
}
.prime-banner:hover { transform: translateY(-1px); }
.prime-banner::before {
  content: 'ADVERTISEMENT';
  position: absolute; top: -10px; left: 1.4rem;
  font-family: var(--mono);
  font-size: .58rem; font-weight: 600;
  letter-spacing: .22em;
  background: var(--paper); padding: 0 .5rem;
  color: var(--ink-mid);
}
.prime-banner-icon {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  background: var(--ink); color: var(--signal);
  flex-shrink: 0;
}
.prime-banner-text strong {
  font-family: var(--serif);
  font-size: 1.35rem;
  font-style: italic;
  font-weight: 400;
  letter-spacing: -.01em;
  display: block;
  color: var(--ink);
}
.prime-banner-text span {
  font-family: var(--sans);
  font-size: .88rem;
  color: var(--ink-mid);
  display: block;
  margin-top: .15rem;
}
.prime-banner-cta {
  font-family: var(--mono);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  padding: .65rem 1rem;
  white-space: nowrap;
  transition: background .15s, color .15s;
}
.prime-banner:hover .prime-banner-cta { background: var(--signal); }

@media (max-width: 600px) {
  .prime-banner { grid-template-columns: 1fr; text-align: center; }
  .prime-banner-icon { margin: 0 auto; }
  .prime-banner-cta { width: 100%; text-align: center; }
}

/* =====================================================================
   CATEGORY NAV — department index strip
   ===================================================================== */
.category-nav {
  margin: clamp(2rem, 4vw, 3.2rem) auto 0;
  padding: 1.4rem 0 1.2rem;
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--rule-soft);
  text-align: center;
}
.category-nav-eyebrow {
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0 0 .9rem;
}
.category-nav h2 { display: none; } /* old heading; replaced by eyebrow */
.category-nav-list {
  display: flex; flex-wrap: wrap; gap: 0;
  justify-content: center;
  list-style: none; padding: 0; margin: 0;
}
.category-nav-list a {
  display: inline-flex; align-items: baseline; gap: .5rem;
  padding: .55rem 0;
  margin: 0 .7rem;
  text-decoration: none;
  font-family: var(--serif);
  font-size: 1.1rem;
  font-style: italic;
  color: var(--ink);
  border-bottom: 1px solid transparent;
  transition: color .15s, border-color .15s;
  position: relative;
}
.category-nav-list a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--signal);
  transform: scaleX(0); transform-origin: center;
  transition: transform .25s ease;
}
.category-nav-list a:hover { color: var(--signal); }
.category-nav-list a:hover::after { transform: scaleX(1); }
.category-nav-list a[aria-current="page"] {
  color: var(--signal);
  font-weight: 400;
}
.category-nav-list a[aria-current="page"]::after {
  transform: scaleX(1);
}
.category-nav-list a span {
  font-family: var(--mono);
  font-style: normal;
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .1em;
  color: var(--ink-faint);
}

/* =====================================================================
   FAQ — editorial accordion
   ===================================================================== */
.faq-section {
  margin: clamp(3rem, 6vw, 5rem) auto 0;
  max-width: var(--col-text);
  padding: 0 var(--gutter);
}
.faq-item {
  border-bottom: var(--rule-w) solid var(--rule-soft);
  padding: 1.2rem 0;
}
.faq-item:first-of-type { border-top: 2px solid var(--ink); margin-top: 1rem; }
.faq-item summary {
  cursor: pointer;
  list-style: none;
  font-family: var(--serif);
  font-size: 1.25rem;
  font-style: italic;
  font-weight: 400;
  color: var(--ink);
  display: flex; align-items: center; gap: 1rem;
  position: relative;
  padding-right: 2.5rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: '+';
  position: absolute; right: 0; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: 1.6rem; font-style: normal;
  color: var(--signal);
  transition: transform .25s;
}
.faq-item[open] summary::after { content: '−'; }
.faq-item p {
  margin: 1rem 0 0;
  font-family: var(--sans);
  font-size: .96rem;
  color: var(--ink-mid);
  line-height: 1.65;
  max-width: 60ch;
}

/* =====================================================================
   FOOTER + DISCLAIMER
   ===================================================================== */
.disclaimer-note {
  margin: clamp(3rem, 6vw, 5rem) auto 0 !important;
  max-width: var(--col-text) !important;
  padding: 1.8rem var(--gutter) !important;
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--rule-soft);
  font-family: var(--mono) !important;
  font-size: .72rem !important;
  line-height: 1.7 !important;
  color: var(--ink-mid) !important;
  text-align: left !important;
  letter-spacing: .01em;
}
.disclaimer-note strong {
  display: block;
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--signal);
  margin-bottom: .4rem;
}

.app-footer {
  display: flex; align-items: center; justify-content: space-between;
  padding: 2rem var(--gutter) 2.5rem;
  margin-top: 0;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .06em;
  color: var(--ink-mid);
  flex-wrap: wrap; gap: 1rem;
}
.app-footer small { font-size: inherit; }
.footer-links { display: flex; gap: 1rem; }
.footer-links a {
  text-decoration: none;
  color: var(--ink-mid);
  border-bottom: 1px solid var(--rule-soft);
  transition: color .15s, border-color .15s;
}
.footer-links a:hover { color: var(--signal); border-color: var(--signal); }
.footer-sep { display: none; }

/* =====================================================================
   BACK TO TOP
   ===================================================================== */
.back-to-top {
  position: fixed; bottom: 1.2rem; right: 1.2rem;
  width: 44px; height: 44px;
  background: var(--ink); color: var(--paper);
  border: 0; border-radius: 0;
  display: grid; place-items: center;
  opacity: 0; transform: translateY(8px);
  transition: opacity .25s, transform .25s, background .15s;
  z-index: 30;
}
.back-to-top::after {
  content: 'TOP';
  position: absolute; left: -34px; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: .6rem; font-weight: 600;
  letter-spacing: .2em;
  color: var(--ink);
  background: var(--paper);
  padding: .3rem .4rem;
  border: 1px solid var(--ink);
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s;
}
.back-to-top:hover { background: var(--signal); }
.back-to-top:hover::after { opacity: 1; }
.back-to-top.visible { opacity: 1; transform: translateY(0); }

/* =====================================================================
   PAGE-LOAD STAGGERED REVEAL
   ===================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .filters-bar,
  .featured-deals,
  .seasonal-picks,
  .prime-banner,
  .products-grid {
    animation: rise .65s cubic-bezier(.2,.7,.2,1) both;
  }
  .filters-bar { animation-delay: .05s; }
  .featured-deals { animation-delay: .25s; }
  .prime-banner { animation-delay: .35s; }
  .seasonal-picks { animation-delay: .4s; }
  .products-grid { animation-delay: .45s; }

  .product-card { animation: fade .5s ease both; }
  .products-grid .product-card:nth-child(1) { animation-delay: .50s; }
  .products-grid .product-card:nth-child(2) { animation-delay: .55s; }
  .products-grid .product-card:nth-child(3) { animation-delay: .60s; }
  .products-grid .product-card:nth-child(4) { animation-delay: .65s; }
  .products-grid .product-card:nth-child(5) { animation-delay: .70s; }
  .products-grid .product-card:nth-child(6) { animation-delay: .75s; }

  @keyframes rise {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  @keyframes fade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
}

.fade-in { animation: fade .4s ease both; }

.noscript {
  padding: 2rem;
  border: 1px solid var(--signal);
  background: var(--signal-soft);
  font-family: var(--mono);
  text-align: center;
}

/* High-drop typographic celebration */
[data-mega-drop="true"] .drop-badge {
  font-size: 2.05rem;
  letter-spacing: -.04em;
}
[data-high="true"] .drop-badge {
  text-shadow: 0 1px 0 rgba(200,40,30,.1);
}

/* =====================================================================
   CATEGORY PAGE — H1 + intro
   ===================================================================== */
.category-h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.2rem, 5vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -.02em;
  color: var(--ink);
  margin: 2rem 0 .6rem;
}
.category-h1 em {
  font-style: italic;
  color: var(--signal);
}
.category-intro {
  max-width: 62ch;
  font-family: var(--serif);
  font-size: 1.08rem;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 2rem;
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--rule-soft);
}

/* =====================================================================
   EMPTY CATEGORY STATE — rendered when a market has no live deals for a
   category that exists in another market. Goal: tell the visitor what's
   going on, point them at categories that ARE live, and invite them back.
   ===================================================================== */
.empty-cat-state {
  max-width: 62ch;
  margin: 0 0 3rem;
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--rule-soft);
}
.empty-cat-lead {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  line-height: 1.25;
  color: var(--ink);
  margin: 0 0 .9rem;
}
.empty-cat-deck {
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 1.4rem;
}
.empty-cat-siblings {
  display: flex; flex-wrap: wrap; gap: .55rem;
  margin: 0 0 1.4rem;
}
.empty-cat-siblings a {
  display: inline-flex; align-items: baseline; gap: .4rem;
  padding: .55rem .85rem;
  background: var(--paper-deep);
  border: 1px solid var(--rule-soft);
  font-family: var(--mono);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--ink);
  text-decoration: none;
  transition: background .15s, color .15s, border-color .15s;
}
.empty-cat-siblings a:hover {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
}
.empty-cat-siblings a span {
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 400;
  color: var(--ink-mid);
}
.empty-cat-siblings a:hover span { color: var(--paper); opacity: .7; }
.empty-cat-cross {
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .04em;
  color: var(--ink-mid);
  margin: 0;
}
.empty-cat-cross a {
  color: var(--signal);
  text-decoration: none;
  margin-left: .5rem;
  border-bottom: 1px solid currentColor;
}
.empty-cat-cross a:hover { color: var(--signal-deep); }

/* =====================================================================
   BREADCRUMBS — mono trail above the H1 on category / roundup pages
   ===================================================================== */
.breadcrumbs {
  margin: 1.6rem 0 -.2rem;
}
.breadcrumbs ol {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
  list-style: none;
  padding: 0;
  margin: 0;
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.breadcrumbs li + li::before {
  content: '/';
  margin: 0 .5rem;
  color: var(--ink-faint);
  opacity: .5;
}
.breadcrumbs a {
  text-decoration: none;
  color: var(--ink-mid);
  border-bottom: 1px solid transparent;
  transition: color .15s, border-color .15s;
}
.breadcrumbs a:hover {
  color: var(--signal);
  border-bottom-color: var(--signal);
}
.breadcrumbs [aria-current="page"] {
  color: var(--ink);
}

/* =====================================================================
   ABOUT PAGE — editorial long-read layout
   ===================================================================== */
.about-content {
  max-width: var(--col-text);
  margin: 0 auto;
  padding: clamp(2rem, 5vw, 4rem) var(--gutter) clamp(3rem, 6vw, 5rem);
}
.about-lead {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1.35rem, 2.6vw, 1.9rem);
  line-height: 1.3;
  color: var(--ink);
  margin: 0 0 2rem;
  padding-bottom: 1.4rem;
  border-bottom: 2px solid var(--ink);
}
.about-section {
  margin: 2rem 0 0;
  padding-bottom: 1.8rem;
  border-bottom: 1px solid var(--rule-soft);
}
.about-section:last-child {
  border-bottom: 0;
}
.about-section h2 {
  font-family: var(--mono);
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0 0 .85rem;
}
.about-section p {
  font-family: var(--sans);
  font-size: .98rem;
  line-height: 1.68;
  color: var(--ink-soft);
  margin: 0 0 .9rem;
}
.about-section p:last-child { margin-bottom: 0; }
.about-section p em {
  font-family: var(--serif);
  font-size: 1.08rem;
  color: var(--ink);
}
.about-section strong {
  font-family: var(--mono);
  font-size: .88rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: .01em;
}
.about-social-links {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: 1rem;
}
.about-social-links a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .45rem .85rem;
  border: 1px solid var(--rule-soft);
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .06em;
  color: var(--ink);
  text-decoration: none;
  background: var(--paper-deep);
  transition: background .15s, color .15s, border-color .15s;
}
.about-social-links a:hover {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}

/* ═══════════════════════════════════════════════════════════════════════
   Viral Finds directory (/viral) — landing pages + index grid.
   Reuses the site shell; a `.viral-page` body class hides the deal-grid chrome
   so these read as focused editorial landing pages.
   ═══════════════════════════════════════════════════════════════════════ */

.viral-page .filters-bar,
.viral-page .masthead-dateline,
.viral-page #scroll-sentinel,
.viral-page #active-filters,
.viral-page #results-summary,
.viral-page #featured-deals,
.viral-page #seasonal-picks,
.viral-page #products-grid,
.viral-page #product-card-template { display: none !important; }

.viral-eyebrow {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0 0 .5rem;
}

/* ── Index ── */
.viral-index-head { max-width: var(--col-text); margin: 1.5rem auto 2rem; text-align: center; }
.viral-index-h1 {
  font-family: var(--serif);
  font-size: clamp(2.6rem, 7vw, 4.4rem);
  line-height: 1.02;
  margin: 0 0 .6rem;
  color: var(--ink);
}
.viral-index-sub { font-size: 1.08rem; line-height: 1.6; color: var(--ink-mid); margin: 0; }

.viral-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.25rem;
  max-width: var(--col-max);
  margin: 0 auto 2rem;
}
.viral-card {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: var(--rule-w) solid var(--rule-soft);
  border-radius: 12px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--paper-lift);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.viral-card:hover { transform: translateY(-3px); box-shadow: var(--paper-lift-hover); border-color: var(--signal); }
.viral-card-visual {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 16 / 10;
  background: var(--paper-deep);
  border-bottom: var(--rule-w) solid var(--rule-soft);
}
.viral-card-emoji { font-size: 4.5rem; line-height: 1; }
.viral-card-photo { max-width: 82%; max-height: 82%; object-fit: contain; }
.viral-card-body { padding: 1rem 1.1rem 1.15rem; display: flex; flex-direction: column; gap: .35rem; }
.viral-card-cat {
  font-family: var(--mono); font-size: .68rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-faint);
}
.viral-card-hook { font-family: var(--serif); font-size: 1.35rem; line-height: 1.15; margin: 0; color: var(--ink); }
.viral-card-sub { font-size: .92rem; line-height: 1.45; color: var(--ink-mid); margin: 0; }
.viral-card-more { font-family: var(--mono); font-size: .78rem; color: var(--signal); margin-top: .35rem; }

/* ── Landing page ── */
.viral-landing-article { max-width: var(--col-text); margin: 0 auto; }
.viral-hero { text-align: center; margin: 1rem 0 1.75rem; }
.viral-h1 {
  font-family: var(--serif);
  font-size: clamp(2.4rem, 6.5vw, 4rem);
  line-height: 1.03;
  margin: 0 0 .7rem;
  color: var(--ink);
}
.viral-deck { font-size: 1.2rem; line-height: 1.5; color: var(--ink-mid); margin: 0 auto 1.4rem; max-width: 34em; }
.viral-visual {
  display: flex; align-items: center; justify-content: center;
  margin: 1.4rem auto;
  border-radius: 16px;
}
.viral-visual-illustrated {
  aspect-ratio: 16 / 9;
  max-width: 460px;
  background:
    radial-gradient(120% 120% at 50% 0%, var(--signal-soft), transparent 60%),
    var(--paper-deep);
  border: var(--rule-w) solid var(--rule-soft);
}
.viral-emoji { font-size: clamp(5rem, 18vw, 8rem); line-height: 1; filter: drop-shadow(0 6px 14px rgba(20,17,13,.18)); }
.viral-photo { max-width: 420px; max-height: 340px; object-fit: contain; }

.viral-proof { font-size: 1.05rem; color: var(--ink-soft); margin: .9rem 0 1.2rem; }
.viral-stars { color: var(--gold); letter-spacing: .05em; }
.viral-proof-count { color: var(--ink-faint); font-size: .92rem; }
.viral-trend-badge {
  display: inline-block;
  font-family: var(--mono); font-size: .8rem; letter-spacing: .04em;
  color: var(--signal-deep);
  background: var(--signal-soft);
  border: 1px solid rgba(200,40,30,.2);
  padding: .4rem .8rem; border-radius: 999px;
}

/* CTA button */
.viral-cta {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--sans); font-weight: 700; font-size: 1.05rem;
  text-decoration: none;
  color: #fff; background: var(--signal);
  padding: .95rem 1.6rem; border-radius: 10px;
  box-shadow: 0 6px 18px -6px rgba(200,40,30,.5);
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.viral-cta:hover { background: var(--signal-deep); transform: translateY(-2px); box-shadow: 0 10px 24px -8px rgba(200,40,30,.6); }
.viral-cta-price {
  background: rgba(255,255,255,.2); padding: .12rem .5rem; border-radius: 6px;
  font-variant-numeric: tabular-nums;
}
.viral-cta-arrow { font-size: 1.2em; }
.viral-source { font-family: var(--mono); font-size: .74rem; color: var(--ink-faint); margin: .9rem 0 0; }

.viral-pitch { font-size: 1.18rem; line-height: 1.65; color: var(--ink-soft); margin: 1.6rem 0; }
.viral-section { margin: 2rem 0; }
.viral-section h2 {
  font-family: var(--serif); font-size: 1.7rem; color: var(--ink);
  margin: 0 0 .7rem; padding-bottom: .35rem; border-bottom: var(--rule-w) solid var(--rule-soft);
}
.viral-section p { font-size: 1.05rem; line-height: 1.7; color: var(--ink-soft); margin: 0; }
.viral-why p { color: var(--ink-mid); }
.viral-bullets { margin: 0; padding: 0; list-style: none; }
.viral-bullets li {
  position: relative; padding: .5rem 0 .5rem 1.9rem;
  font-size: 1.05rem; line-height: 1.55; color: var(--ink-soft);
  border-bottom: var(--rule-w) solid var(--rule-soft);
}
.viral-bullets li::before {
  content: '✓'; position: absolute; left: 0; top: .55rem;
  color: var(--signal); font-weight: 700;
}
.viral-video { margin: 1.6rem auto; }
.viral-video iframe { width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: 12px; }

.viral-cta-block {
  text-align: center;
  margin: 2.5rem 0 1rem;
  padding: 2rem 1.5rem;
  background: var(--paper-deep);
  border: var(--rule-w) solid var(--rule-soft);
  border-radius: 14px;
}
.viral-disclosure { font-size: .8rem; color: var(--ink-faint); line-height: 1.5; margin: 1rem auto 0; max-width: 40em; }

/* Nav link to the directory */
.category-nav-viral { color: var(--signal) !important; font-weight: 600; }

@media (max-width: 560px) {
  .viral-cta { width: 100%; justify-content: center; }
}

/* Homepage entry-point banner into /viral.
   Was a saturated orange->red gradient card with a white pill button — loud, rounded, and from a
   different design system than everything around it. Re-cut in the page's own language: paper
   ground, ruled edges, corner brackets (same motif as the product image chips), a letterspaced
   micro-label, serif display name, and one red accent. Still the loudest thing on the page. */
.viral-banner {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    'label label'
    'text  cta';
  align-items: center;
  gap: .35rem 1.2rem;
  margin: 1.5rem 0 0;
  padding: 1.15rem 1.5rem 1.2rem;
  text-decoration: none;
  color: var(--ink);
  background: var(--paper-deep);
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  position: relative;
  transition: background .18s ease;
}
.viral-banner::after {
  /* hairline corner brackets — the same printed-frame mark used on product image chips */
  content: ''; position: absolute; inset: 6px; pointer-events: none;
  background:
    linear-gradient(to right, var(--signal) 12px, transparent 12px) top left / 12px 1px no-repeat,
    linear-gradient(to bottom, var(--signal) 12px, transparent 12px) top left / 1px 12px no-repeat,
    linear-gradient(to left, var(--signal) 12px, transparent 12px) top right / 12px 1px no-repeat,
    linear-gradient(to bottom, var(--signal) 12px, transparent 12px) top right / 1px 12px no-repeat,
    linear-gradient(to right, var(--signal) 12px, transparent 12px) bottom left / 12px 1px no-repeat,
    linear-gradient(to top, var(--signal) 12px, transparent 12px) bottom left / 1px 12px no-repeat,
    linear-gradient(to left, var(--signal) 12px, transparent 12px) bottom right / 12px 1px no-repeat,
    linear-gradient(to top, var(--signal) 12px, transparent 12px) bottom right / 1px 12px no-repeat;
  opacity: .7;
}
.viral-banner:hover { background: var(--paper-edge); }
.viral-banner-label {
  grid-area: label;
  font-family: var(--mono);
  font-size: .62rem;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--signal);
}
.viral-banner-label::before { content: '◆'; margin-right: .5em; }
.viral-banner-text { grid-area: text; display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.viral-banner-text strong {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.5rem;
  letter-spacing: -.01em;
  color: var(--ink);
}
.viral-banner-text span { font-family: var(--sans); font-size: .88rem; color: var(--ink-mid); margin-top: .1rem; }
.viral-banner-cta {
  grid-area: cta;
  flex-shrink: 0;
  font-family: var(--mono);
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  padding: .6rem 1rem;
  white-space: nowrap;
  transition: background .15s ease;
}
.viral-banner:hover .viral-banner-cta { background: var(--signal); }
@media (max-width: 560px) {
  .viral-banner {
    grid-template-columns: 1fr;
    grid-template-areas: 'label' 'text' 'cta';
    gap: .5rem;
    padding: 1rem 1.15rem 1.1rem;
  }
  .viral-banner-text strong { font-size: 1.3rem; }
  .viral-banner-cta { text-align: center; }
}

/* Star rating + review count on deal cards (shown only when the generator captured a rating) */
.rating-row {
  display: flex;
  align-items: center;
  gap: .35rem;
  margin: .2rem 0 0;
  font-size: .82rem;
  color: var(--ink-mid);
}
/* The `hidden` attribute must win over the flex rule above (equal specificity otherwise), so an
   empty client-side rating row stays invisible instead of showing a bare star. */
.rating-row[hidden] { display: none; }
.rating-row .star { color: var(--gold); line-height: 1; }
.rating-row .rating-val { font-weight: 700; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.rating-row .rating-count { color: var(--ink-faint); }

/* =====================================================================
   Monthly roundup archive — hub (/<market>/roundups/) + cross-links
   =====================================================================
   The roundups are the site's only evergreen pages, so the archive that
   holds them has to read like a real section of the paper, not a link
   dump: ruled index rows, a mono month rail, serif headlines, one red.
   Same language as the category nav and the Viral Finds index. */

/* Directory pages index other pages, not products — hide the deal-grid
   chrome the shared template ships. (Mirrors the .viral-page rules.) */
.directory-page .filters-bar,
.directory-page .masthead-dateline,
.directory-page #scroll-sentinel,
.directory-page #active-filters,
.directory-page #results-summary,
.directory-page #featured-deals,
.directory-page #seasonal-picks,
.directory-page #products-grid,
.directory-page #product-card-template { display: none !important; }

.hub-head {
  max-width: var(--col-text);
  margin: 1.25rem 0 2.25rem;
}
.hub-eyebrow {
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0 0 .7rem;
}
.hub-eyebrow::before { content: '◆'; margin-right: .5em; }
.hub-h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.4rem, 6.5vw, 4.1rem);
  line-height: 1.02;
  letter-spacing: -.015em;
  margin: 0 0 .75rem;
  color: var(--ink);
}
.hub-h1 em { font-style: italic; color: var(--signal); }
.hub-sub {
  font-size: 1.05rem;
  line-height: 1.65;
  color: var(--ink-mid);
  margin: 0;
}
.hub-months {
  font-family: var(--mono);
  font-size: .7rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 1rem 0 0;
  padding-top: .8rem;
  border-top: var(--rule-w) solid var(--rule-soft);
}

.hub-groups { margin: 0 0 1rem; }
.hub-group { margin: 0 0 2.4rem; }
.hub-group-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .4rem .9rem;
  padding-bottom: .5rem;
  border-bottom: 2px solid var(--ink);
}
.hub-group-name {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.4vw, 2rem);
  line-height: 1.1;
  margin: 0;
  color: var(--ink);
}
.hub-group-count {
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}
.hub-group-live {
  margin-left: auto;
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--signal);
  text-decoration: none;
  border-bottom: 1px solid var(--signal-soft);
}
.hub-group-live:hover { border-bottom-color: var(--signal); }

.hub-rows { list-style: none; margin: 0; padding: 0; }
.hub-row { border-bottom: var(--rule-w) solid var(--rule-soft); }
.hub-row-link {
  display: grid;
  grid-template-columns: 11rem 1fr auto;
  align-items: baseline;
  gap: .35rem 1.2rem;
  padding: .95rem .6rem;
  margin: 0 -.6rem;
  text-decoration: none;
  color: inherit;
  transition: background .15s ease;
}
.hub-row-link:hover { background: var(--paper-deep); }
.hub-row-month {
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--signal);
}
.hub-row-title {
  font-family: var(--serif);
  font-size: 1.22rem;
  line-height: 1.25;
  color: var(--ink);
  min-width: 0;
}
.hub-row-link:hover .hub-row-title { color: var(--signal); }
.hub-row-meta {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

.hub-empty {
  max-width: var(--col-text);
  padding: 1.6rem 0 0;
  border-top: 2px solid var(--ink);
}
.hub-empty-lead {
  font-family: var(--serif);
  font-size: 1.5rem;
  line-height: 1.25;
  margin: 0 0 .7rem;
  color: var(--ink);
}
.hub-empty-deck, .hub-empty-cross { font-size: 1rem; line-height: 1.65; color: var(--ink-mid); margin: 0 0 .6rem; }
.hub-empty-deck a, .hub-empty-cross a { color: var(--signal); text-decoration: none; border-bottom: 1px solid var(--signal-soft); }
.hub-empty-deck a:hover, .hub-empty-cross a:hover { border-bottom-color: var(--signal); }

/* ── Cross-links at the foot of each roundup ── */
.roundup-crosslinks {
  margin: clamp(2.5rem, 5vw, 4rem) auto 0;
  padding: 1.4rem 0 0;
  border-top: 2px solid var(--ink);
}
.roundup-crosslinks-eyebrow {
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0 0 .35rem;
}
.roundup-crosslinks h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.4vw, 2rem);
  line-height: 1.1;
  margin: 0 0 1rem;
  color: var(--ink);
}
.roundup-nav-months {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: .5rem 1.5rem;
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .05em;
  margin: 0 0 1.2rem;
}
.roundup-nav-next { margin-left: auto; }
.roundup-nav-months a { color: var(--signal); text-decoration: none; border-bottom: 1px solid var(--signal-soft); }
.roundup-nav-months a:hover { border-bottom-color: var(--signal); }

/* Flex, not an auto-fit grid: with a single sibling published a grid track would stretch the
   one card across the full column, which reads like a banner rather than one of several. */
.roundup-sibling-list {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin: 0 0 1.2rem;
}
.roundup-sibling {
  flex: 0 1 220px;
  display: flex;
  flex-direction: column;
  gap: .2rem;
  padding: .85rem .95rem;
  text-decoration: none;
  color: inherit;
  background: var(--paper-deep);
  border: var(--rule-w) solid var(--rule-soft);
  transition: border-color .15s ease, background .15s ease;
}
.roundup-sibling:hover { border-color: var(--signal); background: var(--paper-edge); }
.roundup-sibling-cat {
  font-family: var(--serif);
  font-size: 1.15rem;
  line-height: 1.15;
  color: var(--ink);
}
.roundup-sibling-month {
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.roundup-crosslinks-hub {
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .08em;
  margin: 0;
}
.roundup-crosslinks-hub a { color: var(--signal); text-decoration: none; border-bottom: 1px solid var(--signal-soft); }
.roundup-crosslinks-hub a:hover { border-bottom-color: var(--signal); }

/* Standing nav + footer entries into the archive */
.category-nav-roundups { color: var(--signal) !important; font-weight: 600; }

@media (max-width: 620px) {
  .hub-row-link {
    grid-template-columns: 1fr;
    gap: .15rem;
    padding: .85rem .5rem;
    margin: 0 -.5rem;
  }
  .hub-row-meta { white-space: normal; }
  .hub-group-live { margin-left: 0; flex-basis: 100%; }
  .roundup-nav-next { margin-left: 0; }
}
