/* ============================================================================
   Bedrock Energy Corp — homepage sections
   ----------------------------------------------------------------------------
   These are the homepage-only compositions: header, hero, the two pinned
   scroll sequences, and the two-stage contact form. They live apart from
   components.css because the Elementor pages do NOT use them — an editor
   should never be able to drop a pinned scroll sequence onto a page and then
   need someone to debug the sticky context.

   Everything an Elementor page needs is in components.css. Everything here is
   the homepage's own.

   Requires tokens.css and components.css.
   ========================================================================== */

/* --------------------------------------------------------------- header --- */

/* Suspended, not attached.
 *
 * The bar floats inset from all three edges rather than spanning the viewport,
 * so the film runs underneath it and the page reads as one continuous surface
 * with a control layer above. A full-bleed bar with a bottom border cuts the
 * hero off and announces itself as chrome.
 *
 * The outer element is only a positioning frame — transparent, no background.
 * Everything visible is on __inner, which is what lets the bar be narrower
 * than the viewport.
 */
.bd-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--bd-z-header);
  padding: var(--bd-s4) var(--bd-gutter);
  background: none;
  border: 0;
  transition: transform var(--bd-dur) var(--bd-ease),
              padding var(--bd-dur) var(--bd-ease);
  pointer-events: none;   /* the gutter beside the bar stays clickable */
}
.bd-header > * { pointer-events: auto; }

/* Three tracks, not a flex row. 1fr | auto | 1fr centres the nav against the
   BAR rather than against whatever is left over after the logo and the CTA —
   so the menu stays optically centred however wide those two grow. */
.bd-header__inner {
  position: relative;          /* containing block for the mega panels */
  width: min(100%, var(--bd-content));
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--bd-s4);
  min-height: 76px;
  padding-inline: var(--bd-s5);
  border-radius: 16px;

  /* Opaque #FFFFFF, not translucent.
     The glass treatment let 10% of whatever sat behind it through, so over the
     dark film the bar read as a grey tint rather than as white — and it never
     matched the white bands further down the page. Solid white is also cheaper:
     no backdrop-filter means no per-frame blur of everything underneath a
     fixed element, which is one of the more expensive things a page can ask
     for while scrolling. */
  background: var(--bd-white);
  border: 1px solid color-mix(in srgb, var(--bd-petrol) 8%, transparent);
  box-shadow: var(--bd-shadow-md);

  transition: background-color var(--bd-dur) var(--bd-ease),
              box-shadow var(--bd-dur) var(--bd-ease),
              min-height var(--bd-dur) var(--bd-ease);
}


.bd-header.is-stuck { padding-block: var(--bd-s3); }
.bd-header.is-stuck .bd-header__inner {
  min-height: 66px;
  box-shadow: var(--bd-shadow-lg);
}
.bd-header.is-hidden { transform: translateY(calc(-100% - var(--bd-s4))); }

.bd-header__logo { justify-self: start; display: flex; align-items: center; }
.bd-header__logo img {
  height: 48px; width: auto;
  transition: height var(--bd-dur) var(--bd-ease);
}
.bd-header.is-stuck .bd-header__logo img { height: 40px; }

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

.bd-nav { justify-self: center; }
.bd-nav__list {
  display: flex; align-items: center;
  gap: 2px;                    /* tight: the padding supplies the rhythm */
  list-style: none; margin: 0; padding: 0;
}

/* ONE type treatment across the whole menu. Top-level links previously ran
   700 at 14.5px while the dropdown items ran 500 at 15px, which read as two
   different menus stacked on each other. Everything now uses the lighter,
   slightly larger setting — it is calmer, and at this size weight was doing
   nothing that colour does not do better. */
.bd-nav__link,
.bd-mega__title,
.bd-mega__link {
  font-family: var(--bd-font-ui);
  font-size: 0.9375rem;        /* 15px */
  font-weight: 500;
  letter-spacing: -0.008em;
  line-height: 1.3;
}

.bd-nav__link {
  display: block;
  padding: var(--bd-s2) var(--bd-s3);
  color: var(--bd-petrol);
  text-decoration: none;
  border-radius: 8px;
  white-space: nowrap;
  transition: color var(--bd-dur-fast) ease, background-color var(--bd-dur-fast) ease;
}
.bd-nav__link:hover,
.bd-nav__item.is-open > .bd-nav__link { color: var(--bd-green-bright); }
.bd-nav__link.is-current { color: var(--bd-green-bright); }

.bd-nav__item { position: static; }   /* the mega spans the bar, not the item */
.bd-nav__toggle {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; cursor: pointer;
}
.bd-nav__chevron { opacity: 0.5; transition: transform var(--bd-dur) var(--bd-ease); }
.bd-nav__item.is-open .bd-nav__chevron { transform: rotate(180deg); opacity: 1; }

.bd-header__cta { justify-self: end; }

/* --- mega menu ---------------------------------------------------------- */

/* Full bar width rather than a column hanging off one item. The Community
   menu carries six entries with dates in their titles; as a narrow dropdown
   every one of them wrapped. Given the width, each entry can also carry a
   line of description, which is the actual argument for a mega menu — it
   turns a list of labels into something you can choose from. */
.bd-mega {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100% + var(--bd-s3));
  background: var(--bd-white);
  border: 1px solid color-mix(in srgb, var(--bd-petrol) 8%, transparent);
  box-shadow: var(--bd-shadow-lg);
  padding: var(--bd-s5);
  margin: 0; list-style: none;
  /* Shape comes from the leaf rule in components.css — declaring a radius here
     would win on load order and silently drop the motif. */
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--bd-s2);
  opacity: 0; visibility: hidden;
  transform: translateY(-8px);
  transition: opacity var(--bd-dur) var(--bd-ease),
              transform var(--bd-dur) var(--bd-ease),
              visibility var(--bd-dur);
}
.bd-nav__item.is-open .bd-mega,
.bd-nav__item:hover .bd-mega { opacity: 1; visibility: visible; transform: none; }

.bd-mega__link {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--bd-s3);
  align-items: start;
  padding: var(--bd-s4);
  border-radius: 10px;
  text-decoration: none;
  color: var(--bd-petrol);
  transition: background-color var(--bd-dur-fast) ease;
}
.bd-mega__link:hover { background: var(--bd-paper); }

.bd-mega__num {
  font-family: var(--bd-font-mono);
  font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--bd-green-bright);
  padding-top: 3px;
}
.bd-mega__title { display: block; font-weight: 700; }
.bd-mega__desc {
  grid-column: 2;
  display: block;
  margin-top: 3px;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--bd-text-soft);
}
.bd-mega__link:hover .bd-mega__title { color: var(--bd-green-bright); }

.bd-burger { display: none; }

@media (max-width: 1080px) {
  /* Flex, not grid, below the breakpoint.
     The nav goes position:absolute here, so the only children left in flow are
     the logo, the switcher and the burger. As a two-column grid the switcher
     had nowhere to sit and dropped onto a second row, pushing the bar to twice
     its height. A row with the logo pushed left orders them properly. */
  .bd-header__inner {
    display: flex;
    align-items: center;
    min-height: 68px;
  }
  .bd-header__logo { margin-inline-end: auto; }
  .bd-header__end { order: 2; }
  .bd-burger { order: 3; }
  .bd-header__logo img, .bd-header.is-stuck .bd-header__logo img { height: 40px; }
  .bd-burger {
    display: inline-flex; align-items: center; justify-content: center;
    justify-self: end;
    /* 44px, not 42 — this is the one control every mobile visitor must hit. */
    width: 44px; height: 44px;
    background: none; cursor: pointer;
    border: 1px solid color-mix(in srgb, var(--bd-petrol) 14%, transparent);
    border-radius: 8px;
  }
  /* The logo is a link home. The mark stays 40px; the tappable box does not. */
  .bd-header__logo { min-height: 44px; }
  .bd-nav {
    position: absolute; inset-block-start: calc(100% + var(--bd-s2));
    inset-inline: 0;
    justify-self: stretch;
    background: var(--bd-white);
    border: 1px solid color-mix(in srgb, var(--bd-petrol) 8%, transparent);
    border-radius: 16px;
    box-shadow: var(--bd-shadow-lg);
    padding: var(--bd-s3);
    max-height: calc(100dvh - 150px); overflow-y: auto;
    display: none;
  }
  .bd-nav.is-open { display: block; }
  .bd-nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .bd-nav__link, .bd-nav__toggle { width: 100%; padding-block: var(--bd-s4); }

  /* The mega collapses to a plain nested list — a three-column panel inside a
     phone-width drawer is unreadable. */
  .bd-mega {
    position: static; opacity: 1; visibility: visible; transform: none;
    display: none; grid-template-columns: 1fr;
    box-shadow: none; border: 0; border-radius: 0;
    padding: 0 0 var(--bd-s3) var(--bd-s4);
  }
  .bd-nav__item.is-open .bd-mega { display: grid; }
  .bd-nav__item:hover .bd-mega { display: none; }
  .bd-nav__item.is-open:hover .bd-mega { display: grid; }
  .bd-mega__desc { display: none; }
  .bd-header__cta { display: none; }
}

/* ----------------------------------------------------------------- hero --- */

/* The hero is the film, and nothing else.
 *
 * No scrim, no headline, no lede — one centred Watch Video button over
 * full-bleed video, exactly as the live site does it. The headline that used
 * to sit here has moved to the band below, which is also where the live site
 * puts it.
 *
 * The reason this is right and the overlay version was not: the film is the
 * strongest asset the brand owns, and a petrol scrim at 94% opacity was
 * throwing most of it away to make room for type that reads perfectly well one
 * scroll further down.
 */
.bd-hero {
  position: relative;
  height: 100svh;
  min-height: 560px;
  display: grid;
  place-items: center;
  background: var(--bd-petrol);   /* only ever seen before the video paints */
  overflow: hidden;
  isolation: isolate;
}
.bd-hero__media { position: absolute; inset: 0; z-index: 0; }
.bd-hero__media img,
.bd-hero__media video { width: 100%; height: 100%; object-fit: cover; }

/* A very light wash — enough to guarantee the button's contrast over an
   unknown frame, far short of hiding the film. */
.bd-hero__scrim {
  position: absolute; inset: 0; z-index: 1;
  background: rgba(0, 40, 56, 0.18);
}

.bd-hero__content {
  position: relative; z-index: 3;
  display: grid; place-items: center;
  text-align: center;
  padding-inline: var(--bd-gutter);
}
/* The welcome sits directly over the button, both centred on the film. The
   scrim beneath is only 18%, so the text carries its own shadow rather than
   darkening the whole hero to make room for it. */
.bd-hero__welcome-kicker {
  color: var(--bd-white);
  opacity: 0.9;
  margin-bottom: var(--bd-s4);
  text-shadow: 0 1px 12px rgba(0, 40, 56, 0.55);
}
.bd-hero__welcome {
  color: var(--bd-white);
  max-width: 20ch;
  margin-bottom: var(--bd-s5);
  text-shadow: 0 2px 24px rgba(0, 40, 56, 0.5);
}

/* The invitation sits between the claim and the control, so the button reads
   as the answer to a sentence rather than as a bare affordance. */
.bd-hero__invite {
  color: rgba(255, 255, 255, 0.92);
  font-size: var(--bd-size-sub);
  line-height: 1.5;
  max-width: 40ch;
  margin: 0 0 var(--bd-s6);
  text-shadow: 0 1px 14px rgba(0, 40, 56, 0.55);
}

/* The porous crest cutting into the hero, as on the live site — but as
   geometry rather than a raster, and coloured as the band it introduces.
   The height is declared here rather than read back from the SVG so the
   crest occupies its space from first paint. Keep in step with the crest
   height in tools/porous.py. */

.bd-hero__crest {
  /* ABOVE the scrim, not below it.
     The scrim is an 18% petrol wash over the whole hero. With the crest
     underneath it, that wash tinted the white pattern to roughly #D2D6D8 — so
     the crest read grey and the join into the white band below stopped being
     fluid. The scrim exists to hold the button's contrast against the film; it
     has no business dimming the band arriving. */
  position: absolute; inset-inline: 0; inset-block-end: 0; z-index: 2;
}


/* ------------------------------------------------------------ showcase ---- */

/* Scroll-driven showcase. A sticky visual column with a scrolling text column
   beside it. Each text block activates the matching visual.
   `position: sticky` needs an ancestor that is neither overflow-hidden nor a
   new containing block, which is why nothing here sets transform or filter. */
.bd-showcase__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(var(--bd-s6), 5vw, var(--bd-s10));
  align-items: start;
}
.bd-showcase__visual {
  position: sticky; inset-block-start: calc(96px + var(--bd-s5));
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--bd-petrol);
}
.bd-showcase__frame {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity var(--bd-dur-slow) var(--bd-ease);
}
.bd-showcase__frame.is-active { opacity: 1; }
.bd-showcase__frame img { width: 100%; height: 100%; object-fit: cover; }

.bd-showcase__steps { display: flex; flex-direction: column; }
.bd-showcase__step {
  min-height: 82vh;
  display: flex; flex-direction: column; justify-content: center;
  opacity: 0.34;
  transition: opacity var(--bd-dur-slow) var(--bd-ease);
}
.bd-showcase__step.is-active { opacity: 1; }
.bd-showcase__index {
  font-family: var(--bd-font-mono);
  font-size: 0.71875rem;
  font-weight: 500;
  letter-spacing: var(--bd-track-eyebrow);
  color: var(--bd-green-bright);
  margin-bottom: var(--bd-s4);
}

@media (max-width: 860px) {
  /* Sticky stacking does not survive a single column — the visual would pin
     over its own text. Fall back to a plain sequence of blocks. */
  .bd-showcase__layout { grid-template-columns: 1fr; }
  .bd-showcase__visual { position: static; aspect-ratio: 16 / 10; margin-bottom: var(--bd-s6); }
  .bd-showcase__frame { position: absolute; }
  .bd-showcase__step { min-height: 0; opacity: 1; padding-block: var(--bd-s6); }
}

/* --------------------------------------------------------------- proof ---- */

/* The pinned proof sequence — the structural centrepiece, and the longest
   section on the page. A tall track provides the scroll distance; the stage
   pins inside it and its phases cross-fade as scroll progresses.

   The track's height IS the scroll budget: 100vh of pin plus 100vh per phase
   after the first. Getting this wrong is what makes pinned sections feel
   either rushed or endless. */
/* Light, not petrol. Every band on the live site is transparent over white;
   a full-height dark sequence here was the single biggest reason the page did
   not read as Bedrock. The pinning does the work — it does not need contrast
   inversion on top. */
/* No background of its own: the band modifier on the element supplies it, so
   the pinned sequence can sit on any colourway without a second rule here. */
.bd-proof {
  --bd-proof-phases: 4;
  position: relative;
}
.bd-proof__track {
  position: relative;
  height: calc(100svh * var(--bd-proof-phases));
}
.bd-proof__stage {
  position: sticky; inset-block-start: 0;
  height: 100svh;
  display: grid; align-items: center;
  overflow: hidden;
}
.bd-proof__phase {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--bd-dur-slow) var(--bd-ease),
              transform var(--bd-dur-slow) var(--bd-ease);
  pointer-events: none;
}
.bd-proof__phase.is-active { opacity: 1; transform: none; pointer-events: auto; }

.bd-proof__progress {
  position: absolute; inset-block-end: var(--bd-s7); inset-inline: 0;
  display: flex; justify-content: center; gap: var(--bd-s3);
}
.bd-proof__dot {
  width: 40px; height: 3px; border: 0; padding: 0;
  background: rgba(0, 40, 56, 0.18);
  cursor: pointer;
  transition: background-color var(--bd-dur) var(--bd-ease);
}
.bd-proof__dot.is-active { background: var(--bd-green-bright); }

/* Below the breakpoint the pin is dropped entirely rather than shortened.
   A pinned sequence on a phone competes with the browser's own URL-bar
   collapse and with momentum scrolling, and loses both. */
@media (max-width: 860px), (prefers-reduced-motion: reduce) {
  .bd-proof__track { height: auto; }
  .bd-proof__stage { position: static; height: auto; display: block; }
  .bd-proof__phase {
    opacity: 1; transform: none; pointer-events: auto;
    padding-block: var(--bd-band-y);
  }
  .bd-proof__progress { display: none; }
}

/* ------------------------------------------------------------- contact ---- */

/* Two-stage form. Stage one captures contact details only; stage two asks for
   the site-specific detail. Splitting it this way is the single highest-value
   pattern being borrowed — a short first ask converts far better than one
   long form, and stage two is answered by people who have already committed. */
.bd-form__stage { display: none; }
.bd-form__stage.is-active { display: block; }

.bd-form__steps {
  display: flex; gap: var(--bd-s3); align-items: center;
  margin-bottom: var(--bd-s6);
  font-family: var(--bd-font-mono); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: var(--bd-track-eyebrow); text-transform: uppercase;
}
.bd-form__step { display: flex; align-items: center; gap: var(--bd-s2); opacity: 0.45; }
.bd-form__step.is-active { opacity: 1; }
.bd-form__step-num {
  display: grid; place-items: center;
  width: 26px; height: 26px; border-radius: 50%;
  background: currentColor;
}
.bd-form__step-num span { color: var(--bd-white); }
.bd-form__step.is-active .bd-form__step-num { background: var(--bd-green-bright); }

.bd-field { display: flex; flex-direction: column; gap: var(--bd-s2); margin-bottom: var(--bd-s5); }
.bd-field__label {
  font-family: var(--bd-font-ui); font-size: var(--bd-size-small);
  font-weight: var(--bd-weight-strong);
}
.bd-field__req { color: var(--bd-green-bright); }
.bd-field input, .bd-field select, .bd-field textarea {
  font: inherit; font-size: var(--bd-size-body);
  padding: var(--bd-s4);
  border: var(--bd-border); border-radius: var(--bd-radius);
  background: var(--bd-white); color: var(--bd-text);
  width: 100%;
}
.bd-field input:focus, .bd-field select:focus, .bd-field textarea:focus {
  border-color: var(--bd-green-bright);
}
.bd-field__error {
  font-size: var(--bd-size-small); color: #B3261E; min-height: 1.2em;
}
.bd-field.has-error input,
.bd-field.has-error select { border-color: #B3261E; }

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

.bd-form__actions { display: flex; gap: var(--bd-s4); flex-wrap: wrap; margin-top: var(--bd-s6); }

.bd-form__success { display: none; }
.bd-form__success.is-active { display: block; }

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

/* Green, continuing the contact band above it. The two share a value, so the
   closing green spread flows through the CTA and the footer as one block with
   no boundary — which is the same bracket logic the coloured bands use. *//* --------------------------------------------------------------- footer ---
 *
 * SaferSmart Zones' footer, in Bedrock's green.
 *
 * The proportions are SSZ's: a brand column at 1fr beside four link columns at
 * 2fr, mono uppercase headings, 14px links at partial opacity that come up to
 * full white on hover. What changes is the ground — green rather than navy —
 * and the pages.
 */
.bd-footer {
  background: var(--bd-green);
  color: rgba(255, 255, 255, 0.78);
  padding-block: clamp(48px, 5vw, 76px) 0;
}

.bd-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: clamp(32px, 5vw, 72px);
  padding-bottom: 48px;
}

.bd-footer__home { display: inline-block; text-decoration: none; }
.bd-footer__home img { display: block; width: auto; height: 62px; }

/* The fallback for an install whose theme has no reversed logo: the name set
   in type. The colour mark on dark is wrong, and a wordmark is honest where a
   recoloured logo is not. bedrock-logo-white.png now ships with the theme, so
   this is only reached if that file is deleted.

   Scoped to the span. There is a .bd-footer__mark rule further down that sizes
   the reversed IMG in the static build, and without the element selector these
   two fight over the same class. */
span.bd-footer__mark {
  display: block;
  font-family: var(--bd-font-display);
  font-size: 1.6rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--bd-white);
}

.bd-footer__tag {
  font-size: 14px;
  line-height: 1.6;
  margin-top: 18px;
  max-width: 34ch;
  color: rgba(255, 255, 255, 0.72);
}

.bd-footer__region {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 18px;
  font-family: var(--bd-font-mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bd-white);
}
.bd-footer__dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--bd-yellow);
}

.bd-footer__cta { margin-top: 18px; }

/* auto-fit, not a fixed four.
   Two of these columns are generated by the theme and the rest come from the
   footer menu, so the count is whatever the site has — and at a hard four, a
   fifth column dropped onto a second row beside three empty cells. */
.bd-footer__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: clamp(20px, 3vw, 40px);
}
.bd-footer__h {
  font-family: var(--bd-font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bd-white);
  margin: 0 0 16px;
}
.bd-footer__col ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
.bd-footer__col a {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.78);
  text-decoration: none;
  transition: color var(--bd-dur-fast) ease;
}
.bd-footer__col a:hover { color: var(--bd-white); }

.bd-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--bd-s4);
  padding-block: 22px 30px;
  border-top: 1px solid rgba(255, 255, 255, 0.28);
  font-size: 13px;
  color: rgba(255, 255, 255, 0.78);
}
.bd-footer__bottom p { margin: 0; }
.bd-footer__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--bd-s5); }
.bd-footer__meta a {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.78);
  text-decoration: none;
  transition: color var(--bd-dur-fast) ease;
}
.bd-footer__meta a:hover { color: var(--bd-white); }

@media (max-width: 1080px) { .bd-footer__top { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 720px)  { .bd-footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; } }
@media (max-width: 480px)  { .bd-footer__cols { grid-template-columns: minmax(0, 1fr); } }

@media (pointer: coarse) {
  .bd-footer__col a,
  .bd-footer__meta a { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ------------------------------------------------------------------ map --- */

/* Ontario energy-flow map. Stripped to a silhouette, the two sites, the demand
   centres they serve, and the flows between — no basemap tiles, no roads, no
   labels the story does not need. */
/* Flow colour is carried on the container as a custom property and inherited
   down to the paths, rather than re-stated by a descendant selector. Custom
   property inheritance resolves cleanly on SVG presentation attributes, where
   a `.bd-map[data-mode] .bd-map__flow { stroke: ... }` override did not take
   despite matching and winning specificity. */
.bd-map {
  display: grid; gap: var(--bd-s6); grid-template-columns: 1fr;
  --bd-flow: var(--bd-green-bright);
}
.bd-map[data-mode="charge"] { --bd-flow: var(--bd-blue); }
.bd-map__stage {
  position: relative;
  background: var(--bd-paper);
  overflow: hidden;
}
.bd-map__svg { display: block; width: 100%; height: auto; }

.bd-map__land {
  fill: color-mix(in srgb, var(--bd-petrol) 7%, transparent);
  stroke: color-mix(in srgb, var(--bd-petrol) 22%, transparent);
  stroke-width: 1.5;
  stroke-linejoin: round;
}

/* Flows are drawn with pathLength="1", so one dash pattern animates identically
   on a 200px hop to London and an 800px run to Ottawa. Without it the dashes
   crawl on long paths and sprint on short ones. */
.bd-map__flow {
  fill: none;
  stroke: var(--bd-flow);
  /* stroke-width is in USER UNITS. pathLength="1" normalises the dash pattern
     so one rhythm suits a short hop and a long run alike — it does not rescale
     the stroke, and setting 0.004 here rendered the flows invisible. */
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 0.02 0.03;
  opacity: 0.45;
  /* `stroke` is deliberately NOT transitioned. Its value comes from var(--bd-flow),
     and a property fed by a custom property does not reliably restart its
     transition when only that custom property changes — the paths held the old
     colour indefinitely when switching to charge mode. Opacity still animates. */
  transition: opacity var(--bd-dur) var(--bd-ease);
  animation: bd-flow 3.2s linear infinite;
}
@keyframes bd-flow { to { stroke-dashoffset: -0.05; } }

/* Discharging is the default reading: stored air returning to the grid. The
   charge state reverses the animation rather than redrawing anything. */
.bd-map[data-mode="charge"] .bd-map__flow { animation-direction: reverse; }

.bd-map__flow.is-lit { opacity: 0.95; stroke-width: 3; }
.bd-map__flow.is-dim { opacity: 0.1; }

.bd-map__halo { fill: var(--bd-green-bright); opacity: 0; transition: opacity var(--bd-dur) var(--bd-ease); }
.bd-map__node:hover .bd-map__halo,
.bd-map__node:focus-visible .bd-map__halo,
.bd-map__node.is-lit .bd-map__halo { opacity: 0.16; }

.bd-map__dot { fill: var(--bd-petrol); transition: fill var(--bd-dur) var(--bd-ease); }
.bd-map__node--site .bd-map__dot { fill: var(--bd-green-bright); stroke: var(--bd-white); stroke-width: 2.5; }
.bd-map__node { cursor: pointer; }
.bd-map__node:focus { outline: none; }
.bd-map__node:focus-visible .bd-map__dot { stroke: var(--bd-petrol); stroke-width: 3; }

.bd-map__label {
  font-family: var(--bd-font-mono);
  font-size: 15px; font-weight: 500;
  letter-spacing: 0.04em;
  fill: var(--bd-petrol);
  paint-order: stroke;
  stroke: var(--bd-paper); stroke-width: 4px; stroke-linejoin: round;
}
.bd-map__node--site .bd-map__label { font-weight: 600; }

/* Controls sit outside the SVG so they are real buttons — an SVG-native
   control would need its own focus and keyboard handling for no gain. */
.bd-map__controls { display: flex; flex-wrap: wrap; gap: var(--bd-s3); align-items: center; }
.bd-map__toggle {
  display: inline-flex; padding: 3px;
  background: color-mix(in srgb, var(--bd-petrol) 6%, transparent);
  border-radius: 999px;
}
.bd-map__toggle button {
  font-family: var(--bd-font-mono); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 9px 16px; border: 0; border-radius: 999px;
  background: none; color: var(--bd-text-soft); cursor: pointer;
  transition: background-color var(--bd-dur-fast) ease, color var(--bd-dur-fast) ease;
}
/* The pill keeps its proportions on a mouse; a finger needs the full 44. */
@media (pointer: coarse) {
  .bd-map__toggle button { min-height: 44px; padding-inline: var(--bd-s4); }
}
.bd-map__toggle button[aria-pressed="true"] {
  background: var(--bd-white); color: var(--bd-petrol);
  box-shadow: var(--bd-shadow-sm);
}

.bd-map__legend {
  display: flex; flex-wrap: wrap; gap: var(--bd-s5);
  font-family: var(--bd-font-mono); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--bd-text-soft);
}
.bd-map__legend span { display: inline-flex; align-items: center; gap: 7px; }
.bd-map__key { width: 10px; height: 10px; border-radius: 50%; }
.bd-map__key--site { background: var(--bd-green-bright); }
.bd-map__key--centre { background: var(--bd-petrol); }

/* The touch picker.
 *
 * Hidden where the map itself is a usable control surface. It appears on
 * narrow screens and on any coarse pointer — a touch laptop at 1300px has the
 * same problem a phone does, and width alone would miss it.
 */
.bd-map__picker { display: none; }

@media (max-width: 900px), (pointer: coarse) {
  .bd-map__picker {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bd-s3);
    margin-block-start: var(--bd-s4);
  }
  .bd-map__picker button {
    /* 44px is the finger-sized target the map nodes cannot be. */
    min-height: 44px;
    padding: 0 var(--bd-s4);
    font-family: var(--bd-font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bd-text-soft);
    background: var(--bd-white);
    border: 1px solid color-mix(in srgb, var(--bd-petrol) 12%, transparent);
    border-radius: 999px;
    cursor: pointer;
    transition: background-color var(--bd-dur-fast) ease,
                color var(--bd-dur-fast) ease,
                border-color var(--bd-dur-fast) ease;
  }
  .bd-map__picker button[aria-pressed="true"] {
    background: var(--bd-petrol);
    border-color: var(--bd-petrol);
    color: var(--bd-white);
  }
  .bd-map__picker-clear {
    margin-inline-start: auto;
    /* Reads as an escape from the current state, not another place. */
    background: none;
    border-style: dashed;
  }
}

/* Motion is the whole point of the flows, so when it is switched off the
   dashes stop but stay visible — the connections still read as connections. */
@media (prefers-reduced-motion: reduce) {
  .bd-map__flow { animation: none; opacity: 0.4; }
}
@media (max-width: 720px) {
  .bd-map__label { font-size: 21px; }
}

/* --- map: water labels, zoom, estimator ---------------------------------- */

.bd-map__water {
  font-family: var(--bd-font-mono);
  font-size: 15px; font-weight: 400;
  letter-spacing: 0.1em;
  fill: color-mix(in srgb, var(--bd-blue) 62%, transparent);
  pointer-events: none;
  font-style: italic;
}

.bd-map__zoom { transition: transform var(--bd-dur-slow) var(--bd-ease); }
.bd-map__zoom.is-dragging { transition: none; }   /* dragging must track the cursor */

.bd-map__stage { touch-action: pan-y; }           /* vertical page scroll still works */
.bd-map__stage.is-zoomed { cursor: grab; }
.bd-map__stage.is-grabbing { cursor: grabbing; }

.bd-map__zoomctl {
  position: absolute; inset-block-start: var(--bd-s4); inset-inline-end: var(--bd-s4);
  display: flex; flex-direction: column; gap: 4px; z-index: 2;
}
.bd-map__zoomctl button {
  width: 36px; height: 36px;
  display: grid; place-items: center;
  background: var(--bd-white);
  border: 1px solid color-mix(in srgb, var(--bd-petrol) 12%, transparent);
  border-radius: 8px;
  color: var(--bd-petrol);
  font-family: var(--bd-font-mono); font-size: 15px;
  cursor: pointer;
  box-shadow: var(--bd-shadow-sm);
  transition: background-color var(--bd-dur-fast) ease;
}
/* Stacked 4px apart, so at 36px a miss lands on the neighbouring control and
   zooms the wrong way. On touch they get the full 44 and a clearer gap. */
@media (pointer: coarse) {
  .bd-map__zoomctl { gap: var(--bd-s2); }
  .bd-map__zoomctl button { width: 44px; height: 44px; font-size: 17px; }
}
.bd-map__zoomctl button:hover { background: var(--bd-paper); }
.bd-map__zoomctl button[disabled] { opacity: 0.35; cursor: default; }

/* --- estimator ----------------------------------------------------------- */

.bd-est {
  display: grid; gap: var(--bd-s6);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: center;
  padding: var(--bd-s6);
  background: var(--bd-paper);
}
@media (max-width: 860px) { .bd-est { grid-template-columns: 1fr; } }

.bd-est__slider { width: 100%; }
.bd-est__range {
  width: 100%; margin: var(--bd-s4) 0 0;
  accent-color: var(--bd-green-bright);

  /* Safari on iOS zooms the whole page when a control smaller than 16px takes
     focus. On a range that zoom lands mid-drag, so the slider jumps under the
     finger. The font is invisible on a range; the size is purely the fix. */
  font-size: 1rem;
}

/* A bare range is about 16px tall, which is a poor thing to catch with a
   thumb. The track keeps its slim look; the hit area is grown around it. */
@media (pointer: coarse) {
  .bd-est__range {
    min-height: 44px;
    /* Vertical padding on a range does not grow the hit box in every engine,
       so the height is set directly and the track stays centred within it. */
  }
  .bd-est__range::-webkit-slider-thumb { width: 26px; height: 26px; }
  .bd-est__range::-moz-range-thumb { width: 26px; height: 26px; }
}
.bd-est__scale {
  display: flex; justify-content: space-between;
  font-family: var(--bd-font-mono); font-size: 0.6875rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--bd-text-soft); margin-top: var(--bd-s2);
}
.bd-est__value {
  font-family: var(--bd-font-display);
  font-size: clamp(2rem, 1.4rem + 2vw, 3rem);
  font-weight: 800; letter-spacing: -0.04em; line-height: 1;
}
.bd-est__value small {
  font-family: var(--bd-font-mono); font-size: 0.75rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--bd-text-soft); display: block; margin-top: var(--bd-s2);
}
.bd-est__out { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: var(--bd-s5); }
@media (max-width: 560px) { .bd-est__out { grid-template-columns: 1fr 1fr; } }
.bd-est__metric strong {
  display: block;
  font-family: var(--bd-font-display); font-size: 1.5rem;
  font-weight: 800; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.bd-est__metric span {
  display: block; margin-top: 4px;
  font-family: var(--bd-font-mono); font-size: 0.625rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--bd-text-soft);
}
/* The figures are placeholders. This notice is not decoration — it is the only
   thing stopping an illustrative number being read as a claim. */
.bd-est__caveat {
  grid-column: 1 / -1;
  font-family: var(--bd-font-mono); font-size: 0.625rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--bd-text-soft);
  border-top: 1px solid var(--bd-rule); padding-top: var(--bd-s4);
}

/* --- project sites ------------------------------------------------------- */

/* Centred as a pair. Two cards on the full 1200px container leave a canyon
   between them and read as a row of three with one missing; capping the pair
   and centring it makes them read as a set of two. */
.bd-sites {
  max-width: 860px;
  margin: var(--bd-s8) auto 0;
  display: grid;
  gap: var(--bd-s7);
}
.bd-sites .bd-card__media { aspect-ratio: 4 / 3; }

.bd-sites__cta {
  display: flex; flex-wrap: wrap; gap: var(--bd-s5);
  align-items: center; justify-content: center;
  text-align: center;
}
.bd-sites__cta .bd-lede { max-width: 34ch; }
@media (max-width: 560px) {
  .bd-sites__cta { flex-direction: column; }
}

/* --- page header with imagery -------------------------------------------- */

/* The migrated pages whose Elementor section carried a background photograph.
   Only seven of twenty-seven have one; the rest open on white, which is how
   the live site has them. */
.bd-band--media {
  position: relative;
  isolation: isolate;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: var(--bd-petrol);   /* seen only before the image paints */
  color: var(--bd-text-on-dark);
  /* The crest is a full-bleed raster at 2560x604, so its rendered height is
     always 23.6vw — it grows with the viewport. Bottom padding has to clear
     that or the lede ends up behind the pattern, which is exactly what a fixed
     pixel value did. Top padding clears the floating header bar. */
  padding-block: calc(var(--bd-band-y) + 76px) calc(23.6vw + var(--bd-s5));
}

/* Weighted left, where the headline sits, so the photograph stays visible on
   the right rather than being flattened under a uniform wash. */
.bd-band--media::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg,
    rgba(0, 40, 56, 0.90) 0%,
    rgba(0, 40, 56, 0.74) 46%,
    rgba(0, 40, 56, 0.34) 100%);
}

.bd-band--media :is(h1, h2, .bd-hero-title, .bd-display) { color: var(--bd-white); }
.bd-band--media .bd-lede { color: rgba(255, 255, 255, 0.88); }
.bd-band--media .bd-eyebrow { color: var(--bd-white); opacity: 0.85; }
.bd-band--media .bd-rule-accent { background: var(--bd-green-bright); }

/* The porous crest closes the header into the white band below, the same way
   the homepage hero does — so a page with imagery and a page without still
   arrive at the same edge. */
.bd-band--media .bd-porous-wrap {
  position: absolute; inset-inline: 0; inset-block-end: 0; z-index: 0;
}

/* --- embedded film -------------------------------------------------------- */

/* A 16:9 iframe made to cover an arbitrary box.
 *
 * object-fit does not apply to iframes, so the frame is sized to whichever of
 * 100vw-by-56.25vw or 177.78vh-by-100vh is larger and then centred. That
 * overflows on one axis by design — the same thing object-fit: cover does for
 * an image — and the hero's overflow:hidden crops it.
 *
 * pointer-events: none matters: without it the YouTube player swallows every
 * click in the hero, including the Watch Video button sitting over it.
 */
.bd-hero__media iframe {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  transform: translate(-50%, -50%);
  width: 100vw;
  height: 56.25vw;
  min-height: 100%;
  min-width: 177.78vh;
  border: 0;
  pointer-events: none;

  /* Overscanned by 18%. `modestbranding` no longer removes the watermark and
     there is no parameter that does — but the logo, the title card and the
     end-screen thumbnails all live within a few percent of the edges, so
     scaling past the frame pushes them outside the crop. The hero is a
     background loop, so losing the outer band costs nothing. */
  transform: translate(-50%, -50%) scale(1.18);
}


/* ---------------------------------------------------- hero, portrait ------ */

/* On a portrait screen the cover maths stops working. Filling a 375x812 box
 * with a 16:9 film needs it 1444px wide before the 18% overscan, so the
 * viewer sees a 22% slice of the middle — the aerial shot stops reading as a
 * place and becomes an abstract texture. There is no scale that fixes this;
 * the two aspect ratios are simply too far apart.
 *
 * So portrait stops covering. The film takes a full-width 16:9 band of its
 * own and the copy sits beneath it on petrol. The whole frame is visible, and
 * the headline gains a solid ground instead of relying on shadows over an
 * unpredictable moving image.
 *
 * Landscape phones are left alone: at 2.17 they are wider than the film, so
 * cover crops a little off the top and bottom and looks right.
 */
@media (orientation: portrait) and (max-width: 900px) {
  .bd-hero {
    /* The floating bar is fixed and sits over the hero: a 16px offset plus the
       68px pill. Over a full-height film that costs nothing, but over a 211px
       band it covered a third of the picture — so the film starts below it. */
    --hero-clear: calc(var(--bd-s4) * 2 + 68px);

    height: auto;
    min-height: 0;
    place-items: stretch;
    text-align: center;
    padding-block-start: var(--hero-clear);
  }

  /* Out of the overlay stack and into the flow, as the first row. */
  .bd-hero__media {
    position: relative;
    inset: auto;
    aspect-ratio: 16 / 9;
    overflow: hidden;
  }

  .bd-hero__media iframe {
    /* The cover minimums are what force the enlargement — clear them and the
       frame fits its box.
       The overscan stays at 1.18, the same as landscape. 1.06 was tried first,
       to show as much of the film as possible, and it showed YouTube's title
       card, channel avatar, transport controls and watermark along with it:
       that chrome sits 6-8% in from the edges, so anything under about 1.15
       puts it back on screen. 1.18 still leaves ~85% of the frame visible,
       against 22% before this treatment existed. */
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    transform: translate(-50%, -50%) scale(1.18);
  }

  /* Over the film only. Below it the copy is on petrol already, and washing
     that would just make the band murky. Offset to match, because an absolute
     child is positioned against the hero's padding box, not its content. */
  .bd-hero__scrim {
    inset-block: var(--hero-clear) auto;
    width: 100%;
    aspect-ratio: 16 / 9;
  }

  .bd-hero__content {
    /* The crest is 604/2560 of the viewport width; the copy has to clear it. */
    padding-block: var(--bd-s7) calc(23.6vw + var(--bd-s6));
  }

  /* Nothing sits on film any more, so the shadows that bought contrast there
     now just soften the type against a flat ground. */
  .bd-hero__welcome-kicker,
  .bd-hero__welcome,
  .bd-hero__invite {
    text-shadow: none;
  }
  .bd-hero__welcome { max-width: 16ch; }
  .bd-hero__invite { max-width: 34ch; }
}

/* Click-to-play facade. The poster is real markup and the iframe is injected
   on click, so a page carrying two films does not load two YouTube players —
   roughly a megabyte of script each — before anyone asks for one. */
.bd-video__frame[data-video-facade] { cursor: pointer; }
.bd-video__frame iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0;
}
.bd-video__frame.is-playing::after,
.bd-video__frame.is-playing .bd-video__play,
.bd-video__frame.is-playing .bd-video__meta,
.bd-video__frame.is-playing img { display: none; }

/* RECOVERED. These four rules were lost when this file was edited by slicing
   between two markers earlier in the project; the two __frame rules below
   survived, so the modal still had a black 16:9 box and nothing else — the
   <dialog> fell back to the browser's default 70x82 fit-content box with a
   3px border, in the middle of the screen, with the film inside it.

   Nothing but a click on "Watch the film" would have shown this, which is
   why it sat unnoticed. */
/* <dialog> handles focus trapping, Escape and background inert on its own.
   Only the appearance is ours. */
.bd-video-dialog {
  border: 0; padding: 0; background: transparent;
  width: min(92vw, 1200px);
  max-width: none; max-height: 92vh;
  overflow: visible;
}

.bd-video-dialog::backdrop { background: rgba(0, 40, 56, 0.88); }

.bd-video-dialog video {
  width: 100%; height: auto; max-height: 86vh;
  background: #000;
  display: block;
}

.bd-video-dialog__close {
  position: absolute; inset-block-start: -40px; inset-inline-end: 0;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: none; border: 0; cursor: pointer;
  color: var(--bd-white);
}

.bd-video-dialog__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
}
.bd-video-dialog__frame iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%; border: 0;
}


/* The footer mark, set to the measure of the sentence beneath it.
   The cap lives on the shared parent rather than on each child: `34ch` on an
   image resolves against a different font than `34ch` on a paragraph, so
   setting it twice produced two different widths (332px against 301px). One
   constraint, two children, one edge. */
.bd-footer__brand { max-width: 34ch; }
.bd-footer__brand p { max-width: none; }
.bd-footer__mark {
  width: 100%;
  height: auto;
  margin-bottom: var(--bd-s5);
}

/* A caption laid over the panorama rather than beneath it. The scrim is
   weighted to the bottom only, so the photograph stays readable above it. */
.bd-media-wide--captioned { position: relative; }
.bd-media-wide--captioned::after {
  content: "";
  position: absolute; inset-inline: 0; inset-block-end: 0;
  height: 62%;
  background: linear-gradient(180deg, rgba(0,40,56,0) 0%, rgba(0,40,56,0.78) 100%);
  pointer-events: none;
}
.bd-media-wide--captioned figcaption {
  position: absolute;
  inset-inline-start: clamp(var(--bd-s5), 4vw, var(--bd-s8));
  inset-block-end: clamp(var(--bd-s5), 4vw, var(--bd-s8));
  z-index: 1;
  max-width: 18ch;
  font-family: var(--bd-font-display);
  font-size: clamp(1.5rem, 1rem + 1.8vw, 2.625rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--bd-white);
}


/* ------------------------------------------------- language switcher ------ */

/* Two states, always both visible. A dropdown hides the fact that the site
 * exists in the reader's language at all, which is the whole point of putting
 * this in the bar. The current language is a span, not a link — offering a
 * link to the page you are already on is noise for a screen-reader user.
 *
 * The labels are abbreviations with a title, so assistive technology reads
 * "English" and "Français" rather than spelling out E-N.
 */
.bd-header__end {
  display: flex;
  align-items: center;
  gap: var(--bd-s3);
  justify-self: end;
}

.bd-langswitch {
  display: inline-flex;
  align-items: center;
  padding: 3px;
  gap: 2px;
  background: color-mix(in srgb, var(--bd-petrol) 6%, transparent);
  border-radius: 999px;
}
.bd-langswitch a,
.bd-langswitch__current {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 38px;
  padding: 7px 10px;
  border-radius: 999px;
  font-family: var(--bd-font-mono);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-decoration: none;
  color: var(--bd-text-soft);
  transition: background-color var(--bd-dur-fast) ease,
              color var(--bd-dur-fast) ease;
}
/* The abbr carries the accessible name; it must not also draw a dotted rule. */
.bd-langswitch abbr {
  text-decoration: none;
  border: 0;
  cursor: inherit;
}
.bd-langswitch__current {
  background: var(--bd-white);
  color: var(--bd-petrol);
  box-shadow: var(--bd-shadow-sm);
}
.bd-langswitch a:hover { color: var(--bd-petrol); }

@media (pointer: coarse) {
  .bd-langswitch a,
  .bd-langswitch__current { min-height: 44px; min-width: 44px; }
}

/* On the green footer everything is white, including this. */
.bd-langswitch--footer {
  background: color-mix(in srgb, var(--bd-white) 16%, transparent);
}
.bd-langswitch--footer a,
.bd-langswitch--footer .bd-langswitch__current { color: var(--bd-white); }
.bd-langswitch--footer .bd-langswitch__current {
  background: var(--bd-white);
  color: var(--bd-green);
  box-shadow: none;
}

/* The bar is tight at the breakpoint where the burger appears; the switcher
   stays (it is how a French reader finds the site) and the CTA goes, since
   Contact is already in the menu it opens. */
@media (max-width: 1080px) {
  .bd-header__end { gap: var(--bd-s2); }
}

/* Administrator-only diagnostic, where the switcher would be. Visitors never
   see it; it exists so "the switcher is missing" is answerable at a glance. */
.bd-langswitch--notice {
  padding: 6px 10px;
  font-family: var(--bd-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bd-text-soft);
  background: color-mix(in srgb, var(--bd-yellow) 55%, transparent);
  border-radius: 999px;
  cursor: help;
  white-space: nowrap;
}


/* ------------------------------------------------- team, as Elementor --- */

/* The team page is the one migrated page built as real Elementor blocks, so a
   director can be added without a rebuild.

   Elementor owns the LAYOUT of these rows — it generates per-page CSS keyed on
   each element's id, at a specificity no theme class reaches without
   !important, so anything here that set display or grid tracks would either
   lose or break the editor's own controls. What is left is the skin: the rule
   between people and the rhythm, which is what made the static page read as a
   list of directors rather than a wall of cards. */
/* Elementor's heading widget puts the custom class on its WRAPPER and the
   real heading inside it, so the wrapper picks up the theme's type and the
   <h1> then overrides it with Elementor's own — 108px where the theme sets
   54, 63 where it sets 42. Inheriting hands the wrapper's setting back to the
   element that renders it, which is what the class was for.

   This applies to any Elementor heading given a theme class, not just the
   team page, so pages built later inherit correctly too. */
:is(.bd-hero-title, .bd-display, .bd-title, .bd-person__name, .bd-eyebrow, .bd-lede)
  > .elementor-heading-title {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  line-height: inherit;
  text-transform: inherit;
  margin: 0;
}

/* The same spacing and scrim as .bd-band--media, which every other page's
   hero uses. It cannot simply reuse that class: the band is written for a
   full-bleed <section> and collapses an Elementor container to zero width. */
.bd-team-hero {
  position: relative;
  isolation: isolate;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: var(--bd-petrol);
  color: var(--bd-text-on-dark);
  padding-block: calc(var(--bd-band-y) + 76px) calc(23.6vw + var(--bd-s5));
}
.bd-team-hero::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg,
              color-mix(in srgb, var(--bd-petrol) 88%, transparent) 0%,
              color-mix(in srgb, var(--bd-petrol) 62%, transparent) 46%,
              color-mix(in srgb, var(--bd-petrol) 18%, transparent) 100%);
}
.bd-team-hero :is(h1, h2, .bd-hero-title) { color: var(--bd-white); }

.bd-person-row {
  /* Rule only — the spacing is an Elementor padding setting, so an editor
     changing it in the panel actually changes it. */
  border-top: 1px solid var(--bd-rule);
}
.bd-person-row:first-of-type { border-top: 0; padding-block-start: 0; }

.bd-person-row .bd-portrait img { width: 100%; height: auto; display: block; }

/* Email and LinkedIn, wearing the site's own ghost button rather than
   Elementor's. Elementor's button widget ships a solid pill with its own
   font, size, padding and radius from the global kit; every one of those has
   to be handed back for the two buttons to match the ones on every other
   page. */
.bd-person__link .elementor-button {
  font: inherit;
  font-family: var(--bd-font-ui);
  font-size: var(--bd-size-small);
  font-weight: 700;
  letter-spacing: -0.01em;
  padding: 9px 15px;
  border-radius: 8px;
  background: transparent;
  color: var(--bd-ink);
  border: 1px solid color-mix(in srgb, var(--bd-ink) 26%, transparent);
  fill: currentColor;
  text-decoration: none;
  transition: border-color var(--bd-dur-fast) ease,
              background-color var(--bd-dur-fast) ease;
}
.bd-person__link .elementor-button:hover {
  border-color: color-mix(in srgb, var(--bd-ink) 55%, transparent);
  background: color-mix(in srgb, var(--bd-ink) 6%, transparent);
}

/* Elementor puts the class on the widget's own wrapper, which is a
   block-level flex child filling the column — width:auto is what actually
   puts the two buttons on one line. */
/* The envelope and LinkedIn marks, back on the buttons.

   As masks rather than images, and as data URIs rather than an icon font.
   These are the same two SVGs the page carried as static markup, so the
   shapes are the brand's own — but Elementor's button widget escapes its
   label, so they cannot be inlined in the markup the way the theme does it
   elsewhere. A mask keeps what matters about an inline SVG: the glyph is
   painted with currentColor, so it follows the button's colour and its hover
   exactly, which a background-image at a fixed fill could not.

   The previous attempt used Elementor's Font Awesome icons instead. The
   envelope arrived zero pixels wide and LinkedIn needs the Brands font, which
   nothing on the site loads — one button ended up 14px wide and the other
   794. Nothing here depends on a font loading. */
/* Guarded: where masks are unsupported the pseudo-element would paint as a
   solid coloured rectangle beside the label, which is worse than no mark at
   all. Inside @supports it simply does not exist there. */
/* Elementor's own icon slot, removed.
   Earlier versions of this page were built with Font Awesome icons on these
   buttons, and a page keeps whatever document it was built with until it is
   rebuilt. On a site running the current stylesheet against an older
   document, the dead icon slot and the mark below were both rendering — two
   marks per button, and the button 20px wider than it should be. Hiding the
   slot makes the stylesheet correct on its own, whether or not the page has
   been rebuilt. */
.bd-person__link .elementor-button-icon { display: none; }

@supports (mask-image: none) or (-webkit-mask-image: none) {
  .bd-person__link .elementor-button-text::before {
    content: "";
    display: inline-block;
    vertical-align: -1px;
    margin-inline-end: 7px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
  }
  .bd-person__link--email .elementor-button-text::before {
    width: 15px; height: 12px;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2215%22%20height%3D%2212%22%20viewBox%3D%220%200%2015%2012%22%20fill%3D%22none%22%3E%3Crect%20x%3D%22.75%22%20y%3D%22.75%22%20width%3D%2213.5%22%20height%3D%2210.5%22%20rx%3D%221.5%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%2F%3E%3Cpath%20d%3D%22M1%202l6.5%204.5L14%202%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%2F%3E%3C%2Fsvg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2215%22%20height%3D%2212%22%20viewBox%3D%220%200%2015%2012%22%20fill%3D%22none%22%3E%3Crect%20x%3D%22.75%22%20y%3D%22.75%22%20width%3D%2213.5%22%20height%3D%2210.5%22%20rx%3D%221.5%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%2F%3E%3Cpath%20d%3D%22M1%202l6.5%204.5L14%202%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%2F%3E%3C%2Fsvg%3E");
  }
  .bd-person__link--linkedin .elementor-button-text::before {
    width: 14px; height: 14px;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2214%22%20height%3D%2214%22%20viewBox%3D%220%200%2014%2014%22%20fill%3D%22%23000%22%3E%3Cpath%20d%3D%22M3%205h2.2v8H3V5zm1.1-3.2a1.3%201.3%200%20110%202.6%201.3%201.3%200%20010-2.6zM7%205h2.1v1.1c.3-.6%201-1.2%202.1-1.2%202.2%200%202.6%201.4%202.6%203.3V13h-2.2V8.6c0-1%200-2.3-1.4-2.3s-1.6%201.1-1.6%202.2V13H7V5z%22%2F%3E%3C%2Fsvg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2214%22%20height%3D%2214%22%20viewBox%3D%220%200%2014%2014%22%20fill%3D%22%23000%22%3E%3Cpath%20d%3D%22M3%205h2.2v8H3V5zm1.1-3.2a1.3%201.3%200%20110%202.6%201.3%201.3%200%20010-2.6zM7%205h2.1v1.1c.3-.6%201-1.2%202.1-1.2%202.2%200%202.6%201.4%202.6%203.3V13h-2.2V8.6c0-1%200-2.3-1.4-2.3s-1.6%201.1-1.6%202.2V13H7V5z%22%2F%3E%3C%2Fsvg%3E");
  }
}

/* Each button is sized by its own label and neither stretches or shrinks.
   Without this the flex row gave one 14px and the other the whole width, and
   a margin on only one of them put them on different baselines. */
.bd-person__links > .bd-person__link {
  flex: 0 0 auto;
  width: auto;
  margin: 0;
  align-self: center;
}

/* The body column is an Elementor flex container; the two buttons are the
   only siblings that should share a line. */
.bd-person__body.e-con { --align-items: flex-start; }

/* The two buttons on one line, whatever Elementor's default direction is. */
.bd-person__links.e-con {
  --flex-direction: row;
  --gap: var(--bd-s3);
  --align-items: center;
  --width: auto;
  margin-block-start: var(--bd-s4);
}


/* ------------------------------------------ hero, framed below desktop --- */

/* The leaf corner on the hero film, tablet and phone only.
 *
 * On a desktop the film is the page: full-bleed, edge to edge, with the type
 * over it. Rounding it there would turn the strongest asset the brand owns
 * into a panel sitting on a background, which is the opposite of the intent.
 *
 * Below 1024px it is already a different thing. On a portrait phone the media
 * leaves the overlay stack entirely and becomes an in-flow 16:9 block above
 * the headline, and on a tablet it reads as a contained picture rather than a
 * backdrop. A framed block is where the motif belongs — the same rule the rest
 * of the system follows: the leaf goes on large framed surfaces, never small.
 *
 * It is inset from the edges as well. A rounded corner that runs into the edge
 * of the screen has nothing to be rounded against, and the shape disappears;
 * pulling the film in by the page gutter puts petrol behind the corners and
 * makes it read as a framed panel.
 *
 * The scrim carries both the radius and the inset. It is a separate layer over
 * the film, so leaving it full-bleed and square would lay a hard-cornered wash
 * over a rounded video and undo the shape at exactly the corners that matter.
 */
@media (max-width: 1024px) {
  .bd-hero__media,
  .bd-hero__scrim {
    border-radius: var(--bd-radius-quarry);
    overflow: hidden;          /* clips the film, overscanned past its box */
    inset: var(--bd-gutter);   /* both are absolute at these widths */
  }
}

/* Portrait phones and tablets, where the media is in the flow rather than
   behind the type. inset does nothing to a relatively positioned element, so
   the film insets with a margin — and the scrim, still absolute, has to be
   given the matching inset by hand or it sits proud of the film it washes. */
@media (orientation: portrait) and (max-width: 900px) {
  .bd-hero__media {
    inset: auto;
    margin-inline: var(--bd-gutter);
  }

  .bd-hero__scrim {
    inset-block: var(--hero-clear) auto;
    inset-inline: var(--bd-gutter);
    width: auto;
  }
}

/* The motif needs room, and steps down on the way to the small end — the same
   50/25 to 28/14 the leaf uses everywhere else in the system. */
@media (max-width: 720px) {
  .bd-hero__media,
  .bd-hero__scrim { border-radius: 28px 14px 28px 0; }
}
