/* ===========================================================
   KILN — shared design system (sub-pages)
   The homepage keeps its own inline styles + WebGL hero.
   Tokens here mirror the homepage exactly. See DESIGN.md.
   =========================================================== */

/* Channel tokens (--*-rgb) exist so every translucent colour below follows the
   page theme. Never hardcode an rgba() literal — see the project themes at the
   foot of this file. */
:root{
  --char:#141009; --char-2:#1C160E; --char-3:#0E0B06;
  --ash:#EADFCE; --ash-dim:#B7AC96; --ash-mute:#8A7C63;
  --ember:#E2632A; --ember-hi:#F08A3C; --ember-deep:#7A3417;
  --char-rgb:20,16,9; --char3-rgb:14,11,6; --ash-rgb:234,223,206;
  --ember-rgb:226,99,42; --ember-hi-rgb:240,138,60;
  --line:rgba(var(--ash-rgb),.12); --line-2:rgba(var(--ash-rgb),.06);
  --disp:"Libre Caslon Display",Georgia,serif;
  --sans:"Hanken Grotesk",system-ui,-apple-system,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,Consolas,monospace;
  --ease:cubic-bezier(.22,.8,.28,1);
  --wrap:1180px;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{background:var(--char);color:var(--ash);font-family:var(--sans);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overflow-x:hidden}
a{color:inherit;text-decoration:none}
::selection{background:var(--ember);color:var(--char)}
:focus-visible{outline:2px solid var(--ember);outline-offset:3px}
img{max-width:100%;display:block}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 40px}
@media(max-width:640px){.wrap{padding:0 20px}}

.mono{font-family:var(--mono)}
.lbl{font-family:var(--mono);font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--ash-mute)}
.disp{font-family:var(--disp);font-weight:400;line-height:1.02;letter-spacing:-.01em}
.em{color:var(--ember)}

/* ---------- reveal on scroll ---------- */
.reveal{transition:opacity 1s var(--ease),transform 1.05s var(--ease);transition-delay:var(--d,0s)}
.js .reveal{opacity:0;transform:translateY(32px)}
.js .reveal[data-rv="left"]{transform:translateX(-46px)}
.js .reveal[data-rv="right"]{transform:translateX(46px)}
.js .reveal[data-rv="scale"]{transform:scale(.93)}
.js .reveal.in{opacity:1;transform:none}

/* ---------- atmosphere ---------- */
.ambient{position:fixed;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(58% 42% at 50% var(--ay,55%),rgba(var(--ember-rgb),.16),rgba(var(--ember-hi-rgb),.05) 45%,rgba(var(--char-rgb),0) 72%)}
.grain{position:fixed;inset:0;z-index:85;pointer-events:none;opacity:.045;mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:140px 140px}
/* ---------- firing gauge (thermometer) ----------
   An instrument, not a progress bar: the mercury tracks TEMPERATURE, climbing
   to this page's own firing peak. Matches index.html's copy. */
#therm{position:fixed;right:34px;top:50%;transform:translateY(-50%);z-index:92;pointer-events:none;
  height:min(46vh,380px);display:flex;flex-direction:column;align-items:center;gap:14px}
/* the cap NAMES the instrument. Without it the climbing number is a puzzle a
   first-time visitor spends attention on; with it, it reads at a glance. */
#therm .t-cap{font-family:var(--disp);font-size:10.5px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--ash-mute);writing-mode:vertical-rl;opacity:.75;white-space:nowrap}
#therm .t-rail{position:relative;flex:1;width:1px;background:rgba(var(--ash-rgb),.16)}
#therm .t-fill{position:absolute;left:0;bottom:0;width:1px;height:100%;transform-origin:50% 100%;
  transform:scaleY(0);
  background:linear-gradient(0deg,var(--ember-deep),var(--ember) 55%,var(--ember-hi))}
#therm .t-tick{position:absolute;left:-5px;bottom:var(--y);width:11px;height:1px;
  background:rgba(var(--ash-rgb),.22)}
#therm .t-tick::after{content:attr(data-l);position:absolute;right:16px;top:-7px;
  font-family:var(--disp);font-size:11px;color:var(--ash-mute);opacity:.6;letter-spacing:.04em}
#therm .t-bulb{position:absolute;left:50%;bottom:-11px;width:11px;height:11px;margin-left:-5.5px;
  border-radius:50%;border:1px solid var(--ember-deep);background:var(--char-3)}
#therm .t-head{position:absolute;left:50%;bottom:0;transform:translate3d(-50%,0,0);
  display:flex;align-items:baseline;white-space:nowrap}
#therm .t-head::before{content:"";position:absolute;left:50%;top:-1px;width:9px;height:3px;
  margin-left:-4.5px;background:var(--ember-hi)}
#therm .t-head .t-val{font-family:var(--disp);font-style:normal;font-size:23px;line-height:1;
  color:var(--ash);position:absolute;right:24px;top:-11px}
#therm .t-head .deg{font-family:var(--disp);font-style:normal;font-size:12px;color:var(--ash-mute);
  position:absolute;right:6px;top:-12px}
@media(max-width:1360px){
  #therm{right:20px}
  #therm .t-tick::after{display:none}
  /* the unit has to fit without pushing the readout back over the 1180px
     content column — measured at 1280px, where the margin is tightest */
  #therm .t-head .t-val{font-size:16px;right:13px;top:-8px}
  #therm .t-head .deg{font-size:8px;right:4px;top:-9px}
  #therm .t-cap{font-size:9px;letter-spacing:.22em}
}
@media(max-width:1100px){#therm{display:none}}

/* ---------- custom cursor ---------- */
#cur,#curDot{position:fixed;left:0;top:0;z-index:200;pointer-events:none;opacity:0;
  transform:translate(-50%,-50%);will-change:left,top,transform}
#cur{width:34px;height:34px;border:1px solid var(--ember);border-radius:50%;
  transition:transform .3s var(--ease),background .3s var(--ease),border-color .3s var(--ease),opacity .3s}
#curDot{width:6px;height:6px;border-radius:50%;background:var(--ember-hi)}
#cur.hot{transform:translate(-50%,-50%) scale(1.65);background:rgba(var(--ember-rgb),.12);border-color:var(--ember-hi)}
#cur.press{transform:translate(-50%,-50%) scale(.76)}
@media (hover:hover) and (pointer:fine){
  html.cur-on,html.cur-on *{cursor:none !important}
  html.cur-on #cur,html.cur-on #curDot{opacity:1}
}

/* ---------- nav ---------- */
.bar{position:fixed;inset:0 0 auto 0;z-index:90;display:flex;align-items:center;justify-content:space-between;
  padding:20px 40px;transition:background .4s var(--ease),border-color .4s var(--ease);border-bottom:1px solid transparent}
.bar.stuck{background:rgba(var(--char-rgb),.82);backdrop-filter:blur(14px);border-bottom-color:var(--line)}
.mark{font-weight:700;letter-spacing:.4em;font-size:15px;padding-left:.4em}
.mark .dot{color:var(--ember)}
.bar nav{display:flex;gap:30px;align-items:center}
.bar nav a{font-size:13px;color:var(--ash-dim);transition:color .25s}
.bar nav a:hover{color:var(--ash)}
.bar nav a.cta{color:var(--char);background:var(--ember);padding:9px 16px;border-radius:2px;font-weight:600;letter-spacing:.02em}
.bar nav a.cta:hover{background:var(--ember-hi);color:var(--char)}
@media(max-width:760px){.bar,.bar.stuck{padding:16px 22px}.bar nav a:not(.cta){display:none}}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;gap:10px;font-family:var(--sans);font-weight:600;font-size:14px;letter-spacing:.01em;
  padding:14px 24px;border-radius:2px;transition:.25s var(--ease);cursor:pointer;border:1px solid transparent}
.btn.solid{background:var(--ember);color:var(--char)}
.btn.solid:hover{background:var(--ember-hi)}
.btn.ghost{border-color:rgba(var(--ash-rgb),.26);color:var(--ash)}
.btn.ghost:hover{border-color:var(--ash-mute);background:rgba(var(--ash-rgb),.04)}
.btn .arw{color:inherit;transition:transform .25s var(--ease)}
.btn:hover .arw{transform:translateX(5px)}

/* ---------- section shell ---------- */
section.blk{position:relative;z-index:1;padding:120px 0}
section.blk::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background:linear-gradient(90deg,transparent,rgba(var(--ember-rgb),.4) 20%,rgba(var(--ember-hi-rgb),.75) 50%,rgba(var(--ember-rgb),.4) 80%,transparent);
  transform:scaleX(0);transform-origin:center;transition:transform 1.15s var(--ease)}
section.blk.lit::before{transform:scaleX(1)}
html:not(.js) section.blk::before{transform:scaleX(1)}
.sec-head{display:flex;align-items:baseline;gap:20px;margin-bottom:26px;position:relative}
.sec-head .big{font-family:var(--disp);font-size:clamp(46px,7vw,92px);line-height:.78;color:transparent;
  -webkit-text-stroke:1px rgba(var(--ash-rgb),.17);letter-spacing:-.02em}
.sec-head .ttl{font-family:var(--mono);font-size:12px;letter-spacing:.22em;text-transform:uppercase;color:var(--ash-mute);padding-bottom:6px}

/* ---------- prose ---------- */
.prose{max-width:64ch}
.prose p{font-size:clamp(15px,1.6vw,18px);line-height:1.72;color:var(--ash-dim);margin-bottom:1.3em}
.prose p:last-child{margin-bottom:0}
.prose strong{color:var(--ash);font-weight:600}
.lead{font-family:var(--disp)!important;font-size:clamp(22px,2.8vw,32px)!important;line-height:1.4!important;color:var(--ash)!important}

/* ---------- footer ---------- */
footer{position:relative;z-index:1;background:var(--char-3);border-top:1px solid var(--line);padding:60px 0 40px}
footer .row{display:flex;justify-content:space-between;align-items:flex-start;gap:30px;flex-wrap:wrap}
footer .mark{font-size:22px}
footer .fnav{display:flex;gap:40px;flex-wrap:wrap}
footer .fcol .h{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--ash-mute);margin-bottom:14px}
footer .fcol a{display:block;font-size:14px;color:var(--ash-dim);margin-bottom:9px;transition:color .2s}
footer .fcol a:hover{color:var(--ember)}
footer .base{margin-top:48px;padding-top:22px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;font-family:var(--mono);font-size:11px;color:var(--ash-mute);letter-spacing:.05em}
.placeholder-note{margin-top:14px;font-family:var(--mono);font-size:10.5px;color:var(--ember-deep);letter-spacing:.04em}

/* ---------- unfired copy ----------
   Body text I could not write for the studio owner: it is visibly marked so it
   can never be mistaken for finished copy, and so it is trivial to find. */
.unfired{position:relative;padding:16px 18px 16px 20px;margin:18px 0;
  border-left:2px solid var(--ember-deep);background:rgba(var(--ember-rgb),.05);
  color:var(--ash-mute);font-size:14.5px;line-height:1.62}
.unfired b{display:block;margin-bottom:7px;font-family:var(--mono);font-size:10px;font-weight:500;
  letter-spacing:.18em;text-transform:uppercase;color:var(--ember)}

/* ---------- the stack ----------
   "Design + build" is a claim until it is itemised. Grouped so a technical
   reader can scan for what they need and a non-technical one still sees range. */
.stack{display:grid;grid-template-columns:repeat(3,1fr);gap:38px 34px;margin-top:26px}
.stack .sgrp{padding-top:20px;border-top:1px solid var(--line)}
.stack .sgrp .k{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--ember)}
.stack .sgrp ul{list-style:none;margin-top:13px}
.stack .sgrp li{font-size:14.5px;line-height:1.55;color:var(--ash-dim);padding:5px 0 5px 15px;position:relative}
.stack .sgrp li::before{content:"";position:absolute;left:0;top:13px;width:5px;height:1px;background:var(--ember-deep)}
.stack .sgrp li i{font-style:normal;color:var(--ash-mute)}
.stack .sgrp li code{font-family:var(--mono);font-size:12.5px;color:var(--ash)}
@media(max-width:900px){.stack{grid-template-columns:repeat(2,1fr);gap:30px 26px}}
@media(max-width:560px){.stack{grid-template-columns:1fr;gap:0}.stack .sgrp{margin-top:26px}}

/* ===========================================================
   SUB-PAGE COMPONENTS
   =========================================================== */

/* ---------- smooth scroll ----------
   Only active when html.smooth is set (desktop + fine pointer + motion allowed).
   Off, these two wrappers are inert and the page scrolls natively. */
html.smooth{scroll-behavior:auto}
html.smooth #smooth-wrap{position:fixed;inset:0;overflow:hidden;z-index:1}
html.smooth #smooth-content{will-change:transform}

/* ---------- page transition (kiln wipe) ---------- */
#wipe{position:fixed;inset:0;z-index:250;pointer-events:none;background:var(--char-3);transform:translateY(-100%)}
#wipe::before,#wipe::after{content:"";position:absolute;left:0;right:0;height:2px;
  background:linear-gradient(90deg,transparent,var(--ember-hi),transparent)}
#wipe::before{top:0}#wipe::after{bottom:0}
html.js #wipe{transform:translateY(0);animation:wipeOut .7s var(--ease) .05s forwards}
#wipe.cover{animation:wipeIn .5s var(--ease) forwards}
@keyframes wipeOut{from{transform:translateY(0)}to{transform:translateY(-100%)}}
@keyframes wipeIn{from{transform:translateY(100%)}to{transform:translateY(0)}}

/* ---------- masked type reveal ---------- */
/* mask, not clip-path: clip-path zeroes the element's intersection rect,
   so the observer that reveals it would never fire */
.js .mrv{-webkit-mask-image:linear-gradient(180deg,transparent 50%,#000 50%);mask-image:linear-gradient(180deg,transparent 50%,#000 50%);
  -webkit-mask-size:100% 200%;mask-size:100% 200%;-webkit-mask-position:0 0;mask-position:0 0;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;transform:translateY(16px);
  transition:-webkit-mask-position 1.1s var(--ease) var(--d,0s),mask-position 1.1s var(--ease) var(--d,0s),transform 1.1s var(--ease) var(--d,0s)}
.js .mrv.in{-webkit-mask-position:0 100%;mask-position:0 100%;transform:none}

/* ---------- page hero (case study + about) ---------- */
.phero{position:relative;z-index:1;padding:180px 0 70px;overflow:hidden}
.phero .pshader{position:absolute;inset:0;width:100%;height:100%;display:block;opacity:.6}
.phero .pveil{position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,rgba(var(--char-rgb),.92),rgba(var(--char-rgb),.62) 42%,rgba(var(--char-rgb),.3) 100%),
             linear-gradient(180deg,rgba(var(--char-rgb),.8),rgba(var(--char-rgb),0) 34%,rgba(var(--char-rgb),.55) 78%,var(--char) 100%)}
.phero > .wrap{position:relative;z-index:2}
.phero .kick{display:flex;align-items:center;gap:12px;margin-bottom:22px;flex-wrap:wrap;
  font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--ash-mute)}
.phero .kick .heat{color:var(--ember)}
.phero .back{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ash-mute);margin-bottom:30px;transition:color .25s}
.phero .back:hover{color:var(--ember)}
.phero h1{font-family:var(--disp);font-weight:400;font-size:clamp(44px,8vw,104px);line-height:.98;letter-spacing:-.02em;max-width:14ch;text-wrap:balance}
.phero h1 i{font-style:italic;color:var(--ember-hi)}
.phero .sub{margin-top:26px;max-width:56ch;font-size:clamp(15px,1.6vw,19px);line-height:1.6;color:var(--ash-dim)}
.phero .ctas{margin-top:36px;display:flex;gap:14px;flex-wrap:wrap}
@media(max-width:640px){.phero{padding:132px 0 50px}}

/* ---------- fact strip ---------- */
.facts{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:6px;overflow:hidden;margin-top:56px}
.facts .f{background:var(--char);padding:22px 24px}
.facts .f .k{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ash-mute)}
.facts .f .v{margin-top:8px;font-family:var(--disp);font-size:19px;color:var(--ash);line-height:1.2}
@media(max-width:820px){.facts{grid-template-columns:1fr 1fr}}
@media(max-width:460px){.facts{grid-template-columns:1fr}}

/* ---------- live embed ---------- */
.embed{position:relative;display:block;aspect-ratio:16/10;border-radius:8px;overflow:hidden;border:1px solid var(--line);
  background:var(--pvbg,#1c160e);transition:border-color .5s var(--ease)}
.embed:hover{border-color:var(--ember)}
.embed .pvf{position:absolute;top:0;left:0;border:0;transform-origin:top left;pointer-events:none;background:var(--pvbg,#1c160e);
  opacity:0;transition:opacity .8s var(--ease)}
.embed.loaded .pvf{opacity:1}
.embed .pv-face{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;align-items:center;
  gap:14px;padding:22px;text-align:center;color:var(--pvfg,#eadfce);transition:opacity .8s var(--ease)}
.embed.loaded .pv-face{opacity:0}
.embed .pv-face .fn{font-family:var(--disp);font-size:clamp(28px,4vw,48px);line-height:1.02}
.embed .pv-face .ld{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;opacity:.7}
.embed .cap{position:absolute;left:0;right:0;bottom:0;z-index:2;display:flex;justify-content:space-between;align-items:center;
  gap:16px;padding:16px 20px;font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--ash);
  text-shadow:0 1px 8px rgba(var(--char3-rgb),.85);background:linear-gradient(0deg,rgba(var(--char3-rgb),.72),rgba(var(--char3-rgb),0))}
/* the way out of the preview was a caption-sized link in the corner and read as
   a label, not a control. It is the only route to the real demo on a phone, so
   it is now a pill you can actually see and hit. */
.embed .cap .open{flex:none;display:inline-flex;align-items:center;gap:8px;color:var(--ember-hi);
  padding:9px 15px;border:1px solid rgba(var(--ember-rgb),.55);border-radius:100px;
  background:rgba(var(--char3-rgb),.62);text-shadow:none;transition:background .35s var(--ease),border-color .35s var(--ease),color .35s var(--ease)}
.embed:hover .cap .open{background:var(--ember);border-color:var(--ember);color:var(--char-3)}

/* ---- preview mode: is this face a placeholder, or the thing itself? ----
   On a phone the live preview never loads (these demos are laid out for 1440px
   and would scale to an illegible ~26%), so the face must say so plainly rather
   than promise a preview that is not coming. */
.embed .ld-touch,.embed .pv-go{display:none}
.embed .pv-go{font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  padding:12px 20px;border-radius:100px;border:1px solid rgba(var(--ember-rgb),.6);
  background:rgba(var(--ember-rgb),.12);color:var(--ember-hi);margin-top:4px}
@media (pointer:coarse),(max-width:759px),(prefers-reduced-motion:reduce){
  .embed .ld-desk{display:none}
  .embed .ld-touch{display:block}
  .embed .pv-go{display:inline-block}
  .embed .cap .open{display:none}      /* the face carries the action instead */
}
html:not(.js) .embed .ld-desk{display:none}
html:not(.js) .embed .ld-touch{display:block}
html:not(.js) .embed .pv-go{display:inline-block}

/* ---------- content block two-col ---------- */
.split{display:grid;grid-template-columns:0.9fr 1.1fr;gap:60px;align-items:start}
.split .side .k{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--ember)}
.split .side h2{font-family:var(--disp);font-weight:400;font-size:clamp(26px,3.4vw,40px);line-height:1.08;margin-top:12px;letter-spacing:-.01em;text-wrap:balance}
/* The artefact makes the left column far taller than the prose, so top-aligning
   leaves a hole under the text. Only where an artefact is present — about.html's
   splits have no artefact and should still hang from the top. */
.split.split-art{align-items:center}
@media(max-width:820px){.split{grid-template-columns:1fr;gap:24px}
  .split.split-art{align-items:start}}

/* ---------- SIGNATURE ARTEFACT ----------
   Each case study shows the actual technique it is about, running live in the
   dead space beside "The idea" — the page argues the point instead of claiming it.
   Object floats over a display disc; everything is theme-token driven so it
   picks up that project's palette. */
.arti{margin:44px 0 0;max-width:440px}
.arti-stage{position:relative;aspect-ratio:1/1;width:100%}
.arti-gl,.arti-2d{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:2}
/* the disc: a lit ellipse the object stands on, plus its contact shadow */
.arti-disc{position:absolute;left:50%;bottom:11%;z-index:1;transform:translateX(-50%);
  width:62%;aspect-ratio:6/1;border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(var(--ember-rgb),.34),rgba(var(--ember-rgb),.07) 62%,rgba(var(--ash-rgb),0) 100%)}
.arti-disc::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:104%;height:1px;background:linear-gradient(90deg,rgba(var(--ash-rgb),0),rgba(var(--ash-rgb),.28),rgba(var(--ash-rgb),0))}
.arti-shadow{position:absolute;left:50%;bottom:9.4%;z-index:0;transform:translateX(-50%);
  width:40%;aspect-ratio:7/1;border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(var(--char3-rgb),.85),rgba(var(--char3-rgb),0) 100%)}
.arti-cap{margin-top:16px;display:flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--ash-mute)}
.arti-cap i{width:5px;height:5px;border-radius:50%;background:var(--ember);flex:none;
  animation:artiPulse 2.6s ease-in-out infinite}
@keyframes artiPulse{0%,100%{opacity:.35}50%{opacity:1}}
/* readout for artefacts that have a live value to show (the clock, the hour) */
.arti-read{position:absolute;left:0;top:0;z-index:3;pointer-events:none;
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;color:var(--ash-dim)}
.arti-read b{color:var(--ember);font-weight:500}
@media(max-width:820px){.arti{max-width:340px;margin-top:32px}}
@media(prefers-reduced-motion:reduce){.arti-cap i{animation:none}}

/* ---------- feature list ---------- */
.feats{display:grid;grid-template-columns:1fr 1fr;gap:26px;margin-top:56px}
.feats .ft{padding-top:22px;border-top:1px solid var(--line)}
.feats .ft .n{font-family:var(--mono);font-size:11px;color:var(--ember);letter-spacing:.12em}
.feats .ft h3{font-family:var(--disp);font-size:22px;font-weight:400;margin:12px 0 9px}
.feats .ft p{font-size:14.5px;line-height:1.62;color:var(--ash-dim)}
@media(max-width:700px){.feats{grid-template-columns:1fr;gap:0}.feats .ft{margin-top:24px}}

/* ---------- next-project pager ---------- */
.pager{position:relative;z-index:1;border-top:1px solid var(--line);padding:64px 0}
.pager a{display:flex;justify-content:space-between;align-items:center;gap:24px;flex-wrap:wrap}
.pager .lb{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--ash-mute)}
.pager .nm{font-family:var(--disp);font-size:clamp(30px,5vw,58px);line-height:1;color:var(--ash);transition:color .3s}
.pager a:hover .nm{color:var(--ember)}
.pager .arw{font-family:var(--disp);font-size:clamp(30px,5vw,54px);color:var(--ember)}

/* ---------- big CTA ---------- */
.cta-blk{position:relative;z-index:1;text-align:center;padding:140px 0}
.cta-blk h2{font-family:var(--disp);font-weight:400;font-size:clamp(38px,6vw,74px);line-height:1;letter-spacing:-.02em;text-wrap:balance}
.cta-blk h2 i{font-style:italic;color:var(--ember)}
.cta-blk p{margin:24px auto 38px;max-width:44ch;color:var(--ash-dim);font-size:16px;line-height:1.6}
/* ---- what happens after you send it ----
   A bare mailto asks the visitor to compose the first move with no idea what to
   say or when they will hear back. These three lines remove both unknowns, and
   the mail link itself arrives pre-filled with the questions worth answering. */
.ctaq{display:grid;grid-template-columns:repeat(3,1fr);gap:0 34px;max-width:820px;margin:52px auto 0;
  text-align:left;list-style:none}
.ctaq li{padding-top:20px;border-top:1px solid var(--line);font-size:14px;line-height:1.6;color:var(--ash-dim)}
.ctaq li span{display:block;margin-bottom:9px;font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ember)}
@media(max-width:820px){.ctaq{grid-template-columns:1fr;gap:0;max-width:32rem;margin-top:40px}
  .ctaq li{margin-top:20px}}
.cta-blk .mail{display:inline-block;font-family:var(--disp);font-size:clamp(22px,3vw,34px);color:var(--ember);
  border-bottom:1px solid var(--ember-deep);padding-bottom:4px;transition:.3s}
.cta-blk .mail:hover{border-color:var(--ember)}

/* ---------- about: value columns ---------- */
.vals{display:grid;grid-template-columns:repeat(3,1fr);gap:34px;margin-top:20px}
.vals .c{padding-top:22px;border-top:1px solid var(--line)}
.vals .c .n{font-family:var(--mono);font-size:11px;color:var(--ember);letter-spacing:.14em}
.vals .c h3{font-family:var(--disp);font-size:23px;margin:14px 0 10px;font-weight:400}
.vals .c p{font-size:14.5px;line-height:1.65;color:var(--ash-dim)}
@media(max-width:820px){.vals{grid-template-columns:1fr;gap:0}.vals .c{margin-top:26px}}

/* ===========================================================
   PROJECT THEMES
   A case study wears its own project's palette for the WHOLE page,
   not just the hero shader — ground, accent, rules and text all shift.
   The studio pages (about, 404, homepage) keep the kiln ember default.
   Every value below is drawn from that demo's real palette.
   =========================================================== */
body[data-theme="slow-glass"]{
  --char:#08080B; --char-2:#111116; --char-3:#050507;
  --ash:#E9E7E2; --ash-dim:#A8A7A3; --ash-mute:#78787A;
  --ember:#9BA0B5; --ember-hi:#D6D9E4; --ember-deep:#454A5C;
  --char-rgb:8,8,11; --char3-rgb:5,5,7; --ash-rgb:233,231,226;
  --ember-rgb:155,160,181; --ember-hi-rgb:214,217,228;
}
body[data-theme="kembang"]{
  --char:#141A12; --char-2:#1C2418; --char-3:#0A0E09;
  --ash:#EDF0E6; --ash-dim:#B2BBA5; --ash-mute:#818B74;
  --ember:#C4CE23; --ember-hi:#DDE64F; --ember-deep:#5C6B1F;
  --char-rgb:20,26,18; --char3-rgb:10,14,9; --ash-rgb:237,240,230;
  --ember-rgb:196,206,35; --ember-hi-rgb:221,230,79;
}
body[data-theme="ember-and-ash"]{
  --char:#171009; --char-2:#211609; --char-3:#0F0A05;
  --ash:#F0E4D2; --ash-dim:#BCAC92; --ash-mute:#8B7C62;
  --ember:#E8A54B; --ember-hi:#F6C177; --ember-deep:#8A4A12;
  --char-rgb:23,16,9; --char3-rgb:15,10,5; --ash-rgb:240,228,210;
  --ember-rgb:232,165,75; --ember-hi-rgb:246,193,119;
}
body[data-theme="keel"]{
  --char:#0B1220; --char-2:#121C2E; --char-3:#070C16;
  --ash:#E4E8EE; --ash-dim:#A5B0BF; --ash-mute:#75808F;
  --ember:#C4573A; --ember-hi:#E0764F; --ember-deep:#6E2C1C;
  --char-rgb:11,18,32; --char3-rgb:7,12,22; --ash-rgb:228,232,238;
  --ember-rgb:196,87,58; --ember-hi-rgb:224,118,79;
}
body[data-theme="quiet-hours"]{
  --char:#0B1A19; --char-2:#112523; --char-3:#071211;
  --ash:#E2ECEA; --ash-dim:#A2B7B3; --ash-mute:#738885;
  --ember:#5FA9A2; --ember-hi:#8CC7BF; --ember-deep:#1D5E5C;
  --char-rgb:11,26,25; --char3-rgb:7,18,17; --ash-rgb:226,236,234;
  --ember-rgb:95,169,162; --ember-hi-rgb:140,199,191;
}

/* ---------- reduced motion ---------- */
@media(prefers-reduced-motion:reduce){
  .reveal,section.blk::before,.js .mrv{transition:none !important}
  .js .reveal{opacity:1 !important;transform:none !important}
  .js .mrv{-webkit-mask-image:none !important;mask-image:none !important;transform:none !important}
  section.blk::before{transform:scaleX(1) !important}
  #wipe,.phero .pshader{display:none !important}
  #cur,#curDot,.grain,#therm{display:none !important}
  html.cur-on,html.cur-on *{cursor:auto !important}
  html{scroll-behavior:auto}
}
