/* Stage 1 page styles, shipped verbatim and deliberately UNLAYERED,
   with every .esa-* selector prefixed by `body`.
   Bricks' element defaults (.brxe-section flex-direction, .brxe-div
   resets) sit at the same specificity as our class selectors and print
   after this file, so a plain copy kept losing property by property.
   One element in the compound outranks them all without !important.
   Trade-off: builder per-element styling still wins (id selectors),
   but class-level tweaks in the UI will not. Edit pages/<page>/styles.css. */
/* =============================================================================
   Equipment Sales Australia — Home
   Standalone build (Stage 1 of docs/SPEC-PLAN.md), converted to Bricks later.

   Rules that keep Stage 2 mechanical:
   - Tokens mirror the Bricks global variables 1:1 (same names, same values).
   - 1rem = 16px, matching the Bricks theme style (html 100%).
   - Media queries ONLY at the Bricks breakpoints, desktop-first:
     1279 / 991 / 767 / 478. Everything between them is fluid via clamp().
   ============================================================================= */


/* Animatable number for the "lift out of shadow" half of the image reveal.
   Registering it lets GSAP tween it smoothly instead of swapping strings. */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  overflow-x: clip;
  background: var(--alloy);          /* light sections in the design are Alloy, cards Workshop White */
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: var(--text-m);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.1;
  /* No `text-wrap: balance` here on purpose — it fights SplitText's line
     splitting and produces wrong line breaks in the masked reveals. */
}

p { margin: 0; text-wrap: pretty; }
ul { margin: 0; padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--esa-violet);
  outline-offset: 3px;
}

input, button { font: inherit; color: inherit; }body .esa-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}body .esa-skip-link {
  position: absolute;
  left: var(--space-m);
  top: -4rem;
  z-index: 100;
  padding: var(--space-s) var(--space-m);
  background: var(--esa-violet);
  color: var(--ice-grey);
  border-radius: var(--radius-m);
  transition: top var(--transition-base);
}body .esa-skip-link:focus { top: var(--space-m); }

/* The skip-link target is focusable only programmatically; never draw a ring
   around the whole page when it receives focus. */
main[tabindex="-1"]:focus { outline: none; }

/* ---------- Layout primitives -------------------------------------------- */
.esa-container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}body .esa-section { padding-block: var(--section-pad-y); }

/* ---------- Buttons ------------------------------------------------------ */
.esa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  min-height: 44px;                 /* WCAG touch target */
  padding: var(--space-s) var(--space-l);
  border: 1px solid transparent;
  border-radius: var(--radius-m);
  font-size: var(--text-s);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}body .esa-btn--primary {
  background: var(--esa-violet);
  color: var(--ice-grey);
  box-shadow: 0 4px 6px -4px rgb(0 0 0 / 0.1), 0 10px 15px -3px rgb(0 0 0 / 0.1);
}body .esa-btn--primary:hover { background: var(--esa-violet-d-1); }body .esa-btn--ghost {
  border-color: var(--steel-violet);
  color: var(--ice-grey);
}body .esa-btn--ghost:hover {
  border-color: var(--ice-grey);
  background: rgb(220 220 238 / 0.1);
}

/* ---------- Eyebrow pill ------------------------------------------------- */
.esa-pill {
  display: inline-block;
  padding: var(--space-xs) var(--space-s);
  border: 1px solid var(--esa-violet);
  border-radius: var(--radius-pill);
  background: rgb(220 220 238 / 0.1);
  color: var(--ice-grey);
  font-size: var(--text-s);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  line-height: 1.4;
}

/* =============================================================================
   HEADER — Figma 1:394
   ============================================================================= */
.esa-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 20;
  padding-block: var(--space-xl);
  transition: padding-block var(--transition-base);
}

/* Liquid glass plate.
   Its own layer rather than a background on the header, so it can fade in
   once the page is scrolled without touching the header's own layout.

   Legibility never depends on backdrop-filter: the tint and the inset
   highlights alone already separate the bar from the page, so browsers with
   no backdrop support still get a readable header. */
.esa-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: hsl(245 12% 10% / 0.82);
  box-shadow:
    inset 0 0 2px 1px rgb(255 255 255 / 0.35),
    inset 0 0 10px 4px rgb(255 255 255 / 0.14),
    inset 0 4px 16px rgb(17 17 26 / 0.05),
    inset 0 8px 24px rgb(17 17 26 / 0.05),
    inset 0 6px 56px rgb(17 17 26 / 0.05);
  border-block-end: 1px solid rgb(255 255 255 / 0.12);
  opacity: 0;
  transition: opacity 350ms ease;
  pointer-events: none;
}

/* Tier 1: frost. Supported everywhere backdrop-filter is. */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {body .esa-header::before {
    /* Still clearly a dark bar. The header's logo and links are light
       artwork, so the plate has to stay dark enough for them regardless of
       what scrolls behind — glass is the finish, not the contrast strategy. */
    background: hsl(245 12% 10% / 0.62);
    -webkit-backdrop-filter: blur(10px) saturate(1.5);
    backdrop-filter: blur(10px) saturate(1.5);
  }
}

/* Tier 2: refraction. Only Chromium actually renders an SVG filter inside
   backdrop-filter — Safari and Firefox parse it but paint nothing, so this is
   gated on a class that motion-free JS sets after probing at runtime rather
   than on @supports, which would report a false positive. */
.esa-glass .esa-header::before {
  -webkit-backdrop-filter: url(#esa-glass-filter) saturate(1.45);
  backdrop-filter: url(#esa-glass-filter) saturate(1.45);
}

/* Scrolled away from the top, or the mobile menu is open. */
.esa-header.is-stuck { padding-block: var(--space-m); }body .esa-header.is-stuck::before, body .esa-header.is-open::before { opacity: 1; }

/* The filter element itself is never painted. */
.esa-glass-filter {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  pointer-events: none;
}body .esa-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xl);
}body .esa-header__logo img { width: clamp(11rem, 16vw, 14.6875rem); height: auto; }body .esa-nav {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-xl);
  flex: 1;
}body .esa-nav__list {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2.2vw, 2rem);
}body .esa-nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--space-xs);
  color: var(--ice-grey);
  font-size: var(--text-m);
  text-transform: uppercase;
  transition: color var(--transition-base);
}body .esa-nav__link:hover { color: var(--electric-lilac); }

/* =============================================================================
   GROWING UNDERLINE — header nav + footer link lists
   One rule for every navigational link. Each context supplies its own inset
   and offset through custom properties, because the header links are 44px
   tall touch targets (so the line is measured from their centre) while the
   footer links are plain inline text (measured from their bottom).
   Painted in currentColor, so it inherits each link's hover colour.
   ============================================================================= */
.esa-nav__link,
.esa-footer__list a,
.esa-footer__legal a {
  position: relative;
}body .esa-footer__list a, body .esa-footer__legal a {
  display: inline-block;   /* gives the pseudo-element a box to measure */
}body .esa-nav__link::after, body .esa-footer__list a::after, body .esa-footer__legal a::after {
  content: "";
  position: absolute;
  inset-inline: var(--underline-inset, 0);
  inset-block-end: var(--underline-offset, -0.1em);
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}body .esa-nav__link:hover::after, body .esa-nav__link:focus-visible::after, body .esa-footer__list a:hover::after, body .esa-footer__list a:focus-visible::after, body .esa-footer__legal a:hover::after, body .esa-footer__legal a:focus-visible::after {
  transform: scaleX(1);
}

/* Header links carry padding and a 44px height; pull the line back to the text. */
.esa-nav__link {
  --underline-inset: var(--space-xs);
  --underline-offset: calc(50% - 0.85em);
}body .esa-nav__link.is-current { color: var(--esa-violet); }

/* ESA Violet reads well against the dark hero, but washes out once the glass
   plate is over a light section — lift the current link to Electric Lilac
   there. The state is also carried by aria-current, so colour is not the only
   signal either way. */
.esa-header.is-stuck .esa-nav__link.is-current { color: var(--electric-lilac); }body .esa-search {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  width: 171px;
  padding: var(--space-xs) var(--space-s);
  border: 1px solid var(--steel-violet);
  border-radius: var(--radius-m);
  background: rgb(220 220 238 / 0.1);
  color: var(--ice-grey);
}body .esa-search__icon { flex: none; }body .esa-search__input {
  width: 100%;
  border: 0;
  background: none;
  font-size: var(--text-m);
  text-transform: uppercase;
}body .esa-search__input::placeholder { color: var(--ice-grey); opacity: 0.9; }body .esa-search__input:focus { outline: none; }

/* Burger — hidden until the nav collapses */
.esa-header__toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--steel-violet);
  border-radius: var(--radius-m);
  background: rgb(220 220 238 / 0.1);
  cursor: pointer;
}body .esa-header__toggle-bar {
  width: 18px;
  height: 2px;
  background: var(--ice-grey);
  transition: transform var(--transition-base), opacity var(--transition-base);
}body .esa-header__toggle[aria-expanded="true"] .esa-header__toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }body .esa-header__toggle[aria-expanded="true"] .esa-header__toggle-bar:nth-child(2) { opacity: 0; }body .esa-header__toggle[aria-expanded="true"] .esa-header__toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* =============================================================================
   HERO — Figma 1:5
   ============================================================================= */
.esa-hero {
  position: relative;
  display: flex;
  /* Bricks' own `.brxe-section` sets flex-direction: column. A plain page
     defaults to row, so this was never needed in the standalone build — but
     without it the converted hero stops centring its content vertically. */
  flex-direction: row;
  align-items: center;
  min-height: clamp(34rem, 62vw, 56.25rem);   /* 900px at 1440 */
  padding-block: var(--space-4xl) var(--space-3xl);
  overflow: hidden;
  background: var(--ink);
  isolation: isolate;
}body .esa-hero__bg {
  position: absolute;
  inset-inline: 0;
  /* Taller than the section so the parallax drift never exposes an edge. */
  top: -9%;
  z-index: -2;
  width: 100%;
  height: 118%;
  object-fit: cover;
  will-change: transform;
}body .esa-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Figma runs this gradient's transparent stop to 213%, so the image never
     fully clears the scrim inside the frame — keeps the right side readable. */
  background: linear-gradient(120deg, rgb(37 36 45 / 1) 4%, rgb(37 36 45 / 0) 213%);
}

/* Keeps .esa-container's centring so the copy stays flush with the header
   logo on viewports wider than --container-max. The block is narrowed by
   capping its children, never by detaching it from the container. */
.esa-hero__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-l);
}body .esa-hero__inner > * { max-width: min(100%, 600px); }body .esa-hero__title {
  max-width: 15ch;
  color: var(--ice-grey);
  font-size: var(--text-4xl);
  line-height: 1.2;
  text-transform: uppercase;
}body .esa-hero__lead {
  max-width: 600px;
  color: var(--ice-grey);
  font-size: var(--text-l);
  line-height: 1.4;
}body .esa-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-m);
  margin-block-start: var(--space-xs);
}

/* =============================================================================
   SECTION HEADING — shared by every light section
   ============================================================================= */
.esa-section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-l);
  margin-block-end: var(--space-xl);
}body .esa-section-head__title {
  margin-block-start: var(--space-xs);
  font-size: var(--text-3xl);
  text-transform: uppercase;
}body .esa-pill--light {
  border-color: var(--esa-violet);
  background: transparent;
  color: var(--charcoal);
}body .esa-link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 44px;
  color: var(--esa-violet);
  font-size: var(--text-s);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
  transition: color var(--transition-base);
}body .esa-link-arrow:hover { color: var(--esa-violet-d-1); }body .esa-link-arrow svg { transition: transform var(--transition-base); }body .esa-link-arrow:hover svg { transform: translateX(3px); }

/* =============================================================================
   CATEGORY CARDS — Figma 1:31
   ============================================================================= */
.esa-card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-xl);
}body .esa-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  border-radius: 8px;
  background: var(--workshop-white);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}body .esa-card:hover {
  box-shadow: 0 12px 24px -12px rgb(37 36 45 / 0.35);
}body .esa-card__media {
  position: relative;
  display: block;
  aspect-ratio: 389 / 225;
  overflow: hidden;
  background: var(--ink);
  isolation: isolate;   /* keeps the blend scoped to the card */
}

/* Duotone, built so it can be transitioned away on hover.
   `mix-blend-mode` itself is not animatable, so the greyscale lives on the
   image (a filter, which animates) and the brand hue lives on an overlay
   whose opacity animates. Colour-blending violet over a greyscale photo is
   equivalent to the luminosity-over-violet plate used in Figma. */
.esa-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.04);
  transition: filter 450ms ease;
}

/* Brand hue */
.esa-card__media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--esa-violet);
  mix-blend-mode: color;
  opacity: 0.9;
  transition: opacity 450ms ease;
}

/* Grounding scrim so the card reads as one block against the light section. */
.esa-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to top, #0D0E1A 0%, rgb(111 112 181 / 0) 100%);
  opacity: 0.55;
  transition: opacity 450ms ease;
}

/* Hover / keyboard focus: the photo returns to full colour and both
   overlays clear. Focus is included so the effect is reachable without a
   pointer; on touch, the resting duotone simply stays. */
.esa-card:hover .esa-card__media img,
.esa-card:focus-visible .esa-card__media img {
  filter: grayscale(0) contrast(1);
}body .esa-card:hover .esa-card__media::before, body .esa-card:focus-visible .esa-card__media::before, body .esa-card:hover .esa-card__media::after, body .esa-card:focus-visible .esa-card__media::after {
  opacity: 0;
}body .esa-card__badge {
  position: absolute;
  z-index: 2;   /* above both overlays */
  inset-block-start: var(--space-m);
  inset-inline-end: var(--space-m);
  padding: 0.5625rem 0.8125rem;
  border: 1px solid var(--esa-violet);
  border-radius: var(--radius-pill);
  background: var(--ice-grey);
  color: var(--esa-violet);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
}body .esa-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-m);
  flex: 1;
  padding: var(--space-m);
}body .esa-card__icon { width: 48px; height: 48px; }body .esa-card__title {
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: 1.2;
}body .esa-card__text {
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}body .esa-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-s);
  min-height: 50px;
  padding: var(--space-m);
  border-block-start: 1px solid var(--esa-violet);
  color: var(--esa-violet);
  font-size: var(--text-s);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}body .esa-card__foot svg { transition: transform var(--transition-base); }body .esa-card:hover .esa-card__foot svg { transform: translateX(3px); }

/* =============================================================================
   WHY ESA + ACCORDION — Figma 52:836
   Content column is capped to the container's left half; the photo runs
   edge-to-edge on the right, so the section is a grid, not a container.
   ============================================================================= */
.esa-why {
  display: grid;
  /* 772 / 668 split, measured off the 1440 frame */
  grid-template-columns: minmax(0, 772fr) minmax(0, 668fr);
  align-items: center;
  background: var(--ink);
  color: var(--ice-grey);
  /* The photo bleeds to the right edge, so this section cannot use
     .esa-container. Instead the start gutter grows past --container-pad once
     the viewport exceeds --container-max, so the copy lines up with the
     header. `100%` resolves against the full-width section, which — unlike
     100vw — excludes the scrollbar. */
  padding-inline-start: max(
    var(--container-pad),
    calc((100% - var(--container-max)) / 2 + var(--container-pad))
  );
}body .esa-why__content {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
  padding-block: var(--space-4xl);
  padding-inline-end: var(--space-xl);
}body .esa-why__content > * { max-width: 564px; }body .esa-why__intro {
  font-size: clamp(1.25rem, 1.07rem + 0.89vw, 1.75rem);   /* 20 → 28 */
  font-weight: 600;
  line-height: 1.35;
}body .esa-why__media { align-self: stretch; }body .esa-why__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(calc(1 - var(--esa-veil) * 0.6));
}body .esa-accordion {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}body .esa-accordion__item {
  border: 1px solid var(--workshop-white);
  border-radius: var(--radius-m);
  transition: background-color var(--transition-base), border-color var(--transition-base);
}body .esa-accordion__item h3 { margin: 0; font: inherit; }body .esa-accordion__trigger {
  display: flex;
  align-items: center;
  gap: var(--space-m);
  width: 100%;
  padding: var(--space-xl);
  color: var(--ice-grey);
  font-family: var(--font-body);
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: 1.2;
  text-align: left;
  text-transform: uppercase;
  cursor: pointer;
}

/* The icons ship from Figma with their colour baked in — one violet (for the
   open item) and three ice-grey (for the closed ones). That only holds while
   the first item is the open one; opening any other left an ice-grey icon on
   the light plate, i.e. invisible. Painting them as masks in `currentColor`
   makes every icon follow its trigger's text colour instead. */
.esa-accordion__icon {
  flex: none;
  width: 26px;
  height: 24px;
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
  transition: background-color var(--transition-base);
}body .esa-accordion__panel {
  padding: 0 var(--space-xl) var(--space-xl) calc(var(--space-xl) + 26px + var(--space-m));
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

/* Open state — light plate with a violet spine, per the design. */
.esa-accordion__item.is-open {
  border-color: transparent;
  border-inline-start: 4px solid var(--esa-violet);
  background: var(--workshop-white);
  box-shadow: 0 4px 6px -4px rgb(0 0 0 / 0.1), 0 10px 15px -3px rgb(0 0 0 / 0.1);
}body .esa-accordion__item.is-open .esa-accordion__trigger {
  color: var(--esa-violet);
  padding-block-end: var(--space-m);   /* design gap between title and body is 16px */
}

/* =============================================================================
   BRAND STRIP — Figma 1:169
   ============================================================================= */
.esa-brands {
  padding-block: var(--space-2xl);
  background: var(--ice-grey);
  text-align: center;
}body .esa-brands__label {
  margin-block-end: var(--space-xl);
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: var(--text-m);
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}body .esa-brands__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xl);
}body .esa-brands__list li { flex: 1 1 140px; display: flex; justify-content: center; }body .esa-brands__list img {
  width: auto;
  max-height: 3.25rem;
  /* Logos ship in full colour; the design greys them so no single brand shouts. */
  filter: grayscale(1);
  opacity: 0.75;
  transition: filter var(--transition-base), opacity var(--transition-base);
}body .esa-brands__list img:hover { filter: none; opacity: 1; }

/* =============================================================================
   SPLIT SECTIONS — Figma 1:209 (service) and 27:591 (finance)
   ============================================================================= */
.esa-split__inner {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: center;
  gap: var(--space-3xl);
}

/* Finance mirrors the service section: content first, image second. */
.esa-split--reverse .esa-split__media { order: 2; }body .esa-split__media img {
  width: 100%;
  height: auto;
  border-radius: 8px;
  filter: grayscale(1) brightness(calc(1 - var(--esa-veil) * 0.6));
}body .esa-split__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-m);
}body .esa-split__title {
  font-size: var(--text-3xl);
  line-height: 1.15;
  text-transform: uppercase;
}body .esa-split__text {
  max-width: 52ch;
  color: var(--charcoal);
  font-size: var(--text-m);
  line-height: 1.5;
}body .esa-checklist {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  margin-block: var(--space-xs);
}body .esa-checklist li {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  font-size: var(--text-m);
}body .esa-checklist img { flex: none; width: 16px; height: 16px; }

/* =============================================================================
   PRE-FOOTER CTA CARDS — Figma 1:274
   ============================================================================= */
.esa-cta { background: var(--ink); }body .esa-cta__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-xl);
}body .esa-cta__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-m);
  padding: var(--space-xl);
  border-radius: 8px;
  background: var(--workshop-white);
  text-align: center;
}body .esa-cta__title {
  font-size: var(--text-2xl);
  text-transform: uppercase;
}body .esa-cta__text {
  flex: 1;
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}body .esa-cta__card .esa-btn { width: 100%; }body .esa-btn--outline {
  border-color: var(--machine-grey);
  color: var(--charcoal);
}body .esa-btn--outline:hover {
  border-color: var(--esa-violet);
  color: var(--esa-violet);
}

/* =============================================================================
   FOOTER — Figma 132:1989
   ============================================================================= */
.esa-footer {
  padding-block: var(--space-3xl) var(--space-xl);
  background: var(--alloy);
}body .esa-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 350px);
  gap: var(--space-3xl);
}body .esa-footer__cols {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-l);
}body .esa-footer__heading {
  margin-block-end: var(--space-m);
  color: var(--esa-violet);
  font-family: var(--font-body);
  font-size: var(--text-m);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}body .esa-footer__list { display: flex; flex-direction: column; gap: var(--space-s); }body .esa-footer__list a {
  color: var(--steel-violet);
  font-size: var(--text-m);
  transition: color var(--transition-base);
}body .esa-footer__list a:hover { color: var(--esa-violet); }body .esa-contact-card {
  padding: var(--space-l);
  border-radius: 8px;
  background: var(--ink);
  color: var(--ice-grey);
}body .esa-contact-card__title {
  margin-block-end: var(--space-l);
  font-family: var(--font-body);
  font-size: var(--text-m);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}body .esa-contact-card__list { display: flex; flex-direction: column; gap: var(--space-l); }body .esa-contact-card__list li {
  display: grid;
  grid-template-columns: 16px 1fr;
  gap: var(--space-s);
  align-items: start;
  font-size: var(--text-m);
  line-height: 1.4;
}body .esa-contact-card__list img { margin-block-start: 0.2em; }body .esa-contact-card__list a { transition: color var(--transition-base); }body .esa-contact-card__list a:hover { color: var(--electric-lilac); }body .esa-footer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  margin-block-start: var(--space-2xl);
  padding-block-start: var(--space-m);
  border-block-start: 1px solid var(--esa-violet);
  color: var(--machine-grey);
  font-size: var(--text-s);
}body .esa-footer__legal { display: flex; gap: var(--space-l); }body .esa-footer__legal a { transition: color var(--transition-base); }body .esa-footer__legal a:hover { color: var(--esa-violet); }

/* =============================================================================
   RESPONSIVE — Bricks breakpoints only (desktop-first)
   ============================================================================= */

/* Tablet portrait */
@media (max-width: 991px) {body .esa-header__toggle { display: flex; }body .esa-nav {
    position: absolute;
    inset-inline: var(--container-pad);
    top: calc(100% + var(--space-s));
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-m);
    padding: var(--space-l);
    border: 1px solid var(--steel-violet);
    border-radius: var(--radius-l);
    background: var(--ink);
    display: none;
  }body .esa-nav[data-esa-open] { display: flex; }body .esa-nav__list { flex-direction: column; align-items: stretch; gap: 0; }body .esa-nav__link { min-height: 48px; }body .esa-search { width: 100%; }body .esa-hero__inner { max-width: 100%; }body .esa-card-grid { grid-template-columns: repeat(2, 1fr); }body .esa-why { grid-template-columns: 1fr; padding-inline-start: 0; }body .esa-why__content {
    justify-self: stretch;
    max-width: none;
    padding-inline: var(--container-pad);
  }body .esa-why__media { order: -1; }body .esa-why__media img { max-height: 60vh; }body .esa-split__inner { grid-template-columns: 1fr; gap: var(--space-xl); }body .esa-split--reverse .esa-split__media { order: 0; }body .esa-split__media img { max-height: 55vh; object-fit: cover; }body .esa-cta__grid { grid-template-columns: 1fr; }body .esa-footer__top { grid-template-columns: 1fr; gap: var(--space-xl); }body .esa-footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-xl); }
}

/* Mobile landscape */
@media (max-width: 767px) {body .esa-hero { min-height: 32rem; }body .esa-hero__scrim { background: linear-gradient(180deg, rgb(37 36 45 / 0.92) 0%, rgb(37 36 45 / 0.75) 100%); }body .esa-hero__actions .esa-btn { flex: 1 1 100%; }body .esa-section-head { flex-direction: column; align-items: flex-start; }body .esa-brands__list { gap: var(--space-l); }body .esa-footer__bottom { flex-direction: column; align-items: flex-start; }

  /* Single column from here down. Deliberately switched at 767 rather than 478:
     on HiDPI screens the viewport can be fractional (478.4px), so a
     `max-width: 478px` query misses by a hair right at the breakpoint. */
  .esa-card-grid { grid-template-columns: 1fr; }body .esa-hero__title { max-width: 100%; }
}

/* Mobile portrait */
@media (max-width: 478px) {body .esa-footer__cols { grid-template-columns: 1fr; }body .esa-contact-card { padding: var(--space-m); }
}

/* =============================================================================
   MOTION START STATES
   Only applied while `esa-js` is on <html>. motion.js drops that class the
   moment it has set the real start states, and a failsafe in <head> drops it
   if GSAP never runs — so the page is never left invisible.
   ============================================================================= */
.esa-js [data-esa-hero-pill],
.esa-js .esa-hero__title,
.esa-js [data-esa-hero-lead],
.esa-js [data-esa-hero-actions],
.esa-js [data-esa-reveal],
.esa-js [data-esa-fade],
.esa-js [data-esa-stagger] > * {
  opacity: 0;
}

[data-esa-reveal="image"] { will-change: clip-path, transform, filter; }

/* ---------- Motion preferences ------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==ESA-SHARED-START== */
/* Shared components from pages/_shared/base.css. Generated by
   pages/_shared/bricks/deploy_shared_css.py — do not hand-edit. */
/* =============================================================================
   ACTION CARD — bordered card with a badge, title, copy and an optional
   ticked list. Service uses it for lifecycle support, Finance for the
   numbered ownership steps.
   ============================================================================= */

body .esa-action-grid{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-l);            /* 32 at 1440, as drawn on both pages */
}
body .esa-action{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-l);            /* 32 at 1440, as drawn */
  height: 100%;
  padding: var(--space-l);
  border: 1px solid var(--steel-violet);
  border-radius: 10px;
  background: var(--workshop-white);
  text-align: center;
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}
body .esa-action:hover{
  transform: translateY(-3px);
  border-color: var(--esa-violet);
  box-shadow: 0 20px 42px -22px rgb(37 36 45 / 0.45);
}
/* The Figma export draws the badge border inside the 48px icon SVG. Here the
   box is CSS so it can carry the tokens and pick up the card's hover. */
body .esa-action__badge{
  display: grid;
  place-items: center;
  flex: none;
  width: 48px;
  height: 48px;
  border: 1px solid var(--steel-violet);
  border-radius: var(--radius-m);
  color: var(--esa-violet);
  transition: border-color var(--transition-base), background-color var(--transition-base);
}
body .esa-action:hover .esa-action__badge{
  border-color: var(--esa-violet);
  background: var(--esa-violet-l-4);
}
body .esa-action__badge svg{ width: 18px; height: 18px; }
body .esa-action__title{
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: clamp(1.5rem, 1.29rem + 1.07vw, 2rem);   /* Subtitle 32 */
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
}
body .esa-action__text{
  /* The card runs on one gap; the design pairs title and text at 8px. */
  margin-block-start: calc(8px - var(--space-l));
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}
/* Pinned to the card foot so the ticks line up across a row of uneven copy. */
body .esa-action__list{
  display: flex;
  flex-direction: column;
  gap: 15.5px;
  width: 100%;
  margin-block-start: auto;
}
body .esa-action__list li{
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-s);
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}
/* Violet is set here rather than inherited: the row's own colour is Machine Grey
   for the label, and the icons are Primary in the design. */
body .esa-action__list svg{
  flex: none;
  width: 17px;
  height: 17px;
  color: var(--esa-violet);
}
/* =============================================================================
   VALUE PROP — icon, uppercase heading, copy. Finance uses it under Fueling
   Momentum, About under Forged in the Trenches.
   ============================================================================= */
body .esa-valueprops{
  display: flex;
  flex-direction: column;
  gap: var(--space-l);             /* 32 between props, as drawn */
  margin-block-start: var(--space-s);
  padding-inline-end: var(--space-l);
}
body .esa-valueprop{ display: flex; flex-direction: column; gap: var(--space-s); }
/* The icon sits on the heading's own baseline row, 16px in front of the text.
   Figma paints these Primary; d-1 is used instead so the label clears AA on
   Alloy at every step of the clamp (the brand tint is 3.61:1 here). The icon
   inherits it through currentColor, so both stay one colour. */
body .esa-valueprop__title{
  display: flex;
  align-items: center;
  gap: var(--space-s);             /* 16 from icon to label */
  color: var(--esa-violet-d-1);
  font-family: var(--font-body);
  font-size: var(--text-xl);       /* Heading 24 */
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
}
body .esa-valueprop__title svg{ flex: none; width: 25px; height: auto; }
body .esa-valueprop__text{
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}
/* =============================================================================
   STAT PANEL — a stepped figure panel notched into a split photo. Service
   uses it for 80+ technicians, About for 100k+ machine sales.
   ============================================================================= */
body .esa-split__media--stat{ position: relative; }
/* Stepped panel, per the inverted-radius reference. The two lines are separate
   white blocks of different widths, flush to the photo's left edge so the white
   reads as running off it. An inverted radius exists to smooth a STEP between
   two white areas — a single card in a corner has no step, which is why the
   effect only lands once the panel is built this way. */
body .esa-stat{
  --_r: 22px;
  /* How far the narrow step pulls in. Must clear the fillet plus the wide
     step's own corner radius, or the fillet overhangs the step it is smoothing. */
  --_step: 56px;
  /* Gutter between the panel and the photo, in the page colour, so the panel
     reads as cut into the plate rather than welded to it. Drawn as borders on
     the three sides that face the photo — the left edge is flush with the plate
     and gets none. */
  --_gap: 8px;
  position: absolute;
  inset-block-end: var(--space-2xl);
  inset-inline-start: 0;
  display: flex;
  flex-direction: column;
  width: max-content;
  max-width: 82%;
}
body .esa-stat__value,
body .esa-stat__label{
  position: relative;
  padding-block: var(--space-s);
  padding-inline: var(--space-l);
  background: var(--workshop-white);
}
/* The wide step. Both its right corners are convex — nothing sits above it. The
   outer radius stays --_r and the border makes the white's own corner --_r minus
   the gutter, which is what an evenly offset outline wants. */
body .esa-stat__value{
  border-block: var(--_gap) solid var(--alloy);
  border-inline-end: var(--_gap) solid var(--alloy);
  border-start-end-radius: var(--_r);
  border-end-end-radius: var(--_r);
  color: var(--esa-violet-d-1);   /* d-1: the brand tint is 3.6:1 on this card */
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.57rem + 2.14vw, 3rem);     /* Title Page 48 */
  font-weight: 700;
  line-height: 1.2;
}
/* The narrow step: convex at the bottom, and its top-right is the inside corner
   the fillet below fills. Pulled in by a fixed amount rather than left to fall
   out of the text lengths, so the step never collapses under the fillet.

   The negative top margin lifts it over the wide step's bottom gutter, so that
   band survives only where it should — across the step, to the right of this
   block. Without it a full-width line of page colour would cut the panel in two. */
body .esa-stat__label{
  margin-block-start: calc(var(--_gap) * -1);
  margin-inline-end: var(--_step);
  padding-block-start: 0;
  border-inline-end: var(--_gap) solid var(--alloy);
  border-block-end: var(--_gap) solid var(--alloy);
  border-end-end-radius: var(--_r);
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}
/* The fillet rounds the inside corner where the step's underside meets the
   narrow block's right edge. It now carries three zones instead of two, read as
   distance from the square's far corner:

     >= --_r            the panel
     .. --_r - --_gap   the gutter band
     <  --_r - --_gap   photo shows through

   The square stays --_r on a side with the circle centred on its far corner.
   Sizing it --_r + --_gap to "make room" for the band is wrong: past --_r the
   distance rises again, so the far corners would paint white over the step.
   Concentric rings keep the panel's curve and the gutter's curve exactly
   --_gap apart the whole way round, and the band meets the two borders
   precisely at the square's edges. */
body .esa-stat__label::after{
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 100%;
  width: var(--_r);
  aspect-ratio: 1;
  background-image: radial-gradient(circle at 100% 100%,
    transparent calc(var(--_r) - var(--_gap) - 0.5px),
    var(--alloy) calc(var(--_r) - var(--_gap)),
    var(--alloy) calc(var(--_r) - 0.5px),
    var(--workshop-white) var(--_r));
  pointer-events: none;
}
/* =============================================================================
   FORM CONTROLS — shared by the Finance quote and the Contact inquiry.
   The equipment single template still carries its own older copy of these
   class names; its block loads later, so that page is unaffected.
   ============================================================================= */
body .esa-field-grid{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-l);             /* 32 both axes, as drawn */
}
body .esa-field{
  display: flex;
  flex-direction: column;
  gap: 8px;                        /* label to input, as drawn */
  margin: 0;
}
body .esa-field--wide{ grid-column: 1 / -1; }
/* Figma draws these in Steel Violet, which is 2.5:1 on the card — well under
   AA for 12px. The darker violet keeps the label in the same family at 5.6:1. */
body .esa-field__label{
  /* Bricks gives every <label> a 5px bottom margin, which stacked on the
     field's own 8px gap and made each row 5px taller than Stage 1. */
  margin: 0;
  color: var(--esa-violet-d-1);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
  text-transform: uppercase;
}
body .esa-input{
  width: 100%;
  padding: 14px 12px;
  border: 0;
  border-radius: var(--radius-m);
  background: var(--alloy);
  color: var(--charcoal);
  font-family: inherit;
  font-size: var(--text-m);
  line-height: 1.4;
  transition: box-shadow var(--transition-base), background-color var(--transition-base);
}
body .esa-input::placeholder{ color: var(--machine-grey); opacity: 1; }
body .esa-input:hover{ box-shadow: inset 0 0 0 1px var(--steel-violet); }
body .esa-input:focus-visible{
  background: var(--white);
  box-shadow: inset 0 0 0 1px var(--esa-violet);
  outline: 2px solid var(--esa-violet);
  outline-offset: 1px;
}
/* A field the browser has judged invalid, but only once the user has left it. */
body .esa-input:user-invalid{ box-shadow: inset 0 0 0 1px #A4343A; }
/* Native select chrome varies too much between browsers to sit next to the
   text inputs; the caret is redrawn to match the listing's sort control. */
body .esa-select{
  appearance: none;
  padding-inline-end: var(--space-xl);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' fill='none' stroke='%235E5E5E' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-s) center;
  cursor: pointer;
}
/* The placeholder option should read as placeholder text, not as an answer. */
body .esa-select:has(option[value=""]:checked){ color: var(--machine-grey); }
body .esa-textarea{
  min-height: 6.75rem;             /* 108 as drawn */
  resize: vertical;
}
body .esa-form-submit{
  justify-content: center;
  width: 100%;
  min-height: 58px;
}
body .esa-form-status{
  margin: 0;
  color: var(--machine-grey);
  font-size: var(--text-s);
  line-height: 1.4;
}
body .esa-form-status:empty{ display: none; }
body .esa-form-status[data-state="error"]{ color: #A4343A; }
@media (max-width: 1279px) {

  body .esa-action-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 991px) {

  /* Full-width column below this: the trailing gutter the props keep
     beside the photo has nothing to clear. */
  body .esa-valueprops{ padding-inline-end: 0; }
}
@media (max-width: 767px) {

  body .esa-field-grid{ grid-template-columns: 1fr; }

  body .esa-action-grid{ grid-template-columns: 1fr; }
}
@media (max-width: 478px) {

  /* The panel stays on the photo — white only reads as a shape against the
     photo, not against the page's alloy. It just gets tighter so it takes less
     of a small image; the step shrinks with the radius it has to clear. */
  body .esa-stat{
    --_r: 16px;
    /* 36 not 32: the step still has to clear the fillet (--_r + --_gap) plus the
       wide block's own inner radius (--_r - --_gap). */
    --_step: 36px;
    --_gap: 6px;
    inset-block-end: var(--space-l);
  }
  body .esa-stat__value,
  body .esa-stat__label{ padding-inline: var(--space-m); }
}

/* ---- search.css ---- */
/* =============================================================================
   Equipment Sales Australia — search overlay
   The header search field's results. Its own file rather than part of base.css
   for one reason: the Home page's Stage 1 build does not load base.css (it
   predates it and is self-contained), and linking base.css there moves 124
   element boxes. This component is on every page, Home included, so it needs a
   home every page can load.

   Ships to the built site inside the SHARED block of esa-pages.css — see
   bricks/deploy_shared_css.py. Behaviour lives in ../search.js.
   ============================================================================= */

body .esa-search-dialog{
  width: min(880px, calc(100vw - 2 * var(--space-m)));
  max-width: none;
  max-height: min(78vh, 760px);
  padding: 0;
  border: 0;
  background: none;
  overflow: visible;
}
/* Only when open — a bare display:flex would defeat the UA's display:none. */
body .esa-search-dialog[open]{ display: flex; }

body .esa-search-dialog::backdrop{
  background: rgb(37 36 45 / 0.72);
  backdrop-filter: blur(4px);
}

body .esa-search-dialog__panel{
  --_pad: clamp(var(--space-m), 3vw, var(--space-xl));
  display: flex;
  flex-direction: column;
  min-height: 0;
  width: 100%;
  overflow: hidden;
  border-radius: 12px;
  background: var(--workshop-white);
  box-shadow: 0 40px 80px -40px rgb(37 36 45 / 0.7);
}

/* The field sits on the same ink as the site's dark panels, so the thing you
   are typing into is the loudest element in the overlay. */
body .esa-search-dialog__head{
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-s);
  padding: var(--_pad);
  background: var(--ink);
  color: var(--ice-grey);
}

body .esa-search-dialog__icon{ flex: none; color: var(--steel-violet); }

body .esa-search-dialog__input{
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: none;
  color: var(--ice-grey);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1.1;
  text-transform: uppercase;
}
body .esa-search-dialog__input::placeholder{
  color: var(--steel-violet);
  font-weight: 600;
}
body .esa-search-dialog__input:focus{ outline: none; }
body .esa-search-dialog__input::-webkit-search-cancel-button{ display: none; }

body .esa-search-dialog__close{
  display: grid;
  flex: none;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid rgb(152 152 176 / 0.4);
  border-radius: var(--radius-pill);
  background: none;
  color: var(--steel-violet);
  cursor: pointer;
  transition: color var(--transition-base), border-color var(--transition-base),
              background-color var(--transition-base);
}
body .esa-search-dialog__close:hover{
  border-color: var(--ice-grey);
  background: rgb(220 220 238 / 0.12);
  color: var(--ice-grey);
}
body .esa-search-dialog__close:focus-visible{
  outline: 2px solid var(--electric-lilac);
  outline-offset: 2px;
}

body .esa-search-dialog__status{
  flex: none;
  margin: 0;
  padding: var(--space-s) var(--_pad);
  border-block-end: 1px solid var(--alloy);
  background: var(--ice-grey);
  color: var(--machine-grey);
  font-size: var(--text-s);
  line-height: 1.4;
}

body .esa-search-results{
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
  /* A visible track, not the overlay scrollbar the platform would fade out. With
     a searchable inventory the list is usually taller than the panel, and there
     is nothing else in the layout that says so. */
  scrollbar-width: thin;
  scrollbar-color: var(--steel-violet) var(--ice-grey);
}

body .esa-search-result + .esa-search-result{ border-block-start: 1px solid var(--alloy); }

body .esa-search-result__link{
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-m);
  padding: var(--space-s) var(--_pad);
  color: inherit;
  text-decoration: none;
  /* Inset, so the hover edge cannot shift the row it is drawn on. */
  box-shadow: inset 0 0 0 0 var(--esa-violet);
  transition: background-color var(--transition-base), box-shadow var(--transition-base);
}
body .esa-search-result__link:hover{
  background: var(--ice-grey);
  box-shadow: inset 3px 0 0 0 var(--esa-violet);
}
body .esa-search-result__link:focus-visible{
  background: var(--ice-grey);
  outline: 2px solid var(--esa-violet);
  outline-offset: -2px;
}

body .esa-search-result__media{
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border-radius: 6px;
  background: var(--alloy);
}
body .esa-search-result__media img{
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

body .esa-search-result__body{
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

body .esa-search-result__model{
  color: var(--charcoal);
  font-family: var(--font-display);
  font-size: var(--text-l);
  font-weight: 700;
  line-height: 1.15;
  text-transform: uppercase;
}

/* One line: the row is a way to recognise a machine, not to read its listing. */
body .esa-search-result__title{
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  color: var(--machine-grey);
  font-size: var(--text-s);
  line-height: 1.35;
}

body .esa-search-result__meta{
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin-block-start: var(--space-2xs);
}
body .esa-search-result__tag{
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: var(--alloy);
  color: var(--machine-grey);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

body .esa-search-result__price{
  color: var(--charcoal);
  font-family: var(--font-display);
  font-size: var(--text-l);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

body .esa-search-result--all .esa-search-result__link{
  display: flex;
  gap: var(--space-xs);
  padding-block: var(--space-m);
  /* Fallback for Home's Stage 1 build, the one page with no token sheet of its
     own for this variable. #43436d is what the Bricks global carries live —
     base.css says #323374, a drift that predates this component. */
  color: var(--esa-violet-d-2, #43436d);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
body .esa-search-result__arrow{ flex: none; }

@media (max-width: 767px) {
  /* Two columns, with the photo spanning both rows so the price can drop under
     the title instead of squeezing it. */
  body .esa-search-result__link{
    grid-template-columns: 84px minmax(0, 1fr);
    gap: var(--space-s);
  }
  body .esa-search-result__media{ grid-row: span 2; }
  body .esa-search-result__price{ grid-column: 2; justify-self: start; }
  body .esa-search-dialog{ max-height: min(86vh, 760px); }
  body .esa-search-dialog__input{ font-size: var(--text-xl); }
}
/* ==ESA-SHARED-END== */

/* ==ESA-EQUIPMENT-START== */
/* Home ships these as <img>; the equipment split inlines the Figma exports as
   <svg>, which has no intrinsic size to fall back on. Size both, and colour the
   inline ones through currentColor. */
body .esa-checklist img,
body .esa-checklist svg{ flex: none; width: 16px; height: 16px; }

/* The inline exports paint through currentColor. */
body .esa-checklist svg{ color: var(--esa-violet); }

/* The eyebrow pill sits closer to the heading than the column's own gap. */
body .esa-split__content .esa-pill{ margin-block-end: calc(var(--space-m) * -0.35); }


/* =============================================================================
   CTA BAND — shared full-bleed band with one action. Each page sets the image.
   ============================================================================= */
body .esa-cta-band{
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding-block: var(--space-4xl);
  background: var(--ink);
  color: var(--ice-grey);
}
/* Fixed-scroll background: the image stays pinned to the viewport while the band
   scrolls over it (a reveal/parallax effect). A CSS background is used rather
   than an <img> because background-attachment is what produces the effect.
   Each page supplies its own `background-image`. */
body .esa-cta-band__bg{
  position: absolute;
  inset: 0;
  z-index: -2;
  background-position: center;
  background-size: cover;
  background-attachment: fixed;
}
body .esa-cta-band__scrim{
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, rgb(37 36 45 / 0.92) 0%, rgb(37 36 45 / 0.6) 100%);
}
body .esa-cta-band__inner{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xl);
  flex-wrap: wrap;
}
body .esa-cta-band__title{
  max-width: 16ch;
  font-size: var(--text-3xl);
  text-transform: uppercase;
  color: var(--ice-grey);
}


/* =============================================================================
   EQUIPMENT CARD — shared by the listing grid and the detail page's
   "You might be interested in" row. The grid that lays the cards out stays
   with each page, since the column counts differ.
   Figma V7Jfat2FjJXWvsBDlQN3Uk 221:847 (260x440). The whole card is one link:
   the design has no separate targets, and three links to the same machine is
   noise for anyone tabbing or listening.
   ============================================================================= */
body .esa-eq-card{
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  border-radius: var(--radius-m);
  background: var(--workshop-white);
  color: inherit;
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}
body .esa-eq-card:hover{
  transform: translateY(-3px);
  box-shadow: 0 20px 42px -22px rgb(37 36 45 / 0.45);
}
body .esa-eq-card:focus-visible{ outline: 2px solid var(--esa-violet); outline-offset: 3px; }

/* The machine sits on a white plate, desaturated, under an ink gradient that
   grounds the card and gives the badge something to sit on. */
body .esa-eq-card__media{
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 260 / 192;
  overflow: hidden;
  background: var(--white);
}
body .esa-eq-card__media img{
  /* 173 of the design's 260-wide plate. Sized off the width because a
     percentage height here resolves against the replaced element's own box,
     not the grid area, and overflows. */
  width: 66.5%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  filter: grayscale(1);
  transition: transform 500ms ease, filter var(--transition-base);
}

/* Pointing at a card drops both the overlay and the desaturation, so the
   machine comes up in its real colours. */
body .esa-eq-card:hover .esa-eq-card__media img,
body .esa-eq-card:focus-visible .esa-eq-card__media img{
  filter: grayscale(0);
  transform: scale(1.05);
}

body .esa-eq-card__media::after{
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, #0D0E1A 0%, rgb(111 112 181 / 0) 100%);
  opacity: 1;
  transition: opacity var(--transition-base);
  pointer-events: none;
}

/* Keyboard focus gets the same reveal as hover. */
body .esa-eq-card:hover .esa-eq-card__media::after,
body .esa-eq-card:focus-visible .esa-eq-card__media::after{ opacity: 0; }

body .esa-eq-card__badge{
  position: absolute;
  z-index: 1;
  inset-block-start: var(--space-m);
  inset-inline-end: var(--space-m);
  padding: 9px 13px;
  border: 1px solid var(--esa-violet);
  border-radius: var(--radius-m);
  background: var(--ice-grey);
  /* d-1 rather than the brand tint: 12px violet on Ice Grey is 3.8:1. */
  color: var(--esa-violet-d-1);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
}

body .esa-eq-card__body{
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-m);
}

/* Model code leads, price sits on its baseline at the other end of the row. */
body .esa-eq-card__head{
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-s);
  padding-block-end: var(--space-xs);
}

body .esa-eq-card__model{
  min-width: 0;
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: var(--text-l);
  font-weight: 400;
  line-height: 1.2;
}

body .esa-eq-card__price{
  flex: none;
  color: var(--esa-violet-d-1);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  text-align: right;
}

body .esa-eq-card__subtitle{
  padding-block-end: var(--space-m);
  color: var(--machine-grey);
  font-size: var(--text-s);
  line-height: 1.4;
}

/* Two columns of icon + value, carrying only the specs a machine actually has,
   so the card is 2, 4 or 6 rows deep depending on the data. */
body .esa-eq-card__specs{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px var(--space-xs);
}

body .esa-eq-spec{
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-width: 0;
  color: var(--machine-grey);
  font-size: var(--text-xs);
  line-height: 1.4;
}
body .esa-eq-spec svg{ flex: none; width: 12px; height: 12px; color: var(--esa-violet); }
body .esa-eq-spec span{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

body .esa-eq-card__foot{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-s);
  min-height: 50px;
  padding: var(--space-s) var(--space-m);
  border-block-start: 1px solid var(--esa-violet);
  color: var(--esa-violet-d-1);
  font-size: var(--text-s);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
body .esa-eq-card__foot svg{ flex: none; width: 12px; height: 12px; transition: transform var(--transition-base); }
body .esa-eq-card:hover .esa-eq-card__foot svg{ transform: translateX(3px); }


/* =============================================================================
   Equipment Sales Australia — Equipment listing (archive)
   Standalone build (Stage 1 of docs/SPEC-PLAN.md). Shared shell lives in
   ../_shared/base.css; this file only adds the listing-specific sections.
   Figma node 1:422. Becomes the Bricks CPT archive (query loop + query filters).
   ============================================================================= */

/* ---------- Hero copy (uses the shared .esa-hero shell) ------------------ */
body .esa-hero__eyebrow{ /* alias so the shared pill sits above the title */ }

/* =============================================================================
   LISTING — filter sidebar + results
   ============================================================================= */
body .esa-listing{ background: var(--alloy); }

body .esa-listing__grid{
  display: grid;
  grid-template-columns: minmax(0, 280px) minmax(0, 1fr);
  align-items: start;
  gap: var(--space-2xl);
}

/* ---------- Filter sidebar ----------------------------------------------- */
body .esa-filters{
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  padding: var(--space-l);
  border-radius: var(--radius-l);
  background: var(--workshop-white);
  /* Sticks under the fixed header while the results scroll past. */
  position: sticky;
  top: calc(var(--space-4xl) + var(--space-m));
}

/* The gap on .esa-filters only separates the mobile toggle from this body, and
   the toggle is hidden on desktop — so without a gap here the three groups
   stacked flush and the last option of one ran into the next heading. */
body .esa-filters__body{
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}

body .esa-filter-group{ display: flex; flex-direction: column; gap: var(--space-s); }

body .esa-filter-group__heading{
  margin: 0 0 var(--space-2xs);
  color: var(--esa-violet-d-1);
  font-family: var(--font-body);
  font-size: var(--text-m);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

body .esa-filter-options{ display: flex; flex-direction: column; gap: var(--space-2xs); }

/* Category rows — full-width pill buttons */
body .esa-filter-option{
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: var(--space-xs) var(--space-s);
  border: 1px solid transparent;
  border-radius: var(--radius-m);
  background: transparent;
  color: var(--charcoal);
  font-size: var(--text-s);
  text-align: left;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}
body .esa-filter-option:hover{ background: var(--ice-grey); }
body .esa-filter-option[aria-pressed="true"]{
  background: var(--esa-violet);
  border-color: var(--esa-violet);
  color: var(--white);
}

/* Brand + condition — inline chips */
body .esa-filter-chips{ display: flex; flex-wrap: wrap; gap: var(--space-xs); }

body .esa-chip-toggle{
  min-height: 40px;
  padding: var(--space-xs) var(--space-m);
  border: 1px solid var(--technical-grey);
  border-radius: var(--radius-m);
  background: var(--white);
  color: var(--charcoal);
  font-size: var(--text-s);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}
body .esa-chip-toggle:hover{ border-color: var(--esa-violet); }
body .esa-chip-toggle[aria-pressed="true"]{
  background: var(--esa-violet);
  border-color: var(--esa-violet);
  color: var(--white);
}
body .esa-filter-group--condition .esa-chip-toggle{ flex: 1; text-align: center; }

/* ---------- Results column ----------------------------------------------- */
body .esa-listing__main{ display: flex; flex-direction: column; gap: var(--space-l); }

body .esa-toolbar{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  flex-wrap: wrap;
}

body .esa-toolbar__count{
  color: var(--machine-grey);
  font-size: var(--text-m);
}
body .esa-toolbar__count b{ color: var(--charcoal); font-weight: 600; }

body .esa-sort{
  display: flex;
  align-items: center;
  gap: var(--space-s);
  color: var(--machine-grey);
  font-size: var(--text-s);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

body .esa-sort__select{
  min-height: 40px;
  padding: var(--space-xs) var(--space-l) var(--space-xs) var(--space-s);
  border: 1px solid var(--technical-grey);
  border-radius: var(--radius-m);
  background: var(--white);
  color: var(--charcoal);
  font-size: var(--text-s);
  text-transform: uppercase;
  cursor: pointer;
  /* native chevron replaced by an inline one for consistent cross-browser look */
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' fill='none' stroke='%235E5E5E' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-s) center;
}

/* ---------- Results grid (card itself lives in _shared/base.css) --------- */
body .esa-eq-grid{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-l);
}


/* ---------- Pagination --------------------------------------------------- */
body .esa-pagination{
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  margin-block-start: var(--space-m);
}

body .esa-pagination a,
body .esa-pagination span{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 40px;
  padding-inline: var(--space-xs);
  border: 1px solid var(--technical-grey);
  border-radius: var(--radius-m);
  background: var(--white);
  color: var(--charcoal);
  font-size: var(--text-s);
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}
body .esa-pagination a:hover{ border-color: var(--esa-violet); color: var(--esa-violet); }
body .esa-pagination [aria-current="page"]{
  background: var(--esa-violet);
  border-color: var(--esa-violet);
  color: var(--white);
}
body .esa-pagination__gap{ border: 0; background: none; color: var(--machine-grey); min-width: auto; }

/* ---------- CTA band image (the band itself lives in _shared/base.css) ---- */
body .esa-cta-band__bg{ background-image: url("https://esa.wearemyooz.com/wp-content/uploads/2026/08/esa-cta-band.jpg"); }

/* The filter accordion toggle only exists on mobile; base state is hidden and
   the ≤991 media query below reveals it. Declared BEFORE the media query so the
   query's `display: flex` wins on source order. */
body .esa-filters__toggle{
  display: none;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: 44px;
  padding: var(--space-xs) var(--space-s);
  border: 1px solid var(--technical-grey);
  border-radius: var(--radius-m);
  background: var(--white);
  color: var(--charcoal);
  font-size: var(--text-s);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
}
body .esa-filters__toggle svg{ transition: transform var(--transition-base); }
body .esa-filters[data-esa-open] .esa-filters__toggle svg{ transform: rotate(180deg); }

/* =============================================================================
   RESPONSIVE — Bricks breakpoints
   ============================================================================= */
@media (max-width: 1279px) {
  body .esa-eq-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 991px) {
  /* Filters move above the results and stop sticking. */
  body .esa-listing__grid{ grid-template-columns: 1fr; gap: var(--space-l); }
  body .esa-filters{ position: static; }
  body .esa-filters__body{ display: none; }
  body .esa-filters[data-esa-open] .esa-filters__body{ display: flex; flex-direction: column; gap: var(--space-xl); }
  body .esa-filters__toggle{ display: flex; }
}

@media (max-width: 767px) {
  body .esa-eq-grid{ grid-template-columns: 1fr; }
  body .esa-toolbar{ flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
  body .esa-cta-band__inner{ flex-direction: column; align-items: flex-start; }
  body .esa-cta-band__title{ max-width: 100%; }
  body .esa-cta-band__bg{ background-attachment: scroll; }
}


/* ==ESA-EQUIPMENT-END== */

/* ==ESA-EQUIP-OVERRIDES-START== */
/* =============================================================================
   Equipment archive — Bricks-only overrides (Stage 2)
   These rules exist because Bricks' native query-filter and pagination elements
   emit their own markup, which the Stage-1 stylesheet never saw. They restyle
   that markup to the approved design. Not used by the standalone Stage-1 page.

   Filter markup (per option):
     ul.esa-filter-radio | ul.esa-filter-check
       > li > label(.brx-option-active|.brx-option-disabled)
           > input.brx-a11y-hidden
           + span.brx-input-indicator
           + span.brx-option-text > span.brx-option-count
   ============================================================================= */

/* Shared: reset list chrome, hide native indicator + count, drop empty terms */
body .esa-filter-radio,
body .esa-filter-check{ list-style: none; margin: 0; padding: 0; }
body .esa-filter-radio .brx-input-indicator,
body .esa-filter-check .brx-input-indicator{ display: none; }
body .esa-filter-radio .brx-option-count,
body .esa-filter-check .brx-option-count{ display: none; }
body .esa-filter-radio li:has(> label.brx-option-disabled),
body .esa-filter-check li:has(> label.brx-option-disabled){ display: none; }
body .esa-filter-radio .brx-option-text,
body .esa-filter-check .brx-option-text{ color: inherit; }
body .esa-filter-radio label,
body .esa-filter-check label{
  display: flex;
  align-items: center;
  min-height: 40px;
  margin: 0;
  cursor: pointer;
  font-size: var(--text-s);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}

/* Category — full-width pill buttons (single-select radio) */
body .esa-filter-radio{ display: flex; flex-direction: column; gap: var(--space-xs); }
body .esa-filter-radio label{
  width: 100%;
  min-height: 48px;
  padding: var(--space-s) var(--space-m);
  border: 1px solid transparent;
  border-radius: var(--radius-m);
  background: transparent;
  color: var(--charcoal);
  text-align: left;
}
body .esa-filter-radio label:hover{ background: color-mix(in srgb, var(--esa-violet) 14%, #fff); }
body .esa-filter-radio label.brx-option-active,
body .esa-filter-radio label:has(input:checked){
  background: var(--esa-violet);
  border-color: var(--esa-violet);
  color: var(--white);
}

/* Brand + condition — 2-column chip grid (multi-select checkbox).
   Bricks' .brxe-filter-checkbox defaults to flex-direction:column, so use grid. */
body .esa-filter-check{ display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-s); }
body .esa-filter-check li{ display: block; }
body .esa-filter-check label{
  width: 100%;
  min-height: 56px;
  justify-content: center;
  text-align: center;
  padding: var(--space-s);
  border: 1px solid var(--technical-grey);
  border-radius: var(--radius-m);
  background: var(--white);
  color: var(--charcoal);
}
body .esa-filter-check label:hover{ border-color: var(--esa-violet); }
body .esa-filter-check label.brx-option-active,
body .esa-filter-check label:has(input:checked){
  background: var(--esa-violet);
  border-color: var(--esa-violet);
  color: var(--white);
}

/* Pagination — Bricks renders .bricks-pagination > (ul li)? a.page-numbers */
body .esa-pagination .bricks-pagination{
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-block-start: var(--space-m);
}
body .esa-pagination .bricks-pagination ul,
body .esa-pagination .bricks-pagination li{ display: contents; }
body .esa-pagination .page-numbers{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 40px;
  padding-inline: var(--space-xs);
  border: 1px solid var(--technical-grey);
  border-radius: var(--radius-m);
  background: var(--white);
  color: var(--charcoal);
  font-size: var(--text-s);
  text-decoration: none;
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}
body .esa-pagination a.page-numbers:hover{ border-color: var(--esa-violet); color: var(--esa-violet); }
body .esa-pagination .page-numbers.current{
  background: var(--esa-violet);
  border-color: var(--esa-violet);
  color: var(--white);
}
body .esa-pagination .page-numbers.dots{ border: 0; background: none; min-width: auto; }

/* The equipment archive uses the colour Figma split photo — drop the shared
   grayscale treatment here only (scoped to the archive so Home is untouched).
   Starts with `body` so the prefixer leaves it, keeping specificity above the
   shared `body .esa-split__media img` grayscale rule. */
body.post-type-archive-equipment .esa-split__media img { filter: none; }

/* ==ESA-EQUIP-OVERRIDES-END== */

/* ==ESA-DETAIL-START== */
/* =============================================================================
   Equipment Sales Australia — Equipment detail (single machine)
   Standalone build (Stage 1 of docs/SPEC-PLAN.md). Shared shell, tokens and the
   equipment card live in ../_shared/base.css; this file adds only what is
   specific to the machine page. Figma node 153:542.
   Becomes the Bricks single template for the `equipment` CPT.
   ============================================================================= */

:root {
  /* The Figma frame is 1440 wide: 104 gutters, a 737 content column, a 74 gap
     and a 421 rail. Below 1279 the rail drops under the content. */
  --detail-rail: 421px;
  --detail-gap: clamp(2rem, 5.14vw, 74px);

  /* Section headings are Barlow SemiBold 32 in the design (Subtitle token), not
     the condensed display face the page title uses. */
  --detail-heading: clamp(1.5rem, 1.29rem + 1.07vw, 2rem);
  /* Price is Title Page 48 in the design, between --text-2xl and --text-3xl. */
  --detail-price: clamp(2rem, 1.57rem + 2.14vw, 3rem);
}

/* =============================================================================
   HEADER — this page has no hero photo, so the bar needs its own plate
   Every other page puts a scrimmed photo behind the header, which is what makes
   the Ice Grey nav and search legible. Here the first thing under the bar is the
   Alloy title block, and Ice Grey on Alloy measures 1.07:1 — the nav, the search
   field and the logo all disappear.

   Stage 1 handles it with `.esa-header--solid` on the element (base.css). The
   Bricks header is one global template, so no page can apply a modifier to it;
   once this block is pinned to the single-equipment body class on deploy, the
   same rule reaches the built page. The calculator does the same.
   ============================================================================= */
/* Both selectors, because `.esa-glass .esa-header::before` outranks the bare one
   and would keep the refraction filter running behind an opaque plate — a
   compositing pass whose result is then completely covered. */
body.single-equipment .esa-header::before,
body .esa-glass .esa-header::before{
  opacity: 1;
  /* Opaque, not the 0.62 glass. Glass needs something behind it: over the Alloy
     title block the translucent plate only composites to rgb(102,101,105), which
     washes the bar out and leaves the active nav link at 3.4:1. Opaque takes the
     nav to 15.4:1 and the active link to 10.6:1, and it looks like the dark bar
     every other page shows once it is scrolled. */
  background: hsl(245 12% 10%);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* The active link is Esa Violet at rest because on every other page "at rest"
   means over a bright hero photo; it switches to Electric Lilac in the stuck
   state, once the plate is behind it. The plate is behind it from the top here,
   so make the switch from the top too — Esa Violet on the plate is 1.3:1. */
body.single-equipment .esa-nav__link.is-current{ color: var(--electric-lilac); }

/* =============================================================================
   TITLE — category pill + machine name, full width above the two columns
   ============================================================================= */
body .esa-detail-head{
  /* Clears the fixed header: ~143px at 1440, ~109px on a phone. The clamp
     handles the wide end; the floor handles the narrow end, where the clamp
     alone left only 15px of gap. See ../_shared/overrides.css. */
  padding-block: max(clamp(7.5rem, 5.9rem + 8vw, 14rem), calc(48px + 2 * var(--space-xl) + var(--space-l)))
                 var(--space-xl);
  background: var(--alloy);
}

body .esa-detail-head__title{
  max-width: 40ch;
  margin-block-start: var(--space-m);
  color: var(--charcoal);
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 700;
  line-height: 1.2;
  text-transform: uppercase;
}

/* The shared start-state block in base.css does not know this page's title,
   so it would flash at full opacity before motion.js takes over. */
body .esa-js .esa-detail-head__title{ opacity: 0; }

/* =============================================================================
   LAYOUT — content column + buy rail
   ============================================================================= */
body .esa-detail{
  padding-block-end: var(--space-4xl);
  background: var(--alloy);
}

body .esa-detail__grid{
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--detail-rail);
  align-items: start;
  gap: var(--detail-gap);
}

body .esa-detail__main{
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
  min-width: 0;
}

body .esa-detail__rail{
  display: flex;
  flex-direction: column;
  gap: var(--space-l);
  min-width: 0;
}

/* =============================================================================
   GALLERY — one stage image driven by a thumbnail strip
   ============================================================================= */
/* <figure> carries a 40px browser margin that would eat into the column. */
body .esa-gallery{ display: flex; flex-direction: column; gap: var(--space-l); margin: 0; }

body .esa-gallery__stage{
  position: relative;
  aspect-ratio: 737 / 365;
  overflow: hidden;
  border-radius: var(--radius-l);
  background: var(--workshop-white);
}

body .esa-gallery__image{
  width: 100%;
  height: 100%;
  object-fit: cover;
}

body .esa-gallery__badges{
  position: absolute;
  inset-block-start: var(--space-l);
  inset-inline-end: var(--space-l);
  display: flex;
  gap: var(--space-xs);
}

/* The design draws these as the same outlined chip as the category pill. Over a
   photo that needs a backing, so it is a light glass plate rather than a plain
   border — dark text on it stays readable whatever the machine is shot against. */
body .esa-badge{
  padding: 0.5rem 0.85rem;
  border: 1px solid rgb(255 255 255 / 0.7);
  border-radius: var(--radius-m);
  background: rgb(242 242 242 / 0.82);
  backdrop-filter: blur(6px);
  color: var(--charcoal);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

body .esa-gallery__thumbs{
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--space-l);
}

body .esa-gallery__thumb{
  display: block;
  width: 100%;
  aspect-ratio: 122 / 118;
  padding: 0;
  overflow: hidden;
  border: 2px solid transparent;
  border-radius: var(--radius-m);
  background: var(--workshop-white);
  cursor: pointer;
  transition: border-color var(--transition-base), transform var(--transition-base);
}
body .esa-gallery__thumb img{ width: 100%; height: 100%; object-fit: cover; }
body .esa-gallery__thumb:hover{ transform: translateY(-2px); }
body .esa-gallery__thumb[aria-current="true"]{ border-color: var(--esa-violet); }

/* =============================================================================
   CONTENT BLOCKS — description, overview, specifications
   ============================================================================= */
body .esa-detail-block{ display: flex; flex-direction: column; gap: var(--space-m); }

body .esa-detail-block__title{
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: var(--detail-heading);
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
}

body .esa-detail-block__text{
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

/* The source is a bullet list; the design shows plain lines, so the markers go
   but the list semantics stay. The gap has to clear the line-height, or a
   wrapped item reads as two separate points. */
body .esa-detail-block__list{
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

/* Bare headings the source writes inside the body ("STANDARD FEATURES",
   "Specifications:") — a label for the lines under it, not one of them. */
body .esa-detail-block__lead{
  margin-block-start: var(--space-xs);
  color: var(--charcoal);
  font-size: var(--text-s);
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.4;
  text-transform: uppercase;
}
body .esa-detail-block__lead:first-child{ margin-block-start: 0; }

/* ---------- Specification bento ------------------------------------------ */
body .esa-spec-grid{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-l);
}

body .esa-spec{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--space-l);
  border-radius: var(--radius-m);
  background: var(--workshop-white);
}

body .esa-spec__icon{ width: auto; height: 20px; }

/* The five designed tiles carry an icon; the tiles built from the imported spec
   rows do not, and would otherwise reserve the space where one would sit. */
body .esa-spec:not(:has(.esa-spec__icon)) .esa-spec__label{ margin-block-start: 0; }

body .esa-spec__label{
  margin-block-start: var(--space-m);
  color: var(--charcoal);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
}

body .esa-spec__value{
  margin-block-start: var(--space-2xs);
  color: var(--machine-grey);
  font-size: var(--text-l);
  line-height: 1.2;
  text-transform: uppercase;
}

/* =============================================================================
   RAIL — price, finance calculator, enquiry. One card chrome, three payloads.
   ============================================================================= */
body .esa-rail-card{
  display: flex;
  flex-direction: column;
  gap: var(--space-l);
  padding: var(--space-l);
  border-radius: 10px;
  background: var(--workshop-white);
}

body .esa-rail-card__title{
  color: var(--machine-grey);
  font-family: var(--font-body);
  font-size: var(--text-l);
  font-weight: 400;
  line-height: 1.2;
  text-transform: uppercase;
}

/* ---------- Price -------------------------------------------------------- */
body .esa-price{ display: flex; flex-direction: column; gap: var(--space-2xs); }

body .esa-price__value{
  color: var(--charcoal);
  font-family: var(--font-display);
  font-size: var(--detail-price);
  font-weight: 700;
  line-height: 1.2;
}

body .esa-price__note{
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

/* ---------- Rail buttons — 38px tall, quieter than the hero CTAs ---------- */
body .esa-rail-actions{ display: flex; flex-direction: column; gap: var(--space-m); }

body .esa-rail-btn{
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;               /* design draws 38; 44 keeps the tap target legal */
  padding: var(--space-xs) var(--space-s);
  border: 1px solid var(--steel-violet);
  border-radius: var(--radius-m);
  background: transparent;
  color: var(--machine-grey);
  font-family: inherit;
  font-size: var(--text-s);
  letter-spacing: var(--tracking-wide);
  text-align: center;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}
body .esa-rail-btn:hover{ border-color: var(--esa-violet); color: var(--esa-violet-d-1); }

body .esa-rail-btn--primary{
  border-color: var(--esa-violet-d-1);
  background: var(--esa-violet-d-1);   /* d-1 rather than the brand tint: 14px label needs AA */
  color: var(--ice-grey);
  box-shadow: 0 4px 3px rgb(0 0 0 / 0.1), 0 10px 7.5px rgb(0 0 0 / 0.1);
}
body .esa-rail-btn--primary:hover{
  border-color: var(--ink);
  background: var(--ink);
  color: var(--white);
}

/* ---------- Two icon actions under a violet rule ------------------------- */
body .esa-rail-split{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-m);
  padding-block-start: var(--space-m);
  border-block-start: 1px solid var(--esa-violet);
}

body .esa-rail-link{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  min-height: 44px;
  color: var(--machine-grey);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: center;
  text-transform: uppercase;
  transition: color var(--transition-base);
}
/* Stage 1 ships these as <img>; the Bricks build inlines the same exports as
   <svg>, which has no intrinsic size to fall back on. Size both. */
body .esa-rail-link img,
body .esa-rail-link svg{ width: auto; height: 20px; }
body .esa-rail-link:hover{ color: var(--esa-violet-d-1); }

/* ---------- Form fields — shared by the calculator and the enquiry ------- */
body.single-equipment .esa-field{ display: flex; flex-direction: column; gap: var(--space-xs); min-width: 0; }

body.single-equipment .esa-field-row{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-m);
}

body.single-equipment .esa-field__label{
  color: var(--machine-grey);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

body.single-equipment .esa-input{
  width: 100%;
  min-height: 50px;
  padding: var(--space-s) var(--space-m);
  border: 1px solid transparent;
  border-radius: var(--radius-m);
  background: var(--alloy);
  color: var(--charcoal);
  font-family: inherit;
  font-size: var(--text-m);
  line-height: 1.4;
  transition: border-color var(--transition-base), background-color var(--transition-base);
}
body.single-equipment .esa-input::placeholder{ color: var(--machine-grey); }
body.single-equipment .esa-input:hover{ border-color: var(--technical-grey); }
body.single-equipment .esa-input:focus-visible{
  outline: 2px solid var(--esa-violet);
  outline-offset: 2px;
  border-color: transparent;
}

body.single-equipment .esa-input--area{ min-height: 84px; resize: vertical; }

body.single-equipment .esa-input--select{
  appearance: none;
  cursor: pointer;
  /* Inlined rather than a file: the block ships into esa-pages.css from the
     child theme, where a page-relative path resolves against the theme and
     404s. This is the data URI the live sheet already carries. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13.5' height='7.5' viewBox='0 0 13.5 7.5' fill='none'%3E%3Cpath d='M0.75 0.75L6.75 6.75L12.75 0.75' stroke='%235E5E5E' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-m) center;
  background-size: 12px 6px;
  padding-inline-end: var(--space-xl);
}

/* ---------- Calculator result ------------------------------------------- */
body .esa-estimate{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2xs);
  padding-block-start: var(--space-m);
  border-block-start: 1px solid var(--esa-violet);
  text-align: center;
}

body .esa-estimate__label{
  color: var(--machine-grey);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

body .esa-estimate__value{
  color: var(--charcoal);
  font-size: var(--detail-heading);
  font-weight: 600;
  line-height: 1.2;
}

body.single-equipment .esa-form-status{
  color: var(--esa-violet-d-1);
  font-size: var(--text-s);
  line-height: 1.4;
}
body.single-equipment .esa-form-status:empty{ display: none; }
body.single-equipment .esa-form-status[data-state="error"]{ color: #A4343A; }

/* =============================================================================
   RELATED — dark band carrying the same equipment card
   ============================================================================= */
body .esa-related{
  padding-block: var(--space-4xl);
  background: var(--ink);
  color: var(--ice-grey);
}

body .esa-related__head{
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-xl);
  margin-block-end: var(--space-2xl);
}

body .esa-related__title{
  max-width: 30ch;
  margin-block-start: var(--space-m);
  color: var(--ice-grey);
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 700;
  line-height: 1.2;
  text-transform: uppercase;
}

body .esa-related__nav{ display: flex; flex: none; gap: var(--space-l); }

body .esa-related__btn{
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--steel-violet);
  border-radius: var(--radius-m);
  background: transparent;
  color: var(--ice-grey);
  cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base), opacity var(--transition-base);
}
body .esa-related__btn:hover{ border-color: var(--electric-lilac); color: var(--electric-lilac); }
body .esa-related__btn[disabled]{ opacity: 0.35; cursor: default; }
body .esa-related__btn[disabled]:hover{ border-color: var(--steel-violet); color: var(--ice-grey); }

/* Four across at 1440, and a swipeable snap rail once they no longer fit. */
body .esa-related__grid{
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - var(--space-l) * 3) / 4);
  gap: var(--space-l);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* Cards lift on hover; without room the transform clips against the scroller. */
  padding-block: 4px;
}
body .esa-related__grid::-webkit-scrollbar{ display: none; }
body .esa-related__grid > li{ scroll-snap-align: start; }

/* =============================================================================
   RESPONSIVE — Bricks breakpoints
   ============================================================================= */
@media (max-width: 1279px) {
  /* The rail can no longer hold 421px next to a readable content column. */
  body .esa-detail__grid{ grid-template-columns: 1fr; }
  body .esa-detail__rail{ display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  body .esa-related__grid{ grid-auto-columns: calc((100% - var(--space-l) * 2) / 3); }
}

@media (max-width: 991px) {
  body .esa-gallery__thumbs{ gap: var(--space-m); }
  body .esa-related__grid{ grid-auto-columns: calc((100% - var(--space-l)) / 2); }
  body .esa-related__head{ align-items: flex-start; }
}

@media (max-width: 767px) {
  body .esa-detail__rail{ grid-template-columns: 1fr; }
  body .esa-spec-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-m); }
  body .esa-gallery__stage{ aspect-ratio: 4 / 3; }
  body .esa-related__grid{ grid-auto-columns: 82%; }
  body .esa-related__nav{ display: none; }   /* swipe replaces the buttons */
}

@media (max-width: 478px) {
  body .esa-spec-grid{ grid-template-columns: 1fr; }
  body .esa-gallery__thumbs{ grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-s); }
  body.single-equipment .esa-field-row{ grid-template-columns: 1fr; }
}
/* ==ESA-DETAIL-END== */

/* ==ESA-SERVICES-START== */
/* =============================================================================
   Equipment Sales Australia — Service
   Standalone build (Stage 1 of docs/SPEC-PLAN.md). The shell, hero, split, CTA
   band and footer all come from ../_shared/base.css; this file adds only the
   two components this page introduces. Figma node 1:1404.
   ============================================================================= */

/* The Service page's own band; the card itself lives in ../_shared/base.css. */
body.esa-page-services .esa-lifecycle{ background: var(--alloy); }

/* Six promises read as two columns of three in the design, filled down the
   column rather than across the row so the pairs match Figma. */
body.esa-page-services .esa-checklist--two-col{
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(3, auto);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 15.5px var(--space-m);
}
/* The six icons are drawn at a common 12px width with their own heights (12–16),
   so width is what to pin — squaring them off a fixed height oversizes half. */
body.esa-page-services .esa-checklist--two-col svg{ width: 12px; height: auto; }

/* The design shows this workshop in colour; the shared split desaturates by
   default for the Home page's editorial treatment. */
body.esa-page-services .esa-split__media img{ filter: none; }

/* The split content column stacks CTA, copy and list on one gap; the eyebrow
   and the button both want to sit tighter than that. */
body.esa-page-services .esa-split__content .esa-btn{ margin-block-start: var(--space-xs); }

/* =============================================================================
   CTA BAND — page image only; the band lives in _shared/base.css
   ============================================================================= */
body.esa-page-services .esa-cta-band__bg{ background-image: url("https://esa.wearemyooz.com/wp-content/uploads/2026/08/esa-service-cta.jpg"); }

/* =============================================================================
   RESPONSIVE — Bricks breakpoints
   ============================================================================= */
@media (max-width: 767px) {
  body.esa-page-services .esa-checklist--two-col{ grid-auto-flow: row; grid-template-columns: 1fr; grid-template-rows: none; }
}
/* ==ESA-SERVICES-END== */

/* ==ESA-FINANCE-START== */
/* =============================================================================
   Equipment Sales Australia — Finance
   Standalone build (Stage 1 of docs/SPEC-PLAN.md). The shell, hero, split,
   action card and footer all come from ../_shared/base.css; this file adds the
   four components this page introduces. Figma node 1:820.
   ============================================================================= */

/* The shared 15ch cap is tuned to Home's shorter headline and leaves 489px,
   9px short of "Finance Solutions" — so this hero broke onto three lines where
   the design has two. Widened just enough to hold the longer line; the break
   after "Flexible" still falls out of the measure. */
body.esa-page-finance .esa-hero__title{ max-width: 17ch; }

/* Both photos on this page are colour; the shared split desaturates by default
   for the Home page's editorial treatment.

   The design crops both to the same 600x570 plate. The shared rule leaves the
   image at its own ratio, which here means a 4:3 landscape and a 2:3 portrait
   rendering at wildly different heights either side of the page. */
body.esa-page-finance .esa-split__media img{ filter: none; }

/* Direct child only — the logo card nested inside the media column carries its
   own ratio and must not be cropped to the plate. */
body.esa-page-finance .esa-split__media > img{
  aspect-ratio: 600 / 570;
  object-fit: cover;
}

/* The split content column stacks on one gap; the button wants to sit tighter. */
body.esa-page-finance .esa-split__content .esa-btn{ margin-block-start: var(--space-xs); }

/* Figma sets the phone number as plain copy, but here it is a tel: link inside a
   paragraph — with no underline and the inherited colour there is nothing to
   tell a reader it is actionable at all. */
body.esa-page-finance .esa-split__text a{
  color: var(--esa-violet-d-1);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color var(--transition-base);
}
body.esa-page-finance .esa-split__text a:hover{ color: var(--esa-violet); }

/* =============================================================================
   LOGO CARD — the finance partner's mark, over the photo's bottom corner
   ============================================================================= */
body.esa-page-finance .esa-split__media--logo{ position: relative; }

/* Notched into the photo's bottom-right corner rather than floated over it. An
   inverted radius only reads where two edges MEET — the card has to be flush to
   the plate's right and bottom, so the white looks carved out of the photo
   instead of laid on top of it.

   Four corners, three different jobs:
     top-left      convex — the only corner that projects into the photo
     bottom-right  follows the plate's own 8px corner
     top-right     inverted, where the card's top edge meets the plate's right
     bottom-left   inverted, where the card's left edge meets the plate's bottom
   The two inverted ones are fillets drawn outside the box, below. */
body.esa-page-finance .esa-logo-card{
  --_r: 22px;
  /* A gutter along the two edges that face the photo, drawn in the page colour
     so the notch reads as a cut with a little air rather than the card being
     welded to the plate. It is a border, not an offset: the box stays flush to
     the plate's right and bottom, which is what the fillets need. */
  --_gap: 8px;
  position: absolute;
  inset-block-end: 0;
  inset-inline-end: 0;
  display: grid;
  place-items: center;
  /* The card shrink-wraps the logo, and an absolutely positioned box sizes off
     max-content — so the width has to come from the img, not from a percentage
     of the card, or the file's own 424px pixel width sets it. */
  max-width: calc(100% - var(--space-xl));
  padding: var(--space-l);
  border-block-start: var(--_gap) solid var(--alloy);
  border-inline-start: var(--_gap) solid var(--alloy);
  border-start-start-radius: var(--_r);
  border-end-end-radius: 8px;      /* the plate's radius, so the corner matches */
  background: var(--workshop-white);
}
body.esa-page-finance .esa-logo-card img{
  display: block;
  width: 13.25rem;                 /* 212 as drawn */
  max-width: 100%;
  height: auto;
}

/* Each fillet is a square with a quarter-disc bitten out of the corner nearest
   the card, leaving the concave sliver that carries the gutter's edge into the
   plate's edge. Same gradient both times — one sits above the card, the other
   to its left, and each fills the corner they share. They paint in the gutter
   colour, since it is the gutter's outline they continue, not the card's. */
body.esa-page-finance .esa-logo-card::before,
body.esa-page-finance .esa-logo-card::after{
  content: "";
  position: absolute;
  width: var(--_r);
  aspect-ratio: 1;
  background-image: radial-gradient(circle at 0 0,
    transparent var(--_r), var(--alloy) calc(var(--_r) + 0.5px));
  pointer-events: none;
}
/* Above the card, flush to the plate's right edge. */
body.esa-page-finance .esa-logo-card::before{
  inset-block-end: 100%;
  inset-inline-end: 0;
}
/* Left of the card, flush to the plate's bottom edge. */
body.esa-page-finance .esa-logo-card::after{
  inset-block-end: 0;
  inset-inline-end: 100%;
}

/* =============================================================================
   BLUEPRINT — dark band carrying the shared action card, numbered
   ============================================================================= */
body.esa-page-finance .esa-blueprint{
  background: var(--ink);
  color: var(--ice-grey);
}

/* The band sets a colour for its children to inherit, which is enough in Stage 1
   but not in Bricks: .brxe-heading assigns a colour explicitly, and an explicit
   value beats an inherited one at any specificity. Left to inherit, this heading
   came out charcoal on ink at 1.13:1. */
body.esa-page-finance .esa-blueprint .esa-section-head__title{ color: var(--ice-grey); }

/* The badge holds a step number rather than an icon, so it carries real text —
   d-1 rather than the brand tint, which is 4.02:1 on the card at this size. */
body.esa-page-finance .esa-action__badge--number{
  color: var(--esa-violet-d-1);
  font-family: var(--font-body);
  font-size: var(--text-l);        /* Subheading 20 */
  font-weight: 400;
  line-height: 1.2;
}

/* The steps are an ordered list; the numbers are already drawn in the badges. */
body.esa-page-finance .esa-blueprint .esa-action-grid{ list-style: none; margin: 0; padding: 0; }

/* =============================================================================
   QUOTE — dark band, one card split between a photo and the form
   ============================================================================= */
body.esa-page-finance .esa-quote{ background: var(--ink); }

body.esa-page-finance .esa-quote__card{
  display: grid;
  /* 549.81 / 682.19 of the 1232 card, as drawn. */
  grid-template-columns: minmax(0, 55fr) minmax(0, 68fr);
  overflow: hidden;
  border-radius: 12px;
  box-shadow: 0 40px 80px -40px rgb(0 0 0 / 0.55);
}

/* ---------- Visual side --------------------------------------------------- */
body.esa-page-finance .esa-quote__visual{
  position: relative;
  display: grid;
  min-height: 40rem;               /* 640 as drawn */
  isolation: isolate;
}

body.esa-page-finance .esa-quote__visual img{
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
}

body.esa-page-finance .esa-quote__scrim{
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(37 36 45 / 0.72) 0%, rgb(37 36 45 / 0.88) 100%);
}

/* Heading block at the top, trust list at the foot — the design pins them to
   opposite ends of the panel rather than stacking them on a gap. */
body.esa-page-finance .esa-quote__visual-inner{
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-xl);
  padding: var(--space-xl);        /* 48 as drawn */
}

body.esa-page-finance .esa-quote__title{
  margin-block-start: var(--space-m);
  color: var(--ice-grey);
  font-size: var(--text-4xl);      /* Title Hero 72 */
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-finance .esa-trust{
  display: flex;
  flex-direction: column;
  gap: var(--space-s);             /* 16 as drawn */
  color: var(--ice-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}
body.esa-page-finance .esa-trust li{ display: flex; align-items: center; gap: var(--space-s); }
body.esa-page-finance .esa-trust svg{ flex: none; width: auto; height: 21px; color: var(--esa-violet); }

/* ---------- Form side ---------------------------------------------------- */
body.esa-page-finance .esa-quote__form{
  display: flex;
  flex-direction: column;
  gap: var(--space-l);
  padding: var(--space-xl);        /* 48 as drawn */
  background: var(--workshop-white);
}

/* =============================================================================
   RESPONSIVE — Bricks breakpoints
   ============================================================================= */
@media (max-width: 1279px) {
  body.esa-page-finance .esa-quote__title{ font-size: var(--text-3xl); }
}

@media (max-width: 991px) {
  /* The card stacks: photo panel first, then the form. */
  body.esa-page-finance .esa-quote__card{ grid-template-columns: 1fr; }
  body.esa-page-finance .esa-quote__visual{ min-height: 26rem; }
}

@media (max-width: 767px) {
  body.esa-page-finance .esa-quote__visual-inner,
  body.esa-page-finance .esa-quote__form{ padding: var(--space-l); }
  body.esa-page-finance .esa-quote__form{ gap: var(--space-m); }
}

@media (max-width: 478px) {
  /* Held at the design's 212px the card covers 76% of a phone-width photo
     against 47% at 1440, so the mark scales down with the plate. It stays flush
     to the corner — the notch depends on that; only the radius comes down with
     the card, so the corner does not swallow a 76px-tall box. */
  body.esa-page-finance .esa-logo-card{
    --_r: 16px;
    padding: var(--space-m);
  }
  body.esa-page-finance .esa-logo-card img{ width: 9rem; }
}
/* ==ESA-FINANCE-END== */

/* ==ESA-ABOUT-START== */
/* =============================================================================
   Equipment Sales Australia — About
   Standalone build (Stage 1 of docs/SPEC-PLAN.md). The shell, hero, split,
   value prop, stat panel, action card and footer all come from
   ../_shared/base.css; this file adds the three components this page
   introduces. Figma node 1:1114.
   ============================================================================= */

/* The shared 15ch cap leaves 489px, short of the 547 "Industry Expertise" needs,
   so this hero broke onto three lines where the design has two. 17.5ch clears
   that and still stops short of the 592 that would pull "Industry" up. */
body.esa-page-about .esa-hero__title{ max-width: 17.5ch; }

/* The split photo is shown in colour here; the shared rule desaturates by
   default for the Home page's editorial treatment. */
body.esa-page-about .esa-split__media img{ filter: none; }

/* The design crops it to the same 600x570 plate the other pages use. */
body.esa-page-about .esa-split__media > img{
  aspect-ratio: 600 / 570;
  object-fit: cover;
}

/* =============================================================================
   SECTION HEAD — this page is the first to use the right-hand column
   ============================================================================= */
/* .esa-section-head is already a space-between row, so the paragraph only needs
   a measure and its own colour. */
body.esa-page-about .esa-section-head__lead{
  max-width: 34ch;
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

body.esa-page-about .esa-pillars{ background: var(--alloy); }

/* =============================================================================
   LEGACY — timeline panel beside the copy
   ============================================================================= */
body.esa-page-about .esa-legacy__inner{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: center;
  gap: var(--space-3xl);
}

body.esa-page-about .esa-legacy__text{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-xl);
}

body.esa-page-about .esa-legacy__title{
  font-size: var(--text-4xl);      /* Title Hero 72, larger than a section head */
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-about .esa-legacy__lead{
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

/* ---------- Crew line ----------------------------------------------------- */
body.esa-page-about .esa-crew{ display: flex; align-items: center; gap: var(--space-m); }

/* Overlapping tiles, each ringed so the stack reads as separate people rather
   than one strip. The ring is white, not the page colour — against Alloy the
   two tints are close enough that the tiles merge.

   The design fills these with staff photos; there are none, and inventing faces
   on a live page is worse than an obvious placeholder, so they carry the brand
   tint and a person glyph until the client supplies real ones. */
body.esa-page-about .esa-crew__avatars{ display: flex; }
body.esa-page-about .esa-crew__avatar{
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 2px solid var(--white);
  border-radius: 12px;
  background: var(--esa-violet-l-4);
  color: var(--esa-violet-d-1);
}
body.esa-page-about .esa-crew__avatar + .esa-crew__avatar{ margin-inline-start: -16px; }
body.esa-page-about .esa-crew__avatar svg{ width: 26px; height: 26px; }

body.esa-page-about .esa-crew__text{ display: flex; flex-direction: column; }

body.esa-page-about .esa-crew__headline{
  color: var(--charcoal);
  font-size: var(--text-l);        /* Subheading 20 */
  line-height: 1.2;
  text-transform: uppercase;
}

/* Figma paints this Primary, which is 3.61:1 at 12px on Alloy. */
body.esa-page-about .esa-crew__caption{
  color: var(--esa-violet-d-1);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
}

/* =============================================================================
   TIMELINE — four milestones on a curve
   ============================================================================= */
body.esa-page-about .esa-timeline{
  position: relative;
  /* The drawn panel, so the curve keeps its proportions as the column flexes. */
  aspect-ratio: 563.5 / 400;
  padding: var(--space-l);
  border: 1px solid var(--steel-violet);
  border-radius: 10px;
  background: rgb(220 220 238 / 0.1);
}

/* Stretched to the padded box rather than drawn at a fixed size, so the curve
   and the dots stay registered at every width. `non-scaling-stroke` keeps the
   line an even weight despite the non-uniform scale. */
body.esa-page-about .esa-timeline__path{
  position: absolute;
  inset: var(--space-l);
  width: calc(100% - var(--space-l) * 2);
  height: calc(100% - var(--space-l) * 2);
  color: var(--esa-violet);
  opacity: 0.55;
}

body.esa-page-about .esa-timeline__list{ position: relative; height: 100%; }

/* Each milestone is pinned to its point on the curve. Percentages, not pixels:
   the dots have to track the stretched path, and a flex row would place them by
   content width instead — the labels are all different lengths. */
body.esa-page-about .esa-timeline__item{
  position: absolute;
  left: var(--_x);
  top: var(--_y);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  width: max-content;
  max-width: 9rem;
  /* Anchored on the dot, not the box, so the label can grow downward freely. */
  transform: translate(-50%, -8px);
}
body.esa-page-about .esa-timeline__item:nth-child(1){ --_x: 8.24%;  --_y: 40.27%; }
body.esa-page-about .esa-timeline__item:nth-child(2){ --_x: 35.66%; --_y: 21.11%; }
body.esa-page-about .esa-timeline__item:nth-child(3){ --_x: 65.15%; --_y: 59.43%; }
body.esa-page-about .esa-timeline__item:nth-child(4){ --_x: 91.56%; --_y: 41.47%; }

body.esa-page-about .esa-timeline__dot{
  width: 16px;
  height: 16px;
  border-radius: var(--radius-pill);
  background: var(--esa-violet);
  box-shadow: 0 0 15px 0 rgb(50 51 116 / 0.5);
}

body.esa-page-about .esa-timeline__year{
  color: var(--charcoal);
  font-size: var(--text-l);        /* Subheading 20 */
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-about .esa-timeline__label{
  color: var(--machine-grey);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
}

/* The present is the emphasis: a larger dot with a stronger glow. */
body.esa-page-about .esa-timeline__item--now{ transform: translate(-50%, -12px); }
body.esa-page-about .esa-timeline__item--now .esa-timeline__dot{
  width: 24px;
  height: 24px;
  box-shadow: 0 0 20px 0 rgb(50 51 116 / 0.8);
}

/* =============================================================================
   SPEAK — closing card, copy left and the two ways to reach us bottom-right
   ============================================================================= */
body.esa-page-about .esa-speak__card{
  display: grid;
  /* 633 for the copy, as drawn — a narrower column breaks the 72px heading
     onto four lines where the design has two. */
  grid-template-columns: minmax(0, 39.5rem) auto;
  align-items: end;
  gap: var(--space-xl);
  padding: clamp(var(--space-l), 5vw, 4.5rem);   /* 72 at 1440 */
  border-radius: 10px;
  background: var(--workshop-white);
  box-shadow: 0 30px 60px -40px rgb(37 36 45 / 0.5);
}

body.esa-page-about .esa-speak__body{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-m);
}

body.esa-page-about .esa-speak__title{
  font-size: var(--text-4xl);      /* Title Hero 72 */
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-about .esa-speak__lead{
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

body.esa-page-about .esa-speak__actions{
  display: flex;
  flex-wrap: wrap;
  justify-self: end;
  gap: var(--space-m);
}

/* =============================================================================
   RESPONSIVE — Bricks breakpoints
   ============================================================================= */
@media (max-width: 991px) {
  body.esa-page-about .esa-legacy__inner{ grid-template-columns: 1fr; gap: var(--space-xl); }

  /* Stacked, the card has the full width, so the copy no longer needs to be
     held back from the buttons. */
  body.esa-page-about .esa-speak__card{ grid-template-columns: 1fr; }
  body.esa-page-about .esa-speak__actions{ justify-self: start; }
}

@media (max-width: 767px) {
  body.esa-page-about .esa-section-head__lead{ max-width: 100%; }

  /* The curve stops working long before this: four labels across a phone width
     collide, and squeezing the horizontal spread makes the milestones illegible.
     It becomes a plain vertical timeline instead — the same four moments read
     top to bottom, with the curve dropped rather than distorted. */
  body.esa-page-about .esa-timeline{
    aspect-ratio: auto;
    padding: var(--space-l) var(--space-m);
  }
  body.esa-page-about .esa-timeline__path{ display: none; }

  body.esa-page-about .esa-timeline__list{
    display: flex;
    flex-direction: column;
    gap: var(--space-l);
    height: auto;
    padding-inline-start: var(--space-m);
    /* The rule the dots sit on, in place of the curve. */
    border-inline-start: 2px solid rgb(111 112 181 / 0.35);
  }

  body.esa-page-about .esa-timeline__item{
    position: static;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 0 var(--space-m);
    width: auto;
    max-width: 100%;
    transform: none;
  }
  body.esa-page-about .esa-timeline__item .esa-timeline__dot{ grid-row: span 2; margin-inline-start: -1.5rem; }
  body.esa-page-about .esa-timeline__year,
  body.esa-page-about .esa-timeline__label{ text-align: start; }
  body.esa-page-about .esa-timeline__item--now{ transform: none; }
}

@media (max-width: 478px) {
  body.esa-page-about .esa-speak__actions .esa-btn{ flex: 1 1 100%; }
}
/* ==ESA-ABOUT-END== */

/* ==ESA-CONTACT-START== */
/* =============================================================================
   Equipment Sales Australia — Contact
   Standalone build (Stage 1 of docs/SPEC-PLAN.md). The shell, hero, form
   controls, CTA band and footer all come from ../_shared/base.css; this file
   adds the three components this page introduces. Figma node 1:1687.
   ============================================================================= */

/* =============================================================================
   PROJECT INQUIRY — one card, dark form side and light channels side
   ============================================================================= */
body.esa-page-contact .esa-contact__card{
  display: grid;
  /* 718.67 / 513 of the 1232 card, as drawn. */
  grid-template-columns: minmax(0, 719fr) minmax(0, 513fr);
  overflow: hidden;
  border-radius: 10px;
  box-shadow: 0 30px 60px -40px rgb(37 36 45 / 0.5);
}

/* ---------- Form side ----------------------------------------------------- */
body.esa-page-contact .esa-contact__form-panel{
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  padding: clamp(var(--space-l), 5vw, 4.5rem);   /* 72 at 1440 */
  background: var(--ink);
}

body.esa-page-contact .esa-contact__intro{ display: flex; flex-direction: column; gap: var(--space-xs); }

body.esa-page-contact .esa-contact__title{
  color: var(--ice-grey);
  font-size: clamp(2rem, 1.57rem + 2.14vw, 3rem);   /* Title Page 48 */
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-contact .esa-contact__lead{
  color: var(--ice-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

body.esa-page-contact .esa-contact__form{ display: flex; flex-direction: column; gap: var(--space-l); }

/* The shared label colour is tuned for the light card on Finance, where the
   design's Steel Violet is 2.5:1. On this dark panel it is the darker violet
   that fails (2.0:1) and Figma's own Steel Violet that passes at 5.15:1. */
body.esa-page-contact .esa-contact__form-panel .esa-field__label{ color: var(--steel-violet); }

/* ---------- Channels side -------------------------------------------------- */
body.esa-page-contact .esa-contact__details{
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(var(--space-xl), 5vw, 4.5rem);      /* 72 at 1440 */
  padding: clamp(var(--space-l), 5vw, 4.5rem);
  background: var(--workshop-white);
}

/* A rule down the left rather than an underline — the design uses it to tie the
   heading to the list beneath it. */
body.esa-page-contact .esa-panel-title{
  padding-inline-start: 28px;
  border-inline-start: 4px solid var(--esa-violet);
  color: var(--esa-violet-d-2);
  font-family: var(--font-body);
  font-size: clamp(1.5rem, 1.29rem + 1.07vw, 2rem);   /* Subtitle 32 */
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-contact .esa-channels{ display: flex; flex-direction: column; gap: var(--space-xl); }

body.esa-page-contact .esa-channel{ display: flex; align-items: flex-start; gap: var(--space-l); }

/* Same 48px bordered badge as the action card, so the two read as one family. */
body.esa-page-contact .esa-channel__badge{
  display: grid;
  place-items: center;
  flex: none;
  width: 48px;
  height: 48px;
  border: 1px solid var(--steel-violet);
  border-radius: var(--radius-m);
  color: var(--esa-violet);
}
body.esa-page-contact .esa-channel__badge svg{ width: auto; height: 20px; }

body.esa-page-contact .esa-channel__text{ display: flex; flex-direction: column; gap: var(--space-2xs); }

body.esa-page-contact .esa-channel__title{
  color: var(--esa-violet-d-2);
  font-size: var(--text-l);        /* Subheading 20 */
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-contact .esa-channel__value{
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}
body.esa-page-contact .esa-channel__value a{
  color: var(--esa-violet-d-1);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color var(--transition-base);
}
body.esa-page-contact .esa-channel__value a:hover{ color: var(--esa-violet); }

/* =============================================================================
   QUICK LINKS — two dark cards under a centred heading
   ============================================================================= */
body.esa-page-contact .esa-quicklinks__title{
  max-width: 56rem;                /* 896 as drawn */
  margin-inline: auto;
  margin-block-end: var(--space-xl);
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: clamp(1.5rem, 1.29rem + 1.07vw, 2rem);   /* Subtitle 32 */
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-transform: uppercase;
}

body.esa-page-contact .esa-quicklinks__grid{
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-l);
}

body.esa-page-contact .esa-quicklink{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  min-width: 17.5rem;              /* 280 as drawn */
  height: 100%;
  padding: var(--space-xl);
  border: 1px solid transparent;
  border-radius: var(--radius-s);
  background: var(--ink);
  text-align: center;
  transition: transform var(--transition-base), border-color var(--transition-base);
}
body.esa-page-contact .esa-quicklink:hover{
  transform: translateY(-3px);
  border-color: var(--esa-violet);
}

body.esa-page-contact .esa-quicklink__icon{
  display: grid;
  place-items: center;
  margin-block-end: var(--space-xs);
  color: var(--esa-violet);
}
body.esa-page-contact .esa-quicklink__icon svg{ width: 27px; height: 27px; }
body.esa-page-contact .esa-quicklink:hover .esa-quicklink__icon{ color: var(--electric-lilac); }

body.esa-page-contact .esa-quicklink__title{
  color: var(--ice-grey);
  font-size: var(--text-l);        /* Subheading 20 */
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-contact .esa-quicklink__caption{
  color: var(--workshop-white);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
}

/* =============================================================================
   CLOSING BAND — the shared band, centred and with no button
   ============================================================================= */
body.esa-page-contact .esa-cta-band__bg{ background-image: url("https://esa.wearemyooz.com/wp-content/uploads/2026/08/esa-contact-band.jpg"); }

body.esa-page-contact .esa-cta-band--centred .esa-cta-band__inner{
  justify-content: center;
  text-align: center;
}
body.esa-page-contact .esa-cta-band--centred .esa-cta-band__title{
  max-width: 20ch;
  margin-inline: auto;
}

/* =============================================================================
   RESPONSIVE — Bricks breakpoints
   ============================================================================= */
@media (max-width: 991px) {
  /* The card stacks: form first, then the channels. */
  body.esa-page-contact .esa-contact__card{ grid-template-columns: 1fr; }
  body.esa-page-contact .esa-contact__details{ justify-content: flex-start; }
}

@media (max-width: 478px) {
  body.esa-page-contact .esa-quicklinks__grid{ flex-direction: column; }
  body.esa-page-contact .esa-quicklink{ min-width: 0; }
}
/* ==ESA-CONTACT-END== */

/* ==ESA-CALCULATOR-START== */
/* =============================================================================
   Equipment Sales Australia — Calculate Repayments
   Standalone build (Stage 1 of docs/SPEC-PLAN.md). Shell, form controls and
   footer come from ../_shared/base.css. No Figma frame: this page did not
   exist in the design, so it is assembled from the system's own parts —
   the two-tone card from Contact, the shared inputs, the shared buttons.
   ============================================================================= */

/* =============================================================================
   HERO — text only. There is no photo for this page and inventing one would
   push the tool below the fold for no gain.
   ============================================================================= */
body.esa-page-calculator .esa-calc-hero{
  /* The mobile floor clears the fixed header — see the table in
     ../_shared/overrides.css. max() rather than a media query because this
     hero is padding-driven at every width (no min-height centring to absorb
     a change), so raising the floor only moves the widths that were short. */
  padding-block: max(calc(var(--space-4xl) + var(--space-2xl)), calc(48px + 2 * var(--space-xl) + var(--space-l)))
                 var(--space-2xl);
  background: var(--alloy);
}

/* Stage 1 puts .esa-header--solid on the header for this. The Bricks header is
   one global template, so no page can apply a modifier to it — once this block
   is scoped to the page's body class, the same rule reaches it there.

   Opaque rather than the 0.62 glass, for the reason spelled out in
   ../equipment-detail/styles.css: over a light hero the translucent plate only
   composites to a washed-out mid grey. */
body.esa-page-calculator .esa-header::before,
body.esa-page-calculator .esa-glass .esa-header::before{
  opacity: 1;
  background: hsl(245 12% 10%);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

body.esa-page-calculator .esa-calc-hero__title{
  max-width: 18ch;
  margin-block-start: var(--space-s);
  font-size: var(--text-4xl);
  line-height: 1.1;
  text-transform: uppercase;
}

body.esa-page-calculator .esa-calc-hero__lead{
  max-width: 56ch;
  margin-block-start: var(--space-m);
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.5;
}

/* =============================================================================
   CALCULATOR — inputs on the light side, the answer on the dark side
   ============================================================================= */
body.esa-page-calculator .esa-calc{ padding-block-start: 0; }

body.esa-page-calculator .esa-calc__card{
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 26rem);
  overflow: hidden;
  border-radius: 10px;
  box-shadow: 0 30px 60px -40px rgb(37 36 45 / 0.5);
}

body.esa-page-calculator .esa-calc__inputs{
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  padding: clamp(var(--space-l), 4vw, 3rem);
  background: var(--workshop-white);
}

/* The dollar sign sits inside the field rather than in the label, so the number
   reads as money at a glance and the input keeps its own affordance. */
body.esa-page-calculator .esa-calc__money{ position: relative; display: block; }
body.esa-page-calculator .esa-calc__money-symbol{
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 12px;
  transform: translateY(-50%);
  color: var(--machine-grey);
  font-size: var(--text-l);
  pointer-events: none;
}
body.esa-page-calculator .esa-calc__price{
  padding-inline-start: 28px;
  font-size: var(--text-l);
}

/* The live value belongs beside its label — a slider with no read-out is a
   control you cannot answer a question with. */
body.esa-page-calculator .esa-calc__echo{
  margin-inline-start: var(--space-2xs);
  color: var(--charcoal);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}

body.esa-page-calculator .esa-calc__hint{
  margin-block-start: var(--space-2xs);
  color: var(--machine-grey);
  font-size: var(--text-s);
  line-height: 1.4;
}

/* ---------- Range ---------------------------------------------------------- */
body.esa-page-calculator .esa-range{
  width: 100%;
  height: 24px;
  padding: 0;
  background: transparent;
  appearance: none;
  cursor: pointer;
}
body.esa-page-calculator .esa-range::-webkit-slider-runnable-track{
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--alloy);
}
body.esa-page-calculator .esa-range::-moz-range-track{
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--alloy);
}
body.esa-page-calculator .esa-range::-webkit-slider-thumb{
  appearance: none;
  width: 20px;
  height: 20px;
  margin-block-start: -7px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--esa-violet);
  box-shadow: 0 0 0 0 rgb(111 112 181 / 0.25);
  transition: box-shadow var(--transition-base);
}
body.esa-page-calculator .esa-range::-moz-range-thumb{
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--esa-violet);
}
body.esa-page-calculator .esa-range:hover::-webkit-slider-thumb{ box-shadow: 0 0 0 6px rgb(111 112 181 / 0.2); }
body.esa-page-calculator .esa-range:focus-visible{ outline: none; }
body.esa-page-calculator .esa-range:focus-visible::-webkit-slider-thumb{ box-shadow: 0 0 0 6px rgb(111 112 181 / 0.35); }
body.esa-page-calculator .esa-range:focus-visible::-moz-range-thumb{ box-shadow: 0 0 0 6px rgb(111 112 181 / 0.35); }

/* ---------- Result --------------------------------------------------------- */
body.esa-page-calculator .esa-calc__result{
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: clamp(var(--space-l), 4vw, 3rem);
  background: var(--ink);
  color: var(--ice-grey);
}

body.esa-page-calculator .esa-calc__result-label{
  color: var(--steel-violet);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

body.esa-page-calculator .esa-calc__headline{
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 1.86rem + 3.21vw, 4rem);
  font-weight: 700;
  line-height: 1.1;
}
body.esa-page-calculator .esa-calc__per{
  color: var(--steel-violet);
  font-family: var(--font-body);
  font-size: var(--text-m);
  font-weight: 400;
}

body.esa-page-calculator .esa-calc__monthly{
  color: var(--ice-grey);
  font-size: var(--text-m);
}

body.esa-page-calculator .esa-calc__breakdown{
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin: var(--space-m) 0 0;
  padding-block-start: var(--space-m);
  border-block-start: 1px solid rgb(152 152 176 / 0.35);
}
body.esa-page-calculator .esa-calc__breakdown > div{
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-m);
}
body.esa-page-calculator .esa-calc__breakdown dt{
  color: var(--steel-violet);
  font-size: var(--text-s);
}
body.esa-page-calculator .esa-calc__breakdown dd{
  margin: 0;
  font-size: var(--text-m);
  font-variant-numeric: tabular-nums;
}

body.esa-page-calculator .esa-calc__breakdown-total{
  margin-block-start: var(--space-2xs);
  padding-block-start: var(--space-xs);
  border-block-start: 1px solid rgb(152 152 176 / 0.35);
}
body.esa-page-calculator .esa-calc__breakdown-total dt{ color: var(--ice-grey); font-weight: 600; }
body.esa-page-calculator .esa-calc__breakdown-total dd{ font-weight: 600; }

body.esa-page-calculator .esa-calc__note{
  margin-block-start: auto;
  padding-block-start: var(--space-m);
  color: var(--steel-violet);
  font-size: var(--text-s);
  line-height: 1.4;
}

/* ---------- Assumptions ---------------------------------------------------- */
/* Deliberately not a footnote: the rate is an assumption the number depends on,
   so it is stated at full size rather than hidden in fine print. */
body.esa-page-calculator .esa-calc__assumptions{
  margin-block-start: var(--space-xl);
  padding: var(--space-xl);
  border: 1px solid var(--steel-violet);
  border-radius: 10px;
  background: rgb(220 220 238 / 0.1);
}

body.esa-page-calculator .esa-calc__assumptions-title{
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
}

body.esa-page-calculator .esa-calc__assumptions-list{
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  margin-block-start: var(--space-m);
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.5;
}
body.esa-page-calculator .esa-calc__assumptions-list strong{ color: var(--charcoal); font-weight: 600; }

body.esa-page-calculator .esa-calc__disclaimer{
  margin-block-start: var(--space-m);
  padding-block-start: var(--space-m);
  border-block-start: 1px solid var(--technical-grey);
  color: var(--machine-grey);
  font-size: var(--text-s);
  line-height: 1.5;
}

/* =============================================================================
   NEXT STEP — the same closing card the About page uses
   ============================================================================= */
body.esa-page-calculator .esa-calc-next__card{
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--space-xl);
  padding: clamp(var(--space-l), 5vw, 4.5rem);
  border-radius: 10px;
  background: var(--workshop-white);
  box-shadow: 0 30px 60px -40px rgb(37 36 45 / 0.5);
}

body.esa-page-calculator .esa-calc-next__body{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-m);
  max-width: 46ch;
}

body.esa-page-calculator .esa-calc-next__title{
  font-size: var(--text-3xl);
  line-height: 1.15;
  text-transform: uppercase;
}

body.esa-page-calculator .esa-calc-next__lead{
  color: var(--machine-grey);
  font-size: var(--text-m);
  line-height: 1.4;
}

body.esa-page-calculator .esa-calc-next__actions{
  display: flex;
  flex-wrap: wrap;
  justify-self: end;
  gap: var(--space-m);
}

/* =============================================================================
   RESPONSIVE — Bricks breakpoints
   ============================================================================= */
@media (max-width: 991px) {
  /* Stacked, the answer sits under the controls that produce it. */
  body.esa-page-calculator .esa-calc__card{ grid-template-columns: 1fr; }
  body.esa-page-calculator .esa-calc__note{ margin-block-start: var(--space-m); }

  body.esa-page-calculator .esa-calc-next__card{ grid-template-columns: 1fr; }
  body.esa-page-calculator .esa-calc-next__body{ max-width: 100%; }
  body.esa-page-calculator .esa-calc-next__actions{ justify-self: start; }
}

@media (max-width: 478px) {
  body.esa-page-calculator .esa-calc-next__actions .esa-btn{ flex: 1 1 100%; }
}
/* ==ESA-CALCULATOR-END== */

/* ==ESA-OVERRIDES-START== */
/* pages/_shared/overrides.css, shipped last on purpose. Generated by
   pages/_shared/bricks/deploy_overrides_css.py — do not hand-edit. */
/* =============================================================================
   Equipment Sales Australia — corrections that must outrank the Home block
   The Home block is the unmarked head of esa-pages.css and has no deploy
   script: it does not reproduce from source (31,457 bytes live against
   33,585 built), so rebuilding it for a small fix is not safe. Anything that
   has to override it goes here.

   Rules that have to beat the Home block. The header is one global Bricks
   template and `.esa-hero` is owned by the Home block, so a page stylesheet
   cannot reach either — and the Home block has no deploy script: it is the
   unmarked head of esa-pages.css and does not reproduce from source (31,457
   bytes live against 33,585 built), so it is not safe to rebuild for a one-line
   change. This file ships inside the SHARED block instead, which sits
   immediately after Home and therefore wins.

   Load it AFTER the page's own styles.css in Stage 1, so the local cascade
   matches the deployed one. Media queries add no specificity, so linking it
   earlier would let home/styles.css win and the fix would only apply to the
   pages that take their hero from base.css.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   HERO CLEARANCE UNDER THE FIXED HEADER

   The header is `position: fixed`, so the first section has to make its own room.
   On desktop that room is a side effect rather than a rule: the hero is
   `min-height: clamp(34rem, 62vw, 56.25rem)` with `align-items: center`, so the
   content is centred in a box far taller than it needs, which happens to leave
   the header clear. As the viewport narrows that spare height disappears while
   `--space-4xl` shrinks faster than the header does, and the top padding alone
   decides where the first line lands. Measured on staging:

       width   header   pill top   clearance
       1440    143      232        +89
       1279    139      187        +45
        991    127      128         +1
        375    109       75        -34   ← pill drawn over the logo
        320    108       72        -36

   So below the Figma reference width the clearance is stated explicitly. The
   header's height is its padding plus its tallest child: the 44px menu button
   under 991, the ~48px search field above it. 48px covers both.
   ----------------------------------------------------------------------------- */
@media (max-width: 1279px) {
  body .esa-hero{
    padding-block-start: calc(48px + 2 * var(--space-xl) + var(--space-l));
  }
}

/* -----------------------------------------------------------------------------
   REVEAL IMAGES MUST NOT WIDEN THE PAGE

   `[data-esa-reveal="image"]` starts at `scale(1.12)` behind a full `clip-path`
   inset and animates to scale 1. Nothing is visible in that state, but the
   transformed box is still 420px wide inside a 375px column, so the document
   carried 22px of horizontal scroll on a phone until the section was reached — a
   sideways drag with nothing at the end of it.

   Home's `.esa-why__media` was the only wrapper that left this unclipped; every
   other page's already clips, and Home was the only page overflowing at load.
   `clip` rather than `hidden` so it cannot become a scroll container.
   ----------------------------------------------------------------------------- */
body .esa-why__media{ overflow: clip; }

/* -----------------------------------------------------------------------------
   CATEGORY CARDS BECOME A CAROUSEL ON PHONES

   `.esa-card-grid` is 3 columns, then 2 at 991, then 1 at 767 — and one column
   of six cards is a 1406px wall of scrolling on a phone. Below 767 it becomes a
   snap carousel showing 1.5 cards, so the cut-off second card advertises that
   there is more sideways instead of below.

   Native scroll-snap rather than a slider library: the same 1.5-per-view spec
   costs about 1KB here against 40KB gzipped for Swiper, and the phone's own
   momentum scrolling beats anything driven from JS. Arrows are in
   ../_shared/carousel.js — swiping works without them.
   ----------------------------------------------------------------------------- */
@media (max-width: 767px) {
  body .esa-card-grid{
    --_gap: var(--space-l);
    --_per-view: 1.5;
    --_reveal-lift: 34px;   /* matches gsap.set(items, {y: 34}) in home/motion.js */

    display: flex;
    gap: var(--_gap);
    /* Bleed to the screen edges, so the half card is cut by the screen rather
       than by the container's gutter — that is what reads as "keep going".
       `max-width: none` is required: a global `max-width: 100%` caps this at the
       container's content box, so the negative margins would shift the carousel
       left without widening it and leave a dead strip down the right. */
    max-width: none;
    margin-inline: calc(var(--container-pad) * -1);
    padding-inline: var(--container-pad);
    scroll-padding-inline-start: var(--container-pad);
    overflow: auto hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    /* A horizontal scroller cannot keep overflow-y visible, so the stagger's
       rise from y:34 would be clipped. Take the room, then hand the layout back
       so nothing below moves. */
    padding-block-end: var(--_reveal-lift);
    margin-block-end: calc(var(--_reveal-lift) * -1);
    /* The arrows and the cut card are the affordance; a scrollbar under a snap
       carousel just adds noise. */
    scrollbar-width: none;
  }
  body .esa-card-grid::-webkit-scrollbar{ display: none; }

  /* 100vw, not a percentage: the visible width that has to hold 1.5 cards is the
     screen, and the container's own gutter is already bled out above. */
  body .esa-card-grid > *{
    flex: 0 0 calc((100vw - var(--container-pad) - var(--_gap)) / var(--_per-view));
    scroll-snap-align: start;
  }
}

/* ---------- Arrows: below the carousel, right aligned ---------------------- */
/* Built by carousel.js, so they cannot appear without their behaviour. */
body .esa-card-nav{ display: none; }

@media (max-width: 767px) {
  body .esa-card-nav{
    display: flex;
    justify-content: flex-end;
    gap: var(--space-xs);
    margin-block-start: var(--space-l);
  }
}

body .esa-card-nav__btn{
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--esa-violet);
  border-radius: var(--radius-pill);
  background: none;
  color: var(--esa-violet);
  cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base),
              border-color var(--transition-base), opacity var(--transition-base);
}
body .esa-card-nav__btn:hover:not([disabled]){
  background: var(--esa-violet);
  color: var(--workshop-white);
}
body .esa-card-nav__btn:focus-visible{
  outline: 2px solid var(--esa-violet);
  outline-offset: 2px;
}
/* Kept in place rather than hidden, so the pair does not jump at either end. */
body .esa-card-nav__btn[disabled]{
  border-color: var(--technical-grey);
  color: var(--technical-grey);
  cursor: default;
  opacity: 0.55;
}
body .esa-card-nav__btn--prev svg{ transform: rotate(180deg); }

/* -----------------------------------------------------------------------------
   BRAND LOGOS BECOME AN INFINITE MARQUEE

   `.esa-brands__list` is a static wrapped flex row of four logos. It now loops
   continuously on desktop and mobile, faded at both edges, paused on hover.

   The wrapper, the clone count, the repeat distance and the duration all come
   from ../_shared/marquee.js — everything here is gated on `.is-ready`, which
   that file adds only once the lazy logos have loaded and the strip has been
   measured. Without the gate the row would flash as an unwrapped max-content
   line while the images were still zero-width.

   The gap is a margin on each item rather than a flex `gap`, so one repeat is a
   whole number of logo-plus-gap units and the seam lands exactly.
   ----------------------------------------------------------------------------- */
body .esa-marquee.is-ready{
  --_fade: clamp(1.5rem, 7vw, 7rem);

  /* Same bleed as the card carousel, and the same reason `max-width` has to be
     released: a global `max-width: 100%` would pin this to the container's
     content box and the negative margins would only shift it. */
  max-width: none;
  margin-inline: calc(var(--container-pad) * -1);
  overflow: clip;
  /* The left and right fade. Pure mask, so it works over any section colour
     without a gradient overlay to keep in sync with the background. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--_fade),
                      #000 calc(100% - var(--_fade)), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 var(--_fade),
              #000 calc(100% - var(--_fade)), transparent 100%);
}

body .esa-marquee.is-ready .esa-brands__list{
  flex-wrap: nowrap;
  justify-content: flex-start;
  gap: 0;
  /* Both, and both matter: `max-width: none` releases the same global
     `max-width: 100%` that pins the wrapper, and without it `max-content` is
     capped at the viewport — the track's offsetWidth then never grows, so the
     clone loop cannot tell when it has enough and runs to its guard (96 clones
     for a strip that needs 8). */
  max-width: none;
  width: max-content;
  will-change: transform;
  animation: esa-marquee var(--_duration, 26s) linear infinite;
}

/* Hover anywhere on the strip stops it, so a logo can actually be read. */
body .esa-marquee.is-ready:hover .esa-brands__list{ animation-play-state: paused; }

/* clamp() lands on 272px at 1440 — the width the static row already gave each
   logo — and 160px on a phone, so the marquee does not restyle the logos, it
   only moves them. */
body .esa-marquee.is-ready .esa-brands__list > li{
  flex: 0 0 clamp(160px, 22vw, 272px);
  margin-inline-end: var(--space-xl);
}

/* One repeat unit, set by marquee.js. The default of 0 means an unmeasured strip
   sits still rather than sliding off. */
@keyframes esa-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(var(--_shift, 0px) * -1)); }
}

/* -----------------------------------------------------------------------------
   EQUIPMENT ARCHIVE — STICKY FILTERS ON MOBILE

   The desktop sidebar is already `position: sticky`, and the equipment block
   turns it off below 991 with `position: static`. It had to: the listing is a
   two-column grid on desktop, where the sidebar's grid area is as tall as the
   results column, but at one column each item gets its own row and a grid item's
   sticky travel is its own area — 93px, the height of the closed bar.

   So the mobile fix is a layout change, not just a position change: the listing
   becomes a block, the filters become a block child of a 6400px parent, and
   sticky has the whole scroll to work with.

   Open, the panel measured 854px against an 800px viewport — taller than the
   screen, which leaves sticky nothing to hold. It is capped to what is actually
   left and scrolls itself.
   ----------------------------------------------------------------------------- */
@media (max-width: 991px) {
  body .esa-listing__grid{ display: block; }
  /* The grid's row-gap goes with the grid. */
  body .esa-filters{ margin-block-end: var(--space-l); }

  body .esa-filters{
    /* Same expression the hero clearance uses: the header is its padding plus
       its tallest child, the 44px menu button below 991. */
    --_sticky-top: calc(48px + 2 * var(--space-xl) + var(--space-2xs));

    position: sticky;
    top: var(--_sticky-top);
    /* Above the cards, below the header (20). */
    z-index: 5;
  }

  /* What is left of the screen once the sticky offset, the toggle, the gap and
     the panel's own padding are taken out. */
  body .esa-filters[data-esa-open] .esa-filters__body{
    max-height: calc(100vh - var(--_sticky-top) - 44px
                     - var(--space-l) * 3 - var(--space-xl));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* ---------- ...and it never worked on desktop either ------------------------
   The equipment block sets `position: sticky; top: calc(var(--space-4xl) +
   var(--space-m))` on the sidebar and a comment saying it "sticks under the fixed
   header while the results scroll past". It does not: with every group open the
   sidebar measures 914px against a 900px viewport, and sticky only engages when
   the element fits the space it is sticking in. Measured at 1440x900 it scrolled
   clean off the top (barTop -144 at scrollY 2400) exactly like a static column.

   Same remedy as the phone: cap it to the room under the header and let it scroll
   itself. The cap only bites on screens where it was already failing.
   --------------------------------------------------------------------------- */
@media (min-width: 992px) {
  body .esa-filters{
    --_sticky-top: calc(var(--space-4xl) + var(--space-m));

    max-height: calc(100vh - var(--_sticky-top) - var(--space-l));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
/* ==ESA-OVERRIDES-END== */
