/* ============================================================
   4PHASE CONSULTING

   The visual system is the one built for the Turning Over site —
   its tokens, its spacing rhythm, its component behaviour and its
   restraint — carrying the 4Phase palette and the three 4Phase
   typefaces. Two rules survive the change of brand because they are
   about behaviour rather than looks:

   - One primary action per screen. Here that is the blue button,
     and it says "start a conversation".
   - Nothing is carried by colour alone. A phase is a number and a
     word before it is a lit bar.

   Both themes are first class. Every colour is defined on :root and
   redefined once, together, in the dark block — never a value that
   exists in only one scheme.
   ============================================================ */

/* ---------- fonts: self-hosted ------------------------------------
   Nothing on this site is fetched from a third party, fonts
   included. Latin and latin-extended subsets of the variable files,
   so every weight in the system costs one download per subset. */
@font-face{font-family:"Lora";font-style:normal;font-weight:400 700;font-display:swap;
  src:url("/assets/fonts/lora-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Lora";font-style:normal;font-weight:400 700;font-display:swap;
  src:url("/assets/fonts/lora-latin-ext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Inter Tight";font-style:normal;font-weight:400 500;font-display:swap;
  src:url("/assets/fonts/inter-tight-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Inter Tight";font-style:normal;font-weight:400 500;font-display:swap;
  src:url("/assets/fonts/inter-tight-latin-ext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
/* Fragment Mono ships one weight. The 400 file answers to 500 as well,
   so the label style can ask for medium without the browser faking a
   bold that would thicken the tracked caps. */
@font-face{font-family:"Fragment Mono";font-style:normal;font-weight:400 500;font-display:swap;
  src:url("/assets/fonts/fragment-mono-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Fragment Mono";font-style:normal;font-weight:400 500;font-display:swap;
  src:url("/assets/fonts/fragment-mono-latin-ext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

/* ============================================================
   TOKENS
   ============================================================ */
:root{
  color-scheme:light dark;

  /* ---- palette ----
     The blue is the one in the mark. The navy is the deck's ground,
     and it is where the call to action and the footer live. */
  --accent:#1d5eff;
  --accent-strong:#1b4fd8;      /* the same blue, darkened for hover and for link text */
  --accent-quiet:rgba(29,94,255,.08);
  /* Two colours beside the blue, each with one job. Blue is the work,
     pink is your decision, cyan is what we measure.

     Pink marks what you get and what you decide — never a label on a
     section. Four places, and they are the whole list:

       - the decision panel on a phase page, where an engagement can end
       - the quotes the proposition rests on, all of which are about
         stopping
       - what a level includes: the chips on /engagement/
       - the word "required" on a form, and every hover state, which is
         the one moment a control can carry colour without carrying
         noise

     An eyebrow is a label, not a decision, so it stays quiet. The text
     form is deepened because the bright pink as type on a light ground
     is 3.1:1.

     --figure is the colour a measurement takes — the hero figures and
     the step numerals. At 40px and up a numeral is large text, held
     to 3:1 rather than 4.5:1, so it can run lighter than the blue the
     rest of the page uses. It takes the lightest blue each ground
     allows: #3d78ff on the page and on a card, and --accent-light on
     every dark ground, where a light blue is the only one that does
     not sink into the navy. The one place that does not hold is the
     11px counter in the page contents, which is small text and takes
     --accent-strong instead. */
  --accent-2:#fa4a6e;
  --accent-2-text:#c2143f;         /* 5.5:1 on the page ground */
  --accent-2-strong:#d81b48;       /* a fill that carries a white label at 5:1 */
  --accent-2-quiet:rgba(250,74,110,.10);
  --accent-light:#7fb2ff;          /* the light blue a numeral takes on a dark ground */
  --figure:#3d78ff;                /* 3.6:1 on the page, 3.3:1 on a card — large text and graphics */
  --pm-lit:var(--accent);
  --navy:#051835;
  --navy-lift:#0b2144;           /* the navy one step up, for a panel on the dark band */
  --sky:#a8b3cc;                 /* the quiet blue-grey used on navy */

  --bg:#f4f4f6;
  --surface:#ffffff;
  --surface-sunk:#eceef3;        /* a recessed panel on the page ground */
  --inverse-bg:#051835;

  --ink:#121529;
  --ink-muted:#4a5270;           /* 7.0:1 on the page ground */
  --ink-reverse:#eef1f7;
  --ink-reverse-muted:#a8b3cc;   /* 8.4:1 on the navy band */

  --rule:rgba(18,21,41,.13);
  --rule-strong:rgba(18,21,41,.22);
  --rule-reverse:rgba(238,241,247,.20);
  --rule-input:#6f7691;          /* 3.6:1 on white — a field boundary is a non-text component */
  --veil:rgba(18,21,41,.05);     /* the tint that stands in for a card on the page ground */
  --veil-reverse:rgba(238,241,247,.06);

  --error-ink:#b3261e;
  --wash-back:#f4f4f6;           /* the ground the hero shader paints onto */

  /* The arrow on every call to action. A mask rather than a
     character: the subset fonts carry no U+2192, so a literal arrow
     would fall back to whatever the operating system offers and
     change shape from machine to machine. */
  --icon-arrow:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 8h11M9 4l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* ---- typography ----
     Fraunces for display, DM Sans for body, DM Mono for labels and
     figures. The same three as the 4Phase report system, so a report
     and the website read as one brand. */
  --font-display:"Lora",Georgia,"Iowan Old Style",serif;
  --font-body:"Inter Tight",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-mono:"Fragment Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;
  /* Labels are words, and words on this site are set in the body face.
     A mono eyebrow over every section is a look rather than a reason —
     the mono stays where it does actual work, on the figures in the
     pricing table, where the columns have to line up. */
  --font-label:var(--font-body);

  --text-caption:12.5px;  --leading-caption:1.2;   --tracking-caption:.04em;
  --text-body-sm:14px;    --leading-body-sm:1.43;  --tracking-body-sm:.018em;
  --text-body:16px;       --leading-body:1.5;
  --text-body-lg:24px;    --leading-body-lg:1.17;
  --text-lede:19px;       --leading-lede:1.5;
  --text-heading-sm:24px; --leading-heading-sm:1.17; --tracking-heading-sm:-.063em;
  --text-heading:32px;    --leading-heading:1.13;    --tracking-heading:-.023em;
  --text-heading-lg:40px; --leading-heading-lg:1.1;  --tracking-heading-lg:-.05em;
  --text-display:64px;    --leading-display:1.06;    --tracking-display:-.047em;

  --weight-light:300;
  --weight-regular:400;
  --weight-medium:500;

  /* ---- spacing ---- */
  --spacing-4:4px;   --spacing-6:6px;   --spacing-8:8px;   --spacing-12:12px;
  --spacing-16:16px; --spacing-20:20px; --spacing-24:24px; --spacing-32:32px;
  --spacing-40:40px; --spacing-48:48px; --spacing-64:64px; --spacing-80:80px;
  --spacing-120:120px; --spacing-160:160px;

  /* ---- layout ----
     The rhythm is the brand signal: sections breathe at 120px and
     step down through the scale at each breakpoint, never below
     48px. --measure holds prose to a reading length; headings get a
     much tighter one of their own, or a section heading sets as one
     enormous line while the standfirst under it wraps at 44ch and
     the two stop looking related. */
  --page-max-width:1440px;
  --page-padding:var(--spacing-64);
  --section-gap:120px;
  --card-padding:28px;
  --element-gap:16px;
  --header-h:80px;
  --measure:66ch;
  --measure-heading:22ch;

  /* ---- radius ----
     The same 4px scale the spacing runs on, one step up at every size:
     12 for the small things, 16 for a card, 24 for a panel. Controls
     are fully round — a button is the one shape on the page that should
     read as pressable at a glance. */
  --radius-4:4px;  --radius-8:8px;   --radius-12:12px;
  --radius-16:16px; --radius-20:20px; --radius-24:24px;
  --radius-circle:9999px;
  --radius-small:var(--radius-12);
  --radius-cards:var(--radius-16);
  --radius-large:var(--radius-24);

  /* ---- shadow ---- */
  --shadow-nav:0 4px 18px -6px rgba(5,24,53,.16);
  --shadow-card:0 18px 40px -28px rgba(5,24,53,.45);

  /* ---- motion ----
     Linear is right for a colour fade and wrong for anything that
     moves, so the things that travel get an easing of their own. */
  --duration-card-hover:200ms; --easing-card-hover:ease;
  --duration-ui:280ms;         --easing-ui:linear;
  --duration-reveal:340ms;     --easing-reveal:cubic-bezier(.32,.72,0,1);
}

@media (prefers-color-scheme:dark){
  :root{
    /* The same blue as the light theme, not a tint of it. A pale
       accent on a dark ground reads as washed out, and the mark's blue
       is legible here: 3.8:1 on the page ground, which carries a
       button fill, a 40px numeral or a drawn arc, while small link
       text takes --accent-strong below at 5.6:1. */
    --accent:#1d5eff;
    --accent-strong:#4d84ff;
    --accent-quiet:rgba(29,94,255,.14);
    --accent-2:#fa4a6e;
    --accent-2-text:#fa4a6e;       /* 5.8:1 on the dark page ground */
    --accent-2-strong:#d81b48;
    --accent-2-quiet:rgba(250,74,110,.12);
    --navy:#0b1526;
    --navy-lift:#132241;
    --sky:#9aa6c2;
    --figure:var(--accent-light);  /* 8.6:1 on the dark page ground */

    --bg:#080d18;
    --surface:#0e1626;
    --surface-sunk:#0b1220;
    --inverse-bg:#0d1a30;

    --ink:#eef1f7;
    --ink-muted:#9aa6c2;
    --ink-reverse:#eef1f7;
    --ink-reverse-muted:#9aa6c2;

    --rule:rgba(238,241,247,.14);
    --rule-strong:rgba(238,241,247,.24);
    --rule-reverse:rgba(238,241,247,.16);
    --rule-input:#7b86a3;
    --veil:rgba(238,241,247,.05);
    --veil-reverse:rgba(238,241,247,.05);

    --error-ink:#ff9b93;
    --wash-back:#080d18;
    /* On a dark page the closing band cannot be the page ground with
       a different name, so it steps up rather than down and takes a
       hairline to mark the join. */
    --shadow-nav:0 4px 18px -6px rgba(0,0,0,.6);
    --shadow-card:0 18px 40px -28px rgba(0,0,0,.8);
  }
}

/* ============================================================
   BASE
   ============================================================ */
*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none !important}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
  *::details-content{transition-duration:.01ms !important}
}
::selection{background:var(--navy);color:#eef1f7}

body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:var(--text-body);
  line-height:var(--leading-body);
  font-weight:var(--weight-regular);
  -webkit-font-smoothing:antialiased;
  overflow-wrap:break-word;
}

/* Fraunces at 400 for every heading, never bold. The optical size
   axis is set high so large text keeps the fine, drawn contrast the
   report system uses, and the negative tracking is what stops it
   feeling loose. */
h1,h2,h3,h4,h5,h6{
  font-family:var(--font-display);
  font-weight:var(--weight-regular);
  color:var(--ink);
  text-wrap:balance;
  overflow-wrap:break-word;
  margin:0 0 var(--spacing-16);
}
h1{font-size:clamp(var(--text-heading),1.9rem + 2.2vw,var(--text-display));line-height:var(--leading-display);letter-spacing:var(--tracking-display)}
h2{font-size:clamp(26px,1.5rem + 1vw,var(--text-heading-lg));line-height:var(--leading-heading-lg);letter-spacing:var(--tracking-heading-lg)}
h3{font-size:var(--text-heading-sm);line-height:var(--leading-heading-sm);letter-spacing:var(--tracking-heading-sm)}
h4,h5,h6{font-size:var(--text-body-lg);line-height:var(--leading-body-lg);letter-spacing:-.015em}
/* A headline is one voice the whole way through. The phrase the
   sentence turns on is doing that work with the words; setting it in
   italic blue as well says it twice and reads as decoration. */
h1 em,h2 em,h3 em{font-style:normal;font-weight:inherit;color:inherit}

p{margin:0 0 var(--spacing-20)}
strong,b{font-weight:var(--weight-medium)}
a{color:var(--ink);text-underline-offset:3px;text-decoration-thickness:1px;
  transition:color var(--duration-ui) var(--easing-ui)}
a:hover{color:var(--accent-2-text)}
img,svg{max-width:100%}
hr{border:0;border-top:1px solid var(--rule);margin:var(--spacing-48) 0}
:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:var(--radius-small)}

/* ============================================================
   LAYOUT
   ============================================================ */
.wrap{max-width:var(--page-max-width);margin:0 auto;padding:0 var(--page-padding)}
.narrow{max-width:var(--measure)}
.wide{max-width:820px}
/* A stack of questions reads as one column rather than as a column
   set against an empty right half, so it sits on the page centre
   with its heading over the top of it. */
.faqs{max-width:820px;margin-inline:auto}
.section-head--center{margin-inline:auto;text-align:center}
.section-head--center h2{margin-inline:auto}
.visually-hidden{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}
.skip{position:absolute;left:-9999px;top:0;background:var(--navy);color:#eef1f7;
  padding:var(--spacing-12) var(--spacing-20);z-index:200;border-radius:0 0 var(--radius-small) 0;text-decoration:none}
.skip:focus{left:0;top:0}

/* Sections stack with no decorative dividers — a 1px rule in the ink
   tint is the only thing that ever marks a break. */
.section{padding:var(--section-gap) 0}
.section--tight{padding:var(--spacing-80) 0}
.section--flush{padding-top:0}
/* A lifted band: the page ground steps up to the card surface, so a
   run of sections has a light and a lighter, and the eye gets a
   join without a line being drawn. */
.section.lift{background:var(--surface)}
/* The navy band. Two in a row are one dark block as far as the eye
   is concerned, so the join keeps one gap rather than two. */
.section.inverse{background:var(--inverse-bg);color:var(--ink-reverse);--figure:var(--accent-light)}
.section.inverse + .section.inverse{padding-top:var(--spacing-40)}
.section.inverse:last-child{padding-bottom:var(--spacing-80)}
.section.inverse h1,.section.inverse h2,.section.inverse h3,.section.inverse h4{color:var(--ink-reverse)}
.section.inverse a{color:var(--ink-reverse)}
.section.inverse a:hover{color:var(--accent-2-text)}
.section.inverse .lede,.section.inverse .muted{color:var(--ink-reverse-muted)}
.section.inverse .eyebrow{color:var(--sky)}
.section.inverse :focus-visible{outline-color:var(--accent)}
.section.inverse hr{border-color:var(--rule-reverse)}

/* A page head. Element-qualified where it needs to outrank a band
   modifier, because the failure is silent: 80px onto 120px reads as
   a hole, and 0 reads as a collision. */
.pagehead{padding-top:var(--spacing-80)}
.pagehead + section.section{padding-top:var(--spacing-48)}
.wash + section.section{padding-top:var(--spacing-80)}

.section-head{margin-bottom:var(--spacing-48);max-width:var(--measure)}
.section-head h2{max-width:var(--measure-heading)}
.section-head > :last-child{margin-bottom:0}

/* A light panel lifted inside a dark surround — the composition the
   call to action band is built on. */
.lifted{background:var(--surface);color:var(--ink);border-radius:var(--radius-large);padding:var(--spacing-64)}
.lifted h2,.lifted h3,.lifted p{color:var(--ink)}
.lifted .eyebrow,.lifted .muted{color:var(--ink-muted)}
.lifted a{color:var(--ink)}
.lifted :focus-visible{outline-color:var(--accent)}
.lifted > :last-child{margin-bottom:0}

.grid{display:grid;gap:var(--element-gap)}
.grid.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
.grid.gphase{gap:var(--spacing-20)}
/* Two columns with air between them, for a heading beside a block of
   prose rather than for cards. The text column takes a measure of
   its own so the line length does not follow the window. */
.split{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:var(--spacing-80);align-items:start}
.split > div:not(.card):not(.panel){max-width:38rem}
/* A quote pinned to the top of a tall column leaves a half-page of
   nothing under it. Centred, it sits against the middle of the
   argument it is quoting. */
.split--middle{align-items:center}
.centred{text-align:center}

/* ============================================================
   TYPE ROLES
   ============================================================ */
/* DM Mono, all caps, tracked. Category labels and functional
   metadata only, never prose. */
.eyebrow,.label{
  font-family:var(--font-label);font-weight:var(--weight-medium);
  font-size:var(--text-caption);line-height:var(--leading-caption);
  letter-spacing:var(--tracking-caption);
  color:var(--ink-muted);margin:0 0 var(--spacing-20);display:block}
.lede{font-size:var(--text-lede);line-height:var(--leading-lede);color:var(--ink);max-width:46ch}
.small{font-size:var(--text-body-sm);line-height:var(--leading-body-sm)}
.muted{color:var(--ink-muted)}

/* ============================================================
   HEADER
   A bar that floats over the page, takes the page ground and a soft
   shadow once anything has scrolled, and tucks away going down.
   ============================================================ */
.site-header{position:sticky;top:0;z-index:100;background:transparent;
  transition:background var(--duration-ui) var(--easing-ui),
             box-shadow var(--duration-ui) var(--easing-ui),
             transform var(--duration-ui) var(--easing-ui)}
.site-header.is-scrolled{background:var(--bg);box-shadow:var(--shadow-nav)}
/* Out of the way going down, back on the way up. It returns whenever
   focus enters it, so a keyboard user is never tabbing into
   something parked off screen. */
.site-header.is-tucked{transform:translateY(-100%)}
/* Without JavaScript there is no scroll listener, so the bar simply
   carries its ground from the start rather than floating over the
   text it would otherwise overlap. */
html:not(.js) .site-header{background:var(--bg);border-bottom:1px solid var(--rule)}
.header-inner{display:flex;align-items:center;justify-content:space-between;
  gap:var(--spacing-24);min-height:var(--header-h)}

.brand{display:inline-flex;align-items:center;min-height:44px;
  text-decoration:none;color:var(--ink);flex-shrink:0;
  transition:opacity var(--duration-ui) var(--easing-ui)}
.brand:hover{opacity:.72}
/* The wordmark carries its own colour: blue arcs, ink lettering, and a
   second file with the lettering reversed for the navy footer and the
   dark theme. Width comes from the artwork's own ratio, so the header
   reserves its space before the file has loaded. */
.brand__logo{display:block;width:auto;height:34px}
.site-footer .brand__logo{height:44px}
@media (prefers-color-scheme:dark){
  /* The light-ground artwork sets its lettering in near-black, which
     is invisible on the dark page. The header takes the reversed file
     the footer already uses. */
  .site-header .brand__logo{content:url("/assets/img/logo-inverse.svg")}
}

/* The phase indicator: the mark with one arc lit. */
.phasemark{display:block;width:22px;height:22px;flex:none;color:var(--ink-muted)}
/* On a phase card the mark is the card's subject, not an annotation on
   it, so it is set at heading scale. */
.ph-head .phasemark{width:36px;height:36px}
.phasemark--1{--pm-1:var(--pm-lit);--pm-1-o:1}
.phasemark--2{--pm-2:var(--pm-lit);--pm-2-o:1}
.phasemark--3{--pm-3:var(--pm-lit);--pm-3-o:1}
.phasemark--4{--pm-4:var(--pm-lit);--pm-4-o:1}
.section.inverse .phasemark,.ph-head .phasemark{color:var(--ink-reverse-muted)}

.site-nav{margin-left:auto}
.site-nav ul{display:flex;align-items:center;gap:var(--spacing-4);list-style:none;margin:0;padding:0;flex-wrap:wrap}
.site-nav a{font-size:var(--text-body-sm);color:var(--ink);text-decoration:none;
  padding:var(--spacing-8) var(--spacing-12);border-radius:var(--radius-small);
  display:inline-flex;align-items:center;min-height:44px;
  transition:background var(--duration-ui) var(--easing-ui),color var(--duration-ui) var(--easing-ui)}
.site-nav a:hover{background:var(--veil);color:var(--accent-2-text)}
.site-nav a[aria-current="page"]{background:var(--veil);font-weight:var(--weight-medium)}
/* The one action in the bar. It restates its colours because the nav
   link rule above is the more specific of the two. */
.site-nav .nav-cta,.site-nav .nav-cta:hover{background:var(--accent);color:#fff;font-weight:var(--weight-medium);
  margin-left:var(--spacing-8);padding-inline:var(--spacing-20);border-radius:var(--radius-circle)}
.site-nav .nav-cta:hover{background:var(--accent-2-strong)}

.navtoggle{display:none;align-items:center;justify-content:center;background:transparent;
  border:1px solid var(--rule-strong);border-radius:var(--radius-small);
  width:44px;height:44px;padding:0;cursor:pointer;color:var(--ink);
  transition:background var(--duration-ui) var(--easing-ui)}
/* Guarded: on a touch screen :hover latches after a tap, so the
   button would keep the hover fill while the menu is open and read
   as disabled. The open state is styled deliberately instead. */
@media (hover:hover){.navtoggle:hover{background:var(--veil)}}
.navtoggle[aria-expanded="true"]{background:var(--veil);border-color:var(--ink)}
.navtoggle__bars{width:16px;height:1px;background:currentColor;
  box-shadow:0 -5px 0 currentColor,0 5px 0 currentColor;display:block}

/* ============================================================
   BUTTONS AND LINKS
   ============================================================ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-8);
  font-family:var(--font-body);font-weight:var(--weight-medium);
  font-size:var(--text-body);line-height:1.2;
  padding:var(--spacing-16) var(--spacing-32);
  border-radius:var(--radius-circle);border:1px solid transparent;
  min-height:52px;text-decoration:none;cursor:pointer;
  transition:background var(--duration-ui) var(--easing-ui),
             border-color var(--duration-ui) var(--easing-ui),
             transform var(--duration-ui) var(--easing-ui),
             color var(--duration-ui) var(--easing-ui)}
/* Every call to action carries the same arrow, so the shape of the
   thing says it goes somewhere before the label has been read. It
   slides on hover: the movement is the affordance. */
.btn::after{content:"";flex:none;width:1.05em;height:1.05em;margin-left:var(--spacing-4);
  background:currentColor;
  -webkit-mask:var(--icon-arrow) center/contain no-repeat;
          mask:var(--icon-arrow) center/contain no-repeat;
  transition:transform var(--duration-ui) var(--easing-ui)}
@media (hover:hover){.btn:hover::after{transform:translateX(4px)}}
.site-nav .btn::after{content:none}
.btn-primary{background:var(--accent);color:#fff;border-color:var(--accent)}
.btn-primary:hover{background:var(--accent-2-strong);border-color:var(--accent-2-strong);color:#fff}
@media (hover:hover){.btn-primary:hover{transform:translateY(-1px)}}
.btn-primary:active{transform:translateY(0)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--rule-strong)}
.btn-ghost:hover{background:var(--veil);color:var(--accent-2-text);border-color:var(--accent-2)}
.btn-sm{padding:var(--spacing-8) var(--spacing-16);font-size:var(--text-body-sm);min-height:44px}
/* Each variant restates its ink on the navy band, where the reversed
   link colour is otherwise the more specific rule. */
.section.inverse .btn-primary,.section.inverse .btn-primary:hover{color:#fff}
.section.inverse .btn-ghost{color:var(--ink-reverse);border-color:var(--rule-reverse)}
.section.inverse .btn-ghost:hover{background:rgba(238,241,247,.10);color:var(--accent-2);border-color:var(--accent-2)}
.btn-row{display:flex;gap:var(--element-gap);flex-wrap:wrap;align-items:center;margin:var(--spacing-32) 0 0}
.btn-row:first-child{margin-top:0}

/* Tertiary: an underlined link, never a third button. */
.arrow-link{
  font-family:var(--font-body);font-weight:var(--weight-medium);
  font-size:var(--text-body-sm);color:var(--accent-strong);
  display:inline-flex;align-items:center;gap:var(--spacing-8);min-height:44px;
  text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1px}
.arrow-link::after{content:"";width:1em;height:1em;background:currentColor;
  -webkit-mask:var(--icon-arrow) center/contain no-repeat;
          mask:var(--icon-arrow) center/contain no-repeat;
  transition:transform var(--duration-ui) var(--easing-ui)}
.arrow-link:hover{color:var(--accent-2-text)}
@media (hover:hover){.arrow-link:hover::after{transform:translateX(4px)}}
.section.inverse .arrow-link{color:var(--ink-reverse)}
.section.inverse .arrow-link:hover{color:var(--accent-2-text)}
/* A link that ends a card sits in a 44px target wrapped around 19px
   of text, so a third of that box is empty space stacked on top of
   the card's own padding. Pulled back by the difference, so the gap
   under the words is the padding and nothing else. */
.card > .arrow-link:last-child,.panel > .arrow-link:last-child{margin-bottom:-12px}

/* ============================================================
   TAGS
   ============================================================ */
/* A chip is a name, not a piece of data: set in the body face like
   everything else that is read as words. The mono face is kept for the
   things that really are labels and figures — eyebrows, table heads,
   field labels. Fully round, so a row of them reads as tokens rather
   than as a row of little boxes. */
.tag,.tag-soft{
  display:inline-flex;align-items:center;gap:var(--spacing-8);
  font-family:var(--font-body);font-size:var(--text-body-sm);line-height:1.2;
  letter-spacing:0;
  padding:var(--spacing-8) var(--spacing-16);border-radius:var(--radius-circle);
  background:var(--veil);white-space:nowrap;color:var(--ink-muted)}
.tag-soft{background:var(--accent-2-quiet);border-color:transparent;color:var(--accent-2-text)}
.section.inverse .tag{background:var(--veil-reverse);color:var(--ink-reverse-muted)}

/* ============================================================
   CARDS
   ============================================================ */
/* A light surface always states its own ink: inside the navy band
   the section colour would otherwise cascade in and leave reversed
   text on a white ground. */
.card,.panel,.enquiry{color:var(--ink)}
.section.inverse .card h2,.section.inverse .card h3,.section.inverse .card p,
.section.inverse .panel h2,.section.inverse .panel h3,.section.inverse .panel p{color:var(--ink)}
.section.inverse .card a,.section.inverse .panel a{color:var(--accent-strong)}
.section.inverse .card :focus-visible,.section.inverse .panel :focus-visible{outline-color:var(--accent)}
.card{
  position:relative;
  background:var(--surface);
  border-radius:var(--radius-cards);
  padding:var(--card-padding);
  transition:transform var(--duration-card-hover) var(--easing-card-hover),
             border-color var(--duration-card-hover) var(--easing-card-hover),
             box-shadow var(--duration-card-hover) var(--easing-card-hover)}
.card{box-shadow:0 1px 2px rgba(5,24,53,.05),0 12px 28px -22px rgba(5,24,53,.28)}
@media (prefers-color-scheme:dark){.card,.phase-card{box-shadow:none}}
.card > :last-child{margin-bottom:0}
.card h3{margin-bottom:var(--spacing-12)}
.card p{font-size:var(--text-body-sm);line-height:var(--leading-body-sm);color:var(--ink-muted)}
/* On the lifted band the card cannot be the surface colour or it
   disappears into it, so the two swap: the band takes the surface
   and the card takes the page ground. */
.section.lift .card{background:var(--bg)}
/* Only a card that is itself a link lifts on hover. A static panel
   that rises under the pointer promises a click that is not there. */
a.card:hover,.card:has(> a:only-of-type):hover{transform:translateY(-3px)}
.grid.g2 > .card{padding:var(--spacing-40)}

/* A quieter card: the same shape, tinted rather than filled, for a
   block that belongs to the section around it rather than standing
   apart from it. */
.panel{background:var(--veil);border-radius:var(--radius-cards);padding:var(--spacing-40)}
.panel > :last-child{margin-bottom:0}
.section.lift .panel{background:var(--bg)}
/* Frosted, not merely tinted, on the navy band: the contour map runs
   behind it, and a flat tint lets every line through at full
   definition so the heading sits on terrain rather than on a
   surface. */
.section.inverse .panel{background:rgba(238,241,247,.07);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.section.inverse .panel h2,.section.inverse .panel h3{color:var(--ink-reverse)}
.section.inverse .panel p,.section.inverse .panel .prose p{color:var(--ink-reverse)}
.section.inverse .panel .eyebrow{color:var(--sky)}
.section.inverse .panel a{color:var(--ink-reverse)}

/* A list inside a card is a set of names, not prose: the browser's
   disc and its indent push every line away from the heading above it,
   which is the one thing they should line up with. Flush left, and the
   marker is a short rule in the accent — the same mark the site uses
   for a phase's methods. */
.card ul{list-style:none;padding:0;margin:var(--spacing-16) 0 0;
  font-size:var(--text-body-sm);line-height:var(--leading-body-sm);color:var(--ink-muted)}
.card ul li{position:relative;padding-left:var(--spacing-20);margin-bottom:var(--spacing-8)}
.card ul li:last-child{margin-bottom:0}
.card ul li::before{content:"";position:absolute;left:0;top:.62em;
  width:8px;height:1px;background:var(--accent);opacity:.7}
.section.inverse .card ul{color:var(--ink-reverse-muted)}
/* A card whose body is a list wants its heading a step smaller: at
   24px over four short items the heading outweighed the card. */
.grid.g4 .card h3{font-size:var(--text-body-lg);letter-spacing:-.015em}

/* A statement the page makes on its own behalf, in the accent rather
   than in the neutral tint, so it does not read as one more content
   card. It is a sentence, so it takes a reading measure rather than
   the full width of the grid above it, and it stands clear of that
   grid rather than butting into it. */
.note{background:var(--accent-quiet);border:0;border-left:3px solid var(--accent);
  border-radius:0 var(--radius-cards) var(--radius-cards) 0;
  padding:var(--spacing-24) var(--spacing-32);margin-top:var(--spacing-24);
  max-width:var(--measure);
  font-size:var(--text-body-sm);line-height:var(--leading-body-sm);color:var(--ink)}
.note > :last-child{margin-bottom:0}

.section.inverse .note{background:rgba(238,241,247,.07);border-left-color:var(--sky);color:var(--ink-reverse);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}

/* ============================================================
   THE HERO WASH
   A blue gradient that drifts behind the opening of a page. Drawn
   in CSS rather than fetched: two soft plates on their own slow
   loops, blurred past the point where either edge is legible, so
   what moves is the light rather than a shape. Where WebGL is
   available a grain-gradient canvas paints over the same box and
   takes it further; where it is not, this is what there is, and it
   is a finished thing rather than a fallback.

   It is pulled up behind the header, which is transparent until the
   page moves, so the wash starts at the top of the window rather
   than under the bar.
   ============================================================ */
.wash{position:relative;isolation:isolate}
/* The opening block can be a screen in its own right, with whatever
   sits at its floor pinned there by an auto margin. Below that
   height it simply grows, so a long page head is never clipped. */
.wash--hero{display:flex;flex-direction:column;min-height:calc(100svh - var(--header-h))}
.wash--hero > *{width:100%}
.wash__plate{position:absolute;z-index:-1;pointer-events:none;overflow:hidden;
  left:0;right:0;bottom:0;top:calc(var(--header-h) * -1);
  background:var(--wash-back);
  /* Faded out at the foot, or the plate ends in a straight
     horizontal cut where the wash meets the page ground below. */
  -webkit-mask-image:linear-gradient(to bottom,#000 55%,transparent 97%);
          mask-image:linear-gradient(to bottom,#000 55%,transparent 97%)}
.wash__plate::before,.wash__plate::after{content:"";position:absolute;inset:-25%;
  filter:blur(44px);will-change:transform}
/* Two colours, kept apart. Every extra translucent layer over a dark
   ground mixes down toward grey, so there are four stops, each near
   its own value and each falling off quickly — the blue arriving from
   the top right, the pink answering it from the far side. */
.wash__plate::before{
  background:
    radial-gradient(30% 34% at 82% 12%,rgba(29,94,255,.92),transparent 62%),
    radial-gradient(22% 26% at 99% 44%,rgba(29,94,255,.66),transparent 66%);
  animation:wash-drift-a 34s ease-in-out infinite alternate}
.wash__plate::after{
  background:
    radial-gradient(17% 19% at 97% 3%,rgba(61,120,255,.8),transparent 68%),
    radial-gradient(13% 15% at 68% 94%,rgba(250,74,110,.7),transparent 70%);
  animation:wash-drift-b 46s ease-in-out infinite alternate}
@keyframes wash-drift-a{
  from{transform:translate3d(0,0,0) scale(1)}
  to{transform:translate3d(-6%,4%,0) scale(1.12)}}
@keyframes wash-drift-b{
  from{transform:translate3d(0,0,0) scale(1.06)}
  to{transform:translate3d(5%,-5%,0) scale(1)}}
@media (prefers-color-scheme:dark){
  .wash__plate::before{background:
    radial-gradient(30% 34% at 82% 12%,rgba(29,94,255,.98),transparent 62%),
    radial-gradient(22% 26% at 99% 44%,rgba(20,72,220,.86),transparent 66%)}
  .wash__plate::after{background:
    radial-gradient(17% 19% at 97% 3%,rgba(61,120,255,.86),transparent 68%),
    radial-gradient(13% 15% at 68% 94%,rgba(250,74,110,.74),transparent 70%)}
}
/* The shader library injects its own positioning in a <style>
   element it creates at runtime. Written here instead, so the canvas
   is styled by the site rather than by its own script. */
[data-paper-shader] canvas{contain:strict;display:block;position:absolute;
  inset:0;z-index:-1;width:100%;height:100%}

/* ============================================================
   HERO
   ============================================================ */
.hero{display:flex;flex-direction:column;padding:var(--spacing-64) 0 var(--spacing-40)}
/* .wrap centres itself with auto side margins, and an auto margin on
   the cross axis of a flex container cancels the stretch it would
   otherwise get — which shrank the page head to its own text and sat
   it 272px from the edge while every other container was at 64. */
.hero > .wrap,.wash--hero > *{width:100%}
/* A page head inside a wash carries its own closing space, so the
   gradient has somewhere to fade and the first section below is not
   crowded up against the lede. */
.wash:not(.wash--hero) > .hero{padding-top:var(--spacing-80);padding-bottom:var(--spacing-64)}
.wash--hero > .hero{flex:1;justify-content:center}
.hero h1{max-width:22ch}
.hero .lede{max-width:56ch;margin-bottom:0;font-size:17px;line-height:1.6}
.hero .eyebrow{margin-bottom:var(--spacing-24)}
.hero .btn-row{margin-top:var(--spacing-40)}



/* Three figures, set the way a byline is: quiet, in a row, with a
   rule above them. Pinned to the floor of the hero by the auto
   margin, so the first screen carries the proposition and the proof
   of it. */
.stats{margin-top:auto;padding:var(--spacing-40) 0 var(--spacing-24);
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--spacing-40);
  border-top:1px solid var(--rule)}
/* The figure and its caption sit side by side: at this size the numeral
   is the thing being read and the words are the note on it, which is a
   relationship you read across rather than down. */
.stat{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--spacing-20);align-items:center}
.stat b{display:block;font-family:var(--font-display);
  font-weight:var(--weight-regular);font-size:clamp(48px,4.4vw,68px);line-height:.9;
  letter-spacing:-.04em;color:var(--figure);
  /* The digits are replaced one frame at a time while the count runs,
     so the column has to be as wide as the widest value it will show
     or the caption beside it walks left and right. */
  font-variant-numeric:tabular-nums;min-width:2.1ch}
.stat span{display:block;font-size:var(--text-body-sm);line-height:var(--leading-body-sm);
  color:var(--ink-muted);max-width:26ch}

/* ---- the hero aside ----
   The signature composition of this system: a light panel wearing a
   translucent ring, sitting in the wash rather than on top of it.
   background-clip keeps the fill inside the border, which is what
   lets the ring stay see-through at all. */
.hero__grid{display:grid;grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  gap:var(--spacing-80);align-items:center}
.hero__aside{position:relative;background:var(--surface);background-clip:padding-box;
  border:14px solid rgba(255,255,255,.42);
  border-radius:calc(var(--radius-cards) + 14px);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  padding:var(--spacing-32)}
.hero__aside .eyebrow{margin-bottom:var(--spacing-16)}
.hero__aside-note{margin:var(--spacing-20) 0 0;font-size:var(--text-body-sm);
  line-height:var(--leading-body-sm);color:var(--ink-muted)}
@media (prefers-color-scheme:dark){
  .hero__aside{border-color:rgba(238,241,247,.10)}
}

/* The four phases as a ladder. One row per phase: the mark with that
   phase's bar lit, its name, and the deck's own word for it. */
.ladder{list-style:none;margin:0;padding:0}
.ladder li + li{border-top:1px solid var(--rule)}
.ladder a{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  gap:var(--spacing-16);padding:var(--spacing-12) 0;min-height:48px;
  text-decoration:none;color:var(--ink)}
.ladder a:hover{color:var(--accent-2-text)}
.ladder a:hover b{text-decoration:none}
.ladder b{font-family:var(--font-display);
  font-weight:var(--weight-regular);font-size:var(--text-body-lg);letter-spacing:-.015em}
.ladder span:last-child{font-family:var(--font-label);font-size:11px;letter-spacing:.01em;
  color:var(--ink-muted);text-align:right}

/* ============================================================
   THE FOUR PHASES
   ============================================================ */

.phase-card{position:relative;background:var(--surface);
  border-radius:var(--radius-cards);overflow:hidden;
  transition:transform var(--duration-card-hover) var(--easing-card-hover),
             border-color var(--duration-card-hover) var(--easing-card-hover)}
.phase-card:hover{transform:translateY(-4px)}
.section.lift .phase-card{background:var(--bg)}
/* The head is a band across the top of the card rather than a line
   of text inside it: the phase number and its name are the label on
   the box, and the body below is what is in it. */
.ph-head{display:flex;align-items:center;gap:var(--spacing-16);
  padding:var(--spacing-20) var(--spacing-24);background:var(--veil)}
.ph-num{font-family:var(--font-body);font-size:var(--text-body-sm);
  font-variant-numeric:tabular-nums;color:var(--ink-muted)}
.ph-name{margin-left:auto;font-family:var(--font-display);
  font-size:var(--text-heading-sm);line-height:1;letter-spacing:var(--tracking-heading-sm)}
.ph-body{padding:var(--spacing-24)}
.ph-body > p{font-size:var(--text-body-sm);line-height:var(--leading-body-sm);color:var(--ink-muted)}
/* The methods inside a phase, as chips. They are a list of named
   techniques, so they are set as tags rather than as a sentence. */
.ph-body ul{list-style:none;display:flex;flex-wrap:wrap;gap:var(--spacing-8);
  padding:0;margin:0 0 var(--spacing-24)}
.ph-body ul li{font-family:var(--font-body);font-size:13px;line-height:1.2;
  color:var(--ink-muted);background:var(--veil);
  padding:var(--spacing-8) var(--spacing-12);border-radius:var(--radius-circle)}

/* ============================================================
   STEPS — a numbered sequence, one card each
   ============================================================ */
.steps{counter-reset:s;display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:var(--element-gap);list-style:none;padding:0;margin:0}
.steps li{counter-increment:s;display:flex;flex-direction:column;
  padding:var(--spacing-32);background:var(--veil);border-radius:var(--radius-cards)}
/* The numeral is set in the display serif at heading size. At label
   size in mono it read as metadata about the step rather than as the
   step's own number, which is the one thing a sequence needs. */
.steps li::before{content:counter(s,decimal-leading-zero);display:block;
  font-family:var(--font-display);
  font-size:var(--text-heading-lg);line-height:1;letter-spacing:var(--tracking-heading-lg);
  color:var(--figure);margin-bottom:var(--spacing-20)}
.steps h3{margin-bottom:var(--spacing-12)}
.steps p{font-size:var(--text-body-sm);line-height:var(--leading-body-sm);color:var(--ink-muted);margin:0}
.section.lift .steps li{background:var(--bg)}
.section.inverse .steps li{background:rgba(238,241,247,.05)}
.section.inverse .steps h3{color:var(--ink-reverse)}
.section.inverse .steps p{color:var(--ink-reverse-muted)}

/* ============================================================
   THE TEAM
   ============================================================ */
/* Two to a row rather than four. At four, a person is a narrow column
   with a small tile stranded at the top of it and the name broken over
   two lines; at two, the card is wide enough to set the tile beside the
   words, which is the shape a person reads as. */
.people{grid-template-columns:repeat(2,minmax(0,1fr))}
/* stretch, not flex-start, so the body fills the card and the auto
   margin lands both links on one line across a row. */
.person{display:flex;gap:var(--spacing-24);align-items:stretch;
  padding:var(--spacing-32);border-radius:var(--radius-large);
  background:var(--veil);text-decoration:none;color:var(--ink);
  transition:transform var(--duration-card-hover) var(--easing-card-hover)}
.person:hover{transform:translateY(-4px);color:var(--ink)}
.person .avatar{flex:none;width:124px;align-self:flex-start}
/* Flex rather than grid, and the words in a box of their own: on a
   grid the role and the link auto-placed themselves into the tile's
   column, because a spanning tile leaves free cells behind it. */
.person__body{display:flex;flex-direction:column;align-items:flex-start;
  min-width:0;flex:1}
.person h3{margin:0 0 var(--spacing-4);font-size:var(--text-heading-sm);
  font-family:var(--font-display);line-height:var(--leading-heading-sm);
  letter-spacing:var(--tracking-heading-sm)}
.person:hover h3{text-decoration:none}
.person .role{display:block;font-family:var(--font-label);
  font-size:var(--text-body-sm);line-height:var(--leading-body-sm);
  letter-spacing:0;color:var(--ink-muted);margin:0 0 var(--spacing-12)}
.person .bio{display:block;margin:0;color:var(--ink-muted);
  font-size:var(--text-body-sm);line-height:var(--leading-body-sm)}

/* Initials until there are photographs. Set in the display serif at
   a size that reads as a portrait tile rather than as an avatar
   chip, so dropping a real photograph in changes nothing else. */
.avatar{display:flex;align-items:center;justify-content:center;
  aspect-ratio:1/1;width:100%;border-radius:var(--radius-cards);
  background:var(--veil);overflow:hidden}
.avatar > span{font-family:var(--font-display);
  font-weight:var(--weight-regular);font-size:clamp(34px,4vw,52px);letter-spacing:.02em;
  color:var(--ink-muted);opacity:.75}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}
/* Inside a card the tile needs its own ground, or a veil on a veil
   disappears. It steps toward the page rather than away from it. */
.person .avatar{background:var(--surface-sunk);border-radius:var(--radius-16)}
/* The link that ends a person card is a label rather than a control of
   its own — the whole card is the link — so it takes the arrow and the
   underline but not a target of its own. */
.person .arrow-link{margin-top:auto;padding-top:var(--spacing-20);min-height:0;text-decoration:none}
.person:hover .arrow-link{text-decoration:none}
/* The strip of other people at the foot of a profile is a link, not a
   person card: no portrait, three lines, and it must not inherit the
   row layout above — that laid the name, the role and the link out
   side by side and wrapped all three. */
.person-mini{display:flex;flex-direction:column;align-items:flex-start;
  text-decoration:none;color:var(--ink);
  transition:transform var(--duration-card-hover) var(--easing-card-hover)}
.person-mini:hover{transform:translateY(-4px);color:var(--ink)}
.person-mini h3{margin:0 0 var(--spacing-4);font-size:var(--text-heading-sm);
  font-family:var(--font-display);line-height:var(--leading-heading-sm);
  letter-spacing:var(--tracking-heading-sm)}
.person-mini .role{display:block;font-size:var(--text-body-sm);
  line-height:var(--leading-body-sm);color:var(--ink-muted);margin:0}
.person-mini .arrow-link{margin-top:var(--spacing-20);min-height:0;
  text-decoration:none}
.section.inverse .person-mini{color:var(--ink-reverse)}
.section.inverse .person-mini h3{color:var(--ink-reverse)}
.section.inverse .person-mini .role{color:var(--ink-reverse-muted)}
@media (hover:hover){
  .person-mini:hover h3{color:var(--accent-2-text)}
  .section.inverse .person-mini:hover h3{color:var(--accent-2)}
}

.section.lift .person{background:var(--bg)}
.section.lift .avatar{background:var(--bg)}
.section.lift .person .avatar{background:var(--surface-sunk)}

.profile-hero{display:grid;grid-template-columns:230px minmax(0,1fr);
  gap:var(--spacing-64);align-items:start}
.profile-hero .lede{max-width:52ch}

/* ============================================================
   SECTORS
   ============================================================ */
/* A row of names, not a logo wall: these are sectors worked in, and
   until a client has agreed to be named that is the honest form. */
.logos{display:flex;flex-wrap:wrap;gap:var(--spacing-8);
  border-block:1px solid var(--rule);padding:var(--spacing-24) 0}
.logos > div{font-family:var(--font-body);font-size:var(--text-body-sm);
  color:var(--ink-muted);
  padding:var(--spacing-8) var(--spacing-20);border-radius:var(--radius-circle);background:var(--veil)}
.section.lift .logos > div{background:var(--veil)}

/* ============================================================
   ON THIS PAGE
   ============================================================ */
.toc{border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  padding:var(--spacing-24) 0;margin:0}
.toc p{font-family:var(--font-label);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caption);color:var(--ink-muted);margin:0 0 var(--spacing-16)}
.toc ol{counter-reset:tc;list-style:none;display:flex;flex-wrap:wrap;
  gap:var(--spacing-12);margin:0;padding:0}
.toc li{counter-increment:tc}
/* Each entry is a control, so it is shaped like one: the same pill the
   rest of the site uses, at a size a thumb can hit. */
.toc a{display:inline-flex;align-items:center;gap:var(--spacing-12);min-height:48px;
  padding:var(--spacing-12) var(--spacing-24);border-radius:var(--radius-circle);
  background:var(--veil);font-size:var(--text-body);text-decoration:none;color:var(--ink);
  transition:background var(--duration-ui) var(--easing-ui),color var(--duration-ui) var(--easing-ui)}
.toc a::before{content:counter(tc,decimal-leading-zero);font-family:var(--font-label);
  font-size:var(--text-body-sm);color:var(--accent-strong)}
.toc a:hover{color:var(--accent-2-text);background:var(--accent-2-quiet)}
.toc a:hover::before{color:var(--accent-2-text)}

/* ============================================================
   PULL QUOTE
   ============================================================ */
.pull{font-family:var(--font-display);font-weight:var(--weight-regular);
  font-size:clamp(24px,2.2vw,32px);line-height:1.25;letter-spacing:-.015em;
  border-left:2px solid var(--accent-2);padding-left:var(--spacing-32);
  margin:0;max-width:26ch;color:var(--ink)}
.pull cite{display:block;margin-top:var(--spacing-20);
  font-family:var(--font-label);font-style:normal;font-size:var(--text-caption);
  letter-spacing:var(--tracking-caption);color:var(--ink-muted)}
.pull.wide{max-width:34ch}
/* The lead quote of a section carries the section, so it is set larger
   than a quote dropped inside one, and its attribution is a label
   rather than a smaller line of the same voice. */
.pull--lead{font-size:clamp(28px,2.7vw,40px);line-height:1.2;max-width:20ch;
  padding-left:var(--spacing-40);border-left-width:3px}
.pull--lead cite{margin-top:var(--spacing-24);font-size:var(--text-caption);
  text-transform:none;color:var(--accent-2-text)}
.section.inverse .pull--lead cite{color:var(--accent-2)}

/* The closing line of an argument, set between the body it follows and
   the heading it answers to: heavier than the paragraph above, quieter
   than the heading. */
.kicker{font-family:var(--font-display);font-weight:var(--weight-regular);
  font-size:var(--text-body-lg);line-height:1.4;letter-spacing:-.01em;
  color:var(--ink);margin:var(--spacing-24) 0 0;max-width:var(--measure)}
.section.inverse .kicker{color:var(--ink-reverse)}
.section.inverse .pull{color:var(--ink-reverse);border-left-color:var(--accent-2)}
.section.inverse .pull cite{color:var(--ink-reverse-muted)}

/* ============================================================
   PROSE, LISTS AND TABLES
   ============================================================ */
.prose{max-width:var(--measure)}
.prose h2{margin-top:var(--spacing-64)}
.prose h2:first-child{margin-top:0}
.prose h3{margin-top:var(--spacing-48)}
.prose ul,.prose ol{padding-left:var(--spacing-20);margin:0 0 var(--spacing-20)}
.prose li{margin-bottom:var(--spacing-8)}
.prose > :last-child{margin-bottom:0}

/* A list of commitments, each one ticked. The tick is drawn rather
   than set as a character, so it keeps its shape whatever the
   subset fonts carry, and it is decorative: the sentence beside it
   says the same thing. */
.ticks{list-style:none;padding:0;margin:0 0 var(--spacing-20)}
.ticks li{position:relative;padding-left:var(--spacing-32);margin-bottom:var(--spacing-12)}
/* Blue, through --figure: a 14px mask is a graphic rather than text,
   held to 3:1, so it takes the lightest blue each ground allows. */
.ticks li::before{content:"";position:absolute;left:0;top:.42em;width:14px;height:14px;
  background:var(--figure);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}

/* Key and value, stacked in rows with a rule between them. A
   definition list set as a table of two columns collapses badly on a
   phone; this reads the same at every width. */
.deflist{margin:0}
.deflist > div{display:grid;grid-template-columns:minmax(0,12rem) minmax(0,1fr);
  gap:var(--spacing-24);padding:var(--spacing-16) 0;border-bottom:1px solid var(--rule)}
.deflist > div:last-child{border-bottom:0}
.deflist dt{font-family:var(--font-label);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caption);color:var(--ink-muted);padding-top:2px}
.deflist dd{margin:0}

.tablewrap{overflow-x:auto;margin:0 0 var(--spacing-32);border-radius:var(--radius-small)}
.tablewrap:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
table{border-collapse:collapse;width:100%;margin:0 0 var(--spacing-32);
  font-size:var(--text-body-sm);line-height:var(--leading-body-sm)}
th,td{text-align:left;padding:var(--spacing-16);border-bottom:1px solid var(--rule);vertical-align:top}
th{font-family:var(--font-label);font-size:var(--text-caption);letter-spacing:var(--tracking-caption);
  color:var(--ink-muted);font-weight:var(--weight-regular)}
tbody tr:last-child td{border-bottom:0}
/* A figure in a table is data, so it is set in the mono face and
   aligned on its own axis rather than left with the words. */
td.num,th.num{font-family:var(--font-mono);text-align:right;white-space:nowrap}

/* ============================================================
   FORM
   ============================================================ */
.enquiry{background:var(--surface);border-radius:var(--radius-cards);padding:var(--spacing-40)}
.section.lift .enquiry{background:var(--bg)}
.field{margin-bottom:var(--spacing-24)}
.field label{display:block;font-family:var(--font-label);font-size:var(--text-caption);
  line-height:var(--leading-caption);letter-spacing:var(--tracking-caption);
  color:var(--ink-muted);margin-bottom:var(--spacing-12)}
.field .req{color:var(--accent-2-text);letter-spacing:var(--tracking-caption)}
.field .hint{display:block;text-transform:none;letter-spacing:normal;
  font-family:var(--font-body);font-size:var(--text-body-sm);margin-top:var(--spacing-8)}

.field input,.field select,.field textarea{
  width:100%;font-family:var(--font-body);font-size:var(--text-body);line-height:var(--leading-body);
  padding:var(--spacing-12) var(--spacing-16);min-height:52px;
  /* A drawn border rather than a filled grey block: six stacked
     filled fields read as disabled, and the border is also what says
     the field is editable. */
  background:var(--surface);color:var(--ink);
  border:1px solid var(--rule-input);border-radius:var(--radius-small);
  transition:border-color var(--duration-ui) var(--easing-ui)}
.field input:hover,.field select:hover,.field textarea:hover{border-color:var(--ink)}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:3px solid var(--accent);outline-offset:2px;border-color:var(--accent)}
.field textarea{min-height:150px;resize:vertical}
/* Radios are choices, so each one is a target rather than a dot with
   a word beside it. */
.radios{display:grid;gap:var(--spacing-8)}
.radios label{display:flex;align-items:flex-start;gap:var(--spacing-12);
  font-family:var(--font-body);font-size:var(--text-body-sm);line-height:var(--leading-body-sm);
  text-transform:none;letter-spacing:normal;color:var(--ink);margin:0;
  padding:var(--spacing-12) var(--spacing-16);min-height:44px;
  border:1px solid var(--rule);border-radius:var(--radius-small);cursor:pointer;
  transition:border-color var(--duration-ui) var(--easing-ui),background var(--duration-ui) var(--easing-ui)}
.radios label:hover{border-color:var(--rule-strong);background:var(--veil)}
.radios input{accent-color:var(--accent);margin:2px 0 0;min-height:0;width:auto;flex:none}
.radios label:has(input:checked){border-color:var(--accent);background:var(--accent-quiet)}

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer{background:var(--inverse-bg);color:var(--ink-reverse);
  padding:var(--spacing-120) 0 var(--spacing-48)}
.site-footer a{color:var(--ink-reverse);text-decoration:none}
.site-footer a:hover{color:var(--accent-2);text-decoration:none}
.site-footer :focus-visible{outline-color:var(--accent)}
.footer-grid{display:grid;grid-template-columns:1.6fr 1fr 1fr;gap:var(--spacing-64);
  padding-bottom:var(--spacing-64);border-bottom:1px solid var(--rule-reverse)}
/* The brand column leads with the mark; the two navigation columns
   keep their mono heads. Each head is still a heading — the words
   are there for anyone not seeing the artwork. */
.footer-brand .brand{color:var(--ink-reverse);margin-bottom:var(--spacing-24)}
.footer-brand .brand:hover{opacity:.72}
.footer-brand .brand b span{color:var(--ink-reverse-muted)}
.footer-brand p{max-width:34ch;font-size:var(--text-body-sm);line-height:var(--leading-body-sm);
  color:var(--ink-reverse-muted)}
.footer-brand p a{color:var(--ink-reverse)}
.footer-grid h2{font-family:var(--font-label);font-weight:var(--weight-regular);
  font-size:var(--text-caption);line-height:var(--leading-caption);letter-spacing:var(--tracking-caption);
  color:var(--sky);margin:0 0 var(--spacing-20)}
.footer-grid ul{list-style:none;padding:0;margin:0;
  font-size:var(--text-body-sm);line-height:var(--leading-body-sm)}
/* 28px rather than the 44 used elsewhere: at 44 the rows sat further
   apart than the head sits from its own list, and each column read
   as six unrelated links rather than one group. 28 is as tight as
   this can honestly go — WCAG 2.5.8 sets the floor at 24. */
.footer-grid ul a{display:inline-flex;align-items:center;min-height:28px}
.footer-legal{padding-top:var(--spacing-40);font-size:var(--text-body-sm);
  line-height:var(--leading-body-sm);color:var(--ink-reverse)}
.footer-legal p{margin:0 0 var(--spacing-8)}
/* Quieter than the disclosure above it: that one is a legal
   requirement and reads at full strength, this is a note about the
   site. Still 8:1. */
.footer-legal p:last-child{color:var(--ink-reverse-muted);margin-bottom:0}

/* The contour map behind the end of every page. The canvas is
   created by the script and inserted here, so a page with the script
   blocked carries no empty canvas and looks exactly as it did.
   Behind everything, and it holds no information. */
.has-topo{position:relative;isolation:isolate;overflow:hidden}
.has-topo > .topo{position:absolute;inset:0;z-index:-1;display:block;width:100%;height:100%}
@media print{.topo{display:none}}

/* ============================================================
   MOBILE ACTION BAR
   Shown only once the in-page action has scrolled away, so the same
   action is never on screen twice.
   ============================================================ */
.thumbbar{position:fixed;left:0;right:0;bottom:0;z-index:110;display:none;
  padding:var(--spacing-12) var(--spacing-16) calc(var(--spacing-12) + env(safe-area-inset-bottom));
  background:var(--bg);box-shadow:0 -4px 18px -6px rgba(5,24,53,.24)}
.thumbbar .btn{width:100%}

/* ============================================================
   RESPONSIVE — lg 991, md 767, sm 479
   ============================================================ */
@media (max-width:1200px){
  :root{--section-gap:var(--spacing-80);--page-padding:var(--spacing-48)}
  .split{gap:var(--spacing-48)}
}
@media (max-width:991px){
  :root{--page-padding:var(--spacing-40);--text-display:48px}
  .grid.g3,.grid.g4{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* Below the wide layout the card is too narrow to hold a tile beside
     a paragraph, so the tile goes back over the words at a size that
     still reads as a portrait rather than as a chip. */
  .person{flex-direction:column;gap:var(--spacing-20)}
  .person .avatar{width:104px}
  /* The hero stacks before the columns get narrow enough to break the
     headline: at two columns a 60px display face has nowhere to go. */
  .hero__grid{grid-template-columns:minmax(0,1fr);gap:var(--spacing-40)}
  .hero__aside{border-width:10px}
  .split{grid-template-columns:minmax(0,1fr);gap:var(--spacing-40)}
  .split > div:not(.card):not(.panel){max-width:none}
  .profile-hero{grid-template-columns:180px minmax(0,1fr);gap:var(--spacing-40)}
  .footer-grid{grid-template-columns:1fr 1fr;gap:var(--spacing-40)}
  .lifted{padding:var(--spacing-40)}
  .stats{gap:var(--spacing-24)}

  /* With JavaScript the navigation collapses behind a button.
     Without it, it simply stacks and stays reachable — never a dead
     control. */
  .js .navtoggle{display:inline-flex}
  .js .site-nav{display:none}
  .js .site-nav.is-open{display:block}
  /* Opened as an overlay under the bar, not as another row inside
     it: growing the header pushed the whole page down the moment the
     menu appeared. */
  .js .site-nav{position:absolute;top:100%;left:0;right:0;
    background:var(--bg);border-top:1px solid var(--rule);box-shadow:var(--shadow-nav);
    padding:var(--spacing-8) var(--page-padding) var(--spacing-20)}
  html:not(.js) .site-nav{width:100%;order:3;margin-left:0}
  html:not(.js) .header-inner{flex-wrap:wrap}
  .site-nav ul{flex-direction:column;align-items:stretch;gap:var(--spacing-4);padding:var(--spacing-8) 0 0}
  .site-nav a{padding:var(--spacing-12);min-height:48px}
  .site-nav .nav-cta{margin:var(--spacing-12) 0 0;justify-content:center}
}
@media (max-width:767px){
  :root{--section-gap:var(--spacing-64);--page-padding:var(--spacing-24);
        --measure:none;--text-lede:18px;--card-padding:24px}
  h1{letter-spacing:-.03em}
  .hero{padding:var(--spacing-40) 0 var(--spacing-24)}
  /* The aside takes the same padding as every other panel once there
     is one column: inset further than the cards below it, it reads as
     a different kind of thing rather than the same thing higher up. */
  .hero__aside{padding:var(--spacing-24);border-width:8px}
  .wash--hero{min-height:0}
  /* The wash stays on a phone, but the stops move: at this width the
     wide ones spread into a flat tint, so they tighten and pull into
     the top right corner, which is where the light arrives on a wide
     screen too. */
  /* The plate is as tall as the whole opening block, so a stop placed
     by percentage lands somewhere down the page rather than in the
     corner. On a phone the two layers are pinned to a band across the
     top instead, and the stops are placed inside that band. */
  .wash__plate::before,.wash__plate::after{
    inset:-120px -30% auto -30%;height:620px;filter:blur(38px)}
  .wash__plate::before{background:
    radial-gradient(30% 30% at 84% 34%,rgba(29,94,255,.95),transparent 66%),
    radial-gradient(24% 24% at 99% 52%,rgba(29,94,255,.72),transparent 70%)}
  .wash__plate::after{background:
    radial-gradient(20% 20% at 92% 24%,rgba(61,120,255,.9),transparent 68%),
    radial-gradient(17% 17% at 74% 66%,rgba(250,74,110,.62),transparent 72%)}
  .pagehead{padding-top:var(--spacing-48)}
  .pagehead + section.section,.wash + section.section{padding-top:var(--spacing-32)}
  .grid.g2,.grid.g3,.grid.g4,.people,.steps{grid-template-columns:minmax(0,1fr)}
  .person{padding:var(--spacing-24)}
  .stats{grid-template-columns:minmax(0,1fr);gap:var(--spacing-20);padding-top:var(--spacing-32)}
  .stat b{font-size:46px}
  .profile-hero{grid-template-columns:minmax(0,1fr);gap:var(--spacing-24)}
  .profile-hero .avatar{max-width:160px}
  .deflist > div{grid-template-columns:minmax(0,1fr);gap:var(--spacing-4)}
  .footer-grid{grid-template-columns:1fr;gap:var(--spacing-40)}
  .site-footer{padding-top:var(--spacing-80)}
  .lifted,.panel,.enquiry,.grid.g2 > .card{padding:var(--spacing-32)}
  .section-head{margin-bottom:var(--spacing-32)}
  .js .thumbbar{display:block}
  .js body{padding-bottom:84px}
}
@media (max-width:479px){
  /* Never below 24px, even here — the breathing room is the brand. */
  :root{--section-gap:var(--spacing-48)}
  /* "Post implementation" cannot share a line with the phase name on a
     320px screen, and a label that pushes the page sideways is worse
     than one that sits under the name. */
  .ladder a{grid-template-columns:auto minmax(0,1fr);row-gap:2px}
  .ladder span:last-child{grid-column:2;text-align:left}
  .lifted,.panel,.enquiry{padding:var(--spacing-24)}
  .btn{width:100%}
  .btn-row{gap:var(--spacing-12)}
  .pull{font-size:22px;padding-left:var(--spacing-20)}
}

/* ============================================================
   PRINT
   ============================================================ */
@media print{
  .site-header,.thumbbar,.skip,.btn,.wash__plate,.toc{display:none !important}
  body{background:#fff;color:#000;font-size:11pt}
  .section,.section--tight,.hero{padding:16pt 0}
  .section.inverse,.site-footer{background:#fff;color:#000;border-top:1px solid #999;padding:16pt 0}
  .section.inverse h2,.section.inverse p,.site-footer a,.footer-legal{color:#000}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:.85em}
}

/* ============================================================
   UTILITIES
   A small, closed set drawn from the spacing scale. The prototype
   scattered inline styles for these; a fixed set stops the next
   person inventing a fourteenth margin value.
   ============================================================ */
.u-mt-s{margin-top:var(--spacing-16)}
.u-mt-m{margin-top:var(--spacing-24)}
.u-mt-l{margin-top:var(--spacing-40)}
.u-mb-0{margin-bottom:0}
.u-mb-m{margin-bottom:var(--spacing-24)}
.u-mb-l{margin-bottom:var(--spacing-40)}

/* A phase's mark and its number, set as one line: the bars never
   travel without the words beside them. */
.phase-flag{display:flex;align-items:center;gap:var(--spacing-12)}
.card .phase-flag{margin-bottom:var(--spacing-16)}
.u-mt-x{margin-top:var(--spacing-32)}

/* ============================================================
   FAQ
   The answer slides rather than appearing. Browsers cannot animate to
   height:auto on their own, and a <details> has no height to animate
   at all until it opens, so this needs two newer features:
   interpolate-size, which lets a transition reach a keyword, and
   ::details-content, the box the browser draws around the answer.
   Both sit behind @supports, so a browser without them opens the
   answer instantly. No script either way.
   ============================================================ */
.faq{border-bottom:1px solid var(--rule)}
.faq summary{cursor:pointer;list-style:none;position:relative;
  padding:var(--spacing-24) var(--spacing-48) var(--spacing-24) 0;
  font-family:var(--font-display);
  font-weight:var(--weight-regular);font-size:var(--text-heading-sm);
  line-height:var(--leading-heading-sm);letter-spacing:var(--tracking-heading-sm);
  color:var(--ink);min-height:48px;display:flex;align-items:center}
.faq summary::-webkit-details-marker{display:none}
/* Drawn as two bars rather than set as "+" and "−": swapping one
   character for another cannot be animated, collapsing the upright of
   a cross into the bar beneath it can, and it says opening and
   closing rather than plus and minus. */
.faq summary::before,.faq summary::after{content:"";position:absolute;right:var(--spacing-8);top:50%;
  background:var(--accent);border-radius:1px;
  transition:background var(--duration-ui) var(--easing-ui)}
.faq summary::after{width:14px;height:1.5px;transform:translateY(-50%)}
.faq summary::before{width:1.5px;height:14px;transform:translate(-6.25px,-50%);
  transition:transform var(--duration-reveal) var(--easing-reveal),
             opacity var(--duration-reveal) var(--easing-reveal),
             background var(--duration-ui) var(--easing-ui)}
.faq[open] summary::before{transform:translate(-6.25px,-50%) scaleY(0);opacity:0}
/* The bars carry the hover colour with the words: the whole row is one
   target, so one half of it should not change while the other holds. */
.faq summary:hover{color:var(--accent-2-text)}
.faq summary:hover::before,.faq summary:hover::after{background:var(--accent-2)}
.faq__a{padding:0 var(--spacing-48) var(--spacing-32) 0;max-width:var(--measure)}
.faq__a > :last-child{margin-bottom:0}
@supports (interpolate-size: allow-keywords) and (selector(::details-content)) {
  :root{interpolate-size:allow-keywords}
  .faq::details-content{
    block-size:0;overflow:hidden;opacity:0;
    transition:block-size var(--duration-reveal) var(--easing-reveal),
               content-visibility var(--duration-reveal) var(--easing-reveal) allow-discrete,
               opacity var(--duration-reveal) var(--easing-reveal)}
  .faq[open]::details-content{block-size:auto;opacity:1}
}

/* A group of choices is a field like any other: the browser's own
   fieldset border and legend make it look like a different kind of
   control from the inputs above it. */
/* Not scoped to .field: the radio group is a fieldset in its own
   right, which is exactly why it was the one showing the browser's
   box and a body-sized legend. */
fieldset{border:0;margin:0 0 var(--spacing-24);padding:0;min-inline-size:0}
legend{padding:0;font-family:var(--font-label);font-size:var(--text-caption);
  line-height:var(--leading-caption);letter-spacing:var(--tracking-caption);
  color:var(--ink-muted);margin-bottom:var(--spacing-12)}

/* ============================================================
   COMPONENTS ON THE DARK BAND
   Every light surface has to restate its own ink here, or the band
   colour cascades into it and leaves reversed text on a white
   ground. Everything drawn in a rule or a tint gets the reversed
   value of the same thing.
   ============================================================ */
.section.inverse .phase-card{background:var(--navy-lift)}

.section.inverse .ph-head{background:rgba(238,241,247,.05)}
.section.inverse .ph-name{color:var(--ink-reverse)}
.section.inverse .ph-num,.section.inverse .ph-body > p{color:var(--ink-reverse-muted)}
.section.inverse .ph-body ul li{color:var(--ink-reverse-muted);background:var(--veil-reverse)}
.section.inverse .card{background:var(--navy-lift)}
.section.inverse .card h3,.section.inverse .card h2{color:var(--ink-reverse)}
.section.inverse .card p{color:var(--ink-reverse-muted)}
.section.inverse .card a{color:var(--ink-reverse)}
.section.inverse .person{color:var(--ink-reverse);background:rgba(238,241,247,.05)}
.section.inverse .person .avatar{background:rgba(238,241,247,.06)}
.section.inverse .person h3{color:var(--ink-reverse)}
.section.inverse .person .role,.section.inverse .person .bio{color:var(--ink-reverse-muted)}
.section.inverse .avatar{background:rgba(238,241,247,.05)}
.section.inverse .avatar > span{color:var(--ink-reverse-muted)}
.section.inverse .logos{border-color:var(--rule-reverse)}
.section.inverse .logos > div{background:rgba(238,241,247,.05);color:var(--ink-reverse-muted)}
.section.inverse .deflist > div{border-bottom-color:var(--rule-reverse)}
.section.inverse .deflist dt{color:var(--ink-reverse-muted)}
.section.inverse .faq{border-bottom-color:var(--rule-reverse)}
.section.inverse .faq summary{color:var(--ink-reverse)}
.section.inverse .faq summary:hover{color:var(--sky)}
.section.inverse .faq summary::before,.section.inverse .faq summary::after{background:var(--sky)}
.section.inverse .faq summary:hover::before,.section.inverse .faq summary:hover::after{background:var(--accent-2)}
.section.inverse th,.section.inverse td{border-bottom-color:var(--rule-reverse)}
.section.inverse th{color:var(--ink-reverse-muted)}
.section.inverse .stats{border-top-color:var(--rule-reverse)}
.section.inverse .stat span{color:var(--ink-reverse-muted)}
.section.inverse .toc{border-color:var(--rule-reverse)}
.section.inverse .toc a{color:var(--ink-reverse)}
.section.inverse .toc p{color:var(--ink-reverse-muted)}
.section.inverse .ladder li + li{border-top-color:var(--rule-reverse)}
.section.inverse .prose a,.section.inverse .ticks a{color:var(--ink-reverse)}

.section.inverse .field label,.section.inverse .field legend{color:var(--ink-reverse-muted)}
.section.inverse .enquiry{background:var(--navy-lift);color:var(--ink-reverse)}
.section.inverse .enquiry input,.section.inverse .enquiry select,.section.inverse .enquiry textarea{
  background:rgba(238,241,247,.04);color:var(--ink-reverse);border-color:var(--rule-reverse)}
.section.inverse .radios label{border-color:var(--rule-reverse);color:var(--ink-reverse)}

/* ---- the decision point ----
   The one place on a phase page where the engagement can end, so it is
   the one block that carries the second colour: an amber edge, an amber
   eyebrow, and nothing else different about it. */
.panel--decision{border-left:3px solid var(--accent-2);background:var(--accent-2-quiet);
  border-radius:0 var(--radius-cards) var(--radius-cards) 0}
.panel--decision .eyebrow{color:var(--accent-2-text)}
.section.inverse .panel--decision{background:rgba(250,74,110,.12);border-left-color:var(--accent-2)}
.section.inverse .panel--decision .eyebrow{color:var(--accent-2)}
/* The link out of the decision panel is part of the decision, so it
   takes the panel's pink rather than the blue every other link uses.
   It has to beat `.section.inverse .panel a`, which is why it names
   the panel too. */
.panel--decision .arrow-link{color:var(--accent-2-text)}
.section.inverse .panel--decision .arrow-link{color:var(--accent-2)}
.panel--decision .arrow-link:hover,
.section.inverse .panel--decision .arrow-link:hover{color:var(--accent-2-strong)}
.section.inverse .panel--decision .arrow-link:hover{color:#ff7d99}
.section.lift .panel--decision{background:var(--accent-2-quiet)}

/* The four things we work on are a set, not a label, so they are set as
   four tokens rather than as one line with separators in it. They sit
   over the wash, so the fill has to hold up against a gradient rather
   than against a flat ground. */
.domains{display:flex;flex-wrap:wrap;gap:var(--spacing-8);list-style:none;
  margin:0 0 var(--spacing-24);padding:0}
/* The same tint as the sector strip at the foot of the hero: both sit
   on the wash, and --veil is light enough to let the gradient through,
   so the pills take the blue underneath them rather than flattening it
   to grey. The label stays at full ink — the strip can afford muted
   because it is decorative, this names what the firm does. */
.domains li{font-size:var(--text-body-sm);line-height:1.2;color:var(--ink);
  padding:var(--spacing-8) var(--spacing-16);border-radius:var(--radius-circle);
  background:var(--veil);backdrop-filter:blur(4px)}

/* ---- the closing panel ----
   The contour map runs across the closing band and the footer as one
   piece of terrain. The call to action sits on a plain panel inside
   that field, so the pattern surrounds it rather than running behind
   the words: an opaque ground here is what makes the terrain read as a
   surround rather than as noise. */
.cta-panel{background:var(--navy-lift);border-radius:var(--radius-large);
  padding:var(--spacing-64);max-width:760px;margin-inline:auto}
.cta-panel > :last-child{margin-bottom:0}
.cta-panel .lede{max-width:44ch}
/* The band's own padding closes up: the panel now carries the space
   that the copy used to need from the section around it. */
.section--cta{padding:var(--spacing-80) 0}
.section--cta:last-child{padding-bottom:var(--spacing-80)}
@media (max-width:767px){
  .cta-panel{padding:var(--spacing-32)}
  .section--cta{padding:var(--spacing-48) 0}
}

/* A column that stays put while the one beside it scrolls. The contact
   details are four lines and a note; the form beside them is a screen
   and a half, and a phone number that has scrolled away is a phone
   number you have to go looking for. Only where there are two columns
   to begin with — stuck to the top of a stacked layout it would cover
   the thing it sits above. */
@media (min-width:992px){
  .sticky-aside{position:sticky;top:calc(var(--header-h) + var(--spacing-32));align-self:start}
}

/* A sector card leads with its glyph. The icon is 24px and carries the
   accent, so a grid of eight reads as a set at a glance without the
   headings competing with one another. */
.icon{display:block;width:24px;height:24px;color:var(--accent);margin-bottom:var(--spacing-16)}

/* ============================================================
   THE STRIP
   Runs along the floor of the hero: the proposition above it, the
   proof of it underneath. It moves continuously and has no pause
   control — the accessibility statement records that rather than
   claiming a conformance the page does not have.
   ============================================================ */
.marquee{margin-top:auto;padding:var(--spacing-32) 0 var(--spacing-40)}
.marquee__head{margin:0 0 var(--spacing-20)}
.marquee__head .eyebrow{margin:0}
/* The fade is a fixed distance rather than a percentage: as a
   percentage it grows with the viewport, so on a wide screen the first
   whole item does not appear until a long way in. */
.marquee__viewport{overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 64px,#000 calc(100% - 64px),transparent);
          mask-image:linear-gradient(90deg,transparent,#000 64px,#000 calc(100% - 64px),transparent)}
/* Without JavaScript nothing moves, so the strip becomes an ordinary
   scrollable row instead — no motion means nothing to pause. */
html:not(.js) .marquee__viewport{overflow-x:auto}
.marquee__track{display:flex;width:max-content;list-style:none;margin:0;padding:0;align-items:center}
/* Margin rather than gap: the loop translates exactly half the track,
   which only lands cleanly if both runs are identical boxes. */
.marquee__item{flex:none;margin-right:var(--spacing-12);
  font-family:var(--font-display);font-size:var(--text-heading-sm);
  line-height:1.1;letter-spacing:var(--tracking-heading-sm);color:var(--ink-muted);
  padding:var(--spacing-8) var(--spacing-20);border-radius:var(--radius-circle);
  background:var(--veil);white-space:nowrap}
/* 44s is the fallback. The script replaces it with a duration taken
   from the track's own width, so the strip travels at one speed
   whatever the count. */
.js .marquee__track{animation:marquee-loop 44s linear infinite}
@keyframes marquee-loop{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  .js .marquee__track{animation:none}
  .js .marquee__viewport{overflow-x:auto}
}
@media (max-width:767px){
  .marquee{padding-top:var(--spacing-24)}
  .marquee__item{font-size:var(--text-body-lg)}
}

/* Hover is where the second colour lives on a control. Nothing is pink
   at rest — the blue still says "this is the action" — but everything
   that answers the pointer answers in pink, which is the one moment a
   page can carry colour without carrying noise. The fill uses the
   deeper #D81B48 rather than the bright pink, because white on the
   bright one is 3.4:1 and a button label has to hold at 4.5. */
@media (hover:hover){
  .person:hover h3{color:var(--accent-2-text)}
  .section.inverse .person:hover h3{color:var(--accent-2)}
  .phase-card:hover .ph-name{color:var(--accent-2-text)}
  .section.inverse .phase-card:hover .ph-name{color:var(--accent-2)}
}

/* A headline of three short sentences sets one to a line: left to the
   measure the breaks move with the viewport, and "Four phases. Four"
   is not a line. Each sentence is its own block, so the stack is the
   same at every width and the three lines answer the four arcs beside
   them. */
.h1--stack span{display:block}

/* The whole phase card is the link. The arrow link at the foot of it
   stretches an overlay across the card, so anywhere on the card is the
   target and there is still exactly one link in the accessibility tree.
   The overlay is ::before because ::after already draws the arrow. */
.phase-card .arrow-link::before{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}
/* The focus ring belongs on the card, not on the four words of the
   link, so it is drawn on the overlay. */
.phase-card .arrow-link:focus-visible{outline:none}
.phase-card .arrow-link:focus-visible::before{outline:3px solid var(--accent);outline-offset:4px;
  border-radius:var(--radius-cards)}
@media (hover:hover){
  /* Hovering anywhere on the card answers in the same place the rest of
     the site does: the link goes pink, and the lit arc of the mark goes
     with it. */
  .phase-card:hover{--pm-lit:var(--accent-2)}
  .phase-card:hover .arrow-link{color:var(--accent-2-text)}
  .section.inverse .phase-card:hover .arrow-link{color:var(--accent-2)}
  .phase-card:hover .arrow-link{text-decoration-color:currentColor}
}

/* The mark beside each phase in the hero ladder: bigger than an
   annotation, because in that card it is the row's subject. It answers
   a hover the same way the phase cards do — the lit arc goes pink with
   the name beside it. */
.ladder .phasemark{width:30px;height:30px}
@media (hover:hover){
  .ladder a:hover{--pm-lit:var(--accent-2)}
}

/* What a level includes sits at the foot of its card, under a hairline,
   with the label and the list on one baseline rather than the label
   dropped into the middle of a paragraph for the text to wrap around.
   margin-top:auto pushes it to the bottom, so the hairline lands at the
   same height in all three cards however long their descriptions run —
   and the padding below it is the smallest gap it can end up with.

   Scoped to .steps deliberately: .steps p sets margin:0, and a bare
   .includes loses to it on specificity, taking the auto margin the
   alignment depends on with it. */
.steps .includes{display:flex;align-items:baseline;gap:var(--spacing-16);
  margin:auto 0 0;padding-top:var(--spacing-24);border-top:1px solid var(--rule);
  font-size:var(--text-body-sm);line-height:var(--leading-body-sm);color:var(--ink-muted)}
/* Baselines, not box tops. The chip is a pill with its own padding, so
   aligning the two boxes leaves the label sitting above the line it is
   labelling; aligning their baselines puts the two texts on one line,
   which is what the eye reads as aligned. It also retires a 6px nudge
   that only worked while the list ran to two lines. */
.steps .includes .tag{flex:none;align-self:baseline}
/* The auto margin resolves to zero in the tallest card, which would put
   the rule hard against the last line of the paragraph. This gives the
   rule the same air above it as below, in every card. */
.steps li > p:has(+ .includes){margin-bottom:var(--spacing-24)}
.section.inverse .steps .includes{border-top-color:var(--rule-reverse);color:var(--ink-reverse-muted)}
/* The steps' own rhythm: the numeral, then the name, then the sentence,
   each with the space its size asks for rather than one gap for all
   three. */
.steps li{padding:var(--spacing-32)}
.steps li::before{margin-bottom:var(--spacing-16)}
.steps h3{margin-bottom:var(--spacing-8)}
