/* ═══════════════════════════════════════════════════════════════════════════
   BASE — the shared design system for every page on this site.

   Extracted verbatim from concepts-warm-circuit.html (2026-08-12) when
   case-studies.html was added, so the two pages cannot drift apart on the next
   token change. Nothing here was rewritten; the comments are the originals.

   Loaded by:  concepts-warm-circuit.html, case-studies.html

   NOTE: @font-face for Sentient stays inline in each HTML file. Its src is
   relative to the document, and moving it here would resolve the woff2 paths
   against assets/css/ instead of the site root.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════════
   SHARED SYSTEM — all three concepts run on exactly this much in common:
   palette, type ramp, border token, illustration craft, motion easing.
   Everything structural below diverges per concept.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  --bg:#FAF6F1;        /* page */
  --panel:#EFE7DC;     /* alternate surface */
  --ink:#10243A;       /* headline / primary text */
  --body:#33465A;      /* body text */
  --cta:#FF6F4E;       /* primary interactive */
  --accent:#2FA9A0;    /* secondary accent */
  --amber:#FFA94D;     /* tertiary */
  --ember:#C8452A;     /* darker orange */
  /* Brand coral is 2.56:1 on cream -- it fails AA for anything text-sized.
     This is the same hue darkened until it passes (5.5:1), and it is used ONLY
     for small coral text. Fills, buttons and illustration accents keep --cta. */
  --cta-text:#B0381F;
  /* One border token at low alpha, not a separate warm gray. A single
     rgba(ink) hairline stays correct over both --bg and --panel; a solid
     #E3D9CC would read wrong on one of the two. */
  --line:rgba(16,36,58,0.12);
  --line-strong:rgba(16,36,58,0.24);
  --ease:cubic-bezier(.16,1,.3,1);
}
*{box-sizing:border-box;margin:0;padding:0;}
html{scroll-behavior:smooth;}
/* The header is sticky and 74px tall, but an anchor scrolls its target to y=0 --
   so every nav jump landed the section heading underneath the bar. */
#top,#services,#about,#contact{scroll-margin-top:96px;}
body{background:var(--bg);color:var(--body);font-family:'Inter',system-ui,-apple-system,sans-serif;
  font-size:17px;line-height:1.65;-webkit-font-smoothing:antialiased;}
img{max-width:100%;display:block;}
a{color:inherit;}

/* Display type: Sentient at weight 400 with negative tracking. Size and
   tracking carry the hierarchy — headlines are never bolded. */
.d{font-family:'Sentient',Georgia,serif;font-weight:400;color:var(--ink);
  letter-spacing:-0.022em;line-height:1.06;}
.d-xl{font-size:clamp(40px,5.6vw,78px);}
.d-lg{font-size:clamp(32px,3.6vw,52px);}
.d-md{font-size:clamp(25px,2.3vw,34px);line-height:1.16;}
.d-sm{font-size:clamp(20px,1.5vw,24px);line-height:1.25;}
.mono{font-variant-numeric:tabular-nums;}
.lede{font-family:'Sentient',Georgia,serif;font-size:clamp(20px,1.9vw,26px);line-height:1.5;
  color:var(--ink);letter-spacing:-0.012em;}

/* Container. 1200px capped the content at 1120px inner at every size above it,
   so a 1920px display used 58% of its width and a 2560px display 44% — the page
   read as a narrow ribbon floating in cream. The measure now steps up twice.
   It is still capped: text set across 1800px is unreadable, so wide screens are
   SUPPOSED to have generous gutters. This just makes them generous, not vast. */
.wrap{width:100%;max-width:1320px;margin:0 auto;padding:0 40px;}
@media(min-width:1800px){ .wrap{max-width:1480px;} }
.wrap-narrow{width:100%;max-width:720px;margin:0 auto;padding:0 32px;}
.sect{padding:96px 0;}          /* 96px between major sections, not 48-64 */
.sect-lg{padding:128px 0;}
.panel{background:var(--panel);}
.rule{height:1px;background:var(--line);border:0;}

/* Fill is --ember, not --cta: white text on --cta is 2.75:1, an AA fail.
   --ember passes at 4.84:1 while staying in the same coral/orange family. */
.btn{display:inline-flex;align-items:center;gap:9px;background:var(--ember);color:#fff;
  font-size:15px;font-weight:500;padding:15px 30px;border-radius:3px;text-decoration:none;
  border:0;cursor:pointer;transition:transform .4s var(--ease),background .2s;}
.btn:hover{transform:translateY(-2px);background:#D14E31;}
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible{
  outline:2px solid var(--ink);outline-offset:3px;border-radius:2px;}
.btn-quiet{display:inline-flex;align-items:center;gap:9px;background:transparent;color:var(--ink);
  font-size:15px;font-weight:500;padding:14px 28px;border-radius:3px;text-decoration:none;
  border:1px solid var(--line-strong);transition:background .2s,border-color .2s;}
.btn-quiet:hover{background:rgba(16,36,58,0.04);border-color:var(--ink);}
.lnk{display:inline-flex;align-items:center;gap:7px;font-size:15px;font-weight:500;
  color:var(--body);text-decoration:none;transition:color .2s,gap .3s var(--ease);}
.lnk:hover{color:var(--ink);gap:11px;}

/* Fade-in on scroll. Exponential ease-out, never bounce or elastic. */
.rise{opacity:0;transform:translateY(22px);transition:opacity .9s var(--ease),transform .9s var(--ease);}
.rise.in{opacity:1;transform:none;}

/* ── Shared hero ──────────────────────────────────────────────────────────
   Identical in all three concepts, by request. Three stacked layers over one
   WebGL field:
     z0  canvas          the drifting plume field
     z1  .hero::after    wash: calms the field, and lifts a tight ellipse
                         low-centre so the 18px subhead has a readable ground
     z2  .neg            mix-blend-mode:difference — white glyphs here render
                         1 - field, the true colour negative of whatever is
                         drifting beneath them. Screen can only reveal; only
                         difference can inverpt. Everything except line 2 is
                         transparent, present purely to reserve identical
                         layout metrics so both h1 copies centre the same way.
     z3  .stage          the real, selectable content. Line 1 is solid ink.
                         Line 2 is a semi-opaque BLACK glaze over the inverted
                         glyphs, settling the raw inversion toward ink so it is
                         not overstimulating while still shifting as it moves.
   ------------------------------------------------------------------------- */
.hero{position:relative;min-height:640px;overflow:hidden;isolation:isolate;background:var(--bg);}
.hero canvas{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:0;}
.hero::after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(ellipse 40% 16% at 50% 62%,
      rgba(255,255,255,0.62) 0%, rgba(255,255,255,0.32) 62%, rgba(255,255,255,0.12) 100%),
    rgba(255,255,255,0.12);}
.neg,.stage{display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:0 24px;}
.neg{position:absolute;inset:0;z-index:2;mix-blend-mode:difference;pointer-events:none;}
.neg .l1,.neg .sub,.neg .ghost{color:transparent;}
.neg .btn{background:transparent;color:transparent;}
.neg .l2{color:#fff;}
.stage{position:relative;z-index:3;min-height:inherit;height:100%;}
.hero h1{margin:0 0 26px;max-width:19ch;}
.stage .l1{color:var(--ink);}
.stage .l2{color:rgba(0,0,0,0.36);}
.hero .sub{font-size:18px;line-height:1.65;color:var(--body);max-width:52ch;margin-bottom:38px;}
.hero .row{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:22px;}

/* ── Shared illustration frame ────────────────────────────────────────────
   The animated SVG figures carried over from the original site. Motion is
   gated on entering the viewport so the reveal reads as intentional. */
.fig svg{display:block;max-width:100%;height:auto;margin:0 auto;}
.fig .anim-arc{transition:stroke-dashoffset 1.9s var(--ease);}
/* pathLength is 100, so 40% filled means an offset of 60, not 40. */
.fig.in .anim-arc{stroke-dashoffset:60;}
.fig .anim-barx{transition:transform 1.3s var(--ease);}
.fig.in .anim-barx{transform:scaleX(1) !important;}
.fig .anim-bary{transition:transform 1.2s var(--ease);}
.fig.in .anim-bary{transform:scaleY(1) !important;}
.fig .anim-line{transition:stroke-dashoffset 1.5s var(--ease);}
.fig.in .anim-line{stroke-dashoffset:0;}
.fig .pulse{animation:pulse 3.4s ease-in-out infinite;transform-box:fill-box;transform-origin:center;}
@keyframes pulse{0%,100%{opacity:.72;transform:scale(1);}50%{opacity:1;transform:scale(1.07);}}
.fig .spin-slow{animation:spin 150s linear infinite;transform-box:fill-box;transform-origin:center;}
@keyframes spin{to{transform:rotate(360deg);}}
.fig .flow{stroke-dasharray:4 6;animation:flow 1.6s linear infinite;}
@keyframes flow{to{stroke-dashoffset:-20;}}


/* ═══════════════ NAV ═══════════════
   Sticky pill rail with a sliding indicator. Sticky matters on a page this
   tall; the alternative nav from the stat-chapters concept scrolled away. */
.nav{position:sticky;top:0;z-index:50;background:rgba(250,246,241,0.86);
  backdrop-filter:blur(14px);border-bottom:1px solid var(--line);}
.nav-in{display:flex;align-items:center;justify-content:space-between;height:74px;}
.rail{position:relative;display:flex;gap:2px;background:rgba(16,36,58,0.05);
  padding:4px;border-radius:4px;}
.rail a{position:relative;z-index:2;font-size:14px;font-weight:500;color:var(--body);
  text-decoration:none;padding:11px 18px;border-radius:2px;transition:color .3s;}
.rail a.on{color:var(--ink);}
#pill{position:absolute;top:4px;left:4px;height:calc(100% - 8px);width:100px;
  border-radius:3px;background:var(--bg);box-shadow:0 1px 3px rgba(16,36,58,.1);z-index:1;
  transform-origin:left center;transition:transform .55s var(--ease);}
/* Disclosure button for the mobile menu. Hidden on desktop, where the rail is
   always visible. 44px square — AAA target size, and it is the one control on
   the page a thumb has to hit precisely. */
.navtoggle{display:none;align-items:center;justify-content:center;width:44px;height:44px;
  flex:0 0 auto;background:transparent;border:1px solid var(--line-strong);border-radius:3px;
  cursor:pointer;color:var(--ink);transition:background .2s,border-color .2s;}
.navtoggle:hover{background:rgba(16,36,58,0.04);border-color:var(--ink);}
.navtoggle svg{width:20px;height:20px;display:block;}
.nav.open .navtoggle .i-bars,.navtoggle .i-x{display:none;}
.nav.open .navtoggle .i-x{display:block;}

/* ═══════════════ STATS STRIP ═══════════════
   Directly under the hero. These are the headline proof points, so they lead
   the page rather than being used to introduce individual services. */
.statband{border-bottom:1px solid var(--line);}
.statgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:40px;padding:56px 0 64px;}
.statgrid > div{border-top:2px solid var(--ink);padding-top:18px;}
.statv{font-family:'Sentient',Georgia,serif;font-size:clamp(36px,3.8vw,54px);color:var(--ink);
  letter-spacing:-0.035em;line-height:1;}
.statl{font-size:14px;line-height:1.4;color:var(--body);margin-top:10px;max-width:20ch;}

/* ═══════════════ SERVICE CHAPTERS ═══════════════
   Full-bleed bands alternating surface. No cards, no rounded containers.
   Each chapter is opened by its 01-04 numeral rather than by a statistic. */
.chapter{border-bottom:1px solid var(--line);}
.chapter.flip{background:var(--panel);}
/* align-items:start, not center: centring the two columns against each other is
   what made the plate float mid-band with dead space above and below it. */
.chap-in{display:grid;grid-template-columns:minmax(0,0.94fr) minmax(0,1.06fr);
  gap:64px;align-items:start;padding:104px 0;}
.chapter.flip .chap-in{grid-template-columns:minmax(0,1.06fr) minmax(0,0.94fr);}
.chapter.flip .chap-text{order:2;}
.chapter.flip .chap-fig{order:1;}
/* --ember, not --cta: --cta is 2.56:1 on cream / 2.24:1 on panel, below the
   3.0 large-text AA minimum. --ember passes both (4.5:1 / 3.95:1). */
.chapnum{font-family:'Sentient',Georgia,serif;font-weight:400;color:var(--ember);
  font-size:clamp(46px,5vw,74px);line-height:.9;letter-spacing:-0.04em;
  font-variant-numeric:tabular-nums;}
.chapname{font-size:11px;letter-spacing:.19em;text-transform:uppercase;color:var(--body);
  margin:12px 0 30px;padding-bottom:16px;border-bottom:2px solid var(--ink);
  display:inline-block;}
.chap-text h3{margin:0 0 18px;}
.chap-text p{max-width:46ch;}
.chap-text ol{list-style:none;margin-top:28px;display:grid;gap:0;}
.chap-text li{font-size:14.5px;padding:13px 0;border-top:1px solid var(--line);
  display:flex;gap:14px;}
.chap-text li:last-child{border-bottom:1px solid var(--line);}
.chap-text li b{font-family:'Sentient',Georgia,serif;font-weight:400;color:var(--cta-text);
  min-width:22px;font-size:13px;}
.plate{border:1px solid var(--line-strong);padding:22px;background:var(--bg);}
.chapter.flip .plate{background:var(--panel);}
/* The figure fills the plate. Left at its authored pixel width it rendered at
   420px inside a ~570px box, which is why every figure read as small. */
.plate .fig svg{width:100%;height:auto;}
.platecap{font-size:10.5px;letter-spacing:.17em;text-transform:uppercase;color:var(--body);
  opacity:.85;margin-bottom:16px;text-align:center;}
/* Two links close each chapter — one into the form, one to the case studies. A
   row rather than a stack: at 46ch measure they fit side by side, and stacking
   two arrow links reads as a menu instead of a pair of next steps. Wrapping is
   left on so the narrow breakpoint handles itself. */
.chapcta{display:flex;flex-wrap:wrap;gap:14px 30px;margin-top:26px;}

/* ═══════════════ SECTION OPENERS ═══════════════
   The three major sections open centred, with no frame. A ruled kicker names
   the section above the headline and a short hairline closes the block below —
   the two rules are what make the centring read as deliberate rather than as
   the default. The beige panel frame this replaced was roughly three-quarters
   empty, and framing empty space only measures it. */
.opener{text-align:center;padding:16px 0 0;}
.opener .kicker{display:inline-flex;align-items:center;gap:14px;font-size:11px;
  letter-spacing:.22em;text-transform:uppercase;color:var(--cta-text);margin-bottom:30px;}
.opener .kicker::before,.opener .kicker::after{content:'';width:40px;height:1px;
  background:var(--line-strong);}
.opener h2{margin:0 auto;max-width:20ch;}
.opener .lede{margin:22px auto 0;max-width:54ch;}
.opener .closer{width:64px;height:2px;background:var(--ink);margin:38px auto 0;}
.opener + *{margin-top:0;}

/* ═══════════════ FOUNDERS ═══════════════
   Ruled columns rather than cards, with the portraits in colour and at a size
   you can actually read a face in. */
.founders{display:grid;grid-template-columns:1fr 1fr;gap:0;border-top:2px solid var(--ink);}
.founders > div{padding:44px 40px;border-left:1px solid var(--line);}
.founders > div:first-child{border-left:0;padding-left:0;}
.founders img{width:100%;max-width:260px;aspect-ratio:4/5;border-radius:3px;
  object-fit:cover;object-position:center 18%;margin-bottom:26px;}
.frole{font-size:14.5px;color:var(--cta-text);margin:6px 0 18px;}

/* ── Contact + footer: shared skeleton, per-concept surface ─────────────── */
.form{display:grid;gap:16px;}
.form .two{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
.field label{display:block;font-size:13.5px;color:var(--body);margin-bottom:7px;}
.field input,.field textarea{width:100%;background:var(--bg);border:1px solid var(--line);
  border-radius:9px;padding:13px 15px;font-family:inherit;font-size:15px;color:var(--ink);
  transition:border-color .2s;}
.field input:focus,.field textarea:focus{outline:0;border-color:var(--cta);}
.field textarea{min-height:120px;resize:vertical;}
.contactlist{display:grid;gap:2px;}
.contactlist a,.contactlist div{display:block;text-decoration:none;padding:20px 0;
  border-top:1px solid var(--line);}
.contactlist .cl,.contactlist .cs,.contactlist .cv{display:block;}
.contactlist .cl{font-family:'Sentient',Georgia,serif;font-size:19px;color:var(--ink);}
.contactlist .cs{font-size:14px;margin-top:3px;}
.contactlist .cv{font-size:14px;color:var(--cta-text);margin-top:7px;}
.expect{list-style:none;display:grid;margin-top:18px;}
.expect li{font-size:14.5px;padding:12px 0;border-top:1px solid var(--line);}
.expect li:last-child{border-bottom:1px solid var(--line);}
/* Form states */
.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;}
.field select{width:100%;background:var(--bg);border:1px solid var(--line);border-radius:3px;
  padding:13px 15px;font-family:inherit;font-size:15px;color:var(--ink);appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--body) 50%),
    linear-gradient(135deg,var(--body) 50%,transparent 50%);
  background-position:calc(100% - 19px) 50%,calc(100% - 13px) 50%;
  background-size:6px 6px,6px 6px;background-repeat:no-repeat;}
.field select:focus{outline:0;border-color:var(--cta);}
.err{font-size:13.5px;color:var(--cta-text);margin-top:6px;}
.field.invalid input,.field.invalid textarea{border-color:var(--cta-text);}
.summary{border:1px solid var(--cta-text);background:rgba(176,56,31,0.06);
  padding:16px 18px;font-size:14.5px;border-radius:3px;}
.summary:focus{outline:2px solid var(--ink);outline-offset:2px;}
.summary ul{margin:8px 0 0 18px;display:grid;gap:5px;}
.summary a{color:var(--cta-text);}
.formnote{font-size:13.5px;color:var(--body);}
/* align-self so the panel does not stretch to the taller sidebar column --
   the form has no background so its stretch was invisible; this one's is not. */
.sent{border:1px solid var(--line-strong);background:var(--panel);padding:32px 30px;
  align-self:start;border-radius:3px;}
.sent:focus{outline:2px solid var(--ink);outline-offset:3px;}
.receipt{margin:22px 0 26px;display:grid;gap:0;}
.receipt > div{display:grid;grid-template-columns:96px 1fr;gap:16px;padding:11px 0;
  border-top:1px solid var(--line);font-size:14px;}
.receipt dt{color:var(--body);}
.receipt dd{color:var(--ink);overflow-wrap:anywhere;}
button.more{background:none;border:0;padding:6px 0;margin-top:4px;cursor:pointer;
  font-family:inherit;font-size:14px;color:var(--cta-text);text-decoration:underline;
  text-underline-offset:3px;}
/* Capped measure. These columns grow with the container, and at the widened
   1480px tier an uncapped bio would set past 90 characters a line. */
.bio p{font-size:14.5px;max-width:62ch;}

/* ═══════════════ FAQ ═══════════════
   Native <details>/<summary> — free keyboard support and no JS needed to
   toggle. */
.faqitem{border-top:1px solid var(--line);padding:20px 0;}
.faqitem:last-child{border-bottom:1px solid var(--line);}
.faqitem summary{cursor:pointer;font-family:'Sentient',Georgia,serif;font-size:19px;
  color:var(--ink);list-style:none;display:flex;align-items:baseline;justify-content:space-between;
  gap:20px;}
.faqitem summary::-webkit-details-marker{display:none;}
.faqitem summary::after{content:'+';font-size:20px;color:var(--cta-text);flex:0 0 auto;}
.faqitem[open] summary::after{content:'–';}
.faqitem p{margin-top:14px;max-width:62ch;font-size:15px;}

/* Dark CTA band -- the navy surface used when a CTA needs more weight than
   the cream/panel treatment gives it. */
.ctaband{background:var(--ink);color:rgba(245,240,234,0.78);}
.ctaband h2{color:#fff;}

footer{border-top:1px solid var(--line);padding:64px 0 40px;}
.footgrid{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:40px;}
.footgrid h3{font-family:'Sentient',Georgia,serif;font-size:16px;color:var(--ink);
  margin-bottom:16px;font-weight:400;}
.footgrid ul{list-style:none;display:grid;gap:2px;}
.footgrid a,.footgrid li{font-size:14px;text-decoration:none;display:inline-block;padding:4px 0;}
.footgrid a:hover{color:var(--ink);}
.footbase{margin-top:52px;padding-top:24px;border-top:1px solid var(--line);
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px;font-size:13px;}
.logo{height:26px;width:auto;}

@media (prefers-reduced-motion: reduce){
  .rise{opacity:1;transform:none;transition:none;}
  .fig .pulse,.fig .spin-slow,.fig .flow{animation:none;}
  .fig .anim-arc,.fig .anim-barx,.fig .anim-bary,.fig .anim-line{transition:none;}
  #pill,.btn,.btn-quiet,.lnk,.rail a{transition:none;}
  .btn:hover{transform:none;}
  html{scroll-behavior:auto;}
}

@media(max-width:900px){
  .cgrid,.headrow{grid-template-columns:1fr !important;gap:34px !important;}
  .wrap{padding:0 24px;}
  .sect,.sect-lg{padding:72px 0;}
  .statgrid{grid-template-columns:1fr 1fr;gap:28px;padding:44px 0 48px;}
  /* `.chapter.flip .chap-in` (3 classes) outranks a bare `.chap-in` — media
     queries add no specificity — so without naming it here the flipped chapters
     stayed two-column on phones and their plates rendered at 143px. */
  .chap-in,.chapter.flip .chap-in,.founders,.footgrid,.form .two{grid-template-columns:1fr;}
  .chap-in{gap:38px;padding:64px 0;}
  .chapter.flip .chap-text{order:1;}
  .chapter.flip .chap-fig{order:2;}
  .founders > div{padding:34px 0;border-left:0;border-top:1px solid var(--line);}
  .founders > div:first-child{border-top:0;}
  /* The rail becomes a disclosure panel rather than disappearing. Previously
     it was simply display:none below 900px, which left phones with no way to
     reach Services, About or Contact at all. */
  .navtoggle{display:inline-flex;}
  .nav-in{gap:12px;}
  .rail{display:none;position:absolute;top:100%;left:0;right:0;flex-direction:column;
    gap:0;padding:6px 24px 14px;border-radius:0;background:var(--bg);
    border-bottom:1px solid var(--line);box-shadow:0 14px 28px rgba(16,36,58,.08);}
  .nav.open .rail{display:flex;}
  .rail a{padding:16px 2px;font-size:16px;border-radius:0;
    border-bottom:1px solid var(--line);}
  .rail a:last-child{border-bottom:0;}
  .rail a.on{color:var(--cta-text);}
  #pill{display:none;}
  .hero h1{max-width:16ch;}
  .d-xl{font-size:clamp(31px,8.4vw,46px);}
}

/* Narrow phones. The 157px logo + 93px CTA + 44px toggle + gaps + gutters came
   to 366px, so a 320px device (iPhone SE, and the narrowest width worth
   supporting) scrolled sideways. Nothing is dropped — everything shrinks. */
@media(max-width:400px){
  .nav-in{gap:8px;}
  .logo{height:22px;}
  .nav-in .btn{padding:11px 14px;font-size:13px;}
}
