/* ============================================================
   Brad O'Haire portfolio - shared design system
   Single source of truth for tokens + components across every page.
   Extracted from the original single-file index.html, plus shared
   chrome (header/footer active states, mobile nav) and case-study styles.
   A token change here propagates to every page.
   ============================================================ */

:root{
  --bg:#0a0b0f; --panel:#13151c; --panel2:#181b24; --line:#262a36;
  --ink:#e7e9ee; --muted:#9aa3b2; --dim:#8a92a6;
  --accent:#6ea8fe; --accent2:#9d7bff; --ok:#43d692;
  --radius:16px; --maxw:1040px;
}
*{box-sizing:border-box}
/* The page background lives on <html> so it is the bottom-most backstop. The
   ambient canvas (position:fixed; z-index:-1, injected by site.js) then sits
   above this backstop but below the transparent <body> content, so it shows
   through without any markup change. The gradient is unchanged from before. */
html{scroll-behavior:smooth;
  background:radial-gradient(1200px 600px at 80% -10%, #1a1f2e 0%, var(--bg) 55%) no-repeat, var(--bg)}
body{
  margin:0; background:transparent;
  color:var(--ink); font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px}

/* focus visibility for keyboard users */
a:focus-visible, button:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:6px}

/* visually hidden but available to screen readers (e.g. aria-live status) */
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* skip link: first focusable element on every page */
.skip-link{position:absolute;left:-9999px;top:0;z-index:100;background:var(--accent);color:#0a0b0f;
  padding:10px 16px;border-radius:0 0 10px 0;font-weight:700;font-size:14px}
.skip-link:focus{left:0}

/* nav (shared chrome, identical markup per page) */
nav{position:sticky;top:0;z-index:10;backdrop-filter:blur(10px);
  background:rgba(10,11,15,.6);border-bottom:1px solid var(--line)}
nav .wrap{display:flex;align-items:center;justify-content:space-between;height:60px}
.brand{font-weight:700;letter-spacing:.2px}
.brand span{color:var(--accent)}
.navlinks a{color:var(--muted);margin-left:22px;font-size:14px}
.navlinks a:hover{color:var(--ink)}
/* active page marker: the current page's nav item gets ink color + an underline */
.navlinks a[aria-current="page"]{color:var(--ink);
  border-bottom:2px solid var(--accent);padding-bottom:3px}

/* ============================================================
   Site-wide ambient backdrop (injected by site.js on every page).
   A single fixed, full-viewport canvas that sits BEHIND all content:
   fixed so it never adds scroll height or horizontal overflow, low opacity
   so text stays fully legible, pointer-events:none and aria-hidden so it is
   inert and invisible to assistive tech. It draws a faint night-sky starfield
   (drifting, lightly twinkling stars joined by constellation links), the same
   star language as the hero, kept quiet here as ambient depth.

   CONSISTENCY: the layer carries the SAME on every page. It uses ONE flat,
   even, full-viewport opacity with NO directional mask, so the sky has the
   same density and brightness top-to-bottom and page-to-page (the old radial
   mask anchored at the top-right made the field uneven and made content pages
   feel different from home). The only per-page exception is the home hero:
   .has-hero eases just the top band so the bright hero cluster is not crowded,
   then the same starfield resumes immediately below, keeping the sky unified. */
#ambient-bg{position:fixed;inset:0;width:100vw;height:100vh;z-index:-1;
  opacity:.62;pointer-events:none}
/* Home only: gently fade the top band (the hero's vertical span) so the bright
   hero constellation stays the focal cluster, then bring the ambient sky fully
   in just below the hero. The fade is short so the field still carries down the
   whole page exactly like every other page. */
body.has-hero #ambient-bg{
  -webkit-mask-image:linear-gradient(180deg,rgba(0,0,0,.28) 0,rgba(0,0,0,.72) 32vh,#000 64vh);
  mask-image:linear-gradient(180deg,rgba(0,0,0,.28) 0,rgba(0,0,0,.72) 32vh,#000 64vh)}

/* hero */
header{position:relative;padding:88px 0 56px;overflow:hidden}
#hero-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:0;opacity:.55;pointer-events:none}
header .wrap{position:relative;z-index:1}
/* Static labeled orchestration diagram: shown ONLY under reduced-motion, where the
   animated canvas is suppressed. Same coordinator -> specialists -> auditor topology,
   no pulse, no motion. Hidden for everyone else. */
#hero-static{display:none}
#hero-static .hs-link{stroke:var(--accent);stroke-width:1.4;opacity:.5}
/* the verdict paths carry the same colors as the animated tokens */
#hero-static .hs-pass{stroke:var(--ok);opacity:.55}
#hero-static .hs-revise{stroke:#f6c454;opacity:.55;stroke-dasharray:5 4}
#hero-static .hs-node{fill:var(--accent)}
#hero-static .hs-ring{fill:none;stroke:var(--accent2);stroke-width:1.2;opacity:.55}
#hero-static .hs-label{fill:var(--muted);font-size:11px;font-weight:600;text-anchor:middle}
/* small flow labels naming the sequence (task / result / pass / revise) */
#hero-static .hs-flow{fill:var(--accent);font-size:10px;font-weight:600;text-anchor:middle;opacity:.85}
#hero-static .hs-flow-ok{fill:var(--ok)}
#hero-static .hs-flow-amber{fill:#f6c454}
.eyebrow{color:var(--accent);font-weight:600;font-size:13px;letter-spacing:2px;text-transform:uppercase}
h1{font-size:clamp(34px,6vw,58px);line-height:1.05;margin:14px 0 0;letter-spacing:-1px}
h1 .grad{color:var(--accent2)}
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  h1 .grad{background:linear-gradient(90deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
}
.lede{color:var(--muted);font-size:clamp(17px,2.2vw,20px);max-width:660px;margin:22px 0 0}
.cta{display:flex;gap:12px;flex-wrap:wrap;margin-top:32px}
/* honest role-fit line: subtle, muted, sits just under the hero CTA row */
.open-to{color:var(--muted);font-size:14px;margin:18px 0 0;max-width:660px}
.open-to b{color:var(--ink);font-weight:600}
.btn{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:11px 18px;border-radius:12px;font-weight:600;font-size:14px;border:1px solid var(--line)}
.btn.primary{background:linear-gradient(90deg,var(--accent),var(--accent2));color:#0a0b0f;border:none}
.btn:hover{transform:translateY(-1px)}
.btn.ghost:hover{border-color:var(--accent)}

/* sections */
section{padding:48px 0}
.sec-head{display:flex;align-items:baseline;gap:14px;margin-bottom:26px}
/* page-title h1 in a section head reads identically to the h2 section heads */
.sec-head h1, .sec-head h2{font-size:24px;margin:0;letter-spacing:-.3px;font-weight:700}
.sec-head .rule{flex:1;height:1px;background:var(--line)}

/* project grid */
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:18px}
.card{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);border-radius:var(--radius);padding:24px;display:flex;flex-direction:column;transition:.2s}
.card:hover{border-color:#37405a;transform:translateY(-3px);box-shadow:0 18px 40px -24px rgba(110,168,254,.5)}
.tag{display:inline-block;font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--accent);background:rgba(110,168,254,.1);border:1px solid rgba(110,168,254,.25);padding:4px 9px;border-radius:999px}
.card h3{margin:16px 0 8px;font-size:20px}
.card p{color:var(--muted);font-size:14.5px;margin:0 0 16px;flex:1}
.stack{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:18px}
.chip{font-size:11.5px;color:var(--dim);border:1px solid var(--line);border-radius:6px;padding:3px 8px}
.card .links{display:flex;gap:14px;font-size:13.5px;font-weight:600}
.card .links a{color:var(--accent)}
.card .links a:hover{text-decoration:underline}

/* highlights */
.hl{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}
.hl div{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:20px}
.hl b{display:block;font-size:28px;background:linear-gradient(90deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
.hl span{color:var(--muted);font-size:14px}
/* "verify ->" receipt links: subtle, only ever pointing at a real public repo */
.verify{display:inline-block;margin-top:10px;font-size:12.5px;font-weight:600;color:var(--accent)}
.verify:hover{text-decoration:underline}

/* guardrail / safety-floor proof strip (illustrative, not a live system) */
#guardrails .wrap{position:relative;z-index:1}
.guard{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:24px 24px 22px}
.guard-cap{color:var(--dim);font-size:12.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;margin:0 0 8px}
.guard-frame{color:var(--muted);font-size:15px;max-width:640px;margin:0 0 6px}
.guard-frame b{color:var(--ink);font-weight:600}
.guard-note{color:var(--dim);font-size:12.5px;margin:0 0 18px}
.guard-actions{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:18px}
.guard-run{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 16px;border-radius:11px;font-weight:600;
  font-size:13.5px;cursor:pointer;background:linear-gradient(90deg,var(--accent),var(--accent2));color:#0a0b0f;border:none}
.guard-run:hover{transform:translateY(-1px)}
.guard-reset{display:inline-flex;align-items:center;min-height:44px;padding:10px 14px;border-radius:11px;font-weight:600;
  font-size:13.5px;cursor:pointer;background:transparent;color:var(--muted);border:1px solid var(--line)}
.guard-reset:hover{border-color:var(--accent);color:var(--ink)}
.guard-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
/* each row is a button so it is keyboard-operable and focusable on its own */
.guard-row{display:flex;align-items:center;gap:14px;width:100%;text-align:left;cursor:pointer;
  background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:13px 16px;
  color:var(--ink);font:inherit;transition:border-color .2s ease,background .2s ease}
.guard-row:hover{border-color:#37405a}
.guard-act{flex:1;font-size:14.5px}
.guard-arrow{color:var(--dim);font-size:14px;flex:0 0 auto}
/* verdict stamp: hidden until "stamped" (revealed), then fades/scales in */
.guard-verdict{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:700;
  letter-spacing:.5px;text-transform:uppercase;border-radius:999px;padding:5px 12px;border:1px solid transparent;
  opacity:0;transform:scale(.86);transition:opacity .32s ease,transform .32s cubic-bezier(.22,1.4,.4,1)}
.guard-row.stamped .guard-verdict{opacity:1;transform:none}
.guard-row.stamped .guard-arrow{color:var(--accent)}
.guard-verdict .dot{width:7px;height:7px;border-radius:50%}
/* verdict palettes: allowed green, needs-approval amber, blocked red */
.v-allow{color:var(--ok);background:rgba(67,214,146,.12);border-color:rgba(67,214,146,.4)}
.v-allow .dot{background:var(--ok)}
.v-approve{color:#f6c454;background:rgba(246,196,84,.12);border-color:rgba(246,196,84,.4)}
.v-approve .dot{background:#f6c454}
.v-block{color:#ff6b6b;background:rgba(255,107,107,.13);border-color:rgba(255,107,107,.45)}
.v-block .dot{background:#ff6b6b}
.guard-illus{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  color:var(--dim);border:1px solid var(--line);border-radius:5px;padding:2px 7px;margin-left:8px;vertical-align:middle}
@media (max-width:480px){
  .guard{padding:20px 14px 18px}
  .guard-row{flex-wrap:wrap;gap:8px 12px;padding:12px 13px}
  .guard-act{flex:1 1 100%;font-size:14px}
  .guard-arrow{order:3}
}

/* about */
.about p{color:var(--muted);max-width:720px}
.about p strong{color:var(--ink);font-weight:600}

/* approach / how I build */
.sec-intro{color:var(--muted);max-width:700px;margin:-10px 0 26px;font-size:15px}

/* "How this page is built" teardown: opt-in collapsed details, the page proving itself */
.teardown{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);margin-top:18px;overflow:hidden}
.teardown summary{cursor:pointer;list-style:none;padding:18px 22px;display:flex;align-items:center;gap:12px;
  font-weight:600;font-size:15.5px;color:var(--ink)}
.teardown summary::-webkit-details-marker{display:none}
.teardown summary .chev{color:var(--accent);font-size:13px;transition:transform .25s ease;flex:0 0 auto}
.teardown[open] summary .chev{transform:rotate(90deg)}
/* summary holds a title plus a muted one-line teaser so a fast scanner gets the hook */
.teardown summary .td-head{display:flex;flex-direction:column;gap:3px;min-width:0}
.teardown summary .td-teaser{color:var(--muted);font-size:12.5px;font-weight:400;letter-spacing:0}
.teardown summary .td-tag{margin-left:auto;font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--dim);border:1px solid var(--line);border-radius:5px;padding:3px 8px}
.teardown-body{padding:0 22px 22px;color:var(--muted);font-size:14.5px}
.teardown-body p{margin:0 0 14px;max-width:760px}
.teardown-body ul{margin:0 0 14px;padding-left:18px;max-width:760px}
.teardown-body li{margin:0 0 9px}
.teardown-body li b{color:var(--ink);font-weight:600}
.teardown-body code{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:1px 6px;
  font-size:12.5px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.teardown-body .td-src{color:var(--dim);font-size:13px;margin-top:4px}
@media (max-width:480px){
  .teardown summary{padding:15px 14px;font-size:14.5px}
  .teardown summary .td-tag{display:none}
  .teardown-body{padding:0 14px 18px}
}

/* ============================================================
   Agent-driven delivery: honest ROI panel (Home) + expanded
   block (About). Reuses panel/card tokens. The cost/time figure
   is always rendered as a clearly labeled ESTIMATE with its
   assumptions shown, never as a measured metric.
   ============================================================ */
.adel{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:24px 24px 22px}
.adel-lede{color:var(--muted);font-size:15.5px;max-width:720px;margin:0 0 20px}
.adel-lede b{color:var(--ink);font-weight:600}
/* supporting points: compact 2-col grid that collapses to one column on phones */
.adel-points{list-style:none;margin:0 0 22px;padding:0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px}
.adel-points li{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:14px 16px}
.adel-points .ap-h{display:block;color:var(--ink);font-weight:600;font-size:14.5px;margin:0 0 4px}
.adel-points .ap-b{display:block;color:var(--muted);font-size:13.5px;line-height:1.5}
/* the estimate callout: bordered, with a small "Estimate" tag so it never reads as measured fact */
.adel-est{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:16px 18px}
.adel-est-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 8px}
.adel-est-head .est-tag{font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  color:var(--accent);background:rgba(110,168,254,.1);border:1px solid rgba(110,168,254,.25);
  border-radius:999px;padding:3px 9px}
.adel-est-head .est-title{color:var(--ink);font-weight:600;font-size:14.5px}
.adel-est p{color:var(--muted);font-size:14px;line-height:1.6;margin:0 0 10px;max-width:720px}
.adel-est p:last-child{margin-bottom:0}
.adel-est .est-assume{color:var(--dim);font-size:12.5px;line-height:1.55;margin:0}
.adel-est .est-assume b{color:var(--muted);font-weight:600}
/* footer link from the home panel out to the fuller about block */
.adel-more{margin:18px 0 0;font-size:13.5px;font-weight:600}
.adel-more a{color:var(--accent)}
.adel-more a:hover{text-decoration:underline}
@media (max-width:480px){
  .adel{padding:20px 14px 18px}
  .adel-est{padding:14px 14px}
}

/* "How a run works" process flow diagram (inline SVG, no library) */
.flow{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:22px 24px 18px;margin-bottom:18px}
.flow-cap{color:var(--dim);font-size:12.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;margin:0 0 14px}
.flow svg{display:block;width:100%;height:auto;overflow:visible}
/* connecting paths draw in; dimmed until revealed */
.flow .flow-link{fill:none;stroke:var(--line);stroke-width:2}
.flow .flow-link.draw{stroke:url(#flowGrad);stroke-dasharray:var(--len);stroke-dashoffset:var(--len);
  transition:stroke-dashoffset 1s cubic-bezier(.22,1,.36,1)}
.flow .flow-loop{fill:none;stroke:var(--accent2);stroke-width:1.6;stroke-dasharray:5 5;opacity:.5}
.flow .flow-loop.draw{stroke-dashoffset:var(--len);transition:stroke-dashoffset 1.1s ease .2s}
/* stage chips light up in sequence */
.flow .stage rect{fill:var(--panel2);stroke:var(--line);stroke-width:1.4;transition:fill .45s ease,stroke .45s ease}
.flow .stage text{fill:var(--muted);font-size:13px;font-weight:600;transition:fill .45s ease}
.flow .stage circle{fill:var(--line);transition:fill .45s ease}
.flow.lit .stage.on rect{fill:rgba(110,168,254,.12);stroke:var(--accent)}
.flow.lit .stage.on text{fill:var(--ink)}
.flow.lit .stage.on circle{fill:var(--accent)}
.flow-loop-label{fill:var(--accent2);font-size:10.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;opacity:.8}
@media (max-width:480px){
  .flow{padding:18px 14px 14px}
  .flow .stage text{font-size:11px}
}

/* data experience section */
#data{position:relative}
/* faint echo of the hero node-network behind the Data heading area.
   Sits under the content (z-index:0), low opacity so the heading and viz stay readable. */
#data-echo{position:absolute;top:0;left:0;width:100%;height:300px;z-index:0;opacity:.22;
  pointer-events:none;-webkit-mask-image:linear-gradient(180deg,#000 0%,#000 55%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 0%,#000 55%,transparent 100%)}
#data .wrap{position:relative;z-index:1}
.data-lede{color:var(--muted);max-width:740px;margin:-10px 0 28px;font-size:15.5px}
.data-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:16px;margin-bottom:30px}
.data-cols .card h3{font-size:17px;margin:14px 0 8px}
.data-cols .card p{font-size:14px}

/* "Built in production" block: two REAL shipped agents (not illustrative).
   Reuses .card tokens; the outcome metric is a big animated count-up. */
.built-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:2px 0 6px}
.built-head h3{font-size:18px;margin:0;letter-spacing:-.2px}
.built-lede{color:var(--muted);max-width:740px;margin:0 0 18px;font-size:14.5px}
.built-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px;margin-bottom:30px}
/* "Production" tag: green, deliberately distinct from the muted "Illustrative" badges below */
.tag.prod{color:var(--ok);background:rgba(67,214,146,.1);border-color:rgba(67,214,146,.3)}
.built-grid .card h3{font-size:18px;margin:14px 0 6px}
.built-grid .card p{font-size:14px;margin:0 0 18px}
/* big animated outcome metric, sits at the foot of each card */
.metric{display:flex;align-items:baseline;gap:10px;margin-top:auto;padding-top:14px;border-top:1px solid var(--line)}
.metric b{font-size:40px;line-height:1;font-variant-numeric:tabular-nums;
  background:linear-gradient(90deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
.metric .metric-label{color:var(--muted);font-size:13px;line-height:1.3;max-width:160px}
.built-note{color:var(--dim);font-size:12.5px;margin:0 0 30px;max-width:740px}
@media (max-width:480px){
  .metric b{font-size:34px}
  .built-grid{gap:12px}
}

.viz-grid{display:grid;grid-template-columns:1.35fr 1fr;gap:18px}
@media (max-width:760px){ .viz-grid{grid-template-columns:1fr} }
.viz{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);border-radius:var(--radius);padding:22px}
.viz h3{margin:0 0 4px;font-size:16px}
.viz .viz-sub{color:var(--dim);font-size:12.5px;margin:0 0 16px}
.viz .illustrative{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--dim);border:1px solid var(--line);border-radius:5px;padding:2px 7px;margin-left:8px;vertical-align:middle}
.viz svg{display:block;width:100%;height:auto;overflow:visible}
.legend{display:flex;flex-wrap:wrap;gap:14px;margin-top:14px;font-size:12px;color:var(--muted)}
.legend span{display:inline-flex;align-items:center;gap:6px}
.legend i{width:12px;height:3px;border-radius:2px;display:inline-block}
.bar-row{display:flex;align-items:center;gap:12px;margin:11px 0;font-size:13px}
.bar-row .bar-label{flex:0 0 122px;color:var(--muted)}
.bar-track{flex:1;height:10px;background:var(--line);border-radius:6px;overflow:hidden}
.bar-fill{height:100%;width:0;border-radius:6px;background:linear-gradient(90deg,var(--accent),var(--accent2));transition:width 1.1s cubic-bezier(.22,1,.36,1)}
.bar-row .bar-val{flex:0 0 38px;text-align:right;color:var(--dim);font-variant-numeric:tabular-nums}

footer{border-top:1px solid var(--line);padding:32px 0 56px;color:var(--dim);font-size:13.5px}
footer .wrap{display:flex;justify-content:space-between;width:100%;flex-wrap:wrap;gap:12px}
footer a{color:var(--muted)} footer a:hover{color:var(--ink)}

/* scroll reveal */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .7s ease, transform .7s cubic-bezier(.22,1,.36,1)}
.reveal.in{opacity:1;transform:none}
.reveal.d1{transition-delay:.06s}
.reveal.d2{transition-delay:.12s}
.reveal.d3{transition-delay:.18s}

/* ============================================================
   Work index page
   ============================================================ */
.work-intro{color:var(--muted);max-width:720px;margin:-8px 0 30px;font-size:15.5px}
.work-group{margin-bottom:34px}
.work-group-head{display:flex;align-items:baseline;gap:12px;margin:0 0 16px}
.work-group-head h2{font-size:18px;margin:0;letter-spacing:-.2px;color:var(--ink)}
.work-group-head .rule{flex:1;height:1px;background:var(--line)}
.work-group-head .count{color:var(--dim);font-size:12.5px;font-variant-numeric:tabular-nums}
/* a work card is a full-card link; the outcome teaser sits above the chip row */
.card .outcome{display:inline-block;font-size:12.5px;font-weight:700;letter-spacing:.3px;
  color:var(--ok);background:rgba(67,214,146,.1);border:1px solid rgba(67,214,146,.3);
  border-radius:999px;padding:4px 10px;margin:0 0 14px;align-self:flex-start}
.card .outcome.q{color:var(--accent);background:rgba(110,168,254,.1);border-color:rgba(110,168,254,.25)}
.card.soon{opacity:.92}
.card .soon-flag{font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--dim)}

/* ============================================================
   Case-study page (fixed 11-section template)
   ============================================================ */
.cs-head{padding:64px 0 8px}
.cs-back{display:inline-flex;align-items:center;gap:7px;color:var(--muted);font-size:13.5px;font-weight:600;margin-bottom:22px}
.cs-back:hover{color:var(--ink)}
.cs-eyebrow{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.cs-h1{font-size:clamp(28px,4.6vw,42px);line-height:1.1;margin:0;letter-spacing:-.6px;max-width:880px}
.cs-summary{color:var(--muted);font-size:clamp(16px,2vw,18px);max-width:760px;margin:18px 0 0}
/* outcome line, above the fold, the result stated first */
.cs-outcome{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin:28px 0 0;
  background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:22px 24px}
.cs-outcome b{font-size:clamp(36px,6vw,52px);line-height:1;font-variant-numeric:tabular-nums;
  background:linear-gradient(90deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
.cs-outcome .cs-outcome-label{color:var(--muted);font-size:14.5px;line-height:1.35;max-width:300px}
/* qualitative outcome variant: no big number, a stated result */
.cs-outcome.q{display:block}
.cs-outcome.q p{margin:0;color:var(--ink);font-size:16px;max-width:680px}

.cs-body section{padding:34px 0;border-top:1px solid var(--line)}
.cs-body section:first-of-type{border-top:none}
.cs-body h2{font-size:21px;margin:0 0 14px;letter-spacing:-.2px}
.cs-body p{color:var(--muted);max-width:760px;margin:0 0 14px;font-size:15.5px}
.cs-body p strong{color:var(--ink);font-weight:600}
.cs-body ul{color:var(--muted);max-width:760px;margin:0 0 14px;padding-left:20px;font-size:15.5px}
.cs-body li{margin:0 0 10px}
.cs-body li strong{color:var(--ink);font-weight:600}

/* the capability-then-leash decision list */
.decisions{list-style:none;padding:0;margin:0 0 8px;display:flex;flex-direction:column;gap:14px;max-width:820px}
.decisions li{display:flex;flex-direction:column;gap:5px;background:var(--panel);border:1px solid var(--line);
  border-radius:12px;padding:16px 18px;margin:0}
.decisions .d-cap{color:var(--ink);font-weight:600;font-size:15px}
.decisions .d-leash{color:var(--muted);font-size:14px}
.decisions .d-leash b{color:var(--accent);font-weight:600}

/* dedicated guardrails block: the through-line, never buried in prose */
.cs-guardrails{background:linear-gradient(180deg,var(--panel),var(--panel2));
  border:1px solid rgba(255,107,107,.28);border-radius:var(--radius);padding:24px}
.cs-guardrails h2{margin:0 0 6px}
.cs-guardrails .gr-sub{color:var(--dim);font-size:13px;margin:0 0 16px;max-width:680px}
.cs-guardrails ul{list-style:none;padding:0;margin:0;max-width:760px;display:flex;flex-direction:column;gap:11px}
.cs-guardrails li{display:flex;align-items:flex-start;gap:12px;margin:0;color:var(--muted);font-size:14.5px}
.cs-guardrails li .gr-no{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;font-size:11px;
  font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:#ff6b6b;background:rgba(255,107,107,.12);
  border:1px solid rgba(255,107,107,.4);border-radius:999px;padding:4px 11px;margin-top:1px;white-space:nowrap}
.cs-guardrails li span:last-child strong{color:var(--ink);font-weight:600}

/* role line */
.cs-role{color:var(--muted);font-size:15.5px;max-width:760px}
.cs-role strong{color:var(--ink);font-weight:600}

/* links / verify block */
.cs-links p{margin:0 0 4px}
.cs-links .cs-verify{display:inline-flex;align-items:center;gap:7px;color:var(--accent);font-weight:600;font-size:14.5px}
.cs-links .cs-verify:hover{text-decoration:underline}
.cs-links .cs-nolink{color:var(--dim);font-size:14px;max-width:720px}

/* prev / next cross-links */
.cs-nav{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  border-top:1px solid var(--line);padding:28px 0 0;margin-top:8px}
.cs-nav a{display:flex;flex-direction:column;gap:4px;color:var(--muted);font-size:14px;max-width:48%}
.cs-nav a:hover{color:var(--ink)}
.cs-nav .cs-nav-dir{color:var(--dim);font-size:12px;font-weight:700;letter-spacing:.5px;text-transform:uppercase}
.cs-nav .cs-nav-title{color:var(--accent);font-weight:600;font-size:15px}
.cs-nav a.next{text-align:right;align-items:flex-end;margin-left:auto}
@media (max-width:480px){
  .cs-head{padding:40px 0 8px}
  .cs-nav a{max-width:100%}
  .cs-outcome{padding:18px 16px}
}

/* ============================================================
   First-pass triage demo (case study only).
   Honest, interactive illustration on SYNTHETIC data. Reuses the
   panel/card/chip tokens and the verdict-pill pattern from the
   guardrail strip. All numbers are computed live in site.js.
   ============================================================ */
.triage{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:24px 24px 22px}
.triage-cap{color:var(--dim);font-size:12.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;margin:0 0 8px}
/* the synthetic-data honesty badge, deliberately prominent */
.triage-cap .triage-illus{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.5px;
  text-transform:uppercase;color:var(--dim);border:1px solid var(--line);border-radius:5px;
  padding:2px 7px;margin-left:8px;vertical-align:middle}
.triage-frame{color:var(--muted);font-size:15px;max-width:680px;margin:0 0 6px}
.triage-frame b{color:var(--ink);font-weight:600}
/* the required, visible honesty label */
.triage-honesty{color:var(--dim);font-size:12.5px;line-height:1.55;margin:0 0 18px;max-width:680px}
.triage-honesty b{color:var(--muted);font-weight:600}

.triage-actions{display:flex;align-items:center;gap:10px 14px;flex-wrap:wrap;margin-bottom:16px}
.triage-run{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 16px;border-radius:11px;
  font-weight:600;font-size:13.5px;cursor:pointer;background:linear-gradient(90deg,var(--accent),var(--accent2));
  color:#0a0b0f;border:none}
.triage-run:hover{transform:translateY(-1px)}
.triage-reset{display:inline-flex;align-items:center;min-height:44px;padding:10px 14px;border-radius:11px;
  font-weight:600;font-size:13.5px;cursor:pointer;background:transparent;color:var(--muted);border:1px solid var(--line)}
.triage-reset:hover{border-color:var(--accent);color:var(--ink)}

/* confidence threshold control: a real labeled range input */
.triage-thresh{display:inline-flex;align-items:center;gap:10px;flex:1 1 280px;min-width:240px}
.triage-thresh label{color:var(--muted);font-size:13px;white-space:nowrap}
.triage-thresh input[type=range]{flex:1;min-width:120px;accent-color:var(--accent);height:24px;cursor:pointer}
.triage-thresh .triage-thresh-val{color:var(--ink);font-weight:600;font-size:13.5px;font-variant-numeric:tabular-nums;
  min-width:42px;text-align:right}

/* results panel: four live-computed metric cells */
.triage-results{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:4px 0 20px}
.tr-cell{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:15px 16px}
.tr-cell b{display:block;font-size:30px;line-height:1;font-variant-numeric:tabular-nums;
  background:linear-gradient(90deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
.tr-cell span{display:block;color:var(--muted);font-size:13px;line-height:1.4;margin-top:8px}
.tr-cell .tr-sub{display:block;color:var(--dim);font-size:11.5px;margin-top:3px}

/* two-state stage: raw flat queue vs triaged grouped queue */
.triage-stage{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media (max-width:760px){ .triage-stage{grid-template-columns:1fr} }
.triage-pane{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:16px;min-width:0}
.triage-pane h3{margin:0 0 3px;font-size:15px;color:var(--ink)}
.triage-pane .tp-sub{color:var(--dim);font-size:12.5px;margin:0 0 14px}
/* before "Run first pass": raw pane is lit, triaged pane is dimmed. After: swap. */
.triage-stage .pane-triaged{opacity:.5;transition:opacity .4s ease}
.triage-stage.is-triaged .pane-raw{opacity:.5}
.triage-stage.is-triaged .pane-triaged{opacity:1}

/* scrollable item lists so the panel never grows unbounded */
.triage-scroll{max-height:340px;overflow-y:auto;margin:0;padding:0;list-style:none}
.triage-item{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;
  background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:9px 11px;margin:0 0 7px}
.triage-item .ti-text{color:var(--ink);font-size:13px;line-height:1.4}
.ti-unlabeled{flex:0 0 auto;font-size:10.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;
  color:var(--dim);border:1px dashed var(--line);border-radius:5px;padding:3px 7px;margin-top:1px;white-space:nowrap}
.ti-meta{flex:0 0 auto;display:flex;align-items:center;gap:8px;margin-top:1px}
.ti-conf{color:var(--dim);font-size:12px;font-variant-numeric:tabular-nums}
/* confidence-lane pills reuse the guardrail verdict palette: auto=green, review=amber */
.ti-lane{font-size:10.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;border-radius:999px;
  padding:3px 9px;white-space:nowrap;border:1px solid transparent}
.lane-auto{color:var(--ok);background:rgba(67,214,146,.12);border-color:rgba(67,214,146,.4)}
.lane-review{color:#f6c454;background:rgba(246,196,84,.12);border-color:rgba(246,196,84,.4)}

/* grouped (triaged) queue: category headers, sorted items beneath */
.triage-group{margin:0 0 14px}
.triage-group:last-child{margin-bottom:0}
.tg-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 0 8px}
.tg-name{color:var(--ink);font-weight:600;font-size:13.5px}
.tg-count{color:var(--dim);font-size:11.5px;font-variant-numeric:tabular-nums}
.tg-list{list-style:none;margin:0;padding:0}

@media (max-width:480px){
  .triage{padding:20px 14px 18px}
  .triage-results{grid-template-columns:1fr 1fr;gap:10px}
  .tr-cell{padding:13px 13px}
  .tr-cell b{font-size:26px}
  .triage-item{flex-wrap:wrap;gap:6px}
  .ti-meta{margin-top:0}
  /* threshold control: label on its own line, slider + value share the next row,
     so the slider can shrink and nothing pushes past a 375px viewport. */
  .triage-thresh{flex:1 1 100%;flex-wrap:wrap;gap:6px 10px}
  .triage-thresh label{flex:1 1 100%}
  .triage-thresh input[type=range]{flex:1 1 auto;min-width:0}
}

/* reduced motion: drop the opacity transitions; both panes simply shown. */
@media (prefers-reduced-motion: reduce){
  .triage-stage .pane-triaged,.triage-stage.is-triaged .pane-raw{transition:none}
}

/* ============================================================
   Projected-savings calculator (case study only).
   A viewer-driven PROJECTION that sits after the triage demo.
   Reuses panel/card/chip tokens and the tr-cell metric style.
   Every output is computed live in site.js; the page stores no
   result numbers. The cost-per-hour field is a labeled assumption,
   never a price tag, so this carries no store/pricing semantics.
   ============================================================ */
.calc{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:24px 24px 22px}
.calc-cap{color:var(--dim);font-size:12.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;margin:0 0 12px}
.calc-cap .calc-illus{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.5px;
  text-transform:uppercase;color:var(--accent);background:rgba(110,168,254,.1);
  border:1px solid rgba(110,168,254,.25);border-radius:999px;padding:2px 9px;margin-left:8px;vertical-align:middle}
/* the required, prominent projection label: a bordered callout, not fine print */
.calc-projection{color:var(--muted);font-size:13.5px;line-height:1.55;margin:0 0 20px;max-width:700px;
  background:var(--panel2);border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:10px;padding:12px 15px}
.calc-projection b{color:var(--ink);font-weight:700}

/* input grid: 2-up on desktop, single column on phones */
.calc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px;margin:0 0 20px}
.calc-field{display:flex;flex-direction:column;gap:7px;min-width:0}
.calc-field label{color:var(--ink);font-weight:600;font-size:13.5px}
.calc-field input[type=number]{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:10px;
  color:var(--ink);font:inherit;font-size:15px;padding:10px 12px;min-height:44px;
  font-variant-numeric:tabular-nums;-moz-appearance:textfield}
.calc-field input[type=number]:hover{border-color:#37405a}
.calc-field input[type=number]:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-color:var(--accent)}
.calc-hint{color:var(--dim);font-size:12px;line-height:1.5}
/* lift slider sits inline with its live value readout */
.calc-slider-row{display:flex;align-items:center;gap:12px}
.calc-slider-row input[type=range]{flex:1;min-width:0;accent-color:var(--accent);height:24px;cursor:pointer}
.calc-slider-row input[type=range]:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:6px}
.calc-lift-val{color:var(--ink);font-weight:600;font-size:14px;font-variant-numeric:tabular-nums;
  min-width:46px;text-align:right}

/* results: four live-computed cells, the money cell emphasized */
.calc-results{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:0 0 16px}
.calc-cell{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:15px 16px}
.calc-cell b{display:block;font-size:28px;line-height:1.05;font-variant-numeric:tabular-nums;
  background:linear-gradient(90deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
.calc-cell span{display:block;color:var(--muted);font-size:13px;line-height:1.4;margin-top:8px}
.calc-cell .calc-sub{display:block;color:var(--dim);font-size:11.5px;margin-top:3px}
.calc-cell-money{border-color:rgba(110,168,254,.4);background:rgba(110,168,254,.06)}

/* formula disclosure reuses the teardown details pattern */
.calc-formula{background:var(--panel2);border:1px solid var(--line);border-radius:12px;overflow:hidden;margin-top:4px}
.calc-formula summary{cursor:pointer;list-style:none;padding:13px 16px;display:flex;align-items:center;gap:10px;
  font-weight:600;font-size:13.5px;color:var(--ink);min-height:44px}
.calc-formula summary::-webkit-details-marker{display:none}
.calc-formula summary .chev{color:var(--accent);font-size:14px;transition:transform .25s ease;flex:0 0 auto}
.calc-formula[open] summary .chev{transform:rotate(90deg)}
.calc-formula-body{padding:0 16px 16px;color:var(--muted);font-size:13.5px}
.calc-formula-body p{margin:0 0 12px;max-width:720px;line-height:1.6}
.calc-formula-body ol{margin:0 0 12px;padding-left:20px;max-width:720px}
.calc-formula-body li{margin:0 0 8px;line-height:1.55}
.calc-formula-body li b{color:var(--ink);font-weight:600}
.calc-formula-body .calc-formula-note{color:var(--dim);font-size:12.5px;margin:0;line-height:1.55}

@media (max-width:480px){
  .calc{padding:20px 14px 18px}
  .calc-grid{grid-template-columns:1fr;gap:14px}
  .calc-results{grid-template-columns:1fr 1fr;gap:10px}
  .calc-cell{padding:13px 13px}
  .calc-cell b{font-size:24px}
  .calc-formula-body{padding:0 14px 16px}
}

/* reduced motion: drop the chevron rotation transition */
@media (prefers-reduced-motion: reduce){
  .calc-formula summary .chev{transition:none}
}

/* mobile: phones <= 480px. Desktop-first base, tightened for narrow screens. */
@media (max-width:480px){
  .wrap{padding:0 16px}
  /* Nav: let the brand and links share rows without overflow; keep links tappable. */
  nav .wrap{height:auto;min-height:60px;flex-wrap:wrap;gap:6px 0;padding-top:10px;padding-bottom:10px}
  .navlinks{display:flex;flex-wrap:wrap;justify-content:flex-start;gap:4px 14px}
  .navlinks a{margin-left:0;font-size:13px;padding:8px 4px;line-height:1;min-height:44px;display:inline-flex;align-items:center}
  .navlinks a[aria-current="page"]{padding-bottom:6px}
  /* Stats: 2x2 grid instead of a tall single column. */
  #stats .hl{grid-template-columns:1fr 1fr;gap:12px}
  #stats .hl div{padding:16px}
  #stats .hl b{font-size:24px}
  /* Data bars: shrink the fixed label column so the track stays readable. */
  .bar-row{gap:8px;font-size:12px}
  .bar-row .bar-label{flex:0 0 76px;font-size:12px}
  .bar-row .bar-val{flex:0 0 30px}
  /* Hero CTA buttons wrap comfortably and stay full-tap. */
  .cta .btn{padding:11px 16px}
}

/* reduced motion: cut animation, show everything, kill heavy backdrop */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  .reveal{opacity:1;transform:none;transition:none}
  .bar-fill{transition:none}
  .btn:hover, .card:hover{transform:none}
  /* All animated canvases stay hidden under reduced-motion. site.js also never
     starts the ambient field here, so no motion appears anywhere. */
  #hero-canvas, #data-echo, #ambient-bg{display:none}
  /* In place of the animated sky, render a STATIC starfield in pure CSS so the
     night-sky look is still present but completely still (no drift, no twinkle,
     no links that move). It is a fixed, full-viewport layer behind all content
     (z-index:-1, pointer-events:none) built from layered radial-gradient points
     of varied size and brightness, tinted toward the brand accents over the dark
     background. Fixed + inert means it cannot shift layout, add scroll height,
     cause horizontal overflow, or touch text legibility. The constellation links
     are intentionally omitted in the static fallback to keep it calm and clean. */
  body::before{
    content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
    background-repeat:no-repeat;
    background-image:
      radial-gradient(1.6px 1.6px at 12% 18%, rgba(231,233,238,.85), transparent 60%),
      radial-gradient(1.4px 1.4px at 78% 12%, rgba(110,168,254,.80), transparent 60%),
      radial-gradient(2px 2px at 42% 30%, rgba(255,255,255,.70), transparent 60%),
      radial-gradient(1.2px 1.2px at 64% 44%, rgba(157,123,255,.75), transparent 60%),
      radial-gradient(1.5px 1.5px at 88% 62%, rgba(231,233,238,.65), transparent 60%),
      radial-gradient(1.2px 1.2px at 22% 56%, rgba(110,168,254,.60), transparent 60%),
      radial-gradient(1.8px 1.8px at 33% 78%, rgba(255,255,255,.62), transparent 60%),
      radial-gradient(1.2px 1.2px at 56% 70%, rgba(157,123,255,.55), transparent 60%),
      radial-gradient(1.3px 1.3px at 72% 84%, rgba(231,233,238,.55), transparent 60%),
      radial-gradient(1.1px 1.1px at 9% 88%, rgba(110,168,254,.50), transparent 60%),
      radial-gradient(1.6px 1.6px at 92% 34%, rgba(255,255,255,.55), transparent 60%),
      radial-gradient(1.1px 1.1px at 50% 14%, rgba(157,123,255,.50), transparent 60%);
    opacity:.6}
  /* The animated hero is hidden; the static labeled orchestration diagram appears. */
  #hero-static{display:block}
  /* Process diagram: show the full diagram immediately, fully lit, no draw/transition. */
  .flow .flow-link, .flow .flow-loop{transition:none}
  .flow .flow-link.draw{stroke:url(#flowGrad);stroke-dashoffset:0}
  .flow .flow-loop.draw{stroke-dashoffset:0}
  .flow .stage rect{fill:rgba(110,168,254,.12);stroke:var(--accent);transition:none}
  .flow .stage text{fill:var(--ink);transition:none}
  .flow .stage circle{fill:var(--accent);transition:none}
  /* Guardrail panel: every verdict shown statically, no stamp-in motion. */
  .guard-verdict{opacity:1;transform:none;transition:none}
  .guard-run:hover, .guard-reset:hover{transform:none}
  .teardown summary .chev{transition:none}
  *{animation:none !important}
}

/* ============================================================
   Layout balance: count-aware, section-scoped grid columns.
   The shared base grids use repeat(auto-fit,minmax(...)), which
   orphans the last card whenever the item count does not divide
   evenly into the columns that fit at a given width (e.g. 4 cards
   -> 3+1, or 3 cards -> 2+1 at tablet). These rules pin explicit
   column counts per section at clean breakpoints so no grid ever
   leaves a lone card stranded beside dead space, and sparse blocks
   read as intentional. Single column below 640px everywhere, so an
   orphan is impossible on phones. Cards keep equal heights because
   grid items stretch by default and .card is a flex column.
   Breakpoints: 640px = two-up tier, 900px = three-up tier.
   ============================================================ */

/* (1) About / How I build: #approach .grid has 4 method cards.
   Balanced 2x2 from 640px up; auto-fit never gets to orphan 3+1. */
@media (min-width:640px){
  #approach .grid{grid-template-columns:repeat(2,1fr)}
}

/* (1b) adel-points supporting lists (home delivery + about): 4 items.
   Pin to a 2x2 so the fourth item never sits alone in a 3-up row. */
@media (min-width:640px){
  .adel-points{grid-template-columns:repeat(2,1fr)}
}

/* (2) Work index groups (/work): each .work-group .grid holds a
   different count (2, 3, 1). Pin columns to the group size at each
   tier so none orphan, and constrain a lone card so it sits at a
   natural card width instead of stretching full-bleed with 50%+
   empty beside it. Groups are tagged in source by their card count
   via :has(); a no-:has() fallback covers older engines below. */
@supports selector(:has(*)){
  /* two-card group: one column on phones so the headline production
     cards get full width, side by side from 640px, never a 1+1 orphan row */
  .work-group .grid:has(> .card:nth-child(2):last-child){
    grid-template-columns:1fr}
  @media (min-width:640px){
    .work-group .grid:has(> .card:nth-child(2):last-child){
      grid-template-columns:repeat(2,minmax(0,1fr))}
  }
  /* three-card group: one column to 900px, then 3-across (skips the
     2-column tablet state that would strand the third card) */
  .work-group .grid:has(> .card:nth-child(3):last-child){
    grid-template-columns:1fr}
  @media (min-width:900px){
    .work-group .grid:has(> .card:nth-child(3):last-child){
      grid-template-columns:repeat(3,minmax(0,1fr))}
  }
  /* lone-card group (e.g. Operations): hold the single card to a
     natural ~half-to-third width and left-align it, so it reads as a
     deliberate single item, not a full-width banner with a dead zone */
  .work-group:not(.work-group--feature) .grid:has(> .card:only-child){
    grid-template-columns:minmax(0,420px);justify-content:start}
}
/* Fallback for engines without :has(): keep the work-group grids on a
   sane card-width track so the lone card cannot bleed full width and
   the multi-card groups wrap without a stranded trailing card. */
@supports not selector(:has(*)){
  .work-group:not(.work-group--feature) .grid{
    grid-template-columns:repeat(auto-fit,minmax(300px,360px));
    justify-content:start}
  @media (max-width:639px){
    .work-group:not(.work-group--feature) .grid{grid-template-columns:1fr}
  }
}

/* (2b) Operations feature group: a single case study rendered as a full-width
   card so it fills the row with no dead space. The grid is one full-bleed
   column; the card itself uses a horizontal split (copy on the left, the
   outcome + chips + read-link on the right) that collapses to a single
   stacked column on phones. Scoped to .work-group--feature so the Production
   (2-up) and Open-source (3-up) grids are untouched. */
.work-group--feature .grid{grid-template-columns:1fr;justify-content:stretch}
.feature-card{display:grid;grid-template-columns:1fr;gap:18px}
@media (min-width:760px){
  .feature-card{grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);
    gap:32px;align-items:center}
}
.feature-card-main{display:flex;flex-direction:column;min-width:0}
.feature-card-main p{margin-bottom:0}
.feature-card-aside{display:flex;flex-direction:column;align-items:flex-start;min-width:0}
@media (min-width:760px){
  /* right column reads as a tidy block, aligned to the divider edge */
  .feature-card-aside{border-left:1px solid var(--line);padding-left:32px;align-self:stretch;justify-content:center}
}
/* the outcome chip already has margin-bottom:14px; keep the stack/link rhythm */
.feature-card-aside .stack{margin-bottom:14px}

/* (3) Contact page: two contact cards. Cap to two columns and cap the
   container width so the pair feels like an intentional, centered block
   rather than two small cards floating in a wide empty page. */
.about .grid{max-width:760px;grid-template-columns:1fr}
@media (min-width:640px){
  .about .grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* (4) Home "Selected work": #work .grid has 3 cards. One column below
   900px, three across at and above it. This deliberately skips any
   2-column width, which at 768 to 900 would orphan the third card. */
#work .grid{grid-template-columns:1fr}
@media (min-width:900px){
  #work .grid{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* (5) Home stats: #stats .hl has 2 tiles. Pin to two-up from 640px so
   they balance side by side instead of spreading across auto-fit
   columns. (The <=480px rule below already gives a tidy 2-up phone
   layout; between 481 and 639 they stack, which never orphans.) */
@media (min-width:640px){
  #stats .hl{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* (6) Home "Agent-driven delivery": the .adel panel already fills the
   .wrap, but its lede and estimate copy use max-width:720 and would
   read as half-empty in the wide panel. Widen those measures so the
   text fills the panel as one balanced block (no content change). */
#delivery .adel-lede,
#delivery .adel-est p{max-width:none}

/* (7) About "Data craft": .data-cols has 3 cards. Same treatment as
   home Selected work: one column to 900px, three across above it, so
   the tablet 2-column state cannot strand the third card. */
.data-cols{grid-template-columns:1fr}
@media (min-width:900px){
  .data-cols{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* (8) Ambient backdrop consistency: the starfield canvas is fixed to the
   viewport and drawn with one flat, even opacity (set on #ambient-bg above)
   and no directional mask, so the sky reads the same top-to-bottom and on
   every page regardless of page height. A previous radial mask anchored at
   80% 0% lived here and made the field uneven on tall content pages; it is
   intentionally removed so there is a single, consistent ambient sky. The
   home hero keeps only its short top-band ease via body.has-hero (declared
   earlier). Nothing further to override here. */

/* Safety: never let these pinned multi-column grids force horizontal
   overflow on very narrow phones. Below 480px everything is one column.
   (#stats .hl is intentionally excluded: the existing <=480px rule above
   gives it a deliberate, non-orphaning 2x2 phone layout that stands.) */
@media (max-width:480px){
  #approach .grid,
  .adel-points,
  .work-group .grid,
  .about .grid,
  #work .grid,
  .data-cols{grid-template-columns:1fr}
  .work-group .grid{justify-content:stretch}
}
