@property --aj-ang{syntax:'<angle>';initial-value:0deg;inherits:false}
:root{
 /* Spacing scale for section rhythm: chapter breaks get the most air, grouped content the least. Each step follows the
    viewport height but is clamped, so tall monitors do not balloon and landscape phones do not collapse. */
 --sp-xs:clamp(12px,2vh,24px);--sp-s:clamp(24px,4.5vh,48px);--sp-m:clamp(48px,8.5vh,96px);--sp-l:clamp(72px,12vh,140px);--sp-xl:clamp(96px,15vh,180px);
 /* Corner radius system: chips, controls and frames, cards, large panels; pills and circles use 999px and 50%. */
 --r-xs:6px;--r-sm:12px;--r-md:18px;--r-lg:24px;
 --bg:#050506;--fg:#f5f2ec;--text:#e9e5de;--mute:#c7c2ba;--soft:#a39e96;--line:#f5f2ec1f;
 --hot:#ff2d75;--orange:#ff7a3d;--gold:#ffc861;--violet:#b48cff;--cyan:#5ee6ff;
 --a:#ff7a3d;--b:#ff2d75;
 --display:'Syne',system-ui,sans-serif;--body:'Geist',system-ui,sans-serif;--mono:'JetBrains Mono',ui-monospace,monospace;
 --ease:cubic-bezier(.2,.8,.2,1);--pad:clamp(20px,4vw,72px);--max:1440px;--hdr:84px
}
*{box-sizing:border-box;margin:0;padding:0}
html{background:var(--bg);scroll-behavior:smooth;overflow-x:clip;scroll-padding-top:var(--hdr)}
/* Motion off scrolls the way reduced motion does: jumps and focus land at once rather than gliding */
html:has(>body.still){scroll-behavior:auto}
body{background:var(--bg);color:var(--text);font-family:var(--body);font-size:17px;line-height:1.55;overflow-x:clip;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
img{display:block;max-width:100%}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
::selection{background:var(--hot);color:#fff}
:focus-visible{outline:2px solid var(--cyan);outline-offset:4px;border-radius:var(--r-xs)}
.sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip{position:fixed;left:16px;top:-80px;z-index:200;background:var(--fg);color:var(--bg);padding:12px 18px;border-radius:999px}
.skip:focus{top:16px}

/* field + atmosphere */
/* lvh: the largest viewport, so the field's frame stays the same size while a phone's toolbars slide in and out */
#field{position:fixed;inset:0;width:100vw;height:100vh;height:100lvh;z-index:0;pointer-events:none}
.atmos{position:fixed;inset:0;z-index:0;pointer-events:none;background:radial-gradient(60% 50% at 50% 55%,#13151c 0,#050506 72%)}
.aura{position:fixed;inset:-20%;z-index:0;pointer-events:none;opacity:.26;filter:blur(90px);background:radial-gradient(30% 30% at 72% 38%,var(--a),transparent 70%),radial-gradient(28% 28% at 22% 70%,var(--b),transparent 70%);animation:aj-drift 18s ease-in-out infinite alternate}
@keyframes aj-drift{to{transform:translate(4%,-3%) scale(1.08)}}
.grain{position:fixed;inset:0;z-index:90;pointer-events:none;opacity:.045;mix-blend-mode:soft-light;background-size:120px 120px;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.35' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>")}
/* The page's full-screen layers keep one size while a phone's toolbars slide in and out (the particle canvas's own height, set by site.js;
   l = largest viewport before it). Sized
   to the visible viewport, each toolbar change resized them, and the aura's 90px blur was re-rendered at the screen's
   full pixel density every time: on an iPhone the page stalled for seconds whenever the reader scrolled back up (the likely cause). */
.atmos,.grain{bottom:auto;height:100vh;height:var(--frame-h,100lvh)}
.aura{bottom:auto;top:-20vh;top:calc(-.2*var(--frame-h,100lvh));height:140vh;height:calc(1.4*var(--frame-h,100lvh))}
main,header,footer{position:relative;z-index:2}

/* pause motion */
.motion-toggle{margin-left:auto;width:44px;height:44px;flex:none;border-radius:50%;border:1px solid var(--line);background:#16161acc;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);display:grid;place-items:center;transition:border-color .3s}
@media (hover:hover){.motion-toggle:hover{border-color:#f5f2ec88}}
.motion-toggle+.nav{margin-left:2px}
.still *,.still *:before,.still *:after{animation-play-state:paused!important}

/* type */
.display{font-family:var(--display);font-weight:800;letter-spacing:-.04em;line-height:.98;color:var(--fg)}
.mono{font-family:var(--mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase}
.kicker{font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--mute);display:inline-flex;align-items:center;gap:10px}
/* The label marks are a few loose particles from the field, not UI dots: tiny soft points in the section's colours that
   twinkle and drift like the field's idle particles, and hold still when motion is off or reduced (2026-10-15). */
.kicker b,.avail i{--p1:var(--a);--p2:var(--b);position:relative;flex:none;width:12px;height:12px}
.avail i{--p1:#4dffa6;--p2:#b8ffd9}
.kicker b::before,.kicker b::after,.avail i::before,.avail i::after{content:'';position:absolute;left:50%;top:50%;width:2px;height:2px;margin:-1px 0 0 -1px;border-radius:50%;filter:drop-shadow(0 0 1.5px var(--p1));animation:aj-mote 3.4s ease-in-out infinite}
.kicker b::before,.avail i::before{background:var(--p1);box-shadow:0 -2.4px 0 -.2px var(--p2),2.3px -.7px 0 -.2px var(--p1),1.4px 2px 0 -.2px var(--p2),-1.4px 2px 0 -.2px var(--p1),-2.3px -.7px 0 -.2px var(--p2)}
.kicker b::after,.avail i::after{background:transparent;box-shadow:none;animation-duration:4.1s;animation-delay:-1.7s}
/* with the field running, real field particles settle on the marks (site.js marks, engine setMotes); these CSS motes
   stand in only for Motion off, reduced field support and the no-WebGL page */
html.field-marks:not(.no-field):not(.portfolio-fallback) body:not(.still) :is(.kicker b,.avail i)::before,html.field-marks:not(.no-field):not(.portfolio-fallback) body:not(.still) :is(.kicker b,.avail i)::after{opacity:0;animation:none}
@keyframes aj-mote{0%,100%{opacity:.5;translate:0 0}35%{opacity:1;translate:.5px -.7px}70%{opacity:.75;translate:-.6px .3px}}
.still :is(.kicker b,.avail i)::before,.still :is(.kicker b,.avail i)::after{animation:none;opacity:.9}
@media (prefers-reduced-motion:reduce){:is(.kicker b,.avail i)::before,:is(.kicker b,.avail i)::after{animation:none;opacity:.9}}
/* the metal gradient repeats once per line (1lh tiles), so the middle line of a long title never lands in the dark band */
.chrome{background:linear-gradient(105deg,transparent 38%,#ffffffee 48%,#c9d4ff 52%,transparent 60%) 0 0/300% 100% no-repeat,linear-gradient(180deg,#ffffff 0%,#e9edf3 34%,#9aa3b2 50%,#4c5361 54%,#b9c3d1 66%,#f2f5f9 84%,#ffffff 100%) 0 0/100% 1lh repeat-y;-webkit-background-clip:text;background-clip:text;color:transparent;animation:aj-sheen 7s var(--ease) infinite}
@keyframes aj-sheen{0%,40%{background-position:120% 0,0 0}80%,100%{background-position:-60% 0,0 0}}
.grad{background:linear-gradient(90deg,var(--a),var(--b));-webkit-background-clip:text;background-clip:text;color:transparent}
/* gradient text paints only inside its own box: pad the box so descenders and the J's hook are inside it, without moving layout */
.chrome,.grad,.hotgrad{padding:0 .06em .2em;margin:0 -.06em -.2em;-webkit-box-decoration-break:clone;box-decoration-break:clone}
span.chrome,span.grad,span.hotgrad,b.grad{margin-bottom:0}
.hotgrad{background:linear-gradient(90deg,var(--hot),var(--orange),var(--gold),var(--violet),var(--hot));-webkit-background-clip:text;background-clip:text;color:transparent;background-size:200% 100%;animation:aj-pan 10s linear infinite}
@keyframes aj-pan{to{background-position:200% 0}}
h1,h2,h3{font-weight:inherit}
.lede{font-size:clamp(18px,1.45vw,22px);line-height:1.5;color:var(--text);max-width:600px}

/* header */
/* Safari takes its toolbar colour from the fixed element at the top edge. For a header without a solid background it
   snapshots the fixed layers under that edge, and the snapshot redraws the aura's 90px blur at full quality while the page
   waits (about 0.4 s at the start of the greeting on an M1 Mac, about 1 s before the first particles on an iPhone). A backdrop
   filter on the header makes Safari skip that snapshot. blur(0px) draws the same pixels on macOS Safari; on iPhone the
   header strip can differ by up to 2/255 per channel, which is not visible (accepted 2026-10-20). */
.hdr{position:fixed;top:0;left:0;right:0;z-index:60;display:flex;align-items:center;gap:24px;padding:16px var(--pad);height:var(--hdr);transition:transform .5s var(--ease),background .4s;-webkit-backdrop-filter:blur(0px);backdrop-filter:blur(0px)}
.hdr.scrolled{background:linear-gradient(#050506e6,#05050600)}
.logo{font-family:var(--display);font-weight:800;font-size:24px;letter-spacing:-.06em;display:flex;align-items:center;gap:10px;color:var(--fg);min-height:44px}
.logo i{width:10px;height:10px;border-radius:50%;background:conic-gradient(var(--hot),var(--orange),var(--gold),var(--cyan),var(--violet),var(--hot))}
.nav{display:flex;gap:4px;padding:5px;border-radius:999px;background:#16161acc;border:1px solid var(--line);-webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4)}
.nav a{position:relative;padding:10px 18px;border-radius:999px;font-size:15px;font-weight:500;color:#e9e5de;transition:color .15s ease-out,background .15s ease-out;min-height:42px;display:inline-flex;align-items:center}
.nav a[aria-current=page]{color:var(--fg);background:#ffffff1a}@media (hover:hover){.nav a:hover{color:var(--fg);background:#ffffff1a}}
.nav a.cta{background:var(--fg);color:var(--bg)}
@media (hover:hover){.nav a.cta:hover{background:#fff}}
.menu-btn{display:none;margin-left:10px;width:48px;height:48px;border-radius:50%;border:1px solid var(--line);background:#16161acc;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);position:relative}
.menu-btn span{position:absolute;left:15px;right:15px;height:1.5px;background:var(--fg);transition:transform .4s var(--ease),top .4s var(--ease)}
.menu-btn span:first-child{top:20px}.menu-btn span:last-child{top:27px}
.menu-open .menu-btn span:first-child{top:23.5px;transform:rotate(45deg)}
.menu-open .menu-btn span:last-child{top:23.5px;transform:rotate(-45deg)}
.overlay-menu{position:fixed;inset:0;z-index:55;background:#050506f5;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);display:flex;flex-direction:column;justify-content:safe center;overflow-y:auto;overscroll-behavior:contain;padding:calc(var(--hdr,84px) + 8px) var(--pad) var(--pad);gap:8px;clip-path:circle(0% at calc(100% - 44px) 42px);transition:clip-path .8s var(--ease);visibility:hidden}
.menu-open .overlay-menu{clip-path:circle(150% at calc(100% - 44px) 42px);visibility:visible}
.overlay-menu a{font-family:var(--display);font-weight:800;font-size:clamp(34px,min(13vw,7.6svh),96px);letter-spacing:-.05em;line-height:1.05;color:var(--fg)}
.overlay-menu small{margin-top:30px;color:var(--mute)}
.progress{position:fixed;top:0;left:0;height:2px;z-index:70;background:linear-gradient(90deg,var(--hot),var(--orange),var(--gold),var(--cyan));transform-origin:left;transform:scaleX(0);width:100%}

/* buttons */
.actions{display:flex;gap:10px;flex-wrap:wrap}
.btn{position:relative;display:inline-flex;align-items:center;gap:14px;padding:16px 26px;border-radius:999px;font-weight:600;font-size:15px;border:1px solid #f5f2ec33;background:#16161acc;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);color:var(--fg);transition:background .15s ease-out,color .15s ease-out,border-color .15s ease-out;min-height:52px;white-space:nowrap}
@media (hover:hover){.btn:hover{background:#26262c}}
.btn .ar{display:inline-block;transition:transform .15s ease-out}
@media (hover:hover){.btn:hover .ar{transform:translate(2px,-2px)}}
@media (hover:hover){.btn:hover .ar-x{transform:translateX(2px)}}
.btn.solid{background:var(--fg);color:var(--bg);border-color:var(--fg)}
@media (hover:hover){.btn.solid:hover{background:#fff}}
.btn.ring{border:1px solid transparent;background:linear-gradient(#0d0d10,#0d0d10) padding-box,conic-gradient(from var(--aj-ang),#ffffff,#7b8494,var(--hot),var(--gold),#ffffff,#3a404c,var(--cyan),#ffffff) border-box;animation:aj-ring 2.6s var(--ease) .6s 1 both}
@media (hover:hover){.btn.ring:hover{background:linear-gradient(#1b1b21,#1b1b21) padding-box,conic-gradient(from var(--aj-ang),#ffffff,#7b8494,var(--hot),var(--gold),#ffffff,#3a404c,var(--cyan),#ffffff) border-box}}
@keyframes aj-ring{from{--aj-ang:0deg}to{--aj-ang:360deg}}

/* cursor */
.cur,.cur-ring{position:fixed;left:0;top:0;pointer-events:none;z-index:400;border-radius:50%;transform:translate3d(-100px,-100px,0);opacity:0}
/* once a real mouse is seen the custom cursor replaces the system one; text fields keep their caret */
html.has-cur,html.has-cur *{cursor:none}
html.has-cur :is(input,textarea,select,[contenteditable]){cursor:text}
html.has-cur .cur,html.has-cur .cur-ring{opacity:1}
html.has-cur.cur-out .cur,html.has-cur.cur-out .cur-ring{opacity:0}
.cur{width:6px;height:6px;background:#fff;margin:-3px 0 0 -3px;transition:opacity .3s}
.cur-ring{width:36px;height:36px;margin:-18px 0 0 -18px;border:1px solid #ffffff55;transition:width .35s var(--ease),height .35s var(--ease),margin .35s var(--ease),background .35s,border-color .35s,opacity .3s;display:grid;place-items:center;font:600 11px/1 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--bg)}
.cur-ring.link{width:56px;height:56px;margin:-28px 0 0 -28px;border-color:#ffffffaa}
.cur-ring.label{width:62px;height:24px;margin:16px 0 0 14px;border-radius:999px;background:var(--fg);border-color:var(--fg);color:var(--bg);font-size:9.5px;letter-spacing:.14em;box-shadow:0 8px 24px -8px #000}
@media (hover:none),(pointer:coarse){.cur,.cur-ring{display:none}}

section{position:relative}

/* home hero */
.hero{min-height:100svh;display:flex;flex-direction:column;justify-content:space-between;padding:calc(var(--hdr) + 10px) var(--pad) 32px}
.hero-top{display:grid;grid-template-columns:1fr auto 1fr;align-items:baseline;gap:20px;color:var(--mute);white-space:nowrap}
/* the middle label sits exactly on the page's centre line, whatever the widths of its neighbours */
.hero-top>:first-child{justify-self:start}.hero-top>:nth-child(2){justify-self:center}.hero-top>:last-child{justify-self:end}
@media(max-width:640px){.hero-top{grid-template-columns:1fr 1fr}.hero-top>:nth-child(2){display:none}}
.hero-bottom{display:grid;grid-template-columns:1fr auto;gap:30px;align-items:end}
.hero-bottom h1{font-family:var(--body);font-weight:500;font-size:clamp(21px,2vw,30px);line-height:1.3;letter-spacing:-.015em;max-width:640px;color:var(--fg)}
.hero-bottom h1 span{color:var(--mute)}
.hero-role{font-size:12px;letter-spacing:.08em;text-transform:uppercase;max-width:640px}
.hero-role{display:flex;flex-wrap:wrap;gap:4px 16px;color:var(--mute);margin-bottom:14px}
.hero-role .hero-engagements{white-space:nowrap}
@media(max-width:640px){.hero .actions{gap:8px}.hero .actions .btn{padding:15px 20px;gap:10px}}

/* page heros */
.phero{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);gap:4vw;align-items:center;min-height:min(100svh,960px);padding:calc(var(--hdr) + 3vh) var(--pad) 6vh}
.phero h1{margin:16px 0 22px;font-size:clamp(52px,6.6vw,124px)}
.phero .lede{margin-bottom:28px}

.statement{min-height:100vh;display:flex;align-items:center;padding:var(--sp-xl) var(--pad)}
.statement .inner{max-width:min(860px,52vw)}
.statement p.big{font-family:var(--display);font-weight:700;font-size:clamp(30px,2.9vw,46px);max-width:24em;line-height:1.12;letter-spacing:-.028em;color:var(--fg)}
.statement p.big .w{opacity:.38;transition:opacity .25s}
.statement p.big .w.on{opacity:1}
.statement p.big .lit-line{display:block;margin-top:.42em}
/* key phrases (designer, developer, search agency, I do all three) arrive white with the rest, then sweep left to right
   into the section's pink-to-gold once a reader reaches them (site.js times it). Same white-layer wipe as .split .hotgrad;
   the phrase spans stay inline so Safari paints background-clip:text. Without the sweep they simply stay white. */
.statement p.big .w.key{--wipe:0%;background-image:linear-gradient(90deg,#f5f2ec00 calc(var(--wipe) - 40%),var(--fg) var(--wipe)),linear-gradient(90deg,var(--ka,#ff2d75),var(--kb,#ffc861));-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-box-decoration-break:clone;box-decoration-break:clone;transition:opacity .25s,--wipe 1.1s cubic-bezier(.45,0,.25,1)}
.statement p.big .w.key.swept{--wipe:140%}
@media (prefers-reduced-motion:reduce){.statement p.big .w.key{transition:opacity .25s}}
/* the professional summary under the statement: quiet body text, no surface of its own */
.statement .summary{margin-top:40px;max-width:44em;font-size:16px;line-height:1.6;color:var(--mute)}
.statement .summary b{font-weight:500;color:var(--text)}

/* split words: room for descenders like g, p, y */
.split .wd{display:inline-block;overflow:hidden;vertical-align:top;padding:0 .06em .32em;margin:0 -.06em -.32em}
/* Print-in: each word is printed left to right, its leading edge breaking into halftone dots (the site's ink) before
   it resolves into solid type. Three mask layers: a solid wipe, plus a band where only the dots show. The band and
   wipe slide together (mask-position): at 100% the word is hidden, at 0 the solid part (117% of the word) covers it and the
   dotted band lies just past its right edge. Padding keeps overhangs and descenders inside
   the masked box. */
.split .wd>span{display:inline-block;padding:0 .08em .3em;margin:0 -.08em -.3em;-webkit-mask-image:linear-gradient(90deg,#000 0 45%,transparent 49%),linear-gradient(90deg,transparent 39%,#000 44%,#000 56%,transparent 62%),radial-gradient(circle,#000 0 1.15px,transparent 1.55px);mask-image:linear-gradient(90deg,#000 0 45%,transparent 49%),linear-gradient(90deg,transparent 39%,#000 44%,#000 56%,transparent 62%),radial-gradient(circle,#000 0 1.15px,transparent 1.55px);-webkit-mask-size:260% 100%,260% 100%,5px 5px;mask-size:260% 100%,260% 100%,5px 5px;-webkit-mask-repeat:no-repeat,no-repeat,repeat;mask-repeat:no-repeat,no-repeat,repeat;-webkit-mask-composite:source-over,source-in;mask-composite:add,intersect;-webkit-mask-position:var(--portfolio-print,100%) 0,var(--portfolio-print,100%) 0,0 0;mask-position:var(--portfolio-print,100%) 0,var(--portfolio-print,100%) 0,0 0}
.split.in .wd>span{animation:aj-print .5s cubic-bezier(.3,.65,.25,1) both;animation-delay:calc(var(--i)*30ms)}
@keyframes aj-print{from{-webkit-mask-position:100% 0,100% 0,0 0;mask-position:100% 0,100% 0,0 0}to{-webkit-mask-position:0 0,0 0,0 0;mask-position:0 0,0 0,0 0}}
.portfolio-fallback .split .wd>span,.still .split .wd>span{-webkit-mask:none!important;mask:none!important;animation:none!important}

/* home project chapters */
.work-intro{padding:var(--sp-xl) var(--pad) var(--sp-xs);display:flex;justify-content:space-between;align-items:flex-end;gap:30px;flex-wrap:wrap}
.work-intro h2{font-size:clamp(44px,5.4vw,96px);max-width:min(900px,58vw)}
.work-intro p{max-width:400px;color:var(--mute)}
.chapter{min-height:100vh;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center;padding:var(--sp-l) var(--pad);gap:5vw}
.chapter.flip .ch-copy{order:2}
.ch-copy{position:relative;z-index:3;max-width:620px}
.ch-tags{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:22px}
.ch-tags span{font:500 12px/1 var(--mono);letter-spacing:.04em;padding:9px 12px;border-radius:999px;border:1px solid var(--line);color:var(--text);background:#0d0d10cc}
.ch-copy h2{margin-bottom:20px}
.ch-copy p.line{font-size:clamp(18px,1.4vw,21px);color:var(--text);max-width:540px;line-height:1.45}
.stats{display:flex;gap:40px;margin:28px 0 6px;flex-wrap:wrap}
.stat b{display:block;font-family:var(--display);font-weight:800;font-size:clamp(34px,3.2vw,54px);letter-spacing:-.035em;line-height:1.1}
.stat span{display:block;font-size:14px;color:var(--mute);margin-top:4px;max-width:200px}
.qual{font-size:13px;color:var(--soft);max-width:520px;margin:14px 0 24px;line-height:1.5}
.quote-mini{border-left:2px solid var(--a);padding:4px 0 4px 16px;color:var(--text);font-size:16px;max-width:520px;margin:6px 0 26px}
.quote-mini small{display:block;color:var(--mute);margin-top:6px;font-size:13px}
.shot{display:block;position:relative;margin-top:32px;border-radius:var(--r-md);perspective:1200px}
.shot .card{display:block;position:relative;border-radius:var(--r-md);overflow:hidden;border:1px solid #ffffff2a;box-shadow:0 40px 100px -40px #000,0 0 90px -40px var(--a);background:#0c0c10;aspect-ratio:16/9}
.shot img{width:100%;height:100%;object-fit:cover;object-position:top;transition:transform 1s var(--ease)}
@media (hover:hover){.shot:hover img{transform:scale(1.02)}}


/* proof + logos */
.proof{padding:var(--sp-xl) var(--pad);display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);gap:5vw;align-items:center}
blockquote{font-family:var(--display);font-weight:700;font-size:clamp(26px,2.6vw,42px);line-height:1.18;letter-spacing:-.022em;color:var(--fg)}
blockquote:before{content:'\201C';display:block;font-size:2.2em;line-height:.6;margin-bottom:10px;background:linear-gradient(90deg,var(--a),var(--b));-webkit-background-clip:text;background-clip:text;color:transparent}
.cite{margin-top:24px;color:var(--mute);display:flex;align-items:center;gap:12px}
.cite i{width:34px;height:34px;border-radius:50%;background:conic-gradient(from 200deg,var(--a),var(--b),var(--a))}
/* a real photo of the person quoted, reduced to a 32-pixel grid, shown at its own size so every cell lands on whole screen pixels: small, honest, and a little playful */
.cite-avatar{flex:none;width:32px;height:32px;border-radius:5px;image-rendering:pixelated;box-shadow:0 0 0 1px #ffffff2e}
.quotes{display:grid;gap:14px}
.glass{position:relative;border-radius:var(--r-lg);border:1px solid var(--line);background:linear-gradient(160deg,#1c1c22e6,#0d0d10e6);-webkit-backdrop-filter:blur(22px) saturate(1.3);backdrop-filter:blur(22px) saturate(1.3);box-shadow:inset 0 1px 0 #ffffff1a}
.quotes .glass{padding:26px}
.quotes .glass p{font-size:18px;color:var(--fg)}
.quotes .glass small{display:block;color:var(--mute);margin-top:12px;font-size:14px}
.logos{padding:var(--sp-s) var(--pad) var(--sp-l)}
.logos .head{display:flex;justify-content:space-between;gap:30px;align-items:end;margin-bottom:6vh;flex-wrap:wrap}
.logos .head h2{font-size:clamp(34px,3.8vw,60px)}
.logos .head p{max-width:460px;color:var(--mute)}
.logo-row{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));align-items:center;gap:34px 36px;padding:34px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.logo-row figure{display:flex;align-items:center;justify-content:center}
.logo-row .lg{height:48px;display:flex;align-items:center;justify-content:center;width:100%}
.logo-row img{height:36px;width:144px;max-width:100%;object-fit:contain;object-position:center;filter:brightness(0) invert(1);opacity:.85;transition:opacity .3s}
@media (hover:hover){.logo-row figure:hover img{opacity:1}}
.next-links{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;padding:var(--sp-xs) var(--pad) var(--sp-l)}
.next-links a{padding:30px;min-height:230px;display:flex;flex-direction:column;justify-content:space-between}
@media (hover:hover){.next-links a:hover{border-color:#ffffff40}}
.next-links h3{font-family:var(--display);font-weight:800;font-size:clamp(32px,2.8vw,46px);letter-spacing:-.04em;color:var(--fg);line-height:1.1}
.next-links p{color:var(--mute);margin-top:10px}
.next-links .ar{font-size:24px;color:var(--fg)}
.built{padding:var(--sp-s) var(--pad) var(--sp-m)}
.built .head{display:flex;justify-content:space-between;gap:30px;align-items:end;margin-bottom:5vh;flex-wrap:wrap}
.built .head h2{font-size:clamp(40px,5vw,84px)}
.built .head p{max-width:440px;color:var(--mute)}
.built-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.built-card{padding:16px 16px 26px;display:flex;flex-direction:column}
.built-shot{display:block;aspect-ratio:16/9;overflow:hidden;border-radius:14px;border:1px solid var(--line);background:#0d0d10}
.built-shot img{display:block;width:100%;height:100%;object-fit:cover;transition:transform .6s cubic-bezier(.2,.7,.2,1)}
@media (hover:hover){.built-card:hover .built-shot img{transform:scale(1.025)}}
@media (prefers-reduced-motion:reduce){.built-shot img{transition:none}.built-card:hover .built-shot img{transform:none}}
.built-label{display:block;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--soft);margin:26px 14px 0}
.built-card h3{font-family:var(--display);font-weight:800;font-size:clamp(34px,3vw,52px);letter-spacing:-.04em;color:var(--fg);line-height:1.05;margin:12px 14px 0}
.built-card>p{color:var(--mute);margin:12px 14px 0;max-width:540px}
.built-card .stats{margin:auto 14px 0;padding-top:28px;gap:40px}
.built-card .stat b{font-size:clamp(30px,2.6vw,44px)}
.built-card .stat span{max-width:none}
.built-foot{display:flex;justify-content:space-between;align-items:center;gap:16px;margin:0 14px;padding-top:24px}
.built-foot .mono{font-size:12px;letter-spacing:.08em;color:var(--mute)}
.built-foot .ar{font-size:24px;color:var(--fg)}
.built-oss{margin-top:24px;color:var(--mute)}

/* services page */
.svc-list{padding:var(--sp-xs) var(--pad) var(--sp-m);display:grid;gap:14px}
.svc-row{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:4vw;padding:44px;align-items:start;overflow:hidden}
.svc-row:before{content:'';position:absolute;width:420px;height:420px;border-radius:50%;right:-140px;top:-160px;background:radial-gradient(var(--c),transparent 65%);opacity:.3;filter:blur(30px);pointer-events:none}
.svc-row h2{font-size:clamp(30px,2.5vw,46px);display:flex;flex-direction:column;align-items:flex-start;gap:20px}
.svc-row .orb{flex:none;width:52px;height:52px;border-radius:50%;background:radial-gradient(circle at 32% 30%,#fff,var(--c) 42%,#000 100%);box-shadow:0 0 40px -6px var(--c)}
.svc-row p{color:var(--text);font-size:19px;max-width:620px;position:relative}
.svc-row ul{list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin-top:22px;position:relative}
.svc-row ul.pill-grid{display:grid;grid-template-columns:repeat(var(--cols,2),minmax(0,1fr))}
.svc-row li{font-size:14px;padding:9px 14px;border-radius:999px;background:#ffffff0f;border:1px solid var(--line);color:var(--fg)}
.process{padding:var(--sp-l) var(--pad)}
.process h2{font-size:clamp(40px,4.4vw,74px);max-width:900px}
.steps{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);margin-top:7vh;position:relative}
.steps:before{content:'';position:absolute;left:0;right:0;top:9px;height:1px;background:var(--line)}
.steps .bar{position:absolute;left:0;top:9px;height:1px;width:100%;background:linear-gradient(90deg,var(--hot),var(--orange),var(--gold),var(--cyan));transform-origin:left;transform:scaleX(var(--p,0))}
.step{padding-right:3vw;position:relative}
.step .dot{display:block;width:19px;height:19px;border-radius:50%;background:var(--bg);border:1px solid #ffffff66;position:relative;z-index:1;transition:background .4s,box-shadow .4s}
.step.on .dot{background:#fff;box-shadow:0 0 24px #fff}
.step h3{font-family:var(--display);font-weight:800;font-size:30px;letter-spacing:-.03em;margin:24px 0 10px;color:var(--fg)}
.step p{color:var(--mute);font-size:16px;max-width:300px}
.model{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;padding:0 var(--pad) var(--sp-m)}
.model .glass{padding:28px}
.model h3{font-family:var(--display);font-weight:700;font-size:24px;letter-spacing:-.02em;color:var(--fg);line-height:1.2}
.model p{color:var(--mute);margin-top:10px;font-size:16px}

/* work page */
.filters{display:flex;gap:8px;flex-wrap:wrap}
.filters button{padding:12px 20px;border-radius:999px;border:1px solid var(--line);background:#16161acc;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);font-weight:500;font-size:15px;transition:background .3s,color .3s;min-height:46px;color:var(--fg)}
.filters button[aria-pressed=true]{background:var(--fg);color:var(--bg)}
.wgrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:18px;padding:0 var(--pad) var(--sp-l)}
.wcard{grid-column:span 6;position:relative;border-radius:var(--r-lg);overflow:hidden;border:1px solid var(--line);background:#0d0d10;display:flex;flex-direction:column;transition:transform .6s var(--ease),border-color .4s,opacity .5s;isolation:isolate}
.wcard.wide{grid-column:span 7}.wcard.narrow{grid-column:span 5}
.wcard:focus-visible{border-color:#ffffff40}@media (hover:hover){.wcard:hover{border-color:#ffffff40}}
.wcard .img{aspect-ratio:16/10;overflow:hidden;position:relative;display:block}
.wcard .img img{width:100%;height:100%;object-fit:cover;object-position:top;transition:transform 1.1s var(--ease)}
@media (hover:hover){.wcard:hover .img img{transform:scale(1.02)}}
.wcard .bd{padding:24px 26px 26px;display:flex;flex-direction:column;flex:1;border-top:1px solid var(--line)}
.wcard h3{font-family:var(--display);font-weight:800;font-size:clamp(28px,2.4vw,40px);letter-spacing:-.035em;line-height:1.1;color:var(--fg)}
.wcard p{color:var(--mute);margin-top:10px;max-width:540px;font-size:16px}
.wcard .meta{display:flex;justify-content:space-between;align-items:center;margin-top:auto;padding-top:18px;color:var(--soft)}
.wcard .meta i{font-style:normal;width:42px;height:42px;border-radius:50%;display:grid;place-items:center;border:1px solid var(--line);color:var(--fg);transition:background .3s,color .3s,transform .4s var(--ease)}
@media (hover:hover){.wcard:hover .meta i{background:var(--fg);color:var(--bg)}}
.wcard .glow{position:absolute;left:-20%;right:-20%;bottom:-50%;height:70%;background:radial-gradient(50% 50% at 50% 50%,var(--ca),transparent 70%);opacity:0;filter:blur(40px);transition:opacity .6s;z-index:-1}
@media (hover:hover){.wcard:hover .glow{opacity:.35}}
.wcard[hidden]{display:none}
.work-count{margin-top:16px;color:var(--soft)}

/* case study */
.facts{display:grid;grid-template-columns:1fr 1fr;padding:6px 24px;max-width:640px}
.facts div{padding:16px 12px 16px 0;font-size:14px;color:var(--mute)}
.facts div:not(:nth-last-child(-n+2)){border-bottom:1px solid var(--line)}
.facts b{display:block;color:var(--fg);font-weight:500;font-size:16px;margin-top:4px}
.facts a{color:var(--gold)}
.cs-image{padding:var(--sp-xs) var(--pad) var(--sp-m)}
.cs-image figure{max-width:var(--max);margin:0 auto}
.cs-image .frame{border-radius:var(--r-lg);overflow:hidden;border:1px solid var(--line);box-shadow:0 60px 160px -40px #000,0 0 120px -50px var(--a);background:#0a0a0d}
.cs-image img{width:100%;height:auto}
.cs-image figcaption{color:var(--mute);font-size:14px;line-height:1.5;margin-top:14px;max-width:760px}
.cs-sec{display:grid;grid-template-columns:minmax(0,.75fr) minmax(0,1.5fr);gap:5vw;padding:var(--sp-m) var(--pad);max-width:calc(var(--max) + 2*var(--pad));margin:0 auto}
.cs-sec h2{font-size:clamp(34px,3.4vw,56px);position:sticky;top:calc(var(--hdr) + 4vh);align-self:start}
.cs-sec .txt{font-size:clamp(20px,1.7vw,26px);line-height:1.45;color:var(--text);max-width:760px}
.cs-sec .contribution{font-size:16px;color:var(--mute);margin-top:22px;max-width:760px}
.cs-sec .contribution b{display:block;color:var(--fg);font-weight:500;margin-bottom:4px}
.dec{padding:0 0 32px}
.dec+.dec{padding-top:32px}
.dec h3{font-family:var(--display);font-weight:700;font-size:clamp(24px,2vw,32px);letter-spacing:-.022em;line-height:1.2;color:var(--fg)}
.dec p{color:var(--mute);margin-top:10px;max-width:660px;font-size:17px}
.big-stats{display:flex;gap:4vw;flex-wrap:wrap;margin-bottom:4vh}
.big-stats .stat b{font-size:clamp(48px,5.4vw,96px)}
/* Palisades case evidence only. Shared case and card treatments stay intact. */
.palisades-proof{padding:0;margin:0 0 32px;max-width:760px}
.palisades-proof .frame{box-shadow:0 60px 160px -40px #000,0 0 120px -50px var(--a)}
.palisades-proof figcaption a{color:var(--gold);text-decoration:underline;text-underline-offset:3px}
.palisades-proof-excerpts,.palisades-proof-excerpt-note{display:none}
.palisades-proof--calendar{max-width:520px}
.palisades-search{padding:0 0 32px}
.palisades-search h3{font-family:var(--display);font-weight:700;font-size:clamp(24px,2vw,32px);letter-spacing:-.022em;line-height:1.2;color:var(--fg);margin-bottom:24px}
.palisades-search-stats{gap:24px 4vw}
.palisades-search-stats .stat span{max-width:none}
.palisades-search-stats .stat .palisades-search-label{font-size:17px;color:var(--fg)}
.palisades-outcome .grad{background-image:linear-gradient(90deg,var(--palisades-lake),var(--palisades-stone))}
.palisades-result-label{font-size:17px;font-weight:500;color:var(--mute);margin-bottom:20px}
.palisades-articles{list-style:none;margin-top:22px;max-width:660px}
.palisades-articles li+li{margin-top:14px}
.palisades-articles a,.palisades-blog-link a{color:var(--gold);text-decoration:underline;text-underline-offset:3px}
.palisades-articles li>span{display:block;color:var(--mute);font-size:14px;margin-top:3px}
.dec .palisades-blog-link{margin-top:22px}
@media(max-width:767px){
 .palisades-proof-full{display:none}
 .palisades-proof-excerpts{display:grid;gap:14px}
 .palisades-proof-excerpt-note{display:inline}
 .palisades-proof-excerpts .frame{border-radius:var(--r-sm)}
 .palisades-proof--gsc .palisades-proof-excerpts{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
}
.next{min-height:80vh;display:flex;flex-direction:column;justify-content:center;align-items:flex-start;padding:0 var(--pad)}
.next a.n{max-width:min(980px,54vw);font-family:var(--display);font-weight:800;letter-spacing:-.045em;line-height:1.1;display:block;margin-top:2vh;padding-bottom:.12em}
.next a.n{background:none;animation:none;color:inherit}
.next a.n span{display:inline-block;transition:transform .2s ease-out}
@media (hover:hover){.next a.n:hover span{transform:translateX(6px)}}

/* about */
.ab-meta{display:flex;flex-wrap:wrap;gap:8px 22px;margin-top:18px;color:var(--soft);letter-spacing:.06em}
.avail{display:inline-flex;align-items:center;gap:9px;color:var(--mute);letter-spacing:.06em}

.contact .avail{margin-top:14px}
.contact .grid small.loc{display:block;color:var(--soft);font-size:13px;margin-top:4px}
.timeline{list-style:none;padding:0 var(--pad) var(--sp-s);max-width:calc(var(--max) + 2*var(--pad));margin:0 auto}
.timeline li{display:grid;grid-template-columns:minmax(150px,.32fr) minmax(0,1fr) 200px;gap:4vw;padding:24px 0;border-top:1px solid var(--line)}
/* employer marks: one white, single-colour treatment at one height, matching the Selected accounts logos */
.tl-logo{display:flex;align-items:center;justify-content:flex-end;gap:10px;align-self:center;height:52px}
.tl-logo img{max-height:28px;width:auto;max-width:170px;object-fit:contain;filter:brightness(0) invert(1);opacity:.9}
.tl-logo img.mark{height:26px}
.tl-logo img.mark.js{height:46px}
.tl-logo img.script{max-height:42px;opacity:1}
.tl-logo b{font-family:var(--display);font-weight:700;font-size:19px;letter-spacing:-.02em;line-height:1;color:#fff;opacity:.9;white-space:nowrap}
.timeline li:last-child{border-bottom:1px solid var(--line)}
.tl-date{color:var(--soft);padding-top:6px;letter-spacing:.06em}
.timeline h3{font-family:var(--display);font-weight:700;font-size:clamp(22px,1.8vw,28px);letter-spacing:-.02em;color:var(--fg);line-height:1.15}
.timeline .tl-role{color:var(--gold);font-size:15px;margin-top:4px}
.timeline p{color:var(--mute);font-size:16px;margin-top:8px;max-width:720px}
.xp-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 20px;padding:var(--sp-s) var(--pad) 18px}
.xp-head p{color:var(--soft);font-size:15px}
.ab-writing{padding:0 var(--pad) var(--sp-m);color:var(--mute)}
.ab-copy{position:relative;z-index:1}
.ab-portrait{position:relative;display:flex;justify-content:center;align-items:center;align-self:center;min-height:200px}
.pr-stage{position:relative}
.pr-stage canvas{position:absolute;display:block;pointer-events:none}
.pr-shadow{position:absolute;inset:0;border-radius:var(--r-md);box-shadow:0 60px 120px -40px #000,0 0 0 1px #ffffff14;opacity:0;transition:opacity 1.2s var(--ease)}
.ab-portrait.pr-done .pr-shadow{opacity:1}
.ab-portrait.pr-cutout .pr-shadow{display:none}
.pr-fallback{display:block;width:100%;height:auto;border-radius:var(--r-md)}
.ab-copy p{font-size:18px;color:var(--text);max-width:600px;margin-top:16px;line-height:1.6}
.inline-link{color:var(--fg);text-decoration:underline;text-decoration-color:#f5f2ec55;text-underline-offset:4px;transition:text-decoration-color .3s}
@media (hover:hover){.inline-link:hover{text-decoration-color:var(--gold)}}
.ab-copy p.first{font-size:clamp(20px,1.6vw,25px);color:var(--fg);line-height:1.4}
.cards4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;padding:0 var(--pad) var(--sp-m)}
.cards4 .glass{padding:26px;min-height:240px;display:flex;flex-direction:column;justify-content:space-between}
.cards4 h3{font-family:var(--display);font-weight:700;font-size:24px;letter-spacing:-.02em;line-height:1.2;color:var(--fg)}
.cards4 p{color:var(--mute);font-size:16px;margin-top:14px}
.sec-head{padding:var(--sp-l) var(--pad) var(--sp-s);display:flex;justify-content:space-between;align-items:flex-end;gap:30px;flex-wrap:wrap}
.sec-head h2{font-size:clamp(38px,4.4vw,78px);max-width:900px}
.sec-head h2.wide{font-size:clamp(34px,3.6vw,64px);max-width:min(1180px,100%)}
.sec-head p{max-width:440px;color:var(--mute)}
.xp{padding:0 var(--pad) var(--sp-m);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.xp .glass{padding:24px 26px;display:grid;grid-template-columns:150px minmax(0,1fr);gap:26px;align-items:center}
.xp .lg{height:52px;display:flex;align-items:center}
.xp img{max-height:28px;width:auto;max-width:140px;object-fit:contain;filter:brightness(0) invert(1);opacity:.9}
.xp img.short{max-height:18px}
.xp b{display:block;color:var(--fg);font-weight:600;font-size:17px}
.xp span{display:block;color:var(--mute);font-size:15px;margin-top:4px}

/* writing: index */
.wr-hero{min-height:min(74svh,720px)}
.wr-topics{color:var(--soft);letter-spacing:.06em;line-height:1.9;max-width:560px}
.wr-index{padding:0 var(--pad) var(--sp-l);max-width:calc(var(--max) + 2*var(--pad));margin:0 auto}
.wr-feature{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);overflow:hidden;transition:border-color .15s ease-out}
@media (hover:hover){.wr-feature:hover{border-color:#ffffff40}}
.wr-feature-img{display:block;min-height:300px;overflow:hidden}
.wr-feature-img img{width:100%;height:100%;object-fit:cover;object-position:top;transition:transform 1.1s var(--ease)}
@media (hover:hover){.wr-feature:hover .wr-feature-img img{transform:scale(1.02)}}
.wr-feature-bd{display:flex;flex-direction:column;padding:34px 36px}
/* Instructions that depend on the input: hover wording for mouse and trackpad, tap wording for touch screens. */
.on-touch{display:none}
@media (hover:none){.on-hover{display:none}.on-touch{display:inline}}
.wr-feature :is(h2,h3){font-family:var(--display);font-weight:800;font-size:clamp(28px,2.6vw,44px);letter-spacing:-.035em;line-height:1.08;color:var(--fg);margin-top:16px}
.wr-feature p{color:var(--mute);margin-top:14px;font-size:18px;max-width:460px}
.wr-more{margin-top:auto;padding-top:24px;color:var(--fg);font-weight:600}
.wr-meta{display:flex;flex-wrap:wrap;gap:6px 16px;color:var(--soft);letter-spacing:.06em}
.wr-meta span+span:before{content:'·';margin-right:16px;color:var(--line)}
.wr-list{list-style:none;margin-top:5vh;border-top:1px solid var(--line)}
.wr-list>li>*{display:grid;grid-template-columns:150px minmax(0,1fr) 70px;gap:3vw;padding:26px 0;border-bottom:1px solid var(--line)}
.wr-list a{transition:background .3s}
@media (hover:hover){.wr-list a:hover h3{color:#fff;text-decoration:underline;text-decoration-color:#ffffff44;text-underline-offset:5px}}
.wr-date,.wr-time{color:var(--soft);letter-spacing:.06em;padding-top:5px}
.wr-time{text-align:right}
.wr-topic{color:var(--gold);letter-spacing:.06em}
.wr-list h3{font-family:var(--display);font-weight:700;font-size:clamp(22px,1.9vw,30px);letter-spacing:-.02em;line-height:1.15;color:var(--fg);margin-top:6px}
.wr-list p{color:var(--mute);font-size:16px;margin-top:6px;max-width:640px}

/* writing: article. Reading quality first: a comfortable measure, steady rhythm, no motion inside the text */
.art{padding:calc(var(--hdr) + 7vh) var(--pad) 8vh}
.art-head,.prose,.art-end{max-width:720px;margin:0 auto}
.art-crumb{display:flex;gap:10px;color:var(--soft);letter-spacing:.06em}
.art-crumb a{color:var(--mute)}@media (hover:hover){.art-crumb a:hover{color:var(--fg)}}
.art h1{font-family:var(--display);font-weight:800;font-size:clamp(36px,4.4vw,64px);letter-spacing:-.035em;line-height:1.04;color:var(--fg);margin-top:22px}
.art-deck{font-size:clamp(20px,1.6vw,24px);line-height:1.45;color:var(--text);margin-top:20px}
.art-meta{display:flex;flex-wrap:wrap;gap:6px 18px;color:var(--soft);margin-top:24px;letter-spacing:.06em}
.art-meta span+span:before{content:'·';margin-right:18px}
.art-note{margin-top:22px;padding:12px 16px;border-left:2px solid var(--gold);color:var(--mute);font-size:15px;background:#ffc8610a}
.prose{margin-top:6vh;font-size:19px;line-height:1.75;color:var(--text)}
.prose>*+*{margin-top:1.15em}
.prose h2{font-family:var(--display);font-weight:700;font-size:clamp(26px,2.2vw,34px);letter-spacing:-.025em;line-height:1.2;color:var(--fg);margin-top:2.2em}
.prose h3{font-family:var(--display);font-weight:700;font-size:23px;letter-spacing:-.015em;line-height:1.3;color:var(--fg);margin-top:1.9em}
.prose a{color:var(--fg);text-decoration:underline;text-decoration-color:var(--gold);text-underline-offset:4px}
@media (hover:hover){.prose a:hover{text-decoration-thickness:2px}}
.prose em{color:var(--fg)}
.prose ul,.prose ol{padding-left:1.3em}
.prose li+li{margin-top:.5em}
.prose li::marker{color:var(--gold)}
.prose code{font-family:var(--mono);font-size:.84em;background:#ffffff10;border:1px solid var(--line);border-radius:var(--r-xs);padding:.1em .35em}
.prose :not(pre)>code{overflow-wrap:anywhere}
.prose figure.code pre{overflow-x:auto;padding:20px 22px;border-radius:var(--r-sm);background:#0c0c10;border:1px solid var(--line);font:14.5px/1.65 var(--mono);color:#e6e1d8}
.prose figure.code pre code{background:none;border:0;padding:0;font-size:inherit}
.prose figure img{width:100%;height:auto;border-radius:var(--r-sm);border:1px solid var(--line)}
.prose figcaption{font-size:14px;line-height:1.5;color:var(--soft);margin-top:10px}
.prose figure{margin-top:2em;margin-bottom:2em}
.prose blockquote{font-size:clamp(24px,2.2vw,32px);margin:2em 0;padding-left:22px;border-left:2px solid var(--a)}
.prose blockquote:before{display:none}
.prose blockquote cite{display:block;font:500 14px/1.5 var(--body);font-style:normal;color:var(--soft);margin-top:14px;letter-spacing:0}
.art-end{margin-top:10vh;padding-top:var(--sp-s);border-top:1px solid var(--line);display:grid;gap:36px}
.art-author p{margin-top:12px;color:var(--mute)}
.art-author b{color:var(--fg);font-weight:600}
.art-links{display:flex;flex-wrap:wrap;gap:18px}
.art-related{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start}
.art-related .kicker{grid-column:1/-1}
.art-card{display:flex;flex-direction:column;gap:6px;padding:22px 24px;transition:border-color .15s ease-out}
@media (hover:hover){.art-card:hover{border-color:#ffffff40}}
.art-card .mono{color:var(--soft)}
.art-card b{font-family:var(--display);font-size:22px;letter-spacing:-.02em;color:var(--fg)}
.art-card span:last-child{color:var(--mute);font-size:15px}

/* contact */
/* the top space holds the Say Hello stage: a band below the header height, above the availability line (site.js) */
.contact{padding:calc(var(--hdr,84px) + clamp(240px,30vh,330px)) var(--pad) clamp(24px,4vh,40px);min-height:100vh;display:flex;flex-direction:column;justify-content:flex-end}
.contact h2{font-size:clamp(40px,5vw,90px);max-width:1000px;margin-top:18px}
.contact .mail{display:inline-block;align-self:flex-start;font-family:var(--display);font-weight:800;letter-spacing:-.04em;line-height:1.15;margin:4vh 0 5vh;white-space:normal;overflow-wrap:anywhere;font-size:clamp(22px,4.6vw,104px);padding-bottom:.1em;max-width:100%}
.contact .grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px;border-top:1px solid var(--line);padding-top:26px}
.contact .grid>*{color:var(--mute);font-size:14px;text-align:left}
.contact .grid button{text-align:left;padding:0;display:block}
.contact .grid b{display:block;color:var(--fg);font-weight:500;font-size:17px;margin-top:6px}
@media (hover:hover){.contact .grid a:hover b,.contact .grid button:hover b{color:var(--gold)}}
.copy-status{min-height:20px;font-size:14px;color:var(--gold);margin-top:6px}
.foot{position:relative;z-index:2;background:var(--bg);border-top:1px solid var(--line);color:var(--mute);font-size:15px}
.foot-top{display:grid;grid-template-columns:minmax(0,1.6fr) repeat(3,minmax(0,1fr));gap:40px;padding:64px var(--pad) 48px;max-width:calc(var(--max) + 2*var(--pad));margin:0 auto}
.foot-brand .logo{display:inline-flex}
.foot-brand p{margin-top:18px;max-width:380px;line-height:1.55}
.foot-brand p a{color:var(--fg);text-decoration:underline;text-decoration-color:#f5f2ec55;text-underline-offset:3px}
.foot-mail{display:inline-block;margin-top:18px;color:var(--fg);font-weight:500}
.foot-col{display:flex;flex-direction:column;gap:2px}
.foot-col h2{color:var(--soft);margin-bottom:12px}
.foot-col a{padding:7px 0;color:var(--text);width:max-content;max-width:100%}
.foot-col a .ar{display:inline-block;transition:transform .3s var(--ease)}
@media (hover:hover){.foot-col a:hover .ar{transform:translate(2px,-2px)}}
@media (hover:hover){.foot a:hover,.foot-brand p a:hover{color:#fff}}
.foot-bottom{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;padding:20px var(--pad);border-top:1px solid var(--line);max-width:calc(var(--max) + 2*var(--pad));margin:0 auto;font-size:14px}
.foot-bottom b{font-weight:500;color:var(--text)}
.foot-top-link{padding:8px 0}

/* reveal */
/* Root recovery leaves authored element animations, including chrome sheen, intact. */
:root:not(.portfolio-enhanced):not(.portfolio-fallback){animation:portfolio-readable 0s 3s forwards}
@keyframes portfolio-readable{to{--portfolio-reveal-opacity:1;--portfolio-reveal-transform:none;--portfolio-print:0%}}
[data-reveal]{opacity:var(--portfolio-reveal-opacity,0);transform:var(--portfolio-reveal-transform,translateY(30px));transition:opacity 1s var(--ease),transform 1.2s var(--ease)}
.portfolio-enhanced [data-reveal]{opacity:0;transform:translateY(30px)}
.portfolio-enhanced [data-reveal].in{opacity:1;transform:none}
.portfolio-fallback [data-reveal]{opacity:1;transform:none}
/* design lab, calm reveals (only with html, set by the ?lab=1 panel): body text, buttons, stats and text cards
   are simply there; headings and pictures keep one short, consistent reveal */
html [data-reveal]:not(h1,h2,h3,.shot,figure,.logo-row,.wcard,.wr-feature,.ab-portrait,.csx-figure,.csx-story-visual){opacity:1!important;transform:none!important;transition:none!important;animation:none!important}
html [data-reveal]:is(h1,h2,h3,.shot,figure,.logo-row,.wcard,.wr-feature,.ab-portrait,.csx-figure,.csx-story-visual){transition:opacity .7s var(--ease),transform .8s var(--ease)}
html.portfolio-enhanced [data-reveal]:is(h1,h2,h3,.shot,figure,.logo-row,.wcard,.wr-feature,.ab-portrait,.csx-figure,.csx-story-visual):not(.in){transform:translateY(14px)}
/* Motion off: content arrives in place, as with reduced motion, instead of rising into view */
html body.still [data-reveal]{transition:none!important}
.portfolio-fallback .split .wd>span{-webkit-mask:none;mask:none}
.portfolio-fallback .statement p.big .w{opacity:1}



@media (max-width:1100px){.cards4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (min-width:861px) and (max-width:1100px){.logo-row{grid-template-columns:repeat(8,minmax(0,1fr))}.logo-row figure{grid-column:span 2}.logo-row figure:nth-child(5){grid-column:2/span 2}}
@media (max-width:860px){
 :root{--hdr:72px}
 body{font-size:16px}
 .statement p.big,.ch-copy,.phero>div:first-child{text-shadow:0 1px 2px #050506,0 0 18px #050506,0 0 34px #050506}
/* The legibility halo is for type over the particle field. Buttons draw their own surface, and on a light (solid or
   pressed) one the inherited dark halo smeared the label, so it stops at the control. */
.btn,.filters button{text-shadow:none}
 .chrome,.grad,.hotgrad,.chrome *,.grad *,.hotgrad *,.statement p.big .w.key{text-shadow:none}
 .nav{display:none}.menu-btn{display:block}
 .hero-bottom{grid-template-columns:1fr}
 .phero{grid-template-columns:minmax(0,1fr);padding-top:47vh;min-height:auto}
 .next{justify-content:flex-end;min-height:100vh;padding-bottom:var(--sp-l)}
 .statement .inner{max-width:none}
 .statement{align-items:flex-end;min-height:90vh;padding-bottom:var(--sp-m)}
 .chapter,.chapter.flip{grid-template-columns:minmax(0,1fr);min-height:auto;padding:44vh var(--pad) var(--sp-m);gap:24px}
 .chapter.flip .ch-copy{order:0}
 .proof{grid-template-columns:minmax(0,1fr)}
 .logo-row{grid-template-columns:repeat(2,minmax(0,1fr));gap:30px 20px}
 .logo-row figure:last-child:nth-child(odd){grid-column:1/-1;width:calc((100% - 20px)/2);justify-self:center}
 .next-links{grid-template-columns:minmax(0,1fr)}
 .built-grid{grid-template-columns:minmax(0,1fr)}
 .built-card .stats{flex-wrap:nowrap;gap:22px}.built-card .stat{flex:1 1 0;min-width:0}
 .svc-row{grid-template-columns:minmax(0,1fr);padding:28px}
 .svc-row ul{display:flex}
 .svc-row ul.pill-grid{grid-template-columns:minmax(0,1fr)}
 .steps{grid-auto-flow:row;grid-template-columns:minmax(0,1fr);gap:34px}.steps:before,.steps .bar{display:none}.step{padding-right:0}
 .model{grid-template-columns:minmax(0,1fr)}
 .wcard,.wcard.wide,.wcard.narrow{grid-column:span 12}
 .cs-sec{grid-template-columns:minmax(0,1fr)}.cs-sec h2{position:static}
 .facts{grid-template-columns:1fr}.facts div{border-bottom:1px solid var(--line)}.facts div:last-child{border-bottom:0}
 .cards4{grid-template-columns:minmax(0,1fr)}
 .xp{grid-template-columns:minmax(0,1fr)}.xp .glass{grid-template-columns:minmax(0,1fr);gap:12px}
 .contact .grid{grid-template-columns:1fr 1fr}
 /* like the chapters and page heros, reserve open space above the contact heading for its particle shape */
 .contact{padding-top:40vh}
 .wr-feature{grid-template-columns:minmax(0,1fr)}
 .wr-feature-img{min-height:200px;max-height:260px}
 .wr-feature-bd{padding:24px}
 .wr-list>li>*{grid-template-columns:minmax(0,1fr);gap:6px}
 .wr-time{text-align:left;padding-top:0}
 .art-related{grid-template-columns:minmax(0,1fr)}
 .prose{font-size:18px}
 .timeline li{grid-template-columns:minmax(0,1fr);gap:8px;padding:20px 0}
 .timeline li>div{order:2}.tl-logo{order:1;justify-content:flex-start;height:auto;margin:4px 0 2px}.tl-logo img{max-height:22px}.tl-logo img.mark{height:20px}.tl-logo img.mark.js{height:32px}.tl-logo img.script{max-height:28px}.tl-logo b{display:none}
 .tl-date{padding-top:0}
 .foot-top{grid-template-columns:repeat(2,minmax(0,1fr));gap:32px 20px;padding-top:48px}
 .foot-brand{grid-column:1/-1}
 /* the about portrait leads on phones, with its own space instead of the reserved particle area */
 .phero.about-hero{padding-top:calc(var(--hdr) + 8vh)}
 .about-hero .ab-portrait{order:-1;margin-bottom:4vh}
 .next a.n{max-width:100%}
}
@media (max-width:480px){
 .phero h1{font-size:clamp(34px,11.2vw,52px)}
 .sec-head h2,.logos .head h2,.process h2,.work-intro h2{font-size:clamp(28px,9.1vw,43px)}
 .contact h2{font-size:clamp(28px,9.2vw,44px)}
 .statement p.big{font-size:clamp(23px,6.5vw,29px);line-height:1.16}
 .foot-top{grid-template-columns:minmax(0,1fr)}
 .filters{gap:6px}
 .filters button{padding-inline:13px}
}
@media (prefers-reduced-motion:reduce){
 *,*:before,*:after{animation-duration:.001s!important;animation-iteration-count:1!important;transition-duration:.001s!important;scroll-behavior:auto!important}
 [data-reveal],.portfolio-enhanced [data-reveal]{opacity:1;transform:none}.split .wd>span{-webkit-mask:none;mask:none;animation:none}
}

/* Approved UX choices, October 4, 2026. Capsule geometry retains circular end caps. */
html{scroll-padding-top:calc(var(--hdr) + 24px)}
#portfolio-sheet :focus-visible{outline:2px solid #f5f2ec;outline-offset:5px;box-shadow:0 0 0 7px #ffc86133}
/* sections focused by an in-page link jump are focused for screen readers only, not drawn as a focus ring */
[data-jump-target]:focus,#portfolio-sheet [data-jump-target]:focus{outline:none;box-shadow:none}
.hdr{isolation:isolate}.hdr.capsule-ready.scrolled{background:none}
.header-surface{position:absolute;pointer-events:none;z-index:-1;top:var(--capsule-top);height:var(--capsule-height);left:var(--capsule-start);right:var(--capsule-right);background:rgb(22 22 26 / .9);border:1px solid var(--line);border-radius:999px;visibility:hidden;transition:left 560ms var(--ease)}
.capsule-ready .header-surface{visibility:visible}.hdr.scrolled .header-surface,.menu-open .header-surface{left:var(--capsule-end)}
.hdr.capsule-ready .nav{background:transparent;border-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.hdr.scrolled .motion-toggle{background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}
/* the open menu is fully opaque: at 96% the page's white display type still read through it on phones */
.overlay-menu{background:var(--bg);-webkit-backdrop-filter:none;backdrop-filter:none;transition:clip-path .48s var(--ease),visibility 0s .48s}.menu-open .overlay-menu{transition:clip-path .48s var(--ease),visibility 0s}
body.menu-open{overflow:hidden}
.contact-mechanism{width:100%;max-width:1100px}.contact .lead-in{color:var(--mute);max-width:560px;margin-bottom:22px;font-size:16px}.lead-in b{color:var(--fg);font-weight:500}
.contact-meta{display:flex;flex-direction:column;align-items:center;gap:4px;text-align:center;border-top:1px solid var(--line);padding-top:22px;margin-top:6vh;color:var(--mute);font-size:14px}.contact-meta span:first-child{color:var(--text)}.contact-meta b{font-weight:400}.contact-meta a{color:var(--fg)}
.copy-status{min-height:24px;margin-top:12px;font-size:13px;color:var(--mute)}.btn.copied{border-color:#b5ebe4;color:#b5ebe4}.email-fallback{margin-top:12px;font-size:14px;color:var(--mute)}
.copy-label{display:inline-flex;align-items:center;justify-content:space-between;gap:14px;flex:1}
.contact-context{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:18px;font-size:13px;color:var(--mute)}.contact-context button{width:44px;height:44px;border:1px solid var(--line);border-radius:50%;font-size:22px}.contact-context b{color:var(--fg)}
.contact [hidden]{display:none!important}
.conversion{padding:var(--sp-s) var(--pad) 0}.editorial-conversion{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;border-top:1px solid #f5f2ec33;border-bottom:1px solid #f5f2ec33;padding:20px 2px;margin-top:8px;max-width:980px;transition:border-color .3s}
.editorial-conversion .ctx{font:500 12px/1.6 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--soft);display:block;margin-bottom:6px}.editorial-conversion .ph{font:700 clamp(24px,3.2vw,48px)/1.08 var(--display);letter-spacing:-.04em;color:var(--fg)}
.editorial-conversion .ar{font:300 clamp(28px,3vw,44px)/1 var(--body);color:var(--fg);transition:transform .45s var(--ease)}@media (hover:hover){.editorial-conversion:hover{border-color:#f5f2ec88}}@media (hover:hover){.editorial-conversion:hover .ar{transform:translate(2px,-2px)}}
@media (hover:hover){.editorial-conversion:hover .ar-x{transform:translateX(2px)}}.editorial-conversion:active .ph{color:var(--gold)}
.case-context{font-size:16px;color:var(--mute);margin-bottom:36px;max-width:800px}.case-context .inline-link{min-height:44px;display:inline-flex;align-items:center;gap:8px}
@media(max-width:860px){.menu-btn{width:44px;height:44px;flex-shrink:0}.menu-btn span{left:13px;right:13px}.menu-btn span:first-child{top:18px}.menu-btn span:last-child{top:24px}.menu-open .menu-btn span:first-child,.menu-open .menu-btn span:last-child{top:21px}.hdr.capsule-ready .menu-btn{border-color:transparent;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.editorial-conversion{display:inline-flex;align-items:center;border:1px solid var(--fg);border-radius:999px;background:var(--fg);padding:16px 26px;min-height:56px;gap:22px;max-width:100%}.editorial-conversion .ctx{display:none}.editorial-conversion .ph{font:500 15px/1.4 var(--body);letter-spacing:0;color:var(--bg)}.editorial-conversion .ar{font:400 20px/1 var(--body);color:var(--bg)}}
@media(max-width:560px){.contact-mechanism .actions{flex-direction:column;align-items:stretch}.contact-mechanism .btn{justify-content:space-between}}
/* contact: the enquiry form. Field and chip styling follow the writing search and the work filters. */
.enquiry{display:grid;gap:18px;max-width:760px;padding:26px;margin-bottom:6px}
.enquiry [hidden]{display:none}
.enq-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}
.enq-field{display:grid;gap:8px}
.enq-field>span,.enq-type legend{font-family:var(--mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--soft)}
.enq-field :is(input,select,textarea){width:100%;min-height:48px;padding:12px 14px;border-radius:var(--r-sm);border:1px solid var(--line);background:#0d0d10cc;color:var(--fg);font:400 16px/1.45 var(--body);transition:border-color .25s,box-shadow .25s}
.enq-field textarea{resize:vertical;min-height:132px}
.enq-field select{appearance:none;-webkit-appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--mute) 50%),linear-gradient(135deg,var(--mute) 50%,transparent 50%);background-position:calc(100% - 20px) 21px,calc(100% - 15px) 21px;background-size:5px 5px;background-repeat:no-repeat;padding-right:40px}
.enq-field select option{background:#16161a;color:var(--fg)}
.enq-field :is(input,select,textarea):focus{outline:0;border-color:#ffc86199;box-shadow:0 0 0 4px #ffc8611a}
.enquiry:has(input[name="type"]:checked:not([value="project"])) [data-project-only]{display:none}
.enq-type{border:0;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:8px}
.enq-type legend{margin-bottom:10px;padding:0;width:100%}
.enq-type label{position:relative;cursor:pointer}
.enq-type input{position:absolute;opacity:0;width:1px;height:1px}
.enq-type span{display:inline-flex;align-items:center;min-height:42px;padding:10px 16px;border-radius:999px;border:1px solid var(--line);background:#16161acc;color:var(--text);font-size:15px;font-weight:500;transition:background .15s ease-out,color .15s ease-out}
.enq-type input:checked+span{background:var(--fg);color:var(--bg);border-color:var(--fg)}
.enq-type input:focus-visible+span{outline:2px solid var(--cyan);outline-offset:3px}
@media (hover:hover){.enq-type label:hover input:not(:checked)+span{background:#ffffff1a;color:var(--fg)}}
.enq-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.enquiry .actions{margin:0;align-items:center;gap:0 18px}
.enq-status{font-size:14px;color:var(--mute)}.enq-status.is-sent{color:#b5ebe4}.enq-status.is-error{color:var(--gold)}
.enq-alt{margin-top:14px;font-size:15px;color:var(--mute);line-height:1.9}
.enq-alt button.inline-link{background:none;border:0;padding:0;font:inherit;color:var(--fg);cursor:pointer;text-decoration:underline;text-decoration-color:#f5f2ec55;text-underline-offset:4px}
.enq-alt button.copied{color:#b5ebe4}.enq-alt button.inline-link .copy-label{text-decoration:inherit;text-decoration-line:underline;text-decoration-color:#f5f2ec55;text-underline-offset:4px}
@media(max-width:640px){.enq-row{grid-template-columns:minmax(0,1fr)}.enquiry{padding:20px}.enq-status:not(:empty){padding-top:12px}}

@media(prefers-reduced-motion:reduce){.header-surface,.overlay-menu{transition:none!important}}
@media(max-width:860px){.hdr.capsule-ready.scrolled .motion-toggle,.menu-open .hdr.capsule-ready .motion-toggle{border-color:transparent;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}}
/* homepage greeting caption, positioned per frame above the forming name */
.intro-cap{position:fixed;left:0;top:0;z-index:3;pointer-events:none;opacity:0;font-size:clamp(14px,calc(1.25vw + 4px),20px);font-weight:500;line-height:1;text-transform:uppercase;color:#cdd3e0;white-space:nowrap;will-change:transform,opacity,filter}
/* Without the particle field (no WebGL, or enhancements unavailable) the heroes keep their composition: the homepage
   shows the name the particles would spell, in the chrome display face, and inner heroes get a printed halftone glow in
   their open space, in the page accent. Hidden whenever the field runs. */
.hero-name{display:none}
.no-field .hero-name,.portfolio-fallback .hero-name{display:block;align-self:center;margin:auto 0;text-align:center;text-transform:uppercase;font-size:clamp(36px,10.4vw,190px);line-height:.86;letter-spacing:-.045em}
.no-field .phero>div:nth-of-type(2),.portfolio-fallback .phero>div:nth-of-type(2){align-self:stretch;min-height:min(62vh,580px);background:radial-gradient(circle,var(--a,#9aa7ff) 0 1.3px,transparent 1.9px) 0 0/11px 11px;-webkit-mask:radial-gradient(closest-side,#000 20%,transparent 100%);mask:radial-gradient(closest-side,#000 20%,transparent 100%);opacity:.62;pointer-events:none}
@media(max-width:860px){
 .no-field .phero>div:nth-of-type(2),.portfolio-fallback .phero>div:nth-of-type(2){display:none}
 .no-field .phero,.portfolio-fallback .phero{position:relative}
 .no-field .phero::before,.portfolio-fallback .phero::before{content:"";position:absolute;left:0;right:0;top:var(--hdr);height:calc(47vh - var(--hdr) - 72px);background:radial-gradient(circle,var(--a,#9aa7ff) 0 1.1px,transparent 1.7px) 0 0/10px 10px;-webkit-mask:radial-gradient(closest-side,#000 15%,transparent 100%);mask:radial-gradient(closest-side,#000 15%,transparent 100%);opacity:.5;pointer-events:none}
}
/* Interface arrows (lib/icons.ts): one stroke set instead of platform-dependent arrow characters. 1em square, sitting on
   the text like the glyph it replaces, coloured by the surrounding text. */
.ico{display:inline-block;width:1em;height:1em;vertical-align:-.14em;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;overflow:visible;flex:none}
.editorial-conversion .ar .ico{stroke-width:1.15}
.wcard .meta i .ico{width:17px;height:17px}
/* First-screen content does not wait for scripts. Hero reveals play the same rise as the scripted reveal, but as a CSS
   animation from the first paint, so the largest text paints with the page (LCP) instead of after the particle field
   boots. Paused or reduced motion shows it at rest. */
@keyframes aj-reveal{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:none}}
:is(.hero,.phero) [data-reveal],.portfolio-enhanced :is(.hero,.phero) [data-reveal]{opacity:1;transform:none;transition:none;animation:aj-reveal 1.1s var(--ease) backwards}
:is(.hero,.phero) [data-reveal]:nth-child(2){animation-delay:.08s}
:is(.hero,.phero) [data-reveal]:nth-child(3){animation-delay:.16s}
:is(.hero,.phero) [data-reveal]:nth-child(n+4){animation-delay:.24s}
.still :is(.hero,.phero) [data-reveal]{animation:none!important}
@media(prefers-reduced-motion:reduce){:is(.hero,.phero) [data-reveal]{animation:none}}
/* Reserve the portrait's final frame before its canvas mounts, so the copy beside it never shifts (CLS). The heights
   mirror portrait-resolve.js: viewport minus header and 140px on desktop (capped at 600px wide, 3:4), 38% of the
   viewport on phones (capped at 420px wide). */
.ab-portrait{min-height:min(calc(100svh - var(--hdr) - 140px),800px)}
@media(max-width:859px){.ab-portrait{min-height:min(38svh,560px)}}
/* Same formula as fitTitles (lib/fit.ts), from the first paint: fit x 1vw (x 2.3 on phones), or the size at which the
   longest word fills 96% of the parent's width, whichever is smaller, clamped to the title's min and max. */
:has(>[data-fit][style*="--fit:"]){container-type:inline-size}
html body [data-fit][style*="--fit:"]{font-size:clamp(var(--fit-min),min(calc(var(--fit)*1vw),calc(96cqw/var(--fit-r))),var(--fit-max))}
@media(max-width:859px){html body [data-fit][style*="--fit:"]{font-size:clamp(var(--fit-min),min(calc(var(--fit)*2.3vw),calc(96cqw/var(--fit-r))),var(--fit-max))}}
/* Hero titles rise word by word in CSS from the first paint (same 1.1s ease and 45ms stagger as the scripted
   reveal); titles further down keep the scripted on-scroll reveal. Without scripts, words settle after 3s. */
/* fill backwards only: once risen, the words return to plain rest styles, so no layer stays composited and gradient
   titles (background-clip:text) keep painting through them */
:is(.hero,.phero) .split .wd>span{animation:aj-print .5s cubic-bezier(.3,.65,.25,1) both;animation-delay:calc(var(--i)*30ms)}
@media(prefers-reduced-motion:reduce){.split .wd>span{animation:none!important;-webkit-mask:none!important;mask:none!important}}
/* ---------- page transitions (public/assets/transitions.js, lib/arrival-script.ts) ---------- */
@view-transition{navigation:auto}
::view-transition-group(root),::view-transition-old(root),::view-transition-new(root){animation-duration:.18s}
/* the header is the same on both pages: it holds still through every transition */
.hdr{view-transition-name:aj-header}
::view-transition-group(aj-header),::view-transition-new(aj-header){animation:none}
::view-transition-old(aj-header){display:none}
/* Dither Particle: the ink erases the page; while it does, the field draws above the page and the header stays on top */
#aj-ink,#aj-cover{position:fixed;inset:0;width:100vw;height:100vh;height:100lvh;pointer-events:none}
#aj-ink{z-index:175}
#aj-cover{z-index:177;display:block}
html.dp-on #field{z-index:176}
html.dp-on .hdr,html.nav-dither .hdr{z-index:180}
/* A work card's picture steps away under its particle copy before the dither erases the page */
.wcard.dp-dissolve .img img{opacity:0;transition:opacity .14s linear}
@media(prefers-reduced-motion:reduce){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}}
/* Motion switch: MOTION ON / MOTION OFF in the site's mono label voice, the same words as the phone menu. It sits inside
   the header capsule at its leading end (interactions.js measures the capsule from it). The state word reserves the
   width of "OFF", so the switch never changes size. */
.motion-toggle{width:auto;border-radius:999px;display:inline-flex;align-items:center;gap:7px;padding:0 10px 0 15px;font:500 12px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--mute)}
.motion-toggle b{font-weight:500;color:var(--fg);display:inline-block;min-width:3.2ch;text-align:left}
.motion-toggle[aria-checked=false] b{color:var(--mute)}
.motion-toggle+.nav{margin-left:-16px}
.hdr.capsule-ready .motion-toggle{width:auto;height:42px;border-color:transparent;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}
@media (hover:hover){.hdr.capsule-ready .motion-toggle:hover{background:#ffffff1a;color:var(--fg)}}
@media(max-width:860px){.motion-toggle,.hdr.capsule-ready .motion-toggle{height:44px;padding:0 12px}}
.menu-motion{align-self:flex-start;min-height:44px;padding:0;margin-top:18px;color:var(--mute);font-size:12px;letter-spacing:.12em;text-transform:uppercase}
.menu-motion b{color:var(--fg);font-weight:500}
@media(min-width:861px){.menu-motion{display:none}}
/* The header capsule is real frosted glass, and above it a progressive blur dissolves content before it reaches the
   top edge: strong at the very top, nothing at its lower edge. Only once the hero has scrolled away. */
.header-surface{background:rgb(16 16 19 / .93);-webkit-backdrop-filter:blur(26px) saturate(1.2);backdrop-filter:blur(26px) saturate(1.2)}
.hdr-veil{position:fixed;top:0;left:0;right:0;height:calc(var(--hdr) + 40px);z-index:59;pointer-events:none;opacity:0;transition:opacity .45s var(--ease);background:linear-gradient(#050506f2,#050506cc 45%,#05050600);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);-webkit-mask:linear-gradient(#000 55%,transparent);mask:linear-gradient(#000 55%,transparent)}
.hdr-veil.on,body:has(.hdr.scrolled) .hdr-veil{opacity:1}
@media(prefers-reduced-transparency:reduce){.hdr-veil{-webkit-backdrop-filter:none;backdrop-filter:none;background:linear-gradient(#050506,#050506e6 50%,#05050600)}.header-surface{background:rgb(18 18 22);-webkit-backdrop-filter:none;backdrop-filter:none}}
/* short screens (landscape phones): the hero grows rather than squeezing the name onto its tagline */
@media(max-height:520px){.hero{min-height:max(100svh,560px)}}
/* The cursor inverts whatever is beneath it, pixel by pixel: white on the dark page, black over white buttons and white
   type, and split cleanly when it straddles an edge. Nothing is detected or switched, so it can never be wrong or late,
   and the change follows the pointer continuously. */
.cur,.cur-ring{mix-blend-mode:difference}
.cur-ring{border-color:#ffffffa6}
/* Over links and buttons the ring steps aside (they have their own hover state, and a ring drawn across their text read
   as clutter) and the dot grows a touch to show the target is live. */
.cur{transition:opacity .3s,width .25s var(--ease),height .25s var(--ease),margin .25s var(--ease)}
.cur.link{width:10px;height:10px;margin:-5px 0 0 -5px}
.cur-ring.link{width:36px;height:36px;margin:-18px 0 0 -18px;border-color:transparent}
html.has-cur .cur-ring.link{opacity:0}
/* the label pill (View, Email, Next) sits on photographs: no difference blend, so it is always a light pill with dark text */
.cur-ring.label{mix-blend-mode:normal;width:auto;min-width:64px;height:26px;padding:0 12px;background:#f5f2ec;border-color:#f5f2ec;color:#0b0b0d;font-size:10.5px;letter-spacing:.12em;box-shadow:0 6px 18px -6px #000c}
/* Headlines wrap into balanced lines (no lonely last word); body copy avoids single-word last lines. */
h1,h2,h3,.display,.lede,.csx-lead{text-wrap:balance}
p,li,dd,figcaption{text-wrap:pretty}
/* Pressed: buttons, cards and chips sink slightly under the finger or pointer and spring back, with a fast response
   (90ms) on press and the shared ease on release. */
.btn,.nav a,.csx-chapters a,.filters button,.next-links a,.wcard,.csx-rcard,.motion-toggle,.menu-btn,.csx-tabs button{transition-property:background,color,border-color,opacity,filter;-webkit-tap-highlight-color:transparent}
.btn:active,.nav a:active,.csx-chapters a:active,.filters button:active,.next-links a:active,.motion-toggle:active,.menu-btn:active,.csx-tabs button:active{filter:brightness(.88);transition-duration:60ms}
.wcard:active,.csx-rcard:active{filter:brightness(.92);transition-duration:60ms}
@media(prefers-reduced-motion:reduce){.btn:active,.nav a:active,.wcard:active,.csx-rcard:active,.csx-chapters a:active,.filters button:active,.next-links a:active,.motion-toggle:active,.menu-btn:active,.csx-tabs button:active{transform:none}}
@media(max-width:400px){
 .svc-row{padding:22px}
 .svc-row h2{font-size:clamp(20px,6.6vw,30px)}
 .wcard h3{font-size:clamp(20px,6.9vw,28px)}
 .art-head h1{font-size:clamp(26px,10.4vw,36px)}
}

/* Display titles with authored lines may borrow up to 6% past their column (never nearer than 8px to the page edge),
   so a line that misses its box by a few pixels stays whole instead of stranding a word. */
.display:is(h1,h2):has(br){margin-right:calc(-1*min(6%,max(0px,var(--pad) - 8px)))}
/* "Every project gets / its own world.": the title takes the width its authored lines need (the paragraph beside it
   wraps below when they do not fit together, as it already does on narrower screens). On phones the line cannot fit,
   so the break is dropped and the title wraps as one balanced block. */
.work-intro h2{max-width:none;width:fit-content}
@media(max-width:860px){.work-intro h2 br{display:none}}
/* Safari (WebKit) paints background-clip:text only through inline text; words wrapped in inline-blocks inside a
   gradient run were left invisible on iPhone ("its own world.", "and growth.", "The whole website."). Inside a
   gradient run the word wrappers stay inline; the print-in mask still applies to each word. */
.hotgrad .wd,.hotgrad .wd>span{display:inline}
/* gradient words in a printed headline arrive white like the rest of it, then their colour sweeps in from the left once
   the words have printed (2026-10-15, on trial). A white top layer with a soft edge slides off to the right; at full size
   it ignores the gradient's own pan. White from the first frame, so nothing flashes colour first. Without JavaScript
   the layout's noscript style shows the colour. */
@property --wipe{syntax:'<percentage>';inherits:false;initial-value:140%}
.split .hotgrad{background-image:linear-gradient(90deg,#f5f2ec00 calc(var(--wipe) - 40%),var(--fg) var(--wipe)),linear-gradient(90deg,var(--hot),var(--orange),var(--gold),var(--violet),var(--hot));background-size:100% 100%,200% 100%;transition:--wipe 1.6s cubic-bezier(.45,0,.25,1) .45s}
.split:not(.in) .hotgrad{--wipe:0%;transition:none}
.still .split .hotgrad,.portfolio-fallback .split .hotgrad{--wipe:140%;transition:none}
@media (prefers-reduced-motion:reduce){.split .hotgrad{transition:none}}
@media (prefers-reduced-motion:reduce){.split .hotgrad{transition:none}}
/* A word's print mask ends fully open; once its reveal has played the mask is dropped, so the finished title never
   depends on mask painting (some Chromium releases do not paint background-clip:text through a masked word). */
.split .wd>span.printed{-webkit-mask:none!important;mask:none!important;animation:none!important}
/* ---------- composition decisions, 2026-10-06 (compared in design/visual-lab-2026-10-06) ---------- */
/* a deliberate non-breaking phrase in a display title; the fit routines (site.js, lib/fit.ts) measure it as one unit */
.nw{white-space:nowrap}
/* very large screens: the contact question keeps its three-line shape (Have a website / that needs / to win work?) */
@media(min-width:1600px){.contact h2{max-width:1120px}}
/* Work: wherever the particle word WORK is drawn it is the page's label, so the kicker beneath would repeat it. Without
   the field (no WebGL, or the enhancement failed) the kicker stays. */
html:not(.no-field):not(.portfolio-fallback) .phero[data-scene=work] .kicker{display:none}
/* Homepage chapters: the lead figure carries the weight; its qualification is one quiet line beneath, not a paragraph
   competing with it. Full sourcing stays in each case study. */
.ch-copy .stats{align-items:flex-end}
.ch-copy .stats .stat:first-child b{font-size:clamp(44px,4.4vw,76px)}
.ch-copy .qual{font:500 12px/1.5 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--soft);margin:12px 0 26px;max-width:520px;display:flex;gap:10px;align-items:baseline}
.ch-copy .qual::before{content:"";flex:none;width:14px;height:1px;background:currentColor;opacity:.6;transform:translateY(-3px)}

/* Surface depth (2026-10-15). Three tiers, applied by role rather than by component:
   flat     labels and lists (chapter tags, service tags, timeline, logo row): unchanged, no depth
   resting  static surfaces (info cards, service rows): a lit top edge, a shaded bottom edge and a
            tight contact shadow, so they read as thin slabs on the page; nothing moves or changes on hover
   raised   things you press (link cards, work cards, buttons, filters): the resting edge plus one clear state change
   On a near-black page a soft drop shadow barely registers, so the edges carry the depth. Neutral black only. */
:root{
 --edge:inset 0 1px 0 #ffffff24,inset 0 -1px 0 #00000099;
 --contact:0 1px 2px #000000b3,0 10px 22px -14px #000000e6;
 --lifted:0 2px 4px #00000099,0 22px 40px -22px #000000f2;
}
.glass,.svc-row{box-shadow:var(--edge),var(--contact)}
.btn{box-shadow:var(--edge),var(--contact)}
.btn.solid{box-shadow:inset 0 1px 0 #ffffff80,inset 0 -1px 0 #00000033,var(--contact)}
.filters button{box-shadow:var(--edge),var(--contact)}
.filters button[aria-pressed=true]{box-shadow:inset 0 1px 0 #ffffff80,inset 0 -1px 0 #00000033,var(--contact)}
.wcard{box-shadow:var(--edge),var(--contact)}
/* raised: the hover lift is smaller than before, and the shadow grows with it, so it reads as one physical movement */
.next-links a,.wcard{transition:border-color .15s ease-out,box-shadow .2s ease-out,opacity .5s}
@media (hover:hover){
 .next-links a:hover{border-color:#ffffff38;box-shadow:var(--edge),var(--lifted)}
 .wcard:hover{box-shadow:var(--edge),var(--lifted)}
 /* the coloured glow under a hovered work card is retired: the lift, the image and the arrow already answer the hover */
 .wcard:hover .glow{opacity:0}
}
.wcard:focus-visible,.next-links a:focus-visible{box-shadow:var(--edge),var(--lifted)}
/* pressed: the surface drops its contact shadow and sits on the page */
.btn:active,.next-links a:active,.filters button:active{box-shadow:var(--edge)}
.btn,.filters button{transition-property:background,color,border-color,opacity,box-shadow,filter;transition-duration:.15s;transition-timing-function:ease-out}
/* About: editorial layout (2026-10-16) */
.ab-statement{padding:var(--sp-l) var(--pad) var(--sp-m)}
.ab-statement h2{font-size:clamp(38px,4.4vw,78px);max-width:1000px}
.ab-work{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:4vw;align-items:start;padding:0 var(--pad)}
.ab-work .kicker{margin-bottom:22px}
.ab-work p{font-size:18px;line-height:1.6;color:var(--text);max-width:600px}
.ab-work p+p{margin-top:16px}
.ab-work figure{margin:6px 0 0;position:sticky;top:calc(var(--hdr) + 24px)}
.ab-work .frame{border-radius:var(--r-md);overflow:hidden;border:1px solid var(--line);box-shadow:var(--lifted);background:#101014}
.ab-work .frame img{display:block;width:100%;height:auto}
.ab-work figcaption{margin-top:14px;font-size:14px;line-height:1.5;color:var(--soft)}
.ab-work figcaption a{color:var(--fg)}
.ab-facts{margin-top:32px;padding-top:8px;border-top:1px solid var(--line);max-width:600px}
.ab-facts p{display:grid;grid-template-columns:96px minmax(0,1fr);gap:20px;align-items:baseline;margin:0;padding:14px 0;border-bottom:1px solid var(--line);font-size:15px;line-height:1.55;color:var(--mute)}
.ab-work .ab-facts p+p{margin-top:0}
.ab-skills{padding:0 var(--pad) var(--sp-m)}.ab-skills .ab-facts{max-width:980px;margin-top:0}.ab-skills .ab-facts p{grid-template-columns:180px minmax(0,1fr)}
.ab-facts span{font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--soft)}
.ab-place{gap:8px 26px}
.ab-place span{display:grid;grid-template-columns:4px auto;column-gap:10px;align-items:baseline}
.ab-place span::before{content:"";width:4px;height:4px;border-radius:50%;background:var(--soft);opacity:.7;transform:translateY(-.3em)}
.ab-copy .ab-studio{font-family:"Poiret One",sans-serif;font-weight:400;font-size:1.12em;letter-spacing:-.01em;white-space:nowrap;color:#e3b85a;text-decoration-color:#e3b85a73}
.ab-copy .ab-studio:hover{text-decoration-color:#e3b85a}
.timeline p.tl-date{margin-top:0;font-size:12px;color:var(--soft);max-width:none}
.timeline p.tl-logo{margin-top:0;max-width:none}
main:has(.ab-work) .contact{padding-bottom:clamp(24px,4vh,40px)}
.ab-fit{list-style:none;margin:0 var(--pad) var(--sp-m);padding:0}
.ab-fit li{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:4vw;padding:clamp(24px,3.6vh,36px) 0;border-top:1px solid var(--line);align-items:baseline}
.ab-fit li:last-child{border-bottom:1px solid var(--line)}
.ab-fit h3{font-family:var(--display);font-weight:700;font-size:clamp(24px,2.3vw,36px);letter-spacing:-.025em;line-height:1.08;color:var(--fg)}
.ab-fit p{font-size:16px;line-height:1.6;color:var(--mute);max-width:600px}
@media (max-width:859px){
.ab-statement{padding-top:var(--sp-m)}
.ab-statement h2{font-size:clamp(28px,9.1vw,43px)}
.ab-work{grid-template-columns:minmax(0,1fr);gap:var(--sp-s)}
.ab-work figure{position:static}
.ab-facts p,.ab-skills .ab-facts p{grid-template-columns:minmax(0,1fr);gap:4px}
.ab-place{flex-direction:column;gap:6px}
.ab-fit li{grid-template-columns:minmax(0,1fr);gap:10px}
}

/* Agency proof follows the introduction, before delivery details. */
.agency-experience-head{padding-top:var(--sp-s)}
.agency-experience{padding-bottom:var(--sp-m)}
