/**
 * `bd/site-header` + `bd/site-footer` component CSS (Task 3).
 *
 * Sibling to tokens.css (Task 2), enqueued the same way — see functions.php.
 * Only new `bd-site-header__*`/`bd-site-footer__*` classes live here; the
 * `bd-bg-*`/`bd-spacing-*`/`bd-divider`/`bd-btn*` chrome classes these two
 * blocks also carry are already defined in tokens.css and untouched here.
 *
 * Layout/positioning is re-expressed from `SiteHeader.dc.html`/
 * `SiteFooter.dc.html`'s inline `style="..."` attributes and `<style>` block
 * as real classes — reasonable-fidelity, not pixel-perfect (per Task 3's
 * brief).
 */

/*
 * Two variables, deliberately:
 *
 * `--header-h-min` is an *input* — the bar's designed height, set on
 * `.bd-site-header__inner`/`__link` as a `min-height` so real content (a
 * wrapped nav, a bigger font size) can still push the bar taller.
 *
 * `--header-h` is an *output* — how tall the bar actually ended up. It feeds
 * the `body` top offset and, critically, the `scroll-padding-top` below:
 * without that, every in-page anchor (`/services/#scanning` and friends, which
 * the nav dropdowns link to) lands with its heading underneath the fixed bar.
 * assets/js/header-height.js overwrites it with the measured height; the value
 * here is the no-JS default.
 *
 * Keeping them separate is what stops the feedback loop — if the measured
 * height were also the declared height, the script would only ever re-measure
 * its own last answer.
 */
:root {
  --header-h-min: 72px;
  --header-h: var(--header-h-min);

  /*
   * Everything an anchor has to clear, not just the header. A page may dock a
   * second bar under it — `bd/products-catalog`'s search-and-filter row does,
   * and /products/#automated used to land behind it. JS sums the header and
   * every `.bd-sticky-under-header` on the page into this; the default here is
   * the header alone, which is right for every page that has no such bar.
   */
  --scroll-offset: var(--header-h);
}

html {
  scroll-behavior: smooth;
  /* Obstructions, plus a little breathing room above the section's own top. */
  scroll-padding-top: calc(var(--scroll-offset) + var(--space-6));
}

/*
 * A bar that docks directly beneath the fixed header rather than scrolling
 * under it. Carrying this class is also what tells header-height.js to count
 * the element as an obstruction when it computes `--scroll-offset` above — the
 * two have to agree, so they are one contract rather than a block stylesheet
 * choosing its own `top` value.
 */
.bd-sticky-under-header {
  position: sticky;
  top: var(--header-h);
}

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

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

/**
 * Shared eyebrow label — the small uppercase kicker above a heading.
 *
 * Cross-block rather than per-block: `bd/site-footer` and `bd/hero` both emit
 * a bare `.bd-eyebrow`, and their own `__eyebrow` modifiers (e.g.
 * `.bd-site-footer__eyebrow` below) only override colour and spacing on top
 * of it. It lives here, next to `.bd-container`, because a per-block
 * stylesheet in assets/css/blocks/ would either duplicate it or make one
 * block's sheet a load-order dependency of another's.
 *
 * Blocks whose eyebrow is a block-scoped element instead
 * (`.bd-cta-band__eyebrow`, `.bd-page-header__eyebrow`,
 * `.bd-rich-section__eyebrow`) declare the same typography in their own
 * stylesheet and do not depend on this rule.
 */
.bd-eyebrow {
  font-size: var(--type-eyebrow-size);
  font-weight: var(--type-eyebrow-weight);
  letter-spacing: var(--type-eyebrow-ls);
  text-transform: uppercase;
}

/* ============================================================ header == */

.bd-site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: saturate(180%) blur(10px);
  -webkit-backdrop-filter: saturate(180%) blur(10px);
  border-bottom: var(--border-width) solid var(--border);
  padding: 0 !important;
  /* overrides bd-spacing-* — a sticky nav bar has its own fixed height, not section rhythm */
}

.bd-site-header__inner {
  max-width: var(--container-xl);
  margin: 0 auto;
  padding: 0 var(--gutter);
  min-height: var(--header-h-min);
  display: flex;
  align-items: center;
  gap: var(--space-8);
}

.bd-site-header__logo {
  display: flex;
  align-items: center;
  flex: none;
}

.bd-site-header__logo img {
  height: 28px;
  width: auto;
  display: block;
}

.bd-site-header__logo-text {
  font-family: var(--font-sans);
  font-weight: var(--fw-extrabold);
  font-size: var(--fs-lg);
  color: var(--ink);
}

.bd-site-header__nav {
  display: flex;
  align-items: stretch;
  gap: 2px;
  flex: 1;
}

.bd-site-header__item {
  position: relative;
  display: flex;
  align-items: center;
}

.bd-site-header__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--header-h-min);
  padding: 0 var(--space-4);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  color: var(--text-secondary);
  transition: var(--transition-base);
  /*
   * Current-page underline, declared here transparent and coloured in by
   * `.is-active` below. `text-decoration` rather than a positioned `::after`
   * so the rule tracks the text's own width and baseline instead of the
   * link's 72px padding box — the export draws a full-bleed tab bar down at
   * the bottom edge of the header, which reads as a tab strip, not as an
   * underline on the word.
   *
   * Transparent-not-absent so `--transition-base` animates the colour and
   * nothing reflows on state change.
   */
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: transparent;
  text-underline-offset: 6px;
}

/* Hover is colour-only: the underline means "you are here", so lending it to
 * hover would make a second link look half-current. */
.bd-site-header__link:hover {
  color: var(--ink);
}

.bd-site-header__link.is-active {
  color: var(--ink);
  text-decoration-color: var(--first-blue);
}

/* The mobile panel has no room for an underline — the label goes blue instead. */
.bd-site-header__mobile-toggle.is-active,
.bd-site-header__mobile-children a.is-active {
  color: var(--first-blue);
}

.bd-site-header__dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  padding-top: 6px;
}

.bd-site-header__dropdown[hidden] {
  display: none;
}

.bd-site-header__dropdown-panel {
  /*
   * Wide enough for the longest dropdown title ("Automated 3D Inspection
   * Systems") to sit on one line — at 264px it wrapped.
   */
  min-width: 280px;
  background: var(--surface-page);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-2);
  overflow: hidden;
}

.bd-site-header__drop-item {
  display: block;
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: background var(--dur-base);
}

.bd-site-header__drop-item:hover {
  background: var(--first-blue-050);
}

.bd-site-header__drop-item:hover .bd-site-header__drop-title {
  color: var(--first-blue);
}

.bd-site-header__drop-title {
  display: block;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--ink);
}

.bd-site-header__drop-desc {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin-top: 2px;
}

.bd-site-header__right {
  display: flex;
  align-items: center;
  gap: 18px;
  flex: none;
  margin-left: auto;
}

/*
 * ZEISS Certified Metrology Partner lockup + its hairline divider, between
 * the nav and the CTA (FIR-004). Hidden at the same breakpoint as the nav and
 * the CTA — the export drops all three together rather than trying to fit the
 * lockup next to a burger.
 */
.bd-site-header__partner {
  display: flex;
  align-items: center;
  padding-right: 18px;
  border-right: var(--border-width) solid var(--border);
}

.bd-site-header__partner-mark {
  display: block;
  /*
   * 64px, not the 38px the export passes to its `PartnerLockup` component —
   * `SiteHeader.dc.html`'s own `<style>` block overrides that component prop
   * with `.fm-partner img { height: 64px !important }`, and 64px is what the
   * page actually renders. At 38px the lockup's "Certified Metrology Partner"
   * wordmark is too small to read.
   */
  height: 64px;
  width: auto;
}

.bd-site-header__cta {
  --bd-btn-height: 40px;
  padding: 0 18px;
  font-size: var(--fs-sm);
  white-space: nowrap;
}

.bd-site-header__burger {
  display: none;
  width: 42px;
  height: 42px;
  align-items: center;
  justify-content: center;
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-page);
  cursor: pointer;
  color: var(--ink);
}

.bd-site-header__mobile {
  border-top: var(--border-width) solid var(--border);
  background: var(--surface-page);
  padding: var(--space-3) var(--space-5) var(--space-6);
  max-height: 78vh;
  overflow-y: auto;
}

.bd-site-header__mobile[hidden] {
  display: none;
}

.bd-site-header__mobile-item {
  border-bottom: var(--border-width) solid var(--surface-subtle);
}

.bd-site-header__mobile-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 15px 4px;
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  color: var(--ink);
  text-align: left;
  text-decoration: none;
}

/*
 * The +/− glyph is generated content, not markup. It has to be: the open state
 * needs to *replace* the character, and a `::before` on a span that already
 * contained a literal "+" only ever prepends, so every expanded section read
 * "−+". The span in blocks/site-header.php is empty for this reason.
 */
.bd-site-header__chevron::before {
  content: "+";
}

.bd-site-header__chevron.is-open::before {
  content: "−";
}

.bd-site-header__mobile-children {
  padding: 0 4px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.bd-site-header__mobile-children[hidden] {
  display: none;
}

.bd-site-header__mobile-children a {
  display: block;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-subtle);
  text-decoration: none;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
}

.bd-site-header__mobile-cta {
  margin-top: 18px;
  width: 100%;
}

@media (max-width: 1024px) {

  .bd-site-header__nav,
  .bd-site-header__partner,
  .bd-site-header__cta {
    display: none;
  }

  .bd-site-header__burger {
    display: inline-flex;
  }
}

@media (max-width: 560px) {
  .bd-site-header__inner {
    padding: 0 var(--space-4);
  }
}

/* Body offset so fixed header doesn't cover page content. */
body {
  padding-top: var(--header-h);
  /*
   * The design system's base.css sets `body { line-height: var(--type-body-lh) }`
   * (1.65) and everything inherits it. The theme never ported that line, so
   * every element without an explicit line-height computed to `normal` (~1.2)
   * instead of 1.65.
   *
   * That single omission was the root cause of a whole family of "a few px
   * short" defects that each looked local but were not: the section eyebrow
   * (15px vs 20px), the card CTA row (23 vs 29), the stat unit (21 vs 29, which
   * shortened the baseline-aligned value row), and every footer link (17 vs 24,
   * which alone made the footer 35px short at 1440 and 261px at 390).
   *
   * Fixed here at the base layer rather than per component, so the next ported
   * block inherits the right leading instead of rediscovering this.
   */
  line-height: var(--type-body-lh);
}

/*
 * The other half of the same omission. base.css gives headings their own
 * leading, so they do NOT inherit the body's 1.65 — without this, adding the
 * body rule above would push every h1-h6 from `normal` (~1.2) to 1.65, which
 * is the opposite of the export. Card titles are the visible case: 20px type
 * is a 24px line in the export (1.2), not 33px.
 *
 * Only line-height is ported here. base.css also sets margin/weight/colour on
 * headings, but the theme's blocks already set those per component and
 * changing them globally would be a much wider behavioural change.
 */
h1,
h2,
h3,
h4,
h5,
h6 {
  line-height: var(--type-heading-lh);
}

/*
 * The third instance of the same omission, and the one that actually broke a
 * font. Form controls do NOT inherit `font-family` — UA stylesheets set their
 * own. base.css ports `font: inherit` for exactly that reason; the theme never
 * did, so every bare `<button>` rendered in the UA default. The blog's category
 * filter row was the visible case: drawing in **Arial** while every other word
 * on the site was Inter, and the only broken family anywhere in the port.
 */
button,
input,
select,
textarea {
  font: inherit;
}

/*
 * Heading tracking, ported at the base layer for the same reason the leading
 * above was: 25 headings across seven pages computed to `letter-spacing:
 * normal` while the export tracks every one of them. Patching those 25 rules
 * would have left the 26th — the next card block someone ports — to
 * rediscover it.
 *
 * Two steps, because display type needs more negative tracking than a card
 * title does: at 48px `--ls-snug` is invisible, and at 20px `--ls-tight` is
 * visibly over-tight. Components that genuinely want neither still override.
 */
h1,
h2 {
  letter-spacing: var(--ls-tight);
}

h3,
h4,
h5,
h6 {
  letter-spacing: var(--ls-snug);
}

/*
 * FIR-002 — the "weird gap above the hero".
 *
 * With no `styles.spacing.blockGap` in theme.json, core's global stylesheet
 * emits `:where(.wp-site-blocks) > * { margin-block-start: 24px }`, so the
 * `<main>` wrapper was pushed 24px clear of the fixed header and the hero
 * started with a band of page background above it. Every `bd/*` section owns
 * its own vertical padding (`.bd-spacing-*`), so top-level sections want no
 * gap between them at all.
 *
 * Overridden here rather than by setting `blockGap` in theme.json, because
 * that token also drives the spacing between paragraphs and other flow
 * content inside a post body — zeroing it globally would collapse blog post
 * typography. `:where()` contributes no specificity, so this single class
 * selector is enough to win.
 */
.wp-site-blocks>* {
  margin-block-start: 0;
}

/*
 * The same 24px block gap again, one level down.
 *
 * `wp:post-content` is a flow layout, so core also emits
 * `:where(.is-layout-flow) > * + * { margin-block-start: 24px }` — which put a
 * 24px band of page background between *every* pair of `bd/*` sections. It
 * only reads as a bug where two adjacent sections have different backgrounds,
 * which is why it showed up as "hero got gap below" (dark hero into the pale
 * stats strip) rather than as seven separate reports.
 *
 * Scoped to `section`/`header` children rather than all of them: every `bd/*`
 * block roots at one of those two elements, while ordinary post copy roots at
 * `p`/`h2`/`ul`/`figure`. So a blog post's paragraph rhythm keeps the block
 * gap and only the full-bleed sections lose it.
 */
.wp-block-post-content>section,
.wp-block-post-content>header {
  margin-block-start: 0;
}

/* ============================================================ footer == */

.bd-site-footer {
  background: var(--surface-dark);
  color: var(--text-on-dark);
  /*
   * Same reasoning as `.bd-site-header` above: the footer is a composite of
   * three bands that each carry their own padding (the indigo CTA, the link
   * grid, the partner/legal bar), so the section-level `bd-spacing-*` class
   * chrome resolves to only added a slab of bare `--surface-dark` above the
   * CTA and below the copyright — the black strips either side of the footer
   * in FIR-012.
   */
  padding: 0 !important;
}

.bd-site-footer__cta {
  background: var(--indigo);
  border-bottom: var(--border-width) solid rgba(255, 255, 255, 0.08);
}

.bd-site-footer__cta-inner {
  display: grid;
  grid-template-columns: 1.3fr 0.9fr;
  gap: 56px;
  align-items: center;
  padding: 68px var(--gutter);
}

.bd-site-footer__eyebrow {
  color: var(--first-blue-300);
  margin-bottom: var(--space-4);
}

.bd-site-footer__heading {
  font-size: var(--fs-5xl);
  font-weight: var(--fw-extrabold);
  letter-spacing: var(--ls-tight);
  line-height: var(--lh-tight);
  margin: 0 0 var(--space-4);
  color: var(--white);
}

.bd-site-footer__body {
  color: var(--text-on-dark-muted);
  font-size: var(--fs-md);
  line-height: var(--lh-relaxed);
  max-width: 480px;
  margin: 0;
}

.bd-site-footer__cta-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.bd-site-footer__cta-actions .bd-btn {
  --bd-btn-height: 52px;
}

.bd-site-footer__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1.6fr 1.4fr;
  gap: 36px;
  padding: var(--space-16) 0 var(--space-10);
}

.bd-site-footer__logo {
  height: 30px;
  width: auto;
}

.bd-site-footer__logo-text {
  font-family: var(--font-sans);
  font-weight: var(--fw-extrabold);
  font-size: var(--fs-lg);
  color: var(--white);
}

.bd-site-footer__desc {
  color: var(--text-on-dark-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-relaxed);
  margin: var(--space-5) 0 var(--space-5);
  max-width: 300px;
}

.bd-site-footer__social {
  display: flex;
  gap: 10px;
}

.bd-site-footer__social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 38px;
  padding: 0 14px;
  border-radius: var(--radius-md);
  border: var(--border-width) solid rgba(255, 255, 255, 0.18);
  color: var(--text-on-dark-secondary);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  text-decoration: none;
  transition: var(--transition-base);
}

.bd-site-footer__social-link:hover {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--white);
}

/*
 * A step below the links it sits above, not level with them.
 *
 * On --fs-sm this tied with the nav links underneath it (both 14px) and the
 * column headings stopped reading as headings — the export runs them at 13
 * against 14.5 links, so the label is quieter than its own list. --fs-xs is
 * the ladder step that preserves that relationship.
 *
 * Tracking down one step too: --ls-widest (0.1em) is the eyebrow treatment and
 * is too loose at this size — it was spacing the word out to compete for
 * attention that the export gives the links.
 */
.bd-site-footer__col-title {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--text-on-dark-subtle);
  margin: 0 0 18px;
}

.bd-site-footer__links {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  font-size: var(--fs-sm);
}

.bd-site-footer__link {
  color: var(--text-on-dark-muted);
  text-decoration: none;
  transition: color var(--dur-base);
  /*
   * Sized here rather than inherited. The class is used in two columns and only
   * one of them declared a size: inside `__links` it picked up --fs-sm, but the
   * office phone numbers sit in `__offices`, which declares none, so they fell
   * back to the footer's 16px base — 2px larger than every other link beside
   * them, for no reason anyone chose.
   */
  font-size: var(--fs-sm);
}

.bd-site-footer__link:hover {
  color: var(--white);
}

/*
 * The office phone is the one footer link the export sets in semibold — it is
 * the actionable line in each office block, and the address above it is not.
 * Scoped to `__offices` so the Explore column stays regular weight.
 */
.bd-site-footer__offices .bd-site-footer__link {
  font-weight: var(--fw-semibold);
}

/*
 * The prominent contact pair — the email and the main phone under "Get in
 * touch". The export sets these at 15px white against the office phones'
 * 13.5px muted, so they are deliberately emphasised.
 *
 * They stay on --fs-sm anyway, and the reason is worth keeping. 15px sits
 * EXACTLY between --fs-sm (14) and --fs-base (16), so the ladder does not
 * force the choice — both are 1px from the export. --fs-base was the first
 * pick and it was wrong in practice: rounding 13.5→14 and 15→16 stretches the
 * export's 1.5px separation to 2px, and `+603-7665 2188` appears in BOTH
 * columns, so the same phone number rendered at two visibly different sizes
 * side by side.
 *
 * At --fs-sm every footer link is one size and the emphasis is carried by
 * colour and weight — white/600 against 66%-white/400 — which is what the
 * export is leaning on regardless. Equally faithful, and internally
 * consistent rather than only locally correct.
 */
.bd-site-footer__link--strong {
  color: var(--white);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
}

.bd-site-footer__offices {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.bd-site-footer__office-name {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--first-blue-300);
  margin-bottom: 5px;
}

/*
 * The office name is a link when the footer block has a page to send it to.
 * An `<a>` is inline and underlined by default, so these two declarations are
 * the whole of what it takes to leave the resting footer looking exactly as it
 * did when the name was an inert `<div>` — the only visible change is on hover
 * and on keyboard focus, where a link has to say that it is one.
 */
a.bd-site-footer__office-name {
  display: block;
  text-decoration: none;
  transition: color 0.15s ease;
}

a.bd-site-footer__office-name:hover,
a.bd-site-footer__office-name:focus-visible {
  color: var(--first-blue-200);
}

.bd-site-footer__office-address {
  color: var(--text-on-dark-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  margin: 0 0 4px;
}

.bd-site-footer__touch {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.bd-site-footer__touch-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--text-on-dark-subtle);
  margin-bottom: 5px;
}

.bd-site-footer__hours {
  color: var(--text-on-dark-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  margin: 0;
}

/*
 * The asterisked footnote under the opening times — a step smaller and a step
 * dimmer than the hours themselves, per the export. Split out of the `hours`
 * field in blocks/site-footer.php; see the comment there for why it cannot be
 * done in CSS alone.
 */
.bd-site-footer__hours-note {
  color: var(--text-on-dark-subtle);
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
  margin: 0;
}

.bd-site-footer__bottom {
  border-top: var(--border-width) solid rgba(255, 255, 255, 0.1);
}

.bd-site-footer__bottom-inner {
  padding: 34px var(--gutter);
}

.bd-site-footer__partner-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 40px;
  margin-bottom: 26px;
}

.bd-site-footer__partner-mark {
  display: block;
  /* `.fm-plk-bar img { height: 110px }` in SiteFooter.dc.html — the divider
     beside it stays 90px, so the marks overhang it slightly by design. */
  height: 110px;
  width: auto;
  /*
   * The marks are wide lockups: at a fixed 110px tall their intrinsic width
   * (~470px) exceeds a phone viewport, which gave EVERY page on the site a
   * horizontal scrollbar.
   *
   * `max-width: 100%` alone does not fix this and previously appeared to,
   * which is why the bug survived a round: the bar is a two-item flex row,
   * and 100% is 100% of the bar *per image*, so two marks were each granted
   * the bar's full 342px and the row still overflowed 187px either side.
   * `min-width: 0` is what actually lets a flex item shrink below its
   * intrinsic content width — without it `flex-shrink: 1` is inert on a
   * replaced element whose fixed height pins its width via aspect ratio.
   */
  min-width: 0;
  max-width: 100%;
  object-fit: contain;
}

/*
 * Below the point where two lockups plus the 40px gap can share a line, stack
 * them. `height: auto` hands sizing back to `max-width`, so each mark scales
 * to the column instead of being letterboxed inside a 110px band, and the
 * divider — a vertical rule between two things no longer side by side — goes
 * away rather than floating under them.
 */
@media (max-width: 720px) {
  .bd-site-footer__partner-bar {
    flex-direction: column;
    gap: 22px;
  }

  /*
   * An explicit width, not `width: auto` + `max-width`: a lazy image that has
   * not loaded yet has no intrinsic width, so `auto` resolved to 0 and the
   * width/height attributes' aspect ratio had nothing to scale — the mark
   * reserved no space and shifted the copyright line on load.
   */
  .bd-site-footer__partner-mark {
    width: min(100%, 300px);
    height: auto;
    max-width: 100%;
  }

  .bd-site-footer__partner-divider {
    display: none;
  }
}

.bd-site-footer__partner-divider {
  width: 1px;
  height: 90px;
  background: rgba(255, 255, 255, 0.16);
}

.bd-site-footer__copyright {
  /*
   * Block, not flex (FIR-012): the copyright line is one run of inline text
   * with a `<strong>` at the end, and as a flex container the whitespace
   * between the text node and that `<strong>` was dropped — rendering
   * "(1108417-P) ·Always Precise." with no space.
   */
  display: block;
  text-align: center;
  padding-top: var(--space-6);
  border-top: var(--border-width) solid rgba(255, 255, 255, 0.08);
  color: var(--text-on-dark-subtle);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}

.bd-site-footer__copyright strong {
  color: var(--text-on-dark-muted);
  font-weight: var(--fw-semibold);
}

@media (max-width: 860px) {
  .bd-site-footer__grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-10) var(--space-8);
  }

  .bd-site-footer__cta-inner {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }
}

@media (max-width: 540px) {
  .bd-site-footer__grid {
    grid-template-columns: 1fr;
  }
}

/* ========================================================== article body == */
/*
 * Post body typography.
 *
 * `templates/single.html` constrains the article column to 720px (it was
 * inheriting theme.json's 1280px `contentSize`, so a post ran the full page
 * width at ~180 characters a line — unreadable). The type itself also needs
 * to step up from the UI defaults: the design sets article copy at 18px/1.75
 * in `--text-secondary`, not 16px in full ink.
 *
 * Scoped to `.bd-article` so it only reaches a post body, never the `bd/*`
 * sections that share `.wp-block-post-content` on the marketing pages.
 */
.bd-article .wp-block-post-content {
  font-size: var(--fs-md);
  line-height: var(--lh-relaxed);
  color: var(--text-secondary);
}

.bd-article .wp-block-post-content>h2 {
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  line-height: var(--lh-snug);
  color: var(--ink);
  margin-block: var(--space-10) var(--space-4);
}

.bd-article .wp-block-post-content>h3 {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  color: var(--ink);
  margin-block: var(--space-8) var(--space-3);
}

/*
 * Prose links only.
 *
 * A post body is not only prose — `bd/*` blocks sit in `post_content` too (the
 * in-article "Have a similar application?" `bd/cta-band`, for one), and their
 * anchors are components with their own colour. Unqualified, this rule's
 * `.bd-article .wp-block-post-content a` (0,2,1) beat `.bd-btn--primary`
 * (0,1,0) and painted the CTA button's label `--text-link` — brand blue on the
 * brand-blue fill, i.e. an empty blue box. Excluding `bd-`prefixed anchors
 * keeps every component link (`bd-btn`, `bd-arrow`, card CTAs) on its own
 * colour while real prose links, which carry no class, still get this one.
 */
.bd-article .wp-block-post-content a:not([class*="bd-"]) {
  color: var(--text-link);
}

/*
 * The article's lead image.
 *
 * `blog-post.dc.html` opens the body with the post's featured image in a
 * 980px column — wider than the 720px text measure — lifted 32px so it
 * overlaps the indigo header above it. The posts have carried a featured
 * image all along; nothing in `templates/single.html` rendered it, so every
 * article ran from the header straight into body copy.
 */
/*
 * The design's column widths are stated border-box — `max-width: 980px;
 * padding: 0 24px` means a 932px image, not a 980px one, and the same for
 * the 720px text column (672px of copy). The template's `contentSize` values
 * are therefore the inner measures, and the gutter is added back here so the
 * columns still clear the viewport edge on narrow screens. Without it both
 * ran 48px wide against the mockup, which is the "page padding" difference.
 *
 * The text column is 772px of copy, not the mockup's 672px: the post title in
 * `bd-post-header__inner` measures 820px border-box — 772px of copy — and
 * title, body and table are meant to share one left and right edge. Only the
 * featured image runs wider (932px). Changed 2026-08-19 on request.
 */
/*
 * Doubled up on `.wp-block-group` for the same reason as the `margin-block-start`
 * rule below, but against a different core rule. Both groups are constrained, so
 * core gives them `has-global-padding` and its global-styles `<style>` emits
 *
 *   .has-global-padding { padding-left: var(--wp--style--root--padding-left);
 *                         padding-right: var(--wp--style--root--padding-right) }
 *
 * — specificity 0,1,0, the same as a bare `.bd-article-figure`, and emitted
 * after the theme's stylesheets, so on a tie core won and both columns computed
 * `padding-left: 0px`. That is invisible on desktop (the max-width leaves room
 * either side) and only shows up on a narrow viewport, where the featured image
 * and every paragraph ran hard against both screen edges while the mockup keeps
 * its 24px. Measured live at 390px before the fix: `padL=0px`.
 */
.wp-block-group.bd-article-figure,
.wp-block-group.bd-article {
  padding-inline: var(--gutter);
}

/*
 * The -32px lift has to sit on the *group*, not the inner `<figure>`, and it
 * has to be written as a logical property. Two core rules from the global
 * stylesheet fight the obvious version of this:
 *
 *   :root :where(.is-layout-constrained) > *            { margin-block: 24px 0 }
 *   :root :where(.is-layout-constrained) > :first-child { margin-block-start: 0 }
 *
 * The figure is the group's only (hence first) child, so the second rule zeroed
 * a `margin-top: -32px` written on it, and the first added a further 24px to
 * the group. Live measured +24px between the header and the image where the
 * export has -32px — 56px of drift, and the "runs straight from the header
 * into the image with a gap" look instead of the overlap.
 *
 * `margin-block-start` is the form that lands, but it needs one extra class to
 * carry it: core's rule is `:root :where(...) > *` — specificity 0,1,0, the
 * same as a bare `.bd-article-figure`, and core's global-styles `<style>` is
 * emitted *after* the theme's stylesheets, so on a tie core wins. Doubling up
 * on `.wp-block-group` (0,2,0) is what actually breaks the tie.
 */
.wp-block-group.bd-article-figure {
  position: relative;
  z-index: 1;
  margin-block-start: -32px;
  margin-bottom: 44px;
}

.bd-article-figure .wp-block-post-featured-image {
  margin-block: 0;
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}

.bd-article-figure .wp-block-post-featured-image img {
  display: block;
  width: 100%;
  height: 420px;
  object-fit: cover;
}

/* A post with no featured image must not leave the 44px gap behind. */
.bd-article-figure:not(:has(img)) {
  display: none;
}

/*
 * The standfirst — the post's excerpt, set in brand blue above the body copy,
 * which is how the design distinguishes the article's one-line summary from
 * the paragraphs that follow. Core's post-excerpt block also emits an
 * optional "read more" link; the template leaves `moreText` unset so none is
 * rendered, but it is hidden here as well so a later editor toggling it on
 * cannot drop a stray link into the middle of the article.
 */
.bd-article-standfirst {
  margin: 0 0 var(--space-6);
}

.bd-article-standfirst .wp-block-post-excerpt__excerpt {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-normal);
  color: var(--color-primary);
}

.bd-article-standfirst .wp-block-post-excerpt__more-text {
  display: none;
}
/*
 * Inline post-body images.
 *
 * Imported posts carry bare `<img>` tags inside a `<p>` (no `wp-block-image`
 * figure, no width/height attributes), so nothing constrained them and a
 * 1600px-wide asset ran straight out of the 772px article column and past the
 * viewport edge. Cap at the column width and keep the aspect ratio.
 */
.bd-article .wp-block-post-content img {
  display: block;
  max-width: 100%;
  height: auto;
}

/*
 * Post-body tables.
 *
 * Imported posts emit a bare `<table>` (no `wp-block-table` figure, no
 * classes), so cells had no rules at all and columns ran together as loose
 * text. Full grid: every cell is boxed, the table carries its own rounded
 * outer border, and the head row sits on a tint with a heavier underline.
 *
 * The table takes the article column exactly — same left and right edge as
 * the post title and the body copy (the featured image is the one element
 * that runs wider). A 5-column comparison table is tight at that measure, so
 * the type steps down to `--fs-sm`/`--lh-snug` and the cells carry 8/12px
 * padding rather than the article's 18px body size.
 *
 * `border-collapse: separate` is what makes the radius possible at all — a
 * collapsed table paints cell borders over the table's own, so the corners
 * stay square and the head tint spills past the curve. Separate borders would
 * double up at every shared edge, so each cell draws only its right and
 * bottom rule and the last column/row drop theirs to the table's own border.
 * `overflow: hidden` clips the head tint to the top corners.
 *
 * `display: block` (needed for `overflow-x`) makes Chrome lay the rows out
 * inside the block's width instead of overflowing it, and when a column
 * cannot fit its longest word it breaks the word mid-way — that is where
 * "Represent / ative" and "ScanCobo / t" came from. So the scroll box is
 * applied only below 1024px, where the columns genuinely cannot fit, and
 * `overflow-wrap: normal` keeps words intact there too.
 */
.bd-article .wp-block-post-content table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: auto;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  margin-block: var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

@media (max-width: 1023px) {
  .bd-article .wp-block-post-content table {
    display: block;
    overflow-x: auto;
  }
}

.bd-article .wp-block-post-content th,
.bd-article .wp-block-post-content td {
  padding: var(--space-2) var(--space-3);
  text-align: left;
  vertical-align: top;
  overflow-wrap: normal;
  word-break: normal;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.bd-article .wp-block-post-content tr > :last-child {
  border-right: 0;
}

.bd-article .wp-block-post-content tbody tr:last-child > * {
  border-bottom: 0;
}

.bd-article .wp-block-post-content thead th {
  color: var(--ink);
  font-weight: var(--fw-bold);
  background: var(--surface-subtle);
  border-bottom: 2px solid var(--border);
}
