/* ==========================================================================
   DINKOMART — Atmosphere

   Three things that apply to every page and are easiest to reason about in one
   place:

     1  Background   a very slow gradient field, so no page is ever a flat
                     rectangle of one colour
     2  Cursor       a custom pointer, on fine-pointer devices only
     3  Feedback     the visual half of the sound system (see req/js/sound.js)

   Loads last, after commerce.css.
   ========================================================================== */

/* ==================================================================== 1. background

   A flat #FCFAF4 across a 9000px page reads as dead. Three very soft radial
   washes sit behind everything at low opacity — warm near the top where the
   hero is, green through the middle, warm again at the foot.

   Fixed attachment, so it does not repaint on scroll. It is one element on its
   own layer rather than a background on <body>, which keeps it off the paint
   path of everything else. */
body { position: relative; }

/* The amber wash used to sit at 8% 0% — top left, directly behind the hero and
   the first screen of every page. Combined with the cream bone scale it made
   the whole site read yellow. Green and cold lead now; the one warm note is
   pushed to the very bottom of the viewport, which is also where it belongs
   in the story: produce goes out cold, money and inputs come back warm. */
/* LAYER ORDER IS THE WHOLE FIX HERE. First listed paints on top.

   The white lift used to sit UNDERNEATH all three tints, so the brand wash at
   10% painted straight over it. Composited against --bg that landed on
   #E3EDE8 across the top of every page — six points darker and distinctly
   greener than the #FAFBFA it is supposed to be sitting on. That is the
   "faded" reading: a tint with nothing above it is haze, not light.

   The two white layers now go on top, and the tints have been eased back so
   they read through the light rather than smothering it.

   THE WARM NOTE HAD TO COME DOWN WITH THEM, AND MISSING THAT TURNED THE PAGE
   YELLOW. Three things were cooling this field: the brand green, the chill
   blue, and a 50% neutral grain multiplying over the top. All three were
   reduced — and the harvest radial was left at 6%, so it stopped being a note
   and became a cast. `--accent` is #DC7A16; at 6% over --bg its centre
   composites to #F8F3EC, blue twelve points under red. That is cream, on a
   paper the palette comment at the top of tokens.css says was deliberately
   neutralised to a green-grey BECAUSE an earlier build read yellow.

   It is now 2.5% and confined to the bottom edge rather than washing the
   lower third, which puts the centre at #F9F9F6 — three points, a warmth you
   can feel rather than see. Green and cold still lead; the warm note is still
   at the foot of the viewport, where it belongs in the story: produce goes
   out cold, money and inputs come back warm. It just is not the loudest
   thing in the room any more.

   THE STRUCTURAL MISTAKE, AND WHY FOUR PASSES ALL FAILED.

   Every version of this field was built by mixing SMALL AMOUNTS OF DARK
   PIGMENT into a near-white base. `--brand` is #166E42 and `--chill` is
   #14707E — both dark. Adding either to #FAFBFA can only ever move it toward
   grey; there is no percentage of a dark green that makes white look
   luminous. So the choice was between "faded" (enough tint to see) and "flat"
   (little enough tint not to muddy). Neutralising it just landed on flat:
   the whole field measured within three points of #FAFBFA, which is no
   gradient at all.

   It is built the other way round now. The blooms come from the LIGHT end of
   the palette — `--forest-100` #DDEEE3 and `--chill-400` #4FBECE — at alphas
   high enough to see, and the ground itself is a vertical gradient rather
   than a flat fill. Colour that is lighter than the paper reads as light
   falling on it. Colour that is darker reads as dirt on it. That is the whole
   difference, and it is why the earlier passes could not get there by tuning
   percentages.

   THERE IS NO WARM LAYER IN THE LIGHT FIELD ANY MORE. The harvest radial is
   gone rather than reduced again — twice now it has been the thing that made
   the page read yellow, and `--harvest-100` is still a cream (#FBEBD6, red
   thirty-seven points over blue) so even the light end of it casts. The lower
   bloom is a second, weaker mint instead. Dark keeps its warm note. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  /* ITS OWN LAYER, ON PURPOSE. This is a full-viewport fixed element carrying
     five radial gradients. Left in the page layer it is re-rasterised on every
     scroll frame, under everything else that is also being painted. Promoted,
     it is composited — drawn once and moved, which is free.

     `translateZ(0)` rather than `will-change`, because will-change is a hint
     that something is ABOUT to animate and this never animates; it just needs
     to stop being repainted. Safe on a pseudo-element with no descendants: a
     transform makes a containing block for `position: fixed` children, and
     this has none. */
  transform: translateZ(0);
  background:
    /* Light pools. Where the glass catches the light. */
    radial-gradient(78% 62% at 10% -12%, rgba(255, 255, 255, .72) 0%, transparent 60%),
    radial-gradient(58% 46% at 99% 10%,  rgba(255, 255, 255, .52) 0%, transparent 58%),

    /* Colour blooms, FROM THE LIGHT END OF THE PALETTE. See the note above.

       AMPLITUDE, WHICH IS A SEPARATE QUESTION FROM DIRECTION.

       Building the field from the light end was right and is kept. The alphas
       it shipped with were not: 78% of `--forest-100` over the ground
       composites to #E3F1E8, twenty points of red under white, across roughly
       three quarters of the viewport. At that strength it stops reading as
       light falling on paper and starts reading as the paper's own colour —
       and a large, low-chroma green-grey field does not read as "green" to
       anyone looking at it, it reads as dirty white. Cream, most often, which
       is the exact complaint the warm layer was removed to fix.

       26% composites to #F3F8F4 — about eight points under white, which is a
       graduation you can see when you look for it and cannot see when you are
       reading. The direction was never the problem. The volume was. */
    radial-gradient(74% 60% at -2% 40%,  color-mix(in srgb, var(--forest-100) 26%, transparent) 0%, transparent 68%),
    radial-gradient(64% 50% at 102% 2%,  color-mix(in srgb, var(--chill-400)   8%, transparent) 0%, transparent 64%),
    radial-gradient(70% 40% at 88% 104%, color-mix(in srgb, var(--forest-100) 16%, transparent) 0%, transparent 66%),

    /* The ground carries the gradient itself, so there is graduation even on a
       screen the blooms do not reach. Fixed, so light is always at the top of
       the viewport.

       The bottom stop is pulled halfway back to white. At a full `--bone-2` it
       was a fourteen-point step on its own, and it stacks with the lower
       bloom that sits on top of it — the two together were most of why the
       bottom of a long page looked a different colour from the top of it. */
    linear-gradient(180deg,
      #FFFFFF 0%,
      var(--bg) 44%,
      color-mix(in srgb, var(--bone-2) 50%, var(--white)) 100%);
}

/* Dark keeps its depth — the ask was for the light theme to brighten, not for
   the dark one to stop being dark. The tints are eased back by the same
   proportion so the murk lifts, and the top highlight comes up a touch. */
[data-theme='dark'] body::before {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .06) 0%, transparent 44%),
    radial-gradient(64% 48% at 10% -6%,   color-mix(in srgb, var(--brand)  10%, transparent) 0%, transparent 64%),
    radial-gradient(50% 38% at 94% 6%,    color-mix(in srgb, var(--chill)   7%, transparent) 0%, transparent 62%),
    radial-gradient(78% 44% at 50% 106%,  color-mix(in srgb, var(--accent)  6%, transparent) 0%, transparent 68%),
    var(--bg);
}

/* Sections that set their own background need to let the field through, or
   they punch a flat hole in it. These become translucent instead.

   `.mach-band` is excluded because it deliberately sets its own half-step
   surface — this file loads after craft.css, so without the exclusion it wins
   and the machinery section loses its background entirely. */
.section:not(.band):not(.mach-band),
.usp-band,
.page-head { background: transparent; }

/* the one exception: bands are deliberately opaque, that is their whole job */
.band, .site-footer, .ticker { position: relative; z-index: 0; }

/* REMOVED: a 90px gradient across the top of every dark band, meant to soften
   the seam where a light section meets it.

   It used `--bg`, which in the light theme is bone — so it painted a pale wash
   DOWN INTO the dark band and rendered as a grey smear across the top of both
   the machinery band and The Dinkomart Line. It was softening the seam from the
   wrong side.

   The bands do not need it. They are supposed to be a hard cut: that contrast
   is what separates the farm side of the business from the home side. The one
   seam that genuinely needed help is the footer, which is handled properly in
   section 4 below with a rule and real spacing. */

/* ==================================================================== 2. pointer

   The custom cursor that used to live here was removed twice, and it is not
   coming back — see decision 11. What is here now is different in the one way
   that matters: `req/css/cursor.css` never hides the native pointer. It draws
   a label that follows it. Nothing in this codebase should ever set
   `cursor: none`. */

/* ==================================================================== 3. sound toggle

   Sound is OFF until asked for. A site that makes noise unprompted is a site
   people close. The control lives in the header next to the theme switch, and
   the choice is remembered. */
.sound-btn { position: relative; }
.sound-btn .ico-off { display: none; }
.sound-btn[aria-pressed='false'] .ico-on { display: none; }
.sound-btn[aria-pressed='false'] .ico-off { display: block; }
.sound-btn[aria-pressed='true'] { color: var(--brand-ink); }

/* a small ring pulses out of the button when sound is switched on, so the
   change is confirmed visually as well as audibly */
.sound-btn.is-ping::after {
  content: '';
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  border: 1.5px solid var(--brand);
  animation: sound-ping 620ms var(--ease-out) forwards;
}
@keyframes sound-ping {
  from { transform: scale(.7); opacity: .9; }
  to   { transform: scale(2.1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .sound-btn.is-ping::after { animation: none; } }

/* ==================================================================== 4. footer seam

   Measured: the last <main> section is `.band` at rgb(3,12,7) and the footer is
   rgb(6,21,13). Three points of luminance apart with no border between them, so
   on the page they fused into one undifferentiated black slab about 1400px tall
   and the footer stopped reading as a separate thing.

   The fix is a deliberate edge rather than a bigger colour gap, because the two
   SHOULD be close — they are both the dark end of the palette. So: a green-to-
   amber accent rule across the top, a hairline under it, and real space above
   the content. The seam becomes intentional.
   ========================================================================== */

.site-footer {
  position: relative;
  /* one step lighter than the deepest band, so there is a readable step even
     before the rule is drawn */
  background: var(--forest-800);
  border-top: 1px solid var(--band-border);
  padding-top: var(--s-12);
}

/* the accent rule. Sits on the boundary, not inside the footer. */
.site-footer::before {
  content: '';
  position: absolute;
  top: -1px; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(
    90deg,
    var(--forest-500) 0%,
    var(--sprout-500) 34%,
    var(--harvest-500) 68%,
    var(--iron-500) 100%
  );
  opacity: .9;
}

/* a soft lift just under the rule, so the edge has depth rather than being a
   flat line drawn on a flat field */
.site-footer::after {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 140px;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(255, 255, 255, .045), transparent);
}
.site-footer > * { position: relative; z-index: 1; }

/* the last band before the footer gets its bottom padding back, so the two are
   not touching in the first place */
main > .band:last-child,
main > .section.band:last-child { padding-bottom: var(--s-12); }

/* the same treatment where a dark band meets the light page below it */
.band + .section { position: relative; }

/* ==================================================================== 5. section rhythm
   Alternating sections were all sitting on the same field, so the page read as
   one long scroll with headings in it. Every other light section now picks up a
   very slightly different surface, which is enough to separate them without
   introducing another colour.

   THIS RULE SHIPPED THE §7 BUG A SIXTH TIME. It was authored against the raw
   `--bone-2`, and raw palette tokens do not flip with the theme — so in dark
   mode it painted a 55% CREAM wash across every even section and the middle of
   every dark page rendered as a grey-olive smear from roughly the second
   section to the footer.

   `--rhythm` is semantic and defined per theme: the cream in light, a 3% white
   lift in dark. If you ever need another wash like this, add a semantic token.
   Never reach for a `--bone-*`, `--loam-*` or any other raw name here.

   THE RULE ITSELF NOW LIVES IN refine.css §2, and there is only one of it.
   A near-duplicate was declared there too — flat rather than feathered, and
   excluding `.contour-bg` rather than `.mach-band`. Both were (0,4,1), refine
   loads last, so the flat copy won and this one only ever applied to the
   sections refine's selector happened to miss. Keeping the warning above here
   because this is where that history is written down; the declaration moved so
   there is a single place to change it. */

/* ==================================================================== 6. footer, tightened

   Measured problems: 128px of top padding on a 544px footer, a 402px brand
   column against 201px link columns (so the blurb had a wide empty margin while
   the links were cramped), and a background at rgb(10,33,20) that reads olive
   rather than forest.

   The orange "Open the catalogue" button was also the single most saturated
   thing on the page, sitting in the quietest part of it.
   ========================================================================== */

.site-footer {
  /* a deeper, bluer green. The olive came from forest-800 sitting next to the
     warm background field; this sits under it properly. */
  background: #071A10;
  padding-top: var(--s-10);
  padding-bottom: var(--s-6);
}

/* brand column narrower, link columns given room to breathe.

   Five items now — the brand plus Shop, Company, Help and Reach us. At the
   tablet break the brand takes the full width and the four link columns sit
   two-by-two under it, which keeps every label on one line; squeezing five
   tracks into 780px broke "Bio-fertilisers" and "Ordering and delivery" onto
   two lines each. The five-track row starts at 1060px, where it fits. */
@media (min-width: 780px) {
  .foot-grid { grid-template-columns: repeat(4, 1fr); gap: var(--s-7) var(--s-6); }
  .foot-brand { grid-column: 1 / -1; }
}
@media (min-width: 1060px) {
  .foot-grid { grid-template-columns: 1.5fr repeat(4, 1fr); gap: var(--s-8) var(--s-8); }
  .foot-brand { grid-column: auto; }
}

.foot-blurb { margin: var(--s-4) 0 var(--s-5); max-width: 38ch; font-size: var(--t-sm); line-height: 1.6; }

/* the catalogue button was shouting. Outlined, so it reads as an invitation
   rather than the loudest element in the quietest section. */
.foot-brand .btn-accent {
  background: transparent;
  border: 1px solid var(--band-border);
  color: var(--band-fg);
  box-shadow: none;
}
.foot-brand .btn-accent:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}

.foot-col h4 { margin-bottom: var(--s-3); }
.foot-col ul { gap: var(--s-1); }
.foot-col a { min-height: 32px; font-size: var(--t-sm); }

.foot-line { margin-top: var(--s-8); padding-top: var(--s-5); }

/* ==================================================================== 7. glass

   The card layer is translucent, so the gradient field in section 1 reads
   THROUGH the components instead of being covered by 85 opaque rectangles.
   That is the whole point: an opaque card grid on a gradient means you only
   ever see the gradient in the gutters.

   Deliberately NOT full glassmorphism:

     * The lift is a background-image highlight along the top edge, not a
       box-shadow. Several of these components already set box-shadow on a
       state (`.plan.is-pick`, `.pcard:hover`), and an inset shadow here would
       be silently dropped by those rules.
     * `backdrop-filter` is used almost nowhere. Blur only does visible work
       when there is detail behind the element, and behind these there is a
       smooth fixed gradient — so it would cost a compositor layer per card on
       a page that renders 85 of them, and buy nothing. It is applied only to
       the two sticky summaries, which genuinely do scroll over content.

   Opaque on purpose, do not add these: the drawers and the cart panel (they
   sit over the page and must occlude it), `.mach-band .spec-card` (supplier
   flyer artwork is white to the edge and needs a solid white tile), and
   `.pcard-media.is-contain` for the same reason.

   `.usp-item` is opaque on purpose too, and was removed from this list. It is
   still a card — see the usp strip block in components.css — but a glass one
   composited to 1.03:1 against the page with no shadow, so four of them read
   as four smudges. It carries `--surface` and `--shadow-sm` instead, and the
   elevation is what separates it. Putting it back here undoes that.

   `.cred` left for a different reason. Its cells are butt-joined over a
   --border ground inside `.cred-wall`, so a translucent cell lets the divider
   colour through its whole face — the cells composited to #F7F9F8 against
   #E1E9E4 seams, and the wall lost its grid. Opaque --surface keeps the cells
   white and the seams crisp.
   ========================================================================== */

.pcard,
.spec-card,
.cat-card,
.fact,
.plan,
.reach-item,
.crate,
.seq-aside,
.season-cell,
.season-pill,
.variant-opt,
.guarantee-item,
.pdp-fact,
.summary,
.order-summary {
  background-color: var(--glass);
  /* 72%, not 38%. The old stop put the highlight's edge across the middle of a
     product card — opaque above it, translucent below — which read as a seam
     once the body field gained a gradient to show through. Fading almost the
     full height makes it a sheen instead of a band. */
  background-image: linear-gradient(180deg, var(--glass-line) 0%, transparent 72%);
  border-color: var(--glass-border);
}

/* the two that scroll over real content get the blur as well */
.summary,
.order-summary {
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
}

/* Hover raises the glass rather than only lifting the box: the surface goes
   more opaque and the top highlight strengthens, which reads as the card
   coming toward the light. */
.pcard:hover,
.spec-card:hover,
.plan:hover,
.reach-item:hover,
.season-pill:hover { background-color: var(--glass-2); }

/* On a dark band the card layer would otherwise pick up the light theme's
   white highlight, so both are re-stated against the band's own palette.

   `.seller-perk` is NOT in this list any more and must not go back. It now
   carries its own fill and a hover in craft.css, and this rule is (0,2,0) in
   a file that loads after craft — so it beat `.seller-perk:hover` and the
   hover fill silently never landed. */
.on-band .fact {
  background-color: rgba(255, 255, 255, .04);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .06) 0%, transparent 40%);
  border-color: var(--band-border);
}

@media (max-width: 779px) {
  .site-footer { padding-top: var(--s-9); }
  .foot-grid { gap: var(--s-7); }
  .foot-blurb { max-width: none; }
}
