/* ==========================================================================
   Big Top Multimedia — base element styles
   Maps tokens.css onto raw HTML elements and the shared bt-* classes used by
   patterns. tokens.css supplies every value here; this layer supplies no new
   colours, sizes or timings of its own — see readme.md in the design system
   for the rules this file implements.

   Load order (enqueued in functions.php): bigtop-fonts, bigtop-tokens,
   bigtop-base (this file, depends on bigtop-tokens), bigtop-motion.
   ========================================================================== */

/* --- Box model ------------------------------------------------------------ */

html {
  box-sizing: border-box;
}

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

/* --- Body copy -------------------------------------------------------------
   2026-08-22: body copy reads in ink, not charcoal. Rendered pixels of the
   design PDF (Website Design.pdf pp.1-2) put every run of light-surface body
   text — service-card copy, the about paragraphs, stat copy, testimonial
   names — at #000, and #1D1D1D on the grey testimonial band; charcoal
   #545354 appears nowhere as a text colour. Charcoal keeps its borders /
   chip-accent roles; --btm-ink carries text, so body and headings sit in
   one near-black family (DS --text-body mirrors this). */

body {
  font-family: var(--btm-font-body);
  font-weight: var(--btm-fw-regular);
  font-size: var(--btm-text-base);
  line-height: var(--btm-leading-normal);
  color: var(--btm-ink);
  background-color: var(--btm-faun);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

p {
  margin: 0 0 var(--btm-space-4);
}

p:last-child {
  margin-bottom: 0;
}

/* --- Headings --------------------------------------------------------------
   Poppins Bold, tight leading, tracked in slightly tighter on the two large
   sizes per the design system ("-0.02em tracking on large sizes"). */

h1,
h2,
h3,
h4,
h5,
h6,
.wp-block-heading {
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-bold);
  line-height: var(--btm-leading-tight);
  color: var(--btm-ink);
  margin: 0 0 var(--btm-space-4);
}

h1 {
  font-size: var(--btm-text-h1);
  letter-spacing: var(--btm-tracking-tight);
}

h2 {
  font-size: var(--btm-text-h2);
  letter-spacing: var(--btm-tracking-tight);
}

h3 {
  font-size: var(--btm-text-h3);
}

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

h5,
h6 {
  font-size: var(--btm-text-base);
}

/* Headings that are also links (query-loop card titles use isLink) read as
   headings first — ink, like the design system's ServiceCard title — with
   the shift to brand red reserved for hover, rather than permanently red
   running text. */
.wp-block-post-title,
.wp-block-post-title a {
  color: var(--btm-ink);
}

.wp-block-post-title a:hover,
.wp-block-post-title a:focus-visible {
  color: var(--btm-red);
}

/* --- Eyebrow / kicker label --------------------------------------------------
   12px Poppins SemiBold, uppercase, wide tracking, Big Top Red by default —
   individual patterns override the colour inline for dark surfaces. */

.bt-eyebrow {
  /* Block, not inline-block: constrained group layout applies its
     max-width + auto margins to block-level children only, so an
     inline-block eyebrow escaped the content column entirely — measured
     320px left of its own H1 at a 1920 viewport, and centred eyebrows sat
     flush left for the same reason. The case-study hero's one-line
     sector-year row gets its flow from a flex wrapper in the pattern, not
     from inline display here. */
  display: block;
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-semibold);
  font-size: var(--btm-text-base);
  letter-spacing: var(--btm-tracking-wide);
  text-transform: uppercase;
  /* 2026-08 design revision: 16px labels in the deep eyebrow red on light
     surfaces; dark-surface patterns override the colour inline as before. */
  color: var(--btm-red-deep);
  margin: 0 0 var(--btm-space-2);
}

/* --- Links -------------------------------------------------------------------
   Default link colour is brand red, darkening on hover — the base contract
   from the design system's own tokens/base.css. */

a {
  color: var(--btm-red);
  text-decoration: none;
  transition: color var(--btm-transition-fast);
}

a:hover,
a:focus {
  color: var(--btm-red-700);
}

/* Accessible focus ring, using the token built for it, on anything a
   keyboard user can land on. */
a:focus-visible,
button:focus-visible,
.wp-block-button__link:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: none;
  box-shadow: var(--btm-ring-focus);
}

/* --- Navigation ----------------------------------------------------------
   Nav links are chrome, not running body copy: ink by default, shifting to
   red on hover or when marking the current page — mirrors the design
   system's Navbar reference, which keeps nav text on --text-strong and
   reserves --color-primary for the active link.

   Core's own navigation-item__content rule repeats its class
   (".wp-block-navigation-item__content.wp-block-navigation-item__content")
   to deliberately outrank ordinary theme selectors with `color: inherit`.
   Matching that shape (plus a leading type selector) is required to win on
   specificity rather than by accident of enqueue order. */

/* Core navigation defaults to a 0.5em gap — six items render crushed
   together (measured 8px at 1920; 24px was still tight on review). Nav
   items breathe at --btm-space-7, and the flex group holding nav + CTA
   button gets the SAME gap, so Contact sits as far from "Start a project"
   as it does from Insights — that seam used to fall back to core's small
   default and read as one crowded cluster. The footer's vertical list
   keeps its own tighter rhythm. */
.bt-header nav.wp-block-navigation,
.bt-header nav.wp-block-navigation .wp-block-navigation__container,
.bt-header .wp-block-group.is-layout-flex {
  gap: var(--btm-space-7);
}

nav.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content {
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-regular);
  color: var(--btm-ink);
}

nav.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content:hover,
nav.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content:focus {
  color: var(--btm-red);
}

nav.wp-block-navigation .current-menu-item > .wp-block-navigation-item__content.wp-block-navigation-item__content {
  color: var(--btm-red);
}

/* 2026-08 design revision: the header sits on the navy ink surface on every
   page, so its nav links are 20px Manrope in white, warming to yellow on
   hover — the established accent-on-dark convention. Scoped under .bt-header
   so the (light) footer navigation keeps the ink/red contract above. */
.bt-header nav.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content {
  font-size: var(--btm-text-lead);
  color: var(--btm-white);
}

.bt-header nav.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content:hover,
.bt-header nav.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content:focus {
  color: var(--btm-yellow);
}

.bt-header nav.wp-block-navigation .current-menu-item > .wp-block-navigation-item__content.wp-block-navigation-item__content {
  color: var(--btm-yellow);
}

/* Core's mobile overlay panel paints white by default; on the dark header it
   opens as a navy sheet with the same white links. The selector deliberately
   mirrors core's own — `.wp-block-navigation:not(.has-background)
   .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay)`
   — because `:not()` counts its argument, putting core's white at (0,5,0);
   the shorter form this used to be (0,3,0) lost, and the sheet opened white
   under white links (the 2026-08-22 "dropdown is white on white" report).
   The padding is ours for the same reason the colour is: core pads the sheet
   with `clamp(1rem, var(--wp--style--root--padding-left), 20rem)`, and
   GeneratePress defines no root padding, so that declaration is invalid and
   the links sat flush against the screen edge. The inset repeats the header
   pattern's own padding (global-header.php) so the close button opens where
   the burger was and the links line up with the logo. */
.bt-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
  background-color: var(--btm-ink);
  padding: var(--btm-space-5) var(--btm-section-x) var(--btm-space-6);
}

.bt-header .wp-block-navigation__responsive-container-open,
.bt-header .wp-block-navigation__responsive-container-close {
  color: var(--btm-white);
}

/* Core's desktop dropdown (the Services submenu) also paints a white panel
   with black text by default — but the header rule above turns every nav
   link white, submenu links included, which left the dropdown unreadable
   (white on white; 2026-08-22 review). The panel takes the header's own
   surface and contract instead: navy, white links, yellow hover. A hairline
   border and the tile radius separate it from the hero it opens over.
   Submenu links drop to body size with a little more padding so six
   service names read as a list rather than a second nav bar; they never
   wrap, which is what lets the panel grow past core's 200px floor for a
   longer service name (core's open-state rules own `min-width` at (0,5,0),
   so a floor declared here would only ever size the hidden, closed box).
   `:not(.has-background)` mirrors the overlay rule: our navy steps aside
   the same way core's white does if a nav background is ever set in the
   editor. Inside the mobile overlay core lays submenus out inline, where
   the same navy is simply the sheet's colour. */
.bt-header .wp-block-navigation:not(.has-background) .wp-block-navigation__submenu-container {
  background-color: var(--btm-ink);
  color: var(--btm-white);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--btm-radius-md);
  padding: var(--btm-space-2) 0;
}

.bt-header .wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content.wp-block-navigation-item__content {
  font-size: var(--btm-text-base);
  padding: var(--btm-space-2) var(--btm-space-5);
  white-space: nowrap;
}

/* The chevron that opens that dropdown without hover (keyboard, touch on a
   tablet) is a core button drawn in `currentColor`; it sits outside the
   link, so the white-link rule never reached it and it rendered navy on
   navy at 0.6em of the item's 16px — an invisible 9.6px target. Colour it
   like the links, size it to the link's type and pad it to a real target
   (12px glyph + 8px each side). `content-box` matters: the theme's global
   border-box would fold the padding into core's 0.6em width. Core hides
   this icon inside the mobile overlay (submenus are inline there); this
   rule leaves `display` alone so that still holds. */
.bt-header nav.wp-block-navigation .wp-block-navigation__submenu-icon {
  box-sizing: content-box;
  font-size: var(--btm-text-lead);
  padding: var(--btm-space-2);
  margin-left: 0;
  color: var(--btm-white);
  border-radius: var(--btm-radius-md);
  transition: color var(--btm-transition-fast);
}

.bt-header nav.wp-block-navigation .wp-block-navigation__submenu-icon:hover,
.bt-header nav.wp-block-navigation .wp-block-navigation__submenu-icon:focus-visible,
.bt-header nav.wp-block-navigation .wp-block-navigation__submenu-icon[aria-expanded="true"],
.bt-header nav.wp-block-navigation .wp-block-navigation-item__content:hover + .wp-block-navigation__submenu-icon {
  color: var(--btm-yellow);
}

/* --- Buttons -----------------------------------------------------------------
   Pill-shaped. Primary solid red inverting on hover to a white pill with a
   red ring and red label (design PDF p3, 2026-08-21 review); secondary a
   light-blue solid; accent yellow with ink text; outline and ghost round out
   the documented contract even though no pattern currently uses them.
   Motion: colour + shadow shift on hover, a 1px downward nudge on press —
   never a scale change. Every transition here is neutralised by motion.css's
   `prefers-reduced-motion` guard, which targets `*`.

   Selectors target `.wp-block-button__link.wp-element-button` (both classes
   already present on every button link WordPress renders) rather than just
   `.wp-block-button__link`: GeneratePress's own default button colour rule is
   `a.wp-block-button__link:not(.has-background)`, which carries specificity
   (0,2,1) — one class higher than a plain two-class selector like
   `.bt-button--primary .wp-block-button__link` (0,2,0), so it would win
   regardless of stylesheet order. The extra class brings ours to (0,3,0). */

.bt-button .wp-block-button__link.wp-element-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btm-space-2);
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-medium);
  /* 2026-08 design revision: 20px label in a 55px pill (the Figma buttons
     measure 55–60px tall with 20px Manrope). --btm-button-height keeps the
     tap-target floor with room to spare. */
  font-size: var(--btm-text-lead);
  line-height: 1;
  min-height: var(--btm-button-height);
  padding: var(--btm-space-2) var(--btm-space-5);
  border-radius: var(--btm-radius-pill);
  /* 2px, not 1px, so the primary hover's red ring (design PDF p3,
     2026-08-21) reads at the outline variant's weight — carried on every
     state so no geometry shifts at the hover boundary. */
  border: 2px solid transparent;
  cursor: pointer;
  transition:
    background-color var(--btm-transition-fast),
    color var(--btm-transition-fast),
    border-color var(--btm-transition-fast),
    box-shadow var(--btm-transition-fast),
    transform var(--btm-transition-fast);
}

.bt-button .wp-block-button__link.wp-element-button:active {
  transform: translateY(1px);
}

/* Primary — the 2026-08 revision's bright CTA red. Hover inverts the pill:
   white fill, red ring, red label (design PDF p3, 2026-08-21 review — the
   earlier darken-to-brand-red hover was off-spec). Press tints the white
   with red-50 under the shared 1px nudge. */
.bt-button--primary .wp-block-button__link.wp-element-button {
  background-color: var(--btm-red-bright);
  border-color: var(--btm-red-bright);
  color: var(--btm-white);
}

.bt-button--primary .wp-block-button__link.wp-element-button:hover,
.bt-button--primary .wp-block-button__link.wp-element-button:focus-visible {
  background-color: var(--btm-white);
  border-color: var(--btm-red-bright);
  color: var(--btm-red-bright);
  box-shadow: var(--btm-shadow-sm);
}

.bt-button--primary .wp-block-button__link.wp-element-button:active {
  background-color: var(--btm-red-50);
  border-color: var(--btm-red-bright);
  color: var(--btm-red-bright);
}

/* Secondary — light-blue solid. */
.bt-button--secondary .wp-block-button__link.wp-element-button {
  background-color: var(--btm-blue);
  border-color: var(--btm-blue);
  color: var(--btm-ink);
}

.bt-button--secondary .wp-block-button__link.wp-element-button:hover,
.bt-button--secondary .wp-block-button__link.wp-element-button:focus-visible {
  background-color: var(--btm-blue-600);
  border-color: var(--btm-blue-600);
  color: var(--btm-ink);
  box-shadow: var(--btm-shadow-sm);
}

.bt-button--secondary .wp-block-button__link.wp-element-button:active {
  background-color: var(--btm-blue-800);
  border-color: var(--btm-blue-800);
  color: var(--btm-white);
}

/* Accent — yellow with ink text at rest; on hover it swaps to the CTA red
   with white text (Richard, 2026-08-23: the CTA band's yellow stays, the
   rollover goes red/white). */
.bt-button--accent .wp-block-button__link.wp-element-button {
  background-color: var(--btm-yellow);
  border-color: var(--btm-yellow);
  color: var(--btm-ink);
}

.bt-button--accent .wp-block-button__link.wp-element-button:hover,
.bt-button--accent .wp-block-button__link.wp-element-button:focus-visible {
  background-color: var(--btm-red-bright);
  border-color: var(--btm-red-bright);
  color: var(--btm-white);
  box-shadow: var(--btm-shadow-sm);
}

.bt-button--accent .wp-block-button__link.wp-element-button:active {
  background-color: var(--btm-red-700);
  border-color: var(--btm-red-700);
  color: var(--btm-white);
}

/* Outline — red hairline on transparent. Not yet used by a pattern, but part
   of the documented button contract, so it ships ready. */
.bt-button--outline .wp-block-button__link.wp-element-button {
  background-color: transparent;
  border: 2px solid var(--btm-red);
  color: var(--btm-red);
}

.bt-button--outline .wp-block-button__link.wp-element-button:hover,
.bt-button--outline .wp-block-button__link.wp-element-button:focus-visible {
  background-color: var(--btm-red-50);
  border-color: var(--btm-red-700);
  color: var(--btm-red-700);
}

.bt-button--outline .wp-block-button__link.wp-element-button:active {
  background-color: var(--btm-red-100);
}

/* Ghost — text only. */
.bt-button--ghost .wp-block-button__link.wp-element-button {
  background-color: transparent;
  border-color: transparent;
  color: var(--btm-red);
}

.bt-button--ghost .wp-block-button__link.wp-element-button:hover,
.bt-button--ghost .wp-block-button__link.wp-element-button:focus-visible {
  background-color: var(--btm-grey-100);
  color: var(--btm-red-700);
}

.bt-button--ghost .wp-block-button__link.wp-element-button:active {
  background-color: var(--btm-grey-200);
}

/* --- Cards ---------------------------------------------------------------
   bt-service-card, bt-card and bt-quote already carry background, border
   and radius as inline block styles (patterns set those directly); this
   layer adds the resting shadow and hover lift that inline block styles
   cannot express. bt-insight-card ships with no inline surface at all, so
   it gets the same white/hairline/radius contract here. bt-work-card sits
   directly on the dark .bt-work section as a portfolio tile rather than a
   boxed card, so it gets a hover cue and legible text on dark instead. */

.bt-service-card,
.bt-insight-card,
.bt-card,
.bt-quote {
  box-shadow: var(--btm-shadow-sm);
  transition:
    transform var(--btm-transition-base),
    box-shadow var(--btm-transition-base);
}

.bt-service-card:hover,
.bt-insight-card:hover,
.bt-card:hover,
.bt-quote:hover {
  transform: translateY(-4px);
  box-shadow: var(--btm-shadow-lg);
}

/* Journal tiles (2026-08 design revision): white, 20px radius, the image
   flush to the card's top edge and the text padded beneath it. */
.bt-insight-card {
  background-color: var(--btm-white);
  border-radius: var(--btm-radius-tile);
  padding: 0 var(--btm-space-6) var(--btm-space-6);
}

.bt-work-card {
  transition: transform var(--btm-transition-base);
}

.bt-work-card:hover {
  transform: translateY(-4px);
}

.bt-work-card .wp-block-post-title,
.bt-work-card .wp-block-post-title a {
  color: var(--btm-white);
}

.bt-work-card .wp-block-post-title a:hover,
.bt-work-card .wp-block-post-title a:focus-visible {
  color: var(--btm-yellow);
}

/* Eyebrow-style sector label. Matches .bt-eyebrow's weight/size/case/tracking
   contract (see above) rather than inheriting it directly, because the
   pattern needs --btm-yellow here, not .bt-eyebrow's --btm-red default, and
   the eyebrow's own bottom-only margin isn't enough on its own: with zero
   margin this sat flush against both the featured image above it and the
   title below (see tests/test-loops.php's Fix 3 coverage for the anchor half
   of this bug) — margin-top separates it from the unrelated image, and a
   smaller margin-bottom keeps it visually grouped with the title it labels. */
.bt-work-card__sector {
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-semibold);
  font-size: var(--btm-text-xs);
  text-transform: uppercase;
  letter-spacing: var(--btm-tracking-wide);
  color: var(--btm-yellow);
  margin: var(--btm-space-3) 0 var(--btm-space-2);
}

.bt-service-card img,
.bt-work-card img,
.bt-insight-card img {
  display: block;
  width: 100%;
  height: auto;
}

/* The 2026-08 design revision's service cards carry no running number — the
   counter device from the first design round was removed with it. */

/* Service-card hover (design PDF p2, 2026-08-21 review): the card inverts
   to the CTA red with white copy, and a long-tail arrow surfaces at the
   title's right edge. !important on the surface is required, not a
   shortcut: the pattern serialises the resting white background as a
   Gutenberg inline block style, which no ordinary selector can outrank
   (same structural reason as motion.css's .bt-force-visible). The title
   row becomes a flex pair so the arrow — a white-painted mask; it only
   ever shows against the hover red — sits opposite the heading; it is
   present but transparent at rest, so nothing reflows on hover.
   :focus-within mirrors every state for the keyboard path. */
.bt-service-card:hover,
.bt-service-card:focus-within {
  background-color: var(--btm-red-bright) !important;
}

.bt-service-card .wp-block-post-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--btm-space-4);
}

.bt-service-card .wp-block-post-title::after {
  content: "";
  flex: 0 0 auto;
  /* 21×14: the design's arrow measures ~1.1× the title's cap height, not
     the 34px first cut (2026-08-21 review, checked scale-free against the
     PDF). The mask scales the whole SVG, so the stroke thins with it. */
  width: 21px;
  height: 14px;
  background-color: var(--btm-white);
  -webkit-mask: url("../img/redesign/arrow-cta.svg") no-repeat center / contain;
  mask: url("../img/redesign/arrow-cta.svg") no-repeat center / contain;
  opacity: 0;
  transition: opacity var(--btm-transition-fast);
}

.bt-service-card:hover .wp-block-post-title::after,
.bt-service-card:focus-within .wp-block-post-title::after {
  opacity: 1;
}

.bt-service-card:hover .wp-block-post-title,
.bt-service-card:focus-within .wp-block-post-title,
.bt-service-card:hover .wp-block-post-title a,
.bt-service-card:focus-within .wp-block-post-title a,
.bt-service-card:hover .wp-block-post-excerpt__excerpt,
.bt-service-card:focus-within .wp-block-post-excerpt__excerpt {
  color: var(--btm-white);
}

/* Hero photographs: the reference's device of a wide rounded image closing
   the dark hero band. Radius and rhythm live here rather than as inline
   block styles so the pattern markup stays the minimal canonical wp:image
   shape. */
.bt-hero__image {
  margin-top: var(--btm-space-7);
}

.bt-hero__image img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--btm-radius-lg);
}

/* Check chips: the reference's circled-tick device, used on the service
   pages' approach band (yellow chip on ink) and process cards. */
.bt-check-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--btm-space-6);
  height: var(--btm-space-6);
  flex-shrink: 0;
  border-radius: var(--btm-radius-circle);
  background-color: var(--btm-yellow);
  color: var(--btm-ink);
}

/* The bridge photograph: opens the ink chips band and pulls up over the
   seam with the white intro above it — the reference's device of an image
   straddling the light/dark boundary. The pull is half the section rhythm,
   so it scales down with --btm-section-y at the breakpoints and can never
   reach the prose above. */
.bt-svc-bridge {
  margin-top: calc(-0.5 * var(--btm-section-y) - var(--btm-space-8));
  margin-bottom: var(--btm-space-8);
}

.bt-svc-bridge img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--btm-radius-lg);
}

/* Differentiator items: hairline-ruled rows, per the reference's
   "superpowers" list. Spacing lives with the process-card rules above.
   The heading gets a step more air than the base heading margin — at
   16px it sat noticeably tighter than the reference (2026-08-02). */
.bt-diff-item {
  border-bottom: 1px solid var(--btm-grey-200);
}

.bt-diff-item h3 {
  margin-bottom: var(--btm-space-5);
}

.bt-services-intro__photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--btm-radius-lg);
}

.bt-svc-split__image img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--btm-radius-lg);
}

/* FAQ accordion (core/details): card chrome, Poppins summary, and the
   native marker replaced with a +/- cue that the summary's open state
   flips. */
.bt-faq details {
  background-color: var(--btm-white);
  border: 1px solid var(--btm-grey-200);
  border-radius: var(--btm-radius-lg);
  padding: var(--btm-space-5) var(--btm-space-6);
  margin-bottom: var(--btm-space-3);
}

.bt-faq summary {
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-semibold);
  font-size: var(--btm-text-h4);
  color: var(--btm-ink);
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--btm-space-4);
}

.bt-faq summary::-webkit-details-marker {
  display: none;
}

.bt-faq summary::after {
  content: "+";
  font-weight: var(--btm-fw-regular);
  color: var(--btm-red);
  flex-shrink: 0;
}

.bt-faq details[open] summary {
  margin-bottom: var(--btm-space-3);
}

.bt-faq details[open] summary::after {
  content: "\2212";
}

/* Process cards (the shared card row): reference anatomy — everything
   centred, cards fill their row, and the Step pill pins to the bottom so
   the three pills sit level. The chip centres via text-align (it is
   inline-flex). */
.bt-card-row .bt-card,
.bt-svc-process .bt-card {
  text-align: center;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.bt-card-row .bt-card > .wp-block-group__inner-container,
.bt-svc-process .bt-card > .wp-block-group__inner-container {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.bt-card-row .bt-card .bt-check-chip,
.bt-svc-process .bt-card .bt-check-chip {
  /* The flex-column card blockifies the inline chip, so text-align no
     longer places it — flex self-alignment does. The margin matches the
     About page's chip-to-title gap. */
  align-self: center;
  margin-bottom: var(--btm-space-3);
}

.bt-card-row .bt-card p:not(.bt-card__step) {
  margin-bottom: var(--btm-space-5);
}

/* The Step pill: ink capsule with accent text, self-centred at the bottom
   of the flex-column card (margin-top auto pins it; the extra space above
   keeps it clear of the copy on the shortest card). */
.bt-card__step {
  align-self: center;
  margin-top: auto;
  position: relative;
  top: 0;
  margin-bottom: 0;
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-semibold);
  font-size: var(--btm-text-sm);
  line-height: 1;
  color: var(--btm-yellow);
  background-color: var(--btm-ink);
  border-radius: var(--btm-radius-pill);
  padding: var(--btm-space-3) var(--btm-space-5);
}

.bt-card-row .bt-card .bt-check-chip + h3,
.bt-card-row .bt-card h3 {
  margin-top: 0;
}

/* There used to be a section-rhythm exception here zeroing the
   testimonials band's top padding on service singles, from when the band
   shared the FAQ's faun surface and the two paddings read as one 176px
   gap. The 2026-08 revision made the band white, so the surface change
   now marks the boundary and the full --btm-section-y padding is the
   rhythm every other surface change on the site uses. The rule outlived
   its reason and left the "What our clients say" header 24px from the
   seam (2026-08-23 review); it is gone, not relocated. */

/* Equal-height testimonial cards: fill the grid row and pin the
   attribution block to the bottom edge so the name lines up across the
   three cards regardless of quote length. Scoped to the loop grid — the
   About page's static pull quote must not stretch to its column. */
.bt-testimonials__grid .bt-quote {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.bt-testimonials__grid .bt-quote > .wp-block-group__inner-container {
  display: flex;
  flex-direction: column;
  flex: 1;
}

/* The attribution row pins to the card's bottom edge so avatars line up
   across the three cards regardless of quote length. (The 2026-08 design
   revision replaced the in-card YouTube embeds with client logo + avatar;
   each testimonial's video URL is preserved in bigtop_video_url post meta.) */
.bt-testimonials__grid .bt-quote .bt-quote__meta {
  margin-top: auto;
}

/* Quote copy at the design's 20px. The margins are pinned because the two
   places this card appears give .bt-quote__text different elements: in
   the homepage loop it is core's post-content wrapper, which GP's
   `.entry-content:not(:first-child) { margin-top: 2em }` pushed 40px
   below the logo; on the About page it is a bare <p> with the body
   16px bottom margin. The design has the quote ~20px under the logo
   (Website Design.pdf p1: logo bottom y=5530, quote line box y=5548),
   so both collapse to the logo's own 24px margin and the meta row's
   24px padding (2026-08-23 review). The second selector is the
   homepage case at (0,3,0), so it outranks GP's rule on specificity,
   not just on load order. */
.bt-quote .bt-quote__text,
.bt-quote .bt-quote__text.entry-content {
  margin-top: 0;
  margin-bottom: 0;
  font-size: var(--btm-text-lead);
}

/* Client logo at the card's top edge: contained, left-aligned, capped so the
   three logos read as one row (the design renders them 53–64px tall). */
.bt-quote__logo {
  margin: 0 0 var(--btm-space-5);
}

.bt-quote__logo img {
  display: block;
  width: auto;
  max-width: 70%;
  max-height: 64px; /* design magnitude — logo cap inside the quote card */
  object-fit: contain;
}

/* Avatar + name + role. The avatar is a 60px circle (design magnitude).
   nowrap matters: WordPress's flex-group layout defaults to flex-wrap:wrap,
   and a flex line-break decision uses the item's *max-content* width — so
   an attribution with one long line (David Powell's "Chartered Accountants
   Worldwide Network USA", 2026-08-21 review; shortened to "CAW Network
   USA" in the DB on 2026-08-22, but the rule stays — the cause is
   structural) dropped the whole text block underneath the avatar instead
   of wrapping its own text. Forcing one flex
   line makes the text column shrink and wrap internally, keeping the
   portrait beside the name for any attribution length; min-width:0 on the
   text group releases the min-content floor so that shrink can happen.

   The portrait itself must be exempt from that shrink: a flex item gives
   up width in proportion to flex-shrink × its basis, so with the default
   flex-shrink:1 the long attribution squeezed David's 60px figure to 38px
   wide while its height stayed 60 — an oval under border-radius:50%
   (2026-08-22 review; the other two cards' text is short enough that
   nothing shrank). flex: 0 0 auto means only the text column ever gives. */
.bt-quote__meta {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--btm-space-4);
  padding-top: var(--btm-space-5);
}

.bt-quote__meta > .wp-block-group {
  min-width: 0;
}

.bt-quote__meta .bt-quote__avatar {
  flex: 0 0 auto;
}

.bt-quote__meta .bt-quote__avatar img {
  display: block;
  width: 60px;
  height: 60px;
  border-radius: var(--btm-radius-circle);
  object-fit: cover;
}

.bt-quote__meta p {
  margin: 0;
}

/* Icon stat chips on the homepage about teaser — the reference's circled
   glyph beside each figure. The SVG inherits ink via currentColor. */
/* Stacked, centred stat: figure over chip over label. The chip span is
   inline-level, so centring comes from the group's text-align, not auto
   margins (2026-08-02 review — the flex-row treatment read as staggered). */
.bt-stat {
  text-align: center;
}

.bt-stat__chip {
  margin-bottom: var(--btm-space-3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--btm-space-8);
  height: var(--btm-space-8);
  flex-shrink: 0;
  border-radius: var(--btm-radius-circle);
  background-color: var(--btm-grey-100);
  color: var(--btm-ink);
}

.bt-about-teaser__image img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--btm-radius-lg);
}

/* The rule between the split and the stat row breathes at the section-gap
   rhythm rather than core's default separator margins. */
.bt-about-teaser__rule {
  margin-top: var(--btm-section-gap);
  margin-bottom: var(--btm-section-gap);
}

/* Section headers centre everything they contain. The eyebrow needs this
   at the container level: .bt-eyebrow is display:inline-block, so the
   shrink-wrapped box follows the PARENT's text-align — the paragraph's own
   has-text-align-center only centres text inside the box (2026-08-01
   verification pass caught every section-header eyebrow sitting flush
   left). */
.bt-section-header {
  text-align: center;
}

/* Work cards lead with the client name (bound from bigtop_client in the
   loop patterns): the visual headline without being a heading, so the card's
   outline entry stays the full linked title below it. Poppins and the h3
   size make it read as the lead; the linked title beneath is the smaller
   support line. */
.bt-work-card__client {
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-bold);
  font-size: var(--btm-text-h3);
  line-height: var(--btm-leading-snug);
  margin: 0 0 var(--btm-space-1);
}

.bt-work-card .wp-block-post-title {
  margin: 0;
}

/* The card's link affordance — a styled core/read-more block. The arrow
   glyph lives in the block's own text, not in CSS content, so the stylesheet
   stays free of copy. */
.bt-service-card .wp-block-read-more,
.bt-insight-card .wp-block-read-more {
  display: inline-block;
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-semibold);
  font-size: var(--btm-text-sm);
  color: var(--btm-red);
  margin-top: var(--btm-space-4);
}

.bt-service-card .wp-block-read-more:hover,
.bt-service-card .wp-block-read-more:focus-visible,
.bt-insight-card .wp-block-read-more:hover,
.bt-insight-card .wp-block-read-more:focus-visible {
  color: var(--btm-red-700);
}

/* Full-bleed CPT singles: the theme's default 32px top margin on the
   post-content wrapper painted a page-background band between the hero and
   the first content section (2026-08-02 review, measured on
   /services/audio-podcasts/). The template sections carry their own
   rhythm. */
.single-service .wp-block-post-content.entry-content,
.single-case_study .wp-block-post-content.entry-content {
  margin-top: 0;
}

/* Differentiator rows: more air either side of each hairline. */
.bt-diff-item {
  padding-bottom: var(--btm-space-6);
}

.bt-diff-item + .bt-diff-item {
  margin-top: var(--btm-space-6);
}

/* Articles read at a book measure, not a layout width: with the sidebar
   gone the post column stretched to ~1100px of running text (2026-08-01
   verification pass). Container-sm matches the case-study and service
   prose measure. */
/* One extra ancestor: GeneratePress's dynamic CSS loads after this sheet
   and re-zeroes .site-main margins at equal specificity — measured live,
   the column sat flush left (2026-08-02 review). */
.single-post .site-content .site-main {
  max-width: var(--btm-container-sm);
  margin-left: auto;
  margin-right: auto;
}

/* GP's back-to-top control ships translucent black; brand it. */
a.generate-back-to-top {
  background-color: var(--btm-red);
  color: var(--btm-white);
  border-radius: var(--btm-radius-circle);
}

a.generate-back-to-top:hover,
a.generate-back-to-top:focus {
  background-color: var(--btm-red-500);
  color: var(--btm-white);
}

/* At the very bottom of a phone-width page the fixed button (GP: 40px
   square, 30px in from the right and bottom edges) lands on the legal
   bar, covering the end of the first line ("Company N…", measured at
   390px). Reserving its column on the paragraph — not the group, whose
   padding is an inline block style — lets the text wrap clear of it.
   80px = the button's 70px footprint plus a little air. Above 767px the
   line is one line ending well short of the button. */
@media (max-width: 767px) {
  .bt-legal-bar p {
    padding-right: 80px;
  }
}

/* Mobile header: one compact row, like the reference's. Without this the
   header's two inner flex groups wrap into a ~165px two-row stack — logo
   row, then hamburger + CTA row — spending ~11% of a 390px viewport before
   any content (2026-08-01 design review, measured). The logo steps down,
   the header CTA hides (the hero and the sitewide CTA band both carry
   "Start a project" on every page), and the hamburger keeps its 44px hit
   area from the rule above. */
@media (max-width: 767px) {
  .bt-header .wp-block-group {
    flex-wrap: nowrap;
  }

  /* Core's hamburger only takes over at 600px; between 601 and 767px the
     links still render inline, so they must be allowed to wrap. */
  .bt-header nav.wp-block-navigation .wp-block-navigation__container {
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--btm-space-3) var(--btm-space-5);
  }

  .bt-header .wp-block-site-logo img {
    width: auto;
    max-height: var(--btm-space-7);
  }

  .bt-header .wp-block-buttons {
    display: none;
  }
}

/* Insight-card images bleed to the card edges (reference treatment) instead
   of floating inset inside the card's padding. The negative margins undo the
   card's own --btm-space-6 padding; overflow keeps the image inside the
   card's rounded corners. */
.bt-insight-card {
  overflow: hidden;
  /* Fill the grid item so every card in a row is the same height, and
     flow as a column so the read-more can pin to the bottom edge. */
  height: 100%;
  display: flex;
  flex-direction: column;
}

/* Legacy group serialisations wrap children in an inner container; make it
   transparent to the column flow so the pin still reaches the bottom. */
.bt-insight-card > .wp-block-group__inner-container {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.bt-insight-card .wp-block-read-more {
  margin-top: auto;
  padding-top: var(--btm-space-4);
}

.bt-insight-card .wp-block-post-featured-image {
  margin: 0 calc(-1 * var(--btm-space-6)) var(--btm-space-5);
}

.bt-insight-card .wp-block-post-featured-image img {
  border-radius: 0;
}

/* The Journal card's link affordance (2026-08 revision): 20px ink text over
   the design's full-width underline stroke. */
.bt-insight-card .wp-block-read-more {
  font-family: var(--btm-font-body);
  font-weight: var(--btm-fw-regular);
  font-size: var(--btm-text-lead);
  color: var(--btm-ink);
  width: max-content;
  border-bottom: 1px solid currentColor;
  padding-bottom: var(--btm-space-2);
}

.bt-insight-card .wp-block-read-more:hover,
.bt-insight-card .wp-block-read-more:focus-visible {
  color: var(--btm-red-bright);
}

/* An odd count in the 2-column work grid used to strand a card beside a
   ~550px dark void (7 case studies today). The last odd card becomes a
   full-width feature row instead; the rule dissolves on its own the moment
   an eighth case study lands, and the stagger token already zeroes itself
   below 1024px. */
.bt-work__grid > *:last-child:nth-child(odd),
.bt-work-index__grid > *:last-child:nth-child(odd) {
  grid-column: 1 / -1;
}

/* When a featured image carries the block's own aspect-ratio lock, the
   generic height:auto above must yield: the block sets height:100% +
   object-fit so the artwork fills the locked frame. Without this, an image
   smaller than its frame floats at intrinsic size inside it. */
.bt-work-card figure[style*="aspect-ratio"] img,
.bt-insight-card figure[style*="aspect-ratio"] img {
  height: 100%;
  object-fit: cover;
}

/* Mobile nav toggles ship from core at their 24px icon size; the icon stays
   24px but the hit area meets the tap-target floor. */
.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
  min-width: var(--btm-tap-target);
  min-height: var(--btm-tap-target);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Post navigation on articles: the theme's bare "< previous" text link,
   promoted to the same chrome treatment as the nav. */
.post-navigation a,
.paging-navigation a {
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-semibold);
  color: var(--btm-red);
}

/* The comment form's native submit is the one form control on the site that
   neither base.css's button contract nor Gravity's property layer reaches —
   it rendered unbranded dark grey (2026-08-01 review). Scoped to the comment
   form so Gravity's own submit, which resolves through --gf-* properties,
   is never double-styled. */
.comment-form input[type="submit"] {
  font-family: var(--btm-font-heading);
  font-weight: var(--btm-fw-semibold);
  font-size: var(--btm-text-base);
  line-height: 1;
  min-height: var(--btm-tap-target);
  padding: var(--btm-space-3) var(--btm-space-5);
  border-radius: var(--btm-radius-pill);
  border: 1px solid var(--btm-red);
  background-color: var(--btm-red);
  color: var(--btm-white);
  cursor: pointer;
  transition:
    background-color var(--btm-transition-fast),
    box-shadow var(--btm-transition-fast);
}

.comment-form input[type="submit"]:hover,
.comment-form input[type="submit"]:focus-visible {
  background-color: var(--btm-red-500);
  border-color: var(--btm-red-500);
  box-shadow: var(--btm-shadow-sm);
}

/* Map embeds: the raw iframe carries fixed width/height attributes sized for
   a desktop column, which rendered as a 216×450 portrait strip at 390px
   (2026-08-01 review). Width tracks the card, height follows a 4:3 ratio —
   a proportion, not a magnitude, so no token is bypassed. */
.bt-card iframe {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  border: 0;
  border-radius: var(--btm-radius-md);
}

/* --- Section rhythm note (rule retired 2026-08-21) ------------------------
   An earlier rule here collapsed the doubled seam between a --btm-faun
   section closing a page and the then-Faun footer:

     article.type-page .entry-content > [style*="var(--btm-faun)"]:last-child
       { padding-bottom: 0 !important; }

   The 2026-08 design revision repainted the footer white
   (patterns/global-footer.php), so every content/footer boundary now
   contrasts in tone and needs the full --btm-section-y on both sides. Left
   in place, the rule had started stripping the Journal band's bottom
   padding on the homepage — the grid sat flush on the section edge
   (2026-08-21 design review, measured: computed padding-bottom 0 against
   the pattern's inline var(--btm-section-y)). If a Faun-on-Faun seam ever
   returns, restore the rule with its original docblock (git history,
   commit series around 2026-08-05). */

/* Gravity Forms.
   ------------------------------------------------------------------
   The plugin ships its own palette and nothing in this theme had ever
   spoken to it. On /contact/ that produced a #204CE5 submit button —
   Gravity's default blue — under a #8C2927 header, on a page where every
   other control is brand red. Measured, not eyeballed: getComputedStyle
   on #gform_submit_button_2 returned rgb(32, 76, 229).

   This drives Gravity's own custom properties rather than overriding its
   rules. The obvious approach — `.gform_wrapper .gform_button {
   background-color: var(--btm-red) }` — loses, even though the element
   genuinely matches that selector (confirmed with Element.matches() in a
   real browser). Gravity 2.10's Orbital theme resolves colour through
   --gf-* properties, so an equal-specificity override loaded earlier
   never gets a say. Re-pointing the properties wins without a
   specificity war and survives plugin updates, because these names are
   Gravity's documented theming surface rather than its internal
   selectors.

   The class is repeated to reach specificity (0,2,0): Gravity sets some
   of these on `.gform_wrapper.gform-theme--framework`, and a
   single-class selector loses to it. Repeating .gform_wrapper matches
   that weight without coupling this file to Orbital's theme class names,
   which are the part of Gravity's markup most likely to change. Same
   trick, same reason, as the navigation rule above.

   EVERY PROPERTY BELOW WAS VERIFIED TO TAKE EFFECT by reading
   getComputedStyle off the rendered control. That is not pedantry:
   --gf-ctrl-btn-border-radius, --gf-ctrl-border-color,
   --gf-ctrl-label-font-family and --gf-ctrl-required-color were all
   tried, all look plausible, and all do nothing here — the button reads
   --gf-ctrl-btn-radius instead, and the field chrome resolves through a
   derived --gf-local-* layer that a wrapper-level override cannot reach.
   They were removed rather than left in place, because CSS that looks
   like it works is worse than CSS that is absent.

   The consequence: fields keep Gravity's neutral grey border and its own
   required-marker red. Both are legible and neither clashes the way the
   blue button did. Changing them means overriding Gravity's derived
   colour tokens, which couples this file to Orbital's internals — worth
   doing only if the greys become a real complaint.

   Scoped to .gform_wrapper, not to a page, so a form dropped on Request
   a Quote — or any page an editor adds later — inherits the brand
   without anyone remembering to come back here. */
.gform_wrapper.gform_wrapper {
  /* Solid bright red inverting to a white pill with a red ring and red
     label on hover/focus, matching .bt-button--primary (design PDF p3,
     2026-08-21 review — the darken-to-brand-red hover retired with it).
     The /contact/ page shows this submit beside the CTA band's primary
     pill, so the two must move together. */
  --gf-ctrl-btn-bg-color-primary: var(--btm-red-bright);
  --gf-ctrl-btn-bg-color-hover-primary: var(--btm-white);
  --gf-ctrl-btn-bg-color-focus-primary: var(--btm-white);
  --gf-ctrl-btn-border-color-primary: var(--btm-red-bright);
  --gf-ctrl-btn-border-color-hover-primary: var(--btm-red-bright);
  --gf-ctrl-btn-border-color-focus-primary: var(--btm-red-bright);
  --gf-ctrl-btn-color-primary: var(--btm-white);
  --gf-ctrl-btn-color-hover-primary: var(--btm-red-bright);
  --gf-ctrl-btn-color-focus-primary: var(--btm-red-bright);

  /* Gravity's default is 3px; every other button on this site is a pill.
     The property is --gf-ctrl-btn-radius. The similarly named
     --gf-ctrl-btn-border-radius also exists and is not what the submit
     button reads, which is how the first attempt left it square. */
  --gf-ctrl-btn-radius: var(--btm-radius-pill);

  --gf-ctrl-btn-font-family: var(--btm-font-heading);
  --gf-ctrl-btn-font-size: var(--btm-text-base);
  --gf-ctrl-btn-font-weight: var(--btm-fw-semibold);

  /* Field text in the site's body face and ink, so the form reads as
     part of the page rather than as an embedded application. */
  --gf-ctrl-font-family: var(--btm-font-body);
  --gf-ctrl-color: var(--btm-ink);

  /* Field corners. Gravity's own default is 3px and the token is 4px, so
     the difference is one pixel and easy to dismiss as noise — it is
     kept because it was verified to apply (removing it moved the
     rendered radius back to 3px), and because a value that comes from
     the token file is one fewer number to reconcile later. */
  --gf-ctrl-radius: var(--btm-radius-sm);
}

/* Gravity sets no minimum height on its submit; 38px rendered at mobile.
   The property layer has no key for this, so one plain rule. */
.gform_wrapper.gform_wrapper .gform_button {
  min-height: var(--btm-tap-target);
}

/* Checkbox and radio choices as bordered, tappable rows — the reference's
   treatment — instead of bare ~20px native boxes in a stack. The whole row
   is the label's hit area, and accent-color puts the brand on the control
   itself, which is the one part of field chrome the --gf-local-* layer
   (see above) never blocked. Two columns from 768px up, like the
   reference's 2×2 service picker. */
.gform_wrapper.gform_wrapper .gfield_checkbox,
.gform_wrapper.gform_wrapper .gfield_radio {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--btm-space-3);
}

@media (min-width: 768px) {
  .gform_wrapper.gform_wrapper .gfield_checkbox,
  .gform_wrapper.gform_wrapper .gfield_radio {
    grid-template-columns: repeat(2, 1fr);
  }
}

.gform_wrapper.gform_wrapper .gchoice {
  display: flex;
  align-items: center;
  gap: var(--btm-space-3);
  min-height: var(--btm-tap-target);
  padding: var(--btm-space-3) var(--btm-space-4);
  background-color: var(--btm-white);
  border: 1px solid var(--btm-grey-200);
  border-radius: var(--btm-radius-md);
  transition: border-color var(--btm-transition-fast);
}

.gform_wrapper.gform_wrapper .gchoice:hover {
  border-color: var(--btm-grey-400);
}

.gform_wrapper.gform_wrapper .gchoice input[type="checkbox"],
.gform_wrapper.gform_wrapper .gchoice input[type="radio"] {
  accent-color: var(--btm-red);
  width: var(--btm-space-4);
  height: var(--btm-space-4);
  flex-shrink: 0;
}

.gform_wrapper.gform_wrapper .gchoice label {
  cursor: pointer;
  flex: 1;
  margin: 0;
}

/* Focus is deliberately not set here: base.css already gives every
   input, textarea, select and button a --btm-ring-focus ring on
   :focus-visible, and an <input type="submit"> is matched by both of
   those selectors. */

/* ==========================================================================
   2026-08 design revision (design team, Figma "Website Design" 492-1499)
   Homepage + global chrome: dark navy header/hero with the brand watermark,
   a device-framed hero photograph, a scrolling client-logo marquee, the
   about split with circle image and chip stats, column-major staggered
   service cards, a curated dark work grid, logo/avatar testimonial cards,
   Journal tiles and the tent footer with a legal bar.
   ========================================================================== */

/* --- Hero ----------------------------------------------------------------- */

/* The tent floats over the hero's navy at 40% via overlay blend — the same
   art as the footer (footer-tent.svg), not the logo lock-up: the 2026-08-22
   review caught that the first cut used the composite brand watermark.
   Overlay at 0.4 is measured from the design, not guessed: over the ink it
   lifts the cream stripes by ~6 levels and darkens the reds, which is
   exactly what the PDF's hero pixels do.

   Placement follows the design's geometry (Website Design.pdf p1): the art
   is drawn at 202.4% of the page width with its left edge 88.7% off the
   page, so only the right-hand peak shows — flag and pole behind the first
   word of the headline, stripes fanning down-left to the page edge and
   sliding behind the photo frame. The vertical anchor differs slightly: in
   the design the flag rises into the header band (the header and hero are
   one surface there); here the hero clips its overflow, so the flag tip
   sits 12px inside the hero's top edge instead — whole flag visible, pole
   still through "All". 20.96vw is the tip's depth into the art
   (212/2047 of the art's width) scaled to 202.4vw.

   A negative-z pseudo paints above the group's own background but below its
   content (CSS painting order), and isolation keeps the blend inside the
   band. */
.bt-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  text-align: center;
}

.bt-hero::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: calc(12px - 20.96vw);
  left: -88.7%;
  width: 202.4%;
  aspect-ratio: 2047 / 1260;
  background: url("../img/redesign/footer-tent.svg") no-repeat center / contain;
  mix-blend-mode: overlay;
  opacity: 0.4;
  pointer-events: none;
}

/* 100px Manrope Regular, per the design (the only regular-weight heading on
   the site). The measure is capped so the headline breaks at the comma —
   "All your content, / under one big top." — as the design sets it. */
.bt-hero h1 {
  font-weight: var(--btm-fw-regular);
  max-width: 900px; /* design magnitude — headline measure */
  margin-inline: auto;
}

.bt-hero .wp-block-buttons {
  justify-content: center;
}

/* The device frame: a thick rounded bezel around the hero photograph. The
   inner radius follows from the outer minus the bezel so the photo hugs the
   frame at every size. */
.bt-hero__frame {
  margin-top: var(--btm-space-8);
  border: 20px solid var(--btm-grey-device);
  border-radius: var(--btm-radius-device);
  overflow: hidden;
}

.bt-hero__frame img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--btm-radius-device) - 20px);
}

@media (max-width: 767px) {
  .bt-hero__frame {
    border-width: 8px;
    border-radius: var(--btm-radius-card);
  }

  .bt-hero__frame img {
    border-radius: calc(var(--btm-radius-card) - 8px);
  }
}

/* --- Client-logo marquee --------------------------------------------------
   The Figma animation: linear, infinite, ~128px/s. Two identical groups sit
   in a max-content flex track; translating the track by -50% is exactly one
   group's width, so the loop is seamless. motion.css's reduced-motion guard
   neutralises transitions but not keyframes, so the preference is honoured
   here explicitly. */
.bt-marquee {
  overflow: hidden;
  margin-top: var(--btm-space-8);
}

.bt-marquee__track {
  display: flex;
  width: max-content;
  animation: bt-marquee-scroll 22s linear infinite;
}

.bt-marquee__group {
  display: flex;
  align-items: center;
  gap: var(--btm-space-9);
  padding-right: var(--btm-space-9);
}

.bt-marquee__group img {
  display: block;
  width: auto;
  height: 48px; /* design magnitude — uniform logo row on the dark band */
}

@keyframes bt-marquee-scroll {
  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .bt-marquee__track {
    animation: none;
  }
}

/* --- About split ---------------------------------------------------------- */

.bt-about-teaser__circle img {
  display: block;
  width: min(401px, 100%); /* design magnitude — the circle photograph */
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--btm-radius-circle);
  margin-inline: auto;
}

/* Stat rows: yellow chip beside a stacked figure + label (the 2026-08 design
   returns to the horizontal anatomy). */
.bt-stat {
  display: flex;
  align-items: center;
  text-align: left;
  gap: var(--btm-space-5);
}

.bt-stat__chip {
  width: 85px;  /* design magnitude — stat chip circle */
  height: 85px;
  background-color: var(--btm-yellow);
  color: var(--btm-ink);
  margin-bottom: 0;
}

.bt-stat__chip svg {
  width: 42px;
  height: 42px;
}

.bt-stat__figure,
.bt-stat__label {
  text-align: left;
  margin: 0;
}

/* --- Services grid (column-major + stagger) --------------------------------
   The design reads down each column: Graphic, Web, Marketing on the left;
   Audio, Video, E-learning dropped by the stagger on the right. Column-major
   placement keeps the Query Loop's menu_order untouched. Below 782px the
   grid collapses to one column in plain document order.

   The drop is a relative offset, not a margin. A margin on the right-hand
   cards grows every grid ROW by the stagger (auto rows size to their
   tallest item, margin included), so the left column inherited a phantom
   64px on top of the 64px row-gap — panels sat 128px apart (design team,
   2026-08-23: "about 65px"). `top` moves the cards without touching the
   tracks; motion.css animates `transform`, so the two never collide. The
   grid's bottom padding gives the dropped column the room it overhangs
   by, so the View-all button keeps its distance. */
@media (min-width: 782px) {
  .bt-services__grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(3, auto);
    grid-auto-flow: column;
    column-gap: var(--btm-space-8);
    row-gap: var(--btm-space-8);
    padding-bottom: var(--btm-stagger-services);
  }

  .bt-services__grid > *:nth-child(n + 4) {
    position: relative;
    top: var(--btm-stagger-services);
  }
}

/* --- Work grid (dark, curated) --------------------------------------------
   Shares .bt-work chrome with the loop pattern. Figure cards: photograph,
   then sector label, then title. The curated homepage grid lays out here
   (the loop patterns carry their own layout in their markup): two columns,
   right column dropped by the showcase stagger, collapsing to one column
   below 782px. */
.bt-work__grid .bt-work-card img,
.bt-work-home__grid .bt-work-card img {
  border-radius: var(--btm-radius-media);
  width: 100%;
  height: auto;
}

/* The four showcase photographs share one frame. Three sources are 16:9;
   the Kildare Gallery brochure shot is 3:2 (1346×896, the file the design
   itself placed) and rendered 57px taller than its neighbours, which the
   design team flagged (2026-08-23). Cropping in CSS keeps the full frame
   for the case-study hero and means a future swap needs no re-crop. */
.bt-work-home__grid .bt-work-card img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.bt-work-home__grid {
  display: grid;
  grid-template-columns: 1fr;
  column-gap: var(--btm-space-8);
  row-gap: var(--btm-space-8);
}

/* Legacy group serialisations wrap children in an inner container; dissolve
   it so the four cards are the grid's own items — same transparency the
   insight and quote cards need. */
.bt-work-home__grid > .wp-block-group__inner-container {
  display: contents;
}

/* Right column dropped like the services grid (design team, 2026-08-23 —
   the stagger had silently stopped applying: the old rule addressed the
   grid's direct children, and with the inner container in the way the
   cards are grandchildren, so nothing matched). Same relative-offset
   technique as the services grid, for the same row-growth reason. The
   selector counts siblings inside whichever element holds the cards, so
   it works with or without the inner container. */
@media (min-width: 782px) {
  .bt-work-home__grid {
    grid-template-columns: repeat(2, 1fr);
    padding-bottom: var(--btm-stagger-showcase);
  }

  .bt-work-home__grid .bt-work-card:nth-child(2n) {
    position: relative;
    top: var(--btm-stagger-showcase);
  }
}

.bt-work-card__sector {
  color: var(--btm-white); /* 2026-08 revision — was yellow */
}

.bt-work-card__title,
.bt-work-card__title a {
  color: var(--btm-white);
  font-size: var(--btm-text-h3);
  line-height: var(--btm-leading-snug);
}

.bt-work-card__title a:hover,
.bt-work-card__title a:focus-visible {
  color: var(--btm-yellow);
}

/* --- Footer (tent + legal bar) --------------------------------------------- */

.bt-footer {
  position: relative;
  overflow: hidden;
}

/* The big-top illustration — the tent alone, no wordmark — fills the
   footer's full width and meets the legal bar at the bottom edge.

   It is an in-flow ::after block rather than an absolutely positioned
   layer: aspect-ratio sizes it from its own width, so the footer's height
   is simply columns + tent with no vw arithmetic that could drift a few
   pixels out of step with the art (the 2026-08-21 cut reserved the space
   with a padding-bottom guess; the 2026-08-22 review asked for full
   bleed and for the tent to sit closer to the text). The negative
   horizontal margin cancels the footer's own side padding so the art
   runs edge to edge.

   The negative top margin pulls the tent up behind the columns, as in
   the design, where the right-hand flag rises beside the contact text.
   The flag's tip sits 10.3% of the tent width below the tent's top edge
   (212/2047 in the art — re-tune this figure if the art is ever swapped)
   and at x = 59% of the width, which is inside the contact column's text
   run below ~1250px and just clear of it above — so the overlap is
   expressed in vw and the tip always lands a fixed number of pixels
   from the COLUMNS BLOCK's bottom edge:
     - from 1024px: tip at columns-bottom − 34px. The design puts the
       flag tip touching the underside of the e-mail line; with the
       shipped footer copy the six-item Services list is ~50px taller
       than the contact column, so this lands the tip ~16px under the
       e-mail — the design's composition with a little tolerance for
       platform font metrics. THIS IS A CONTENT DEPENDENCY: it holds
       only while Services stays the tallest column — six published
       services and a two-line address. test-loops.php pins the six;
       the footer pattern's docblock carries the rest.
     - 782–1023px (the e-mail can wrap and become the tallest column):
       tip held 24px BELOW whichever column is tallest.
     - below 782px the columns stack, and the tent simply follows them.
   pointer-events: none keeps the links in the overlapped band clickable.

   Asset: footer-tent.svg, vectorised from the design's raster frame
   (Adobe Illustrator image trace, verified against the source at 2.2/255
   mean deviation) — the design only ever had the tent as a bitmap, and a
   bitmap at full bleed went soft on large screens. */
.bt-footer::after {
  content: "";
  display: block;
  width: calc(100% + 2 * var(--btm-section-x));
  margin-left: calc(-1 * var(--btm-section-x));
  aspect-ratio: 2047 / 1260;
  background: url("../img/redesign/footer-tent.svg") no-repeat center bottom / 100% auto;
  pointer-events: none;
}

/* Core gives every columns block a 1.75em bottom margin. In the footer that
   28px would silently pad the overlap figures below, so the tent's own
   margin is the only thing setting the columns-to-tent relationship. */
.bt-footer .wp-block-columns {
  margin-bottom: 0;
}

@media (min-width: 782px) {
  .bt-footer::after {
    margin-top: calc(-1 * (10.3vw - 24px));
  }
}

@media (min-width: 1024px) {
  .bt-footer::after {
    margin-top: calc(-1 * (10.3vw + 34px));
  }
}

.bt-footer h3 {
  font-size: var(--btm-text-h3);
  font-weight: var(--btm-fw-bold);
  margin-bottom: var(--btm-space-5);
}

.bt-footer .bt-footer__services .wp-block-post-title,
.bt-footer .bt-footer__services .wp-block-post-title a,
.bt-footer p,
.bt-footer p a {
  color: var(--btm-ink);
}

.bt-footer .bt-footer__services .wp-block-post-title a:hover,
.bt-footer p a:hover {
  color: var(--btm-red-bright);
}

/* Social icons: the design's colour glyphs at its 61px size with a 19px
   gap (Website Design.pdf p1; the 2026-08-22 review retired the black
   marks). The core block's inline SVG is the monochrome glyph, so it is
   hidden and the anchor paints the brand-colour SVG instead; the block's
   own screen-reader label span stays, so the links keep their names.
   The contact page's "Talk to us" card carries the same marks
   (2026-08-23 review: one set of icons site-wide), so every rule below
   lists both blocks — each selector keeps its own specificity, which is
   what the per-service image rules at the end depend on. */
.bt-footer__social.wp-block-social-links,
.bt-contact__social.wp-block-social-links {
  gap: 19px;
}

/* GP gives every <ul> a 1.5em bottom margin. Under the footer's own
   padding that is invisible; as the last child of the contact page's
   bordered card it read as 69px of padding below the marks against 33px
   above (2026-08-23 review). */
.bt-contact__social.wp-block-social-links {
  margin-bottom: 0;
}

.bt-footer__social.wp-block-social-links .wp-social-link,
.bt-contact__social.wp-block-social-links .wp-social-link {
  background: none;
}

.bt-footer__social.wp-block-social-links .wp-social-link svg,
.bt-contact__social.wp-block-social-links .wp-social-link svg {
  display: none;
}

.bt-footer__social.wp-block-social-links .wp-social-link a,
.bt-contact__social.wp-block-social-links .wp-social-link a {
  display: block;
  width: 61px;
  height: 61px;
  padding: 0;
  border-radius: 14px;
  background: no-repeat center / contain;
  transition: transform var(--btm-transition-fast);
}

/* Core scales the whole <li> to 1.1 on hover; with the anchor's lift that
   made two stacked transforms. The lift alone is the hover here. */
.bt-footer__social.wp-block-social-links .wp-social-link:hover,
.bt-contact__social.wp-block-social-links .wp-social-link:hover {
  transform: none;
}

.bt-footer__social.wp-block-social-links .wp-social-link a:hover,
.bt-footer__social.wp-block-social-links .wp-social-link a:focus-visible,
.bt-contact__social.wp-block-social-links .wp-social-link a:hover,
.bt-contact__social.wp-block-social-links .wp-social-link a:focus-visible {
  transform: translateY(-2px);
}

/* Core's social-links sheet sets `box-shadow: none` on these anchors at
   (0,2,1), which silently cancels the site-wide focus ring from
   `a:focus-visible` (0,1,1) while the ring rule's `outline: none` still
   applies — leaving keyboard users with no indicator at all. Restating
   the ring here at (0,4,1) wins the cascade. */
.bt-footer__social.wp-block-social-links .wp-social-link a:focus-visible,
.bt-contact__social.wp-block-social-links .wp-social-link a:focus-visible {
  box-shadow: var(--btm-ring-focus);
}

/* Same specificity as the anchor rule above (0,3,1) and later in source:
   that rule's `background:` shorthand resets background-image, so a
   lighter per-service selector loses to it and paints nothing. */
.bt-footer__social.wp-block-social-links .wp-social-link-instagram a,
.bt-contact__social.wp-block-social-links .wp-social-link-instagram a {
  background-image: url("../img/redesign/social-instagram.svg");
}

.bt-footer__social.wp-block-social-links .wp-social-link-linkedin a,
.bt-contact__social.wp-block-social-links .wp-social-link-linkedin a {
  background-image: url("../img/redesign/social-linkedin.svg");
  border-radius: 11px;
}

/* The legal bar: full-width ink strip under the footer. */
.bt-legal-bar p {
  color: var(--btm-white);
  font-size: var(--btm-text-sm);
  margin: 0;
}
