/* ==========================================================================
   Cetu, cetucoffee.com
   Register: SICC editorial quiet leads, Nordic confidence, Belco warmth.
   Structural device: the bracketed label [ LIKE THIS ], always left-aligned.
   ========================================================================== */

/* ---------- 1. Tokens ---------- */
:root {
  /* anchor: deep forest green from the Cetu logo */
  --green:      #0B5B4B;
  --green-deep: #073C32;
  --green-mid:  #0E6B58;

  /* warm paper off-white, and the brand cream used on dark ground */
  --paper:     #F7F3E8;
  --paper-alt: #FCFAF4;
  --cream:     #F3EFDD;

  /* near-black ink */
  --ink:   #191C18;
  --muted: #5C665E;

  /* ONE restrained accent, warmed toward dried cherry.
     The brand-guide red #D20B26 sits at hue 351.9deg, on the crimson side of
     red, which is why it read pink against forest green and cream. This is the
     same red pushed to hue 8.6deg: unmistakably the brand colour, but warm.
     Contrast on paper 5.37:1. The brand guide itself is unchanged; this is the
     web accent only. */
  --accent: #B23A26;

  /* Any red dark enough to read on paper is unreadable on green, so dark ground
     uses a light warm tint. Warmed from the old #F5B3A0 (hue 13.4deg, salmon
     pink) to hue 21.2deg apricot. Contrast on green 4.98:1. */
  --accent-dark: #F7C0A2;

  --line:       rgba(25, 28, 24, .14);
  --line-light: rgba(243, 239, 221, .20);

  /* type: characterful serif display, neutral sans body, mono for labels */
  --font-display: 'EB Garamond', Garamond, 'Times New Roman', serif;
  --font-body:    'Aptos', 'Inter', system-ui, -apple-system, sans-serif;
  --font-label:   'IBM Plex Mono', ui-monospace, 'SF Mono', monospace;

  /* statement headers are the page's spine: large, serif, one weighted word */
  --fs-statement: clamp(2.1rem, 5.4vw, 4rem);
  --fs-h1:        clamp(2.2rem, 5.6vw, 4.25rem);
  --fs-h2:        clamp(1.6rem, 3vw, 2.35rem);
  --fs-h3:        clamp(1.1rem, 1.6vw, 1.3rem);
  --fs-lede:      clamp(1.0625rem, 1.4vw, 1.2rem);
  --fs-body:      1.0625rem;
  --fs-small:     .9375rem;
  --fs-label:     .75rem;

  --s-1: .5rem;  --s-2: 1rem;   --s-3: 1.5rem; --s-4: 2rem;
  --s-5: 3rem;   --s-6: 4.5rem; --s-7: 7rem;   --s-8: 9.5rem;

  --wrap: 1180px;
  /* One reading measure for every paragraph on the site, 62 to 68 characters.
     Note this is NOT 65ch. The ch unit is the width of a zero, which in Aptos
     is 0.63em, while the average character in running prose is about 0.46em.
     A 65ch column therefore holds about 89 real characters, well past the
     comfortable band. Measured against three sample sentences, 49ch renders
     63 to 67 characters per line, which is the value wanted. */
  --measure: 49ch;
  --radius: 2px;

  --ease: cubic-bezier(.16, 1, .3, 1);
  --dur:  .6s;
}

/* ---------- 2. Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg { max-width: 100%; display: block; }
h1, h2, h3, h4 { margin: 0; line-height: 1.08; font-weight: 400; }
p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; list-style: none; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ---------- 3. Utilities ---------- */
.wrap {
  width: 100%; max-width: var(--wrap);
  margin-inline: auto; padding-inline: var(--s-3);
}
@media (min-width: 768px)  { .wrap { padding-inline: var(--s-5); } }
@media (min-width: 1240px) { .wrap { padding-inline: var(--s-4); } }

/* the narrow centred column the whole site reads in */
.measure { max-width: var(--measure); }
.measure-wide { max-width: 46rem; }

.mono {
  font-family: var(--font-label); font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
}
.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;
}
.skip-link {
  position: absolute; left: var(--s-2); top: -100px; z-index: 200;
  background: var(--accent); color: var(--paper);
  padding: var(--s-1) var(--s-3); border-radius: var(--radius);
  text-decoration: none; font-weight: 500;
  transition: top .2s var(--ease);
}
.skip-link:focus { top: var(--s-2); }

/* content still to be supplied */
.ph {
  border-bottom: 1px dotted var(--accent);
  background: rgba(178, 58, 38, .06);
  padding: 0 .18em; font-style: italic;
}
.on-dark .ph { border-bottom-color: var(--accent-dark); background: rgba(247,192,162,.14); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
.on-dark :focus-visible { outline-color: var(--accent-dark); }

/* paper grain */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 100;
  pointer-events: none; opacity: .03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* One measure, applied to every paragraph on every page. max-width only caps,
   never stretches, so a paragraph already inside a narrow grid column is
   untouched; this only stops the wide ones filling their container. Several
   components were reaching 82 characters once they collapsed to one column at
   768px. */
/* The measure applies to body paragraphs. It does NOT apply to the hero stacked
   statement, headings, lead-in lines, weighted words, button labels, navigation
   or footer links, short pull lines, or the role lines on About Us. Capping the
   stacked statement turned four clean lines into seven ragged ones. */
main p { max-width: var(--measure); }
main .hero-title,
main .statement,
main .hero-stack li,
main .pull,
main .btn,
main .label,
main .profile-role { max-width: none; }

/* ---------- 4. The bracketed label: the site's recurring device ---------- */
.label {
  display: block;
  font-family: var(--font-label);
  font-size: var(--fs-label);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--s-3);
  text-align: left;              /* always left-aligned, per the brief */
}
.on-dark .label { color: var(--accent-dark); }

/* ---------- 5. Statement headers (one weighted word) ----------
   Modelled on the This Side Up treatment: the lead words sit small and light,
   and the single weighted word drops onto its own line, large and heavy.
   Home centres these; inner pages use the left-aligned bracketed label instead. */
.statement {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 1.95rem);
  font-weight: 400;
  /* 1.15 was tighter than EB Garamond's ascent at this size: the glyph box
     measured 41px inside a 35.88px line box, so ascenders spilled above the
     element and clipped against the section edge. */
  line-height: 1.3;
  padding-top: .2em;
  letter-spacing: -.01em;
  color: var(--green);
  margin-bottom: var(--s-4);
  text-wrap: balance;
}
/* The key phrase carries emphasis through scale alone, not weight.
   Regular weight at this size reads calmer and suits the editorial register. */
/* Trailing punctuation belongs INSIDE this span in the markup, e.g.
   <span class="w">bridge?</span>. Because .w is a block, anything left outside
   it drops onto its own line. */
.statement .w {
  display: block;
  font-size: 1.62em;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: -.015em;
  line-height: 1.08;
  margin-top: .06em;
}
.on-dark .statement { color: var(--cream); }

/* centred variant used across the home page */
/* Wide enough for the longest weighted phrase to hold one line at desktop.
   22ch was tuned for short words like BOTH BANKS and forced MANY POSSIBILITIES
   onto two lines. The lead-in is short either way, so it stays centred and tight. */
/* Home was centred throughout and India left-aligned, which is why the two
   pages read so differently. Centred body copy has a ragged left edge as well
   as a ragged right one, so the eye has to hunt for the start of every line.
   Both pages are now flush left against the grid. The two pull lines are the
   exception: a single short statement is the one case where centring works. */
/* heading to its first paragraph */
.statement { margin-bottom: 24px; }
@media (min-width: 768px) { .statement { margin-bottom: 32px; } }
.statement-centred { text-align: left; max-width: none; margin-inline: 0; }
.home-copy { max-width: var(--measure); margin-inline: 0; text-align: left; }
.home-copy p + p { margin-top: 20px; }
@media (min-width: 768px) { .home-copy p + p { margin-top: 24px; } }
.home-copy p { color: var(--muted); }
.on-dark .home-copy p { color: rgba(243, 239, 221, .84); }
.home-actions { justify-content: flex-start; margin-top: var(--s-4); }
.pull-centred { margin-inline: auto; text-align: center; max-width: 26ch; border-top: 0; }

.pull {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.4vw, 1.9rem);
  line-height: 1.3;
  color: var(--accent);
  border-top: 1px solid var(--line);
  padding-top: var(--s-3);
  margin-top: var(--s-5);
  max-width: 30ch;
}
.on-dark .pull { color: var(--accent-dark); border-top-color: var(--line-light); }

/* ---------- 6. Buttons and quiet next steps ---------- */
.btn {
  --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--line);
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 50px; padding: 0 var(--s-4);
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--btn-bd); border-radius: var(--radius);
  font-size: var(--fs-small); font-weight: 500; letter-spacing: .01em;
  text-decoration: none; cursor: pointer;
  transition: background .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.btn-primary { --btn-bg: var(--green); --btn-fg: var(--paper); --btn-bd: var(--green); }
.btn-primary:hover { --btn-bg: var(--green-deep); --btn-bd: var(--green-deep); }
.btn-quiet:hover { --btn-bd: var(--green); --btn-bg: rgba(11,91,75,.05); }
.on-dark .btn-quiet { --btn-fg: var(--cream); --btn-bd: var(--line-light); }
.on-dark .btn-quiet:hover { --btn-bg: rgba(243,239,221,.1); --btn-bd: var(--cream); }
.on-dark .btn-primary { --btn-bg: var(--cream); --btn-fg: var(--green-deep); --btn-bd: var(--cream); }

.next {
  display: inline-flex; align-items: center; gap: .6em;
  min-height: 44px;
  color: var(--accent); font-weight: 500; font-size: var(--fs-small);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), gap .3s var(--ease);
}
.next:hover { border-bottom-color: var(--accent); gap: .95em; }
.on-dark .next { color: var(--accent-dark); }
.on-dark .next:hover { border-bottom-color: var(--accent-dark); }

.actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* ---------- 7. Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 90;
  background: rgba(247, 243, 232, .9);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease);
}
.site-header.is-stuck { border-bottom-color: var(--line); }
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); min-height: 72px;
}
.brand {
  display: inline-flex; align-items: center; gap: .6rem;
  min-height: 44px; color: var(--green); text-decoration: none;
}
/* The real CETU wordmark, lifted from the brand guide. The logo IS the name, so
   the name is never set as live text beside it. */
.brand-logo { height: 26px; width: auto; flex: none; }
@media (min-width: 768px) { .brand-logo { height: 30px; } }
.nav-menu { display: flex; align-items: center; gap: var(--s-3); }
.nav-menu a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--fs-small); text-decoration: none; color: var(--ink);
  border-bottom: 1px solid transparent;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.nav-menu a:hover { color: var(--accent); border-bottom-color: var(--accent); }
.nav-menu a[aria-current="page"] { border-bottom-color: var(--green); }
/* The action lives in the bar at every width now, not inside the menu, so its
   button styling hangs off the class rather than off where it sits. */
.nav-cta {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 var(--s-3); min-height: 44px;
  background: var(--green); color: var(--paper);
  border: 1px solid var(--green); border-radius: var(--radius);
  text-decoration: none;
}
.nav-cta:hover { background: var(--green-deep); border-color: var(--green-deep); color: var(--paper); }
.nav-menu a.nav-cta { border-bottom: 1px solid var(--green); }

.nav-toggle {
  display: none; align-items: center; gap: .55rem;
  min-height: 44px; padding: 0 var(--s-1);
  background: none; border: 0; cursor: pointer;
  font-family: var(--font-label); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
}
.nav-toggle-bars { display: grid; gap: 4px; width: 20px; }
.nav-toggle-bars span { height: 1.5px; background: var(--ink); transition: transform .3s var(--ease); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:first-child { transform: translateY(2.75px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:last-child  { transform: translateY(-2.75px) rotate(-45deg); }

@media (max-width: 1099px) {
  /* The bar carries three things and no more: the wordmark, the one action
     worth never burying, and the way into everything else. */
  /* backdrop-filter on the header makes it a containing block for anything
     fixed inside it, which pinned the overlay to the 64px bar instead of the
     viewport. The bar is already 90 percent opaque, so the blur costs little. */
  .site-header { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--paper); }
  .header-inner { min-height: 64px; gap: var(--s-2); }
  .brand-logo { width: 108px; height: auto; }
  .nav-toggle { display: inline-flex; order: 3; position: relative; z-index: 210; }
  .site-nav { display: flex; align-items: center; gap: var(--s-2); }

  .nav-cta {
    order: 2;
    min-height: 44px; padding: 0 .85rem;
    font-size: .875rem; white-space: nowrap;
  }
  /* 375 is tight: the label goes and the bars carry it, with the accessible
     name still on the button for anyone not reading it visually */
  .nav-toggle-label { position: absolute; width: 1px; height: 1px; overflow: hidden;
                      clip-path: inset(50%); white-space: nowrap; }
  @media (min-width: 420px) {
    .nav-toggle-label { position: static; width: auto; height: auto; clip-path: none; }
  }

  /* full-screen overlay, not a dropdown */
  .nav-menu {
    position: fixed; inset: 0; z-index: 200;
    display: grid; align-content: center; justify-items: start;
    gap: 0;
    padding: calc(64px + var(--s-5)) var(--s-3) var(--s-5);
    margin: 0;
    background: var(--green);
    overflow-y: auto; overscroll-behavior: contain;
    opacity: 0; visibility: hidden;
    transition: opacity .25s var(--ease), visibility 0s linear .25s;
  }
  .nav-menu.is-open { opacity: 1; visibility: visible; transition-delay: 0s; }
  .nav-menu li { width: 100%; border-bottom: 1px solid rgba(243, 239, 221, .16); }
  .nav-menu li:last-child { border-bottom: 0; }
  .nav-menu a {
    display: flex; align-items: center;
    min-height: 56px; width: 100%;
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 7vw, 2rem);
    letter-spacing: -.01em;
    color: var(--cream); border-bottom: 0;
  }
  .nav-menu a:hover, .nav-menu a[aria-current="page"] { color: var(--accent-dark); border-bottom: 0; }

  /* the toggle doubles as the close control once the overlay is up */
  .nav-menu.is-open ~ .nav-toggle,
  .site-nav:has(.nav-menu.is-open) .nav-toggle { color: var(--cream); }
  .site-nav:has(.nav-menu.is-open) .nav-cta { opacity: 0; pointer-events: none; }

  /* scroll lock, set by the script so the page cannot move behind the overlay */
  body.nav-open { overflow: hidden; }

  /* the bar gives back vertical space on the way down a long page and returns
     the moment the reader scrolls up */
  .site-header { transition: transform .25s var(--ease), border-color .3s var(--ease); }
  .site-header.is-hidden { transform: translateY(-100%); }
}
@media (prefers-reduced-motion: reduce) {
  .site-header, .nav-menu { transition: none; }
  .site-header.is-hidden { transform: none; }
}

/* ---------- 8. Section rhythm ---------- */
/* One vertical rhythm across both pages. Text-only sections breathe more than
   sections carrying an image, because there the space is doing the work. */
main > section { padding-block: 88px; scroll-margin-top: 90px; }
@media (min-width: 768px) { main > section { padding-block: 160px; } }
/* a section carrying an image needs less, the image already fills the eye */
main > section:has(img), main > section:has(.pair), main > section:has(.map-figure) {
  padding-block: 64px;
}
@media (min-width: 768px) {
  main > section:has(img), main > section:has(.pair), main > section:has(.map-figure) {
    padding-block: 120px;
  }
}

.on-dark { background: var(--green); color: var(--cream); }
.on-dark p { color: rgba(243, 239, 221, .84); }
.on-paper-alt { background: var(--paper-alt); }

.body-copy { max-width: var(--measure); }
.body-copy p + p { margin-top: 20px; }
@media (min-width: 768px) { .body-copy p + p { margin-top: 24px; } }
.body-copy p { color: var(--muted); }
.on-dark .body-copy p { color: rgba(243, 239, 221, .84); }

/* ---------- 9. Home hero (typographic, stacked statement) ---------- */
.hero { background: var(--green); color: var(--cream); padding-block: var(--s-7) var(--s-6) !important; }
@media (min-width: 768px) { .hero { padding-block: var(--s-8) var(--s-7) !important; } }

.hero-overline { color: var(--accent-dark); margin-bottom: var(--s-4); }

/* CETU / सेतु lockup: the Devanagari is the brand's visual signature */
.hero-lockup {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-4);
  margin-bottom: var(--s-5);
}
/* The hero uses the actual logo artwork, so the headline CETU is set in the
   brand's own display face rather than an approximation. */
.hero-wordmark {
  height: clamp(3rem, 8.5vw, 6.5rem);
  width: auto; flex: none;
}
.hero-deva {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 8vw, 6rem);
  line-height: 1.25;               /* Devanagari needs headroom for matras */
  /* Brand red, matching the accent used across the page. Note this measures
     1.48:1 against the flat green: it works as part of the CETU / सेतु brand
     lockup, which WCAG exempts as a logotype, but it is deliberately low
     contrast. See the note in the README if you want it lifted. */
  color: var(--accent);
}
.hero-title {
  font-family: var(--font-display);
  font-size: var(--fs-h1);
  line-height: 1.06; letter-spacing: -.02em;
  color: var(--cream);
  max-width: 18ch; margin-bottom: var(--s-5);
  text-wrap: balance;
}
/* the stacked statement: one line per idea, generous leading */
.hero-stack { display: grid; gap: .55rem; max-width: 42rem; margin-bottom: var(--s-5); }
.hero-stack li {
  font-size: var(--fs-lede);
  color: rgba(243, 239, 221, .88);
  line-height: 1.5;
}
.hero-stack li:first-child { color: var(--cream); }

/* ---------- 10. Commitments: 3-then-2 grid, never a bulleted list ---------- */
.commitments {
  display: grid; gap: var(--s-4);
  grid-template-columns: 1fr;
  margin-top: var(--s-5);
}
@media (min-width: 768px) {
  /* Four in two columns, then the fifth centred beneath rather than left in
     the bottom-left with an empty cell beside it. Desktop already runs three
     across and two centred, which is the same idea at a wider size. */
  .commitments { grid-template-columns: repeat(2, 1fr); gap: var(--s-5) var(--s-4); }
}
/* Bounded at the top: from 1000px the rule below runs three across and two
   centred, and an unbounded max-width here was squeezing the fifth item to
   half its column on desktop. */
@media (min-width: 700px) and (max-width: 999px) {
  .commitments > li:nth-child(5) {
    grid-column: 1 / -1;
    max-width: calc(50% - var(--s-2));
    justify-self: center;
  }
}
@media (min-width: 1000px) {
  .commitments { grid-template-columns: repeat(6, 1fr); }
  /* three across the top */
  .commitments > li:nth-child(1) { grid-column: 1 / span 2; }
  .commitments > li:nth-child(2) { grid-column: 3 / span 2; }
  .commitments > li:nth-child(3) { grid-column: 5 / span 2; }
  /* two centred below */
  .commitments > li:nth-child(4) { grid-column: 2 / span 2; }
  .commitments > li:nth-child(5) { grid-column: 4 / span 2; }
}
.commit { display: grid; gap: .7rem; align-content: start; }
.commit-icon { width: 40px; height: 40px; color: var(--green); }
/* On the green section the icons sit in the warm accent: green on green is
   invisible, and cream would compete with the labels. */
.on-dark .commit-icon { color: var(--accent-dark); }
.commit-label {
  font-family: var(--font-body); font-weight: 600;
  font-size: 1.0625rem; color: var(--ink); line-height: 1.3;
}
.on-dark .commit-label { color: var(--cream); }
.commit p { font-size: var(--fs-small); color: var(--muted); }
/* On the green section the muted grey measured 1.35:1 and was unreadable.
   Match the commit label instead: cream at 88% gives 5.78:1. */
.on-dark .commit p { color: rgba(243, 239, 221, .88); }

/* ---------- 11. Two banks / audience split ---------- */
.banks { display: grid; gap: var(--s-5); grid-template-columns: 1fr; margin-top: var(--s-5); }
@media (min-width: 860px) { .banks { grid-template-columns: 1fr 1fr; gap: var(--s-6); } }
.bank { display: grid; gap: var(--s-2); align-content: start; padding-top: var(--s-3); border-top: 2px solid var(--green); }
.bank:nth-child(2) { border-top-color: var(--accent); }
/* When a photograph tops the block, the colour-coded rule moves below it so the
   order reads photograph, rule, heading rather than rule, photograph, heading. */
.bank:has(.bank-photo) { padding-top: 0; border-top: 0; gap: var(--s-3); }
.bank:has(.bank-photo) h3 {
  padding-top: var(--s-3);
  border-top: 2px solid var(--green);
}
.bank:has(.bank-photo):nth-child(2) h3 { border-top-color: var(--accent); }
/* The two photographs are one pair: identical box, identical crop, aligned tops. */
.bank-photo { display: block; }
.bank-photo img {
  width: 100%; height: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover; object-position: center;
  display: block;
}
@media (min-width: 860px) {
  .bank-photo { height: 52vh; height: 52dvh; }
  .bank-photo img { aspect-ratio: auto; }
}
.bank h3 { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--green); }
.bank p { color: var(--muted); }
.bank .next { margin-top: var(--s-1); justify-self: start; }

/* Over a photograph the brand red drops to 1.03:1, which is not low contrast
   any more, it is invisible, and the brand signature disappears. On a photo
   hero the mark takes the warm on-dark tint the rest of the site uses against
   green, which measures 2.45:1 there: still soft by design, but clearly read at
   96px. A logotype carries no WCAG minimum; this is a legibility fix, not a
   conformance one. */
.hero-photo .hero-deva { color: var(--accent-dark); }

/* ---------- 12. Numbered process (a genuine sequence) ---------- */
.process { border-top: 1px solid var(--line); margin-top: var(--s-4); }
.process li {
  display: grid; gap: .3rem var(--s-4); grid-template-columns: 1fr;
  padding-block: var(--s-3); border-bottom: 1px solid var(--line);
}
@media (min-width: 768px) { .process li { grid-template-columns: 4rem 1fr; align-items: baseline; padding-block: var(--s-4); } }
.process-num { color: var(--accent); font-family: var(--font-label); font-size: var(--fs-label); letter-spacing: .14em; }
.process h3 { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--green); margin-bottom: .3rem; }
.process p { color: var(--muted); max-width: 44ch; }

/* ---------- 13. Plain statement lists (no icons doing the talking) ---------- */
.plain { display: grid; gap: 0; border-top: 1px solid var(--line); margin-top: var(--s-4); max-width: 46rem; }
.plain li { padding-block: var(--s-3); border-bottom: 1px solid var(--line); }
.plain strong { display: block; font-weight: 600; margin-bottom: .2rem; }
.plain span { color: var(--muted); font-size: var(--fs-small); }
.on-dark .plain { border-top-color: var(--line-light); }
.on-dark .plain li { border-bottom-color: var(--line-light); }
.on-dark .plain span { color: rgba(243, 239, 221, .8); }

/* ---------- 14. Values, set large, one line each ---------- */
.values { display: grid; gap: var(--s-3); margin-top: var(--s-4); }
.values li {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 2rem);
  line-height: 1.25; color: var(--green);
}
/* "How we think" sits on the green section, where green on green is invisible. */
.on-dark .values li { color: var(--cream); }

/* Defensive overrides so any of these blocks stays readable if it is ever
   moved onto a dark section. */
.on-dark .bank h3,
.on-dark .process h3,
.on-dark .founder h3,
.on-dark .contact-card h3 { color: var(--cream); }
.on-dark .bank p,
.on-dark .process p,
.on-dark .founder p,
.on-dark .contact-card .role,
.on-dark .faq .faq-body,
.on-dark figcaption { color: rgba(243, 239, 221, .84); }

/* ---------- 15. FAQ accordion ---------- */
.faq { border-top: 1px solid var(--line); margin-top: var(--s-4); max-width: 46rem; }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  padding-block: var(--s-3); min-height: 56px;
  cursor: pointer; list-style: none;
  font-weight: 500;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; font-family: var(--font-label); color: var(--accent);
  font-size: 1.15rem; flex: none; transition: transform .3s var(--ease);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq .faq-body { padding-bottom: var(--s-3); color: var(--muted); max-width: 52ch; }

/* ---------- 16. Founders ---------- */
.founders { display: grid; gap: var(--s-5); grid-template-columns: 1fr; margin-top: var(--s-4); }
@media (min-width: 800px) { .founders { grid-template-columns: 1fr 1fr; gap: var(--s-6); } }
.founder h3 { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--green); margin-bottom: .2rem; }
.founder .role { color: var(--accent); margin-bottom: var(--s-2); }
.founder p { color: var(--muted); }

/* ---------- 17. Image slots and figures ---------- */
.img-slot {
  display: grid; place-items: center; text-align: center;
  background:
    repeating-linear-gradient(45deg, rgba(11,91,75,.05) 0 10px, transparent 10px 20px),
    #EDE7D8;
  border: 1px solid var(--line); border-radius: var(--radius);
}
.img-slot-note { color: var(--muted); line-height: 1.8; padding: var(--s-2); }
.img-slot-tall { aspect-ratio: 4 / 5; }
.img-slot-wide { aspect-ratio: 3 / 2; }
figure { margin: 0; }
figcaption { margin-top: .7rem; color: var(--muted); }

/* alternating image / text rows */
.alt-row { display: grid; gap: var(--s-4); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 900px) {
  .alt-row { grid-template-columns: 1fr 1fr; gap: var(--s-6); }
  .alt-row.is-flipped .alt-media { order: 2; }
}
.alt-row + .alt-row { margin-top: var(--s-6); }

/* ---------- 18. Contact ---------- */
.contacts { display: grid; gap: var(--s-4); grid-template-columns: 1fr; margin-top: var(--s-4); }
@media (min-width: 768px) { .contacts { grid-template-columns: 1fr 1fr; gap: var(--s-5); } }
.contact-card { padding-top: var(--s-3); border-top: 2px solid var(--green); display: grid; gap: .4rem; align-content: start; }
.contact-card h3 { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--green); }
.contact-card .role { color: var(--muted); font-size: var(--fs-small); }
.contact-mail {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--accent); font-weight: 500; text-decoration: none;
  border-bottom: 1px solid transparent; justify-self: start;
  word-break: break-word;
}
.contact-mail:hover { border-bottom-color: var(--accent); }

/* ---------- 19. Footer ---------- */
.site-footer { background: var(--green); color: var(--cream); padding-block: var(--s-6) var(--s-3); }
.footer-grid { display: grid; gap: var(--s-4); grid-template-columns: 1fr; padding-bottom: var(--s-5); }
@media (min-width: 800px) { .footer-grid { grid-template-columns: 2fr 1fr 1fr; gap: var(--s-5); } }
.footer-logo { height: 30px; width: auto; display: block; margin-bottom: var(--s-3); }
.footer-tag { color: rgba(243, 239, 221, .84); max-width: 32ch; margin-bottom: var(--s-2); }
.footer-h { color: var(--accent-dark); margin-bottom: var(--s-2); }
.footer-col ul { display: grid; gap: .5rem; }
.footer-col a, .footer-col span { font-size: var(--fs-small); color: rgba(243, 239, 221, .86); text-decoration: none; }
.footer-col a { display: inline-flex; align-items: center; min-height: 34px; border-bottom: 1px solid transparent; }
.footer-col a:hover { color: var(--cream); border-bottom-color: var(--accent-dark); }
.footer-base {
  display: flex; flex-wrap: wrap; gap: var(--s-2); justify-content: space-between;
  padding-top: var(--s-3); border-top: 1px solid var(--line-light);
  /* 0.78 not 0.62: this row carries the Privacy, Terms and Cookies links, and
     at 62% they measured 3.72:1, which fails AA. 78% gives 4.90:1. */
  color: rgba(243, 239, 221, .78);
}
.footer-base a { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
.footer-base a:hover { border-bottom-color: var(--accent-dark); }

@media (pointer: coarse) { .footer-col a, .footer-base a { min-height: 44px; } }

/* ---------- 20. Legal / prose pages ---------- */
.legal-hero { padding-block: var(--s-5) var(--s-4); }
.legal-title { font-family: var(--font-display); font-size: var(--fs-h2); color: var(--green); letter-spacing: -.02em; margin-bottom: var(--s-2); max-width: 30ch; }
.legal-meta { color: var(--muted); font-size: var(--fs-small); }

.draft-note {
  display: grid; gap: .4rem; margin-block: var(--s-4); padding: var(--s-3);
  background: var(--paper-alt);
  border: 1px solid var(--accent); border-left-width: 4px; border-radius: var(--radius);
}
.draft-note strong { font-weight: 600; color: var(--accent); }
.draft-note p { font-size: var(--fs-small); }

.prose { max-width: 42rem; padding-bottom: var(--s-6); }
.prose h2 {
  font-family: var(--font-display); font-size: 1.5rem; color: var(--green);
  margin-top: var(--s-5); margin-bottom: var(--s-2);
  padding-bottom: .4rem; border-bottom: 1px solid var(--line);
}
.prose h3 { font-size: 1.0625rem; font-weight: 600; color: var(--ink); margin-top: var(--s-3); margin-bottom: .4rem; }
.prose p { margin-bottom: var(--s-2); }
.prose ul { list-style: disc; padding-left: 1.4rem; margin-bottom: var(--s-2); }
.prose ol { list-style: decimal; padding-left: 1.4rem; margin-bottom: var(--s-2); }
.prose li { margin-bottom: .4rem; }
.prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.prose dl { margin-bottom: var(--s-2); }
.prose dt { font-weight: 600; margin-top: var(--s-2); }
.prose dd { color: var(--muted); }

.mini-footer { background: var(--green); color: var(--cream); padding-block: var(--s-4); }
.mini-footer-inner { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); align-items: center; justify-content: space-between; }
.mini-footer a { display: inline-flex; align-items: center; min-height: 44px; font-size: var(--fs-small); color: rgba(243, 239, 221, .86); text-decoration: none; border-bottom: 1px solid transparent; }
.mini-footer a:hover { color: var(--cream); border-bottom-color: var(--accent-dark); }
.mini-footer nav ul { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* ---------- 21. Motion: minimal, a gentle reveal at most ---------- */
.js [data-reveal] {
  opacity: 0; transform: translateY(24px);
  transition: opacity .7s ease-out, transform .7s ease-out;
}
.js [data-reveal].is-in { opacity: 1; transform: none; }
/* Text accompanying an image follows it by 120ms, one step per level. */
.js [data-reveal][data-reveal-delay="1"] { transition-delay: .12s; }
.js [data-reveal][data-reveal-delay="2"] { transition-delay: .24s; }
.js [data-reveal][data-reveal-delay="3"] { transition-delay: .36s; }
.js [data-reveal][data-reveal-delay="4"] { transition-delay: .48s; }
.js [data-reveal][data-reveal-delay="5"] { transition-delay: .60s; }

/* The five commitments stagger left to right, top row then bottom, at 80ms.
   Their own scale, not the 120ms one, because they are one group rather than a
   text block following an image. */
.js .commit[data-reveal][data-reveal-delay="1"] { transition-delay: .00s; }
.js .commit[data-reveal][data-reveal-delay="2"] { transition-delay: .08s; }
.js .commit[data-reveal][data-reveal-delay="3"] { transition-delay: .16s; }
.js .commit[data-reveal][data-reveal-delay="4"] { transition-delay: .24s; }
.js .commit[data-reveal][data-reveal-delay="5"] { transition-delay: .32s; }

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* ==========================================================================
   22. HOW WE WORK page components
   ========================================================================== */

/* ---- tall opening: nothing else on the screen ---- */
.hero-tall {
  min-height: 74vh;
  min-height: 74dvh;
  display: grid;
  align-content: center;
}
/* Wide enough to hold SOURCING JOURNEY on one line at desktop. */
.statement-hero { font-size: clamp(1.6rem, 3.2vw, 2.4rem); max-width: 44rem; }
.statement-hero .w { font-size: 1.75em; }

/* ---- 1. The five steps: a connected flow, not a list ---- */
.flow {
  display: grid;
  gap: var(--s-4) var(--s-3);
  grid-template-columns: 1fr;
  margin-top: var(--s-5);
  counter-reset: step;
}
.flow li { position: relative; display: grid; grid-template-columns: 34px 1fr; gap: var(--s-3); }
.flow-num {
  display: inline-grid; place-items: center;
  width: 30px; height: 30px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  background: var(--paper);
  color: var(--accent);
  font-family: var(--font-label); font-size: .6875rem; letter-spacing: .04em;
  position: relative; z-index: 1;
  flex: none;
}
.flow h3 {
  font-family: var(--font-display); font-size: var(--fs-h3);
  color: var(--green); margin-bottom: .3rem;
}
.flow p { color: var(--muted); font-size: var(--fs-small); }

/* the connecting line: vertical on small screens */
.flow li::after {
  content: ""; position: absolute;
  left: 14px; top: 34px; bottom: calc(-1 * var(--s-4));
  width: 1px; background: var(--line);
}
.flow li:last-child::after { display: none; }

/* horizontal on desktop: the line runs between the numbers */
@media (min-width: 900px) {
  .flow { grid-template-columns: repeat(5, 1fr); gap: var(--s-4) var(--s-4); }
  .flow li { grid-template-columns: 1fr; gap: var(--s-2); }
  .flow li::after {
    left: 38px; right: calc(-1 * var(--s-4));
    top: 14px; bottom: auto;
    width: auto; height: 1px;
  }
  .flow p { max-width: 22ch; }
}
/* on the alt-paper section the markers must match their ground */
.on-paper-alt .flow-num { background: var(--paper-alt); }

/* ---- 2. The three parties ---- */
.parties {
  display: grid; gap: var(--s-5);
  grid-template-columns: 1fr;
  margin-top: var(--s-5);
}
@media (min-width: 860px) { .parties { grid-template-columns: repeat(3, 1fr); gap: var(--s-6); } }
.party { display: grid; gap: var(--s-2); align-content: start; }
.party-icon { width: 56px; height: 56px; color: var(--accent-dark); margin-bottom: var(--s-1); }
.party h3 {
  font-family: var(--font-display); font-size: var(--fs-h3);
  color: var(--cream);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--line-light);
}
.party p { color: rgba(243, 239, 221, .86); font-size: var(--fs-small); }

/* ---- 3. Producers paid first: the quiet centrepiece ---- */
/* Left-aligned like everything else on the site. It was the last centred block
   of copy outside the two Home pull lines. */
.centrepiece { text-align: left; padding-block: var(--s-4); }
.centrepiece .statement { margin-inline: 0; max-width: none; }
.centrepiece-lines { display: grid; gap: var(--s-4); max-width: var(--measure); margin: var(--s-5) 0 0; }
.centrepiece-lines p {
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2.2vw, 1.65rem);
  line-height: 1.45;
  color: var(--green);
}
.centrepiece-rule {
  width: 60px; height: 1px; background: var(--accent);
  margin: var(--s-5) auto 0;
}

/* ---- 4. Traceability: what travels with every lot ---- */
.trace {
  display: grid; gap: var(--s-4);
  grid-template-columns: 1fr;
  margin-top: var(--s-5);
}
/* Three items, so three columns. Was a 2x2 when this section carried four. */
@media (min-width: 768px)  { .trace { grid-template-columns: 1fr 1fr; gap: var(--s-5); } }
@media (min-width: 1000px) { .trace { grid-template-columns: repeat(3, 1fr); gap: var(--s-5); } }
.trace-cell { display: grid; grid-template-columns: 40px 1fr; gap: var(--s-3); align-items: start; }
.trace-icon { width: 34px; height: 34px; color: var(--accent-dark); }
.trace h3 {
  font-family: var(--font-body); font-weight: 600; font-size: 1.0625rem;
  color: var(--cream); margin-bottom: .25rem; line-height: 1.35;
}
.trace p { color: rgba(243, 239, 221, .86); font-size: var(--fs-small); }

/* ---- 5. Paired FAQ columns ---- */
.faq-pair { display: grid; gap: var(--s-5); grid-template-columns: 1fr; margin-top: var(--s-4); }
@media (min-width: 900px) { .faq-pair { grid-template-columns: 1fr 1fr; gap: var(--s-6); } }
.faq-col > h3 {
  font-family: var(--font-display); font-size: var(--fs-h3);
  color: var(--green);
  padding-bottom: var(--s-2);
  margin-bottom: 0;
}
.faq-pair .faq { margin-top: 0; max-width: none; }

/* ---- 6. Closing pair of calls to action ---- */
.close-pair {
  display: grid; gap: var(--s-4);
  grid-template-columns: 1fr;
  margin-top: var(--s-5);
}
@media (min-width: 768px) { .close-pair { grid-template-columns: 1fr 1fr; gap: var(--s-6); } }
.close-card {
  display: grid; gap: var(--s-2); align-content: start; justify-items: start;
  padding-top: var(--s-3);
  border-top: 2px solid var(--accent-dark);
}
.close-card p { color: rgba(243, 239, 221, .86); font-size: var(--fs-small); }
/* .close-card p (0-1-1) was beating .label (0-1-0) and rendering these two
   labels at 15px with 2.7px tracking instead of 12px and 2.16px. */
.close-card .label { font-size: var(--fs-label); }
.close-card .btn { margin-top: var(--s-1); }

/* ==========================================================================
   23. ABOUT US page: founder profiles
   ========================================================================== */

/* Two profiles stacked vertically with generous separation. The biographies are
   deliberately asymmetric, so nothing here forces them to match in length. */
.profiles { display: grid; gap: var(--s-7); margin-top: var(--s-5); }
@media (min-width: 1000px) { .profiles { gap: var(--s-8); } }

/* Photograph left, biography right, the same way round for both founders.
   Two people presented identically reads as an equal partnership; alternating
   the sides on a two-person page is a decision made for its own sake. */
.profile { display: grid; gap: var(--s-4); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 860px) {
  .profile:has(.profile-photo) { grid-template-columns: 38% 1fr; gap: var(--s-6); }
  .profile:not(:has(.profile-photo)) .profile-body { max-width: 46rem; }
}
/* Both portraits are cropped to 4:5 at source. The ratio is set here as well so
   the two render identically whatever their pixel dimensions, and so the space
   is reserved before they load. No border, radius, shadow or filter. */
.profile-photo { display: block; }
.profile-photo img {
  width: 100%; height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover; object-position: center;
  display: block;
}
.profile-body { display: grid; gap: var(--s-2); }
/* The biography column is wider than the measure, so the copy stops at it. The
   role line is excluded: it is a label, not body copy, and at the measure it
   wrapped onto two lines. */
.profile-body p:not(.profile-role) { max-width: var(--measure); }
.profile-name {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  color: var(--green);
  letter-spacing: -.01em;
}
/* Name and role are one unit: the role sits on its own line beneath the name,
   8px below it, with 24px before the first biography paragraph. .profile-body
   is a grid, so its own gap is overridden here rather than fought with margins. */
.profile-role {
  display: block;
  color: var(--accent);
  margin: 0;
}
.profile-body { row-gap: 24px; }
.profile-name + .profile-role { margin-top: -16px; }   /* 24px gap becomes 8px */
.profile-body p { color: var(--muted); }
.profile-mail {
  display: inline-flex; align-items: center; min-height: 44px;
  margin-top: var(--s-1); justify-self: start;
  color: var(--accent); font-weight: 500; font-size: var(--fs-small);
  text-decoration: none; border-bottom: 1px solid transparent;
  word-break: break-word;
}
.profile-mail:hover { border-bottom-color: var(--accent); }

/* two-button close, no third call to action */
.about-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }


/* ==========================================================================
   25. INDIA page layouts
   ========================================================================== */

/* two-column comparison, used for Arabica and Robusta */
.cols-2 { display: grid; gap: var(--s-5); grid-template-columns: 1fr; margin-top: var(--s-5); }
@media (min-width: 820px) { .cols-2 { grid-template-columns: 1fr 1fr; gap: var(--s-6); } }
.col-item { display: grid; gap: var(--s-2); align-content: start;
            padding-top: var(--s-3); border-top: 2px solid var(--accent-dark); }
.col-item h3 { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--cream); }
.col-item p { color: rgba(243, 239, 221, .86); font-size: var(--fs-small); }

/* four preparation cells */
.cells-4 { display: grid; gap: var(--s-4); grid-template-columns: 1fr; margin-top: var(--s-5); }
@media (min-width: 768px)  { .cells-4 { grid-template-columns: 1fr 1fr; gap: var(--s-5) var(--s-4); } }
@media (min-width: 1060px) { .cells-4 { grid-template-columns: repeat(4, 1fr); } }
.cell { display: grid; gap: .5rem; align-content: start;
        padding-top: var(--s-3); border-top: 1px solid var(--line); }
.cell h3 { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--green); }
.cell p { color: var(--muted); font-size: var(--fs-small); }

/* harvest timeline: horizontal on desktop, stacked on mobile */
/* Two clean columns, a single dot at the top of each, and no connector.
   The entries differ a lot in length, so any line drawn between them was
   always going to look unbalanced, and the horizontal version ran straight
   through the heading. Dots only. */
.timeline { display: grid; gap: var(--s-5); grid-template-columns: 1fr; margin-top: var(--s-5); }
@media (min-width: 768px) { .timeline { grid-template-columns: 1fr 1fr; gap: var(--s-4); } }
.tl-item { display: block; }
.tl-dot {
  display: block; width: 11px; height: 11px; border-radius: 50%;
  background: var(--accent); margin-bottom: var(--s-3);
}
.on-dark .tl-dot { background: var(--accent-dark); }
.tl-item h3 { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--green); margin-bottom: .3rem; }
.tl-item p { color: var(--muted); font-size: var(--fs-small); }

/* regions list */
.regions { border-top: 1px solid var(--line); margin-top: var(--s-5); max-width: 52rem; }
/* below the map the list runs the full content width as a two-by-two grid */
.regions-grid { max-width: none; }
.regions li { padding-block: var(--s-3); border-bottom: 1px solid var(--line);
              display: grid; gap: .3rem; }
.regions strong { font-family: var(--font-display); font-weight: 400;
                  font-size: var(--fs-h3); color: var(--green); }
.regions span { color: var(--muted); font-size: var(--fs-small); }
.on-dark .regions { border-top-color: var(--line-light); }
.on-dark .regions li { border-bottom-color: var(--line-light); }
.on-dark .regions strong { color: var(--cream); }
.on-dark .regions span { color: rgba(243, 239, 221, .86); }


/* ==========================================================================
   27. INDIA page: the image treatment system

   Exactly three treatments, and every image on the page uses one of them.
   That constraint is the design. Nothing here is a one-off.

     A  FULL BLEED   edge to edge, 85vh desktop / 62vh mobile. Twice only:
                     the hero and the shade canopy.
     B  HALF BLEED   runs off one viewport edge and stops at 55 percent,
                     70vh desktop, text vertically centred opposite.
     C  PAIR         two images of identical height, one gutter between,
                     spanning the content width, 52vh desktop.

   There is no fourth treatment.
   ========================================================================== */

/* The page gutter, matching .wrap, so a half-bleed text column starts exactly
   on the content grid. Expressed as a percentage of the section rather than of
   100vw: 100vw includes the scrollbar, which would push the text a few pixels
   off the grid on any browser that reserves space for one. */
.half-bleed { --hb-pad: var(--s-3); --hb-gut: var(--s-3); }
@media (min-width: 768px) {
  .half-bleed {
    --hb-pad: var(--s-5);
    --hb-gut: max(var(--s-5), (100% - var(--wrap)) / 2 + var(--s-5));
  }
}
@media (min-width: 1240px) {
  .half-bleed { --hb-gut: max(var(--s-4), (100% - var(--wrap)) / 2 + var(--s-4)); }
}

/* --------------------------------------------------------------------------
   Treatment A: full bleed
   -------------------------------------------------------------------------- */
.bleed-full {
  display: block;
  height: 62vh;
  height: 62dvh;
  margin: 0;                       /* butts against the sections above and below */
}
@media (min-width: 768px) { .bleed-full { height: 85vh; height: 85dvh; } }
.bleed-full img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
}

/* The hero is Treatment A carrying text, so it takes a floor rather than a
   fixed height: copy must never be clipped to hit a number.

   The photograph, the scrim and the text all occupy one grid cell and stack in
   plain document order. An earlier version layered them with z-index inside an
   isolate; that is fragile (negative indices paint behind the parent's own
   background, and some compositors drop the layer entirely) and it is not
   needed here. Nothing below sets z-index at all. */
.hero-photo {
  min-height: 70vh;
  min-height: 70dvh;
  display: grid;
  grid-template-rows: 1fr;         /* one row, filling the hero */
  grid-template-columns: 1fr;
  padding-block: 0 !important;     /* padding lives on .wrap so the photo bleeds */
  overflow: hidden;
}
@media (min-width: 768px) { .hero-photo { min-height: 88vh; min-height: 88dvh; } }

/* Photograph, scrim and copy share one grid cell and paint in document order.
   Nothing here uses z-index or an isolate: an earlier version positioned the
   media absolutely and layered it that way, and some compositors dropped the
   layer entirely, leaving a hero of flat green. In-flow grid items are not
   subject to that. */
.hero-photo > * { grid-area: 1 / 1; min-width: 0; min-height: 0; }
.hero-photo-media {
  position: relative;
  align-self: stretch; justify-self: stretch;
}
.hero-photo-media img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
}
/* The only colour treatment on the page: brand green over the photograph, with
   a stronger foot so the lowest line of text stays legible. It hangs off the
   media rather than off the section, so it always paints above the picture and
   below the copy without any stacking rules. */
.hero-photo-media::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgba(11,91,75,0) 28%, rgba(11,91,75,.62) 100%),
    rgba(11, 91, 75, .50);
}
.hero-photo > .wrap {
  position: relative;              /* positioned like the media, so document
                                      order decides: photograph, scrim, text */
  align-self: end;                 /* text sits low, not centred */
  padding-block: var(--s-7) var(--s-6);
}
/* On paper the body copy is cream at 84 percent. Over a photograph that alpha
   composites with the picture as well, so the text darkens in step with the
   scrim and the contrast ratio stops improving however heavy the scrim gets.
   Full-strength cream measures 5.3:1 at the worst pixel; 84 percent tops out
   at 4.4:1 and cannot reach AA. */
.hero-photo .body-copy p { color: var(--cream); }

/* --------------------------------------------------------------------------
   Treatment B: half bleed
   -------------------------------------------------------------------------- */
.half-bleed {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
  padding-inline: var(--hb-pad);   /* mobile: content width, text below */
}
.hb-media { display: block; margin: 0; }
.hb-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 899px) { .hb-media { aspect-ratio: 4 / 3; } }

@media (min-width: 900px) {
  /* Three columns: the page gutter, the text, and the image at exactly 55 percent
     running off its own edge. The gutter column is empty and holds the text on
     the content grid. */
  .half-bleed {
    padding-inline: 0;
    column-gap: 0; row-gap: 0;
    align-items: center;           /* text vertically centred against the image */
  }
  .hb-media { height: 70vh; height: 70dvh; }
  /* Both children are pinned to row 1. The text comes first in the DOM for
     reading order, so without this the media, placed in an earlier column,
     would be pushed to a second row rather than sitting beside it. */
  .half-bleed .hb-text, .half-bleed .hb-media { grid-row: 1; }
  .half-bleed.bleed-right { grid-template-columns: var(--hb-gut) 1fr 55%; }
  .half-bleed.bleed-right .hb-text  { grid-column: 2; padding-right: var(--s-6); }
  .half-bleed.bleed-right .hb-media { grid-column: 3; }
  .half-bleed.bleed-left  { grid-template-columns: 55% 1fr var(--hb-gut); }
  .half-bleed.bleed-left  .hb-media { grid-column: 1; }
  .half-bleed.bleed-left  .hb-text  { grid-column: 2; padding-left: var(--s-6); }
}

/* --------------------------------------------------------------------------
   Treatment C: pair
   -------------------------------------------------------------------------- */
.pair {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-3);
  margin-top: var(--s-5);
  margin-bottom: var(--s-6);
}
.pair picture { display: block; margin: 0; }
.pair img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 819px) { .pair picture { aspect-ratio: 4 / 3; } }
@media (min-width: 820px) {
  .pair { grid-template-columns: 1fr 1fr; gap: var(--s-4); height: 52vh; height: 52dvh; }
}

/* --------------------------------------------------------------------------
   Shared
   -------------------------------------------------------------------------- */
/* Kept as an alias so the class need not be stripped from the markup: there is
   one measure on the site now, and this was the last thing overriding it. */
.measure-read { max-width: var(--measure); }
.col-stack { display: grid; gap: var(--s-4); }
/* the stack supplies the spacing, so the timeline drops its own top margin,
   which otherwise threw the block 24px off centre against a half-bleed image */
.col-stack > .timeline { margin-top: 0; }


/* --------------------------------------------------------------------------
   Treatment D: full bleed with a text panel

   The hero and these are deliberately different techniques. The hero puts a
   green scrim across the whole photograph and sets text straight on it. These
   leave the photograph clear and give the copy its own solid panel, so the hero
   stays the page's one scrimmed moment.
   -------------------------------------------------------------------------- */
.bleed-panel {
  --panel-gut: var(--s-3);
  position: relative;
  min-height: 70vh;
  min-height: 70dvh;
  display: grid;
  overflow: hidden;
  /* full bleed butts against the sections above and below; the panel holder
     supplies the only inset, so the section's own padding would just push the
     height past 88vh */
  padding-block: 0 !important;
}
@media (min-width: 768px) {
  .bleed-panel {
    min-height: 88vh;
    min-height: 88dvh;
    --panel-gut: max(var(--s-5), (100% - var(--wrap)) / 2 + var(--s-5));
  }
}
/* Below 900 the panel takes the full content width. At 768 a 42vw panel is only
   323px, which is too narrow to set body copy in. */
@media (min-width: 1240px) {
  .bleed-panel { --panel-gut: max(var(--s-4), (100% - var(--wrap)) / 2 + var(--s-4)); }
}

/* The photograph is taken out of flow, so the section's height is set by the
   panel alone: a panel with more copy grows the section, an image never does.
   In flow the image's own intrinsic height was forcing these sections to 154vh.
   Media and panel are both positioned with z-index auto, so they paint in
   document order: photograph, then panel. No z-index anywhere. */
.bleed-panel-media { position: absolute; inset: 0; }
.bleed-panel-media img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
}

.panel-holder {
  position: relative;              /* positioned, so it paints over the media */
  align-self: center;              /* panel vertically centred against the image */
  display: grid;
  padding-inline: var(--panel-gut);
  padding-block: var(--s-5);       /* keeps a tall panel off the image edges */
}
.panel-left  .panel-holder { justify-items: start; }
.panel-right .panel-holder { justify-items: end; }

.panel {
  width: 100%;
  background: rgba(11, 91, 75, .94);   /* a trace of the photograph reads through */
  color: var(--cream);
  padding: 32px;
  /* no border, no radius, no shadow */
}
@media (min-width: 900px) {
  /* 640 rather than 560: at 560 the internal measure was about 40 characters,
     which is what made 90 words in the both-banks panel feel like a wall. */
  .panel { width: min(46vw, 640px); padding: 64px; }
}
/* Body copy elsewhere is cream at 84 percent. On a panel that sits over a
   photograph the alpha composites with the picture as well, so it is set at
   full strength, exactly as in the hero. */
.panel p, .panel .body-copy p { color: var(--cream); }
.panel > *:first-child { margin-top: 0; }
.panel > *:last-child  { margin-bottom: 0; }


/* spacing inside a panel: the blocks stack with the standard rhythm */
.panel > * + * { margin-top: var(--s-4); }
.panel .timeline { margin-top: var(--s-4); }
.panel .tl-item h3 { color: var(--cream); }
.panel .tl-item p { color: rgba(243, 239, 221, .88); }
.panel .tl-dot { background: var(--accent-dark); }
/* inside a panel the two entries sit side by side only when there is room */
@media (max-width: 899px) { .panel .timeline { grid-template-columns: 1fr; gap: var(--s-4); } }
/* more air between the two timeline columns, and the closing paragraph separated
   from the timeline rather than running straight on */
@media (min-width: 900px) { .panel .timeline { gap: var(--s-5); } }
.panel .timeline + .body-copy { margin-top: 32px; }

/* breathing room between two adjacent full-bleed images, in the section's green */
.bleed-gap { height: 72px; background: var(--green); }
@media (min-width: 768px) { .bleed-gap { height: 120px; } }

/* .home-copy is centred where it sits under a centred statement. Inside a panel
   it is a left-inset block of body copy and centring it reads as a mistake. */
.panel .home-copy, .panel .body-copy { text-align: left; margin-inline: 0; max-width: none; }
.panel .home-copy p { color: var(--cream); }
.panel .home-copy p + p, .panel .body-copy p + p { margin-top: 30px; }

/* --------------------------------------------------------------------------
   The map: full content width, no ground of its own
   -------------------------------------------------------------------------- */
.map-block { margin-top: var(--s-5); }
.map-figure { margin: 0 auto; max-width: 1000px; }
.map-figure img { width: 100%; height: auto; display: block; }
/* The labels stop being readable below 560px, so on a narrow screen the map
   scrolls inside its own box rather than shrinking into illegibility. */
/* The sideways-scrolling box is gone: below 768 a variant without labels is
   served instead, so the map simply fits. */
.map-figure picture { display: block; }
.map-figure img { width: 100%; height: auto; display: block; }

.regions-grid {
  display: grid; grid-template-columns: 1fr; gap: 0 var(--s-6);
  margin-top: var(--s-6);
}
@media (min-width: 768px) { .regions-grid { grid-template-columns: 1fr 1fr; } }

/* ==========================================================================
   29. Interaction and scroll-linked motion

   Two additions, both governed by the same rule as the rest of the site: they
   are decoration, never a gate on content, and they switch off entirely under
   prefers-reduced-motion.
   ========================================================================== */

/* ---- press feedback ----
   Hover states already exist. What was missing is the moment of the click:
   without it a button feels like a picture of a button. The movement is 1px
   and 1.5 percent, which registers as touch rather than as animation. */
.btn, .nav-cta, .next, .contact-mail, .profile-mail {
  transition:
    background .3s var(--ease),
    color .3s var(--ease),
    border-color .3s var(--ease),
    transform .12s var(--ease);
}
.btn:active, .nav-cta:active { transform: translateY(1px) scale(.985); }
.next:active, .contact-mail:active, .profile-mail:active { transform: translateY(1px); }

/* the accordion summary on How We Work gets the same treatment */
.faq summary { transition: color .3s var(--ease), transform .12s var(--ease); }
.faq summary:active { transform: translateY(1px); }

/* ---- scroll-linked tilt ----
   An element settles into place as it enters the viewport: a small rotation on
   the X axis resolving to flat, with a slight scale. The angle is set here as a
   token so it can be dialled in one place. 10deg reads as the object coming to
   rest; the 20deg of the original reads as a device being presented, which is a
   product idiom rather than an editorial one. */
:root { --tilt-angle: 10deg; --tilt-scale: .04; }
@media (min-width: 768px) { :root { --tilt-angle: 12deg; } }

.js [data-tilt] {
  transform-origin: 50% 0%;
  backface-visibility: hidden;              /* keeps text crisp mid-rotation */
  will-change: auto;
}
.js [data-tilt].is-tilting { will-change: transform; }

/* Before the script reaches it, an element carries the starting transform so
   there is no flash of the settled state on a slow first paint. If the script
   never runs at all, the noscript block below resets it. */
.js [data-tilt]:not(.is-settled) {
  transform: perspective(1200px) rotateX(var(--tilt-angle)) scale(calc(1 - var(--tilt-scale)));
}

@media (prefers-reduced-motion: reduce) {
  .btn:active, .nav-cta:active, .next:active,
  .contact-mail:active, .profile-mail:active, .faq summary:active { transform: none; }
  .js [data-tilt], .js [data-tilt]:not(.is-settled) {
    transform: none !important;
    will-change: auto;
  }
}

/* ==========================================================================
   30. Mobile pass

   Everything below 768px. The desktop rules above are untouched.
   ========================================================================== */

/* ---- the viewport height trap ----
   iOS Safari counts its own chrome in vh, so a vh-sized section grows and
   shrinks as the chrome hides and returns, and the page jumps mid-scroll. dvh
   tracks the live viewport. The vh line stays first as the fallback for
   anything that does not know dvh. */
@media (max-width: 767px) {
  /* 88 rather than 70: the copy will not compress to 70 without cutting it, and
     88 leaves a sliver of the next section at the fold, which is what tells a
     visitor there is more below. */
  .hero-photo   { min-height: 88vh; min-height: 88dvh; }
  .bleed-full   { height: 70vh;     height: 70dvh; }
  .bleed-panel  { min-height: 70vh; min-height: 70dvh; }
  .hb-media     { height: auto; }
  .bank-photo   { height: auto; }
}

@media (max-width: 767px) {

  /* ---- full-bleed images: keep the subject, not the sky ----
     A wide frame on a narrow screen shows roughly a third of its width, so
     each one is anchored on what the picture is actually of. */
  .hero-photo-media img,
  .bleed-panel-media img,
  .bleed-full img { object-position: var(--focal, center); }

  /* ---- text panels ----
     The overlay treatment does not survive a phone. Every panel on the site
     carries 55 to 75 words; at 375 the shortest renders 422px tall against the
     341px it may occupy if 40 percent of the photograph is to stay visible, and
     the longest renders 708px. So below 768 the picture and the words separate:
     photograph on top at 55dvh, copy beneath on the section ground. The layered
     look returns at 768 and above, untouched.

     .panel-over is the opt-in for any panel short enough to sit on the image,
     should the copy ever be cut. Nothing uses it today. */
  .bleed-panel { min-height: 0; display: block; }
  /* a <picture> is inline by default, so a height on it is ignored */
  .bleed-panel .bleed-panel-media { display: block; position: static; height: 55vh; height: 55dvh; }
  .bleed-panel .bleed-panel-media img { width: 100%; height: 100%; }
  /* The panel keeps its own ground and is lifted onto the bottom edge of the
     photograph, so the two read as one composed unit rather than two stacked
     blocks. Same idea as the desktop overlay, at a scale that fits: the picture
     stays fully legible above the overlap, the copy stays fully readable. */
  .panel-holder { padding: 0 var(--s-3); margin-top: -56px; position: relative; }
  .panel { width: 100%; background: rgba(11, 91, 75, .94); padding: 32px; }
  .panel p, .panel h3 { color: var(--cream); }

  .bleed-panel.panel-over { display: grid; align-items: end; min-height: 70vh; min-height: 70dvh; }
  .bleed-panel.panel-over .bleed-panel-media { position: absolute; inset: 0; height: auto; }
  .bleed-panel.panel-over .panel-holder { align-self: end; padding: 0 var(--s-3) var(--s-3); }
  .bleed-panel.panel-over .panel { background: rgba(11, 91, 75, .94); padding: 32px; }

  /* a panel section is green top to bottom once the copy sits beneath the photo */
  .bleed-panel { background: var(--green); padding-bottom: var(--s-6); }

  /* ---- pairs stack ---- */
  .pair { grid-template-columns: 1fr; gap: 24px; height: auto; }
  .pair picture { aspect-ratio: 3 / 2; }
  .banks { gap: var(--s-6); }

  /* ---- typography ----
     Body never below 16px: smaller is hard to read, and on any input it makes
     iOS zoom the page. Large display type comes down so no heading runs past
     two lines, and its tracking tightens with it. */
  /* Body never below 16px. The label token is not body copy, so the 16px rule
     does not reach it, but 12px uppercase mono at 2.16px tracking is tight on a
     phone, so it goes up a step. A judgement call, easily reverted. */
  :root { --fs-small: 1rem; --fs-label: .8125rem; }
  .statement { font-size: 1.3rem; letter-spacing: -.02em; }
  .statement .w { font-size: 1.5em; letter-spacing: -.03em; line-height: 1.05; }
  .hero-title { font-size: clamp(1.9rem, 8.5vw, 2.4rem); letter-spacing: -.025em; }
  .body-copy p, .home-copy p, .profile-body p, main p { line-height: 1.62; }

  /* ---- tap targets ----
     44px minimum, and 8px of clear space so a thumb cannot catch two at once. */
  .next, .contact-mail, .profile-mail, .footer-col a, .footer-base a, .mini-footer a {
    min-height: 44px; display: inline-flex; align-items: center;
  }
  .footer-col li + li, .footer-base li + li { margin-top: 8px; }
  .nav-toggle { min-width: 44px; justify-content: center; }
  /* short link text still needs a 44px target; the text stays left so the
     column alignment does not shift */
  .footer-col a, .footer-base a, .mini-footer a { min-width: 44px; justify-content: flex-start; }
  .actions { flex-direction: column; align-items: stretch; gap: 12px; }
  .actions .btn { width: 100%; }

  /* ---- page margin ---- */
  .wrap { padding-inline: var(--s-3); }   /* 24px */

  /* the hero holds more than any other full-bleed section, so its own padding
     comes in rather than letting the section grow past the others */
  .hero-photo > .wrap { padding-block: var(--s-5) var(--s-4); }
  .hero-lockup { margin-bottom: var(--s-3); }
  .hero-stack { margin-bottom: var(--s-4); gap: .4rem; }
}

/* ---- motion: less of it on a phone ----
   Scroll-triggered work costs battery and stutters on mid-range Android, and
   there is less on screen to reward it. The rise halves, the duration shortens,
   the commitments arrive together instead of in sequence, and the scroll-linked
   tilt is off entirely. */
@media (max-width: 767px) {
  /* The rise starts at 12px and the settled state must still win, so .is-in is
     restated here. Without it the mobile rule and the base .is-in rule both
     apply and every revealed element sits 12px low for good. */
  .js [data-reveal] {
    transform: translateY(12px);
    transition: opacity .5s ease-out, transform .5s ease-out;
  }
  .js [data-reveal].is-in { transform: none; }
  .js .commit[data-reveal][data-reveal-delay="1"],
  .js .commit[data-reveal][data-reveal-delay="2"],
  .js .commit[data-reveal][data-reveal-delay="3"],
  .js .commit[data-reveal][data-reveal-delay="4"],
  .js .commit[data-reveal][data-reveal-delay="5"] { transition-delay: 0s; }
  .js [data-tilt], .js [data-tilt]:not(.is-settled) { transform: none !important; }
}

/* ---- 768 to 899: the tablet gap ----
   The mobile rules stop at 767 and the desktop panel does not begin until 900,
   where it becomes an inset 640px column. In between, the panel was running the
   full width over the photograph and covering it, and headings were still at
   desktop size and wrapping to three lines. This band gets the mobile panel
   treatment and the mobile display sizes; everything else stays as built. */
@media (min-width: 768px) and (max-width: 899px) {
  .bleed-panel { min-height: 0; display: block; background: var(--green); padding-bottom: var(--s-6); }
  .bleed-panel .bleed-panel-media { display: block; position: static; height: 58vh; height: 58dvh; }
  .bleed-panel .bleed-panel-media img { width: 100%; height: 100%; }
  .panel-holder { align-self: auto; padding: 0 var(--s-5); margin-top: -56px; position: relative; }
  .panel { width: 100%; background: rgba(11, 91, 75, .94); padding: 40px; }
  .panel p, .panel h3 { color: var(--cream); }

  .statement { font-size: 1.5rem; letter-spacing: -.018em; }
  .statement .w { font-size: 1.55em; letter-spacing: -.028em; }
  .hero-photo { min-height: 78vh; min-height: 78dvh; }
  .bleed-full { height: 78vh; height: 78dvh; }
}

/* A tablet is a touch device too, so the 16px floor and the 44px target hold
   all the way to the desktop layout rather than stopping at 767. */
@media (max-width: 899px) {
  :root { --fs-small: 1rem; --fs-label: .8125rem; }
  .next, .contact-mail, .profile-mail,
  .footer-col a, .footer-base a, .mini-footer a, .nav-menu a {
    min-height: 44px; min-width: 44px;
    display: inline-flex; align-items: center; justify-content: flex-start;
  }
  .footer-col li + li, .footer-base li + li { margin-top: 8px; }
  .nav-toggle { min-width: 44px; }

  /* A link inside a sentence cannot be given a 44px box without wrecking the
     line it sits in. Padding plus an equal negative margin grows the hit area
     vertically to 45px while leaving the text exactly where it was. */
  main a:not(.btn):not(.next):not(.nav-cta):not(.contact-mail):not(.profile-mail):not(.map-figure a) {
    padding-block: 12px; margin-block: -12px;
    position: relative;
  }
}

/* ---------- 28. Print ---------- */
@media print {
  body::before, .site-header, .nav-toggle { display: none; }
  body { background: #fff; color: #000; }
  .on-dark, .hero, .site-footer, .mini-footer { background: #fff; color: #000; }
}
