/* ==========================================================================
   Poseidon Pump Service — "Trident Deep" flagship
   Cinematic intro + raymarched 3D storm ocean behind dark glass sections.
   ========================================================================== */

:root {
  /* brand palette */
  --abyss:      #0C0F14;
  --graphite:   #1B1F24;
  --navy:       #0E2A47;
  --deep:       #00417F;
  --poseidon:   #005AA8;
  --azure:      #2E7FC4;
  --sky:        #7FB6E8;
  --sky-bright: #BFDBF5;
  --foam:       #EEF4FA;
  --steel:      #B0B6BE;
  --steel-dark: #5C646E;
  --ink:        #14181D;

  /* surfaces --------------------------------------------------------------
     Everything below the hero is frosted glass over the live ocean, and it is
     ONE recipe: the same blur and the same tint on the background sheet
     (.deep-frost) and on every card, panel and form that sits on it. Two
     tokens carry it so "consistent" is enforced by the stylesheet rather than
     by remembering to keep six values in step.

     The tint is deliberately lighter than the flat panels it replaces (.72
     against the old .88/.85/.95) so more of the water reads through. The
     alpha is not a taste call: measured against the blurred scene's 99.9th
     percentile backdrop (its brightest realistic patch — a lit whitecap under
     the horizon glow), .72 holds --text at 11:1, --text-mute and --sky at
     6:1, i.e. AA with room to spare. Below about .62 --text-mute starts to
     slide under 5:1, so that is the floor. */
  --glass-blur:   blur(8px) saturate(1.1);
  --glass-bg:     rgba(8, 13, 21, .72);
  /* cards sit ON the band glass, so their own tint only has to lift them off
     it — a hair brighter at the top edge for the usual pane-of-glass read */
  --card-bg:      linear-gradient(180deg, rgba(30, 45, 64, .42), rgba(10, 17, 27, .50));
  --line:         rgba(127, 182, 232, .14);
  --line-strong:  rgba(127, 182, 232, .30);

  /* text */
  --text:      #E4EDF6;
  --text-mute: #9FB2C6;
  --text-dim:  #7C8FA4;

  /* icon art */
  --ic-line:    #9FCBF2;
  --ic-acc:     #4E9BE0;
  --ic-dim:     #55738F;
  --ic-water:   rgba(46, 127, 196, .38);
  --ic-water-l: #7FB6E8;

  /* geometry */
  --maxw:   1180px;
  --gutter: clamp(20px, 4vw, 44px);
  --r-lg:   18px;
  --r-md:   13px;
  --r-sm:   9px;
  --r-pill: 999px;
  --sec-y:  clamp(60px, 6.2vw, 96px);
  --wl-h:   clamp(56px, 6.5vw, 104px);

  --sh-card: 0 26px 54px -36px rgba(0, 0, 0, .95), inset 0 1px 0 rgba(255, 255, 255, .05);
  --sh-pop:  0 30px 60px -30px rgba(0, 0, 0, .9);

  /* hero scene geometry — see SCENE GEOMETRY IS svh below, which restates both
     of these (and every media-query override of them) against the SMALL
     viewport. These vh lines are the pre-svh fallback and nothing else. */
  --waterline: 61vh;   /* distance from viewport bottom to the trident tip */
  --trident-h: 26vh;

  --font-display: "Arial Black", "Arial Bold", "Segoe UI", system-ui, sans-serif;
  --font-body: "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;

  --ease-out: cubic-bezier(.2, .8, .25, 1);

  /* The pages also carry <meta name="color-scheme" content="dark">; this is
     the same opt-out where a browser checks computed style instead of the
     meta. Forced-dark features that honor either will leave the site alone —
     it is already dark, and recoloring inverts the silver artwork to black. */
  color-scheme: dark;
}

/* ================================================ SCENE GEOMETRY IS svh
   The trident hangs inside #scene, which is position:fixed — so its box is the
   SMALL viewport (browser chrome showing), and the canvas waterline is painted
   at window.innerHeight * (1 - waterline/100), i.e. small viewport too. But vh
   on a phone resolves against the LARGE viewport (URL bar collapsed), and the
   intro's scroll lock guarantees the bar never collapses while the intro plays.
   So the trident column was measured in units 10-20% taller than the box it
   hangs in: its top jammed into the header (-8 to -95px of clearance) and its
   tip floated 50-126px above the water it is supposed to be striking.

   svh IS the small viewport, by definition, so every scene-geometry value is
   restated in it. The vh line above each @supports block is the fallback for
   browsers without svh (they keep exactly today's behaviour, bug included —
   there is no unit there that can express what this needs).

   It has to be @supports, not the two-declarations-in-a-row idiom this file
   uses elsewhere (.hero's min-height, work.css's .work-hero padding). That
   idiom works because a browser drops a DECLARATION it cannot parse — but a
   custom property is parsed permissively and accepts almost any token stream,
   so `--waterline: 61svh` would be stored happily by a browser that has no
   svh and only fail later, at var() substitution, leaving #tridentWrap with
   `bottom: auto` and no anchor at all. The wrong fallback here is worse than
   the bug.

   --trident-h additionally takes a ceiling: whatever is left between the
   waterline and 78px below the top of the screen (65px of header + 13px of
   air). Without it a short viewport has no room for the designed column at all
   and the top of the trident lands behind the header however the units resolve.
   On a 568px-tall phone that trims the trident ~19%; in landscape, more. The
   alternative is a trident behind the header, so the trim wins.

   AND THE SCENE BOX ITSELF MUST NOT BREATHE. "#scene's box is the small
   viewport" above is only true while the browser bar is showing: `inset: 0`
   on a fixed element tracks the DYNAMIC viewport, so the first light scroll
   after the intro collapsed the bar, grew the box, and everything anchored
   to its bottom — waterline, trident, godray — slid down ~the bar height
   while the hero copy (laid out in svh, which never moves) stayed put. The
   same resize re-sized the WebGL canvas, so the waves visibly snapped too.
   So #scene is anchored to the TOP and given a constant height: 100lvh, the
   large viewport, which covers the screen in both bar states and changes
   only on a real resize. Its bottom edge now sits (100lvh - 100svh) below
   the visible bottom while the bar is showing — that difference is
   --vp-slack, and every bottom-anchored scene child adds it so the tuned
   svh geometry lands on the same screen rows as before, permanently.
   Fallback story unchanged: no lvh means no svh either, --vp-slack stays
   0px and #scene keeps a plain 100vh box — exactly the old behaviour. */
:root { --vp-slack: 0px; }
@supports (height: 1svh) {
  :root {
    --waterline: 61svh;
    --trident-h: min(26svh, calc(100svh - var(--waterline) - 78px));
  }
}
@supports (height: 1lvh) {
  :root { --vp-slack: calc(100lvh - 100svh); }
}

/* ------------------------------------------------------------------ reset */
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; }
html {
  background: #05080D;
  overflow-x: hidden;
  /* NOT smooth here. A page opened at a deep link (index.html#request from
     another page's Contact link) makes the browser animate the whole 6000px
     to the anchor, so the visitor watches the top of the homepage for a
     beat before it slides away — which reads as the link having failed and
     then jumped. Landing is instant; script.js adds .nav-ready once the
     browser has done that initial scroll, and smooth applies from then on,
     which is the only place it was ever wanted (in-page anchor clicks). */
  scroll-behavior: auto;
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}
html.nav-ready { scroll-behavior: smooth; }
body {
  font-family: var(--font-body);
  font-size: clamp(1rem, .96rem + .18vw, 1.075rem);
  line-height: 1.68;
  color: var(--text);
  background: transparent;
  overflow-x: hidden;
  min-height: 100%;
}
img, svg { max-width: 100%; }
img { height: auto; border: 0; }
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 900;
  line-height: 1.06;
  letter-spacing: .02em;
  margin: 0;
  text-wrap: balance;
}
p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; }
li { list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--sky-bright);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: fixed; top: 10px; left: 10px; z-index: 200;
  transform: translateY(-160%);
  background: var(--poseidon); color: #fff;
  padding: .7em 1.2em; border-radius: var(--r-sm);
  font-weight: 700; letter-spacing: .04em;
  transition: transform .2s var(--ease-out);
}
.skip-link:focus-visible { transform: translateY(0); }

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ================================================================== SCENE */
#scene {
  position: fixed;
  /* top-anchored with a CONSTANT height — never `inset: 0`, which tracks the
     dynamic viewport and made the whole scene jump when the phone browser
     bar collapsed (see SCENE GEOMETRY IS svh above) */
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(120% 70% at 50% 34%, rgba(46, 127, 196, .10), transparent 60%),
    linear-gradient(180deg,
      #05080E 0%, #070D18 20%, #0B1A2C 34%, #10314F 39%,
      #0B2138 46%, #071426 66%, #040A12 100%);
}
@supports (height: 1lvh) {
  #scene { height: 100lvh; }
}
#scene canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
#ocean { z-index: 1; }
/* #surf sits at the same layer as the trident but later in the DOM, so the
   waterline it paints closes over the submerged prongs. */
#surf  { z-index: 3; }

#godray {
  position: absolute;
  left: 50%;
  /* --vp-slack lifts every bottom anchor off the scene's lvh bottom edge to
     the visible (svh) one — see SCENE GEOMETRY IS svh */
  bottom: calc(var(--waterline) + var(--vp-slack));
  width: min(100vw, 1400px);
  /* The ray's stops are percentages of its own height, so this length sets how
     far the shaft reaches above the waterline. It is scene geometry like the
     rest of it: svh, or the ray stands ~27% taller than designed on a phone
     while the trident inside it is the right size. Plain vh is the fallback. */
  height: 150vh;
  transform: translate(-50%, 0);
  z-index: 2;
  opacity: 0;
  background:
    radial-gradient(26% 20% at 50% 100%, rgba(191, 219, 245, .34), transparent 72%),
    radial-gradient(7% 46% at 50% 100%, rgba(159, 203, 242, .20), transparent 74%),
    radial-gradient(15% 30% at 50% 100%, rgba(159, 203, 242, .10), transparent 78%);
  filter: blur(10px);
  mix-blend-mode: screen;
}
@supports (height: 1svh) {
  #godray { height: 150svh; }
}

#tridentWrap {
  position: absolute;
  left: 50%;
  bottom: calc(var(--waterline) + var(--vp-slack));
  height: var(--trident-h);
  /* Stated, not shrink-wrapped: #trident is a canvas, and a canvas with a
     percentage height contributes no intrinsic width while this absolutely
     positioned box is sizing itself — the wrap collapsed to 0 wide. 0.6083
     is the sprite's own ratio, 660/1085; script.js carries the same number
     as its pre-layout fallback. */
  width: calc(var(--trident-h) * 0.6083);
  z-index: 3;
  transform: translate(-50%, 0);
  will-change: transform, opacity;
}
#trident {
  height: 100%;
  width: 100%;
  display: block;
  filter:
    drop-shadow(0 0 18px rgba(159, 203, 242, .35))
    drop-shadow(0 14px 30px rgba(0, 0, 0, .75));
}
#tridentGlow {
  position: absolute;
  left: 50%; bottom: -6%;
  width: 340%; height: 62%;
  transform: translateX(-50%);
  background: radial-gradient(50% 50% at 50% 50%, rgba(126, 183, 232, .40), rgba(0, 90, 168, .16) 45%, transparent 72%);
  filter: blur(12px);
  opacity: 0;
  mix-blend-mode: screen;
}

#lightning {
  position: absolute; inset: 0; z-index: 5;
  opacity: 0;
  background: linear-gradient(180deg, rgba(203, 228, 255, .62), rgba(160, 200, 245, .16) 38%, transparent 62%);
  mix-blend-mode: screen;
}

#vignette {
  position: absolute; inset: 0; z-index: 6;
  background:
    radial-gradient(130% 95% at 50% 42%, transparent 38%, rgba(3, 6, 11, .58) 100%),
    linear-gradient(180deg, rgba(4, 8, 14, .55) 0%, transparent 22%, transparent 72%, rgba(4, 8, 14, .60) 100%);
}

/* skip intro control */
.skip-intro {
  position: fixed;
  right: clamp(16px, 3vw, 34px);
  bottom: clamp(16px, 3vw, 34px);
  z-index: 120;
  display: inline-flex;
  align-items: center;
  gap: .6em;
  padding: .78em 1.25em;
  border-radius: var(--r-pill);
  border: 1px solid rgba(159, 203, 242, .34);
  background: rgba(8, 14, 22, .72);
  backdrop-filter: blur(8px);
  color: var(--sky-bright);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transition: background .2s ease, border-color .2s ease, color .2s ease;
}
.skip-intro[hidden] { display: none; }
.skip-intro:hover { background: rgba(0, 90, 168, .55); border-color: var(--sky); color: #fff; }

/* ================================================================= HEADER */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 90;
  background: rgba(6, 11, 18, .74);
  backdrop-filter: blur(16px) saturate(130%);
  border-bottom: 1px solid rgba(127, 182, 232, .12);
  transition: background .3s ease, border-color .3s ease;
}
.intro-armed .site-header { transform: translateY(-102%); opacity: 0; }
/* On a short viewport (landscape phone, small window) the hero call button
   sits below the fold and scroll is locked for the intro, so staging the
   header away leaves NO phone number on screen for ~5 seconds. Someone mid-
   emergency gets the header instead; the intro plays on underneath it. */
@media (max-height: 520px) {
  .intro-armed .site-header { transform: none; opacity: 1; }
}
.site-header.is-scrolled { background: rgba(5, 9, 15, .92); }

.header-inner {
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 10px var(--gutter);
  /* viewport-fit=cover lets the page run under the notch in landscape; these
     keep the brand and the call button out from under it. No-ops elsewhere. */
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
  padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 28px);
}

.brand { display: flex; align-items: center; gap: 11px; margin-right: auto; }
.brand-mark { width: 40px; height: 40px; flex: none; filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .6)); }
.brand-text { display: flex; flex-direction: column; line-height: 1; }
.brand-name {
  font-family: var(--font-display);
  font-size: 1.14rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--foam);
}
.brand-sub {
  margin-top: 3px;
  font-size: .58rem;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--sky);
}

.nav-desktop { display: flex; align-items: center; gap: clamp(14px, 1.8vw, 26px); }
.nav-desktop a {
  position: relative;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-mute);
  padding: 6px 0;
  white-space: nowrap;
  transition: color .2s ease;
}
.nav-desktop a::after {
  content: "";
  position: absolute; left: 0; right: 100%; bottom: 0;
  height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--azure), var(--sky));
  transition: right .28s var(--ease-out);
}
.nav-desktop a:hover { color: var(--foam); }
.nav-desktop a:hover::after { right: 0; }

.header-actions { display: flex; align-items: center; gap: 10px; }

.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: rgba(12, 22, 36, .6);
  cursor: pointer;
}
.nav-toggle-bars { display: block; width: 20px; }
.nav-toggle-bars i {
  display: block; height: 2px; border-radius: 2px;
  background: var(--sky-bright);
  transition: transform .28s var(--ease-out), opacity .2s ease;
}
.nav-toggle-bars i + i { margin-top: 5px; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars i:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav-panel {
  /* not display:block until the hand-off query below says so — see the note
     there. The reset's [hidden] rule still carries the open/closed state. */
  display: none;
  border-top: 1px solid var(--line);
  background: rgba(5, 9, 15, .97);
  padding: 18px var(--gutter) 26px;
  /* Fills the viewport rather than hanging as a short flap. The panel tint is
     .97, so whatever it covers is gone; what it did NOT cover stayed at full
     strength, and the menu grew a secondary group — which put the panel's own
     call button a few pixels above the hero's identical one, reading as a
     duplicate rather than as page behind a menu. Owning the height is cheaper
     than a scrim and makes the foot's position meaningful. */
  min-height: calc(100vh - 66px);
  max-height: calc(100vh - 66px);
  /* dvh where the browser has it: on iOS, 100vh is the height WITH the
     toolbar collapsed, so the panel overran the visible area and the call
     button pinned to its foot landed under the toolbar. Older browsers keep
     the vh line above. */
  min-height: calc(100dvh - 66px);
  max-height: calc(100dvh - 66px);
  /* the foot clears the home indicator on notched phones */
  padding-bottom: calc(26px + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
}
.nav-panel nav { display: flex; flex-direction: column; }
.nav-panel nav a {
  padding: 14px 2px;
  border-bottom: 1px solid rgba(127, 182, 232, .10);
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text);
}
.nav-panel nav a:hover { color: var(--sky-bright); }

/* The panel keeps all seven destinations, in two groups rather than one flat
   run of links: the four the header carries, then the three that came out of
   it. The split is a second <nav> so it exists in the accessible tree too —
   named by its own heading, against the first landmark's "Mobile" — and the
   heading borrows the footer columns' label voice (.72rem/800/.24em in
   --sky), which is the type this site already uses to head a short list of
   links. The group reads quieter than the four above it: the same links one
   step down in size and in --text-mute rather than --text, which is the
   difference between "primary" and "also here" without a second border. */
.nav-panel-more { margin-top: 24px; }
.nav-panel-more h2 {
  margin-bottom: 6px;
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--sky);
}
.nav-panel-more a { font-size: .86rem; color: var(--text-mute); }

/* margin-top:auto pins the call to the bottom of a now full-height panel;
   the 20px floor keeps it off the last link when the list is long enough to
   scroll. */
.nav-panel-foot { margin-top: auto; padding-top: 20px; display: grid; gap: 10px; justify-items: start; }
.nav-panel-mail { color: var(--sky); font-size: .92rem; word-break: break-word; }
.nav-panel-mail:hover { color: var(--sky-bright); text-decoration: underline; }
.nav-panel-hours { color: var(--text-dim); font-size: .85rem; }

/* ------------------------------------------ the hand-off to the hamburger
   The header row is brand | four nav links | call button, inside the same
   content box the sections below use. Every number here was measured in a
   container with no Segoe UI, so the stack falls back to DejaVu Sans — the
   widest face it can land on, about 9% wider across the nav labels than the
   Segoe UI / Arial a real visitor reads. They are worst case on purpose:

     · the row stops fitting below 743px on work.html and below 726px on
       index and faq (work.html reserves 15px for a scrollbar with
       scrollbar-gutter). Under those widths the call button leaves its
       padding box and the brand and the first link close up together.
     · at 768px the brand clears the first link by 37.6px on work.html and
       52.6px on the other two, with 15.4px between the last link and the
       call button: three groups, not one crowd.
     · in Arial metrics that same row already fits at 721px with 33.5px of
       brand clearance, and at 768px it has 75.8px of it — so a real visitor
       reads about 38px more air than these numbers admit to.

   So the fold is 767px — the last width that cannot hold the row with room
   to breathe — and tablet portrait keeps the real nav. It was 1180px, set
   when the nav carried seven items and the row needed ~795px of a 1180px
   box; the four it carries now need ~600px, and the old number was handing
   the hamburger 400px of width it did not need. Gone with it: the block of
   compensations that used to sit further down this file (a tighter nav gap,
   0.015em off the tracking, .75rem type). That was width bought for items
   six and seven, and without them the nav goes back to the rhythm the rest
   of the header was drawn to.

   This is the only place .nav-desktop is hidden — two media queries hiding
   one element is two places to find when the breakpoint next moves, and the
   one you miss is the one that wins. (work.css still carries a page-scoped
   copy of the old 1180px hand-off for work.html, which is why that page
   folds early; it wants deleting, and that file was outside this change.)

   The panel hangs off the same query rather than a second one: above the
   fold there is no toggle to open it, and script.js only closes an open
   panel on a resize past 1080px, so a rotate from portrait to landscape
   would otherwise leave it stranded under a full nav. */
@media (max-width: 767px) {
  .nav-desktop { display: none; }
  .nav-toggle { display: inline-flex; }
  /* flex, not block: the foot's margin-top:auto needs a column to push against. */
  .nav-panel:not([hidden]) { display: flex; flex-direction: column; }
}

/* ================================================================ BUTTONS */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  padding: .92em 1.55em;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: .8rem;
  font-weight: 800;
  letter-spacing: .11em;
  text-transform: uppercase;
  cursor: pointer;
  white-space: nowrap;
  transition: transform .18s var(--ease-out), background .2s ease,
              border-color .2s ease, box-shadow .2s ease, color .2s ease;
}
.btn svg { flex: none; }
.btn-lg { padding: 1.05em 1.9em; font-size: .84rem; }
.btn-block { width: 100%; }

.btn-primary {
  background: linear-gradient(180deg, #1E76C6 0%, var(--poseidon) 55%, #00447F 100%);
  color: #fff;
  border-color: rgba(191, 219, 245, .28);
  box-shadow: 0 14px 30px -16px rgba(0, 90, 168, .95), inset 0 1px 0 rgba(255, 255, 255, .25);
}
.btn-primary:hover {
  background: linear-gradient(180deg, #3A8FDC 0%, #0C69BB 55%, #005096 100%);
  transform: translateY(-2px);
  box-shadow: 0 20px 38px -18px rgba(46, 127, 196, .95), inset 0 1px 0 rgba(255, 255, 255, .3);
}
.btn-primary:active { transform: translateY(0); }

.btn-ghost {
  background: rgba(11, 20, 32, .5);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-color: var(--line-strong);
  color: var(--sky-bright);
}
/* the hero is explicitly out of the shared-glass scheme; its buttons keep the
   softer 6px they were tuned against the bare sea with */
.hero .btn-ghost {
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.btn-ghost:hover {
  background: rgba(0, 90, 168, .26);
  border-color: var(--sky);
  color: #fff;
  transform: translateY(-2px);
}

.btn-call {
  padding: .72em 1.15em;
  font-size: .76rem;
  color: var(--sky-bright);
  border-color: var(--line-strong);
  background: rgba(0, 90, 168, .18);
}
.btn-call:hover { background: var(--poseidon); color: #fff; border-color: var(--sky); }

/* ========================================================== CONTENT LAYER */
/* The page's content layer, above the fixed ocean. This used to live on <main>,
   but the frosted sheet has to reach past </main> and cover the footer too, so
   the positioning context moved out one level to .deep (main + footer). main
   itself is left unpositioned on purpose: that is what makes .deep the
   containing block for .deep-frost. The clip is what lets .deep-frost be sized
   as height:100% (see below) without that overshoot growing the page. */
.deep { position: relative; z-index: 1; isolation: isolate; overflow: clip; }

/* =================================================================== HERO */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  /* The trident hangs off --waterline, which is a viewport height, so it moves
     down the screen as the window gets taller. The copy used to be pinned to
     the bottom behind a padding that stopped growing at 78px, so on a tall
     display the two drifted apart and left a dead gap under the tip.
     Anchoring the block to the waterline instead keeps that gap the same
     fraction of the screen at every height — which only holds if this offset
     is measured in the same unit the waterline is (see SCENE GEOMETRY IS svh).
     The vh line is the fallback; the svh restatement is directly below. */
  justify-content: flex-start;
  align-items: center;
  padding: 0 var(--gutter) clamp(30px, 4vh, 56px);
  padding-top: calc(100vh - var(--waterline) + 4.5vh);
  text-align: center;
}
@supports (height: 1svh) {
  .hero { padding-top: calc(100svh - var(--waterline) + 4.5svh); }
}
.hero-inner { width: 100%; max-width: 860px; position: relative; }
/* The hero copy used to sit on a large radial scrim. Over a moving sea it
   read as a dark oval blob travelling with the text — obvious the moment the
   page scrolled. Legibility is carried by the type itself instead: a tight
   shadow on each block, which costs nothing and has no shape of its own.
   (It was also the one element in the hero measured against 100vw, i.e.
   against a width that includes the scrollbar, while everything around it is
   laid out in the narrower content width.) */

.hero-title,
.hero-eyebrow,
.hero-tagline,
.hero-copy { text-shadow: 0 1px 2px rgba(2, 6, 12, .55), 0 6px 22px rgba(2, 6, 12, .62); }
.hero-eyebrow {
  margin-bottom: clamp(10px, 1.6vh, 16px);
  font-size: clamp(.72rem, 1.35vw, .84rem);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--sky);
}
.hero-title {
  font-size: clamp(2.1rem, 6.4vw, 4.4rem);
  letter-spacing: .045em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 6px 34px rgba(0, 0, 0, .75), 0 0 60px rgba(46, 127, 196, .30);
}
.hero-line { display: block; }
.hero-line + .hero-line {
  font-size: .84em;
  color: var(--sky-bright);
  letter-spacing: .1em;
}
.hero-title .ch { display: inline-block; white-space: pre; }

.hero-tagline {
  margin-top: clamp(12px, 2vh, 20px);
  font-family: var(--font-display);
  font-size: clamp(.95rem, 2.6vw, 1.35rem);
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--steel);
}
.hero-copy {
  margin: clamp(14px, 2.4vh, 22px) auto 0;
  max-width: 62ch;
  /* --text, not --text-mute: this paragraph sits on the bare ocean above the
     waterline, with no frost sheet behind it, and the crests move — measured
     against real composited frames, 18.7% of the glyph area fell under the
     4.5:1 line with the muted token, and WHICH words failed changed second to
     second. Full --text holds ~8:1 on the same frames. Everything below the
     waterline keeps --text-mute; behind the frost it measures 8:1 already. */
  color: var(--text);
  font-size: clamp(.96rem, 1.5vw, 1.08rem);
  text-shadow: 0 2px 14px rgba(0, 0, 0, .7);
}
.hero-copy strong { color: var(--sky-bright); font-weight: 700; }

.hero-cta {
  margin-top: clamp(22px, 3.4vh, 34px);
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
}

.hero-chips {
  margin-top: clamp(20px, 3vh, 30px);
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  justify-content: center;
}
.hero-chips li {
  padding: .5em 1em;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: rgba(9, 16, 26, .5);
  backdrop-filter: blur(6px);
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--text-mute);
}

/* The scroll cue.
   Centring is done with auto margins, NOT translateX(-50%): the intro drives
   this element's transform as it lifts into view and finally sets it to
   `none`, which silently wiped a transform-based centring the moment the
   scene settled — the cue has been sitting half its own width right of centre.
   It also sat 14px off the bottom edge, close enough to read as clipped.
   The connector line only appears where there is genuinely room for it: on a
   900px-tall window the hero stack already reaches to within ~64px of the
   bottom, and the full 50px cue would land on the chips. */
.hero-scroll {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(28px, 3.4vh, 40px);
  width: max-content;
  margin-inline: auto;
  /* an 18px-wide chevron is not a tap target; the box is centred by
     margin-inline:auto so symmetric padding widens it in place */
  padding-inline: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: var(--text-dim);
  transition: color .2s ease;
}
.hero-scroll span {
  display: none; width: 1px; height: 26px;
  background: linear-gradient(180deg, transparent, var(--azure));
}
/* 1000px is measured, not chosen: at 960 the 50px cue leaves only 10px between
   itself and the chips, at 1000 it leaves 28px. */
@media (min-height: 1000px) {
  .hero-scroll span { display: block; }
}
.hero-scroll:hover { color: var(--sky); }
.hero-scroll svg { animation: nudge 2.6s ease-in-out infinite; }
@keyframes nudge { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }

/* intro staging ------------------------------------------------------- */
/* Pre-first-frame state while the intro is armed. Every one of these
   properties is then driven per-frame from JS, so the sequence renders
   correctly at any frame rate and never leaves content stranded. */
.intro-armed .hero-inner > * { opacity: 0; }
.intro-armed .hero-scroll { opacity: 0; }
.intro-armed .hero-title .ch { opacity: 0; transform: translateY(-.5em) scale(1.45); }

body.is-locked { overflow: hidden; }

/* ============================================== THE BELOW-HERO GLASS SHEET */
/* Everything under the waterline is frosted glass over the moving water, and
   it is ONE piece of glass — a single element, a single backdrop-filter, a
   single tint, running from the hero's bottom edge to the last pixel of the
   footer.

   It used to be seven: .band::before on each section plus the footer's own
   background, all with identical tint and blur, butting edge to edge. That
   still showed a line at every junction, for two reasons:

   1. backdrop-filter is resampled per element. Chromium blurs the backdrop
      inside the element's own bounds, so within a blur radius of a top or
      bottom edge the blur weakens and the raw water starts to show through.
      Two frosted boxes meeting therefore met halo-to-halo: a ~3px band where
      both were under-blurred, measuring ~9% darker than the glass on either
      side of it. No gap and no overlap — the tint was continuous — but the
      seam was there, and it was there at every junction.
   2. Some bands and the footer added hairline rules of their own on top of
      that, which is what made those junctions the loudest.

   One element has no internal edges, so neither failure has anywhere to
   happen. Its own two edges are still there, but they are harmless: the top
   one is masked to zero alpha (the waterline fade below), and the bottom one
   is the end of the document. The per-card and per-panel glass (.card,
   .request-hours, .form-panel, .btn-ghost) is untouched — those are panes
   sitting ON this sheet, and their edges are drawn on purpose. */
.deep-frost {
  position: absolute;
  /* top and bottom are deliberately both left auto. That is the one case where
     an absolutely positioned box keeps its static position — exactly where it
     sits in the flow, i.e. the hero's bottom edge — and the height is taken
     from the height property. Nothing is measured and nothing has to be kept
     in sync with the hero, which is the point: the hero is 100svh tall on a
     desktop but taller than the window on a phone, so no fixed offset works.
     height:100% is .deep's full height, so the sheet is guaranteed to reach
     past the last footer row; the surplus (one hero) hangs off the bottom and
     is taken off by .deep's overflow:clip. */
  left: 0;
  right: 0;
  height: 100%;
  z-index: -1;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  /* The hero's live ocean runs behind the top edge. Instead of a drawn wave
     divider sitting on top of the animation, the sheet simply fades up out of
     the water over --wl-h so the boundary reads as depth, not as a graphic.
     The fade is a mask rather than a gradient in the background, because the
     blur has to ramp with the tint — a flat backdrop-filter under a fading
     tint would put a hard, perfectly horizontal frost edge across the water.
     It also takes the element's own top edge to zero alpha, which is what
     keeps the resampling halo of rule 1 above off the screen. */
  -webkit-mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, .42) calc(var(--wl-h) * .55),
    rgba(0, 0, 0, .82) var(--wl-h),
    #000 calc(var(--wl-h) + 190px));
  mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, .42) calc(var(--wl-h) * .55),
    rgba(0, 0, 0, .82) var(--wl-h),
    #000 calc(var(--wl-h) + 190px));
}

/* ================================================================== BANDS */
/* Bands are now pure layout — spacing and a positioning context for their own
   contents. The glass behind them is .deep-frost, not theirs. */
.band { position: relative; padding: var(--sec-y) 0; }
/* clears the waterline fade before any copy starts */
.band-services { padding-top: calc(var(--sec-y) * .55 + var(--wl-h)); }

.sec-head { max-width: 760px; margin: 0 auto clamp(34px, 4vw, 54px); text-align: center; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 12px;
  font-size: .7rem; font-weight: 700;
  letter-spacing: .28em; text-transform: uppercase;
  color: var(--sky);
  margin-bottom: 16px;
}
.eyebrow .rule {
  width: 30px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--poseidon), var(--sky));
}
.sec-head h2, .band h2 {
  font-size: clamp(1.85rem, 4.1vw, 3rem);
  text-transform: uppercase;
  letter-spacing: .025em;
  color: #fff;
}
.sec-sub {
  margin-top: 18px;
  color: var(--text-mute);
  font-size: clamp(1rem, 1.4vw, 1.1rem);
}

/* =================================================================== CARD */
.card {
  position: relative;
  background: var(--card-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-card);
  transition: transform .28s var(--ease-out), border-color .28s ease, box-shadow .28s ease;
}
.card::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(120% 80% at 50% 0%, rgba(127, 182, 232, .10), transparent 60%);
  opacity: 0;
  transition: opacity .28s ease;
}
.card:hover {
  transform: translateY(-4px);
  border-color: var(--line-strong);
  box-shadow: 0 34px 60px -34px rgba(0, 0, 0, .95), 0 0 0 1px rgba(127, 182, 232, .06), inset 0 1px 0 rgba(255, 255, 255, .07);
}
.card:hover::after { opacity: 1; }

/* =============================================================== SERVICES */
/* Four services, so the grid is a 2x2 quad rather than the 3-up row it was
   when there were seven cards: three-up would have left a single orphan on
   the second row, and four-up inside the 1180px wrap gives each card ~190px
   of copy measure — two lines of title and a nine-line paragraph. The quad
   also lets the card go horizontal (icon beside the copy, below), which is
   what makes a 535px-wide card look deliberate instead of empty. */
.svc-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 1.8vw, 22px);
}
.svc { padding: clamp(24px, 2.4vw, 32px); }
/* icon beside the copy, but only while the card is wide enough to earn it */
@media (min-width: 961px) {
  .svc {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: clamp(18px, 1.8vw, 24px);
    align-items: start;
  }
  .svc-icon { grid-row: 1 / span 2; margin-bottom: 0; }
}
.svc-icon {
  display: grid; place-items: center;
  width: 58px; height: 58px;
  border-radius: 15px;
  background: linear-gradient(160deg, rgba(0, 90, 168, .35), rgba(14, 42, 71, .55));
  border: 1px solid rgba(127, 182, 232, .22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08);
  margin-bottom: 20px;
}
.svc-icon svg { width: 36px; height: 36px; display: block; }
.svc h3 {
  font-size: 1.02rem;
  letter-spacing: .055em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 11px;
}
/* Even out the icon-to-copy rhythm only in the stacked two-up band, where the
   titles wrap to different line counts side by side. In the horizontal card
   above 960px the title sits on one line and a min-height would just push the
   paragraph off the icon's baseline. */
@media (min-width: 621px) and (max-width: 960px) { .svc h3 { min-height: 2.4em; } }
.svc p { color: var(--text-mute); font-size: .96rem; line-height: 1.62; }

/* ================================================================== SCOPE */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 2vw, 26px);
}
.scope-card { overflow: hidden; display: flex; flex-direction: column; }
.scope-art {
  background: linear-gradient(180deg, #0A1522, #060D16);
  border-bottom: 1px solid var(--line);
}
.scope-art svg { display: block; width: 100%; height: auto; }
.scope-body { padding: clamp(24px, 2.6vw, 34px); }
.scope-kicker {
  font-size: .7rem; font-weight: 700;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--sky);
  margin-bottom: 10px;
}
.scope-body h3 {
  font-size: clamp(1.2rem, 2.1vw, 1.55rem);
  text-transform: uppercase;
  letter-spacing: .035em;
  color: #fff;
  margin-bottom: 14px;
}
.scope-body > p { color: var(--text-mute); font-size: .99rem; }

.ticks { margin-top: 22px; display: grid; gap: 11px; }
.ticks li {
  position: relative;
  padding-left: 30px;
  font-size: .94rem;
  color: var(--text);
}
.ticks li::before {
  content: "";
  position: absolute; left: 0; top: .34em;
  width: 17px; height: 17px;
  border-radius: 50%;
  border: 1px solid rgba(127, 182, 232, .45);
  background:
    linear-gradient(180deg, rgba(46, 127, 196, .35), rgba(0, 90, 168, .2));
}
.ticks li::after {
  content: "";
  position: absolute; left: 5px; top: .62em;
  width: 7px; height: 4px;
  border-left: 2px solid var(--sky-bright);
  border-bottom: 2px solid var(--sky-bright);
  transform: rotate(-45deg);
}
.ticks-inline { display: flex; flex-wrap: wrap; gap: 10px 26px; }

/* ==================================================================== WHY */
.why-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 1.8vw, 22px);
}
.why { padding: clamp(22px, 2.2vw, 30px); }
.why-icon {
  display: grid; place-items: center;
  width: 46px; height: 46px;
  margin-bottom: 16px;
}
.why-icon svg { width: 40px; height: 40px; }
.why h3 {
  font-size: .96rem; letter-spacing: .06em; text-transform: uppercase;
  color: #fff; margin-bottom: 9px;
}
.why p { color: var(--text-mute); font-size: .93rem; line-height: 1.6; }

/* ====================================================== COMMON QUESTIONS */
/* The homepage's three featured answers, sitting directly under the six .why
   cards. Three more cards in a grid would have read as a second helping of the
   same course, so the band changes rhythm instead: full-width rows, question
   on the left and answer on the right, which is the shape of the FAQ page it
   leads to and a deliberate breath before the map splits the page in two.

   No new glass. The rows are plain .card, so the tint, blur, border, shadow
   and hover lift are the ones every other card on the page already uses, and
   nothing new is stacked on the single .deep-frost sheet (see THE BELOW-HERO
   GLASS SHEET above — a second frosted surface is what puts seams in it).

   The marker is the .eyebrow rule stood on its end: same gradient, same 2px
   radius, already the page's way of saying "a section starts here". It costs
   no new artwork and it repeats down the list the way a list marker should. */
.faq-teasers { display: grid; gap: clamp(13px, 1.5vw, 18px); }

/* The two-column split is what keeps both halves at a readable measure. One
   column across the 1180px wrap would set the summaries ~110 characters wide;
   side by side they land near 60, and the questions — one of which is 84
   characters — get three lines instead of one very long one. Below 880px
   there is no width to split, so the answer drops under its question and the
   rule spans both rows. */
.faq-teaser-link {
  display: grid;
  grid-template-columns: 3px minmax(0, .92fr) minmax(0, 1.18fr) auto;
  grid-template-areas: "rule question answer go";
  align-items: start;
  column-gap: clamp(18px, 2.2vw, 32px);
  row-gap: 12px;
  padding: clamp(20px, 2vw, 28px);
  border-radius: inherit;
}
.faq-teaser-rule {
  grid-area: rule;
  align-self: stretch;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--poseidon), var(--sky));
  opacity: .8;
  transition: opacity .28s ease;
}
/* Sentence case, unlike every other h3 here, because this one is a question
   somebody asks out loud rather than a label on a card — and 84 characters of
   uppercase Arial Black is a wall. The display family and the white keep it in
   the same voice as the rest; only the shouting is dropped. */
.faq-teaser-q {
  grid-area: question;
  font-size: clamp(1.02rem, 1.25vw, 1.14rem);
  line-height: 1.26;
  letter-spacing: .012em;
  color: #fff;
}
.faq-teaser-a {
  grid-area: answer;
  color: var(--text-mute);
  font-size: .95rem;
  line-height: 1.6;
}
.faq-teaser-go {
  grid-area: go;
  align-self: center;
  display: flex;
  color: var(--sky);
  transition: color .2s ease;
}
.faq-teaser-go svg { transition: transform .2s var(--ease-out); }
.faq-teaser:hover .faq-teaser-rule { opacity: 1; }
.faq-teaser:hover .faq-teaser-go { color: var(--sky-bright); }
.faq-teaser:hover .faq-teaser-go svg { transform: translateX(4px); }

@media (max-width: 880px) {
  .faq-teaser-link {
    grid-template-columns: 3px minmax(0, 1fr) auto;
    grid-template-areas:
      "rule question go"
      "rule answer   answer";
  }
  .faq-teaser-go { align-self: start; margin-top: .15em; }
}

.faq-all { margin-top: clamp(28px, 3vw, 40px); text-align: center; }

/* =================================================================== AREA */
.area-inner {
  display: grid;
  grid-template-columns: minmax(0, .95fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 62px);
  align-items: center;
}
.area-map {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--sh-pop);
  background: #08131F;
}
.area-map svg { display: block; width: 100%; height: auto; }
/* The map is drawn in a 640-unit viewBox, so its type scales with the box.
   Below ~520px the box is under 470px wide and 16-unit town names fall under
   12px — so on phones the labels come up and the second-tier towns (the ones
   the roads already imply) drop out rather than collide with the larger type. */
@media (max-width: 520px) {
  .area-map .mp-town { font-size: 20px; }
  .area-map .mp-state { font-size: 15px; letter-spacing: 2.6px; }
  .area-map .mp-minor,
  .area-map .mp-terr { display: none; }
}
.area-copy .eyebrow { margin-bottom: 14px; }
.area-copy h2 { text-align: left; }
.area-copy > p { margin-top: 18px; color: var(--text-mute); }
.area-copy strong { color: var(--sky-bright); }

.area-facts {
  margin-top: 30px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px 22px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
}
.area-facts dt {
  font-size: .66rem; font-weight: 700;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--sky);
  margin-bottom: 5px;
}
.area-facts dd { font-size: .95rem; color: var(--text); overflow-wrap: anywhere; }
.area-facts .wide { grid-column: 1 / -1; }
.area-facts a { color: var(--text); border-bottom: 1px solid var(--line-strong); }
.area-facts a:hover { color: var(--sky-bright); border-color: var(--sky); }

/* ================================================================ REQUEST */
.request-inner {
  display: grid;
  grid-template-columns: minmax(0, .82fr) minmax(0, 1fr);
  gap: clamp(30px, 4vw, 64px);
  align-items: start;
}
.request-intro h2 { text-align: left; margin-bottom: 18px; }
.request-intro > p { color: var(--text-mute); }
.inline-link { color: var(--sky-bright); border-bottom: 1px solid var(--line-strong); font-weight: 600; }
.inline-link:hover { border-color: var(--sky); }

.request-points { margin-top: 28px; display: grid; gap: 14px; }
.request-points li {
  display: flex; align-items: baseline; gap: 14px;
  font-size: .95rem;
  color: var(--text);
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(127, 182, 232, .10);
}
.request-points span {
  font-family: var(--font-display);
  font-size: .78rem;
  letter-spacing: .1em;
  /* --azure measured 4.1:1 through the lighter glass; --sky is what every
     other small label on the page already uses */
  color: var(--sky);
}
.request-mail {
  margin-top: 26px;
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--sky);
  font-size: .95rem;
  word-break: break-word;
}
.request-mail:hover { color: var(--sky-bright); text-decoration: underline; }

.request-hours {
  margin-top: 30px;
  padding: 22px 24px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--poseidon);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--card-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}
.request-hours h3 {
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--sky);
  margin-bottom: 14px;
}
.request-hours dl { display: grid; gap: 12px; }
.request-hours dl > div {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 4px 16px;
  align-items: baseline;
}
.request-hours dt { font-size: .88rem; color: var(--text-mute); }
.request-hours dd { font-size: .9rem; font-weight: 600; color: var(--text); text-align: right; }

.form-panel {
  background: linear-gradient(180deg, rgba(26, 40, 58, .46), rgba(9, 16, 25, .58));
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-pop);
  padding: clamp(24px, 3vw, 40px);
}
.form-panel form { display: grid; gap: 18px; }
.field-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
/* align-content keeps the control at the top of its cell: side-by-side fields
   stretch to the taller of the two, and without it the shorter column's input
   grew to fill the space left by a shorter error message. */
.field { display: grid; gap: 7px; align-content: start; }

/* -------------------------------------------------------- mode segmented */
/* Two very different intakes behind one control. Radio semantics rather than
   tabs: the choice is a property of the request ("who is asking"), and it is
   the first thing the form asks — the panel below is its answer, not a
   separate view of the same content. */
.form-modes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  padding: 6px;
  margin-bottom: 24px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: rgba(5, 10, 17, .5);
}
.mode-btn {
  appearance: none;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: transparent;
  padding: .78em .7em;
  font-size: .74rem;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-mute);
  cursor: pointer;
  text-align: center;
  line-height: 1.25;
  transition: background .2s ease, color .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.mode-btn:hover { color: var(--sky-bright); background: rgba(0, 90, 168, .16); }
.mode-btn[aria-checked="true"] {
  background: linear-gradient(180deg, #1E76C6 0%, var(--poseidon) 55%, #00447F 100%);
  border-color: rgba(191, 219, 245, .28);
  color: #fff;
  box-shadow: 0 10px 22px -14px rgba(0, 90, 168, .95), inset 0 1px 0 rgba(255, 255, 255, .22);
}
.mode-btn:focus-visible { outline: 2px solid var(--sky-bright); outline-offset: 2px; }
.mode-hint {
  margin: -12px 0 4px;
  font-size: .84rem;
  color: var(--text-mute);
}

/* ------------------------------------------------------- checkbox groups */
.field-group { display: grid; gap: 10px; border: 0; padding: 0; margin: 0; min-width: 0; }
.field-group > legend {
  padding: 0;
  font-size: .72rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-mute);
}
.check-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.check-sm {
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  border-radius: var(--r-sm);
}
.check-sm .check-box { width: 19px; height: 19px; border-radius: 5px; margin-top: 0; }
.check-sm .check-box svg { width: 12px; height: 12px; }
.check-sm .check-text { font-size: .87rem; line-height: 1.4; color: var(--text); }
.field-group.has-error .check { border-color: var(--sky-bright); background: rgba(46, 127, 196, .12); }
.field label {
  font-size: .72rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-mute);
}
.req { color: var(--sky); }
.check-optional { color: var(--text-dim); font-weight: 600; letter-spacing: .08em; text-transform: none; }

.field input,
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  /* 16px, not .97rem (15.52px): iOS Safari zooms the whole page into any
     control under 16px the moment it is focused, and the visitor has to
     pinch back out to see the form. The .48px is invisible; the zoom is not. */
  font-size: 1rem;
  color: var(--text);
  background: rgba(5, 10, 17, .62);
  border: 1px solid rgba(127, 182, 232, .18);
  border-radius: var(--r-sm);
  padding: .82em .95em;
  transition: border-color .2s ease, box-shadow .2s ease, background .2s ease;
  appearance: none;
}
.field textarea { resize: vertical; min-height: 118px; line-height: 1.6; }
/* one step up from the old #6E8398: measured against the lighter form-panel
   glass that tone landed at 4.3:1, this holds 5:1 without competing with a
   real value typed into the field */
.field input::placeholder,
.field textarea::placeholder { color: #7A8FA6; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: rgba(127, 182, 232, .3); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--sky);
  background: rgba(7, 14, 24, .8);
  box-shadow: 0 0 0 3px rgba(46, 127, 196, .26);
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--sky-bright); outline-offset: 2px;
}

.select-wrap { position: relative; display: block; }
.select-wrap select { padding-right: 2.6em; cursor: pointer; }
.select-wrap option, .select-wrap optgroup { background: #0B1420; color: var(--text); }
.select-wrap optgroup { font-weight: 800; letter-spacing: .08em; color: var(--sky); }
.select-caret {
  position: absolute; right: 12px; top: 50%;
  transform: translateY(-50%);
  color: var(--sky);
  pointer-events: none;
}

.field.has-error input,
.field.has-error select,
.field.has-error textarea {
  border-color: var(--sky-bright);
  background: rgba(46, 127, 196, .12);
  box-shadow: 0 0 0 3px rgba(191, 219, 245, .18);
}
.err {
  display: flex; align-items: flex-start; gap: 7px;
  font-size: .84rem;
  font-weight: 600;
  color: var(--sky-bright);
}
.err[hidden] { display: none; }
.err::before {
  content: "!";
  flex: none;
  display: grid; place-items: center;
  width: 16px; height: 16px;
  margin-top: 2px;
  border-radius: 50%;
  background: var(--sky-bright);
  color: #06121F;
  font-size: .68rem;
  font-weight: 900;
}

.form-status {
  margin: 0;
  padding: .85em 1em;
  border-radius: var(--r-sm);
  border: 1px solid var(--sky);
  background: rgba(46, 127, 196, .16);
  color: var(--sky-bright);
  font-size: .9rem;
  font-weight: 600;
}
.form-status[hidden] { display: none; }

.check {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 13px;
  padding: 16px 18px;
  border: 1px solid rgba(127, 182, 232, .18);
  border-radius: var(--r-md);
  background: rgba(5, 10, 17, .5);
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease;
}
.check:hover { border-color: var(--line-strong); background: rgba(0, 90, 168, .12); }
.check input { position: absolute; opacity: 0; width: 0; height: 0; }
.check-box {
  flex: none;
  display: grid; place-items: center;
  width: 22px; height: 22px;
  margin-top: 1px;
  border-radius: 6px;
  border: 1px solid var(--line-strong);
  background: rgba(6, 12, 20, .8);
  color: transparent;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.check input:checked + .check-box {
  background: var(--poseidon);
  border-color: var(--sky);
  color: #fff;
}
.check input:focus-visible + .check-box { outline: 2px solid var(--sky-bright); outline-offset: 2px; }
.check-text { font-size: .92rem; color: var(--text-mute); line-height: 1.55; }
.check-text strong { display: block; color: var(--text); font-weight: 700; }
.check-note {
  margin-top: -8px;
  padding: 12px 16px;
  border-left: 3px solid var(--sky);
  background: rgba(46, 127, 196, .12);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: .88rem;
  color: var(--sky-bright);
}
.check-note[hidden] { display: none; }
.check-note a { text-decoration: underline; font-weight: 700; }

.form-fine { font-size: .78rem; color: var(--text-dim); text-align: center; }

/* Honeypot. Off-screen by clip rather than by display:none or visibility:hidden
   — both of those are cheap for a bot to detect, and neither leaves a field a
   naive form-filler will populate. One CSS pixel, out of flow, so it can cause
   neither a layout shift nor a scrollbar. It is never focusable in practice:
   tabindex="-1" and aria-hidden on the element keep it out of the tab order and
   off the accessibility tree, so the only thing that ever types in it is a bot. */
.hp-field {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* Submit button, mid-flight. The spinner is a flex item sized in em, and at
   1em it is shorter than the button's own line box, so switching it on cannot
   change the button's height — the panel does not move under the pointer. */
.btn[disabled] { cursor: progress; opacity: .78; }
.btn[disabled]:hover { transform: none; }
.btn.is-sending::before {
  content: "";
  flex: none;
  width: 1em; height: 1em;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .32);
  border-top-color: #fff;
  animation: btn-spin .7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

.form-success { text-align: center; }
.form-success:focus { outline: none; }
.form-success:focus-visible { outline: 2px solid var(--sky); outline-offset: 8px; border-radius: 14px; }
.form-success[hidden] { display: none; }
.success-mark { display: block; margin: 0 auto 20px; width: 84px; }
.success-mark svg { width: 84px; height: 84px; }
.form-success h3 {
  font-size: clamp(1.5rem, 3vw, 2rem);
  text-transform: uppercase;
  letter-spacing: .05em;
  color: #fff;
  margin-bottom: 12px;
}
.form-success > p { color: var(--text-mute); max-width: 46ch; margin-inline: auto; }
.success-summary {
  margin: 28px auto;
  max-width: 440px;
  display: grid;
  gap: 1px;
  background: rgba(127, 182, 232, .14);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  text-align: left;
}
.success-summary > div {
  display: flex;
  gap: 16px;
  justify-content: space-between;
  padding: 12px 16px;
  background: rgba(7, 13, 21, .92);
}
.success-summary dt {
  font-size: .68rem; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--sky);
  flex: none;
  padding-top: 3px;
}
.success-summary dd { font-size: .93rem; color: var(--text); text-align: right; }
.success-actions {
  display: flex; flex-wrap: wrap; gap: 12px; justify-content: center;
  margin-bottom: 20px;
}

/* Delivery-failed panel. Same panel, same geometry, same type — only the mark
   changes, from the blue check to a steel notice. Brand accent rule is blue +
   steel and nothing else, so "something went wrong" is carried by dropping the
   blue rather than by borrowing a red the brand does not own. */
.form-fallback h3 { color: var(--foam); }
.fallback-back { margin: -6px 0 18px; }
.link-btn {
  background: none;
  border: 0;
  padding: 4px 2px;
  font: inherit;
  font-size: .86rem;
  color: var(--sky);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.link-btn:hover { color: var(--sky-bright); }
.link-btn:focus-visible { outline: 2px solid var(--sky-bright); outline-offset: 3px; border-radius: 4px; }

/* ================================================================= FOOTER */
.site-footer {
  position: relative;
  z-index: 1;
  /* The footer sits on the same sheet of glass as the sections above it —
     .deep-frost runs under it — so it carries no background, no blur and no
     rule of its own; that combination was the third visible seam. It does
     carry the page's smallest, dimmest type, and at --glass-bg the old
     --text-dim (#7C8FA4) measures 3.9:1 against the brightest patch of blurred
     water — under AA. Lifting the dim tone inside the footer only, rather than
     densening the tint, keeps the glass consistent and puts the small print
     back at 5.2:1. */
  --text-dim: #93A6BA;
  padding-top: clamp(52px, 6vw, 80px);
}
.footer-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .92fr) minmax(0, .82fr) minmax(0, 1.16fr);
  gap: clamp(26px, 3vw, 44px);
  padding-bottom: clamp(38px, 4vw, 56px);
}
.footer-logo { width: min(190px, 60%); height: auto; display: block; }
.footer-tag {
  margin-top: 18px;
  max-width: 30ch;
  color: var(--text-dim);
  font-size: .92rem;
  font-style: italic;
}
.footer-col h2 {
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--sky);
  margin-bottom: 16px;
}
.footer-col ul { display: grid; gap: 10px; }
.footer-col a {
  color: var(--text-mute);
  font-size: .93rem;
  /* same trick as .link-arrow: 18px text becomes a 24px target, no shift */
  display: inline-block;
  padding-block: 3px;
  margin-block: -3px;
}
.footer-col a:hover { color: var(--sky-bright); }
.footer-contact { display: grid; gap: 12px; align-content: start; }
.footer-contact p { color: var(--text-dim); font-size: .9rem; line-height: 1.6; }
.footer-contact strong { color: var(--sky-bright); }
.footer-phone {
  font-family: var(--font-display);
  font-size: 1.32rem;
  letter-spacing: .04em;
  color: #fff;
}
.footer-phone:hover { color: var(--sky-bright); }
.footer-mail { color: var(--sky); font-size: .82rem; letter-spacing: -.005em; overflow-wrap: break-word; }
.footer-mail:hover { color: var(--sky-bright); text-decoration: underline; }

.footer-base {
  border-top: 1px solid rgba(127, 182, 232, .10);
  padding-top: 22px;
  padding-bottom: 30px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 26px;
  justify-content: space-between;
  color: var(--text-dim);
  font-size: .82rem;
}
.footer-note { color: var(--text-dim); }

/* ============================================================ ARROW LINKS */
/* The signposts into the work gallery. They are links, not buttons, on
   purpose: every one of them sits next to something louder (the hero CTA
   pair, a service card's title, the request form) and must read as an aside
   rather than compete. So they borrow the page's existing quiet link voice —
   .request-mail's inline-flex row, --sky at rest and --sky-bright on hover,
   the same 8-10px icon gap — and add only the arrow's 4px nudge, which is
   the one affordance that says "this goes somewhere else". */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* 19px of text is a thin thing to hit with a thumb. Pad the hit box to
     27px and pull the margin back the same amount so nothing moves. */
  padding-block: 4px;
  margin-block: -4px;
  color: var(--sky);
  font-size: .86rem;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1.4;
  transition: color .2s ease;
}
.link-arrow svg { flex: none; transition: transform .2s var(--ease-out); }
.link-arrow:hover { color: var(--sky-bright); }
.link-arrow:hover svg { transform: translateX(4px); }

/* Block-level placements: fit-content keeps the hit area on the words rather
   than the full card width, and lets margin-top behave like a block margin. */
.svc-link, .scope-link, .why-link, .hours-link { display: flex; width: fit-content; }
.svc-link   { margin-top: 18px; }
.scope-link { margin-top: 24px; }
.why-link   { margin-top: 13px; font-size: .82rem; }

/* Hero: a third action in the existing button row. Stretching to the row's
   height (the flex default) centres it against the two pills without adding
   a line, so the approved hero composition keeps its exact vertical rhythm;
   the extra left margin buys back the optical space a pill has as padding
   and a bare text link does not. It carries the same tight shadow as the
   rest of the hero copy because it, too, sits on open water. */
.hero-work {
  margin-left: 4px;
  padding-inline: 2px;
  color: var(--sky-bright);
  text-shadow: 0 1px 2px rgba(2, 6, 12, .65), 0 6px 22px rgba(2, 6, 12, .62);
}
.hero-work:hover { color: #fff; }

/* Request intro: one muted line of context with the link at its end. */
.request-nudge { margin-top: 16px; color: var(--text-mute); font-size: .93rem; }
.request-nudge .link-arrow { vertical-align: -.18em; }

/* The same muted line as .request-nudge, closing a band rather than opening
   a column: centred under the section it follows, on the sec-head's own
   axis. It carries What We Cover out of the service cards — one of the two
   sections the header stopped naming, so losing the header link costs a
   visitor a scroll rather than the section. */
.band-nudge {
  margin-top: clamp(26px, 3vw, 34px);
  text-align: center;
  color: var(--text-mute);
  font-size: .93rem;
}
.band-nudge .link-arrow { vertical-align: -.18em; }
/* Inside the hours panel the link is a last row under the definition list,
   the way .scope-link closes a scope card. */
.hours-link { margin-top: 18px; }

/* Service cards above 960px are icon-beside-copy grids whose icon spans the
   whole card. The link is a third row in the copy column, and the middle row
   takes the slack so all four links land on the same baseline across the
   2x2 quad instead of tracking each paragraph's length. */
@media (min-width: 961px) {
  .svc { grid-template-rows: auto minmax(0, 1fr) auto; }
  .svc-icon { grid-row: 1 / span 3; }
  .svc-link { grid-column: 2; }
}

/* The one-line privacy note under each submit button. Quiet on purpose: it is
   there to be found by someone who wants it, not to argue with the CTA above it. */
.form-privacy {
  margin: 12px 0 0;
  font-size: .78rem;
  line-height: 1.55;
  color: var(--text-dim);
  text-align: center;
}
.form-privacy a { color: var(--text-mute); text-underline-offset: 3px; }
.form-privacy a:hover { color: var(--sky); }

/* Standalone text links that are not inside a sentence still need a thumb-
   sized hit box (WCAG 2.5.8). Padding grows the target; the negative margin
   hands the space back so the layout does not move. */
dd > a[href^="tel:"],
.footer-note a,
.form-privacy a {
  display: inline-block;
  padding-block: 4px;
  margin-block: -4px;
}

/* ==================================================================== CHIPS
   The filter control, shared by the gallery's category row and the FAQ's. It
   lived in work.css and was copied into faq.css when the FAQ reused it, which
   is one control with two definitions and no way to notice them drifting. It
   belongs here, with the other things more than one page draws.

   The FAQ dims chips whose count has gone to zero (.chip.is-empty, in
   faq.css): that is its own behaviour, so the opacity transition is carried
   here and the rule that uses it stays there. */
.chip {
  display: inline-flex;
  align-items: baseline;
  gap: .55em;
  padding: .62em 1.15em;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: rgba(9, 16, 26, .55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--text-mute);
  cursor: pointer;
  white-space: nowrap;
  transition: color .2s ease, background .2s ease, border-color .2s ease, transform .18s var(--ease-out), opacity .2s ease;
}
.chip:hover {
  color: var(--sky-bright);
  border-color: var(--line-strong);
  background: rgba(0, 90, 168, .2);
  transform: translateY(-1px);
}
.chip[aria-pressed="true"] {
  background: linear-gradient(180deg, rgba(46, 127, 196, .4), rgba(0, 90, 168, .3));
  border-color: var(--sky);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16);
}
.chip-n {
  font-size: .68rem;
  font-weight: 800;
  letter-spacing: .06em;
  color: var(--sky);
}
.chip[aria-pressed="true"] .chip-n { color: var(--sky-bright); }

@media (max-width: 599px) {
  .chip {
    font-size: .7rem;
    letter-spacing: .1em;
    padding: .55em .9em;
    flex: 0 0 auto;
    scroll-snap-align: start;
  }
}

/* =============================================================== RESPONSE */
/* The nav's own hand-off to the hamburger is up with the nav, at 767px, and
   it is deliberately NOT repeated here. Two media queries hiding the same
   element is two places to find when the breakpoint next moves, and the one
   you miss is the one that wins. This block keeps only what is actually
   about this width: the footer dropping to two columns. */
@media (max-width: 1080px) {
  .footer-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-brand { grid-column: 1 / -1; }
}

@media (max-width: 960px) {
  .why-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .split { grid-template-columns: minmax(0, 1fr); }
  .area-inner, .request-inner { grid-template-columns: minmax(0, 1fr); }
  .area-map { order: 2; }
  .request-intro h2, .area-copy h2 { text-align: left; }
}

@media (max-width: 720px) {
  :root { --waterline: 64vh; --trident-h: 24vh; }
  @supports (height: 1svh) {
    :root { --waterline: 64svh; --trident-h: min(24svh, calc(100svh - var(--waterline) - 78px)); }
  }
  .btn-call-label { display: none; }
  .btn-call { padding: .72em .85em; }
  .hero { padding-bottom: 46px; }
  /* the hero stack already fills a phone screen — the cue would sit on the chips */
  .hero-scroll { display: none; }
  .hero-chips li { font-size: .68rem; letter-spacing: .09em; padding: .45em .8em; }
  .area-facts { grid-template-columns: minmax(0, 1fr); }
  .footer-base { flex-direction: column; }
}

@media (max-width: 620px) {
  .svc-grid, .why-grid { grid-template-columns: minmax(0, 1fr); }
  .field-row, .check-grid { grid-template-columns: minmax(0, 1fr); }
  .form-modes { grid-template-columns: minmax(0, 1fr); border-radius: var(--r-md); }
  .mode-btn { border-radius: var(--r-md); }
  .hero-cta .btn { width: 100%; }
  .success-summary > div { flex-direction: column; gap: 4px; }
  .success-summary dd { text-align: left; }
}

@media (max-width: 400px) {
  :root { --trident-h: 20vh; --waterline: 70vh; }
  @supports (height: 1svh) {
    :root { --waterline: 70svh; --trident-h: min(20svh, calc(100svh - var(--waterline) - 78px)); }
  }
  .footer-inner { grid-template-columns: minmax(0, 1fr); }
}

/* Short windows: the title is anchored to the bottom of the hero while the
   trident hangs off the waterline, so the two converge as the viewport gets
   shorter. Lift the waterline to keep clear air between tip and wordmark. */
@media (max-height: 880px) and (min-width: 721px) {
  :root { --waterline: 64vh; --trident-h: 24vh; }
  @supports (height: 1svh) {
    :root { --waterline: 64svh; --trident-h: min(24svh, calc(100svh - var(--waterline) - 78px)); }
  }
}
@media (max-height: 780px) and (min-width: 721px) {
  :root { --waterline: 67vh; --trident-h: 21vh; }
  @supports (height: 1svh) {
    :root { --waterline: 67svh; --trident-h: min(21svh, calc(100svh - var(--waterline) - 78px)); }
  }
}
/* Below ~880px of viewport the hero stack is taller than the window, so the
   cue would sit under the fold or on top of the chips whatever its offset.
   (Was 780px, which left an 780–880 band where it collided.) */
@media (max-height: 880px) and (min-width: 721px) {
  .hero-scroll { display: none; }
}
@media (max-height: 660px) and (min-width: 721px) {
  :root { --waterline: 71vh; --trident-h: 17vh; }
  @supports (height: 1svh) {
    :root { --waterline: 71svh; --trident-h: min(17svh, calc(100svh - var(--waterline) - 78px)); }
  }
  .hero-title { font-size: clamp(1.9rem, 4.6vw, 3rem); }
  .hero-copy { font-size: .94rem; max-width: 70ch; }
  .hero-chips { display: none; }
}

/* ========================================================= REDUCED MOTION */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .card:hover, .btn:hover { transform: none; }
  .hero-scroll svg { animation: none; }
}

/* ================================================================ ROTATE ASK
   A slab phone held sideways gives this page a 320-480px-tall window, and the
   scene is built tall — the trident shrinks to an icon and the bands turn to
   ribbon. So we ask, politely, for upright. The gate is the SHAPE, not the
   device name: coarse pointer + landscape + height <= 480px is exactly "a
   phone on its side" — an unfolded Z Fold or Pixel Fold is ~690px tall in
   landscape and never matches, tablets and desktops never match, and turning
   the phone back dismisses it with no script involved. The ask carries the
   call button, because the one visitor who must never be walled off is the
   one with water rising. Sits above everything (header 90, skip 120, lb 200). */
.rotate-ask { display: none; }
@media (pointer: coarse) and (orientation: landscape) and (max-height: 480px) {
  .rotate-ask {
    display: grid;
    position: fixed;
    inset: 0;
    z-index: 300;
    place-content: center;
    justify-items: center;
    gap: 10px;
    padding: 18px max(24px, env(safe-area-inset-left, 0px)) calc(18px + env(safe-area-inset-bottom, 0px)) max(24px, env(safe-area-inset-right, 0px));
    background: #05080D;
    text-align: center;
  }
}
.rotate-ask svg { color: var(--sky); margin-bottom: 2px; }
@media (prefers-reduced-motion: no-preference) {
  .rotate-ask svg { animation: rotate-nudge 2.4s ease-in-out infinite; }
  /* rests sideways — the visitor's current reality — and nudges upright,
     which is the request */
  @keyframes rotate-nudge {
    0%, 55%, 100% { transform: rotate(90deg); }
    70%, 85% { transform: rotate(0deg); }
  }
}
.rotate-ask h2 {
  font-family: var(--font-display);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-size: 1.15rem;
  color: var(--text);
  margin: 0;
}
.rotate-ask p {
  color: var(--text-mute);
  font-size: .92rem;
  line-height: 1.55;
  max-width: 44ch;
  margin: 0;
}
.rotate-ask .btn { margin-top: 8px; }
@media print { .rotate-ask { display: none !important; } }

/* ===================================================================== PRINT
   People print the page that has the diagrams on it and hand it to the person
   whose basement is wet. Without this block Chrome printed grey text and
   white headings on white paper, and spent sheet one on the ocean. faq.css
   and privacy.html carry their own equivalents. */
@media print {
  #scene, .deep-frost, .site-header, .skip-link, .nav-panel, .hero-scroll,
  .lb, #skipIntro { display: none !important; }
  html, body { background: #fff !important; }
  * { color: #000 !important; text-shadow: none !important; box-shadow: none !important; }
  .deep, .band, .card { background: none !important; }
  a { text-decoration: underline; }
}
