/* csr eco solutions — shared site styles
   Mobile-first. Every media query below is min-width, at 480 / 768 / 1024 / 1440 only. */

/* ---------- fonts ---------- */

@font-face {
  font-family: 'Lato';
  src: url('/fonts/lato-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lato';
  src: url('/fonts/lato-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lato';
  src: url('/fonts/lato-latin-900-normal.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: url('/fonts/lora-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Lora';
  src: url('/fonts/lora-latin-400-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* ---------- custom properties ---------- */

:root {
  /* neutrals — #333333, #2A2A2A, #1C1C1C and #383838 were four barely-different
     dark grays doing the same job. One ink color does all of it now: body text,
     the footer background, and dark card fills. */
  --color-ink: #333333;
  --color-white: #ffffff;
  --color-cream: #f7f6f1;
  --color-mist: #c9c7bf;
  --color-placeholder: #b9b7ac;

  /* muted subtext. #888780 failed AA outright at 3.61:1; #76756f passed on white
     at 4.62 but slipped to 4.27 on the cream panels and 4.08 on the accent tint,
     which is where most of it actually sits. This clears 4.5 on all three. */
  --color-muted: #6b6a64;

  /* brand green. #83c340 is for fills, backgrounds and large decorative accents
     only — it fails AA as text on white (2.13:1). Small green text/icons on a
     light background use --color-accent-text instead (5.33:1 on white,
     4.70:1 on the lightest tint it sits on). This also folds
     in the old #5a8a2a, which was doing the same job with a slightly different
     value. */
  --color-accent: #83c340;
  --color-accent-text: #4e7625;
  --color-accent-soft: #eaf5d6;
  --color-accent-tint-bg: rgba(131, 195, 64, 0.16);
  --color-accent-tint-border: rgba(131, 195, 64, 0.45);

  /* dark section gradients. Forest green is the primary hero/CTA background;
     navy is the alternate used on partner-programs and case-studies. */
  --color-forest-1: #1a2a0e;
  --color-forest-2: #2d4a18;
  --color-forest-3: #3a5e20;
  --gradient-forest: linear-gradient(160deg, var(--color-forest-1) 0%, var(--color-forest-2) 55%, var(--color-forest-3) 100%);

  --color-navy-1: #0e1e2e;
  --color-navy-2: #123047;
  --color-navy-3: #1a3a52;
  --gradient-navy: linear-gradient(160deg, var(--color-navy-1) 0%, var(--color-navy-2) 55%, var(--color-navy-3) 100%);

  /* type scale — collapsed from 54 distinct font-size declarations down to this. */
  --text-2xs: 0.6875rem;   /* 11px — footer legal, fine print */
  --text-xs: 0.78125rem;   /* 12.5px — form labels, small tags */
  --text-sm: 0.84375rem;   /* 13.5px — nav links, small UI text */
  --text-base: 0.9375rem;  /* 15px — body copy, buttons */
  --text-md: 1.0625rem;    /* 17px — card titles, lead-ish text */
  --text-lg: 1.1875rem;    /* 19px — Lora intro paragraphs */
  --text-xl: clamp(1.375rem, 2.8vw, 2rem);      /* 22-32px — h4 */
  --text-2xl: clamp(1.75rem, 3.6vw, 2.875rem);  /* 28-46px — h3 */
  --text-3xl: clamp(2rem, 4.4vw, 3.375rem);     /* 32-54px — h2 */
  --text-4xl: clamp(2.375rem, 5.6vw, 4.75rem);  /* 38-76px — h1 */

  --font-sans: 'Lato', sans-serif;
  --font-serif: 'Lora', serif;

  /* spacing */
  --gutter: clamp(20px, 4vw, 40px);
  --space-section-sm: clamp(56px, 8vh, 88px);
  --space-section-md: clamp(72px, 12vh, 130px);
  --space-section-lg: clamp(84px, 16vh, 160px);
  --content-width: 1440px;
  --measure: 68ch;

  /* radii */
  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 22px;
  --radius-pill: 100px;

  /* shadows — 14 box-shadows in the old site were minor variants of three. */
  --shadow-sm: 0 10px 24px rgba(0, 0, 0, 0.08);
  --shadow-md: 0 16px 40px rgba(0, 0, 0, 0.07);
  --shadow-lg: 0 30px 70px rgba(0, 0, 0, 0.22);

  /* transitions */
  --transition-fast: 0.2s ease;
  --transition-base: 0.4s ease;
  --transition-reveal: 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------- reset ---------- */

*, *::before, *::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd {
  margin: 0;
}

ul, ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

img, picture, svg {
  display: block;
  max-width: 100%;
}

input, button, textarea, select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
}

/* ---------- base typography ---------- */

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--color-ink);
  background: var(--color-white);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-weight: 900;
  line-height: 1.1;
}

h1 {
  font-size: var(--text-4xl);
  line-height: 1.05;
  letter-spacing: -0.04em;
  text-wrap: balance;
}

h2 {
  font-size: var(--text-3xl);
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

h3 {
  font-size: var(--text-md);
  letter-spacing: -0.01em;
}

h4 {
  font-size: var(--text-base);
}

a {
  text-decoration: none;
  color: var(--color-accent-text);
}

a:hover {
  color: var(--color-accent);
}

::selection {
  background: rgba(131, 195, 64, 0.3);
}

input::placeholder,
textarea::placeholder {
  color: var(--color-placeholder);
}

/* ---------- skip link ---------- */

.skip-link {
  position: absolute;
  top: -100%;
  left: 12px;
  z-index: 1000;
  background: var(--color-white);
  color: var(--color-ink);
  font-weight: 700;
  font-size: var(--text-base);
  padding: 12px 20px;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}

.skip-link:focus {
  top: 12px;
}

/* ---------- focus ---------- */

:focus {
  outline: none;
}

:focus-visible {
  outline: 2px solid var(--color-accent-text);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.6);
  border-radius: 2px;
}

/* ---------- site nav ---------- */

.site-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 66px;
  padding: 0 var(--gutter);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-bottom: 1px solid rgba(51, 51, 51, 0.09);
  transition: background var(--transition-base), border-color var(--transition-base);
}

.site-logo {
  display: flex;
  align-items: center;
}

.site-logo-img {
  height: 30px;
  width: auto;
  display: block;
}

.nav-links {
  display: none;
  align-items: center;
  gap: clamp(16px, 2.2vw, 32px);
}

.nav-link {
  font-size: var(--text-sm);
  font-weight: 700;
  color: rgba(51, 51, 51, 0.72);
  transition: color var(--transition-base);
}

.nav-link[aria-current='page'] {
  color: var(--color-accent-text);
}

.nav-cta {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-ink);
  background: var(--color-accent);
  padding: 10px 22px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

/* Same specificity trap as the buttons above — see that comment. */
.nav-cta:hover,
.nav-cta:focus-visible,
.nav-menu-cta:hover,
.nav-menu-cta:focus-visible {
  background: var(--color-accent-text);
  color: var(--color-white);
}

.nav-burger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 10px;
  cursor: pointer;
  color: var(--color-ink);
}

.nav-burger-bar {
  display: block;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
}

.nav-menu {
  display: none;
  position: fixed;
  inset: 66px 0 0 0;
  z-index: 99;
  background: rgba(255, 255, 255, 0.97);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  flex-direction: column;
  gap: 4px;
  padding: 24px var(--gutter);
  overflow-y: auto;
}

.nav-menu.is-open {
  display: flex;
}

.nav-menu-link {
  font-size: 20px;
  font-weight: 700;
  color: var(--color-ink);
  padding: 14px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.07);
}

.nav-menu-cta {
  margin-top: 18px;
  text-align: center;
  font-size: 16px;
  font-weight: 900;
  color: var(--color-ink);
  background: var(--color-accent);
  padding: 16px 22px;
  border-radius: var(--radius-pill);
}

/* Pages whose hero sits on a dark background start the nav transparent with a
   white logo/links, then solidify once JS marks it scrolled past the hero. */
body.nav-on-dark .site-nav {
  background: rgba(255, 255, 255, 0);
  backdrop-filter: blur(0);
  -webkit-backdrop-filter: blur(0);
  border-bottom-color: rgba(255, 255, 255, 0);
}

body.nav-on-dark .site-nav .site-logo-img {
  filter: brightness(0) invert(1);
}

/* The burger inherits --color-ink, which is invisible against the dark heroes.
   The logo was already being inverted here; the bars were missed. */
body.nav-on-dark .site-nav .nav-burger {
  color: var(--color-white);
}

body.nav-on-dark .site-nav .nav-link {
  color: rgba(255, 255, 255, 0.82);
}

body.nav-on-dark .site-nav .nav-link[aria-current='page'] {
  color: var(--color-accent);
}

body.nav-on-dark .site-nav.is-scrolled {
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-bottom-color: rgba(51, 51, 51, 0.09);
}

body.nav-on-dark .site-nav.is-scrolled .site-logo-img {
  filter: none;
}

body.nav-on-dark .site-nav.is-scrolled .nav-burger {
  color: var(--color-ink);
}

body.nav-on-dark .site-nav.is-scrolled .nav-link {
  color: rgba(51, 51, 51, 0.72);
}

body.nav-on-dark .site-nav.is-scrolled .nav-link[aria-current='page'] {
  color: var(--color-accent-text);
}

@media (min-width: 1024px) {
  .nav-links {
    display: flex;
  }

  .nav-burger {
    display: none;
  }

  /* Beats a stale .is-open class left over from a narrower viewport — there is
     no resize listener closing the menu, so CSS has to win outright here. */
  .nav-menu {
    display: none !important;
  }
}

/* ---------- footer ---------- */

.site-footer {
  background: var(--color-ink);
  padding: 74px var(--gutter) 44px;
}

/* Four blocks, one of which wants to be wider than the rest, so the columns are
   set explicitly. auto-fit was fitting whatever would go and stranding a link
   column on a row of its own at 1024, and splitting 1+2+1 below 480. */
.footer-grid {
  max-width: 1180px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
}

.footer-about {
  min-width: 240px;
}

@media (min-width: 768px) {
  /* The three link columns line up as a row; the about block takes its own. */
  .footer-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .footer-about {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1024px) {
  /* Wide enough for everything on one row, with the about block given the
     extra width its paragraph needs. */
  .footer-grid {
    grid-template-columns: 2fr 1fr 1fr 1fr;
  }

  .footer-about {
    grid-column: auto;
  }
}

.footer-logo {
  height: 28px;
  width: auto;
  display: block;
  margin-bottom: 14px;
}

.footer-about p {
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.5);
  line-height: 1.75;
  max-width: 320px;
}

.footer-contact {
  margin-top: 20px;
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.5);
  line-height: 1.9;
}

.footer-heading {
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 2px;
  color: rgba(255, 255, 255, 0.35);
  margin-bottom: 16px;
}

/* The padding is what gets these over the 24px minimum target size in WCAG 2.5.8
   — as bare text links they were 20px tall. It replaces the old bottom margin
   rather than adding to it, so the spacing between links looks the same. */
.footer-links a {
  display: block;
  padding: 6px 0;
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.55);
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
}

.footer-legal a {
  display: inline-block;
  padding: 6px 0;
  color: rgba(255, 255, 255, 0.55);
}

.footer-legal a:hover,
.footer-legal a:focus-visible {
  color: var(--color-accent);
}

.footer-bottom {
  max-width: 1180px;
  margin: 40px auto 0;
  padding-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.3);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

/* ---------- buttons ---------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: var(--radius-pill);
  font-weight: 900;
  font-size: var(--text-base);
  padding: 16px 38px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.button-primary {
  background: var(--color-accent);
  color: var(--color-forest-1);
  border: none;
}

.button-outline {
  background: transparent;
  color: var(--color-white);
  border: 2px solid rgba(255, 255, 255, 0.42);
}

/* Explicit hover states, and they have to be explicit. The generic `a:hover` near
   the top of this file is specificity (0,1,1), which outranks a single class like
   `.button-primary` at (0,1,0) — so without these a primary button's label turns
   accent-green on an accent-green background and vanishes under the cursor.
   White on the darker green measures 4.66:1, so the hover passes AA too. */

.button-primary:hover,
.button-primary:focus-visible {
  background: var(--color-accent-text);
  color: var(--color-white);
}

.button-outline:hover,
.button-outline:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--color-white);
  color: var(--color-white);
}

.button-sm {
  padding: 10px 22px;
  font-size: var(--text-sm);
}

.button-lg {
  padding: 17px 44px;
  font-size: 1rem;
}

/* ---------- eyebrow ---------- */

.eyebrow {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--color-accent-text);
}

.eyebrow-on-dark {
  color: rgba(255, 255, 255, 0.5);
}

.eyebrow-pill {
  display: inline-block;
  background: var(--color-accent-tint-bg);
  border: 1px solid var(--color-accent-tint-border);
  color: var(--color-accent);
  padding: 7px 18px;
  border-radius: var(--radius-pill);
  margin-bottom: 28px;
}

/* ---------- card ---------- */

.card,
.card-elevated,
.card-dark {
  border-radius: var(--radius-lg);
  padding: 30px 28px;
}

.card {
  background: var(--color-cream);
  border: 1px solid rgba(51, 51, 51, 0.07);
}

.card-elevated {
  background: var(--color-white);
  box-shadow: var(--shadow-sm);
}

.card-dark {
  background: var(--color-ink);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--color-white);
}

/* ---------- stat pill ---------- */

.stat-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--color-accent-tint-border);
  color: var(--color-accent-text);
  border-radius: var(--radius-pill);
  padding: 8px 16px;
  font-size: var(--text-xs);
  font-weight: 700;
}

.stat-pill-on-dark {
  color: var(--color-accent);
}

/* ---------- FAQ accordion ---------- */

/* The heading above a FAQ list had nothing between it and the first question. */
.faq-list {
  margin-top: 34px;
}

.faq-item {
  background: var(--color-white);
  border: 1px solid rgba(51, 51, 51, 0.08);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.faq-item + .faq-item {
  margin-top: 12px;
}

.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  text-align: left;
  cursor: pointer;
  padding: 24px 26px;
  font-family: var(--font-sans);
}

.faq-question-text {
  font-size: var(--text-md);
  font-weight: 900;
  color: var(--color-ink);
  letter-spacing: -0.01em;
}

.faq-icon {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-accent-tint-bg);
  color: var(--color-accent-text);
  font-size: 16px;
  font-weight: 900;
  display: flex;
  align-items: center;
  justify-content: center;
}

.faq-icon::before {
  content: '+';
}

.faq-item.is-open .faq-icon::before {
  content: '\2013';
}

/* No JS: the answer is fully visible, which is the correct baseline for
   accessibility and for search/AI crawlers reading the page. JS marks the
   list ready and collapses answers via the grid-rows trick below. */
.faq-answer {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.3s ease;
}

/* The paragraph is the grid item, so collapsing the row to 0fr clips its text
   but not its padding — 26px of it stayed behind and pushed the question's
   underline down onto nothing. The padding has to collapse with the row. */
.faq-answer p {
  overflow: hidden;
  min-height: 0;
  padding: 0 26px 26px;
  transition: padding-bottom 0.3s ease;
  font-family: var(--font-serif);
  font-size: var(--text-base);
  line-height: 1.75;
  color: var(--color-muted);
}

.faq-list.js-ready .faq-answer {
  grid-template-rows: 0fr;
}

.faq-list.js-ready .faq-answer p {
  padding-bottom: 0;
}

.faq-list.js-ready .faq-item.is-open .faq-answer {
  grid-template-rows: 1fr;
}

.faq-list.js-ready .faq-item.is-open .faq-answer p {
  padding-bottom: 26px;
}

/* ---------- content container ---------- */

.container {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.measure {
  max-width: var(--measure);
}

/* ---------- scroll reveals ---------- */

/* No .is-pending class until site.js confirms it's running, so content stays
   fully visible if JS fails to load. */
[data-reveal] {
  transition: opacity var(--transition-reveal), transform var(--transition-reveal);
}

[data-reveal].is-pending {
  opacity: 0;
  transform: translateY(24px);
}

[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* ---------- parallax ---------- */

[data-parallax] {
  transform: translate3d(0, var(--parallax-y, 0), 0);
}

/* ---------- image pending ---------- */

/* Sizing is left to whatever aspect-ratio the page sets inline per instance
   (height: auto lets that ratio drive the box). A full-bleed background use
   sets its own position/inset/height inline, which wins over this default. */
/* Stand-in panel for photography that hasn't landed yet. Deliberately plain —
   a brand gradient with a faint diagonal weave, no caption — so a missing image
   reads as an intentional block rather than a broken one. Swap the whole div for
   an <img> when the real photo arrives. */
.image-pending {
  position: relative;
  width: 100%;
  height: auto;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--gradient-forest);
}

.image-pending::before {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.05) 0,
    rgba(255, 255, 255, 0.05) 2px,
    transparent 2px,
    transparent 14px
  );
}

/* Heroes drop the weave. At full-bleed size behind a headline the texture
   reads as noise rather than as a deliberate stand-in, which is the opposite
   of what it's for on a small inline panel. Kept as one rule here instead of
   four page-level overrides so a new page's hero inherits the same treatment
   by adding its selector to this list. */
.hero-media.image-pending::before,
.pp-hero-media .image-pending::before,
.decom-hero-media .image-pending::before,
.about-hero-media .image-pending::before {
  content: none;
}


/* ---------- the ITF tree-and-soil scene ----------
   Shared by the home page carbon-legacy panel and the About page ITF section,
   so it lives here rather than being duplicated in two page stylesheets. */

.itf-tree-scene {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: linear-gradient(#dcefbe, #cfe7ad);
}

/* The tree sits low on purpose: 10% from the top at 74% height puts its base well
   past the soil's top edge (which starts at 51%), so the trunk emerges from the
   mound rather than resting on it. The root mass is the bottom ~38% of the PNG and
   ends up entirely below the soil line. Both images have transparent backgrounds,
   which is what lets them read as one scene against the panel gradient. */

.itf-tree {
  position: absolute;
  left: 14%;
  right: 14%;
  top: 10%;
  height: 74%;
  width: auto;
  margin: 0 auto;
  object-fit: contain;
  object-position: bottom center;
}

/* bottom/height are paired: the mound hangs 12% below the panel and is 64%
   tall, which leaves its visible top edge at the same 48% line it always sat
   on while burying far more of it underneath. That buried strip is what the
   parallax eats into. */
.itf-soil {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -12%;
  height: 64%;
  width: 100%;
  object-fit: cover;
  object-position: top center;
}

/* At full drift the soil used to lift clear of the panel and expose the green
   container behind it. Clamping the travel to 40px fixes that for good: the
   panel is never shorter than 400px, so the 12% overhang above is at least
   48px, and 40px of movement stays inside it at every viewport size. Raising
   this number, or reducing the overhang, reopens the gap.
   Selector names the element so it beats the generic [data-parallax] rule
   rather than relying on source order. */
img.itf-soil[data-parallax] {
  transform: translate3d(0, clamp(-40px, var(--parallax-y, 0px), 40px), 0);
}


/* ---------- small print under a headline number ---------- */

/* The qualifier that keeps a published figure accurate without competing with
   the number for attention. It lives here rather than in a page stylesheet
   because the 94% diversion rate carries it on five pages now. Every one of
   those stats sits on a dark hero, so white at 60% — 5.63:1 on the ink panel
   and higher on the darker heroes. The asterisk is drawn in CSS so it always
   matches the marker on the label above and can't drift out of sync with it. */
.legal-footnote {
  margin-top: 8px;
  font-size: 10.5px;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0.2px;
  text-transform: none;
  color: rgba(255, 255, 255, 0.6);
}

.legal-footnote::before {
  content: '*';
  margin-right: 3px;
}

/* Same small print on the light panels. --color-muted measures 4.79:1 on the
   accent tint these sections use, so it clears AA there too. */
.legal-footnote-on-light {
  max-width: 62ch;
  color: var(--color-muted);
}


/* ---------- accessibility helpers ---------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Honeypot field: unlike .visually-hidden this also hides from screen readers
   (aria-hidden on the wrapper) and drops out of tab order (tabindex="-1" on
   the input) — a real visitor should never know it exists. */
.form-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}


/* ---------- shared form fields ----------
   These lived in contact.css and charities.css as two byte-identical copies,
   with a note in charities.css saying they belonged in base. The ESG demo form
   would have made three, so they're here now. The only difference between the
   two copies was the textarea min-height (100 vs 120); 100 is the base and
   contact.css keeps a one-line override. */

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.form-field label {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--color-ink);
}

.form-field input,
.form-field select,
.form-field textarea {
  height: 48px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(51, 51, 51, 0.16);
  padding: 0 16px;
  font-size: var(--text-base);
  color: var(--color-ink);
  background: var(--color-white);
}

.form-field textarea {
  height: auto;
  min-height: 100px;
  padding: 14px 16px;
  resize: vertical;
}

/* Marks a field as not required. Regular weight against the bold label so it
   reads as an aside rather than part of the field name. */
.form-optional {
  font-weight: 400;
  color: var(--color-muted);
}

/* Shown when quote.php sends someone back with ?form_error=. Amber rather than
   red: two of the three cases are our fault, not the visitor's, and a red
   alarm on "we couldn't send that, try again" overstates it. Text measures
   7.48:1 against the tint, the border 5.14:1. */
.form-error {
  margin-bottom: 20px;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(140, 96, 12, 0.28);
  background: #fdf6e6;
  color: #6b4a08;
  font-size: var(--text-base);
  line-height: 1.55;
}

/* ---------- hidden ---------- */

.is-hidden {
  display: none;
}

/* ---------- print ---------- */

@media print {
  .site-nav,
  .nav-menu,
  .site-footer,
  .skip-link {
    display: none;
  }

  body {
    color: #000;
    background: #fff;
  }

  a {
    color: #000;
  }

  .faq-answer {
    grid-template-rows: 1fr !important;
  }

  .image-pending {
    background: #eee;
    color: #000;
  }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  [data-parallax] {
    transform: none !important;
  }
}
