/* ==========================================================================
   #services — ASA list with "+" accordions (spec §2.4)

   Values measured from reference/asa/list.css. ASA is Tailwind with
   --spacing:.25rem on a 16px root, so the utility names in
   reference/asa/list.skeleton.txt convert as:

     py-16  -> padding-block: 64px      pb-2    -> padding-bottom: 8px
     mt-10  -> margin-top: 40px         gap-y-1 -> row-gap: 4px
     gap-2  -> gap: 8px                 space-y-8 -> 32px between groups
     .body-s     -> 14px / 1.4          .heading-4 -> 28px / 1.25
     .subtitle-m -> 16px / 1.4          .heading-5 -> 22px / 1.4
     text-b20/b40/b60 -> 20/40/60% ink; ASA's ink is black, ours is --slate,
     so #0003 -> rgba(48,38,32,.2) and so on.
     hover:opacity-40 + transition-opacity -> opacity .15s cubic-bezier(.4,0,.2,1)
     (ASA's default transition duration/easing).

   Side padding comes from .container (Senawa, 140/80/40/24 by breakpoint);
   only the block padding is ours.
   ========================================================================== */

.svc {
  background: var(--wool);
  padding-block: clamp(72px, 12vh, 150px);
}

/* ASA's py-16 pb-2 label block. The FIRST group loses its top padding: ASA's
   list starts under a fixed header, ours starts under the hero. */
.svc-label-wrap { padding: 64px 0 8px }
.svc-group:first-of-type .svc-label-wrap { padding-top: 0 }

.svc-label {
  font: 400 14px/1.4 var(--font-body);
  color: rgba(48, 38, 32, .4);
}

/* mt-10 off the label, gap-y-1 between rows */
.svc-list {
  margin-top: 40px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* space-y-8 */
.svc-group + .svc-group { margin-top: 32px }

/* ------------------------------------------------------------------ ROW -- */
.svc-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  color: var(--slate);
  transition: opacity .15s cubic-bezier(.4, 0, .2, 1);
}
.svc-row:hover { opacity: .4 }
/* an open row stays at full strength — dimming the header of the panel you
   are reading is the one place ASA's hover does not translate */
.svc-row[aria-expanded="true"]:hover { opacity: 1 }
.svc-row:focus-visible { outline: 2px solid; outline-offset: 3px }

.svc-title { font: 400 28px/1.25 var(--font-display) }

/* ASA's "(count)" slot */
.svc-plus {
  font: 300 16px/1.4 var(--font-body);
  color: rgba(48, 38, 32, .2);
  display: inline-block;
  transition: transform .4s var(--ease-out), color .15s cubic-bezier(.4, 0, .2, 1);
}
.svc-row[aria-expanded="true"] .svc-plus {
  transform: rotate(45deg);
  color: rgba(48, 38, 32, .6);
}

/* ---------------------------------------------------------------- PANEL -- */
/* 0fr -> 1fr grid row: the only height animation that needs no measuring.
   All padding lives on .svc-panel-content so the collapsed box is truly 0. */
.svc-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .5s var(--ease-out);
}
.svc-panel.is-open { grid-template-rows: 1fr }
.svc-panel-inner { overflow: hidden; min-height: 0 }
.svc-panel-inner > * { max-width: 560px }
.svc-panel-content { padding: 12px 0 28px }

/* Senawa's overview body */
.svc-lead {
  font: 300 clamp(.9375rem, 1vw, 1.0625rem)/1.75 var(--font-display);
  color: var(--slate);
}

.svc-points {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font: 300 13px/1.6 var(--font-body);
  color: rgba(48, 38, 32, .6);
}
.svc-points strong { font-weight: 500; color: var(--slate) }

/* --------------------------------------------------------------- MOBILE -- */
/* ASA drops heading-4 to heading-5 in its mobile menu; same move here. */
@media (max-width: 767px) {
  .svc-title { font-size: 22px; line-height: 1.4 }
}

@media (prefers-reduced-motion: reduce) {
  .svc-row, .svc-plus, .svc-panel { transition: none }
}


/* ==========================================================================
   ==========================================================================
   PART 2 — the /services/ PAGE (main.svc)

   Everything above this banner is the HOME page's ASA accordion section
   (`<section id="services" class="svc container">`). Everything below is the
   /services/ page, a replica of cominvi.com.mx/our-services. The two share
   this file only because they share the name `services` — the class `.svc`
   was already taken by the accordion, so every rule here is prefixed
   `main.svc` and the accordion's `.svc-*` rules cannot reach this page's
   reference class names. The one rule that WOULD have leaked is the bare
   `.svc { background; padding-block }` at the top of the file: `main.svc`
   below re-declares both, and a later, more specific rule wins.

   WHAT WAS VENDORED (spec docs/superpowers/specs/2026-09-23-services-cominvi.md)
   - §1 Osmo scaling system, verbatim from reference/cominvi/inline-styles.css
     block 2, scoped to `main.svc` the way blog.css §1 scopes Kalkbrenner's,
     with the same `max(12px, …)` floor (their breakpoints restart the clamp,
     so the raw scale troughs below 9px just above each breakpoint).
   - §3 every rule from reference/cominvi/services.css-extract.txt that
     touches this page, rule body for rule body, media queries kept. The
     `.button*`, `.is-arrow-square`, `.arrow-*`, `.scroll-tick*`,
     `.project-card*`, `.project-overlay*`, `.projects-overlay*`, `.content*`,
     `.is-col-*` and `.sr-only` rules are not in the extract and were grepped
     out of reference/cominvi/webflow.shared.css.
   - Webflow's `#w-node-…` grid-area rules become classes (same values; see
     `.hero-content_left`, `.hero-bottom_cards-wrapper`, `.processes_inner`).

   ADAPT (the only permitted deviations, all from the spec)
   - §1.2 palette: --primary → slate, --accent → clay (wool text on it),
     --light-green → linen, --gray → sand. --white stays white.
   - §1.3 type: Helvetica Now Display → Sora 600 (.h1/.body-xl/.body-l),
     Inter 400 for `.body-s` running copy, PP Supply Mono →
     JetBrains Mono 400 for the eyebrows.
   - §4.5 icons: their Lottie mining drawings → five inline SVG line icons.
   - §6 the sticky process video → ten cross-fading step photos
     (`.svc-step-img`).
   - `.button-sm_inner` uses the reference's <=991 value, `translate(-.7em)`,
     at EVERY width instead of its published base `translate(.2em)` — .2em
     renders the leading triangle and clips the trailing one, the inverse of
     their own recorded 1440 frame. Measured; see the rule in §3.
   - `.cards-wrapper` gets `overflow:hidden` and `align-items:flex-start`
     where the reference has neither/`flex-end`: their Swiper is always
     initialised, which measures the box; un-initialised (JS off, or before
     Task 3) the six cards are taller than the column, so flex-end cut off
     cards 1-3 and the stack spilled up over the previous section. Both
     revert once Swiper measures. @991 keeps their `flex-end`. (Full
     reasoning sits on the rule itself in §5.)
   - No `.marker*` / `.region*` rules exist in webflow.shared.css, because
     they live in the stylesheet their bundle INJECTS at runtime
     (reference/cominvi/main.pretty.js:19159, the `tg` string). §5 vendors
     that block's `.marker*`, `.region*`, `svg.is-map`, `.project-card`,
     `.project-item` and `.swiper.projects-wrapper` rules; the fills are ours
     (slate/clay, not their orange) and `.marker.dimmed` is .35 rather than
     their 0 — on an island this small a marker faded to nothing reads as
     "no project there".
   - §5 `.section_projects` loses the reference's `aspect-ratio:1440/1120`
     for `min-height:100svh` (plan Task 3 step 3): that ratio was measured
     against a near-square map of Mexico, and Roatán is a 1000x420 strip, so
     it left ~550px of empty slate under the island. `.map-wrapper` stays
     sticky, as the reference has it.
   - §5 `.island` is `--flax` at .9, not the spec's `#3a2f28`: that fill is
     1.13:1 on this section (measured), and unlike their outline-drawn map of
     Mexico our island is a plain silhouette, so the fill is the only thing
     carrying it. (Full reasoning sits on the rule itself in §5.)
   - §5 the stacked-slide rules from 768 up are gated on `.is-map-ready`
     (services.js sets it when Swiper initialises). Un-gated they hide all
     six project cards whenever the swiper never runs — JS off, a blocked
     vendor script, prefers-reduced-motion. The same gate is on the swiper
     wrapper's `overflow:hidden`, on `.projects-list.swiper-wrapper`'s row
     direction, on the `gap:0` that goes with it and on the 479 row: all four
     describe a list Swiper is translating, and without it they turned the
     column stack into six full-width cards side by side in a clipped box.
   - `.marker-hitbox` is sized in services.js, not here, and it is allowed to
     leave its marker: the three West Bay buttons are fanned out from the
     cluster centroid until each is 24x24 (WCAG 2.5.8) without overlapping
     its neighbour. Their flat 12px pad cannot do that on markers 13px apart.
   - `.marker-hitbox:focus-visible` gets a ring the reference kills with an
     inline `outline:none`. Those buttons are the only keyboard route to a
     marker, so they must show focus. It is the one rule in this file that
     is NOT scoped to main.svc — the buttons are appended to <body>.

   STATIC-FIRST: with JS off the page must be whole. Every state the intro
   animates FROM (`.card`, `.is-h1-span`, `.eyebrow-l`, `.service-image`)
   lives under `main.svc.js` — services.js adds `.js` to the <main> before it
   runs. §9 at the foot of this file.
   ========================================================================== */

/* ---------------------------------------------- 1. sizing, tokens, reset */
main.svc{
  --size-unit:16;
  --size-container-ideal:1440;
  --size-container-min:992px;
  --size-container-max:1920px;
  --size-container:clamp(var(--size-container-min),100vw,var(--size-container-max));
  --size-font:calc(var(--size-container) / (var(--size-container-ideal) / var(--size-unit)));

  --primary:var(--slate);
  --white:#fff;
  --accent:var(--clay);
  --accent-ink:var(--wool);
  --light-green:var(--linen);
  --gray:var(--sand);
  --site-margin:2em;
  --font-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --ease-card:cubic-bezier(.5,0,0,1);

  font-size:max(12px,var(--size-font));
  line-height:1;
  font-family:var(--font-display);
  font-weight:600;
  color:var(--primary);
  background:var(--white);
  display:block;
  padding-block:0;          /* undo the accordion's bare .svc rule, part 1 */
  overflow-x:clip;
}
@media screen and (max-width:991px){main.svc{--size-container-ideal:834;--size-container-min:768px;--size-container-max:991px}}
@media screen and (max-width:767px){main.svc{--size-container-ideal:550;--size-container-min:480px;--size-container-max:767px}}
@media screen and (max-width:479px){main.svc{--size-container-ideal:390;--size-container-min:320px;--size-container-max:479px}}

main.svc a{color:inherit;text-decoration:none}
main.svc button{padding:0;background:transparent;text-align:inherit;border:0;color:inherit;font:inherit;cursor:pointer}
main.svc svg{max-width:none;height:auto;vertical-align:middle}
main.svc svg:not(:root){overflow:hidden}
main.svc p,main.svc h1,main.svc h2,main.svc h3{margin:0}
main.svc .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ------------------------------------------------------------- 2. type */
main.svc .h1{font-size:unset;flex-flow:column;justify-content:center;align-items:flex-start;display:flex}
main.svc .is-h1-span-wrap{padding-bottom:.125em;overflow:hidden}
main.svc .is-h1-span{color:var(--white);font-size:3.5em;font-weight:600;line-height:110%;display:block}

main.svc .body-xl{color:var(--white);letter-spacing:-.0098em;font-size:3em;font-weight:600;line-height:100%;display:block}
main.svc .body-xl.is-black{color:var(--primary);display:block}
main.svc .body-xl.is-black.is-center{text-align:center}

main.svc .body-l{letter-spacing:-.025em;margin-bottom:0;font-size:2em;font-weight:600;line-height:1.1;transform:translate(0)}

main.svc .body-s{font-family:var(--font-body);font-size:1em;font-weight:400;line-height:1.2}
main.svc .body-s.is-grey{color:var(--gray)}
main.svc .body-s.is-white{color:var(--white)}
main.svc .body-s.is-white.is-o-50{opacity:.5}

main.svc .eyebrow-l{color:var(--white);text-transform:uppercase;font-family:var(--font-mono);font-size:.75em;font-weight:400;line-height:120%;display:block}
main.svc .eyebrow-l-alt{color:var(--white);text-transform:none;font-family:var(--font-body);font-size:.813em;font-weight:400;line-height:120%;display:block}
main.svc .eyebrow-l-alt.is-o-50{opacity:1}
main.svc .eyebrow-m{text-transform:uppercase;font-family:var(--font-mono);font-size:.75em;font-weight:400;line-height:1;display:block}
main.svc .eyebrow-m.o-60,main.svc .eyebrow-m.is-o-60{opacity:.6}
main.svc .eyebrow-s{text-transform:uppercase;font-family:var(--font-mono);font-size:.7em;font-weight:400;line-height:.9}

main.svc .eyebrows{grid-column-gap:.25em;grid-row-gap:.25em;float:left;flex-flow:column;justify-content:flex-start;align-items:flex-start;margin-right:1.725em;padding-top:.3em;display:flex}
main.svc .is-eyebrow{border:1px solid var(--primary);border-radius:.25em;justify-content:center;align-items:center;padding:.135em .25em .18em;display:flex}
main.svc .is-eyebrow.is-black{background-color:var(--primary)}
main.svc .is-eyebrow.is-black>.eyebrow-s{color:var(--white)}
main.svc .eyebrows.is-white .is-eyebrow{border-color:var(--white)}
main.svc .eyebrows.is-white .eyebrow-s{color:var(--white)}

@media screen and (max-width:991px){
  main.svc .body-xl,main.svc .body-xl.is-black{font-size:2em}
  main.svc .eyebrow-l{font-size:.638em}
  main.svc .eyebrow-l-alt{font-size:.638em}
  main.svc .eyebrow-s{font-size:.5em}
  main.svc .eyebrow-m{font-size:.75em}
  main.svc .body-l{font-size:1.5em}
  main.svc .body-s{font-size:.75em}
  main.svc .is-h1-span{font-size:2em}
  main.svc .is-eyebrow{padding:.1em .2em}
  main.svc .eyebrows{grid-column-gap:.125em;grid-row-gap:.125em;margin-right:1em;padding-top:.25em}
}
@media screen and (max-width:767px){
  main.svc .body-xl{font-size:2em}
  main.svc .body-s{font-size:16px}
  main.svc .eyebrow-m{font-size:.75em}
}

/* ------------------------------------------------------------- 3. hero */
main.svc .section_hero{width:100%;height:100vh;padding-right:var(--site-margin);padding-left:var(--site-margin);position:relative}
main.svc .hero-content{z-index:1;grid-column-gap:1em;grid-row-gap:1em;grid-template-rows:auto;grid-template-columns:repeat(12,1fr);grid-auto-columns:1fr;place-items:end stretch;width:100%;display:grid;position:relative;top:50%;transform:translateY(-50%)}
main.svc .hero-content_left{flex:1;grid-area:span 1/span 8/span 1/span 8}
main.svc .hero-content_right{grid-area:span 1/span 4/span 1/span 4;grid-column-gap:0em;grid-row-gap:0em;flex-flow:column;flex:1;justify-content:flex-start;align-items:flex-start;padding-bottom:.5em;display:flex}

main.svc .hero-bottom{left:var(--site-margin);top:auto;right:var(--site-margin);z-index:1;grid-template-rows:auto auto;grid-template-columns:1fr 1fr;grid-auto-columns:1fr;position:absolute;bottom:1.5em}
main.svc .hero-bottom_cards{order:0;grid-area:1/8/2/13;grid-column-gap:1em;grid-row-gap:1em;grid-template-rows:auto;grid-template-columns:repeat(12,1fr);grid-auto-columns:1fr;width:100%;display:grid}
main.svc .hero-bottom_cards-wrapper{grid-area:1/9/2/13;grid-column-gap:1em;grid-row-gap:1em;width:100%;display:flex}

main.svc .card{border:1px solid #fff3;border-radius:4px;flex:1;justify-content:center;align-items:flex-end;height:9em;padding:.5em;display:flex;position:relative;overflow:hidden}
main.svc .card_bg{object-fit:cover;width:100%;max-width:none;height:100%;position:absolute;inset:0%}
main.svc .button-sm{grid-column-gap:3px;grid-row-gap:3px;background-color:var(--white);text-transform:uppercase;border-radius:2px;justify-content:flex-start;align-items:center;width:100%;height:1.75em;padding:.25em;font-size:.75em;font-weight:600;display:flex;position:relative;overflow:hidden}
/* Their published base rule is `translate(.2em)`, but that renders the
   LEADING triangle and clips the trailing one to <1px — the inverse of
   reference/cominvi/rec-1440-top.png, where the label is flush-left and the
   triangle sits ~6px inside the right edge. Their own <=991 value, -.7em,
   reproduces the recorded frame to the pixel (leading arrow clipped by
   `.button-sm{overflow:hidden}`, trailing arrow inset 5.8px), so it is used
   at every width here. Measured, not guessed — see the task report. */
main.svc .button-sm_inner{grid-column-gap:4px;grid-row-gap:4px;justify-content:space-between;align-items:center;width:100%;display:flex;position:absolute;transform:translate(-.7em)}
main.svc .button-sm_inner-left{grid-column-gap:4px;grid-row-gap:4px;width:100%;display:flex;align-items:center}
main.svc .button-sm_label{font-family:var(--font-mono);font-size:.9em;font-weight:400}
main.svc .is-arrow{width:.5em;flex:none;color:var(--primary)}
main.svc .is-arrow.is-right{transform:rotate(0)}

main.svc .hero-background{z-index:0;flex-flow:column;justify-content:center;align-items:center;display:flex;position:absolute;inset:0%;overflow:hidden}
main.svc .hero-background .background-inner{flex-flow:column;justify-content:center;align-items:center;width:120%;height:120%;flex:0 0 auto;transform-origin:50% 50%;will-change:transform;backface-visibility:hidden;transform-style:preserve-3d;display:flex}
main.svc .background_image{object-fit:cover;width:100%;max-width:none;height:100%;display:block}
main.svc .background{object-fit:cover;width:100%;max-width:none;height:100%}

@media screen and (max-width:991px){
  main.svc .section_hero{height:100svh}
  main.svc .hero-content{grid-template-columns:repeat(8,1fr)}
  main.svc .hero-content_left,main.svc .hero-content_right{grid-column:span 4/span 4}
  main.svc .hero-content_right{padding-bottom:.25em}
  main.svc .hero-bottom{bottom:1em}
  main.svc .hero-bottom_cards{grid-template-columns:repeat(8,1fr)}
  main.svc .hero-bottom_cards-wrapper{grid-column:5/9;grid-column-gap:.5em;grid-row-gap:.5em}
  main.svc .card{height:7em}
  main.svc .button-sm_inner{transform:translate(-.7em)}   /* their @991 value; same as the base above */
}
@media screen and (max-width:767px){
  main.svc .section_hero{grid-column-gap:1em;grid-row-gap:1em;flex-flow:column;height:auto;min-height:100vh;padding:14.5em 1em 1em;display:flex}
  main.svc .hero-content{flex-flow:column;flex:1;place-items:start stretch;width:auto;height:100%;display:flex;position:relative;top:0;left:0;right:0;transform:translate(0)}
  main.svc .hero-content_right{flex:0 auto}
  main.svc .hero-bottom{position:relative;inset:0 0 0}
  main.svc .hero-bottom_cards{grid-template-columns:repeat(4,1fr)}
  main.svc .hero-bottom_cards-wrapper{grid-column-start:1}
  main.svc .card{height:9em}
}
@media screen and (max-width:479px){
  main.svc .section_hero{min-height:100dvh;padding-top:14.5em}
  main.svc .hero-content{display:flex}
  main.svc .card{height:6.5em}
  main.svc .hero-background{height:100%}
}

/* --------------------------------------------------------- 4. S.01 cards */
main.svc .section_services{width:100%;padding:var(--site-margin) var(--site-margin) 16em;grid-column-gap:16em;grid-row-gap:16em;background-color:var(--light-green);flex-flow:column;display:flex;position:relative}
main.svc .intro{grid-column-gap:16px;grid-row-gap:16px;width:100%;padding-right:21.688em;display:block}
main.svc .content{grid-column-gap:1em;grid-row-gap:1em;justify-content:space-between;align-items:stretch;display:flex}
main.svc .content.is-g{height:100%;min-height:0}
main.svc .is-grid-3{grid-column-gap:1em;grid-row-gap:1em;grid-template-rows:auto auto;grid-template-columns:1fr 1fr 1fr;grid-auto-columns:1fr;width:100%;display:grid}

main.svc .service-card{padding:var(--site-margin);aspect-ratio:1;background-color:var(--white);cursor:default;border-radius:.5em;flex-flow:column;justify-content:space-between;align-items:flex-start;display:flex;overflow:hidden;transition:background-color .8s var(--ease-card),color .8s var(--ease-card)}
main.svc .service-card.is-svc-hover{background-color:var(--accent);color:var(--accent-ink)}
main.svc .service-icon_icon{mix-blend-mode:multiply;width:3.5em}
main.svc .service-card.is-svc-hover .service-icon_icon{mix-blend-mode:normal}
main.svc .svc-icon{width:100%;height:auto;display:block}

/* Adapt (spec §4.5): their five Lottie mining drawings are five inline SVG
   line icons, and the two halves of the Lottie are two keyframes.
   AT REST THE ICON IS WHOLE — no `stroke-dasharray` outside the animation —
   so the page with JS off, or under 992, shows finished icons. `--svc-dash`
   is each path's own measured length (services.js `measureIcons`), so the
   draw runs edge to edge whatever the path; the 120 fallback only matters if
   getTotalLength() ever throws. The hover-out half is the second segment of
   their Lottie: one tilt that settles. Both are gated >=992, where the hover
   handlers are bound at all. */
@keyframes svc-icon-in{
  from{stroke-dasharray:var(--svc-dash,120);stroke-dashoffset:var(--svc-dash,120)}
  to{stroke-dasharray:var(--svc-dash,120);stroke-dashoffset:0}
}
@keyframes svc-icon-out{
  0%{transform:rotate(0)}
  50%{transform:rotate(6deg)}
  100%{transform:rotate(0)}
}
@media screen and (min-width:992px){
  main.svc .service-card.is-svc-hover .svc-icon path{animation:svc-icon-in .45s var(--ease-card) both}
  main.svc .service-card.is-svc-leave .svc-icon{animation:svc-icon-out .45s var(--ease-card);transform-origin:50% 50%}
}

/* `.line-inner` is created by services.js (their `_e`) around each split line;
   its transform/transition are inline, and this is only the belt-and-braces
   `display` a stylesheet can guarantee if the inline style is ever cleared. */
main.svc .desc .line-inner{display:inline-block}
main.svc .card-inner{grid-column-gap:1.15em;grid-row-gap:1.15em;flex-flow:column;justify-content:flex-start;align-items:flex-start;width:100%;display:flex}
main.svc .desc{width:100%}

main.svc .services-viewer{border-radius:.5em;justify-content:flex-end;align-items:flex-end;display:flex;position:relative;overflow:hidden}
main.svc .service-image{z-index:0;object-fit:cover;width:100%;height:100%;position:absolute;inset:0%}

main.svc .text-wrapper{grid-column-gap:6em;grid-row-gap:6em;justify-content:flex-start;align-items:center;padding-left:18.125em;padding-right:18.125em}

@media screen and (max-width:991px){
  main.svc .section_services{grid-column-gap:8em;grid-row-gap:8em;padding-bottom:8em}
  main.svc .intro{padding-right:0}
  main.svc .content{flex-flow:column}
  main.svc .service-icon_icon{width:2em}
  main.svc .text-wrapper{padding-left:11.525em;padding-right:11.525em}
}
/* The reference hides the viewer at EVERY width below 992 — its `T` bails on
   `(max-width:991px)` and never shows an image, and its own `.services-viewer
   {height:0}` only lands at 767. Between 768 and 991 that left a 448px empty
   white box in the grid. `display:none` takes it out of the flow instead, so
   the five cards close up; below 768 their `height:0` rule still applies. */
@media screen and (min-width:768px) and (max-width:991px){
  main.svc .services-viewer{display:none}
}
@media screen and (max-width:767px){
  main.svc .section_services{grid-column-gap:12em;grid-row-gap:12em;padding-bottom:12em}
  main.svc .intro{flex-flow:column;display:flex}
  main.svc .is-grid-3{grid-template-columns:1fr}
  main.svc .service-card{grid-column-gap:6.75em;grid-row-gap:6.75em;aspect-ratio:auto;flex-flow:row;padding-top:1.5em;padding-bottom:1.5em}
  main.svc .card-inner{gap:1em}
  main.svc .section_services .body-s{opacity:.5;font-weight:500}
  main.svc .services-viewer{height:0}
  main.svc .text-wrapper.is-about{padding-left:6em;padding-right:6em}
}
@media screen and (max-width:479px){
  main.svc .section_services{grid-column-gap:12em;grid-row-gap:12em;padding-top:1em;padding-bottom:12em}
  main.svc .service-card{grid-column-gap:2.8em;grid-row-gap:2.8em}
  main.svc .service-icon_icon{width:4em}
  main.svc .text-wrapper{padding-left:0;padding-right:0}
  main.svc .text-wrapper.is-about{padding-left:1em;padding-right:1em}
}

/* --------------------------------------------------- 5. S.02 map + cards */
/* ADAPT (plan Task 3 step 3): the reference's `aspect-ratio:1440/1120` was
   measured against a near-square map of Mexico. Roatán is a 1000x420 strip,
   so at 1440 that ratio left ~550px of empty slate under the island. The
   section now sizes to its content with a 100svh floor; everything else
   (the sticky .map-wrapper, the absolutely-placed .is-col-3) is unchanged. */
main.svc .section_projects{width:100%;padding:var(--site-margin) var(--site-margin) 6.25em;aspect-ratio:auto;min-height:100svh;background-color:var(--primary);flex-flow:column;justify-content:space-between;display:flex;position:relative}
main.svc .section_projects .intro{color:var(--white)}
main.svc .map-section{width:100%;height:100%;position:relative}
main.svc .is-grid-12{grid-column-gap:1em;grid-row-gap:1em;grid-template-rows:auto auto;grid-template-columns:repeat(12,1fr);grid-auto-columns:1fr;width:100%;display:grid;position:sticky}
main.svc .is-grid-12.is-map{display:block}
main.svc .map-wrapper{width:100%;height:100%;position:sticky;top:0}
main.svc svg.is-map{width:100%;height:100%}

/* The generated outline carries NO fill attribute (make-roatan-map.mjs says
   so in the file's own comment) — a presentation attribute would beat this
   rule and the island would vanish. `.island path` is the selector that does
   the work, not a spare: the class sits on the wrapping `g#island-group` and
   the shape inside it is `path#island`.

   ADAPT: spec §5 names `fill:#3a2f28`, and on this section's #302620 that is
   1.13:1 — measured off a 1440 capture, not estimated. The reference gets
   away with a land fill at background level because its map of Mexico is
   drawn as state OUTLINES: what you read there is the stroke, not the fill.
   Roatán is one filled silhouette with no internal borders, so the fill IS
   the map and it has to clear the 3:1 WCAG floor for a graphic you need in
   order to understand the section. --flax at .9 over --primary computes to
   #836f56 = 3.18:1, and it stays the quietest of the three warm tokens that
   do clear it (--flax 3.58, --oak 5.15 at full; --walnut is only 2.36). */
main.svc .island,main.svc .island path{fill:var(--flax);fill-opacity:.9}
main.svc .region{fill:#fff;fill-opacity:0;stroke:#ffffff1f;stroke-width:1;transition:fill-opacity .5s ease-out,stroke .5s ease-out}
main.svc .region.highlight{fill-opacity:.07;stroke:#ffffff5c}
main.svc .marker{cursor:pointer;opacity:1;transition:opacity .5s ease-out}
main.svc .marker rect{fill:#fff;fill-opacity:.1}
/* The reference lights a marker with a bright core (#ff9345) plus two
   drop-shadow glows, and drops the resting dot to a flat fill. Same idea in
   our palette, and it has to be this way round: `fill:var(--accent)` on the
   highlight — which is what this rule used to say — paints clay #7a3a20 on
   the flax island, 1.5:1, so the ONE marker the page is pointing at became
   the dimmest thing on the map. Resting is sand, highlighted is white with a
   clay ring and a white glow: brightest element in the section, measured on
   a capture. */
main.svc .marker circle{fill:var(--sand);transition:fill .25s ease,filter .25s ease}
main.svc .marker.highlight circle{fill:#fff;stroke:var(--clay);stroke-width:2.5;paint-order:stroke fill;filter:drop-shadow(0 0 2px #fff) drop-shadow(0 0 6px rgba(122,58,32,.9))}
/* theirs is opacity:0 — .35 keeps the six sites legible on an island this
   small, where a vanished marker reads as "there is nothing there" */
main.svc .marker.dimmed{opacity:.35}

/* Their hit-testing, verbatim (`tg`): the wrapper <g>s must not swallow the
   pointer, the markers and regions must take it. */
main.svc svg.is-map g[id]{pointer-events:none}
main.svc svg.is-map .marker[id],main.svc svg.is-map .region[id]{pointer-events:all}

/* The keyboard target. initMap() appends these buttons to <body> (they are
   position:fixed and must not inherit a transformed ancestor), so this rule
   cannot be scoped to main.svc. The reference sets `outline:none` inline on
   them; we do not — they are the page's only way to reach a marker by
   keyboard, so they get a visible ring. */
.marker-hitbox:focus-visible{outline:2px solid var(--clay);outline-offset:0;border-radius:4px}

main.svc .map-gradients{z-index:1;pointer-events:none;justify-content:space-between;align-items:center;width:100%;height:100%;display:none;position:absolute;inset:0%}
main.svc .map-gradient{background-image:linear-gradient(90deg,var(--primary),#30262000);width:15em;height:100%}
main.svc .map-gradient.is-2{background-image:linear-gradient(270deg,var(--primary),#30262000)}

main.svc .is-col-3.is-map{width:20.75em;display:flex;position:absolute;inset:0% 0% 0% auto}
/* `overflow:hidden` is OURS, not the reference's: their Swiper is always
   initialised, which gives `.swiper` a measured height and translates the
   slides. Un-initialised (JS off, or before Task 3's Swiper lands) the six
   cards are taller than the column and spill UP over the previous section.
   `align-items` is flex-START here rather than the reference's flex-end so
   the clipped edge is the BOTTOM of the stack and cards 1..n read from the
   top; with flex-end the first three were cut off. Both this and the
   overflow go away the moment Swiper measures the box (Task 3). */
main.svc .cards-wrapper{justify-content:flex-start;align-items:flex-start;width:100%;height:100%;padding-top:2em;padding-bottom:2em;display:flex;overflow:hidden}
/* …and this is that "moment": services.js adds `is-map-ready` only after
   Swiper has actually initialised, which is when the reference's own
   flex-end can come back. Card 1 then sits at the bottom of the column the
   way it does on cominvi, instead of hanging off the top of a sticky map. */
main.svc.is-map-ready .cards-wrapper{align-items:flex-end;overflow:visible}
main.svc .swiper.projects-wrapper{width:100%;height:auto;padding-left:0;padding-right:0}
/* `overflow:hidden` belongs to the INITIALISED swiper only. Un-initialised it
   clipped a list that is still in the document flow, so with JS off (or a
   blocked vendor script) only the cards that happened to fall inside the box
   could be seen. */
main.svc.is-map-ready .swiper.projects-wrapper{overflow:hidden}
main.svc .projects-list{grid-column-gap:2em;grid-row-gap:2em;flex-flow:column;justify-content:flex-end;align-items:stretch;height:100%;display:flex}
/* Their `tg` block again, and it is load-bearing: `.projects-list` above is
   a COLUMN (that is the un-initialised, JS-off stack), and Swiper lays its
   slides out horizontally. Without the row direction here the initialised
   swiper stacks its six translated slides on top of each other.
   GATED on `.is-map-ready` for the same reason as the overflow above: the row
   direction is only right once Swiper is translating the slides. Ungated, a
   page with no JS laid the six cards out side by side at `width:100%` each —
   600% of the column, clipped to the first one. Not ready = the column stack
   `.projects-list` above already describes. */
main.svc.is-map-ready .projects-list.swiper-wrapper{width:100%;height:auto;flex-direction:row;align-items:flex-end;justify-content:flex-start!important;display:flex}
main.svc .projects-list.swiper-wrapper .swiper-slide{flex:0 0 auto}
main.svc .project-item.swiper-slide{width:100%;transition:all .2s ease-out}
main.svc .swiper.projects-wrapper .swiper-wrapper{cursor:grab;will-change:transform;backface-visibility:hidden;transform:translateZ(0)}
main.svc .swiper.projects-wrapper .swiper-wrapper:active{cursor:grabbing}
main.svc .swiper.projects-wrapper .project-card,main.svc .swiper.projects-wrapper .project-item{-webkit-user-drag:none;user-select:none}
main.svc .project-card{grid-column-gap:1em;grid-row-gap:1em;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background-color:#ffffff0a;border-radius:.5em;flex-flow:column;width:100%;padding:1.5em;display:flex;transition:all .2s ease-out}
main.svc .project-card_infos{grid-column-gap:1em;grid-row-gap:1em;flex-flow:column;justify-content:space-between;align-items:flex-start;display:flex}
main.svc .project-card_infos-col{flex-flow:column;justify-content:space-between;align-items:flex-start;display:flex}
main.svc .project-card_infos-col.is-left{grid-column-gap:.25em;grid-row-gap:.25em;opacity:.6;justify-content:space-between;align-items:flex-end}

/* The reference's right-hand drawer: parked off-screen at translate(110%)
   and display:none until map.custom.js opens it (Task 3). */
main.svc .projects_overlays{width:35.125em;display:none;position:fixed;inset:2em 2em 2em auto;transform:translate(110%)}
main.svc .projects-overlay-wrapper{height:100%}
main.svc .projects-overlay-list{grid-column-gap:2em;grid-row-gap:2em;flex-flow:column;height:100%;display:flex}
main.svc .projects-overlay-item{height:100%;display:none}
main.svc .projects-overlay-item.is-active{display:flex;pointer-events:auto}
main.svc .project-overlay{background-color:var(--white);border-radius:.5em;flex-flow:column;justify-content:space-between;align-items:center;height:100%;padding:1.5em;display:flex}
main.svc .project-overlay_top{grid-column-gap:2.5em;grid-row-gap:2.5em;flex-flow:column;justify-content:space-between;align-items:flex-start;width:100%;display:flex}
main.svc .overlay-top_inner{justify-content:space-between;align-items:flex-start;width:100%;display:flex}
main.svc .project-overlay_infos{flex-flow:row;flex:1;justify-content:flex-start;align-items:flex-start;display:flex}
main.svc .project-overlay_infos-left{grid-column-gap:.25em;grid-row-gap:.25em;flex-flow:column;flex:1;justify-content:flex-start;align-items:flex-start;display:flex}
main.svc .close-button{width:.875em;height:.875em;flex:none}
main.svc .close-button svg{width:100%;height:100%}
main.svc .project-overlay_bottom{grid-column-gap:1.5em;grid-row-gap:1.5em;flex-flow:column;justify-content:space-between;align-items:flex-start;width:100%;display:flex}
main.svc .project-overlay_img{border-radius:.5em;width:100%;overflow:hidden}
main.svc .project-overlay_img-img{width:100%;display:block}

/* `tg` again: from 768 up the reference stacks its slides and shows only the
   active one (speed 0, no drag, no mousewheel — initMap() sets those); below
   it the slides are a draggable row and every card stays lit. */
@media screen and (min-width:768px){
  /* `.is-map-ready` (services.js sets it once Swiper has initialised) is
     load-bearing, not tidiness: un-gated, these two rules hide all six cards
     on any page where the swiper never runs — JS off, a blocked vendor
     script, or prefers-reduced-motion — because nothing is ever given
     `swiper-slide-active`. That was the state this section shipped in. */
  main.svc.is-map-ready .swiper.projects-wrapper .swiper-slide{opacity:0;pointer-events:none}
  main.svc.is-map-ready .swiper.projects-wrapper .swiper-slide.swiper-slide-active{opacity:1;pointer-events:auto;display:block}
  main.svc .swiper.projects-wrapper .swiper-wrapper,main.svc .swiper.projects-wrapper .swiper-wrapper:active{cursor:default}
  /* same family as the two rules above: killing the column's 2em gap only
     makes sense once Swiper owns the spacing. */
  main.svc.is-map-ready .swiper.projects-wrapper .projects-list.swiper-wrapper{gap:0!important;padding-left:0!important;padding-right:0!important}
  main.svc .swiper.projects-wrapper{padding-left:0!important;padding-right:0!important}
}
@media screen and (max-width:991px){
  main.svc .swiper.projects-wrapper .project-card,main.svc .swiper.projects-wrapper .project-item{transition:none!important}
  main.svc .swiper.projects-wrapper .project-card{opacity:1!important;transform:none!important}
}

@media screen and (max-width:991px){
  main.svc .section_projects{aspect-ratio:auto;height:auto;min-height:100svh;padding-left:0;padding-right:0}
  main.svc .section_projects .intro{padding-left:1em;padding-right:1em}
  main.svc .section_projects .content{position:relative}
  main.svc .is-grid-12.is-map{flex-flow:column;justify-content:space-between;height:100%;display:flex}
  main.svc .is-col-9.is-map{flex:1;order:-9999;justify-content:center;align-items:center;display:flex}
  main.svc .map-wrapper{position:relative}
  main.svc .cards-wrapper{justify-content:flex-end;align-items:flex-end;padding-top:0;padding-bottom:0;display:flex}
  main.svc .map-gradients{flex-flow:column}
  main.svc .map-gradient{background-image:linear-gradient(180deg,var(--primary),#30262000);width:100%;height:9em}
  main.svc .map-gradient.is-2{background-image:linear-gradient(0deg,var(--primary),#30262000)}
  main.svc .map-section{flex:1;width:100%}
  main.svc .projects_overlays{display:none;position:absolute;top:auto;bottom:auto;right:1em;transform:translate(110%)}
  main.svc .projects-list{grid-column-gap:1em;grid-row-gap:1em;padding-left:1em;padding-right:1em}
  main.svc .projects-list.swiper-wrapper{padding-bottom:1em;padding-left:0;padding-right:0}
  main.svc .project-card{padding:1em}
  main.svc .project-overlay{padding:1em}
  main.svc .swiper.projects-wrapper{padding-left:1em;padding-right:1em}
}
@media screen and (max-width:767px){
  main.svc .section_projects{height:auto;min-height:100svh}
  /* ADAPT: the marker plate is 24 units of a 1000-unit viewBox — ~9px once
     the island is scaled into a 390 screen, and the 4-unit dot lands under
     2px. `transform-box:fill-box` scales each marker about its own centre,
     so the site stays exactly where it is. Desktop is untouched. */
  main.svc .marker{transform-box:fill-box;transform-origin:center;transform:scale(1.9)}
  main.svc .projects_overlays{z-index:2;width:calc(100vw - 2em);position:absolute;top:5em}
  main.svc .is-grid-12.is-map{grid-column-gap:0em;grid-row-gap:0em;height:100%}
  main.svc .is-col-3.is-map{width:100%;height:auto;position:static;inset:auto 0% 0%}
  main.svc .map-wrapper{width:90%}
  main.svc .cards-wrapper{width:100%;height:auto}
  main.svc .map-gradients{flex-flow:column;display:flex}
  main.svc .map-gradient{height:8em}
  /* …and the same gate at 479: this is the horizontal phone swiper, so with
     no Swiper it has to stay the column, or six `width:100%` cards run off
     the side of a wrapper that no longer clips them. */
  main.svc.is-map-ready .projects-list{grid-column-gap:0em;grid-row-gap:0em;flex-flow:row;justify-content:flex-start;align-items:flex-end;height:auto;padding-bottom:1em;padding-left:0}
  main.svc .project-item.swiper-slide{padding-right:1em}
  main.svc .project-card_infos{pointer-events:none}
}
@media screen and (max-width:479px){
  main.svc .section_projects{height:auto;min-height:100vh}
  main.svc .is-col-9.is-map{flex-flow:column;overflow:hidden}
  /* ADAPT: theirs is `width:120%` (inline-styles.css block 5, @479) — their
     map is a compact blob and the overspill only crops empty sea. Roatán is
     a 2.4:1 strip whose western tip carries five of the six projects, and at
     390 a 120%-wide map put that tip (and three markers) off the left edge,
     measured: svg x -39, marker-1 x -11. 100% keeps the whole island on
     screen. */
  main.svc .map-wrapper{flex:1;justify-content:center;align-items:center;display:flex;width:100%}
  main.svc .project-card_infos-col.is-left{grid-column-gap:.25em;grid-row-gap:.25em}
}

/* ------------------------------------------------------- 6. S.03 process */
main.svc .section_process{width:100%;padding:var(--site-margin) var(--site-margin) 0em;grid-column-gap:16em;grid-row-gap:16em;background-color:var(--white);flex-flow:column;display:flex;position:relative}
main.svc .processes{grid-column-gap:16px;grid-row-gap:16px;grid-template-rows:auto;grid-template-columns:6fr 1fr 5fr;grid-auto-columns:1fr;width:100%;padding-bottom:2em;display:grid;position:relative}
main.svc .processes_inner{grid-area:1/3/2/4;justify-content:flex-start;align-items:center}
main.svc .process{grid-column-gap:1em;grid-row-gap:1em;place-content:start flex-start;align-items:flex-start;width:100%;display:flex}
main.svc .process-infos{grid-area:1/3/2/4;grid-column-gap:10em;grid-row-gap:10em;flex-flow:column;justify-content:space-between;padding-top:2em;display:flex;width:100%}
main.svc .process-title{grid-column-gap:1em;grid-row-gap:1em;flex-flow:row;justify-content:flex-start;align-items:flex-start;display:flex}
main.svc .process_index{padding-top:.5em}
main.svc .process_inner{grid-column-gap:1em;grid-row-gap:1em;border:1px rgba(48,38,32,.5);border-bottom-style:solid;flex-flow:row;justify-content:flex-start;align-items:flex-start;width:100%;padding-bottom:2em;display:flex}
main.svc .process-desc{grid-column-gap:1em;grid-row-gap:1em;flex:1;grid-template-rows:auto;grid-template-columns:repeat(5,1fr);grid-auto-columns:1fr;display:grid}
/* their #w-node on this <p>: span 3 of the 5 columns. */
main.svc .process-desc>p{grid-column:span 3/span 3}

main.svc .video{width:100%;height:calc(100vh - 4em);margin-bottom:4em;position:sticky;top:2em;overflow:hidden}
main.svc .video-inner{position:relative;overflow:hidden;z-index:0;aspect-ratio:16/9;border-radius:.5em;width:100%}
/* Adapt (spec §6): ten stacked step photos instead of their process video. */
main.svc .svc-step-img{position:absolute;inset:0;object-fit:cover;width:100%;height:100%;opacity:0;transition:opacity .6s var(--ease-card)}
main.svc .svc-step-img.is-active{opacity:1}

main.svc .process-progression-wrap{z-index:3;grid-column-gap:1em;grid-row-gap:1em;pointer-events:none;grid-template-rows:auto;grid-template-columns:6fr 1fr 5fr;grid-auto-columns:1fr;padding-top:0;display:grid;position:absolute;inset:0%}
main.svc .process-progression-inner{grid-area:span 1/span 1/span 1/span 1;grid-column-gap:1em;grid-row-gap:1em;flex-flow:column;justify-content:flex-end;align-items:flex-start;width:100%;height:100vh;padding-top:2em;padding-bottom:2em;display:flex;position:sticky;top:0}
main.svc .process-progression{grid-column-gap:.5em;grid-row-gap:.5em;justify-content:flex-start;align-items:flex-end;width:100%;display:flex}
main.svc .process-progression_number{justify-content:flex-start;align-items:flex-start;width:100%;display:flex}
/* The reference spells this class `procress-progression_number-inner`
   (their typo); ours is the corrected spelling. Task 5's port of
   process-progression.pretty.js must map the one to the other. */
main.svc .process-progression_number-inner{display:flex;position:relative}
main.svc .scroll-tick{background-color:var(--primary);opacity:.2;width:.75em;height:.063em;flex:none}
main.svc .scroll-tick.vertical{width:.063em;height:.75em}
main.svc .scroll-tick.vertical.is-m{height:.8755em;opacity:.45}
main.svc .scroll-tick.vertical.is-l{height:1em;opacity:.55}
main.svc .scroll-tick.vertical.is-xl{height:1.25em;opacity:.65}
main.svc .scroll-tick.vertical.is-xxl{height:1.5em;opacity:.75}

@media screen and (max-width:767px){
  main.svc .processes{padding-bottom:0;display:flex;flex-flow:column}
  main.svc .process{grid-column-gap:2em;grid-row-gap:2em;flex-flow:column;padding-top:2em;display:flex}
  main.svc .process-infos{grid-column-gap:2em;grid-row-gap:2em;padding-top:0}
  main.svc .video{order:-9999;position:static;height:18em}
  main.svc .process_inner{padding-bottom:6em}
  main.svc .process-progression-wrap{display:none}
  main.svc .processes .process:nth-child(10){height:auto}
}
@media screen and (max-width:479px){
  main.svc .section_process{padding-top:1em}
  main.svc .processes_inner{grid-area:span 1/span 1/span 1/span 1}
  main.svc .processes{padding-bottom:6em}
  main.svc .process{padding-top:1em}
  main.svc .video{height:12.5em}
}

/* ---------------------------------------------- 7. S.04 next + buttons */
main.svc .section_next{width:100%;height:100svh;padding:2em var(--site-margin) 0;grid-column-gap:2em;grid-row-gap:2em;background-color:var(--primary);flex-flow:column;display:flex;position:relative}
main.svc .intro_next{z-index:1;grid-column-gap:16px;grid-row-gap:16px;padding-right:7.188em;display:block;position:absolute}
main.svc .next-button-scroll{height:100%;position:absolute;inset:0%;overflow:clip}
main.svc .next-button-scroll_inner{height:120vh;margin-top:-10vh}
main.svc .next-button-wrapper{z-index:1;justify-content:center;align-items:center;display:flex;position:sticky;top:50svh;transform:translateY(-50%)}
main.svc .next_background-wrap{z-index:0;position:absolute;inset:0%;overflow:hidden}
main.svc .next_background{z-index:0;position:absolute;inset:0%}

main.svc .button{background-color:var(--primary);color:var(--white);text-transform:uppercase;border-radius:.5em;justify-content:flex-start;align-items:center;width:fit-content;display:flex;overflow:hidden}
main.svc .button.is-white{background-color:var(--white);color:var(--primary)}
main.svc .button_inner{justify-content:space-between;align-items:center;padding:.25em .25em .25em 0;display:flex}
main.svc .button-inner_content{justify-content:space-between;align-items:center;height:2em;display:flex;position:relative}
main.svc .label-wrap{justify-content:flex-start;align-items:center;padding-left:1.5em;padding-right:1.5em;display:flex}
main.svc .button_label-small{color:var(--white);font-family:var(--font-mono);font-size:.75em;font-weight:400;line-height:.8;text-decoration:none;display:block}
main.svc .button.is-white .button_label-small{color:var(--primary)}
main.svc .is-arrow-square{width:2em;height:2em;flex:none}
main.svc .is-arrow-square.is-left{position:absolute;left:-2em}
main.svc .button-arrow{width:2em;flex:none}
main.svc .arrow-bg{width:100%;height:100%;color:var(--white)}
main.svc .button.is-white .arrow-bg{color:var(--primary)}
main.svc .arrow-arrow{color:var(--primary)}
main.svc .button.is-white .arrow-arrow{color:var(--white)}
main.svc .arrow-white-1_bg{color:var(--accent)}
main.svc .arrow-white-1_arrow{color:var(--primary)}

@media screen and (max-width:991px){
  main.svc .section_next{padding-bottom:0}
  main.svc .is-arrow-square{width:1.5em;height:1.5em}
  main.svc .button{padding:0}
  main.svc .button_label-small{font-size:.813em}
}
@media screen and (max-width:767px){
  main.svc .intro_next{padding-right:1em}
}

/* ---------------------------------------- 8. sizes the reference measured */
/* Nothing here — every size above is the reference's own em value. Kept as a
   heading so the next task knows this file has no "our own" geometry. */

/* -------------------------------------------- 9. hidden-until-JS states --
   `.js` is put on <main class="svc"> by an inline script INSIDE the <main>
   tag (build/build.js `SVC_NO_FLASH`), not by site/js/services.js: a module
   runs after the first paint, so setting it there showed the finished hero
   for ~2s and then dropped it out. With JS off nothing below applies and the
   page is complete. These are the ONLY rules that hide anything. */
main.svc.js .is-h1-span{opacity:0}
main.svc.js .eyebrow-l{opacity:0}
/* `.eyebrow-l-alt` is NOT hidden here. The reference hides it too, but every
   instance on this page also carries `.is-o-50` (which the reference sets back
   to opacity 1), so the pair cancels out and nothing would ever un-hide a bare
   one — the hero intro only animates `.is-h1-span`, `.eyebrow-l` and
   `.section_hero .body-xl`. */
main.svc.js .card{opacity:0}
main.svc.js .section_hero .body-xl{opacity:0}
@media screen and (min-width:992px){
  main.svc.js .service-image{opacity:0;display:none}
}

/* The card reveal's fromTo is `immediateRender:false` (the reference's own
   flag), so nothing touches a card until its ScrollTrigger fires. Without
   this the card would paint in full and then snap to opacity 0 as it entered
   the viewport. services.js adds the class per card and removes it in the
   tween's onStart, from which point GSAP's inline opacity/visibility wins.
   NOT `visibility:hidden`: these cards are <button>s, and hiding them would
   take all five out of the tab order until they happened to scroll in.
   `opacity:0` leaves them focusable, and services.js finishes the reveal of
   whichever one takes focus. */
main.svc.js .service-card.is-card-reveal-pending{opacity:0;pointer-events:none}

/* The escape hatch. services.js reaches `.is-intro-done` on every path,
   including a throw and a fonts.ready that never settles, and the inline
   script's 6s watchdog adds it even if services.js never loads at all — so
   this is what guarantees the hero cannot be stranded invisible. During a NORMAL intro it
   is inert: GSAP's inline `autoAlpha` has already taken over by the time the
   class lands, and inline beats a stylesheet. Deliberately not listing
   `.is-card-reveal-pending` — those cards are still legitimately waiting. */
main.svc.js.is-intro-done .is-h1-span,
main.svc.js.is-intro-done .eyebrow-l,
main.svc.js.is-intro-done .card,
main.svc.js.is-intro-done .section_hero .body-xl{opacity:1;visibility:visible}

/* -------------------------------------------------------- 10. Lenis ------
   Lenis 1.3's own lenis.css ships five rules; these are the three this page
   needs. The two unused ones are omitted: the `.lenis-scrolling` autoToggle
   rule (we never pass `autoToggle`) and the `html.lenis-smooth`
   scroll-behavior reset, which only matters when a stylesheet sets
   `scroll-behavior:smooth` — none on this page does. They are `html`-level,
   which is why they sit outside the `main.svc` prefix: this stylesheet only
   ever loads on /services/, the one page that runs Lenis. */
html.lenis,html.lenis body{height:auto}
.lenis:not(.lenis-autoToggle).lenis-stopped{overflow:clip}
.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}

@media (prefers-reduced-motion:reduce){
  main.svc .service-card,main.svc .svc-step-img,main.svc .marker circle,main.svc .region{transition:none}
  main.svc .service-card.is-svc-hover .svc-icon path,
  main.svc .service-card.is-svc-leave .svc-icon{animation:none}
}
