/* Fertilize-it refresh layer (docs/ui-ux/). Loaded after site.css, which is the reference's own stylesheet.
   Each block names the audit finding it answers (docs/ui-ux/findings.md).
   Sections: 1 tokens · 2 accessibility · 3 de-slop · 4 icons · 5 illustrations · 6 micro-interactions · 7 screen sizes.

   HOW THE CASCADE WORKS HERE (ADR-1): site.css keeps 500 of its 517 KB inside `@layer components`, and Layout.php declares
   `@layer fi-pre, properties, theme, base, components, utilities` before it. So:
   - a normal declaration in this file (unlayered) beats the site's normal declarations whatever their specificity;
   - an `!important` declaration only beats the site's `!important` when it sits in `@layer fi-pre` (earlier layer = wins for important).
   Therefore: plain rules below, and every rule that needs `!important` inside an `@layer fi-pre { }` block. */

/* ============ 1. Tokens ============ */
:root {
  /* spacing (4 px base) */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px; --sp-9: 96px;
  /* colour roles that were missing (measured against white, paper, sage and butter) */
  --gold-deep: #7f6419;          /* was #B8953F: 2.4–2.8:1 as text; now 4.6:1 or better on every light surface */
  --text-muted: #5a645d;         /* 5.1:1 or better */
  --field-line: #76847a;         /* form borders: 3.3–3.9:1 (WCAG 1.4.11); card hairlines keep --line */
  --focus: #1d3a2c;              /* 11:1 on paper; dark bands switch to gold below */
  --focus-on-dark: #e9cf86;      /* 8.1:1 on --green-ink */
  --star: #8a6d1d;               /* filled rating stars: 4.9:1 on white (the pale gold was 1.5:1) */
  --ok: #1f7a4d; --warn: #8a5a00; --err: #b3261e; --info: #1d5f8a;
  /* elevation: five levels; shadows are for layering and interaction, not decoration */
  --elev-0: none;
  --elev-1: 0 1px 2px rgba(30, 60, 44, .06), 0 4px 12px -6px rgba(30, 60, 44, .14);
  --elev-2: 0 2px 4px rgba(30, 60, 44, .06), 0 12px 24px -12px rgba(30, 60, 44, .22);
  --elev-3: 0 4px 8px rgba(30, 60, 44, .06), 0 20px 40px -20px rgba(30, 60, 44, .28);
  --elev-4: 0 8px 16px rgba(30, 60, 44, .08), 0 32px 64px -24px rgba(30, 60, 44, .36);
  --sh-1: var(--elev-1);
  --sh-2: var(--elev-2);
  --sh-chip: 0 0 0 1px rgba(30, 60, 44, .08);
  /* motion */
  --dur-instant: 90ms; --dur-fast: 150ms; --dur-base: 220ms; --dur-slow: 380ms;
  --ease-out: cubic-bezier(.2, .7, .2, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);
  /* icon tiers */
  --icon-inline: 18px; --icon-ui: 24px; --icon-feature: 32px; --icon-tile: 64px; --icon-stroke: 1.7;
  /* green gradient of the buttons: 5.2–6.0:1 with white text (was 4.2–4.5:1) */
  --g-green: linear-gradient(180deg, #2f7a55 0%, #2a7050 100%);
  /* header offset: a focused element is never hidden behind the sticky header (WCAG 2.2: 2.4.11) */
  --scroll-offset: 96px;
}
html { scroll-padding-top: var(--scroll-offset); scroll-padding-bottom: 96px; }

/* ============ 2. Accessibility ============ */

/* 2a. One focus ring (3 px, offset 3 px, 11:1 on light surfaces). The audit found controls with an earlier `outline: 0 !important`
   (selected pack size, quantity, area calculator) that showed nothing at all. Dark bands switch to gold. */
@layer fi-pre {
  :is(a, button, input, select, textarea, summary, [role="button"], [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 3px solid var(--focus) !important;
    outline-offset: 3px !important;
  }
}
.site-footer, footer, .nl-wrap, .qr-final-cta, .pg-feature.pg-tone-dark, .pg-cta-dark, .pdp-section.dark, .faq-aside, .wu-pillar.dark,
.rv-item.dark, .soil-section.dark, .wu-crf, .ba-after { --focus: var(--focus-on-dark); }
:is(article, li, .ed-card, .case-card, .news-card):has(a.ed-stretched:focus-visible),
label.check:has(input:focus-visible) {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--r-lg, 10px);
}

/* 2b. Touch targets. Header controls: 44 px at every width. Everything else: 44 px on touch screens only (WCAG 2.2 floor is 24 px). */
@layer fi-pre {
  .nav-actions .icon-btn { width: 44px !important; height: 44px !important; }
}
.nav-logo-link { min-height: 44px; }
.nav-burger { flex-shrink: 0; min-width: 44px; }   /* the header row squeezed it from 44 to 36–43 px */
nav.breadcrumbs a { min-width: 28px; justify-content: center; }
.nav-lang a { min-width: 40px; min-height: 44px; }
.lang a { display: inline-grid; place-items: center; }
@media (pointer: coarse) {
  nav li > a, .footer-col li > a, nav.breadcrumbs a, .text-link, .ssb-clear, .pdp-variant-help {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  nav li > a, .footer-col li > a { min-width: 44px; }
  .pc-name a { display: block; min-height: 44px; }
  .check, label.check { min-height: 44px; }
}
@media (pointer: coarse) and (max-width: 1000px) { .lang a { min-width: 44px; min-height: 44px; } }
@layer fi-pre {
  @media (pointer: coarse) {
    input:not([type=checkbox]):not([type=radio]):not([type=hidden]):not([type=range]), select, textarea { font-size: 16px !important; }   /* iOS zooms in on anything smaller (491 field runs below 16 px) */
  }
}

/* 2c. Contrast. Breadcrumb separators, rating counts, labels, gold text and the primary button were below the limit. */
nav.breadcrumbs .sep, .pc-rating > span:not(.pc-stars), .pc-rating > b, dt, .sz-unit-price { color: var(--text-muted); opacity: 1; }   /* opacity: they were also faded to .5–.85 */
.stars > span:not(.off), .review-stars > span, .pdp-rev-stars-row > span { color: var(--star); }
@layer fi-pre {
  /* The contact fields had `border: 0 !important` (only a pale fill told you where to type: 1.17:1); the newsletter field the same. */
  .c-field :is(input, select, textarea), .nls-form input { border: 1.5px solid var(--field-line) !important; box-shadow: none !important; }
  .c-field :is(input, select, textarea):focus, .nls-form input:focus { border-color: var(--green-deep) !important; }
  /* The checkout and withdrawal fields (floating labels) are borderless white boxes: an inset outline marks them without changing their size. The site's own invalid state is left alone. */
  .fld :is(input, select, textarea):not(.invalid):not([aria-invalid="true"]):not(:focus),
  .pdp-calc-input input:not(:focus), .cart-promo-input input:not(:focus) { box-shadow: inset 0 0 0 1.5px var(--field-line) !important; }
  /* Green text on a tinted green surface was 3.6–4.4:1 (initials in avatars, "see the whole programme", "how does it work"). */
  .hx-season-cta, .rv-avatar, .review-avatar, .pdp-rev-avatar, .cx-up-more { color: var(--green-ink) !important; }
}
:where(.field:not(.has-error), .fld:not(.has-error), .shop-toolbar-right) :is(input, select, textarea):not(:focus):not([aria-invalid="true"]) { border-color: var(--field-line); }
.pdp-qty, .cart-qty { border-color: var(--field-line); }   /* the quantity stepper's own frame */

/* 2d. Nothing below 12 px: badges, tags, payment marks, the AI label, calendar days, review meta, the cart count. */
.icon-btn .badge { font-size: 12px; min-width: 20px; padding: 2px 6px; line-height: 1.2; }
@layer fi-pre {
  :is(.pay-badge, .pc-badge, .ba-tag, .news-tag, .ai-label, .rv-verified-text, .rv-meta time, .cal-h abbr, dt, .pdp-variant-opt .area, .pg-sz-ai, .ssb-active-count, .grass-cal-legend span, .cart-item-line, .pg-season-card h3, .pg-compare-note, .cx-up-badge) { font-size: 12px !important; }
}

/* 2e. Reduced motion: no entrance movement; the page stays complete. */
@media (prefers-reduced-motion: reduce) {
  .motion .rv, .motion .rv.in { opacity: 1; transform: none; }
  .fi-bump, [data-fi-add].is-added { animation: none !important; }
}
@layer fi-pre {
  @media (prefers-reduced-motion: reduce) { .motion .rv, .motion .rv.in { opacity: 1 !important; transform: none !important; transition: none !important; } }
}

/* ============ 3. De-slop ============ */
/* One word picked out in gold in every heading is a template tell, and the gradient text vanished in forced colours. */
@layer fi-pre {
  .accent, .hero h1 .accent, .section-head h2 .accent, .nl-wrap h2 .accent {
    background: none !important; -webkit-background-clip: border-box !important; background-clip: border-box !important;
    color: inherit !important; -webkit-text-fill-color: currentColor !important; font-style: normal !important;
  }
  /* Decorative motion that carried no information: the endless gradient drift of the dark soil bands. */
  .soil-section.dark, .wu-crf, .join-quiz, .faq-help, .soil-price-card.featured, .write-review, .cart-upsell { animation: none !important; }
}
/* Promo bar on phones: a 28 s endless marquee (WCAG 2.2.2) whose first message the site's own rules shrank to 0 px, so the strip looked empty. Now all three messages sit in a strip you can swipe, with a soft
   edge as the hint, and nothing moves by itself. (The site's own reduced-motion rule showed only the first message.) */
@layer fi-pre {
  @media (max-width: 760px) {
    .promo-items {
      animation: none !important; display: flex !important; flex-wrap: nowrap !important; gap: 28px !important;
      justify-content: flex-start !important;   /* the site centres the row: when it overflows, the first message sat 240 px off the left edge, unreachable */
      padding: 0 28px 0 16px !important; max-width: 100% !important; overflow-x: auto !important; overflow-y: hidden !important;
      scroll-snap-type: x proximity; scrollbar-width: none; will-change: auto !important;
      -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
    }
    .promo-item { display: flex !important; flex: 0 0 auto !important; scroll-snap-align: start; white-space: nowrap; }
  }
}
@media (max-width: 760px) { .promo-items::-webkit-scrollbar { display: none; } }
/* Buttons: honest pressed and disabled states. */
.btn { transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-instant) var(--ease-out); }
.btn:active { transform: scale(.97); }
.btn[disabled] { opacity: .55; cursor: not-allowed; transform: none; }

/* ============ 4. Icons ============ */
/* Audit: 14–18 px icons were 70% of all icons; 12 stroke widths. Tiers: inline 18 · UI 24 · feature 32 inside a 64 px tile. */
:is(.btn, .cat-link, .text-link, .pc-meta, .promo-item, .hx-promise, .icon-btn, .chip) svg { stroke-width: var(--icon-stroke); }
.btn svg, .cat-link svg, .pc-meta svg, .promo-item svg, .hx-promise svg { width: var(--icon-inline); height: var(--icon-inline); }
.icon-btn svg { width: var(--icon-ui); height: var(--icon-ui); }
@layer fi-pre {
  :is(.wu-pillar, .pillar, .soil-measure, .faq-block, .has-ico) .ico {
    width: var(--icon-tile) !important; height: var(--icon-tile) !important; border-radius: 20px !important;
    background: var(--sage) !important; color: var(--green-deep) !important;
  }
  :is(.wu-pillar, .pillar, .soil-measure, .faq-block, .has-ico) .ico svg { width: var(--icon-feature) !important; height: var(--icon-feature) !important; stroke-width: 1.5; }
}
.has-ico { column-gap: var(--sp-4); }

/* ============ 5. Illustrations (vector, in the palette; pseudo-elements and backgrounds carry no meaning for screen readers) ============ */
@layer fi-pre {
  .cart-empty .icon { width: 168px !important; height: 132px !important; border-radius: 24px !important; background: url("../img/photo/lawn-dew.webp") center / cover no-repeat !important; }
  .ed-empty-icon { width: 120px !important; height: 96px !important; border-radius: 20px !important; background: url("../img/photo/lawn-dew.webp") center / cover no-repeat !important; }
}
.cart-empty .icon svg, .ed-empty-icon svg { display: none; }
@media (min-width: 601px) { .ed-empty { grid-template-columns: 120px minmax(0, 1fr); } }
.ed-status-card::before { content: ""; display: block; width: 168px; height: 132px; border-radius: 24px; background: url("../img/photo/lawn-dew.webp") center / cover no-repeat; margin-bottom: var(--sp-2); }

/* ============ 6. Micro-interactions ============ */
/* Scroll reveal: shorter and softer (14 px, 0.5 s instead of 22 px, 0.8 s). The .in state returns to rest. */
.motion .rv:not(.in) { transform: translateY(14px); }
@layer fi-pre {
  .motion .rv, .motion .rv.in { transition: opacity .5s var(--ease-out) var(--d, 0s), transform .5s var(--ease-out) var(--d, 0s), box-shadow .45s var(--ease-out) !important; }
}
/* Add to cart: the pressed button pops (refresh.js sets .is-added when cart.js confirms with fi:cart-added). Toast and live region still announce it. */
[data-fi-add].is-added { animation: fi-added var(--dur-slow) var(--ease-out); }
@keyframes fi-added { 0% { transform: scale(1); } 40% { transform: scale(1.07); } 100% { transform: scale(1); } }
/* The cart count bumps when it changes. */
.fi-bump { animation: fi-bump var(--dur-slow) cubic-bezier(.34, 1.56, .64, 1); }
@keyframes fi-bump { 0% { transform: scale(1); } 40% { transform: scale(1.4); } 100% { transform: scale(1); } }
/* The header gets a shadow once the page has scrolled (refresh.js sets .is-stuck): layering is shown only when it exists. */
.nav { transition: box-shadow var(--dur-base) var(--ease-out); }
.nav.is-stuck { box-shadow: var(--elev-2); }

/* ============ 7. Screen sizes ============ */
/* Narrowest phones: header controls stay on one row; nothing may force a horizontal scroll. */
@layer fi-pre {
  @media (max-width: 359px) {
    .container { padding-inline: 14px !important; }
    .nav-inner { gap: 8px !important; }
    .nav-logo-link img { max-height: 28px; width: auto; }
  }
  @media (max-width: 319px) {
    .nav-logo-link img { max-height: 24px; }
    .nav-actions .icon-btn { width: 40px !important; height: 40px !important; }
  }
}
@media (max-width: 359px) { :root { --scroll-offset: 80px; } }
@media (max-width: 319px) { .nav-lang a { min-width: 30px; padding-inline: 2px; } }
/* Short landscape phones (height under 500 px): the bars must not eat the screen. Above 1000 px wide the promo bar holds the language switch, so it stays. */
@media (max-height: 500px) and (orientation: landscape) and (max-width: 1000px) {
  .promo { display: none; }
  .nav { position: static; }
  :root { --scroll-offset: 24px; }
}
