/* ============================================================================
   Bedrock Energy Corp — component library
   ----------------------------------------------------------------------------
   THE BRIDGE. Every class here is designed to be applied two ways:

     · directly in the static homepage markup
     · typed into Elementor's "CSS Classes" field on a widget or container

   That is what keeps the static homepage and the Elementor pages looking like
   one site. An editor drags a Heading widget, types `bd-eyebrow`, and it is
   correct — no per-page styling, nothing to drift.

   Consequences of that dual use, which explain some choices below:

     · No class depends on a specific element. `.bd-eyebrow` works on a <p>,
       <h2>, <span> or <div>, because Elementor decides the tag, not us.
     · No class depends on being a direct child of another. Elementor injects
       wrapper divs at will, so `>` combinators break the moment a widget is
       nested in a container.
     · Layout classes set their own display, so dropping one on an Elementor
       container that already has flex applied still lands correctly.

   Requires tokens.css.
   ========================================================================== */

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

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--bd-font-body);
  font-size: var(--bd-size-body);
  line-height: var(--bd-leading-body);
  letter-spacing: var(--bd-track-body);
  color: var(--bd-text);
  background: var(--bd-surface);
  -webkit-font-smoothing: antialiased;
}

img, svg, video { display: block; max-width: 100%; }
img, video { height: auto; }

:where(a) { color: var(--bd-blue); text-underline-offset: 0.18em; }

/* A visible focus ring everywhere, in a colour that survives both the light
   and petrol bands. Elementor's own styles frequently strip focus outlines;
   this is deliberately specific enough to win that fight. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--bd-green-bright);
  outline-offset: 3px;
  border-radius: var(--bd-radius-sm);
  box-shadow: 0 0 0 5px var(--bd-ring);
}

.bd-visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

.bd-skip {
  position: absolute; left: var(--bd-s4); top: -100%;
  z-index: var(--bd-z-overlay);
  background: var(--bd-white); color: var(--bd-petrol);
  padding: var(--bd-s3) var(--bd-s5); border-radius: var(--bd-radius);
  font-weight: var(--bd-weight-strong); text-decoration: none;
}
.bd-skip:focus { top: var(--bd-s4); }

/* ------------------------------------------------------------ structure --- */

/* A full-width horizontal band. The whole page is a stack of these. */
.bd-band {
  position: relative;
  padding-block: var(--bd-band-y);
  background: var(--bd-surface);
  color: var(--bd-text);
}
.bd-band--alt   { background: var(--bd-surface-alt); }
.bd-band--petrol{ background: var(--bd-petrol); color: var(--bd-text-on-dark); }
/* These three exist because the porous spreads end in exactly these colours.
   A band's value must match its spread's solid edge to the byte, or the join
   shows as a hairline. They are not decorative choices. */
.bd-band--green { background: var(--bd-green);  color: var(--bd-text-on-dark); }
.bd-band--yellow{ background: var(--bd-yellow); color: var(--bd-petrol); }
.bd-band--blue  { background: var(--bd-blue);   color: var(--bd-text-on-dark); }
.bd-band--flush { padding-block: 0; }
.bd-band--tight { padding-block: var(--bd-s7); }

/* Dark bands need their descendants recoloured, and Elementor will nest
   headings several wrappers deep, so this cannot use a child combinator. */
.bd-band--petrol :is(h1,h2,h3,h4,.bd-display,.bd-title),
.bd-band--green  :is(h1,h2,h3,h4,.bd-display,.bd-title),
.bd-band--yellow :is(h1,h2,h3,h4,.bd-display,.bd-title),
.bd-band--blue   :is(h1,h2,h3,h4,.bd-display,.bd-title) { color: inherit; }
.bd-band--petrol .bd-lede,
.bd-band--blue   .bd-lede { color: var(--bd-text-on-dark-soft); }
/* White on this green measures 2.99:1. Secondary copy is therefore kept at
   FULL white rather than the softened white used on petrol and blue — fading
   it would drop it further still. */
.bd-band--green  .bd-lede { color: var(--bd-white); }
/* Yellow is a light band, so its secondary text darkens rather than lightens. */
.bd-band--yellow .bd-lede { color: color-mix(in srgb, var(--bd-petrol) 72%, transparent); }
.bd-band--yellow .bd-eyebrow { color: var(--bd-petrol); opacity: 0.7; }
.bd-band--blue .bd-eyebrow { color: var(--bd-white); opacity: 0.85; }

/* Angular texture for light bands.
 *
 * Drawn on ::before rather than as a background so it can be masked
 * independently of the band's own colour. The mask fades the lattice out at
 * the top and bottom edges, which matters: a hard-edged texture running into
 * a porous spread produces two competing geometries meeting at a line, and
 * the join stops reading as fluid.
 */
.bd-band--texture::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    repeating-linear-gradient(30deg,
      transparent 0 calc(var(--bd-texture-cell) - 1px),
      var(--bd-texture-ink) calc(var(--bd-texture-cell) - 1px) var(--bd-texture-cell)),
    repeating-linear-gradient(-30deg,
      transparent 0 calc(var(--bd-texture-cell) - 1px),
      var(--bd-texture-ink) calc(var(--bd-texture-cell) - 1px) var(--bd-texture-cell));
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
}
/* The band is already position:relative, but its content has to out-rank the
   texture layer or the lattice sits over the copy. */
.bd-band--texture > * { position: relative; z-index: 1; }

/* Denser and shorter-range, for narrow bands where the wide lattice would
   show only two or three lines and read as a stray rule. */
.bd-band--texture-fine { --bd-texture-cell: 22px; }

.bd-container {
  width: min(100% - (var(--bd-gutter) * 2), var(--bd-content));
  margin-inline: auto;
}
.bd-container--narrow { width: min(100% - (var(--bd-gutter) * 2), var(--bd-content-narrow)); }
.bd-container--full   { width: 100%; }

/* Generic responsive grid. `--cols` is set per use so Elementor users can
   override it in the widget's own Custom CSS without touching this file. */
.bd-grid {
  display: grid;
  gap: var(--bd-s6);
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
}
.bd-grid--2 { --cols: 2; }
.bd-grid--3 { --cols: 3; }
.bd-grid--4 { --cols: 4; }

@media (max-width: 980px) { .bd-grid { --cols: 2 !important; } }
@media (max-width: 640px) { .bd-grid { --cols: 1 !important; } }

/* Two-column editorial split: media one side, prose the other. */
.bd-split {
  display: grid;
  gap: clamp(var(--bd-s6), 4vw, var(--bd-s9));
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: center;
}
.bd-split--media-right > :first-child { order: -1; }
@media (max-width: 860px) {
  .bd-split { grid-template-columns: 1fr; }
  .bd-split--media-right > :first-child { order: 0; }
}

/* ----------------------------------------------------------------- type --- */

/* Mono, small, wide-tracked. This one change does more to modernise the page
   than anything else: the same label set in a wide-tracked sans reads like a
   2014 lifestyle brand, and in mono it reads technical — which is what an
   energy infrastructure company should sound like. */
.bd-eyebrow {
  font-family: var(--bd-font-mono);
  font-size: 0.71875rem;   /* 11.5px */
  font-weight: 500;
  letter-spacing: var(--bd-track-eyebrow);
  text-transform: uppercase;
  line-height: 1.2;
  margin: 0 0 var(--bd-s4);
  color: var(--bd-green-bright);
}
.bd-band--petrol .bd-eyebrow { color: var(--bd-white); opacity: 0.85; }
.bd-band--green  .bd-eyebrow { color: var(--bd-white); opacity: 1; }

/* The eyebrow's trailing letter-space pushes short labels visibly
   off-centre when centred. Reclaim it. */
.bd-eyebrow { margin-inline-end: calc(var(--bd-track-eyebrow) * -1); }

.bd-hero-title,
.bd-display,
.bd-title {
  font-family: var(--bd-font-display);
  text-wrap: balance;
  margin: 0 0 var(--bd-s5);
}
.bd-hero-title {
  font-size: var(--bd-size-hero);
  font-weight: var(--bd-weight-display);
  letter-spacing: var(--bd-track-hero);
  line-height: var(--bd-leading-hero);
}
.bd-display {
  font-size: var(--bd-size-display);
  font-weight: var(--bd-weight-display);
  letter-spacing: var(--bd-track-display);
  line-height: var(--bd-leading-display);
}
.bd-title {
  font-size: var(--bd-size-title);
  font-weight: var(--bd-weight-title);
  letter-spacing: var(--bd-track-title);
  line-height: var(--bd-leading-title);
}

.bd-lede {
  font-size: var(--bd-size-sub);
  line-height: 1.55;
  letter-spacing: var(--bd-track-body);
  color: var(--bd-text-soft);
  max-width: var(--bd-measure);
  margin: 0 0 var(--bd-s5);
}
.bd-prose { max-width: var(--bd-measure); }
.bd-prose > * + * { margin-top: var(--bd-s5); }

/* A rule that picks up the accent, used under section headings. */
.bd-rule-accent {
  width: 64px; height: 4px; border: 0; margin: 0 0 var(--bd-s5);
  background: var(--bd-green-bright);
}
.bd-center { text-align: center; }
.bd-center .bd-lede,
.bd-center .bd-rule-accent { margin-inline: auto; }

/* --------------------------------------------------------------- porous --- */

/* The brand's porous pattern spreads, in all four colourways the brand ships:
   white, green, yellow, blue.
 *
 * All four have an alpha channel — the coloured shapes float on transparency.
 * That matters more than it sounds. They are NOT band transitions that have to
 * match the colour of the band below; they are ornamental spreads that overlay
 * whatever sits behind them. So the modifier names the pattern's own colour,
 * not a destination band, and any band colour may sit on either side.
 *
 * The live site cycles them by theme as the page descends —
 * white, green, green, yellow, yellow, blue, green — and that progression is
 * the colour fluidity the site is built around. Used one at a time they read as
 * decoration; used in sequence they read as movement.
 */
.bd-porous-wrap {
  display: block;
  line-height: 0;
  position: relative;
  z-index: var(--bd-z-band);
  pointer-events: none;
}
.bd-porous-wrap img {
  display: block;
  width: 100%;
  height: auto;
}

/* Hanging from the top edge of a band rather than rising from the bottom. */
.bd-porous-wrap--flip img { transform: scaleY(-1); }

/* Force the white spread to TRUE white.
 *
 * The artwork is two-tone — white shapes plus a ~#E5E5E5 shade face. On a light
 * band that second tone is the pattern's internal detail and it is correct. Over
 * the dark hero film it is the only thing visible as grey, so the crest reads as
 * a grey shelf rather than as the white band arriving, and the join stops being
 * fluid.
 *
 * brightness(0) crushes every tone to black and invert(1) lifts it to white,
 * while alpha is untouched — so the silhouette and the porous gaps survive
 * exactly, and every remaining pixel is #FFFFFF. A brightness multiplier would
 * also work here (229 → 255 needs ~1.12) but only because this artwork happens
 * to be greyscale; this pair is exact whatever the source tones. */
.bd-porous-wrap--white img { filter: brightness(0) invert(1); }

/* Pull the divider up over the preceding band so the two overlap rather than
   stack — otherwise the band's padding leaves a visible gap above it. */
.bd-porous-wrap--overlap { margin-top: calc(var(--bd-s7) * -1); }

/* THE RULE THAT MAKES THE COLOUR CHANGES FLUID.
 *
 * Each spread is transparent at the top and solid colour at the bottom. So a
 * spread only works where its solid edge meets a band of the SAME colour: the
 * mass simply continues into the band and there is no edge to see. Put a green
 * spread above a white band and its solid #00AB67 base draws a hard horizontal
 * line across the page — which is exactly the break this replaced.
 *
 * Leaving a band is the same move inverted: a flipped copy puts the solid edge
 * at the top, continuing the band, while its transparent base dissolves into
 * the white below.
 *
 *     white band                       ← transparent top shows it
 *     ░▒▓ spread (solid base) ▓▒░
 *     ███ coloured band ███            ← same colour, no seam
 *     ░▒▓ spread, flipped ▓▒░
 *     white band                       ← transparent base shows it
 *
 * Zero margin between the two is not optional; a single pixel of gap puts the
 * page background through the join and the hairline comes back.
 */
.bd-porous-wrap + .bd-band,
.bd-band + .bd-porous-wrap,
.bd-porous-wrap + .bd-proof,
.bd-proof + .bd-porous-wrap { margin-block: 0; }

/* --------------------------------------------------------------- button --- */

/* Soft radius, solid fill, and a single pixel of lift into a real shadow on
   hover. The old hard green offset was the most dated element on the page —
   a flat-design device with no blur and no spread, unmistakably 2016 — so it
   is retired from the default and kept as an opt-in variant below.
*/
.bd-btn {
  --bd-btn-py: 12px;
  --bd-btn-px: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--bd-s2);
  padding: var(--bd-btn-py) var(--bd-btn-px);
  font-family: var(--bd-font-ui);
  font-size: 0.90625rem;          /* 14.5px */
  font-weight: 700;
  letter-spacing: -0.008em;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: var(--bd-btn-radius);
  background: var(--bd-blue);
  color: var(--bd-white);
  transition: background-color var(--bd-dur-fast) ease,
              border-color var(--bd-dur-fast) ease,
              color var(--bd-dur-fast) ease,
              box-shadow var(--bd-dur-fast) ease,
              transform var(--bd-dur-fast) var(--bd-ease);
}
.bd-btn:hover { transform: translateY(-1px); box-shadow: var(--bd-shadow-md); }
.bd-btn:active { transform: translateY(0); box-shadow: none; }

@media (prefers-reduced-motion: reduce) {
  .bd-btn:hover, .bd-btn:active { transform: none; }
}

.bd-btn--sm { --bd-btn-py: 9px;  --bd-btn-px: 16px; font-size: 0.84375rem; }
.bd-btn--lg { --bd-btn-py: 15px; --bd-btn-px: 30px; font-size: 0.96875rem; }
.bd-btn--wide { width: 100%; }

.bd-btn--primary { background: var(--bd-blue); }
.bd-btn--primary:hover { background: #0067A8; }

.bd-btn--green { background: var(--bd-green-bright); }
.bd-btn--green:hover { background: var(--bd-green); }

/* Outline, weighted by proportion of the inherited colour rather than a fixed
   value — so one rule works on white, petrol, green and blue bands alike. */
.bd-btn--ghost {
  background: transparent;
  color: currentColor;
  border-color: color-mix(in srgb, currentColor 26%, transparent);
}
.bd-btn--ghost:hover {
  border-color: color-mix(in srgb, currentColor 55%, transparent);
  background: color-mix(in srgb, currentColor 6%, transparent);
}

/* The brand's hard offset, kept as an opt-in for a hero CTA where the cue is
   wanted deliberately. Not the default — on every control it reads as a dated
   theme rather than as a signature. */
.bd-btn--offset {
  border-radius: 0;
  box-shadow: var(--bd-btn-offset);
}
.bd-btn--offset:hover {
  transform: translate(2px, 5px);
  box-shadow: 0 0 0 0 var(--bd-green-bright);
}

/* A text link that behaves like a button's quieter sibling. The arrow travels
   on hover, so the affordance is motion rather than an underline. */
.bd-link-arrow {
  display: inline-flex; align-items: center; gap: var(--bd-s2);
  font-weight: 700; font-size: 0.90625rem; letter-spacing: -0.008em;
  color: var(--bd-blue); text-decoration: none;
}
.bd-link-arrow svg { transition: transform var(--bd-dur) var(--bd-ease); }
.bd-link-arrow:hover svg { transform: translateX(4px); }
.bd-band--petrol .bd-link-arrow,
.bd-band--blue .bd-link-arrow { color: var(--bd-white); }
.bd-band--green .bd-link-arrow { color: var(--bd-white); }

/* ---------------------------------------------------------------- cards --- */

/* Unboxed. The card is a media block with an open body beneath it, not a
   bordered container — a bordered white box on a white band is a rectangle
   drawn around nothing, and it is the most dated pattern on the old page.
   Structure comes from the media block's own edge and from alignment.

   `bd-card--boxed` is kept for the cases that genuinely need a container:
   cards on a coloured band, where an open card floats with nothing to sit on.
*/
.bd-card {
  position: relative;
  display: flex; flex-direction: column;
  background: none;
  border: 0;
  border-radius: 0;
}

/* The thread: a rule that draws itself across the top as the card enters.
   Cheaper than a border and it gives the grid a rhythm on scroll. */
.bd-card__thread {
  height: 2px;
  background: var(--bd-green-bright);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--bd-dur-slow) var(--bd-ease);
  margin-bottom: var(--bd-s5);
}
.is-in .bd-card__thread,
.bd-card:hover .bd-card__thread { transform: scaleX(1); }

.bd-card__media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--bd-radius-lg);
  background: var(--bd-paper);
  border: 1px solid var(--bd-rule);
  transition: border-color var(--bd-dur) var(--bd-ease),
              box-shadow var(--bd-dur) var(--bd-ease);
}
.bd-card__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.7s var(--bd-ease);
}
.bd-card:hover .bd-card__media {
  border-color: color-mix(in srgb, var(--bd-green-bright) 45%, var(--bd-rule));
  box-shadow: var(--bd-shadow-md);
}
/* A very small scale. Anything more and the crop visibly changes, which reads
   as the image moving rather than the card responding. */
.bd-card:hover .bd-card__media img { transform: scale(1.02); }

.bd-card__body {
  padding: var(--bd-s5) 0 0;
  display: flex; flex-direction: column; gap: var(--bd-s3); flex: 1;
}
.bd-card__body > :last-child { margin-top: auto; padding-top: var(--bd-s4); }
.bd-card__body .bd-title { margin: 0; }
.bd-card__body p { margin: 0; }

/* Whole-card link without nesting interactives: the anchor covers the card via
   ::after, so the card is one tab stop and one hit target. */
.bd-card__link { text-decoration: none; color: inherit; }
.bd-card__link::after { content: ""; position: absolute; inset: 0; }

/* Boxed variant — for coloured bands, where an open card has nothing to sit on. */
/* A boxed card is its OWN surface, so it sets its own text colour.
 *
 * This is the whole reason the variant exists — it sits on coloured bands.
 * Those bands set `color: white` and force headings to `inherit`, which is
 * right for text directly on blue or green and catastrophic inside a white
 * card: the homepage's three latest articles rendered as white type on a white
 * card. Every word was present and none of it was visible.
 *
 * Declared after the band rules and at equal specificity, so these win on
 * order. Anything painting a light background inside a dark band needs the
 * same treatment.
 */
.bd-card--boxed {
  background: var(--bd-white);
  color: var(--bd-text);
  border: 1px solid var(--bd-rule);
  border-radius: var(--bd-radius-lg);
  overflow: hidden;
  transition: transform var(--bd-dur) var(--bd-ease),
              box-shadow var(--bd-dur) var(--bd-ease);
}
.bd-card--boxed :is(h1, h2, h3, h4, .bd-display, .bd-title) { color: var(--bd-petrol); }
.bd-card--boxed :is(p, li, .bd-lede) { color: var(--bd-text); }
.bd-card--boxed .bd-eyebrow { color: var(--bd-text-soft); }
.bd-card--boxed .bd-card__link { color: var(--bd-petrol); }
.bd-card--boxed .bd-card__link:hover { color: var(--bd-green-bright); }
.bd-card--boxed .bd-card__media { border: 0; border-radius: 0; }
.bd-card--boxed .bd-card__body { padding: var(--bd-s6); }
.bd-card--boxed:hover { transform: translateY(-3px); box-shadow: var(--bd-shadow-lg); }


/* ---------------------------------------------------------------- video --- */

/* A poster with a play control over it. The film opens in the same <dialog>
   the hero uses — one player, one place to change the source, and the
   background loop stays muted while the dialog copy carries sound. */
.bd-video__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--bd-radius-lg);
  background: var(--bd-petrol);
  border: 1px solid var(--bd-rule);
}
.bd-video__frame img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.8s var(--bd-ease);
}
.bd-video__frame:hover img { transform: scale(1.015); }

/* A scrim under the control only, not across the whole frame — a full overlay
   dulls the poster to make room for a button that supplies its own contrast. */
.bd-video__frame::after {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 50%,
              rgba(0, 40, 56, 0.34) 0%, rgba(0, 40, 56, 0) 46%);
  pointer-events: none;
}

.bd-video__play {
  position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  display: grid; place-items: center;
  width: clamp(64px, 6vw, 88px); aspect-ratio: 1;
  border: 0; border-radius: 50%;
  background: var(--bd-blue);
  color: var(--bd-white);
  cursor: pointer;
  box-shadow: var(--bd-shadow-lg);
  transition: transform var(--bd-dur) var(--bd-ease),
              background-color var(--bd-dur) var(--bd-ease);
}
.bd-video__play svg { margin-inline-start: 4px; }   /* optical centring */
.bd-video__frame:hover .bd-video__play,
.bd-video__play:hover { transform: translate(-50%, -50%) scale(1.06); background: #0067A8; }

@media (prefers-reduced-motion: reduce) {
  .bd-video__frame:hover img { transform: none; }
  .bd-video__frame:hover .bd-video__play,
  .bd-video__play:hover { transform: translate(-50%, -50%); }
}

/* A mono runtime chip, so the control says how much time it is asking for. */
.bd-video__meta {
  position: absolute; inset-block-end: var(--bd-s4); inset-inline-start: var(--bd-s4);
  z-index: 1;
  font-family: var(--bd-font-mono); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--bd-white);
  background: rgba(0, 40, 56, 0.72);
  padding: 6px 10px; border-radius: 6px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}

/* ----------------------------------------------------------- wide media --- */

/* A panoramic slot running the full width of its container. Its aspect ratio
   is set on the frame rather than left to the image, so the space is reserved
   before the file loads and the band cannot reflow underneath a pinned
   sequence — which would fight the scroll. */
.bd-media-wide {
  position: relative;
  width: 100%;
  aspect-ratio: 8 / 3;
  overflow: hidden;
  background: color-mix(in srgb, var(--bd-petrol) 8%, transparent);
}
.bd-media-wide img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 720px) {
  /* 8:3 leaves a letterbox sliver on a phone. */
  .bd-media-wide { aspect-ratio: 3 / 2; }
}

/* ---------------------------------------------------------------- stats --- */

.bd-stat { text-align: center; }
/* Figures in the display face, tightly tracked — mono at this size reads as
   code rather than as a headline number. Mono stays on the label beneath. */
.bd-stat__value {
  font-family: var(--bd-font-numeric);
  font-feature-settings: var(--bd-numeric-feat);
  font-size: clamp(3rem, 1.9rem + 3.4vw, 5rem);
  font-weight: 800;
  line-height: 0.94;
  letter-spacing: -0.045em;
  display: block;
}
.bd-stat__label {
  font-family: var(--bd-font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: var(--bd-track-eyebrow);
  text-transform: uppercase;
  margin-top: var(--bd-s3);
  display: block;
  opacity: 0.75;
}
/* Reserve the counter's final width so the count-up cannot reflow the row.
   Tabular figures make every digit the same width, so this holds. */
.bd-stat__value[data-count] { min-width: 3ch; }

/* The numbers band. Yellow is the loudest colour in the brand and is used
   exactly once per page, here. */
.bd-band--numbers {
  background: var(--bd-yellow);
  color: var(--bd-petrol);
}
.bd-band--numbers .bd-eyebrow { color: var(--bd-petrol); opacity: 0.7; }

/* ---------------------------------------------------------- wide list ----- */

/* The seven-item service list: a single column of large rules, each row a
   link. Reads as a list, behaves as navigation. */
.bd-list-wide { list-style: none; margin: 0; padding: 0; }
.bd-list-wide__item { border-top: var(--bd-border); }
.bd-list-wide__item:last-child { border-bottom: var(--bd-border); }
.bd-band--petrol .bd-list-wide__item { border-color: var(--bd-petrol-soft); }
.bd-band--green .bd-list-wide__item { border-color: rgba(255, 255, 255, 0.28); }

.bd-list-wide__link {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--bd-s5);
  padding: clamp(var(--bd-s5), 2.4vw, var(--bd-s7)) 0;
  text-decoration: none; color: inherit;
  font-family: var(--bd-font-display);
  font-size: var(--bd-size-title);
  font-weight: var(--bd-weight-title);
  letter-spacing: var(--bd-track-title);
  transition: padding-inline-start var(--bd-dur) var(--bd-ease),
              color var(--bd-dur) var(--bd-ease);
}
.bd-list-wide__link:hover {
  padding-inline-start: var(--bd-s5);
  color: var(--bd-green-bright);
}
.bd-list-wide__arrow { flex: none; transition: transform var(--bd-dur) var(--bd-ease); }
.bd-list-wide__link:hover .bd-list-wide__arrow { transform: translateX(6px); }

/* ------------------------------------------------------------- reveal ----- */

/* Entrance animation, driven by app.js adding .is-in. Kept as a single
   utility rather than per-component so the timing is consistent and there is
   one place to disable it. */
.bd-reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--bd-dur-slow) var(--bd-ease),
              transform var(--bd-dur-slow) var(--bd-ease);
}
.bd-reveal.is-in { opacity: 1; transform: none; }

/* Staggered children. --i is set inline by the markup or by app.js. */
.bd-reveal-stagger > * {
  opacity: 0; transform: translateY(18px);
  transition: opacity var(--bd-dur-slow) var(--bd-ease),
              transform var(--bd-dur-slow) var(--bd-ease);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.bd-reveal-stagger.is-in > * { opacity: 1; transform: none; }

/* If motion is reduced, content must still be visible — never leave an
   element stuck at opacity 0 because its observer never fired. */
@media (prefers-reduced-motion: reduce) {
  .bd-reveal, .bd-reveal-stagger > * { opacity: 1; transform: none; }
}
/* Same guarantee when JavaScript never runs. */
.no-js .bd-reveal, .no-js .bd-reveal-stagger > * { opacity: 1; transform: none; }


/* One-colour logo treatments, until proper single-colour exports exist.
   brightness(0) crushes the mark to black; the sepia/saturate/hue chain then
   tints it. Both lose the blue and green in the mark, which is why a real
   export is on the outstanding list. */
.bd-logo--reversed { filter: brightness(0) invert(1); }
.bd-logo--petrol {
  filter: brightness(0) saturate(100%) invert(11%) sepia(38%)
          saturate(2000%) hue-rotate(170deg) brightness(94%) contrast(101%);
}


/* --------------------------------------------------- green band overrides --- */

/* All text on green is white, by design decision.
 *
 * Measured: white on #00AB67 is 2.99:1, which is below the 4.5:1 AA threshold
 * for body text and a hair under the 3:1 large-text threshold. Petrol on the
 * same green measures 5.16:1.
 *
 * The band cannot simply be darkened to fix it: its value has to match the
 * solid edge of porous-green.png exactly or the spread stops flowing into it,
 * and that artwork is fixed. A compliant version needs a darker green EXPORT
 * of the spread, at which point the band follows it. Noted in README.
 *
 * Everything below is at full opacity for that reason — hierarchy comes from
 * size and weight, since any fade drops the ratio further.
 */
.bd-band--green :is(.bd-eyebrow, .bd-lede, .bd-title, .bd-display, p, li, label, h2, h3) {
  color: var(--bd-white);
  opacity: 1;
}

.bd-band--green .bd-field__label { color: var(--bd-white); }
.bd-band--green .bd-field__req { color: var(--bd-white); }
.bd-band--green .bd-form__steps { color: var(--bd-white); }
.bd-band--green .bd-form__step { opacity: 1; }
.bd-band--green .bd-form__step:not(.is-active) .bd-form__step-num { background: rgba(0, 40, 56, 0.45); }
.bd-band--green .bd-form__step-num { background: var(--bd-petrol); }
.bd-band--green .bd-form__step-num span { color: var(--bd-white); }
.bd-band--green .bd-form__success { color: var(--bd-white); }


/* ---------------------------------------------------------------- leaf --- */

/* The leaf corner — 50px 25px 50px 0, the one asymmetric shape already in the
   brand. It reads as a signature only where it lands on a large surface, so it
   goes on the big framed elements and nowhere else: never on a button, a chip
   or a small card, where it just looks like a rounding mistake.

   Declared as one list rather than repeated per component, so the shape has a
   single definition to change. It must also stay LAST in this file — several
   of these components set their own radius earlier, and on equal specificity
   the later rule wins. */
.bd-leaf,
.bd-card--quarry .bd-card__media,
.bd-card--boxed.bd-card--quarry,
.bd-mega,
.bd-showcase__visual,
.bd-media-wide,
.bd-video__frame--leaf { border-radius: var(--bd-radius-quarry); }

/* The motif needs room. Below the breakpoint these elements are near
   full-width and a 50px corner eats the content, so it steps down. */
@media (max-width: 720px) {
  .bd-leaf,
  .bd-card--quarry .bd-card__media,
  .bd-card--boxed.bd-card--quarry,
  .bd-showcase__visual,
  .bd-media-wide,
  .bd-video__frame--leaf { border-radius: 28px 14px 28px 0; }
}

/* -------------------------------------------------------------- figures --- */

/* Content images, at their own aspect ratio.
 *
 * These must never be cropped. The panoramic slot on the homepage uses
 * `bd-media-wide`, which forces 8:3 and covers — correct there, because that
 * slot is a deliberate shape choice. Reusing it for migrated content pushed
 * twelve portrait headshots on the Team page into a letterbox and cut the
 * faces off.
 *
 * width:auto with both max-width and max-height lets the browser scale to fit
 * whichever constraint binds first, so a portrait is capped by height and a
 * landscape by width, and neither is ever cropped.
 */
.bd-figure { margin: var(--bd-s6) 0; }
.bd-figure img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 78vh;
  margin-inline: auto;
  border-radius: var(--bd-radius-lg);
}
.bd-figure figcaption {
  margin-top: var(--bd-s3);
  font-family: var(--bd-font-mono);
  font-size: 0.6875rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--bd-text-soft);
  text-align: center;
}

/* Prose bands on migrated pages. The homepage band rhythm (up to 7.5rem top
   and bottom) is built for full-width compositions; around a paragraph of body
   copy it reads as an empty screen with a sentence in it. */
.bd-band--content { padding-block: clamp(2.5rem, 1.6rem + 2.8vw, 4rem); }
.bd-band--content + .bd-band--content { padding-block-start: 0; }

/* ------------------------------------------------------- page container --- */

/* Aligns page content to the left edge of the logo.
 *
 * The floating header bar is `.bd-container`-wide but carries 24px of its own
 * inline padding inside its rounded shell, so the logo starts 24px in from
 * where a plain `.bd-container` begins. Content in a plain container therefore
 * sits 24px to the LEFT of the logo, and content in `--narrow` (800px, centred)
 * lands somewhere else again — nothing shared an edge down the page.
 *
 * This container matches the bar's geometry exactly: same outer width, same
 * inline padding. Reading measure is then applied to the prose itself rather
 * than by narrowing and re-centring the container, so long-form text stays
 * comfortable to read while its left edge stays locked to the logo.
 */
.bd-container--page {
  width: min(100% - (var(--bd-gutter) * 2), var(--bd-content));
  margin-inline: auto;
  /* Bar padding plus the logo: content starts where the logo ends, and is
     held off the right by the same distance so the column is symmetric. */
  padding-inline: calc(var(--bd-s5) + var(--bd-logo-w));
}

/* The container now supplies the measure, so no inner cap — an inner
   max-width would pull the text off the right inset and break the symmetry
   this exists to create. */
.bd-container--page .bd-prose { max-width: none; }

/* Below this the inset would take 294px out of the content and leave a
   column too narrow to read. It steps back to the bar's own padding, which
   still aligns to the logo's LEFT edge. */
@media (max-width: 1024px) {
  .bd-container--page { padding-inline: var(--bd-s5); }
}

/* --------------------------------------------------------------- person --- */

/* Portrait left, name and biography right. Stacked, each person occupied a
   full screen and the page read as a scroll of unrelated headshots; side by
   side, a reader can scan the names. */
.bd-person {
  display: grid;
  grid-template-columns: minmax(0, 280px) minmax(0, 1fr);
  gap: clamp(var(--bd-s5), 3vw, var(--bd-s7));
  align-items: start;
  padding-block: var(--bd-s7);
  border-top: 1px solid var(--bd-rule);
}
.bd-person:first-of-type { border-top: 0; padding-block-start: 0; }

.bd-person__media {
  overflow: hidden;
  border-radius: var(--bd-radius-lg);
  background: var(--bd-paper);
}
/* No forced aspect ratio and no cover: these are portraits at 0.81 and
   cropping them to a shared box cuts faces. */
.bd-person__media img { display: block; width: 100%; height: auto; }

.bd-person__body > * { margin-block: 0; }
.bd-person__body > * + * { margin-block-start: var(--bd-s4); }
.bd-person__name { margin: 0; }
.bd-person__role {
  font-family: var(--bd-font-mono);
  font-size: 0.71875rem; font-weight: 500;
  letter-spacing: var(--bd-track-eyebrow); text-transform: uppercase;
  color: var(--bd-green-bright);
}

.bd-person__links { display: flex; flex-wrap: wrap; gap: var(--bd-s3); }
.bd-person__links .bd-btn { --bd-btn-py: 9px; --bd-btn-px: 15px; font-size: 0.84375rem; }

@media (max-width: 720px) {
  .bd-person { grid-template-columns: 1fr; }
  .bd-person__media { max-width: 240px; }
}


/* Photo credit. Required by CC BY, so it is a component rather than something
   an editor can quietly delete along with a caption. */
.bd-credit {
  font-family: var(--bd-font-mono);
  font-size: 0.625rem; font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--bd-text-soft);
  margin-block-start: var(--bd-s3) !important;
}
.bd-credit a { color: inherit; text-underline-offset: 0.2em; }

/* Media column inside an alternating row. The prose cap is lifted here: the
   column already constrains the measure, and 68ch inside a half-width column
   would never bind anyway. */
.bd-split__media img { width: 100%; max-height: none; }
.bd-split .bd-prose { max-width: none; }
.bd-split .bd-prose > :first-child { margin-block-start: 0; }

/* --------------------------------------------------------------- slider --- */

/* A slideshow for pages that are a deck rather than an article — the
   presentation boards, where fourteen full-width figures made a page four
   screens tall that nobody would reach the end of.
 *
 * Built on scroll-snap: the track is a real horizontal scroller, so it works
 * with a trackpad swipe, a touch drag and the scrollbar before any JavaScript
 * runs. The arrows and dots drive scrollLeft rather than a transform, which is
 * what keeps those input methods in agreement with the controls.
 */
.bd-slider { position: relative; }

.bd-slider__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  gap: var(--bd-s5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  border-radius: var(--bd-radius-lg);
}
.bd-slider__track::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) {
  .bd-slider__track { scroll-behavior: auto; }
}

.bd-slider__slide {
  /* `start`, not `center`: the controls scroll to each slide's LEFT edge, and a
     centre-aligned snap point sits half a gap away from that. */
  scroll-snap-align: start;
  margin: 0;
  background: var(--bd-paper);
  border-radius: var(--bd-radius-lg);
  overflow: hidden;

  /* A RESERVED box, and the reason the carousel would not scroll at all.
     The slides held lazily-loaded images with no intrinsic size, so every
     image that arrived changed the track's layout — and `scroll-snap-type:
     mandatory` re-snaps on layout change, yanking the scroll position back to
     the first slide each time. Every scroll, programmatic or not, was being
     undone within a frame. Reserving the box removes the layout change, so
     there is nothing to re-snap. */
  aspect-ratio: 16 / 10;
  display: grid;
  place-items: center;
}

/* Boards are documents: contained inside the reserved box, never cropped. */
.bd-slider__slide img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.bd-slider__nav {
  position: absolute;
  inset-block-start: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border: 1px solid color-mix(in srgb, var(--bd-petrol) 12%, transparent);
  border-radius: 50%;
  background: var(--bd-white);
  color: var(--bd-petrol);
  cursor: pointer;
  box-shadow: var(--bd-shadow-md);
  transition: background-color var(--bd-dur-fast) ease, opacity var(--bd-dur) ease;
}
.bd-slider__nav:hover { background: var(--bd-paper); }
.bd-slider__nav--prev { inset-inline-start: calc(var(--bd-s5) * -1); }
.bd-slider__nav--next { inset-inline-end: calc(var(--bd-s5) * -1); }
.bd-slider__nav[disabled] { opacity: 0.3; cursor: default; }

@media (max-width: 900px) {
  /* Inside the frame on narrow screens, where there is no gutter to sit in. */
  .bd-slider__nav--prev { inset-inline-start: var(--bd-s3); }
  .bd-slider__nav--next { inset-inline-end: var(--bd-s3); }
}

.bd-slider__dots {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--bd-s2);
  margin-top: var(--bd-s5);
}
.bd-slider__dot {
  width: 9px; height: 9px; padding: 0;
  border: 0; border-radius: 50%;
  background: color-mix(in srgb, var(--bd-petrol) 22%, transparent);
  cursor: pointer;
  transition: background-color var(--bd-dur-fast) ease, transform var(--bd-dur-fast) ease;
}
.bd-slider__dot[aria-current="true"] {
  background: var(--bd-green-bright);
  transform: scale(1.35);
}

.bd-slider__count {
  margin-top: var(--bd-s3);
  text-align: center;
  font-family: var(--bd-font-mono);
  font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--bd-text-soft);
}

/* --------------------------------------------------- page layout + aside --- */

/* Content column with a sidebar that stays with you.
 *
 * The pattern is SCA's: the page's argument runs down the main column while a
 * narrow rail holds one figure and one call to action, pinned so it is never
 * more than a glance away. On a long page — Questions runs 6,300 words — the
 * alternative is a reader who finishes with nothing to act on.
 */
.bd-page-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: clamp(var(--bd-s6), 4vw, var(--bd-s9));
  align-items: start;
}

.bd-aside {
  position: sticky;
  /* Clears the floating header bar plus its top padding. */
  inset-block-start: calc(76px + var(--bd-s6));
  display: grid;
  gap: var(--bd-s5);
}

@media (max-width: 1024px) {
  /* Below this the rail would be narrower than its own contents. It drops
     under the article and stops being sticky — a sticky element in a single
     column just follows you down the page for no benefit. */
  .bd-page-layout { grid-template-columns: 1fr; }
  .bd-aside { position: static; max-width: 34rem; }
}

.bd-aside__stat {
  background: var(--bd-white);
  border: 1px solid var(--bd-rule);
  border-radius: var(--bd-radius-lg);
  padding: var(--bd-s6);
  text-align: center;
}
.bd-aside__stat .bd-stat__value { font-size: clamp(2rem, 1.4rem + 1.8vw, 2.75rem); }
/* The mark carries the card, so it is sized to the card rather than tucked in
   a corner: 72% of the available width, at full strength. */
.bd-aside__mark {
  width: 72%;
  max-width: 190px;
  height: auto;
  margin: 0 auto var(--bd-s5);
  display: block;
}

.bd-aside__cta {
  background: var(--bd-petrol);
  color: var(--bd-text-on-dark);
  border-radius: var(--bd-radius-lg);
  padding: var(--bd-s6);
  text-align: center;
}
.bd-aside__cta .bd-title { color: var(--bd-white); margin-bottom: var(--bd-s4); }
.bd-aside__cta p { color: var(--bd-text-on-dark-soft); font-size: var(--bd-size-small);
                   margin: 0 0 var(--bd-s5); }
.bd-aside__cta .bd-btn { width: 100%; }

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

/* Built on <details>, so it opens without JavaScript, is searchable by the
   browser's own find-in-page, and needs no ARIA of its own. */
.bd-accordion { display: grid; }
.bd-accordion__item {
  border-top: 1px solid var(--bd-rule);
}
.bd-accordion__item:last-child { border-bottom: 1px solid var(--bd-rule); }

.bd-accordion__item summary {
  display: flex; align-items: flex-start; gap: var(--bd-s4);
  padding: var(--bd-s5) 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--bd-font-display);
  font-size: var(--bd-size-sub);
  font-weight: 700;
  letter-spacing: var(--bd-track-title);
  line-height: 1.35;
  transition: color var(--bd-dur-fast) ease;
}
.bd-accordion__item summary::-webkit-details-marker { display: none; }
.bd-accordion__item summary:hover { color: var(--bd-green-bright); }

/* The marker is drawn rather than a glyph, so it can rotate. */
.bd-accordion__icon {
  flex: none; margin-inline-start: auto;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  transition: transform var(--bd-dur) var(--bd-ease);
  color: var(--bd-green-bright);
}
.bd-accordion__item[open] .bd-accordion__icon { transform: rotate(45deg); }

.bd-accordion__body { padding-block: 0 var(--bd-s6); }
.bd-accordion__body > * { margin-block: 0 var(--bd-s4); }
.bd-accordion__body > :last-child { margin-block-end: 0; }

/* Article column. Spacing lives here rather than on page-wide bands, so the
   rhythm holds inside a two-thirds column. */
.bd-article { display: grid; gap: clamp(var(--bd-s6), 3vw, var(--bd-s8)); }
.bd-article > .bd-prose { max-width: var(--bd-measure); }


/* With a rail beside it, the full logo-edge inset on BOTH sides left the
   article at 530px — too narrow for body copy. The left edge still meets the
   logo; the right inset is dropped because the rail already occupies that
   side, which returns roughly 150px to the column. */
.bd-container--page:has(.bd-page-layout) { padding-inline-end: var(--bd-s5); }
@media (max-width: 1024px) {
  .bd-container--page:has(.bd-page-layout) { padding-inline: var(--bd-s5); }
}


/* A visibly provisional image slot: dashed frame and a caption, so nobody
   mistakes a stand-in for chosen art direction. */
.bd-figure--placeholder img { outline: 2px dashed color-mix(in srgb, var(--bd-petrol) 22%, transparent);
                              outline-offset: -8px; }
.bd-figure--placeholder figcaption { color: var(--bd-green-bright); }

/* Inside the two-column layout a split row would divide the article again —
   photo beside text beside the rail is three columns of about 250px each, and
   the Impact page's Q&A ended up in one of them. Stack instead, with the image
   BELOW its text in the same column. */
.bd-page-layout .bd-split { grid-template-columns: 1fr; gap: var(--bd-s5); }
.bd-page-layout .bd-split__media { order: 2; }
.bd-page-layout .bd-split .bd-prose { order: 1; }

/* --------------------------------------------------------- sidebar reel --- */

.bd-aside__reel {
  background: var(--bd-white);
  border: 1px solid var(--bd-rule);
  border-radius: var(--bd-radius-lg);
  padding: var(--bd-s5);
}
.bd-reel { list-style: none; margin: 0 0 var(--bd-s4); padding: 0; display: grid; }
.bd-reel__item + .bd-reel__item { border-top: 1px solid var(--bd-rule); }

.bd-reel__link {
  display: grid;
  grid-template-columns: 68px minmax(0, 1fr);
  gap: var(--bd-s3);
  align-items: center;
  padding: var(--bd-s3) 0;
  text-decoration: none;
  color: inherit;
}
.bd-reel__thumb {
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: 6px;
  background: var(--bd-paper);
}
/* Thumbnails are the one place cropping is right: a uniform strip of ragged
   aspect ratios reads as broken, and at 68px no detail survives anyway. */
.bd-reel__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bd-reel__blank { display: block; width: 100%; height: 100%; }

.bd-reel__cat {
  display: block;
  font-family: var(--bd-font-mono);
  font-size: 0.5625rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--bd-green-bright);
  margin-bottom: 2px;
}
.bd-reel__title {
  display: block;
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.01em;
  /* Two lines maximum: a four-line headline in a 200px column pushes the CTA
     below the fold of a sticky rail. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.bd-reel__link:hover .bd-reel__title { color: var(--bd-green-bright); }

/* The rail's figure reads as a sentence: lead-in, number, unit. */
.bd-aside__lead, .bd-aside__stat .bd-stat__label {
  display: block;
  font-family: var(--bd-font-mono);
  font-size: 0.6875rem; font-weight: 500;
  letter-spacing: var(--bd-track-eyebrow); text-transform: uppercase;
  color: var(--bd-text-soft);
}
.bd-aside__lead { margin-bottom: var(--bd-s2); }
.bd-aside__stat .bd-stat__label { margin-top: var(--bd-s2); opacity: 1; }

/* ----------------------------------------------------------------- form --- */

.bd-formcard {
  background: var(--bd-white);
  border: 1px solid var(--bd-rule);
  border-radius: var(--bd-radius-lg);
  padding: clamp(var(--bd-s6), 3vw, var(--bd-s8));
}
.bd-formcard--dark {
  background: var(--bd-petrol);
  color: var(--bd-text-on-dark);
  border-color: var(--bd-petrol-soft);
}
.bd-formcard--dark .bd-field__label { color: var(--bd-white); }
.bd-formcard--dark .bd-lede { color: var(--bd-text-on-dark-soft); }

/* Inputs carry their state on the border, which is the only edge a filled
   field still shows. A background change would fight the card behind it. */
.bd-field input, .bd-field select, .bd-field textarea {
  border: 1px solid var(--bd-rule);
  border-radius: var(--bd-radius);
  transition: border-color var(--bd-dur-fast) ease, box-shadow var(--bd-dur-fast) ease;
}
.bd-field input:focus, .bd-field select:focus, .bd-field textarea:focus {
  outline: none;
  border-color: var(--bd-green-bright);
  box-shadow: 0 0 0 4px var(--bd-ring);
}
.bd-field textarea { resize: vertical; min-height: 7rem; }

.bd-field__hint {
  font-size: 0.8125rem;
  color: var(--bd-text-soft);
  margin: 0;
}
.bd-formcard--dark .bd-field__hint { color: var(--bd-text-on-dark-soft); }

/* Consent is a real control, not fine print: a large hit area and the label
   wrapping the box so the whole line is clickable. */
.bd-consent {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: var(--bd-s3);
  align-items: start;
  cursor: pointer;
  font-size: 0.875rem;
  line-height: 1.5;
  margin-block: var(--bd-s5);
}
.bd-consent input {
  /* 24px is the WCAG 2.2 minimum. The label toggles the box too, so the real
     target is wider than this — but consent is the one field a visitor must
     not fumble, so the box itself clears the bar rather than relying on it. */
  width: 24px; height: 24px; margin: 0;
  accent-color: var(--bd-green-bright);
}

.bd-form__status {
  margin-top: var(--bd-s5);
  padding: var(--bd-s4) var(--bd-s5);
  border-radius: var(--bd-radius);
  font-size: var(--bd-size-small);
  display: none;
}
.bd-form__status.is-error {
  display: block;
  background: color-mix(in srgb, #B3261E 10%, transparent);
  color: #B3261E;
}
.bd-formcard--dark .bd-form__status.is-error { color: #FFB4AB; }
.bd-form__status.is-ok {
  display: block;
  background: color-mix(in srgb, var(--bd-green-bright) 12%, transparent);
  color: var(--bd-green);
}

/* -------------------------------------------------------------- portrait --- */

/* A photo frame that adapts to whatever is uploaded.
 *
 * No fixed aspect ratio: the image sets the box height and the overlays are
 * absolutely positioned inside it, so a portrait, a square and a landscape all
 * get a correctly-sized frame with no cropping. That is the whole point —
 * forcing a ratio here is what cut the heads off the team photographs before.
 *
 * Every treatment is a custom property so an Elementor control can set it
 * per-image without new CSS.
 */
.bd-portrait {
  --p-gray: 0;
  --p-bright: 1;
  --p-contrast: 1;
  --p-saturate: 1;
  --p-pattern: 0.35;
  --p-gradient: 0.55;
  --p-grad-from: transparent;
  --p-grad-to: var(--bd-petrol);

  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--bd-radius-lg);
  background: var(--bd-paper);
  isolation: isolate;
}

.bd-portrait img {
  display: block;
  width: 100%;
  height: auto;
  filter:
    grayscale(var(--p-gray))
    brightness(var(--p-bright))
    contrast(var(--p-contrast))
    saturate(var(--p-saturate));
  transition: filter var(--bd-dur-slow) var(--bd-ease);
}

/* Sharpening is not a CSS filter, so it comes from an SVG convolution kernel
   referenced by url(). The chain order matters: sharpen first, then the colour
   adjustments, or the kernel amplifies whatever brightness already did. */
.bd-portrait--sharp img {
  filter:
    url(#bd-sharpen)
    grayscale(var(--p-gray))
    brightness(var(--p-bright))
    contrast(var(--p-contrast))
    saturate(var(--p-saturate));
}

.bd-portrait__gradient {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg, var(--p-grad-from) 38%, var(--p-grad-to) 100%);
  opacity: var(--p-gradient);
}

/* The porous spread, anchored to the bottom edge and coloured by the frame —
   the same device the page headers use, at portrait scale. `soft-light` keeps
   the photograph's detail visible through it; `normal` would paste a flat
   shape over a face. */
.bd-portrait__pattern {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 2;
  pointer-events: none;
  aspect-ratio: 2560 / 604;
  background-image: url("../img/porous-white.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  mix-blend-mode: soft-light;
  opacity: var(--p-pattern);
}
.bd-portrait--pattern-green .bd-portrait__pattern { background-image: url("../img/porous-green.png"); }
.bd-portrait--pattern-blue  .bd-portrait__pattern { background-image: url("../img/porous-blue.png"); }
.bd-portrait--pattern-yellow .bd-portrait__pattern { background-image: url("../img/porous-yellow.png"); }

/* Hover restores colour where a portrait is set to greyscale — a common
   directorial choice for team pages, and one an editor gets for free. */
.bd-portrait--reveal:hover img { --p-gray: 0; --p-saturate: 1.02; }

@media (prefers-reduced-motion: reduce) {
  .bd-portrait img { transition: none; }
}


/* ------------------------------------------------- touch target sizes ---- */

/* WCAG 2.2 SC 2.5.8 asks for 24x24 CSS px; 44 is the size a thumb actually
 * wants, and what Apple and Google both publish. These raise the components
 * that fall short of it, and only where the pointer is coarse — on a mouse
 * the tighter proportions are correct and worth keeping.
 *
 * Links sitting inline within a sentence are exempt under 2.5.8 and are left
 * alone: growing them would break the line box they live in. The licence
 * credits are the case in point.
 */
@media (pointer: coarse) {
  /* Card links read as one line of type but are the card's whole affordance,
     so they get a real box rather than the 23px the text alone occupies. */
  .bd-card__link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* The buttons land at 43px from padding alone — one pixel short. */
  .bd-btn {
    min-height: 44px;
  }

  /* Accordion headers are the control for the panel below them. The trigger
     is the <summary>, not a class — questions run long enough that these
     already clear 44px, so this is a floor for a short one, not a fix. */
  .bd-accordion summary {
    min-height: 44px;
  }

  /* Slider arrows and dots. Dots stay visually small; the box around each
     grows so neighbouring dots do not become a lottery. */
  .bd-slider__dot {
    min-width: 44px;
    min-height: 44px;
  }
  /* The arrows are .bd-slider__nav — there is no .bd-slider__arrow, and a
     rule aimed at one is silently dead rather than wrong-looking. */
  .bd-slider__nav {
    min-width: 44px;
    min-height: 44px;
  }
}

/* Footer navigation.
 *
 * These render as 20px lines of type — under the 24px WCAG 2.2 minimum, and
 * they are a navigation list rather than links inside a sentence, so the
 * inline exemption does not cover them. They appear on every page, which
 * makes this the most widespread target problem on the site.
 *
 * Spacing the list rather than padding each link keeps the rhythm of the
 * column intact while giving every row a full-height box.
 */
@media (pointer: coarse) {
  .bd-footer__list a,
  .bd-footer__bottom a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .bd-footer__list li + li {
    margin-block-start: 0;
  }
}


/* ------------------------------------------------ card image placeholder ---
 *
 * A card with no picture collapses to the height of its text, and in a grid
 * beside cards that have one the row goes ragged — which reads as a bug
 * rather than as a missing photograph. This holds the same shape a thumbnail
 * would, in the brand's own pattern, so the absence looks deliberate.
 */
.bd-card__placeholder {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 10;
  background: color-mix(in srgb, var(--bd-petrol) 6%, var(--bd-paper));
  overflow: hidden;
}
.bd-card__placeholder img {
  width: 118%;
  height: auto;
  opacity: 0.5;
  /* The spread is drawn white-on-transparent, so on a pale ground it needs
     inverting to read at all. */
  filter: invert(1) brightness(0.72);
}


/* ---------------------------------------------------- card summary text ---
 *
 * Clamped to four lines.
 *
 * Summaries are written by people and imported from elsewhere, so their
 * lengths will never agree. Left alone, one card carries two lines and its
 * neighbour six, and the row reads as a layout fault rather than as articles
 * of differing length. Clamping settles the block height without truncating
 * anything an editor can see in the admin.
 *
 * -webkit-line-clamp is unprefixed nowhere yet, but is supported in every
 * browser this site targets; where it is not, the text simply runs on.
 */
.bd-card__body > p:not(.bd-eyebrow) {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  overflow: hidden;
}


/* ============================================================ blog lead ====
 *
 * The featured article, across the full measure.
 *
 * Wide, not tall. At full width a portrait card strands the headline in a
 * narrow column beside a large picture; here the photograph takes the larger
 * share and the words sit beside it at a readable measure.
 */
.bd-feature {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: var(--bd-s7);
  align-items: center;
  margin-block-end: var(--bd-s8);
}

.bd-feature__media {
  display: block;
  overflow: hidden;
  border-radius: var(--bd-radius-quarry);
  background: var(--bd-paper);
}
.bd-feature__media img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform var(--bd-dur-slow) var(--bd-ease);
}
.bd-feature:hover .bd-feature__media img { transform: scale(1.02); }

.bd-feature__body > * + * { margin-block-start: var(--bd-s4); }

/* One step up from a card title, one step down from a page heading: this is
   the most important thing on the page, but it is not the page's name. */
.bd-feature__title {
  font-size: clamp(1.75rem, 1.15rem + 1.9vw, 2.5rem);
  line-height: 1.1;
  margin: 0;
}
.bd-feature__title a {
  color: inherit;
  text-decoration: none;
}
.bd-feature__title a:hover { color: var(--bd-green-bright); }

/* Only shown when an editor has actually pinned the article, so it means
   something. The newest article is featured by default and says nothing. */
.bd-feature__flag {
  display: inline-block;
  margin-inline-end: var(--bd-s3);
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--bd-green-bright);
  color: var(--bd-white);
  letter-spacing: 0.08em;
}

@media (max-width: 860px) {
  .bd-feature { grid-template-columns: 1fr; gap: var(--bd-s5); }
}


/* ========================================================== blog topics ====
 *
 * Chips, not a <select>. Two or three topics are faster to scan and one tap
 * away; a dropdown hides the choices and costs an extra interaction.
 * Rendered as a nav because that is what it is — links to archives.
 */
.bd-topics {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bd-s3) var(--bd-s4);
  padding-block-end: var(--bd-s6);
  margin-block-end: var(--bd-s7);
  border-bottom: 1px solid var(--bd-rule);
}
.bd-topics__label { margin: 0; color: var(--bd-text-soft); }

.bd-topics__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bd-s3);
  list-style: none;
  margin: 0;
  padding: 0;
}

.bd-topics__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--bd-s2);
  min-height: 40px;
  padding: 0 var(--bd-s4);
  border: 1px solid color-mix(in srgb, var(--bd-petrol) 14%, transparent);
  border-radius: 999px;
  font-family: var(--bd-font-ui);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--bd-petrol);
  text-decoration: none;
  transition: background-color var(--bd-dur-fast) ease,
              border-color var(--bd-dur-fast) ease,
              color var(--bd-dur-fast) ease;
}
.bd-topics__chip:hover {
  border-color: var(--bd-green-bright);
  color: var(--bd-green-bright);
}
.bd-topics__chip.is-current {
  background: var(--bd-petrol);
  border-color: var(--bd-petrol);
  color: var(--bd-white);
}

/* The count is information, not emphasis. */
.bd-topics__count {
  font-family: var(--bd-font-mono);
  font-size: 0.6875rem;
  opacity: 0.65;
}
.bd-topics__chip.is-current .bd-topics__count { opacity: 0.8; }

@media (pointer: coarse) {
  .bd-topics__chip { min-height: 44px; }
}

/* The lead sits directly above the filter, so the band between them closes up. */
.bd-band--flush-bottom { padding-block-end: 0; }
