/* ==========================================================================
   Shoreline Design — 2026 overhaul design system ("sd")
   --------------------------------------------------------------------------
   One stylesheet for the whole new site: tokens, type, header, menu, buttons,
   forms, footer and the shared cinematic components. Pages load, in order:

       fonts-redesign.css   self-hosted Instrument Serif / Sans + JetBrains Mono
       scroll.css           the pinned-scene mechanics (--p driven)
       sd.css               this file

   and then their own <style> for anything page-specific.

   Palette: the brochure palette from Shoreline_Design_Colour_Reference.pdf —
   deep green, warm cream, stone, bronze and the sage greys. Confirmed by Tyrin
   on 7 Sept 2026 as the palette the whole site falls in line with. Every colour
   token is re-declared inside .dark so any component can sit on deep green
   without a second set of rules.
   ========================================================================== */

:root {
  /* ---- BRAND PALETTE — Shoreline_Design_Colour_Reference.pdf -----------------
     These nine are the solid palette. Do not add a tenth without Tyrin's word.

       Deep Green      #182925   main dark backgrounds and text
       Warm Cream      #F3F0E8   light pages and text on dark pages
       Stone           #D8D0C2   labels and icons on dark pages
       Bronze          #A98057   icons, dividers and step numbers
       Dark Bronze     #805938   small labels on light pages
       Sage Grey       #65706B   muted text and footers
       Soft Grey       #C8C9BF   fine dividers on light pages
       Light Sage      #D4DBD5   secondary text on dark pages
       Deep Sage Grey  #516059   fine dividers on dark pages

     The token NAMES are historical (--navy, --gold, --glass…) and are left
     alone deliberately: every page and script already refers to them, so only
     the values change. Read --navy as "deep green" and --gold as "bronze".
     Four values are tonal steps derived off Deep Green / Warm Cream because a
     screen needs panel and sheet tones the print palette does not: --navy-2,
     --navy-3, --navy-4 and --paper. They sit on the Deep Green →
     Deep Sage Grey axis.

     --navy-4 HAS NO CONSUMER as of Round 3 (7 Sep 2026). It was the roof plane.
     The roof is now --sage-deep with limestone ridge and hips. --navy-4 is left
     in place only because it is the last step of the derived -2/-3/-4 ramp and
     removing one step of a ramp invites someone to re-derive it wrongly. Delete
     it with the ramp, not on its own.

     ANYTHING INSIDE THE CANVAS IS MEASURED OFF RENDERED PIXELS, NEVER OFF THIS
     FILE. (Fizz's rule, 8 Sep 2026, after a roof was chosen on a token number
     that described a swatch and not the scene.) A MeshLambert surface is lit, so
     it renders well below its token; a line material renders at its own opacity
     over whatever is behind it. Both sides of a comparison move, and they do not
     move by the same amount, so a token ratio is not even a reliable bound --
     it can read high OR low. Measured on the rendered canvas, 1440x900, sheet 01:
         surface            token      rendered
         roof   --sage-deep #516059    #3B453E
         wall   --limestone #F3F0E8    #B3B4AD
         plate  --sage-grnd #93A48D    #657262
         street --soft-grey #C8C9BF    #8A8980
         pair                          rendered   on tokens
         roof vs wall  (the silhouette)   4.78       5.85
         ridge/hip stroke vs its roof     2.21       5.85   <- stroke is at .55 opacity
         roof vs street                   2.83
         roof vs plate                    1.96
     The ridge/hip line is the clearest case: same two tokens as the roof/wall
     pair, less than half the reading, purely because the stroke is drawn at 0.55
     opacity. Raise mRoofEdge's opacity if it ever needs to be crisper -- but
     re-measure, don't re-derive. Method is in .scratch/spine-tone.js: poison one
     token to magenta AFTER load and BEFORE the section builds, and the poisoned
     pixels are that surface wherever it landed. */
  --navy: #182925; --navy-2: #1F332E; --navy-3: #2A3B34; --navy-4: #3C4F45;  /* -2..-4 derived */
  --glass: #D4DBD5; --glass-2: #C8C9BF; --glass-ink: #516059;
  --limestone: #F3F0E8; --sand: #D8D0C2; --gold: #A98057; --paper: #FAF8F3; /* --paper derived; --flag is semantic, see below */
  /* Filled bronze only. Navy on --gold measures 4.22-4.32 on the rendered button
     against a 4.5 bar, i.e. an AA fail on the primary CTA, and navy is already
     the darkest ink we have (paper on bronze is worse, ~3.1), so the fill is the
     only lever. This is --gold stepped 10% toward --limestone: the same hue
     family moved along an axis the palette already contains, not a new colour.
     --gold itself is UNCHANGED and stays the brand bronze for rules, outlines,
     accents and type. Use this token only where bronze is a background behind
     text. Ruled by Fizz 8 Sep, flagged to Tyrin as a palette change. */
  --gold-fill: #B08B66;
  --stone: #D8D0C2; --bronze-dark: #805938; --sage: #65706B; --sage-deep: #516059; --soft-grey: #C8C9BF;
  /* atmosphere: a soft mesh of light sage and bronze over the deep green ground, plus grain (body::after) */
  --mesh-dark: radial-gradient(120% 80% at 88% 0%, rgba(212, 219, 213, .16), transparent 58%), radial-gradient(90% 70% at 0% 100%, rgba(169, 128, 87, .18), transparent 55%), var(--navy);
  --mesh-dark-2: radial-gradient(110% 80% at 0% 0%, rgba(212, 219, 213, .14), transparent 58%), radial-gradient(90% 70% at 100% 100%, rgba(169, 128, 87, .16), transparent 55%), var(--navy-2);
  --mesh-teal: radial-gradient(120% 90% at 100% 0%, rgba(212, 219, 213, .2), transparent 60%), radial-gradient(80% 60% at 0% 100%, rgba(24, 41, 37, .6), transparent 60%), var(--navy-3);
  --heading: 'Newsreader', Georgia, 'Times New Roman', serif;
  --body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
  --gutter: clamp(20px, 4vw, 64px);
  --ease: cubic-bezier(.2, .7, .2, 1);
  --nav-h: 76px;
  --radius: 3px;

  /* semantic tokens — light ground.
     --muted is Sage Grey ("muted text and footers"), --line is Soft Grey
     ("fine dividers on light pages"), --label is Dark Bronze ("small labels on
     light pages"). --line-2 is the same family one step stronger. */
  --bg: var(--limestone); --panel: var(--paper); --ink: var(--navy);
  --muted: #65706B; --line: #C8C9BF; --line-2: rgba(101, 112, 107, .55);
  --label: #805938;
  --accent: var(--gold);
  /* --flag is the SECOND accent: the line paired with bronze in the drawings,
     the "you" half of the you/us pairs, active states and form errors. The old
     palette used a coral here; the brochure has no coral, so --flag is the
     palette tone that stays legible AND stays distinct from bronze on each
     ground — Dark Bronze on cream, Stone on deep green (redeclared in .dark). */
  --flag: #805938;
  --on-flag: var(--limestone);   /* text/marks sitting ON a --flag fill */
}
.dark, [data-dark] {
  /* dark ground: --muted is Light Sage ("secondary text on dark pages"),
     --line is Deep Sage Grey ("fine dividers on dark pages"), --label is Stone
     ("labels and icons on dark pages"). */
  --bg: var(--navy); --panel: var(--navy-2); --ink: var(--limestone);
  --muted: #D4DBD5; --line: #516059; --line-2: rgba(212, 219, 213, .38);
  --label: #D8D0C2;
  --flag: #D8D0C2;   /* Stone: 9.92:1 on deep green, and clearly not bronze */
  --on-flag: var(--navy);
  color: var(--ink);
}
.dark h1, .dark h2, .dark h3, [data-dark] h1, [data-dark] h2, [data-dark] h3 { color: var(--ink); }

/* ---- Base ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body { margin: 0; font-family: var(--body); font-size: 16.5px; line-height: 1.6; letter-spacing: -.005em; font-feature-settings: 'ss02' on, 'cv11' on; color: var(--ink); background: var(--bg); overflow-x: clip; transition: background-color .8s ease; }
body[data-bg="navy"] { background: var(--navy); } body[data-bg="limestone"] { background: var(--limestone); }
body[data-bg="sand"] { background: var(--sand); } body[data-bg="paper"] { background: var(--paper); } body[data-bg="teal"] { background: var(--navy-3); }
img, svg, video { display: block; max-width: 100%; }
body::after { content: ""; position: fixed; inset: 0; z-index: 2000; pointer-events: none; opacity: .05; will-change: transform; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.dark, [data-dark] { background-image: var(--mesh-dark); }
[hidden] { display: none !important; }
a { color: inherit; }
h1, h2, h3, h4 { font-family: var(--heading); font-weight: 400; margin: 0; letter-spacing: -.015em; line-height: 1.02; text-wrap: pretty; }
h1 { font-size: clamp(44px, 7vw, 108px); letter-spacing: -.03em; line-height: .94; }
h2 { font-size: clamp(36px, 4.6vw, 68px); }
h3 { font-size: clamp(22px, 2.2vw, 30px); }
p { margin: 0; }
em, .it { font-style: italic; }
.lede { font-size: clamp(17px, 1.35vw, 21px); line-height: 1.5; font-weight: 350; color: var(--muted); max-width: 560px; }
.mono, .kicker { font-family: var(--body); font-size: 13px; }
.kicker { color: var(--muted); display: inline-flex; align-items: center; gap: 12px; }
.kicker::before { content: ""; width: 28px; height: 1px; background: var(--gold); }
.kicker--plain::before { display: none; }
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 var(--gutter); }
.sr { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
::selection { background: var(--gold-fill); color: var(--navy); }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* ---- Buttons ------------------------------------------------------------- */
/* white-space: normal + min-height (not height) is the fix for horizontal page
   scroll on a phone. .cta shipped white-space: nowrap, which makes a button's
   min-content the whole label - so a long label inside a narrow column refuses to
   shrink, pushes its container past the viewport, and the whole page scrolls
   sideways. It bit three buttons at 320: #sk-explore on the home page (311px in a
   240px column, +31), .cta--line on about (318.6 in 280, +19) and #x-send on
   subdivision (331.5 in 280, +32). Fixed labels one at a time and the fourth long
   label reintroduces it, so it is fixed here.
   A button that will not shrink inside its column is the button ignoring the
   layout, not the layout being too tight (Fizz, 8 Sept).
   height -> min-height matters just as much: .cta has overflow: hidden, so a
   wrapped label inside a fixed 52px box is silently CLIPPED rather than visibly
   broken. Two lines still fit inside 52px, so nothing moves where the label fits.
   Swept every .cta on all 11 pages at 320/375/390/768/1024/1440/1920, old rule vs
   new: nothing changes at 375 and above except three sketch-panel buttons getting
   narrower (they were overflowing their own column there too). At 320 the changes
   are the three page-scroll fixes, three labels that stop being clipped
   (#j-send was losing 26px, .cta--light on both feasibility pages 5px), and
   #br-send shrinking 14px to fit its column. text-align: left so a wrapped label
   lines up under itself instead of centring against the arrow - the only place
   that shows above 320 is #sk-send, a <button> (UA text-align: center) sitting
   between two <a> siblings it now matches. */
.cta { display: inline-flex; align-items: center; gap: 12px; min-height: 52px; padding: 0 24px; font-family: var(--body); font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; border-radius: var(--radius); border: 1px solid transparent; text-decoration: none; cursor: pointer; white-space: normal; line-height: 1.35; text-wrap: balance; text-align: left; transition: background .25s, color .25s, border-color .25s, transform .25s var(--ease); position: relative; overflow: hidden; }
.cta > span[aria-hidden] { display: inline-block; transition: transform .3s var(--ease); }
.cta:hover > span[aria-hidden] { transform: translateX(4px); }
.cta:active { transform: scale(.98); }
/* Button hierarchy. The old palette had two loud fills — brass and a coral — so
   the primary and secondary buttons could differ by hue. The brochure palette
   has one accent, so they differ by WEIGHT instead: primary is solid bronze,
   secondary is the same bronze as an outline. Both read on cream and on deep
   green, which is what the old coral was doing.
     .cta--flag  primary action  (sticky CTA, "send this to us", "book a call")
     .cta--gold  secondary       (hero, in-page prompts)
   Bronze as an OUTLINE or as type on deep green is 4.28:1 and stays that way -
   that is the long-standing AA-marginal pair in the PLANS note. Bronze as a FILL
   behind navy text was the same 4.28 and is no longer accepted: it now uses
   --gold-fill. Do not fold the two back into one token; they fail for different
   reasons and only one of them has text sitting on it. */
.cta--flag { background: var(--gold-fill); color: var(--navy); border-color: var(--gold-fill); }
.cta--flag:hover { background: var(--limestone); color: var(--navy); border-color: var(--limestone); }
.cta--gold { background: transparent; color: var(--ink); border-color: var(--gold); }
.cta--gold:hover { background: var(--gold-fill); color: var(--navy); } /* filled on hover, so --gold-fill */
.cta--navy { background: var(--navy); color: var(--limestone); }
.cta--navy:hover { background: var(--glass-ink); color: var(--limestone); }
.cta--paper { background: var(--paper); color: var(--navy); }
.cta--paper:hover { background: var(--gold); }
.cta--ghost { background: transparent; color: var(--ink); border-color: var(--line-2); }
.cta--ghost:hover { border-color: var(--gold); color: var(--ink); box-shadow: 0 0 0 3px rgba(169,128,87,.2); }
.cta--sm { min-height: 42px; padding: 0 16px; font-size: 11px; }
.link { display: inline-flex; align-items: center; gap: 8px; font-family: var(--body); font-size: 13px; text-decoration: none; color: var(--ink); position: relative; padding-bottom: 4px; }
.link::after { content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%; background: var(--glass-2); transform: scaleX(.35); transform-origin: left; transition: transform .35s var(--ease); }
.link:hover::after { transform: scaleX(1); }

/* ---- Header -------------------------------------------------------------- */
/* sd.css owns the whole nav treatment: transparent at the top of a page so a
   full-bleed hero runs under it, tinted per data-bg once scrolled (below).
   background and border-bottom are declared EXPLICITLY as transparent, and that
   is load-bearing rather than tidy. Five pages (404, about, feasibility-review,
   privacy, subdivision-delivery) load the legacy site.css BEFORE this file, and
   its own bare '.site-nav' sets 'background: var(--bg)' at equal specificity.
   The cascade resolves per property, so anything sd.css leaves unset is still
   painted by site.css. Leaving background unset gave subdivision-delivery an
   opaque cream bar over the top 76px of its aerial while sd.css's white
   wordmark, spine, Book-a-consult and hamburger all rendered on top of it —
   measured 1.03:1 at 1440. Do not delete these two declarations because they
   look like no-ops; they are what stops site.css painting here. */
.site-nav { position: fixed; top: 0; left: 0; right: 0; z-index: 120; height: var(--nav-h); display: grid; background: transparent; grid-template-columns: 1fr auto 1fr; align-items: center; padding: 0 var(--gutter); color: var(--paper); --spine: var(--glass); transition: background .35s, color .35s, border-color .35s, transform .4s var(--ease); border-bottom: 1px solid transparent; }
.site-nav__logo a { display: block; }
.site-nav__logo img { width: clamp(150px, 15vw, 200px); height: auto; }
.site-nav .logo-dark { display: none; }
/* The spine was paper at 'opacity: .85'. That is not a colour, it is 85% of
   whatever is behind it - and behind it is a .88 bar, i.e. 12% photograph. It
   measured 4.56-4.62 against a 4.5 bar, so the pass depended on the frame, and
   the frame was about to be replaced. Named colour per state instead:
   --glass (#D4DBD5) on a dark bar, --glass-ink (#516059) on the cream one.
   --glass on cream is ~1.3:1, so the light case MUST stay scoped separately.
   Hierarchy under the wordmark is now carried by colour, not by fade. */
.site-nav__spine { justify-self: center; font-family: var(--body); font-size: 12px; color: var(--spine); white-space: nowrap; }
/* The separators are punctuation doing the job of a rule, so they are drawn as
   one. As 10px bronze GLYPHS they measured 3.41-3.59 on the dark bar and 3.04 on
   the cream one against a 4.5 text bar, and bronze as type tops out at 4.28 on
   navy - there is no fill that reaches 4.5, so it could not be fixed as text.
   font-size: 0 removes the glyph; the element then paints a 1px bronze hairline.
   That is a graphic, not text: 1.4.3 does not apply, and it is not required to
   understand "Design Drafting Development" either. It clears the 3:1 non-text bar
   anyway. Keep font-size: 0 - without it the pipe still renders next to the rule. */
.site-nav__spine b { display: inline-block; width: 1px; height: 9px; margin: 0 10px; vertical-align: middle; background: var(--gold); font-size: 0; line-height: 0; overflow: hidden; }
.site-nav__right { justify-self: end; display: flex; align-items: center; gap: 22px; }
/* color: inherit for the same reason — site.css pins .site-nav__phone to
   var(--ink), so without this the phone number stayed navy while the rest of
   the nav flipped to paper over a dark hero, and it was the one element that
   did not follow the nav's colour. */
.site-nav__phone { font-family: var(--body); font-size: 12px; text-decoration: none; opacity: .9; color: inherit; }
.site-nav__phone:hover { color: var(--gold); opacity: 1; }
.nav-toggle { display: inline-flex; align-items: center; gap: 12px; height: 44px; padding: 0 0 0 4px; background: transparent; border: 0; color: inherit; cursor: pointer; font-family: var(--body); font-size: 13px; }
.nav-toggle__bars { display: flex; flex-direction: column; gap: 6px; width: 28px; }
.nav-toggle__bar { display: block; height: 1px; width: 28px; background: currentColor; transition: transform .35s var(--ease), opacity .25s, width .3s; }
.nav-toggle__bar:nth-child(2) { width: 18px; margin-left: auto; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
/* Scrolled: header tints with whatever the page backdrop is right now. */
body.is-scrolled .site-nav { background: rgba(243, 240, 232, .9); color: var(--navy); --spine: var(--glass-ink); border-bottom-color: rgba(24, 41, 37, .1); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
body.is-scrolled .site-nav .logo-light { display: none; } body.is-scrolled .site-nav .logo-dark { display: block; }
body.is-scrolled[data-bg="sand"] .site-nav { background: rgba(216, 208, 194, .9); }
body.is-scrolled[data-bg="paper"] .site-nav { background: rgba(250, 248, 243, .9); }
body.is-scrolled[data-bg="teal"] .site-nav { background: rgba(42, 59, 52, .88); color: var(--paper); --spine: var(--glass); border-bottom-color: rgba(243,240,232,.1); }
body.is-scrolled[data-bg="teal"] .site-nav .logo-light { display: block; } body.is-scrolled[data-bg="teal"] .site-nav .logo-dark { display: none; }
body.is-scrolled[data-bg="navy"] .site-nav, body.is-scrolled.is-dark .site-nav { background: rgba(24, 41, 37, .88); color: var(--paper); --spine: var(--glass); border-bottom-color: rgba(243, 240, 232, .1); }
body.is-scrolled[data-bg="navy"] .site-nav .logo-light, body.is-scrolled.is-dark .site-nav .logo-light { display: block; }
body.is-scrolled[data-bg="navy"] .site-nav .logo-dark, body.is-scrolled.is-dark .site-nav .logo-dark { display: none; }
/* A photographic hero cannot carry a floating nav. Measured at 1440 on the
   subdivision aerial: small white mono needs its backing at roughly .87 alpha
   before it clears 4.5:1, and at .87 it is not translucent any more - a
   translucent scrim at .78 still left 51.7% of the nav's glyph area under bar.
   So pages whose hero is a photograph opt in here with data-nav-bar and take the
   SAME bar they already take when scrolled over a dark section: same .88, same
   paper text, same hairline, same blur, same transition. One component in two
   positions, not two components.
   index.html deliberately does NOT opt in - its hero is dark by construction and
   its floating nav measures clear. Do not unify these.
   Rendered check, six widths, glyph-masked: nav text 8.01-8.13 min, wordmark
   9.12, bars 11.21. Off .88 the numbers do not move much, but re-measure rather
   than assume if the value changes - both sides of a lit pair move. */
body[data-nav-bar]:not(.is-scrolled) .site-nav {
  background: rgba(24, 41, 37, .88); color: var(--paper);
  border-bottom-color: rgba(243, 240, 232, .1);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
body.nav-solid:not(.is-scrolled) .site-nav { color: var(--navy); --spine: var(--glass-ink); }
body.nav-solid:not(.is-scrolled) .site-nav .logo-light { display: none; } body.nav-solid:not(.is-scrolled) .site-nav .logo-dark { display: block; }
body.menu-open .site-nav { background: transparent; color: var(--paper); --spine: var(--glass); border-bottom-color: transparent; backdrop-filter: none; }
body.menu-open .site-nav .logo-light { display: block; } body.menu-open .site-nav .logo-dark { display: none; }
@media (max-width: 900px) { .site-nav { grid-template-columns: 1fr auto; } .site-nav__spine { display: none; } .site-nav__phone { display: none; } .nav-toggle span.t { display: none; } }

/* ---- Menu: full-screen navy panel ---------------------------------------- */
.site-menu { position: fixed; inset: 0; z-index: 110; background: var(--mesh-dark); color: var(--paper); display: grid; grid-template-columns: 1.2fr .8fr; gap: 40px; padding: calc(var(--nav-h) + 4vh) var(--gutter) 6vh; opacity: 0; visibility: hidden; transition: opacity .45s var(--ease), visibility .45s; overflow-y: auto; }
.site-menu[data-open="true"] { opacity: 1; visibility: visible; }
.site-menu__links { display: flex; flex-direction: column; justify-content: center; gap: 4px; }
.site-menu__links a { font-family: var(--heading); font-size: clamp(34px, 5.6vw, 76px); line-height: 1.06; letter-spacing: -.02em; color: var(--paper); text-decoration: none; display: flex; align-items: baseline; gap: 18px; transform: translateY(24px); opacity: 0; transition: transform .6s var(--ease), opacity .5s, color .25s; }
.site-menu__links a small { font-family: var(--body); font-size: 12px; color: var(--glass); }
.site-menu__links a:hover { color: var(--gold); }
.site-menu[data-open="true"] .site-menu__links a { transform: none; opacity: 1; }
.site-menu[data-open="true"] .site-menu__links a:nth-child(2) { transition-delay: .05s; } .site-menu[data-open="true"] .site-menu__links a:nth-child(3) { transition-delay: .1s; } .site-menu[data-open="true"] .site-menu__links a:nth-child(4) { transition-delay: .15s; } .site-menu[data-open="true"] .site-menu__links a:nth-child(5) { transition-delay: .2s; } .site-menu[data-open="true"] .site-menu__links a:nth-child(6) { transition-delay: .25s; } .site-menu[data-open="true"] .site-menu__links a:nth-child(7) { transition-delay: .3s; }
.site-menu__side { display: flex; flex-direction: column; justify-content: center; gap: 28px; border-left: 1px solid rgba(243, 240, 232, .14); padding-left: 40px; }
.site-menu__side .kicker { color: rgba(243, 240, 232, .7); }
.site-menu__doors { display: flex; flex-direction: column; gap: 10px; }
.site-menu__doors a { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 14px 16px; border: 1px solid rgba(243, 240, 232, .18); border-radius: var(--radius); text-decoration: none; color: var(--paper); font-size: 15px; transition: border-color .25s, background .25s; }
.site-menu__doors a:hover { border-color: var(--glass); background: rgba(212,219,213,.08); }
.site-menu__doors a span { font-family: var(--body); font-size: 12px; color: var(--glass); }
.site-menu__contact { font-size: 14px; color: rgba(243, 240, 232, .7); line-height: 1.7; }
.site-menu__contact a { color: var(--paper); text-decoration: none; }
.site-menu__contact a:hover { color: var(--gold); }
.menu-back { display: none; }
body.menu-open { overflow: hidden; }
@media (max-width: 900px) { .site-menu { grid-template-columns: 1fr; gap: 28px; padding-top: calc(var(--nav-h) + 2vh); } .site-menu__links { justify-content: flex-start; } .site-menu__side { border-left: 0; padding-left: 0; padding-top: 24px; border-top: 1px solid rgba(243, 240, 232, .14); justify-content: flex-start; } }

/* ---- Forms (site.js drives validation + sending) ------------------------- */
.form { display: flex; flex-direction: column; gap: 22px; position: relative; }
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
@media (max-width: 640px) { .form__row { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; gap: 6px; position: relative; }
.field label { font-family: var(--body); font-size: 12px; color: var(--muted); }
.field input, .field select, .field textarea { font-family: var(--body); font-size: 16px; color: var(--ink); background: transparent; border: 0; border-bottom: 1px solid var(--line-2); padding: 10px 0; border-radius: 0; outline: 0; transition: border-color .25s; -webkit-appearance: none; appearance: none; }
.field select { background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); background-position: calc(100% - 14px) 50%, calc(100% - 9px) 50%; background-size: 5px 5px; background-repeat: no-repeat; padding-right: 28px; }
.dark .field select option, [data-dark] .field select option { color: var(--navy); }
.field textarea { resize: vertical; min-height: 96px; }
.field input:focus, .field select:focus, .field textarea:focus { border-bottom-color: var(--gold); }
.field__error { display: none; font-size: 12px; color: var(--flag); }
.field--error label { color: var(--flag); } .field--error input, .field--error select, .field--error textarea { border-bottom-color: var(--flag); }
.field--error .field__error { display: block; }
.form__failed { font-size: 14px; color: var(--flag); border: 1px solid var(--flag); padding: 12px 14px; border-radius: var(--radius); }
.form .btn { align-self: flex-start; }
.btn { display: inline-flex; align-items: center; height: 52px; padding: 0 26px; font-family: var(--body); font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; background: var(--gold-fill); color: var(--navy); border: 0; border-radius: var(--radius); cursor: pointer; transition: background .25s, color .25s; }
.btn:hover { background: var(--paper); }
.btn:disabled { opacity: .6; cursor: default; }
.btn__label--hover { display: none; } .btn:hover .btn__label--default { display: none; } .btn:hover .btn__label--hover { display: inline; }
.thanks { display: none; padding: 32px; border: 1px solid var(--gold); border-radius: var(--radius); }
.thanks__title { font-family: var(--heading); font-size: 34px; margin-bottom: 8px; }
.thanks p { color: var(--muted); }
.is-submitted .thanks { display: block; } .is-submitted .form { display: none; }

/* ---- Thank-you: first light ------------------------------------------------
   Plays when the enquiry has arrived. A warm glow rises from below like early
   sun, gold specks drift slowly up through it (and keep drifting, gently),
   the seal draws itself with a tick, and the words rise in. Colours come from
   --ink / --muted / --flag / --gold, so it works on the light page and in the
   dark side panel alike. Small text uses --flag: Dark Bronze on cream, Stone
   on deep green, both legible; the gold is for light and line. */
.thanks[data-journey] { padding: 0; border: 0; background: transparent; outline: none; }
.trip { position: relative; isolation: isolate; display: grid; gap: 14px; justify-items: start; padding: 26px 0 40px; }
.trip > :not(.trip__sun):not(.trip__motes) { position: relative; z-index: 1; }
/* fades to nothing well inside its own box, so it never shows an edge */
.trip__sun { position: absolute; z-index: 0; left: 30%; bottom: -30%; width: 120%; aspect-ratio: 1.5; translate: -50% 0;
  background: radial-gradient(closest-side, rgba(232,190,130,.34), rgba(232,190,130,.14) 40%, rgba(232,190,130,.04) 62%, rgba(232,190,130,0) 80%); pointer-events: none; }
/* the specks stay inside the message, fading out before the top */
.trip__motes { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; -webkit-mask-image: linear-gradient(to top, #000 55%, transparent); mask-image: linear-gradient(to top, #000 55%, transparent); }
.trip__motes span { position: absolute; bottom: -8px; width: var(--z); height: var(--z); border-radius: 50%; background: #E3B77C; box-shadow: 0 0 6px 1px rgba(227,183,124,.75); opacity: 0; }
.trip__seal { width: 48px; height: 48px; fill: none; stroke: var(--gold); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.trip__seal circle { stroke-dasharray: 132; }
.trip__seal path { stroke-dasharray: 30; stroke-width: 2.4; }
.trip__kicker { font-family: var(--body); font-size: 12px; letter-spacing: .16em; text-transform: uppercase; color: var(--flag); margin-top: 4px; }
.trip .trip__title { font-size: clamp(32px, 3.8vw, 46px); line-height: 1.04; margin: 0; color: var(--ink); }
.trip__title span { display: inline-block; }
.trip__lede { font-size: 15.5px; line-height: 1.6; color: var(--muted); margin: 0; max-width: 440px; }

@media (prefers-reduced-motion: no-preference) {
  .is-submitted .trip__sun { animation: trip-dawn 2.6s cubic-bezier(.2,.7,.2,1) both, trip-breathe 7s 2.6s ease-in-out infinite alternate; }
  .is-submitted .trip__motes span { animation: trip-drift var(--t) calc(1s + var(--d)) linear infinite; }
  .is-submitted .trip__seal circle { animation: trip-stroke-c 1s .25s cubic-bezier(.5,0,.2,1) both; }
  .is-submitted .trip__seal path { animation: trip-stroke-p .5s 1.05s cubic-bezier(.5,0,.2,1) both; }
  .is-submitted .trip__seal { animation: trip-glint .9s 1.4s ease-out both; }
  .is-submitted .trip__kicker, .is-submitted .trip__lede { animation: trip-fade .8s ease both; }
  .is-submitted .trip__kicker { animation-delay: .5s; }
  .is-submitted .trip__lede { animation-delay: 1.15s; }
  .is-submitted .trip__title span { animation: trip-rise .9s cubic-bezier(.2,.8,.2,1) both; }
  .is-submitted .trip__title span:nth-child(1) { animation-delay: .6s; }
  .is-submitted .trip__title span:nth-child(2) { animation-delay: .68s; }
  .is-submitted .trip__title span:nth-child(3) { animation-delay: .76s; }
  .is-submitted .trip__title span:nth-child(4) { animation-delay: .84s; }
  .is-submitted .trip__title span:nth-child(5) { animation-delay: .92s; }
}
@media (prefers-reduced-motion: reduce) { .trip__sun { opacity: .8; } }
@keyframes trip-dawn { from { opacity: 0; transform: translateY(30%) scale(.8); } to { opacity: 1; transform: none; } }
@keyframes trip-breathe { from { opacity: 1; } to { opacity: .72; } }
@keyframes trip-drift {
  0%   { opacity: 0; transform: translate(0, 0); }
  15%  { opacity: .75; }
  60%  { transform: translate(var(--sway), -150px); }
  100% { opacity: 0; transform: translate(calc(var(--sway) * -.4), -280px); }
}
@keyframes trip-stroke-c { from { stroke-dashoffset: 132; } to { stroke-dashoffset: 0; } }
@keyframes trip-stroke-p { from { stroke-dashoffset: 30; } to { stroke-dashoffset: 0; } }
@keyframes trip-glint { 0% { filter: drop-shadow(0 0 0 rgba(214,170,112,0)); } 40% { filter: drop-shadow(0 0 10px rgba(214,170,112,.7)); } 100% { filter: drop-shadow(0 0 0 rgba(214,170,112,0)); } }
@keyframes trip-fade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes trip-rise { from { opacity: 0; transform: translateY(70%); } to { opacity: 1; transform: none; } }

.form__hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---- Footer -------------------------------------------------------------- */
.site-footer { background: var(--mesh-dark-2); color: var(--paper); padding: clamp(64px, 9vh, 110px) var(--gutter) 34px; position: relative; overflow: hidden; }
.site-footer__grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 40px; max-width: 1240px; margin: 0 auto; }
.site-footer__brand img { width: 200px; }
.site-footer__brand p { margin-top: 18px; font-size: 14px; line-height: 1.7; color: rgba(243, 240, 232, .66); max-width: 320px; }
.site-footer h3 { font-family: var(--body); font-size: 12px; color: var(--glass); margin-bottom: 16px; }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.site-footer li a, .site-footer li { font-size: 15px; color: rgba(243, 240, 232, .82); text-decoration: none; }
.site-footer li a:hover { color: var(--gold); }
.site-footer__spine { margin: clamp(48px, 7vh, 80px) auto 0; max-width: 1240px; border-top: 1px solid rgba(243, 240, 232, .14); padding-top: 24px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px; font-family: var(--body); font-size: 12px; color: rgba(243, 240, 232, .55); }
.site-footer__spine b { font-weight: 400; color: var(--gold); margin: 0 8px; }
.site-footer__spine a { color: inherit; text-decoration: none; } .site-footer__spine a:hover { color: var(--paper); }
.site-footer__big { position: absolute; right: -2vw; bottom: -3vw; font-family: var(--heading); font-size: clamp(120px, 22vw, 340px); line-height: 1; color: transparent; -webkit-text-stroke: 1px rgba(243, 240, 232, .08); pointer-events: none; user-select: none; white-space: nowrap; }
@media (max-width: 900px) { .site-footer__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .site-footer__grid { grid-template-columns: 1fr; gap: 28px; } }

/* ---- Shared cinematic components ---------------------------------------- */
/* Headings rise one word at a time (sd.js splits .words into spans). */
.words { overflow: hidden; }
.words .w { display: inline-block; opacity: 0; transform: translateY(110%) rotate(2deg); transition: opacity .6s var(--ease), transform .8s var(--ease); transition-delay: calc(var(--i) * 50ms); }
.words.in .w { opacity: 1; transform: none; }
/* Cards that tilt toward the cursor (sd.js). */
.tilt { transform: perspective(900px) rotateX(var(--rx, 0)) rotateY(var(--ry, 0)); transition: transform .5s var(--ease); transform-style: preserve-3d; }
.tilt:hover { transition-duration: .08s; }
/* Marquee band. */
/* Counters that count up when they arrive (sd.js, data-count). */
.num { font-family: var(--heading); font-size: clamp(56px, 7vw, 112px); line-height: .9; letter-spacing: -.03em; }
/* Progress bar + sticky mobile CTA. */
.progress { position: fixed; left: 0; top: 0; right: 0; height: 3px; z-index: 130; pointer-events: none; }
.progress i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--glass), var(--gold)); }
/* white-space: nowrap here on purpose, against the base .cta rule. This pill is
   position:fixed with left:50%, so its shrink-to-fit width is (viewport - 50%) =
   160px at 320vw - and a wrapping label breaks "Book a strategy call" onto three
   lines inside a 52px box. It cannot cause page scroll the way an in-flow button
   can, because a fixed element contributes nothing to document scrollWidth, so
   the reason the base rule wraps does not apply to it. Centred by the translate. */
.sticky-cta { position: fixed; left: 50%; bottom: 18px; transform: translate(-50%, 140%); z-index: 100; box-shadow: 0 16px 40px rgba(24, 41, 37, .35); transition: transform .4s var(--ease); display: none; white-space: nowrap; }
.sticky-cta.show { transform: translate(-50%, 0); }
@media (max-width: 800px) { .sticky-cta { display: inline-flex; } }
/* Chapter rail (right edge, desktop). */
.rail { pointer-events: none; align-items: flex-end; }
.rail a { pointer-events: auto; position: relative; display: flex; align-items: center; justify-content: flex-end; gap: 10px; height: 20px; text-decoration: none; }
.rail a i { width: 1px; height: 12px; background: var(--ink); opacity: .3; transition: height .3s, opacity .3s; display: block; }
.rail a.on i { height: 28px; opacity: 1; }
.rail a span { font-family: var(--body); font-size: 12px; color: var(--ink); opacity: 0; transform: translateX(6px); transition: opacity .25s, transform .25s; white-space: nowrap; }
.rail:hover a span, .rail a.on span { opacity: .8; transform: none; }
body.is-dark .rail a i { background: var(--paper); } body.is-dark .rail a span { color: var(--paper); }
/* The three doors (home + menu + enquiry). */
.doors { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.door { position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 10px; min-height: 300px; padding: 26px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); text-decoration: none; color: var(--ink); overflow: hidden; transition: border-color .3s, transform .5s var(--ease), box-shadow .5s var(--ease); }
.door::before { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 40%, rgba(24, 41, 37, .12)); opacity: 0; transition: opacity .4s; }
.door:hover { border-color: var(--gold); transform: translateY(-6px); box-shadow: 0 30px 60px -30px rgba(24, 41, 37, .5); }
.door:hover::before { opacity: 1; }
.door .n { font-family: var(--body); font-size: 12px; color: var(--muted); }
.door h3 { font-size: clamp(26px, 2.4vw, 34px); }
.door p { font-size: 14px; line-height: 1.55; color: var(--muted); }
.door .go { font-family: var(--body); font-size: 12px; margin-top: 8px; display: inline-flex; gap: 8px; align-items: center; }
.door .go i { width: 22px; height: 1px; background: currentColor; transition: width .3s var(--ease); }
.door:hover .go i { width: 40px; }
.door svg.pic { position: absolute; right: 18px; top: 18px; width: 40%; height: auto; opacity: .55; transition: opacity .4s, transform .6s var(--ease); }
.door:hover svg.pic { opacity: 1; transform: translateY(-4px); }
.door svg.pic path, .door svg.pic rect, .door svg.pic circle, .door svg.pic line { fill: none; stroke: var(--ink); stroke-width: 1; vector-effect: non-scaling-stroke; }
.door svg.pic .g { stroke: var(--gold); } .door svg.pic .f { stroke: var(--flag); }
@media (max-width: 900px) { .doors { grid-template-columns: 1fr; } .door { min-height: 190px; } }
/* Line-drawing that draws itself as --p advances (paths need pathLength="100"). */
/* No vector-effect here on purpose: Chrome applies dash lengths in screen space under non-scaling-stroke, which breaks the pathLength=100 trick. */
.draw path, .draw line, .draw polyline, .draw rect, .draw circle { fill: none; stroke: var(--ink); stroke-width: .8; stroke-dasharray: 100; stroke-dashoffset: calc(100 - min(1, max(0, (var(--p, 0) - var(--d, 0)) * var(--k, 3))) * 100); }
.draw .g { stroke: var(--gold); } .draw .f { stroke: var(--flag); } .draw .thin { stroke-width: .5; opacity: .7; }
.draw text { font-family: var(--body); fill: var(--ink); opacity: min(1, max(0, (var(--p, 0) - var(--d, 0)) * var(--k, 3))); }
/* Plate figure (Surveyed Silence artworks).
   margin: 0 is load-bearing. .plate is a bare <figure>, so the UA default
   margin: 1em 40px was still on it and the picture lost 80px of width at every
   viewport - 200px of a 280px column at 320, 504 of 584 at 1440 - while the copy
   beneath ran the full column. Nobody chose that inset. */
.plate { position: relative; overflow: hidden; border-radius: var(--radius); margin: 0; }
.plate img { width: 100%; height: 100%; object-fit: cover; }
.plate figcaption { position: absolute; left: 16px; bottom: 14px; font-family: var(--body); font-size: 12px; color: var(--paper); opacity: .8; }
/* A plate holding a PHOTOGRAPH takes the chip; a plate holding a line drawing on
   cream keeps the caption above, unchanged. The distinction is disclosure rule 1 in
   IMAGE-SHOT-LIST.md: a disclosure never sits on a surface that can change under it.
   Drawing paper is a ground we control and it cannot change; a photograph can, and
   does - a re-shoot, a re-crop or a different hour moves what is under the label.

   Every .plate on this site was a drawing until the Perth street photograph landed on
   8 Sept, which is why the base rule was never stressed. Bare on that frame the caption
   measured 7.6-8.9 and passed - but it passed because that particular shot happens to
   have a near-black lower-left corner, and a dark corner is not a design decision. The
   .8 goes too: the same .8 measured 4.53 where full ink measured 4.90 on this class of
   element, and a disclosure is a legibility element, not decoration (rule 5).

   Same chip as the three home-page door captions and as slot 9
   (subdivision-delivery.html:414), deliberately identical so the disclosure reads as
   one component everywhere. rgba(24,41,37,.82) over a PURE WHITE frame still gives
   paper about 7.7, so the floor belongs to the chip and not to the picture.
   Put .plate--photo on any future plate that holds a photograph. */
.plate--photo figcaption { color: var(--paper); opacity: 1; background: rgba(24,41,37,.82); padding: 5px 9px; border-radius: 2px; }
/* Tooltip pill. */
.pill { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px; font-family: var(--body); font-size: 12px; color: var(--muted); }
.pill i { width: 6px; height: 6px; border-radius: 50%; background: var(--gold); }
/* Standard section spacing. */
.sec { padding: clamp(80px, 12vh, 150px) var(--gutter); }
.sec__head { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: end; margin-bottom: clamp(36px, 6vh, 72px); }
@media (max-width: 800px) { .sec__head { grid-template-columns: 1fr; gap: 18px; } }
/* Range inputs & segmented controls follow the current ink. */
.ctl input[type="range"]::-webkit-slider-thumb { background: var(--gold); border-color: var(--ink); }
.ctl input[type="range"]::-moz-range-thumb { background: var(--gold); border-color: var(--ink); }
.seg button { font-family: var(--body); }
.seg button[aria-pressed="true"] { border-color: var(--glass-2); background: var(--panel); color: var(--ink); box-shadow: inset 0 0 0 1px var(--glass-2); }
.seg button:hover { border-color: var(--glass-2); }
@media (hover: none) { .seg button { min-height: 44px; } }

/* ---- Reduced motion --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .words .w, .tilt, .door, .cta { transition: none !important; transform: none !important; opacity: 1 !important; }
  .draw path, .draw line, .draw polyline, .draw rect, .draw circle { stroke-dashoffset: 0; } .draw text { opacity: 1; }
}

/* site.js appends a decorative "wave" element for the home enquiry dialog; the
   overhaul does not use that entrance, so keep it out of the layout. */
.wave, .wavedialog { display: none; }

/* ---- Ask Shoreline assistant (assets/js/assistant.js) ---------------------- */
#sd-assist { position: fixed; right: 18px; bottom: 18px; z-index: 140; font-family: var(--body); }
body.menu-open #sd-assist { display: none; }
.sda-launch { display: inline-flex; align-items: center; gap: 10px; height: 48px; padding: 0 18px 0 12px; border-radius: 999px; border: 1px solid rgba(243,240,232,.2); background: var(--navy); color: var(--paper); font-family: var(--body); font-size: 12px; cursor: pointer; box-shadow: 0 18px 40px -18px rgba(24,41,37,.6); transition: transform .3s var(--ease), background .25s; }
.sda-launch:hover { transform: translateY(-2px); background: var(--navy-3); box-shadow: 0 18px 40px -14px rgba(212,219,213,.5); }
.sda-launch svg { width: 22px; height: 22px; } .sda-launch svg * { fill: none; stroke: var(--paper); stroke-width: 1.4; } .sda-launch svg .g { stroke: var(--gold); } .sda-launch svg circle { fill: var(--gold); stroke: none; }
#sd-assist.open .sda-launch { display: none; }
.sda-panel { position: absolute; right: 0; bottom: 0; width: min(380px, calc(100vw - 24px)); height: min(620px, calc(100vh - 100px)); display: flex; flex-direction: column; background: var(--paper); color: var(--navy); border-radius: 6px; box-shadow: 0 40px 100px -30px rgba(24,41,37,.6), 0 0 0 1px rgba(24,41,37,.1); overflow: hidden; animation: sda-in .35s var(--ease) both; }
@keyframes sda-in { from { opacity: 0; transform: translateY(14px) scale(.98); } to { opacity: 1; transform: none; } }
.sda-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 14px 16px; background: var(--navy); color: var(--paper); }
.sda-head b { display: block; font-family: var(--heading); font-weight: 400; font-size: 22px; line-height: 1; }
.sda-head small { display: block; font-family: var(--body); font-size: 12px; color: rgba(243,240,232,.6); margin-top: 5px; }
.sda-close { width: 36px; height: 36px; border-radius: 50%; border: 1px solid rgba(243,240,232,.25); background: transparent; color: var(--paper); font-size: 20px; cursor: pointer; flex: none; }
.sda-log { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; background: var(--limestone); }
.sda-msg { max-width: 86%; padding: 10px 14px; border-radius: 12px; font-size: 14.5px; line-height: 1.5; }
.sda-msg p { margin: 0; }
.sda-msg--bot { align-self: flex-start; background: var(--paper); border: 1px solid rgba(24,41,37,.1); border-bottom-left-radius: 3px; }
.sda-msg--me { align-self: flex-end; background: var(--navy); color: var(--paper); border-bottom-right-radius: 3px; }
.sda-link { display: inline-block; margin-top: 8px; font-family: var(--body); font-size: 12px; color: var(--navy); text-decoration: none; border-bottom: 1px solid var(--gold); padding-bottom: 2px; }
.sda-typing { display: flex; gap: 4px; padding: 12px 14px; } .sda-typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--gold); animation: sda-dot 1s infinite; } .sda-typing i:nth-child(2) { animation-delay: .15s; } .sda-typing i:nth-child(3) { animation-delay: .3s; }
@keyframes sda-dot { 0%, 100% { opacity: .3; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-3px); } }
.sda-sugg { display: flex; gap: 6px; flex-wrap: wrap; padding: 8px 12px 0; background: var(--limestone); }
.sda-sugg:empty { display: none; }
.sda-sugg button { font-family: var(--body); font-size: 12.5px; padding: 7px 11px; border-radius: 999px; border: 1px solid rgba(24,41,37,.2); background: var(--paper); color: var(--navy); cursor: pointer; }
.sda-sugg button:hover { border-color: var(--navy); }
.sda-form { display: flex; gap: 8px; padding: 12px; background: var(--limestone); border-top: 1px solid rgba(24,41,37,.08); }
.sda-form input { flex: 1; height: 44px; padding: 0 14px; border-radius: 999px; border: 1px solid rgba(24,41,37,.2); background: var(--paper); font-family: var(--body); font-size: 14px; color: var(--navy); outline: 0; }
.sda-form input:focus { border-color: var(--glass-2); }
.sda-form button { width: 44px; height: 44px; border-radius: 50%; border: 0; background: var(--gold); color: var(--limestone); font-size: 18px; cursor: pointer; }
.sda-foot { padding: 8px 12px 12px; background: var(--limestone); text-align: center; }
.sda-hand { background: transparent; border: 0; font-family: var(--body); font-size: 12px; color: var(--muted); cursor: pointer; text-decoration: underline; text-underline-offset: 4px; }
/* One floating control on a phone at a time, but never at the cost of a feature.
   The sticky CTA and the assistant are not the same job: the CTA is for someone
   ready to enquire, the assistant is for someone who is not ready yet. The CTA has
   substitutes on mobile (scroll, menu); the assistant has exactly one entry point
   (assistant.js:97) and hiding the launcher removes it outright.
   So they take turns off the same signal. While the CTA is up driving you to the
   form, the pill stands down; the moment the CTA steps aside at the form - which is
   when a question is most likely - the pill takes its place. body.cta-up is set in
   sd.js from the same condition that shows the CTA, so the two can never disagree.
   Opacity only, no transform: nothing moves, so this is not motion to suppress.
   Never hidden while open, or it would vanish mid-conversation. */
@media (max-width: 800px) {
  #sd-assist { right: 12px; bottom: 18px; transition: opacity .3s var(--ease), visibility .3s; }
  body.cta-up #sd-assist:not(.open) { opacity: 0; visibility: hidden; pointer-events: none; }
  .sda-launch span { display: none; }
  .sda-launch { width: 48px; padding: 0; justify-content: center; }
  .sda-panel { position: fixed; inset: auto 0 0 0; width: 100vw; height: min(78vh, 640px); border-radius: 14px 14px 0 0; }
}
@media (prefers-reduced-motion: reduce) { .sda-panel { animation: none; } .sda-typing i { animation: none; } #sd-assist { transition: none; } }

/* ---- Book a consult (header button + dialog; sd.js moves the page's form in) - */
.site-nav__book { display: inline-flex; align-items: center; height: 38px; padding: 0 16px; border-radius: 999px; border: 1px solid currentColor; font-family: var(--body); font-size: 12px; text-decoration: none; color: inherit; background: transparent; cursor: pointer; transition: background .25s, color .25s; white-space: nowrap; }
.site-nav__book:hover { background: var(--gold-fill); color: var(--navy); border-color: var(--gold-fill); }
@media (max-width: 1100px) { .site-nav__book { display: none; } }
.consult { border: 0; padding: 0; background: transparent; max-width: none; width: 100vw; height: 100vh; color: var(--paper); }
.consult::backdrop { background: rgba(24,41,37,.7); backdrop-filter: blur(8px); }
.consult__inner { position: absolute; right: 0; top: 0; bottom: 0; width: min(560px, 100vw); background: var(--navy); overflow-y: auto; padding: clamp(28px, 4vw, 48px); transform: translateX(6%); opacity: 0; transition: transform .5s var(--ease), opacity .4s; display: flex; flex-direction: column; gap: 22px; }
.consult[open] .consult__inner { transform: none; opacity: 1; }
.consult__close { position: absolute; top: 18px; right: 18px; width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(243,240,232,.3); background: transparent; color: var(--paper); font-size: 22px; cursor: pointer; }
.consult h2 { font-size: clamp(34px, 3.6vw, 52px); }
.consult .lede { color: rgba(243,240,232,.72); font-size: 16px; }
.consult .consult__slot { --flag: #D8D0C2; --ink: var(--paper); --muted: rgba(243,240,232,.66); --line: rgba(243,240,232,.16); --line-2: rgba(243,240,232,.34); --panel: var(--navy-2); color: var(--paper); }
.consult .consult__slot .thanks { border-color: var(--gold); }
.consult__fine { font-size: 12px; color: rgba(243,240,232,.5); }
html.consult-lock, html.consult-lock body { overflow: hidden; }

/* ---- Light "sheet" surfaces inside dark sections ------------------------------
   The interactive tools sit on paper so they read as drawings. Apply .sheet-light
   (or the selectors below) and the text tokens flip back to ink-on-paper. */
.sheet-light, .dark .sheet, .dark .sheet__plan, .dark .sheet__elev,
.dark .tile, .dark .rank button, .dark .door:not(.door--pro), .dark .psheet__inner,
.dark .sda-panel, .dark .lot-tip {
  --ink: var(--navy); --muted: var(--sage); --line: var(--soft-grey); --line-2: rgba(101, 112, 107, .55);
  --panel: var(--paper); color: var(--navy);
  /* the ground-aware accents must flip too, or a Stone mark lands on cream */
  --label: var(--bronze-dark); --flag: var(--bronze-dark); --on-flag: var(--limestone);
}
.dark .door:not(.door--pro) { background: var(--paper); border-color: rgba(24, 41, 37, .1); }
.dark .door:not(.door--pro) h3 { color: var(--navy); }
.dark .door--pro { background: var(--glass); color: var(--navy); --ink: var(--navy); --muted: var(--sage); --label: var(--bronze-dark); --flag: var(--bronze-dark); --on-flag: var(--limestone); border-color: transparent; }
.dark .door--pro h3 { color: var(--navy); } .dark .door--pro .n { color: var(--navy-3); }
.dark .door--pro svg.pic path, .dark .door--pro svg.pic rect, .dark .door--pro svg.pic circle, .dark .door--pro svg.pic line { stroke: var(--navy); }
.dark .pill { border-color: var(--line); }

/* ==========================================================================
   GLASS NAV — 9 Sept 2026, HOME-STORY-SESSION.md
   Replaces the floating nav on every page. The old markup is kept verbatim in
   _original/nav-pre-glass/ so it can be put back.

   Structure is borrowed from the Apple/Sony scrollytelling pattern; the COLOUR
   is not. Per BRAND-PALETTE.md: where that pattern says "deep black" this reads
   Deep Green, where it says "cyan accent" it reads Bronze, where it says
   "white/90" it reads Warm Cream. Nothing here is outside the nine colours.

   These rules come after the originals on purpose — same specificity, later in
   the file, so they win without an !important anywhere.
   ========================================================================== */
:root { --nav-h: 56px; }

.site-nav {
  height: var(--nav-h);
  grid-template-columns: auto 1fr auto;
  gap: 24px;
  background: transparent;
  border-bottom: 1px solid transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  transition: background .3s var(--ease), color .3s var(--ease),
              border-color .3s var(--ease), backdrop-filter .3s var(--ease);
}
.site-nav__logo img { width: clamp(122px, 11vw, 156px); }

/* Centre links. Sage at rest, ink on hover with a 1px bronze underline that
   grows from the left — the same accent the rest of the site uses for a rule. */
.site-nav__links { justify-self: center; display: flex; align-items: center; gap: clamp(16px, 2.2vw, 34px); }
.site-nav__links a {
  position: relative; text-decoration: none; color: var(--sage);
  font-family: var(--body); font-size: 13px; font-weight: 500;
  letter-spacing: -.005em; white-space: nowrap;
  transition: color .22s var(--ease);
}
.site-nav__links a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: -6px; height: 1px;
  background: var(--gold); transition: right .28s var(--ease);
}
.site-nav__links a:hover, .site-nav__links a:focus-visible,
.site-nav__links a[aria-current="page"] { color: var(--ink); }
.site-nav__links a:hover::after, .site-nav__links a:focus-visible::after,
.site-nav__links a[aria-current="page"]::after { right: 0; }

/* The CTA is a bronze-outline pill. --gold-fill on hover is the one bronze that
   carries text at AA (BRAND-PALETTE.md); plain --gold does not. */
.site-nav__book {
  display: inline-flex; align-items: center; height: 34px; padding: 0 16px;
  border: 1px solid var(--gold); border-radius: 999px;
  font-family: var(--body); font-size: 12px; font-weight: 600;
  letter-spacing: .01em; text-decoration: none; color: var(--gold);
  white-space: nowrap; background: transparent;
  transition: background .22s var(--ease), color .22s var(--ease), border-color .22s var(--ease);
}
.site-nav__book:hover, .site-nav__book:focus-visible {
  background: var(--gold-fill); border-color: var(--gold-fill); color: var(--limestone);
}

/* Settled state — 40px of scroll (scroll.js). Warm Cream at .78 behind a 14px
   blur, with a Soft Grey hairline. */
body.is-scrolled .site-nav {
  background: rgba(243, 240, 232, .78);
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  border-bottom-color: var(--soft-grey);
  color: var(--ink);
}
/* Over a dark section the glass inverts to Deep Green and the type goes cream. */
body.is-scrolled[data-bg="navy"] .site-nav,
body.is-scrolled[data-bg="teal"] .site-nav,
body.is-scrolled.is-dark .site-nav {
  background: rgba(24, 41, 37, .78);
  border-bottom-color: rgba(243, 240, 232, .14);
  color: var(--limestone);
}
body.is-scrolled[data-bg="navy"] .site-nav__links a,
body.is-scrolled[data-bg="teal"] .site-nav__links a,
body.is-scrolled.is-dark .site-nav__links a { color: var(--glass); }
body.is-scrolled[data-bg="navy"] .site-nav__links a:hover,
body.is-scrolled[data-bg="teal"] .site-nav__links a:hover,
body.is-scrolled.is-dark .site-nav__links a:hover,
body.is-scrolled[data-bg="navy"] .site-nav__links a[aria-current="page"],
body.is-scrolled[data-bg="teal"] .site-nav__links a[aria-current="page"],
body.is-scrolled.is-dark .site-nav__links a[aria-current="page"] { color: var(--limestone); }

/* At the very top, over the hero photograph, the links have to survive whatever
   the image is doing — cream with a soft shadow rather than sage. */
body:not(.is-scrolled) .site-nav__links a { color: var(--glass); text-shadow: 0 1px 10px rgba(24,41,37,.45); }
body:not(.is-scrolled) .site-nav__links a:hover,
body:not(.is-scrolled) .site-nav__links a[aria-current="page"] { color: var(--limestone); }
body:not(.is-scrolled) .site-nav__book { color: var(--limestone); border-color: rgba(243,240,232,.55); }
body:not(.is-scrolled) .site-nav__book:hover { background: var(--gold-fill); border-color: var(--gold-fill); color: var(--limestone); }

/* Mobile: wordmark + CTA + menu. The centre links are what the menu is for. */
@media (max-width: 900px) {
  .site-nav { grid-template-columns: auto 1fr auto; gap: 12px; }
  .site-nav__links { display: none; }
  .site-nav__book { height: 30px; padding: 0 12px; font-size: 11px; }
}
@media (max-width: 560px) {
  .site-nav__book { display: none; }
}
/* backdrop-filter is not universal; without it .78 alpha leaves the type sitting
   on whatever scrolls under it. Fall back to an opaque bar. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body.is-scrolled .site-nav { background: rgba(243, 240, 232, .97); }
  body.is-scrolled[data-bg="navy"] .site-nav,
  body.is-scrolled[data-bg="teal"] .site-nav,
  body.is-scrolled.is-dark .site-nav { background: rgba(24, 41, 37, .97); }
}
