/* Direction A "Markt" (design/design_handoff_bestekortingen_markt). Tokens from its README. */
:root {
  --bg: #f7f5f0; --surface: #fff; --ink: #1c1b18; --ink-inv: #f7f5f0;
  --muted: #4d4a43; --muted2: #6f6a60; --muted3: #8a857a;
  --line: #e4e0d6; --line2: #d9d4c8; --line3: #ece8df; --warm: #f1ede4; --hair: #f0ede6;
  /* dealio brand (logo: design/dealio-logo-source.png; the palette is from design/brand-style-guide-chatgpt.png, the plingpling.be guide): primary red, orange accents, peach */
  --accent: #F44323; --accent-dark: #D8361A; --orange: #FF7043;
  --accent-tint: #FFE8E1; --accent-ink: #B02A10;
  --star: #E8A317;   /* a favourite store's star */
  --hand: "Caveat", "Segoe Print", cursive;
  --display: "Bricolage Grotesque", system-ui, sans-serif;
  --ui: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --header-h: 69px;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
body { margin: 0; background: var(--bg); color: var(--ink); font: 15px/1.45 var(--ui); -webkit-font-smoothing: antialiased; }
a { color: var(--ink); }
a:hover { color: var(--accent); }
button { font-family: inherit; color: var(--ink); cursor: pointer; }
input::placeholder { color: var(--muted3); }
.wrap { max-width: 1320px; margin: 0 auto; padding: 0 20px; }

/* ---- header ---- */
.top { position: sticky; top: 0; z-index: 30; background: rgba(247,245,240,.94); backdrop-filter: blur(10px);
       -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
.top-in { display: flex; align-items: center; gap: 14px; padding-top: 12px; padding-bottom: 12px; }
/* one width in both states (the full logo's), so the search box doesn't move when the logo switches */
.logo { display: flex; align-items: center; flex-shrink: 0; width: 200px; }
.logo img { width: auto; display: block; }
/* the logo with its slogan under it (handwriting, as the site's other notes); scrolled, only the compact logo */
.logo .logo-stack { display: flex; flex-direction: column; align-items: center; }
.logo .logo-full { height: 54px; }
.logo, .logo:hover { text-decoration: none; }
.logo-tag { font: 700 19px/1 var(--hand); color: var(--ink); margin-top: 1px; white-space: nowrap; }
.logo .logo-mark { height: 44px; display: none; }
.top.scrolled .logo .logo-stack { display: none; }
.top.scrolled .logo .logo-mark { display: block; }
.search { position: relative; flex: 1; min-width: 0; max-width: 560px; height: 44px; margin: 0; display: flex; align-items: center;
          gap: 10px; padding: 0 16px; background: var(--surface); border: 1px solid var(--line); border-radius: 999px; }
.search:focus-within { border-color: var(--ink); }
.lens { width: 12px; height: 12px; border: 2px solid var(--muted3); border-radius: 50%; flex-shrink: 0; }
.search input { flex: 1; min-width: 0; align-self: stretch; border: 0; outline: 0; background: transparent; font: 15px var(--ui); color: var(--ink); }   /* the whole box height is tappable */
/* Our own clear button, not the browser's: that one shows only while the field has focus (Chrome) or never
   (iOS Safari), so on a phone a search could only be erased key by key. Shown whenever there is text,
   also text app.js put there (a link, a suggestion): :placeholder-shown follows the value, not typing. */
.search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.qclear { flex: 0 0 auto; width: 32px; height: 32px; margin-right: -10px; border: 0; border-radius: 999px; background: var(--line3);
          color: var(--muted2); font-size: 20px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.qclear:hover { color: var(--ink); }
.search input:placeholder-shown ~ .qclear { display: none; }
.search { padding-right: 5px; }
.qclear { margin-right: 0; }
.qgo { flex: 0 0 auto; height: 34px; padding: 0 18px; border: 0; border-radius: 999px; background: var(--accent); color: #fff;
       font-size: 14px; font-weight: 600; }
.qgo:hover { background: var(--accent-dark); }
.listbtn { margin-left: auto; height: 44px; padding: 0 8px 0 16px; border-radius: 999px; border: 1px solid var(--ink);
           background: var(--ink); color: var(--ink-inv); font-size: 14px; font-weight: 600; display: flex; align-items: center;
           gap: 8px; white-space: nowrap; }
.listbtn span { min-width: 28px; height: 28px; border-radius: 14px; background: var(--accent); color: #fff; font-size: 13px;
                display: flex; align-items: center; justify-content: center; padding: 0 8px; }

/* the link to the remembered selections, beside the list button */
.selbtn { margin-left: auto; height: 44px; padding: 0 8px 0 16px; border-radius: 999px; border: 1px solid var(--line2); background: var(--surface);
          color: var(--ink); font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 8px; white-space: nowrap; text-decoration: none; }
.selbtn:hover { border-color: var(--ink); }
.selbtn span { min-width: 24px; height: 24px; border-radius: 12px; background: var(--accent); color: #fff; font-size: 12px;
               display: flex; align-items: center; justify-content: center; padding: 0 7px; }
.selbtn span[hidden] { display: none; }
.selbtn + .listbtn { margin-left: 8px; }
/* the menu under the header's Mijn selecties button: a selection each, then the overview */
.selmenu { position: absolute; top: calc(100% + 10px); z-index: 60; width: max-content; min-width: 240px; max-width: min(360px, calc(100vw - 16px)); box-sizing: border-box;
           padding: 6px; background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 10px 28px rgba(0,0,0,.16); max-height: 70vh; overflow-y: auto; }
.selmenu::before { content: ""; position: absolute; top: -7px; left: calc(var(--pt, 90%) - 6px); width: 12px; height: 12px; background: var(--surface);
                   border: solid var(--line); border-width: 1px 0 0 1px; transform: rotate(45deg); border-radius: 2px; }
.selmenu button { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; text-align: left; border: 0; background: none; color: var(--ink);
                  font: inherit; font-size: 14px; padding: 10px 12px; border-radius: 10px; cursor: pointer; position: relative; }
.selmenu button:hover, .selmenu button:focus-visible { background: var(--warm); outline: none; }
.selmenu .sm-name { min-width: 0; overflow-wrap: anywhere; }
.selmenu b { flex: 0 0 auto; background: var(--accent); color: #fff; border-radius: 999px; padding: 1px 8px; font-size: 12px; font-weight: 600; }
.selmenu .sm-all { margin-top: 4px; border-top: 1px solid var(--line3); border-radius: 0 0 10px 10px; font-weight: 700; }
.selmenu .sm-none { margin: 0; padding: 10px 12px; color: var(--muted2); font-size: 14px; }
/* the bubble under the header's Mijn selecties button: new promotions since the last visit */
.selhint { position: absolute; top: calc(100% + 10px); z-index: 60; width: min(300px, calc(100vw - 16px)); box-sizing: border-box; padding: 14px 36px 14px 16px;
           background: var(--ink); color: var(--ink-inv); border-radius: 14px; box-shadow: 0 10px 28px rgba(0,0,0,.22); animation: selhint-in .25s ease-out; }
.selhint::before { content: ""; position: absolute; top: -6px; left: calc(var(--pt, 90%) - 6px); width: 12px; height: 12px; background: var(--ink); transform: rotate(45deg); border-radius: 2px; }
.selhint p { margin: 0 0 10px; font-size: 14px; line-height: 1.35; }
.selhint strong { color: #fff; }
.selhint-go { border: 0; border-radius: 999px; background: var(--accent); color: #fff; font: inherit; font-size: 13px; font-weight: 700; padding: 7px 16px; cursor: pointer; }
.selhint-x { position: absolute; top: 6px; right: 6px; width: 28px; height: 28px; border: 0; border-radius: 999px; background: none; color: inherit; opacity: .7; font-size: 18px; line-height: 1; cursor: pointer; }
.selhint-x:hover { opacity: 1; background: rgba(255,255,255,.12); }
@keyframes selhint-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .selhint { animation: none; } }

/* /mijn-selecties/: only the blocks; the app's filters stay in the page for app.js but are not shown */
.selecties:not(.selnew) .filterbar, .selecties:not(.selnew) .sheet, .selecties:not(.selnew) .countrow, .selecties .stats { display: none; }
.selecties:not(.selnew) .layout, .selview .layout { display: block; }
/* the same view inside another page of the app (header link, no reload): that page's own parts are hidden */
.selview .filterbar, .selview .sheet, .selview .countrow, .selview .stats, .selview .intro, .selview .crumbs, .selview .gone,
.selview .faq, .selview .related, .selview .more-ssr { display: none; }
/* adding a selection: the normal page (search, filters, results) under a bar with the pills; its own intro and buttons are out of the way */
.selnew .themes, .selnew .intro, .selnew .crumbs, .selnew .gone, .selnew .faq, .selnew .related, .selnew .more-ssr, .selnew .stats, .selnew #follow, .selnew #sharepage { display: none; }
.selbar { margin: 0 0 14px; }
.selbar .selpills { position: static; padding: 0 0 8px; margin-bottom: 4px; }
.selbarhint { margin: 8px 0 0; }
.selnewpanel { background: var(--accent-tint); border: 1px solid var(--line2); border-radius: 16px; padding: 14px 18px 16px; margin-top: 4px; }
.selnewtitle { margin: 0 0 10px; font: 800 22px/1.2 var(--display); letter-spacing: -.02em; }
.selnewpanel .selnewform { margin-bottom: 0; }
.seltop { grid-column: 1 / -1; margin: 8px 0 20px; }
.seltop h1 { margin: 0 0 6px; font: 800 clamp(30px, 6vw, 52px)/1.05 var(--display); letter-spacing: -.03em; }
.seltop p { margin: 0; color: var(--muted2); max-width: 60ch; }
.selblock { grid-column: 1 / -1; margin: 0 0 20px; min-width: 0; }
.selhead { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px; margin-bottom: 12px; }
.selhead h2 { margin: 0; font-size: 20px; overflow-wrap: anywhere; }
.selpen { border: 0; background: none; color: var(--muted2); cursor: pointer; width: 28px; height: 28px; border-radius: 999px; padding: 0;
          display: inline-flex; align-items: center; justify-content: center; align-self: center; margin-left: -8px; }
.selpen:hover { background: var(--line3); color: var(--ink); }
.selpen[hidden] { display: none; }
.seledit { display: inline-flex; gap: 8px; align-items: center; }
.seledit button { font: inherit; font-size: 14px; font-weight: 600; border-radius: 999px; padding: 6px 14px; cursor: pointer; border: 1px solid var(--line2); background: var(--surface); color: var(--ink); }
.seledit .selsave { background: var(--ink); border-color: var(--ink); color: var(--ink-inv); }
/* the row of pills at the top of Mijn selecties: one per selection with its number; the chosen one is shown in full below */
.selpills { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 8px; position: sticky; top: var(--header-h, 72px); z-index: 25; background: var(--bg); padding: 10px 0 12px; margin-bottom: 8px; }
.selpill { display: inline-flex; align-items: center; gap: 8px; border: 1px solid var(--line2); background: var(--surface); color: var(--ink); border-radius: 999px; padding: 7px 8px 7px 14px;
           font: inherit; font-size: 14px; cursor: pointer; max-width: 100%; }
.selpill:first-child { padding-right: 14px; }
.selpill:hover { border-color: var(--ink); }
.selpill.on { background: var(--ink); border-color: var(--ink); color: var(--ink-inv); }
.selpill span { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.selpill small { min-width: 24px; height: 22px; padding: 0 7px; border-radius: 999px; background: var(--line3); color: var(--ink); font-size: 12px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; }
.selpill.on small { background: rgba(255,255,255,.2); color: inherit; }
.selpill b { background: var(--accent); color: #fff; border-radius: 999px; padding: 1px 8px; font-size: 12px; font-weight: 600; }
.selpill-add { border-style: dashed; padding-right: 14px; font-weight: 600; }
.selpill-add.on { border-style: solid; }
.selnewform { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 0 0 14px; }
.selnewform input { flex: 1 1 320px; min-width: 0; height: 44px; padding: 0 16px; border: 1px solid var(--ink); border-radius: 999px; background: var(--surface); color: var(--ink); font: inherit; font-size: 16px; }
.selsave2 { height: 44px; padding: 0 20px; border: 0; border-radius: 999px; background: var(--accent); color: #fff; font: inherit; font-weight: 700; cursor: pointer; }
.selsave2:disabled { opacity: .45; cursor: not-allowed; }
.selmorerow { text-align: center; margin: 20px 0 0; }
.selmore { border: 1px solid var(--ink); background: var(--surface); color: var(--ink); border-radius: 999px; padding: 10px 24px; font: inherit; font-weight: 600; cursor: pointer; }
.selmore:hover { background: var(--ink); color: var(--ink-inv); }
.selhead .selauto { color: var(--muted2); font-size: 13px; }
.selname { font: inherit; font-size: 20px; font-weight: 700; padding: 2px 8px; border: 1px solid var(--ink); border-radius: 8px; background: var(--surface);
           color: var(--ink); min-width: 0; width: min(100%, 340px); }
.selhead .seln { color: var(--muted2); font-size: 14px; }
.selhead .seln b { background: var(--accent); color: #fff; border-radius: 999px; padding: 1px 8px; font-size: 12px; }
.selhead .linkbtn { font-size: 14px; }
.selhead .selx { margin-left: auto; color: var(--muted2); }
.selcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: 16px; }
.selnone { color: var(--muted2); margin: 0; }

/* autosuggest: under the search, at least as wide, long names wrap */
.suggest { position: absolute; left: 0; top: calc(100% + 6px); z-index: 40; min-width: 100%; width: max-content;
           max-width: min(520px, calc(100vw - 32px)); list-style: none; margin: 0; padding: 4px; background: var(--surface);
           border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 10px 24px rgba(0,0,0,.12); max-height: 360px; overflow-y: auto; }
.suggest li { padding: 8px 10px; border-radius: 8px; cursor: pointer; display: flex; gap: 8px; align-items: baseline; }
.suggest li:hover, .suggest li.on { background: var(--warm); }
.suggest .sk { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted2); flex: 0 0 112px; }
.suggest .sl { min-width: 0; overflow-wrap: anywhere; }
.suggest small { margin-left: auto; padding-left: 12px; color: var(--muted2); }
/* recent searches: removable, and a line to clear them all */
.suggest li.recent { align-items: center; }
.suggest .rm { margin-left: auto; border: 0; background: none; color: var(--muted2); font-size: 18px; line-height: 1;
               width: 28px; height: 28px; border-radius: 999px; cursor: pointer; flex: 0 0 auto; }
.suggest .rm:hover { background: var(--line3); color: var(--ink); }
.suggest li.clearrecent { color: var(--muted2); font-size: 13px; justify-content: center; border-top: 1px solid var(--line3);
                          border-radius: 0 0 8px 8px; margin-top: 2px; }

/* ---- intro ---- */
.intro { padding-top: 36px; padding-bottom: 8px; display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 20px; }
.intro h1 { font: 800 clamp(34px, 5.5vw, 64px)/.98 var(--display); letter-spacing: -.035em; margin: 0; max-width: 14ch; text-wrap: balance;
            position: relative; }
/* the brand's spark strokes after the headline */
.intro h1 .spark { display: inline-block; width: .5em; height: .5em; margin-left: -.2em; vertical-align: .26em;
                   background: url("illustrations/spark.svg") no-repeat center / contain; }
.intro .side { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
.hand { font: 700 26px/1.05 var(--hand); color: var(--accent); transform: rotate(-5deg); text-align: right; }
.intro p { margin: 14px 0 0; font-size: 17px; line-height: 1.5; color: var(--muted); max-width: 52ch; text-wrap: pretty; }
.intro .updated { font-size: 13px; color: var(--muted2); }
@media (max-width: 640px) { .intro .side { align-items: flex-start; } .hand { text-align: left; font-size: 22px; } }
.sub-intro { padding: 12px 0 20px; }
.sub-intro h1 { max-width: none; font-size: clamp(30px, 4vw, 48px); }
/* start page: "61.776 kortingen van deze week" on one line, as big as the screen allows (at most 64 px). On one line
   it is about 15.1 em wide with the tabular digits of the count (measured 2026-09-28); 15.8 keeps it inside the margins. */
.intro:not(.lp-intro) h1 { max-width: none; font-size: min(64px, calc((100vw - 40px) / 15.8)); }   /* sized to fit one line in the webfont; in a fallback font (blocked or not yet loaded) it wraps rather than widening the page (tests/ui/layout.test.mjs) */
.crumbs { font-size: 13px; color: var(--muted2); padding-top: 20px; }

/* ---- filter bar ---- */
.filterbar { position: sticky; top: var(--header-h); z-index: 20; background: var(--bg); }
.barwrap { position: relative; }
.bar { display: flex; gap: 8px; align-items: center; padding-top: 14px; padding-bottom: 10px; overflow-x: auto; scrollbar-width: none;
       cursor: grab; }
.bar.dragging { cursor: grabbing; user-select: none; }
.bar.dragging .chip { pointer-events: none; }
/* ‹ › at the edges while there is more to see that way; the fade makes the cut-off visible */
.arrow { position: absolute; top: 14px; width: 56px; height: 40px; border: 0; font-size: 26px; line-height: 1; z-index: 2;
         display: flex; align-items: center; color: var(--ink); }
.arrow.left { left: 0; padding-left: 12px; justify-content: flex-start; background: linear-gradient(90deg, var(--bg) 55%, transparent); }
.arrow.right { right: 0; padding-right: 12px; justify-content: flex-end; background: linear-gradient(270deg, var(--bg) 55%, transparent); }
.arrow:hover { color: var(--accent); }
.bar::-webkit-scrollbar { display: none; }
/* the subcategory and store rows: under the categories, a little tighter */
.shoprow .bar, .subrow .bar { padding-top: 0; }
.shoprow .arrow, .subrow .arrow { top: 0; }
.shoprow .chip, .subrow .chip { height: 34px; font-size: 13px; }
/* subcategories read as a level of the category, not as more stores: squarer, on a tint (chosen as other chips) */
.subrow .chip { border-radius: 8px; background: var(--warm); border-color: var(--line); }
.cats { display: flex; gap: 8px; }
.btn-filters, .chip { flex-shrink: 0; height: 40px; border-radius: 999px; background: var(--surface); font-size: 14px;
                                 display: flex; gap: 6px; align-items: center; white-space: nowrap; }
.btn-filters { padding: 0 16px; border: 1px solid var(--ink); font-weight: 600; gap: 8px; }
.btn-filters span { background: var(--accent); color: #fff; border-radius: 10px; font-size: 12px; padding: 1px 7px; }
.divider { flex-shrink: 0; width: 1px; height: 24px; background: var(--line2); margin: 0 4px; }
/* the category row: the Filters button, then the scrolling chips with their own arrows */
.fbrow { display: flex; align-items: center; gap: 4px; }
.fbrow > .btn-filters, .fbrow > .divider { margin-top: 4px; }   /* level with the chips (.bar pads 14 above, 10 below) */
.fbrow > .barwrap { flex: 1; min-width: 0; }
.shoprow[hidden] { display: none; }
@media (max-width: 1023.98px) { .pill.favpill { display: none; } }   /* the store row shows a chosen favourite */
.chip { padding: 0 14px; border: 1px solid var(--line2); font-weight: 500; }
.chip small { opacity: .6; font-size: 12px; }
.chip .ico { flex-shrink: 0; margin-left: -2px; }
/* the chosen category in the brand red */
#cats .chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); }
.chip[aria-pressed="true"] { background: var(--ink); color: #fff; border-color: var(--ink); }
.chip.zero { opacity: .45; }
.pills { display: flex; gap: 6px; flex-wrap: wrap; padding-bottom: 10px; }
.pill { height: 30px; padding: 0 10px 0 12px; border-radius: 999px; border: 0; background: var(--accent-tint); color: var(--accent-ink);
        font-size: 13px; font-weight: 600; display: flex; gap: 6px; align-items: center; }
.pill b { font-size: 15px; line-height: 1; font-weight: 400; }
.linkbtn { height: 30px; padding: 0 10px; border: 0; background: transparent; font-size: 13px; text-decoration: underline; color: var(--muted); }

/* ---- grid + card ---- */
main.wrap { padding-top: 8px; padding-bottom: 60px; }
.count { font-size: 14px; color: var(--muted2); margin: 4px 0 14px; }
.count strong { color: var(--ink); font-weight: 700; }
.countrow { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.count:empty { display: none; }
.follow { border: 1px solid var(--line2); background: var(--surface); border-radius: 999px; padding: 6px 14px; font-size: 13px; font-weight: 600; }
.follow:hover { border-color: var(--ink); }
.follow.on { background: var(--accent-tint); border-color: var(--accent-tint); color: var(--accent-ink); }
/* start page: seasonal themes and followed searches above the category tiles */
.themes { grid-column: 1 / -1; display: flex; gap: 12px; flex-wrap: wrap; }
.theme { display: flex; align-items: center; gap: 14px; background: var(--accent-tint); border: 0; border-radius: 18px; padding: 10px 40px 10px 10px;
         font: inherit; color: var(--ink); cursor: pointer; text-align: left; }
.theme:hover { box-shadow: 0 0 0 2px var(--accent) inset; }
.theme-wrap { position: relative; display: flex; }
.thx { position: absolute; top: 6px; right: 6px; width: 28px; height: 28px; border: 0; border-radius: 999px; background: none;
       color: var(--muted2); font-size: 18px; line-height: 1; cursor: pointer; }
.thx:hover { background: rgba(0,0,0,.06); color: var(--ink); }
.theme img { width: 96px; height: 72px; }
.theme > span { display: flex; flex-direction: column; gap: 2px; }
.th-k { font: 700 18px/1 var(--hand); color: var(--accent); }
.theme strong { font: 800 22px/1.1 var(--display); letter-spacing: -.02em; }
.th-n { font-size: 13px; color: var(--muted); font-weight: 600; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: 16px; }
.card { background: var(--surface); border-radius: 18px; padding: 10px; display: flex; flex-direction: column; gap: 10px;
        border: 1px solid var(--line3); min-width: 0; position: relative; }
.card.best { border: 2px solid var(--accent); box-shadow: 0 6px 18px rgba(244,67,35,.14); }
.best-ribbon { position: absolute; top: -11px; left: 50%; transform: translateX(-50%); z-index: 3; background: var(--accent); color: #fff;
               font: 700 12px/1 var(--ui); padding: 6px 12px; border-radius: 999px; white-space: nowrap; }
.card .img { position: relative; aspect-ratio: 4/3; border-radius: 12px; background: #fff; overflow: hidden; }
.card .img > a { text-decoration: none; display: flex; width: 100%; height: 100%; align-items: center; justify-content: center; }
.card .img img { width: 100%; height: 100%; object-fit: contain; }
.card.skel .ph { position: absolute; inset: 0; background: repeating-linear-gradient(135deg, #f1ede4 0 8px, #ebe6db 8px 16px); }
.noimg { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-size: 12px; color: var(--muted3);
         background: repeating-linear-gradient(135deg, #f1ede4 0 8px, #ebe6db 8px 16px); }
.badge { position: absolute; top: 8px; left: 8px; background: var(--accent); color: #fff; font: 800 20px/1.2 var(--display);
         letter-spacing: -.02em; padding: 4px 10px; border-radius: 10px; pointer-events: none; }
.add { position: absolute; top: 8px; right: 8px; height: 34px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--line);
       background: #fff; font-size: 13px; font-weight: 600; }
.add:hover { border-color: var(--ink); }
.add.on { background: var(--ink); border-color: var(--ink); color: #fff; }
.card .body { padding: 0 4px; display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.meta { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; font-weight: 600; }
.ends { color: var(--muted3); white-space: nowrap; }
.ends.soon { color: var(--accent-dark); }
.card h3 { margin: 0; font-size: 15px; line-height: 1.3; font-weight: 600; text-wrap: pretty; overflow-wrap: anywhere;
           display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card h3 a { color: inherit; text-decoration: none; }
.card h3 a:hover { text-decoration: underline; }
.card .brand { font-size: 13px; color: var(--muted2); overflow-wrap: anywhere; }   /* an unbroken 80-character brand widened the whole page (tests/fixture) */
.tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; align-items: flex-start; }
.tag { font-size: 12px; font-weight: 600; padding: 3px 8px; border-radius: 6px; background: var(--warm); color: var(--muted); max-width: 100%; overflow-wrap: anywhere; }
.tag.promo { font-weight: 700; background: var(--ink); color: var(--ink-inv); }
.vars summary { list-style: none; cursor: pointer; }
.vars summary::-webkit-details-marker { display: none; }
.vars summary::after { content: " ▾"; }
.vars[open] summary { background: var(--ink); color: #fff; }
/* the variant list lies over the card, so an open list doesn't stretch the row */
.vars ul { position: absolute; left: 10px; right: 10px; z-index: 5; margin: 6px 0 0; padding: 6px; list-style: none; background: #fff;
           border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 10px 24px rgba(0,0,0,.14); max-height: 280px; overflow-y: auto; font-size: 13px; }
.vars li { display: flex; justify-content: space-between; gap: 10px; padding: 6px; border-bottom: 1px solid var(--hair); }
.vars li:last-child { border-bottom: 0; }
.vars li.more { color: var(--muted2); justify-content: center; }
.vars li a { text-decoration: none; }
.vars li span { white-space: nowrap; font-weight: 600; }
/* The price block (owner's design, 2026-09-29): left what you pay at the till, right the price per item, named. */
.pricebar { margin-top: auto; padding-top: 10px; border-top: 1px dashed var(--line); display: flex; align-items: stretch; gap: 8px; }
.cap { display: block; font: 700 10px/1 var(--ui); letter-spacing: .08em; text-transform: uppercase; color: var(--muted2); }
.pcol { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.now { display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap; margin-top: 6px; }
.now strong { font: 800 28px/1 var(--display); letter-spacing: -.03em; }
.now.l strong { font-size: 22px; }               /* a long amount (€104,00) a size smaller, so both blocks fit */
.now small { font-size: 12px; color: var(--muted2); }
.pnote { font-size: 12px; line-height: 1.3; color: var(--muted); margin-top: 4px; white-space: nowrap; }
/* the old price: darker, heavier and struck by an accent line, so it stays readable as "the old price" */
.pnote s, .ucol s { color: var(--muted); font-weight: 600; text-decoration-color: var(--accent-ink); text-decoration-thickness: 1.5px; }
.pnote s { display: block; margin-top: 2px; font-size: 13px; }   /* the old total under the note, so the note never wraps */
.ucol { flex: 0 1 108px; min-width: 84px; background: var(--accent-tint); border-radius: 12px; padding: 9px 10px; display: flex; flex-direction: column; justify-content: center; }
.ucol .cap { color: var(--accent-ink); }
.ucol strong { margin-top: 6px; font: 800 20px/1 var(--display); letter-spacing: -.03em; }
.ucol strong small { font-size: 11px; font-weight: 600; letter-spacing: 0; color: var(--muted); }
.ucol s { font-size: 13px; margin-top: 3px; }
.usub { font-size: 12px; font-weight: 600; color: var(--muted); margin-top: 3px; line-height: 1.2; }
/* start page: one tile per category */
.cattiles { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.cattile { display: flex; flex-direction: column; gap: 8px; text-align: left; background: var(--surface); border: 1px solid var(--line3);
           border-radius: 18px; padding: 18px 18px 16px; font: inherit; color: var(--ink); cursor: pointer; min-height: 170px; }
.cattile:hover { border-color: var(--ink); }
.ct-pics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 4px; }
.ct-pics img { width: 100%; aspect-ratio: 1; object-fit: contain; background: #fff; border-radius: 10px; border: 1px solid var(--line3); }
.ct-pics .ph { aspect-ratio: 1; border-radius: 10px; background: repeating-linear-gradient(135deg, #f1ede4 0 8px, #ebe6db 8px 16px); }
.ct-name { font: 800 24px/1.1 var(--display); letter-spacing: -.02em; }
.ct-n { font-size: 14px; color: var(--muted); }
.ct-n strong { font: 800 28px/1 var(--display); letter-spacing: -.03em; color: var(--ink); margin-right: 4px; }
.ct-max { font-size: 14px; color: var(--muted); }
.ct-max b { display: inline-block; background: var(--accent); color: #fff; font: 800 16px/1.2 var(--display); padding: 2px 8px;
            border-radius: 8px; margin: 0 2px; }
.ct-shops { margin-top: auto; padding-top: 10px; border-top: 1px dashed var(--line); font-size: 12px; font-weight: 600; color: var(--muted); }
.ct-shops em { font-style: normal; color: var(--muted3); }
.empty { grid-column: 1 / -1; padding: 60px 0; text-align: center; color: var(--muted2); }
.empty button { border: 0; background: none; text-decoration: underline; font-size: inherit; }
.empty .showall { font-size: 16px; font-weight: 600; color: var(--ink); }
.empty .elsewhere { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.empty .elsewhere .chip { text-decoration: none; border: 1px solid var(--line2); background: var(--surface); }
.empty .emptypills { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin: 18px auto 20px; max-width: 560px; }
.empty .emptypills .pill { height: 34px; padding: 0 12px 0 14px; background: var(--accent-tint); color: var(--accent-ink); text-decoration: none; cursor: pointer; }
.empty .emptypills .pill:hover { filter: brightness(.96); }
.empty .emptypills .pill b { font-size: 17px; }
.empty .emptypills .pill small { font-size: 12px; font-weight: 700; padding: 1px 7px; border-radius: 999px; background: #fff; color: var(--accent-ink); }
.empty .emptyclear { margin-top: 4px; font-size: 14px; color: var(--muted); }
.foot { margin-top: 48px; font-size: 12px; color: var(--muted3); max-width: 60ch; }
.foot p { margin: 0 0 6px; }
.foot a { color: inherit; }
.prose { max-width: 62ch; padding: 32px 0; font-size: 17px; line-height: 1.6; }
.prose h1 { font: 800 clamp(30px, 4vw, 48px)/1 var(--display); letter-spacing: -.03em; }

/* ---- sheet (filters) + drawer (list) ---- */
.drawer { position: fixed; inset: 0; z-index: 50; display: flex; justify-content: flex-end; }
/* phones and tablets: the filters are a sheet from the bottom, opened with the Filters button */
@media (max-width: 1023.98px) {
  .sheet { position: fixed; inset: 0; z-index: 50; display: none; align-items: flex-end; justify-content: center; }
  .sheet.open { display: flex; }
  .side-clear { display: none; }
}
.backdrop { position: absolute; inset: 0; background: rgba(20,19,17,.45); }
.sheet-panel { position: relative; width: 100%; max-width: 680px; max-height: 88vh; background: #fff; border-radius: 22px 22px 0 0;
               box-shadow: 0 -10px 40px rgba(0,0,0,.15); display: flex; flex-direction: column; }
.grab { width: 40px; height: 4px; border-radius: 2px; background: var(--line2); margin: 10px auto 0; }
.sheet-head, .drawer-head { display: flex; justify-content: space-between; align-items: center; padding: 10px 22px 14px; border-bottom: 1px solid #eee; }
.sheet-head h2 { margin: 0; font: 800 22px/1.2 var(--display); letter-spacing: -.02em; }
.round { width: 40px; height: 40px; border-radius: 20px; border: 1px solid var(--line); background: #fff; font-size: 20px; flex-shrink: 0; }
.sheet-body { overflow-y: auto; padding: 18px 22px; display: flex; flex-direction: column; gap: 26px; }
.sheet-body h3 { margin: 0 0 10px; font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted2); }
.sheet-body .chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* a list of options with a box and a count (stores, subcategories, kinds, brands) */
.sheet-body .chips.list { flex-direction: column; flex-wrap: nowrap; gap: 0; }
.chips.list .chip { width: 100%; height: auto; min-height: 34px; padding: 4px 2px; border: 0; border-radius: 6px; background: none;
                    font-weight: 400; white-space: normal; text-align: left; gap: 10px; }
@media (hover: hover) { .chips.list .chip:hover { background: var(--warm); } }
.chips.list .chip::before { content: ""; width: 16px; height: 16px; flex-shrink: 0; border: 1.5px solid var(--line2); border-radius: 4px;
                            background: #fff center / 12px no-repeat; margin: 0; font-size: 11px; line-height: 13px; text-align: center; }
.chips.list .chip small { margin-left: auto; padding-left: 8px; }
.chips.list .chip[aria-pressed="true"] { background: none; color: var(--ink); font-weight: 600; }
.chips.list .chip[aria-pressed="true"]::before { border-color: var(--accent); background-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2 5 8.5l4.5-5' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.chips.list.radio-list .chip::before { border-radius: 50%; }
.chips.list.radio-list .chip[aria-pressed="true"]::before { background-image: none; box-shadow: inset 0 0 0 3px #fff; }
.chips.list.short .chip:nth-child(n+9):not([aria-pressed="true"]) { display: none; }
/* the store list: a row per store, its box and a star; starred stores stand first and always show (app.js) */
.shopitem { display: flex; align-items: center; gap: 2px; }
.shopitem[hidden] { display: none; }
.shopitem .chip { flex: 1; min-width: 0; }
.chips.list.short .shopitem:nth-child(n+9):not(.fav):not(:has(.chip[aria-pressed="true"])) { display: none; }
.star { flex-shrink: 0; width: 30px; height: 30px; padding: 0; border: 0; border-radius: 6px; background: none;
        color: var(--line2); font-size: 16px; line-height: 1; cursor: pointer; }
@media (hover: hover) { .star:hover { color: var(--star); background: var(--warm); } }
.star[aria-pressed="true"] { color: var(--star); }
#shoprow .chip.fav::before { content: "★"; color: var(--star); font-size: 12px; margin-right: 1px; }
.listfind { width: 100%; height: 36px; margin: 0 0 6px; padding: 0 12px; border: 1px solid var(--line2); border-radius: 999px;
            background: var(--surface); font: 14px var(--ui); color: var(--ink); }
.linkbtn.more { height: auto; padding: 6px 2px; }
.h3row { display: flex; justify-content: space-between; align-items: center; }
.h3row .linkbtn { height: auto; padding: 0; font-size: 13px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--muted); }
.h3-note { font-size: 11px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--muted3); }

.radios { display: flex; flex-direction: column; gap: 2px; }
.radio { display: flex; align-items: center; gap: 12px; padding: 10px 4px; border: 0; background: transparent; font-size: 15px;
         text-align: left; min-height: 44px; }
.radio .dot { width: 20px; height: 20px; border-radius: 10px; border: 2px solid var(--ink); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.radio[aria-pressed="true"] .dot::after { content: ""; width: 10px; height: 10px; border-radius: 5px; background: var(--ink); }
.toggle { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 12px 0; border: 0;
          border-bottom: 1px solid var(--hair); background: transparent; font-size: 15px; text-align: left; }
.track { width: 44px; height: 26px; border-radius: 13px; background: var(--line2); position: relative; flex-shrink: 0; transition: background .15s; }
.track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 10px; background: #fff;
                box-shadow: 0 1px 3px rgba(0,0,0,.2); transition: left .15s; }
.toggle[aria-pressed="true"] .track { background: var(--accent); }
.toggle[aria-pressed="true"] .track::after { left: 21px; }
.sheet-foot { display: flex; gap: 10px; padding: 14px 22px 20px; border-top: 1px solid #eee; }
.btn-outline { height: 48px; padding: 0 18px; border-radius: 999px; border: 1px solid var(--line2); background: #fff; font-size: 15px; font-weight: 600; }
.btn-primary { flex: 1; height: 48px; border-radius: 999px; border: 0; background: var(--ink); color: #fff; font-size: 15px; font-weight: 600; }

.drawer-panel { position: relative; width: 100%; max-width: 420px; height: 100%; background: #fff; display: flex; flex-direction: column; }
.drawer-head { padding: 18px 22px; }
.drawer-head h2 { margin: 0; font: 800 24px/1.2 var(--display); letter-spacing: -.02em; }
.drawer-head p { margin: 2px 0 0; font-size: 13px; color: var(--muted2); }
.drawer-body { flex: 1; overflow-y: auto; padding: 8px 22px 20px; }
.shopgroup { padding-top: 16px; }
.shopgroup h3 { display: flex; justify-content: space-between; margin: 0 0 6px; font-size: 13px; font-weight: 700; letter-spacing: .04em;
                text-transform: uppercase; color: var(--muted2); }
.li { display: flex; gap: 12px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--hair); }
.li-main { flex: 1; min-width: 0; }
.li-main a { font-size: 14px; font-weight: 600; line-height: 1.3; text-decoration: none; }
.li-main div { font-size: 12px; color: var(--muted2); margin-top: 2px; }
.li.past .li-main { opacity: .55; }
.li-price { font: 800 18px/1 var(--display); white-space: nowrap; text-align: right; }
.li-price small { display: block; font: 500 11px/1.3 var(--ui); color: var(--muted2); margin-top: 2px; }
/* how many times you take the deal */
.qty { display: inline-flex; align-items: center; gap: 4px; margin-top: 6px; }
.qty button { width: 28px; height: 28px; border-radius: 999px; border: 1px solid var(--line2); background: var(--surface);
              font-size: 16px; line-height: 1; color: var(--ink); cursor: pointer; padding: 0; }
.qty button:disabled { opacity: .35; cursor: default; }
.qty span { min-width: 22px; text-align: center; font-weight: 700; font-size: 14px; }
.li .rm { width: 36px; height: 36px; border-radius: 18px; border: 1px solid var(--line); background: #fff; font-size: 16px; color: var(--muted2); flex-shrink: 0; }
.drawer-empty { padding: 48px 0; text-align: center; color: var(--muted2); font-size: 15px; line-height: 1.5; }
.drawer-foot { padding: 16px 22px 22px; border-top: 1px solid #eee; display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.drawer-foot .save-lbl { font-size: 12px; color: var(--muted2); }
.drawer-foot .save-amt { font: 800 28px/1.1 var(--display); color: var(--accent-dark); }
.drawer-foot .sums { display: flex; gap: 22px; }
.drawer-foot .pay-amt { font: 800 28px/1.1 var(--display); color: var(--ink); }
.drawer-foot .btns { display: flex; gap: 8px; }
.drawer-foot button { height: 44px; padding: 0 16px; border-radius: 999px; border: 1px solid var(--line2); background: #fff; font-size: 14px; font-weight: 600; }
body.locked { overflow: hidden; }

@media (max-width: 640px) {
  .wrap { padding-left: 16px; padding-right: 16px; }
  .meta { flex-wrap: wrap; row-gap: 0; }
  .top-in { gap: 10px; }
  .logo { width: 160px; }
  .logo .logo-full { height: 45px; }
  .logo-tag { font-size: 16px; }
  .logo .logo-mark { height: 34px; }
  .listbtn { padding: 0 6px 0 12px; }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .cattiles { grid-template-columns: 1fr; gap: 10px; }
  .cattile { min-height: 0; }
  .card { padding: 8px; border-radius: 16px; gap: 8px; }
  .badge { font-size: 16px; padding: 3px 8px; }
  .add { height: 30px; padding: 0 10px; font-size: 12px; }
  .pricebar { gap: 6px; }
  .now strong { font-size: 22px; }
  .now.l strong { font-size: 18px; }
  .cap { font-size: 9px; letter-spacing: .06em; }
  .pnote { font-size: 11px; }
  .pnote s { font-size: 12px; }
  .ucol { flex-basis: 70px; min-width: 66px; padding: 7px; border-radius: 10px; }
  .ucol strong { font-size: 16px; margin-top: 5px; }
  .ucol s, .usub { display: none; }   /* the block is narrow: the per-kg line and the old unit price are in the popup */
  .sheet-panel { max-height: 92vh; }
}
/* narrow phones (320-380 px, two cards per row): a round + save button so the discount badge stays visible,
   and the long amounts a size smaller */
@media (max-width: 380px) {
  .add { width: 30px; padding: 0; font-size: 0; display: flex; align-items: center; justify-content: center; }
  .add::before { content: "+"; font-size: 18px; font-weight: 700; line-height: 1; }
  .add.on::before { content: "✓"; font-size: 15px; }
  .now.l strong { font-size: 16px; }
  /* 320-380 px: two cards per row leave ~140 px inside a card, too little for two blocks side by side: the per-item price
     becomes a strip under the amount ("PER STUK €1,67") */
  .pricebar { flex-direction: column; gap: 6px; }
  .ucol { flex: none; width: auto; min-width: 0; flex-direction: row; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 6px; padding: 6px 8px; }   /* a long amount wraps under its caption */
  .ucol .cap, .ucol strong { margin-top: 0; white-space: nowrap; }
  .ucol .cap { letter-spacing: .03em; }
  .ucol strong { font-size: 15px; }
}
@media (max-width: 480px) {
  /* logo, search and list button don't fit one phone row: the search goes to a second row */
  .top-in { flex-wrap: wrap; }
  .search { order: 3; flex-basis: 100%; max-width: none; }
  :root { --header-h: 125px; }
}

/* mascot and illustrations (static/illustrations) */
.empty .mascot, .drawer-empty .mascot { width: 200px; max-width: 70%; height: auto; display: inline-block; }   /* dealio/*.webp, transparent */
.ct-name { display: flex; align-items: center; gap: 10px; }
.ct-ill { width: 40px; height: 40px; flex-shrink: 0; }
.pling { position: fixed; left: 50%; bottom: 24px; z-index: 60; display: flex; align-items: center; gap: 10px; padding: 8px 18px 8px 8px;
         background: var(--ink); color: #fff; border-radius: 999px; box-shadow: 0 10px 30px rgba(0,0,0,.2); font-size: 14px;
         transform: translate(-50%, 140%); opacity: 0; transition: transform .25s ease, opacity .25s ease; pointer-events: none; }
.pling.show { transform: translate(-50%, 0); opacity: 1; }
.pling img { width: 44px; height: 44px; }
.pling b { color: #FF7043; font: 700 20px/1 var(--hand); margin-right: 4px; }
/* Loading popup: floats over the page while the store files arrive and the grid fills in behind it.
   The mascot bobs, three dots hop in turn, a bar fills; it fades out when every store is in. */
.loadpop { position: fixed; left: 50%; top: 50%; z-index: 55; display: flex; flex-direction: column; align-items: center;
           gap: 14px; width: min(400px, calc(100vw - 32px)); padding: 28px 32px 30px; text-align: center;
           background: var(--surface); border: 1px solid var(--line2); border-radius: 24px; box-shadow: 0 24px 60px rgba(0,0,0,.22);
           transform: translate(-50%, -50%); transition: opacity .5s ease, transform .5s ease; }
.loadpop.done { opacity: 0; transform: translate(-50%, -50%) scale(.92); pointer-events: none; }
.loadpop > div { width: 100%; }
.loadpop p { margin: 0 0 14px; font: 700 22px/1.25 var(--display); color: var(--ink); }
.loadpop small { display: block; margin-top: 4px; font: 400 14px/1.3 var(--ui); color: var(--muted2); }
.loader { position: relative; display: inline-block; flex-shrink: 0; width: 132px; height: 118px; }
.loader img { width: 132px; height: auto; animation: bob 1.1s ease-in-out infinite; }
.loader i { position: absolute; bottom: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--accent);
            animation: hop .9s ease-in-out infinite; }
.loader i:nth-of-type(1) { left: 45px; }
.loader i:nth-of-type(2) { left: 61px; background: var(--orange); animation-delay: .15s; }
.loader i:nth-of-type(3) { left: 77px; animation-delay: .3s; }
.loadpop .lp-bar { display: block; height: 8px; border-radius: 99px; background: var(--accent-tint); overflow: hidden; }
.loadpop .lp-bar span { display: block; width: 0; height: 100%; border-radius: inherit; background: var(--accent); transition: width .3s ease; }
@keyframes bob { 0%, 100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-10px) rotate(2deg); } }
@keyframes hop { 0%, 60%, 100% { transform: translateY(0); opacity: .5; } 30% { transform: translateY(-9px); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .pling { transition: none; } .loader img, .loader i { animation: none; } .loadpop { transition: none; } }

/* ---- landing pages (pages.py): the server's first view, facts, related pages, site navigation ---- */
.loadpop.ssr { display: none; }
a.cattile { color: inherit; text-decoration: none; }
.crumbs.wrap { padding-top: 16px; }
.crumbs a { color: inherit; }
.facts { margin: 12px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-size: 15px; color: var(--muted); max-width: 70ch; }
.facts li::before { content: "•"; color: var(--accent); margin-right: 8px; }
.more-ssr { text-align: center; margin: 20px 0; }
.more-ssr a { display: inline-block; padding: 10px 18px; border-radius: 999px; background: var(--ink); color: #fff; text-decoration: none; font-weight: 600; }
.related { margin-top: 40px; display: grid; gap: 20px; }
.related h2, .sitenav h2 { margin: 0 0 8px; font: 700 17px/1.2 var(--display); }
.related p { margin: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.related a { display: inline-flex; gap: 6px; align-items: center; padding: 6px 12px; border: 1px solid var(--line2); border-radius: 999px;
             background: var(--surface); color: var(--ink); text-decoration: none; font-size: 13px; }
.related a:hover { border-color: var(--ink); }
.related small { color: var(--muted3); }
.sitenav { display: grid; gap: 14px; margin-bottom: 24px; padding-top: 24px; border-top: 1px solid var(--line); }
.sitenav p { margin: 0; line-height: 1.8; }
.sitenav a { color: var(--muted2); }

/* ---- a card in a popup (static/cardpop.js) ---- */
.cardpop { width: min(480px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); padding: 0; border: 0; border-radius: 24px;
           background: var(--surface); color: var(--ink); overflow: auto; box-shadow: 0 30px 80px rgba(0,0,0,.3); }
.cardpop::backdrop { background: rgba(20, 18, 14, .5); }
.cardpop .popx { position: sticky; top: 12px; float: right; margin: 10px 12px -50px 0; z-index: 3; width: 40px; height: 40px;
                 border-radius: 50%; border: 0; background: var(--surface); box-shadow: 0 2px 8px rgba(0,0,0,.15); font-size: 22px; }
.card.big { box-shadow: none; border: 0; padding: 60px 16px 16px; cursor: default; }   /* the × gets its own row */
.card.big .vars { flex-basis: 100%; }
.card.big .vars summary { display: inline-flex; }
.card.big .img { aspect-ratio: auto; height: clamp(120px, 24dvh, 220px); }   /* the whole card fits the screen */
.card.big h3 { font-size: 20px; display: block; overflow: visible; }   /* the popup shows the whole title; the grid cuts it at 2 lines */
.card.big .cap { font-size: 11px; }
.card.big .now { margin-top: 8px; }
.card.big .now strong { font-size: 40px; }
.card.big .now.l strong { font-size: 32px; }
.card.big .pnote { font-size: 14px; }
.card.big .pnote s { font-size: 15px; }
.card.big .ucol { flex-basis: 148px; padding: 12px 14px; border-radius: 14px; }
.card.big .ucol strong { font-size: 26px; margin-top: 8px; }
.card.big .ucol s, .card.big .usub { display: block; font-size: 14px; }
.card.big .vars ul { position: static; max-height: 18dvh; overflow: auto; margin-top: 8px; box-shadow: none; border: 1px solid var(--line3); }
.card.big .tags { flex-wrap: wrap; }
.gotoshop { display: flex; align-items: center; justify-content: center; height: 52px; margin-top: 8px; border-radius: 999px;
            background: var(--accent); color: #fff; font: 700 17px var(--display); text-decoration: none; }
.gotoshop:hover { background: var(--accent-dark); }
.goto-note { margin: 6px 0 0; text-align: center; font-size: 12px; color: var(--muted2); }
.grid .card:not(.skel) { cursor: pointer; }
/* short screens (small phones): tighter, so the whole card still fits without scrolling */
@media (max-height: 760px) {
  .card.big { padding: 50px 12px 12px; gap: 6px; }
  .card.big .img { height: clamp(100px, 20dvh, 180px); }
  .card.big h3 { font-size: 17px; }
  .card.big .vars ul { max-height: 14dvh; }
  .gotoshop { height: 46px; margin-top: 4px; }
  .goto-note { display: none; }
}
.countup { color: var(--accent); font-variant-numeric: tabular-nums; }

/* landing page intro: the title left, the page's facts in a panel right (under it on phones) */
.lp-intro { align-items: flex-start; flex-wrap: nowrap; }
.lp-intro > div:first-child { flex: 1 1 auto; min-width: 0; }
.lp-intro h1 { max-width: 16ch; }
.lp-intro .lp-lead { margin: 16px 0 0; max-width: 46ch; }
.lp-intro .updated { margin-top: 10px; }
.stats { flex: 0 1 440px; min-width: 0; display: flex; flex-direction: column; gap: 12px; padding: 18px 20px;
         background: var(--surface); border: 1px solid var(--line3); border-radius: 20px; box-shadow: 0 6px 24px rgba(0,0,0,.05); }
.stats p { margin: 0; max-width: none; font-size: 14px; line-height: 1.4; color: var(--ink); }   /* not .intro p */
.stats small { display: block; margin-bottom: 4px; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted3); }
.stats .st-head { font-size: 15px; color: var(--muted); }
.st-head strong { font: 800 34px/1 var(--display); letter-spacing: -.02em; color: var(--ink); margin-right: 4px; }
.st-best { display: flex; gap: 12px; align-items: center; padding: 10px 12px; border-radius: 14px; background: var(--accent-tint); font-size: 14px; line-height: 1.35; }
.st-best small { color: var(--accent-dark); }
.st-best em { font-style: normal; color: var(--muted2); }
.st-pct { flex-shrink: 0; padding: 6px 10px; border-radius: 10px; background: var(--accent); color: #fff; font: 800 20px/1 var(--display); }
.st-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.st-chips a, .st-chips span { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 999px;
                             border: 1px solid var(--line2); background: var(--bg); color: var(--ink); text-decoration: none; font-size: 13px; }
.st-chips a:hover { border-color: var(--ink); }
.st-chips b { font-weight: 600; color: var(--muted2); font-size: 12px; }
.stats .st-soon { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--accent-dark); font-weight: 600; }
@media (max-width: 760px) {
  .lp-intro { flex-direction: column; flex-wrap: wrap; }
  .stats { flex-basis: auto; width: 100%; }
}

/* landing page questions (pages._summary faq) */
.faq { margin-top: 40px; max-width: 760px; }
.faq h2 { margin: 0 0 12px; font: 700 22px/1.2 var(--display); }
.faq details { border-top: 1px solid var(--line); padding: 12px 0; }
.faq details:last-child { border-bottom: 1px solid var(--line); }
.faq summary { cursor: pointer; font-weight: 600; font-size: 16px; list-style: none; display: flex; justify-content: space-between; gap: 12px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-size: 20px; line-height: 1; }
.faq details[open] summary::after { content: "−"; }
.faq p { margin: 8px 0 0; color: var(--muted); line-height: 1.5; }
/* sharing: the page (count row) and a promotion (popup) */
/* sort: a dropdown next to the count */
.sortsel { margin-left: auto; display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted2); }
.sortsel select { height: 36px; padding: 0 34px 0 14px; border: 1px solid var(--line2); border-radius: 999px; appearance: none;
                  -webkit-appearance: none; font: 600 14px var(--ui); color: var(--ink); cursor: pointer;
                  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5 6 7.5l3-3' fill='none' stroke='%231c1b18' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") right 12px center / 12px no-repeat; }
.sortsel select:hover { border-color: var(--ink); }
/* a card's saving in euros */
.save { align-self: flex-start; margin-top: 2px; padding: 3px 8px; border-radius: 6px; background: var(--accent-tint); color: var(--accent-ink);
        font-size: 13px; font-weight: 700; }
.countrow .follow.share + .follow { margin-left: 8px; }
.sharedeal { display: block; width: 100%; height: 44px; margin-top: 8px; border-radius: 999px; border: 1px solid var(--line2);
             background: var(--surface); color: var(--ink); font: 600 15px var(--ui); }
.sharedeal:hover { border-color: var(--ink); }
/* where there is no share sheet: WhatsApp, mail, copy (static/cardpop.js) */
.sharemenu { position: fixed; z-index: 70; min-width: 220px; padding: 6px; background: var(--surface); border: 1px solid var(--line2); border-radius: 14px;
             box-shadow: 0 8px 28px rgba(28, 27, 24, .16); display: flex; flex-direction: column; }
.sharemenu a, .sharemenu button { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 12px; border: 0; border-radius: 10px;
             background: none; color: var(--ink); font: 600 15px var(--ui); text-align: left; cursor: pointer; text-decoration: none; }
.sharemenu a + a, .sharemenu a + button { border-top: 1px solid var(--line3); border-radius: 0; }
.sharemenu svg { flex: 0 0 auto; color: var(--accent); }
.sharemenu a:hover, .sharemenu button:hover, .sharemenu a:focus-visible, .sharemenu button:focus-visible { background: var(--warm); color: var(--ink); outline: none; }
@media (max-height: 760px) { .sharedeal { height: 40px; margin-top: 6px; } }

/* ---- wide screens: the filters are a sidebar left of the results; stores and subcategories are in it ---- */
.layout { display: block; }
@media (min-width: 1024px) {
  .layout { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 24px; align-items: start; }
  .sheet { position: sticky; top: calc(var(--header-h) + var(--bar-h, 64px) + 8px); z-index: 1;
           max-height: calc(100vh - var(--header-h) - var(--bar-h, 64px) - 16px); overflow-y: auto; scrollbar-width: thin; }
  .sheet .backdrop, .sheet .grab, .sheet .round, .sheet-foot { display: none; }
  .sheet-panel { position: static; max-width: none; max-height: none; border-radius: 18px; box-shadow: none; border: 1px solid var(--line3); }
  .sheet-head { padding: 16px 18px 8px; border-bottom: 0; }
  .sheet-head h2 { font-size: 20px; }
  .sheet-body { overflow: visible; padding: 6px 18px 18px; gap: 20px; }
  .sheet-body h3 { margin-bottom: 6px; }
  .toggle { font-size: 14px; padding: 9px 0; }
  #open-filters, #open-filters + .divider, .shoprow, .subrow { display: none !important; }
}
@media (max-width: 640px) {
  /* the count on its own line, then the sort dropdown (full width) and Deel side by side */
  .count { flex-basis: 100%; margin-bottom: 0; }
  /* at least 180 px: with "Volg deze zoekopdracht" beside Deel, a min-width of 0 squeezed it to a sliver ("K") */
  .sortsel { margin-left: 0; flex: 1 1 180px; min-width: 180px; }
  .sortsel span { display: none; }
  .sortsel select { width: 100%; }
  .countrow { row-gap: 8px; margin-bottom: 12px; align-items: center; }
  .qgo { padding: 0 14px; }
}
@media (max-width: 400px) {
  /* logo and list button on one row (at 375 px the button wrapped to a row of its own: 50 px more sticky header) */
  .logo { width: auto; }
  .logo .logo-full { height: 40px; }
  .logo-tag { font-size: 14px; }
  .logo .logo-mark { height: 32px; }
}
@media (max-width: 340px) { .logo .logo-full { height: 32px; } .logo-tag { font-size: 12px; } .listbtn { padding-left: 10px; } }
@media (max-width: 380px) { .save { font-size: 12px; padding: 2px 6px; } }

/* Phones and small tablets up to 820 px (owner, 2026-09-28: the header was cramped: on phones all 123 px of it
   stayed on screen while scrolling, and from 481 to about 820 px the search box shrank to a few pixels).
   Row 1 is the logo, row 2 the search with a round search button and the list as a round icon with its
   count. The header sticks with its logo row scrolled away (a negative sticky top), so only the search row
   stays on screen, with no layout change while scrolling; app.js headerH() counts only that part. */
@media (max-width: 820px) {
  :root { --logo-row: 60px; }
  .top { top: calc(8px - var(--logo-row)); }   /* 8 px above the search stay: room for the list count's badge */
  .top-in { flex-wrap: wrap; gap: 0 8px; padding-top: 0; padding-bottom: 10px; }
  .logo { flex-basis: 100%; width: auto; height: var(--logo-row); align-items: flex-start; padding-top: 5px; }
  .logo .logo-stack, .top.scrolled .logo .logo-stack { display: flex; }
  .logo .logo-full { height: 38px; }
  .logo-tag { font-size: 16px; }
  .logo .logo-mark, .top.scrolled .logo .logo-mark { display: none; }
  .search { order: 2; flex: 1 1 0; min-width: 0; padding-left: 16px; }
  .lens { display: none; }
  .qgo { width: 36px; height: 36px; padding: 0; font-size: 0;
         background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='m15.5 15.5 5 5'/%3E%3C/svg%3E") center / 18px no-repeat; }
  .selbtn { order: 3; position: relative; width: 44px; margin-left: 0; padding: 0; justify-content: center; font-size: 0; }
  .selbtn::before { content: "☆"; font-size: 22px; line-height: 1; color: var(--ink); }
  .selbtn span { position: absolute; top: -5px; right: -5px; min-width: 22px; height: 22px; padding: 0 5px; font-size: 12px; border: 2px solid var(--bg); }
  .selbtn + .listbtn { margin-left: 0; }
  .listbtn { order: 3; position: relative; width: 44px; margin-left: 0; padding: 0; justify-content: center; font-size: 0; }
  .listbtn::before { content: ""; width: 20px; height: 20px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f7f5f0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6h11M9 12h11M9 18h11'/%3E%3Ccircle cx='4.5' cy='6' r='1' fill='%23f7f5f0'/%3E%3Ccircle cx='4.5' cy='12' r='1' fill='%23f7f5f0'/%3E%3Ccircle cx='4.5' cy='18' r='1' fill='%23f7f5f0'/%3E%3C/svg%3E") center / contain no-repeat; }
  .listbtn span { position: absolute; top: -5px; right: -5px; min-width: 22px; height: 22px; padding: 0 5px;
                  font-size: 12px; border: 2px solid var(--bg); }
}

/* Touch screens below 1024 px: no arrow buttons over the chip rows (a swipe scrolls them); the edge where
   there is more fades out instead (app.js sets .more-l / .more-r). */
@media (max-width: 1023.98px) and (pointer: coarse) {
  .barwrap .arrow { display: none !important; }
  .bar.more-r { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
                mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent); }
  .bar.more-l { -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px);
                mask-image: linear-gradient(90deg, transparent, #000 28px); }
  .bar.more-l.more-r { -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
                       mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent); }
}
.chip .cl-short { display: none; }
@media (max-width: 400px) { .chip .cl-full { display: none; } .chip .cl-short { display: inline; } }

/* Wide screens (owner, 2026-09-28): no pill row; the sidebar shows the chosen filters, and the count line
   says how many are on, with Wis alles. Phones keep the pills: their filters are in a closed sheet. */
.activef { display: none; }
@media (min-width: 1024px) {
  .pills { display: none !important; }
  .countrow .count { margin-right: 0; }
  .activef:not([hidden]) { display: block; margin: 4px auto 14px -7px; font-size: 14px; color: var(--muted2); }   /* -7: the row gap (12) down to a word space */
  .activef .linkbtn { height: auto; padding: 0; font-size: 14px; }
}

/* Touch screens: tap targets of at least 44 px (owner, 2026-09-28, after a mobile audit found 30 px ones).
   The favourite star and its store row grow to 44 px; a pill and its Wis alles keep a slim look (34 px)
   with an invisible 44 px tap area around them, the rows of pills spaced so those areas don't overlap. */
@media (pointer: coarse) {
  .shopitem .chip { min-height: 44px; }
  .star { width: 44px; height: 44px; font-size: 18px; }
  .pills { gap: 10px 6px; padding-top: 6px; }   /* room for the top row's tap area below the category bar */
  .pill, .pills .linkbtn { position: relative; height: 34px; }
  .pill::after, .pills .linkbtn::after { content: ""; position: absolute; inset: -5px -3px; }
}
/* touch screens: the small controls at least 36 px to tap (the card's save button, the variants tag, the list's
   - and +, a theme's x, "Meer ...", Deel/Volg); measured 23-31 px on phones on 2026-09-28 */
@media (pointer: coarse) {
  .add { height: 36px; min-width: 36px; }
  .vars summary.tag { display: inline-flex; align-items: center; min-height: 34px; padding: 0 10px; }
  .qty button { width: 36px; height: 36px; }
  .thx { width: 36px; height: 36px; top: 2px; right: 2px; }
  .linkbtn.more { padding: 9px 2px; }
  .follow { min-height: 36px; }
}
@media (pointer: coarse) and (max-width: 380px) { .add { width: 36px; } }
/* the card's save button: seen at 36 px, tapped at 44 (owner, 2026-09-28): an invisible area 5 px around it (46 px), inside
   the picture's 8 px margin, so a bigger button doesn't cover more of a small product picture */
@media (pointer: coarse) {
  .add::after { content: ""; position: absolute; inset: -6px; }   /* from inside the 1 px border: 5 px beyond the button, 46 px */
}

/* Touch screens, more 44 px tap targets (owner, 2026-09-28, after a tap-target audit): the store rows' box to the
   row's full 44 px (".chips.list .chip" set 34 over ".shopitem .chip"), and invisible 44 px tap areas for the search
   button, the breadcrumb link and the facts panel's links, without moving anything. */
@media (pointer: coarse) {
  .chips.list .shopitem .chip { min-height: 44px; }
  .qgo { position: relative; }
  .qgo::after { content: ""; position: absolute; inset: -5px; }
  .crumbs a { display: inline-block; padding: 14px 0; margin: -14px 0; }
  .st-chips a { position: relative; min-height: 38px; }
  .st-chips a::after { content: ""; position: absolute; inset: -4px; }   /* 3 px beyond its 1 px border: half the 6 px gap */
}
/* the empty state's "Wis filters" and "Toon alle" were 21 px tall on phones */
@media (pointer: coarse) { .empty button { min-height: 36px; padding: 0 8px; } }

/* a landing page kept without (enough) promotions: what it had the last time (pages.py) */
.gone { margin: 4px 0 16px; padding: 16px 18px; background: var(--surface); border: 1px solid var(--line3); border-radius: 18px; }
.gone h2 { margin: 0 0 6px; font: 700 18px/1.25 var(--display); }
.gone p { margin: 4px 0; font-size: 14px; color: var(--muted); }
.gone ul { list-style: none; margin: 10px 0 6px; padding: 0; display: grid; gap: 8px; }
.gone li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; padding: 8px 0; border-top: 1px dashed var(--line); font-size: 14px; }
.gone li:first-child { border-top: 0; }
.gone .gt { font-weight: 600; flex: 1 1 220px; min-width: 0; overflow-wrap: anywhere; }
.gone .gt a { text-decoration: none; }
.gone .gs, .gone .gv { color: var(--muted2); font-size: 13px; }
.gone .gn { font-size: 13px; color: var(--muted2); margin-top: 8px; }

/* the active filters at the top of the filter panel (sidebar, phone sheet): app.js pills() */
.side-pills { display: flex; flex-wrap: wrap; gap: 6px; flex-shrink: 0; max-height: 30vh; overflow-y: auto; padding: 2px 22px 12px; }
/* in the sidebar the whole panel scrolls (.sheet): the pills stay at its top while the lists move */
@media (min-width: 1024px) { .side-pills { position: sticky; top: 0; z-index: 2; background: var(--surface); padding: 6px 18px 10px; border-bottom: 1px solid var(--line3); } }
@media (pointer: coarse) { .side-pills { gap: 10px 6px; padding-top: 8px; } }

/* iOS Safari zooms into a text field or select set below 16px when it gets focus, and the page stays zoomed (found by
   tests/ui/layout.test.mjs: the search box was 15px, the sort select 14px). */
@media (max-width: 767px), (pointer: coarse) {
  .search input, .sortsel select, .listfind { font-size: 16px; }
}

/* 404 page (templates/404.html, shown by nginx for an unknown address) */
.notfound { text-align: center; padding: 28px 0 56px; }
.notfound img { display: block; margin: 0 auto 8px; width: min(480px, 92%); height: auto; }
.notfound h1 { margin: 0 0 8px; font: 800 28px/1.15 var(--display); letter-spacing: -.02em; }
.notfound p { margin: 0 0 12px; color: var(--muted2); }
.notfound-go { display: inline-block; height: 44px; line-height: 44px; padding: 0 22px; border-radius: 999px; background: var(--accent); color: #fff; font-weight: 700; text-decoration: none; margin-right: 10px; }

/* mascots on the landing pages "vanaf N% korting" (beside the headline), the kept page without promotions, and the About page */
.lp-mascot { width: 132px; height: auto; align-self: center; }
@media (max-width: 640px) { .lp-mascot { display: none; } }
.gone-ill { display: block; width: 160px; height: auto; margin: 0 0 6px; }
.prose .prose-ill { float: right; width: 170px; height: auto; margin: 0 0 12px 22px; }
.prose .prose-ill.left { float: left; margin: 4px 22px 12px 0; width: 150px; }
.prose h2 { clear: both; }
.prose code { overflow-wrap: anywhere; }   /* the MCP address on the about page is one 40-character word: it scrolled the page sideways on phones */
@media (max-width: 640px) { .prose .prose-ill, .prose .prose-ill.left { float: none; display: block; margin: 0 auto 12px; width: 140px; } }
.empty .elsewhere-h { margin: 18px 0 8px; font-size: 14px; color: var(--muted2); }

/* Search help: the (?) in the search box and the dialog it opens (templates/base.html) */
.qhelp { position: relative; flex: 0 0 auto; width: 32px; height: 32px; border: 0; background: transparent;
         color: var(--muted2); font: 600 13px/1 var(--ui); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.qhelp::before { content: ""; position: absolute; inset: 4px; border: 1px solid var(--line2); border-radius: 50%; }   /* 24px circle in a 32px tap target */
.qhelp:hover, .qhelp:focus-visible { color: var(--ink); }
.qhelp:hover::before, .qhelp:focus-visible::before { border-color: var(--ink); }
.qhelpdlg { width: min(520px, calc(100vw - 32px)); max-height: 88vh; overflow: auto; padding: 24px 24px 20px; border: 0; border-radius: 18px;
            background: var(--surface); color: var(--ink); font-family: var(--ui); }
.qhelpdlg::backdrop { background: rgba(28, 27, 24, .45); }
.qhelpdlg h2 { margin: 0 32px 8px 0; font: 800 22px/1.2 var(--display); }
.qhelp-x { position: absolute; top: 12px; right: 12px; width: 36px; height: 36px; border: 0; border-radius: 50%; background: var(--line3);
           color: var(--muted2); font-size: 22px; line-height: 1; cursor: pointer; }
.qhelp-lead, .qhelp-note { margin: 0 0 12px; color: var(--muted); font-size: 15px; line-height: 1.45; }
.qhelp-note { margin: 14px 0 0; font-size: 13px; color: var(--muted2); }
.qhelp-list { margin: 0; }
.qhelp-list dt { margin-top: 12px; }
.qhelp-list dd { margin: 4px 0 0; font-size: 14px; line-height: 1.45; color: var(--muted); }
.qhelp-list code { font: 600 14px ui-monospace, SFMono-Regular, Menlo, monospace; }
.qhelp-list dt a { display: inline-block; padding: 4px 10px; border-radius: 8px; background: var(--accent-tint); color: var(--accent-ink); text-decoration: none; }
.qhelp-list dt a:hover { background: var(--warm); }
.qhelp-list dd code { padding: 0 4px; border-radius: 4px; background: var(--warm); }

/* ---- micro-animations (first batch) ----
   Only transform and opacity move, 120 to 260 ms, like the "Pling" toast. Opening is animated; closing is not (it stays instant, so nothing
   waits on an animation). One prefers-reduced-motion block at the end switches all of these off. */
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pop-in { from { opacity: 0; transform: translateY(12px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes sheet-up { from { opacity: 0; transform: translateY(36px); } to { opacity: 1; transform: none; } }
@keyframes drawer-in { from { opacity: 0; transform: translateX(32px); } to { opacity: 1; transform: none; } }
@keyframes add-pop { 0% { transform: scale(1); } 40% { transform: scale(1.18); } 100% { transform: scale(1); } }
@keyframes count-bump { 0% { transform: scale(1); } 40% { transform: scale(1.3); } 100% { transform: scale(1); } }

/* buttons and chips: state changes ease instead of flipping, and a press gives a little */
.chip, .pill, .btn-filters, .listbtn, .selbtn, .add { transition: background-color .15s, border-color .15s, color .15s, opacity .2s, transform .12s; }
.chip:active, .pill:active, .btn-filters:active, .listbtn:active, .selbtn:active, .add:active { transform: scale(.97); }
/* a deal was just saved: its button pops, the count on the list button bumps */
.add.pop { animation: add-pop .28s ease-out; }
#listcount.bump { animation: count-bump .26s ease-out; }

/* cards lift a little under a pointer that hovers (a tap on touch has no hover, so nothing sticks) */
@media (hover: hover) {
  .grid .card:not(.skel) { transition: transform .15s ease, box-shadow .15s ease; }
  .grid .card:not(.skel):hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(28, 27, 24, .09); }
  .grid .card.best:not(.skel):hover { box-shadow: 0 10px 24px rgba(244, 67, 35, .2); }
}

/* the card popup, the filters sheet (phones and tablets) and the list drawer ease in */
.cardpop[open] { animation: pop-in .22s ease-out; }
.cardpop[open]::backdrop { animation: fade-in .22s ease-out; }
@media (max-width: 1023.98px) {
  .sheet.open .sheet-panel { animation: sheet-up .26s cubic-bezier(.2, .8, .2, 1); }
  .sheet.open .backdrop { animation: fade-in .2s ease-out; }
}
.drawer:not([hidden]) .drawer-panel { animation: drawer-in .26s cubic-bezier(.2, .8, .2, 1); }
.drawer:not([hidden]) .backdrop { animation: fade-in .2s ease-out; }

@media (prefers-reduced-motion: reduce) {
  .chip, .pill, .btn-filters, .listbtn, .selbtn, .add, .grid .card:not(.skel) { transition: none; }
  .chip:active, .pill:active, .btn-filters:active, .listbtn:active, .selbtn:active, .add:active, .grid .card:not(.skel):hover { transform: none; }
  .add.pop, #listcount.bump, .cardpop[open], .cardpop[open]::backdrop, .sheet.open .sheet-panel, .sheet.open .backdrop,
  .drawer:not([hidden]) .drawer-panel, .drawer:not([hidden]) .backdrop { animation: none; }
}

/* ---- micro-animations (second batch): changed results, count line, skeletons, mascots, page navigation ---- */
@keyframes card-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes tick { from { opacity: .35; } to { opacity: 1; } }
@keyframes shimmer { to { transform: translateX(100%); } }
@keyframes mascot-in { from { opacity: 0; transform: scale(.92); } to { opacity: 1; transform: none; } }
@keyframes mascot-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }

/* a changed result: the first cards ease in (app.js adds .fresh for 400 ms after a redraw that is not the first, partial or a scroll append) */
.grid.fresh .card:nth-child(-n+12) { animation: card-in .2s ease-out both; }
.count.tick { animation: tick .3s ease-out; }

/* loading placeholders: a light band sweeps across the striped picture box (.img clips it) */
.card.skel .ph::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%);
                        background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .6) 50%, transparent 70%); animation: shimmer 1.4s ease-in-out infinite; }

/* the mascots on empty and 404 pages appear with a small pop and float a few times, then rest */
.empty .mascot, .gone-ill, .notfound img { animation: mascot-in .35s ease-out, mascot-float 3s ease-in-out .35s 3; }

/* a click on a link to another page of the site cross-fades instead of cutting (browsers that support it; the in-page filtering is not a navigation) */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  ::view-transition-group(root) { animation-duration: .18s; }
}

@media (prefers-reduced-motion: reduce) {
  .grid.fresh .card, .count.tick, .card.skel .ph::after, .empty .mascot, .gone-ill, .notfound img { animation: none; }
}

/* ---- micro-animations (third batch): closing, list rows, checkboxes, suggestions, the star, pills ---- */
@keyframes ghost-fade { from { opacity: 1; } to { opacity: 0; } }
@keyframes ghost-pop { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(8px) scale(.97); } }
@keyframes ghost-down { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(36px); } }
@keyframes ghost-right { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(32px); } }
@keyframes ghost-left { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(-28px); } }
@keyframes ghost-shrink { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(.7); } }
@keyframes row-flash { from { background-color: var(--accent-tint); } to { background-color: transparent; } }
@keyframes suggest-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@keyframes pill-in { from { opacity: 0; transform: scale(.8); } to { opacity: 1; transform: none; } }

/* Things that close at once leave a visual copy that fades away (list.js ghostOut): the copy sits fixed where the original was and ignores the pointer.
   The copy of the popup is a plain div, so it does not match .cardpop[open] and does not play the opening animation again. */
.ghost { position: fixed; margin: 0; z-index: 2000; pointer-events: none; animation-duration: .18s; animation-timing-function: ease-in; animation-fill-mode: forwards; }
.ghost.ghost-dim { inset: 0; width: auto; height: auto; background: rgba(20, 19, 17, .45); animation-name: ghost-fade; z-index: 1999; }
.ghost.ghost-pop { animation: ghost-pop .18s ease-in forwards; }
.ghost.ghost-down { animation: ghost-down .2s ease-in forwards; }
.ghost.ghost-right { animation: ghost-right .2s ease-in forwards; }
.ghost.ghost-left { animation: ghost-left .18s ease-in forwards; background: var(--surface, #fff); }
.ghost.ghost-shrink { animation: ghost-shrink .15s ease-in forwards; }

/* the deal saved last is highlighted once in the list drawer */
.li.justadded { animation: row-flash 1.4s ease-out; }

/* a filter checkbox: the tick grows and the colours ease (the box is a ::before; a background image cannot fade, its size can) */
.chips.list .chip::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2 5 8.5l4.5-5' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
                            background-size: 0; transition: background-color .15s, border-color .15s, background-size .15s ease-out, box-shadow .15s; }
.chips.list .chip[aria-pressed="true"]::before { background-size: 12px; }
.chips.list.radio-list .chip[aria-pressed="true"]::before { background-size: 0; }

/* the search suggestions drop in, the remembered star pops, a new pill pops in */
.suggest:not([hidden]) { animation: suggest-in .14s ease-out; }
.follow.popstar { animation: add-pop .3s ease-out; }
.pill.new { animation: pill-in .2s ease-out; }

@media (prefers-reduced-motion: reduce) {
  .ghost { display: none; }
  .li.justadded, .suggest:not([hidden]), .follow.popstar, .pill.new { animation: none; }
  .chips.list .chip::before { transition: none; }
}

/* the account panel of Mijn selecties (static/account.js): mail alerts per selection; and the pages the mails link to */
.acct { display: none; margin: 0 0 22px; padding: 16px 20px 18px; background: var(--surface); border: 1px solid var(--line); border-radius: 16px; max-width: 760px; }
.selecties .acct:not([hidden]), .selview .acct:not([hidden]) { display: block; }
.acct h2 { margin: 0 0 6px; font: 700 20px/1.2 var(--display); }
.acct p { margin: 6px 0; color: var(--muted); }
.acct-form { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0; }
.acct-form input { flex: 1 1 240px; min-width: 0; height: 44px; padding: 0 16px; border: 1px solid var(--line2); border-radius: 999px; font: inherit; background: var(--bg); color: var(--ink); }
.acct-form button { height: 44px; padding: 0 20px; border: 0; border-radius: 999px; background: var(--accent); color: #fff; font: inherit; font-weight: 700; }
.acct-form button:hover { background: var(--accent-dark); }
.acct-form button:disabled { opacity: .6; }
.acct-list { list-style: none; margin: 10px 0; padding: 0; }
.acct-list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 0; border-top: 1px solid var(--line3); }
.acct-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-weight: 600; }
.acct select { font: inherit; height: 36px; padding: 0 10px; border: 1px solid var(--line2); border-radius: 10px; background: var(--surface); color: var(--ink); }
.acct-small { font-size: 13px; color: var(--muted2); }
.acct-note { color: var(--accent-ink); font-weight: 600; }
.acctpage { max-width: 560px; margin: 40px auto; }
.acctpage h1 { font: 800 clamp(28px, 5vw, 40px)/1.1 var(--display); }

/* /beheer/: the owner's admin of accounts and alerts (static/beheer.js) */
.adm { max-width: 1100px; margin: 24px auto 60px; }
.adm h1 { font: 800 clamp(28px, 5vw, 40px)/1.1 var(--display); margin: 0 0 14px; }
.adm h2 { font: 700 20px/1.2 var(--display); margin: 26px 0 8px; }
.adm h3 { font: 700 16px/1.2 var(--display); margin: 20px 0 6px; }
.adm-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 18px; }
.adm-tabs a { padding: 8px 16px; border: 1px solid var(--line2); border-radius: 999px; background: var(--surface); text-decoration: none; font-weight: 600; font-size: 14px; }
.adm-tabs a[aria-current] { background: var(--ink); color: var(--ink-inv); border-color: var(--ink); }
.adm-notice { padding: 10px 14px; border-radius: 12px; background: var(--accent-tint); color: var(--accent-ink); font-weight: 600; }
.adm-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.adm-stat { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px; display: flex; flex-direction: column; gap: 2px; }
.adm-stat b { font: 800 30px/1.1 var(--display); }
.adm-stat span { color: var(--muted); font-weight: 600; }
.adm-stat small { color: var(--muted2); }
.adm-scroll { overflow-x: auto; background: var(--surface); border: 1px solid var(--line); border-radius: 14px; }
.adm-table { border-collapse: collapse; width: 100%; font-size: 14px; }
.adm-table th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted2); padding: 10px 12px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.adm-table td { padding: 9px 12px; border-top: 1px solid var(--line3); vertical-align: top; }
.adm-empty { color: var(--muted2); }
.adm-tag { display: inline-block; padding: 1px 10px; border-radius: 999px; background: var(--accent-tint); color: var(--accent-ink); font-size: 12px; font-weight: 700; }
.adm-search { display: flex; gap: 8px; margin: 0 0 10px; max-width: 480px; }
.adm-search input { flex: 1; height: 40px; padding: 0 14px; border: 1px solid var(--line2); border-radius: 999px; font: inherit; background: var(--surface); color: var(--ink); }
.adm button, .adm-pager button { font: inherit; font-size: 14px; font-weight: 600; padding: 8px 16px; border: 1px solid var(--line2); border-radius: 999px; background: var(--surface); color: var(--ink); cursor: pointer; }
.adm button:disabled { opacity: .45; cursor: default; }
.adm-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0; }
.adm-danger { border-color: var(--accent) !important; color: var(--accent-ink) !important; }
.adm-pager { display: flex; gap: 12px; align-items: center; color: var(--muted2); }
.adm-bars { display: flex; align-items: flex-end; gap: 6px; height: 120px; padding: 10px 12px 0; background: var(--surface); border: 1px solid var(--line); border-radius: 14px; }
.adm-bar { flex: 1; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 4px; min-width: 0; }
.adm-bar i { display: block; width: 100%; max-width: 36px; background: var(--accent); border-radius: 4px 4px 0 0; }
.adm-bar span { font-size: 11px; color: var(--muted2); padding-bottom: 4px; }

/* /beheer/: mail warnings and status */
.adm-warn { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 8px; }
.adm-warn li { padding: 10px 14px; border-radius: 12px; border: 1px solid var(--line2); background: var(--surface); font-weight: 600; }
.adm-warn-bad { background: var(--accent-tint) !important; border-color: var(--accent) !important; color: var(--accent-ink); }
.adm-warn-warn { background: #fff6dc !important; border-color: #e8c76a !important; }
.adm-ok { padding: 10px 14px; border-radius: 12px; background: #e6f4ea; color: #1e5b2f; font-weight: 600; }
.adm-small { font-size: 13px; color: var(--muted2); }
.adm code { font-size: 12.5px; word-break: break-all; }

/* the privacy and contact pages while they are drafts (bestekortingen/legal.py): what still has to be filled in or confirmed stands out */
mark.todo { background: #fff1b8; color: #5a4300; padding: 0 .25em; border-radius: 3px; }
.draft-banner { border: 2px solid #e0a100; background: #fff8dc; color: #4a3800; padding: 12px 16px; border-radius: 8px; margin: 0 0 20px; font-size: 15px; }
.prose dl.facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px 16px; }
.prose dl.facts dt { font-weight: 600; }
.prose dl.facts dd { margin: 0; }
