/* ============================================================
   GreenBat — Advanced Adhesive Solutions
   Design tokens & shared styles
   Palette: green-tinted paper, forest ink, mint accent
   Type:    Big Shoulders Display (headlines) / IBM Plex Sans (body)
            / IBM Plex Mono (spec data) — Sans + Mono share the same
            type family on purpose, one engineered system rather than
            a generic grotesk borrowed from any other site.
   ============================================================ */

:root {
  --paper:      #F3F5F1;
  --card:       #FFFFFF;
  --ink:        #0E231A;
  --ink-soft:   #3E5247;
  --green:      #17603D;
  --green-deep: #0C4229;
  --green-mist: #E3ECE4;
  --mint-deep:  #0E8F5C;
  --mint:       #2FD08A;
  --mint-hover: #29C280;
  --mint-light: #8FF0C4;
  --mint-soft:  #D7F5E6;
  --mint-soft-ink: #0E6B47; /* darker than --mint-deep — needed for small badge text on --mint-soft to clear 4.5:1 */
  --line:       #D3DCD3;
  --line-dark:  rgba(255,255,255,.14);

  /* display face is scoped to headlines, the wordmark and big stat numbers —
     not h3 (card-title scale) or UI text, where a condensed face gets harder
     to read at small sizes. Everything else stays on the IBM Plex body face. */
  --font-display: "Big Shoulders Display", "IBM Plex Sans", system-ui, sans-serif;
  --font-body:    "IBM Plex Sans", system-ui, sans-serif;
  --font-mono:    "IBM Plex Mono", ui-monospace, "Courier New", monospace;

  /* two-token radius system: hard layer (information surfaces — cards, specs,
     badges, icon tiles) vs soft layer (anything inviting action — buttons,
     filter chips). The enquiry dialog keeps its own 14px, exempt from both. */
  --radius-hard: 4px;
  --radius-soft: 999px;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --seam: linear-gradient(90deg, #0E8F5C, #2FD08A 35%, #8FF0C4 50%, #2FD08A 65%, #0E8F5C);

  /* six-step type scale for everything under 1rem — replaces ~20 one-off sizes.
     --text-base/--text-md are the existing body (1.0625rem) and h3/card-title
     (1.25rem) sizes, named here for documentation only; those rules keep their
     literal values unchanged per the design direction. */
  --text-micro: 0.6875rem; /* 11px — brand-tag */
  --text-2xs:   0.75rem;   /* 12px — eyebrow, chip, spec, field-label */
  --text-xs:    0.8125rem; /* 13px — sheet-more drawer copy, dialog-sub */
  --text-sm:    0.875rem;  /* 14px — cap-col/step/pillar/cert-row body copy, sheet-desc */
  --text-base:  1.0625rem; /* unchanged body size */
  --text-md:    1.25rem;   /* unchanged h3 / card-title size */

  /* 4px-based spacing ramp — replaces six uncoordinated card-padding pairs.
     Info cards (cap/cert/step/pillar) standardise on --space-6/--space-5;
     product sheets keep denser --space-5/--space-5. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 48px;

  /* interaction timing — a small deliberate set, not one-off values per element.
     ease-out: entering/responding (hover, click, appear). ease-in: exiting.
     ease-in-out: state changes that stay on screen (e.g. the nav-toggle morph).
     spring: gentle overshoot for physical moments (cards, drawer) — the
     iOS-sheet-style curves that make motion feel fluid rather than mechanical. */
  --ease-out: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --spring: cubic-bezier(0.34, 1.35, 0.64, 1);
  --quick: .2s;     /* hover response */
  --press: .09s;    /* click/tap confirmation — faster than hover */

  /* focus ring: --mint-deep clears 3:1 (WCAG 2.4.13) against paper/white; on-dark
     sections switch to the lighter --mint-light, which clears 3:1 against green-deep
     but fails badly against light backgrounds — never use one color for both. */
  --focus: var(--mint-deep);
}
.on-dark { --focus: var(--mint-light); }

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  /* inherited: keep the last line of any paragraph from stranding a single
     word (a widow). Headlines override this with balance below. */
  text-wrap: pretty;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; }

.container { max-width: 1180px; margin-inline: auto; padding-inline: var(--gutter); }

/* ---------- typography ---------- */
/* Big Shoulders Display is already condensed, so it doesn't need the tight
   negative tracking a normal-width grotesk does — that combination reads
   cramped rather than sharp. Loosened tracking and slightly larger sizes let
   the condensed letterforms actually show their character at this scale.
   Line height: the face's descenders reach .22em below the baseline and its
   ascenders .81em above it, so anything under 1.03 lets a j, y or g on one
   line cut into an f, l or t on the next (measured 26 Sep: .96 overlapped by
   up to 5px at hero size on "Every bond, / catalogued."). 1.06 clears by
   2.5px at hero size and 1.2px at phone size (measured). Don't tighten it. */
h1, h2 { font-family: var(--font-display); line-height: 1.06; letter-spacing: -0.005em; text-wrap: balance; }
h1 { font-size: clamp(2.9rem, 7.2vw, 5.1rem); font-weight: 800; }
h2 { font-size: clamp(2.1rem, 4.4vw, 3.2rem); font-weight: 800; }
h3 { font-family: var(--font-body); font-size: 1.25rem; font-weight: 700; letter-spacing: -0.01em; line-height: 1.15; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--green);
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  margin-bottom: 1rem;
}
.on-dark .eyebrow { color: #A9D8BC; }

.lede { font-size: clamp(1.05rem, 1.8vw, 1.25rem); color: var(--ink-soft); max-width: 58ch; }
.on-dark .lede { color: #C7D8CC; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .55rem;
  /* body face, not the condensed display face — buttons are an invitation,
     and the industrial headline face reads stern at button size. */
  font-family: var(--font-body); font-weight: 600; font-size: .95rem; letter-spacing: .005em;
  padding: .85rem 1.5rem; border-radius: var(--radius-soft);
  text-decoration: none; border: 2px solid transparent;
  cursor: pointer;
  transition: transform var(--quick) var(--ease-out), background var(--quick) var(--ease-out),
              color var(--quick) var(--ease-out), border-color var(--quick) var(--ease-out);
}
.btn:hover { transform: scale(1.03); transition: transform .3s var(--spring), background var(--quick) var(--ease-out), color var(--quick) var(--ease-out), border-color var(--quick) var(--ease-out); }
.btn:active { transform: scale(.97); transition-duration: var(--press); }
.btn-primary { background: var(--green); color: #fff; }
.btn-primary:hover { background: var(--green-deep); }
.btn-resin { background: var(--mint); color: var(--green-deep); }
.btn-resin:hover { background: var(--mint-hover); }
.btn-ghost { border-color: currentColor; color: var(--green); background: transparent; }
.btn-ghost:hover { background: var(--green); color: #fff; border-color: var(--green); }
.on-dark .btn-ghost { color: #E8F2EA; }
.on-dark .btn-ghost:hover { background: #E8F2EA; color: var(--green-deep); border-color: #E8F2EA; }
.btn .arrow { transition: transform var(--quick) var(--ease-out); }
.btn:hover .arrow { transform: translateX(3px); }

:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 4px; }

/* ---------- header / nav ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(243,245,241,.88);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.nav {
  display: flex; align-items: center; justify-content: space-between;
  height: 76px;
}
.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; }
.brand-mark { width: 42px; height: 42px; flex: none; }
.brand-text { line-height: 1.1; }
.brand-name { font-family: var(--font-display); font-weight: 800; font-size: 1.35rem; letter-spacing: -0.005em; }
.bat { color: var(--green); } /* default: any brand-name mention, in prose or the logo, light bg */
/* on dark green sections, --green text would nearly vanish — reuse the same
   accent-highlight idea (colored portion of the brand name) but in a shade
   that actually shows up against green-deep. */
.on-dark .bat { color: var(--mint-light); }
/* footer is dark but not .on-dark (different bg, --ink not --green-deep) —
   --green fails contrast there (2.18:1), needs its own bright-on-dark shade. */
.site-footer .bat { color: var(--mint-light); }
.brand-tag { font-family: var(--font-mono); font-weight: 600; font-size: var(--text-micro); letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft); }

.nav-links { display: flex; align-items: center; gap: 2rem; list-style: none; }
.nav-links a:not(.btn) {
  text-decoration: none; font-weight: 600; font-size: .95rem;
  color: var(--ink-soft); padding-block: .4rem; position: relative;
}
.nav-links a:not(.btn)::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 3px; border-radius: 2px;
  background: var(--seam);
  transform: scaleX(0); transform-origin: left;
  transition: transform .2s var(--ease-out);
}
.nav-links a:not(.btn):hover::after,
.nav-links a[aria-current="page"]::after { transform: scaleX(1); }
.nav-links a[aria-current="page"] { color: var(--ink); }

.nav-toggle {
  display: none; background: none; border: 0; cursor: pointer;
  width: 44px; height: 44px; border-radius: 8px;
}
.nav-toggle span {
  display: block; width: 22px; height: 2.5px; background: var(--ink);
  margin: 5px auto; border-radius: 2px;
  /* ease-in-out: this morphs between two on-screen states (hamburger ↔ X),
     not an entrance/exit, so it should ease at both ends. */
  transition: transform .2s var(--ease-in-out), opacity .2s var(--ease-in-out);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

@media (max-width: 840px) {
  .nav-toggle { display: block; }
  .nav-links {
    position: absolute; top: 76px; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper); border-bottom: 1px solid var(--line);
    padding: .5rem var(--gutter) 1.25rem;
    display: none;
  }
  .nav-links.open { display: flex; }
  .nav-links li { border-top: 1px solid var(--line); }
  .nav-links li:last-child { border-top: 0; padding-top: 1rem; }
  .nav-links a:not(.btn) { display: block; padding: .9rem 0; }
}

/* ---------- grain — keeps flat dark-green fills from reading as a digital gradient ---------- */
.hero::before, .section.dark::before, .page-hero::before {
  content: "";
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: .05;
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* ---------- hero (home) ---------- */
.hero {
  /* not a flat fill: a mint radial bloom on the right, deepening toward
     the bottom-left. */
  background:
    radial-gradient(ellipse 60% 55% at 74% 45%, rgba(47,208,138,.16), transparent 70%),
    radial-gradient(ellipse 80% 90% at 10% 110%, rgba(5,28,18,.85), transparent 65%),
    var(--green-deep);
  color: #F0F6F1;
  overflow: hidden;
  position: relative;
}
/* faint engineering grid — sits under the grain, over the gradients */
.hero .hero-inner::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(143,240,196,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(143,240,196,.05) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: radial-gradient(ellipse 70% 70% at 70% 50%, #000 30%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 70% 70% at 70% 50%, #000 30%, transparent 75%);
  pointer-events: none;
}
.hero .hero-inner { position: relative; }
.hero-inner {
  padding-block: clamp(4rem, 9vw, 7.5rem);
}
/* text-only hero (2026-09-24) until a real product photo takes the right half */
.hero-inner > div { max-width: 46rem; }
.hero h1 { color: #fff; }
.hero h1 .accent { color: var(--mint-light); }
.hero .lede { margin-top: 1.4rem; }
.hero-actions { display: flex; flex-wrap: wrap; gap: .9rem; margin-top: 2.2rem; }

/* ---------- sections ---------- */
.section { padding-block: clamp(3.5rem, 8vw, 6.5rem); }
.section-head { max-width: 60ch; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head.center .eyebrow { justify-content: center; }
.section.tinted { background: var(--green-mist); }
/* hero handoff — the first light section after a dark hero: a mint wash
   bleeds down from the top edge and fades into the paper, so the section
   reads as the hero's glow settling rather than a hard cut to flat
   background. Used by "What we do" (home) and "Our story" (about). */
.section.capabilities,
.section.hero-handoff {
  background:
    radial-gradient(ellipse 75% 60% at 50% -15%, rgba(47,208,138,.14), transparent 70%),
    linear-gradient(180deg, var(--green-mist), var(--paper) 55%);
}
.section.dark { background: var(--green-deep); color: #E9F1EA; position: relative; overflow: hidden; }
.section.dark h2 { color: #fff; }

/* ---------- capability columns (plain, card-less — Direction §3 index.html "Capabilities") ---------- */
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.4rem; }
@media (max-width: 900px) { .grid-3 { grid-template-columns: 1fr; } }
.capabilities .grid-3 { gap: var(--space-6); }

.cap-col { border-top: 1px solid var(--line); padding-top: var(--space-6); }
.cap-col p { color: var(--ink-soft); font-size: var(--text-sm); margin-top: .5rem; }
.cap-icon-bare { display: block; color: var(--green); margin-bottom: 1.1rem; }

/* ---------- shared info-card foundation (hard layer) ----------
   .step and .pillar share one hairline, no-elevation base here (see
   design-direction Section 4, "duplicated card rule blocks"). Each block
   below layers only its distinguishing detail (icon/numeral, colour bar) on
   top. .cap-card/.cap-icon/.cert-card/.cert-grid used to belong to this same
   group but were removed in the 2026-08-10 consolidation pass: capabilities
   and certifications moved to card-less layouts (.cap-col, .cert-row) and
   nothing in index.html/about.html/products.html references the old classes
   any more (verified by grep across all three live pages). .info-block is
   kept, unused for now, as a deliberate extension point for markup that
   adopts this pattern later — anything given the class gets the same base
   for free. */
.step, .pillar, .info-block {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-hard);
  padding: var(--space-6) var(--space-5); position: relative; overflow: hidden;
}
/* seam-reveal top border on hover — the cheap, already-proven hover signal,
   kept on pillar only now (step has no hover state per the design direction;
   cert moved to hairline rows with no hover treatment requested). */
.pillar::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: var(--seam); transform: scaleX(0); transform-origin: left; transition: transform .25s var(--ease-out);
}
.pillar:hover::before { transform: scaleX(1); }

/* ---------- proof — certifications (hairline rows) ---------- */
.cert-rows { display: flex; flex-direction: column; }
.cert-row {
  display: flex; gap: 1.1rem; align-items: flex-start;
  padding-block: var(--space-5); border-bottom: 1px solid var(--line);
}
.cert-row:last-child { border-bottom: none; }
.cert-icon {
  flex: none; width: 46px; height: 46px; border-radius: var(--radius-hard);
  background: var(--green-mist); color: var(--green);
  display: grid; place-items: center;
}
.cert-row h3 { margin-bottom: .3rem; }
.cert-row p { color: var(--ink-soft); font-size: var(--text-sm); }

/* ---------- about — range list (hairline rows, like the cert rows) ---------- */
.make-list { list-style: none; max-width: 60ch; border-top: 1px solid var(--line); }
.make-list li {
  padding-block: var(--space-4); border-bottom: 1px solid var(--line);
  color: var(--ink-soft); font-size: var(--text-sm);
}
.make-list strong { display: block; color: var(--ink); font-size: 1rem; }
.lede + .lede { margin-top: var(--space-4); }

/* ---------- datasheet product cards ---------- */
.product-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.4rem; }
@media (max-width: 980px) { .product-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .product-grid { grid-template-columns: 1fr; } }

.sheet {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-hard);
  overflow: hidden; display: flex; flex-direction: column;
  position: relative;
  transition: transform .35s var(--spring), box-shadow .35s var(--ease-out);
}
/* the whole card is one tap target: the CTA link stretches over the card via
   a pseudo-element, so a click anywhere goes through the same anchor (and the
   same data-product prefill handler). The button stays as the visual cue. */
.sheet .sheet-cta::after { content: ""; position: absolute; inset: 0; }
/* the Enquire button rides above the drawer, switching to a filled mint chip
   so it stays legible (and inviting) on the dark panel. */
.sheet .sheet-cta { position: relative; z-index: 3; }
.sheet:hover .sheet-cta,
.sheet:focus-within .sheet-cta {
  background: var(--mint); color: var(--green-deep); border-color: var(--mint);
}
.sheet:hover .sheet-cta:hover { background: var(--mint-hover); border-color: var(--mint-hover); }

/* hover drawer — extra product context slides up over the lower card. The
   .45s reveal delay means casual mouse-travel across the grid doesn't trigger
   it; only a deliberate pause does (tooltip-style intent detection). Exit is
   quick + ease-in per the exit rule. pointer-events: none lets clicks pass
   through to the stretched card link. */
.sheet-more {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  background: linear-gradient(180deg, rgba(12,66,41,.96), rgba(7,40,25,.98));
  /* bottom padding reserves the Enquire button's zone (button top sits ~68px
     off the card's bottom edge) so drawer text ends above it — the button
     then reads as the drawer's own action rather than floating over its copy. */
  color: #D6E5DA; padding: 1.2rem 1.3rem 5.25rem;
  font-size: var(--text-xs); line-height: 1.5;
  transform: translateY(100%);
  transition: transform .18s var(--ease-in);
  pointer-events: none;
}
.sheet:hover .sheet-more,
.sheet:focus-within .sheet-more {
  transform: translateY(0);
  transition: transform .4s var(--spring) .45s;
}
.sheet-more .more-title {
  font-family: var(--font-mono); font-size: var(--text-micro); letter-spacing: .16em;
  text-transform: uppercase; color: var(--mint-light); margin-bottom: .5rem;
}
.sheet-more .more-packs { margin-top: .55rem; color: #A9CDB4; font-size: var(--text-xs); }
/* "pending" = honest placeholder on a dark drawer bg — needs its own muted
   shade, distinct from .spec-row/.sheet-desc's light-card pending style above. */
.sheet-more p.pending { font-style: italic; color: #8FA795; }
.sheet-more .more-packs.pending { color: #8FA795; font-style: italic; } /* was #7C9587, 4.21:1 on the drawer; #8FA795 measures 5.26:1 */

/* enquiry choice dialog */
.enquire-dialog {
  border: none; border-radius: 14px; padding: 2rem 2.1rem;
  max-width: 26rem; width: calc(100% - 2.5rem);
  background: var(--card); color: var(--ink);
  box-shadow: 0 30px 70px rgba(8,30,20,.35);
}
.enquire-dialog::backdrop { background: rgba(8,30,20,.55); backdrop-filter: blur(4px); }
.enquire-dialog[open] { animation: dialogIn .25s var(--ease-out); }
@keyframes dialogIn { from { opacity: 0; transform: translateY(14px); } }
.enquire-dialog h3 { margin: .3rem 0 .5rem; }
.enquire-dialog .dialog-sub { color: var(--ink-soft); font-size: var(--text-xs); margin-bottom: 1.4rem; }
.dialog-actions { display: flex; flex-wrap: wrap; gap: .7rem; }
.sheet:hover {
  transform: translateY(-4px) scale(1.012);
  box-shadow: 0 16px 34px rgba(14,35,26,.1), 0 0 28px rgba(47,208,138,.35);
}
.sheet-head {
  padding: var(--space-5) var(--space-5); border-bottom: 1px dashed var(--line);
  display: flex; justify-content: space-between; align-items: baseline; gap: .8rem;
}
.sheet-code { font-family: var(--font-body); font-size: var(--text-xs); font-weight: 600; letter-spacing: .02em; color: var(--green); }
.sheet-cat {
  font-family: var(--font-body); font-size: var(--text-2xs); font-weight: 600; letter-spacing: .02em;
  background: var(--mint-soft); color: var(--mint-soft-ink); padding: .22rem .55rem; border-radius: var(--radius-hard); white-space: nowrap;
}
.sheet-body { padding: var(--space-5) var(--space-5); display: flex; flex-direction: column; flex: 1; }
.sheet h3 { margin-bottom: .35rem; }
.sheet-desc { color: var(--ink-soft); font-size: var(--text-sm); margin-bottom: 1.1rem; }
.spec { font-family: var(--font-body); font-size: var(--text-xs); border-top: 1px solid var(--line); margin-top: auto; font-variant-numeric: tabular-nums; }
.spec-row { display: flex; justify-content: space-between; gap: 1rem; padding: .5rem 0; border-bottom: 1px solid var(--line); }
.spec-row dt { color: var(--ink-soft); }
.spec-row dd { font-weight: 500; text-align: right; }
/* honest placeholder for fields Ronald hasn't confirmed yet — distinct from
   real data so nothing invented is mistaken for a spec, and easy to grep for
   before this goes live (see GreenBat-Website-Checklist.docx). */
.spec-row dd.pending, .sheet-cat.pending, .sheet-desc.pending { font-weight: 400; font-style: italic; color: var(--ink-soft); }
.sheet-cat.pending { background: var(--line); color: var(--ink-soft); }
.sheet-cta {
  margin-top: 1.1rem; align-self: flex-start;
  font-size: var(--text-xs); padding: .6rem 1.1rem;
}

/* ---------- filter chips (products page) ---------- */
.filters {
  display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 2.2rem;
  /* stays reachable while scrolling the 10-card grid — switching category
     shouldn't require scrolling back to the top. Sits just below the sticky
     header; translucent paper + blur so cards sliding under it stay legible. */
  position: sticky; top: 76px; z-index: 40;
  background: rgba(243,245,241,.9);
  backdrop-filter: blur(8px);
  padding-block: .75rem;
}
.chip {
  font-family: var(--font-body); font-size: var(--text-xs); font-weight: 600;
  padding: .55rem 1.05rem; border-radius: var(--radius-soft); cursor: pointer;
  /* 44px floor: these are primary tap targets on the products page, and at
     34px they fell under the minimum comfortable touch size. */
  min-height: 44px; display: inline-flex; align-items: center;
  background: transparent; border: 1.5px solid var(--line); color: var(--ink-soft);
  transition: background-color var(--quick) var(--ease-out), border-color var(--quick) var(--ease-out),
              color var(--quick) var(--ease-out), transform var(--press) var(--ease-out);
}
.chip:hover { border-color: var(--green); color: var(--green); }
.chip:active { transform: scale(.95); }
.chip.active { background: var(--green); border-color: var(--green); color: #fff; }
.sheet.hidden { display: none; }
.filter-empty { font-family: var(--font-body); font-size: var(--text-sm); color: var(--ink-soft); padding: 2rem 0; display: none; }

/* ---------- page hero (inner pages) ---------- */
.page-hero {
  /* same lit-scene treatment as the home hero, adapted to this hero's
     geometry: its seam runs along the bottom edge, so the mint bloom rises
     from there, with the top-left falling into shadow behind the headline. */
  background:
    radial-gradient(ellipse 70% 60% at 50% 115%, rgba(47,208,138,.15), transparent 70%),
    radial-gradient(ellipse 80% 90% at 5% -20%, rgba(5,28,18,.8), transparent 65%),
    var(--green-deep);
  color: #EAF2EB; padding-block: clamp(3.2rem, 7vw, 5.5rem); position: relative; overflow: hidden;
}
.page-hero h1 { color: #fff; max-width: 16ch; }
.page-hero .lede { margin-top: 1.1rem; }
.page-hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 6px; background: var(--seam);
}
/* faint engineering grid over the open right side, matching the home hero */
.page-hero .container { position: relative; }
.page-hero .container::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(143,240,196,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(143,240,196,.05) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: radial-gradient(ellipse 55% 85% at 85% 50%, #000 30%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 55% 85% at 85% 50%, #000 30%, transparent 75%);
  pointer-events: none;
}

/* ---------- eco band ---------- */
.eco-band { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }
@media (max-width: 900px) { .eco-band { grid-template-columns: 1fr; } }
.eco-points { list-style: none; display: grid; gap: 1rem; margin-top: 1.6rem; }
.eco-points li { display: flex; gap: .85rem; align-items: flex-start; color: #D6E5DA; font-size: var(--text-sm); }
/* honest placeholder in the enquiry contact list (sales line still owed, C1) — same muted mint as the drawer's pending copy */
.eco-points .pending { font-style: italic; color: #A9CDB4; }
.eco-points .tick {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  background: rgba(47,208,138,.15); color: var(--mint-light);
  display: grid; place-items: center; font-size: var(--text-2xs); margin-top: .15rem;
}
.eco-figure {
  background: #114F31; border: 1px solid var(--line-dark); border-radius: var(--radius-hard);
  padding: 2rem; font-family: var(--font-body);
}

/* the enquiry section is the target of every "Request a quote" link — offset the
   scroll so the sticky 76px header doesn't land on top of its heading. */
#enquire { scroll-margin-top: 92px; }

/* ---------- enquiry form fields ---------- */
.field-label {
  display: grid; gap: .35rem; font-size: var(--text-sm); font-weight: 500; color: #A9CDB4;
}
.field {
  font-family: var(--font-body); font-size: 1rem; padding: .7rem .9rem;
  border-radius: var(--radius-hard); border: 1px solid var(--line-dark);
  background: #0C4229; color: #fff; resize: vertical;
  /* the global :focus-visible ring sits outside the field with a 3px offset,
     which reads fine for links/buttons but a text field also needs its own
     border to visibly change — otherwise there's no feedback tight against
     the edge you're about to type into. */
  transition: border-color var(--quick) var(--ease-out);
}
.field:focus-visible { border-color: var(--focus); }

/* inline-block + symmetric padding/negative margin lifts the tap box from
   23px to ~28px without moving the text (2026-09-07 QA sweep, WCAG 2.5.8). */
.contact-link { text-decoration: none; transition: opacity var(--quick) var(--ease-out); display: inline-block; padding-block: .15rem; margin-block: -.15rem; }
.contact-link:hover { opacity: .75; }
.eco-stat { padding: 1rem 0; border-bottom: 1px dashed var(--line-dark); }
.eco-stat:last-child { border-bottom: 0; }
.eco-stat .num { font-family: var(--font-display); font-weight: 800; font-size: 2.15rem; color: var(--mint-light); letter-spacing: -0.005em; font-variant-numeric: tabular-nums; }
.eco-stat .lbl { font-size: var(--text-2xs); letter-spacing: .14em; text-transform: uppercase; color: #A9CDB4; }
.meter { height: 4px; background: rgba(255,255,255,.14); border-radius: 2px; margin: .6rem 0 .5rem; overflow: hidden; }
.meter-fill {
  height: 100%; width: 0; border-radius: 2px;
  background: var(--seam);
  /* capped at .6s (top of the "deliberate" tier) — this is a routine reveal
     repeated per stat, not the page's one signature moment, so it shouldn't
     compete with other motion on the page. */
  transition: width .6s var(--ease-out);
}
.eco-figure.in .meter-fill { width: var(--fill); }
.eco-stat:nth-child(2) .meter-fill { transition-delay: .18s; }

/* ---------- process timeline (about) ---------- */
.process { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.4rem; counter-reset: step; position: relative; }
@media (max-width: 980px) { .process { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .process { grid-template-columns: 1fr; } }
/* background/border/radius/padding/position come from the shared info-card
   rule above (.step, .pillar, .info-block) — .process .step below strips all
   of it back off again. step is deliberately left out of the seam-reveal
   hover group — no hover animation here, the enlarged mono numeral is the
   sole visual device. */
.step {
  counter-increment: step;
  z-index: 1; /* sit above the hairline rail, which is drawn behind the row */
}
/* Process drops the card chrome entirely (no border, no box) — only .step
   gets this, so it doesn't touch .pillar/.info-block, which share the same
   base rule and keep their hairline box. */
.process .step {
  background: none;
  border: none;
  padding: var(--space-2) 0 0;
}
/* the numeral is the section's primary visual device now, not a quiet corner
   index: it flows as a real static block above the icon (DOM order is
   already numeral → icon → h3 → p via this ::before, no markup change
   needed) and scales up accordingly. line-height: 1 keeps its box tight so
   the hairline rail below can line up with its visual centre predictably
   instead of drifting inside 20px+ of inherited body line-height. */
.step::before {
  content: "0" counter(step);
  font-family: var(--font-mono);
  position: static;
  display: block;
  line-height: 1;
  font-size: clamp(2.25rem, 3.4vw, 2.75rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--green);
  margin-bottom: var(--space-3);
}
.step-icon {
  width: 40px; height: 40px; border-radius: var(--radius-hard);
  background: var(--green-mist); color: var(--green);
  display: grid; place-items: center; margin-bottom: 1rem;
}
.step p { font-size: var(--text-sm); color: var(--ink-soft); margin-top: .45rem; }
/* hairline rail behind the row — visualises the four steps as one continuous
   line, a quiet callback to "the strongest joints are the ones you never
   see." top is tuned to the numeral's vertical centre at the one width range
   the rail is actually shown at (see the 980px decision below), not a
   generic guess.
   980px two-row-wrap decision: below 980px .process drops from 4 columns to
   a 2×2 wrap. A single full-width line at that point would either cross
   both rows or land level with only one of them — neither reads as "one
   continuous line," it reads as a bug — and a per-row rail would need
   nth-child-pair selectors keyed to a fixed column count, which breaks the
   moment the wrap count changes. Rather than fake it, the rail is turned
   off for the whole two-column/one-column range below; above 980px (the one
   place it renders) it is deliberate, not detached. */
.process::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  /* padding-top (--space-2) + half the numeral's own font-size clamp, not a
     fixed guess — this tracks the numeral's line-height:1 vertical centre
     exactly at every width in the range the rail is shown (verified to
     within 0.2px at 1280px against the numeral's measured centre). */
  top: calc(var(--space-2) + clamp(2.25rem, 3.4vw, 2.75rem) / 2);
  height: 1px;
  background: var(--line);
  z-index: 0;
}
@media (max-width: 980px) {
  .process::before { display: none; }
}

/* ---------- values — four pillars, bonded on one seam ---------- */
.pillars { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.4rem; position: relative; padding-bottom: 1.8rem; }
.pillars::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 4px;
  background: var(--seam); border-radius: 2px;
  box-shadow: 0 0 16px rgba(47,208,138,.35);
}
@media (max-width: 980px) { .pillars { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .pillars { grid-template-columns: 1fr; } }

/* background/border/radius/padding/position/seam-reveal hover come from the
   shared info-card rule above; pillar only adds its own layout + colour bar. */
.pillar {
  display: flex; flex-direction: column;
}
.pillar-cap { width: 28px; height: 6px; border-radius: 3px; background: var(--green); margin-bottom: 1.1rem; }
.pillar h3 { color: var(--green); margin-bottom: .5rem; }
.pillar p { color: var(--ink-soft); font-size: var(--text-sm); }

/* ---------- CTA band ---------- */
.cta-band { text-align: center; }
.cta-band h2 { max-width: 22ch; margin-inline: auto; }
.cta-band .lede { margin: 1rem auto 2rem; }

/* ---------- footer ---------- */
.site-footer {
  background:
    radial-gradient(ellipse 70% 55% at 50% -10%, rgba(47,208,138,.07), transparent 70%),
    var(--ink);
  color: #B9CBBE; padding-block: 3.5rem 2rem; font-size: .92rem;
  position: relative; overflow: hidden;
  /* focus ring: match the other dark surfaces — mint-light hits 12:1 here
     where the default mint-deep only manages 4:1 against --ink. */
  --focus: var(--mint-light);
}
/* seam along the footer's top edge — bookends the page: inner-page heroes
   carry the seam on their bottom edge, the footer answers with its top. */
.site-footer::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 4px;
  background: var(--seam);
}
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 2.5rem; margin-bottom: 2.5rem; }
@media (max-width: 800px) { .footer-grid { grid-template-columns: 1fr; } }
.site-footer h4 { font-family: var(--font-mono); font-size: var(--text-micro); letter-spacing: .18em; text-transform: uppercase; color: #7FA98B; margin-bottom: 1rem; }
.site-footer ul { list-style: none; display: grid; gap: .55rem; }
/* same underline-reveal language as the nav, scaled down — one hover idiom
   for text links across the whole site, not a different one per region. */
.site-footer a {
  text-decoration: none; position: relative; display: inline-block;
  transition: color .15s var(--ease-out);
}
/* extend the tap area vertically past the text's visual bounds — gets these
   ~30px-tall text links to a comfortable touch size without moving anything
   on screen (padding would push the underline away from the text). */
.site-footer a::before {
  content: ""; position: absolute; left: 0; right: 0; top: -8px; bottom: -8px;
}
.site-footer a::after {
  content: ""; position: absolute; left: 0; bottom: -2px; width: 100%; height: 2px;
  border-radius: 1px; background: var(--mint);
  transform: scaleX(0); transform-origin: left;
  transition: transform .2s var(--ease-out);
}
.site-footer a:hover { color: #fff; }
.site-footer a:hover::after, .site-footer a:focus-visible::after { transform: scaleX(1); }
.footer-brand .brand-name { color: #fff; }
.footer-brand .brand-mark { width: 34px; height: 34px; margin-bottom: .7rem; }
.footer-contact li { display: flex; align-items: center; gap: .6rem; }
.footer-contact svg { flex: none; color: #7FA98B; }
/* honest placeholder for a contact not confirmed yet, distinct from a real
   mailto link so nobody mistakes a guess for a working address. */
.footer-contact .pending { font-style: italic; color: #7C9587; }
.footer-brand p { margin-top: .8rem; max-width: 34ch; color: #8FA795; font-size: .9rem; }
.footer-base {
  border-top: 1px solid var(--line-dark); padding-top: 1.4rem;
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: .8rem;
  /* #7FA98B (6.24:1 on --ink) not the earlier #6D8674, which measured 4.17:1
     on the 2026-09-07 QA sweep — 11px text needs the full 4.5:1. */
  font-family: var(--font-body); font-size: var(--text-2xs); color: #7FA98B;
}

/* ---------- misc layout utilities ----------
   Hoisted from per-element inline `style` attributes during the 2026-08-10
   consolidation pass (the three HTML agents that authored them could not
   touch this file, so they parameterised with existing tokens inline —
   see _refine/CSS-REQUESTS-*.md). Grouped here since each is a small,
   single-purpose utility rather than belonging to one component family. */
.center-cta { text-align: center; margin-top: 2.4rem; }
.hero-handoff .lede:not(:last-child) { margin-bottom: 1.2rem; }
.cta-actions { display: flex; gap: .9rem; justify-content: center; flex-wrap: wrap; }
.enquiry-fields { display: grid; gap: .9rem; }
.form-note { font-size: var(--text-xs); color: #A9CDB4; display: none; }
.field-hint { font-size: var(--text-xs); color: #A9CDB4; margin-top: -.5rem; }
.field-hint.over { color: #FFB8A8; font-weight: 600; } /* warm coral: readable on the dark section, no brand clash */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.enquiry-fields .btn:disabled { opacity: .7; cursor: progress; transform: none; }
.enquire-email-link { color: var(--mint-light); font-weight: 600; }

/* ---------- copy-email button (added by main.js beside each mailto) ----------
   Both homes are dark surfaces. Muted until hover, same as the footer icons,
   so it reads as a helper beside the address rather than a second CTA. */
.copy-email {
  position: relative; flex: none; display: inline-grid; place-items: center;
  width: 28px; height: 28px; margin-block: -2px; padding: 0;
  border: 1px solid var(--line-dark); border-radius: var(--radius-hard);
  background: transparent; color: #7FA98B; cursor: pointer;
  transition: color var(--quick) var(--ease-out), border-color var(--quick) var(--ease-out), background-color var(--quick) var(--ease-out);
}
.eco-points .copy-email { color: #A9CDB4; margin-top: -.05rem; }
.copy-email:hover { color: #fff; border-color: rgba(143,240,196,.45); background: rgba(47,208,138,.1); }
.copy-email:active { transform: scale(.94); transition-duration: var(--press); }
.copy-email.copied { color: var(--mint-light); border-color: var(--mint); }
.copy-email-tip {
  position: absolute; bottom: calc(100% + 6px); left: 50%;
  translate: -50% 4px; opacity: 0; pointer-events: none; white-space: nowrap;
  font-family: var(--font-mono); font-size: var(--text-micro); letter-spacing: .08em;
  color: var(--ink); background: var(--mint-light); padding: .2rem .45rem; border-radius: var(--radius-hard);
  transition: opacity .15s var(--ease-out), translate .2s var(--ease-out);
}
.copy-email.copied .copy-email-tip { opacity: 1; translate: -50% 0; }
@media (prefers-reduced-motion: reduce) {
  .copy-email, .copy-email-tip { transition: none; }
  .copy-email:active { transform: none; }
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.enquire-phone-link { color: #E9F1EA; }

/* ---------- enquiry consent (POPIA) ----------
   The whole label is the tap target (min 24px tall), not just the 20px box. */
.field-check {
  display: flex; gap: .7rem; align-items: flex-start; min-height: 24px;
  font-size: var(--text-xs); line-height: 1.5; color: #C7D8CC; cursor: pointer;
}
.field-check input { flex: none; width: 20px; height: 20px; margin-top: .1rem; accent-color: var(--mint); cursor: pointer; }
.field-check a { color: var(--mint-light); font-weight: 600; display: inline-block; padding-block: .25rem; margin-block: -.25rem; }

/* ---------- legal pages (privacy notice) ----------
   Hard register throughout: this is information, not an invitation. Hairline
   borders, --radius-hard, no elevation, no hover motion. */
.legal { max-width: 68ch; }
.legal h2 { font-size: clamp(1.5rem, 2.6vw, 2rem); margin-top: var(--space-8); margin-bottom: var(--space-3); }
.legal h2:first-of-type { margin-top: 0; }
.legal p, .legal li { color: var(--ink-soft); }
.legal p + p, .legal ul, .legal ul + p { margin-top: var(--space-4); }
.legal ul { padding-left: 1.25rem; display: grid; gap: var(--space-2); }
.legal a { color: var(--green); text-underline-offset: 3px; display: inline-block; padding-block: .25rem; margin-block: -.25rem; }
.legal-meta {
  font-family: var(--font-mono); font-size: var(--text-2xs); letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-soft); margin-bottom: var(--space-6);
}
.legal-facts {
  border: 1px solid var(--line); border-radius: var(--radius-hard); background: var(--card);
  padding: var(--space-5); margin-top: var(--space-5); display: grid; gap: var(--space-3);
  font-family: var(--font-mono); font-size: var(--text-2xs);
}
.legal-facts div { display: grid; grid-template-columns: minmax(9rem, 12rem) 1fr; gap: var(--space-3); }
.legal-facts dt { color: var(--green); letter-spacing: .1em; text-transform: uppercase; }
.legal-facts dd { color: var(--ink); }
@media (max-width: 640px) { .legal-facts div { grid-template-columns: 1fr; gap: var(--space-1); } }
/* same honest-placeholder convention as the product sheets, on a light surface */
.legal .pending { font-style: italic; color: var(--ink-soft); }

/* ---------- scroll reveal ---------- */
/* .45s, not .6s — this fires on nearly every section down the page, so it
   needs to read as "routine" rather than compete with the hero's one-time
   signature motion for the page's slowest timing. */
html.js .reveal { opacity: 0; transform: translateY(22px); transition: opacity .45s var(--ease-out), transform .45s var(--ease-out); }
html.js .reveal.in { opacity: 1; transform: none; }
