/* ============================================================
   NJ INDOOR OUTDOOR — /get-a-free-quote/'s COMPACT HERO

   The page slice for the contact page, same arrangement as
   v2-nav.css, v2-hero.css and v2-pricing.css and for the same reason:
   this page is a 1:1 Webflow mirror styled by Webflow's stylesheet and
   cannot load v2.css — the two collide on *, html, body, a and img.

   THE BRIDGE IS SCOPED TO .chero AND WRAPPED IN :where(). Unscoped it
   would restyle the whole mirrored page. Verified: `.chero` appears
   nowhere in Webflow's 137KB stylesheet.

   WHAT IT REPLACED. A 320px band of flat #14A800 green holding a
   dark-green rounded box with "GET IN TOUCH WITH US" in heavy black
   type. Three problems, and the brief named the third:

     1. THE GREEN IS NOT v2'S. #14A800 against v2's #71B745, and it
        was the largest area of saturated colour left anywhere in the
        build.
     2. A BOX INSIDE A BAND, doing nothing but holding one line.
     3. NOTHING WAS GOING ON IN THE BACKGROUND. A flat fill, which is
        also what the display pipeline spatial-dithers into a
        diagonal hairline.

   IT IS A HERO, BUT A SHORT ONE. The three page heroes run
   78-84svh; this is capped at 400px, which is about what the green
   band occupied. The contact form is the point of this page and it
   should stay above the fold on a laptop.

   THE COPY IS LIVE'S, to the character — "GET IN TOUCH WITH US", the
   page's own h1. Nothing was added: the sentence that would have made
   a lede is already directly below in the Contact Us panel, and
   repeating it here would be the same fault as the junk panel's four
   identical tags.
   ============================================================ */

/* --- bridge: v2's base rules, scoped to the hero subtree --- */
:where(.chero) {
  font-family: var(--font, 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif);
  color: #FFFFFF;
  -webkit-font-smoothing: antialiased;
}
:where(.chero) h1  { margin: 0; }
:where(.chero) p   { margin: 0; }
:where(.chero) img { max-width: 100%; height: auto; display: block; }

.chero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Shows while the photograph decodes. Two-stop, never a flat fill. */
  background: linear-gradient(180deg, #131B2E 0%, #0F172A 100%);
}

/* contact-hero.jpg — an aerial of a suburban neighbourhood, houses
   and tree-lined streets around a green. Pexels 9716228, Kindel
   Media, Pexels License. Cropped to 3:2 and re-encoded to 1600x1067,
   q62, 347KB — heavier than the library's usual 280-310KB because a
   detailed aerial is the worst case for JPEG, and it was traded down
   from 1800px to keep it near that.

   WHY THIS AND NOT SOMEONE ON A PHONE. The first attempt used
   gallery-11, the client's own office shot of someone taking a call,
   and it was rejected outright. The search that followed is worth
   recording so it is not repeated:

     · CALL-CENTRE STOCK reads corporate. Rows of headsets and
       cubicles belong to a telecoms company, not a family firm in
       Aberdeen.
     · "WORKER ON THE PHONE" STOCK is almost all VERTICAL and almost
       all business suits, neither of which survives a 6:1 band.
     · A CLOSE-UP OF A FACE OR A HEADSET, cropped to this ratio, is a
       slice of a mouth. Checked against the real band ratio before
       being discarded.

   AN AERIAL SOLVES THE FORMAT. A wide short band wants a wide subject,
   and a neighbourhood read from above is one. It also says something
   the page needs: these are the streets the business covers, which is
   the same claim the footer's Service Areas list makes.

   object-position 50% 42%: the band is about 6:1 at desktop, so cover
   matches the WIDTH and shows roughly a sixth of the height. 42%
   keeps the green and the curved street in frame across the middle
   and holds houses on the left, under the type. Only the y value
   does anything at desktop; on a phone the band is nearly square and
   the crop takes the middle. */
.chero__photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
}

/* A LEFT-WEIGHTED VEIL, NOT THE ELLIPSE THE PAGE HEROES USE. Those
   centre their type and an ellipse follows it. This one is
   left-aligned in a band a third the height, where an ellipse would
   have to be so wide it would flatten the whole photograph. A linear
   ramp darkens the left third where the type sits and lets the right
   two thirds stay a photograph.

   Measured figures are in the note below .chero__title. */
.chero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(90deg,
      rgba(8, 14, 28, .80)  0%,
      rgba(8, 14, 28, .62) 32%,
      rgba(8, 14, 28, .24) 62%,
      rgba(8, 14, 28, .10) 100%);
}

/* Same rail as the pricing page and the footer — padding inside the
   max-width — so the headline starts on the same vertical as the
   content below it. */
.chero__inner {
  position: relative;
  z-index: 2;
  max-width: 1800px;
  margin: 0 auto;
  padding: 0 clamp(20px, 5vw, 110px);
  /* vh first as the fallback: where svh is unsupported the clamp is
     dropped entirely and the band collapses to the height of one line
     of type. The three page heroes carry the same risk and no
     fallback, but they are a matched set that has to stay identical;
     this file answers to nothing, so it takes the safer pair. */
  min-height: clamp(260px, 34vh, 400px);
  min-height: clamp(260px, 34svh, 400px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* WEIGHT 800, heavier than the three page heroes' 400, and that is a
   deliberate split rather than drift. Those headlines run 50-60px
   across two or three lines and carry the page on their own. This one
   is a single short line in a band a third the height, sitting over
   an aerial with detail at every scale — at 400 it read as a caption
   laid on a photograph rather than as the page's title. 800 is the
   same weight the junk panel and the pricing closer use.

   Uppercase is live's, not an addition — its own h1 was
   "GET IN TOUCH WITH US".

   MEASURED, not estimated: the band is reconstructed from
   contact-hero.jpg, the object-fit: cover geometry and the ramp above,
   then sampled inside the headline's real glyph box read off the live
   page (a Range around the text, not the h1's block box — the block
   runs the full rail and would have averaged in bright pixels the
   words never touch).

                    no veil         with veil        floor
       headline     5.32 / 2.02    12.95 / 9.41       3.0   PASS
       accent       2.10 / 1.11     5.23 / 4.06       3.0   PASS
                    (mean / worst tenth)

   The headline is 50px at weight 800, which is large text, so both
   rows answer to 3.0 rather than 4.5. The accent is the tighter of
   the two at 4.06 and it is still a third clear of the floor —
   measured where the word "TOUCH" actually falls, x 326-507, not
   where the line starts. Move the accent to a different word and this
   number moves with it.

   THE VEIL WAS LIGHTENED AFTER MEASURING, not before. It opened at
   .88/.74/.34/.18, which measured 15.11 / 12.57 — four times the
   floor, bought by taking the right two thirds of the frame 22%
   darker than the bare photograph. At .80/.62/.24/.10 the headline
   still runs 9.54 across its worst tenth and the cost drops to 14.7%,
   so more of the picture survives. The brief asked for something
   going on in the background; there is no reason to bury it to clear
   a floor three times over.

   RE-MEASURE IF THE PICTURE, THE CROP OR THE BAND HEIGHT CHANGES. */
.chero__title {
  font-size: clamp(28px, 3.6vw, 50px);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1.06;
  color: #FFFFFF;
  text-transform: uppercase;
}

@media (max-width: 860px) {
  .chero__inner {
    min-height: clamp(220px, 30vh, 320px);
    min-height: clamp(220px, 30svh, 320px);
  }
  /* The veil goes vertical on a phone: the type block is nearly as
     wide as the frame there, so a left-weighted ramp leaves the end
     of the line uncovered. */
  .chero__scrim {
    background:
      linear-gradient(180deg,
        rgba(8, 14, 28, .62)  0%,
        rgba(8, 14, 28, .80) 55%,
        rgba(8, 14, 28, .86) 100%);
  }
}

@media (max-width: 560px) {
  .chero__inner { padding-inline: 18px; }
}

/* THE GREEN LANDS ON "TOUCH" and on nothing else. The three page
   heroes each accent one phrase — "Dumpster Rentals", "Same-Day" —
   and this is the same move on the one word in the line that is not
   grammar. Measured where it actually sits, which is the point of
   accenting a word rather than a position: see the ratios below.

   #71B745 is v2's brand green. It is safe here because the veil keeps
   this part of the band dark; on a LIGHT ground it drops to 2.45:1
   and has to become #49772D, which is what the pricing sections do. */
.chero__accent { color: #71B745; }


/* ============================================================
   THE CONTACT BOX — TREATMENT B OUT OF design-lab/contact-box.html

   WHAT IT REPLACED, and the first two were failures rather than taste:

     1. WHITE BODY COPY ON #0FA608 MEASURED 3.24:1. The lede and the
        three contact lines are 16px, so their floor is 4.5. They
        failed. The 48px heading scraped past the 3.0 large-text floor
        on the same 3.24.
     2. THE TWO LEGAL LINKS WERE NEVER STYLED AT ALL. They computed to
        rgb(0, 0, 238) — the browser default link blue, underlined —
        which on that green is 2.90:1. They sat stacked and centred
        between the message box and the button.
     3. THE FIELDS WERE SET IN system-ui, so the text a visitor types
        was in a typeface used nowhere else on the page, coloured
        #00529F — a navy that is not in v2.
     4. THE SUBMIT BUTTON WAS 125px WIDE in a 550px column, centred
        under those links rather than aligned to the fields.
     5. THE LEFT COLUMN DEAD-ENDED — about 300px of content in a 630px
        panel, the rest flat green.
     6. THE SLAB WAS 1280px on a page whose hero and footer run to
        1800px, so it lined up with nothing.

   B KEEPS LIVE'S IDEA — a bold solid block — AND CHANGES ITS COLOUR.
   The ink gradient, same two stops as the footer and the featured
   pricing card, with the noise layer over it. That one swap fixes 1
   and 2 outright rather than by going quiet, which is the mistake
   made once already on the junk panel.

   MEASURED ON THE NEW PANEL, computed against the ink ground:

     #FFFFFF heading, copy, field text ... 17.16
     rgba(255,255,255,.70) legal links ...  8.89
     #71B745 field labels ................  7.00
     rgba(255,255,255,.55) placeholders ..  5.14   on the field fill
     #0B1226 on #71B745, the button ......  8.06

   THE FIELDS ARE TRANSLUCENT, NOT SOLID WHITE. Five solid white boxes
   on a coloured card is what made the old one read as bandages stuck
   to a slab. rgba(255,255,255,.07) with a .22 hairline keeps them
   reading as wells recessed into the panel.

   EVERY FIELD HAS A REAL <label>. Live had none, only placeholders,
   which disappear the moment you type and leave a screen reader with
   an unnamed box. That was never a style choice.

   THE FORM WIRING IS UNTOUCHED: the form id, name, data-name,
   redirect, method, data-wf-page-id and data-wf-element-id are all
   live's, every field keeps its name, data-name, id, type, maxlength
   and required, and the .w-form wrapper with its .w-form-done and
   .w-form-fail siblings is intact. Only classes changed. The w-node-*
   ids came OFF the legal links and the submit button deliberately —
   they are Webflow grid-placement hooks and would fight this layout.

   ONE STRING CHANGED, AND IT IS THE ONLY ONE: the button read
   "SUBMIT!" and now reads "Submit". Every other button in v2 is title
   case with no exclamation mark.
   ============================================================ */

:where(.cbox) {
  font-family: var(--font, 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif);
  -webkit-font-smoothing: antialiased;
}
:where(.cbox) h2,
:where(.cbox) p,
:where(.cbox) ul       { margin: 0; }
:where(.cbox) ul       { padding: 0; list-style: none; }
:where(.cbox) li       { margin: 0; }
:where(.cbox) a        { color: inherit; text-decoration: none; }
:where(.cbox) input,
:where(.cbox) textarea { font: inherit; }

.cbox {
  background: #FFFFFF;
  padding-block: clamp(48px, 5vw, 76px);
}

.cbox__inner {
  max-width: 1800px;
  margin: 0 auto;
  padding-inline: clamp(20px, 5vw, 110px);
}

/* Ink gradient plus noise, never a flat fill — the standing
   dark-section rule. THE NOISE DIV IS LOAD-BEARING, do not drop it. */
.cbox__panel {
  position: relative;
  overflow: hidden;
  border-radius: 20px;
  background: linear-gradient(180deg, #131B2E 0%, #0F172A 100%);
  padding: clamp(28px, 3vw, 48px);
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(32px, 4.5vw, 72px);
}
.cbox__noise {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/></svg>");
}
.cbox__col { position: relative; z-index: 2; }

.cbox__title {
  font-size: clamp(28px, 3.2vw, 44px);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1.12;
  color: #FFFFFF;
}
.cbox__lede {
  margin-top: 14px;
  max-width: 44ch;
  font-size: 15.5px;
  line-height: 1.7;
  color: rgba(255, 255, 255, .80);
}

.cbox__list { margin-top: 28px; display: grid; gap: 16px; }
.cbox__list li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  font-size: 15px;
  line-height: 1.5;
  color: #FFFFFF;
}
.cbox__list svg { flex: none; margin-top: 2px; }
.cbox__list a { border-bottom: 1px solid transparent; transition: border-color .15s linear; }
.cbox__list a:hover,
.cbox__list a:focus-visible { border-bottom-color: rgba(255, 255, 255, .6); }

.cbox__form { display: grid; gap: 16px; }

/* Name and number share a row, so the form is four rows instead of
   five and the panel's two columns finish nearer each other — which
   is most of the fix for the dead space in the old left column. */
.cbox__pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

.cbox__field { display: grid; gap: 6px; }
.cbox__field label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #71B745;
}
.cbox__field input,
.cbox__field textarea {
  width: 100%;
  min-height: 50px;              /* clears the 44px touch minimum */
  padding: 13px 16px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .07);
  color: #FFFFFF;
  font-size: 15.5px;
}
.cbox__field textarea { min-height: 130px; resize: vertical; }
.cbox__field input::placeholder,
.cbox__field textarea::placeholder { color: rgba(255, 255, 255, .55); }
.cbox__field input:focus,
.cbox__field textarea:focus {
  outline: 3px solid #71B745;
  outline-offset: 2px;
  border-color: rgba(255, 255, 255, .45);
}

/* The button aligns to the right edge of the field column and the
   legal links sit opposite it on the same line. The old 125px centred
   button and its two stacked links both went wrong here. */
.cbox__submitrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 6px;
}
.cbox__legal { font-size: 13px; color: rgba(255, 255, 255, .70); }
.cbox__legal a { border-bottom: 1px solid currentColor; padding-bottom: 1px; }
.cbox__legal a + a { margin-left: 18px; }

.cbox__submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 34px;
  border: 1px solid #71B745;
  border-radius: 100px;
  background: #71B745;
  color: #0B1226;
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background-color .2s linear, border-color .2s linear;
}
.cbox__submit:hover { background: #63A63B; border-color: #63A63B; }

/* The fields get their focus ring from the outline on :focus above;
   the button and the two link groups had nothing and were falling
   back to the browser default, which on a green pill sitting on ink
   is close to invisible. White, offset clear of the control so the
   ring lands on the ink at 17:1 rather than on the green. */
.cbox__submit:focus-visible,
.cbox__legal a:focus-visible,
.cbox__list a:focus-visible {
  outline: 3px solid #FFFFFF;
  outline-offset: 3px;
}

/* Webflow's own success and failure blocks, restyled to sit on ink
   instead of its default pale green and pink. */
.cbox .w-form-done,
.cbox .w-form-fail {
  margin-top: 16px;
  padding: 14px 18px;
  border-radius: 12px;
  font-size: 14.5px;
  line-height: 1.5;
  color: #FFFFFF;
}
.cbox .w-form-done { background: rgba(113, 183, 69, .16); border: 1px solid rgba(113, 183, 69, .45); }
.cbox .w-form-fail { background: rgba(179, 38, 30, .18); border: 1px solid rgba(179, 38, 30, .50); }

@media (max-width: 1080px) {
  .cbox__panel { grid-template-columns: 1fr; gap: 34px; }
}
@media (max-width: 620px) {
  .cbox__pair { grid-template-columns: 1fr; }
  .cbox__submitrow { flex-direction: column-reverse; align-items: stretch; }
  .cbox__submit { width: 100%; }
  .cbox__inner { padding-inline: 18px; }
  .cbox__panel { border-radius: 16px; padding: 24px 20px 28px; }
}
@media (prefers-reduced-motion: reduce) {
  .cbox__submit,
  .cbox__list a,
  .cbox__field input,
  .cbox__field textarea { transition: none; }
}


/* ============================================================
   OUR LOCATION — TREATMENT A OUT OF design-lab/location.html

   ONE-TO-ONE WITH LIVE ON COPY. Every string in this section is the
   live embed's, to the character: the heading, the lede, "Open today",
   the seven day rows INCLUDING their colons, all three button labels,
   the modal heading and all 28 towns. Diffed string by string against
   the embed this replaced, not eyeballed.

   TWO CHARACTERS ARE GONE AND THEY ARE THE ONLY OMISSIONS: the 🕒
   before the hours and the 🗺️ before "SERVICE AREAS". Both were emoji
   doing an icon's job — they change shape with the platform font,
   cannot be aligned optically, and are read aloud by a screen reader
   as "clock" and "world map". Drawn SVG replaces both. If the client
   wants them back it is two characters.

   THE PHONE NUMBERS ARE LIVE'S, UNTOUCHED, AND THAT IS A PROBLEM
   SOMEBODY HAS TO SETTLE:

       CALL NOW!     tel:+17325830378        (732) 583-0378
       TEXT US NOW!  sms:+17329479729        (732) 947-9729
       the contact box above shows           (848) 218-9705

   Three different numbers on one screen. The call button and the text
   button do not reach the same line as each other, and neither is the
   number printed above them. NOT resolved here on purpose — guessing
   which is right is worse than leaving it visible. Only the encoding
   was fixed: live wrote tel:+1 (732) 583-0378 with literal spaces and
   parentheses in the URI.

   WHAT CHANGED IN THE LOOK:

     1. THE PANEL WAS #17a31b — a THIRD green, after the #14A800 in
        the old hero band and the #0FA608 in the contact box. It is
        now the same ink gradient as the contact box directly above,
        so the bottom of the page reads as one block in two halves.
     2. THE BUTTONS WERE #0048a7, a third blue after #00529F and
        #003D76.
     3. FOUR RADII BECAME ONE. It ran 8px panel, 5px buttons, 6px
        dropdown, 10px modal.
     4. THE HOURS DROPDOWN IS GONE AND THE SEVEN DAYS ARE PRINTED.
        Every day is 07:00 am – 07:00 pm, which is exactly what the
        button that hid them already said. It was a disclosure widget
        concealing a repeat of its own label, and it carried no
        aria-expanded and no Escape.
     5. transition: all 0.3s ease came off the buttons.

   THE MODAL IS KEPT AND REBUILT. The old one assigned window.onclick,
   which REPLACES any other window click handler on the page rather
   than adding to one — the sort of thing that silently breaks a
   feature added later. The new one uses addEventListener, closes on
   Escape and on the backdrop, returns focus to the button that opened
   it, and is hidden from the accessibility tree while closed.
   ============================================================ */

:where(.loc) {
  font-family: var(--font, 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif);
  -webkit-font-smoothing: antialiased;
}
:where(.loc) h2,
:where(.loc) p,
:where(.loc) ul     { margin: 0; }
:where(.loc) ul     { padding: 0; list-style: none; }
:where(.loc) li     { margin: 0; }
:where(.loc) a      { color: inherit; text-decoration: none; }
:where(.loc) iframe { display: block; border: 0; }
:where(.loc) button { font: inherit; cursor: pointer; }

.loc { background: #FFFFFF; padding-block: 0 clamp(48px, 5vw, 76px); }
.loc__inner { max-width: 1800px; margin: 0 auto; padding-inline: clamp(20px, 5vw, 110px); }

.loc__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(20px, 2.4vw, 32px);
  align-items: stretch;
}

/* The map is a positioned shell with the iframe filling it, so the
   two columns match height instead of the map dictating its own. */
.loc__map {
  position: relative;
  overflow: hidden;
  border-radius: 20px;
  min-height: 440px;
  background: var(--surface, #F1F5F7);
}
.loc__map iframe { position: absolute; inset: 0; width: 100%; height: 100%; }

.loc__panel {
  position: relative;
  overflow: hidden;
  border-radius: 20px;
  background: linear-gradient(180deg, #131B2E 0%, #0F172A 100%);
  padding: clamp(26px, 2.6vw, 40px);
  display: flex;
  flex-direction: column;
}
.loc__noise {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/></svg>");
}
.loc__in { position: relative; z-index: 2; display: flex; flex-direction: column; height: 100%; }

/* Live sets this as an <h3> reading "OUR LOCATION". It is an <h2>
   here because the page's only other heading in this region is the
   contact box's h2 and an h3 under an h1 with no h2 between them is a
   skipped level. The words are unchanged. */
.loc__title {
  font-size: clamp(22px, 2.1vw, 28px);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.2;
  color: #FFFFFF;
}
.loc__lede {
  margin-top: 12px;
  max-width: 38ch;
  font-size: 15px;
  line-height: 1.65;
  color: rgba(255, 255, 255, .80);
}

.loc__hours {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, .14);
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}
.loc__hours svg { flex: none; margin-top: 1px; }
.loc__open { font-size: 13px; color: rgba(255, 255, 255, .72); }
.loc__open b { display: block; margin-top: 2px; font-size: 16px; font-weight: 700; color: #FFFFFF; }
.loc__days { margin-top: 12px; display: grid; gap: 5px; font-size: 13px; color: rgba(255, 255, 255, .72); }
.loc__days div { display: flex; justify-content: space-between; gap: 16px; max-width: 270px; }
.loc__days span:first-child { font-weight: 700; color: #FFFFFF; }

.loc__btns { margin-top: auto; padding-top: 26px; display: grid; gap: 10px; }

.loc .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;              /* clears the 44px touch minimum */
  padding: 0 24px;
  border: 1px solid transparent;
  border-radius: 100px;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  transition: background-color .2s linear, border-color .2s linear, color .2s linear;
}
.loc .btn--green { background: #71B745; border-color: #71B745; color: #0B1226; }
.loc .btn--green:hover { background: #63A63B; border-color: #63A63B; }
.loc .btn--light { background: transparent; border-color: rgba(255, 255, 255, .55); color: #FFFFFF; }
.loc .btn--light:hover { background: #FFFFFF; border-color: #FFFFFF; color: #0B1226; }
.loc .btn:focus-visible { outline: 3px solid #FFFFFF; outline-offset: 3px; }

/* ---- the service areas dialog ---- */
.locmodal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(8, 14, 28, .72);
}
.locmodal.is-open { display: flex; }
.locmodal__box {
  background: #FFFFFF;
  color: var(--head-ink, #0B1226);
  border-radius: 20px;
  padding: clamp(26px, 3vw, 40px);
  width: 100%;
  max-width: 720px;
  max-height: 82vh;
  overflow: auto;
}
.locmodal__head { display: flex; align-items: center; gap: 12px; }
.locmodal__title { font-size: 20px; font-weight: 800; letter-spacing: -.02em; }
.locmodal__list {
  margin-top: 22px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px 22px;
}
.locmodal__list li { font-size: 14px; line-height: 1.5; color: var(--head-ink, #0B1226); }
.locmodal__foot { margin-top: 26px; display: flex; justify-content: flex-end; }
.locmodal__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  padding: 0 30px;
  border: 1px solid #0B1226;
  border-radius: 100px;
  background: #0B1226;
  color: #FFFFFF;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1;
  transition: background-color .2s linear, border-color .2s linear;
}
.locmodal__close:hover { background: #1A2438; border-color: #1A2438; }
.locmodal__close:focus-visible { outline: 3px solid #0B1226; outline-offset: 3px; }

@media (max-width: 1080px) {
  .loc__grid { grid-template-columns: 1fr; }
  .loc__map { min-height: 320px; }
  .locmodal__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .loc__inner { padding-inline: 18px; }
  .loc__panel { border-radius: 16px; padding: 24px 20px 28px; }
  .loc__map { border-radius: 16px; }
  .locmodal__list { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .loc .btn, .locmodal__close { transition: none; }
}


/* --- Quote form: submit states -------------------------------------------
   Added 2026-09-08 with the contact service. The panel is dark, so these are
   tuned for white-on-dark rather than the usual light-background defaults.
   #71B745 is --accent-green from v2.css; the error red is lifted enough in
   luminance to clear 4.5:1 against the panel. */

.cbox__status {
  margin: 14px 0 0;
  font-size: 14px;
  line-height: 1.5;
  min-height: 0;
  color: rgba(255, 255, 255, .82);
}
.cbox__status:empty { display: none; }   /* no reserved gap before it speaks */
.cbox__status a { color: inherit; border-bottom: 1px solid currentColor; }

.cbox__status.is-ok  { color: #8FD45F; }
.cbox__status.is-err { color: #FF9C8A; }

/* Field-level error, set by quote-form.js alongside the message. Border only:
   a red fill on a translucent dark input turns the typed text unreadable. */
.cbox__field input.err,
.cbox__field textarea.err {
  border-color: #FF9C8A;
  box-shadow: 0 0 0 1px rgba(255, 156, 138, .35);
}

/* The form needs JS while the token is required, so there has to be a way out
   for anyone without it. form-context.md landmine #10. */
.cbox__noscript {
  margin: 14px 0 0;
  font-size: 14px;
  line-height: 1.55;
  color: rgba(255, 255, 255, .82);
}
.cbox__noscript a { color: #FFFFFF; border-bottom: 1px solid currentColor; }
