/* NovusConfido homepage. Requires tokens.css. */

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;font-family:var(--font);font-size:var(--t-body);
  line-height:1.7;color:var(--c-mid);background:var(--c-white);
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
h1,h2,h3,h4,h5,h6{margin:0;color:var(--c-dark)}
p{margin:0}
a{color:inherit}
img{max-width:100%;display:block}

h1{font-size:var(--t-h1);font-weight:700;line-height:1.08;letter-spacing:-.035em}
h2{font-size:var(--t-h2);font-weight:700;line-height:1.14;letter-spacing:-.03em}
h3{font-size:var(--t-h3);font-weight:700;line-height:1.2;letter-spacing:-.022em}
h4{font-size:var(--t-h4);font-weight:600;line-height:1.25;letter-spacing:-.012em}

.overline{
  font-size:var(--t-caption);font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--c-blue);margin:0 0 var(--s-sm);
  display:flex;align-items:center;gap:12px;
}
.overline::before{
  content:"";width:28px;height:2px;background:currentColor;
  border-radius:2px;transform-origin:left;
}
.body-lg{font-size:var(--t-body-lg);line-height:1.65}
:focus-visible{outline:3px solid var(--c-blue);outline-offset:3px;border-radius:6px}

.wrap{width:100%;max-width:var(--w-content);margin:0 auto;padding:0 var(--s-md)}
.reading{max-width:var(--w-reading)}

/* Every section shares the same rhythm. Nothing is taller than anything else. */
.section{padding:var(--s-3xl) 0;position:relative}
.section--surface{background:var(--c-surface)}
.section--dark{background:var(--c-darker);color:rgba(255,255,255,.74)}
.section--dark h1,.section--dark h2,.section--dark h3,.section--dark h4{color:#fff}
.section--dark .overline{color:var(--c-blue-light)}
@media(max-width:767px){.section{padding:var(--s-2xl) 0}}

/* ============================================================
   SCROLL PROGRESS — the only fixed element on the page
   ============================================================ */
.prog{position:fixed;top:0;left:0;height:3px;width:0;background:var(--c-blue);z-index:99}

/* ============================================================
   BUTTONS
   ============================================================ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--font);font-size:var(--t-body);font-weight:600;
  line-height:1.2;text-decoration:none;padding:16px 30px;
  border-radius:var(--r-button);border:2px solid transparent;cursor:pointer;
  transition:background .35s var(--ease),transform .35s var(--ease),box-shadow .35s var(--ease),color .35s var(--ease);
}
.btn--primary{background:var(--c-blue);color:#fff;box-shadow:0 6px 18px rgba(10,116,218,.28)}
.btn--primary:hover{background:var(--c-blue-dark);transform:translateY(-2px) scale(1.02);box-shadow:0 12px 28px rgba(10,116,218,.34)}
.btn--secondary{background:transparent;color:var(--c-blue);border-color:rgba(10,116,218,.35)}
.btn--secondary:hover{border-color:var(--c-blue);background:var(--c-blue-wash);transform:translateY(-2px) scale(1.02)}
.section--dark .btn--secondary{color:#fff;border-color:rgba(255,255,255,.28)}
.section--dark .btn--secondary:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.6)}

/* Astra prints an inline rule site-wide: a:hover, a:focus{color:...}. It is
   (0,1,1) and matches every <a>, including buttons. A button's colour is set
   on its base class at (0,1,0), which loses — so the colour has to be stated
   again for the hover and focus states, where the selector is (0,2,0) and wins.
   Astra's rule carries no !important, so specificity alone is enough. */
.btn--primary:hover,
.btn--primary:focus{color:var(--c-white)}
.btn--secondary:hover,
.btn--secondary:focus{color:var(--c-blue)}
.section--dark .btn--secondary:hover,
.section--dark .btn--secondary:focus{color:var(--c-white)}

.btn-row{display:flex;flex-wrap:wrap;gap:var(--s-sm);margin-top:var(--s-xl)}

.tlink{
  display:inline-flex;align-items:center;gap:10px;font-weight:600;
  color:var(--c-blue);text-decoration:none;
  border-bottom:2px solid transparent;padding-bottom:3px;
  transition:border-color .3s var(--ease),gap .3s var(--ease);
}
.tlink:hover{border-bottom-color:var(--c-blue);gap:16px}

/* ============================================================
   HEADER
   ============================================================ */
.hdr{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.82);backdrop-filter:blur(16px);
  border-bottom:1px solid transparent;transition:border-color .3s var(--ease)}
.hdr.is-stuck{border-bottom-color:var(--c-border)}
.hdr__in{display:flex;align-items:center;justify-content:space-between;height:74px}
.logo{font-weight:800;font-size:1.15rem;letter-spacing:-.025em;color:var(--c-dark);text-decoration:none}
.logo span{color:var(--c-blue)}
.nav{display:flex;align-items:center;gap:var(--s-lg)}
.nav a{font-size:var(--t-small);font-weight:600;color:var(--c-mid);text-decoration:none;transition:color .3s}
.nav a:hover{color:var(--c-blue)}
.nav .btn{padding:11px 22px;font-size:var(--t-small)}
/* The nav's own link colour must not reach the button inside it. `.nav a:hover`
   is (0,2,1), which also beats the generic button rules above, so the nav needs
   its own (0,3,0) version. Specificity does the work; no !important needed. */
.nav .btn--primary,
.nav .btn--primary:hover,
.nav .btn--primary:focus{color:var(--c-white)}
.navtog{display:none;background:none;border:0;padding:8px;cursor:pointer}
.navtog span{display:block;width:22px;height:2px;background:var(--c-dark);margin:5px 0}
/* ------------------------------------------------------------
   MOBILE MENU

   The panel is anchored directly beneath the header and slides
   down out of it, rather than travelling from above the page.

   translateY(-100%) moves it exactly its own height upwards,
   so it sits flush against the header's underside while closed.
   The parent clips it, so nothing shows through the header.
   ------------------------------------------------------------ */

@media (max-width:1024px){

  .hdr{
    position:sticky;
    top:0;
    z-index:50;
    overflow:visible;
  }

  /* Clipping layer. Sits under the header, hides the panel
     while it is closed, and never intercepts clicks. */
  .hdr::after{
    content:"";
    position:absolute;
    top:100%;
    left:0;
    right:0;
    height:100vh;
    overflow:hidden;
    pointer-events:none;
  }

  .nav{
    position:absolute;
    top:100%;
    left:0;
    right:0;
    z-index:-1;

    display:flex;
    flex-direction:column;
    align-items:flex-start;
    gap:var(--s-md);

    background:var(--c-white);
    padding:var(--s-lg) var(--s-md);
    border-bottom:1px solid var(--c-border);
    box-shadow:var(--sh-md);

    transform:translateY(-100%);
    opacity:0;
    visibility:hidden;
    transition:transform var(--dur) var(--ease),
               opacity var(--dur) var(--ease),
               visibility 0s linear var(--dur);
  }

  .nav.is-open{
    transform:translateY(0);
    opacity:1;
    visibility:visible;
    transition:transform var(--dur) var(--ease),
               opacity var(--dur) var(--ease),
               visibility 0s;
  }

  .navtog{display:block}
}

@media (prefers-reduced-motion:reduce){
  .nav{transition:none !important}
}

/* ============================================================
   CHAPTER LABEL — gives the page a sense of progress
   ============================================================ */
.chap{
  font-size:var(--t-caption);font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--c-light);margin-bottom:var(--s-xs);
}
.section--dark .chap{color:rgba(255,255,255,.42)}

/* ============================================================
   1 · HERO
   ============================================================ */
.hero{
  padding:var(--s-3xl) 0;position:relative;overflow:hidden;
  background:
    radial-gradient(900px 520px at 82% 12%,rgba(10,116,218,.10),transparent 62%),
    radial-gradient(700px 460px at 6% 88%,rgba(10,116,218,.06),transparent 60%),
    var(--c-white);
}
/* VIDEO SLOT A — hero ambient loop. Sits behind everything, very low opacity. */
.hero__video{position:absolute;inset:0;overflow:hidden;z-index:0;opacity:.18;pointer-events:none}
.hero__video video{width:100%;height:100%;object-fit:cover}
.hero__mask{position:absolute;inset:0;z-index:1;
  background:linear-gradient(to bottom,rgba(255,255,255,.55),rgba(255,255,255,.9))}
.hero .wrap{position:relative;z-index:2}
.hero__grid{display:grid;grid-template-columns:1.1fr .9fr;gap:var(--s-2xl);align-items:center}
.hero h1{margin-bottom:var(--s-md);max-width:17ch}
.hero .body-lg{max-width:50ch}

/* Glass card — the framework, previewed */
.stack{
  background:rgba(255,255,255,.62);backdrop-filter:blur(18px);
  border:1px solid rgba(255,255,255,.9);
  box-shadow:var(--sh-lg);border-radius:var(--r-image);
  padding:var(--s-lg);
}
.stack__t{font-size:var(--t-caption);font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--c-light);margin-bottom:var(--s-md)}
.stack__row{display:flex;align-items:center;gap:var(--s-md);padding:14px 16px;
  border-radius:12px;border:1px solid transparent;transition:all .4s var(--ease)}
.stack__row + .stack__row{margin-top:6px}
.stack__row:hover{background:#fff;border-color:var(--c-border)}
.stack__n{font-size:var(--t-caption);font-weight:700;color:var(--c-light);font-variant-numeric:tabular-nums}
.stack__label{font-size:var(--t-small);font-weight:600;color:var(--c-dark)}
.stack__row--hit{background:#fff;border-color:rgba(10,116,218,.4);box-shadow:var(--sh-sm)}
.stack__row--hit .stack__n{color:var(--c-blue)}
.stack__tag{margin-left:auto;font-size:var(--t-caption);font-weight:700;color:var(--c-blue);white-space:nowrap}
.stack__cap{margin-top:var(--s-md);font-size:var(--t-caption);color:var(--c-light)}
@media(max-width:1024px){.hero__grid{grid-template-columns:1fr;gap:var(--s-xl)}}

/* ============================================================
   2 · THE PROBLEM — claims as cards with animated markers
   ============================================================ */
.claims{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s-sm);margin:var(--s-xl) 0}
.claim{
  background:#fff;border:1px solid var(--c-border);border-radius:var(--r-card);
  padding:var(--s-md) var(--s-lg);display:flex;align-items:flex-start;gap:14px;
  box-shadow:var(--sh-sm);transition:transform .4s var(--ease),box-shadow .4s var(--ease);
}
.claim:hover{transform:translateY(-3px);box-shadow:var(--sh-md)}
.claim__dot{
  flex:0 0 10px;height:10px;border-radius:50%;background:var(--c-blue);margin-top:9px;
  transform:scale(0);transition:transform .5s var(--ease) .15s;
}
.in .claim__dot,.claim.in .claim__dot{transform:scale(1)}
.claim p{font-size:var(--t-body);font-weight:600;color:var(--c-dark);line-height:1.45}
@media(max-width:767px){.claims{grid-template-columns:1fr}}

.verdict{font-size:var(--t-h4);font-weight:700;color:var(--c-dark);line-height:1.3;margin-top:var(--s-lg)}
.verdict em{font-style:normal;color:var(--c-blue)}

/* ============================================================
   3 · HOW I THINK — dark, with video slot behind
   ============================================================ */
.dark-media{position:absolute;inset:0;overflow:hidden;z-index:0;opacity:.30}
.dark-media video{width:100%;height:100%;object-fit:cover}
.dark-media::after{content:"";position:absolute;inset:0;
  background:linear-gradient(120deg,var(--c-darker) 18%,rgba(11,18,32,.72) 60%,rgba(11,18,32,.9))}
.section--dark .wrap{position:relative;z-index:1}

.glass{
  background:rgba(255,255,255,.06);backdrop-filter:blur(16px);
  border:1px solid rgba(255,255,255,.14);border-radius:var(--r-image);
  padding:var(--s-xl);
}
.quote p{font-size:var(--t-h3);font-weight:600;line-height:1.32;color:#fff;letter-spacing:-.02em}
.think__grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-2xl);align-items:start}
@media(max-width:1024px){.think__grid{grid-template-columns:1fr;gap:var(--s-xl)}}

/* ============================================================
   4 · THE ARCHITECTURE
   ============================================================ */
.arch__grid{display:grid;grid-template-columns:340px 1fr;gap:var(--s-2xl);align-items:start;margin-top:var(--s-2xl)}
.arch__nav{position:sticky;top:110px;display:flex;flex-direction:column;gap:4px}
.arch__navtitle{font-size:var(--t-caption);font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--c-light);margin-bottom:var(--s-md)}

/* Astra styles every <button> on the site. These resets have to be loud
   enough to beat it, hence the !important. This was the blue-blocks bug. */
.arch__item{
  all:unset;
  display:flex !important;gap:16px;align-items:flex-start;
  width:100%;box-sizing:border-box;cursor:pointer;
  font-family:var(--font) !important;text-align:left !important;
  background:transparent !important;color:inherit !important;
  border:0 !important;border-left:2px solid var(--c-border) !important;
  border-radius:0 12px 12px 0 !important;
  padding:14px 18px !important;box-shadow:none !important;
  transition:background .35s var(--ease),border-color .35s var(--ease);
}
.arch__item:hover{background:#fff !important}
.arch__item.is-active{
  background:#fff !important;
  border-left-color:var(--c-blue) !important;
  box-shadow:var(--sh-sm) !important;
}
.arch__n{font-size:var(--t-caption);font-weight:700;color:var(--c-light);padding-top:3px;
  font-variant-numeric:tabular-nums;transition:color .35s}
.arch__item.is-active .arch__n{color:var(--c-blue)}
.arch__q{font-size:var(--t-small);font-weight:600;color:var(--c-light);line-height:1.4;transition:color .35s}
.arch__item.is-active .arch__q{color:var(--c-dark)}

.arch__panels{display:flex;flex-direction:column;gap:var(--s-xl)}
.arch__panel{
  scroll-margin-top:130px;background:#fff;border:1px solid var(--c-border);
  border-radius:var(--r-image);padding:var(--s-xl);box-shadow:var(--sh-sm);
  display:grid;grid-template-columns:1fr 200px;gap:var(--s-lg);align-items:start;
}
.arch__pn{font-size:var(--t-caption);font-weight:700;letter-spacing:.12em;color:var(--c-blue);margin-bottom:10px}
.arch__panel h3{margin-bottom:12px;max-width:18ch}
.lbl{display:inline-block;font-size:var(--t-caption);font-weight:600;color:var(--c-blue);
  background:var(--c-blue-wash);padding:5px 14px;border-radius:999px;margin-bottom:var(--s-md)}
.arch__panel p + p{margin-top:14px}
.sting{color:var(--c-dark);font-weight:600}
@media(max-width:1024px){
  .arch__grid{grid-template-columns:1fr}
  .arch__nav{display:none}
  .arch__panel{grid-template-columns:1fr;padding:var(--s-lg)}
}

/* How I work */
.steps{margin-top:var(--s-3xl);border-top:1px solid var(--c-border);padding-top:var(--s-2xl)}
.steps__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-sm);margin-top:var(--s-xl)}
.step{
  background:#fff;border:1px solid var(--c-border);border-radius:var(--r-card);
  padding:var(--s-lg);display:flex;flex-direction:column;box-shadow:var(--sh-sm);
  transition:transform .45s var(--ease),box-shadow .45s var(--ease),border-color .45s var(--ease);
}
.step:hover{transform:translateY(-4px);box-shadow:var(--sh-md);border-color:rgba(10,116,218,.4)}
.step__n{font-size:2rem;font-weight:800;color:var(--c-blue-light);line-height:1;margin-bottom:10px}
.step h4{font-size:var(--t-h6);margin-bottom:8px}
.step p{font-size:var(--t-small)}
.step__out{margin-top:auto;padding-top:var(--s-md);font-size:var(--t-caption);
  color:var(--c-light);font-weight:600;border-top:1px solid var(--c-border)}
.step__out::before{content:"→ ";color:var(--c-blue)}
@media(max-width:1024px){.steps__grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.steps__grid{grid-template-columns:1fr}}

/* ============================================================
   6 · WHAT I BUILD — surface section so white cards read as cards
   ============================================================ */
.builds{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-md);margin-top:var(--s-xl)}
.build{
  background:#fff;border:1px solid var(--c-border);border-radius:var(--r-card);
  padding:0 0 var(--s-lg);overflow:hidden;box-shadow:var(--sh-sm);
  transition:transform .45s var(--ease),box-shadow .45s var(--ease);
}
.build:hover{transform:translateY(-4px);box-shadow:var(--sh-md)}
.build__body{padding:0 var(--s-lg)}
.build h4{font-size:var(--t-h6);margin:var(--s-md) 0 10px}
.build h4 .if{color:var(--c-blue)}
.build p{font-size:var(--t-small)}
@media(max-width:1024px){.builds{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.builds{grid-template-columns:1fr}}

.builds__close{margin-top:var(--s-xl);max-width:var(--w-reading);padding:var(--s-lg);
  background:#fff;border:1px solid var(--c-border);border-left:3px solid var(--c-blue);
  border-radius:0 var(--r-card) var(--r-card) 0;box-shadow:var(--sh-sm)}

/* ============================================================
   7 · WHY ME
   ============================================================ */
.why__grid{display:grid;grid-template-columns:.85fr 1.15fr;gap:var(--s-2xl);align-items:start}
.why__item{padding:var(--s-md) 0 var(--s-md) var(--s-md);border-left:2px solid var(--c-border);
  transition:border-color .4s var(--ease)}
.why__item:hover{border-left-color:var(--c-blue)}
.why__item h4{font-size:var(--t-h6);margin-bottom:6px}
.why__item p{font-size:var(--t-small)}
@media(max-width:1024px){.why__grid{grid-template-columns:1fr;gap:var(--s-xl)}}

/* ============================================================
   9 · START A CONVERSATION
   ============================================================ */
.next__grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-2xl);align-items:start}
.nstep{display:flex;gap:var(--s-md);align-items:flex-start;padding:var(--s-md) 0}
.nstep + .nstep{border-top:1px solid rgba(255,255,255,.1)}
.nstep__n{flex:0 0 42px;height:42px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);
  font-size:var(--t-caption);font-weight:700;color:var(--c-blue-light)}
.nstep h4{font-size:var(--t-h6);margin-bottom:2px}
.nstep p{font-size:var(--t-small)}
@media(max-width:1024px){.next__grid{grid-template-columns:1fr;gap:var(--s-xl)}}

/* ============================================================
   CONTACT PAGE
   ============================================================ */

/* Form left, steps panel right. The panel is sticky so "what happens
   next" stays readable at the point someone decides whether to finish
   the form, rather than only before they start it. */
.contact__grid{display:grid;grid-template-columns:1.38fr 1fr;gap:var(--s-2xl);align-items:start}
.contact__aside{position:sticky;top:110px}

/* The hero reuses the same grid, so its two columns line up with the form and
   panel below. Centred rather than top-aligned — the image is a solid block and
   sits better level with the text than hard against the chapter label. */
.hero .contact__grid{align-items:center}

/* The light-background counterpart to .glass, which is dark-only and reads as
   a dirty grey box on white or surface. Used by the contact aside and by
   Chapter 06 on the homepage. */
.panel{
  background:var(--c-white);border:1px solid var(--c-border);
  border-radius:var(--r-card);padding:var(--s-lg);box-shadow:var(--sh-sm);
}

/* .nstep is written for dark sections. These recolour it for the panel. */
.panel .nstep + .nstep{border-top-color:var(--c-border)}
.panel .nstep__n{
  background:var(--c-blue-wash);border-color:rgba(10,116,218,.25);color:var(--c-blue);
}
.panel .nstep h4{color:var(--c-dark)}
.panel .nstep p{color:var(--c-mid)}

/* The alternative routes, folded in under the submit button. A rule separates
   them from the form without needing a section of their own. */
/* Sits outside .contact__grid, so the margin replaces the row gap it used to
   get from the grid. It must stay outside — as a grid item it gave the sticky
   panel a second row to travel through, and the panel rode over it. */
.form-alt{
  margin-top:var(--s-2xl);
  padding-top:var(--s-md);
  border-top:1px solid var(--c-border);
  font-size:var(--t-small);color:var(--c-light);line-height:1.7;
}
/* Colour stated again on hover and focus, or Astra's inline a:hover rule
   overrides it. */
.form-alt a{color:var(--c-blue);font-weight:600;text-decoration:none}
.form-alt a:hover,
.form-alt a:focus{color:var(--c-blue-dark);text-decoration:underline}

/* Contact hero. The homepage caps its h1 at 17ch because the five-layer panel
   sits beside it. Nothing sits beside this one, so the heading runs the full
   container width and the section reads as a hero rather than as one column of
   a two-column layout with the other column missing. */
.nc-contact .hero h1{max-width:none}

@media(max-width:1024px){
  /* Panel below the form — the form is the point of the page. DOM order
     already puts it first, so the single column needs no reordering. */
  .contact__grid{grid-template-columns:1fr;gap:var(--s-xl)}
  .contact__aside{position:static}

  /* The footnote is a footnote. At full width 64px above the rule and 24px
     below reads as considered spacing; in a single narrow column it reads as a
     hole. Halved on both sides so the rule sits close under the panel and the
     text close under the rule. */
  .form-alt{margin-top:var(--s-lg);padding-top:var(--s-sm)}
}

/* ============================================================
   IMAGE / VIDEO SLOTS — placeholders until real files exist
   ============================================================ */
.ph{
  margin:0;position:relative;overflow:hidden;border-radius:var(--r-image);
  background:
    repeating-linear-gradient(45deg,rgba(10,116,218,.05) 0 10px,transparent 10px 20px),
    var(--c-blue-wash);
  border:1px dashed rgba(10,116,218,.45);
  display:flex;align-items:center;justify-content:center;text-align:center;padding:12px;
}
.ph span{font-size:11px;font-weight:700;letter-spacing:.06em;color:var(--c-blue);line-height:1.5}
.ph--16x9{aspect-ratio:16/9}
.ph--4x5{aspect-ratio:4/5}
.ph--1x1{aspect-ratio:1/1}
.ph--sq{aspect-ratio:1/1;border-radius:14px}
.ph--wide{aspect-ratio:21/9}
.section--dark .ph{background:rgba(255,255,255,.05);border-color:rgba(124,184,240,.5)}
.section--dark .ph span{color:var(--c-blue-light)}

/* A .ph slot holding a real image: keep the sizing, drop the placeholder chrome */
.ph--img,.section--dark .ph--img{background:none;border:0;padding:0}
.ph--img img{display:block;width:100%;height:100%;object-fit:cover}

.gap{border:1px dashed var(--c-border);border-radius:var(--r-card);padding:var(--s-lg);
  text-align:center;color:var(--c-light);font-size:var(--t-small);background:var(--c-surface)}

/* ============================================================
   FOOTER
   ============================================================ */
.ftr{background:var(--c-darker);color:rgba(255,255,255,.62);padding:var(--s-3xl) 0 var(--s-lg)}
.ftr__grid{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:var(--s-xl)}
.ftr h5{color:#fff;font-size:var(--t-h6);margin-bottom:10px}
.ftr__label{font-size:var(--t-caption);font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(255,255,255,.4);margin-bottom:var(--s-md)}
.ftr ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.ftr a{color:rgba(255,255,255,.62);text-decoration:none;font-size:var(--t-small);transition:color .3s}
.ftr a:hover{color:#fff}
.ftr p{font-size:var(--t-small)}

/* Social icons. The SVGs are filled with currentColor, so they follow the
   link's colour and only the link needs a hover state. No brand colours —
   blue is the site's one accent, and two brand palettes in the footer would
   make it the most colourful thing on the page. */
.ftr__social{flex-direction:row;align-items:center;gap:var(--s-md);margin-top:4px}
.ftr__social a{display:inline-flex;color:rgba(255,255,255,.62);
  transition:color .3s var(--ease)}
.ftr__social a:hover,
.ftr__social a:focus{color:#fff}
.ftr__social svg{display:block;width:20px;height:20px}
.ftr__bar{margin-top:var(--s-2xl);padding-top:var(--s-md);border-top:1px solid rgba(255,255,255,.1);
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:var(--s-sm);
  font-size:var(--t-caption);color:rgba(255,255,255,.4)}
@media(max-width:767px){.ftr__grid{grid-template-columns:1fr;gap:var(--s-lg)}}

/* ============================================================
   MOTION
   Headings wipe up behind a mask. Everything else fades and rises,
   staggered. Nothing bounces, nothing spins.
   ============================================================ */
.rv{opacity:0;transform:translateY(20px);transition:opacity .7s ease,transform .7s var(--ease)}
.rv.in{opacity:1;transform:none}
.rv-1{transition-delay:.08s}.rv-2{transition-delay:.16s}
.rv-3{transition-delay:.24s}.rv-4{transition-delay:.32s}
.rv-5{transition-delay:.4s}

/* The clip box needs headroom at BOTH ends.

   Headings run at line-height 1.08–1.14, which is tighter than the font's own
   ascent plus descent, so the glyphs are taller than the line boxes holding
   them. Tall letters sit above the first line box, and descenders — g, y, p, q,
   j, and the comma — hang below the last one. overflow:hidden shaves off
   anything outside the padding box.

   The padding-top and equal negative margin-top below have always made room at
   the top. Nothing made room at the bottom, so every heading whose last line
   ended in a descender had it sliced flat. Measured in Chrome at 1440px with
   Satoshi loaded, the overhang is 2.9px on an h2 and 5.8px on an h1 — small, but
   plainly visible at 48–64px, and it hit 14 of the 27 headings across the five
   coded pages, the homepage included.

   It is NOT a three-line problem. The overhang is the same on a one-line heading
   as on a four-line one; what decides it is whether the last line happens to end
   in a descender. "Four steps, in this order." is one line and was cut. "I did
   the exact thing I now tell founders to watch out for." is three lines and was
   not. See the note on the wipe below for why it looks line-count dependent in a
   full-page screen capture.

   THE FIX IS overflow-clip-margin, NOT MORE PADDING. A padding-bottom with a
   matching negative margin-bottom is the obvious move and it does not work here:
   the negative margin collapses with the margin-top of whatever follows the
   heading, so on the homepage and Contact heroes — where the h1 is a plain block
   sibling of its paragraph — the padding stayed and the negative margin was
   swallowed, pushing everything below down 10px. overflow-clip-margin expands
   the clip region without touching the box, so no heading changes height and
   nothing on any page moves by a pixel.

   The overflow:hidden line above it is the fallback for engines without
   overflow:clip (Safari before 16). There the clip stays at the padding box and
   the descender trimming remains exactly as it is today — not fixed, but not
   made worse either, and the top headroom still comes from the padding.

   The start offset changes with it. translateY(105%) was sized against a clip
   box that ended at the text; the clip now ends .16em lower, and 5% of a
   heading's own height does not clear that on a short heading — 5% of a one-line
   h2 is 2.7px against 7.6px of clip margin, so the top of the heading would sit
   visible below the mask before the wipe ran. calc(100% + .16em) is the exact
   distance — the span's own height plus the clip margin — and it is right for
   any number of lines, where 105% was an approximation that happened to work.
   Measured at rest across all five pages, every heading now sits 0.00px below
   the clip line: hidden exactly, with nothing peeking and nothing to spare.

   The animation is unchanged: the heading still slides up from behind its
   container over 850ms on var(--ease), as DESIGN.md specifies. */
.mask{
  display:block;
  overflow:hidden;
  overflow:clip;
  overflow-clip-margin:.16em;
  padding-top:.16em;margin-top:-.16em;
}
.mask > span{display:block;transform:translateY(calc(100% + .16em));transition:transform .85s var(--ease)}
.mask.in > span{transform:translateY(0)}

.overline.rv::before{transform:scaleX(0);transition:transform .7s var(--ease) .1s}
.overline.rv.in::before{transform:scaleX(1)}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{transition-duration:.01ms !important;animation:none !important}
  .rv{opacity:1;transform:none}
  .mask > span{transform:none}
  .overline::before{transform:scaleX(1)}
  .claim__dot{transform:scale(1)}
  /* Cancels both the lift and the scale, so buttons stay completely still.
     Later in the file at equal specificity, so no !important is needed. */
  .btn:hover{transform:none}
  .prog{display:none}
}

/* ============================================================
   GROWTH ARCHITECTURE  ·  page-growth-architecture.php

   Six rules. Everything else on that page reuses classes that
   were already here. Tokens only — no hex values, no pixel
   values that are not already tokens.

   All of it inherits the prefers-reduced-motion block above.
   Nothing here introduces motion of its own, so nothing here
   can bypass it.
   ============================================================ */

/* ---- 1 · Hero heading width ----
   .hero h1 is capped at 17ch because the homepage's five-layer panel sits
   beside it. Nothing sits beside this one, so the cap turns a one-line
   sentence into five short ones. Same fix, same reason, as .nc-contact. */
.nc-ga .hero h1{max-width:none}

/* ---- 2 · The long half of a layer panel ----
   .arch__panel is a 1fr/200px grid. On the homepage each panel is about
   sixty words, so the image sits beside the whole thing. Here the panels
   run to several hundred, and a 200px square pinned to the top of a very
   tall panel leaves most of the second column empty. So the number,
   question, pill, contents and principle share the top row with the image,
   and everything below spans both columns.

   Works unchanged on mobile: below 1024px the panel is a single column,
   and 1 / -1 spans that. */
.arch__more{
  grid-column:1 / -1;
  margin-top:var(--s-lg);
  padding-top:var(--s-lg);
  border-top:1px solid var(--c-border);
}

/* ---- 3 · Quiet labels inside a panel ----
   "What I've seen", "What it shows", "How you know it's this one". Not
   headings — the page is one H1, then H2 and H3, and turning these into
   H4s would put four heading levels inside one section for what is really
   a change of register. Same caps treatment as .chap and .arch__navtitle.

   The margin needs to beat .arch__panel p + p, which is (0,2,0), so it is
   stated at (0,2,0) too and wins on order. */
.arch__panel .arch__sub{
  margin-top:var(--s-lg);
  font-size:var(--t-caption);
  font-weight:700;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--c-light);
}
.arch__more > .arch__sub:first-child{margin-top:0}

/* ---- 4 · Lists inside a panel ----
   home.css styles ul only inside .ftr, so without this these fall through
   to Astra's defaults. Rows, not bullets crammed against the text. */
.arch__list{
  margin:var(--s-sm) 0 0;
  padding:0;
  list-style:none;
}
.arch__list li{
  position:relative;
  padding-left:var(--s-md);
}
.arch__list li + li{margin-top:var(--s-xs)}
.arch__list li::before{
  content:"";
  position:absolute;
  left:0;
  top:.68em;
  width:var(--s-xs);
  height:var(--s-xs);
  border-radius:var(--r-pill);
  background:var(--c-blue);
}

/* The closing note on the five, below the grid. */
.arch__close{margin-top:var(--s-2xl)}

/* ---- 5 · The four steps, on a dark section ----
   .step is a white card, which is right on the homepage's surface section
   and wrong here. These are the .glass values, applied to the same
   component. Stated after the .step block, so order wins and no !important
   is needed.

   .glass itself cannot just be added alongside .step: it sets a larger
   padding and a different radius, and .step is later in the file, so the
   two would fight and .step would win the parts that should have changed. */
.step--dark{
  background:rgba(255,255,255,.06);
  backdrop-filter:blur(16px);
  border-color:rgba(255,255,255,.14);
  box-shadow:none;
}
.step--dark:hover{
  border-color:rgba(255,255,255,.38);
  box-shadow:none;
}
/* Step titles are H3 here, not H4 — the section H2 is "Four steps, in this
   order", so the next level down is H3. .step h4 carries the size, so H3
   needs it stated. */
.steps__grid h3{
  font-size:var(--t-h6);
  font-weight:600;
  letter-spacing:-.012em;
  margin-bottom:var(--s-xs);
}
.step--dark .step__out{
  border-top-color:rgba(255,255,255,.14);
  color:rgba(255,255,255,.6);
}
/* Blue becomes Blue Light on dark. DESIGN.md, Sections. */
.step--dark .step__out::before{color:var(--c-blue-light)}
.step--dark .step__out strong{color:rgba(255,255,255,.82);font-weight:600}

/* ---- 6 · The italic question under each step title ----
   Muted white, not Blue Light. The card already carries blue in two places —
   the step number and the arrow on the outcome line — and a third would put
   four blue marks on every card. Blue is a pointer. DESIGN.md, 70/20/10. */
.step__q{
  font-size:var(--t-small);
  font-style:italic;
  color:rgba(255,255,255,.62);
  margin-bottom:var(--s-xs);
}

/* ============================================================
   GROWTH ARCHITECTURE  ·  v1.3 layout fixes

   Fix 2 of 3 from the 6 August review: the hero H1 and the body
   paragraph beneath it were on unrelated widths, so the body read as
   if it had run out rather than as a considered measure.
   ============================================================ */

/* ---- Fix 2 · Hero heading/body relationship ----
   The H1 was set to max-width:none because nothing sits beside it on
   this page (unlike the homepage, where the five-layer panel occupies
   the other half of the grid and justifies a narrow 17ch heading).
   Uncapped, the H1 ran close to the full 1280px container while
   .hero .body-lg stayed capped at the shared 50ch rule (~500px at this
   font size) — roughly double, which is the mismatch flagged.

   Two changes, both additive overrides of shared rules by specificity,
   neither edits the shared rule itself:

   1. The H1 gets a ch-based cap of its own. ch scales with the
      element's own font-size, which is how the homepage's 17ch header
      and 50ch body already land at comparable pixel widths despite the
      large gap in font size — the same technique, a wider number
      because this heading has no side content taking up room.

   2. The body paragraph is widened from the shared 50ch (~500px) up to
      DESIGN.md's own body-text ceiling, --w-reading (700px) — not
      beyond it. This does not contradict "body text never exceeds
      700px"; it uses the full allowance instead of stopping short of
      it.

   Together these bring the two blocks' right edges much closer without
   widening body text past its documented limit and without touching
   .hero .body-lg, which the homepage's hero still depends on.

   26ch is a first pass, sized from the same em-per-ch approximation
   that explains the homepage's 17ch/50ch pairing. Check it against the
   live H1 text and adjust in a few ch either way if the two blocks
   still look unrelated. */
.nc-ga .hero h1{max-width:26ch}
.nc-ga .hero .body-lg{max-width:var(--w-reading)}

/* ============================================================
   GROWTH ARCHITECTURE  ·  v1.4 fixes
   ============================================================ */

/* ---- Bug · list jammed against the paragraph after it ----
   .arch__list only ever got a top margin (spacing from whatever came
   before it). Nothing set a bottom margin, so in Layer 2 — the one
   panel where a plain paragraph follows the list directly, rather than
   the next .arch__sub header — the paragraph sat flush against the
   last bullet with no gap and read as part of it.

   This is an addition to the existing unscoped .arch__list rule, not
   an edit of it: .nc-ga wins on specificity over the bare .arch__list
   selector, so only this page is affected, and only the bottom margin
   changes — the shorthand rule's top margin is untouched.

   Where a .arch__sub header follows instead (every other case, after
   this v1.4 reorder), its own larger top margin (--s-lg) already wins
   the collapse, so this is a no-op there and only fixes the one panel
   that needed it. */
.nc-ga .arch__list{margin-bottom:var(--s-md)}

/* ============================================================
   GROWTH ARCHITECTURE  ·  v2.0 copy pass
   ============================================================ */

/* ---- Watch item A · hero H1 cap, revisited ----
   The v1.3 fix (above) capped the H1 at 26ch for a single 73-character
   sentence. v2.0's H1 is two sentences, about 123 characters combined.
   At the same 26ch cap that would wrap to five or six lines — noticeably
   taller than the three-line block 26ch produced for the old, shorter
   sentence, and heavier than the body paragraph beneath it can balance.

   This rule has the same selector as the one above and comes later in
   the file, so it wins on source order — the usual technique in this
   file for superseding an earlier value without editing it in place,
   since this pass is append-only. The 26ch rule above is dead from here
   down; left in place as the record of what v1.3 shipped.

   34ch is sized so each of the two sentences (~61-62 characters) wraps
   to roughly two lines of its own — four lines total, rather than five
   or six. Estimated the same way the 26ch value was: not measured in a
   browser. Check it against the live two-sentence H1 and adjust. */
.nc-ga .hero h1{max-width:34ch}

/* ---- B · Section 5's five tests, now a numbered list ----
   Same technique as .arch__list above: a real list, list-style
   suppressed, and a custom marker painted with a ::before counter
   instead of the browser default — so the numeral can be styled to
   match the page's number treatment (weight, colour, tabular figures)
   rather than left at browser defaults. It stays a real <ol>, so
   assistive tech still gets real ordinal semantics ("2 of 5"),
   which list-style:none does not take away.

   Left padding matches .arch__list's own left padding. The gap between
   items stays at --s-md rather than .arch__list's tighter --s-xs: these
   are full reading-width sentences carrying the section's main
   argument, not short bullets in a panel column, and --s-md is the gap
   this section already used between them back when they were plain
   paragraphs — the numbering is new, the rhythm is not. */
.nc-ga .tests{
  margin:0;
  padding:0;
  list-style:none;
  counter-reset:tests;
}
.nc-ga .tests li{
  counter-increment:tests;
  position:relative;
  padding-left:var(--s-md);
}
.nc-ga .tests li + li{margin-top:var(--s-md)}
.nc-ga .tests li::before{
  content:counter(tests)".";
  position:absolute;
  left:0;
  top:0;
  font-weight:700;
  color:var(--c-blue);
  font-variant-numeric:tabular-nums;
}

/* ============================================================
   WHAT I BUILD  ·  page-what-i-build.php

   Eight rules. Everything else on that page reuses classes that
   were already here. Tokens only — no hex values, no pixel values
   that are not already tokens.

   EVERY SELECTOR IS SCOPED TO .nc-wib. home.css is shared with
   front-page.php, page-contact.php and page-growth-architecture.php,
   so an unscoped rule here would silently change three finished
   pages.

   Nothing here declares an animation, and the prefers-reduced-motion
   block above carries !important on its * rule, so nothing here can
   bypass it.
   ============================================================ */

/* ---- 1 · Hero heading and body width ----
   .hero h1 is capped at 17ch and .hero .body-lg at 50ch, both written
   for the homepage's two-column hero where the five-layer panel
   occupies the other half. This hero has no side column, so the caps
   leave the heading in a narrow ragged stack. Same override, same
   reason, as .nc-ga and .nc-contact.

   34ch is carried over from the Growth Architecture hero, which has a
   two-sentence H1 of similar shape. It is an estimate, not a
   measurement — check it against the live page. */
.nc-wib .hero h1{max-width:34ch}
.nc-wib .hero .body-lg{max-width:var(--w-reading)}

/* ---- 2 · The five cards ----
   Two columns, not three. Each card carries about a hundred words plus
   its "what this is not" block; at three columns that is roughly 37
   characters a line, which reads as a ragged tall column. Two gives
   about 60. The homepage's three-column .builds grid holds one short
   sentence per card, so its shape does not transfer here.

   Five is an odd number, so the fifth card sits alone on the last row
   at half width. That is accepted rather than worked around — spanning
   it would make it look special when it is not. */
.nc-wib .wib-cards{
  display:grid;
  grid-template-columns:repeat(2,1fr);
  gap:var(--s-md);
  margin-top:var(--s-xl);
  align-items:start;
}
@media(max-width:1024px){
  .nc-wib .wib-cards{grid-template-columns:1fr}
}

/* ---- 3 · Card hover ----
   .panel supplies the shell and is already DESIGN.md's card spec
   exactly — white fill, 1px border, --r-card, --s-lg padding, --sh-sm —
   but it was written as a container and deliberately has no hover. This
   adds only the transition and the lift. Values copied from .step:hover
   so the two behave identically. */
.nc-wib .wib-card{
  transition:transform .45s var(--ease),
             box-shadow .45s var(--ease),
             border-color .45s var(--ease);
}
.nc-wib .wib-card:hover{
  transform:translateY(-4px);
  box-shadow:var(--sh-md);
  border-color:rgba(10,116,218,.4);
}

/* ---- 4 · The "If…" heading inside a card ----
   Has to be an <h3> for heading order — the section H2 is "Five
   problems. Five different jobs." A bare h3 is --t-h3 (26–38px), which
   overwhelms a 604px card. --t-h4 keeps it the loudest thing in the
   card without shouting. .lbl below it already carries its own bottom
   margin, so the heading only needs a small one. */
.nc-wib .wib-card h3{
  font-size:var(--t-h4);
  margin-bottom:var(--s-xs);
}
.nc-wib .wib-card p + p{margin-top:var(--s-sm)}

/* ---- 5 · "What this is not" ----
   The scoped equivalent of .arch__sub, which is NOT reusable here: it
   exists only as `.arch__panel .arch__sub`, and this page has no
   .arch__panel, so the bare class name would render as unstyled body
   text. Same five declarations, so the register matches the Growth
   Architecture page exactly.

   Stated at three classes so it beats the p + p rule above, which is
   (0,2,1). */
.nc-wib .wib-card .wib-sub{
  margin-top:var(--s-lg);
  font-size:var(--t-caption);
  font-weight:700;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--c-light);
}

/* ---- 6 · The four bold items on the dark section ----
   There is no generic strong rule anywhere in this theme, so on a dark
   section a <strong> inherits rgba(255,255,255,.74) — the same colour
   as the body text around it — and the four items would read as barely
   separated from their own explanations. This lifts them, following the
   one existing precedent at .step--dark .step__out strong.

   Not pure white: DESIGN.md's Don'ts forbid pure white on dark. .92 is
   a clear step up from the .74 body text around it without going to
   #fff, which on this ground is reserved for headings.

   Weight 600 rather than the browser's 700, matching every other
   emphasis on the site — .sting, .lbl and .step__out strong all use
   600, so Inter carries two weights in this view and no more. */
.nc-wib .section--dark strong{
  color:rgba(255,255,255,.92);
  font-weight:600;
}

/* ============================================================
   WHAT I BUILD  ·  v1.1 fixes

   Four fixes. Every selector scoped to .nc-wib, as above. Nothing
   here declares an animation; the existing prefers-reduced-motion
   block's * rule carries !important, so nothing here bypasses it.
   ============================================================ */

/* ---- Fix 1 · hero H1 cap, revisited ----
   v1.1's H1 is different text ("You don't need all five of these.
   You need the one that's blocking everything else."), and the old
   34ch value — sized for the previous heading — left a trailing word
   stranded alone on its own line.

   Checked by counting characters per line at candidate widths rather
   than guessing:

   Sentence 1, 33 characters. The only break points before the final
   word are after "five" (23 chars) and after "of" (26 chars). A cap of
   26–32 puts "of" on line 1 and leaves "these." alone on line 2 —
   stranded. A cap of 33+ fits the whole sentence on one line — safe.

   Sentence 2, 49 characters. Break points fall after "that's" (23),
   "blocking" (32) and "everything" (43). A cap of 43–48 puts
   "everything" on line 1 and leaves "else." alone — stranded. A cap of
   32–42 breaks after "blocking", leaving "everything else." together
   on line 2 — safe. 49+ fits on one line — also safe.

   Overlap of both sentences' safe ranges: 33–42. This selector has the
   same specificity as the 34ch rule above and comes later in the file,
   so it wins on source order — the file's usual way of superseding a
   value without editing it in place. The 34ch rule is dead from here
   down. */
.nc-wib .hero h1{max-width:36ch}

/* ---- Fix 1 · Section 2's H2, now three sentences ----
   Markup change, not CSS: a <br> after each of the first two sentences,
   same technique as both hero H1s on this site. Deterministic at every
   viewport, unlike a ch cap on a heading that also has to share width
   rules with .reading — so no new rule is needed here. See
   page-what-i-build.php. */

/* ---- Fix 2a · equal-height cards ----
   align-items:start (set when this grid was first built) is exactly
   why the two cards in a row sat at their own natural height instead
   of matching each other. Grid's own default is stretch; this restores
   it. Same specificity, later in the file, wins on source order. */
.nc-wib .wib-cards{align-items:stretch}

/* ---- Fix 2b · "what this is not" pinned to the card's bottom ----
   .wib-card becomes a flex column so a margin-top:auto inside it can
   push content to the bottom of the now-stretched card — the exact
   technique .step already uses for .step__out two blocks up this file,
   which is why that pattern was trusted here rather than invented.
   .steps__grid relies on the same grid default (stretch) for the same
   reason: no explicit height is needed on the card itself. */
.nc-wib .wib-card{
  display:flex;
  flex-direction:column;
}

/* ---- Fix 3 · the fifth card spans both columns ----
   :last-child, not a class on the fifth <article> — five cards is a
   fact about this section's copy (five problems), not a state the
   template should have to declare. Only grid-column changes; every
   other .wib-card rule still applies untouched, so it is the same card,
   wider. At the 1024px breakpoint the grid is already one column, where
   spanning "both columns" has no visible effect — no separate mobile
   rule needed. */
.nc-wib .wib-cards > .wib-card:last-child{
  grid-column:1 / -1;
}

/* ---- Fix 4a · "what this is not" gets more presence ----
   Two changes, both restrained: a rule above it, matching how
   .step__out is already separated from the body text above it on the
   homepage's dark section — and its own colour raised from the shared
   --c-light to --c-blue, the same colour the label pill next to the
   H3 already carries, so the two blue marks in the card read as
   related. Still a caps label at caption size, not a heading, not an
   h4 — only colour and a divider changed.

   margin-top and color both have the same specificity as rule 5 above
   (.nc-wib .wib-card .wib-sub, also three classes) and come later, so
   they win on source order without editing it; padding-top and
   border-top are new properties with nothing to override. No tinted
   background: DESIGN.md's wash tokens are fills, not text colours, and
   a filled panel inside an already-bordered card would read as a
   second component nested in the first rather than one card. */
.nc-wib .wib-card .wib-sub{
  margin-top:auto;
  padding-top:var(--s-md);
  border-top:1px solid var(--c-border);
  color:var(--c-blue);
}

/* ---- Fix 4b · Section 3 as a real DESIGN.md Lists component ----
   Stacked rows, divider between each, 16/24px padding — --s-sm and
   --s-md are exactly those two values, so this is the token spec
   verbatim, not an approximation of it.

   NOT the Growth Architecture page's dark card grid: those four items
   are numbered and sequential ("Four steps, in this order"); these
   four are unnamed, unordered examples. Same shape would read as the
   same idea, which is the opposite of what this section says.

   Divider and hover values are both checked against this file's own
   existing dark-section treatments rather than picked freely:

   - The divider technique — border-top on every row but the first —
     is .nstep + .nstep's, a few hundred lines up, written for the same
     stacked-rows-on-dark situation.
   - Its opacity is raised from .nstep's .10 to .14, matching
     .step--dark and .glass instead: .nstep is a quiet metadata
     divider, but DESIGN.md's Lists rows are content blocks in their
     own right and need a division as visible as a card edge, not as
     subtle as a glass panel's.
   - The hover fill, rgba(255,255,255,.10), is .section--dark
     .btn--secondary:hover's value. DESIGN.md's Lists entry says hover
     goes to Surface, but --c-surface is a near-white token meant for a
     light background — on this dark section it would flash bright
     instead of shifting quietly, so the site's own existing dark-hover
     value is used instead of that light-mode default. */
.nc-wib .wib-list{
  list-style:none;
  margin:0;
  padding:0;
}
.nc-wib .wib-list li{
  padding:var(--s-sm) var(--s-md);
  transition:background-color .3s var(--ease);
}
.nc-wib .wib-list li + li{
  border-top:1px solid rgba(255,255,255,.14);
}
.nc-wib .wib-list li:hover{
  background-color:rgba(255,255,255,.10);
}

/* ============================================================
   WHAT I BUILD  ·  two bugs from the v1.1 build
   ============================================================ */

/* ---- Bug 1 · the label pills stretched full width ----
   .wib-card became display:flex;flex-direction:column for the
   equal-height fix, and flex's own default cross-axis behaviour is
   stretch — the same default this file already relied on for the grid
   fix two blocks up, working against a different child this time. .lbl
   is normally inline-block and hugs its own text (see it correctly
   sized on page-growth-architecture.php, where .arch__panel is grid,
   not flex, so .lbl was never a flex item there and needed nothing).

   Fixed on the one child that needs it, not by changing .wib-card's own
   align-items: doing that would also shrink the body paragraphs to
   their own content width, which is wrong — they need to stay full
   width to wrap normally. .wib-sub's margin-top:auto is a different
   property and is untouched by this. */
.nc-wib .wib-card .lbl{align-self:flex-start}

/* ---- Bug 2 · the hero H1 still stranded a single word ----
   Two rounds of guessing a ch cap (34, then 36) each fixed one heading
   and broke on the next. text-wrap:balance is the CSS built for exactly
   this failure mode: instead of the default greedy wrap — fill each
   line as full as possible, dump whatever's left on the last one — it
   picks the line count first and then finds the narrowest width that
   still fits in that many lines, so the lines it produces are close to
   even. No more measuring characters by hand.

   Does not fight the <br> already in the H1: a <br> is a forced break,
   which balance cannot remove or move — it still guarantees the two
   sentences start on separate lines. Balance only decides where the
   soft wrap falls inside whichever sentence is long enough to still
   need one, which is the one place the old ch cap kept guessing wrong.

   Support: shipped in Chrome, Edge and Firefox for some time, and in
   Safari since 17.5. No @supports guard is needed for the no-support
   case either way — text-wrap is a real, long-standing property, so an
   older engine that doesn't recognise the balance keyword drops just
   that one value and keeps every other declaration in the rule,
   including the existing max-width. That is the ordinary CSS rule for
   an invalid value, not a special case to code around, and it leaves
   exactly the current greedy-wrap behaviour as the fallback — which is
   what was asked for.

   The max-width:36ch rule above is untouched and still sets the
   heading's overall width; balance only changes how the text inside
   that width is distributed across lines, so the two rules do not
   compete.

   Applied to Section 2's H2 too. Its three sentences already get their
   own line each from the <br>s added in the last round, but "Only one
   is yours right now." is 29 characters and sits close to the same
   per-line character budget that stranded the H1 — worth covering
   before it fails the same way. .nc-wib h2 rather than a selector
   scoped to Section 2 alone: this page has no existing hook for "just
   this section's heading" without adding a class, and balance is a
   no-op on a heading that already fits its available width on one
   line, so reaching the other section headings costs nothing. */
.nc-wib .hero h1{text-wrap:balance}
.nc-wib h2{text-wrap:balance}

/* ============================================================
   ABOUT  ·  page-about.php

   Six rules. Everything else on that page reuses classes that
   were already here — .hero, .section, .section--surface,
   .wrap, .reading, .overline, .mask, .rv, .body-lg, .btn,
   .btn-row, .ph, .ph--4x5, .ph--img.

   Tokens only. No hex values. The one raw pixel value is a
   media query breakpoint, 600px, which is this file's own
   existing breakpoint — tokens.css defines no breakpoints, so
   .builds, .steps__grid and .nc-wib all state theirs the same
   way.

   Nothing here declares an animation or a transform. The two
   transitions below are both caught by the
   prefers-reduced-motion block above, whose * rule carries
   !important, so nothing here can bypass it.

   No dark-section rules, because this page has no dark section.
   ============================================================ */

/* ---- 1 · Hero heading width ----
   .hero h1 is capped at 17ch for the homepage's two-column hero, where the
   five-layer panel occupies the other half. This hero has no side column, so
   the cap leaves the heading in a narrow ragged stack. Same override, same
   reason, as .nc-ga, .nc-contact and .nc-wib.

   text-wrap:balance rather than a ch cap. Two rounds of guessing a cap on the
   What I Build hero each fixed one heading and broke on the next, and the note
   at that fix records why balance is the right tool: it picks the line count
   first, then finds the narrowest width that still fits, so no single word is
   left stranded on a line of its own. The <br> in the H1 is a forced break,
   which balance cannot move — the two sentences still start on separate lines
   regardless. Applied to the section H2s too, for the same reason and at no
   cost: balance is a no-op on a heading that already fits on one line. */
.nc-about .hero h1{max-width:none;text-wrap:balance}
.nc-about h2{text-wrap:balance}

/* ---- 2 · Paragraph rhythm inside a chapter ----
   Chapters 01 and 02 run to seven paragraphs each. The other coded templates
   set the gap with an inline style:margin-top on every paragraph after the
   first, which works but would mean fourteen inline styles on this page. One
   scoped rule states it once, with the same token those inline styles use.

   p + p, so the first paragraph in a chapter keeps its position under the
   heading and only the gaps between paragraphs are set. The closing paragraph
   in Chapter 03 wants the wider --s-xl gap after the list and states it
   inline, which wins as inline styles always do. */
.nc-about .reading p + p{margin-top:var(--s-md)}

/* ---- 3 · The portrait ---- SUPERSEDED, see the ABOUT block at the foot of
   this file. The portrait moved out of Chapter 01 into the hero, where
   .nc-about .textcols--hero .about-portrait sets max-width:none at (0,3,0) and
   wins over both rules below at every width. They are inert and are kept only
   as the record of the Chapter 01 placement. Do not reinstate them, and do not
   read the reasoning below as current — the sizing argument it makes was about
   a figure sitting inside the reading column, which is not where it now sits.

   Capped below the 700px reading column. At full reading width a 4:5 portrait
   renders 875px tall — taller than most viewports, and the loudest thing on a
   page whose argument is restraint. DESIGN.md is explicit that images support
   an argument the words are already making and never carry it.

   60% of the reading column is roughly 420 x 525, close to the size the same
   photograph already renders at on the homepage, where it sits in a .why__grid
   column rather than at full width. A percentage rather than a pixel value, so
   nothing is hardcoded and the cap scales with the column.

   Released at 600px, where 60% of an already narrow column would render the
   portrait as a thumbnail. .ph--4x5 supplies the aspect ratio and .ph the 16px
   radius, both untouched.

   margin-bottom rather than a margin-top on the paragraph below it: the figure
   is not a <p>, so rule 2's p + p never fires across it. */
.nc-about .about-portrait{
  max-width:60%;
  margin-bottom:var(--s-lg);
}
@media(max-width:600px){
  .nc-about .about-portrait{max-width:100%}
}

/* ---- 4 · Inline link in body copy ----
   home.css sets a{color:inherit} site-wide, so an unclassed link inside a
   paragraph is invisible as a link. This page has one, in Chapter 02, pointing
   at the Growth Architecture page — it is in the copy file, mid-sentence.

   Not .tlink: that class is inline-flex, which makes an atomic box that cannot
   wrap mid-phrase, and it is built for a standalone link on its own line with
   an arrow. This one sits inside a sentence and has to wrap like text.

   Underlined at rest, not on hover only. Colour alone is not allowed to carry
   the meaning of a link, and an underline is the one affordance a reader does
   not have to hover to find. The offset keeps it clear of the descenders.

   Astra prints an inline a:hover, a:focus{color:...} rule site-wide at
   (0,1,1), which would otherwise turn this link dark blue on both states. The
   colour is stated again on each: .nc-about .ilink:hover is (0,3,0) and wins
   on the class count. Astra's rule carries no !important, so specificity alone
   is enough — the same fix, and the same reasoning, as the buttons above. */
.nc-about .ilink{
  color:var(--c-blue);
  font-weight:600;
  text-decoration:underline;
  text-underline-offset:3px;
  transition:color .3s var(--ease);
}
.nc-about .ilink:hover,
.nc-about .ilink:focus{color:var(--c-blue-dark)}

/* ---- 5 · Chapter 03's five capabilities ----
   DESIGN.md's Lists component, stated verbatim: stacked rows separated by 1px
   borders, 16px vertical and 24px horizontal padding, hover to Surface, and no
   shadow. --s-sm and --s-md are exactly 16px and 24px, so this is the token
   spec rather than an approximation of it.

   NOT .wib-list, which is .nc-wib-scoped and written for a dark section — its
   divider and hover are both white at low opacity, which would be invisible
   here. Rescoping it would also change a live page. This is its light-section
   equivalent, written separately, as the brief requires.

   The negative left margin pulls the rows' padding back out to the reading
   column's own left edge, so the bold lead-ins stay aligned with the body text
   above and below them. Without it the whole list would sit 24px indented from
   every other paragraph on the page. */
.nc-about .about-list{
  list-style:none;
  margin:0 0 0 calc(var(--s-md) * -1);
  padding:0;
}
.nc-about .about-list li{
  padding:var(--s-sm) var(--s-md);
  transition:background-color .3s var(--ease);
}
.nc-about .about-list li + li{
  border-top:1px solid var(--c-border);
}
.nc-about .about-list li:hover{
  background-color:var(--c-surface);
}

/* ---- 6 · The bold lead-in on each row ----
   A bare <strong> renders at the browser's 700 and inherits --c-mid, the same
   colour as the explanation following it, so the five lead-ins would barely
   separate from their own sentences.

   Weight 600, not 700, matching every other emphasis on this site — .sting,
   .lbl, .step__out strong and .nc-wib .section--dark strong all use 600, so
   Inter carries two weights in this view and no more, as DESIGN.md requires.
   --c-dark is the same colour .sting uses to lift emphasised body text on a
   light section. */
.nc-about .about-list strong{
  color:var(--c-dark);
  font-weight:600;
}

/* ============================================================
   TWO-COLUMN TEXT SECTION  ·  .textcols

   Used by page-growth-architecture.php, page-what-i-build.php
   and page-about.php. Generic, not page-scoped, because three
   pages share it — and named in the coded vocabulary (section,
   wrap, reading, btn, glass), not the nc- one.

   The problem it solves. Every page sits inside a 1280px .wrap,
   and body text is capped at the 700px reading measure. But the
   reading column is pinned to the left edge of the wrap, so a
   section made only of text leaves roughly 530px of empty wrap
   on its right. Widening the measure is not the fix: DESIGN.md
   caps body text at 700px, and a tiring line length is a worse
   outcome than an unbalanced one.

   So the section's label and heading move into a left column,
   and the body text stays at the reading measure on the right.
   The two together fill the wrap. DESIGN.md puts the register
   "closer to a well-set annual report than to a marketing
   site", and an annual report sets its headings in the margin.

   ADDITIVE ONLY. Nothing above this block is edited. Every
   selector below begins with .textcols, so no existing markup
   on any page can pick these rules up by accident, and .wrap,
   .reading, .section, .mask, .chap and .overline are all
   untouched.

   PROPORTIONS, taken from tokens:

   - Right column: minmax(0, var(--w-reading)) — 700px, the
     existing reading measure, unchanged. minmax(0, …) rather
     than a bare 700px so the column gives ground instead of
     overflowing when the window is narrow.
   - Gap: var(--s-2xl) — 64px, the value every other two-column
     layout in this file already uses (.arch__grid, .think__grid,
     .why__grid, .contact__grid, .next__grid, .hero__grid).
   - Left column: 1fr — whatever is left, so the two columns
     fill the wrap exactly, as the brief requires. At the full
     1280px container that is 1232 − 700 − 64 = 468px.

   THE ONE RAW PIXEL VALUE is the 300px floor on the left
   column, and it earns its place. With a bare 1fr the left
   column is the only one that gives ground, so just above the
   1024px breakpoint it would fall to about 213px — and an h2
   renders at roughly 42px at that viewport, which is four or
   five characters to a line. 300px holds about fourteen, enough
   for the longest word in any of these three pages' headings
   plus a short one after it. Below that the reading column
   gives up its last pixels instead: 700px is a cap, not a
   minimum, and the roughly 613px this bottoms out at is well
   inside DESIGN.md's rule. It only bites between about 1025px
   and 1112px of viewport, and below 1024px the layout collapses
   to one column anyway.

   Nothing here declares an animation, a transform or a
   transition, so the prefers-reduced-motion block above — whose
   * rule carries !important — still governs every page that
   uses this.
   ============================================================ */
.textcols{
  display:grid;
  grid-template-columns:minmax(300px,1fr) minmax(0,var(--w-reading));
  column-gap:var(--s-2xl);
  row-gap:0;
  align-items:start;
}
.textcols__head{grid-column:1}
.textcols__body{grid-column:2}

/* Static, never sticky. The Growth Architecture page already owns the
   sticky pattern with .arch__nav, and a second sticky element on the
   same page would make two different things read as the same thing. */

/* ---- Heroes ----
   The h1 runs 40→64px. In a 468px column that is seven to twelve
   characters a line, which would wreck all three hero headings and
   strand exactly the sort of single word the brief warns about. So the
   head spans both columns and only the body text and the button row
   take the right column.

   Because the head spans the full wrap, each h1's available width is
   exactly what it is today — .wrap's 1232px, less whatever ch cap that
   page already sets on it — so no h1 changes where its lines break.

   The overline travels with the h1 rather than being left alone in the
   margin. The two are glued together by design: 16px apart, with the
   blue rule that grows into the heading. Splitting them would break a
   relationship that is already working, to fill a column with one short
   line of caps. */
.textcols--hero .textcols__head{grid-column:1 / -1}

/* ---- Hero body column ----
   The head spans both columns, so leaving the body in column 2 put the
   supporting paragraph and the button row halfway across the page, under the
   right-hand half of a full-width headline, with a 532px hole to their left. It
   read as though the text had slipped sideways rather than as a margin column.

   So the body spans both columns too, and takes the reading measure as its own
   width instead of taking it from the grid track. Same 700px line length, same
   left-aligned text, now starting at the same left edge as the h1 above it.

   Only .textcols--hero. The four-chapter body sections keep the side-by-side
   arrangement, where the left column carries the heading and the two columns
   genuinely sit beside each other.

   The h1 is untouched: it still spans 1 / -1 at the full container width, so its
   line breaks cannot move. Below 1024px the grid is one column and 1 / -1 is
   that column, so this is a no-op there — the max-width is already what
   .body-lg carries. */
.textcols--hero .textcols__body{
  grid-column:1 / -1;
  max-width:var(--w-reading);
}

/* ---- Heading wrap in the margin column ----
   The h2s were set at 700px and are now set at 468px, so their wrap
   points move. text-wrap:balance picks the line count first and then
   the narrowest width that still fits it, which is the tool this file
   already reaches for when a heading strands a single word — see the
   What I Build hero note above. .nc-wib h2 and .nc-about h2 already
   carry it page-wide, so in practice this only reaches the Growth
   Architecture headings, which is where the new risk is.

   Deliberately not applied to h1. The h1 spans the full wrap, its
   available width does not change, and so its line breaks must not
   change either. */
.textcols__head h2{text-wrap:balance}

/* ---- Collapse ----
   One column below 1024px — the breakpoint this file already uses
   everywhere (.hero__grid, .think__grid, .arch__grid, .contact__grid,
   .next__grid, .why__grid, .nc-wib .wib-cards). Not a new one. This is
   the layout these pages have on mobile today.

   The body wrapper's top margin is stated here rather than inline in
   the templates, because at desktop the two columns are top-aligned and
   there must be no margin at all. --s-lg is the gap the section
   templates set inline before this change; --s-md is the hero's, where
   the h1's own margin-bottom does the work at desktop. Written as an
   adjacent-sibling selector so a .textcols with no head — the closing
   passage on the Growth Architecture page — gets no margin it has no
   use for. */
@media(max-width:1024px){
  .textcols{grid-template-columns:1fr}
  .textcols__head,
  .textcols__body{grid-column:1}
  .textcols__head + .textcols__body{margin-top:var(--s-lg)}
  .textcols--hero .textcols__head + .textcols__body{margin-top:var(--s-md)}
}

/* ============================================================
   ABOUT  ·  one column, portrait in the hero

   About is prose from top to bottom. The other two long pages
   are broken up by card grids, image grids and panels, which is
   what .textcols was designed around — something already fills
   the container width and the heading column reads as a margin
   beside it. Here nothing does, so the 468px heading column
   stood empty for most of every section and the page rendered at
   five different widths: 1232 for the h1, 700 for the body, 468
   for the headings, 631 for the hero intro and 420 for the
   portrait, on two different left edges.

   So on this page the two-column arrangement is dropped for a
   single flush-left column at the reading measure, and the hero
   takes the portrait in a second column to give the page an
   opening with some weight in it.

   EVERY SELECTOR IS SCOPED TO .nc-about. .textcols itself is not
   touched — Growth Architecture and What I Build depend on it and
   both are live.

   Tokens only, no hex. The one raw pixel value is the 1024px
   breakpoint, which is this file's own, reused.
   ============================================================ */

/* ---- 1 · The hero: text left, portrait right ----
   The arrangement and the .ph ph--4x5 ph--img figure treatment are Chapter 05's
   on front-page.php — a two-column grid, top-aligned, --s-2xl between the
   columns. The sides are swapped: the homepage puts the portrait left and its
   list right, and here the copy takes the left so it starts on the page's own
   left edge, level with the header logo and the footer's first column.

   The left track is the reading measure, so the h1, the intro and the button all
   sit at the width the rest of the page uses. The portrait takes what is left —
   468px at the full container, rendering 585px tall at its 4:5 ratio.

   row-gap:0 because the h1's own margin-bottom already supplies the gap under
   it, exactly as it does in the shared .textcols--hero rule. */
.nc-about .textcols--hero{
  display:grid;
  grid-template-columns:minmax(0,var(--w-reading)) 1fr;
  column-gap:var(--s-2xl);
  row-gap:0;
  align-items:start;
}
.nc-about .textcols--hero .textcols__head{grid-column:1;grid-row:1}
.nc-about .textcols--hero .textcols__body{
  grid-column:1;
  grid-row:2;
  max-width:var(--w-reading);
}
.nc-about .textcols--hero .about-portrait{
  grid-column:2;
  grid-row:1 / span 2;
  max-width:none;
  margin-bottom:0;
}

/* ---- 2 · Everything below the hero: one column, flush left ----
   Not centred. The same left edge as the hero text above it, so the whole page
   reads down a single axis. :not(.textcols--hero) so the hero keeps its grid. */
.nc-about .textcols:not(.textcols--hero){
  display:block;
  max-width:var(--w-reading);
}

/* The row gap goes with the grid in those sections, so the heading-to-body gap
   is stated here — the same two tokens the collapsed layout below 1024px
   already uses, so the rhythm is the one this page has on mobile today. */
.nc-about .textcols__head + .textcols__body{margin-top:var(--s-lg)}
.nc-about .textcols--hero .textcols__head + .textcols__body{margin-top:var(--s-md)}

/* ---- 3 · The hero intro's own width cap ----
   .hero .body-lg is capped at 50ch, written for the homepage's two-column hero
   where the five-layer panel takes the other half. On a page reduced to one
   width that left the intro 631px against 700px for everything around it — the
   last width on the page that did not line up. */
.nc-about .hero .body-lg{max-width:none}

/* ---- 4 · Collapse ----
   Below 1024px the hero stacks: text, then portrait. Same breakpoint as the
   shared .textcols collapse above and everything else in this file. --s-xl above
   the portrait so it reads as a separate block under the button rather than
   crowding it. */
@media(max-width:1024px){
  .nc-about .textcols--hero{grid-template-columns:1fr}
  .nc-about .textcols--hero .textcols__head{grid-column:1;grid-row:1}
  .nc-about .textcols--hero .textcols__body{grid-column:1;grid-row:2}
  .nc-about .textcols--hero .about-portrait{
    grid-column:1;
    grid-row:3;
    margin-top:var(--s-xl);
  }
}

/* ============================================================
   CONTACT  ·  the booking line under the form

   Two rules. Both scoped to .nc-contact, so nothing reaches
   another page. Tokens only.

   Sits under .form-alt, inside the footnote group that rule's
   top border already separates from the form — so no second
   border, and no extra section.

   DELIBERATELY QUIET. Small text at body weight, not .btn. The
   form is the better path and stays primary; a second call to
   action of equal weight makes somebody choose before they act.
   ============================================================ */

.nc-contact .form-book{
  margin-top:var(--s-md);
  font-size:var(--t-small);
  color:var(--c-light);
  line-height:1.7;
}

/* home.css sets a{color:inherit} site-wide, so an unclassed link in
   body copy is invisible as a link. Colour stated again on hover and
   focus, or Astra's inline a:hover, a:focus rule takes it to dark
   blue — the same treatment .form-alt a already carries. */
.nc-contact .form-book a{
  color:var(--c-blue);
  font-weight:600;
  text-decoration:underline;
}
.nc-contact .form-book a:hover,
.nc-contact .form-book a:focus{color:var(--c-blue-dark)}

.nc-contact .form-book__note{
  margin-top:var(--s-xs);
  font-size:var(--t-caption);
  color:var(--c-light);
  line-height:1.5;
}


/* ============================================================
   THANK-YOU PAGES  ·  page-thank-you.php, page-answers-received.php

   One shared scope, .nc-thanks — the two pages are the same shape
   twice. Six rules; everything else reuses classes that already
   exist. Tokens only, no hex, no raw pixel values at all.

   Layout is .wrap > .reading, as on the Growth Assessment: one
   flush-left column at the reading measure, on the same left edge
   as the header logo. No .textcols grid to cancel.

   Nothing here declares an animation or a transform, so the
   prefers-reduced-motion block already in this file covers both
   pages through .rv and .mask.
   ============================================================ */

/* .hero caps its h1 at 17ch because the homepage seats a panel
   beside it. Nothing sits beside these, and the .reading column
   already bounds the line length, so the cap comes off — the same
   fix .nc-contact and .nc-about already carry. */
.nc-thanks .hero h1{max-width:none}
.nc-thanks .hero .body-lg{max-width:none}

/* home.css sets p{margin:0} globally, so every page states its own
   rhythm. Same value and technique as .nc-about .reading. */
.nc-thanks .reading p + p{margin-top:var(--s-md)}

/* The line under each primary button. Caption in Light, matching
   the assessment's .as__note, which is the same thing in the same
   position. */
.nc-thanks .thanks__note{
  margin-top:var(--s-sm);
  font-size:var(--t-caption);
  color:var(--c-light);
  line-height:1.5;
}
