/* ==========================================================================
   Sidrlabs — site.css
   Lumena-derived system, with the client's weight and component overrides.

   Deliberate departure from the reference: the reference holds everything at
   weight 400. This build steps headings, labels and standfirst to 600 (a
   "+50%" move) because the client asked for more presence. Running copy sits
   at --w-body so a heading still reads louder than the paragraph beneath it.
   ========================================================================== */

/* ==========================================================================
   Typeface — self-hosted, no third-party requests

   inter-subset.woff2 is Inter 4.1 (rsms.me/inter, SIL OFL — see OFL.txt),
   subset by us to Latin-1 + Latin Extended-A + general punctuation, currency
   and arrows. Two axes survive: wght limited to 400–600, opsz left intact so
   the browser optically sizes 14px meta and 112px display differently.
   59 KB, one file, both weights. Rebuild instructions in
   brand/notes/fonts-README.txt, outside the published folder.
   ========================================================================== */
@font-face{
  font-family:"Inter";
  src:url("../fonts/inter-subset.woff2") format("woff2");
  font-weight:400 600;
  font-style:normal;
  font-display:swap;
}

:root{
  /* --- Colour --------------------------------------------------------- */
  --bone:#F6F4E9;
  --white:#FFFFFF;
  --ink:#1D1D1D;
  --mauve:#70626B;
  /* The dark field: footer, menu, selected tabs, button hovers. Was a forest
     green taken from the reference system this palette came from; it is now
     the same ink the hero animation draws with, so the dark ground and the
     marks on the page are one colour. Kept separate from --ink because one
     means "a field" and the other means "text". */
  --dark:#1D1D1D;
  /* Text on the dark ground. Bone is the page background, so a dark section
     is the page reversed rather than a second colour scheme. Butter used to
     do this job, but a warm yellow spread across every word turns the whole
     field yellow: it is an accent, not a body colour. */
  --on-dark:#F6F4E9;
  --signal:#FF303C;
  --rule:#DAD5C4;           /* decorative hairlines — 1.33:1, not a control edge */
  --rule-strong:#958D72;    /* the edge of an interactive control. 3:1 on bone and
                               white, per WCAG 1.4.11 (tabs, accordions) */
  --rule-soft:#E8E3D4;
  --grey-btn:rgba(0,0,0,.05);
  --grey-btn-h:rgba(0,0,0,.10);
  --on-dark-soft:rgba(246,244,233,.62);
  --on-dark-rule:rgba(246,244,233,.22);

  /* --- Type ------------------------------------------------------------ */
  --base:"Inter",ui-sans-serif,-apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;

  --w-base:400;             /* UI: nav, buttons, numbering */
  --w-body:400;             /* running copy — the lever for paragraph weight */
  --w-mid:600;              /* the "+50%" weight: headings, labels, standfirst */

  --fs-display:clamp(2.5rem,1.2rem + 6.5vw,7rem);        /*  40 → 112 */
  --fs-h1:clamp(2.375rem,1.6rem + 3.6vw,4.5rem);          /*  38 →  72 */
  /* Statistics only. This had collapsed to the same value as --fs-h2, so a
     result read exactly as loud as the word above it. It now clears the
     heading by half again, which is the whole job of the number. */
  --fs-quote:clamp(2.5rem,1.6rem + 4vw,5rem);             /*  40 →  80 */
  --fs-h2:clamp(1.75rem,1.3rem + 2.1vw,3rem);             /*  28 →  48 */
  --fs-lead:clamp(1.3125rem,1.1rem + 1vw,2rem);           /*  21 →  32 */
  --fs-stand:clamp(1.125rem,1.08rem + .2vw,1.25rem);      /*  18 →  20 */
  --fs-body:1rem;
  --fs-meta:.875rem;
  --fs-menu:1.5rem;                                       /*  24, per Lumena */

  /* One leading per size. --lh-quote is the single deliberate exception:
     testimonials are full sentences at standfirst size and need the air.
     Pills and menu links set line-height:1 directly — that is a layout
     requirement for the control's height, not a type setting. */
  --lh-display:1;
  --lh-h1:1.1;
  --lh-h2:1.08;
  --lh-lead:1.25;
  --lh-stand:1.3;
  --lh-body:1.55;
  --lh-meta:1.3;
  --lh-quote:1.4;

  /* --- Space & shape ---------------------------------------------------- */
  /* Header height is fixed; the logo sits inside it at 2x its previous size. */
  --head-h:69px;
  --logo-h:52px;          /* header and footer share one value */
  --pad:24px;
  --sec:80px;
  --sec-tight:72px;         /* Career Tracks only: pulls the reader out of the
                               hero instead of stranding them in whitespace */
  --measure:50ch;          /* about 68 real characters in Inter — 1ch is the
                             width of a zero and overshoots lowercase ~25% */
  --pill:40px;
  --media:70px;
  --ease:cubic-bezier(.55,0,.1,1);
}
@media(min-width:768px){ :root{ --pad:32px; --sec:120px } }

*,*::before,*::after{box-sizing:border-box}
/* letter-spacing inherits as a computed px value, not em — re-declare it so
   -.02em stays true at every size */
*{letter-spacing:-.02em}

html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:calc(var(--head-h) + 16px)}

body{
  margin:0;background:var(--bone);color:var(--ink);
  font-family:var(--base);font-size:var(--fs-body);font-weight:var(--w-base);
  line-height:var(--lh-body);-webkit-font-smoothing:antialiased;overflow-x:hidden;
}

h1,h2,h3,h4{margin:0;font-weight:var(--w-mid);color:var(--ink);text-wrap:balance}
p{margin:0}
ul{margin:0;padding:0;list-style:none}
a{color:inherit;text-decoration:none}
/* height:auto is load-bearing — without it a replaced element uses its
   height attribute and ignores aspect-ratio, which stretched the photo */
img,canvas,svg{display:block;max-width:100%;height:auto}
/* NOT letter-spacing:inherit — that inherits a computed px value and beats
   the * rule, leaving buttons tracked for their parent's size, not their own */
/* padding:0 matters: browsers give a bare button 1px 6px of their own, which
   indents its text against anything beside it. Every styled button here sets
   its own padding, so nothing else is affected. */
button{font:inherit;letter-spacing:-.02em;color:inherit;background:none;border:0;
  padding:0;text-align:inherit;cursor:pointer}
strong,b{font-weight:var(--w-mid);color:var(--ink)}
em,i{font-style:normal}

:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.menu :focus-visible,.footer :focus-visible{outline-color:var(--on-dark)}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;z-index:300;background:var(--dark);
  color:var(--on-dark);padding:14px 22px}
.skip:focus{left:0}

/* ==========================================================================
   Layout
   ========================================================================== */
.wrap{width:100%;max-width:1440px;margin-inline:auto;padding-inline:var(--pad)}
.sec{padding-block:var(--sec)}
.sec--white{background:var(--white)}
.sec--dark{background:var(--dark);color:var(--on-dark)}
.hr{height:1px;background:var(--rule);border:0;margin:0}

/* --- type roles ------------------------------------------------------- */
.t-display{font-size:var(--fs-display);line-height:var(--lh-display);font-weight:var(--w-mid)}
.t-h1{font-size:var(--fs-h1);line-height:var(--lh-h1);font-weight:var(--w-mid)}
.t-h2{font-size:var(--fs-h2);line-height:var(--lh-h2);font-weight:var(--w-mid)}
.t-lead{font-size:var(--fs-lead);line-height:var(--lh-lead);font-weight:var(--w-mid)}
.t-stand{font-size:var(--fs-stand);line-height:var(--lh-stand);font-weight:var(--w-mid)}
.t-body{font-size:var(--fs-body);line-height:var(--lh-body);font-weight:var(--w-body);
  color:var(--mauve);max-width:var(--measure)}
.t-meta{font-size:var(--fs-meta);line-height:var(--lh-meta);color:var(--mauve)}
/* Running copy is mauve. Ink is reserved for the lines that carry the point:
   what a statistic means (.stat__c) and the sentence that leads into a call
   to action (.sec-out). Both are classes, never inline, so the exception is
   discoverable here rather than buried in the markup. */
.muted{color:var(--mauve)}
.ink{color:var(--ink)}

.block-head{margin-bottom:48px}
/* a sub-heading inside a block keeps the same 48px before its content */
.block-h3{margin-bottom:48px}
/* the closing paragraph that carries a block's call to action */
.sec-out{margin-top:48px;max-width:var(--measure);color:var(--ink)}
/* a closing line and its button on one row; wraps to two on narrow screens */
.sec-ask{margin-top:48px;display:flex;flex-wrap:wrap;align-items:center;gap:14px 24px}
.sec-ask p{color:var(--ink);font-weight:var(--w-mid);max-width:none}
/* 28px when it follows the closing sentence, 48px when it stands alone
   after a block's content — as it now does in 02 Career Change */
.sec-out__cta{margin-top:28px}
.sec-out + .sec-out__cta{margin-top:28px}
.arc__brackets + .sec-out__cta{margin-top:48px}
/* a pause control sitting between a block opening and its marquee */
.sec-toggle{margin-bottom:28px}
.block-head .hr{margin-top:28px}
.block-sub{margin-top:16px;max-width:var(--measure)}

/* ==========================================================================
   Buttons & links

   ONE interactive style across the site — nav Contact, "See how", "Learn more",
   "Request a conversation". Nav-sized, sentence case, light grey at rest,
   Forest with Butter type on hover.
   ========================================================================== */
.btn-body{
  display:inline-flex;align-items:center;gap:8px;
  font-size:var(--fs-meta);font-weight:var(--w-base);line-height:1;
  padding:11px 16px;border-radius:2px;
  background:var(--grey-btn);color:var(--ink);
  transition:background .45s var(--ease),color .45s var(--ease);
}
.btn-body:hover,.btn-body:focus-visible{background:var(--dark);color:var(--on-dark)}

/* Variant used once, in the hero: the label stays bare and only the arrow
   carries the grey chip. */
.btn-arrow{display:inline-flex;align-items:center;gap:10px;
  font-size:var(--fs-meta);color:var(--ink)}
.btn-arrow__ico{display:grid;place-items:center;width:30px;height:30px;flex:none;
  background:var(--grey-btn);border-radius:2px;line-height:1;
  transition:background .45s var(--ease),color .45s var(--ease),transform .45s var(--ease)}
.btn-arrow:hover .btn-arrow__ico,.btn-arrow:focus-visible .btn-arrow__ico{
  background:var(--dark);color:var(--on-dark);transform:translateY(3px)}
.sec--dark .btn-body{background:rgba(246,244,233,.12);color:var(--on-dark)}

/* underline wipe — nothing at rest, grows on hover */
.wipe{
  background-image:linear-gradient(currentColor,currentColor);
  background-size:0% 1px;background-position:0 100%;background-repeat:no-repeat;
  padding-bottom:3px;
  transition:background-size .45s var(--ease);
}
a:hover .wipe,a:focus-visible .wipe,.wipe:hover,.wipe:focus-visible{background-size:100% 1px}

/* ==========================================================================
   Header
   ========================================================================== */
.head{position:fixed;inset-inline:0;top:0;z-index:200;height:var(--head-h);
  border-bottom:1px solid var(--rule);
  transition:background .45s var(--ease)}
.head.is-stuck{background:rgba(246,244,233,.94);backdrop-filter:blur(12px)}
.head__in{display:flex;align-items:center;justify-content:space-between;
  height:calc(var(--head-h) - 1px);gap:24px}
.brand{display:flex;align-items:center;position:relative;z-index:2}
.brand img{height:var(--logo-h);width:auto}
.nav{display:none;align-items:center;gap:28px}
.nav a,.nav button{font-size:var(--fs-meta);font-weight:var(--w-base)}
.burger{display:inline-flex;align-items:center;font-size:var(--fs-meta);
  padding:8px 4px;position:relative;z-index:2;
  transition:color .45s var(--ease)}
@media(min-width:1024px){ .nav{display:flex} .burger{display:none} }

/* --- mobile overlay: Forest ground, Butter type, 24px items (Lumena) ---- */
.menu{position:fixed;inset:0;z-index:150;background:var(--dark);color:var(--on-dark);
  display:flex;flex-direction:column;
  padding:var(--head-h) var(--pad) var(--pad);
  opacity:0;visibility:hidden;transition:opacity .45s var(--ease),visibility .45s var(--ease)}
.menu.is-open{opacity:1;visibility:visible}
.menu__rule{height:1px;background:var(--on-dark-rule);margin-bottom:40px}
.menu__links{display:flex;flex-direction:column;gap:18px;flex:1}
/* a, not just a: Contact opens the contact panel and so is a <button>. A
   selector matching only links leaves it at the inherited 16px beside its
   24px neighbours. Same trap as the footer. */
.menu__links a,.menu__links button{font-size:var(--fs-menu);font-weight:var(--w-base);
  line-height:1;color:var(--on-dark);text-align:left}
.menu__foot{border-top:1px solid var(--on-dark-rule);padding-top:20px}
.menu__foot a,.menu__foot button{font-size:var(--fs-meta);color:var(--on-dark)}
.menu.is-open ~ .head .burger,.head.menu-open .burger{color:var(--on-dark)}

/* ==========================================================================
   1 · Hero
   ========================================================================== */
.hero{padding-top:calc(var(--head-h) + 40px);padding-bottom:56px}
@media(min-width:1024px){
  .hero{padding-top:calc(var(--head-h) + 40px);padding-bottom:80px;
        min-height:100svh;display:flex;align-items:center}
}

/* Three rows. The headline sits beside the ring; the lead paragraph has the
   second row to itself on the right; the standfirst and the CTA share the
   third, one in each column. The standfirst runs to two lines and the pill is
   a single 30px control, so both are centred in that row: the row takes its
   height from the standfirst and the pill centres against it. */
.hero__grid{display:grid;gap:28px;width:100%}
@media(min-width:1024px){
  .hero__grid{
    grid-template-columns:1fr 1fr;
    grid-template-rows:1fr auto auto;
    column-gap:20px;row-gap:36px;
  }
  .hero__h1{grid-column:1;grid-row:1;align-self:start}
  #lattice-hero{grid-column:2;grid-row:1;align-self:center}
  .hero__stand{grid-column:1;grid-row:3;align-self:center}
  .hero__lead{grid-column:2;grid-row:2;align-self:end}
  .hero__cta{grid-column:2;grid-row:3;align-self:center}
}
/* Narrow: the standfirst leads, above the headline. */
@media(max-width:1023px){
  .hero__grid{display:flex;flex-direction:column;gap:28px}
  .hero__stand{order:1}
  .hero__h1{order:2}
  #lattice-hero{order:3}
  .hero__lead{order:4}
  .hero__cta{order:5}
}
.hero__h1{max-width:11ch}
.hero__stand{max-width:34ch;margin:0}
.hero__lead{max-width:34ch;margin:0}
.hero__cta{margin:0}
/* The hero is exactly one viewport tall, so a fixed-height canvas pushed the
   CTA below the fold on any laptop shorter than about 830px. The canvas now
   yields to the viewport: everything below it is fixed in height, so the
   drawing is the only thing that can give. */
#lattice-hero{width:100%;aspect-ratio:16/10;
  max-height:clamp(160px, calc(100svh - 470px), 360px)}
/* clamp, not min: the lower bound stops the drawing collapsing to nothing on
   a very short window. Below 1024px the hero is no longer one viewport tall,
   so this only governs laptops. */

/* ==========================================================================
   2 · Career tracks
   ========================================================================== */
#services{background:var(--white);padding-top:var(--sec-tight)}
.svc{display:grid;gap:0;border-top:1px solid var(--rule);margin-top:48px}
@media(min-width:900px){ .svc{grid-template-columns:1fr 1fr} }
.svc__col{display:flex;flex-direction:column;border-bottom:1px solid var(--rule);
  padding:40px 0}
@media(min-width:900px){
  .svc__col{padding-right:48px}
  .svc__col + .svc__col{border-left:1px solid var(--rule);padding-left:48px;padding-right:0}
}
.svc__num{font-size:var(--fs-meta);font-weight:var(--w-base);line-height:var(--lh-meta);color:var(--mauve);margin-bottom:12px}
.svc__t{margin-bottom:16px}
.svc__desc{margin-bottom:32px;color:var(--mauve)}
.svc__meta{border-top:1px solid var(--rule);margin-bottom:32px}
.svc__row{display:flex;flex-wrap:wrap;gap:8px 40px;justify-content:space-between;
  padding:18px 0;border-bottom:1px solid var(--rule)}
.svc__row dt{font-size:var(--fs-body);font-weight:var(--w-mid);color:var(--ink);flex:none}
.svc__row dd{margin:0;font-size:var(--fs-body);font-weight:var(--w-body);color:var(--mauve);
  text-align:left;max-width:46ch}
@media(min-width:560px){ .svc__row dd{text-align:right} }
.svc__cta{margin-top:auto}

/* ==========================================================================
   3 · Tabs
   ========================================================================== */
.tabs{display:grid;gap:32px}
@media(min-width:900px){ .tabs{grid-template-columns:minmax(0,360px) minmax(0,1fr);gap:64px;align-items:start} }
.tablist{display:flex;flex-direction:column;border-top:1px solid var(--rule-strong)}
.tab{
  display:flex;gap:14px;align-items:baseline;text-align:left;width:100%;
  padding:20px 16px;border-bottom:1px solid var(--rule-strong);
  font-size:var(--fs-stand);font-weight:var(--w-mid);line-height:var(--lh-stand);color:var(--mauve);
  transition:background .45s var(--ease),color .45s var(--ease);
}
.tab:hover,.tab:focus-visible{background:var(--dark);color:var(--on-dark)}
.tab[aria-selected="true"]{background:var(--dark);color:var(--on-dark)}
.tab__n{font-size:var(--fs-meta);font-weight:var(--w-base);opacity:.72;flex:none}
.tabpanels{min-height:240px}
.tabpanel{display:grid;gap:24px}
.tabpanel[hidden]{display:none}
.tabpanel dt{font-size:var(--fs-stand);font-weight:var(--w-mid);line-height:var(--lh-stand);margin-bottom:8px}
.tabpanel dd{margin:0;font-size:var(--fs-body);font-weight:var(--w-body);
  line-height:var(--lh-body);color:var(--mauve);max-width:var(--measure)}

/* ==========================================================================
   Client organisations — now sits in the footer row of block 3, reusing the
   .tabs grid so the roster lines up with the panel above it and the CTA lines
   up with the tab list.
   ========================================================================== */
.ec-foot{margin-top:56px;align-items:start}
.ec-foot > p{margin:0}
/* WCAG 2.2.2: anything moving for more than five seconds needs a way to stop
   it. The heading and its control share a row so the button reads as
   belonging to the strip below. */
.clients__head{display:flex;align-items:center;justify-content:space-between;
  gap:16px;flex-wrap:wrap;margin-bottom:18px}
.clients__h{font-size:var(--fs-stand);font-weight:var(--w-mid);
  line-height:var(--lh-stand);margin:0}
.clients{min-width:0}
.marquee{position:relative;overflow:hidden;
  -webkit-mask:linear-gradient(90deg,transparent,#000 4%,#000 96%,transparent);
          mask:linear-gradient(90deg,transparent,#000 4%,#000 96%,transparent)}
.marquee__track{display:flex;width:max-content;will-change:transform}
.marquee__group{display:flex;flex:0 0 auto;align-items:center;gap:56px;padding-right:56px}
.marquee__group li{font-size:var(--fs-body);font-weight:var(--w-body);
  color:var(--mauve);white-space:nowrap}
.marquee.is-paused .marquee__track{animation-play-state:paused}
@keyframes marq{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
.marquee__track--run{animation:marq 60s linear infinite}

/* Pause control — a marquee that cannot be stopped fails WCAG 2.2.2, since
   the text is moving for longer than five seconds. */
.mq-toggle{display:inline-flex;align-items:center;gap:8px;
  font-size:var(--fs-meta);font-weight:var(--w-base);line-height:1;
  padding:11px 16px;border-radius:2px;background:var(--grey-btn);color:var(--ink);
  transition:background .45s var(--ease),color .45s var(--ease)}
.mq-toggle:hover,.mq-toggle:focus-visible{background:var(--dark);color:var(--on-dark)}

/* ==========================================================================
   5 · Impact & growth
   ========================================================================== */
.stats{display:grid;gap:0;border-top:1px solid var(--rule);margin-top:8px}
/* a footnote to the figures: it qualifies the grid above it, so it sits
   under the closing rule rather than in the standfirst */
.stats__note{margin-top:14px;font-size:var(--fs-meta);line-height:var(--lh-meta);
  color:var(--mauve)}
@media(min-width:640px){ .stats{grid-template-columns:repeat(2,1fr)} }
@media(min-width:1100px){ .stats{grid-template-columns:repeat(4,1fr)} }
.stat{padding:36px 24px 36px 0;border-bottom:1px solid var(--rule);
  display:flex;flex-direction:column;gap:14px}
@media(min-width:640px){ .stat:nth-child(2n){padding-left:24px;border-left:1px solid var(--rule)} }
@media(min-width:1100px){
  .stat{padding-left:0}
  .stat + .stat{padding-left:24px;border-left:1px solid var(--rule)}
}
.stat__n{font-size:var(--fs-quote);line-height:var(--lh-display);font-weight:var(--w-mid);
  color:var(--ink);font-variant-numeric:tabular-nums}
.stat__n span{font-size:.55em}                 /* the % sign sits smaller */
.stat__c{font-size:var(--fs-body);line-height:var(--lh-body);font-weight:var(--w-body);
  color:var(--ink);max-width:var(--measure)}

/* ==========================================================================
   6 & 9 · Accordions
   ========================================================================== */
.acc{border-top:1px solid var(--rule-strong)}
.acc__item{border-bottom:1px solid var(--rule-strong)}
.acc__btn{display:flex;width:100%;gap:16px;align-items:baseline;justify-content:space-between;
  text-align:left;padding:22px 0;
  font-size:var(--fs-stand);font-weight:var(--w-mid);line-height:var(--lh-stand);
  transition:padding-left .45s var(--ease)}
.acc__btn:hover{padding-left:10px}
.acc__btn .ico{flex:none;font-size:var(--fs-stand);font-weight:var(--w-base);
  color:var(--mauve);transition:transform .45s var(--ease)}
.acc__btn[aria-expanded="true"] .ico{transform:rotate(45deg)}
.acc__n{font-size:var(--fs-meta);font-weight:var(--w-base);color:var(--mauve);
  margin-right:10px;flex:none}
.acc__panel{overflow:hidden;height:0;transition:height .6s var(--ease)}
.acc__inner{padding-bottom:26px;display:grid;gap:10px}
#moves .acc__inner li{font-size:var(--fs-stand);line-height:var(--lh-stand)}
/* "What she brings" takes the same square marker as the programme steps in
   02 Career Change. Scoped to #about: the transition rows in #moves are
   aligned into columns and a bullet in front of each would break that. */
#about .acc__inner li{padding-left:16px;position:relative}
#about .acc__inner li::before{content:"";position:absolute;left:0;top:.62em;
  width:5px;height:5px;background:var(--ink)}
.acc__inner li,.acc__inner p{font-size:var(--fs-body);line-height:var(--lh-body);
  font-weight:var(--w-body);color:var(--mauve);max-width:var(--measure)}
.moves{display:grid;gap:40px}
/* Right column sized to the animation, matching block 8. An even split
   left the panel with a void beside it. */
@media(min-width:1000px){ .moves{grid-template-columns:minmax(0,1fr) 420px;
  gap:64px;align-items:start} }
#ripple{width:min(100%,420px);aspect-ratio:1/1;max-height:420px}


/* ==========================================================================
   7 · Career change programme
   ========================================================================== */
.arc{display:grid;gap:28px;border-top:1px solid var(--rule);padding-top:26px;margin-top:48px}
@media(min-width:760px){ .arc{grid-template-columns:repeat(2,1fr);column-gap:40px} }
@media(min-width:1120px){ .arc{grid-template-columns:repeat(4,1fr);column-gap:32px} }
.arc__step{display:flex;flex-direction:column}
/* a hairline before step 04 marks where the fixed programme ends and the
   open-ended part begins. Only at four-across; below that the band labels
   carry the step numbers instead. */
@media(min-width:1120px){
  .arc__step--after{border-left:1px solid var(--rule);padding-left:32px;margin-left:-8px}
}
.arc__n{font-size:var(--fs-meta);line-height:1;color:var(--mauve);margin-bottom:8px}
.arc__t{font-size:var(--fs-stand);line-height:var(--lh-stand);font-weight:var(--w-mid);margin:0 0 14px}
.arc__list{display:grid;gap:10px}
.arc__list li{font-size:var(--fs-body);line-height:var(--lh-body);font-weight:var(--w-body);
  color:var(--mauve);padding-left:16px;position:relative}
.arc__list li::before{content:"";position:absolute;left:0;top:.62em;width:5px;height:5px;background:var(--ink)}

/* Which part is fixed and which continues. The step numbers are written into
   the labels so the mapping survives when the grid drops to two-across. */
.arc__brackets{display:grid;gap:14px;margin-top:26px}
@media(min-width:1120px){ .arc__brackets{grid-template-columns:repeat(4,1fr);column-gap:32px} }
.arc__band{border-top:1px solid var(--ink);padding-top:12px}
@media(min-width:1120px){ .arc__band--fixed{grid-column:1/4} .arc__band--open{grid-column:4/5} }
.arc__band b{display:block;font-size:var(--fs-body);line-height:var(--lh-stand);
  font-weight:var(--w-mid);color:var(--ink);margin-bottom:3px}
.arc__band span{font-size:var(--fs-meta);line-height:var(--lh-meta);color:var(--mauve)}

/* ==========================================================================
   8 · Career changes
   ========================================================================== */
.changes{display:grid;gap:48px}
/* The right column is sized to the animation rather than split evenly: at
   1fr 1fr the 420px panel left a 236px void beside itself. The rows take
   the reclaimed width, and the panel's right edge now lands on the page
   margin like everything else. */
@media(min-width:1000px){ .changes{grid-template-columns:minmax(0,1fr) 420px;
  gap:64px;align-items:start} }
.chg{border-top:1px solid var(--rule)}
.chg__row{padding:22px 0;border-bottom:1px solid var(--rule);
  transition:padding-left .45s var(--ease)}
.chg__row:hover{padding-left:10px}
.chg__t{font-size:var(--fs-stand);font-weight:var(--w-mid);line-height:var(--lh-stand);margin-bottom:7px}
/* Three tiers per row: what changed, what it achieved, how it was done.
   The outcome was previously the last clause of a middot list set in the
   same mauve as the method, so the achievement read as a footnote to the
   process. It now carries ink and weight; the method recedes to meta. */
.chg__win{font-size:var(--fs-body);line-height:var(--lh-body);font-weight:var(--w-mid);
  color:var(--ink);margin-bottom:5px;max-width:var(--measure)}
.chg__m{font-size:var(--fs-meta);line-height:var(--lh-meta);font-weight:var(--w-body);
  color:var(--mauve);max-width:var(--measure)}
/* sits higher in the block than the results list beside it */
/* The animation needs a vertical runway of its own: the sticky unit has to
   stay pinned long enough for all four transitions to play out while it is
   fully in view. Without the rail it is pinned for ~320px and most of the
   sequence happens while the canvas is sliding into or out of the viewport. */
.morph-rail{min-height:1180px}
@media(max-width:999px){ .morph-rail{min-height:0} }
/* Centred in the space below the fixed header rather than pinned near the
   top: at top:109 it sat with 40px above it and 326px below. The scroll
   length is rail minus unit height, so it does not depend on this offset
   and centring costs nothing. The max() keeps it clear of the header on
   short viewports, where it pins just beneath instead. */
#morph{position:sticky;
  top:max(calc(var(--head-h) + 16px), calc(var(--head-h)/2 + 50vh - 232px))}

/* one tick per transition, stacked vertically: shows how many there are and
   which one is arriving */
.morph__steps{list-style:none;display:flex;flex-direction:column;gap:6px;
  margin:22px 0 0;padding:0;width:26px}
.morph__steps li{height:2px;background:var(--rule-strong);opacity:.35;
  transition:opacity .45s var(--ease),background-color .45s var(--ease)}
.morph__steps li.is-on{background:var(--ink);opacity:1}
/* the archetype currently arriving. The object depicts it, so naming it
   is a description rather than a claim the drawing cannot keep. */
/* Subordinate to the statement below it: this names what is on screen right
   now, the line under the rule is what the block is actually saying. */
.morph__now{margin-top:18px;font-size:var(--fs-body);line-height:var(--lh-body);
  font-weight:var(--w-mid);color:var(--mauve)}
/* the drawing scales to min(width,height), so an over-wide canvas leaves the
   object stranded in a letterbox. Capping the width keeps the panel ~4:3. */
#morph-canvas{width:min(100%,420px);aspect-ratio:4/3;max-height:315px}  /* width, not max-width: a later rule sets max-width:100% on this id */

/* ==========================================================================
   9 · About
   ========================================================================== */
.about{display:grid;gap:48px}
@media(min-width:1000px){ .about{grid-template-columns:1.55fr 1fr;gap:64px;align-items:start} }
.about__side{display:flex;flex-direction:column;gap:12px;max-width:420px}
@media(min-width:1000px){ .about__side{position:sticky;top:calc(var(--head-h) + 40px);max-width:50%} }
.about__photo{width:100%;aspect-ratio:1/1;object-fit:cover;
  background:var(--rule-soft)}
.about__li{display:flex;align-items:center;justify-content:center;gap:10px;
  width:100%;padding:14px 16px;border:1px solid var(--rule);
  font-size:var(--fs-meta);color:var(--ink);white-space:nowrap;
  transition:background .45s var(--ease),color .45s var(--ease),border-color .45s var(--ease)}
.about__li:hover,.about__li:focus-visible{background:var(--dark);border-color:var(--dark);color:var(--on-dark)}
.about__li svg{width:16px;height:16px;fill:currentColor;flex:none}
.about__lead{max-width:34ch;margin-bottom:28px}
.about__body{display:grid;gap:18px;margin-bottom:48px}
.about__body p{font-size:var(--fs-body);line-height:var(--lh-body);font-weight:var(--w-body);
  color:var(--mauve);max-width:var(--measure)}
.about__brings{font-size:var(--fs-stand);font-weight:var(--w-mid);line-height:var(--lh-stand);margin-bottom:24px}

/* ==========================================================================
   10 · Testimonials
   ========================================================================== */
.quotes .marquee__group{align-items:stretch;gap:20px;padding-right:20px}
.quotes .marquee__group li{white-space:normal;font-size:inherit;color:inherit}
.quote{flex:0 0 auto;width:min(80vw,440px);padding:30px;
  box-shadow:inset 0 0 0 1px var(--rule);display:flex}
.quote p{font-size:var(--fs-stand);line-height:var(--lh-quote);font-weight:var(--w-mid);
  color:var(--ink);max-width:none}

/* ==========================================================================
   11 · Footer
   ========================================================================== */
.footer{background:var(--dark);color:var(--on-dark);padding-block:var(--sec) 32px}
.footer a,.footer button{color:rgba(246,244,233,.82);
  transition:color .45s var(--ease)}
.footer a:hover,.footer button:hover{color:var(--on-dark)}
.footer__top{margin-bottom:64px;max-width:24ch}
.footer__cols{display:grid;gap:36px;padding-bottom:48px}
@media(min-width:700px){ .footer__cols{grid-template-columns:repeat(4,1fr)} }
.footer__h{font-size:var(--fs-meta);font-weight:var(--w-base);
  color:var(--on-dark-soft);margin-bottom:16px}
.footer__cols li{margin-bottom:10px;font-size:var(--fs-meta)}
.footer__bot{display:flex;flex-wrap:wrap;gap:18px 32px;justify-content:space-between;
  align-items:center;padding-top:28px;border-top:1px solid var(--on-dark-rule)}
.footer__bot img{height:var(--logo-h);width:auto;filter:brightness(0) invert(1);opacity:.9}
.footer__legal{font-size:var(--fs-meta);color:var(--on-dark-soft)}

/* ==========================================================================
   Consent — built, dormant
   ========================================================================== */
.consent{position:fixed;left:var(--pad);bottom:var(--pad);z-index:250;max-width:420px;
  background:var(--dark);color:var(--on-dark);padding:26px;
  box-shadow:0 18px 48px -18px rgba(0,0,0,.5)}
.consent[hidden]{display:none}
.consent p{font-size:var(--fs-body);line-height:var(--lh-body);color:rgba(246,244,233,.82);margin-bottom:18px}
.consent__row{display:flex;flex-wrap:wrap;gap:10px}

/* ==========================================================================
   Reveals — hidden only under .js; ui.js force-reveals after 2.5s
   ========================================================================== */
.js .rv{opacity:0;transform:translateY(22px);
  transition:opacity .9s var(--ease),transform .9s var(--ease)}
.js .rv.in{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition-duration:.01ms!important}
  .js .rv{opacity:1!important;transform:none!important}
  .marquee{-webkit-mask:none;mask:none}
  .marquee__track{width:auto;flex-wrap:wrap}
  .marquee__group[aria-hidden="true"]{display:none}
  .marquee__group{flex-wrap:wrap}
  #morph,.about__side{position:static}
}

/* ==========================================================================
   Grid children must be allowed to shrink, or they push the page sideways
   ========================================================================== */
.hero__grid > *,.svc > *,.tabs > *,.clients > *,.stats > *,.moves > *,
.arc > *,.arc__brackets > *,.changes > *,.about > *,.footer__cols > *,
.legal > *,.pf__head > *{min-width:0}
#morph-canvas,#lattice-hero,#ripple{max-width:100%}

/* ==========================================================================
   Privacy page
   ========================================================================== */
.legal{display:grid;gap:48px;padding-top:24px}
/* Sticky ONLY where the contents is a sidebar. Below 900px the grid collapses
   to one column, so a sticky contents pins to the top of the viewport while
   the prose scrolls underneath it. With no background behind it the two
   render on top of each other and neither is readable. */
.toc{border-top:1px solid var(--rule)}
@media(min-width:900px){
  .legal{grid-template-columns:minmax(0,260px) minmax(0,1fr);gap:64px;align-items:start}
  .toc{position:sticky;top:calc(var(--head-h) + 32px)}
}
.toc a{display:block;padding:12px 0;border-bottom:1px solid var(--rule);
  font-size:var(--fs-meta);color:var(--mauve);
  transition:padding-left .45s var(--ease),color .45s var(--ease)}
.toc a:hover,.toc a.is-active{padding-left:8px;color:var(--ink)}
/* Headings need their own leading. Without it they inherit the body ratio
   of 1.55, so a 48px heading gets a 74px line box and a wrapped heading
   reads as two disconnected lines. The .t-* utility classes set this;
   these element selectors did not. */
.prose h2{font-size:var(--fs-h2);line-height:var(--lh-h2);margin:56px 0 16px}
.prose h2:first-child{margin-top:0}
.prose h3{font-size:var(--fs-stand);line-height:var(--lh-stand);margin:32px 0 10px}
.prose p,.prose li{font-size:var(--fs-body);line-height:var(--lh-body);color:var(--mauve);
  max-width:var(--measure);margin-bottom:12px}
.prose ul{list-style:disc;padding-left:20px;margin-bottom:16px}

/* ==========================================================================
   Header while the mobile overlay is open: the bar sits above the Forest
   ground, so the wordmark inverts and the rule goes light.
   ========================================================================== */
.head.menu-open{background:transparent;backdrop-filter:none;border-bottom-color:var(--on-dark-rule)}
.head.menu-open .brand img{filter:brightness(0) invert(1)}
.head.menu-open .burger{color:var(--on-dark)}

/* ==========================================================================
   Client roster: accepts either styled wordmarks (current) or logo files.
   Drop SVGs into assets/img/logos/ and swap the <li> text for an <img> —
   no other change needed. Logos render greyscale at a fixed cap height so
   wildly different source dimensions still sit on one optical line.
   ========================================================================== */
/* brightness(0) flattens whatever colour the supplied file happens to be to
   solid black while keeping its alpha; the opacity then lifts it to a dark
   grey on the bone ground. grayscale(1) would NOT do this — it preserves
   luminance, so a yellow mark stays pale and a black one stays black, and
   the strip reads as a jumble of greys rather than one tone. */
.marquee__group img{
  height:26px;width:auto;max-width:150px;object-fit:contain;
  filter:brightness(0);opacity:.72;
  transition:opacity .45s var(--ease);
}
.marquee__group li:hover img{opacity:1}

/* ==========================================================================
   Small components that previously carried inline styles
   ========================================================================== */
/* The line under each animation is the block's conclusion, not a caption. It
   had been set exactly like .block-sub (16/400/mauve), which is the voice the
   site uses for disclaimers, so the most important sentence in the block read
   as the least important. A rule above it and standfirst size make it a
   statement without raising its voice. */
.morph__cap,.ripple__cap{margin-top:26px;padding-top:18px;
  border-top:1px solid var(--rule);max-width:none;
  font-size:var(--fs-stand);line-height:var(--lh-stand);
  font-weight:var(--w-mid);color:var(--ink)}
.consent h2{margin-bottom:12px;color:var(--on-dark)}

/* ==========================================================================
   Transitions — the before/after rows in both results blocks

   The right-hand side is the result, so it carries ink and the heavier
   weight; the starting role recedes to mauve. Same size either side, so the
   distinction is made by colour and weight rather than by adding a step to
   the type scale.
   ========================================================================== */
/* Where there is room, the rows align into columns: every starting role in
   one column, every arrow in the next, every destination in the third. The
   arrows then form a single vertical line and the outcomes read as a stack
   rather than as fifteen separate sentences. Container query rather than a
   media query, because what matters is the width of the list, not the
   viewport — the block is half-width above 1000px. Falls back to inline
   flow wherever there isn't room. */
/* the container must sit ABOVE the element the query restyles: a rule inside
   @container is matched against the element's ancestor container, never
   against itself, so .chg would never have picked up its own grid */
#moves .acc,.chg-wrap{container-type:inline-size}
@container (min-width:560px){
  #moves .acc__inner{grid-template-columns:auto auto 1fr;column-gap:0}
  #moves .acc__inner li{display:grid;grid-column:1/-1;grid-template-columns:subgrid;
    align-items:baseline;max-width:none}
  #moves .tr__x{margin:0 .8em}

  /* the career-change rows carry a metrics line beneath, so the grid runs
     two levels deep: the row inherits the columns, the transition sits on
     them, and the metrics span the full width underneath */
  .chg{display:grid;grid-template-columns:auto auto 1fr;column-gap:0}
  .chg__row{grid-column:1/-1;display:grid;grid-template-columns:subgrid}
  .chg__t{grid-column:1/-1;display:grid;grid-template-columns:subgrid;align-items:baseline}
  .chg__win,.chg__m{grid-column:1/-1}
  .chg .tr__x{margin:0 .8em}
}

.tr__a{color:var(--mauve);font-weight:var(--w-body)}
.tr__x{color:var(--mauve);margin:0 .45em;font-weight:var(--w-body)}
.tr__b{color:var(--ink);font-weight:var(--w-mid)}

/* ==========================================================================
   Contact panel

   A right-hand panel on desktop, full screen below 600px. Built on <dialog>,
   so the backdrop, focus trap and Escape come from the platform rather than
   from script. The square progress marks reuse the site's own motif.
   ========================================================================== */
.cf{border:0;padding:0;margin:0;max-width:none;max-height:none;
  width:100%;height:100%;background:transparent;overflow:visible;
  inset:0;color:var(--ink)}
.cf::backdrop{background:rgba(29,29,29,.34);opacity:0;
  transition:opacity .34s var(--ease)}
.cf.is-in::backdrop{opacity:1}
html.cf-open{overflow:hidden}

.cf__panel{position:fixed;top:0;right:0;bottom:0;width:min(100%,520px);
  background:var(--bone);display:flex;flex-direction:column;
  box-shadow:-1px 0 0 var(--rule);
  transform:translateX(100%);transition:transform .38s var(--ease)}
.cf.is-in .cf__panel{transform:none}
@media(max-width:599px){ .cf__panel{width:100%;box-shadow:none} }

.cf__head{display:flex;align-items:center;justify-content:space-between;
  padding:20px var(--pad);border-bottom:1px solid var(--rule);flex:none}
.cf__eyebrow{font-size:var(--fs-meta);line-height:1;color:var(--mauve);margin:0}
.cf__x{display:grid;place-items:center;width:36px;height:36px;border-radius:2px;
  background:var(--grey-btn);color:var(--ink);
  transition:background .45s var(--ease),color .45s var(--ease)}
.cf__x:hover,.cf__x:focus-visible{background:var(--dark);color:var(--on-dark)}
.cf__x svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round}

/* The panel drives every state through the hidden attribute, and an author
   display rule silently beats the UA's display:none. Without this the
   confirmation screen sat visible underneath the live form. */
.cf [hidden]{display:none!important}
.cf__body,.cf__done{padding:26px var(--pad) 34px;overflow-y:auto;
  -webkit-overflow-scrolling:touch;flex:1}
.cf__done{display:flex;flex-direction:column;align-items:flex-start;gap:14px;
  justify-content:center}

.cf__h{font-size:var(--fs-lead);line-height:var(--lh-lead);font-weight:var(--w-mid);
  margin:0 0 8px;text-wrap:balance}
.cf__sub{font-size:var(--fs-body);line-height:var(--lh-body);color:var(--mauve);
  margin:0 0 22px;max-width:44ch}
.cf__done .cf__sub{margin-bottom:8px}
.cf__h3{font-size:var(--fs-stand);line-height:var(--lh-stand);font-weight:var(--w-mid);
  margin:26px 0 12px;padding-top:20px;border-top:1px solid var(--rule)}

/* ---- the two paths ---- */
.cf__paths{display:grid;gap:10px;margin-bottom:26px}
.cf__path{display:block;text-align:left;padding:16px 18px;border:1px solid var(--rule);
  border-radius:2px;background:transparent;color:var(--ink);
  transition:border-color .3s var(--ease),background .3s var(--ease)}
.cf__path b{display:block;font-size:var(--fs-body);font-weight:var(--w-mid);
  margin-bottom:3px}
.cf__path span{display:block;font-size:var(--fs-meta);line-height:1.45;color:var(--mauve)}
.cf__path:hover{border-color:var(--rule-strong)}
.cf__path.is-on{border-color:var(--ink);background:var(--white)}
.cf__path:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* ---- square progress: the site's motif, not dots ---- */
.cf__steps{display:flex;gap:6px;margin-bottom:22px}
.cf__steps i{width:9px;height:9px;border:1px solid var(--rule-strong);
  transition:background .4s var(--ease),border-color .4s var(--ease)}
.cf__steps i.is-on{background:var(--ink);border-color:var(--ink)}

/* ---- questions ---- */
.cf__q{border:0;padding:0;margin:0 0 22px;min-width:0}
.cf__label{display:block;font-size:var(--fs-body);font-weight:var(--w-mid);
  line-height:1.4;margin-bottom:9px;padding:0}
.cf__opt-tag{font-weight:var(--w-body);color:var(--mauve)}
.cf__opts{display:flex;flex-wrap:wrap;gap:8px}
.cf__opt{position:relative}
.cf__opt input{position:absolute;opacity:0;width:0;height:0}
.cf__opt span{display:block;padding:9px 14px;border:1px solid var(--rule);
  border-radius:2px;font-size:var(--fs-meta);line-height:1.2;color:var(--ink);
  cursor:pointer;transition:border-color .3s var(--ease),background .3s var(--ease)}
.cf__opt span:hover{border-color:var(--rule-strong)}
.cf__opt input:checked + span{border-color:var(--ink);background:var(--ink);
  color:var(--bone)}
.cf__opt input:focus-visible + span{outline:2px solid var(--ink);outline-offset:2px}

/* ---- fields ---- */
.cf__field{margin:0 0 16px}
.cf__input{display:block;width:100%;padding:11px 12px;border:1px solid var(--rule);
  border-radius:2px;background:var(--white);color:var(--ink);
  font:inherit;font-size:var(--fs-body);line-height:1.4;
  transition:border-color .3s var(--ease)}
.cf__input:hover{border-color:var(--rule-strong)}
.cf__input:focus{outline:none;border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.cf__ta{resize:vertical;min-height:96px}
.cf__input::placeholder{color:var(--mauve);opacity:.85}

.cf__note a{color:var(--ink);text-decoration:underline;text-underline-offset:2px}
.cf__note{font-size:var(--fs-meta);line-height:1.5;color:var(--mauve);
  margin:-4px 0 0;padding:10px 12px;background:var(--white);
  border-left:2px solid var(--rule-strong);max-width:46ch}

/* ---- consent + submit ---- */
.cf__foot{margin-top:26px;padding-top:20px;border-top:1px solid var(--rule)}
/* padding, not just the 17px box: the label is the real target and at
   21px tall it fell under the 24px WCAG 2.2 minimum */
.cf__consent{display:flex;gap:11px;align-items:flex-start;padding:6px 0;
  font-size:var(--fs-meta);line-height:1.5;color:var(--ink);cursor:pointer}
.cf__consent input{flex:none;width:17px;height:17px;margin:1px 0 0;accent-color:var(--dark)}
.cf__consent a{text-decoration:underline;text-underline-offset:2px}
.cf__err{margin:14px 0 0;font-size:var(--fs-meta);line-height:1.4;color:var(--signal)}
.cf__submit{display:inline-flex;align-items:center;gap:8px;margin-top:18px;
  padding:13px 20px;border-radius:2px;background:var(--dark);color:var(--on-dark);
  font-size:var(--fs-meta);line-height:1;
  transition:opacity .3s var(--ease)}
.cf__submit:hover,.cf__submit:focus-visible{opacity:.88}
.cf__submit[disabled]{opacity:.55;cursor:default}
.cf__submit.is-sending span:first-child::after{content:'\2026'}

/* the honeypot: off-screen rather than display:none, since some bots skip
   anything that is not rendered at all */
.cf__hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

@media (prefers-reduced-motion:reduce){
  .cf__panel{transition:none}
  .cf::backdrop{transition:none}
}

/* ==========================================================================
   11 · Confidentiality

   Three promises, set at standfirst size so they read as commitments rather
   than as body copy. The square marker is the logo's motif, used here because
   the list is genuinely a set of discrete undertakings.
   ========================================================================== */
.conf__list{list-style:none;margin:40px 0 0;padding:0;display:grid;gap:20px;
  border-top:1px solid var(--rule);padding-top:32px}
@media(min-width:900px){ .conf__list{grid-template-columns:repeat(3,1fr);gap:40px} }
.conf__list li{position:relative;padding-left:20px;
  font-size:var(--fs-stand);line-height:var(--lh-stand);font-weight:var(--w-mid);
  color:var(--ink);max-width:34ch}
.conf__list li::before{content:"";position:absolute;left:0;top:.5em;
  width:7px;height:7px;border:1.5px solid var(--ink)}
