/* ================= CROSS-BROWSER / RESPONSIVE FOUNDATION =====================
   Design-preserving. Fixes the causes of Mac-vs-Windows drift, not the symptoms.

   ROOT CAUSE 1 — viewport units include the scrollbar.
     Mac uses overlay scrollbars, so 100vw == the content width and the
     full-bleed trick (width:var(--vw,100vw); margin-left:calc(var(--vw,100vw) / -2)) lines up perfectly.
     Windows/Chrome/Edge/Firefox reserve ~15-17px for a classic scrollbar, so
     100vw is WIDER than the content box: every full-bleed block overhangs,
     a horizontal scrollbar appears and the whole page shifts. --sbw is measured
     once by JS (0 on Mac, ~15px on Windows) and every viewport-width dependency
     is corrected by it, so both platforms resolve to the same composition.

   ROOT CAUSE 2 — stale layout measurements.
     GSAP pins and the stacked scroll measure on init. Web fonts and large
     images land later (and later still on Windows), so the numbers go stale.
     Handled in JS below with refreshes on font-ready, load and resize.
   ------------------------------------------------------------------------- */
:root{--sbw:0px;--vw:calc(100vw - var(--sbw))}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
img,svg,video,canvas{max-width:100%}
/* ---- v60: intrinsic-size guard -------------------------------------------
   Every <img> below now carries width/height attributes so the browser can
   reserve the box before the file arrives — that is what stops the page
   jumping as images load. But `img{max-width:100%}` combined with width/height
   attributes and NO height rule SQUASHES an image the moment it is constrained
   (it keeps the attribute height while the width shrinks). This one low-
   specificity declaration restores the aspect ratio. It is (0,0,1), so every
   class-scoped height rule on the site still wins. */
img{height:auto}

button,input,select,textarea{font-family:inherit}

/* full-bleed blocks: same result on both platforms */
#about-view #lm-04,
#about-view #lm-02 .vms-wrap{width:var(--vw);margin-left:calc(var(--vw) / -2);margin-right:calc(var(--vw) / -2)}
#about-view .tlc-stage{width:var(--vw)}
.eqc-stage{width:var(--vw);flex:0 0 var(--vw)}
.nav-dd{max-width:calc(var(--vw) - 32px)}
/* carousel centring padding was half-a-scrollbar out on Windows */
.film-track{padding-left:calc(var(--vw) / 2 - 220px);padding-right:calc(var(--vw) / 2 - 220px)}
@media(max-width:760px){
  .film-track{padding-left:calc(var(--vw) / 2 - 150px);padding-right:calc(var(--vw) / 2 - 150px)}
}

/* nav: never let the pill wrap, and keep the full bar on Windows laptops that
   run 125% scaling (1536 physical -> 1229 CSS px, which used to fall under the
   1280 cutoff and drop the whole centre nav to a hamburger) */
.center-cap{flex-wrap:nowrap}
.center-cap a{white-space:nowrap}
@media(min-width:1181px) and (max-width:1280px){
  .center-cap{display:flex}
  .center-cap a{padding:10px clamp(6px,.62vw,11px);font-size:clamp(10.6px,.85vw,12.2px)}
}

/* short laptops (768 / 864 tall) — trim vertical rhythm, keep the composition */
@media(min-width:1081px) and (max-height:800px){
  .sl-stage .sl-in{padding-top:clamp(64px,9vh,96px);padding-bottom:clamp(48px,7vh,80px)}
}

/* mobile: address-bar-safe hero heights (the desktop stack is untouched) */
@media(max-width:760px){
  @supports(height:100svh){
    .lm-hero,.sl-stage{min-height:100svh}
  }
}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
}

/* ---- tap-to-enlarge imagery (sustainability pages) ------------------------
   Not full screen — the picture grows to a comfortable reading size, centred,
   over a soft scrim. Click anywhere, press Escape or scroll to put it back. */
.sz-scrim{position:fixed;inset:0;background:#0b0c0a;opacity:0;z-index:9998;
  pointer-events:none;will-change:opacity}
.sz-scrim.on{pointer-events:auto}
.sz-clone{position:fixed;z-index:9999;margin:0;object-fit:cover;will-change:transform,width,height;
  box-shadow:0 40px 90px -40px rgba(0,0,0,.55);cursor:zoom-out}
body.sz-open{cursor:zoom-out}
.sus-overview main img,.sus-explore main img,
.sus-overview section img,.sus-explore section img{cursor:zoom-in}
@media(prefers-reduced-motion:reduce){
  .sz-scrim,.sz-clone{transition:none !important}
}

/* ============================================================
   PERSPECTIVE ROTATE MENU
   Final block. Declares no section margins — seam-continuity safe.

   THREE ADAPTATIONS to this codebase, each with a reason:
   · the nav stays position:fixed at rest and only becomes absolute
     (pinned at the frozen scroll offset) WHILE open. Switching it to
     sticky as the pattern suggests would put it back in flow and push
     every page down by its height, which the 100vh stacked sections
     and the seam maths cannot absorb.
   · the shell uses overflow:clip, not hidden, while open. hidden makes
     a scroll container and would break every position:sticky section
     (the whole stacked architecture and the equipment carousel).
   · no pinType change: this site has zero ScrollTrigger pins, so the
     pin problem the pattern warns about does not exist here.
   ============================================================ */
:root{
  --rot-dur:.82s;
  --rot-ease:cubic-bezier(.16,1,.3,1);
  --rot-angle:-34deg;
  --rot-depth:-420px;   /* deeper than the reference values: at -320px the card
                           is wide enough to sit under the menu at every common
                           desktop width (checked 1280-2560) */
  --rot-shift:-2%;
  --rot-persp:1400px;
}

#rot-inner{transition:transform 0s}
#rot-shell{
  position:relative;z-index:1;background:#fff;
  transform-origin:100% 50%;
  transition:transform var(--rot-dur) var(--rot-ease),
             border-radius var(--rot-dur) var(--rot-ease),
             box-shadow var(--rot-dur) var(--rot-ease);
}
/* ---- open state -------------------------------------------------------
   GEOMETRY FIX: #rot-shell wraps the entire document, so rotating it about
   "50%" pivots around the middle of a page that is many screens tall — the
   visible part swings clean out of frame. While open the shell becomes a
   VIEWPORT-SIZED card (position:fixed; inset:0) and #rot-inner is shifted up
   by the frozen scroll offset so the same content stays on screen. Now the
   pivot really is the right edge of the screen, and perspective 1400px with
   translateZ(-320px) scales it to ~0.81 — the inset card in the reference. */
body.rot-open{
  height:100vh;                      /* viewport-sized box, so perspective-origin
                                        resolves against the screen, not the page */
  overflow:hidden;
  padding-right:var(--sbw,0px);
  perspective:var(--rot-persp);
  perspective-origin:100% 50%;
}
html.rot-lock{overflow:hidden}

body.rot-open #rot-shell{
  position:fixed;inset:0;            /* the card */
  transform-origin:100% 50%;
  transform:translateZ(var(--rot-depth)) rotateY(var(--rot-angle)) translateX(var(--rot-shift));
  border-radius:18px;
  overflow:clip;                     /* clip, NOT hidden — keeps sticky alive */
  box-shadow:-44px 0 96px rgba(0,0,0,.46);
  cursor:pointer;
  will-change:transform;
}
/* hold the same content on screen that was there before the card formed */
body.rot-open #rot-inner{transform:translateY(calc(-1 * var(--rot-scroll,0px)))}
/* the fixed navbar is inside the shifted inner, so pin it at the frozen offset */
body.rot-open .nav{position:absolute;top:var(--rot-scroll,0px)}

/* the swing-back keeps the card geometry until it finishes, so the shell never
   pivots against the full-document box mid-transition */
body.rot-closing #rot-shell{position:fixed;inset:0;overflow:clip;border-radius:18px;
  transform-origin:100% 50%}
body.rot-closing #rot-inner{transform:translateY(calc(-1 * var(--rot-scroll,0px)))}
body.rot-closing .nav{position:absolute;top:var(--rot-scroll,0px)}
/* other fixed widgets have their own offsets and would jump — park them */
body.rot-open #lmnav,
body.rot-open .eqc-glowctl{visibility:hidden}
/* the legacy overlay menu is replaced by this one */
body.rot-open .menu{display:none}

/* ---- backdrop ------------------------------------------------------------
   The warm light used to sit at 88%/6% — directly BEHIND the rotated card —
   and a second at 4%/92%, below the list. Both were invisible where you
   actually look, so the field read as flat black. The key light now sits
   behind the MENU COLUMN, the base is the brand warm-black rather than pure
   black, a vignette gives the field edges, and a fine grain stops a large
   dark area reading as a hole. */
.rot-bg{
  position:fixed;inset:0;z-index:0;pointer-events:none;
  /* v127 FIX — the whole `background` shorthand was being DROPPED by the parser,
     so the backdrop painted nothing and the panel's white labels sat on the
     white page. Cause: `radial-gradient(min(78%,900px) min(66%,620px) ...)`.
     A radial-gradient SIZE cannot mix % and px inside a math function — it is
     not resolvable at parse time, so the layer is invalid, and one invalid
     layer invalidates the entire shorthand INCLUDING the #0f0e0c base.
     (min() in the gradient POSITION is fine and is kept.)
     Two changes: the size is now plain percentages (62.5% x 66% reproduces the
     capped ellipse exactly at the 1440 design width), and the base colour is
     split into its own `background-color` longhand so no future bad image
     layer can ever take the black down with it again. */
  background-color:#0f0e0c;
  background-image:
    radial-gradient(120% 100% at 50% 45%,transparent 40%,rgba(0,0,0,.5) 100%),
    radial-gradient(62.5% 66% at min(24%,300px) 36%,rgba(233,85,10,.20),transparent 62%),
    radial-gradient(60% 55% at 82% 88%,rgba(168,96,48,.13),transparent 64%);
  opacity:0;visibility:hidden;
  transition:opacity .55s var(--rot-ease),visibility 0s .55s;
}
/* grain: greyscale fractal noise, tiled, barely there */
.rot-bg::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  background-size:170px 170px;
  opacity:.05;
}
body.rot-open .rot-bg{opacity:1;visibility:visible;transition:opacity .5s var(--rot-ease),visibility 0s 0s}

.rot-menu{
  position:fixed;inset:0;z-index:2;pointer-events:none;
  visibility:hidden;transition:visibility 0s var(--rot-dur);
}
.rot-menu.is-open{visibility:visible;transition:visibility 0s 0s}
.rot-menu.is-open .rot-panel,.rot-menu.is-open .rot-x{pointer-events:auto}

.rot-panel{
  position:absolute;left:0;top:0;bottom:0;width:min(32%,400px);
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(80px,12vh,120px) clamp(20px,2.6vw,44px) 40px;
}
.rot-x{
  position:absolute;top:18px;left:clamp(20px,2.6vw,44px);
  width:44px;height:44px;border-radius:50%;
  border:1px solid rgba(255,255,255,.14);background:none;color:#fff;
  font-size:17px;line-height:1;cursor:pointer;display:grid;place-content:center;
  opacity:0;transition:opacity .4s var(--rot-ease) .3s,background .25s var(--rot-ease),
    border-color .25s var(--rot-ease),transform .3s var(--rot-ease);
}
.rot-menu.is-open .rot-x{opacity:1}
.rot-x:hover{background:#E9550A;border-color:#E9550A;transform:rotate(90deg)}

/* the panel takes focus silently so no ring is painted on open */
.rot-panel:focus{outline:none}

/* ---- the list ----------------------------------------------------------
   Reworked for rhythm rather than size (the panel width caps the type):
   hairline rules give the eight items a measured beat, the numbers recede
   into a proper mono column, the labels sit tighter and darker at rest so
   the hovered one genuinely stands out, and an orange marker rises at the
   left edge instead of turning the whole label orange. */
.rot-list{list-style:none;margin:0;padding:0;border-top:1px solid rgba(255,255,255,.08)}
.rot-row{border-bottom:1px solid rgba(255,255,255,.08);
  opacity:0;transform:translateX(-26px);
  transition:opacity .5s var(--rot-ease),transform .6s var(--rot-ease)}
.rot-menu.is-open .rot-row{opacity:1;transform:none;transition-delay:calc(.05s * var(--i) + .22s)}
.rot-row a{position:relative;display:flex;align-items:baseline;gap:12px;
  padding:clamp(10px,1.6vh,18px) 0;text-decoration:none}
.rot-row a::before{content:"";position:absolute;left:-14px;top:16%;bottom:16%;width:2px;
  border-radius:2px;background:#E9550A;transform:scaleY(0);transform-origin:50% 100%;
  transition:transform .34s var(--rot-ease)}
.rot-row a:hover::before,.rot-row a:focus-visible::before{transform:scaleY(1)}
.rot-row span{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:9.5px;letter-spacing:.2em;
  color:rgba(255,255,255,.32);width:20px;flex:none;font-variant-numeric:tabular-nums;
  transition:color .25s var(--rot-ease)}
.rot-row b{font-family:'Bricolage Grotesque',Arial,sans-serif;
  font-size:clamp(16px,2.6vw,31px);line-height:1.04;letter-spacing:-.035em;font-weight:600;
  color:rgba(255,255,255,.6);white-space:nowrap;
  transition:color .25s var(--rot-ease),transform .35s var(--rot-ease)}
.rot-row a:hover b,.rot-row a:focus-visible b{color:#fff;transform:translateX(5px)}
.rot-row a:hover span,.rot-row a:focus-visible span{color:#E9550A}

.rot-x:focus-visible,.rot-row a:focus-visible{outline:2px solid #E9550A;outline-offset:4px;border-radius:4px}

@media(max-width:900px){
  :root{--rot-angle:-30deg;--rot-depth:-520px;--rot-shift:26%;--rot-persp:1400px}
  /* no room for both on a phone, so the card slides right like a drawer */
  .rot-panel{width:54%}
  .rot-row b{font-size:clamp(20px,5.4vw,28px)}
}
@media(max-width:560px){
  :root{--rot-angle:-26deg;--rot-depth:-560px;--rot-shift:30%}
  /* phone: a wider panel with tighter gutters so the longest label still fits */
  .rot-panel{width:60%;padding-left:16px;padding-right:14px}
  .rot-x{left:22px}
}
body.rot-open.rot-flat{perspective:none}
body.rot-open.rot-flat #rot-shell{transform:none;border-radius:0;box-shadow:none;opacity:.28;
  transition:opacity .45s var(--rot-ease)}
@media(prefers-reduced-motion:reduce){
  #rot-shell,.rot-row,.rot-x,.rot-bg{transition-duration:.01ms!important}
  body.rot-open #rot-shell{transform:none;opacity:.25;box-shadow:none}
}

/* About: land the heading clear of the fixed navbar */
#about{scroll-margin-top:0px}
#products{scroll-margin-top:34px}
#about.ab{padding-top:clamp(60px,7vh,96px)}
/* Industries: drop the "INDUSTRIES · 01 / 04" tag and the bottom numerals */
.ip-tag{display:none}
.ip-nav-item .nn{display:none}
/* Products: drop the 01-05 numerals above the cards */
.film-num{display:none}

/* v43: about-view idle nav links were still white on the white cap */
#about-view .center-cap a{color:var(--ink);opacity:.78}
/* v43: tighter blob morph so it does not bridge two menu items */
.center-cap .blob,#about-view .center-cap .blob{transition:transform .34s cubic-bezier(.3,.7,.2,1),width .34s cubic-bezier(.3,.7,.2,1),opacity .3s ease}
/* v43: the page card glides between sections while previewing from the menu */
body.rot-open.rot-preview #rot-inner{transition:transform .65s cubic-bezier(.22,.9,.28,1)}

/* v43: the pinned nav rides the same variable as the card — give it the
   same glide so it moves WITH the preview instead of jumping ahead */
body.rot-open.rot-preview .nav{transition:top .65s cubic-bezier(.22,.9,.28,1)}

/* ============ WHATSAPP FLOATING BUTTON =================================
   Fixed bottom-left on every page. Markup + CSS only — no JavaScript.

   MOUNTED INSIDE #rot-inner, NOT at body level. #rot-shell{z-index:1} is a
   stacking context, so a body-level button would paint above EVERYTHING
   inside the shell — including the fullscreen company-overview video and
   its scrim (.au-cine-scrim, z 9998, mounted into #rot-inner by v43). This
   is the same trap v43 documented. Living inside the shell makes it layer
   with the page it belongs to.

   z-index 85 is chosen against the overlay ladder, not picked round:
     60  .eqc-glowctl / 3D back button
     85  .wa-fab          <-- above all ordinary page content
     90  .pr-cine, #lmnav, .eqc-cine       (cinematics cover it)
     100 .menu            (legacy overlay covers it)
     120 .nav             (never covers navigation)
     9998+ .au-cine-scrim (fullscreen video covers it)
   On equipment.html .eqc-cine mounts to document.body at z 90, which beats
   the whole shell at root z 1, so that cinematic covers it there too.

   Bottom-left was empty: every other fixed widget on this site anchors
   bottom-RIGHT (#lmtoggle 20/20, .eqc-glowctl 12/12) or centre. */
.wa-fab{
  position:fixed;left:22px;bottom:22px;z-index:85;
  display:flex;align-items:center;justify-content:center;
  width:58px;height:58px;border-radius:50%;
  background:#25D366;color:#fff;
  text-decoration:none;border:0;
  -webkit-tap-highlight-color:transparent;
  box-shadow:0 6px 20px rgba(0,0,0,.28),0 2px 6px rgba(0,0,0,.18);
  transition:transform .24s cubic-bezier(.3,.7,.2,1),box-shadow .24s ease;
}
.wa-fab svg{width:28px;height:28px;display:block;flex:none}
@media (hover:hover){
  .wa-fab:hover{transform:translateY(-3px) scale(1.04);box-shadow:0 12px 30px rgba(0,0,0,.34)}
}
.wa-fab:focus-visible{outline:2px solid #E9550A;outline-offset:3px}
/* Deterministic while the rotate menu is open. Inside a transformed
   #rot-inner a fixed child resolves against the shell box and would drift
   off-screen anyway — this makes the outcome explicit rather than emergent,
   and matches how #lmnav and .eqc-glowctl are already parked. */
body.rot-open .wa-fab,body.rot-closing .wa-fab{visibility:hidden}
@media (max-width:760px){
  .wa-fab{left:16px;bottom:16px;width:54px;height:54px}
  .wa-fab svg{width:26px;height:26px}
}
@media (prefers-reduced-motion:reduce){
  .wa-fab{transition:none}
  .wa-fab:hover{transform:none}
}

/* ---- rotate-menu backdrop: independent reveal hooks ----------------------
   Observed on the live site: the menu panel was OPEN and hoverable (the status
   bar showed a menu link URL, and pointer-events:auto comes ONLY from
   .rot-menu.is-open) while .rot-bg stayed hidden. With the backdrop absent the
   white page showed through, and the panel's white labels became invisible.
   The backdrop was keyed solely off body.rot-open, so if that one class ever
   goes missing while the panel is open, the menu is unreadable.
   Fixed by keying the reveal off two MORE signals that open() sets in the same
   breath — html.rot-lock (universally supported) and the very class that grants
   the panel its pointer-events. Any one of the three now reveals it, so the
   panel and its backdrop cannot desynchronise. No visual change when the
   existing rule already works. */
html.rot-lock .rot-bg{opacity:1;visibility:visible}
body:has(.rot-menu.is-open) .rot-bg{opacity:1;visibility:visible}

/* ============ FOOTER v57 — light, map-led =================================
   Every rule is scoped .ft.ftx (specificity 0,2,0) so it beats the legacy
   `.ft` rules (0,1,0) regardless of where this block lands in the cascade.
   That is what lets it live in <head> instead of last-before-</body>, which
   is the FOUC trap from v50. The seam rule `.ft{margin-top:calc(-100vh - 1px)}`
   is deliberately NOT redeclared here — the stacked-section seam still owns it.
   New children use the .ftx-* namespace, which no legacy rule targets. */
.ft.ftx{
  background:#fbfbfa;color:#3f3d3a;padding:0;overflow:hidden;
  border-top:1px solid rgba(15,14,12,.08);
  /* ---- v59: cover the whole band the footer is pulled into ----------------
     .ft carries margin-top:calc(-100vh - 1px) so it rises over the empty tail
     of #sustain's 300vh scaffold (its sticky panel has already been released
     by then). That only works while the footer is AT LEAST as tall as the band
     it covers. The new light footer is shorter than the old dark one, so the
     last stretch of that scaffold was left showing underneath it — the dark
     strip with a sliver of the sustainability image below the legal bar.
     Filling the band costs no extra scrolling: the 100vh already exists in the
     document either way. The extra space goes ABOVE the content so the legal
     bar still sits flush at the very bottom of the page. */
  min-height:calc(100vh + 1px);
  display:flex;flex-direction:column;justify-content:flex-end;
}
.ftx-wrap{max-width:1440px;margin:0 auto;padding:0 clamp(20px,3.6vw,54px)}

/* ---- top band ---- */
.ftx-top{
  display:grid;grid-template-columns:1.15fr .72fr .95fr .82fr 1.45fr;
  gap:clamp(20px,2.6vw,42px);
  padding:clamp(40px,5vw,66px) 0 clamp(34px,4vw,52px);
}
.ftx-logo{display:block;width:clamp(150px,13vw,196px);height:auto;margin:0 0 22px}
.ftx-tag{
  font:500 12px/1 var(--mono,'IBM Plex Mono',monospace);letter-spacing:.2em;
  text-transform:uppercase;color:#0f0e0c;margin:0 0 18px;
}
.ftx-tag i{font-style:normal;color:#E9550A}
.ftx-blurb{
  font:400 14.5px/1.75 var(--disp,'Bricolage Grotesque',Arial,sans-serif);
  color:#5d5a55;max-width:34ch;margin:0 0 24px;
}
.ftx-soc{display:flex;gap:12px}
.ftx-soc a{
  width:44px;height:44px;border-radius:50%;display:grid;place-items:center;
  border:1px solid rgba(233,85,10,.32);color:#E9550A;text-decoration:none;
  transition:background .22s,border-color .22s,color .22s,transform .22s;
}
.ftx-soc a:hover{background:#E9550A;border-color:#E9550A;color:#fff;transform:translateY(-2px)}
.ftx-soc svg{width:18px;height:18px;display:block}

.ftx-h{
  display:flex;align-items:center;gap:9px;margin:0 0 6px;
  font:500 11.5px/1 var(--mono,'IBM Plex Mono',monospace);letter-spacing:.16em;
  text-transform:uppercase;color:#0f0e0c;
}
.ftx-h::before{content:"";width:6px;height:6px;border-radius:50%;background:#E9550A;flex:none}
.ftx-rule{width:34px;height:2px;background:#E9550A;opacity:.55;margin:0 0 22px}
.ftx-list{list-style:none;margin:0;padding:0}
.ftx-list li{margin:0 0 15px}
.ftx-list a{
  font:400 14px/1.4 var(--disp,'Bricolage Grotesque',Arial,sans-serif);
  color:#5d5a55;text-decoration:none;display:inline-block;
  transition:color .2s,transform .2s;
}
.ftx-list a:hover{color:#E9550A;transform:translateX(3px)}

/* ---- world map ---- */
.ftx-map{position:relative;align-self:center}
/* v140: pins are positioned against THIS box, not .ftx-map — .ftx-map also
   contains the caption below the image, so percentages resolved against it
   landed the pins ~3.5% too low (the same trap as the Palej pin in v135). */
.ftx-mapin{position:relative;display:block}
.ftx-map img{width:100%;height:auto;display:block}
.ftx-pin{
  position:absolute;width:9px;height:9px;border-radius:50%;background:#E9550A;
  transform:translate(-50%,-50%);
}
.ftx-pin::after{
  content:attr(data-n);position:absolute;left:50%;top:-8px;transform:translate(-50%,-100%);
  background:#0f0e0c;color:#fff;white-space:nowrap;
  font:500 10px/1 var(--mono,'IBM Plex Mono',monospace);letter-spacing:.1em;
  padding:6px 9px;border-radius:6px;opacity:0;pointer-events:none;transition:opacity .2s;
}
.ftx-pin:hover::after{opacity:1}
.ftx-pin--hq{width:13px;height:13px}
/* v140: the pulse ring moved from .ftx-pin--hq to EVERY pin — V wants all
   five markets pulsating. --hq stays as the larger dot for the plant.
   transform-box/origin are not needed here (a normal element scales about
   its own centre), but the ring must be centred with negative margins
   because ::before is positioned from the pin's top-left. */
.ftx-pin::before{
  content:"";position:absolute;left:50%;top:50%;width:9px;height:9px;
  margin:-4.5px 0 0 -4.5px;border-radius:50%;border:1.5px solid #E9550A;
  animation:ftxPulse 2.6s ease-out infinite;
}
.ftx-pin--hq::before{
  width:13px;height:13px;margin:-6.5px 0 0 -6.5px;
}
@keyframes ftxPulse{
  0%{transform:scale(1);opacity:.75}
  100%{transform:scale(3.4);opacity:0}
}
@media (prefers-reduced-motion:reduce){
  .ftx-pin::before{animation:none;transform:scale(2.1);opacity:.35}
}
.ftx-mapcap{
  margin:14px 0 0;text-align:right;
  font:500 10.5px/1 var(--mono,'IBM Plex Mono',monospace);letter-spacing:.16em;
  text-transform:uppercase;color:#8a867f;
}

/* ---- contact strip ---- */
.ftx-strip{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(212px,1fr));
  border-top:1px solid rgba(233,85,10,.34);
}
.ftx-cell{
  display:flex;gap:16px;align-items:flex-start;
  padding:clamp(24px,2.8vw,34px) clamp(14px,2vw,30px);
  border-left:1px solid rgba(15,14,12,.09);
}
.ftx-cell:first-child{border-left:0;padding-left:0}
.ftx-ico{
  width:52px;height:52px;border-radius:50%;flex:none;display:grid;place-items:center;
  border:1px solid rgba(233,85,10,.30);color:#E9550A;
}
.ftx-ico svg{width:21px;height:21px;display:block}
.ftx-cell h4{
  font:500 11px/1 var(--mono,'IBM Plex Mono',monospace);letter-spacing:.16em;
  text-transform:uppercase;color:#E9550A;margin:5px 0 9px;
}
.ftx-cell p{
  font:400 14px/1.6 var(--disp,'Bricolage Grotesque',Arial,sans-serif);
  color:#3f3d3a;margin:0;
}
.ftx-cell a{color:#3f3d3a;text-decoration:none;transition:color .2s}
.ftx-cell a:hover{color:#E9550A}

/* ---- bottom bar ---- */
.ftx-base{
  border-top:1px solid rgba(15,14,12,.10);
  display:flex;flex-wrap:wrap;gap:10px 26px;align-items:center;justify-content:space-between;
  padding:20px 0 24px;
}
.ftx-copy{
  font:400 13px/1.7 var(--disp,'Bricolage Grotesque',Arial,sans-serif);color:#5d5a55;margin:0;
}
.ftx-reg{
  display:block;font:400 11px/1.6 var(--mono,'IBM Plex Mono',monospace);
  letter-spacing:.06em;color:#8a867f;
}
.ftx-legal{display:flex;flex-wrap:wrap;align-items:center;gap:12px 18px}
.ftx-legal a{
  font:400 13px/1 var(--disp,'Bricolage Grotesque',Arial,sans-serif);
  color:#5d5a55;text-decoration:none;transition:color .2s;
}
.ftx-legal a:hover{color:#E9550A}
.ftx-legal span{color:rgba(15,14,12,.22)}

/* ---- responsive ---- */
@media (max-width:1180px){
  .ft.ftx .ftx-top{grid-template-columns:1.2fr .9fr 1.1fr .9fr}
  .ft.ftx .ftx-map{grid-column:1 / -1;max-width:720px;margin:8px auto 0}
  .ft.ftx .ftx-mapcap{text-align:center}
}
@media (max-width:900px){
  .ft.ftx .ftx-top{grid-template-columns:1fr 1fr;gap:32px}
  .ft.ftx .ftx-strip{grid-template-columns:1fr 1fr}
  .ft.ftx .ftx-cell{border-left:0;border-top:1px solid rgba(15,14,12,.09);padding-left:0}
  .ft.ftx .ftx-cell:nth-child(-n+2){border-top:0}
}
@media (max-width:600px){
  .ft.ftx .ftx-top{grid-template-columns:1fr}
  .ft.ftx .ftx-strip{grid-template-columns:1fr}
  .ft.ftx .ftx-cell{border-top:1px solid rgba(15,14,12,.09)}
  .ft.ftx .ftx-cell:first-child{border-top:0}
  .ft.ftx .ftx-base{flex-direction:column;align-items:flex-start}
}
