/* =============================================================
   ABI Hydrovac — design system
   Hello Elementor Child · assets/css/abi-system.css
   Tokens, fluid type scale, shared components and motion.
   Every selector is scoped to an abi- class so nothing here
   reaches WordPress admin UI or unrelated plugin markup.
   ============================================================= */

:root{
  /* ink + greys */
  --abi-ink:#14181c;
  --abi-g800:#2b3238;
  --abi-g600:#566069;
  --abi-g500:#6f7981;
  --abi-g300:#c9d0d6;
  --abi-g100:#e8ecef;
  --abi-fleet:#f4f6f7;
  /* brand */
  --abi-brand:#1449b0;
  --abi-brand5:#2a63d2;
  --abi-brand7:#0e357f;
  --abi-brand9:#0a1f4d;
  --abi-brand05:#f3f7fd;
  /* accent */
  --abi-amber:#f08a1c;
  --abi-amber8:#8a4700;
  --abi-amber1:#fdefdc;
  /* burnt amber, for a caution band: white measures 9.2:1 on it and the
     amber itself 3.7:1, so the number carries at display size */
  --abi-amber9:#6f3a00;
  --abi-scrim:#0a1f4dcc;
  /* logo */
  --logo-ink:#2b3238;
  --logo-brand:#1449b0;
  /* type */
  --abi-disp:Archivo,"Helvetica Neue",Arial,sans-serif;
  --abi-txt:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;
  --abi-mono:"IBM Plex Mono",ui-monospace,Menlo,monospace;
  /* metrics */
  --abi-hdr-h:clamp(82px,6.6vw,104px);
  --abi-rail-h:64px;
  --abi-ease:cubic-bezier(.22,1,.36,1);--abi-ease-glide:cubic-bezier(.4,0,.2,1);
  --abi-gut:clamp(20px,4.2vw,100px);
  --abi-pad:clamp(56px,6.6vw,96px);
  --abi-max:1440px;
  /* The hero's text axis. It is the gutter everywhere except on very wide
     screens, where the hero opens up and its copy moves further in. Anything
     that has to line up with the hero copy reads this rather than --abi-gut,
     so the two cannot drift apart again above 1800px. */
  --abi-axis:var(--abi-gut);
}
@media(min-width:1800px){ :root{ --abi-axis:clamp(100px,7vw,180px); } }
@media(max-width:700px){ :root{ --abi-pad:clamp(40px,8vw,58px); } }

/* -------------------------------------------------------------
   1. Base
   ------------------------------------------------------------- */
body.abi-site{
  background:#fff;
  color:var(--abi-ink);
  font-family:var(--abi-txt);
  -webkit-font-smoothing:antialiased;
}
body.abi-site .elementor-widget :where(h1,h2,h3,h4,h5,h6,p){ margin:0; }

/* Elementor already clips the page; belt and braces against the
   negative margins used by the fleet shelf and the hero plinth. */
body.abi-site{ overflow-x:clip; }

/* -------------------------------------------------------------
   2. Type scale
   Applied to the Elementor widget wrapper; inner nodes inherit.
   ------------------------------------------------------------- */
.abi-d0,.abi-d1,.abi-d2,.abi-d3,.abi-d4,
.abi-h3,.abi-h4,.abi-lede,.abi-bdy,.abi-sm,.abi-cap,.abi-ey,.abi-mn{
  color:inherit;
}
.abi-d0 :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-d1 :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-d2 :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-d3 :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-d4 :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-h3 :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-h4 :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-ey :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span,a),
.abi-mn :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span),
.abi-cap :where(.elementor-heading-title,.elementor-widget-container,h1,h2,h3,h4,p,span),
.abi-lede :where(.elementor-widget-container,p,span),
.abi-bdy :where(.elementor-widget-container,p,span),
.abi-sm :where(.elementor-widget-container,p,span){
  font:inherit; letter-spacing:inherit; text-transform:inherit; color:inherit; margin:0;
}

.abi-d0{font-family:var(--abi-disp);font-weight:700;font-size:clamp(46px,8.2vw,162px);
  line-height:.88;letter-spacing:-.035em;text-transform:uppercase}
.abi-d1{font-family:var(--abi-disp);font-weight:700;font-size:clamp(38px,5.6vw,92px);
  line-height:.92;letter-spacing:-.03em;text-transform:uppercase}
.abi-d2{font-family:var(--abi-disp);font-weight:700;font-size:clamp(30px,3.6vw,56px);
  line-height:1.02;letter-spacing:-.025em}
.abi-d3{font-family:var(--abi-disp);font-weight:700;font-size:clamp(26px,2.8vw,44px);
  line-height:1.1;letter-spacing:-.02em}
.abi-d4{font-family:var(--abi-disp);font-weight:600;font-size:clamp(22px,2.1vw,34px);
  line-height:1.18;letter-spacing:-.01em}
.abi-h3{font-family:var(--abi-disp);font-weight:600;font-size:clamp(18px,1.5vw,22px);line-height:1.3}
.abi-h4{font-family:var(--abi-disp);font-weight:600;font-size:17px;line-height:1.4}
.abi-lede{font-size:clamp(17px,1.35vw,21px);line-height:1.6;color:var(--abi-g600);max-width:36em}
.abi-bdy{font-size:clamp(16px,1.1vw,17px);line-height:1.65;color:var(--abi-g600);max-width:38em}
.abi-sm{font-size:15px;line-height:1.6;color:var(--abi-g600)}
.abi-cap{font-family:var(--abi-mono);font-size:12px;line-height:1.5;letter-spacing:.04em;color:var(--abi-g600)}
.abi-ey{font-size:12px;line-height:16px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--abi-amber8)}
.abi-mn{font-family:var(--abi-mono);font-size:12px;line-height:1.5;letter-spacing:.07em;text-transform:uppercase}

/* index-row headings sit a step above .abi-h3 */
.abi-h3--lg{font-size:clamp(20px,1.9vw,27px)}

@media(max-width:700px){ .abi-d0{font-size:clamp(42px,11vw,64px)} }

/* on dark / on blue */
.abi-on{color:#fff}
.abi-on .abi-lede,.abi-on .abi-bdy,.abi-on .abi-sm,.abi-on .abi-cap{color:var(--abi-g300)}
.abi-on .abi-ey{color:var(--abi-amber)}
.abi-on .abi-d0,.abi-on .abi-d1,.abi-on .abi-d2,.abi-on .abi-d3,.abi-on .abi-d4,
.abi-on .abi-h3,.abi-on .abi-h4,.abi-on .abi-mn{color:#fff}
.abi-blue .abi-lede,.abi-blue .abi-sm,.abi-blue .abi-bdy{color:#dbe4f7}
.abi-blue .abi-ey{color:#fff}

/* surfaces */
.abi-dark{background:var(--abi-ink)}
.abi-graphite{background:var(--abi-g800)}
.abi-fleetbg{background:var(--abi-fleet)}
.abi-blue{background:var(--abi-brand)}
.abi-navy{background:var(--abi-brand9)}

/* rules */
.abi-tick{width:clamp(48px,5vw,120px);height:3px;background:var(--abi-amber);flex:none}
.abi-tick--sm{width:32px}
.abi-tick--md{width:40px}
.abi-tick--lg{width:64px}
.abi-vrule{width:3px;height:130px;background:var(--abi-amber)}

/* -------------------------------------------------------------
   3. Section rhythm
   Padding is set through Elementor's own padding control using the
   custom unit, so it stays editable. These are only the defaults
   for containers that carry no explicit value.
   ------------------------------------------------------------- */
.abi-sec{
  --padding-top:var(--abi-pad);
  --padding-bottom:var(--abi-pad);
  --padding-left:var(--abi-gut);
  --padding-right:var(--abi-gut);
}
.abi-sec--tight{ --padding-top:clamp(40px,4vw,56px); --padding-bottom:clamp(40px,4vw,56px); }
.abi-flush{ --padding-left:0; --padding-right:0; }

/* -------------------------------------------------------------
   4. Bespoke grids
   Elementor containers whose track sizing cannot be expressed by
   the flex/grid controls. Children stay ordinary containers.
   ------------------------------------------------------------- */
.abi-split.e-con{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,420px);
  gap:clamp(24px,4vw,80px);align-items:end}
.abi-two.e-con{display:grid;grid-template-columns:minmax(0,440px) minmax(0,1fr);
  gap:clamp(28px,4vw,60px);align-items:start}
.abi-two-r.e-con{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,520px);
  gap:clamp(28px,4vw,60px);align-items:start}
.abi-half.e-con{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(28px,4vw,60px);align-items:center}
.abi-two--narrow.e-con{grid-template-columns:minmax(0,420px) minmax(0,1fr)}
.abi-two-r--380.e-con{grid-template-columns:minmax(0,1fr) minmax(0,380px)}
.abi-two-r--400.e-con{grid-template-columns:minmax(0,1fr) minmax(0,400px)}
.abi-two-r--wide.e-con{grid-template-columns:minmax(0,1.72fr) minmax(0,1fr)}
.abi-two-r--work.e-con{grid-template-columns:minmax(0,1.9fr) minmax(0,1fr)}
.abi-two--label.e-con{grid-template-columns:minmax(0,240px) minmax(0,1fr);align-items:center}
@media(max-width:899px){
  .abi-split.e-con,.abi-two.e-con,.abi-two-r.e-con,.abi-half.e-con{
    grid-template-columns:1fr!important;align-items:start}
}

/* -------------------------------------------------------------
   5. Numbered steps and index rows
   ------------------------------------------------------------- */
.abi-step.e-con{display:grid;grid-template-columns:56px minmax(0,1fr);gap:18px;
  padding:22px 0;border-top:1px solid var(--abi-g300);align-content:start}
.abi-on .abi-step.e-con{border-color:rgba(255,255,255,.2)}
.abi-step__num{font-family:var(--abi-mono);font-size:13px;font-weight:600;
  letter-spacing:.06em;color:var(--abi-amber8)}
.abi-on .abi-step__num{color:var(--abi-amber)}

.abi-idx.e-con{display:grid;
  grid-template-columns:56px minmax(0,260px) minmax(0,1fr) 24px;
  gap:clamp(12px,2vw,32px);align-items:start;
  padding:22px 12px 24px 0;border-top:1px solid rgba(255,255,255,.2);
  text-decoration:none;color:#fff;
  transition:background-color .2s ease,padding-left .2s ease}
.abi-idx.e-con:hover{background:rgba(255,255,255,.05);padding-left:12px;color:#fff}
.abi-idx__num{font-family:var(--abi-mono);font-size:13px;font-weight:600;
  letter-spacing:.06em;color:var(--abi-amber);line-height:1.9}
.abi-idx .abi-idx__arrow{margin-top:8px;color:var(--abi-g300);justify-self:end}
.abi-idx .abi-idx__arrow svg{width:16px;height:16px;display:block}
/* light variant — careers "ways in" list, which is not a link */
.abi-idx--light.e-con{color:var(--abi-ink);border-top-color:var(--abi-g300);cursor:default}
.abi-idx--light.e-con:hover{background:transparent;padding-left:0;color:var(--abi-ink)}
.abi-idx--light .abi-idx__num{color:var(--abi-amber8)}
@media(max-width:899px){
  .abi-idx.e-con{grid-template-columns:44px minmax(0,1fr);gap:8px 14px}
  .abi-idx .abi-idx__arrow{display:none}
  .abi-idx .abi-idx__body{grid-column:2}
  .abi-step.e-con{padding:18px 0}
  .abi-idx.e-con{padding:18px 0 20px}
}

/* -------------------------------------------------------------
   6. Specification grid
   ------------------------------------------------------------- */
.abi-spec.e-con{border-top:1px solid rgba(255,255,255,.22);padding:14px 0 0;gap:7px}
.abi-spec__k{font-family:var(--abi-mono);font-size:12px;line-height:normal;letter-spacing:.06em;
  text-transform:uppercase;color:var(--abi-g300)}
.abi-spec__v{font-family:var(--abi-mono);font-size:clamp(17px,1.5vw,22px);line-height:1.3;color:#fff}

/* -------------------------------------------------------------
   7. Photographic reveal frame
   .abi-ph            the frame (an Elementor container)
   .abi-ph__i         the image widget inside it
   .abi-ph::after     the curtain, carrying its amber edge
   ------------------------------------------------------------- */
.abi-ph.e-con{
  position:relative;overflow:hidden;width:100%;
  padding:0;display:block;background:#fff;
  view-timeline-name:--abi-frame;contain:paint;
}
.abi-fleetbg .abi-ph.e-con,.abi-capsec .abi-ph.e-con{background:var(--abi-fleet)}
.abi-dark .abi-ph.e-con{background:var(--abi-ink)}
.abi-graphite .abi-ph.e-con{background:var(--abi-g800)}
.abi-blue .abi-ph.e-con{background:var(--abi-brand)}
.abi-ph__i{position:absolute;inset:0;will-change:transform;width:100%;height:100%}
.abi-ph__i .elementor-widget-container,.abi-ph__i figure{height:100%}
.abi-ph__i img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s cubic-bezier(.16,.8,.3,1);
}
.abi-ph.e-con:hover .abi-ph__i img{transform:scale(1.035)}
.abi-ph::after{
  content:"";position:absolute;left:0;right:0;top:-1px;bottom:-1px;
  z-index:2;pointer-events:none;will-change:transform;
  background-color:inherit;
  background-image:linear-gradient(to bottom,var(--abi-amber) 0 3px,transparent 3px);
  transform:translateY(101%);
}
/* aspect-ratio utilities — swap the class to change the crop */
.abi-ar-1x1{aspect-ratio:1/1}
.abi-ar-5x4{aspect-ratio:5/4}
.abi-ar-4x3{aspect-ratio:4/3}
.abi-ar-3x2{aspect-ratio:3/2}
.abi-ar-16x9{aspect-ratio:16/9}
.abi-ar-16x10{aspect-ratio:16/10}
.abi-ar-16x11{aspect-ratio:16/11}
.abi-ar-21x9{aspect-ratio:21/9}
.abi-ar-21x8{aspect-ratio:21/8}
.abi-ar-32x11{aspect-ratio:32/11}
.abi-ar-3x4{aspect-ratio:3/4}
/* One shape for every framed photograph on a phone. 16/10 cut the portrait
   originals in half, so it is 4/3: taller, and closer to what most of these
   photographs actually are. */
@media(max-width:700px){ .abi-ph.e-con[class*="abi-ar-"]{aspect-ratio:4/3} }

.abi-figcap{display:block;margin-top:12px}
/* directly under a reveal frame the container's own 12px gap already supplies
   the step, so the caption does not add a second one */
.abi-ph + .abi-figcap{margin-top:0}

/* -------------------------------------------------------------
   8. Buttons and text links
   Skins for the Elementor Button widget.
   ------------------------------------------------------------- */
.abi-btn .elementor-button{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  min-height:56px;padding:0 clamp(20px,2vw,30px);border-radius:2px;
  font-family:var(--abi-txt);font-size:15px;font-weight:600;letter-spacing:.01em;
  text-decoration:none;border:0;white-space:nowrap;
  transition:background-color .18s ease,transform .18s ease,border-color .18s ease;
}
.abi-btn .elementor-button:hover{transform:translateY(-1px)}
.abi-btn .elementor-button-content-wrapper{display:inline-flex;align-items:center;gap:10px}
.abi-btn .elementor-button-icon svg{width:16px;height:16px;display:block;
  transition:transform .2s var(--abi-ease)}
.abi-btn .elementor-button:hover .elementor-button-icon svg{transform:translateX(4px)}
.abi-btn--sm .elementor-button{min-height:44px;padding:0 20px;font-size:14px}
.abi-btn--primary .elementor-button{background:var(--abi-brand);color:#fff}
.abi-btn--primary .elementor-button:hover{background:var(--abi-brand7);color:#fff}
.abi-btn--bright .elementor-button{background:var(--abi-brand5);color:#fff}
.abi-btn--bright .elementor-button:hover{background:#4a80e4;color:#fff}
.abi-btn--ghost .elementor-button{background:transparent;color:#fff;border:2px solid rgba(255,255,255,.45)}
.abi-btn--ghost .elementor-button:hover{background:rgba(255,255,255,.1);border-color:#fff;color:#fff}
.abi-btn--white .elementor-button{background:#fff;color:var(--abi-brand)}
.abi-btn--white .elementor-button:hover{background:var(--abi-brand05)}
.abi-btn--block .elementor-button{width:100%}

.abi-lnk a,.abi-lnk .elementor-button{
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--abi-txt);font-size:15px;font-weight:600;
  text-decoration:none;background:transparent;padding:0;min-height:0;border:0;
  color:var(--abi-brand)}
.abi-lnk .elementor-button:hover{background:transparent;transform:none}
.abi-lnk--light a,.abi-lnk--light .elementor-button{color:#fff}
.abi-lnk .elementor-button-icon svg{width:16px;height:16px;transition:transform .2s var(--abi-ease)}
.abi-lnk .elementor-button:hover .elementor-button-icon svg{transform:translateX(4px)}

/* telephone treatment */
.abi-tel a,.abi-tel .elementor-heading-title a{
  font-family:var(--abi-mono);color:inherit;text-decoration:none;white-space:nowrap}
.abi-tel--xl{font-family:var(--abi-mono);font-size:clamp(17px,1.6vw,21px);line-height:normal}
.abi-tel--xxl{font-family:var(--abi-mono);font-size:clamp(28px,3.2vw,44px);line-height:1.1}
.abi-tel--lg{font-family:var(--abi-mono);font-size:clamp(24px,2.4vw,30px);line-height:1.1}

/* focus */
body.abi-site :where(a,button,input,select,textarea,summary):focus-visible{
  outline:2px solid var(--abi-brand5);outline-offset:2px}

/* -------------------------------------------------------------
   9. Callout strip
   ------------------------------------------------------------- */
.abi-callout.e-con{display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:24px 32px;align-items:start;border-left:3px solid var(--abi-amber);
  padding-left:28px}
.abi-callout--blue.e-con{border-left-color:var(--abi-brand)}
.abi-callout__num{font-family:var(--abi-mono);font-size:clamp(20px,2vw,28px);color:var(--abi-ink)}
.abi-callout__num a{color:inherit;text-decoration:none}
@media(max-width:899px){ .abi-callout.e-con{grid-template-columns:1fr} }

/* marked list (service page "specify when…") */
.abi-marklist.e-con{gap:0}
.abi-markrow.e-con{display:grid;grid-template-columns:auto minmax(0,1fr);gap:16px;
  padding:14px 0;border-top:1px solid var(--abi-g300);align-items:start}
.abi-markrow__mark{color:var(--abi-amber);font-family:var(--abi-mono);font-size:13px;line-height:1.9}
.abi-markrow__t{font-size:16px;line-height:1.6;color:var(--abi-ink)}

/* numbered disc (service page steps) */
.abi-disc{width:44px;height:44px;border-radius:999px;background:var(--abi-amber);
  display:flex;align-items:center;justify-content:center;font-family:var(--abi-mono);
  font-size:16px;font-weight:600;color:var(--abi-ink);flex:none}

/* stat block */
.abi-stat.e-con{border-top:3px solid var(--abi-amber);padding-top:22px}
.abi-stat__n{font-family:var(--abi-mono);font-size:clamp(38px,3.4vw,48px);
  font-weight:600;letter-spacing:-.03em;color:var(--abi-ink)}

/* leadership portrait placeholder */
.abi-portrait.e-con{aspect-ratio:16/9;background:var(--abi-g800);
  display:flex;align-items:flex-end;padding:20px}
.abi-portrait__i{font-family:var(--abi-mono);font-size:clamp(32px,3vw,48px);
  font-weight:600;letter-spacing:-.03em;color:#fff}

/* certification row */
.abi-certrow.e-con{display:flex;justify-content:space-between;gap:20px;
  padding:14px 0;border-top:1px solid var(--abi-g300);flex-direction:row}
.abi-certrow__s{font-family:var(--abi-mono);font-size:14px;color:var(--abi-g600)}

/* -------------------------------------------------------------
   10. Hero
   ------------------------------------------------------------- */
.abi-hero.e-con{background:var(--abi-ink);color:#fff;position:relative;overflow:hidden;padding:0}
.abi-hero-grid.e-con{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,46%);
  align-items:stretch;min-height:min(calc(100vw * 0.6),900px);padding:0;gap:0}
@media(min-width:900px){
  .abi-hero--home .abi-hero-grid.e-con{
    min-height:calc(100vh - var(--abi-hdr-h) - var(--abi-rail-h));
    min-height:calc(100dvh - var(--abi-hdr-h) - var(--abi-rail-h))}
}
.abi-hero--short .abi-hero-grid.e-con{min-height:min(58vh,560px)}

.abi-hero-type.e-con{
  padding:clamp(14px,2.6vh,56px) clamp(24px,3vw,56px) clamp(14px,2.6vh,56px) var(--abi-gut);
  display:flex;flex-direction:column;justify-content:center;position:relative;z-index:2;gap:0}
.abi-hero-h{margin:clamp(10px,2vh,26px) 0 0 0}
.abi-hero--home .abi-d0{font-size:max(36px,min(calc(8vw - 26px),12.5vh,160px))}
/* below 700px the headline leaves the viewport-height formula behind and takes the
   narrow-screen scale; it repeats the general rule here so it outranks the
   hero-scoped line above, exactly as the prototype's ordering does */
@media(max-width:700px){ .abi-hero--home .abi-d0{font-size:clamp(42px,11vw,64px)} }
/* The block does not travel. Its dark field opens left to right — the
   direction the block itself points — uncovering the copy, the call and the
   amber edge as it passes, so nothing lurches into position. The negative
   bottom inset holds the clip open past the border box, which is what keeps
   the dark field that carries down over the photograph from being cut off. */
.abi-hero-foot.e-con{margin-top:clamp(14px,2.6vh,56px);position:relative;padding:0;
  /* an even travel with a soft landing — a curtain, not a snap */
  animation:abi-plinthin 1250ms cubic-bezier(.4,.32,.5,.96) 880ms both}
@keyframes abi-plinthin{
  from{clip-path:inset(0 100% -460px 0)}
  to{clip-path:inset(0 0 -460px 0)}}
.abi-hero-sep{position:absolute;left:0;right:0;top:-3px;height:3px;overflow:hidden;line-height:0}
.abi-hero-sep span{display:block;width:clamp(88px,12vw,140px);height:3px;background:var(--abi-amber);
  will-change:transform;animation:abi-sepslide 820ms var(--abi-ease) 1240ms both}
@keyframes abi-sepslide{from{transform:translateX(760%)}to{transform:translateX(0)}}
.abi-hero-foot .abi-lede{color:#fff;max-width:30ch;line-height:1.5;
  font-size:max(15px,min(1.5vw,2.2vh,22px))}
body.abi-site .abi-hero .abi-btn .elementor-button{min-height:clamp(46px,6.2vh,56px)}
.abi-hero-cta.e-con{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;
  gap:clamp(16px,2vw,28px);margin-top:clamp(14px,2.4vh,28px);padding:0;
  /* the row spans the plinth so the equipment plate can sit on its right edge */
  --width:100%}
/* its own stacking context, so the amber seam inside it stays under the plinth */
.abi-hero-img.e-con{position:relative;overflow:hidden;padding:0;z-index:1}
.abi-hero-img .abi-hero-photo{position:absolute;inset:0;width:100%;height:100%}
.abi-hero-img .abi-hero-photo img{position:absolute;inset:0;width:100%;height:100%;
  /* centred. The crop used to be pushed down and right to keep the cab door
     out of frame; the originals are shown as they are now. */
  object-fit:cover;object-position:50% 50%;display:block}
/* The plinth reaches out over the photograph, so its right end carries the
   equipment strip: copy and call at the left, the machine's figures at the right,
   and the width the block takes is doing a job rather than sitting empty. Same
   rule-over-label-over-value cell as the fleet band, at hero scale. */
.abi-hero-plate.e-con{--width:auto;margin-left:auto;flex:0 0 auto;align-self:stretch;
  border-left:3px solid var(--abi-amber);
  /* the block's right edge is an overhang, not a page edge — it takes the type
     column's own gutter so the strip is not flush against the photograph */
  padding:0 clamp(24px,3vw,56px) 0 clamp(22px,2.4vw,40px);
  /* Equal tracks, not content-width cells. Each cell used to hug its own
     text, so the three marks landed at 104px then 116px at 1440, and 109
     then 125 at 1920 -- the rhythm was being set by how long a measurement
     happens to be rather than by the block. 1fr floors at max-content, so
     the widest cell sets all three and nothing is ever squeezed. */
  display:grid;grid-template-columns:repeat(3,1fr);align-items:stretch;
  /* the strip is the last thing to arrive, sliding in from the right as the
     amber seam finishes drawing */
  animation:abi-platein 820ms cubic-bezier(.25,.62,.3,1) 2200ms both}
@keyframes abi-platein{from{opacity:0;transform:translateX(28px)}to{opacity:1;transform:none}}
.abi-hero-spec.e-con{--width:auto;flex:0 0 auto;padding:0;gap:4px;white-space:nowrap}
/* the rule sits under the mark, short of the cell's full width */
.abi-hero-spec__i{line-height:0;color:var(--abi-amber);position:relative;
  align-self:stretch;padding-bottom:11px;margin-bottom:3px}
.abi-hero-spec__i::after{content:"";position:absolute;left:0;bottom:0;width:20px;height:1px;
  background:rgba(255,255,255,.34)}
.abi-hero-spec__i .abi-ico{display:block;width:24px;height:24px;stroke-width:1.5}
.abi-hero-spec__k{font-family:var(--abi-mono);font-size:11px;line-height:1.4;
  letter-spacing:.07em;text-transform:uppercase}
.abi-hero-spec__v{font-family:var(--abi-mono);font-size:clamp(15px,1.2vw,18px);
  line-height:1.25}
@media(max-width:1099px){
  /* no overhang below 1100px, so the strip returns under the call */
  .abi-hero-plate.e-con{--width:100%;margin-left:0;padding:0;border-left:0;align-self:auto}
  /* the cells were flex:1 1 0 here to even them out at this width; the grid
     above does that at every width now, and flex on a grid item does nothing */
}
@media(max-width:400px){
  /* three cells still fit across a 320px screen, with the labels trimmed */
  .abi-hero-spec__i .abi-ico{width:20px;height:20px}
  .abi-hero-spec__i::after{width:16px}
  .abi-hero-spec__k{font-size:10px;letter-spacing:.05em}
  .abi-hero-spec__v{font-size:14px}
}
.abi-hero-cap{position:absolute;right:20px;bottom:18px;text-align:right;color:#fff;
  font-size:11px;z-index:3;font-family:var(--abi-mono);letter-spacing:.07em;text-transform:uppercase}
.abi-hero-scrim{position:absolute;left:0;right:0;bottom:0;height:150px;z-index:2;
  background:linear-gradient(to top,var(--abi-scrim),rgba(10,31,77,0));pointer-events:none}

@media(min-width:1800px){
  .abi-hero-grid.e-con{grid-template-columns:minmax(0,1fr) minmax(0,52%)}
  .abi-hero-type.e-con{padding-left:var(--abi-axis)}
  .abi-hero--home .abi-d0{font-size:max(36px,min(calc(6.4vw - 26px),12.5vh,160px))}
}
@media(min-width:1100px){
  .abi-hero--home .abi-hero-foot.e-con{
    background:var(--abi-ink);border-top:1px solid rgba(255,255,255,.2);padding-top:32px;
    padding-bottom:clamp(14px,2.4vh,48px);margin-right:clamp(-220px,-14vw,-40px);
    /* Elementor pins every container to width:var(--width) (100% on full-width
       containers), which fixes the box at the column width and leaves the negative
       margin nothing to expand. Releasing --width lets the stretched item resolve
       its own width and ride out over the photograph, as the prototype does. */
    --width:auto}
  .abi-hero--home .abi-hero-foot.e-con::after{content:"";position:absolute;left:0;right:0;
    top:calc(100% - 1px);height:420px;background:var(--abi-ink);z-index:1}
  /* The amber follows the whole edge of the dark mass. The cutline above draws
     downward from the top of the photograph; this one draws upward from the foot
     of the hero, so the two open the seam from opposite ends. The bar runs past
     the hero's bottom edge and is clipped there, which is what lets the reveal
     rise out of the clip rather than beginning in mid air. */
  .abi-hero--home .abi-hero-foot.e-con::before{content:"";position:absolute;
    /* left:auto, because a container's own ::before is pinned to both edges
       elsewhere and an over-constrained box would jump to the left one */
    left:auto;right:0;top:0;
    width:3px;height:calc(100% + 420px);background:var(--abi-amber);z-index:2;
    transform-origin:bottom center;
    animation:abi-cutgrow 1150ms cubic-bezier(.25,.62,.3,1) 1950ms both}
}
@media(max-width:1099px){
  .abi-hero--home .abi-hero-foot.e-con{border-top:1px solid rgba(255,255,255,.2);
    padding-top:clamp(16px,2.6vh,28px)}
}
@media(max-width:899px){
  .abi-hero-grid.e-con{grid-template-columns:1fr;min-height:0}
  .abi-hero-img.e-con{order:-1;aspect-ratio:16/9}
  .abi-hero-type.e-con{padding:clamp(28px,6vw,48px) var(--abi-gut) clamp(40px,7vw,64px)}
  .abi-hero--home .abi-hero-foot.e-con{border-top:1px solid rgba(255,255,255,.2);
    padding-top:28px;margin-right:0}
  .abi-hero-foot.e-con{border-top:1px solid rgba(255,255,255,.2);padding-top:28px;margin-right:0}
  /* the estimate button takes the full column and pushes the secondary link
     onto its own row, as the prototype does below 900px */
  .abi-hero-cta.e-con{width:100%}
  .abi-hero-cta.e-con > .abi-btn{width:100%}
  .abi-hero-cta.e-con .abi-btn .elementor-button{width:100%}
}
@media(max-width:600px){ .abi-hero-img.e-con{aspect-ratio:16/11} }
@media(max-width:700px){ .abi-hero-img.e-con{aspect-ratio:16/11!important} }
@media(min-width:900px) and (max-height:700px){ .abi-hero-plate.e-con{display:none} }
@media(min-width:900px) and (max-height:660px){
  .abi-hero--home .abi-d0{font-size:max(30px,min(calc(8vw - 26px),10.6vh))}
  .abi-hero-foot .abi-lede{font-size:max(14px,min(1.4vw,2vh,18px));line-height:1.45;max-width:46ch}
  .abi-hero--home .abi-hero-foot.e-con{padding-top:clamp(10px,1.8vh,20px)}
  .abi-hero-foot.e-con{padding-top:clamp(10px,1.8vh,20px)}
  body.abi-site .abi-hero .abi-btn .elementor-button{min-height:44px}
}

/* -------------------------------------------------------------
   11. Numbered service rail under the hero
   ------------------------------------------------------------- */
.abi-rail.e-con{background:var(--abi-fleet);border-bottom:1px solid var(--abi-g300);
  padding:0 var(--abi-gut);min-height:var(--abi-rail-h);
  display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;
  gap:12px clamp(16px,2.6vw,40px);justify-content:space-between;
  font-family:var(--abi-mono);font-size:12px;line-height:1.5;letter-spacing:.07em;
  text-transform:uppercase;
  animation:abi-railwipe 620ms var(--abi-ease) 1480ms both}
@keyframes abi-railwipe{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
.abi-rail__item.e-con{display:flex;flex-direction:row;gap:9px;width:auto;padding:0;
  text-decoration:none;color:var(--abi-g600);
  font-family:var(--abi-mono);font-size:12px;line-height:1.5;letter-spacing:.07em;
  text-transform:uppercase;
  animation:abi-railitem 420ms var(--abi-ease) both}
@keyframes abi-railitem{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.abi-rail__item.e-con:hover{color:var(--abi-ink)}
.abi-rail__item .abi-rail__n{color:var(--abi-amber);font-weight:500}
.abi-rail__item:nth-child(1){animation-delay:1600ms}
.abi-rail__item:nth-child(2){animation-delay:1660ms}
.abi-rail__item:nth-child(3){animation-delay:1720ms}
.abi-rail__item:nth-child(4){animation-delay:1780ms}
.abi-rail__item:nth-child(5){animation-delay:1840ms}
.abi-rail__item:nth-child(6){animation-delay:1900ms}
@media(max-width:899px){ .abi-rail.e-con{padding-block:16px} }

/* -------------------------------------------------------------
   12. Fleet band — photo, then the shelf pulled up over its foot
   ------------------------------------------------------------- */
.abi-capsec.e-con{position:relative;background:var(--abi-fleet);padding:0;display:block}
.abi-capphoto.e-con{width:100%;aspect-ratio:21/9;overflow:hidden;position:relative;
  background:var(--abi-fleet);view-timeline-name:--abi-frame;padding:0;display:block}
/* The band is a slot 2.33 wide over a photograph that is 1.86, so most of
   its height is cut either way; the window is placed on the cabs rather
   than centred, which lands on bumpers and gravel. This is composition,
   not the old rule about keeping doors out of frame. */
.abi-capphoto .abi-ph__i img{object-position:center 30%}
.abi-capgrid.e-con{display:grid;grid-template-columns:minmax(0,62fr) minmax(0,38fr);
  gap:clamp(28px,3.4vw,64px);align-items:start;max-width:var(--abi-max);
  margin:-96px auto 0;padding-inline:var(--abi-gut);position:relative;z-index:2;
  timeline-scope:--abi-slab}
.abi-cappanel.e-con{background:var(--abi-g800);color:#fff;padding:clamp(28px,3vw,44px);
  position:relative;view-timeline-name:--abi-slab}
.abi-capsep{position:absolute;left:0;right:0;top:0;height:3px;overflow:hidden;line-height:0}
.abi-capsep span{display:block;width:clamp(88px,12vw,140px);height:3px;
  background:var(--abi-amber);will-change:transform}
/* the spec grid sits at the wider step below the heading and carries no padding
   of its own; the panel's own gap supplies the rest */
.abi-cappanel > .abi-specs.e-con{padding:0;
  margin-top:calc(clamp(28px,3.4vw,56px) - clamp(18px,2vw,32px))}
.abi-capnote.e-con{padding-top:calc(96px + clamp(10px,1.6vw,26px))}
.abi-capnote .abi-mn{color:var(--abi-g600);padding-bottom:14px;border-bottom:1px solid var(--abi-g300)}
@media(max-width:899px){
  .abi-capphoto.e-con{aspect-ratio:16/9}
  .abi-capgrid.e-con{grid-template-columns:1fr;margin-top:-40px;gap:clamp(24px,4vw,36px)}
  .abi-capnote.e-con{padding-top:0}
}

/* -------------------------------------------------------------
   13. Header
   ------------------------------------------------------------- */
.abi-hdr.e-con{
  position:sticky;top:0;z-index:100;background:#fff;
  border-bottom:1px solid var(--abi-g300);
  display:flex;flex-direction:row;align-items:center;
  gap:clamp(12px,2vw,40px);padding:0 var(--abi-gut);
  min-height:var(--abi-hdr-h);height:var(--abi-hdr-h);width:100%}
.abi-hdr .abi-logo{height:clamp(46px,4.6vw,68px);width:auto;display:block}
.abi-hdr .abi-logo svg,.abi-hdr .abi-logo img{height:100%;width:auto;display:block}
.abi-hdr__brand.e-con{width:auto;padding:0;flex:none}
.abi-hdr__spacer{margin-left:auto}

/* desktop nav — Elementor Pro Nav Menu */
.abi-nav .elementor-nav-menu{display:flex;align-items:center;gap:clamp(14px,1.7vw,30px);
  align-self:stretch;height:var(--abi-hdr-h)}
.abi-nav .elementor-nav-menu li{display:flex;align-items:stretch}
.abi-nav .elementor-nav-menu a.elementor-item{
  position:relative;font-family:var(--abi-txt);font-size:15px;font-weight:500;
  letter-spacing:.005em;color:var(--abi-g600);text-decoration:none;
  display:flex;align-items:center;align-self:stretch;padding:0;
  transition:color .2s ease;background:transparent}
.abi-nav .elementor-nav-menu a.elementor-item::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--abi-amber);
  transform:scaleX(0);transform-origin:left center;transition:transform .24s var(--abi-ease);
  border:0;opacity:1}
.abi-nav .elementor-nav-menu a.elementor-item:hover{color:var(--abi-ink);background:transparent}
/* The amber bar now means exactly one thing: this is the page you are on.
   Hover is carried by the text colour alone, so a passing cursor can no
   longer draw something identical to the marker two items away. */
.abi-nav .elementor-nav-menu a.elementor-item.elementor-item-active::after,
.abi-nav .elementor-nav-menu a.elementor-item:focus-visible::after{transform:scaleX(1)}
.abi-nav .elementor-nav-menu a.elementor-item.elementor-item-active{color:var(--abi-ink)}
@media(max-width:1100px) and (min-width:880px){
  .abi-nav .elementor-nav-menu{gap:clamp(14px,1.6vw,22px)}
  .abi-nav .elementor-nav-menu a.elementor-item{font-size:14px}
}

/* mobile menu sheet */
.abi-nav .elementor-menu-toggle{
  width:44px;height:44px;border:1px solid var(--abi-g300);border-radius:2px;
  background:transparent;color:var(--abi-ink)}
.abi-nav .elementor-menu-toggle:hover{background:var(--abi-fleet)}
.abi-nav .elementor-nav-menu--dropdown{
  border:1px solid var(--abi-g300);box-shadow:0 16px 40px rgba(10,31,77,.18);background:#fff}
.abi-nav .elementor-nav-menu--dropdown a.elementor-item{
  position:relative;display:block;padding:14px 24px;font-size:17px;font-weight:500;
  color:var(--abi-ink);text-decoration:none}
.abi-nav .elementor-nav-menu--dropdown a.elementor-item::before{
  content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;background:var(--abi-amber);
  transform:scaleY(0);transform-origin:top center;transition:transform .22s var(--abi-ease)}
.abi-nav .elementor-nav-menu--dropdown a.elementor-item::after{display:none}
.abi-nav .elementor-nav-menu--dropdown a.elementor-item:hover,
.abi-nav .elementor-nav-menu--dropdown a.elementor-item:focus-visible{background:var(--abi-fleet);color:var(--abi-ink)}
.abi-nav .elementor-nav-menu--dropdown a.elementor-item:hover::before,
.abi-nav .elementor-nav-menu--dropdown a.elementor-item:focus-visible::before,
.abi-nav .elementor-nav-menu--dropdown a.elementor-item.elementor-item-active::before{transform:scaleY(1)}

/* the call, on a phone, travels into the sheet
   Below 880px the header cannot carry the logo, the call and the menu button
   without crowding, so the header button is withdrawn and the menu's own
   Contact item is dressed as that button: last in the list, under a rule. The
   same item is hidden in the desktop menu, where the header button is still
   doing the work. Label and destination are edited in Appearance > Menus like
   any other item; the class abi-nav-cta is what marks it. */
.abi-nav .elementor-nav-menu--main li.abi-nav-cta{display:none}
@media(max-width:879px){
  .abi-nav .elementor-nav-menu--dropdown li.abi-nav-cta{
    margin-top:8px;padding:14px 24px 4px;border-top:1px solid var(--abi-g300)}
  body.abi-site .abi-nav .elementor-nav-menu--dropdown li.abi-nav-cta a.elementor-item{
    display:flex;align-items:center;justify-content:center;
    min-height:48px;padding:0 20px;border-radius:2px;
    background:var(--abi-brand);color:#fff;
    font-family:var(--abi-txt);font-size:15px;font-weight:600;letter-spacing:.01em}
  body.abi-site .abi-nav .elementor-nav-menu--dropdown li.abi-nav-cta a.elementor-item:hover,
  body.abi-site .abi-nav .elementor-nav-menu--dropdown li.abi-nav-cta a.elementor-item:focus-visible{
    background:var(--abi-brand7);color:#fff}
  body.abi-site .abi-nav .elementor-nav-menu--dropdown li.abi-nav-cta a.elementor-item::before{display:none}
}

/* The scroll measure and the active-page marker used to be the same object:
   3px of amber, one pixel apart, at the same edge of the header. Once the
   measure grew past the active item the two merged into one line and the
   marker disappeared into it.

   They say different things, so they are drawn differently now. The measure
   moved to the top edge in brand blue, where it cannot cross the marker and
   is not spending the one accent colour on ambient chrome; the header keeps
   its own g300 border-bottom as the cut line it always had. Amber below the
   nav means you are here. Blue above means this much of the page is behind
   you. Blue also measures better: 8:1 on white against the amber 2.4:1. */
.abi-hdr__rule{position:absolute;left:0;top:0;width:100%;height:2px;
  background:var(--abi-brand);transform:scaleX(0);transform-origin:left center;
  will-change:transform;pointer-events:none;z-index:2}

/* -------------------------------------------------------------
   14. Footer
   ------------------------------------------------------------- */
.abi-ftr.e-con{background:var(--abi-brand9);color:#fff;position:relative;
  padding:clamp(44px,4.4vw,68px) var(--abi-gut) clamp(20px,2vw,30px)}
.abi-ftr-grid.e-con{display:grid;
  grid-template-columns:minmax(0,1.35fr) minmax(0,1fr) minmax(0,.8fr) minmax(0,1.05fr);
  gap:clamp(28px,3vw,64px);align-items:start}
.abi-ftr .abi-logo{height:clamp(51px,4.5vw,69px)}
.abi-ftr .abi-logo svg path,.abi-ftr .abi-logo svg circle{fill:#fff}
.abi-ftr-blurb{font-size:15px;line-height:1.62;color:var(--abi-g300);max-width:32ch}
/* This was the one block in the footer built differently from the other three:
   an amber bar down its side where Services, Company and Contact each use a mono
   label over a hairline. It takes the same construction now, which removes the
   second of the two stacked bars and makes the footer read as four of one thing
   rather than three of one and one of another. */
.abi-ftr-mbe.e-con{border-left:0;padding:0;max-width:30ch;gap:0}
.abi-ftr-mbe .abi-mn{color:var(--abi-amber);width:100%;
  padding:0 0 12px;margin-bottom:16px;
  border-bottom:1px solid rgba(255,255,255,.18)}
.abi-ftr-mbe__b{font-family:var(--abi-txt);font-weight:500;font-size:15px;line-height:1.5;color:#fff}
.abi-ftr-h.e-con{display:flex;flex-direction:row;align-items:baseline;gap:10px;
  font-family:var(--abi-mono);font-size:12px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:#fff;padding:0 0 12px;margin-bottom:16px;
  border-bottom:1px solid rgba(255,255,255,.18);width:100%}
.abi-ftr-h__n{color:var(--abi-amber);font-style:normal}
.abi-ftr-links.e-con{gap:0;padding:0}
.abi-ftr-links a{position:relative;display:block;color:#b9c4d6;text-decoration:none;
  font-size:15px;line-height:30px;transition:color .2s ease}
.abi-ftr-links a::before{content:"";position:absolute;left:0;top:calc(50% - 1px);
  width:12px;height:3px;background:var(--abi-amber);
  transform:scaleX(0);transform-origin:left center;transition:transform .26s var(--abi-ease)}
.abi-ftr-links a span{display:inline-block;transition:transform .26s var(--abi-ease)}
.abi-ftr-links a:hover,.abi-ftr-links a:focus-visible{color:#fff}
.abi-ftr-links a:hover::before,.abi-ftr-links a:focus-visible::before{transform:scaleX(1)}
.abi-ftr-links a:hover span,.abi-ftr-links a:focus-visible span{transform:translateX(20px)}
.abi-ftr-tel a{display:block;position:relative;text-decoration:none;padding-bottom:14px;color:#fff}
.abi-ftr-tel .abi-mn{display:block;color:var(--abi-amber);margin-bottom:6px}
.abi-ftr-tel__n{font-family:var(--abi-mono);font-weight:500;letter-spacing:-.01em;color:#fff;
  font-size:clamp(20px,1.9vw,27px);line-height:1.1;white-space:nowrap;display:block}
.abi-ftr-tel a::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;
  background:rgba(255,255,255,.2)}
.abi-ftr-tel a::before{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;
  background:var(--abi-amber);z-index:1;
  transform:scaleX(0);transform-origin:left center;transition:transform .3s var(--abi-ease)}
.abi-ftr-tel a:hover::before,.abi-ftr-tel a:focus-visible::before{transform:scaleX(1)}
.abi-ftr-bar.e-con{margin-top:clamp(34px,3.6vw,52px);padding:20px 0 0;
  border-top:1px solid rgba(255,255,255,.16);
  display:flex;flex-direction:row;flex-wrap:wrap;gap:20px;
  font-family:var(--abi-mono);font-size:12px;letter-spacing:.06em;color:#8fa2c4;
  max-width:var(--abi-max);margin-inline:auto;width:100%}
.abi-ftr-bar__r{margin-left:auto}
@media(max-width:1180px){
  .abi-ftr-grid.e-con{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:clamp(34px,4vw,50px)}
  .abi-ftr-blurb{max-width:38ch}.abi-ftr-mbe.e-con{max-width:36ch}
}
@media(max-width:620px){
  .abi-ftr-grid.e-con{grid-template-columns:repeat(2,minmax(0,1fr));gap:30px 24px}
  .abi-ftr-brand.e-con,.abi-ftr-reach.e-con{grid-column:1 / -1}
  .abi-ftr-blurb,.abi-ftr-mbe.e-con{max-width:44ch}
  .abi-ftr-links a{line-height:28px}
  .abi-ftr-bar__r{margin-left:0}
}

/* the reveal — the page rides up off the pinned footer, but only
   where the footer actually fits the viewport and motion is welcome */
body.abi-site .elementor-location-header,
body.abi-site main#content,
body.abi-site .site-main{position:relative;z-index:1;background:#fff}
body.abi-site main#content::after,
body.abi-site .site-main::after{
  content:"";position:absolute;left:0;bottom:0;width:100%;height:3px;
  background:var(--abi-amber);z-index:2}
@media(min-width:900px) and (min-height:780px){
  @media(prefers-reduced-motion:no-preference){
    body.abi-site .elementor-location-footer{position:sticky;bottom:0;z-index:0}
  }
}

/* -------------------------------------------------------------
   15. Forms — Elementor Pro Form widget
   ------------------------------------------------------------- */
.abi-form .elementor-form{display:flex;flex-direction:column;gap:24px;max-width:760px}
.abi-form .elementor-form-fields-wrapper{row-gap:24px;column-gap:24px;margin:0}
.abi-form .elementor-field-group{padding:0;flex-direction:column;align-items:stretch;gap:8px}
.abi-form .elementor-field-label{
  font-family:var(--abi-txt);font-size:14px;font-weight:600;color:var(--abi-ink);padding:0}
.abi-form .elementor-field-group .elementor-field,
.abi-form .elementor-field-textual{
  width:100%;min-height:52px;padding:12px 14px;border:1px solid var(--abi-g500);
  border-radius:2px;background:#fff;font-family:var(--abi-txt);font-size:16px;
  color:var(--abi-ink);box-shadow:none}
.abi-form textarea.elementor-field-textual{min-height:120px;resize:vertical}
.abi-form .elementor-field-type-upload .elementor-field{border:1px dashed var(--abi-g500);
  padding:14px;background:var(--abi-fleet)}
.abi-form .elementor-button{
  min-height:56px;padding:0 clamp(20px,2vw,30px);border-radius:2px;
  font-family:var(--abi-txt);font-size:15px;font-weight:600;
  background:var(--abi-brand);color:#fff;border:0;
  transition:background-color .18s ease,transform .18s ease}
.abi-form .elementor-button:hover{background:var(--abi-brand7);transform:translateY(-1px)}
.abi-form .elementor-message{font-family:var(--abi-txt);font-size:15px;line-height:1.6;
  padding:14px 16px;border-radius:2px;margin-top:4px}
.abi-form .elementor-message-success{background:var(--abi-brand05);color:var(--abi-brand7);
  border-left:3px solid var(--abi-brand)}
.abi-form .elementor-message-danger{background:var(--abi-amber1);color:var(--abi-amber8);
  border-left:3px solid var(--abi-amber)}
.abi-form .elementor-field-group.elementor-error .elementor-field{border-color:#b3261e}
.abi-form .elementor-error .elementor-error-message{color:#b3261e;font-size:13px;margin-top:6px}
.abi-form-note{font-family:var(--abi-mono);font-size:12px;line-height:1.5;
  letter-spacing:.04em;color:var(--abi-g600)}
@media(max-width:640px){
  .abi-form .elementor-field-group{width:100%!important}
  .abi-form .elementor-button{width:100%}
}

/* -------------------------------------------------------------
   16. Motion — load choreography
   ------------------------------------------------------------- */
.abi-rise{animation:abi-rise 620ms var(--abi-ease) both}
.abi-rise--d1{animation-delay:180ms}
@keyframes abi-rise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}

.abi-hline{display:block;overflow:hidden;padding-top:.18em;margin-top:-.18em}
.abi-hw{display:inline-block;vertical-align:top;
  animation:abi-wordrise 860ms cubic-bezier(.16,.8,.3,1) both}
.abi-hw--1{animation-delay:200ms}.abi-hw--2{animation-delay:330ms}
.abi-hw--3{animation-delay:460ms}.abi-hw--4{animation-delay:590ms}
@keyframes abi-wordrise{0%{opacity:0;transform:translateY(112%)}34%{opacity:1}100%{opacity:1;transform:none}}

.abi-heroimg{animation:abi-imgin 950ms cubic-bezier(.33,1,.5,1) both}
.abi-heroimg img{animation:abi-imgsettle 1800ms var(--abi-ease) both}
@keyframes abi-imgin{from{clip-path:inset(0 0 0 100%)}to{clip-path:inset(0 0 0 0)}}
@keyframes abi-imgsettle{from{transform:scale(1.06)}to{transform:scale(1)}}

@keyframes abi-cutgrow{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@media(max-width:899px){
  @keyframes abi-cutgrow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
}

/* -------------------------------------------------------------
   17. Motion — scroll-driven
   Feature-detected. Where animation-timeline is unsupported every
   element below keeps its ordinary, fully readable static state.
   ------------------------------------------------------------- */
@supports (animation-timeline: view()){
@media(prefers-reduced-motion:no-preference){

  /* photography, site-wide */
  .abi-ph--reveal::after{
    animation:abi-curtain linear both;animation-timeline:--abi-frame;
    animation-range:entry 5% cover 40%}
  @keyframes abi-curtain{from{transform:translateY(0)}to{transform:translateY(101%)}}
  .abi-ph--reveal .abi-ph__i{
    animation:abi-push linear both;animation-timeline:--abi-frame;
    animation-range:entry 5% cover 52%}
  @keyframes abi-push{from{transform:translateY(-6%) scale(1.09)}to{transform:translateY(0) scale(1)}}

  /* the full-bleed bands drift instead of pushing in */
  .abi-ph--drift .abi-ph__i{
    animation:abi-drift linear both;animation-timeline:--abi-frame;
    animation-range:cover 0% cover 100%}
  @keyframes abi-drift{from{transform:scale(1.1) translateY(-3%)}to{transform:scale(1.1) translateY(3%)}}

  /* text gestures — home page only */
  .abi-home .abi-sr,.abi-home .abi-sr1,.abi-home .abi-sr2,.abi-home .abi-sr3,
  .abi-home .abi-sr4,.abi-home .abi-sr5,.abi-home .abi-sr6,
  .abi-home .abi-idx,.abi-home .abi-step,
  .abi-home .abi-cappanel,.abi-home .abi-capnote{
    animation:abi-sr-rise linear both;animation-timeline:view();
    animation-range:entry 10% cover 32%}
  @keyframes abi-sr-rise{from{opacity:0;transform:translateY(56px)}to{opacity:1;transform:none}}
  @keyframes abi-sr-rise-sm{from{opacity:0;transform:translateY(22px)}to{opacity:1;transform:none}}

  .abi-home .abi-sr1{animation-range:entry 19% cover 41%}
  .abi-home .abi-sr2{animation-range:entry 28% cover 50%}
  .abi-home .abi-sr3{animation-range:entry 37% cover 59%}
  .abi-home .abi-sr4{animation-range:entry 46% cover 68%}
  .abi-home .abi-sr5{animation-range:entry 55% cover 77%}
  .abi-home .abi-sr6{animation-range:entry 64% cover 86%}

  .abi-home .abi-idx:nth-child(2),.abi-home .abi-step:nth-child(2){animation-range:entry 19% cover 41%}
  .abi-home .abi-idx:nth-child(3),.abi-home .abi-step:nth-child(3){animation-range:entry 28% cover 50%}
  .abi-home .abi-idx:nth-child(4){animation-range:entry 37% cover 59%}
  .abi-home .abi-idx:nth-child(5){animation-range:entry 46% cover 68%}
  .abi-home .abi-idx:nth-child(6){animation-range:entry 55% cover 77%}
  .abi-home .abi-idx:nth-child(7){animation-range:entry 64% cover 86%}

  /* the note beside the fleet panel rides the panel's own timeline
     (scoped on .abi-capgrid so the sibling can read it) */
  .abi-home .abi-capnote{animation-name:abi-sr-rise-sm;animation-timeline:--abi-slab;
    animation-range:entry 16% cover 30%}

  /* the spec grid settles early and almost together */
  .abi-home .abi-spec{animation:abi-sr-rise-sm linear both;
    animation-timeline:--abi-slab;animation-range:entry 12% cover 24%}
  .abi-home .abi-spec:nth-child(2){animation-range:entry 15% cover 27%}
  .abi-home .abi-spec:nth-child(3){animation-range:entry 18% cover 30%}
  .abi-home .abi-spec:nth-child(4){animation-range:entry 21% cover 33%}
  .abi-home .abi-spec:nth-child(5){animation-range:entry 24% cover 36%}
  .abi-home .abi-spec:nth-child(6){animation-range:entry 27% cover 39%}

  /* headings wipe open */
  .abi-home .abi-srw{animation:abi-sr-wipe linear both;animation-timeline:view();
    animation-range:entry 12% cover 34%}
  @keyframes abi-sr-wipe{
    from{clip-path:inset(0 0 104% 0);transform:translateY(24px)}
    to{clip-path:inset(-24% -6% -24% -6%);transform:none}}

  /* drawn rules */
  .abi-home .abi-srl,.abi-home .abi-tick{transform-origin:left center;
    animation:abi-sr-line linear both;animation-timeline:view();
    animation-range:entry 16% cover 30%}
  @keyframes abi-sr-line{from{transform:scaleX(0)}to{transform:scaleX(1)}}
  .abi-home .abi-srv,.abi-home .abi-vrule{transform-origin:top center;
    animation:abi-sr-vline linear both;animation-timeline:view();
    animation-range:entry 12% cover 40%}
  @keyframes abi-sr-vline{from{transform:scaleY(0)}to{transform:scaleY(1)}}

  /* the fleet slab drives in from the left, its amber rule runs in after */
  .abi-home .abi-cappanel{animation:abi-sr-slab linear both;animation-timeline:view();
    animation-range:entry 4% cover 38%}
  @keyframes abi-sr-slab{0%{opacity:0;transform:translateX(-46%)}22%{opacity:1}
    100%{opacity:1;transform:none}}
  .abi-home .abi-capsep span{animation:abi-sr-sep linear both;animation-timeline:--abi-slab;
    animation-range:entry 24% cover 52%}
  @keyframes abi-sr-sep{from{transform:translateX(720%)}to{transform:translateX(0)}}

  /* the header rule measures the page; the bar lifts once you move */
  .abi-hdr__rule{animation:abi-hdr-measure linear both;
    animation-timeline:scroll(root block);animation-range:0% 100%}
  @keyframes abi-hdr-measure{from{transform:scaleX(0)}to{transform:scaleX(1)}}
  .abi-hdr.e-con{animation:abi-hdr-lift linear both;
    animation-timeline:scroll(root block);animation-range:0 160px}
  @keyframes abi-hdr-lift{
    from{box-shadow:0 0 0 0 rgba(20,24,28,0)}
    to{box-shadow:0 4px 12px rgba(20,24,28,.10)}}

  /* the rule closing each service heading draws itself in as the row
     arrives — the one gesture on this page, so it stays quiet */
  .abi-svch .elementor-heading-title::after{
    transform-origin:left center;
    animation:abi-sr-line linear both;animation-timeline:view();
    animation-range:entry 26% cover 46%}

  /* the six practices arrive one after another as the list comes up */
  .abi-rulecell{animation:abi-sr-rise-sm linear both;animation-timeline:view();
    animation-range:entry 10% cover 28%}
  .abi-rulecell:nth-child(2){animation-range:entry 15% cover 33%}
  .abi-rulecell:nth-child(3){animation-range:entry 20% cover 38%}
  .abi-rulecell:nth-child(4){animation-range:entry 25% cover 43%}
  .abi-rulecell:nth-child(5){animation-range:entry 30% cover 48%}
  .abi-rulecell:nth-child(6){animation-range:entry 35% cover 53%}

  /* the hero is choreographed on load, not on scroll */
  .abi-hero *{animation-timeline:auto}
}}

/* -------------------------------------------------------------
   18. Reduced motion
   ------------------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  body.abi-site *,
  body.abi-site *::before,
  body.abi-site *::after{animation:none!important;transition:none!important}
  .abi-ph::after{transform:translateY(101%)!important}
  .abi-hdr__rule{transform:scaleX(0)!important}
}

/* Never let a failed or unsupported effect hide content. */
.abi-rise,.abi-hw,.abi-hero-foot.e-con,.abi-hero-plate.e-con,
.abi-rail.e-con,.abi-rail__item.e-con{
  animation-fill-mode:both}
@supports not (animation-timeline: view()){
  .abi-ph::after{transform:translateY(101%)}
  /* A measure that cannot measure shows nothing. It used to sit at scaleX(1)
     because it was also the header cut line and had to span the width; the
     border-bottom carries that now, so an unmeasurable bar just goes. */
  .abi-hdr__rule{transform:scaleX(0)}
}

/* -------------------------------------------------------------
   19. Elementor markup bindings
   Written against the markup Elementor actually renders on this
   site (optimised markup is ON, so there is no
   .elementor-widget-container wrapper).
   ------------------------------------------------------------- */

/* logo */
.abi-logo img,.abi-logo svg{height:100%;width:auto;display:block;max-width:none}
.abi-hdr .abi-logo{display:flex;align-items:center}
.abi-hdr__brand.e-con{width:auto;flex:none;align-self:center}
.abi-ftr-home.e-con{width:auto;flex:none}

/* header layout */
.abi-hdr.e-con{position:sticky;top:0}
.abi-nav{margin-left:auto}
.abi-hdr .abi-nav{align-self:stretch;display:flex;align-items:center}
.abi-hdr .abi-nav .elementor-nav-menu--main{align-self:stretch;display:flex;align-items:stretch}
/* the measure rides the top edge now, not the cut line at the bottom */
.abi-hdr__rule-w{position:absolute;left:0;right:0;top:0;bottom:auto;height:2px;width:100%;
  pointer-events:none;padding:0;margin:0}
.abi-hdr .elementor-menu-toggle{margin:0}
.abi-hdr .elementor-nav-menu--dropdown{top:100%;right:0;left:auto;
  min-width:min(74vw,268px);padding:10px 0}
@media(max-width:879px){
  /* the toggle takes the right edge now that the button has gone into the sheet */
  /* the nav widget is a column flex box, so what centres the toggle on the
     header height is justify-content, not align-items */
  .abi-hdr .abi-nav{order:3;margin-left:auto;flex:none;justify-content:center}
  .abi-hdr > .abi-btn{display:none}
  .abi-hdr .abi-nav .elementor-nav-menu--main{display:none}
}

/* footer grid + link lists */
.abi-ftr-grid.e-con{max-width:var(--abi-max);margin-inline:auto;width:100%}
.abi-ftr-links .elementor-nav-menu{display:block}
.abi-ftr-links .elementor-nav-menu li{position:relative;display:block}
.abi-ftr-links .elementor-nav-menu li::before{content:"";position:absolute;left:0;
  top:calc(50% - 1px);width:12px;height:3px;background:var(--abi-amber);
  transform:scaleX(0);transform-origin:left center;
  transition:transform .26s var(--abi-ease);z-index:1}
/* The current page's footer link is shifted 20px like a hovered one, but the
   amber dash that explains the shift only answered :hover, so on its own page the
   link just sat indented with nothing in the gap. The marker is on the li, and
   the active class is on the a inside it, hence :has(). */
.abi-ftr-links .elementor-nav-menu li:hover::before,
.abi-ftr-links .elementor-nav-menu li:focus-within::before,
.abi-ftr-links .elementor-nav-menu li:has(> a.elementor-item-active)::before{transform:scaleX(1)}
.abi-ftr-links a.elementor-item{position:relative;display:block;color:#b9c4d6;
  text-decoration:none;font-family:var(--abi-txt);font-size:15px;line-height:30px;
  padding:0;background:transparent;
  transition:color .2s ease,transform .26s var(--abi-ease)}
.abi-ftr-links a.elementor-item:hover,
.abi-ftr-links a.elementor-item:focus-visible,
.abi-ftr-links a.elementor-item.elementor-item-active{color:#fff;background:transparent;
  transform:translateX(20px)}
.abi-ftr-links a.elementor-item::after,
.abi-ftr-links a.elementor-item::before{display:none}
.abi-ftr-h .elementor-heading-title{font:inherit;letter-spacing:inherit;
  text-transform:inherit;color:inherit}
.abi-ftr-h__n .elementor-heading-title{color:var(--abi-amber)}
.abi-ftr-tel__a{display:block;position:relative;text-decoration:none;
  padding-bottom:14px;color:#fff}
.abi-ftr-bar .elementor-heading-title{font:inherit;letter-spacing:inherit;color:inherit}
.abi-ftr-bar.e-con > .elementor-element{width:auto;flex:none}

/* -------------------------------------------------------------
   20. Neutral base for Elementor's own widget defaults
   Written with :where() so the specificity is zero: the abi- type
   classes above win, and so does anything an editor sets on a
   single widget through Elementor's own controls.
   ------------------------------------------------------------- */
:where(body.abi-site) :where(
  .elementor-widget-heading .elementor-heading-title,
  .elementor-widget-text-editor,
  .elementor-widget-text-editor p,
  .elementor-widget-html
){color:inherit;font:inherit;letter-spacing:inherit;text-transform:inherit}

/* Elementor Pro's nav-menu ships its own colour and metrics; these
   need one more class to win, so they are scoped to body.abi-site. */
body.abi-site .abi-nav .elementor-nav-menu a.elementor-item{
  font-family:var(--abi-txt);font-size:15px;font-weight:500;letter-spacing:.005em;
  color:var(--abi-g600);background:transparent;padding:0;
  fill:currentColor;line-height:1}
body.abi-site .abi-nav .elementor-nav-menu a.elementor-item:hover,
body.abi-site .abi-nav .elementor-nav-menu a.elementor-item.elementor-item-active,
body.abi-site .abi-nav .elementor-nav-menu a.elementor-item.highlighted,
body.abi-site .abi-nav .elementor-nav-menu a.elementor-item:focus{
  color:var(--abi-ink);background:transparent}
body.abi-site .abi-nav .elementor-nav-menu--dropdown a.elementor-item{
  font-size:17px;line-height:1.4;padding:14px 24px;color:var(--abi-ink)}
body.abi-site .abi-nav .elementor-menu-toggle{
  width:44px;height:44px;border:1px solid var(--abi-g300);border-radius:2px;
  background:transparent;color:var(--abi-ink);padding:0}
body.abi-site .abi-nav .elementor-menu-toggle svg{width:22px;height:22px;fill:var(--abi-ink)}

body.abi-site .abi-ftr-links .elementor-nav-menu a.elementor-item{
  font-family:var(--abi-txt);font-size:15px;font-weight:400;line-height:30px;
  color:#b9c4d6;background:transparent;padding:0;letter-spacing:0}
body.abi-site .abi-ftr-links .elementor-nav-menu a.elementor-item:hover,
body.abi-site .abi-ftr-links .elementor-nav-menu a.elementor-item:focus,
body.abi-site .abi-ftr-links .elementor-nav-menu a.elementor-item.elementor-item-active{
  color:#fff;background:transparent;transform:translateX(20px)}

/* the MBE line and the legal bar are plain headings — give them
   their own type rather than Hello's h-tag defaults */
.abi-ftr-mbe__b{font-family:var(--abi-txt);font-weight:500;font-size:15px;
  line-height:1.5;color:#fff}
.abi-ftr-bar{font-family:var(--abi-mono);font-size:12px;letter-spacing:.06em;color:#8fa2c4}

/* -------------------------------------------------------------
   21. Specificity alignment
   Elementor's per-widget stylesheets set colour and typography on
   .elementor-heading-title and on the text-editor wrapper at two
   classes. These rules sit one step above that, and one step below
   Elementor's own per-element output, so the design system holds
   by default and a per-widget override in the editor still wins.
   ------------------------------------------------------------- */
body.abi-site .elementor-widget-heading .elementor-heading-title,
body.abi-site .elementor-widget-text-editor p,
body.abi-site .elementor-widget-text-editor ul,
body.abi-site .elementor-widget-text-editor li{
  color:inherit;font:inherit;letter-spacing:inherit;text-transform:inherit;margin:0}

/* Tone. The kit colours every heading and text widget from its own globals,
   at a specificity the plain class rules in section 2 cannot reach, so the
   design system's tones are restated here. :where() keeps the class names
   weightless, which leaves these just above the kit and just below the
   per-element CSS Elementor writes for a colour chosen in the editor. */
body.abi-site :where(.abi-d0,.abi-d1,.abi-d2,.abi-d3,.abi-d4,
  .abi-h3,.abi-h4){color:var(--abi-ink)}
body.abi-site :where(.abi-lede,.abi-bdy,.abi-sm,.abi-cap){color:var(--abi-g600)}
body.abi-site :where(.abi-ey){color:var(--abi-amber8)}
body.abi-site :where(.abi-mn){color:inherit}
body.abi-site .abi-on :where(.abi-d0,.abi-d1,.abi-d2,.abi-d3,.abi-d4,
  .abi-h3,.abi-h4,.abi-mn){color:#fff}
body.abi-site .abi-on :where(.abi-lede,.abi-bdy,.abi-sm,.abi-cap){color:var(--abi-g300)}
body.abi-site .abi-on :where(.abi-ey){color:var(--abi-amber)}
body.abi-site .abi-blue :where(.abi-lede,.abi-bdy,.abi-sm){color:#dbe4f7}
body.abi-site .abi-blue :where(.abi-ey){color:#fff}
/* the graphite fleet panel is a dark band like the others; the prototype
   leaves its label on the dark amber used for light backgrounds, which is
   close to illegible there, so it takes the band amber */
body.abi-site .abi-cappanel :where(.abi-ey){color:var(--abi-amber)}
body.abi-site .abi-cappanel :where(.abi-d4,.abi-h3,.abi-h4){color:#fff}

body.abi-site .abi-d0 .elementor-heading-title,
body.abi-site .abi-d0 p,body.abi-site .abi-d0 span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-d1 .elementor-heading-title,
body.abi-site .abi-d1 p,body.abi-site .abi-d1 span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-d2 .elementor-heading-title,
body.abi-site .abi-d2 p,body.abi-site .abi-d2 span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-d3 .elementor-heading-title,
body.abi-site .abi-d3 p,body.abi-site .abi-d3 span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-d4 .elementor-heading-title,
body.abi-site .abi-d4 p,body.abi-site .abi-d4 span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-h3 .elementor-heading-title,
body.abi-site .abi-h3 p,body.abi-site .abi-h3 span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-h4 .elementor-heading-title,
body.abi-site .abi-h4 p,body.abi-site .abi-h4 span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-ey .elementor-heading-title,
body.abi-site .abi-ey p,body.abi-site .abi-ey span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-mn .elementor-heading-title,
body.abi-site .abi-mn p,body.abi-site .abi-mn span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-cap .elementor-heading-title,
body.abi-site .abi-cap p,body.abi-site .abi-cap span{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-lede p,body.abi-site .abi-lede span,
body.abi-site .abi-lede .elementor-heading-title{font:inherit;letter-spacing:inherit;color:inherit}
body.abi-site .abi-bdy p,body.abi-site .abi-bdy span,
body.abi-site .abi-bdy .elementor-heading-title{font:inherit;letter-spacing:inherit;color:inherit}
body.abi-site .abi-sm p,body.abi-site .abi-sm span,
body.abi-site .abi-sm .elementor-heading-title{font:inherit;letter-spacing:inherit;color:inherit}

/* the same for the named component classes that carry their own type */
body.abi-site .abi-ftr-mbe__b .elementor-heading-title,
body.abi-site .abi-ftr-blurb p,
body.abi-site .abi-ftr-bar .elementor-heading-title,
body.abi-site .abi-ftr-h .elementor-heading-title,
body.abi-site .abi-step__num .elementor-heading-title,
body.abi-site .abi-idx__num .elementor-heading-title,
body.abi-site .abi-spec__k .elementor-heading-title,
body.abi-site .abi-spec__v .elementor-heading-title,
body.abi-site .abi-stat__n .elementor-heading-title,
body.abi-site .abi-portrait__i .elementor-heading-title,
body.abi-site .abi-callout__num .elementor-heading-title,
body.abi-site .abi-markrow__t .elementor-heading-title,
body.abi-site .abi-markrow__mark .elementor-heading-title,
body.abi-site .abi-certrow__s .elementor-heading-title,
body.abi-site .abi-disc .elementor-heading-title,
body.abi-site .abi-tel--xl .elementor-heading-title,
body.abi-site .abi-tel--lg .elementor-heading-title,
body.abi-site .abi-tel--xxl .elementor-heading-title,
body.abi-site .abi-figcap .elementor-heading-title,
body.abi-site .abi-form-note .elementor-heading-title{
  font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
body.abi-site .abi-ftr-h__n .elementor-heading-title{color:var(--abi-amber)}

/* Elementor's kit paints .elementor-widget-text-editor with the global text
   typography. That rule carries the same specificity as the type-scale classes
   in section 2 but is printed later, so a text widget would quietly ignore its
   ABI class. Restating the scale here settles it, and stays below the per-element
   CSS Elementor writes for a value set in the editor, which still wins. */
body.abi-site .abi-lede{font-size:clamp(17px,1.35vw,21px);line-height:1.6}
body.abi-site .abi-bdy{font-size:clamp(16px,1.1vw,17px);line-height:1.65}
body.abi-site .abi-sm{font-size:15px;line-height:1.6}
body.abi-site .abi-cap{font-family:var(--abi-mono);font-size:12px;line-height:1.5;
  letter-spacing:.04em}
body.abi-site .abi-ey{font-size:12px;line-height:16px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase}
body.abi-site .abi-mn{font-family:var(--abi-mono);font-size:12px;line-height:1.5;
  letter-spacing:.07em;text-transform:uppercase}
body.abi-site .abi-ftr-blurb{font-size:15px;line-height:1.62;color:var(--abi-g300)}
/* the hero lede keeps its own viewport-aware size above that */
body.abi-site .abi-hero-foot .abi-lede{line-height:1.5;color:#fff;
  font-size:max(15px,min(1.5vw,2.2vh,22px))}
@media(min-width:900px) and (max-height:660px){
  body.abi-site .abi-hero-foot .abi-lede{font-size:max(14px,min(1.4vw,2vh,18px));
    line-height:1.45}
}

/* nav items must be able to stretch to the full header height so the
   amber rule lands on the header's bottom edge, as in the prototype */
body.abi-site .abi-nav .elementor-nav-menu--main .elementor-nav-menu{align-items:stretch}
body.abi-site .abi-nav .elementor-nav-menu--main .elementor-nav-menu > li{align-items:stretch}
body.abi-site .abi-nav .elementor-nav-menu--main a.elementor-item{align-items:center}

/* -------------------------------------------------------------
   22. Authored line breaks and the masked headline
   Headlines are ordinary editable text in Elementor. Deliberate
   line breaks are real newlines in the field, held by pre-line, so
   the line structure survives with or without the split script.
   ------------------------------------------------------------- */
body.abi-site .abi-brk .elementor-heading-title,
body.abi-site .abi-brk p,
body.abi-site .abi-splitwords .elementor-heading-title{white-space:pre-line}
body.abi-site .abi-splitwords--done{white-space:normal}
.abi-splitwords .abi-hline{display:block;overflow:hidden;padding-top:.18em;margin-top:-.18em}
/* Between first paint and the splitter running, the headline would paint as
   plain text and then restart as the reveal began. abi-guard.js marks the
   document while scripting is available, which lets this hold that one heading
   until it is split. The second mark is the release: the guard adds it when the
   splitter has not run, and with scripting off neither mark is ever added, so
   the heading is never hidden by this rule. */
html.abi-js:not(.abi-split-fallback) body.abi-site .abi-splitwords .elementor-heading-title,
html.abi-js:not(.abi-split-fallback) body.abi-site .abi-splitwords h1,
html.abi-js:not(.abi-split-fallback) body.abi-site .abi-splitwords h2{visibility:hidden}
html.abi-js:not(.abi-split-fallback) body.abi-site .abi-splitwords
  .abi-splitwords--done{visibility:visible}

/* -------------------------------------------------------------
   23. Hero decoration as pseudo-elements
   The scrim and the vertical cut line are decoration, not content,
   so they ride on the photo container rather than adding widgets
   to the Navigator.
   ------------------------------------------------------------- */
/* top:auto, for the same reason as the plinth's bar: a container's own pseudo
   is pinned to both edges elsewhere, and an over-constrained box drops the
   offset it was given — this scrim was sitting at the top of the photograph */
.abi-hero-img.e-con::before{content:"";position:absolute;left:0;right:0;top:auto;bottom:0;
  height:150px;z-index:2;pointer-events:none;
  background:linear-gradient(to top,var(--abi-scrim),rgba(10,31,77,0))}
/* Below 900px the hero stacks, the photograph sits above the copy, and a short
   amber bar under it carries the eye down into the text — the prototype's own
   mobile treatment. Above that width the dark block's right edge carries the
   amber (section 10) and a second vertical here only competed with it, so the
   mark exists at the stacked widths only. */
@media(max-width:899px){
  .abi-hero-img.e-con::after{content:"";position:absolute;left:0;bottom:0;top:auto;
    width:88px;height:3px;background:var(--abi-amber);transform-origin:left center;z-index:3;
    animation:abi-cutgrow 900ms cubic-bezier(.25,.62,.3,1) 800ms both}
  .abi-hero--home .abi-hero-img.e-con::after{animation-duration:1050ms;animation-delay:1800ms}
}
.abi-hero-photo{position:absolute;inset:0;width:100%;height:100%;z-index:1}
.abi-hero-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}

/* -------------------------------------------------------------
   24. Column utilities and remaining component details
   ------------------------------------------------------------- */
.abi-cols.e-con{display:grid;gap:clamp(28px,3.4vw,56px);align-content:start}
.abi-c2.e-con{grid-template-columns:repeat(2,minmax(0,1fr))}
.abi-c3.e-con{grid-template-columns:repeat(3,minmax(0,1fr))}
.abi-c4.e-con{grid-template-columns:repeat(4,minmax(0,1fr))}
.abi-c5.e-con{grid-template-columns:repeat(5,minmax(0,1fr))}
@media(max-width:1099px){.abi-c5.e-con,.abi-c4.e-con{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:899px){.abi-c3.e-con{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.abi-cols.e-con{grid-template-columns:1fr!important}}

.abi-specs.e-con{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px 32px;
  align-content:start}
@media(max-width:899px){.abi-specs.e-con{grid-template-columns:repeat(2,minmax(0,1fr))}}
.abi-specs--5.e-con{grid-template-columns:repeat(5,minmax(0,1fr))}
@media(max-width:1099px){.abi-specs--5.e-con{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* the index row's arrow, drawn from the shared glyph rather than a widget */
.abi-idx.e-con::after{content:"";width:16px;height:16px;margin-top:8px;justify-self:end;
  align-self:start;background-color:var(--abi-g300);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 12h15M13 6l6 6-6 6' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 12h15M13 6l6 6-6 6' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'/%3E%3C/svg%3E") center/contain no-repeat}
.abi-idx--light.e-con::after{background-color:transparent}
@media(max-width:899px){.abi-idx.e-con::after{display:none}}

/* hero supporting line keeps the prototype's grey, not plain white */
body.abi-site .abi-hero-spec__k{color:var(--abi-g300)}
body.abi-site .abi-hero-spec__v{color:#fff}
body.abi-site .abi-hero-cap{color:#fff}

/* text-editor lists inside body copy */
body.abi-site .abi-bdy ul,body.abi-site .abi-sm ul{list-style:none;padding:0;margin:0}

/* dark surfaces: index rows and steps read on the section colour */
.abi-dark .abi-idx.e-con,.abi-on .abi-idx.e-con{border-top-color:rgba(255,255,255,.2)}

/* spacer helper */
.abi-spacer.e-con{height:clamp(48px,6vw,96px);padding:0;min-height:0}

/* -------------------------------------------------------------
   25. Closing CTA and decorative rule wrappers
   ------------------------------------------------------------- */
/* The 130px amber bar that stood beside this block appeared on every page, and
   on About and Contact it was the third vertical amber bar inside a screen and a
   half -- the MBE note, this, and the certification note in the footer directly
   under it. One marker used three times in a row stops being a marker and starts
   being wallpaper. It carries no mark at all now: every page hands over to this
   section from a different ground -- blue on home and About, white on Safety and
   Our work, blue on Services -- so the change of colour is the division, and a
   rule drawn on top of it was saying the same thing twice. The content sits on
   the page axis now that there is no bar for it to clear. */
.abi-cta-inner.e-con{position:relative;padding-left:0}
/* the button row sits closer than the container's own rhythm, so it gives back
   the gap the container adds and keeps the prototype's step */
.abi-cta-inner.e-con > .abi-hero-cta.e-con{
  margin-top:calc(clamp(14px,2.4vh,28px) - clamp(18px,2vw,32px))}
.abi-hero-sep,.abi-capsep{padding:0;margin:0}
body.abi-site .abi-tel--xl .elementor-heading-title a,
body.abi-site .abi-tel--xl a{font-family:var(--abi-mono);font-size:clamp(17px,1.6vw,21px);
  color:#fff;text-decoration:none;white-space:nowrap}
body.abi-site .abi-tel--xxl .elementor-heading-title a{font-family:var(--abi-mono);
  font-size:clamp(28px,3.2vw,44px);line-height:1.1;color:#fff;text-decoration:none}
body.abi-site .abi-tel--lg .elementor-heading-title a{font-family:var(--abi-mono);
  font-size:clamp(24px,2.4vw,30px);line-height:1.1;color:var(--abi-ink);text-decoration:none}
body.abi-site .abi-callout__num .elementor-heading-title a{font-family:var(--abi-mono);
  font-size:clamp(20px,2vw,28px);color:var(--abi-ink);text-decoration:none}

/* text links built from the Button widget keep no button chrome */
.abi-lnk .elementor-button{background:transparent!important;min-height:0;padding:0;
  border:0;justify-content:flex-start}
.abi-lnk .elementor-button:hover{background:transparent!important;transform:none}

/* -------------------------------------------------------------
   26. Page shell
   Hello Elementor's full-width template prints the Theme Builder
   header, the page and the footer as three siblings of <body> with
   no <main> wrapper, so the stack is built on those three.

   The header wrapper carries the sticky, not the container inside
   it: a sticky element can only travel inside its own containing
   block, and the container's block is exactly its own height.
   ------------------------------------------------------------- */
body.abi-site > header.elementor-location-header{position:sticky;top:0;z-index:100}
body.abi-site .abi-hdr.e-con{position:relative;top:auto;z-index:1}

body.abi-site > .elementor:not([class*="elementor-location-"]){
  position:relative;z-index:1;background:#fff}
body.abi-site > .elementor:not([class*="elementor-location-"])::after{
  content:"";position:absolute;left:0;bottom:0;width:100%;height:3px;
  background:var(--abi-amber);z-index:2}
body.abi-site > footer.elementor-location-footer{position:relative;z-index:0}

/* the reveal: the page rides up off the pinned footer, but only where
   the footer actually fits the viewport and motion is welcome */
@media(min-width:900px) and (min-height:780px){
  @media(prefers-reduced-motion:no-preference){
    body.abi-site > footer.elementor-location-footer{position:sticky;bottom:0}
  }
}

/* the earlier main#content rules no longer apply — neutralise them */
body.abi-site main#content::after,body.abi-site .site-main::after{content:none}

/* -------------------------------------------------------------
   27. Small component wrappers
   ------------------------------------------------------------- */
.abi-tick-w{line-height:0;padding:0;margin:0}
.abi-tick-w .abi-tick{display:block}
/* a supporting line under a card's heading sits tight against it, whether the
   card is led by an amber rule or a numbered disc, so it gives the container's
   step back and takes the prototype's 12px */
.abi-tick-w ~ .abi-sm,
.abi-disc ~ .abi-sm{margin-top:calc(12px - clamp(18px,2vw,32px))}
/* on a service hero the headline follows the breadcrumb at the hero's own
   smaller, height-aware step rather than the container's */
.abi-crumb-w ~ .abi-d1{margin-top:calc(clamp(10px,2vh,26px) - clamp(18px,2vw,32px))}
body.abi-site .abi-svc-note{color:var(--abi-g300)}
.abi-cappanel.e-con > .abi-capsep{position:absolute;left:0;right:0;top:0;height:3px;
  overflow:hidden;line-height:0}
.abi-hero-foot.e-con > .abi-hero-sep{position:absolute;left:0;right:0;top:-3px;height:3px;
  overflow:hidden;line-height:0}

/* -------------------------------------------------------------
   28. Button skins over the Elementor kit defaults
   The kit paints every .elementor-button with the global Accent
   colour at two classes, so the ABI skins are scoped to
   body.abi-site to sit one step above it — still below anything
   an editor sets on an individual button.
   ------------------------------------------------------------- */
body.abi-site .abi-btn .elementor-button{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  min-height:56px;padding:0 clamp(20px,2vw,30px);border-radius:2px;
  font-family:var(--abi-txt);font-size:15px;font-weight:600;letter-spacing:.01em;
  text-decoration:none;border:0;white-space:nowrap;
  transition:background-color .18s ease,transform .18s ease,border-color .18s ease}
body.abi-site .abi-btn--sm .elementor-button{min-height:44px;padding:0 20px;font-size:14px}
body.abi-site .abi-btn--primary .elementor-button{background-color:var(--abi-brand);color:#fff}
body.abi-site .abi-btn--primary .elementor-button:hover,
body.abi-site .abi-btn--primary .elementor-button:focus{background-color:var(--abi-brand7);color:#fff}
body.abi-site .abi-btn--bright .elementor-button{background-color:var(--abi-brand5);color:#fff}
body.abi-site .abi-btn--bright .elementor-button:hover,
body.abi-site .abi-btn--bright .elementor-button:focus{background-color:#4a80e4;color:#fff}
body.abi-site .abi-btn--ghost .elementor-button{background-color:transparent;color:#fff;
  border:2px solid rgba(255,255,255,.45)}
body.abi-site .abi-btn--ghost .elementor-button:hover{background-color:rgba(255,255,255,.1);
  border-color:#fff;color:#fff}
body.abi-site .abi-btn--white .elementor-button{background-color:#fff;color:var(--abi-brand)}
body.abi-site .abi-btn--white .elementor-button:hover{background-color:var(--abi-brand05)}
body.abi-site .abi-btn .elementor-button:hover{transform:translateY(-1px)}

/* the text link is a bare inline-flex row in the prototype; zeroing the widget's
   own strut keeps Elementor's wrapper from adding a line of leading around it */
body.abi-site .abi-lnk{line-height:0}
body.abi-site .abi-lnk .elementor-button{background-color:transparent;color:var(--abi-brand);
  min-height:0;padding:0;border:0;justify-content:flex-start;font-size:15px;font-weight:600;
  line-height:normal}
body.abi-site .abi-lnk .elementor-button:hover{background-color:transparent;transform:none;
  color:var(--abi-brand7)}
body.abi-site .abi-lnk--light .elementor-button,
body.abi-site .abi-lnk--light .elementor-button:hover{color:#fff}
body.abi-site .abi-btn .elementor-button-icon svg,
body.abi-site .abi-lnk .elementor-button-icon svg{width:16px;height:16px;fill:none;
  stroke:currentColor}

/* the form submit button follows the primary skin */
body.abi-site .abi-form .elementor-button{background-color:var(--abi-brand);color:#fff}
body.abi-site .abi-form .elementor-button:hover{background-color:var(--abi-brand7)}

/* -------------------------------------------------------------
   29. Service-detail pattern
   ------------------------------------------------------------- */
.abi-crumb-w{padding:0;margin:0}
.abi-crumb a{color:var(--abi-g300);text-decoration:none}
.abi-crumb a:hover,.abi-crumb a:focus-visible{color:#fff}
.abi-crumb__sep{color:var(--abi-amber);margin:0 .45em}
.abi-crumb__here{color:#fff}
body.abi-site .abi-lede--44{max-width:44ch}

/* the marked condition list, built from the Icon List widget */
body.abi-site .abi-marklist .elementor-icon-list-items{display:block;padding:0;margin:0;list-style:none}
body.abi-site .abi-marklist .elementor-icon-list-item{display:grid;
  grid-template-columns:auto minmax(0,1fr);gap:16px;padding:14px 0;margin:0;
  border-top:1px solid var(--abi-g300);align-items:start}
body.abi-site .abi-marklist .elementor-icon-list-item::before{content:"\25A0";
  color:var(--abi-amber);font-family:var(--abi-mono);font-size:13px;line-height:1.9}
body.abi-site .abi-marklist .elementor-icon-list-icon{display:none}
body.abi-site .abi-marklist .elementor-icon-list-text{font-family:var(--abi-txt);
  font-size:16px;line-height:1.6;color:var(--abi-ink);padding:0}
body.abi-site .abi-on .abi-marklist .elementor-icon-list-item{border-top-color:rgba(255,255,255,.2)}
body.abi-site .abi-on .abi-marklist .elementor-icon-list-text{color:#fff}

/* numbered disc */
body.abi-site .abi-disc{width:44px;height:44px;border-radius:999px;background:var(--abi-amber);
  display:flex;align-items:center;justify-content:center;font-family:var(--abi-mono);
  font-size:16px;font-weight:600;color:var(--abi-ink);flex:none;line-height:1}

/* full-bleed service band keeps a shallower crop on small screens */
@media(max-width:700px){.abi-ar-32x11{aspect-ratio:16/9}}

/* -------------------------------------------------------------
   30. Services index
   ------------------------------------------------------------- */
.abi-numrule-w{padding:0;margin:0;line-height:0}
.abi-numrule{display:flex;align-items:center;gap:20px}
.abi-numrule__n{font-family:var(--abi-mono);font-size:12px;line-height:1.5;letter-spacing:.07em;
  text-transform:uppercase;color:var(--abi-amber8)}
.abi-on .abi-numrule__n{color:var(--abi-amber)}
body.abi-site .abi-lede--grey{color:var(--abi-g300)}
.abi-hero--short .abi-hero-type.e-con{justify-content:center}

/* -------------------------------------------------------------
   31. About page hero and tinted callout bands
   ------------------------------------------------------------- */
.abi-abouthero.e-con{position:relative;background:var(--abi-g800);padding:0;display:block}
.abi-abouthero .abi-ph.e-con{min-height:420px;background:var(--abi-g800)}
/* Header plus hero fills the viewport. The frame's ratio has to be released
   for that — aspect-ratio and an explicit height fight otherwise — and the
   image inside is absolutely positioned and object-fit:cover, so it simply
   fills whatever the frame becomes. dvh second so it wins where it is
   supported and vh covers the browsers where it is not. The header is sticky
   but still in flow, so its own height is all there is to subtract.
   Held to the desktop layout: below 900px the copy sits under a 16:9 frame
   and a full-height photograph would push the whole page past the fold. */
@media(min-width:900px){
  body.abi-site .abi-abouthero .abi-ph.e-con{
    aspect-ratio:auto;
    min-height:calc(100vh - var(--abi-hdr-h));
    min-height:calc(100dvh - var(--abi-hdr-h))}
}
.abi-abouthero::after{content:"";position:absolute;inset:0;background:var(--abi-scrim);
  z-index:2;pointer-events:none}
.abi-abouthero__copy.e-con{position:absolute;left:0;right:0;bottom:0;z-index:3;
  padding:0 var(--abi-gut) clamp(32px,5vw,80px)}
.abi-abouthero__inner.e-con{max-width:var(--abi-max);margin-inline:auto;width:100%}
body.abi-site .abi-lede--soft{color:#e6ebf2}
body.abi-site .abi-mn--brand{color:var(--abi-brand)}
.abi-ambertint{background:var(--abi-amber1)}
.abi-bluetint{background:var(--abi-brand05)}

/* -------------------------------------------------------------
   32. Contact and careers
   ------------------------------------------------------------- */
.abi-alignend.e-con{text-align:right}
body.abi-site .abi-mn--grey{color:var(--abi-g600)}
body.abi-site .abi-on .abi-mn--grey{color:var(--abi-g300)}

/* the plain dash list beside the estimate form */
body.abi-site .abi-dashlist .elementor-icon-list-items{display:block;padding:0;margin:0;list-style:none}
body.abi-site .abi-dashlist .elementor-icon-list-item{display:block;margin:0;padding:0}
body.abi-site .abi-dashlist .elementor-icon-list-icon{display:none}
body.abi-site .abi-dashlist .elementor-icon-list-text{font-family:var(--abi-txt);font-size:16px;
  line-height:1.75;color:var(--abi-ink);padding:0}
body.abi-site .abi-dashlist .elementor-icon-list-text::before{content:"\2014\00a0"}

/* the two forms sit in a column, so the field grid is the form's own */
body.abi-site .abi-form .elementor-form-fields-wrapper{display:flex;flex-wrap:wrap;
  row-gap:24px;column-gap:24px;margin:0;width:100%}
body.abi-site .abi-form .elementor-field-group{padding:0;margin:0}
body.abi-site .abi-form .elementor-field-group.elementor-field-type-honeypot{display:none!important}
body.abi-site .abi-form .elementor-field-group-submit{width:100%}
body.abi-site .abi-form .elementor-field-type-upload .elementor-field{border:1px dashed var(--abi-g500);
  background:var(--abi-fleet);padding:14px;min-height:0}
body.abi-site .abi-form .elementor-field-description{font-family:var(--abi-mono);font-size:12px;
  letter-spacing:.04em;color:var(--abi-g600);margin-top:6px}
body.abi-site .abi-form .elementor-field-required .elementor-field-label::after,
body.abi-site .abi-form .elementor-mark-required .elementor-field-label::after{color:var(--abi-amber8)}

/* -------------------------------------------------------------
   33. Form layout over Elementor Pro's own form stylesheet
   Elementor Pro paints the field group at two classes and loads
   after this file, so these rules carry body.abi-site.
   ------------------------------------------------------------- */
body.abi-site .abi-form .elementor-form{display:block}
body.abi-site .abi-form .elementor-form-fields-wrapper{display:flex;flex-wrap:wrap;
  gap:24px;margin:0;width:100%;max-width:760px}
body.abi-site .abi-form .elementor-field-group{display:flex;flex-direction:column;
  align-items:stretch;gap:8px;padding:0;margin:0;flex:0 0 100%;max-width:100%}
body.abi-site .abi-form .elementor-field-group.elementor-col-50{
  flex:0 0 calc(50% - 12px);max-width:calc(50% - 12px)}
body.abi-site .abi-form .elementor-field-group > .elementor-field-label{
  width:auto;max-width:none;padding:0;margin:0;
  font-family:var(--abi-txt);font-size:14px;font-weight:600;line-height:1.4;
  color:var(--abi-ink);text-align:left}
body.abi-site .abi-form .elementor-field-group .elementor-field-textual,
body.abi-site .abi-form .elementor-field-group select.elementor-field-textual{
  width:100%;min-height:52px;padding:12px 14px;border:1px solid var(--abi-g500);
  border-radius:2px;background-color:#fff;font-family:var(--abi-txt);font-size:16px;
  line-height:1.4;color:var(--abi-ink);box-shadow:none}
body.abi-site .abi-form textarea.elementor-field-textual{min-height:120px;resize:vertical}
body.abi-site .abi-form .elementor-select-wrapper{width:100%;position:relative}
body.abi-site .abi-form .elementor-select-wrapper select{appearance:none;
  -webkit-appearance:none;padding-right:40px}
body.abi-site .abi-form .elementor-select-wrapper::after,
body.abi-site .abi-form .elementor-select-wrapper .e-font-icon-svg{
  color:var(--abi-g600);right:14px}
body.abi-site .abi-form .elementor-field-group-submit{flex:0 0 100%;max-width:100%}
body.abi-site .abi-form .elementor-field-type-honeypot{display:none!important}
body.abi-site .abi-form .elementor-field-type-upload .elementor-field{
  border:1px dashed var(--abi-g500);background-color:var(--abi-fleet);padding:14px;
  min-height:0;border-radius:2px}
body.abi-site .abi-form .elementor-message{font-family:var(--abi-txt);font-size:15px;
  line-height:1.6;padding:14px 16px;border-radius:2px;margin-top:20px;width:100%;max-width:760px}
body.abi-site .abi-form .elementor-message.elementor-message-success{
  background:var(--abi-brand05);color:var(--abi-brand7);border-left:3px solid var(--abi-brand)}
body.abi-site .abi-form .elementor-message.elementor-message-danger{
  background:var(--abi-amber1);color:var(--abi-amber8);border-left:3px solid var(--abi-amber)}
body.abi-site .abi-form .elementor-field-group.elementor-error .elementor-field{border-color:#b3261e}
body.abi-site .abi-form .elementor-error .elementor-error-message{color:#b3261e;
  font-family:var(--abi-txt);font-size:13px;margin-top:2px}
body.abi-site .abi-form .elementor-mark-required .elementor-field-label::after{
  color:var(--abi-amber8);margin-left:.25em}
@media(max-width:640px){
  body.abi-site .abi-form .elementor-field-group.elementor-col-50{flex:0 0 100%;max-width:100%}
  body.abi-site .abi-form .elementor-button{width:100%}
}

/* a column-direction flex group must not wrap, or Elementor's own
   wrap rule pushes the input into a second column beside its label */
body.abi-site .abi-form .elementor-field-group{flex-wrap:nowrap;align-content:flex-start}
body.abi-site .abi-form .elementor-field-group > .elementor-field-label{flex:0 0 auto;width:100%}
body.abi-site .abi-form .elementor-field-group > .elementor-select-wrapper,
body.abi-site .abi-form .elementor-field-group > .elementor-field{flex:1 1 auto;width:100%}

/* the submit sits at its own width, and the select keeps one border */
body.abi-site .abi-form .elementor-field-group-submit{flex:0 0 auto;width:auto;max-width:none}
body.abi-site .abi-form .elementor-field-group-submit .elementor-button{width:auto}
body.abi-site .abi-form .elementor-select-wrapper{border:0;padding:0;background:transparent}
body.abi-site .abi-form .elementor-select-wrapper select.elementor-field-textual{margin:0}
@media(max-width:640px){
  body.abi-site .abi-form .elementor-field-group-submit{flex:0 0 100%;width:100%}
  body.abi-site .abi-form .elementor-field-group-submit .elementor-button{width:100%}
}

/* -------------------------------------------------------------
   34. Narrow screens
   The prototype's header is about 5px wider than a 320px viewport
   once the logo, the Contact button and the menu toggle are laid
   out. These rules tighten it below 380px so nothing overflows,
   and pin the mobile menu sheet so it cannot widen the header.
   ------------------------------------------------------------- */
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown{position:absolute;z-index:40}
body.abi-site .abi-hdr .abi-nav{position:static}
body.abi-site .abi-hdr.e-con{position:relative}

@media(max-width:379px){
  body.abi-site .abi-hdr.e-con{
    --padding-left:16px;--padding-right:16px;
    gap:8px;column-gap:8px}
  body.abi-site .abi-hdr .abi-logo{height:40px}
  body.abi-site .abi-hdr .abi-btn--sm .elementor-button{padding:0 12px;font-size:13px;min-height:40px}
  body.abi-site .abi-nav .elementor-menu-toggle{width:40px;height:40px}
}

/* the sheet is sized to itself, anchored to the header's right edge */
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown{
  right:var(--abi-gut);left:auto;top:100%;
  width:min(74vw,268px);max-width:calc(100vw - 32px);min-width:0}
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown .elementor-nav-menu{
  display:block;width:100%}
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown li{display:block;width:100%}

/* the desktop nav list is stretched to the header height; the sheet's
   list must not inherit that, or the open menu collapses to zero */
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown .elementor-nav-menu{
  display:block;width:100%;height:auto;align-items:initial;gap:0;align-self:auto}
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown li{
  display:block;align-items:initial;height:auto}
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown a.elementor-item{
  display:block;align-self:auto;height:auto;line-height:1.4}

/* open state for the sheet, stated here rather than relying on
   Elementor's own max-height variable, which this build leaves at 0 */
body.abi-site .abi-hdr .abi-nav .elementor-menu-toggle.elementor-active + .elementor-nav-menu--dropdown{
  max-height:calc(100dvh - var(--abi-hdr-h) - 24px);
  overflow-y:auto;overflow-x:hidden}

/* This Elementor Pro build leaves the sheet at max-height:0 and
   scaleY(0) after the toggle opens, so the open and closed states are
   stated here against the aria-hidden attribute the toggle does set. */
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown[aria-hidden="true"]{
  max-height:0;transform:scaleY(0);overflow:hidden}
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown[aria-hidden="false"]{
  max-height:calc(100dvh - var(--abi-hdr-h) - 24px);
  transform:none;overflow-y:auto;overflow-x:hidden}

/* Elementor Pro declares the sheet's closed state with !important in this
   build, so the open state has to answer in kind. Keyed on aria-hidden,
   which the toggle maintains, rather than on a plugin class name. */
body.abi-site .abi-hdr .abi-nav .elementor-nav-menu--dropdown[aria-hidden="false"]{
  max-height:calc(100dvh - var(--abi-hdr-h) - 24px)!important;
  transform:none!important;
  overflow-y:auto!important;overflow-x:hidden!important}

/* -------------------------------------------------------------
   35. Measure
   Elementor pins max-width:100% on every widget inside a container
   (".elementor.elementor .e-con > .elementor-widget", 0-4-0), which no
   component class here can outrank without also outranking the editor.
   So the measure lives on the text node instead, where nothing competes
   and a width set in Elementor still wins on the widget above it.
   ------------------------------------------------------------- */
.abi-lede :where(p){max-width:36em}
.abi-bdy :where(p){max-width:38em}
.abi-hero-foot .abi-lede :where(p){max-width:30ch}
@media(min-width:900px) and (max-height:660px){
  .abi-hero-foot .abi-lede :where(p){max-width:46ch}
}
/* The two numbered lists had no measure at all, so each row sized to its
   own text and text-wrap:balance did the rest: a 128-character step
   balanced into two ~460px lines while a 117-character one still fitted on
   a single 813px line. One list, two measures 1.7x apart, and the long row
   well past a readable line. A shared measure is what balance was missing. */
.abi-step .abi-sm :where(p),
.abi-idx .abi-idx__body :where(p){max-width:37em}
/* The About figures had the same problem in miniature. Three supporting
   lines wrapped to two lines and the first, at 40 characters and 298px,
   just cleared the 331px cell and sat on one -- so one figure in four read
   short against its neighbours. The threshold was about ten pixels wide,
   which is no way to hold a layout together: a different font fallback
   would have flipped a different cell. 18em puts every figure on two lines
   with room either side of the flip point, and leaves the three that were
   already wrapping exactly as they were. */
.abi-stat .abi-sm :where(p){max-width:18em}
.abi-ftr-blurb :where(p){max-width:32ch}
@media(max-width:1180px){ .abi-ftr-blurb :where(p){max-width:38ch} }
@media(max-width:620px){ .abi-ftr-blurb :where(p){max-width:44ch} }

/* -------------------------------------------------------------
   36. Very narrow screens (below the prototype's tested range)
   The prototype stops at the phone widths it was drawn for, and a long
   single word in a display headline runs past the gutter at 320px.
   Trimming the display sizes there keeps every page free of sideways
   scroll; break-word is a floor so no future headline can reintroduce it.
   ------------------------------------------------------------- */
@media(max-width:360px){
  body.abi-site .abi-d1{font-size:clamp(30px,8.6vw,38px)}
  body.abi-site .abi-d2{font-size:clamp(26px,7.6vw,56px)}
}
body.abi-site .abi-d0,body.abi-site .abi-d1,body.abi-site .abi-d2,
body.abi-site .abi-d3,body.abi-site .abi-d4{overflow-wrap:break-word}

/* -------------------------------------------------------------
   37. Elementor global colours inside the dark bands
   The kit paints headings and body copy from its global colours, and in the
   editor Elementor writes those per element at a specificity no component
   class can reach — so a dark band previewed in the kit's primary blue while
   the published page, which has no such per-element rule, was correctly
   white. Re-pointing the globals inside a dark band lets the kit's own rules
   resolve to the right ink in both places. A colour set deliberately on a
   widget is a literal value and still wins over this.
   ------------------------------------------------------------- */
body.abi-site :is(.abi-on,.abi-dark,.abi-blue){
  --e-global-color-primary:#fff;
  --e-global-color-secondary:#fff;
  --e-global-color-text:#fff;
}

/* -------------------------------------------------------------
   38. In-page anchors
   The six service rows are reached by name now that the detail pages
   are gone: from the numbered rail and the service index on the home
   page, and from the Services column in the footer.

   scroll-behavior is forced back to auto. Elementor writes
   html{scroll-behavior:smooth} into its own generated stylesheet, and
   on this site those animations never run to completion: something in
   the scroll-driven stack cancels them the moment they start. The
   result is that no fragment link works at all, and scrollIntoView is
   ignored, on every page. With auto restored both land instantly.
   If smooth scrolling is ever wanted, it has to be fixed at the
   source, not switched back on here.

   The header is sticky, so a row scrolled to the very top would sit
   under it; the offset holds it clear by the header height and a
   little air.
   ------------------------------------------------------------- */
html{ scroll-behavior:auto; }
body.abi-site .abi-anchor{scroll-margin-top:calc(var(--abi-hdr-h) + clamp(12px,2vh,28px))}

/* -------------------------------------------------------------
   39. Services without numbers
   The six services are a set, not a sequence. Numbering them read as
   an order of operations, which is what the "How it works" steps are
   for, so the numerals are gone from the service index on the home
   page and from the rows here. The numbered rail keeps its labels and
   loses its figures the same way.

   On the services page the amber rule that used to sit beside the
   numeral now closes the heading: an inline mark after the last word,
   on the same line, so it punctuates the name instead of labelling it.
   It is drawn from the left as the row arrives (the animation is in
   section 17, with the rest of the scroll-driven work). Its resting
   state here is fully drawn, so a browser without scroll timelines —
   or a visitor who asks for reduced motion — simply sees the rule.
   ------------------------------------------------------------- */
.abi-svch .elementor-heading-title::after{
  content:"";display:inline-block;vertical-align:.24em;
  width:clamp(38px,4.2vw,68px);height:3px;
  margin-left:clamp(14px,1.4vw,22px);
  background:var(--abi-amber)}

/* the index row without its number column */
.abi-idx--nonum.e-con{grid-template-columns:minmax(0,260px) minmax(0,1fr) 24px}
@media(max-width:899px){
  .abi-idx--nonum.e-con{grid-template-columns:minmax(0,1fr)}
  .abi-idx--nonum .abi-idx__body{grid-column:1}
}

/* Between 900 and 1200 these rows sit in a column about 350px wide while
   the heading track is fixed at 260px, which left the copy 16px to wrap
   in — one word per line, a 400px-tall paragraph. Keep the stacked
   arrangement until the row is actually wide enough for two columns.
   This band was wrong before the numbers came out; it affects the home
   page index and the Careers list alike. */
@media(min-width:900px) and (max-width:1199px){
  .abi-idx.e-con{grid-template-columns:56px minmax(0,1fr);gap:8px 14px}
  .abi-idx .abi-idx__body{grid-column:2}
  .abi-idx--nonum.e-con{grid-template-columns:minmax(0,1fr)}
  .abi-idx--nonum .abi-idx__body{grid-column:1}
  .abi-idx .abi-idx__arrow,.abi-idx.e-con::after{display:none}
}

/* -------------------------------------------------------------
   40. Callout on a coloured ground
   The MBE strip sits on the brand blue now. It used to be on the pale
   blue tint, which is within a shade of the grey band above it, so the
   two read as one long section and the certification — the thing a
   utility owner or a municipality actually looks for — disappeared into
   the values. On the solid blue it is a stop, and the rule reverts to
   amber because a blue rule on a blue ground is no rule at all.
   ------------------------------------------------------------- */
body.abi-site :is(.abi-on,.abi-blue) .abi-callout__num,
body.abi-site :is(.abi-on,.abi-blue) .abi-callout__num .elementor-heading-title,
body.abi-site :is(.abi-on,.abi-blue) .abi-callout__num .elementor-heading-title a{color:#fff}

/* -------------------------------------------------------------
   41. Safety — the dispatch plate and the practice cells
   The after-hours line began as a recoloured callout strip: the same
   left-ruled component the About page uses for the MBE note, with a
   background dropped behind it. No colour was going to fix that,
   because the problem was the component. It is a plate now, pulled up
   over the foot of the hero the way the fleet panel is pulled over its
   band — the site's own compositional move — and set in the language
   of the hero equipment strip: a monospaced label over a value, an
   amber rule along one edge, the number carrying the weight.

   Burnt amber ground. Ink on ink was a hole, and the graphite that
   replaced it was legible but anonymous -- a neutral grey on a near
   black, which reads as a shadow of the hero rather than an object on
   it. This is the one warm ground in the palette, which is why it suits:
   it bridges the amber rule above it and the cream band below it instead
   of sitting between two unrelated fields, and it is the only one that
   reads as urgent without being the glaring amber band this started as.
   White measures 9.2:1 on it, the cream copy 8.1:1, and the amber number
   3.7:1 -- under 4.5:1, but the number is set at 44px, well into the
   large-text threshold of 3_:1. It separates from the ink at 1.9:1,
   better than graphite's 1.4:1. The cream is on the wrapper rather than
   the plate, so the plate lands in the same warm field as the practice
   cells below it instead of on a white island.

   No shadow. The only two shadows in this stylesheet are the sticky
   header and the mobile menu sheet — things that leave the page.
   Content here separates by changing plane, with a fine edge on it.

   The amber rule is on the top edge, not the left. A left rule crosses
   the hero/cream seam halfway down its own length: it measures 7.0:1
   against the ink above and 2.4:1 against the cream below, so it
   dissolves partway down. The top edge sits entirely over the hero, so
   the amber holds one value the whole way across — and that was the
   edge that needed defining anyway. Every other amber bar on this site
   is horizontal too.

   The plate is anchored to the page's left edge and padded by the
   gutter, so its label starts on the hero's own text axis at every
   width. Inset, it sat on an axis of its own and drifted further off
   the hero the wider the viewport got, because the section container
   is centred inside a max-width while the hero is padded by --abi-gut.
   ------------------------------------------------------------- */
/* The inset the plate used to sit in is this wrapper's own --abi-gut padding.
   Zeroing it lets the plate reach the page edge; the plate then carries the
   gutter as its own left padding, which is what puts its label on the hero's
   text axis at every width. */
body.abi-site .abi-emgwrap.e-con{
  background:var(--abi-amber1);padding-inline:0;margin-top:0;
  position:relative;z-index:3}
body.abi-site .abi-emgwrap.e-con > .e-con-inner{
  background:transparent;padding-inline:0;max-width:none;width:100%}
/* The rise is on the plate, not the wrapper. On the wrapper the cream climbs
   with it and paints over the foot of the hero. */
body.abi-site .abi-emgplate.e-con{
  margin:0 var(--abi-gut) 0 0;
  /* It stops well short of the right edge so the asymmetry reads as a choice.
     The stop is proportional to the site's own content measure rather than the
     viewport, so the plate stays this size on a very wide screen instead of
     stretching the number away from the copy. */
  /* Three caps. The gutter one only matters on a phone; the measure one holds
     the plate at a fixed size on a very wide screen; the 78% is what makes it
     stop short in the middle of the range, where the other two were both slack
     and the plate ran almost to the edge. */
  width:min(calc(100% - var(--abi-gut)), calc(var(--abi-axis) + var(--abi-max) * .72), 78%);
  background:var(--abi-amber9);
  border-top:3px solid var(--abi-amber);
  border-right:1px solid rgba(255,255,255,.10);
  border-bottom:1px solid rgba(255,255,255,.10);
  border-left:0;
  padding:clamp(20px,1.9vw,28px) clamp(26px,3vw,46px)
          clamp(20px,1.9vw,28px) var(--abi-axis);
  gap:20px clamp(28px,3.4vw,60px);align-items:center}
body.abi-site .abi-emgplate :is(.abi-h3,.abi-h3 .elementor-heading-title){
  font-family:var(--abi-mono);font-size:clamp(12px,.95vw,13px);font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;line-height:1.5;color:#fff}
/* cream rather than the cool grey the dark sections use: on this warm ground it
   measures 8.1:1 against the g300's 5.9:1, and it is the same cream as the band
   the plate is sitting in */
body.abi-site .abi-emgplate .abi-sm{color:var(--abi-amber1);max-width:44ch;line-height:1.5}
/* the label and the line under it are one unit, so they sit closer than the
   container's own rhythm would put them */
body.abi-site .abi-emgplate > .e-con:first-child{gap:7px}
body.abi-site .abi-emgplate .abi-callout__num,
body.abi-site .abi-emgplate .abi-callout__num .elementor-heading-title,
body.abi-site .abi-emgplate .abi-callout__num .elementor-heading-title a{
  color:var(--abi-amber);font-size:clamp(28px,3.3vw,44px);line-height:1;
  white-space:nowrap}
/* The plate is shared. --over is the variant that crosses the foot of a hero:
   it rises out of its cream band and arrives as the last beat of the hero's load,
   on the same 1480ms and the same wipe the home page rail uses, out of the left
   edge it is anchored to. Without the modifier the plate simply sits in its band,
   which is what the Contact page needs, and it wipes in on scroll instead. */
body.abi-site .abi-emgwrap--over.e-con,
body.abi-site .abi-emgwrap--over.e-con > .e-con-inner{padding-top:0}
body.abi-site .abi-emgwrap--over .abi-emgplate.e-con{
  margin-top:calc(-1 * clamp(60px,5.5vw,100px));
  animation:abi-railwipe 1100ms var(--abi-ease) 1480ms both}
@supports (animation-timeline: view()){
@media(prefers-reduced-motion:no-preference){
  body.abi-site .abi-emgwrap:not(.abi-emgwrap--over) .abi-emgplate.e-con{
    animation:abi-railwipe linear both;animation-timeline:view();
    animation-range:entry 14% cover 34%}
}}
@media(max-width:899px){
  /* The hero stacks here and its copy runs to the foot of the block, so the
     plate sits below it rather than over it. Body-prefixed to outrank the
     desktop rule above, which carries the same weight. */
  /* The 78% cap is a desktop composition device — it exists so the plate stops
     short of the hero photograph. There is no photograph beside it here, so it
     goes back to the full measure less one gutter. */
  body.abi-site .abi-emgwrap .abi-emgplate.e-con{margin-top:0;
    width:calc(100% - var(--abi-gut));
    padding:24px 22px 26px var(--abi-axis)}
  body.abi-site .abi-emgwrap.e-con > .e-con-inner{padding-top:clamp(28px,5vw,44px)}
}

.abi-rulecell .abi-tick{transition:width .3s var(--abi-ease)}
.abi-rulecell :is(.abi-h3,.abi-bdy){transition:transform .3s var(--abi-ease)}
.abi-rulecell:hover .abi-tick,
.abi-rulecell:focus-within .abi-tick{width:64px}
.abi-rulecell:hover :is(.abi-h3,.abi-bdy),
.abi-rulecell:focus-within :is(.abi-h3,.abi-bdy){transform:translateX(6px)}

/* -------------------------------------------------------------
   42. Icons
   This site marks things with bars, and that still holds for
   anything that divides or points. These are the exception: a short
   line-drawn set where the glyph names the thing faster than the
   label can — one per figure, one per reason, one on the MBE note.
   One stroke weight, one size step, one colour, all drawn on the
   same 24-unit grid, so five of them in a row read as a set rather
   than as five separate decisions. They are decorative: every one is
   aria-hidden and sits beside a label that already says it.
   ------------------------------------------------------------- */
.abi-ico{line-height:0;color:var(--abi-amber);padding:0;margin:0;flex:none}
.abi-ico svg{width:clamp(26px,2.1vw,32px);height:auto;display:block}
.abi-ico--lg svg{width:clamp(48px,4.6vw,66px)}
/* Amber holds on ink (7.0:1) and matches the eyebrow above it, so the dark
   sections keep it. On the solid blue it goes thin at this stroke weight, the
   same reason the callout number turns white there in section 40. */
body.abi-site .abi-blue .abi-ico{color:#fff}

/* -------------------------------------------------------------
   43. About overview — the spec plate
   Four figures each led by its own 3px amber rule, and four sectors
   under them each led by an amber tick, put eight identical orange
   bars in one screenful. Repeated that many times the bar stops
   being an accent and becomes a texture, and the two rows rhymed so
   closely that the figures and the sectors read as the same kind of
   thing when they are not.

   So: one hairline across each row instead of one per cell, upright
   hairlines between the cells, and the amber used exactly once — a
   short index mark sitting on the start of the figures' rule, which
   gives the eye one place to enter. The result reads as a plate off
   a piece of equipment rather than as four cards, which is the
   register this brand is already in.

   The icon moves off the top of each cell and on to the number's
   own line, pushed to the cell's right edge. The number and the
   line under it then share one left edge, and the icons set up a
   second rhythm down the right of the row.
   ------------------------------------------------------------- */
.abi-specplate.e-con,
.abi-sectorrow.e-con{
  position:relative;gap:0;padding:0;
  border-top:1px solid var(--abi-g300)}
/* the one amber mark. A container's own ::before is pinned to all four edges
   by Elementor, so the unused sides have to be released by hand. */
.abi-specplate.e-con::before{
  content:"";position:absolute;left:0;top:-1px;right:auto;bottom:auto;
  width:clamp(56px,6vw,88px);height:3px;background:var(--abi-amber)}

.abi-specplate > .abi-stat.e-con{
  display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;
  column-gap:14px;row-gap:clamp(10px,1vw,14px);
  border-top:0;
  padding:clamp(18px,1.7vw,26px) clamp(18px,1.8vw,30px) clamp(22px,2vw,32px) 0}
.abi-specplate > .abi-stat + .abi-stat.e-con{
  border-left:1px solid var(--abi-g300);
  padding-left:clamp(18px,1.8vw,30px)}
/* The figure shares its line with the icon now, so it has to hold one line:
   "2,100 gal" is nine monospaced characters and was wrapping in a quarter-width
   cell, which dropped that cell's caption below the other three. */
.abi-specplate .abi-stat .abi-stat__n{grid-column:1;grid-row:1;
  font-size:clamp(28px,2.6vw,42px);white-space:nowrap}
.abi-specplate .abi-stat .abi-ico{grid-column:2;grid-row:1;justify-self:end}
.abi-specplate .abi-stat .abi-sm{grid-column:1 / -1;grid-row:2}

.abi-sectorrow > .e-con{
  padding:clamp(16px,1.5vw,22px) clamp(18px,1.8vw,30px) 0 0}
.abi-sectorrow > .e-con + .e-con{
  border-left:1px solid var(--abi-g300);
  padding-left:clamp(18px,1.8vw,30px)}

/* The grid drops to two columns at 1099 and one at 640, so the upright rules
   have to become horizontal ones at the wraps or they end up drawn down the
   left of a cell that starts a row. */
@media(max-width:1099px){
  .abi-specplate > .abi-stat:nth-child(odd).e-con,
  .abi-sectorrow > .e-con:nth-child(odd){border-left:0;padding-left:0}
  .abi-specplate > .abi-stat:nth-child(n+3).e-con,
  .abi-sectorrow > .e-con:nth-child(n+3){border-top:1px solid var(--abi-g300)}
}
@media(max-width:640px){
  .abi-specplate > .abi-stat.e-con,
  .abi-sectorrow > .e-con{border-left:0;padding-left:0}
  .abi-specplate > .abi-stat + .abi-stat.e-con,
  .abi-sectorrow > .e-con + .e-con{border-top:1px solid var(--abi-g300)}
}

/* The cells arrive one after another, and the icon lifts under the cursor.
   The lift is on the icon rather than the cell because the scroll animation
   below fills its own transform on the cell and would overwrite it. */
.abi-specplate .abi-stat .abi-ico{transition:transform .3s var(--abi-ease)}
.abi-specplate .abi-stat:hover .abi-ico{transform:translateY(-4px)}
@supports (animation-timeline: view()){
@media(prefers-reduced-motion:no-preference){
  .abi-specplate > .abi-stat{animation:abi-sr-rise-sm linear both;
    animation-timeline:view();animation-range:entry 12% cover 30%}
  .abi-specplate > .abi-stat:nth-child(2){animation-range:entry 17% cover 35%}
  .abi-specplate > .abi-stat:nth-child(3){animation-range:entry 22% cover 40%}
  .abi-specplate > .abi-stat:nth-child(4){animation-range:entry 27% cover 45%}
}}

/* -------------------------------------------------------------
   44. Last-line orphans
   A paragraph that ends with one word alone on its own line reads
   as a mistake, and there were fifteen of them across the seven
   pages at 1440. Binding the last two words together in the copy
   would only fix the width it was measured at: the break moves as
   the viewport does, so a hard fix lands the orphan somewhere else
   and has to be redone every time anyone edits a sentence.

   text-wrap:pretty is the browser doing it at every width instead.
   It costs nothing where it is unsupported, which is the same
   ragged last line we have now, so there is no fallback to write.

   balance rather than pretty: balance evens the length of every
   line in a block rather than just repairing the last one, so a
   three-line lede sets as three even lines instead of two full ones
   and a remnant. Note that browsers cap it -- Chrome at six lines --
   so a long paragraph is left alone entirely; the blocks here are
   short enough that it applies. A hard <br> splits a block into
   separate runs that are balanced independently, which leaves the
   deliberate breaks in .abi-brk intact.
   ------------------------------------------------------------- */
body.abi-site :is(p,li,.abi-lede,.abi-bdy,.abi-sm,.abi-h3,.abi-h4,
  .elementor-heading-title,.elementor-widget-text-editor){text-wrap:balance}

/* balance will break INSIDE a word wherever overflow-wrap permits it, because
   splitting a word is a legitimate way to even out line lengths. .abi-d3 and
   .abi-d4 carry overflow-wrap:break-word, and at 1024 that turned the Our Work
   heading "as photographed." into "photographe / d." — pretty never did this,
   because it only ever moves whole words.

   break-word is an overflow guard for a word too long for its column, which is
   a phone problem, so it is scoped to phones; and at that width those two
   headings fall back to pretty, so the pair never meets. */
body.abi-site :is(.abi-d0,.abi-d1,.abi-d2,.abi-d3,.abi-d4),
body.abi-site :is(.abi-d0,.abi-d1,.abi-d2,.abi-d3,.abi-d4)
  :is(.elementor-heading-title,h1,h2,h3,h4,p){overflow-wrap:normal}
@media(max-width:640px){
  body.abi-site :is(.abi-d0,.abi-d1,.abi-d2,.abi-d3,.abi-d4),
  body.abi-site :is(.abi-d0,.abi-d1,.abi-d2,.abi-d3,.abi-d4)
    :is(.elementor-heading-title,h1,h2,h3,h4,p){overflow-wrap:break-word;text-wrap:pretty}
}

/* -------------------------------------------------------------
   45. Services -- the reasons row
   Every page on this site puts a light or a blue section immediately
   before the closing CTA: home and About both hand over from blue to
   the CTA's ink, Safety and Our work from white. Services was the one
   page where the section above the CTA was ink as well, so the foot of
   it was a single black field with a rule across the middle, and no
   amount of treatment inside that field was going to fix a problem
   that was really about the two grounds being the same.

   So the section takes the blue, which is what home and About already
   do in this position, and the page hands over fleet -> blue -> ink.
   The reasons keep the upright hairlines between them so the five read
   as one measured row rather than five floating columns.
   ------------------------------------------------------------- */
.abi-whyplate.e-con{gap:0;padding:0}
.abi-whyplate > .e-con{padding-inline:clamp(18px,1.9vw,34px)}
.abi-whyplate > .e-con:first-child{padding-left:0}
.abi-whyplate > .e-con + .e-con{border-left:1px solid rgba(255,255,255,.26)}
body.abi-site .abi-whyplate .abi-sm{color:#dbe4f5}
/* The reasons were set at the same weight as a caption, which left the section
   quieter than the six service rows above it. The heading in each column steps up
   a size and the glyph with it, so each reason has a point to land on. */
body.abi-site .abi-whyplate :is(.abi-h4,.abi-h4 .elementor-heading-title){
  font-size:clamp(19px,1.55vw,23px);line-height:1.22;font-weight:600;
  letter-spacing:-.015em;color:#fff}
body.abi-site .abi-whyplate .abi-ico svg{width:clamp(32px,2.6vw,40px)}
body.abi-site .abi-whyplate > .e-con{gap:clamp(14px,1.3vw,20px)}

/* the grid drops to two columns at 1099 and one at 640, so the upright rules
   have to become horizontal ones at the wraps */
@media(max-width:1099px){
  .abi-whyplate > .e-con{padding-block:clamp(16px,1.8vw,24px)}
  .abi-whyplate > .e-con:nth-child(odd){border-left:0;padding-left:0}
  .abi-whyplate > .e-con:nth-child(n+3){border-top:1px solid rgba(255,255,255,.26)}
}
@media(max-width:640px){
  .abi-whyplate > .e-con{border-left:0;padding-left:0}
  .abi-whyplate > .e-con + .e-con{border-top:1px solid rgba(255,255,255,.26)}
}

/* the five arrive one after another as the row comes up */
@supports (animation-timeline: view()){
@media(prefers-reduced-motion:no-preference){
  .abi-whyplate > .e-con{animation:abi-sr-rise-sm linear both;
    animation-timeline:view();animation-range:entry 12% cover 30%}
  .abi-whyplate > .e-con:nth-child(2){animation-range:entry 16% cover 34%}
  .abi-whyplate > .e-con:nth-child(3){animation-range:entry 20% cover 38%}
  .abi-whyplate > .e-con:nth-child(4){animation-range:entry 24% cover 42%}
  .abi-whyplate > .e-con:nth-child(5){animation-range:entry 28% cover 46%}
}}

/* -------------------------------------------------------------
   46. The dispatch plate, mirrored
   Contact runs the same plate off the other edge. It hangs from the
   right of the page, its number lands on the page's right margin the
   way the Safety label lands on the hero's text axis, and it wipes out
   of the right edge rather than the left -- same 1100ms, same 1480ms
   start, so both pages close their hero on the same beat.
   ------------------------------------------------------------- */
@keyframes abi-railwipe-r{from{clip-path:inset(0 0 0 100%)}to{clip-path:inset(0 0 0 0)}}
body.abi-site .abi-emgplate--right.e-con{
  margin-left:auto;margin-right:0;
  border-left:1px solid rgba(255,255,255,.10);border-right:0;
  padding:clamp(20px,1.9vw,28px) var(--abi-axis)
          clamp(20px,1.9vw,28px) clamp(26px,3vw,46px)}
body.abi-site .abi-emgwrap--over .abi-emgplate--right.e-con{animation-name:abi-railwipe-r}
@media(max-width:899px){
  body.abi-site .abi-emgwrap .abi-emgplate--right.e-con{
    margin-left:auto;margin-right:0;
    padding:24px var(--abi-axis) 26px 22px}
}

/* -------------------------------------------------------------
   47. Form — underline fields, floating labels
   The estimate form sits on the cream now, so the plate's own band
   runs straight into it and Contact reads ink / cream / ink rather
   than stacking a cream strip on a white one.

   The fields are rules, not boxes. Everything else on this site
   divides with a hairline -- the spec plate, the footer columns,
   the service rows -- and a stack of bordered rectangles was the
   least native thing on it.

   The label starts on the field's own text line, where a
   placeholder would sit, and rises above the rule as soon as the
   field is focused or filled. That is the look a placeholder gives
   you on an empty form without the cost of one: a placeholder is
   gone the moment someone types, so on a nine-field form they
   cannot check what they entered, autofill wipes the only clue
   what the field was, and it is a weak accessible name besides.
   Here the name is a real <label>, always on screen.

   Focus doubles the rule in amber by painting a second line under
   it rather than growing the border, because a border that grows
   on focus shifts every field below it down a pixel.

   :placeholder-shown is what tells the label the field is empty,
   so every text field carries a single-space placeholder; without
   one the selector never matches and the label would sit over the
   typed value. The @supports block below is the belt and braces.
   ------------------------------------------------------------- */
body.abi-site .abi-form .elementor-form-fields-wrapper{gap:34px 24px}
body.abi-site .abi-form .elementor-field-group{position:relative;gap:0;padding-top:24px}

body.abi-site .abi-form .elementor-field-group .elementor-field-textual,
body.abi-site .abi-form .elementor-field-group select.elementor-field-textual{
  width:100%;min-height:0;height:auto;
  padding:0 0 12px;border:0;border-bottom:1px solid var(--abi-g500);border-radius:0;
  background:transparent;box-shadow:none;
  font-family:var(--abi-txt);font-size:18px;line-height:1.45;color:var(--abi-ink);
  transition:border-color .18s ease, box-shadow .18s ease}
body.abi-site .abi-form textarea.elementor-field-textual{min-height:112px;resize:vertical}
/* A text input's box collapses to line-height + padding; a select's does not --
   the UA gives it a taller intrinsic box, so on Careers the Position select's rule
   sat 13px below the Phone field's beside it. Pinning it to the same computed
   height puts the two rules back on one line: 1.45em of line box, 12px of padding
   and the 1px rule itself.

   Note the class. Elementor puts .elementor-field on the select's WRAPPER, not on
   the select -- the select itself is .elementor-field-textual, same as the inputs.
   Anything written against select.elementor-field silently matches nothing. The
   wrapper is stripped of its own box here so only the select's rule is drawn. */
body.abi-site .abi-form .elementor-field-group select.elementor-field-textual{
  height:calc(1.45em + 13px)}
body.abi-site .abi-form .elementor-field-group .elementor-select-wrapper{
  border:0;background:transparent;padding:0;min-height:0;box-shadow:none}

body.abi-site .abi-form .elementor-field-group .elementor-field-textual:hover,
body.abi-site .abi-form .elementor-field-group select.elementor-field-textual:hover{
  border-bottom-color:var(--abi-ink)}
body.abi-site .abi-form .elementor-field-group .elementor-field-textual:focus,
body.abi-site .abi-form .elementor-field-group select.elementor-field-textual:focus{
  outline:none;border-bottom-color:var(--abi-amber);
  box-shadow:0 1px 0 0 var(--abi-amber)}

body.abi-site .abi-form .elementor-field-group > .elementor-field-label{
  position:absolute;left:0;right:0;top:24px;width:auto;max-width:none;margin:0;padding:0;
  font-family:var(--abi-mono);font-size:16px;font-weight:400;letter-spacing:0;
  text-transform:none;color:var(--abi-g500);line-height:1.45;text-align:left;
  pointer-events:none;
  transition:top .18s var(--abi-ease), font-size .18s var(--abi-ease),
             letter-spacing .18s var(--abi-ease), color .18s var(--abi-ease)}

body.abi-site .abi-form .elementor-field-group:focus-within > .elementor-field-label,
body.abi-site .abi-form .elementor-field-group:has(.elementor-field-textual:not(:placeholder-shown)) > .elementor-field-label,
body.abi-site .abi-form .elementor-field-group:has(select) > .elementor-field-label{
  top:0;font-size:11px;letter-spacing:.1em;color:var(--abi-g600)}

body.abi-site .abi-form .elementor-field-required .elementor-field-label::after,
body.abi-site .abi-form .elementor-mark-required .elementor-field-label::after{
  color:var(--abi-amber);font-weight:600}

body.abi-site .abi-form .elementor-select-wrapper select{padding-right:28px}
body.abi-site .abi-form .elementor-select-wrapper::after,
body.abi-site .abi-form .elementor-select-wrapper .e-font-icon-svg{
  right:2px;color:var(--abi-g600)}

/* The upload has no placeholder and is never "filled" in the sense :placeholder-shown
   understands, so a floating label would sit on its box for ever. It keeps a plain
   label above the control. */
body.abi-site .abi-form .elementor-field-group.elementor-field-type-upload{padding-top:0;gap:7px}
body.abi-site .abi-form .elementor-field-type-upload > .elementor-field-label{
  position:static;top:auto;font-size:11px;letter-spacing:.1em;color:var(--abi-g600)}

/* the upload is the one control that still needs to look like a target */
body.abi-site .abi-form .elementor-field-type-upload .elementor-field{
  border:1px dashed var(--abi-g500);background-color:transparent;border-radius:0;padding:14px}
body.abi-site .abi-form .elementor-message{border-radius:0}
body.abi-site .abi-form .elementor-field-group.elementor-error .elementor-field{
  border-bottom-color:#b3261e}

/* Without :has() the label cannot know whether the field is filled, so it stays
   above the rule, where it can never collide with what someone has typed. */
@supports not (selector(:has(*))){
  body.abi-site .abi-form .elementor-field-group{padding-top:0;gap:7px}
  body.abi-site .abi-form .elementor-field-group > .elementor-field-label{
    position:static;top:auto;font-size:11px;letter-spacing:.1em;color:var(--abi-g600)}
}

/* -------------------------------------------------------------
   48. The contact ground, and the checklist beside the form
   Cream is now the designated contact surface: wherever the site
   asks someone to get in touch -- the estimate form, the dispatch
   plate's band, the careers enquiry -- it sits on this. Every page
   that carries a form reads the same, and the colour does the job a
   heading would otherwise have to.

   The checklist earns its entrance from what it already is: a rule
   over a label over four dashed lines. So the rule draws itself in
   first, the label follows, and the four items come in from the
   left one after another, each arriving the way it is already
   punctuated. The amber rule has to become a pseudo-element to do
   it, because a border cannot be transformed.
   ------------------------------------------------------------- */
.abi-contactbg{background:var(--abi-amber1)}

/* One named timeline on the block, not view() on each piece. The amber rule is a
   3px-tall pseudo-element, and its own view() range is so short it never resolves
   to anything usable -- the rule simply stayed at scaleX(0). Hanging every part off
   the parent's timeline also means the four items are staggered against the block's
   progress rather than each against its own, which is what makes them read as one
   gesture. */
.abi-reveal-list.e-con{position:relative;border-top:0;view-timeline-name:--abi-revlist}
.abi-reveal-list.e-con::before{content:"";position:absolute;left:0;top:0;right:auto;bottom:auto;
  width:100%;height:3px;background:var(--abi-amber);transform-origin:left center}
@supports (animation-timeline: view()){
@media(prefers-reduced-motion:no-preference){
  @keyframes abi-sr-slide{from{opacity:0;transform:translateX(-14px)}to{opacity:1;transform:none}}
  /* no static scaleX(0) here: the from-state comes from the animation's own fill,
     so if the animation ever fails to attach the rule draws at full width rather
     than disappearing altogether */
  .abi-reveal-list.e-con::before{
    animation:abi-sr-line linear both;animation-timeline:--abi-revlist;
    animation-range:entry 20% entry 86%}
  .abi-reveal-list > .abi-mn{animation:abi-sr-rise-sm linear both;
    animation-timeline:--abi-revlist;animation-range:entry 42% entry 100%}
  .abi-reveal-list .elementor-icon-list-item{animation:abi-sr-slide linear both;
    animation-timeline:--abi-revlist;animation-range:entry 56% contain 8%}
  .abi-reveal-list .elementor-icon-list-item:nth-child(2){animation-range:entry 66% contain 16%}
  .abi-reveal-list .elementor-icon-list-item:nth-child(3){animation-range:entry 76% contain 24%}
  .abi-reveal-list .elementor-icon-list-item:nth-child(4){animation-range:entry 86% contain 32%}
}}

/* -------------------------------------------------------------
   49. Safety -- the closing statement
   This section went through a full-bleed version that did not work,
   and the reason is worth recording: close-work.jpg is 445x455. A
   21:9 band across a 1920 viewport asked a 445px file to cover 1920,
   a 4.3x upscale, and no amount of layout would have saved it. The
   whole library tops out at 1600px except the two hero plates, so
   full-bleed photography is not available to this page at all.

   So the picture is used at the size it actually is. The right column
   is capped at the file's own width, the frame is square because the
   source is square, and the caption sits under the picture inside
   that column rather than in a full-width row of its own.

   The void the section started with came from two columns of very
   different heights pinned to a common top edge. They are centred on
   each other now and the section runs at the tight rhythm, so the
   space around the statement is the measure of the block rather than
   an empty quadrant under it.
   ------------------------------------------------------------- */
.abi-closespread.e-con{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,445px);
  column-gap:clamp(32px,4.4vw,88px);row-gap:clamp(28px,3vw,44px);
  align-items:center;gap:0 clamp(32px,4.4vw,88px);padding:0}
.abi-closespread > .e-con:first-child{display:block;max-width:none;padding:0}
.abi-closespread > .e-con:last-child{margin:0;padding:0;width:100%;max-width:445px}
/* never ask the file for more pixels than it has */
.abi-closespread .abi-ph.e-con{aspect-ratio:1/1;width:100%;max-width:445px;margin:0}
.abi-closespread .abi-figcap{margin-top:14px;padding:0}
@media(max-width:899px){
  /* The 445px cap stays on when the columns stack. A tablet would otherwise ask
     the same file to cover ~700px, which is the upscale this section started
     with, just smaller. */
  .abi-closespread.e-con{grid-template-columns:1fr;gap:clamp(26px,5vw,38px) 0}
  .abi-closespread .abi-ph.e-con{aspect-ratio:4/3}
}

/* -------------------------------------------------------------
   50. Careers -- "Why this crew."
   The three cells were led by the same 32px amber tick used on a
   dozen other cards, so the row read as a list of notes rather than
   as the reason to apply. Each cell now carries its own figure on
   the shared 24-unit grid: the levers for the equipment, the two
   figures for the crew, the signpost for the trade that travels.

   The accent moves into the drawing, so the cells themselves are
   framed in the neutral hairline the About spec plate uses -- one
   rule across the top of the row and upright rules between the
   cells -- rather than three repeated amber bars. Below 900 the row
   drops to a single column and the uprights become the same
   hairline laid flat, because three text cells in two columns
   always leave one of them stranded.
   ------------------------------------------------------------- */
body.abi-site .abi-whyrow.e-con{
  gap:0;padding:clamp(22px,2.2vw,32px) 0 0;
  border-top:1px solid var(--abi-g300)}
body.abi-site .abi-whyrow > .e-con{
  gap:0;padding-block:0;padding-inline:clamp(18px,2vw,34px)}
body.abi-site .abi-whyrow > .e-con:first-child{padding-left:0}
body.abi-site .abi-whyrow > .e-con:last-child{padding-right:0}
body.abi-site .abi-whyrow > .e-con + .e-con{border-left:1px solid var(--abi-g300)}
/* the figure carries the row's only colour, so it is drawn larger than
   the inline icon default */
body.abi-site .abi-whyrow .abi-ico svg{width:clamp(34px,2.9vw,44px)}
body.abi-site .abi-whyrow :is(.abi-h4,.abi-h4 .elementor-heading-title){
  font-size:clamp(19px,1.55vw,23px);line-height:1.22;
  font-weight:600;letter-spacing:-.015em}
/* the container's gap is off, so the two steps are set here: the figure
   sits a little away from its heading, the supporting line stays tight */
body.abi-site .abi-whyrow .abi-ico + .abi-h4{margin-top:clamp(16px,1.6vw,22px)}
body.abi-site .abi-whyrow .abi-h4 + .abi-sm{margin-top:12px}
@media(max-width:899px){
  body.abi-site .abi-whyrow.e-con{grid-template-columns:1fr}
  body.abi-site .abi-whyrow > .e-con{padding-inline:0}
  body.abi-site .abi-whyrow > .e-con + .e-con{
    border-left:0;border-top:1px solid var(--abi-g300);
    padding-top:clamp(22px,3.4vw,30px);margin-top:clamp(24px,3.6vw,34px)}
}

/* -------------------------------------------------------------
   51. Our work -- photographs at the size the files actually are
   The page promised photography and then upscaled its two lead
   frames: work-site.jpg (640x461) was being drawn at 861 and
   tank-badge.jpg (310x230) at 474, which is 2.7x and 3.1x once a
   retina screen asks for its second pixel. Nothing in the layout
   could have rescued that, so the layout stopped asking.

   A frame now carries the width of its own file as a cap. It may
   be drawn smaller when the column is narrow; it is never drawn
   larger. The right-hand air in the pair is deliberate -- it is
   what honest sizing costs on this library, and it reads as
   margin rather than as a photograph that gave up.

   tank-badge.jpg is not on the page any more. At 310px there was
   no size at which it held, and it was a badge, not the work.
   ------------------------------------------------------------- */
.abi-nat-445.e-con{max-width:445px}
.abi-nat-520.e-con{max-width:520px}
.abi-nat-640.e-con{max-width:640px}
.abi-nat-960.e-con{max-width:960px}

.abi-natpair.e-con{
  --nat-a:640px;--nat-b:445px;
  display:grid;grid-template-columns:minmax(0,var(--nat-a)) minmax(0,var(--nat-b));
  justify-content:start;align-items:start;
  gap:clamp(26px,3vw,44px) clamp(24px,3vw,56px);padding:0}
/* the home teaser pairs the roadway shot with the boom detail instead */
.abi-natpair--640-520.e-con{--nat-a:640px;--nat-b:520px}
body.abi-site .abi-natpair > .e-con{padding:0;gap:12px;max-width:none}
@media(max-width:700px){
  /* one column; each frame is still held by its own .abi-nat-* cap */
  .abi-natpair.e-con{grid-template-columns:minmax(0,1fr)}
}

/* -------------------------------------------------------------
   52. Openings -- the careers post type
   Two surfaces: the list the [abi_openings] shortcode puts on the
   Careers page, and the single posting, which is a plain PHP
   template rather than an Elementor one. Everything here is drawn
   with the same tokens as the rest of the site, but the section
   padding has to be stated rather than inherited: .abi-sec only
   sets the custom properties Elementor's .e-con consumes, and
   there is no .e-con on a theme template.

   The site ships with no openings, so the empty state is not an
   edge case here -- it is the default view, and it is written to
   stand on its own.
   ------------------------------------------------------------- */

/* --- the list on the Careers page --- */
body.abi-site .abi-jobs{display:grid;gap:0}
body.abi-site .abi-job{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:10px clamp(24px,3vw,56px);align-items:start;
  padding:clamp(22px,2.4vw,30px) 0;
  border-top:1px solid var(--abi-g300)}
body.abi-site .abi-jobs .abi-job:last-child{border-bottom:1px solid var(--abi-g300)}
body.abi-site .abi-job__t{
  grid-column:1;margin:0;
  font-family:var(--abi-disp);font-size:clamp(20px,1.8vw,26px);line-height:1.2;
  font-weight:700;letter-spacing:-.015em;color:var(--abi-ink)}
body.abi-site .abi-job__t a{color:inherit;text-decoration:none}
body.abi-site .abi-job__t a:hover{color:var(--abi-brand)}
body.abi-site .abi-job__s{grid-column:1;margin:0;max-width:62ch}
/* the facts someone scans for before they read a word of the posting */
body.abi-site .abi-job__meta{
  grid-column:1;display:flex;flex-wrap:wrap;gap:6px 10px;margin:4px 0 0;padding:0;list-style:none}
body.abi-site .abi-job__meta li{
  font-family:var(--abi-mono);font-size:11px;line-height:1.5;letter-spacing:.06em;
  text-transform:uppercase;color:var(--abi-g600);
  padding:4px 10px;border:1px solid var(--abi-g300);border-radius:2px}
body.abi-site .abi-job__go{grid-column:2;grid-row:1 / span 3;align-self:center;
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--abi-txt);font-size:15px;font-weight:600;
  color:var(--abi-brand);text-decoration:none;white-space:nowrap}
body.abi-site .abi-job__go svg{transition:transform .2s var(--abi-ease)}
body.abi-site .abi-job__go:hover svg{transform:translateX(4px)}
@media(max-width:700px){
  body.abi-site .abi-job{grid-template-columns:minmax(0,1fr)}
  body.abi-site .abi-job__go{grid-column:1;grid-row:auto;margin-top:6px}
}

/* --- no openings: the state the site ships in --- */
/* The same amber rule sat on the empty-state plate. One accent repeated on
   every light panel is the vertical-bar problem again, so this one is held
   by the neutral hairline the About spec plate uses and nothing else. */
body.abi-site .abi-jobs--none{
  display:block;border:1px solid var(--abi-g300);
  background:var(--abi-fleet);padding:clamp(26px,3vw,38px) clamp(24px,3vw,40px)}
body.abi-site .abi-jobs__none-l{margin:0 0 10px;color:var(--abi-g600)}
body.abi-site .abi-jobs__none-p{margin:0;max-width:64ch}

/* --- single posting --- */
body.abi-site .abi-op{background:#fff;position:relative;z-index:1}
body.abi-site .abi-opsec{
  max-width:calc(var(--abi-max) + 2 * var(--abi-gut));margin-inline:auto;
  padding:var(--abi-pad) var(--abi-gut)}
body.abi-site .abi-ophead{padding-bottom:clamp(32px,3.4vw,48px)}
body.abi-site .abi-opback{
  display:inline-block;margin-bottom:clamp(20px,2.4vw,34px);
  font-family:var(--abi-mono);font-size:12px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--abi-g600);text-decoration:none}
body.abi-site .abi-opback:hover{color:var(--abi-brand)}
body.abi-site .abi-ophead .abi-d2{margin:14px 0 0;max-width:20ch}
body.abi-site .abi-ophead__s{margin:clamp(16px,1.8vw,24px) 0 0;max-width:58ch}
body.abi-site .abi-opapply{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  margin-top:clamp(26px,2.8vw,38px);
  min-height:56px;padding:0 clamp(20px,2vw,30px);border-radius:2px;
  background:var(--abi-brand);color:#fff;
  font-family:var(--abi-txt);font-size:15px;font-weight:600;letter-spacing:.01em;
  text-decoration:none;
  transition:background-color .18s ease,transform .18s ease}
body.abi-site .abi-opapply:hover{background:var(--abi-brand7);color:#fff;transform:translateY(-1px)}
body.abi-site .abi-opapply svg{transition:transform .2s var(--abi-ease)}
body.abi-site .abi-opapply:hover svg{transform:translateX(4px)}
/* a posting that is no longer live says so instead of showing Apply */
body.abi-site .abi-opclosed{
  margin:clamp(24px,2.6vw,34px) 0 0;max-width:62ch;
  border-left:3px solid var(--abi-amber);padding:14px 0 14px 18px;
  font-family:var(--abi-txt);font-size:16px;line-height:1.55;color:var(--abi-g600)}
body.abi-site .abi-opclosed a{color:var(--abi-brand)}

/* the facts, on one hairline per row, as on the About spec plate */
body.abi-site .abi-opspecsec{
  padding-block:clamp(34px,3.4vw,48px);
  border-top:1px solid var(--abi-g300);border-bottom:1px solid var(--abi-g300)}
body.abi-site .abi-opspec{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0 clamp(32px,4vw,80px);margin:0}
body.abi-site .abi-opspec__row{
  display:grid;grid-template-columns:minmax(0,13ch) minmax(0,1fr);
  gap:8px clamp(16px,2vw,28px);align-items:baseline;
  padding:13px 0;border-bottom:1px solid var(--abi-g100)}
body.abi-site .abi-opspec__row dt{color:var(--abi-g500);margin:0}
body.abi-site .abi-opspec__row dd{
  margin:0;font-family:var(--abi-txt);font-size:16px;line-height:1.45;
  font-weight:500;color:var(--abi-ink)}
body.abi-site .abi-opspec__note{margin:clamp(18px,2vw,26px) 0 0;max-width:62ch}
@media(max-width:899px){
  body.abi-site .abi-opspec{grid-template-columns:minmax(0,1fr)}
}

body.abi-site .abi-opbody{display:grid;gap:clamp(30px,3.2vw,46px);max-width:calc(880px + 2 * var(--abi-gut))}
body.abi-site .abi-opprose{margin:0}
body.abi-site .abi-opprose p{margin:0 0 1em}
body.abi-site .abi-opprose p:last-child{margin-bottom:0}
body.abi-site .abi-oplist{display:grid;gap:14px}
body.abi-site .abi-oplist h2{margin:0}
body.abi-site .abi-oplist ul{margin:0;padding:0;list-style:none;display:grid;gap:9px}
body.abi-site .abi-oplist li{position:relative;padding-left:22px}
body.abi-site .abi-oplist li::before{
  content:"";position:absolute;left:0;top:.62em;right:auto;bottom:auto;
  width:10px;height:1px;background:var(--abi-amber)}

body.abi-site .abi-opcta{padding-top:0}
/* This was a grey box on a white page held together by a 3px amber rule --
   a line at 2.4:1 on its own ground, asked to carry the end of the posting
   on its own. The block carries itself now. Brand blue is the one ground on
   the page that is not white, so the panel reads as a panel with no rule
   drawn around it, and the button inverts to white instead of competing
   with a background it used to match. */
body.abi-site .abi-opcta__in{
  background:var(--abi-brand);
  padding:clamp(34px,3.8vw,56px) clamp(28px,3.2vw,48px)}
body.abi-site .abi-opcta__in .abi-d4{margin:0;color:#fff}
body.abi-site .abi-opcta__in .abi-bdy{margin:14px 0 0;max-width:58ch;color:#dbe4f5}
body.abi-site .abi-opcta .abi-opapply{background:#fff;color:var(--abi-brand)}
body.abi-site .abi-opcta .abi-opapply:hover{background:var(--abi-brand05);color:var(--abi-brand7)}

/* the careers form is the target of every Apply link */
body.abi-site #apply{scroll-margin-top:calc(var(--abi-hdr-h) + clamp(12px,2vh,28px))}

/* -------------------------------------------------------------
   53. About -- core values, three parts
   The client copy for each value arrives as a title, a short
   declarative line and a paragraph, where the old copy was a title
   and one line. The declarative line is the strongest writing of the
   three, so it leads in body size and medium weight and the detail
   sits under it at supporting size. Both steps are set here because
   the cell carries a 32px flex gap meant for two children, not four.
   ------------------------------------------------------------- */
.abi-val__lead{margin-top:calc(12px - clamp(18px,2vw,32px))}
/* :where(p) carries no specificity, which is right for the measures in
   section 35 where nothing competes, and wrong here: the lead line has to
   outrank the body colour and weight it inherits from .abi-bdy, so the
   element selector earns its point. */
body.abi-site .abi-val__lead p{font-weight:600;color:var(--abi-ink);max-width:32em}
body.abi-site .abi-val__lead ~ .abi-sm{margin-top:calc(14px - clamp(18px,2vw,32px))}
