/* ==========================================================================
   NAVIGO site.css: the shared layer every section sits on.
   Tokens, base, the frame (header, sticky phone header, phone menu) and the
   shared classes copied from the canvas board helmets (snapshot v353,
   10 Oct 2026), one copy each. Mobile first: up to 767px follows the phone
   boards (390), 1024px and up follows the desktop boards (1280), values
   interpolate in between. Section styles live in assets/css/NN-name.css.
   Contract: Website/_build/port/CONTRACT.md
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens. The closed palette and its text tokens (canvas tokens.json,
   brand rulebook). #041027 is the only navy. No sixth colour.
   -------------------------------------------------------------------------- */
:root{
  color-scheme:dark;

  /* surfaces */
  --navy:#041027;          /* page, plates, ink on light. The only navy */
  --navy-900:#09214E;      /* panel and card fill only */
  --navy-800:#0A275C;      /* raised: fields, hover. Never lighter */
  --navy-700:#0D3175;      /* borders only, carries no text */
  --line:#0A2657;          /* hairline on cards and dividers */
  --line-strong:#123C74;   /* heavier divider, separator dot. Decorative */
  --line-control:#8C99A8;  /* border of any interactive control */

  /* the one accent and the blues */
  --teal:#17D4D0;          /* primary button, links, stars. 10% ceiling */
  --teal-hi:#2BF2EE;       /* teal hover, the energy spark */
  --teal-100:#074040;
  --teal-tonal:rgba(23,212,208,.16);  /* tonal teal button fill only (D-132) */
  --blue-600:#005FD6;      /* small controls only, never text */
  --blue-700:#0047A8;      /* pressed blue, chosen chip fill */
  --blue-300:#84B9FF;      /* blue as text or icon, focus ring */
  --blue-100:#082048;

  /* text */
  --bone:#F4F1EA;          /* headings and body on navy, 16.79:1 */
  --muted:#AFB8C2;         /* secondary text on flat navy, 9.43:1 */
  --muted-img:#B8C1CC;     /* secondary text over a photo only */
  --harbour:#8C99A8;       /* rules and dots. Never text */

  /* status signals, not brand colours */
  --success:#10BA80; --warning:#E98E24; --danger:#E58A85;

  /* glass: the tint is a measured floor, never lower (brand rulebook, Glass) */
  --glass-tint:.89;
  --nv-ga:.89;             /* price list and FAQ glass tint (D-154) */
  --glass-blur:16px;

  /* type */
  --font-display:"Space Grotesk",system-ui,-apple-system,sans-serif;
  --font-body:"Figtree",system-ui,-apple-system,sans-serif;
  --fs-h1:clamp(36px,calc(18.78px + 4.416vw),64px);   /* hero: 36 phone, 64 desktop */
  --fs-h2:clamp(30px,calc(23.85px + 1.577vw),40px);   /* section heading: 30 phone, 40 desktop */
  --fs-card:22px;          /* card heading */
  --fs-body:16px;
  --fs-body-card:15px;
  --fs-small:14px;
  --fs-fine:12px;          /* fine print and the caps label */

  /* space: 8px grid */
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px; --space-6:24px;
  --space-8:32px; --space-12:48px; --space-16:64px; --space-24:96px;
  --gutter:clamp(20px,calc(7.7px + 3.155vw),40px);        /* 20 phone, 40 desktop */
  --section-y:clamp(64px,calc(44.32px + 5.047vw),96px);   /* 64 phone, 96 desktop */
  --wrap:1140px;           /* desktop container: 1140 wide, 40px side padding, 1060 content */

  /* shape and motion */
  --radius:4px;            /* every corner. There is no pill */
  --spine-speed:4.2s;      /* the one speed of the energy family */
  --dur-hover:150ms;
  --dur-panel:250ms;

  /* frame */
  --header-h:68px;         /* phone header bar; 77px from 900px (see the header) */
  --header-safe:env(safe-area-inset-top,0px);              /* the notch, when the page runs edge to edge */
}
@media (min-width:900px){:root{--header-h:77px}}

/* --------------------------------------------------------------------------
   2. Fonts are loaded in page.html (Google Fonts, display=swap):
   Space Grotesk 400 500 600 700, Figtree 400 500 600 700 and 400 italic.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   3. Base and reset
   -------------------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{margin:0;background:var(--navy);color:var(--bone);font-family:var(--font-body);
  font-size:var(--fs-body);line-height:1.55}   /* no font-smoothing override: the boards render with the browser default */
h1,h2,h3,h4,p,ul,ol,figure,blockquote,dl,dd{margin:0}
img,video{display:block;max-width:100%;height:auto}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer}
[hidden]{display:none!important}
a{color:var(--teal)}
a:hover{color:var(--teal-hi)}
input::placeholder,textarea::placeholder{color:var(--muted);opacity:1}
::selection{background:var(--teal);color:var(--navy)}
main:focus{outline:none}

/* Focus: one ring everywhere, 2px #84B9FF, as on m01b and the price list. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{outline:2px solid var(--blue-300);outline-offset:2px}

/* --------------------------------------------------------------------------
   4. Layout helpers
   -------------------------------------------------------------------------- */
.nv-wrap{width:100%;max-width:var(--wrap);margin-inline:auto;
  padding-left:max(var(--gutter),env(safe-area-inset-left));
  padding-right:max(var(--gutter),env(safe-area-inset-right))}
.nv-section{position:relative;padding-block:var(--section-y)}
.nv-sr{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* Type helpers, the boards' recurring settings. Sections may also inline the board values. */
.nv-h1{font-family:var(--font-display);font-size:var(--fs-h1);line-height:1.08;font-weight:700;letter-spacing:-.02em;color:var(--bone)}
.nv-h2{font-family:var(--font-display);font-size:var(--fs-h2);line-height:1.08;font-weight:700;letter-spacing:-.02em;color:var(--bone);text-wrap:balance}
.nv-h3{font-family:var(--font-display);font-size:var(--fs-card);line-height:1.15;font-weight:700;letter-spacing:-.02em;color:var(--bone)}
.nv-eyebrow{font-family:var(--font-display);font-size:var(--fs-fine);line-height:1.55;font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}

/* Skip link */
.nv-skip{position:absolute;left:12px;top:-200px;z-index:100;padding:12px 20px;border-radius:var(--radius);
  background:var(--teal);color:var(--navy);font-family:var(--font-display);font-weight:500;text-decoration:none}
.nv-skip:focus,.nv-skip:focus-visible{top:12px;color:var(--navy)}
.nv-skip:hover{color:var(--navy)}

/* --------------------------------------------------------------------------
   5. Buttons shared by more than one section
   -------------------------------------------------------------------------- */
/* "Book your journey": one button, identical everywhere (D-132). Solid teal, navy label,
   WhatsApp icon left, Space Grotesk 16px 500, 48px tall, 12px by 26px. Add nv-btn for the hover. */
.nv-book{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:48px;
  padding:12px 26px;border:1px solid transparent;border-radius:var(--radius);background:var(--teal);color:var(--navy);
  font-family:var(--font-display);font-size:16px;font-weight:500;line-height:1.3;text-decoration:none;white-space:nowrap}
.nv-book:hover,.nv-book:focus-visible{color:var(--navy)}
.nv-book svg{flex-shrink:0}

/* Tonal teal: the one allowed second action (the nav number, D-132). Never the main action. */
.nv-tonal{display:inline-flex;align-items:center;gap:10px;min-height:44px;padding:10px 16px;
  border:1px solid var(--teal);border-radius:var(--radius);
  /* S9 (final check, 10 Oct): the tonal teal sits on a navy backing, so the bone label holds 7:1 over any hero photo */
  background:linear-gradient(var(--teal-tonal),var(--teal-tonal)),var(--navy);color:var(--bone);
  font-family:var(--font-display);font-size:15px;font-weight:500;letter-spacing:.02em;text-decoration:none;white-space:nowrap}
.nv-tonal:hover,.nv-tonal:focus-visible{color:var(--bone)}
.nv-tonal svg{flex-shrink:0;color:var(--teal)}

/* --------------------------------------------------------------------------
   6. Board helmet classes (v353), one copy each
   -------------------------------------------------------------------------- */

/* 6a. Light rims. The element needs position:relative (or absolute). The rim sits above
   the element's own content (z-index 2) so it lights the edge of a photo too. */
.rim::before{content:"";position:absolute;inset:0;z-index:2;border-radius:inherit;padding:1px;pointer-events:none;background:linear-gradient(162deg,rgba(244,241,234,.55),rgba(244,241,234,.07) 32%,rgba(244,241,234,.07) 68%,rgba(132,185,255,.45));-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude}
.rim-hi::before{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;background:linear-gradient(162deg,rgba(244,241,234,.8),rgba(244,241,234,.22) 30%,rgba(244,241,234,.12) 70%,rgba(132,185,255,.6));-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude}
@supports not ((mask-composite:exclude) or (-webkit-mask-composite:xor)){
  .rim::before,.rim-hi::before{background:none;border:1px solid rgba(244,241,234,.18);padding:0}
}

/* 6b. The energy border, the motion signature. One per screen, trust and booking moments only.
   The element needs position:relative. Off under reduced motion. */
@property --energy-a{syntax:"<angle>";inherits:false;initial-value:0deg}
.energy::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:1.5px;pointer-events:none;background:conic-gradient(from var(--energy-a),transparent 0deg 285deg,rgba(43,242,238,.35) 318deg,#2BF2EE 336deg,transparent 360deg);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;animation:energy var(--spine-speed,4.2s) linear infinite}
@keyframes energy{to{--energy-a:360deg}}
@media (prefers-reduced-motion:reduce){.energy::after{animation:none;opacity:0}}

/* 6c. Ambient glow pools and the floating photo tiles. Decorative layers: aria-hidden, no pointer. */
@keyframes glowbreathe{0%,100%{opacity:.7;transform:scale(1)}50%{opacity:1;transform:scale(1.08)}}
.glow{animation:glowbreathe 8.4s ease-in-out infinite}
.glow-late{animation-delay:-4.2s}
@keyframes floaty{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}
.float{animation:floaty 8.4s ease-in-out infinite}
.float-2{animation-delay:-2.8s}   /* Problem and Solution. Services uses -2.1s, -4.2s, -6.3s: scope those in 04-services.css */
.float-3{animation-delay:-5.6s}
@media (prefers-reduced-motion:reduce){.glow,.float{animation:none}}

/* 6d. NAVIGO MICRO-INTERACTIONS. 150ms ease-out for hover and press. Colours, an arrow icon and a
   photo's brightness only: no label, price or phone number ever moves. */
.nv-btn{transition:background-color 150ms ease-out,filter 150ms ease-out}
.nv-btn:active{filter:brightness(.92)}
.nv-link{transition:color 150ms ease-out}
.nv-link .nv-arrow{transition:transform 150ms ease-out}
.nv-nav a{background:linear-gradient(#2BF2EE,#2BF2EE) left bottom / 0 2px no-repeat;transition:background-size 150ms ease-out}
.nv-card .nv-img{transition:filter 150ms ease-out}
.nv-field{transition:border-color 150ms ease-out}
.nv-chip{transition:background-color 150ms ease-out,color 150ms ease-out,border-color 150ms ease-out}
@media (hover:hover){
  .nv-btn:hover{background:#2BF2EE!important}
  .nv-link:hover{color:#F4F1EA!important}
  .nv-link.nv-link-bone:hover{color:#2BF2EE!important}
  .nv-link:hover .nv-arrow{transform:translateX(3px)}
  .nv-nav a:hover{background-size:100% 2px}
  .nv-card:hover .nv-img{filter:brightness(1.06)}
  .nv-field:hover{border-bottom-color:#B8C1CC!important}
}
.nv-field:focus-visible{border-bottom-color:#17D4D0!important}
@media (prefers-reduced-motion:reduce){
  .nv-btn,.nv-link,.nv-link .nv-arrow,.nv-nav a,.nv-card .nv-img,.nv-field,.nv-chip{transition:none!important}
}

/* 6e. NAVIGO SCROLL REVEAL. Visible by default: nothing here hides content unless the script adds
   .nv-pre. Default tempo is Blacklane 1s; html[data-nv-tempo="250"] makes site.js add .nv-t250. */
.nv-rv{--nv-d:56px;--nv-dx:56px;--nv-dur:1000ms;--nv-ease:cubic-bezier(.25,.46,.45,.94);--nv-step:150ms}
.nv-rv.nv-t250{--nv-dur:250ms;--nv-ease:ease-out;--nv-step:50ms}
@media (min-width:768px){.nv-rv.nv-t250:not(.nv-soft){--nv-d:24px;--nv-dx:24px}}
.nv-rv.nv-soft{--nv-d:16px}
.nv-rv.nv-pre .nv-it,.nv-rv.nv-solo.nv-pre{opacity:0;transform:translate3d(0,var(--nv-d),0);transition:none}
.nv-rv.nv-pre .nv-it.nv-l{transform:translate3d(calc(var(--nv-dx) * -1),0,0)}
.nv-rv.nv-pre .nv-it.nv-r{transform:translate3d(var(--nv-dx),0,0)}
.nv-rv.nv-in .nv-it,.nv-rv.nv-solo.nv-in{opacity:1;transform:none;transition:opacity var(--nv-dur) var(--nv-ease),transform var(--nv-dur) var(--nv-ease)}
.nv-rv.nv-in .nv-d1{transition-delay:var(--nv-step)}
.nv-rv.nv-in .nv-d2{transition-delay:calc(var(--nv-step) * 2)}
.nv-rv.nv-in .nv-d3{transition-delay:calc(var(--nv-step) * 3)}
.nv-rv.nv-in .nv-d4{transition-delay:calc(var(--nv-step) * 4)}
@media (max-width:767px){.nv-rv{--nv-d:16px;--nv-dx:16px}}
/* keyboard focus inside a waiting block shows it at once */
.nv-rv.nv-pre:focus-within .nv-it,.nv-rv.nv-solo.nv-pre:focus-within{opacity:1;transform:none;transition:none}
@media (prefers-reduced-motion:reduce),print{
  .nv-rv .nv-it,.nv-rv.nv-solo{opacity:1!important;transform:none!important;transition:none!important}
}

/* 6f. (Retired 11 Oct, D-186.) The phone card stack and its D-163 dwell are gone: Problem and Solution are
   plain lists and Services is a swipe row (6i). No section uses .nv-stk any more. */

/* 6g. NAVIGO GLASS on the price list and FAQ (D-154). The D-105 glass, square and shadowless: a tint
   at .89 (--nv-ga), blur(16px) saturate(120%), the 162deg light rim and a faint top sheen. Tinted
   with the panel blue so cards keep their weight; it sits over the light field behind the section. */
.nv-glass{position:relative;border-radius:4px;background:linear-gradient(180deg,rgba(244,241,234,.06),rgba(244,241,234,0) min(46%,120px)),rgba(9,33,78,var(--nv-ga,.89));-webkit-backdrop-filter:blur(16px) saturate(120%);backdrop-filter:blur(16px) saturate(120%)}
.nv-glass::before{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;background:linear-gradient(162deg,rgba(244,241,234,.55),rgba(244,241,234,.07) 32%,rgba(244,241,234,.07) 68%,rgba(132,185,255,.45));-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude}
.nv-glass-soft{-webkit-backdrop-filter:blur(16px) saturate(120%);backdrop-filter:blur(16px) saturate(120%)}
/* Inner glass on the price list pane: smoked a touch darker than the pane (so grey text keeps 7:1
   over the light behind), with a top sheen and a softer rim. */
.nv-frost{position:relative;background:linear-gradient(180deg,rgba(244,241,234,.03),rgba(244,241,234,0) 40%),rgba(4,16,39,.16)!important;border-color:transparent!important}
.nv-frost::before{content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;pointer-events:none;background:linear-gradient(162deg,rgba(244,241,234,.38),rgba(244,241,234,.06) 32%,rgba(244,241,234,.06) 68%,rgba(132,185,255,.34));-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude}
@supports not ((mask-composite:exclude) or (-webkit-mask-composite:xor)){
  .nv-glass::before{background:none;border:1px solid rgba(244,241,234,.18);padding:0}
  .nv-frost::before{background:none;border:1px solid rgba(244,241,234,.18);padding:0}
}

/* 6h. Disclosures (price list and FAQ). Hide the native marker; the sections draw their own icon. */
summary{list-style:none}
summary::-webkit-details-marker{display:none}

/* 6i. NAVIGO SWIPE ROW, phones only (D-165 Services, D-166 price list areas, D-167 FAQ topics,
   D-168 How it works). A row that scrolls sideways on its own; the page never does. Native scroll
   with CSS snap: no library, no autoplay. The row bleeds to both screen edges and snaps each item to
   the content edge (the last one to the far edge), so the next item peeks in.
   - .nv-swipe on the row: a swipe row below 768px, always.
   - .nv-swipe-auto on the row: a swipe row only from its 4th child up (by :has(), or by the class
     .nv-swipe-on that the section's script adds where :has() is missing); below that the row keeps
     its section's own layout. No count is typed anywhere else.
   - --nv-swipe-l and --nv-swipe-r: how far the row's content edge sits from the screen edge. Default:
     the page gutter (a row inside .nv-wrap). A row inside a padded panel sets its own.
   - Each section sizes its own items (width or flex-basis) and sets its own gap.
   - .nv-swipe-hint: the muted "Swipe for ..." line above a row, two-way arrow icon (aria-hidden),
     phones only. .nv-swipe-hint--auto shows only while the auto row beside it (same parent) swipes.
   Scripts that move a row (a button, a tap, focus) use row.scrollTo, never scrollIntoView (which can
   move the page), smooth, and behavior 'auto' under prefers-reduced-motion. */
.nv-swipe-hint{display:none}
@media (max-width:767px){
  /* :not(nv-x) lifts the row rule to one type selector (0,0,1): it beats the ul/ol reset above, and
     any section rule with a class still beats it. nv-x is not an element; it only weighs the rule. */
  :where(.nv-swipe,.nv-swipe-auto:has(> :nth-child(4)),.nv-swipe-auto.nv-swipe-on):not(nv-x){
    --nv-swipe-l:max(var(--gutter),env(safe-area-inset-left));
    --nv-swipe-r:max(var(--gutter),env(safe-area-inset-right));
    display:flex;flex-wrap:nowrap;
    margin-left:calc(var(--nv-swipe-l) * -1);margin-right:calc(var(--nv-swipe-r) * -1);
    padding-left:var(--nv-swipe-l);padding-right:var(--nv-swipe-r);
    overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding-inline:var(--nv-swipe-l) var(--nv-swipe-r);
    scrollbar-width:none}
  :where(.nv-swipe,.nv-swipe-auto:has(> :nth-child(4)),.nv-swipe-auto.nv-swipe-on)::-webkit-scrollbar{display:none}
  :where(.nv-swipe,.nv-swipe-auto:has(> :nth-child(4)),.nv-swipe-auto.nv-swipe-on) > *{flex:0 0 auto;scroll-snap-align:start}
  :where(.nv-swipe,.nv-swipe-auto:has(> :nth-child(4)),.nv-swipe-auto.nv-swipe-on) > :last-child{scroll-snap-align:end}

  .nv-swipe-hint{display:flex;align-items:center;gap:8px;margin:0;font-family:var(--font-body);font-size:14px;
    font-weight:500;line-height:1.4;color:var(--muted)}   /* 9.4:1 on navy, AAA */
  .nv-swipe-hint svg{flex-shrink:0}
  .nv-swipe-hint--auto{display:none}
  :where(:has(> .nv-swipe-auto > :nth-child(4))) > .nv-swipe-hint--auto,
  .nv-swipe-hint--auto.nv-swipe-on{display:flex}
}
/* Previous and Next under a swipe row of big cards (Services, How it works): a panel with the light
   rim (add .rim), square corners, two 44px buttons with chevrons, centred. Hidden from 768px and
   without JavaScript (ship it with the hidden attribute; the section script removes it). Each button
   moves one card; at either end it is aria-disabled and dimmed (still about 4:1 on the panel). */
.nv-swipe-ctrl{display:none}
@media (max-width:767px){
  .nv-swipe-ctrl{position:relative;display:flex;gap:4px;width:max-content;margin:24px auto 0;padding:4px;
    border-radius:var(--radius);background:var(--navy-900)}
  .nv-swipe-ctrl__btn{display:flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:0;
    border-radius:var(--radius);background:transparent;color:var(--bone);
    transition:background-color 150ms ease-out,opacity 150ms ease-out}
  .nv-swipe-ctrl__btn[aria-disabled="true"]{opacity:.5;cursor:default}
}
@media (max-width:767px) and (hover:hover){
  .nv-swipe-ctrl__btn:not([aria-disabled="true"]):hover{background:var(--navy-800)}
}
@media (prefers-reduced-motion:reduce){.nv-swipe-ctrl__btn{transition:none}}

/* 6j. ONE CONTINUOUS BACKGROUND (D-174, Bobby 11 Oct: "one continuous background without these harsh
   lines separating the sections"). The page carries the one navy (body); sections are transparent; and
   every section's glow layer fades to nothing over --nv-glow-fade at its section's top and bottom edges,
   so no light pool is ever cut off at a straight line and none can reach a neighbour's text (the section
   still clips sideways). A section that adds a glow layer adds it to this list. Checked by
   _System/port/tools/seams.sh (every boundary at or under 2 levels). Glass panels with their own edge
   (price list, FAQ) are inside their sections and stay. */
:root{--nv-glow-fade:clamp(96px,12vw,160px)}
:where(#problem .pb-glows,#solution .sl-glows,#services .sv-glows,#pricelist .pl-glows,#about .ab-glows,
  #faq .faq__glows,#book .bk__glows,.ft .ft__glows){
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 var(--nv-glow-fade),#000 calc(100% - var(--nv-glow-fade)),transparent 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 var(--nv-glow-fade),#000 calc(100% - var(--nv-glow-fade)),transparent 100%)}

/* --------------------------------------------------------------------------
   7. The header. From 900px: logo, nav, number, 77px, absolute over the hero photo and
   transparent (D-127), never sticky. Below 900px (D-164, Blacklane's phone pattern): 68px,
   logo left, "Book now" and the menu button right, fixed to the top at every scroll position.
   On the homepage it is transparent over the hero at the very top, as the boards draw it, and
   turns to the brand glass once the page scrolls past 8px (site.js adds .nv-scrolled). On the
   subpages it is glass from the start (subpage.css). With JavaScript off it is always glass.
   -------------------------------------------------------------------------- */
.nv-header{position:absolute;top:0;left:0;right:0;z-index:30;height:var(--header-h)}
.nv-header__bar{height:var(--header-h);display:flex;align-items:center;justify-content:space-between;gap:24px}
.nv-logo{display:flex;align-items:center;min-height:44px;color:var(--bone);text-decoration:none;flex-shrink:0}
.nv-logo img{width:120.9px;height:18px}   /* phone (D-169): 18px tall, by the logo's own 6.714 ratio */
.nv-header__nav,.nv-header__call{display:none}
.nv-header__nav{gap:32px}
.nv-header__nav a{color:var(--bone);font-size:15px;font-weight:500;padding:12px 2px;text-decoration:none}
.nv-header__nav a:hover{color:var(--bone)}

/* "Book now" (D-164, sized by D-169 to Blacklane's proportions): the solid teal primary, compact.
   Solid teal at every scroll position, first screen included (D-170, Bobby): a named exception to
   the one-primary-CTA rule. Never tone it down to tonal, outline or ghost.
   Phones and tablets only; the journey page (book.html, the booking step itself) has its own send
   button, so it hides there. The link itself is the 44px tall tap area and is transparent; the
   32px teal pill is drawn on its ::before, so the target stays 44px while the button looks small.
   Hover, press and the focus ring are drawn on the pill too. */
.nv-booknow{position:relative;isolation:isolate;display:inline-flex;align-items:center;justify-content:center;
  height:44px;margin-left:auto;padding:0 12px;border:0;background:transparent;color:var(--navy);
  font-family:var(--font-display);font-size:14px;font-weight:600;line-height:1;letter-spacing:0;text-decoration:none;white-space:nowrap}
.nv-booknow::before{content:"";position:absolute;left:0;right:0;top:6px;bottom:6px;z-index:-1;border-radius:var(--radius);
  background:var(--teal);transition:background-color 150ms ease-out,filter 150ms ease-out}
.nv-booknow:hover,.nv-booknow:focus-visible{color:var(--navy)}
.nv-booknow:focus-visible{outline:none}
.nv-booknow:focus-visible::before{outline:2px solid var(--blue-300);outline-offset:2px}
@media (hover:hover){.nv-booknow:hover::before{background:var(--teal-hi)}}
.nv-booknow:active::before{filter:brightness(.92)}
.nv-journey .nv-booknow{display:none}

/* The menu button (D-169): a 44px tap area around a quiet 32px square (a soft bone tint, no border),
   an 18px icon on a thinner stroke. Open, the square takes the panel navy and a blue edge. */
.nv-menu-btn{position:relative;isolation:isolate;display:none;align-items:center;justify-content:center;flex-shrink:0;
  width:44px;height:44px;margin-right:-6px;padding:0;border:0;background:transparent;color:var(--bone)}
.nv-menu-btn::before{content:"";position:absolute;left:6px;top:6px;width:32px;height:32px;z-index:-1;box-sizing:border-box;
  border:1px solid transparent;border-radius:var(--radius);background:rgba(244,241,234,.1);
  transition:background-color 340ms cubic-bezier(.3,0,.2,1),border-color 340ms cubic-bezier(.3,0,.2,1)}   /* D-177 v2: in step with the icon */
.nv-menu-btn svg{width:18px;height:18px;stroke-width:1.75}
.nv-js .nv-menu-btn{display:flex}   /* without JavaScript the menu cannot open, so the button is not shown */
.nv-menu-btn:focus-visible{outline:none}
.nv-menu-btn:focus-visible::before{outline:2px solid var(--blue-300);outline-offset:2px}
@media (hover:hover){.nv-menu-btn:hover::before{background:rgba(244,241,234,.16)}}
.nv-menu-btn[aria-expanded="true"]::before{border-color:var(--blue-300);background:var(--navy-900);transition-duration:400ms}
/* The icon morphs (D-177, smoothed in v2): one drawing of three bars. Opening, the outer bars turn about their
   own centres and slide to the middle while the middle bar fades, 400ms ease-in-out (cubic-bezier(.3,0,.2,1)).
   Closing runs it back in 340ms; the middle bar fades back in over 280ms from 60ms, as the bars uncross.
   The bars are 16 long and the old X's strokes 16.97, so scaleX(1.0607) lands on the old close icon exactly.
   Reduced motion: it simply swaps. */
.nv-menu-btn .nv-i-bar{transform-box:fill-box;transform-origin:center;
  transition:transform 340ms cubic-bezier(.3,0,.2,1),opacity 280ms cubic-bezier(.3,0,.2,1) 60ms}
.nv-menu-btn[aria-expanded="true"] .nv-i-bar{transition:transform 400ms cubic-bezier(.3,0,.2,1),opacity 240ms cubic-bezier(.3,0,.2,1)}
.nv-menu-btn[aria-expanded="true"] .nv-i-bar--top{transform:translateY(5px) rotate(45deg) scaleX(1.0607)}
.nv-menu-btn[aria-expanded="true"] .nv-i-bar--mid{opacity:0}
.nv-menu-btn[aria-expanded="true"] .nv-i-bar--bot{transform:translateY(-5px) rotate(-45deg) scaleX(1.0607)}
@media (prefers-reduced-motion:reduce){.nv-booknow::before,.nv-menu-btn::before,.nv-menu-btn .nv-i-bar,.nv-menu-btn[aria-expanded] .nv-i-bar{transition:none}}

@media (max-width:899px){
  .nv-header{position:fixed;height:calc(var(--header-h) + var(--header-safe));padding-top:var(--header-safe)}
  .nv-header__bar{gap:6px}   /* + the menu button's 6px inner margin = 12px between Book now and the menu square */
  /* the brand glass (rulebook, Glass): navy at .89, blur(16px) saturate(120%), no shadow, square.
     It sits on ::before so it can fade in 150ms; the light rim runs along the bottom edge only. */
  .nv-header::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
    background:rgba(4,16,39,var(--glass-tint,.89));
    -webkit-backdrop-filter:blur(var(--glass-blur,16px)) saturate(120%);backdrop-filter:blur(var(--glass-blur,16px)) saturate(120%);
    opacity:0;transition:opacity 150ms ease-out}
  .nv-header::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;pointer-events:none;
    background:linear-gradient(90deg,rgba(244,241,234,.55),rgba(244,241,234,.07) 32%,rgba(244,241,234,.07) 68%,rgba(132,185,255,.45));
    opacity:0;transition:opacity 150ms ease-out}
  .nv-header.nv-scrolled::before,.nv-header.nv-scrolled::after,
  html:not(.nv-js) .nv-header::before,html:not(.nv-js) .nv-header::after{opacity:1}
  /* in-page jumps (#services, #pricelist, #about) and keyboard focus stop below the fixed header */
  html{scroll-padding-top:calc(var(--header-h) + var(--header-safe) + 12px)}
}
@media (max-width:359px){
  /* 320 to 359px: the logo a touch smaller so logo, Book now and the menu never crowd */
  .nv-logo img{width:107.4px;height:16px}
}
@media (prefers-reduced-motion:reduce){.nv-header::before,.nv-header::after{transition:none}}

@media (min-width:900px){
  .nv-logo img{width:201.4px;height:30px}
  .nv-header__nav,.nv-header__call{display:flex}
  .nv-js .nv-menu-btn,.nv-booknow{display:none}
}

/* The phone menu: a scrim under the header and a glass panel (m01b-hero-v2). */
.nv-menu{position:absolute;left:0;right:0;top:calc(var(--header-h) + var(--header-safe));height:100vh;height:100dvh;z-index:29}
.nv-menu__scrim{position:absolute;inset:0;background:rgba(4,16,39,.72)}
.nv-menu__panel{position:absolute;left:var(--gutter);right:var(--gutter);top:0;display:flex;flex-direction:column;
  padding:8px 16px 16px;border-radius:var(--radius);background:rgba(9,33,78,.96);
  -webkit-backdrop-filter:blur(20px) saturate(140%);backdrop-filter:blur(20px) saturate(140%)}
.nv-menu__link{display:flex;align-items:center;min-height:52px;border-bottom:1px solid var(--line-strong);
  color:var(--bone);font-size:18px;font-weight:500;text-decoration:none}
.nv-menu__link:hover{color:var(--bone)}
.nv-menu__link:last-of-type{border-bottom:0}
.nv-menu__call{justify-content:center;min-height:48px;margin-top:12px;font-size:16px}
/* The menu's motion (D-177; v2 "like butter", 11 Oct). Opacity and transform only, on even curves, and every
   fade runs 280ms or longer, so nothing pops.
   Open: the scrim fades in over 450ms and the panel over 420ms, both on ease, cubic-bezier(.25,.1,.25,1) (seen
   at once, never a pop: under a tenth of the way per frame); the panel settles
   from 16px up at 97% (scaled from its top edge) over 540ms on a long, soft ease-out, cubic-bezier(.33,.8,.25,1).
   The five rows rise 12px in turn, 50ms apart from 110ms in (fade 400ms, rise 440ms); the last settles at 750ms.
   Close, on an even ease-in-out, cubic-bezier(.37,0,.63,1): the rows fade together over 280ms, a little ahead
   of the panel, which fades and lifts 8px over 340ms; the scrim takes 360ms.
   The panel's blur (backdrop-filter) is on only at rest: site.js adds .nv-menu--glass once the open has finished
   and takes it off as the close starts. A live blur under a moving layer is what drops frames on a phone, and
   the panel is 96% opaque, so the blur is barely seen anyway. will-change is set only while the menu moves.
   site.js adds .nv-menu--open, swaps it for .nv-menu--closing on close and sets [hidden] only once the close
   has finished. Without JavaScript the menu never shows. */
.nv-js .nv-menu{pointer-events:none}
.nv-js .nv-menu.nv-menu--open{pointer-events:auto}
.nv-js .nv-menu__scrim{opacity:0}
.nv-js .nv-menu__panel{opacity:0;transform:translateY(-16px) scale(.97);transform-origin:50% 0;
  -webkit-backdrop-filter:none;backdrop-filter:none}
.nv-js .nv-menu__panel>*{opacity:0;transform:translateY(12px)}
.nv-menu--open .nv-menu__scrim,.nv-menu--open .nv-menu__panel,.nv-menu--open .nv-menu__panel>*{opacity:1;transform:none}
.nv-menu--open .nv-menu__scrim{transition:opacity 450ms cubic-bezier(.25,.1,.25,1)}
.nv-menu--open .nv-menu__panel{transition:opacity 420ms cubic-bezier(.25,.1,.25,1),transform 540ms cubic-bezier(.33,.8,.25,1)}
.nv-menu--open .nv-menu__panel>*{transition:opacity 400ms cubic-bezier(.25,.1,.25,1),transform 440ms cubic-bezier(.33,.8,.25,1)}
.nv-menu--open .nv-menu__panel>:nth-child(1){transition-delay:110ms}
.nv-menu--open .nv-menu__panel>:nth-child(2){transition-delay:160ms}
.nv-menu--open .nv-menu__panel>:nth-child(3){transition-delay:210ms}
.nv-menu--open .nv-menu__panel>:nth-child(4){transition-delay:260ms}
.nv-menu--open .nv-menu__panel>:nth-child(5){transition-delay:310ms}
.nv-menu--closing .nv-menu__scrim{transition:opacity 360ms cubic-bezier(.37,0,.63,1)}
.nv-menu--closing .nv-menu__panel{transform:translateY(-8px) scale(.985);
  transition:opacity 340ms cubic-bezier(.37,0,.63,1),transform 340ms cubic-bezier(.37,0,.63,1)}
.nv-menu--closing .nv-menu__panel>*{opacity:0;transform:none;
  transition:opacity 280ms cubic-bezier(.37,0,.63,1),transform 280ms cubic-bezier(.37,0,.63,1)}
.nv-menu--glass .nv-menu__panel{-webkit-backdrop-filter:blur(20px) saturate(140%);backdrop-filter:blur(20px) saturate(140%)}
.nv-menu--open:not(.nv-menu--glass) .nv-menu__scrim,.nv-menu--closing .nv-menu__scrim{will-change:opacity}
.nv-menu--open:not(.nv-menu--glass) .nv-menu__panel,.nv-menu--open:not(.nv-menu--glass) .nv-menu__panel>*,
.nv-menu--closing .nv-menu__panel,.nv-menu--closing .nv-menu__panel>*{will-change:opacity,transform}
@media (prefers-reduced-motion:reduce){
  /* a 120ms fade of the scrim and the panel both ways; nothing slides, no stagger */
  .nv-js .nv-menu .nv-menu__scrim{transition:opacity 120ms linear}
  .nv-js .nv-menu .nv-menu__panel{transform:none;transition:opacity 120ms linear}
  .nv-js .nv-menu .nv-menu__panel>*{opacity:1;transform:none;transition:none}
}
html.nv-menu-open{overflow:hidden}
@media (min-width:900px){.nv-menu{display:none!important}}

/* --------------------------------------------------------------------------
   8. Placeholders for sections not built yet (assemble.py). Never ships.
   -------------------------------------------------------------------------- */
.nv-placeholder{min-height:320px;display:flex;align-items:center;justify-content:center;padding:var(--section-y) var(--gutter);
  border-top:1px dashed var(--line-strong);color:var(--muted);font-family:var(--font-display);font-size:var(--fs-small);letter-spacing:.14em;text-transform:uppercase;text-align:center}
.nv-placeholder--hero{min-height:800px;border-top:0}
.nv-placeholder--footer{min-height:0;flex-direction:column;gap:12px;text-transform:none;letter-spacing:0;font-family:var(--font-body)}

/* --------------------------------------------------------------------------
   9. Print: no frame chrome, every revealed block in plain flow.
   -------------------------------------------------------------------------- */
@media print{
  .nv-header,.nv-menu,.nv-skip{display:none!important}
  .glow,.float,.energy::after{animation:none!important}
}
