/* Norwich Website Design — design system.
   Mirror of style-guide.html (the locked source of truth); DESIGN.md is the
   condensed agent-readable version. Shared by every page. Extracted from
   index.html on 2026-07-14 so a token change is one edit, not fifteen.

   Prototype note: this becomes the theme stylesheet in the WordPress build. */
/* ────────────────────────── Tokens (mirror of style-guide.html) ────────────────────────── */
:root {
  --brown-50:  #FAF7F1;
  --brown-100: #F0E9DA;
  --brown-200: #DCCDB1;
  --brown-300: #C2A988;
  --brown-400: #A18465;
  --brown-500: #8B6647;
  --brown-600: #6E4F35;
  --brown-700: #523A26;
  --brown-800: #3A2A1F;
  --brown-900: #2A1E17;
  --brown-950: #18110D;

  --orange-500: #C94B1F;
  --orange-600: #B03E16;

  --success: #6B7C4A;

  --cream:      #F5EFE3;
  --cream-deep: #ECE4D2;

  --line:      rgb(58 42 31 / 0.12);
  --line-mid:  rgb(58 42 31 / 0.18);
  --line-rev:  rgb(245 239 227 / 0.14);

  --font-display: "Fraunces", Georgia, serif;
  --font-body:    "Mona Sans", system-ui, sans-serif;

  --shadow-sm: 0 1px 3px 0 rgb(58 42 31 / 0.08), 0 1px 2px 0 rgb(58 42 31 / 0.04);

  /* space-3xl: 96 → 160 across 320 → 1440 */
  --sec-pad: clamp(6rem, 4.57rem + 7.14vw, 10rem);
  --gutter: clamp(1.375rem, 0.83rem + 2.7vw, 2rem);

  --ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); /* power2.out */
}

/* ────────────────────────── Base ────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--brown-800);
  font-family: var(--font-body);
  font-size: clamp(0.9375rem, 0.88rem + 0.27vw, 1rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

::selection { background: var(--brown-200); color: var(--brown-900); }

a { color: var(--orange-500); text-decoration: none; }
a:hover { color: var(--orange-600); }

:focus-visible { outline: 2px solid var(--orange-500); outline-offset: 3px; border-radius: 2px; }

/* .nwd-svc[id]: individual service rows are jump targets too, so Rescue and Plugin
   Development don't land under the sticky header. */
section[id], .nwd-svc[id] { scroll-margin-top: 120px; }

.nwd-container { max-width: 1240px; margin: 0 auto; padding-left: var(--gutter); padding-right: var(--gutter); }
.nwd-secpad { padding-top: var(--sec-pad); padding-bottom: var(--sec-pad); }
.nwd-secb   { padding-bottom: var(--sec-pad); }
/* Page openers: the id="top" section every interior page starts with. -deep trades the
   opener's tighter bottom for full section rhythm on pages that run straight into prose. */
.nwd-page-open      { padding-top: clamp(56px, 3rem + 3vw, 96px); padding-bottom: clamp(40px, 5vw, 64px); }
.nwd-page-open-deep { padding-top: clamp(56px, 3rem + 3vw, 96px); padding-bottom: var(--sec-pad); }

/* Sections that pad BOTH ends instead of borrowing a top gap from whatever precedes them
   (work_grid, testimonials). Sections get reordered and deleted in the ACF builder, so one
   that depends on its neighbour eventually collides with something — removing the page
   builders section left "In their words" welded to the shaded block above it, 0px gap.

   The exception: `.nwd-page-open` is the tight variant of a page header, whose 64px bottom
   is deliberately small so the opening flows into the content under it. Adding a full
   section pad after that would tear the two apart. `-deep` is NOT excepted: it already
   means "leave a full gap", and 2x --sec-pad there matches every other section boundary. */
.nwd-sec-both { padding-top: var(--sec-pad); padding-bottom: var(--sec-pad); }
.nwd-page-open + .nwd-sec-both { padding-top: 0; }

/* No orphans, globally: a single word alone on a line reads as a mistake (Ash flagged
   it on the build-includes list). `pretty` is progressive enhancement: engines without
   it simply wrap as before. Deliberately NOT set on headings — their wrapping is tuned
   by hand with max-width and .nwd-nb, and rebalancing would move the hero. */
p, li, dd, figcaption, .nwd-cap { text-wrap: pretty; }

.nwd-skip-link {
  position: absolute; left: 16px; top: -48px; z-index: 100;
  background: var(--brown-800); color: var(--cream);
  padding: 10px 18px; border-radius: 9999px; font-size: 14px; font-weight: 600;
  transition: top 150ms ease-out;
}
.nwd-skip-link:focus-visible { top: 12px; color: var(--cream); }

/* Announced, never drawn. Used for the copy-address confirmation. */
.nwd-sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ────────────────────────── Brand signature: orange dots ──────────────────────────
   The letter inside .nwd-i is a real "i" — copy, search and screen readers are untouched.
   An atomic inline disc is drawn after the glyph and pulled back over the tittle.
   vertical-align:<length> positions its bottom edge relative to the BASELINE, which
   is identical across engines (top/bottom of inline boxes are not — that drifted in
   Safari). --ia is the i's advance width, used to centre the disc horizontally.
   Words containing .nwd-i sit inside .nwd-nb so the atomic inline can't invite a mid-word
   line break. */
.nwd-i {
  white-space: nowrap;
  --ia: 0.25em;   /* i advance width */
  --dsc: 0.30em;  /* cover disc: hides the real tittle, painted in the surface colour */
  --ds: 0.165em;  /* orange disc diameter (per-context scale below) */
  --dy: 0.514em;  /* orange disc bottom above baseline */
  --dyc: 0.505em; /* cover disc bottom above baseline (stem top ~0.48em: don't clip it) */
}
/* One box, two painted discs. The box paints AFTER the glyph, so the surface-colour
   layer erases the real tittle and the logo-sized orange disc sits on top of it. */
.nwd-i::after {
  content: none; /* dots are a display-size signature: enabled per context below */
  display: inline-block;
  width: var(--dsc); height: var(--dsc);
  vertical-align: var(--dyc);
  background-image:
    radial-gradient(closest-side, var(--orange-500) 97%, transparent 100%),
    radial-gradient(closest-side, var(--bg, var(--cream)) 97%, transparent 100%);
  background-repeat: no-repeat;
  background-size: var(--ds) var(--ds), 100% 100%;
  background-position:
    calc((var(--dsc) - var(--ds)) / 2) calc(var(--dsc) - (var(--dy) - var(--dyc)) - var(--ds)),
    0 0;
  margin-left: calc((var(--ia) + var(--dsc)) / -2 + 0.025em);
  margin-right: calc((var(--ia) - var(--dsc)) / 2 - 0.025em);
}
.nwd-h-display .nwd-i::after, .nwd-h-section .nwd-i::after, .nwd-trust-head .nwd-i::after,
.nwd-hero-sub .nwd-i::after, .nwd-contact-inner h2 .nwd-i::after { content: ""; }
/* The logo draws the dot at 0.18em on wght-700 letterforms (r=180 / 2000upm). Lighter
   headings need a proportionally lighter dot or it reads as a blob on thinner strokes.
   --dy is per-context too (2026-07-17): the orange disc's CENTRE must sit at the real
   tittle's centre, 0.583em above baseline, so its bottom is 0.583 - ds/2. The old fixed
   0.514em put the largest dot ~0.014em high and the real tittle peeked out underneath
   (Ash spotted it on the hero). Verified at 340px magnification: covered, stem clear. */
.nwd-h-display .nwd-i        { --ds: 0.165em; --dy: 0.500em; }  /* wght 640 */
.nwd-contact-inner h2 .nwd-i { --ds: 0.159em; --dy: 0.504em; }  /* wght 620 */
.nwd-h-section .nwd-i        { --ds: 0.154em; --dy: 0.506em; }  /* wght 600 */
.nwd-hero-sub .nwd-i         { --ds: 0.144em; --dy: 0.511em; }  /* wght 560 */
.nwd-trust-head .nwd-i       { --ds: 0.134em; --dy: 0.516em; }  /* wght 520 */
.nwd-nb { white-space: nowrap; }
.nwd-dot { color: var(--orange-500); }

/* ────────────────────────── Type ────────────────────────── */
.nwd-eyebrow {
  font-family: var(--font-body);
  text-transform: uppercase; letter-spacing: 0.18em;
  font-size: 11px; font-weight: 600;
  color: var(--brown-600);
  margin: 0 0 24px;
}

.nwd-h-display {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 24, "wght" 640;
  font-size: clamp(2.85rem, 1.5rem + 3.6vw, 4.6rem);
  line-height: 1.02; letter-spacing: -0.02em;
  color: var(--brown-800);
  margin: 0 0 28px;
  text-wrap: balance;
}

.nwd-h-section {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 24, "wght" 600;
  font-size: clamp(2rem, 1.5rem + 1.9vw, 3.1rem);
  line-height: 1.08; letter-spacing: -0.015em;
  color: var(--brown-800);
  margin: 0;
  text-wrap: balance;
}

.nwd-h-item {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "SOFT" 16, "wght" 560;
  font-size: clamp(1.4rem, 1.2rem + 0.7vw, 1.85rem);
  line-height: 1.15;
  color: var(--brown-800);
  margin: 0 0 10px;
}

.nwd-lead {
  font-size: clamp(1.05rem, 1rem + 0.25vw, 1.2rem);
  line-height: 1.6;
  color: var(--brown-800);
  margin: 0;
}

.nwd-muted { color: var(--brown-600); }

.nwd-stamp {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 30, "wght" 700;
  letter-spacing: -0.02em; line-height: 1;
  white-space: nowrap;
}

.nwd-stat-num {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 24, "wght" 620;
  font-size: clamp(3rem, 2.2rem + 3vw, 4.6rem);
  line-height: 0.95; letter-spacing: -0.02em;
  color: var(--brown-800);
}

/* ────────────────────────── Buttons ────────────────────────── */
/* Global button wipe: a background-image layer sized 0% -> 100%, not a ::before
   (a pseudo would paint over the bare text label). TRAP: every button variant must
   set background-COLOR, never the `background` shorthand — the shorthand resets
   background-image and the wipe silently disappears. */
.nwd-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 24px;
  font-family: var(--font-body); font-size: 15px; font-weight: 500; line-height: 1;
  border-radius: 9999px; border: 1.5px solid transparent;
  cursor: pointer;
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 0% 100%;
  /* The wipe must be measured from the BORDER box, not the padding box. Default
     background-origin leaves the 1.5px transparent border showing the base background-COLOR,
     so a fully-wiped button keeps a hairline ring of its old colour. Invisible while primary
     wiped brown-950 over brown-800; instantly obvious once it wiped to orange. */
  background-origin: border-box;
  transition: background-size 420ms var(--ease-out),
              background-color 200ms ease,
              color 260ms var(--ease-out),
              border-color 260ms var(--ease-out),
              box-shadow 200ms ease;
}
.nwd-btn:hover { background-size: 100% 100%; }
/* Reduced motion still gets the colour change, it just arrives rather than travels. */
@media (prefers-reduced-motion: reduce) {
  .nwd-btn { transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease; }
  .nwd-btn:hover { background-size: 100% 100%; }
}

/* Wipes brown-800 -> ORANGE-600 (Ash, 2026-07-30). It used to wipe to brown-950, which is
   near-black arriving over near-black: the animation ran, but nothing looked like it had
   happened. Orange-600 and not orange-500: cream on orange-500 is 4.07:1, under the 4.5 AA
   floor for 15px text, while orange-600 clears it at 5.17:1. An earlier note here ruled out
   "orange" wholesale on that basis, which was too broad — it is only true of the 500. */
.nwd-btn-primary { background-color: var(--brown-800); background-image: linear-gradient(var(--orange-600), var(--orange-600)); color: var(--cream); }
.nwd-btn-primary:hover { color: var(--cream); box-shadow: var(--shadow-sm); }
/* No hover on touch, so :active is the only feedback there — it has to be the orange too,
   not the old brown-950, or a tap looks like a miss. */
.nwd-btn-primary:active { background-color: var(--orange-600); }
/* Secondary fills solid on hover rather than taking a 6% tint: the tint was so quiet it
   read as nothing happening. The label flips to cream as the brown arrives. */
.nwd-btn-secondary { background-color: transparent; background-image: linear-gradient(var(--brown-800), var(--brown-800)); color: var(--brown-800); border-color: var(--brown-800); }
.nwd-btn-secondary:hover { color: var(--cream); }
.nwd-btn-secondary:active { background-color: rgb(58 42 31 / 0.1); }
/* The dark band's CTA — the same "Let's chat" as .nwd-btn-primary, so it wipes to the same
   orange-600 and flips its label to cream (5.17:1). Hovering a CTA turns it orange, wherever
   it sits.
   FIXED 2026-07-30: there were two competing :hover rules here, and the winner used the
   `background` SHORTHAND — which resets background-image and so deleted the wipe layer
   entirely. The button just stepped cream -> cream-deep, a change barely visible on a dark
   band. This is precisely the trap the note at the top of this block warns about. */
.nwd-btn-inverse { background-color: var(--cream); background-image: linear-gradient(var(--orange-600), var(--orange-600)); color: var(--brown-800); }
.nwd-btn-inverse:hover { color: var(--cream); }
.nwd-btn-inverse:active { background-color: var(--orange-600); color: var(--cream); }

.nwd-logo-link { display: inline-flex; line-height: 0; }
.nwd-logo-img { height: clamp(56px, 48px + 1.2vw, 74px); width: auto; display: block; }
.nwd-logo-img-footer { height: 20px; }
.nwd-stamp img { height: clamp(46px, 32px + 2.2vw, 66px); width: auto; display: inline-block; }

/* ────────────────────────── Header ────────────────────────── */
.nwd-site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgb(245 239 227 / 0.86);
  backdrop-filter: saturate(1.1) blur(10px);
  -webkit-backdrop-filter: saturate(1.1) blur(10px);
  border-bottom: 1px solid var(--line);
}
.nwd-site-header .nwd-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding-top: 12px; padding-bottom: 12px;
}
.nwd-site-nav { display: flex; align-items: center; gap: 36px; }
.nwd-site-nav > a:not(.nwd-btn), .nwd-has-mega > a { color: var(--brown-800); font-size: 15px; font-weight: 500; }
.nwd-site-nav > a:not(.nwd-btn):hover, .nwd-has-mega > a:hover { color: var(--orange-600); }

/* Current page: the orange dot under the word. Uses ::before — ::after is already
   the mega's invisible hover bridge. The "Let's chat" button is exempt. */
.nwd-site-nav > a[aria-current="page"]:not(.nwd-btn),
.nwd-has-mega > a[aria-current="page"],
.nwd-has-mega > a.nwd-is-section { position: relative; }

.nwd-site-nav > a[aria-current="page"]:not(.nwd-btn)::before,
.nwd-has-mega > a[aria-current="page"]::before,
.nwd-has-mega > a.nwd-is-section::before {
  content: ""; position: absolute;
  left: 50%; bottom: -8px;
  width: 5px; height: 5px; margin-left: -2.5px;
  border-radius: 50%;
  background: var(--orange-500);
}

/* A service child page marks the top-level Services item too: the exact page's link lives
   inside the mega, which is shut, so without this the header says nothing at all on six of
   the fifteen pages. */
.nwd-mega-item[aria-current="page"] .nwd-mi-name { color: var(--orange-600); }
.nwd-mm-link[aria-current="page"] { color: var(--orange-600); }

/* ────────────────────────── Mega menu (Services) ────────────────────────── */
.nwd-has-mega { align-self: stretch; display: inline-flex; align-items: center; }
.nwd-has-mega > a { position: relative; }
/* Invisible bridge over the header→panel gap so the menu stays open while the
   pointer travels down into it. Only catches events once the menu is open. */
.nwd-has-mega > a::after {
  content: ""; position: absolute;
  top: 100%; left: -24px; right: -24px; height: 3.5rem;
  pointer-events: none;
}
.nwd-has-mega:hover > a::after, .nwd-has-mega:focus-within > a::after { pointer-events: auto; }
.nwd-mega {
  position: absolute; top: 100%; left: 0; right: 0;
  background: var(--cream);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  box-shadow: 0 10px 15px -3px rgb(58 42 31 / 0.10), 0 4px 6px -2px rgb(58 42 31 / 0.05);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out), visibility 0s linear 300ms;
}
.nwd-has-mega:hover .nwd-mega, .nwd-has-mega:focus-within .nwd-mega {
  opacity: 1; visibility: visible; transform: none; pointer-events: auto;
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out);
}
@media (prefers-reduced-motion: reduce) {
  .nwd-mega { transition: none; transform: none; }
}
/* Exactly 3 columns: six services divide evenly into two full rows. auto-fit gave
   four across and left an orphan row of two beside a dead half. The mega only
   exists above 1024px, so a fixed count is safe here. */
.nwd-mega-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 4px 12px; padding-top: 24px; padding-bottom: 28px;
}
.nwd-mega-item {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 13px 14px; border-radius: 4px;
  transition: background 150ms ease-out;
}
.nwd-mega-item:hover { background: var(--brown-50); }
.nwd-mega-item .ph { flex: 0 0 auto; font-size: 24px; line-height: 1; margin-top: 1px; color: var(--brown-800); }
.nwd-mi-name {
  display: block;
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "SOFT" 16, "wght" 560;
  font-size: 17px; line-height: 1.25; color: var(--brown-800);
  margin-bottom: 4px;
}
.nwd-mi-desc { display: block; font-size: 13px; line-height: 1.45; color: var(--brown-600); }
@media (max-width: 1024px) { .nwd-has-mega { display: none; } }

/* ────────────────────────── Mobile nav ────────────────────────── */
.nwd-nav-burger { display: none; }
@media (max-width: 1024px) {
  .nwd-site-nav { display: none; }
  .nwd-nav-burger {
    display: inline-flex; align-items: center; justify-content: center;
    position: relative;
    width: 44px; height: 44px; margin-right: -8px;
    background: none; border: 0; cursor: pointer; color: var(--brown-800);
    -webkit-tap-highlight-color: transparent;
  }
}
/* Both icons live in the button, stacked; opening cross-rotates them so the burger
   MORPHS into the X in place. The header (and its logo) stays put throughout. */
.nwd-nav-burger .ph {
  font-size: 25px; line-height: 1;
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 250ms var(--ease-out), transform 300ms var(--ease-out);
}
.nwd-nav-burger .ph-x { opacity: 0; transform: translate(-50%, -50%) rotate(-90deg); }
html.nwd-menu-open .nwd-nav-burger .ph-list { opacity: 0; transform: translate(-50%, -50%) rotate(90deg); }
html.nwd-menu-open .nwd-nav-burger .ph-x { opacity: 1; transform: translate(-50%, -50%) rotate(0deg); }
.nwd-nav-burger:focus-visible { outline: 2px solid var(--orange-500); outline-offset: 2px; border-radius: 4px; }

/* The panel falls from under the header and draws back up on close. It sits BELOW the
   header (z 40 < 50) so the slide emerges from the header's bottom edge; --nwd-header-h
   is measured by nwd.js at open. The header goes opaque while open, or the panel would
   ghost through its backdrop blur mid-slide. */
.nwd-mobile-menu {
  position: fixed; top: var(--nwd-header-h, 64px); left: 0; right: 0; bottom: 0;
  z-index: 40;
  background: var(--cream);
  display: none; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain;
  visibility: hidden; transform: translateY(-100%);
  transition: transform 420ms var(--ease-out), visibility 0s linear 420ms;
}
@media (max-width: 1024px) { .nwd-mobile-menu { display: flex; } }
html.nwd-menu-open .nwd-mobile-menu {
  visibility: visible; transform: none;
  transition: transform 420ms var(--ease-out);
}
/* Opaque INSTANTLY on open, but on close hold the opacity until the panel has fully
   tucked away (420ms), then fade back to the blur — reverting mid-slide lets the
   panel ghost through the translucent header, which read as a jump. */
.nwd-site-header { transition: background-color 200ms ease 420ms; }
html.nwd-menu-open .nwd-site-header { background: var(--cream); transition: background-color 0s; }
@media (prefers-reduced-motion: reduce) {
  .nwd-mobile-menu { transform: none; opacity: 0; transition: opacity 300ms ease, visibility 0s linear 300ms; }
  html.nwd-menu-open .nwd-mobile-menu { opacity: 1; transition: opacity 300ms ease; }
  .nwd-nav-burger .ph { transition: none; }
}
@media (max-width: 1024px) { html.nwd-menu-open { overflow: hidden; } }
/* width:100% is required — .nwd-container's `margin: 0 auto` would otherwise
   shrink-wrap this inside the column flexbox instead of stretching it. */
.nwd-mm-body { width: 100%; }
.nwd-mm-body { padding-top: 24px; padding-bottom: 48px; }
.nwd-mm-list { list-style: none; margin: 0; padding: 0; }
/* Services accordion: grid-template-rows animates cleanly, height does not. */
.nwd-mm-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; padding: 13px 0; background: none; border: 0; cursor: pointer;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "SOFT" 16, "wght" 540;
  font-size: 21px; line-height: 1.2; color: var(--brown-800); text-align: left;
}
.nwd-mm-toggle:hover, .nwd-mm-toggle:focus-visible { color: var(--orange-600); }
.nwd-mm-toggle .ph { font-size: 20px; transition: transform 300ms var(--ease-out); }
.nwd-mm-toggle[aria-expanded="true"] .ph { transform: rotate(180deg); }
.nwd-mm-panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 300ms var(--ease-out); }
.nwd-mm-toggle[aria-expanded="true"] + .nwd-mm-panel { grid-template-rows: 1fr; }
/* visibility, not just overflow: a 0fr row clips the links to zero height but leaves
   them focusable, so Tab would walk through six invisible service links. Delayed off
   so they stay painted for the 300ms collapse. */
.nwd-mm-panel-inner { overflow: hidden; visibility: hidden; transition: visibility 0s linear 300ms; }
.nwd-mm-toggle[aria-expanded="true"] + .nwd-mm-panel .nwd-mm-panel-inner { visibility: visible; transition-delay: 0s; }
.nwd-mm-services .nwd-mm-link { font-size: 17px; padding-left: 16px; }
@media (prefers-reduced-motion: reduce) {
  .nwd-mm-panel { transition: none; }
  .nwd-mm-toggle .ph { transition: none; }
  /* The rows snap shut instantly here, so the links must leave the tab order
     instantly too rather than lingering for the 300ms fade-out delay. */
  .nwd-mm-panel-inner { transition: none; }
}
.nwd-mm-list li { border-bottom: 1px solid var(--line); }
.nwd-mm-link {
  display: block; padding: 13px 0;
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "SOFT" 16, "wght" 540;
  font-size: 21px; line-height: 1.2; color: var(--brown-800);
}
.nwd-mm-link:hover, .nwd-mm-link:focus-visible { color: var(--orange-600); }
/* Work / Pricing / About are peers of the Services toggle, so they carry the same
   display type. Only the nested service links step down. */
/* No extra margin: the row rhythm (13px padding + hairline) must match between every
   item, Services included — the accordion's collapsed panel contributes zero height. */
.nwd-mm-sub { margin-top: 0; }
.nwd-mm-cta { margin-top: 28px; width: 100%; }

/* ────────────────────────── Hero ────────────────────────── */
.nwd-hero {
  padding-top: clamp(56px, 3rem + 3vw, 96px); padding-bottom: var(--sec-pad);
  display: flex; flex-wrap: wrap; gap: clamp(32px, 4vw, 72px); align-items: center;
}
.nwd-hero-inner { flex: 1 1 520px; max-width: 740px; }

/* ── Hero visual + entrance animation (integrated from the hero animation build) ── */
.nwd-hero-media { flex: 1 1 320px; max-width: 440px; display: flex; flex-direction: column; gap: 12px; }
.nwd-hero-visual { position: relative; width: 100%; aspect-ratio: 10 / 9; }
.nwd-hero-controls { display: flex; justify-content: flex-start; }
.nwd-hero-controls .nwd-seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--cream-deep); border: 1px solid var(--line); border-radius: 9999px; }
.nwd-hero-controls button { appearance: none; -webkit-appearance: none; border: 0; background: transparent; cursor: pointer; font-family: var(--font-body); font-size: 12px; font-weight: 500; letter-spacing: 0.01em; color: var(--brown-600); padding: 6px 14px; border-radius: 9999px; transition: background 200ms var(--ease-out), color 200ms var(--ease-out); }
.nwd-hero-controls button:hover { color: var(--brown-800); }
.nwd-hero-controls button[aria-pressed="true"] { background: var(--cream); color: var(--brown-800); box-shadow: 0 1px 2px rgb(58 42 31 / 0.12); }
.nwd-bframe {
  position: absolute;
  background: var(--cream); border: 1px solid var(--line-mid); border-radius: 4px;
  overflow: hidden; display: flex; flex-direction: column;
}
.nwd-bframe-back { top: 0; right: 0; width: 64%; height: 58%; }
.nwd-bframe-back .nwd-bshot { background: var(--cream); padding: 0; display: flex; align-items: stretch; }
.nwd-bframe-back .nwd-wp { display: flex; width: 100%; height: 100%; }
.nwd-bframe-back .nwd-wp-side { width: 30%; max-width: 72px; flex: 0 0 auto; background: var(--brown-900); padding: 11px 9px; display: flex; flex-direction: column; gap: 8px; }
.nwd-bframe-back .nwd-wp-side .nwd-m { height: 5px; border-radius: 2px; background: rgb(245 239 227 / 0.28); }
.nwd-bframe-back .nwd-wp-side .nwd-m.nwd-w1 { width: 80%; } .nwd-bframe-back .nwd-wp-side .nwd-m.nwd-w2 { width: 64%; } .nwd-bframe-back .nwd-wp-side .nwd-m.nwd-w3 { width: 72%; }
.nwd-bframe-back .nwd-wp-side .nwd-m.nwd-active { background: var(--orange-500); width: 88%; height: 6px; }
.nwd-bframe-back .nwd-wp-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.nwd-bframe-back .nwd-wp-top { height: 28px; flex: 0 0 auto; border-bottom: 1px solid var(--line); display: flex; align-items: center; justify-content: flex-end; padding: 0 10px; }
.nwd-bframe-back .nwd-wp-publish { width: 44px; height: 14px; border-radius: 9999px; background: var(--orange-500); }
.nwd-bframe-back .nwd-wp-doc { padding: 11px 12px; display: flex; flex-direction: column; gap: 7px; }
.nwd-bframe-back .nwd-wp-doc .nwd-h { width: 70%; height: 9px; border-radius: 2px; background: var(--brown-800); }
.nwd-bframe-back .nwd-wp-doc .nwd-l { height: 5px; border-radius: 2px; background: var(--brown-200); }
.nwd-bframe-back .nwd-wp-doc .nwd-l.nwd-a { width: 100%; } .nwd-bframe-back .nwd-wp-doc .nwd-l.nwd-b { width: 92%; } .nwd-bframe-back .nwd-wp-doc .nwd-l.nwd-c { width: 97%; } .nwd-bframe-back .nwd-wp-doc .nwd-l.nwd-d { width: 60%; }
.nwd-bframe-back .nwd-wp-block { margin-top: 5px; height: 44px; border-radius: 5px; border: 1px dashed var(--line-mid); background: repeating-linear-gradient(135deg, rgb(58 42 31 / 0.05) 0 8px, rgb(58 42 31 / 0.02) 8px 16px); }
.nwd-bframe-front { bottom: 0; left: 0; width: 76%; height: 68%; z-index: 2; }
.nwd-bbar {
  display: flex; align-items: center; gap: 5px;
  padding: 0 10px; height: 26px; flex: 0 0 auto;
  border-bottom: 1px solid var(--line);
  background: var(--cream);
}
.nwd-bdot { width: 7px; height: 7px; border-radius: 9999px; background: var(--brown-200); flex: 0 0 auto; }
.nwd-burl {
  margin-left: 8px; font-size: 10px; letter-spacing: 0.04em; line-height: 1.4;
  color: var(--brown-600); background: var(--cream);
  border: 1px solid var(--line); border-radius: 9999px; padding: 2px 10px;
  display: inline-flex; align-items: baseline;
}
/* orange-600, not orange-500: at 9-10px the lighter accent measured 4.07:1 on
   cream, under the 4.5:1 floor. This keeps the brand tint and clears AA. */
.nwd-burl b { color: var(--orange-600); font-weight: 600; }
/* mobile chrome: drop the traffic-light dots and give the full domain the width */
.nwd-bframe-front.nwd-is-mobile .nwd-bbar { gap: 0; justify-content: center; padding: 0 6px; }
.nwd-bframe-front.nwd-is-mobile .nwd-bdot { display: none; }
.nwd-bframe-front.nwd-is-mobile .nwd-burl { margin-left: 0; padding: 2px 8px; font-size: 9px; letter-spacing: 0.02em; }
.nwd-caret {
  display: inline-block; width: 1px; height: 1.05em; margin-left: 1px;
  transform: translateY(0.12em);
  background: var(--brown-600); opacity: 0;
}
.nwd-bshot {
  flex: 1;
  background: repeating-linear-gradient(135deg, rgb(58 42 31 / 0.07) 0 9px, rgb(58 42 31 / 0.02) 9px 18px);
  display: flex; align-items: flex-end; padding: 10px;
}
.nwd-ph-label { font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: 0.12em; color: var(--brown-600); }

/* ────────────────────────── Live responsive website — the whole front window resizes (idle demo) ────────── */
.nwd-bshot--live { position: relative; padding: 0; background: var(--cream); align-items: stretch; }
/* Deliberate exception to "never animate layout properties": the whole point is a
   browser window changing width so the site inside it reflows responsively. A
   transform would scale the contents instead of re-laying them out, which is the
   opposite of the demo. Contained: the frame is absolutely positioned, so it
   reflows only its own subtree, never the page. */
.nwd-bframe-front { transition: width 750ms var(--ease-out); }
.nwd-site { position: absolute; inset: 0; display: flex; flex-direction: column; overflow: hidden; }

.nwd-s-hero { position: relative; flex: 1; min-height: 0; overflow: hidden; background: var(--cream-deep);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 14px; }
.nwd-s-motif { position: absolute; border: 2px solid var(--line-mid); border-radius: 9999px; }
.nwd-s-m1 { width: 150px; height: 150px; top: -56px; left: -42px; }
.nwd-s-m2 { width: 92px; height: 92px; bottom: -38px; right: -18px; border-color: rgb(201 75 31 / 0.3); }
.nwd-s-copy { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; width: 100%; }
.nwd-s-h { height: 7px; border-radius: 2px; background: var(--brown-800); }
.nwd-s-h.nwd-l1 { width: 72%; } .nwd-s-h.nwd-l2 { width: 50%; }
.nwd-s-btn { width: 64px; height: 14px; border-radius: 9999px; background: var(--orange-500); margin-top: 5px; }
.nwd-s-boxes { display: grid; grid-template-columns: repeat(2, 1fr); gap: 7px; padding: 9px; flex: 0 0 auto; }
.nwd-s-box { background: var(--cream-deep); border-radius: 4px; padding: 8px; display: flex; flex-direction: column; gap: 5px; height: 52px; }
.nwd-s-box .nwd-k { width: 13px; height: 13px; border-radius: 4px; background: var(--cream); }
.nwd-s-box .nwd-l { height: 4px; border-radius: 2px; background: var(--brown-200); }

/* device layouts — toggled by JS */
.nwd-dev-tablet .nwd-s-m1 { width: 130px; height: 130px; }
.nwd-dev-mobile .nwd-s-boxes { grid-template-columns: 1fr; }
.nwd-dev-mobile .nwd-s-h.nwd-l1 { width: 82%; } .nwd-dev-mobile .nwd-s-h.nwd-l2 { width: 62%; }
.nwd-dev-mobile .nwd-s-m1 { width: 110px; height: 110px; }

/* ── Hand-drawn peeker (only while Mobile is shown) ── */
.nwd-peeker {
  position: absolute; left: calc(30% - 14px); bottom: 4%; width: 48px; z-index: 1;  transform: rotate(20deg) translateX(-18px); opacity: 0; pointer-events: none;
  transition: transform 500ms var(--ease-out), opacity 400ms var(--ease-out);
}
.nwd-hero-visual.nwd-show-peeker .nwd-peeker { transform: rotate(20deg) translateX(0); opacity: 1; }
.nwd-peeker svg { display: block; overflow: visible; }
.nwd-peeker .nwd-ink { fill: none; stroke: var(--brown-800); stroke-width: 3.6; stroke-linecap: round; stroke-linejoin: round; filter: url(#roughen); }
.nwd-peeker .nwd-wave { transform-box: fill-box; transform-origin: 0px 25px; }
.nwd-hero-visual.nwd-show-peeker .nwd-peeker .nwd-wave { animation: peekWave 0.9s var(--ease-out) 0.45s 3 alternate; }
@keyframes peekWave { from { transform: rotate(-10deg); } to { transform: rotate(26deg); } }
.nwd-peeker .nwd-bubble {
  position: absolute; top: -20px; left: 30px; white-space: nowrap;
  background: var(--cream); color: var(--brown-800);
  font-family: var(--font-body); font-size: 11px; font-weight: 600; letter-spacing: 0.01em;
  padding: 4px 9px; border: 2px solid var(--brown-800); border-radius: 11px 11px 11px 3px;
  transform: scale(0); transform-origin: 0 100%;
  transition: transform 300ms var(--ease-out);
}
.nwd-peeker .nwd-bubble::after {
  content: ""; position: absolute; left: 6px; bottom: -6px;
  width: 8px; height: 8px; background: var(--cream);
  border-right: 2px solid var(--brown-800); border-bottom: 2px solid var(--brown-800);
  transform: rotate(45deg);
}
.nwd-hero-visual.nwd-show-peeker .nwd-peeker .nwd-bubble { transform: scale(1); transition-delay: 350ms; }

/* ══════════════════════════ ANIMATION LAYER ══════════════════════════ */
/* Pre-hide before first paint, only when .nwd-anim is present (added synchronously in
   <head>; never under prefers-reduced-motion / no-WAAPI).
   TRAP — scoped to .nwd-hero on purpose: only hero.js un-hides these and it is
   home-only, so an unscoped rule would hide these classes FOREVER on every other page.
   Don't "simplify" the selectors. */
.nwd-anim .nwd-hero .nwd-h-display,
.nwd-anim .nwd-hero .nwd-hero-sub,
.nwd-anim .nwd-hero .nwd-hero-note,
.nwd-anim .nwd-hero .nwd-hero-small,
.nwd-anim .nwd-hero .nwd-hero-rescue,
.nwd-anim .nwd-hero .nwd-grev,
.nwd-anim .nwd-hero .nwd-bframe { opacity: 0; }
.nwd-anim .nwd-hero .nwd-hero-actions .nwd-btn { opacity: 0; }
.nwd-anim .nwd-hero .nwd-bshot--live .nwd-site { opacity: 0; }

/* Section reveals (600ms / 60ms stagger per DESIGN.md). `.nwd-rv` is applied BY JS,
   never in markup: if JS, WAAPI or the observer is missing, the class never lands and
   nothing can strand invisible. Only the homepage hero opts out (hero.js owns it). */
.nwd-anim .nwd-rv { opacity: 0; }

/* Also .hero-scoped: hero.js pops these, and it is home-only. Unscoped, every
   i-tittle and full stop on every other page would sit at scale(0) permanently. */
.nwd-anim .nwd-hero .nwd-h-display .nwd-i::after,
.nwd-anim .nwd-hero .nwd-hero-sub .nwd-i::after { transform: scale(0); }

/* Only .nwd-h-display carries a terminal orange stop now (see the dot rule in §03). */
.nwd-anim .nwd-hero .nwd-h-display .nwd-dot { display: inline-block; transform: scale(0); }

/* Orange i-dot pop — pseudo-elements can't be driven by WAAPI, so a class does it. */
@keyframes dotPop { from { transform: scale(0); } to { transform: scale(1); } }
.nwd-anim .nwd-i.nwd-dot-in::after { animation: dotPop 200ms var(--ease-out) both; }

@media (prefers-reduced-motion: reduce) {
  .nwd-anim .nwd-hero .nwd-h-display, .nwd-anim .nwd-hero .nwd-hero-sub, .nwd-anim .nwd-hero .nwd-hero-note, .nwd-anim .nwd-hero .nwd-hero-small,
  .nwd-anim .nwd-hero .nwd-hero-rescue, .nwd-anim .nwd-hero .nwd-grev,
  .nwd-anim .nwd-hero .nwd-bframe, .nwd-anim .nwd-hero .nwd-hero-actions .nwd-btn, .nwd-anim .nwd-hero .nwd-bshot--live .nwd-site { opacity: 1; }
  .nwd-anim .nwd-hero .nwd-h-display .nwd-i::after, .nwd-anim .nwd-hero .nwd-hero-sub .nwd-i::after,
  .nwd-anim .nwd-hero .nwd-h-display .nwd-dot { transform: none; }
  .nwd-anim .nwd-rv { opacity: 1; }
  .nwd-bframe-front { transition: none; }
}

@media (max-width: 1024px) {
  /* The animation stays on mobile but follows the copy. The headline names the
     visitor's problem and the CTA answers it, so those own the fold; the visual is
     the proof, and proof comes after the claim. It led here until 2026-07-14, where
     at 42% of a 375x812 fold it pushed "Let's chat" off the screen entirely. */
  .nwd-hero { flex-direction: column; align-items: stretch; }
  .nwd-hero-media { flex: 0 0 auto; width: 100%; max-width: 380px; margin: 8px auto 0; }
  .nwd-hero-inner { flex: 0 0 auto; max-width: none; }
  .nwd-hero-controls { justify-content: center; }
}
.nwd-hero-sub {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "SOFT" 20, "wght" 560;
  font-size: clamp(1.35rem, 1.1rem + 0.9vw, 1.75rem);
  line-height: 1.25; letter-spacing: -0.01em;
  color: var(--brown-600);
  font-weight: normal;
  margin: 0 0 14px;
}
.nwd-hero-note { font-size: clamp(1.05rem, 0.98rem + 0.3vw, 1.2rem); line-height: 1.55; margin: 0 0 40px; max-width: 44ch; }
.nwd-hero-actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.nwd-hero-small { font-size: 15px; color: var(--brown-600); margin: 24px 0 0; }

/* The emergency catch: one quiet line for the visitor whose site is down right now.
   The orange lifebuoy is the only signal — the text stays muted so calm visitors
   read past it without noticing. */
.nwd-hero-rescue { font-size: 14px; margin: 12px 0 0; }
.nwd-hero-rescue a {
  color: var(--brown-600);
  text-decoration: underline;
  text-decoration-color: var(--line-mid);
  text-underline-offset: 3px;
  transition: color 200ms ease, text-decoration-color 200ms ease;
}
.nwd-hero-rescue a:hover { color: var(--brown-800); text-decoration-color: var(--orange-500); }
.nwd-hero-rescue .ph { color: var(--orange-500); font-size: 16px; vertical-align: -2px; margin-right: 7px; }

/* ─────────────────── Google review badge ─────────────────── */
/* Sits where the rescue link used to, under the hero small print. Given its own tinted
   surface so it reads as a badge rather than a fifth line of copy. The star gold is warmed
   towards the brand rather than Google's #FBBC04, which is far too pale to hold on cream. */
.nwd-grev { margin: 18px 0 0; }
.nwd-grev-in {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 9px 15px;
  background: var(--brown-50);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--brown-700);
  text-decoration: none;
  transition: border-color 200ms var(--ease-out), background 200ms var(--ease-out);
}
a.nwd-grev-in:hover { background: #fff; border-color: var(--line-mid); }
.nwd-grev-g { width: 17px; height: 17px; flex: none; }

.nwd-grev-stars { position: relative; display: inline-block; line-height: 0; flex: none; }
.nwd-grev-track, .nwd-grev-fill { display: block; white-space: nowrap; line-height: 0; }
.nwd-grev-fill {
  position: absolute; inset: 0;
  overflow: hidden;   /* inline width clips the gold layer to the score */
}
.nwd-grev-stars svg { width: 15px; height: 14px; margin-right: 2px; }
.nwd-grev-track svg { fill: var(--brown-200); }
.nwd-grev-fill  svg { fill: #E3A008; }

.nwd-grev-text { font-size: 14px; letter-spacing: -0.005em; white-space: nowrap; }
.nwd-grev-text b { font-weight: 600; color: var(--brown-800); }

@media (max-width: 400px) {
  .nwd-grev-in { gap: 8px; padding: 8px 12px; }
  .nwd-grev-text { font-size: 13px; }
  .nwd-grev-stars svg { width: 14px; height: 13px; }
}

/* ────────────────────────── Intro ────────────────────────── */
.nwd-intro-cols { display: flex; flex-wrap: wrap; gap: clamp(28px, 5vw, 72px); margin: 0 0 56px; }
.nwd-intro-col {
  flex: 1 1 300px;
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "SOFT" 16, "wght" 420;
  font-size: clamp(1.5rem, 1.2rem + 1.1vw, 2.15rem);
  line-height: 1.34; letter-spacing: -0.01em;
  max-width: 26ch; margin: 0;
}
.nwd-wp-stat {
  display: flex; flex-wrap: wrap; gap: clamp(28px, 4vw, 64px); align-items: center;
  background: var(--cream-deep); border: 1px solid var(--line); border-radius: 4px;
  padding: clamp(32px, 4vw, 52px);
}
.nwd-wp-stat .nwd-big {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 24, "wght" 640;
  font-size: clamp(3.4rem, 2.4rem + 3.4vw, 5.5rem);
  line-height: 0.9; letter-spacing: -0.02em;
  color: var(--brown-800);
}
.nwd-wp-stat .nwd-cap { font-size: 14px; color: var(--brown-600); margin-top: 10px; max-width: 16ch; }
.nwd-wp-stat p { flex: 1 1 420px; font-size: clamp(1.1rem, 1rem + 0.4vw, 1.35rem); line-height: 1.55; margin: 0; max-width: 64ch; }

/* ────────────────────────── Trust bar ────────────────────────── */
.nwd-trust-head {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 20, "wght" 520;
  font-size: clamp(1.55rem, 1.1rem + 1.6vw, 2.5rem);
  line-height: 1.18; letter-spacing: -0.015em;
  color: var(--brown-800);
  margin: 0 auto; max-width: 24ch;
}
.nwd-marquee {
  overflow: hidden; padding-bottom: 60px;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
}
.nwd-marquee-track { display: flex; width: max-content; animation: marquee 67s linear infinite; }
/* trailing padding matches the gap so the two sets tile seamlessly at -50% */
.nwd-marquee-set { display: flex; gap: 44px; padding-right: 44px; }
.nwd-marquee:hover .nwd-marquee-track { animation-play-state: paused; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .nwd-marquee-track { animation: none; width: auto; }
  .nwd-marquee-set { flex-wrap: wrap; justify-content: center; padding-right: 0; row-gap: 28px; }
  .nwd-marquee-set[aria-hidden] { display: none; }
}
/* Client logos: brand-brown silhouette at rest (the mono SVG used as a mask, so the
   wall reads as one warm rhythm), true brand colour on hover. */
/* Slot hugs the logo so the gap is identical between every pair; --lh is the
   optically-normalised height (see the marquee build note). */
.nwd-logo-slot { flex: 0 0 auto; display: flex; align-items: center; height: 46px; }
/* One artwork, always brand brown: the filter rewrites RGB and keeps alpha.
   No loading="lazy" here — the track is ~7000px wide, so off-screen logos would
   never trip the lazy loader and would arrive as gaps once scrolled in. */
.nwd-logo-mono {
  height: var(--lh, 40px); width: auto; display: block;
  filter: url(#nwd-logo-tint);
}

/* ────────────────────────── Services ────────────────────────── */
.nwd-svc {
  display: grid; grid-template-columns: 1fr auto; gap: 20px 48px;
  align-items: baseline; padding: 36px 0;
  border-top: 1px solid var(--line);
}
.nwd-svc:last-of-type { border-bottom: 1px solid var(--line); }
.nwd-svc-body { display: flex; gap: 20px; align-items: flex-start; }
.nwd-svc-body .ph { flex: 0 0 auto; font-size: 24px; line-height: 1; margin-top: 4px; color: var(--brown-800); }
.nwd-svc-desc { font-size: clamp(1rem, 0.96rem + 0.2vw, 1.12rem); line-height: 1.55; color: var(--brown-600); margin: 0; max-width: 48ch; }
.nwd-svc-price {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "wght" 520;
  font-size: clamp(1.15rem, 1rem + 0.6vw, 1.5rem);
  color: var(--brown-800);
  white-space: nowrap; text-align: right;
}
.nwd-svc-price.nwd-soft {
  font-variation-settings: "opsz" 72, "wght" 420;
  font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.25rem);
  color: var(--brown-600); font-style: italic;
}

/* ────────────────────────── Stat rows (why me / pricing) ────────────────────────── */
.nwd-rule-row { display: flex; flex-wrap: wrap; border-top: 1px solid var(--line); }
.nwd-rule-cell { flex: 1 1 200px; padding: 32px; border-bottom: 1px solid var(--line); border-left: 1px solid var(--line); }
.nwd-rule-cell:first-child { padding-left: 0; border-left: none; }
.nwd-rule-cell .nwd-cap { font-size: 15px; color: var(--brown-600); margin-top: 12px; }
.nwd-price-label { font-size: 14px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--brown-600); margin-bottom: 16px; }
.nwd-price-num {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "wght" 600;
  /* Up 20% on Ash's call (2026-07-30): 1.45/1/1.6/2.2 x 1.2. The figure is the whole point
     of the row, and at the old size the label was competing with it. */
  font-size: clamp(1.74rem, 1.2rem + 1.92vw, 2.64rem);
  line-height: 0.95; letter-spacing: -0.02em;
  color: var(--brown-800);
}
/* "from" and "/mo" are quiet qualifiers: the figure carries the line */
.nwd-price-num small { font-size: 0.5em; letter-spacing: 0; }
.nwd-price-num .nwd-from { margin-right: 0.55em; }

/* ────────────────────────── Split sections ────────────────────────── */
.nwd-split {
  display: flex; flex-wrap: wrap; gap: clamp(32px, 5vw, 80px);
  align-items: flex-start; justify-content: space-between;
}
.nwd-split-head { flex: 1 1 320px; }
/* Fills the left column, which is otherwise empty below the heading on wide screens. Display
   type but deliberately lighter and quieter than the h2 above it, so it reads as a second
   voice rather than a competing headline. The short orange rule marks it as a distinct
   element instead of a stray paragraph. */
.nwd-split-pull {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "SOFT" 18, "wght" 400;
  font-size: clamp(1.25rem, 1.05rem + 0.75vw, 1.7rem);
  line-height: 1.36; letter-spacing: -0.01em;
  color: var(--brown-600);
  max-width: 20ch;
  margin: clamp(28px, 4vw, 44px) 0 0;
  padding-top: clamp(20px, 2.5vw, 28px);
  position: relative;
}
.nwd-split-pull::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: 34px; height: 2px; background: var(--orange-500);
}
/* Stacked, it lands between the heading and the lead and reads as a standfirst, which is fine.
   Deliberately NOT display:none here — indexing is mobile-first, so hiding it on small screens
   would hide it from Google too, and it is real copy. Just tighter. */
@media (max-width: 767px) {
  .nwd-split-pull { max-width: 26ch; margin-top: 22px; padding-top: 18px; }
}
.nwd-split-body { flex: 1 1 380px; max-width: 560px; }
.nwd-split-body .nwd-lead { margin: 0 0 24px; }
/* Optional paragraphs under the lead. The lead keeps its own margin when it is the only
   copy; when a body follows, this block owns the gap down to the button. */
.nwd-split-copy { margin: 0 0 32px; }
.nwd-split-copy p {
  font-size: clamp(0.9375rem, 0.88rem + 0.27vw, 1rem);
  line-height: 1.7; color: var(--brown-700);
  margin: 0 0 16px;
}
.nwd-split-copy p:last-child { margin-bottom: 0; }

/* ────────────────────────── Work ────────────────────────── */
.nwd-work-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px; }
/* /work/ runs the same grid roomier: three abreast instead of four, because there the
   cards ARE the page rather than a taster. */
.nwd-work-grid--lg { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
/* A structurally-real entry whose words aren't known yet. Muted so it reads as
   scaffolding, not as a claim. Two classes outweigh .nwd-work-meta's own h3/p colours. */
.nwd-work-meta .nwd-ph-entry { color: var(--brown-300); }
/* No hover shadow: these cards contain no link, and a lift that promises a
   destination there isn't reads as broken. Restore it if they ever become <a>. */
.nwd-work-card {
  background: var(--cream); --bg: var(--cream);
  border: 1px solid var(--line); border-radius: 4px;
  overflow: hidden;
}
.nwd-work-shot {
  aspect-ratio: 16 / 11;
  border-bottom: 1px solid var(--line);
  display: flex; flex-direction: column;
}
.nwd-work-meta { padding: 22px 22px 26px; }
.nwd-work-meta h3 {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 60, "wght" 560;
  font-size: 1.25rem; color: var(--brown-800); margin: 0 0 6px;
}
.nwd-work-meta p { font-size: 14px; line-height: 1.5; color: var(--brown-600); margin: 0; }

/* The lead carries the argument; this is the story behind it, so it steps down
   to body size rather than competing with it. */
/* Default margin-top is 0: every generated page opens the block flush under its
   heading. The homepage's Why me column is the one place it follows a lead and
   spaces itself with .nwd-about-copy--after-lead. */
.nwd-about-copy { margin-top: 0; max-width: 58ch; }
.nwd-about-copy--after-lead { margin-top: 26px; }
.nwd-about-copy p {
  font-size: clamp(0.9375rem, 0.88rem + 0.27vw, 1rem);
  line-height: 1.7; color: var(--brown-700);
  margin: 0 0 16px;
}
.nwd-about-copy p:last-child { margin-bottom: 0; }

/* Prose lists: what a build includes, what a care plan covers. Same measure, colour and
   rhythm as the paragraphs they sit among, so a list never reads as a different component. */
.nwd-about-copy ul { margin: 0 0 16px; padding-left: 1.15em; }
.nwd-about-copy li {
  font-size: clamp(0.9375rem, 0.88rem + 0.27vw, 1rem);
  line-height: 1.7; color: var(--brown-700);
  margin: 0 0 8px;
}
.nwd-about-copy li::marker { color: var(--brown-200); }

/* ────────── The price book (/pricing/) ──────────
   Every number in one ruled table: denser than the homepage's service rows on purpose,
   because this page's job is comparison, not persuasion. Whole row is a link. */
.nwd-price-list { border-top: 1px solid var(--line); }
.nwd-price-row {
  display: flex; align-items: baseline; gap: 8px 28px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
  text-decoration: none; color: inherit;
}
.nwd-price-cell { flex: 1 1 auto; min-width: 0; }
.nwd-price-name {
  display: block;
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "wght" 520;
  font-size: clamp(1.05rem, 1rem + 0.3vw, 1.25rem);
  line-height: 1.3;
  transition: color 200ms var(--ease-out);
}
.nwd-price-note { display: block; font-size: 14px; line-height: 1.5; color: var(--brown-600); margin-top: 3px; }
.nwd-price-row .nwd-svc-price { font-size: 1rem; flex: 0 0 auto; }
.nwd-price-row .nwd-svc-price.nwd-soft { font-size: 0.95rem; }
.nwd-price-row:hover .nwd-price-name { color: var(--orange-600); }
@media (max-width: 560px) {
  .nwd-price-row { flex-wrap: wrap; }
  .nwd-price-row .nwd-svc-price { margin-left: 0; }
}

/* ────────── Services grid (/services/) ──────────
   Six uniform cells in the same hairline idiom as .nwd-plan-grid: the 1px line-gaps ARE
   the dividers, no floating-card chrome. #svc-… ids stay on the cells for deep links. */
.nwd-svc-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
}
.nwd-svc-cell {
  background: var(--cream);
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 16px;
  padding: clamp(24px, 3vw, 40px);
  scroll-margin-top: 120px;
}
/* The price shares the title's first baseline, right-aligned and a step down from the
   homepage's display-size price — in a cell it's a label, not a headline (Ash's call).
   nowrap + a shrinkable title: a long name wraps inside its own box while the price
   holds the top right, instead of the price being pushed to a line of its own. */
/* Leads the cell in place of the old 16:9 artwork block. Orange because it is the only
   colour in the cell and it gives the eye six anchors to scan down; small because it is a
   marker, not a picture. */
.nwd-svc-icon { margin: 0; line-height: 1; color: var(--orange-500); }
.nwd-svc-icon .ph { display: block; font-size: 30px; }

.nwd-svc-cell .nwd-svc-head { flex-wrap: nowrap; }
.nwd-svc-cell .nwd-svc-head .nwd-h-item { flex: 1 1 auto; min-width: 0; }
/* Up from 1rem, which was set to keep the head on one line but left the price receding
   against a 23px heading right beside it — the price is half the reason anyone reads this
   grid. Longer names now wrap to two lines instead, which is the better trade. */
.nwd-svc-cell .nwd-svc-price { font-size: 1.25rem; }
.nwd-svc-cell .nwd-svc-price.nwd-soft { font-size: 1.05rem; }

/* ── The whole cell is the link ──
   NOT a wrapping <a>: the cell already contains two links (the title and the read-more), and
   nesting them is invalid HTML. Instead the title's link throws a transparent ::after over the
   whole cell, the standard stretched-link pattern. Trade-off worth knowing: the overlay means
   the blurb text can no longer be selected by dragging. Correct for a cell whose entire
   purpose is to be clicked through. */
.nwd-svc-cell { position: relative; transition: background 240ms var(--ease-out); }
.nwd-svc-cell .nwd-svc-head .nwd-h-item a::after { content: ""; position: absolute; inset: 0; }
/* Sits above the overlay so it stays a real, separately clickable link. */
.nwd-svc-more a { position: relative; }

/* Scoped to cells that actually contain a link. card_grid reuses .nwd-svc-cell for the three
   build tiers on /services/websites/, and those have no link unless one is set — an unscoped
   :hover lit them up like buttons that do nothing when clicked. */
.nwd-svc-cell:has(.nwd-svc-head a):hover { background: var(--brown-50); }
/* Hovering anywhere in the cell gives the same feedback as hovering the link itself, so the
   whole box reads as one target rather than a box containing a target. */
.nwd-svc-cell:hover .nwd-svc-head .nwd-h-item a,
.nwd-svc-cell:hover .nwd-svc-more a { color: var(--orange-600); }
.nwd-svc-cell:hover .nwd-svc-more .ph { transform: translateX(4px); }
.nwd-svc-icon { transition: transform 240ms var(--ease-out); }
.nwd-svc-cell:hover .nwd-svc-icon { transform: translateY(-3px); }

/* The stretched link's own outline would trace the whole cell at the browser's offset and
   collide with the neighbouring hairlines, so the cell wears the ring instead, inset.
   :has() rather than :focus-within so a mouse click doesn't leave a ring behind. */
.nwd-svc-cell:has(a:focus-visible) { outline: 2px solid var(--orange-500); outline-offset: -2px; }
.nwd-svc-cell :focus-visible { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .nwd-svc-cell, .nwd-svc-icon { transition: none; }
  .nwd-svc-cell:hover .nwd-svc-icon { transform: none; }
}
.nwd-svc-brief { margin: 0; max-width: 52ch; font-size: 15px; line-height: 1.65; color: var(--brown-600); }
/* Cells in a row share a height; the link pins to the bottom so the six sit level even
   where one cell's copy runs a line longer. */
.nwd-svc-more { margin: auto 0 0; }
.nwd-svc-more a {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 15px; font-weight: 600;
  color: var(--brown-800); text-decoration: none;
  transition: color 200ms var(--ease-out);
}
/* The arrow travels, not the link — the same move the old tab names made on hover. */
.nwd-svc-more .ph { font-size: 16px; transition: transform 260ms var(--ease-out); }
.nwd-svc-more a:hover { color: var(--orange-600); }
.nwd-svc-more a:hover .ph { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .nwd-svc-more .ph { transition: none; }
  .nwd-svc-more a:hover .ph { transform: none; }
}

/* /services/websites/: the three kinds of build reuse the services cell wholesale;
   only the column count differs. Three abreast needs the full desktop width. */
.nwd-svc-grid--tiers { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1024px) { .nwd-svc-grid--tiers { grid-template-columns: 1fr; } }

/* ────────── Prose + artwork split ──────────
   Copy left, artwork right, for prose sections that would otherwise be a bare column
   of text (Ash's call on /services/websites/). The art is sticky so it keeps the tall
   sections company instead of being stranded at the top. */
.nwd-prose-split {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(260px, 2fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: start;
}
.nwd-prose-art { position: sticky; top: 96px; }
/* No artwork and no editor looking: one column, and the prose keeps a readable measure rather
   than stretching the full container width. */
.nwd-prose-split--solo { grid-template-columns: minmax(0, 1fr); }
.nwd-prose-split--solo .nwd-about-copy { max-width: 68ch; }
@media (max-width: 860px) {
  .nwd-prose-split { grid-template-columns: 1fr; }
  .nwd-prose-art { position: static; max-width: 440px; }
}

.nwd-svc-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 20px; width: 100%; }
.nwd-svc-head .nwd-h-item { margin: 0; }
/* Also covers the home page's ruled rows (.nwd-svc-body), whose titles became links once
   the service pages existed. Without this they inherit the default link colour and the
   whole column turns orange. */
.nwd-svc-head .nwd-h-item a,
.nwd-svc-body .nwd-h-item a { color: inherit; text-decoration: none; transition: color 200ms var(--ease-out); }
.nwd-svc-head .nwd-h-item a:hover,
.nwd-svc-body .nwd-h-item a:hover { color: var(--orange-600); }
.nwd-svc-head .nwd-svc-price { margin-left: auto; }

.nwd-svc-art { width: 100%; }

/* ───────────────────── Hosting and care plans ─────────────────────
   A four-tier price table is the one place a card grid is genuinely earned: comparing
   tiers needs aligned columns, and DESIGN.md's "avoid card grids unless earned" is
   exactly that caveat. It stays editorial by refusing the usual card chrome: the 1px
   grid gap over a --line background draws hairline dividers between cells, so the
   dividers are the grid itself rather than four floating boxes with shadows. */
.nwd-plan-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
}
.nwd-plan {
  background: var(--cream);
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 10px;
  padding: clamp(20px, 2vw, 28px);
}
/* The recommended tier is marked by a change of ground, not by a coloured ribbon. */
.nwd-plan--popular { background: var(--cream-deep); }
.nwd-plan-badge {
  margin: 0 0 2px; min-height: 1em;
  font-size: 11px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--orange-600);
}
.nwd-plan .nwd-h-item { margin: 0; }
.nwd-plan-price { margin: 0; display: flex; align-items: baseline; gap: 4px; }
.nwd-plan-num {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "wght" 560;
  font-size: clamp(1.6rem, 1.3rem + 1.1vw, 2.1rem);
  color: var(--brown-800); line-height: 1;
}
.nwd-plan-per { font-size: 13px; color: var(--brown-600); }
.nwd-plan-star { color: var(--orange-600); text-decoration: none; padding-left: 1px; }
.nwd-plan-star:hover { text-decoration: underline; }
/* Ash's brief: included hours are the headline differentiator. So they are set at
   heading weight directly under the price, not buried in a feature list. */
.nwd-plan-hours {
  margin: 6px 0 0;
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "wght" 500;
  font-size: clamp(0.95rem, 0.9rem + 0.25vw, 1.05rem);
  color: var(--brown-800);
}
.nwd-plan-blurb {
  margin: 0; font-size: 14px; line-height: 1.6; color: var(--brown-600);
}
.nwd-plan-response {
  margin: 0; padding-top: 12px; margin-top: auto;
  border-top: 1px solid var(--line);
  width: 100%; font-size: 13px; color: var(--brown-600);
}
.nwd-plan-response-k { display: block; font-weight: 600; color: var(--brown-800); margin-bottom: 2px; }
.nwd-plan .nwd-btn { margin-top: 14px; width: 100%; }

.nwd-plan-included, .nwd-plan-terms { margin-top: clamp(36px, 4vw, 56px); }
.nwd-plan-included-list {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px 32px;
}
.nwd-plan-included-list li {
  position: relative; padding-left: 20px;
  font-size: 15px; line-height: 1.5; color: var(--brown-700);
}
/* The brand's own dot, doing duty as a tick. A checkmark here would be the one piece of
   generic UI iconography on the whole site. */
.nwd-plan-included-list li::before {
  content: ""; position: absolute; left: 2px; top: 0.55em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--orange-500);
}
/* The dagger that ties a conditional included-item to its footnote below the list. */
.nwd-plan-dagger { color: var(--orange-500); }
.nwd-plan-footnote {
  margin: 18px 0 0; max-width: 72ch;
  font-size: 13px; line-height: 1.6; color: var(--brown-500);
}
.nwd-plan-rates { margin-top: clamp(36px, 4vw, 56px); }
.nwd-plan-terms-list { margin: 0; padding-left: 1.15em; max-width: 72ch; }
.nwd-plan-terms-list li { font-size: 14px; line-height: 1.65; color: var(--brown-600); margin-bottom: 8px; }
.nwd-plan-terms-list li::marker { color: var(--brown-200); }
.nwd-plan-terms:target .nwd-h-item { color: var(--orange-600); }

.nwd-plan-from { font-size: 13px; color: var(--brown-600); align-self: center; }
.nwd-plan-features { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 7px; width: 100%; }
.nwd-plan-features li {
  position: relative; padding-left: 18px;
  font-size: 13.5px; line-height: 1.45; color: var(--brown-700);
}
.nwd-plan-features li::before {
  content: ""; position: absolute; left: 2px; top: 0.5em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--orange-500);
}
.nwd-plan-note { margin: 2px 0 0; font-size: 13px; line-height: 1.55; color: var(--brown-600); }

@media (max-width: 1024px) { .nwd-plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .nwd-plan-grid { grid-template-columns: 1fr; } }

@media (max-width: 860px) { .nwd-svc-grid { grid-template-columns: 1fr; } }

/* ────────────────────────── Portrait (Why me) ────────────────────────── */
.nwd-portrait { flex: 0 1 400px; }
.nwd-portrait-frame {
  aspect-ratio: 4 / 5;
  background: repeating-linear-gradient(135deg, rgb(58 42 31 / 0.07) 0 9px, rgb(58 42 31 / 0.02) 9px 18px);
  border: 1px solid var(--line); border-radius: 4px;
  display: flex; align-items: flex-end; padding: 12px;
}
.nwd-portrait-cap { font-size: 14px; line-height: 1.55; color: var(--brown-600); margin: 14px 0 0; max-width: 40ch; }
.nwd-portrait-cap b { color: var(--brown-800); font-weight: 600; }
.nwd-portrait-photo { background: var(--cream-deep); position: relative; padding: 0; overflow: hidden; }
.nwd-portrait-photo img {
  position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  height: 98%; width: auto;
}
/* A real photograph fills its frame edge to edge. The bottom-anchored 98% treatment
   above is for CUTOUTS, where the figure should stand on the frame's floor. */
.nwd-portrait-photo--full img {
  position: static; transform: none;
  width: 100%; height: 100%; object-fit: cover; display: block;
}

/* ────────────────────────── Process stages ──────────────────────────
   The same ruled editorial list as .nwd-svc, which is the page's anti-slop decision:
   eight stages as eight cards would be the exact template this brand avoids.
   Copy left, artwork right, hairline between.

   The tick on each rule is sign-off. Ash signs every stage off before the next
   begins, so it is not a stage of its own — it is the gate between all of them,
   and saying it eight times on the dividers costs nothing. */
/* Lock-in-place: each stage is a tall track with position:sticky content — the pin
   effect without a scroll hijack. The extra 65svh of track IS the hold duration:
   longer feels laboured, shorter barely pins. */
/* A quiet scroll affordance under the opening paragraph. It is a real anchor to the
   first stage, so it doubles as a skip link for anyone who would rather jump than scroll. */
.nwd-scroll-cue {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--brown-600); font-size: 13px; font-weight: 500; letter-spacing: 0.02em;
  text-decoration: none; transition: color 200ms var(--ease-out);
}
.nwd-scroll-cue:hover { color: var(--brown-800); }
.nwd-scroll-cue svg { width: 15px; height: 15px; }
@media (prefers-reduced-motion: no-preference) {
  .nwd-scroll-cue svg { animation: cueBob 1.9s var(--ease-out) infinite; }
}
.nwd-scroll-cue:hover svg { animation-play-state: paused; }
@keyframes cueBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }

.nwd-stage { min-height: 165svh; }

.nwd-stage-inner {
  position: sticky; top: 0;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(360px, 1fr);
  gap: clamp(32px, 5vw, 80px);
  align-items: center;
  padding: clamp(48px, 6vw, 88px) 0;
}
@media (max-width: 1024px) {
  /* No pinning on a phone: the track would be 165vh of scroll per stage on the device
     with the least patience, and sticky + a small viewport is where this pattern is at
     its most annoying. Stages become plain screens. */
  .nwd-stage { min-height: 0; }
  .nwd-stage-inner {
    position: static; min-height: 100svh;
    grid-template-columns: 1fr;
    gap: clamp(24px, 4vw, 40px);
    align-content: center;
  }
}
/* Someone who asked for less motion did not ask to have the scroll held. */
@media (prefers-reduced-motion: reduce) {
  .nwd-stage { min-height: 0; }
  .nwd-stage-inner { position: static; }
}

.nwd-stage-num {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 24, "wght" 620;
  font-size: clamp(1.6rem, 1.3rem + 1vw, 2.2rem);
  line-height: 1; letter-spacing: -0.02em;
  color: var(--brown-300);
  flex: 0 0 auto; min-width: 2ch;
}
.nwd-stage-body { display: flex; gap: clamp(16px, 2vw, 24px); align-items: baseline; }
.nwd-stage-desc {
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.12rem);
  line-height: 1.6; color: var(--brown-600);
  margin: 0 0 14px; max-width: 46ch;
}
.nwd-stage-desc:last-child { margin-bottom: 0; }
/* The one thing Ash needs FROM the client. Set apart by size and weight rather
   than a left border, which would sail too close to the side-stripe cliché. */
.nwd-stage-note {
  font-family: var(--font-body);
  font-size: 14px; line-height: 1.55; font-weight: 500;
  color: var(--brown-800);
  margin: 16px 0 0; max-width: 44ch;
}
/* No scroll-snap. Snapping and sticky fight each other: snap yanks the scroll to a
   point while sticky is holding content in place, and the result is exactly the
   "isn't working" feeling. The pin above does the locking; the wheel stays the
   reader's. */

/* Process-stage scenes. The handoffs centre themselves on their own page; here the
   .nwd-stage grid places them, so only the box and the fluid SVG survive. Scene-specific
   rules (transform-box / transform-origin, which SVG needs before transform-origin
   means anything) are inlined per scene, scoped to that scene's root.

   Sized by height, not width: a stage owns the viewport, so the artwork should fill it
   vertically and let 4:3 decide the width. */
.nwd-pscene {
  width: 100%; aspect-ratio: 4 / 3;
  max-width: min(760px, 100%);
  max-height: 62svh;
  margin-inline: auto;
}
.nwd-pscene svg { width: 100%; height: 100%; display: block; }

/* Ash: "not quite so dark colours (more neutral)". The scenes take their tokens from
   the page rather than carrying their own, so remapping on the scene root softens every
   fill at once without touching a single delivered file. Two steps of hierarchy are
   kept: what was the darkest ink becomes mid-brown, what was mid becomes light. */
.nwd-pscene {
  --brown-800: #6E4F35;   /* was #3A2A1F, the strong bars */
  --brown-600: #A18465;   /* was #6E4F35, the labels */
}

/* ────────────────────────── Care status panel ────────────────────────── */
.nwd-care-panel {
  margin-top: clamp(48px, 6vw, 72px);
  background: var(--cream-deep); border: 1px solid var(--line); border-radius: 4px;
  padding: clamp(20px, 3vw, 32px) clamp(22px, 3.5vw, 40px);
}
.nwd-cp-grid {
  display: grid; grid-template-columns: repeat(2, 1fr);
  column-gap: clamp(28px, 6vw, 96px);
}
@media (max-width: 768px) { .nwd-cp-grid { grid-template-columns: 1fr; } }
.nwd-cp-meta { margin-left: auto; font-size: 13px; font-weight: 400; color: var(--brown-600); }
.nwd-cp-head {
  display: flex; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 600; color: var(--brown-800);
  padding-bottom: 12px; border-bottom: 1px solid var(--line); margin-bottom: 4px;
}
.nwd-cp-dot { width: 10px; height: 10px; border-radius: 9999px; background: var(--success); }
.nwd-cp-row {
  display: flex; justify-content: space-between; gap: 16px;
  font-size: 14px; color: var(--brown-600); padding: 9px 0;
}
.nwd-cp-row b { color: var(--brown-800); font-weight: 600; }

/* ────────────────────────── Testimonials ────────────────────────── */
.nwd-quote-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 24px; }
/* Grid cells stretch to the tallest card, and real testimonials vary wildly in length, so a
   20-word quote next to a 40-word one left a third of its card blank under the attribution.
   Column layout with the caption pushed to the bottom turns that into a consistent baseline
   across the row instead of ragged dead space. */
.nwd-quote-grid figure {
  margin: 0; border: 1px solid var(--line); border-radius: 4px; padding: 32px;
  display: flex; flex-direction: column;
}
.nwd-quote-grid figcaption { margin-top: auto; }
.nwd-quote-grid blockquote {
  margin: 0 0 24px;
  font-family: var(--font-display);
  font-variation-settings: "opsz" 60, "SOFT" 16, "wght" 440;
  font-size: clamp(1.25rem, 1.1rem + 0.5vw, 1.5rem);
  line-height: 1.35; color: var(--brown-800);
}
.nwd-quote-grid figcaption { font-size: 14px; color: var(--brown-600); }
.nwd-quote-grid figcaption b { color: var(--brown-800); font-weight: 600; }

/* ────────────────────────── Map panel ────────────────────────── */
.nwd-map-panel { flex: 1 1 360px; max-width: 480px; width: 100%; }
.nwd-map-frame {
  position: relative; aspect-ratio: 4 / 3;
  background: var(--cream-deep); border: 1px solid var(--line); border-radius: 4px;
  overflow: hidden;
}
.nwd-map-frame svg { position: absolute; inset: 0; }
.nwd-map-frame .nwd-ph-label { position: absolute; bottom: 12px; left: 14px; }
.nwd-map-copy {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 72, 'SOFT' 16, 'wght' 400;
  font-size: clamp(1.15rem, 1.05rem + 0.4vw, 1.4rem);
  line-height: 1.55; margin: 0; max-width: 52ch;
}

/* ────────────────────────── Dark band (contact + footer) ────────────────────────── */
.nwd-band-dark { background: var(--brown-800); color: var(--cream); --bg: var(--brown-800); }
.nwd-band-dark ::selection { background: var(--brown-600); color: var(--cream); }
.nwd-contact-inner { padding-top: clamp(6rem, 12vw, 10rem); padding-bottom: clamp(4rem, 8vw, 6.5rem); text-align: center; }
.nwd-contact-inner h2 {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 144, "SOFT" 24, "wght" 620;
  font-size: clamp(2.3rem, 1.7rem + 2.6vw, 4rem);
  line-height: 1.04; letter-spacing: -0.02em;
  color: var(--cream);
  margin: 0 0 24px;
  text-wrap: balance;
}
.nwd-contact-inner .nwd-lead { color: rgb(245 239 227 / 0.82); margin: 0 auto 44px; max-width: 52ch; }
.nwd-contact-actions { display: flex; flex-wrap: wrap; gap: 16px 28px; align-items: center; justify-content: center; }
.nwd-email-link {
  color: var(--cream); font-size: 16px; font-weight: 500;
  border-bottom: 1px solid rgb(245 239 227 / 0.4); padding-bottom: 2px;
  transition: border-color 200ms ease-out;
}
.nwd-email-link:hover { color: var(--cream); border-color: var(--orange-500); }
/* mailto: is the whole conversion path, and it silently does nothing on a machine
   with no mail client. This is the escape hatch; JS injects it, so without JS the
   link alone still stands. */
.nwd-copy-mail {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  background: transparent; color: var(--cream);
  border: 1px solid rgb(245 239 227 / 0.4); border-radius: 9999px;
  font-family: var(--font-body); font-size: 13px; font-weight: 500;
  padding: 7px 14px;
  transition: border-color 200ms var(--ease-out), background 200ms var(--ease-out);
}
.nwd-copy-mail:hover { border-color: var(--orange-500); background: rgb(245 239 227 / 0.06); }
.nwd-copy-mail .ph { font-size: 15px; }
.nwd-copy-mail[data-copied="true"] { border-color: var(--orange-500); }

/* ────────────────────────── Contact form ──────────────────────────
   Prototype for the Gravity Forms build: in WordPress these classes move onto GF's
   markup. Inputs are 16px minimum — anything smaller makes iOS zoom on focus. */
.nwd-form { display: flex; flex-direction: column; gap: 18px; max-width: 480px; }
.nwd-field { display: flex; flex-direction: column; gap: 6px; }
.nwd-field label { font-size: 14px; font-weight: 600; color: var(--brown-800); }
.nwd-field-opt { font-weight: 400; color: var(--brown-500); }
.nwd-field input, .nwd-field select, .nwd-field textarea {
  font: inherit; font-size: 16px; color: var(--brown-800);
  background: var(--brown-50);
  border: 1px solid var(--line-mid); border-radius: 4px;
  padding: 11px 14px; width: 100%;
}
.nwd-field textarea { resize: vertical; min-height: 132px; }
.nwd-field input:focus-visible, .nwd-field select:focus-visible, .nwd-field textarea:focus-visible {
  outline: 2px solid var(--orange-500); outline-offset: 1px; border-color: var(--orange-500);
}
.nwd-field input::placeholder, .nwd-field textarea::placeholder { color: var(--brown-400); }
.nwd-form > .nwd-btn { align-self: flex-start; }
.nwd-form-note { margin: -4px 0 0; font-size: 13px; color: var(--brown-600); }
.nwd-form-done {
  max-width: 480px; padding: clamp(20px, 3vw, 28px);
  border: 1px solid var(--line-mid); border-radius: 4px; background: var(--cream-deep);
}
.nwd-form-done-head {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72, "wght" 600;
  font-size: 1.4rem; margin: 0 0 8px; color: var(--brown-800);
}
.nwd-form-done p:not(.nwd-form-done-head) { margin: 0; font-size: 15px; line-height: 1.6; color: var(--brown-600); }
.nwd-form-alt { margin: 22px 0 0; font-size: 14px; color: var(--brown-600); }
.nwd-form-alt a {
  color: var(--brown-800);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-mid);
  transition: color 200ms ease, text-decoration-color 200ms ease;
}
.nwd-form-alt a:hover { color: var(--orange-600); text-decoration-color: var(--orange-500); }

/* ────────────────────────── Gravity Forms ──────────────────────────
   GF's own CSS is switched off (see inc/gravity-forms.php), so these are the only form
   styles on the page. Declarations are deliberately the same as .nwd-form above rather
   than layered on top of it: the prototype and the real form must look identical, and
   overriding GF's defaults instead would leave two sources of truth for one appearance. */
.gform_wrapper { max-width: 480px; }
.gform_wrapper .gform_fields {
  display: flex; flex-direction: column; gap: 18px;
  margin: 0; padding: 0; list-style: none;
}
.gform_wrapper .gfield { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.gform_wrapper .gfield_label {
  font-family: var(--font-body);
  font-size: 14px; font-weight: 600; color: var(--brown-800); margin: 0;
}
/* GF prints "(Required)" beside every required label. The approved design marks the two
   OPTIONAL fields instead ("If there is one.", "Pick the closest, or leave it"), which says
   the same thing far more quietly. Clipped rather than display:none, so it stays in the
   accessibility tree alongside the input's own aria-required. */
.gform_wrapper .gfield_required {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.gform_wrapper .gfield_description {
  font-size: 13px; color: var(--brown-600); margin: 0; padding: 0;
}
.gform_wrapper .ginput_container { margin: 0; }
.gform_wrapper input[type="text"],
.gform_wrapper input[type="email"],
.gform_wrapper input[type="url"],
.gform_wrapper input[type="tel"],
.gform_wrapper select,
.gform_wrapper textarea {
  font: inherit; font-size: 16px; color: var(--brown-800);
  background: var(--brown-50);
  border: 1px solid var(--line-mid); border-radius: 4px;
  padding: 11px 14px; width: 100%;
}
.gform_wrapper textarea { resize: vertical; min-height: 132px; }
.gform_wrapper input:focus-visible,
.gform_wrapper select:focus-visible,
.gform_wrapper textarea:focus-visible {
  outline: 2px solid var(--orange-500); outline-offset: 1px; border-color: var(--orange-500);
}
.gform_wrapper input::placeholder, .gform_wrapper textarea::placeholder { color: var(--brown-400); }

.gform_wrapper .gform_footer { margin: 18px 0 0; padding: 0; display: flex; }
.gform_wrapper .gform_footer .nwd-btn { align-self: flex-start; }

/* Validation. GF's default is a red block above the form; this keeps the message with the
   field it belongs to, which is where someone fixing it is already looking. */
.gform_wrapper .gfield_error .gfield_label { color: var(--orange-700, #A33A16); }
.gform_wrapper .gfield_error input,
.gform_wrapper .gfield_error select,
.gform_wrapper .gfield_error textarea { border-color: var(--orange-600); }
.gform_wrapper .validation_message {
  font-size: 13px; color: var(--orange-700, #A33A16); margin: 0;
}
.gform_wrapper .gform_validation_errors {
  margin: 0 0 18px; padding: 14px 16px;
  border: 1px solid var(--orange-500); border-radius: 4px; background: var(--brown-50);
}
.gform_wrapper .gform_validation_errors h2 {
  font-family: var(--font-body);
  font-size: 15px; font-weight: 600; color: var(--brown-800); margin: 0;
}
.gform_wrapper .gform_submission_error { font-size: 15px; }

/* The honeypot is a real field GF hides from people but not from bots. */
.gform_wrapper .gform_validation_container,
.gform_wrapper .gfield_visibility_hidden { position: absolute !important; left: -9999px; }
/* Sized as a signature, not a second logo: the wordmark it replaced was set to
   132px and left a long empty stretch of brown beneath it. */
.nwd-contact-inner .nwd-stamp {
  color: var(--cream);
  margin-top: clamp(52px, 6vw, 76px);
}
.nwd-contact-inner .nwd-stamp img { height: clamp(38px, 26px + 1.8vw, 54px); }

.nwd-site-footer { border-top: 1px solid var(--line-rev); }
.nwd-footer-top {
  display: flex; flex-wrap: wrap; gap: 32px 48px;
  align-items: flex-start; justify-content: space-between;
  padding: 64px 0 44px;
  border-bottom: 1px solid var(--line-rev);
}
.nwd-footer-nav { display: flex; flex-wrap: wrap; gap: 28px; }
.nwd-footer-nav a { color: var(--cream); font-size: 15px; font-weight: 500; }
.nwd-footer-nav a:hover { color: var(--brown-200); }
.nwd-footer-bottom {
  display: flex; flex-wrap: wrap; gap: 12px 24px;
  align-items: baseline; justify-content: space-between;
  padding: 36px 0 48px;
}
.nwd-footer-bottom p { font-size: 13px; color: rgb(245 239 227 / 0.6); margin: 0; max-width: 52ch; line-height: 1.6; }

/* ────────────────────────── Responsive ────────────────────────── */
@media (max-width: 768px) {
  .nwd-svc { grid-template-columns: 1fr; gap: 10px; }
  .nwd-svc-price { text-align: left; }
  .nwd-rule-cell { flex-basis: 100%; padding-left: 0; border-left: none; }
}
@media (max-width: 480px) {
  .nwd-hero-actions { flex-direction: column; align-items: stretch; }
  .nwd-hero-actions > .nwd-btn { justify-content: center; }
}

/* Two actions per panel: the page, then the pre-filled email. Only one panel is ever
   open, so this is two buttons on screen, not twelve. */

/* "+VAT" rides with the price everywhere it is shown. Quiet, but never absent: a price
   that turns out to have had 20% on it is the fastest way to lose someone's trust. */
/* Set in Mona Sans, not the display face it sits inside. Fraunces at 0.5em with a 144 optical
   size puts hairline strokes on four capitals, and "+VAT" became genuinely hard to read at a
   glance — Ash flagged it. The variation settings have to be reset too, or Fraunces' opsz/wght
   axes are inherited onto a font that has no opsz. Global on purpose: it was equally unreadable
   on the service prices and the care-plan rate figures. */
/* Every per-context size below came down ~12% with the font swap: Mona Sans has a far larger
   x-height than Fraunces, so the em values tuned for the serif rendered visibly bigger. */
/* NOTE THE max() FLOOR ON EVERY SIZE BELOW, and do not reduce it to a bare em. Sized purely
   in em, "+VAT" tracks its parent — which is fine beside a 42px price on /pricing/ and
   catastrophic in the services grid, where a 20px price rendered it at 7.7px. Ash flagged it
   as unreadable and he was right. 11px is the floor for four capitals in Mona Sans. */
.nwd-vat {
  font-family: var(--font-body);
  font-variation-settings: normal;
  font-size: max(11px, 0.44em); font-weight: 500; color: var(--brown-600);
  letter-spacing: 0.02em; white-space: nowrap;
}
.nwd-svc-price .nwd-vat { font-size: max(11px, 0.48em); }
/* Smaller against the big display rate figures (£50/hr etc.), where 0.48em read too large. */
.nwd-stat-num .nwd-vat { font-size: max(11px, 0.3em); }
/* Beats `.nwd-price-num small` (0,1,1), which otherwise wins on specificity and forces 0.5em. */
.nwd-price-num .nwd-vat { font-size: max(11px, 0.4em); }
