/*
Theme Name: CommonWatts — Watershed
Theme URI: https://commonwatts.com
Author: CommonWatts
Description: The Shared Ground. Deep water blue and spring green, taken from the isometric graphic. The middle leads with evidence: the load curve is promoted up the page, and the services sit in an illustrated three-up rather than a list. A WordPress block theme for CommonWatts, built for full-site editing. Blog posts, pages and every section on the home page are editable from the Site Editor with no page builder required.
Requires at least: 6.5
Tested up to: 6.8
Requires PHP: 7.4
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: commonwatts-watershed
Tags: full-site-editing, block-patterns, blog, business, one-column, two-columns, custom-colors, custom-logo, custom-menu, editor-style, featured-images, threaded-comments, translation-ready
*/

:root {
  /* ---- colour ----
     --cw-ink is no longer "near-black". The two brand colours ARE the type
     now, split by importance and swapped between the demos:

                     headings / strong      body / everything else
       Porchlight    orange  #A84A16        blue    #3E6285
       Watershed     blue    #3E6285        orange  #AD4300

     These are the text-weight versions of the mark's #FF751F and #5D86AE -
     darker, because they have to clear 4.5:1 as small text on the palest
     ground each theme owns, which is a tint block rather than the page.
     The bright originals stay on fills, buttons and the mark itself.

     --cw-ground is what --cw-ink used to be, and is now only ever a dark
     background: the CTA band, the footer, the photographic bands. */
  --cw-ground: #10222B;
  --cw-ink: #3E6285;
  --cw-ink-soft: #AD4300;
  --cw-ink-faint: #B84700;
  --cw-paper: #F8FBFD;
  --cw-paper-rgb: 248 251 253;
  --cw-surface: #FFFFFF;
  --cw-sunk: #EDF3F8;
  --cw-line: #D8E4EE;
  --cw-line-soft: #EBF1F7;
  --cw-primary: #5F88AF;
  --cw-primary-deep: #456C92;
  --cw-primary-tint: #E7EDF3;
  --cw-on-primary: #0E1F2B;
  --cw-on-dark: #FFA766;
  --cw-strong-on-dark: #7094B8;
  --cw-accent: #FF751F;
  --cw-accent-ink: #B84700;
  --cw-accent-tint: #FFE9DB;
  --cw-strike: #B84700;
  --cw-scrim: 8 24 34;
  --cw-cta-bg: #FF751F;
  --cw-cta-ink: #2B1708;
  --cw-fl-accent: #FF751F;

  /* ---- type: three roles ---- */
  --cw-display: "Bricolage Grotesque", Georgia, serif;
  --cw-body: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --cw-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* ---- spacing scale, decided once ---- */
  --s1: 4px;  --s2: 8px;   --s3: 12px; --s4: 16px; --s5: 24px;
  --s6: 32px; --s7: 48px;  --s8: 64px; --s9: 96px; --s10: 128px;

  --cw-radius: 12px;
  --cw-radius-lg: 20px;
  --cw-shadow: 0 2px 4px rgba(16,34,43,.05), 0 16px 38px -20px rgba(16,34,43,.24);
  --cw-wide: 1200px;
  --cw-text: 700px;
  --cw-gutter: clamp(20px, 5vw, 56px);
  --cw-section: clamp(56px, 8vw, 112px);
}

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

body.cw {
  margin: 0;
  background: var(--cw-paper);
  color: var(--cw-ink-soft);
  font-family: var(--cw-body);
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }
a { color: var(--cw-primary); text-underline-offset: 3px; }
a:hover { color: var(--cw-primary-deep); }

h1, h2, h3, h4 {
  font-family: var(--cw-display);
  color: var(--cw-ink);
  line-height: 1.1;
  margin: 0 0 .45em;
  font-weight: 600;
  letter-spacing: -.018em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.5rem, 5.6vw, 4.1rem); }
h2 { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }
h3 { font-size: clamp(1.15rem, 1.8vw, 1.42rem); }
p { margin: 0 0 1.05em; }
p:last-child { margin-bottom: 0; }

/* ---- the utility face does real work ---- */
.cw-eyebrow {
  font-family: var(--cw-mono);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--cw-accent-ink);
  margin: 0 0 var(--s4);
}
.cw-ref {
  font-family: var(--cw-mono);
  font-size: .72rem;
  letter-spacing: .04em;
  color: var(--cw-ink-faint);
  font-variant-numeric: tabular-nums;
}
.cw-lede { font-size: clamp(1.06rem, 1.55vw, 1.24rem); color: var(--cw-ink-soft); line-height: 1.58; }

/* ---- layout ---- */
.cw-wrap { width: 100%; max-width: var(--cw-wide); margin-inline: auto; padding-inline: var(--cw-gutter); }
.cw-section { padding-block: var(--cw-section); }
.cw-section--tight { padding-block: clamp(40px, 5vw, 68px); }

/* ---- buttons ---- */
.wp-block-button__link, .cw-btn {
  display: inline-block;
  font-family: var(--cw-body);
  font-size: .95rem;
  font-weight: 600;
  line-height: 1;
  padding: 15px 26px;
  border-radius: var(--cw-radius);
  background: var(--cw-primary);
  color: var(--cw-on-primary);
  text-decoration: none;
  border: 1.5px solid var(--cw-primary);
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease, transform .18s ease;
}
.wp-block-button__link:hover, .cw-btn:hover {
  background: var(--cw-primary-deep); border-color: var(--cw-primary-deep); color: #fff;
}
.wp-block-button__link:active, .cw-btn:active { transform: translateY(1px); }
.is-ghost .wp-block-button__link, .cw-btn--ghost {
  background: transparent; color: var(--cw-primary-deep); border-color: var(--cw-line);
}
.is-ghost .wp-block-button__link:hover, .cw-btn--ghost:hover {
  background: var(--cw-primary-tint); border-color: var(--cw-primary); color: var(--cw-primary-deep);
}
.wp-block-buttons { display: flex; flex-wrap: wrap; gap: var(--s3); }
.wp-block-buttons > .wp-block-button { margin: 0; }

.cw-textlink {
  font-family: var(--cw-body); font-weight: 600; font-size: .92rem;
  color: var(--cw-primary-deep); text-decoration: none;
  display: inline-flex; align-items: center; gap: .45em;
}
.cw-textlink::after { content: "\2192"; transition: transform .18s ease; }
.cw-textlink:hover::after { transform: translateX(4px); }

/* ---- imagery ---- */
.cw-fig { margin: 0; position: relative; overflow: hidden; background: var(--cw-sunk); }
.cw-fig img { width: 100%; height: 100%; object-fit: cover; }
.cw-fig figcaption {
  font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .04em;
  color: var(--cw-ink-faint); margin-top: var(--s3);
}

/* ---- header ---- */
.cw-header {
  border-bottom: 1px solid var(--cw-line);
  background-color: rgb(var(--cw-paper-rgb) / .88);
  backdrop-filter: saturate(140%) blur(10px);
  position: sticky; top: 0; z-index: 50;
}
.cw-header__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--s6); min-height: 76px; }
.cw-brand { display: flex; align-items: center; gap: 11px; text-decoration: none; color: var(--cw-ink); flex: none; }
.cw-brand__mark { flex: none; color: var(--cw-primary); }
.cw-brand__name { font-family: var(--cw-display); font-size: 1.26rem; font-weight: 700; letter-spacing: -.022em; }
/* The gap came down from 26px when the nav went from six items to eight.
   Eight labels at the old spacing needed 1235px and the row only has 1200,
   so it would have collapsed to the Menu button on every desktop screen -
   the whole point of shortening the labels was to avoid that. */
.cw-nav, .cw-nav .wp-block-navigation__container {
  display: flex; align-items: center; gap: clamp(12px, 1.5vw, 19px);
  list-style: none; margin: 0; padding: 0; flex-wrap: wrap;
}
/* The nav takes the strong colour, not the body colour. It is navigation,
   read at a glance rather than at length, and the whole row sitting in the
   body orange made the masthead look like a line of links to somewhere
   else. On the flipped theme this follows the flip. */
.cw-nav a, .cw-nav .wp-block-navigation-item__content {
  font-size: .88rem; font-weight: 500; color: var(--cw-ink);
  text-decoration: none; white-space: nowrap; position: relative; padding-block: 4px;
}
.cw-nav a::after, .cw-nav .wp-block-navigation-item__content::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1.5px;
  background: var(--cw-primary); transform: scaleX(0); transform-origin: left;
  transition: transform .2s ease;
}
.cw-nav a:hover::after, .cw-nav .wp-block-navigation-item__content:hover::after { transform: scaleX(1); }
.cw-nav a:hover, .cw-nav .wp-block-navigation-item__content:hover { color: var(--cw-primary-deep); }
.cw-header__cta { flex: none; }
.cw-header__cta .cw-btn { padding: 11px 19px; font-size: .87rem; }
.cw-header__menu {
  display: none; align-items: center; gap: var(--s2); background: none;
  border: 1px solid var(--cw-line); border-radius: var(--cw-radius);
  padding: 9px 14px; font: inherit; font-size: .87rem; font-weight: 600;
  color: var(--cw-ink); cursor: pointer;
}

/* ---- footer ---- */
.cw-footer { background: var(--cw-ground); color: #fff; padding-block: clamp(52px, 6vw, 84px) var(--s6); }
.cw-footer h2, .cw-footer h3 { color: #fff; }
.cw-footer__grid { display: grid; gap: clamp(28px, 4vw, 56px); grid-template-columns: minmax(0,1.7fr) repeat(3, minmax(0,1fr)); }
.cw-footer__blurb { color: rgba(255,255,255,.66); font-size: .93rem; max-width: 34ch; margin-top: var(--s4); }
.cw-footer__col h3 { font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; color: rgba(255,255,255,.5); margin-bottom: var(--s4); font-weight: 500; }
.cw-footer__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.cw-footer__col a { color: rgba(255,255,255,.82); text-decoration: none; font-size: .91rem; }
.cw-footer__col a:hover { color: #fff; text-decoration: underline; }
.cw-footer__brand .cw-brand__name { color: #fff; }
.cw-footer__brand .cw-brand__mark { color: rgba(255,255,255,.75); }
.cw-footer__legal {
  margin-top: clamp(38px, 5vw, 60px); padding-top: var(--s5);
  border-top: 1px solid rgba(255,255,255,.14);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--s3);
  font-family: var(--cw-mono); font-size: .72rem; color: rgba(255,255,255,.5);
}

/* ---- blog: shared atoms ---- */
.cw-postcard { display: flex; flex-direction: column; text-decoration: none; color: inherit; }
.cw-postcard__cat {
  font-family: var(--cw-mono); font-size: .66rem; font-weight: 500; letter-spacing: .1em;
  text-transform: uppercase; color: var(--cw-accent-ink); margin-bottom: var(--s3);
}
.cw-postcard__title { font-family: var(--cw-display); font-size: 1.26rem; line-height: 1.2; margin: 0 0 .45em; color: var(--cw-ink); }
.cw-postcard:hover .cw-postcard__title { color: var(--cw-primary-deep); }
.cw-postcard__excerpt { color: var(--cw-ink-soft); font-size: .94rem; margin: 0 0 1em; }
.cw-postcard__meta {
  margin-top: auto; font-family: var(--cw-mono); font-size: .7rem; color: var(--cw-ink-faint);
  display: flex; gap: var(--s3); align-items: center; letter-spacing: .03em;
}
.cw-thumb { aspect-ratio: 16/10; overflow: hidden; background: var(--cw-sunk); border-radius: var(--cw-radius); margin-bottom: var(--s4); }
.cw-thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s cubic-bezier(.2,.7,.3,1); }
.cw-postcard:hover .cw-thumb img { transform: scale(1.035); }

/* ---- single post ---- */
.cw-post { max-width: var(--cw-text); margin-inline: auto; }
.cw-post__head { margin-bottom: var(--s7); }
/* The standfirst sits between the headline and the date line, so it needs
   air on both sides - core/post-excerpt ships with none. */
.cw-post__lede { margin: var(--s4) 0 var(--s4); max-width: 34em; }
.cw-post h2 { margin-top: 1.6em; }
.cw-post blockquote {
  margin: 1.7em 0; padding-left: var(--s5); border-left: 3px solid var(--cw-accent);
  font-family: var(--cw-display); font-size: 1.24rem; line-height: 1.42; color: var(--cw-ink);
}
.cw-prose > * + * { margin-top: 1.05em; }

/* ---- pagination ---- */
.cw-pagination {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s4);
  flex-wrap: wrap; margin-top: clamp(32px,4vw,52px); padding-top: var(--s5);
  border-top: 1px solid var(--cw-line); font-family: var(--cw-mono); font-size: .82rem;
}
.cw-pagination a { text-decoration: none; font-weight: 500; }
.cw-pagination .page-numbers { padding: 4px 10px; border-radius: var(--cw-radius); }
.cw-pagination .page-numbers.current { background: var(--cw-primary-tint); color: var(--cw-primary-deep); }

/* ---- motion ----
   Progressive by construction: .reveal is visible in plain CSS, and only
   becomes hidden-then-animated once the inline head script has confirmed
   JS is running. A script error, a blocked file or an old browser leaves
   the content on screen rather than stranding it at opacity 0. */
.reveal { opacity: 1; transform: none; }
.cw-js .reveal { opacity: 0; transform: translateY(16px); }
.cw-js .reveal.is-in { opacity: 1; transform: none; transition: opacity .6s cubic-bezier(.2,.7,.3,1), transform .6s cubic-bezier(.2,.7,.3,1); }
.reveal-d1 { transition-delay: .07s; }
.reveal-d2 { transition-delay: .14s; }
.reveal-d3 { transition-delay: .21s; }

/* ---- utility ---- */
.cw-hr { border: 0; border-top: 1px solid var(--cw-line); margin: 0; }
.screen-reader-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(1px,1px,1px,1px); white-space: nowrap; }
.cw-skip { position: absolute; left: -9999px; top: 0; background: var(--cw-primary-deep); color: #fff; padding: 10px 16px; z-index: 100; }
.cw-skip:focus { left: var(--s2); top: var(--s2); }
:focus-visible { outline: 2.5px solid var(--cw-accent-ink); outline-offset: 2px; }

/* ---- touch targets ------------------------------------------------------
   Anything you tap wants roughly 44px of height. At the desktop pointer
   these links are the right size for their type; the problem is that the
   same markup gets prodded with a thumb, and 1024px is an iPad in landscape
   showing the full desktop navigation with 25px-tall links in it. So the
   rule keys off the pointer as well as the width - a small laptop window
   keeps the tight header, a tablet does not.

   All of it is padding. Nothing here changes a type size, a colour or a
   position, so the design is identical; the hit area around it grows. */
@media (max-width: 1024px), (pointer: coarse) {
  /* 17px of line box needs 14 top and bottom to clear 44. The hover
     underline is positioned from the bottom of the padded box, so it moves
     back up by the same amount and sits exactly where it did. */
  .cw-nav a, .cw-nav .wp-block-navigation-item__content { padding-block: 14px; }
  .cw-nav a::after,
  .cw-nav .wp-block-navigation-item__content::after { bottom: 10px; }
  .cw-brand { padding-block: 8px; }
  .cw-header__menu { min-height: 44px; }
  .cw-header__cta .cw-btn { padding-block: 14px; }
  /* the gap shrinks by what the padding adds, so the column is the same
     height it was and only the tap areas overlap the space between */
  .cw-footer__col ul { gap: 0; }
  .cw-footer__col a { display: inline-block; padding-block: 11px; }
  .cw-social { gap: var(--s2); }
  .cw-social a { display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; min-width: 44px; padding-inline: 8px; padding-bottom: 0; }
  /* the "X" link is a single character - tall enough already, 10px wide */
  .cw-footer__col a { min-width: 44px; }
  .cw-textlink { min-height: 44px; }
  .cw-footer__legal { line-height: 2; }
  /* The rail's links were 37px tall on a phone. That was never measured
     before because the rail only appears once posts exist, and there were
     none. Padding rather than min-height, so the whole row is the target
     and not just the word. */
  .cw-cats a { display: block; padding-block: 12px; min-height: 44px; }
  .cw-cats ul { gap: 0; }
  .cw-related__item { min-height: 44px; }
}

/* ---- the mobile drawer -------------------------------------------------
   The panel itself is built by theme.js from the links already in the
   header. These are its clothes. */
.cw-drawer { position: fixed; inset: 0; z-index: 120; }
.cw-drawer__scrim { position: absolute; inset: 0; background: rgb(var(--cw-scrim) / .55);
  opacity: 0; transition: opacity .26s ease; backdrop-filter: blur(2px); }
.cw-drawer__sheet { position: absolute; top: 0; right: 0; bottom: 0;
  width: min(86vw, 360px); background: var(--cw-paper);
  border-left: 1px solid var(--cw-line); box-shadow: -18px 0 48px rgb(var(--cw-scrim) / .22);
  padding: clamp(18px,4vw,26px);
  display: flex; flex-direction: column; gap: var(--s5);
  transform: translateX(100%); transition: transform .26s cubic-bezier(.2,.7,.3,1);
  overflow-y: auto; overscroll-behavior: contain; }
.cw-drawer.is-open .cw-drawer__scrim { opacity: 1; }
.cw-drawer.is-open .cw-drawer__sheet { transform: translateX(0); }
.cw-drawer__close { align-self: flex-end; width: 44px; height: 44px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 1px solid var(--cw-line); border-radius: var(--cw-radius);
  font-size: 1.5rem; line-height: 1; color: var(--cw-ink); cursor: pointer; }
.cw-drawer__list { list-style: none; margin: 0; padding: 0; display: grid; }
.cw-drawer__list a { display: block; padding: 14px 4px; min-height: 48px;
  font-family: var(--cw-display); font-size: 1.12rem; font-weight: 600;
  color: var(--cw-ink); text-decoration: none;
  border-bottom: 1px solid var(--cw-line-soft); }
.cw-drawer__list li:last-child a { border-bottom: 0; }
.cw-drawer__list a:active { color: var(--cw-accent-ink); }
.cw-drawer__cta { margin-top: auto; text-align: center; }

/* The page behind a drawer must not scroll under it. position:fixed on the
   body needs the scroll position parked in an inline top offset, which the
   script sets and clears. */
html.cw-menu-open, html.cw-menu-open body { overflow: hidden; }
html.cw-menu-open body { position: fixed; width: 100%; }

@media (max-width: 900px) {
  .cw-footer__grid { grid-template-columns: 1fr 1fr; }
}

/* ---- the header collapses when the row stops fitting ---------------------
   One media query, at css.NAV_BREAKPOINT, and nothing measures anything.

   The rule this implements is "the drawer takes over once the row can no
   longer be one straight line". That was briefly implemented literally -
   theme.js measured a clone of the header and set a class - and it broke
   the header twice on browsers nobody was testing in. The number is the
   same answer with none of the failure modes: it cannot be measured wrong,
   it needs no JavaScript to be right, and every engine agrees on it.

   Three states, in order of how much the browser knows:
     no JS ............ links visible and wrapping. Ugly at some widths,
                        navigable at all of them, which a dead button is not.
     ready, wide ...... one line, no wrapping, button hidden.
     ready, narrow .... links and CTA hidden, button shown, drawer available.

   The .cw-menu-ready gate is what keeps the middle state honest: the links
   are only hidden once the script that replaces them exists. */
html.cw-menu-ready .cw-nav--static ul { flex-wrap: nowrap; }

@media (max-width: 1300px) {
  html.cw-menu-ready .cw-nav--static,
  html.cw-menu-ready nav.cw-nav--static { display: none; }
  html.cw-menu-ready .cw-header__cta { display: none; }
  html.cw-menu-ready .cw-header__menu { display: inline-flex; }
  /* Without the script the links stay, so let them wrap rather than
     overflow the header. */
  .cw-nav--static ul { flex-wrap: wrap; }
}

@media (max-width: 560px) {
  .cw-footer__grid { grid-template-columns: 1fr; }
  body.cw { font-size: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  .cw-js .reveal { opacity: 1; transform: none; }
}


/* ---------- header sits over the full-bleed hero, solidifies on scroll ----
   The base header is position:sticky, which means it occupies flow space at
   the top of the document. Left alone it pushes the hero down by its own
   height and renders white-on-white over nothing. The hero is therefore
   pulled up underneath it; the header keeps its z-index and floats over the
   photograph. Everything transparent is scoped to pages that actually have
   a hero, so the blog index keeps its normal frosted bar. */
.cw-hero { padding: 0; margin-top: -76px; }
.cw-header { transition: background .3s ease, backdrop-filter .3s ease, box-shadow .3s ease; }

/* ---------- THE LOGO ------------------------------------------------------
   Ordinary background images on relative paths. The stylesheet sits at the
   theme root and assets/logo/ sits directly under it, so one URL resolves
   in WordPress, in the static preview and over file:// with no rewriting.

   This replaces a mask-image + base64 arrangement, which is why the logo
   was coming up blank. A mask that fails to apply paints NOTHING: the
   element keeps its box, the background colour is clipped away entirely,
   and the logo is invisible rather than broken. Long data: URIs are also
   the first thing a host-side CSS optimiser mangles. A background image
   has no such failure mode.

   Two files per lockup — brand colour, and a white knockout for use over
   the hero photograph and in the dark footer. The mark is the same orange
   and steel blue in all three demos, per Nathan's note that it should not
   change between them; only the knockout differs, and that is legibility
   rather than a second palette. */
.cw-logo__mark, .cw-logo__word, .cw-logo__full {
  display: block;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
/* Heights in px, not aspect-ratio.
   These are empty spans carrying a background image, so their height comes
   from nothing but this rule. Sized with aspect-ratio alone they collapse to
   zero on any engine without it - and a zero-height background image is an
   invisible logo, so the brand simply disappears from the masthead. The
   ratios are still exactly the artwork's; they are just resolved here
   instead of by the browser. */
.cw-logo__mark { width: 72px;  height: 29px;
  background-image: url("assets/logo/logo-mark.png"); }
.cw-logo__word { width: 150px; height: 17px;
  background-image: url("assets/logo/logo-word.png"); }
/* The one fluid mark: the height clamp is the width clamp divided by the
   artwork's 2657/1500, so it tracks the same curve without aspect-ratio. */
.cw-logo__full { width: clamp(154px, 17vw, 194px); height: clamp(87px, 9.6vw, 110px);
  background-image: url("assets/logo/logo-full.png"); }
.cw-brand { gap: 11px; align-items: center; }
.cw-brand--stack { display: block; }
/* Header lockup: the mark, then the name with the brand line beneath it.
   The two stack in their own column so the tagline sits under the wordmark
   rather than beside the mark, which is how the artwork reads. */
.cw-brand__lockup { display: flex; flex-direction: column; gap: 3px;
  align-items: flex-start; }
.cw-brand__tagline { font-size: .7rem; font-weight: 500; letter-spacing: .052em;
  color: var(--cw-primary); white-space: nowrap; line-height: 1; }
/* The footer pair sits on one line like the header's, without the tagline. */
.cw-brand--footer { display: flex; align-items: center; gap: 11px; }
/* Below this the wordmark goes and the mark carries the brand alone, so the
   tagline has nothing to sit under. */
@media (max-width: 560px) {
  .cw-logo__word { display: none; }
  .cw-brand__tagline { display: none; }
}

/* The mark stays in brand colour everywhere, including over the hero
   photograph. It was knocked out to white there on legibility grounds; that
   was the wrong call - the orange is the recognisable half of this mark and
   white throws it away. The hero already carries a scrim under the header,
   and the mark is deliberately given a little more of one below, which
   holds the blue without touching the artwork. */

body:has(.cw-hero) .cw-header { background: transparent; backdrop-filter: none; border-bottom: 0; }
/* Not a bar - a soft top-down wash that fades out well before the
   headline, there only so the colour mark keeps its edges over a
   bright frame. */
body:has(.cw-hero) .cw-header::before { content: ""; position: absolute; inset: -1px 0 auto 0;
  height: 190px; pointer-events: none; z-index: -1;
  background: linear-gradient(180deg, rgb(var(--cw-scrim) / .52) 0%,
    rgb(var(--cw-scrim) / .28) 46%, rgb(var(--cw-scrim) / 0) 100%); }
body:has(.cw-hero) .cw-header.is-stuck::before { opacity: 0; transition: opacity .3s ease; }
body:has(.cw-hero) .cw-header .cw-brand { color: #fff; }
body:has(.cw-hero) .cw-header .cw-nav a,
body:has(.cw-hero) .cw-header .cw-nav .wp-block-navigation-item__content { color: rgba(255,255,255,.92); }
body:has(.cw-hero) .cw-header .cw-nav a:hover { color: #fff; }
body:has(.cw-hero) .cw-header .cw-nav a::after { background: var(--cw-accent); }
body:has(.cw-hero) .cw-header__cta .cw-btn { background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.55); color: #fff; backdrop-filter: blur(8px); }
body:has(.cw-hero) .cw-header__cta .cw-btn:hover { background: #fff; border-color: #fff; color: var(--cw-ink); }
body:has(.cw-hero) .cw-header__menu { color: #fff; border-color: rgba(255,255,255,.45); }
body:has(.cw-hero) .cw-header.is-stuck { background-color: rgb(var(--cw-paper-rgb) / .93);
  backdrop-filter: saturate(140%) blur(10px); box-shadow: 0 1px 0 var(--cw-line); }
body:has(.cw-hero) .cw-header.is-stuck .cw-brand { color: var(--cw-ink); }
body:has(.cw-hero) .cw-header.is-stuck .cw-nav a,
body:has(.cw-hero) .cw-header.is-stuck .cw-nav .wp-block-navigation-item__content { color: var(--cw-ink); }
body:has(.cw-hero) .cw-header.is-stuck .cw-nav a:hover { color: var(--cw-primary-deep); }
body:has(.cw-hero) .cw-header.is-stuck .cw-header__cta .cw-btn { background: var(--cw-primary); border-color: var(--cw-primary); color: var(--cw-on-primary); backdrop-filter: none; }
body:has(.cw-hero) .cw-header.is-stuck .cw-header__menu { color: var(--cw-ink); border-color: var(--cw-line); background: none; backdrop-filter: none; }


/* The same rules again for browsers without :has(). See the
   note in css_themes.py - this pair is generated, not typed. */
body.cw-has-hero .cw-header { background: transparent; backdrop-filter: none; border-bottom: 0; }
/* Not a bar - a soft top-down wash that fades out well before the
   headline, there only so the colour mark keeps its edges over a
   bright frame. */
body.cw-has-hero .cw-header::before { content: ""; position: absolute; inset: -1px 0 auto 0;
  height: 190px; pointer-events: none; z-index: -1;
  background: linear-gradient(180deg, rgb(var(--cw-scrim) / .52) 0%,
    rgb(var(--cw-scrim) / .28) 46%, rgb(var(--cw-scrim) / 0) 100%); }
body.cw-has-hero .cw-header.is-stuck::before { opacity: 0; transition: opacity .3s ease; }
body.cw-has-hero .cw-header .cw-brand { color: #fff; }
body.cw-has-hero .cw-header .cw-nav a,
body.cw-has-hero .cw-header .cw-nav .wp-block-navigation-item__content { color: rgba(255,255,255,.92); }
body.cw-has-hero .cw-header .cw-nav a:hover { color: #fff; }
body.cw-has-hero .cw-header .cw-nav a::after { background: var(--cw-accent); }
body.cw-has-hero .cw-header__cta .cw-btn { background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.55); color: #fff; backdrop-filter: blur(8px); }
body.cw-has-hero .cw-header__cta .cw-btn:hover { background: #fff; border-color: #fff; color: var(--cw-ink); }
body.cw-has-hero .cw-header__menu { color: #fff; border-color: rgba(255,255,255,.45); }
body.cw-has-hero .cw-header.is-stuck { background-color: rgb(var(--cw-paper-rgb) / .93);
  backdrop-filter: saturate(140%) blur(10px); box-shadow: 0 1px 0 var(--cw-line); }
body.cw-has-hero .cw-header.is-stuck .cw-brand { color: var(--cw-ink); }
body.cw-has-hero .cw-header.is-stuck .cw-nav a,
body.cw-has-hero .cw-header.is-stuck .cw-nav .wp-block-navigation-item__content { color: var(--cw-ink); }
body.cw-has-hero .cw-header.is-stuck .cw-nav a:hover { color: var(--cw-primary-deep); }
body.cw-has-hero .cw-header.is-stuck .cw-header__cta .cw-btn { background: var(--cw-primary); border-color: var(--cw-primary); color: var(--cw-on-primary); backdrop-filter: none; }
body.cw-has-hero .cw-header.is-stuck .cw-header__menu { color: var(--cw-ink); border-color: var(--cw-line); background: none; backdrop-filter: none; }

/* ---------- THE HERO (Field Notes' stage, kept for all three) ------------- */
.cw-stage {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: 100vh; min-height: 100dvh;
  display: grid; grid-template-rows: auto 1fr auto;
  padding: calc(76px + clamp(26px,3.4vw,52px)) 0 clamp(26px,3.4vw,52px);
}
.cw-stage > * { position: relative; }
/* ---------- THE BACKDROP -------------------------------------------------
   The stage backdrop holds still. It used to carry a scroll-driven pan and
   a slow timer drift on top of it; Nathan asked for the moving picture to
   be the video itself rather than a photograph being pushed around, so both
   are gone and nothing here is wired to the scrollbar.

   Two shapes have to fit this one box. When a clip exists the <video>
   carries .cw-stage__img directly; when it does not, an <img> carries it
   inside a .cw-stage__media wrapper. Positioning the class itself, rather
   than the wrapper, covers both without a second rule. */
.cw-stage__media { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
.cw-stage__img {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: center 54%;
}
.cw-stage__media .cw-stage__img { z-index: auto; }

/* the type arrives rather than simply being there */
@keyframes cw-rise { from { opacity: 0; transform: translateY(20px); }
                     to   { opacity: 1; transform: none; } }
.cw-stage .cw-eyebrow,
.cw-stage h1,
.cw-stage__sub,
.cw-stage .cw-hero__actions { animation: cw-rise .95s cubic-bezier(.2,.7,.25,1) both; }
.cw-stage .cw-scrollcue { animation: cw-rise .95s cubic-bezier(.2,.7,.25,1) both; }
.cw-stage .cw-eyebrow { animation-delay: .12s; }
.cw-stage h1 { animation-delay: .24s; }
.cw-stage__sub { animation-delay: .44s; }
.cw-stage .cw-hero__actions { animation-delay: .56s; }
.cw-stage .cw-scrollcue { animation-delay: 1.1s; }

/* a slow light passing over the frame, barely there but it keeps the hero
   from reading as a flat photograph */
.cw-stage::before { content: ""; position: absolute; inset: -20%; z-index: 0;
  pointer-events: none;
  background: radial-gradient(42% 50% at 28% 38%,
    rgba(255,255,255,.20) 0%, rgba(255,255,255,0) 68%);
  animation: cw-sheen 11s ease-in-out infinite alternate; }
@keyframes cw-sheen {
  from { transform: translate3d(-14%, -7%, 0); opacity: .35; }
  to   { transform: translate3d(16%, 9%, 0); opacity: 1; }
}

/* the figures strip lifts in as it arrives */
.cw-strip__cell { animation: cw-rise .8s cubic-bezier(.2,.7,.25,1) both; }
.cw-strip__cell:nth-child(1) { animation-delay: .70s; }
.cw-strip__cell:nth-child(2) { animation-delay: .80s; }
.cw-strip__cell:nth-child(3) { animation-delay: .90s; }
.cw-strip__cell:nth-child(4) { animation-delay: 1.00s; }

@media (prefers-reduced-motion: reduce) {
    .cw-stage::before { animation: none; opacity: .6; }
}
/* Two scrims, not one. A vertical-only wash cannot carry white type over a
   bright sky — measured against the real composited pixels, the pale-sky
   heroes came back at 1.3:1. The horizontal pass darkens the column the type
   actually occupies and releases by 70% across, so the right-hand side of
   the photograph stays bright. */
.cw-stage::after { content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(97deg,
      rgb(var(--cw-scrim) / .82) 0%, rgb(var(--cw-scrim) / .68) 30%,
      rgb(var(--cw-scrim) / .30) 55%, rgb(var(--cw-scrim) / 0) 78%),
    linear-gradient(180deg,
      rgb(var(--cw-scrim) / .52) 0%, rgb(var(--cw-scrim) / .20) 30%,
      rgb(var(--cw-scrim) / .22) 58%, rgb(var(--cw-scrim) / .88) 100%); }
.cw-stage .cw-eyebrow { color: rgba(255,255,255,.84); }
.cw-stage h1 { color: #fff; font-size: clamp(2.4rem,5.4vw,4.2rem); max-width: 15ch; margin: 0; }
.cw-stage__foot { display: grid; grid-template-columns: minmax(0,1fr) auto;
  gap: clamp(20px,3vw,44px); align-items: end; }
.cw-stage__sub { color: rgba(255,255,255,.9); max-width: 46ch; margin: 0; font-size: clamp(1rem,1.5vw,1.16rem); }
.cw-stage .cw-hero__actions { margin: 0; }
.cw-stage .is-ghost .wp-block-button__link { background: rgba(255,255,255,.14); color: #fff;
  border-color: rgba(255,255,255,.5); backdrop-filter: blur(6px); }
.cw-stage .is-ghost .wp-block-button__link:hover { background: rgba(255,255,255,.28); border-color: #fff; color: #fff; }

.cw-scrollcue { position: absolute; left: 0; right: 0; margin-inline: auto;
  width: max-content; bottom: clamp(16px,2.4vw,26px);
  display: flex; flex-direction: column; align-items: center; gap: var(--s2);
  font-family: var(--cw-mono); font-size: .62rem; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(255,255,255,.8); text-decoration: none; z-index: 3; }
.cw-scrollcue__line { width: 1px; height: 34px; position: relative; overflow: hidden;
  background: linear-gradient(180deg, rgba(255,255,255,.7), rgba(255,255,255,0)); }
.cw-scrollcue__line::after { content: ""; position: absolute; left: 0; top: -60%; width: 1px; height: 60%;
  background: #fff; animation: cw-cue 2.4s cubic-bezier(.6,0,.4,1) infinite; }
@keyframes cw-cue { 0% { top: -60%; } 60%, 100% { top: 100%; } }
@media (prefers-reduced-motion: reduce) { .cw-scrollcue__line::after { animation: none; top: 0; height: 100%; opacity: .5; } }

/* full-width figure strip directly under the hero */
.cw-strip { margin-top: clamp(36px,5vw,60px); border-top: 1px solid var(--cw-line);
  border-bottom: 1px solid var(--cw-line); background: var(--cw-surface); }
.cw-strip__inner { display: grid; grid-template-columns: repeat(4,1fr); }
.cw-strip__cell { padding: clamp(18px,2.4vw,26px) clamp(16px,2vw,24px); }
.cw-strip__cell + .cw-strip__cell { border-left: 1px solid var(--cw-line); }
.cw-strip__n { font-family: var(--cw-display); font-size: clamp(1.5rem,2.6vw,2.05rem); line-height: 1; color: var(--cw-primary-deep); }
.cw-strip__l { font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .04em;
  color: var(--cw-ink-faint); margin-top: var(--s2); line-height: 1.4; }

/* ---------- THE HOMEPAGE (sticky index, body) -----------------------------
   Two columns, not three. The right-hand margin notes were pulled at
   Nathan's request and the space went to the content rather than to
   whitespace, so the body column is now roughly 40% wider and the section
   figures, doors and service rows all get room they did not have. */
.cw-worklayout { display: grid; grid-template-columns: 196px minmax(0,1fr);
  gap: clamp(24px,4vw,52px); align-items: start; }
.cw-secnav { position: sticky; top: 104px; }
.cw-secnav__hd { font-family: var(--cw-mono); font-size: .64rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--cw-ink-faint); margin-bottom: var(--s4); }
.cw-secnav ol { list-style: none; margin: 0; padding: 0; counter-reset: sn; border-left: 2px solid var(--cw-line); }
.cw-secnav li { counter-increment: sn; }
.cw-secnav a { display: grid; grid-template-columns: 24px 1fr; gap: 6px; padding: 8px 0 8px var(--s4);
  margin-left: -2px; border-left: 2px solid transparent; font-size: .87rem; color: var(--cw-ink-soft); text-decoration: none; }
.cw-secnav a::before { content: counter(sn, decimal-leading-zero); font-family: var(--cw-mono);
  color: var(--cw-ink-faint); font-size: .72rem; }
.cw-secnav a:hover, .cw-secnav a.is-active { color: var(--cw-primary-deep); border-left-color: var(--cw-primary); font-weight: 500; }

.cw-block { padding-block: clamp(36px,5vw,58px); border-bottom: 1px solid var(--cw-line); scroll-margin-top: 100px; }
.cw-block:first-child { padding-top: 0; }
.cw-block:last-child { border-bottom: 0; }
.cw-block > h2 { font-size: clamp(1.6rem,2.8vw,2.05rem); margin-bottom: .5em; }
.cw-block__intro { color: var(--cw-ink-soft); max-width: 60ch; margin-bottom: var(--s6); }

/* ---------- THE EMPTY STATE ---------------------------------------------
   Where the post cards go before the first post exists. Deliberately a
   panel rather than nothing: an Insights heading over blank paper reads as
   a broken page, and this one says what will fill it. WordPress swaps it
   for a card the moment something is published. */
.cw-empty { border: 1px dashed var(--cw-line); border-radius: var(--cw-radius-lg);
  background: var(--cw-sunk); padding: clamp(26px,4vw,44px);
  text-align: center; }
.cw-empty__lead { font-family: var(--cw-display); font-weight: 600;
  font-size: clamp(1.06rem,1.6vw,1.24rem); color: var(--cw-ink);
  margin: 0 0 var(--s3); }
.cw-empty__line { color: var(--cw-ink-soft); font-size: .95rem;
  max-width: 54ch; margin: 0 auto; }

/* the index without its topic rail: one column, not a gap where the rail
   was. Doubled class so it outranks .cw-bloglayout wherever that is set. */
.cw-bloglayout.cw-bloglayout--solo { grid-template-columns: minmax(0,1fr); }

/* The three paragraphs the copy opens the home page with. The first is the
   whole positioning of the firm and is set as a statement; the two under it
   are the argument for it and read as body. */
.cw-stance { max-width: 66ch; margin-bottom: var(--s7); }
.cw-stance > .cw-block__intro { font-size: clamp(1.14rem,1.7vw,1.44rem);
  line-height: 1.36; color: var(--cw-ink); max-width: none;
  margin-bottom: var(--s5); }
.cw-stance__p { color: var(--cw-ink-soft); margin: 0 0 var(--s4); }
.cw-stance__p:last-child { margin-bottom: 0; }
/* section heading with its flourish alongside */
.cw-block__hd { display: flex; align-items: center; gap: var(--s4); margin-bottom: .3em; }
.cw-block__hd h2 { margin: 0; font-size: clamp(1.6rem,2.8vw,2.05rem); }

/* ---------- THE FLOURISHES -----------------------------------------------
   The spot art carries its own palette rather than the site's. Nathan asked
   for colour that does not have to follow the interface, and holding one
   illustration language across all three demos means the thing that changes
   between them is the interface colour, not the drawings. Retune here. */
/* Declared at the root, not on .cw-fl: the drawings are also dropped in
   raw (service cards, ruled rows) where that wrapper is absent, and scoping
   the palette to the wrapper left those SVGs painted in undefined colours —
   invisible, but still occupying their full box. */
:root {
  --fl-navy: #24427E;
  --fl-line: #24427E;
  --fl-orange: #F2903A;
  --fl-green: #46A96C;
  --fl-sky: #4FA8D8;
  --fl-yellow: #F3C64B;
  --fl-coral: #E9705C;
  --fl-cream: #FFFCF5;
}
.cw-fl { display: inline-block; line-height: 0; flex: none; }
.cw-fl svg { display: block; width: 100%; height: auto; }
.cw-fl--sm svg { width: 44px; }
.cw-fl--md svg { width: 62px; }
.cw-fl--lg svg { width: 92px; }
.cw-block__hd .cw-fl svg { width: 58px; }
/* raw drawings need their own sizing — they have no .cw-fl box */
.cw-svccard__art svg { width: 62px; height: auto; display: block; }
.cw-svc__art svg { width: 52px; height: auto; display: block; }
.cw-door__art svg { width: 58px; height: auto; display: block; }

/* ---------- doors -------------------------------------------------------- */
.cw-doors { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(18px,2.6vw,26px); }
.cw-door { border: 1px solid var(--cw-line); border-radius: var(--cw-radius-lg); background: var(--cw-surface);
  padding: clamp(22px,2.8vw,30px); display: flex; flex-direction: column; }
.cw-door__label { font-family: var(--cw-mono); font-size: .64rem; letter-spacing: .11em; text-transform: uppercase;
  margin-bottom: var(--s3); display: inline-block; padding: 4px 10px; border-radius: 999px; align-self: flex-start; }
.cw-door--community .cw-door__label { background: var(--cw-primary-tint); color: var(--cw-primary-deep); }
.cw-door--developer .cw-door__label { background: var(--cw-accent-tint); color: var(--cw-accent-ink); }
.cw-door h3 { font-family: var(--cw-display); font-size: clamp(1.24rem,2vw,1.55rem); margin-bottom: .4em; }
.cw-door__body { color: var(--cw-ink-soft); font-size: .94rem; }
.cw-door__list { list-style: none; margin: var(--s5) 0; padding: 0; display: grid; gap: var(--s3); font-size: .91rem; }
.cw-door__list li { display: grid; grid-template-columns: 20px 1fr; gap: var(--s1); align-items: start; }
.cw-door__list li::before { content: "\2014"; color: var(--cw-accent-ink); }
.cw-door .cw-textlink { margin-top: auto; }
.cw-door__art { align-self: flex-end; margin-top: var(--s5); opacity: .9; }

/* ---------- the load curve ----------------------------------------------- */
.cw-curve { border: 1px solid var(--cw-line); border-radius: var(--cw-radius-lg); background: var(--cw-surface);
  padding: clamp(20px,2.6vw,28px); }
.cw-curve__hd { display: flex; gap: var(--s5); flex-wrap: wrap; align-items: center; margin-bottom: var(--s4);
  font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .04em; }
.cw-curve__key { display: inline-flex; align-items: center; gap: var(--s2); color: var(--cw-ink-soft); }
.cw-curve__key i { width: 14px; height: 3px; border-radius: 2px; display: block; }
.cw-curve svg { width: 100%; height: auto; display: block; overflow: visible; }
.cw-curve figcaption { font-family: var(--cw-body); font-size: .86rem; color: var(--cw-ink-soft);
  margin-top: var(--s4); font-style: normal; }

/* ---------- record ------------------------------------------------------- */
.cw-statband { display: grid; grid-template-columns: repeat(4,1fr);
  gap: clamp(14px,1.8vw,20px); }
/* Inside the annotated layout the content column is ~620px, so four stat
   columns leave 155px each and "14 mo." breaks across two lines. Two-up. */
.cw-worklayout .cw-statband { grid-template-columns: 1fr 1fr; }
/* Both take their colour from the band, which takes it from
   --cw-on-primary. They used to hardcode white and a 78%% white; against
   Porchlight's brighter orange that was 2.87:1 on the figure, and no
   opacity below 1 clears AA for the label on Watershed's brighter blue.
   The hierarchy is carried by size and family instead, which is where it
   should have been. */
.cw-stat { background: var(--cw-sunk); border: 1px solid var(--cw-line);
  border-radius: var(--cw-radius-lg); padding: clamp(20px,2.6vw,28px);
  display: flex; flex-direction: column; gap: var(--s3); }
/* The figure is the accent, the claim is the strong colour and the evidence
   is body - the same three-step the rest of the site uses, so the section
   does not read as a component from somewhere else. */
.cw-stat__n { font-family: var(--cw-display); font-weight: 700;
  font-size: clamp(2rem,3.4vw,2.9rem); line-height: 1;
  color: var(--cw-accent-ink); margin: 0; }
.cw-stat__k { font-size: .95rem; font-weight: 700; line-height: 1.34;
  color: var(--cw-ink); }
.cw-stat__note { font-size: .88rem; line-height: 1.5;
  color: var(--cw-ink-soft); margin: 0; }
.cw-phil__pull { max-width: 46ch; }
.cw-phil__pull { font-family: var(--cw-display); font-size: clamp(1.4rem,2.8vw,2rem); line-height: 1.32;
  color: var(--cw-primary-deep); margin: 0 0 var(--s5); max-width: 26ch; }
.cw-phil__sign { font-family: var(--cw-mono); font-size: .74rem; color: var(--cw-ink-faint); }

/* ---------- THE BLOG INDEX (Harbor's, kept for all three) ---------------- */
.cw-bloglayout { display: grid; grid-template-columns: 176px minmax(0,1fr); gap: clamp(28px,5vw,64px); align-items: start; }
.cw-cats { position: sticky; top: 108px; }
.cw-cats__hd { font-family: var(--cw-mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--cw-ink-faint); margin-bottom: var(--s4); }
.cw-cats ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.cw-cats a { display: block; padding: 7px 10px; font-size: .89rem; color: var(--cw-ink-soft);
  text-decoration: none; border-radius: var(--cw-radius); }
.cw-cats a:hover { background: var(--cw-sunk); color: var(--cw-primary-deep); }
.cw-cats a[aria-current] { background: var(--cw-primary); color: var(--cw-on-primary); }

/* alternating rows; the graphic is a quarter of the column, never a banner */
.cw-posts { display: grid; }
.cw-posts .cw-postcard { display: grid; grid-template-columns: minmax(0,1fr) minmax(150px,25%);
  gap: clamp(20px,3vw,40px); align-items: center; padding-block: clamp(24px,3vw,36px); border-top: 1px solid var(--cw-line); }
.cw-posts .cw-postcard:last-child { border-bottom: 1px solid var(--cw-line); }
/* Alternating side. `order` alone moves the thumb into the FIRST track,
   which is the wide one — the image then takes the text's column and the
   copy gets squeezed into 25%. The template has to be swapped too. */
.cw-posts .cw-postcard:nth-child(even) { grid-template-columns: minmax(150px,25%) minmax(0,1fr); }
.cw-posts .cw-postcard:nth-child(even) .cw-thumb { order: -1; }
.cw-posts .cw-thumb { margin: 0; aspect-ratio: 4/3; border-radius: var(--cw-radius);
  overflow: hidden; background: var(--cw-sunk); }
.cw-posts .cw-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cw-posts .cw-postcard__title { font-size: clamp(1.24rem,2.1vw,1.6rem); }

/* ---------- INNER PAGES --------------------------------------------------
   The band hero. Deliberately not the full-screen stage: arriving on an
   inner page should feel like going deeper, not starting the site again. */
.cw-hero--page { margin-top: -76px; }
.cw-pagehero { position: relative; overflow: hidden; isolation: isolate;
  min-height: clamp(360px, 52vh, 520px); display: grid; align-items: end;
  padding: calc(76px + clamp(30px,4vw,56px)) 0 clamp(30px,4vw,56px); }
.cw-pagehero > * { position: relative; }
.cw-pagehero__img { position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 46%; z-index: -2; }

.cw-pagehero .cw-eyebrow,
.cw-pagehero h1,
.cw-pagehero__sub { animation: cw-rise .9s cubic-bezier(.2,.7,.25,1) both; }
.cw-pagehero .cw-eyebrow { animation-delay: .10s; }
.cw-pagehero h1 { animation-delay: .22s; }
.cw-pagehero__sub { animation-delay: .40s; }
@media (prefers-reduced-motion: reduce) {
  .cw-pagehero__img { animation: none; transform: scale(1.04); }
}
.cw-pagehero::after { content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(97deg, rgb(var(--cw-scrim) / .86) 0%, rgb(var(--cw-scrim) / .72) 32%,
      rgb(var(--cw-scrim) / .34) 58%, rgb(var(--cw-scrim) / .06) 80%),
    linear-gradient(180deg, rgb(var(--cw-scrim) / .46) 0%, rgb(var(--cw-scrim) / .22) 40%,
      rgb(var(--cw-scrim) / .56) 100%); }
.cw-pagehero .cw-eyebrow { color: rgba(255,255,255,.86); }
.cw-pagehero h1 { color: #fff; font-size: clamp(2rem,4.4vw,3.3rem); max-width: 17ch; margin: 0 0 var(--s4); }
.cw-pagehero__sub { color: rgba(255,255,255,.92); max-width: 52ch; margin: 0;
  font-size: clamp(.98rem,1.4vw,1.12rem); }

/* a big pale drawing bled off the corner of every page hero */
.cw-pagehero__mark { position: absolute; right: -3%; bottom: -22%; width: clamp(210px,26vw,360px);
  opacity: .14; z-index: 0; pointer-events: none; }
.cw-pagehero__mark svg { width: 100%; height: auto; display: block; }

/* ---------- THE SHOWCASE BAND -------------------------------------------
   Every inner page used to open into a column of ruled text. This sits
   between the hero and the body: a tinted full-width band carrying one of
   the isometric drawings, so there is colour and something to look at
   before the reading starts. */
.cw-showcase { position: relative; overflow: hidden;
  background:
    radial-gradient(120% 140% at 12% 0%, var(--cw-primary-tint) 0%, transparent 62%),
    radial-gradient(110% 130% at 96% 100%, var(--cw-accent-tint) 0%, transparent 58%),
    var(--cw-sunk);
  border-top: 1px solid var(--cw-line); border-bottom: 1px solid var(--cw-line);
  padding-block: clamp(40px,6vw,76px); }
.cw-showcase__grid { display: grid; grid-template-columns: minmax(0,.95fr) minmax(0,1fr);
  gap: clamp(28px,5vw,64px); align-items: center; }
.cw-showcase__art { border-radius: var(--cw-radius-lg); overflow: hidden;
  background: var(--cw-surface); box-shadow: var(--cw-shadow);
  border: 1px solid var(--cw-line); }
.cw-showcase__art img { width: 100%; height: auto; display: block; }
.cw-showcase__kicker { font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .13em;
  text-transform: uppercase; color: var(--cw-accent-ink); margin-bottom: var(--s3);
  display: inline-flex; align-items: center; gap: var(--s2); }
.cw-showcase__kicker::before { content: ""; width: 22px; height: 2px;
  background: var(--cw-accent-ink); display: block; }
.cw-showcase h2 { font-size: clamp(1.7rem,3.2vw,2.5rem); margin-bottom: .4em; max-width: 18ch; }
.cw-showcase__body > p { color: var(--cw-ink-soft); max-width: 54ch; margin-bottom: var(--s5); }
.cw-showcase__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.cw-showcase__list li { display: grid; grid-template-columns: 24px 1fr; gap: var(--s2);
  align-items: start; font-size: .95rem; color: var(--cw-ink); }
.cw-showcase__list li::before { content: ""; width: 15px; height: 15px; margin-top: 4px;
  border-radius: 50%; background: var(--cw-accent-ink);
  box-shadow: 0 0 0 4px var(--cw-accent-tint); }
@media (max-width: 900px) {
  .cw-showcase__grid { grid-template-columns: 1fr; }
  .cw-showcase__art { max-width: 460px; }
}

/* inner pages keep the scrolling index, drop the marginalia */
.cw-worklayout--page { grid-template-columns: 196px minmax(0,1fr); }

/* cards lift a little, so the pages feel responsive to the pointer */
.cw-svccard, .cw-pt__card, .cw-related__item, .cw-status__cell {
  transition: transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s ease,
              border-color .25s ease; }
.cw-svccard:hover, .cw-pt__card:hover, .cw-related__item:hover, .cw-status__cell:hover {
  transform: translateY(-3px); box-shadow: var(--cw-shadow); }

/* the deliverables block gets a tinted panel rather than bare bullets */
/* The ticked lists sit on the page, not on a tinted panel. On How we're
   paid, sections 03 and 04 are both checklists, so the panel put two blue
   slabs down the page - and one of them landed on an already-tinted band,
   which made a box inside a box. */

/* three-claim blocks */
.cw-pt { display: grid; }
.cw-pt__row { padding-block: clamp(16px,2.2vw,24px); border-top: 1px solid var(--cw-line); }
.cw-pt__row h3 { font-size: 1.04rem; margin-bottom: .3em; }
.cw-pt__row p { color: var(--cw-ink-soft); font-size: .93rem; margin: 0; max-width: 68ch; }
.cw-pt__cards { display: grid; grid-template-columns: repeat(3,1fr); gap: clamp(14px,2vw,20px); }
.cw-pt__card { border: 1px solid var(--cw-line); border-radius: var(--cw-radius-lg);
  background: var(--cw-surface); padding: clamp(18px,2.4vw,24px); }
.cw-pt__n { font-family: var(--cw-mono); font-size: .7rem; letter-spacing: .1em;
  color: var(--cw-accent-ink); margin-bottom: var(--s3); }
.cw-pt__card h3 { font-size: 1rem; margin-bottom: .35em; }
.cw-pt__card p { color: var(--cw-ink-soft); font-size: .88rem; margin: 0; }

/* Two-up on inner pages, which carry four items rather than three. The
   theme layers set repeat(3,1fr) after SHARED, so this has to win on
   specificity, not order. */
.cw-svccards.cw-svccards--2 { grid-template-columns: 1fr 1fr; }

/* questions and answers */
.cw-faq { display: grid; }
.cw-faq__row { padding-block: clamp(18px,2.4vw,26px); border-top: 1px solid var(--cw-line); }
.cw-faq__row h3 { font-family: var(--cw-display); font-size: 1.12rem; margin-bottom: .4em; }
.cw-faq__row p { color: var(--cw-ink-soft); font-size: .93rem; margin: 0; max-width: 70ch; }

/* deliverables */
.cw-checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.cw-checklist li { display: grid; grid-template-columns: 26px 1fr; gap: var(--s2);
  align-items: start; font-size: .96rem; }
.cw-checklist li::before { content: ""; width: 18px; height: 18px; margin-top: 3px;
  border-radius: 50%; background: var(--cw-accent-tint);
  box-shadow: inset 0 0 0 1.5px var(--cw-accent-ink); }
.cw-timing { font-size: 1.02rem; color: var(--cw-ink-soft); max-width: 62ch;
  border-left: 3px solid var(--cw-accent); padding-left: var(--s4); margin: 0 0 var(--s7); }

/* related services */
.cw-related__hd { font-family: var(--cw-mono); font-size: .66rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--cw-ink-faint); margin-bottom: var(--s4); }
.cw-related { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
.cw-related__item { display: grid; gap: 4px; padding: clamp(16px,2vw,20px);
  border: 1px solid var(--cw-line); border-radius: var(--cw-radius-lg);
  background: var(--cw-surface); text-decoration: none; }
.cw-related__item:hover { border-color: var(--cw-primary); }
.cw-related__k { font-family: var(--cw-mono); font-size: .64rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--cw-accent-ink); }
.cw-related__t { font-family: var(--cw-display); font-size: 1.06rem; color: var(--cw-ink); }

/* contact form */
.cw-form__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
.cw-field { display: grid; gap: 6px; }
.cw-field--wide { grid-column: 1 / -1; }
.cw-field > span { font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--cw-ink-faint); }
.cw-field input, .cw-field select, .cw-field textarea {
  font: inherit; font-size: .95rem; color: var(--cw-ink); background: var(--cw-surface);
  border: 1px solid var(--cw-line); border-radius: var(--cw-radius);
  padding: 11px 13px; width: 100%; }
/* 16px on touch, and only on touch. iOS Safari zooms the whole page in when
   it focuses a field whose text is under 16px, and it does not zoom back
   out - so on a phone every tap on this form threw the layout sideways and
   left it there. The desktop size is unchanged. This rule has to live here
   rather than with the other touch overrides, because the theme sheet is
   appended after them and would otherwise win on source order. */
@media (max-width: 1024px), (pointer: coarse) {
  .cw-field input, .cw-field select, .cw-field textarea { font-size: 16px; }
}
.cw-field textarea { resize: vertical; min-height: 120px; }
.cw-field input:focus, .cw-field select:focus, .cw-field textarea:focus {
  outline: 2.5px solid var(--cw-accent-ink); outline-offset: 1px; border-color: transparent; }
.cw-form__foot { display: flex; align-items: center; gap: var(--s5);
  flex-wrap: wrap; margin-top: var(--s5); }
.cw-form__note { font-size: .82rem; color: var(--cw-ink-faint); margin: 0; max-width: 40ch; }
/* The honeypot. Off-screen rather than display:none, which some bots skip. */
.cw-hp { position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; }
/* What the page says after a submission. Rendered server-side from the
   redirect, so it works with JavaScript off and survives a refresh. */
.cw-formstate { margin: 0 0 var(--s5); padding: 13px 16px;
  border-radius: var(--cw-radius); font-size: .95rem; line-height: 1.5;
  border: 1px solid var(--cw-line); }
.cw-formstate--ok { background: var(--cw-primary-tint); border-color: var(--cw-primary);
  color: var(--cw-primary-deep); }
.cw-formstate--bad { background: var(--cw-accent-tint); border-color: var(--cw-accent);
  color: var(--cw-accent-ink); }
.cw-details { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--s5); }
.cw-detail__k { font-family: var(--cw-mono); font-size: .66rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--cw-ink-faint); margin-bottom: var(--s2); }
.cw-detail__v { font-size: .98rem; color: var(--cw-ink); }

@media (max-width: 1000px) { .cw-worklayout--page { grid-template-columns: 1fr; } }
@media (max-width: 860px) {
  .cw-pt__cards, .cw-svccards--2, .cw-related, .cw-details,
  .cw-form__grid { grid-template-columns: 1fr; }
}

/* The footer takes the mark in colour too, so the artwork is the artwork
   everywhere on both demos and there is no knocked-out variant left in the
   running. Measured against the footer ground rather than assumed: the blue
   half comes out at 3.7:1 on Porchlight's ink and 4.3:1 on Watershed's, and
   the orange at 5.3 and 6.1 - which is the same or better than the mark
   already manages on white paper, where the blue is 3.8 and the orange only
   2.7. The knockout files stay in assets/logo/ for anything that needs them
   later; nothing in either stylesheet asks for one now. */

/* ---------- THE PHOTOGRAPHIC BAND ----------------------------------------
   One full-bleed frame in the middle of a page, captioned rather than
   overwritten. Both demos use it; it takes its ground from the tokens, so
   it lands warm on Porchlight and cool on Watershed without a second rule. */
.cw-bandsec { padding: 0; background: var(--cw-ground); }
.cw-band { position: relative; margin: 0; }
.cw-band__img { display: block; width: 100%;
  height: clamp(190px,26vw,330px); object-fit: cover; object-position: center 52%; }
.cw-band figcaption { font-family: var(--cw-mono); font-size: .66rem; letter-spacing: .1em;
  text-transform: uppercase; color: rgba(255,255,255,.6);
  padding-block: var(--s3) var(--s4); }

/* ---------- the home page without its index ------------------------------
   Watershed drops the on-this-page column, so its body runs the full
   measure instead of sitting in the right-hand two thirds. */
.cw-worklayout.cw-worklayout--solo {
  /* doubled on purpose: this has to outrank every responsive rule that
     sets .cw-worklayout's columns, whatever order they land in. */
  grid-template-columns: minmax(0,1fr);
}

/* ---------- the CTA with the aerial behind it ----------------------------
   The one photograph left on Watershed. It is not a hero and not a clip,
   and it is deliberately not another captioned slab - it sits behind the
   closing band with the copy over it.

   The scrim is heavy and directional: nearly solid on the left where the
   heading and paragraph sit, releasing across to the right so the far side
   of the frame stays readable as a photograph. Text over this is checked by
   eye rather than by ratio, the same as the hero, because what is behind it
   is an image and not a colour. */
.cw-cta--photo { position: relative; isolation: isolate; overflow: hidden;
  min-height: clamp(340px, 34vw, 470px); display: grid; align-items: center; }
.cw-cta__media { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
.cw-cta__img { width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: center 58%; }
/* Directional, and no heavier than the copy needs. The first pass ran
   .95 flat across and the photograph may as well not have been there. This
   holds the left third for the heading and releases hard across the
   right, where the pylon line and the field edge actually are. */
.cw-cta--photo::after { content: ""; position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(95deg,
      rgb(var(--cw-scrim) / .93) 0%,
      rgb(var(--cw-scrim) / .84) 30%,
      rgb(var(--cw-scrim) / .42) 62%,
      rgb(var(--cw-scrim) / .20) 100%),
    linear-gradient(180deg,
      rgb(var(--cw-scrim) / .34) 0%,
      rgb(var(--cw-scrim) / 0) 34%,
      rgb(var(--cw-scrim) / 0) 66%,
      rgb(var(--cw-scrim) / .34) 100%); }
@media (max-width: 860px) {
  .cw-cta--photo::after { background: rgb(var(--cw-scrim) / .90); }
}

/* ---------- the photograph, plain ---------------------------------------
   What the captioned plate should have been. Full bleed, a fixed band
   height so it crops rather than dictating the page, and nothing on top of
   it - no caption, no mark, no scrim. The only furniture is a hairline top
   and bottom so it reads as a deliberate break between two sections rather
   than as something that fell into the page. */
.cw-figureband { padding: 0; }
.cw-figureband__inner { position: relative; overflow: hidden;
  border-top: 1px solid var(--cw-line); border-bottom: 1px solid var(--cw-line); }
.cw-figureband__img { display: block; width: 100%;
  height: clamp(210px, 27vw, 360px); object-fit: cover; object-position: center 55%; }

/* ---------- the social row ----------------------------------------------
   Text links, not icon glyphs. Three accounts is not enough to justify an
   icon font or a sprite sheet, and the names read the same at any size. */
.cw-social { list-style: none; margin: var(--s5) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--s4); }
.cw-social a { font-family: var(--cw-mono); font-size: .72rem;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--cw-strong-on-dark); text-decoration: none;
  border-bottom: 1px solid transparent; padding-bottom: 2px; }
.cw-social a:hover { border-bottom-color: currentColor; }

/* ---------- CTA ---------------------------------------------------------- */
.cw-cta { background: var(--cw-ground); color: #fff; }
.cw-cta__grid { display: grid; grid-template-columns: minmax(0,1fr) auto; gap: clamp(26px,4vw,56px); align-items: center; }
.cw-cta h2 { color: #fff; max-width: 19ch; }
.cw-cta p { color: rgba(255,255,255,.76); max-width: 50ch; }
.cw-cta .wp-block-button__link, .cw-cta .cw-btn { background: var(--cw-cta-bg); border-color: var(--cw-cta-bg); color: var(--cw-cta-ink); }
.cw-cta .wp-block-button__link:hover, .cw-cta .cw-btn:hover { filter: brightness(1.08); }
.cw-cta__aside { font-family: var(--cw-mono); font-size: .74rem; color: rgba(255,255,255,.58); margin-top: var(--s4); }

/* ---------- responsive --------------------------------------------------- */
@media (max-width: 1100px) {
  .cw-worklayout { grid-template-columns: 180px minmax(0,1fr); }
}
@media (max-width: 1000px) {
  .cw-worklayout { grid-template-columns: 1fr; }
  .cw-secnav { display: none; }
  .cw-statband, .cw-strip__inner,
  .cw-worklayout .cw-statband { grid-template-columns: 1fr 1fr; }
  .cw-strip__cell:nth-child(3) { border-left: 0; }
  .cw-strip__cell:nth-child(n+3) { border-top: 1px solid var(--cw-line); }
}
@media (max-width: 900px) {
  .cw-bloglayout { grid-template-columns: 1fr; }
  .cw-cats { position: static; }
  .cw-cats ul { display: flex; flex-wrap: wrap; gap: var(--s2); }
  .cw-posts .cw-postcard,
  .cw-posts .cw-postcard:nth-child(even) { grid-template-columns: 1fr; }
  .cw-posts .cw-postcard:nth-child(even) .cw-thumb { order: 0; }
  .cw-posts .cw-thumb { max-width: 240px; }
}
@media (max-width: 900px) {
  /* the foot stacks here, and the centred cue lands on top of the buttons */
  .cw-scrollcue { display: none; }
}
/* short viewports squeeze the stage until the cue overlaps the standfirst */
@media (max-height: 760px) { .cw-scrollcue { display: none; } }
@media (max-width: 720px) { .cw-stage__foot { grid-template-columns: 1fr; } }
@media (max-width: 640px) {
  .cw-doors, .cw-statband, .cw-strip__inner,
  .cw-worklayout .cw-statband { grid-template-columns: 1fr; }
  .cw-strip__cell + .cw-strip__cell { border-left: 0; border-top: 1px solid var(--cw-line); }
  .cw-cta__grid { grid-template-columns: 1fr; }
}

/* ===== WATERSHED ===== */
h1,h2 { font-family: var(--cw-display); font-weight: 600; letter-spacing: -.022em; }
h3 { font-family: var(--cw-body); font-weight: 600; letter-spacing: -.008em; }
/* The hero emphasis. This was a hardcoded mint #8FE0B4 and it survived
   the pass that took the green out, because that pass only changed the
   tokens. It follows the palette now, so it cannot drift again. */
.cw-stage h1 em { font-style: normal; color: var(--cw-accent); }

/* horizontal stepper with a connecting rule */
.cw-stepper { display: grid; grid-template-columns: repeat(4,1fr); gap: clamp(14px,2.2vw,22px); position: relative; }
.cw-stepper::before { content: ""; position: absolute; left: 20px; right: 20px; top: 19px; height: 2px;
  background: linear-gradient(90deg, var(--cw-primary), var(--cw-accent)); opacity: .28; }
.cw-step { position: relative; }
.cw-step__dot { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  background: var(--cw-surface); border: 2px solid var(--cw-primary); color: var(--cw-primary-deep);
  font-family: var(--cw-mono); font-size: .74rem; margin-bottom: var(--s4); position: relative; z-index: 1; }
.cw-step:last-child .cw-step__dot { border-color: var(--cw-accent); color: var(--cw-accent-ink); }
.cw-step h3 { font-size: 1.02rem; margin-bottom: .35em; }
.cw-step p { font-size: .87rem; color: var(--cw-ink-soft); margin: 0; }
/* Four across inside the annotated column leaves ~140px per step and the
   copy runs nine lines. Two-up, with the connecting rule drawn per pair so
   the device survives the reflow. */
.cw-worklayout .cw-stepper { grid-template-columns: 1fr 1fr; row-gap: clamp(26px,3vw,38px); }
.cw-worklayout .cw-stepper::before { display: none; }
.cw-worklayout .cw-step:nth-child(odd)::before { content: ""; position: absolute;
  left: 52px; right: calc(-1 * clamp(14px,2.2vw,22px)); top: 19px; height: 2px;
  background: linear-gradient(90deg, var(--cw-primary), var(--cw-accent)); opacity: .28; }

/* illustrated three-up */
.cw-svccards { display: grid; grid-template-columns: repeat(3,1fr); gap: clamp(16px,2.4vw,24px); }
.cw-svccard { border: 1px solid var(--cw-line); border-radius: var(--cw-radius-lg); background: var(--cw-surface);
  padding: clamp(20px,2.6vw,28px); display: flex; flex-direction: column; position: relative; overflow: hidden; }
.cw-svccard::after { content: ""; position: absolute; inset: auto 0 0 0; height: 3px;
  background: linear-gradient(90deg, var(--cw-primary), var(--cw-accent)); opacity: .5; }
.cw-svccard__art { color: var(--cw-primary); margin-bottom: var(--s4); }
.cw-svccard__n { font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .1em; color: var(--cw-accent-ink); }
.cw-svccard h3 { font-size: 1.06rem; margin: var(--s2) 0 .4em; }
.cw-svccard p { font-size: .89rem; color: var(--cw-ink-soft); margin: 0 0 var(--s5); }
.cw-svccard .cw-textlink { margin-top: auto; }

/* the curve leads, so give it more presence */
.cw-curve { background: linear-gradient(180deg, var(--cw-surface), var(--cw-primary-tint)); }
@media (max-width: 900px) {
  .cw-svccards { grid-template-columns: 1fr; }
  .cw-stepper { grid-template-columns: 1fr 1fr; }
  .cw-stepper::before { display: none; }
}
@media (max-width: 560px) {
  .cw-stepper, .cw-worklayout .cw-stepper { grid-template-columns: 1fr; }
}

/* ===========================================================================
   THE RECORD - Watershed's inner pages
   ===========================================================================
   A separate system from the document pages, not a reskin of them. The
   header bar stays in its normal frosted state here because the masthead is
   pale: .cw-hero is deliberately absent from this markup, since that class
   is what knocks the header and the logo out to white for the photographic
   hero.

   Reading order is masthead -> plate -> colour break -> banded sections,
   against the document system's photo-hero -> colour break -> indexed
   column. */

/* ---- masthead: a document header, set on paper ---- */
.cw-mastband {
  background: linear-gradient(180deg, var(--cw-primary-tint) 0%, var(--cw-paper) 76%);
  border-bottom: 1px solid var(--cw-line);
  padding-block: clamp(34px,5vw,64px) clamp(24px,3.4vw,38px);
}
/* Two columns: the words, and the page's drawing. The masthead used to be
   a headline with half a screen of empty paper beside it. The drawing is
   decoration and carries no information the text does not, so it is hidden
   from assistive tech only where it would repeat - it keeps its alt text. */
.cw-mast__grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,34%);
  gap: clamp(24px,4vw,56px); align-items: center; }
.cw-mast__body { min-width: 0; }
.cw-mast__art { min-width: 0; }
.cw-mast__art img { display: block; width: 100%; height: auto; }
/* A portrait is not a diagram: it wants a frame, a crop and a size of its
   own, or it sits in the masthead looking like a stock photo dropped in. */
.cw-mast__art--portrait { justify-self: end; max-width: 320px; width: 100%; }
.cw-mast__art--portrait { margin: 0; }
.cw-mast__art--portrait figcaption { font-family: var(--cw-mono);
  font-size: .72rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--cw-ink-faint); margin-top: var(--s3); text-align: center; }
.cw-mast__art--portrait img { border-radius: var(--cw-radius-lg);
  border: 1px solid var(--cw-line); background: var(--cw-surface);
  box-shadow: var(--cw-shadow); aspect-ratio: 4 / 5; object-fit: cover;
  object-position: 50% 12%; }

@media (max-width: 860px) {
  /* Stacked, the drawing above the headline would push the page title below
     the fold on a phone. It goes under the standfirst instead, at half size. */
  .cw-mast__grid { grid-template-columns: 1fr; gap: var(--s5); }
  .cw-mast__art { max-width: 260px; }
}

.cw-mast__ref { font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--cw-primary-deep);
  display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s5); }
.cw-mast__ref::after { content: ""; flex: 1; height: 2px;
  background: linear-gradient(90deg, var(--cw-accent), var(--cw-line) 42%); }
.cw-mastband h1 { font-size: clamp(2.05rem,4.4vw,3.2rem); line-height: 1.04;
  letter-spacing: -.02em; color: var(--cw-ink); max-width: 16ch; margin: 0 0 var(--s5); }
.cw-mast__sub { color: var(--cw-ink-soft); max-width: 52ch; margin: 0;
  font-size: clamp(1rem,1.5vw,1.14rem); line-height: 1.6; }
.cw-mast__toc { list-style: none; margin: 0; padding: var(--s5) 0 0;
  border-top: 1px solid var(--cw-line);
  display: flex; flex-wrap: wrap; gap: var(--s3) clamp(20px,3vw,40px); }
.cw-mast__toc li { display: flex; align-items: baseline; gap: var(--s2);
  font-size: .93rem; color: var(--cw-ink-soft); }
.cw-mast__toc span { font-family: var(--cw-mono); font-size: .68rem;
  letter-spacing: .08em; color: var(--cw-accent-ink); }

/* ---- the plate: the photograph as a figure, not as a backdrop ---- */
.cw-plateband { padding: 0; background: var(--cw-ground); }
.cw-plate { position: relative; margin: 0; }
.cw-plate__img { display: block; width: 100%;
  height: clamp(200px,30vw,380px); object-fit: cover; object-position: center 46%; }
.cw-plate__mark { position: absolute; right: clamp(10px,3vw,46px); top: 46%;
  transform: translateY(-50%); width: clamp(112px,15vw,200px);
  opacity: .22; pointer-events: none; }
.cw-plate__mark svg { width: 100%; height: auto; display: block; }
.cw-plate figcaption { font-family: var(--cw-mono); font-size: .66rem; letter-spacing: .1em;
  text-transform: uppercase; color: rgba(255,255,255,.6);
  padding-block: var(--s3) var(--s4); }

/* ---- the colour break, reversed: claim large left, drawing small right ---- */
.cw-rshow { background: var(--cw-sunk);
  border-top: 1px solid var(--cw-line); border-bottom: 1px solid var(--cw-line);
  padding-block: clamp(42px,6vw,78px); }
.cw-rshow__grid { display: grid; grid-template-columns: minmax(0,1.15fr) minmax(0,.85fr);
  gap: clamp(28px,5vw,64px); align-items: center; }
.cw-rshow__kicker { font-family: var(--cw-mono); font-size: .68rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--cw-accent-ink); margin-bottom: var(--s3); }
.cw-rshow h2 { font-size: clamp(1.8rem,3.3vw,2.6rem); margin: 0 0 .45em; max-width: 17ch; }
.cw-rshow__body > p { color: var(--cw-ink-soft); max-width: 56ch; margin: 0 0 var(--s6); }
.cw-rshow__list { list-style: none; margin: 0; padding: 0; counter-reset: rs; }
.cw-rshow__list li { counter-increment: rs; display: grid; grid-template-columns: 40px minmax(0,1fr);
  gap: var(--s3); padding: var(--s4) 0; border-top: 1px solid var(--cw-line);
  color: var(--cw-ink-soft); font-size: .95rem; }
.cw-rshow__list li:last-child { border-bottom: 1px solid var(--cw-line); }
.cw-rshow__list li::before { content: counter(rs,decimal-leading-zero);
  font-family: var(--cw-mono); font-size: .7rem; color: var(--cw-accent-ink); }
.cw-rshow__art img { width: 100%; height: auto; display: block;
  border-radius: var(--cw-radius-lg); border: 1px solid var(--cw-line);
  background: var(--cw-surface); box-shadow: var(--cw-shadow); }

/* ---- banded sections, full width, no index column ---- */
.cw-record { counter-reset: rsec; }
.cw-rband { padding-block: clamp(38px,5.2vw,70px); }
.cw-rband.is-tinted { background: var(--cw-sunk);
  border-top: 1px solid var(--cw-line); border-bottom: 1px solid var(--cw-line); }
.cw-rsec { counter-increment: rsec; display: grid;
  grid-template-columns: minmax(0,24ch) minmax(0,1fr);
  gap: clamp(22px,4vw,58px); align-items: start; scroll-margin-top: 96px; }
.cw-rsec__hd { position: sticky; top: 100px; }
/* No number over the section heading. It read as the same "01 Conflict
   assessment" tag as the contents list that used to sit under the page
   title, so taking one and leaving the other would have been half a job.
   To put them back, restore the ::before rule with
   content: counter(rsec,decimal-leading-zero). */
.cw-rsec__hd h2 { font-size: clamp(1.36rem,2.3vw,1.86rem); line-height: 1.12; margin: 0; }
.cw-rsec__body > .cw-block__intro { color: var(--cw-ink-soft); max-width: 64ch;
  margin: 0 0 var(--s6); }

/* A pull quote inside a record section. Set on the display face at a size
   between the section heading and the body, with a rule down the left
   rather than quotation marks - the surrounding text is already first
   person, so the marks would be doing no work. */
.cw-pullquote { margin: var(--s7) 0 0; padding: 0 0 0 clamp(18px,2.4vw,28px);
  border-left: 3px solid var(--cw-accent); max-width: 40ch; }
.cw-pullquote p { font-family: var(--cw-display); font-weight: 600;
  font-size: clamp(1.18rem,2vw,1.56rem); line-height: 1.34;
  color: var(--cw-ink); margin: 0; }

/* Running prose. Three of the pages are now mostly writing, and without a
   measure of their own the paragraphs inherited the full column width,
   which is about twice what is readable at this size.

   The opening paragraph of each section takes the strong colour and the
   rest take the body colour. That is the ordinary lede-then-body device,
   and it is also what keeps the 50/50 split honest on pages that are nine
   sections of solid paragraphs - an all-body page reads 84% one colour. */
.cw-rsec__body > p { max-width: 64ch; margin: 0 0 var(--s5); }
.cw-rsec__body > p:last-child { margin-bottom: 0; }
.cw-rsec__body > p:first-of-type { color: var(--cw-ink); font-size: 1.04rem; }

/* ---- the ledger: what the document system draws as cards ---- */
.cw-ledger { list-style: none; margin: 0; padding: 0; counter-reset: lg; }
.cw-ledger li { counter-increment: lg; display: grid;
  grid-template-columns: 38px minmax(0,19ch) minmax(0,1fr);
  gap: var(--s4); padding: var(--s5) 0; align-items: baseline;
  border-top: 1px solid var(--cw-line); }
.cw-ledger li:last-child { border-bottom: 1px solid var(--cw-line); }
.cw-ledger li::before { content: counter(lg,decimal-leading-zero);
  font-family: var(--cw-mono); font-size: .72rem; color: var(--cw-accent-ink); }
.cw-ledger__k { font-weight: 600; color: var(--cw-ink); font-size: 1.02rem; line-height: 1.35; }
.cw-ledger__v { color: var(--cw-ink-soft); font-size: .95rem; line-height: 1.6; }

/* ---- spec rows: the drawings live here rather than beside the headings ---- */
.cw-spec { list-style: none; margin: 0; padding: 0; counter-reset: sp; }
.cw-spec li { counter-increment: sp; display: grid;
  grid-template-columns: 82px minmax(0,1fr); gap: clamp(16px,2.4vw,34px);
  padding: var(--s6) 0; align-items: start; border-top: 1px solid var(--cw-line); }
.cw-spec li:last-child { border-bottom: 1px solid var(--cw-line); }
.cw-spec__art { width: 82px; }
.cw-spec__art svg { width: 100%; height: auto; display: block; }
.cw-spec__body h3 { font-size: 1.12rem; margin: 0 0 .35em; }
.cw-spec__body h3::before { content: counter(sp,decimal-leading-zero) " \2014 ";
  font-family: var(--cw-mono); font-size: .7rem; letter-spacing: .1em;
  color: var(--cw-accent-ink); }
.cw-spec__body p { color: var(--cw-ink-soft); margin: 0; max-width: 68ch; font-size: .95rem; }

@media (max-width: 900px) {
  .cw-rshow__grid { grid-template-columns: 1fr; }
  .cw-rshow__art { order: -1; }
  .cw-rsec { grid-template-columns: 1fr; gap: var(--s5); }
  .cw-rsec__hd { position: static; }
  .cw-ledger li { grid-template-columns: 34px minmax(0,1fr); row-gap: var(--s2); }
  .cw-ledger__k, .cw-ledger__v { grid-column: 2; }
  .cw-spec li { grid-template-columns: 58px minmax(0,1fr); }
  .cw-spec__art { width: 58px; }
}


/* STRONG — headings, standfirsts, the claim, the service copy, terms. */
.cw-showcase__body > p,
.cw-showcase__list li,
.cw-rshow__body > p,
.cw-rshow__list li,
.cw-svc__row p,
.cw-svccard p,
.cw-spec__body p,
.cw-phil__pull,
.cw-timing,
.cw-ledger__k,
.cw-detail__v,
.cw-postcard__excerpt { color: var(--cw-ink); }

/* BODY — read at length or in passing. */
.cw-faq__row p,
.cw-pt__row p,
.cw-pt__card p,
.cw-mast__sub,
.cw-checklist li,
.cw-rail__step p,
.cw-step p,
.cw-block > p,
.cw-rsec__body > p,
.cw-detail__k,
.cw-ledger__v,
.cw-strip__l,
.cw-curve figcaption,
.cw-postcard__meta,
.cw-ref { color: var(--cw-ink-soft); }

/* The stat band used to be a saturated fill, and its two parts had to
   inherit the fill's foreground to stay legible on it. It is cards on the
   page ground now, so they take the split like everything else and the
   override would only undo the hierarchy. */

/* ---------- the dark bands ----------------------------------------------
   The CTA and the footer were white, which is a third colour and broke the
   split. The text-weight tokens are too dark to sit on --cw-ground, so
   these take the bright pair instead: --cw-primary for strong, and
   --cw-on-dark, which is the body colour lifted to clear AA on that ground. */
.cw-cta, .cw-footer { color: var(--cw-on-dark); }
.cw-cta h2, .cw-cta h3, .cw-footer h2, .cw-footer h3,
.cw-footer__hd { color: var(--cw-strong-on-dark); }
.cw-cta p, .cw-cta__aside, .cw-footer p, .cw-footer__blurb,
.cw-footer__col a, .cw-footer__legal, .cw-footer__legal span,
.cw-band figcaption, .cw-plate figcaption { color: var(--cw-on-dark); }
.cw-footer__col a:hover { color: var(--cw-strong-on-dark); }

/* The hero headline and standfirst sit over photography, where a computed
   ratio is meaningless and white is simply the legible choice. They are the
   one deliberate exception. */

