/*
 * DayFood 2.0 storefront kit — Option A
 * ======================================
 * Ported from the "DayFood 2.0 Storefront Prototype" design canvas (Option A row).
 * Hand-written CSS, not Tailwind. Everything is scoped under `.df2`, which the
 * storefront layout puts on <body>, so this kit cannot reach /admin or the
 * maquina-components partials.
 *
 * Structure:
 *   1. Tokens          — --df-* custom properties on .df2
 *   2. Reset and type
 *   3. Components      — df-* (BEM-ish: block__element--modifier)
 *   4. Responsive      — ONE breakpoint, 900px. See the plan's risk note.
 *   5. Option A accents— every interactive control speaks DayFood red
 *   6. Page components — a2-* carousel, al-* filter tools, hs-* how-to-order,
 *                        df-tab* listing tabs, ac-* category cards
 *   7. Category icons  — a2-ic--<category-slug> mask images
 *
 * Do not edit sections 1-5 to restyle a page; add to section 6 instead, so the
 * kit stays diffable against the prototype.
 *
 * Generated from the prototype by scratchpad/scripts/build_css.py, then
 * maintained by hand. See docs/plans/STOREFRONT_UI_OPTION_A.md.
 */

.df2 {
  --df-brand: #F04148;
  --df-accent: #DC252F;
  --df-accent-strong: #B91B22;
  --df-accent-soft: rgba(220, 37, 47, .10);
  --df-accent-tint: rgba(220, 37, 47, .05);
  --df-ink: #0A0A0A;
  --df-text-2: #404040;
  --df-muted: #525252;
  --df-hairline: #E5E5E5;
  --df-canvas: #FAFAFA;
  --df-surface: #FFFFFF;
  --df-surface-alt: #F4F4F4;
  --df-ok: #04654C;
  --df-warn: #8C4A11;
  --df-danger: #8A1842;
  --df-ok-soft: rgba(4, 101, 76, .10);
  --df-warn-soft: rgba(140, 74, 17, .10);
  --df-danger-soft: rgba(138, 24, 66, .08);

  --df-h-display: clamp(40px, calc(40px + 24 * (100vw - 370px) / 1070), 64px);
  --df-h-page: clamp(30px, calc(30px + 14 * (100vw - 370px) / 1070), 44px);
  --df-h-sec: clamp(24px, calc(24px + 10 * (100vw - 370px) / 1070), 34px);

  --df-space-1: 4px; --df-space-2: 8px; --df-space-3: 12px; --df-space-4: 16px;
  --df-space-5: 20px; --df-space-6: 24px; --df-space-8: 32px; --df-space-10: 40px; --df-space-12: 48px;
  --df-sec-gap: 64px;

  --df-radius: 8px;
  --df-r-card-sm: 16px;
  --df-r-card: 24px;
  --df-radius-pill: 999px;

  --df-shadow-card: 0 1px 2px rgba(10,10,10,.04), 0 4px 16px rgba(10,10,10,.04);
  --df-shadow-card-hover: 0 2px 4px rgba(10,10,10,.06), 0 12px 28px rgba(10,10,10,.08);
  --df-shadow-float: 0 10px 40px rgba(10,10,10,.14);
  --df-ease: cubic-bezier(.2, .7, .2, 1);

  font-family: "Inter", system-ui, sans-serif;
  font-size: 16px; line-height: 1.5; color: var(--df-ink);
  background: var(--df-canvas);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "cv11", "ss01";
}
.df2 *, .df2 *::before, .df2 *::after { box-sizing: border-box; }
.df2 h1, .df2 h2, .df2 h3, .df2 p, .df2 dl, .df2 dd, .df2 figure, .df2 fieldset, .df2 ol, .df2 ul { margin: 0; padding: 0; }
.df2 fieldset { border: 0; min-width: 0; }
.df2 ol, .df2 ul { list-style: none; }
.df2 img { display: block; max-width: 100%; }
.df2 button, .df2 input, .df2 select, .df2 textarea { font: inherit; }
/* `color` is split out at zero specificity on purpose. Folded into the rule
   above it was (0,1,1), which beat every `.df-btn*` colour (0,1,0) — so a
   <button class="df-btn"> inherited the page's ink instead of taking the
   component's white, and rendered near-black on the brand red (measured
   4.10:1 on the quote board's "Send request on Viber", under the 4.5:1 floor),
   while the identical classes on an <a> were correct. `.df-btn--danger-quiet`
   lost its red the same way. :where() keeps the UA's default off form controls
   without outranking a component class. */
:where(.df2) :where(button, input, select, textarea) { color: inherit; }
.df2 :focus-visible { outline: 2px solid var(--df-accent); outline-offset: 2px; }
.df2 svg.df-i { width: 20px; height: 20px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.df2 svg.df-i--16 { width: 16px; height: 16px; }
.df2 svg.df-i--18 { width: 18px; height: 18px; }
.df2 svg.df-i--22 { width: 22px; height: 22px; }

/* Type */
.df2 h1, .df-h-page { font-size: var(--df-h-page); font-weight: 700; letter-spacing: -.03em; line-height: 1.1; }
.df2 h2, .df-h-sec { font-size: var(--df-h-sec); font-weight: 700; letter-spacing: -.025em; line-height: 1.1; }
.df-h-hero { font-size: var(--df-h-display); font-weight: 700; letter-spacing: -.035em; line-height: 1.04; }
.df-sans { font-size: 18px !important; letter-spacing: -.01em !important; line-height: 1.3 !important; }
.df-title { font-size: 18px; font-weight: 700; letter-spacing: -.01em; line-height: 1.3; color: var(--df-ink); }
.df-title--sm { font-size: 15px; }
.df-lede { font-size: 16px; color: var(--df-text-2); max-width: 60ch; }
.df-lede--hero { font-size: 18px; }
.df-eyebrow { font-size: 13px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--df-accent-strong); }
.df-key { font-size: 13px; font-weight: 600; color: var(--df-muted); }
.df-meta { font-size: 13px; color: var(--df-muted); }
.df-help { font-size: 14px; color: var(--df-text-2); }
.df-help strong { color: var(--df-ink); }
.df-amount { font-size: 22px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.df-num, .df-figure { font-variant-numeric: tabular-nums; }
.df-sr { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.df-kv { display: grid; gap: 10px; }
.df-kv > div { display: flex; gap: 16px; justify-content: space-between; border-bottom: 1px solid var(--df-hairline); padding-bottom: 10px; }
.df-kv > div:last-child { border-bottom: 0; padding-bottom: 0; }
.df-kv dt { font-size: 14px; color: var(--df-muted); }
.df-kv dd { font-size: 14px; font-weight: 600; text-align: right; }

/* Layout */
.df-col { width: 100%; max-width: 1240px; margin: 0 auto; padding: 0 32px; }
.df-stack { display: flex; flex-direction: column; gap: var(--df-space-6); }
.df-sec { margin-top: var(--df-sec-gap); }
.df-sechead { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: var(--df-space-6); flex-wrap: wrap; }
.df-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--df-space-5); }
.df-split { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: var(--df-space-8); align-items: start; }
.df-pagehead { display: flex; flex-direction: column; gap: var(--df-space-3); }

/* Buttons and links */
.df-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 56px; padding: 0 28px; border-radius: var(--df-radius-pill); border: 0; background: var(--df-accent); color: #fff; font-size: 16px; font-weight: 600; text-decoration: none; cursor: pointer; transition: transform 160ms var(--df-ease), background 160ms var(--df-ease); white-space: nowrap; }
.df-btn:hover { background: var(--df-accent-strong); }
.df-btn:active { transform: scale(.98); }
.df-btn[disabled] { background: var(--df-hairline); color: var(--df-muted); cursor: not-allowed; }
.df-btn--outline { background: var(--df-surface); color: var(--df-accent-strong); box-shadow: inset 0 0 0 1.5px var(--df-accent-strong); }
.df-btn--outline:hover { background: var(--df-accent-tint); }
.df-btn--quiet { background: transparent; color: var(--df-ink); padding: 0 12px; }
.df-btn--quiet:hover { background: var(--df-surface-alt); }
.df-btn--danger-quiet { background: transparent; color: var(--df-danger); padding: 0 12px; }
.df-btn--danger-quiet:hover { background: var(--df-danger-soft); }
.df-btn--sm { min-height: 44px; padding: 0 18px; font-size: 15px; }
.df-btn--block { display: flex; width: 100%; }
.df-link { color: var(--df-accent-strong); font-weight: 600; text-decoration: none; font-size: 15px; }
.df-link:hover { text-decoration: underline; }
.df-link--inline { text-decoration: underline; font-weight: inherit; }
.df-go { display: inline-flex; align-items: center; gap: 6px; color: var(--df-accent-strong); font-weight: 600; font-size: 15px; }
.df-roundbtn { width: 44px; height: 44px; border-radius: 50%; border: 0; display: inline-grid; place-items: center; background: var(--df-surface); color: var(--df-ink); box-shadow: inset 0 0 0 1px var(--df-hairline); cursor: pointer; transition: transform 120ms var(--df-ease); }
.df-roundbtn:hover { box-shadow: inset 0 0 0 1px var(--df-muted); }
.df-roundbtn:active { transform: scale(.92); }
.df-roundbtn[disabled] { color: #A3A3A3; cursor: not-allowed; }
.df-roundbtn--sm { width: 36px; height: 36px; }
.df-roundbtn--danger { box-shadow: none; color: var(--df-danger); background: transparent; }
.df-roundbtn--danger:hover { background: var(--df-danger-soft); box-shadow: none; }
.df-stepper { display: inline-flex; align-items: center; gap: 4px; }
.df-stepper__v { min-width: 36px; text-align: center; font-weight: 700; font-size: 16px; }
.df-stepper--fill { display: flex; justify-content: space-between; width: 100%; background: var(--df-accent-tint); border-radius: var(--df-radius-pill); padding: 4px; box-shadow: inset 0 0 0 1px rgba(185, 27, 34, .25); }
.df-stepper--fill .df-roundbtn { background: var(--df-surface); box-shadow: none; }

/* Cards */
.df-card { display: block; background: var(--df-surface); border: 1px solid var(--df-hairline); border-radius: var(--df-r-card); box-shadow: var(--df-shadow-card); padding: 32px; color: inherit; text-decoration: none; position: relative; }
@supports (corner-shape: squircle) { .df-card, .df-sum, .df-fcard { corner-shape: squircle; } }
.df-card--sm { border-radius: var(--df-r-card-sm); padding: 20px; }
a.df-card:hover, .df-card--lift:hover { box-shadow: var(--df-shadow-card-hover); border-color: #D4D4D4; }
.df-card--recessed { background: var(--df-canvas); box-shadow: none; }
.df-card--flush { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.df-card__media { display: block; aspect-ratio: 1 / 1; background: var(--df-surface-alt); padding: 18px; }
.df-card__media img { width: 100%; height: 100%; object-fit: contain; mix-blend-mode: multiply; }
.df-card__body { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px 16px; flex: 1; }
.df-card__title { color: var(--df-ink); text-decoration: none; font-weight: 700; font-size: 15px; line-height: 1.3; letter-spacing: -.01em; }
.df-card__title:hover { text-decoration: underline; }
.df-card__foot { margin-top: auto; display: flex; flex-direction: column; gap: 8px; padding-top: 4px; }
label.df-card { cursor: pointer; }
label.df-card:has(input:checked) { border-color: var(--df-accent); box-shadow: 0 0 0 1px var(--df-accent), var(--df-shadow-card); }
label.df-card:has(input:focus-visible) { outline: 2px solid var(--df-accent); outline-offset: 2px; }

/* Pills and notes */
.df-pill { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: var(--df-radius-pill); font-size: 12px; font-weight: 600; background: var(--df-accent-soft); color: var(--df-accent-strong); white-space: nowrap; width: fit-content; }
.df-pill--ok { background: var(--df-ok-soft); color: var(--df-ok); }
.df-pill--warn { background: var(--df-warn-soft); color: var(--df-warn); }
.df-pill--neutral { background: var(--df-surface-alt); color: var(--df-text-2); box-shadow: inset 0 0 0 1px var(--df-hairline); }
.df-pill--muted { background: var(--df-surface-alt); color: var(--df-muted); }
.df-pill__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.df-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.df-note { display: flex; gap: 10px; align-items: flex-start; padding: 14px 16px; border-radius: 12px; background: var(--df-surface-alt); font-size: 14px; color: var(--df-text-2); }
.df-note strong { color: var(--df-ink); }
.df-note--accent { background: var(--df-accent-tint); color: var(--df-ink); }
.df-note--accent svg { color: var(--df-accent-strong); }
.df-note--ok { background: var(--df-ok-soft); color: var(--df-ink); }
.df-note--ok svg { color: var(--df-ok); }
.df-note--warn { background: var(--df-warn-soft); color: var(--df-ink); }
.df-note--warn svg { color: var(--df-warn); }
.df-note--danger { background: var(--df-danger-soft); color: var(--df-ink); box-shadow: inset 0 0 0 1px rgba(138, 24, 66, .25); }
.df-note--danger svg { color: var(--df-danger); }

/* Summary rail */
.df-sum { background: var(--df-accent-tint); border: 1px solid rgba(185, 27, 34, .18); border-radius: var(--df-r-card); padding: 28px; display: flex; flex-direction: column; gap: 12px; }
.df-sum--sticky { position: sticky; top: 96px; }
.df-sum__lines { display: flex; flex-direction: column; gap: 8px; }
.df-sum__line { display: flex; justify-content: space-between; gap: 12px; font-size: 15px; color: var(--df-text-2); }
.df-sum__line span:last-child { color: var(--df-ink); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
/* The quantity is short and must stay on one line. Without this it is just
   another flex item and shrinks with the name beside it: a real product name
   in the 380px rail pushed "4 × Carton" onto two lines, breaking "4 ×" from
   its unit. The name takes the slack instead. */
.df-sum__line span:first-child { min-width: 0; }
.df-sum__line span:last-child { flex: none; white-space: nowrap; }
.df-sum__rule { border: 0; border-top: 1px solid rgba(185, 27, 34, .18); margin: 4px 0; width: 100%; }
.df-sum__total { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-weight: 600; }

/* Forms */
.df-fcard { background: var(--df-surface); border: 1px solid var(--df-hairline); border-radius: var(--df-r-card); box-shadow: var(--df-shadow-card); overflow: hidden; }
.df-fcard__head { padding: 22px 24px 14px; display: flex; flex-direction: column; gap: 4px; }
.df-fcard__head .df-title { font-size: 18px; }
.df-field { display: flex; flex-direction: column; gap: 2px; padding: 14px 24px; border-top: 1px solid var(--df-hairline); cursor: text; transition: background 160ms var(--df-ease); }
.df-field:focus-within { background: var(--df-accent-tint); box-shadow: inset 3px 0 0 var(--df-accent); }
.df-field__k { font-size: 13px; font-weight: 600; color: var(--df-muted); }
.df-field__k em { font-style: normal; font-weight: 500; }
.df-field input, .df-field select, .df-field textarea { border: 0; outline: 0; background: transparent; padding: 2px 0; font-size: 16px; font-weight: 600; width: 100%; }
.df-field input::placeholder { color: var(--df-muted); font-weight: 500; }
.df-field__help { font-size: 13px; color: var(--df-muted); }
.df-item { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto auto; gap: 16px; align-items: center; padding: 16px 24px; border-top: 1px solid var(--df-hairline); }
.df-item__img { width: 64px; height: 64px; border-radius: 12px; background: var(--df-surface-alt); padding: 6px; }
.df-item__img img { width: 100%; height: 100%; object-fit: contain; mix-blend-mode: multiply; }
.df-item__x { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

/* UOM select (compact, on cards) */
.df-uom { position: relative; display: block; }
/* 44px, not 40: this is a primary touch control on a product card and 40 is
   under the minimum comfortable tap target. The filter bar already forced 44
   on its own copy further down; this makes it the default rather than a
   per-page correction. */
.df-uom select { appearance: none; -webkit-appearance: none; width: 100%; min-height: 44px; border-radius: 10px; border: 1px solid var(--df-hairline); background: var(--df-surface); padding: 0 34px 0 12px; font-size: 14px; font-weight: 600; cursor: pointer; }
.df-uom select:hover { border-color: #A3A3A3; }
.df-uom svg { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--df-muted); }

/* Segmented control */
.df-seg { display: inline-flex; padding: 4px; gap: 4px; background: var(--df-surface-alt); border-radius: var(--df-radius-pill); }
.df-seg label { min-height: 40px; padding: 0 16px; display: inline-flex; align-items: center; border-radius: var(--df-radius-pill); font-size: 14px; font-weight: 600; color: var(--df-text-2); cursor: pointer; }
.df-seg label:has(input:checked) { background: var(--df-surface); color: var(--df-ink); box-shadow: var(--df-shadow-card); }

/* Navigation */
.df-sitebar { position: sticky; top: 0; z-index: 5; background: rgba(255,255,255,.92); backdrop-filter: saturate(1.4) blur(12px); border-bottom: 1px solid var(--df-hairline); }
.df-sitebar__in { display: flex; align-items: center; gap: 28px; min-height: 76px; }
.df-brand { display: inline-flex; align-items: center; flex: none; }
.df-brand img { height: 34px; width: auto; }
.df-sitebar__nav { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.df-sitebar__nav a { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px; border-radius: var(--df-radius-pill); color: var(--df-text-2); font-weight: 600; font-size: 15px; text-decoration: none; }
.df-sitebar__nav a:hover { background: var(--df-surface-alt); color: var(--df-ink); }
.df-sitebar__nav a[aria-current="page"] { color: var(--df-accent-strong); background: var(--df-accent-soft); }
.df-sitebar__nav .df-pill { height: 22px; padding: 0 8px; background: var(--df-accent); color: #fff; }
.df-search { flex: 1; max-width: 560px; display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 18px; border-radius: var(--df-radius-pill); background: var(--df-surface-alt); border: 1px solid transparent; }
.df-search:focus-within { background: var(--df-surface); border-color: var(--df-accent); }
.df-search input { border: 0; outline: 0; background: transparent; flex: 1; font-size: 15px; min-width: 0; }
.df-search input::placeholder { color: var(--df-muted); }
.df-search svg { color: var(--df-muted); }
.df-crumbs { display: flex; flex-wrap: wrap; gap: 8px; font-size: 14px; color: var(--df-muted); align-items: center; }
.df-crumbs a { color: var(--df-text-2); text-decoration: none; }
.df-crumbs a:hover { text-decoration: underline; }
.df-crumbs [aria-current] { color: var(--df-ink); font-weight: 600; }
.df-chipbar { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding: 2px; }
.df-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 16px; border-radius: var(--df-radius-pill); background: var(--df-surface); border: 1px solid var(--df-hairline); font-size: 14px; font-weight: 600; color: var(--df-text-2); cursor: pointer; text-decoration: none; white-space: nowrap; flex: none; }
.df-chip:hover { border-color: #A3A3A3; color: var(--df-ink); }
.df-chip[aria-pressed="true"], .df-chip[aria-current="page"] { background: var(--df-accent-soft); border-color: rgba(185, 27, 34, .35); color: var(--df-accent-strong); }
.df-chip__n { font-weight: 500; color: var(--df-muted); font-variant-numeric: tabular-nums; }
/* Mobile web bottom nav: fixed, full width, phones only (mirrors _mobile_navbar) */
.df-bottomnav { display: none; }
.df-bottomnav a { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-height: 60px; font-size: 12px; font-weight: 600; color: var(--df-muted); text-decoration: none; }
.df-bottomnav a[aria-current="page"] { color: var(--df-accent-strong); }
.df-bottomnav a[aria-current="page"]::before { content: ""; position: absolute; top: 0; left: 30%; right: 30%; height: 3px; border-radius: 0 0 3px 3px; background: var(--df-accent); }
.df-bottomnav__ic { position: relative; display: inline-flex; }
.df-bottomnav__n { position: absolute; top: -6px; left: 14px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--df-accent); color: #fff; font-size: 11px; line-height: 18px; text-align: center; font-variant-numeric: tabular-nums; }

/* Success and empty */
.df-success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 16px; }
.df-success__badge { width: 72px; height: 72px; border-radius: 50%; display: grid; place-items: center; background: var(--df-ok); color: #fff; }
.df-success__badge--neutral { background: var(--df-surface-alt); color: var(--df-ink); box-shadow: inset 0 0 0 1px var(--df-hairline); }
.df-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 40px 24px; }
.df-empty__well { width: 72px; height: 72px; border-radius: 24px; display: grid; place-items: center; background: var(--df-accent-soft); color: var(--df-accent-strong); }

/* Storefront additions (drawn in DayFood tokens) */
.df-promo { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); align-items: center; gap: 24px; padding: 36px 40px; background: var(--df-surface); }
.df-promo__media { display: flex; gap: 12px; justify-content: flex-end; align-items: flex-end; height: 200px; }
.df-promo__media img { height: 100%; width: auto; object-fit: contain; mix-blend-mode: multiply; }
.df-promo__title { font-size: 30px; font-weight: 700; letter-spacing: -.025em; line-height: 1.12; }
.df-promise { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; border: 1px solid var(--df-hairline); border-radius: var(--df-r-card-sm); background: var(--df-surface); }
.df-promise__item { display: flex; gap: 14px; align-items: flex-start; padding: 18px 22px; }
.df-promise__item + .df-promise__item { border-left: 1px solid var(--df-hairline); }
.df-promise__ic { width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: var(--df-accent-soft); color: var(--df-accent-strong); flex: none; }
.df-promise__t { font-size: 15px; font-weight: 700; line-height: 1.3; }
.df-promise__d { font-size: 13px; color: var(--df-muted); line-height: 1.45; margin-top: 2px; }
.df-cats { display: grid; grid-auto-flow: column; grid-auto-columns: 132px; gap: 12px; overflow-x: auto; scrollbar-width: none; padding: 2px 2px 6px; }
.df-cat { display: flex; flex-direction: column; gap: 8px; align-items: center; text-align: center; padding: 12px 10px 14px; border-radius: var(--df-r-card-sm); background: var(--df-surface); border: 1px solid var(--df-hairline); text-decoration: none; color: var(--df-ink); font-size: 13px; font-weight: 600; line-height: 1.25; min-height: 44px; }
.df-cat:hover { box-shadow: var(--df-shadow-card-hover); }
.df-cat[aria-current="page"] { border-color: var(--df-accent); box-shadow: 0 0 0 1px var(--df-accent); }
.df-cat__img { width: 76px; height: 76px; border-radius: 50%; background: var(--df-surface-alt); display: grid; place-items: center; padding: 12px; overflow: hidden; }
.df-cat__img img { width: 100%; height: 100%; object-fit: contain; mix-blend-mode: multiply; }
.df-cat__img--more { background: var(--df-accent-soft); color: var(--df-accent-strong); }
.df-inquote { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; color: var(--df-ok); }
.df-pager { display: flex; gap: 6px; justify-content: center; align-items: center; }
.df-pager a, .df-pager span { min-width: 44px; height: 44px; display: inline-grid; place-items: center; border-radius: 50%; font-weight: 600; font-size: 15px; color: var(--df-text-2); text-decoration: none; font-variant-numeric: tabular-nums; }
.df-pager a:hover { background: var(--df-surface-alt); }
.df-pager [aria-current="page"] { background: var(--df-ink); color: #fff; }
.df-foot { margin-top: 80px; border-top: 1px solid var(--df-hairline); background: var(--df-surface); }
.df-foot__in { display: flex; flex-wrap: wrap; gap: 16px 28px; align-items: center; justify-content: space-between; padding-top: 28px; padding-bottom: 28px; font-size: 14px; color: var(--df-muted); }
.df-foot a { color: var(--df-text-2); text-decoration: none; }
.df-foot a:hover { text-decoration: underline; }

@media (max-width: 900px) {
  .df2 { --df-sec-gap: 40px; }
  /* `padding-inline`, not the `padding: 0 16px` shorthand this narrows the
     rails with. Both this and `.df-foot__in` are (0,1,0), and this rule comes
     later in the file, so the shorthand's implicit `padding-block: 0` wiped
     the footer's own 28px — below 900px the wordmark sat 1px under the
     footer's top border and the links ended 0px from its bottom edge, hard
     against the fixed bottom nav. Touching only the inline axis leaves a
     component's vertical padding to the component. */
  .df-col { padding-inline: 16px; }
  .df-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  /* Claw back the select's chrome on a two-up card, where the pack size has
     only ~60px to show itself. 46px of padding for a 16px chevron is a
     desktop measurement; 36px still clears the icon. */
  .df-uom select { padding: 0 26px 0 10px; }
  .df-uom svg { right: 7px; }
  .df-card__body .df-btn--sm { padding-inline: 10px; }
  .df-split { grid-template-columns: minmax(0, 1fr); }
  .df-promo { grid-template-columns: minmax(0, 1fr); padding: 24px; }
  .df-promo__media { height: 140px; justify-content: flex-start; }
  .df-promise { grid-template-columns: minmax(0, 1fr); }
  .df-promise__item + .df-promise__item { border-left: 0; border-top: 1px solid var(--df-hairline); }
  .df-sitebar__in { flex-wrap: wrap; gap: 12px; padding-top: 12px; padding-bottom: 12px; }
  .df-search { order: 3; max-width: none; flex-basis: 100%; }
  .df-sitebar__nav .df-hide-sm { display: none; }
  .df-card { padding: 24px; }
  .df-card--flush { padding: 0; }
  .df-card--sm { padding: 16px; }
  /* Two columns is not enough for the row's four children: the stepper and
     the delete button auto-placed into column 1 on the second row, so they
     sat under the THUMBNAIL, left-aligned and detached from the product they
     act on, with the trash flush against "+". A third auto column lets the
     controls share a row of their own, on the same text rail as the name,
     with the destructive button at the far end. */
  .df-item { grid-template-columns: 56px minmax(0, 1fr) auto; padding: 14px 16px; }
  .df-item__x { grid-column: 2 / -1; }
  .df-item > .df-stepper { grid-column: 2; }
  .df-item > .df-roundbtn--danger { grid-column: 3; }
  .df-item__img { width: 56px; height: 56px; }
  .df-bottomnav { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); position: fixed; left: 0; right: 0; bottom: 0; z-index: 6; padding-bottom: env(safe-area-inset-bottom); background: var(--df-surface); border-top: 1px solid var(--df-hairline); }
}


/* Option A: every interactive control speaks DayFood red. Loaded after df2.css on A pages only. */
.df2 { --df-ctl-line: rgba(185, 27, 34, .30); }

/* Buttons */
.df2 a.df-btn:hover { color: #fff; }
.df2 .df-btn--outline:hover, .df2 a.df-btn--outline:hover { color: var(--df-accent-strong); }
.df2 .df-btn--quiet, .df2 a.df-btn--quiet { color: var(--df-accent-strong); }
.df2 .df-btn--quiet:hover, .df2 a.df-btn--quiet:hover { background: var(--df-accent-tint); color: var(--df-accent-strong); }
.df2 a.df-btn--danger-quiet:hover { color: var(--df-danger); }
.df2 .df-btn:focus-visible, .df2 .df-roundbtn:focus-visible, .df2 .df-chip:focus-visible, .df2 .df-pager a:focus-visible { outline: 2px solid var(--df-accent); outline-offset: 2px; }

/* Round icon buttons and the quantity stepper */
.df2 .df-roundbtn { color: var(--df-accent-strong); box-shadow: inset 0 0 0 1px var(--df-ctl-line); transition: transform 120ms var(--df-ease), background-color 160ms, box-shadow 160ms; }
.df2 .df-roundbtn:hover { background: var(--df-accent-tint); box-shadow: inset 0 0 0 1px var(--df-accent-strong); }
.df2 .df-roundbtn[disabled] { color: #A3A3A3; box-shadow: inset 0 0 0 1px var(--df-hairline); background: var(--df-surface); }
.df2 .df-stepper--fill .df-roundbtn { box-shadow: none; }
.df2 .df-stepper--fill .df-roundbtn:hover { background: var(--df-accent); color: #fff; }
.df2 .df-roundbtn--danger { color: var(--df-danger); box-shadow: none; background: transparent; }
.df2 .df-roundbtn--danger:hover { background: var(--df-danger-soft); box-shadow: none; }

/* Dropdowns (pack size, brand, sort) */
.df2 .df-uom select { color: var(--df-accent-strong); border-color: var(--df-ctl-line); transition: border-color 160ms, background-color 160ms; }
.df2 .df-uom select:hover { border-color: var(--df-accent-strong); background: var(--df-accent-tint); }
.df2 .df-uom select:focus-visible { outline: 2px solid var(--df-accent); outline-offset: 1px; border-color: var(--df-accent); }
.df2 .df-uom select option { color: var(--df-ink); }
.df2 .df-uom svg { color: var(--df-accent-strong); }

/* Pack-size choice cards and segmented control */
.df2 label.df-card:has(input:checked) .df-title { color: var(--df-accent-strong); }
.df2 .df-seg label { color: var(--df-accent-strong); }
.df2 .df-seg label:has(input:checked) { background: var(--df-accent); color: #fff; box-shadow: none; }

/* Filter chips */
.df2 .df-chip { color: var(--df-accent-strong); border-color: var(--df-ctl-line); transition: background-color 160ms, border-color 160ms; }
.df2 .df-chip:hover { border-color: var(--df-accent-strong); background: var(--df-accent-tint); color: var(--df-accent-strong); }
.df2 .df-chip[aria-pressed="true"], .df2 .df-chip[aria-current="page"] { background: var(--df-accent); border-color: var(--df-accent); color: #fff; }
.df2 .df-chip[aria-pressed="true"] .df-chip__n { color: #fff; }

/* Pager */
.df2 .df-pager a { color: var(--df-accent-strong); }
.df2 .df-pager a:hover { background: var(--df-accent-tint); }
.df2 .df-pager [aria-current="page"] { background: var(--df-accent); color: #fff; }

/* Header navigation */
.df2 .df-sitebar__nav a { color: var(--df-accent-strong); }
.df2 .df-sitebar__nav a:hover { background: var(--df-accent-tint); color: var(--df-accent-strong); }

/* Header: logo and nav never hover to black */
.df2 .df-sitebar a:hover { color: var(--df-accent-strong); }
.df2 .df-sitebar .df-brand:hover { opacity: .85; }
.df2 .df-sitebar__nav a[aria-current="page"]:hover { background: var(--df-accent-soft); }

/* ==========================================================================
   6. Page components
   Lifted from the prototype boards' inline <style> blocks, scoped under .df2.
   ========================================================================== */

/* Category carousel (home) */
.df2 .al-tools {display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.df2 .al-tools .df-uom {width:200px}
.df2 .al-tools .df-uom select {min-height:44px}
.df2 .al-active {display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:16px}
.df2 .al-x {display:inline-flex;align-items:center;gap:6px;min-height:36px;padding:0 8px 0 14px;border-radius:999px;border:1px solid #E5E5E5;background:#FFFFFF;font-size:14px;font-weight:600;color:#B91B22;cursor:pointer;border-color:rgba(185,27,34,.30)}
.df2 .al-x:hover {border-color:#B91B22;background:rgba(220,37,47,.05)}
.df2 .a2-cats {display:flex;align-items:center;gap:12px;padding:20px 0 4px}
.df2 .a2-track {flex:1;min-width:0;display:flex;gap:10px;overflow-x:auto;scrollbar-width:none;scroll-behavior:smooth;scroll-snap-type:x proximity;padding:2px 48px 2px 2px;-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 48px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 48px),transparent)}
.df2 .a2-track::-webkit-scrollbar {display:none}
.df2 .a2-chip {flex:none;scroll-snap-align:start;display:inline-flex;align-items:center;gap:10px;min-height:48px;padding:0 18px 0 14px;border-radius:999px;background:#FFFFFF;border:1px solid rgba(185,27,34,.30);color:#B91B22;font-size:15px;font-weight:600;text-decoration:none;white-space:nowrap;transition:background-color .16s,border-color .16s,color .16s}
.df2 .a2-chip:hover {background:rgba(220,37,47,.05);border-color:#B91B22;color:#B91B22}
.df2 .a2-chip[aria-current="page"] {background:#DC252F;border-color:#DC252F;color:#FFFFFF}
.df2 .a2-ic {flex:none;width:22px;height:22px;background:currentColor;-webkit-mask:var(--a2i) center/contain no-repeat;mask:var(--a2i) center/contain no-repeat}
.df2 .a2-arrows {display:flex;gap:8px;flex:none}
.df2 .hs {display:grid;grid-template-columns:minmax(0,4fr) minmax(0,8fr);border-radius:24px;overflow:hidden;border:1px solid #E5E5E5;background:#FFFFFF}
.df2 .hs-lead {display:flex;flex-direction:column;justify-content:space-between;gap:24px;padding:32px;background:#FDF4F4;border-right:1px solid #F3D9DB;color:#0A0A0A;transition:background-color .3s}
.df2 .hs-lead h2 {font-size:28px;line-height:32px;letter-spacing:-.02em;color:#0A0A0A}
.df2 .hs-lead p {font-size:15px;line-height:22px;color:#525252;max-width:320px}
.df2 .hs-btn {align-self:flex-start;display:inline-flex;align-items:center;gap:8px;min-height:48px;padding:0 22px;border-radius:999px;background:#DC252F;color:#FFFFFF;font-weight:600;font-size:15px;text-decoration:none;transition:transform .16s}
.df2 .hs-btn:hover {transform:translateX(2px)}
.df2 .hs-steps {margin:0;padding:8px 40px;list-style:none;display:flex;flex-direction:column}
.df2 .hs-step {display:flex;gap:20px;align-items:flex-start;padding:22px 0}
.df2 .hs-step + .hs-step {border-top:1px solid #E5E5E5}
.df2 .hs-n {flex:none;width:44px;font-size:22px;line-height:26px;font-weight:700;color:#DC252F;font-variant-numeric:tabular-nums}
.df2 .hs-x {display:flex;flex-direction:column;gap:4px}
.df2 .hs-x b {font-size:17px;line-height:24px;font-weight:700;color:#0A0A0A}
.df2 .hs-x span {font-size:14px;line-height:20px;color:#525252}
.df2 .hs-lead {position:relative;overflow:hidden;isolation:isolate}
.df2 .hs-lead > * {position:relative;z-index:1}
.df2 .hs-lead::after {content:"";position:absolute;inset:0;z-index:0;pointer-events:none;background:linear-gradient(105deg,transparent 35%,rgba(255,255,255,.14) 50%,transparent 65%);transform:translateX(-120%);transition:transform 1.1s cubic-bezier(.2,.7,.2,1)}
.df2 .hs-lead::after {display:none}
.df2 .hs:hover .hs-lead {background:#FCEEEF}
.df2 .hs-btn:hover {background:#B91B22;color:#FFFFFF}
.df2 .hs-btn {transition:transform .2s cubic-bezier(.2,.7,.2,1),box-shadow .2s}
.df2 .hs-btn:hover {transform:translateY(-2px);box-shadow:0 8px 20px rgba(185,27,34,.22)}
.df2 .hs-btn svg {transition:transform .25s cubic-bezier(.34,1.56,.64,1)}
.df2 .hs-btn:hover svg {transform:translateX(4px)}
.df2 .hs-step {position:relative}
.df2 .hs-step::before {content:"";position:absolute;left:-20px;top:14px;bottom:14px;width:3px;border-radius:0 3px 3px 0;background:#DC252F;transform:scaleY(0);transition:transform .3s cubic-bezier(.2,.7,.2,1)}
.df2 .hs-step:hover::before {transform:scaleY(1)}
.df2 .hs-n {display:inline-block;transition:transform .35s cubic-bezier(.34,1.56,.64,1),color .2s}
.df2 .hs-step:hover .hs-n {transform:translateX(4px) scale(1.12);color:#B91B22}
.df2 .hs-x {transition:transform .3s cubic-bezier(.2,.7,.2,1)}
.df2 .hs-step:hover .hs-x {transform:translateX(6px)}
.df2 .hs-x b {transition:color .2s}
.df2 .hs-step:hover .hs-x b {color:#B91B22}

/* Listing tabs (category page) */
.df2 .df-tabsbar {border-bottom:1px solid #E5E5E5}
.df2 .df-tabs {display:flex;gap:28px;overflow-x:auto;scrollbar-width:none;-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 48px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 48px),transparent);padding-right:48px}
.df2 .df-tabs::-webkit-scrollbar {display:none}
.df2 .df-tab {flex:none;display:inline-flex;align-items:center;gap:6px;min-height:48px;border-bottom:2px solid transparent;font-size:15px;font-weight:600;color:#B91B22;text-decoration:none;white-space:nowrap;transition:color .15s,border-color .15s}
.df2 .df-tab:hover {color:#B91B22;border-bottom-color:#F6B9BC}
.df2 .df-tab[aria-current="page"] {color:#B91B22;font-weight:700;border-bottom-color:#DC252F}
.df2 .df-tab small {font-size:13px;font-weight:500;color:#525252;font-variant-numeric:tabular-nums}

/* Category cards and collections grid (all-categories page) */
.df2 .ac-collage {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;padding:12px;background:#F4F4F4;aspect-ratio:4/3}
.df2 .ac-collage span {display:block;border-radius:10px;background:#FFFFFF;padding:6px;overflow:hidden}
.df2 .ac-collage span:only-child {grid-column:1 / -1}
.df2 .ac-collage img {width:100%;height:100%;object-fit:contain;mix-blend-mode:multiply}
.df2 .ac-tag {display:flex;align-items:center;gap:16px;padding:16px 20px;text-decoration:none}
.df2 .ac-tag img {width:64px;height:64px;object-fit:contain;mix-blend-mode:multiply;flex:none}
.df2 .ac-tags {display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}

/* Page-component responsive rules */
@media (max-width: 900px) {
  .df2 .al-tools .df-uom {width:100%}
}

@media (max-width: 900px) {
  .df2 .a2-arrows, .df2 .a2-all {display:none}
  .df2 .a2-track {margin-right:-16px}
  .df2 .hs {grid-template-columns:minmax(0,1fr)}
  .df2 .hs-lead {padding:24px}
  .df2 .hs-lead {border-right:0;border-bottom:1px solid #F3D9DB}
  .df2 .hs-lead h2 {font-size:24px;line-height:28px}
  .df2 .hs-steps {padding:4px 24px}
}

@media (prefers-reduced-motion: reduce) {
  .df2 .a2-track {scroll-behavior:auto}
  .df2 .hs-btn, .df2 .a2-chip {transition:none}
}

@media (max-width: 900px) {
  .df2 .hs-step::before {left:-12px}
}

@media (prefers-reduced-motion: reduce) {
  .df2 .hs-lead, .df2 .hs-step::before, .df2 .hs-n, .df2 .hs-x, .df2 .hs-btn, .df2 .hs-btn svg {transition:none}
}

@media (max-width: 900px) {
  .df2 .al-tools .df-uom {width:100%}
}

@media (max-width: 900px) {
  .df2 .ac-tags {grid-template-columns:minmax(0,1fr)}
}

/* ==========================================================================
   7. Category icons
   The prototype keyed these by position (.a2-ic--c0 ... c17). Keyed by
   category slug here instead, so reordering Constants::PRODUCT_CATEGORIES
   cannot silently shuffle the artwork. Each is a mask, so the glyph takes
   its colour from `currentColor` on the chip.
   ========================================================================== */

/* All products */
.df2 .a2-ic--all {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%274%27%20y%3D%274%27%20width%3D%277%27%20height%3D%277%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%2713%27%20y%3D%274%27%20width%3D%277%27%20height%3D%277%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%274%27%20y%3D%2713%27%20width%3D%277%27%20height%3D%277%27%20rx%3D%271.5%27%2F%3E%3Crect%20x%3D%2713%27%20y%3D%2713%27%20width%3D%277%27%20height%3D%277%27%20rx%3D%271.5%27%2F%3E%3C%2Fsvg%3E")}
/* Chips, Crackers & Savoury Snacks */
.df2 .a2-ic--chips-crackers-savoury-snacks {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M7%204h10l-1%2016H8z%27%2F%3E%3Cpath%20d%3D%27M7%204l1.7-1%201.6%201%201.7-1%201.6%201%201.7-1L17%204%27%2F%3E%3Cpath%20d%3D%27M10%2010h4%27%2F%3E%3C%2Fsvg%3E")}
/* Biscuits, Cakes & Chocolates */
.df2 .a2-ic--biscuits-cakes-chocolates {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%278%27%2F%3E%3Cpath%20d%3D%27M9%209h.01M14.5%208.5h.01M15%2014h.01M9.5%2015h.01M12%2012h.01%27%2F%3E%3C%2Fsvg%3E")}
/* Candies */
.df2 .a2-ic--candies {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%274%27%2F%3E%3Cpath%20d%3D%27M8%2012%203%208.5v7zM16%2012l5-3.5v7z%27%2F%3E%3C%2Fsvg%3E")}
/* Beverages */
.df2 .a2-ic--beverages {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M6%208h12l-1.5%2012h-9z%27%2F%3E%3Cpath%20d%3D%27M9%208V5h6v3M7%2012h10%27%2F%3E%3C%2Fsvg%3E")}
/* Soft Drinks */
.df2 .a2-ic--soft-drinks {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M10%203h4v3l2%203v12H8V9l2-3z%27%2F%3E%3Cpath%20d%3D%27M8%2013h8%27%2F%3E%3C%2Fsvg%3E")}
/* Dairy */
.df2 .a2-ic--dairy {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M8%203h8v3l2%203v12H6V9l2-3z%27%2F%3E%3Cpath%20d%3D%27M6%209h12M10%2014h4%27%2F%3E%3C%2Fsvg%3E")}
/* Tea, Coffee & Instants */
.df2 .a2-ic--tea-coffee-instants {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M5%2010h11v5a5%205%200%200%201-5%205h-1a5%205%200%200%201-5-5z%27%2F%3E%3Cpath%20d%3D%27M16%2012h1.5a2%202%200%200%201%200%204H16M9%203.5v3M12.5%203.5v3%27%2F%3E%3C%2Fsvg%3E")}
/* Noodles & Pasta */
.df2 .a2-ic--noodles-pasta {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2012h16a8%208%200%200%201-16%200z%27%2F%3E%3Cpath%20d%3D%27M9%2012%2013%203M12.5%2012%2018%204%27%2F%3E%3C%2Fsvg%3E")}
/* Canned Foods */
.df2 .a2-ic--canned-foods {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%276%27%20y%3D%274%27%20width%3D%2712%27%20height%3D%2716%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M6%208h12M6%2016h12%27%2F%3E%3C%2Fsvg%3E")}
/* Condiments & Sauces */
.df2 .a2-ic--condiments-sauces {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M11%203h2v4l2%202v12H9V9l2-2z%27%2F%3E%3Cpath%20d%3D%27M9%2013h6%27%2F%3E%3C%2Fsvg%3E")}
/* Herbs & Spices */
.df2 .a2-ic--herbs-spices {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M5%2019C5%2010%2010%205%2019%205c0%209-5%2014-14%2014z%27%2F%3E%3Cpath%20d%3D%27M5%2019l8-8%27%2F%3E%3C%2Fsvg%3E")}
/* Cooking & Baking */
.df2 .a2-ic--cooking-baking {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M7%208h10l1%2012H6z%27%2F%3E%3Cpath%20d%3D%27M9%208V5h6v3M10%2013h4%27%2F%3E%3C%2Fsvg%3E")}
/* Grains & Staples */
.df2 .a2-ic--grains-staples {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M6%2010c0-3%203-6%206-6s6%203%206%206v10H6z%27%2F%3E%3Cpath%20d%3D%27M9%204.5l3%203%203-3M9%2014h6%27%2F%3E%3C%2Fsvg%3E")}
/* Nuts & Dry Fruits */
.df2 .a2-ic--nuts-dry-fruits {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203c4.5%203%206.5%207.5%204.5%2012.5S10%2021%208%2018s-1.5-10%204-15z%27%2F%3E%3Cpath%20d%3D%27M12%207c-1%203-1.5%206-1%209%27%2F%3E%3C%2Fsvg%3E")}
/* Oils & Fats */
.df2 .a2-ic--oils-fats {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M10%203h4v3l1%202v13H9V8l1-2z%27%2F%3E%3Cpath%20d%3D%27M12%2011.5c-1%201.5-1.5%202.3-1.5%203a1.5%201.5%200%200%200%203%200c0-.7-.5-1.5-1.5-3z%27%2F%3E%3C%2Fsvg%3E")}
/* Personal Care */
.df2 .a2-ic--personal-care {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M8%209h8v12H8z%27%2F%3E%3Cpath%20d%3D%27M12%209V5h3M10%205h2M10%2014h4%27%2F%3E%3C%2Fsvg%3E")}
/* Household Care */
.df2 .a2-ic--household-care {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M8%2010h6v11H8z%27%2F%3E%3Cpath%20d%3D%27M9%2010V7h4l3%202M17%204.5h2M17%207.5h2%27%2F%3E%3C%2Fsvg%3E")}
/* Baby Products */
.df2 .a2-ic--baby-products {--a2i:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M9%208h6v11a2%202%200%200%201-2%202h-2a2%202%200%200%201-2-2z%27%2F%3E%3Cpath%20d%3D%27M10%208V6l2-3%202%203v2M9%2012h6M9%2016h6%27%2F%3E%3C%2Fsvg%3E")}


/* ==========================================================================
   8. Integration layer
   Rules the prototype did not need but a Rails app does. Kept separate from
   the ported sections so a future diff against the canvas stays clean.
   ========================================================================== */

/* --- Quote-count badge visibility ----------------------------------------
   cart_drawer_controller toggles the Tailwind `hidden` class on the badge.
   tailwind.css is linked BEFORE this file, so `.df-pill { display:inline-flex }`
   beats `.hidden { display:none }` on source order at equal specificity and
   the badge would show "0" permanently. These rules restore the intent;
   without them an empty quote still renders a badge. */
.df2 .df-pill.hidden,
.df2 .df-bottomnav__n.hidden { display: none; }

/* --- Layout one-offs -----------------------------------------------------
   The prototype boards express these as inline `style` attributes (a design
   canvas habit). Named here instead: inline styles are unreviewable, break
   under a strict CSP, and would be copy-pasted across the phase 4/5 views. */

/* Pack-size radio cards on the PDP: a two-up grid of stacked choice cards. */
.df2 .df-choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.df2 .df-card--choice { display: flex; flex-direction: column; gap: 2px; }

/* A horizontal cluster of controls (quantity stepper + primary action). */
.df2 .df-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }

/* A labelled control stacked over its label (the `df-key` + stepper pair). */
.df2 .df-rowstack { display: flex; flex-direction: column; gap: 6px; }

/* Footer link row. The kit's `.df-foot__in` gap spaces the brand from the nav,
   not the links inside it, so without this they run together. */
.df2 .df-foot__in nav { display: flex; flex-wrap: wrap; gap: 20px; }

/* The footer wordmark is smaller than the sitebar's (26px vs 34px). */
.df2 .df-foot__in .df-brand img { height: 26px; }

/* --- Card media aspect ratio ---------------------------------------------
   `.df-card__media` is sized by `aspect-ratio: 1/1`, which leaves its height
   AUTO. A child with `height: 100%` cannot resolve against an auto height,
   so it falls back to its intrinsic height — and any product photo taller
   than the square then stretches the box, breaking the grid's alignment.
   Measured: a 426x596 portrait photo made its card's media 373px tall in a
   row of 277px.

   `max-height: 100%` does NOT fix it: a percentage max-height resolves
   against the containing block's height, and an aspect-ratio-derived height
   is not definite for that purpose, so it computes to `none` and the image
   still overflows. Absolute positioning with all four insets set IS
   definite — the used size fills the gap — and object-fit letterboxes the
   photo inside it. Every tile is then square whatever the source shape. */
.df2 .df-card__media { position: relative; overflow: hidden; }
.df2 .df-card__media img {
  position: absolute; inset: 18px;
  /* Explicit sizes, not `auto`: an absolutely positioned REPLACED element
     with auto width/height uses its INTRINSIC size and ignores the insets.
     These percentages resolve against the positioned containing block (the
     media box's padding box), whose used height is definite, which is the
     whole point of positioning rather than relying on max-height. */
  width: calc(100% - 36px); height: calc(100% - 36px);
  object-fit: contain;
}

/* --- Pager overflow ------------------------------------------------------
   `.df-pager` is a nowrap flex row. The prototype board only ever drew a few
   page links; a real Kaminari window (prev + 6 numbers + next = 8 × 44px plus
   gaps) is ~394px and overflows a 390px phone, giving the whole PAGE a
   horizontal scrollbar. Measured at 417px scrollWidth vs a 390px viewport. */
.df2 .df-pager { flex-wrap: wrap; row-gap: 6px; }

/* --- Control rows --------------------------------------------------------
   `.df-row` centres its children. When one of them is a `.df-rowstack` — a
   label stacked above a control — centring measures against the WHOLE stack,
   so a button beside it sits above the control it belongs to. Measured on the
   product page: the submit button's centre was 13px above the stepper's.
   Aligning to the end puts the button on the control's baseline, where it
   reads as belonging to it. */
.df2 .df-row:has(.df-rowstack) { align-items: flex-end; }

/* --- Pack-size submit button ---------------------------------------------
   The board gives it `flex: 1; min-width: 220px; align-self: flex-end` —
   another inline style the generator never saw, since it parses the boards'
   <style> blocks and not their style= attributes. The button fills the rest
   of the row beside the stepper rather than sitting at its text width.

   Scoped to that row — the one holding the `.df-rowstack` the comment above
   describes — and not to every `.df-row`. Unscoped it stretched each button
   in rows it was never meant for: the quote board's card foot spread "Add
   more products" and "Clear quote" to 349px apiece, which floated the first
   106px right of the 24px text rail the rest of the card lines up against
   and stacked them into two full-width centred rows below 900px, where two
   secondary actions read as two primary ones; the FAQ's pair went to 580px
   each; and the product page's `.df-pagetop` blew a small quiet "Back" link
   up to 220px beside the breadcrumbs. */
.df2 .df-row:has(.df-rowstack) > .df-btn { flex: 1; min-width: 220px; align-self: flex-end; }

/* The foot's own actions hug their labels and start on the card's text rail.
   The destructive one is pushed to the far end rather than sitting 16px from
   a benign link: on the quote board "Clear quote" discards the whole list,
   and it sat one gap away from "Add more products". */
.df2 .df-fcard__foot > .df-btn--danger-quiet { margin-inline-start: auto; }

/* --- Page vertical rhythm ------------------------------------------------
   The prototype carries these as inline `style` attributes on <main> and
   <div class="df-pagehead">, which the generator never saw: it parses the
   boards' <style> blocks, not their style= attributes. Without them every
   page opened flush against the sticky header and the page head butted
   straight into whatever preceded it — measured 0px between the breadcrumbs
   and the title, and 0px between the home page's banner and its title, which
   made the title read as part of the banner.

   Board values: main padding-top 24px everywhere (40px on the quote page,
   72px on the confirmation), pagehead margin-top 20px (28px on home).

   The bottom margin closes the other end of the same gap: the head had none,
   so a page whose first block carries no top margin of its own butted
   straight against the lede — 0px between "our team replies on Viber." and
   the FAQ card, and the same on the quote board. 24px matches `.df-stack`'s
   gap, so the head sits in the rhythm of the cards under it. Pages that open
   with a `.df-sec` are unchanged: these are adjoining sibling margins in
   normal flow, so 24px collapses into that section's 64px. */
.df2 main.df-col { padding-top: var(--df-space-6); }
.df2 .df-pagehead { margin-top: var(--df-space-5); margin-bottom: var(--df-space-6); }

/* The request-sent page is a narrow, centred confirmation rather than a
   full-width page. */
.df2 .df-confirm { max-width: 640px; margin-inline: auto; padding-top: var(--df-space-12); }

/* --- Product grid row heights --------------------------------------------
   A CSS grid sizes each row to its own tallest item, so a row whose product
   names all fit on one line is shorter than a row with a two-line name —
   measured 450px and 470px in the same grid. The cards' feet use
   `margin-top: auto`, so that difference lands on the "Add to quote"
   buttons, which then sit at different heights down the page.

   Equal auto rows make every card in the grid the same height, which is what
   puts those buttons on a line. */
.df2 .df-grid { grid-auto-rows: 1fr; }

/* --- Named replacements for one-off inline styles ------------------------
   Every rule here replaced a `style="..."` attribute in a view. Inline
   styles are unreviewable, invisible to this stylesheet, and were the first
   thing worth removing from the ported prototype — they should not creep
   back in through the views either. */

/* The promo banner slot on the home page. The prototype has no banner, so
   this spacing is ours: without the bottom margin the page head butts
   directly against the banner with a 0px gap and reads as part of it. */
.df2 .df-promoslot { margin-top: var(--df-space-4); margin-bottom: var(--df-space-8); }

/* The back-link and breadcrumb row above a page head. */
.df2 .df-pagetop { margin-bottom: var(--df-space-4); }

/* An action row at the foot of a form card (the quote page's
   "Add more products" / "Clear quote"). */
.df2 .df-fcard__foot { padding: var(--df-space-4) var(--df-space-6); }

/* A fieldset's label, and a key/value list following a card heading. */
.df2 fieldset > .df-key { display: block; margin-bottom: 10px; }
.df2 .df-title + .df-kv { margin-top: var(--df-space-3); }

/* --- Catalogue card controls on a phone ----------------------------------
   A two-up card gives its select 54px of text at 360px and 69px at 390px.
   The full pack labels need up to 116px ("Carton (48 units)"), so the view
   renders `storefront_short_uom_label` in the option text — "Ctn 48", 46px —
   while `data-uom` keeps the full label for the quote line. The widest short
   form is "Pack 12" at 52px, which clears 360px.

   The button is the other half: "Add to quote" is 93px against 72px of room
   at 360px, so below the breakpoint the card shows "Add". The full wording
   stays in the button's aria-label. 419px is where the measurement turns
   over — a 430px card gives the button 107px, so Pro Max and tablets get the
   full label and only the narrower handsets fall back. */
.df2 .df-btn__short { display: none; }

@media (max-width: 419px) {
  .df2 .df-card__body .df-btn__long { display: none; }
  .df2 .df-card__body .df-btn__short { display: inline; }
  /* "Pack 12" clears the 360px card's select by 2px at 14px, which is inside
     the margin of error if Inter has not loaded and the fallback metrics
     differ. 13px takes it to 48px against 54px. */
  .df2 .df-card__body .df-uom select { font-size: 13px; }
}

/* Under 360px nothing fits two-up: the card is 138px, which leaves the
   select 34px of text — less than "Single" (43px). One column rather than a
   row of controls that cannot show what they control. */
@media (max-width: 359px) {
  .df2 .df-grid { grid-template-columns: minmax(0, 1fr); }
}

/* --- FAQ list ------------------------------------------------------------
   One question and answer per row, on the same 24px text rail the rest of
   the kit's cards use. The number is a flex item with `flex: none` and the
   row aligns to flex-start: as an auto-width item centred against the whole
   heading it drifted to the vertical middle of a two-line question instead
   of sitting on its first line, and it squashed below 20px when the question
   was long. The answer's indent is the badge plus the gap, so it hangs under
   the question text rather than under the number. */
.df2 .df-faq { padding: var(--df-space-5) var(--df-space-6); border-top: 1px solid var(--df-hairline); }
.df2 .df-faq:first-child { border-top: 0; }
.df2 .df-faq__q { display: flex; align-items: flex-start; gap: 10px; font-size: 17px; font-weight: 700; letter-spacing: -.01em; line-height: 1.35; color: var(--df-ink); }
.df2 .df-faq__n { flex: none; width: 24px; height: 24px; margin-top: 1px; border-radius: 50%; display: grid; place-items: center; background: var(--df-accent-soft); color: var(--df-accent-strong); font-size: 13px; font-weight: 700; }
.df2 .df-faq__a { margin-top: 6px; padding-inline-start: 34px; font-size: 15px; color: var(--df-text-2); }

@media (max-width: 900px) {
  .df2 .df-faq { padding: var(--df-space-4); }
  .df2 .df-faq__q { font-size: 16px; }
}

/* --- Disabled controls -------------------------------------------------
   The kit styles no disabled state, so a disabled button rendered at full
   opacity and looked pressable — on the product page, on the quote page's
   Send and Clear while the quote is empty, and on the pager's edges. Only
   the cursor gave it away, and only on a device that has one. */
.df2 .df-btn:disabled,
.df2 .df-btn[aria-disabled="true"],
.df2 .df-qbtn:disabled,
.df2 .df-iconbtn:disabled {
  opacity: .45;
  cursor: not-allowed;
  box-shadow: none;
}

.df2 .df-btn:disabled:hover,
.df2 .df-qbtn:disabled:hover,
.df2 .df-iconbtn:disabled:hover {
  filter: none;
  transform: none;
}

/* --- Room for the fixed mobile bar --------------------------------------
   Below 900px `.df-bottomnav` is fixed to the bottom of the viewport. The
   page needs to reserve that height or its last ~60px sits underneath the
   bar — measured with the footer's links completely covered. The legacy
   layout reserved it with a `mb-24` on <body>; this is the kit's equivalent.

   The cookie banner needs lifting for the same reason: it is fixed to
   bottom: 0 at z-index 50 against the bar's 6, so on a first visit it
   covers the primary navigation outright. */
@media (max-width: 900px) {
  /* 72px, not the bar's measured 61: clearing it exactly leaves the footer
     flush against the bar with no visual gap. */
  .df2 { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
  .df2 [data-controller~="cookie-consent"] { bottom: calc(61px + env(safe-area-inset-bottom)); }
}

/* --- Base link colour ----------------------------------------------------
   The boards carry a bare `a { color: #B91B22 }` for links the kit does not
   style. `:where(.df2) a` reproduces its 0,0,1 specificity exactly, so
   .df-card__title and friends still win. Writing it as `.df2 a` would be
   0,1,1 and would turn every card title red. */
:where(.df2) a { color: var(--df-accent-strong); }
