:root {
  --primary: #6A2FE0;
  --primary-hover: #5324B3;
  --on-primary: #FFFFFF;
  --highlight: #D6FF4B;
  --on-highlight: #14121A;
  --ink: #14121A;
  --ink-2: #3B3948;
  --muted: #5F5E6E;
  --faint: #706F80; /* 2026-10-01 a11y: was #7B7A8A (4.21:1), now 4.91:1 on white */
  --surface: #FFFFFF;
  --page: #FFFFFF;
  --tint: #F1ECFD;
  --wash: #F2F3F8;
  --line: #E4E6EF;
  --line-strong: #D3D6E2;
  --good: #0A7A4E;
  --dark: #14121A;
  --dark-2: #1F1D2B;
  --on-dark: #F2F3F8;
  --on-dark-muted: #C9C7D6;
  --shadow: 0 1px 2px rgba(20,18,26,0.04), 0 8px 24px rgba(20,18,26,0.06);
  --radius: 16px;
  --font-display: 'Sora', system-ui, -apple-system, sans-serif;
  --font-body: 'DM Sans', system-ui, -apple-system, sans-serif;
  /* The site is light. Set here rather than in each page's <meta>, so form
     controls and the pre-paint canvas stay light on a phone in dark mode. */
  color-scheme: light;
}
:root[data-theme="dark"] {
  --primary: #8F62FF; --primary-hover: #A883FF; --on-primary: #14121A;
  --highlight: #D6FF4B; --on-highlight: #14121A;
  --ink: #F2F1F8; --ink-2: #D6D4E2; --muted: #A5A3B6; --faint: #8A889B;
  --surface: #1C1A26; --page: #121017; --tint: #262039; --wash: #24222E;
  --line: #2E2C3A; --line-strong: #3E3B4D; --good: #4DD696;
  --dark: #0C0B10; --dark-2: #1A1822; --on-dark: #F2F1F8; --on-dark-muted: #B4B2C4;
  --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 8px 24px rgba(0,0,0,0.35);
}

/* Render the same in an in-app browser as in the phone's real browser.
   Android WebViews (Instagram, Facebook) apply "text autosizing" — an
   algorithmic inflation that guesses at font sizes per block of text. Chrome
   itself does not apply it to a responsive page, which is why the regular
   mobile browser looked right while the in-app view showed oversized bullets,
   oversized pills and, before the min-content work, sideways scrolling. Any
   value other than `auto` switches that guessing off. Standard practice — it is
   in normalize.css for exactly this reason.
   This does NOT stop anyone zooming: the viewport meta sets no maximum-scale
   and no user-scalable=no, so pinch zoom works everywhere. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

* { box-sizing: border-box; }
body { margin: 0; background: var(--page); color: var(--ink); font-family: var(--font-body); font-size: 16px; line-height: 1.5; }
a { color: var(--primary); }
a:hover { color: var(--primary-hover); }
h1, h2, h3 { font-family: var(--font-display); margin: 0; text-wrap: balance; letter-spacing: -0.02em; }
p { margin: 0; }
img { max-width: 100%; }
:focus-visible { outline: 3px solid var(--highlight); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }

.wrap { width: 100%; max-width: 1240px; margin-inline: auto; padding-inline: 16px; }
@media (min-width: 720px) { .wrap { padding-inline: 32px; } }

/* Bars */
.disclosure-bar { background: var(--surface); color: var(--ink); font-size: 12px; border-bottom: 1px solid var(--line); }
.disclosure-bar .wrap { display: flex; justify-content: space-between; gap: 16px; padding-block: 8px; flex-wrap: wrap; }
.disclosure-bar a { color: var(--ink); }

.site-header { position: sticky; top: 0; z-index: 20; background: var(--surface); border-bottom: 1px solid var(--line); }
/* `top` was env(safe-area-inset-top, 0px). On a notched iPhone the page declares
   viewport-fit=cover, so that reports ~47px even inside an in-app browser whose
   own chrome already sits above the page. A sticky header with top:47px parks 47px
   DOWN the viewport: a strip of the page shows above it and the bar lands across the
   hero headline. Reported 2026-09-23 opening the Instagram bio link. A sticky header
   belongs at the top of the scrollport; the safe-area inset is for FIXED elements
   that genuinely sit under the notch, and the disclosure bar is above this anyway. */
.site-header .wrap { display: flex; align-items: center; gap: 24px; padding-block: 14px; }
.logo { font-family: var(--font-display); font-weight: 700; font-size: 24px; color: var(--ink); text-decoration: none; letter-spacing: -0.02em; white-space: nowrap; }
.logo span { color: var(--primary); }
.nav { display: none; gap: 22px; flex-grow: 1; }
.nav a { color: var(--ink); text-decoration: none; font-weight: 500; font-size: 15px; }
.nav a[aria-current="page"] { color: var(--primary); font-weight: 700; }
.header-actions { margin-left: auto; display: flex; gap: 10px; align-items: center; }
.menu-btn { display: inline-flex; width: 44px; height: 44px; align-items: center; justify-content: center; border: 1px solid var(--line-strong); background: var(--surface); border-radius: 999px; color: var(--ink); cursor: pointer; }
@media (min-width: 900px) { .nav { display: flex; } .menu-btn { display: none; } }
.mobile-nav { display: flex; flex-direction: column; gap: 4px; padding: 8px 16px 16px; border-top: 1px solid var(--line); background: var(--surface); }
.mobile-nav a { padding: 10px 4px; color: var(--ink); text-decoration: none; font-weight: 500; }
@media (min-width: 900px) { .mobile-nav { display: none !important; } }

/* Buttons & badges */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 44px; padding: 0 20px; border-radius: 999px; font-weight: 600; font-size: 15px; text-decoration: none; border: 1px solid transparent; cursor: pointer; font-family: inherit; transition: background .15s, color .15s; white-space: nowrap; }
.btn-primary { background: var(--primary); color: var(--on-primary); }
.btn-primary:hover { background: var(--primary-hover); color: var(--on-primary); }
.btn-ghost { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn-ghost:hover { border-color: var(--ink); color: var(--ink); }
.btn-highlight { background: var(--highlight); color: var(--on-highlight); }
.btn-highlight:hover { background: #C4F02E; color: var(--on-highlight); }
.btn-dark { background: var(--dark); color: var(--on-dark); }
.btn-dark:hover { background: var(--dark-2); color: var(--on-dark); }
.btn-sm { height: 36px; padding: 0 14px; font-size: 13px; }
.btn-block { width: 100%; }
.badge { display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; line-height: 1.2; white-space: nowrap; }
.badge-primary { background: var(--primary); color: var(--on-primary); }
.badge-good { background: var(--good); color: #FFFFFF; }
.badge-dark { background: var(--dark); color: var(--on-dark); }
.badge-highlight { background: var(--highlight); color: var(--on-highlight); }
.badge-soft { background: var(--wash); color: var(--ink-2); }
.chip { display: inline-flex; align-items: center; height: 36px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink); font-size: 13px; font-weight: 600; text-decoration: none; cursor: pointer; font-family: inherit; white-space: nowrap; }
.chip[aria-pressed="true"], .chip.is-active { background: var(--dark); color: var(--on-dark); border-color: var(--dark); }
.chips { display: flex; gap: 8px; flex-wrap: wrap; }

/* Hero */
.hero { margin-block: 20px 8px; padding: 28px 24px; border-radius: 24px; background: var(--highlight); color: var(--on-highlight); display: flex; flex-direction: column; gap: 12px; }
@media (min-width: 900px) { .hero { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: 40px; padding: 36px 40px; } }
.hero .eyebrow { font-size: 13px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
.hero h1 { font-size: clamp(30px, 4.2vw, 48px); line-height: 1.05; font-weight: 700; }
.hero p { font-size: 17px; max-width: 62ch; }
.hero .stats { display: flex; gap: 8px; flex-wrap: wrap; }

/* Layout */
.grid-main { display: grid; grid-template-columns: 1fr; gap: 24px; padding-block: 12px 40px; }
@media (min-width: 1000px) { .grid-main { grid-template-columns: minmax(0, 3fr) minmax(280px, 1fr); } }
.stack { display: flex; flex-direction: column; gap: 24px; }
.section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.section-head h2 { font-size: 24px; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.card-pad { padding: 20px; }
.thumb { background: var(--wash); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: var(--faint); font-size: 13px; }

/* Featured deal */
.featured { display: grid; grid-template-columns: 1fr; overflow: hidden; border: 2px solid var(--primary); }
@media (min-width: 720px) { .featured { grid-template-columns: 1fr 1fr; } }
.featured .thumb { border-radius: 0; min-height: 220px; }
@media (min-width: 720px) { .featured .thumb { min-height: 340px; } }
.featured-body { padding: 22px; display: flex; flex-direction: column; gap: 12px; }
@media (min-width: 720px) { .featured-body { padding: 28px 32px; } }
.featured h2 { font-size: clamp(22px, 2.6vw, 30px); line-height: 1.15; font-weight: 600; }
.price-row { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.price { font-family: var(--font-display); font-weight: 700; color: var(--primary); font-size: 26px; font-variant-numeric: tabular-nums; }
.price-lg { font-size: 34px; }
.was { text-decoration: line-through; color: var(--faint); font-size: 14px; }
.off { font-weight: 700; color: var(--good); font-size: 15px; }
.meta { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; color: var(--muted); flex-wrap: wrap; }
.verified { color: var(--good); font-weight: 600; }
.ends-soon { color: var(--primary); font-weight: 700; }

/* Deal grid */
.deals { display: grid; grid-template-columns: 1fr; gap: 20px; }
@media (min-width: 560px) { .deals { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .deals { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.deal { display: flex; flex-direction: column; gap: 10px; padding: 14px; position: relative; }
.deal .thumb { height: 150px; }
.deal .corner { position: absolute; top: 24px; left: 24px; }
.deal .store { font-size: 12px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.deal .name { font-size: 16px; font-weight: 600; line-height: 1.3; }
.deal .name a { color: var(--ink); text-decoration: none; }
.deal .name a:hover { color: var(--primary); }
.deal .note { font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.deal-list-row { display: flex; gap: 12px; align-items: center; padding-block: 10px; border-top: 1px solid var(--line); color: var(--ink); text-decoration: none; }
.deal-list-row:hover { color: var(--primary); }
.deal-list-row .thumb { width: 56px; height: 56px; flex-shrink: 0; }
.toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.select { height: 36px; border-radius: 999px; border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink); padding: 0 12px; font-family: inherit; font-size: 13px; font-weight: 600; }

/* Services strip */
.services { padding: 24px; background: var(--dark); color: var(--on-dark); border-color: var(--dark); display: flex; flex-direction: column; gap: 14px; }
.services h2 { color: var(--highlight); font-size: 22px; }
.services a.more { color: var(--on-dark); font-size: 14px; }
.services-grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 560px) { .services-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .services-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.service { text-decoration: none; color: var(--on-dark); background: var(--dark-2); border-radius: 12px; padding: 14px; display: flex; flex-direction: column; gap: 6px; }
.service:hover { color: var(--highlight); }
.service .brand { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--on-dark-muted); }
.service .offer { font-size: 15px; font-weight: 600; line-height: 1.3; }
.service .term { font-size: 13px; color: var(--on-dark-muted); }

/* Stores */
.stores { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (min-width: 560px) { .stores { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .stores { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.store-tile { text-decoration: none; color: var(--ink); padding: 16px 12px; display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; }
.store-tile:hover { color: var(--primary); }
.store-tile .sname { font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.store-tile .scount { font-size: 12px; color: var(--muted); }

/* Sidebar */
.sidebar { display: flex; flex-direction: column; gap: 20px; }
.signup { border-color: var(--primary); display: flex; flex-direction: column; gap: 10px; }
.signup h3 { font-size: 20px; line-height: 1.15; }
.signup p { font-size: 14px; color: var(--ink-2); }
.signup label { font-size: 13px; font-weight: 600; }
.input { height: 44px; padding: 0 12px; border: 1px solid var(--line-strong); border-radius: 10px; font-size: 14px; font-family: inherit; background: var(--surface); color: var(--ink); width: 100%; }
.side-list h3, .side-box h3 { font-size: 19px; margin-bottom: 8px; }
.side-row { display: flex; justify-content: space-between; gap: 10px; padding-block: 10px; border-top: 1px solid var(--line); color: var(--ink); text-decoration: none; font-size: 14px; }
.side-row:hover { color: var(--primary); }
.side-row .p { font-weight: 700; color: var(--primary); white-space: nowrap; flex-shrink: 0; } /* 2026-10-01 a11y: price labels keep their width, names wrap (all-deals scrolled sideways at 390px) */
.side-box { background: var(--tint); border-color: var(--tint); box-shadow: none; display: flex; flex-direction: column; gap: 6px; }
.side-box .lbl { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.side-box p { font-size: 14px; color: var(--ink-2); }

/* Article (deal page) */
.crumbs { font-size: 13px; color: var(--muted); padding-top: 24px; }
.crumbs a { color: var(--muted); }
.article { display: flex; flex-direction: column; gap: 18px; }
.article h1 { font-size: clamp(28px, 3.4vw, 40px); line-height: 1.1; }
.byline { font-size: 14px; color: var(--muted); display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.byline a { color: var(--ink); font-weight: 600; }
.prose { display: flex; flex-direction: column; gap: 14px; font-size: 17px; line-height: 1.6; color: var(--ink-2); max-width: 70ch; }
.prose h2 { font-size: 22px; color: var(--ink); margin-top: 8px; }
.compare { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; }
.compare .th { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); padding: 10px 12px; border-bottom: 1px solid var(--line); }
.compare .td { font-size: 14px; padding: 12px; border-bottom: 1px solid var(--line); }
.compare-wrap { overflow-x: auto; }

/* Footer */
.site-footer { border-top: 1px solid var(--line); margin-top: 24px; }
.site-footer .wrap { display: flex; flex-direction: column; gap: 14px; padding-block: 28px; font-size: 13px; color: var(--muted); }
@media (min-width: 900px) { .site-footer .wrap { flex-direction: row; justify-content: space-between; gap: 40px; } }
.site-footer p { max-width: 72ch; line-height: 1.5; }
.site-footer nav { display: flex; gap: 18px; flex-wrap: wrap; }
.site-footer nav a { color: var(--muted); }
.sample-note { font-size: 12px; color: var(--muted); background: var(--wash); border-radius: 10px; padding: 8px 12px; }

/* Align deal-card CTAs on a shared baseline across each row */
.deal .price-row { margin-top: auto; }
.deal .name { min-height: 42px; }
.deal .note { min-height: 38px; }

/* Deal card thumbnails: real product photo, or a typographic offer tile */
.thumb { align-items: center; justify-content: center; }
.thumb img { width: 100%; height: 100%; object-fit: contain; object-position: center; display: block; }
.thumb-offer { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; background: var(--tint); }
.thumb-offer span { font-family: var(--font-display); font-weight: 800; font-size: 22px; line-height: 1.1; text-align: center; padding: 0 12px; color: var(--primary); }
.thumb-offer small { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }

/* Photo thumbnails: the product image fills the panel, so no tinted square shows behind it */
.thumb-photo { background: #FFFFFF; aspect-ratio: 1 / 1; height: auto; padding: 0; overflow: hidden; }
:root:not([data-theme="light"]) .thumb-photo { background: #FFFFFF; }

/* Photo panel must be square, so a square product photo fills it edge to edge and its own backdrop reads as the panel */
.card .thumb.thumb-photo, .deal .thumb.thumb-photo, .featured .thumb.thumb-photo { height: auto; min-height: 0; aspect-ratio: 1 / 1; padding: 0; }
.card .thumb.thumb-photo img { width: 100%; height: 100%; object-fit: cover; object-position: center; }

/* Offer tiles match the photo panels so every thumbnail in a row is the same size */
.card .thumb.thumb-offer { height: auto; min-height: 0; aspect-ratio: 1 / 1; }

/* Offer tiles carry an original line illustration drawn for the category — no stock photography, no retailer artwork */
.thumb-offer { flex-direction: column; gap: 8px; }
.thumb-offer svg { width: 68px; height: 68px; color: var(--primary); opacity: .85; flex-shrink: 0; }
.thumb-offer span { font-size: 20px; }
@media (max-width: 640px) { .thumb-offer svg { width: 52px; height: 52px; } }


/* beehiiv subscribe embed: the iframe is ours to size, its contents are not */
.signup-embed { margin-top: 2px; }
.signup-embed iframe { max-width: 100%; border: 0; display: block; }

/* Jump links land below the sticky header instead of under it (header is 65px). */
[id] { scroll-margin-top: 88px; }
/* Show where "Get the weekly roundup" sent you. Skipped under prefers-reduced-motion,
   which already sets animation: none !important on everything. */
@keyframes udt-flash { 0% { box-shadow: 0 0 0 5px var(--primary); } 100% { box-shadow: 0 0 0 0 transparent; } }
#signup:target { animation: udt-flash 1.8s ease-out; }

/* ---------------------------------------------------------------------------
   Mobile layout fixes — 2026-09-23. Three faults seen on a 390px phone:
   the header row overflowed the viewport (page scrollWidth 480 vs 390), the
   mobile nav was permanently expanded, and the page went dark in dark mode.
   The dark palette is removed above; the other two are fixed here.
   --------------------------------------------------------------------------- */

/* The mobile nav's own `display:flex` outranked the UA's [hidden] rule, so the
   nav sat open under the header on every phone and the menu button did nothing.
   Honour the attribute the button actually toggles. */
.mobile-nav[hidden] { display: none; }

/* Header row on phones: the logo, the "Get the weekly roundup" pill and the
   menu button together need ~396px inside a 358px content box, which pushed the
   menu button off the right edge. Below 560px the pill stands down — the signup
   card is in the page, and "Get the weekly roundup" is not worth losing the
   menu button for. */
@media (max-width: 899px) { .site-header .wrap { gap: 12px; } }
@media (max-width: 559px) { .header-actions .btn { display: none; } }


/* viewport-fit=cover lets content sit under a notched phone's rounded corners
   in landscape. Hold the gutter at the larger of the design padding and the
   safe area so nothing touches the edge. */
@supports (padding: max(0px)) {
  .wrap { padding-inline: max(16px, env(safe-area-inset-left)) max(16px, env(safe-area-inset-right)); }
  @media (min-width: 720px) {
    .wrap { padding-inline: max(32px, env(safe-area-inset-left)) max(32px, env(safe-area-inset-right)); }
  }
}


/* ---------------------------------------------------------------------------
   Large text scaling — 2026-09-23 (second pass). Reported from Instagram's
   in-app browser on Android with the system text-scaling setting well up.
   At ~175-200% the wordmark ran under the menu button and the page scrolled
   sideways by up to 127px, clipping every line on the left. Both are
   min-content problems: they appear at NO viewport width at default text size,
   which is why the earlier width testing missed them.
   --------------------------------------------------------------------------- */

/* The wordmark was `white-space: nowrap` on a flex item that had been given
   min-width:0 earlier the same day: the box shrank, the nowrap text did not,
   and it slid out from under its own box and beneath the button. Both are gone.
   "UrDealsToday" has no space in it, so there is no natural break; a zero-width
   space before the "Today" span gives the line breaker one, and the wordmark
   stacks as UrDeals / Today rather than breaking mid-word. */
.logo { white-space: normal; overflow-wrap: break-word; }
.logo span::before { content: "\200B"; }
/* The menu button must never be squeezed; the CTA beside it may be. At 200%
   text "Get the weekly roundup" is 414px wide and pushed the page 114px past
   the edge on tablet widths, so it is allowed to shrink and wrap instead. */
.menu-btn { flex-shrink: 0; }
.header-actions { min-width: 0; }
.header-actions .btn { min-width: 0; white-space: normal; overflow-wrap: break-word;
                       height: auto; min-height: 36px; padding-block: 6px; }

/* Grid and flex children default to min-width:auto, so a single unbreakable
   child sets the whole track's minimum and pushes the page wider than the
   screen. These have to be allowed to be narrower than their content. */
.deals > *, .services-grid > *, .stores > *, .grid-main > *, .stack > *, .sidebar > *,
.section-head > *, .toolbar > *, .store-tile > *, .side-row > *,
.price-row > *, .meta > *, .featured-body > * { min-width: 0; }

/* A centred flex column (align-items:center) sizes its children to their
   content and lets them spill BOTH sides rather than shrinking them, so
   min-width:0 alone does nothing there. "Hostinger" was 188px inside a 138px
   store tile and hung 9px off the page. Cap them at the parent's width so the
   break rule below can do its job. */
.store-tile > *, .thumb-offer > *, .thumb > * { max-width: 100%; }

/* With the minimums released, long words need permission to break. `break-word`
   only breaks a word that cannot fit on a line by itself, so ordinary text is
   untouched: at 200% "subscriptions" breaks but "Services &" stays together. */
h1, h2, h3, p, .hero .eyebrow, .thumb-offer span,
.deal .name, .featured h2, .side-row span, .service .offer,
.price, .price-lg, .was, .store-tile .sname, .store-tile .scount { overflow-wrap: break-word; }

/* A call-to-action label is the other usual page-widener: "Get deal at NordVPN"
   at 200% is wider than a phone. Buttons that fill their card may wrap and grow;
   the small header button keeps its single line. */
.btn-block, .deal .btn, .featured .btn { white-space: normal; height: auto; min-height: 44px; padding-block: 10px; }

/* ---------------------------------------------------------------------------
   Deal-card corner pills — 2026-09-23. Two faults reported on the product
   images: one card showed an empty lime blob, and the rest varied in width.
   --------------------------------------------------------------------------- */

/* The blob: index.html and store.html both render the pill unconditionally from
   offLabel(), which returns '' for a deal with a priceLabel but no `off` and no
   was-price to compute a percentage from — the Fabletics "2 for $24" card. An
   empty badge still paints its background, so a 20x8 lime dot sat on the photo.
   Handling it here rather than in each page's JS covers every hub at once. */
.deal .corner:empty { display: none; }

/* The widths: the pill sized to its text, so "30% off" was 71px while
   "BOGO 20% off" was 114px and "Free shipping" 112px on the same row. They now
   share one width, set just above the longest current label, with the text
   centred. `.badge` is already `white-space: nowrap`, so a longer label in
   future extends the pill rather than wrapping it to a second line. */
.deal .corner { min-width: 116px; justify-content: center; }

/* Deal pages carry one discount pill in the chips row under the breadcrumb.
   Give it the same width as the product-image pills on the home page and the
   hubs, so "50% off" and "BOGO 20% off" look the same size from page to page.
   (On the home page and hubs a small script in the page also equalises the
   pills when the phone's text size setting enlarges them.) */
.article > .chips > .badge-primary { min-width: 116px; justify-content: center; }

/* Above 900px the desktop nav appears and competes for the header row. Letting
   the wordmark wrap there made it stack as UrDeals / Today at ordinary text
   size — the nav links should absorb the squeeze instead, as they did before
   the wordmark was made wrappable. Below 900px the nav is hidden, so the
   wordmark keeps its ability to shrink and stack, which is what large text
   scaling needs. */
@media (min-width: 900px) { .logo { flex-shrink: 0; } }

/* ---------------------------------------------------------------------------
   Bullet lists — 2026-09-23. Reported: the bullets on the About page look too
   large in Instagram's in-app browser, while the same page in the regular
   mobile browser looks right.
   The list text was never the problem — measured, the `li` and the surrounding
   `p` are identical at 16px/26.4px in the same colour, and they scale together.
   What differs is the MARKER: nothing in this stylesheet touched lists, so the
   list-style:disc bullet was drawn by the browser's own default, and engines
   size that glyph differently — an Android WebView renders it noticeably
   heavier than Chrome does. Drawing our own dot removes the browser from the
   decision, so the list looks the same everywhere.
   Sized in `em`, not px, so it stays proportional to the text at any scale
   instead of being locked small when someone turns text scaling up.
   --------------------------------------------------------------------------- */
main ul { list-style: none; padding-left: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
main ul li { position: relative; padding-left: 1.45em; }
main ul li::before {
  content: ""; position: absolute; left: 0.25em; top: 0.62em;
  width: 0.4em; height: 0.4em; border-radius: 50%;
  background: var(--primary); flex-shrink: 0;
}

/* Deal of the day: on a phone the two buttons ("See it at <store>" and
   "Why we picked it") stack. Give them the same full width and the same
   height, so when a larger text size wraps one label onto two lines the other
   button grows to match instead of the pair looking mismatched. */
@media (max-width: 719px) {
  .featured-ctas { display: grid !important; grid-template-columns: 1fr; grid-auto-rows: 1fr; }
}

/* 2026-09-25 (Louis): menu reordered to Today's Deals, Fashion, Beauty, Amazon Picks, Services, Tech,
   By Store. "Amazon Picks" is longer than "Shop", and the one-line menu needs about 1040px, so between
   900 and 1039px the hamburger menu is used instead of letting labels wrap onto two lines.
   2026-09-30 (Louis): "Guides" added after By Store (guides.html). The one-line menu now needs about 1125px
   (measured with Sora/DM Sans), so the hamburger range was 900-1129px.
   2026-10-14: Men’s added after Beauty (+63px measured in DM Sans 500 15px: label 40.7px + 22px gap),
   so the menu needs about 1188px and the hamburger range is now 900-1199px.
   2026-10-14 (Louis: "publish the changes"): menu cut to 8 items - Guides moved to the footer, Tech and Services
   before Amazon Picks. Measured in Chrome: one line with room to spare from 1130px, so the hamburger range is
   900-1129px again. */
.nav a { white-space: nowrap; }
@media (min-width: 900px) and (max-width: 1129px) {
  .nav { display: none; }
  .menu-btn { display: inline-flex; }
  .mobile-nav:not([hidden]) { display: flex !important; }
}

/* 2026-09-25 (Louis): the disclosure sentence is centred, on every page and on the Amazon Picks shop (shop.urdealstoday.com uses the same sentence). */
.disclosure-bar .wrap { justify-content: center; text-align: center; }

/* 2026-09-25 (Louis): one photo backdrop on every deal card - the light grey #EEF0F3 the Amazon Picks shop uses.
   White-background photos (Ulta, Zenni, Lenovo) take on the grey through multiply; retailer photos that are
   already grey (Adidas, Fabletics, Baleaf studio shots) stay close to it. */
.thumb-photo, :root:not([data-theme="light"]) .thumb-photo { background: #EEF0F3; }
.thumb-photo img { mix-blend-mode: multiply; }

/* 2026-09-25 (Louis): one discount pill everywhere - always lavender (no random accent colour), 12px bold,
   right after the struck-through price on grid cards, the featured slide and deal pages. Green "Save $X"
   follows it on the featured slide and deal pages. */
.badge.off-tag, :root:not([data-theme="light"]) .badge.off-tag { background: #F1ECFD; color: #5B21B6; }

/* 2026-09-29 (Louis): card descriptions are equal in size across the grid. The editorial band is
   160-200 characters (claude/urdealstoday-card-description-policy.md), which measures 5-6 lines at 1280px,
   6-7 at the narrowest 3-column width and 4-5 on phones. This caps any note that slips past the band at
   7 lines on the grid cards, so one long description cannot leave blank space on its neighbours.
   The full text still shows on each deal's own page ("Why it's on today's list"). */
.deal .note { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 7; line-clamp: 7; overflow: hidden; }

/* Skip link (2026-10-01, accessibility audit item 3, WCAG 2.4.1): hidden until a keyboard user tabs to it,
   then shown top-left above the disclosure bar. Every page has <a class="skip" href="#main"> right after
   <body> and <main ... id="main">. */
.skip { position: absolute; left: 12px; top: -60px; z-index: 1000; padding: 10px 16px; border-radius: 10px;
  background: var(--primary); color: var(--on-primary); font-weight: 700; text-decoration: none; }
.skip:focus, .skip:focus-visible { top: 12px; color: var(--on-primary); }
