:root{
  --night:#05070f; --night2:#0a0e1f; --dusk:#16112f; --dusk2:#241a48; --deep:#33235e;
  --land:#0b0f1c; --land2:#121829; --panel:#191340;
  --violet:#9d70c8; --violet-deep:#784a9d; --lav:#b8a8dd; --amber:#fdbb25;
  --text:#f4f2ff; --text2:#aca5c0; --text3:#847d99;
  --rule:rgba(184,168,221,.20); --rule-soft:rgba(184,168,221,.11);
  --display:"Bricolage Grotesque",ui-sans-serif,system-ui,sans-serif;
  --body:"Gabarito",ui-sans-serif,system-ui,-apple-system,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --gut:clamp(1.25rem,5vw,4.5rem);
  --max:80rem;
  --mk-shape:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 24' preserveAspectRatio='none'%3E%3Cpath d='M2 12.4 C1.6 6 5.5 3 13 2.8 C39 0.9 62 3.9 85 2.4 C93.5 1.9 98.7 5 98.4 12 C98.9 18.8 93.5 21.4 86 21.5 C59 23.6 37 19.8 13.5 21.6 C6 22 1.7 18.8 2 12.4 Z' fill='%23000'/%3E%3C/svg%3E");
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; scroll-behavior:smooth; background:var(--night)}
body{margin:0; background:transparent; color:var(--text);
  font-family:var(--body); font-size:clamp(16px,1rem + .35vw,19px);
  line-height:1.65; text-rendering:optimizeLegibility;
  font-feature-settings:"kern" 1,"liga" 1; -webkit-font-smoothing:antialiased;
  font-weight:350; overflow-x:hidden}
h1,h2,h3,.h1-visual{font-family:var(--display); font-weight:800; line-height:1.03; letter-spacing:-.024em; hyphens:none; margin:0}
p{margin:0}
a{color:inherit}

:focus{outline:none}
:focus-visible{outline:2px solid var(--amber); outline-offset:4px; border-radius:2px;
  box-shadow:0 0 0 7px rgba(253,187,37,.20), 0 0 22px rgba(253,187,37,.32)}
.skip{position:absolute; left:var(--gut); top:0; transform:translateY(-140%);
  background:var(--violet-deep); color:#fff; padding:.7rem 1.1rem;
  font:600 .85rem/1 var(--body); z-index:120; transition:transform .18s ease}
.skip:focus-visible{transform:translateY(.75rem)}
.vh{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; border:0}

/* ================= THE SKY =================
   A real night sky rather than a field of dots: a twilight gradient,
   a Milky Way band on the diagonal, three parallax star layers,
   Vesper itself as a bright object with diffraction spikes, and a
   headland silhouette so the sky sits over somewhere real. */
/* Sky structure reverted to the arrangement that demonstrably rendered.
   Only two things were added back on top of it: the Vesper star and the
   headland. Everything is a child of this one fixed layer. */
.sky-stage{position:fixed; inset:0; z-index:-2; pointer-events:none; overflow:hidden;
  background:linear-gradient(180deg, #04060d 0%, var(--night) 30%, var(--night2) 62%, var(--dusk) 100%)}
.stars{position:absolute; inset:-20% 0 -20% 0; display:block; will-change:transform}

/* the galactic band, as one more star layer rather than a new mechanism */
.milky{position:absolute; inset:-20% -10%; display:block;
  background:
    radial-gradient(58% 15% at 50% 50%, rgba(196,186,232,.15) 0%, rgba(196,186,232,.06) 42%, rgba(196,186,232,0) 74%),
    radial-gradient(40% 9% at 38% 47%, rgba(226,214,255,.18) 0%, rgba(226,214,255,0) 76%);
  transform:rotate(-24deg) scale(1.4); filter:blur(12px)}
.stars.s1{background-image:
    radial-gradient(1px 1px at 24px 38px,rgba(244,242,255,.85),transparent),
    radial-gradient(1px 1px at 142px 96px,rgba(244,242,255,.5),transparent),
    radial-gradient(1px 1px at 78px 172px,rgba(184,168,221,.65),transparent),
    radial-gradient(1px 1px at 196px 22px,rgba(244,242,255,.42),transparent),
    radial-gradient(1px 1px at 112px 214px,rgba(244,242,255,.6),transparent),
    radial-gradient(1px 1px at 232px 148px,rgba(184,168,221,.46),transparent);
  background-size:250px 230px; opacity:0; animation:fadein 2s .2s ease both}
.stars.s2{background-image:
    radial-gradient(1.5px 1.5px at 60px 120px,rgba(255,252,240,.95),transparent),
    radial-gradient(1.3px 1.3px at 320px 60px,rgba(184,168,221,.75),transparent),
    radial-gradient(1.5px 1.5px at 210px 300px,rgba(255,252,240,.8),transparent),
    radial-gradient(1.2px 1.2px at 400px 240px,rgba(244,242,255,.58),transparent);
  background-size:440px 360px; opacity:0; animation:fadein 2.2s .5s ease both, tw 9s 2.7s ease-in-out infinite alternate}
.stars.s3{background-image:
    radial-gradient(2.2px 2.2px at 140px 210px,rgba(255,250,235,1),transparent),
    radial-gradient(2px 2px at 520px 90px,rgba(200,220,255,.9),transparent),
    radial-gradient(2px 2px at 300px 430px,rgba(255,252,240,.95),transparent);
  background-size:660px 540px; opacity:0; animation:fadein 2.4s .8s ease both}
@keyframes tw{from{opacity:.55}to{opacity:1}}
@keyframes fadein{from{opacity:0}to{opacity:1}}

/* Vesper, the evening star: study 01 blended with 02. Venus shows no
   diffraction spikes to the naked eye, so the bloom does the work and the
   rays are short, heavily blurred, and painted UNDER the halos where they
   read as light bleeding rather than as a camera artifact. */
.vesper{position:absolute; right:12%; top:23%; width:clamp(96px,13vw,190px);
  height:clamp(96px,13vw,190px); transform:translate(50%,-50%);
  will-change:transform, opacity; opacity:0;
  animation:ignite 2.2s .6s cubic-bezier(.16,1,.3,1) both}
.vesper svg{display:block; width:100%; height:100%; overflow:visible}
.v-halo{animation:breathe 11s 2.6s ease-in-out infinite}
.v-spikes{animation:scint 7.3s 2.6s ease-in-out infinite}
@keyframes ignite{from{opacity:0} to{opacity:1}}
@keyframes breathe{0%,100%{opacity:.82} 50%{opacity:1}}
@keyframes scint{0%,100%{opacity:.72} 37%{opacity:1} 61%{opacity:.8}}

/* One slow meteor. `rotate` is applied BEFORE `translateX` so the streak
   travels along its own axis: translating x and y separately made it slide
   sideways while pointing somewhere else. */
.meteor{position:absolute; top:9%; left:-14%; width:150px; height:1.5px;
  transform-origin:0 50%;
  background:linear-gradient(90deg, rgba(255,252,240,0) 0%, rgba(255,252,240,.8) 90%, #fff 100%);
  border-radius:2px; opacity:0;
  transform:rotate(21deg) translateX(0);
  animation:shoot 26s 7s linear infinite}
@keyframes shoot{
  0%{opacity:0; transform:rotate(21deg) translateX(0)}
  1%{opacity:.9}
  5.5%{opacity:0; transform:rotate(21deg) translateX(135vw)}
  100%{opacity:0; transform:rotate(21deg) translateX(135vw)}
}

/* The Coast Range, pinned to the bottom of the viewport. Scrolling lifts
   it while the star sinks, so the page reads as descending below the
   horizon at dusk. */
/* hangs 90px below the fold so lifting it on scroll never exposes a gap */
.range{position:absolute; inset:auto 0 -70px 0; height:auto;
  pointer-events:none; line-height:0; will-change:transform}
.range svg{display:block; width:100%; height:auto; min-height:170px}

.wrap{max-width:var(--max); margin-inline:auto; padding-inline:var(--gut); position:relative; z-index:2}

/* ---------- reveal, with no way to strand content ---------- */
@keyframes rise{from{opacity:0; transform:translateY(28px)} to{opacity:1; transform:none}}
.ld{animation:rise .9s cubic-bezier(.16,1,.3,1) both}
.ld.d1{animation-delay:.55s} .ld.d2{animation-delay:.7s} .ld.d3{animation-delay:.85s}
.ld.d0{animation-delay:.4s}
.rv{animation:rise .8s cubic-bezier(.16,1,.3,1) both}
@supports (animation-timeline: view()){
  .rv{animation-timeline:view(); animation-range:entry 0% entry 60%}
}

/* ---------- header ---------- */
.top{position:relative; z-index:20}
.top .wrap{display:flex; flex-wrap:wrap; gap:1rem 2rem; align-items:center; padding-block:1.4rem}
.mark{display:inline-flex; align-items:center; text-decoration:none; line-height:0}
.mark svg{display:block; height:clamp(30px,4.2vw,40px); width:auto}
nav{margin-left:auto; display:flex; flex-wrap:wrap; gap:.4rem 1.6rem}
nav a{font-size:.92rem; font-weight:500; color:var(--text2); text-decoration:none;
  padding:.2rem 0; border-bottom:1px solid transparent; transition:.16s ease}
nav a:hover{color:var(--text); border-bottom-color:var(--lav)}

/* ---------- hero ---------- */
/* The ridge is pinned to the bottom of the VIEWPORT, so the hero has to
   fill the viewport or the content section's solid background covers it. */
.hero{position:relative; display:flex; align-items:center;
  min-height:100vh; min-height:100svh;
  padding-block:clamp(3rem,10vw,6rem) clamp(11rem,26vh,20rem)}
.hero > .wrap{width:100%}
.eyebrow{font:600 .74rem/1.4 var(--body); text-transform:uppercase; letter-spacing:.18em;
  color:var(--lav); margin-bottom:clamp(1.5rem,3.5vw,2.4rem); display:flex; align-items:center; gap:.6rem}
.eyebrow::before{content:""; width:.42rem; height:.42rem; background:var(--amber); flex:none;
  clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%)}
h1,.h1-visual{font-size:clamp(2.6rem,9.5vw,7rem); max-width:15ch;
  text-shadow:0 2px 40px rgba(5,7,15,.85)}
.lede{max-width:34ch; margin-top:clamp(1.4rem,3vw,2rem);
  font-size:clamp(1.06rem,1rem + .55vw,1.36rem); line-height:1.5; color:var(--text2)}
.acts{display:flex; flex-wrap:wrap; gap:.85rem; margin-top:clamp(1.8rem,4vw,2.6rem)}
.btn{display:inline-flex; align-items:center; gap:.55rem; font:600 1rem/1 var(--body);
  padding:1rem 1.5rem; text-decoration:none; border:1px solid transparent; transition:.18s ease}
.btn-1{background:var(--violet-deep); color:#fff; box-shadow:0 0 34px rgba(120,74,157,.5)}
.btn-1:hover{background:#8a58b0; box-shadow:0 0 54px rgba(138,88,176,.65); transform:translateY(-2px)}
.btn-2{border-color:var(--rule); color:var(--text); backdrop-filter:blur(3px)}
.btn-2:hover{border-color:var(--lav); background:rgba(184,168,221,.08); transform:translateY(-2px)}

/* rotating object with the marker stroke from steventrotter.com */
.rot{display:grid; justify-items:start}
.rot .w{grid-area:1/1; position:relative; isolation:isolate; white-space:nowrap;
  color:var(--text); opacity:0; animation:cyc 17.5s 1.1s infinite both}
.rot .w::before{content:""; position:absolute; z-index:-1;
  left:-.16em; right:-.18em; top:.16em; bottom:.02em; background:#784a9d;
  -webkit-mask:var(--mk-shape) left center / 100% 100% no-repeat;
          mask:var(--mk-shape) left center / 100% 100% no-repeat;
  transform:rotate(-1.3deg); clip-path:polygon(0 0,0 0,0 100%,0 100%);
  animation:wipe 17.5s 1.1s infinite both}
.rot .w:nth-child(2),.rot .w:nth-child(2)::before{animation-delay:4.6s}
.rot .w:nth-child(3),.rot .w:nth-child(3)::before{animation-delay:8.1s}
.rot .w:nth-child(4),.rot .w:nth-child(4)::before{animation-delay:11.6s}
.rot .w:nth-child(5),.rot .w:nth-child(5)::before{animation-delay:15.1s}
@keyframes cyc{0%{opacity:0; transform:translateY(.18em)} 3%{opacity:1; transform:none}
  18%{opacity:1; transform:none} 21%{opacity:0; transform:translateY(-.14em)} 100%{opacity:0; transform:translateY(-.14em)}}
@keyframes wipe{0%{clip-path:polygon(0 0,0 0,0 100%,0 100%)}
  7%{clip-path:polygon(0 0,106% 0,99% 100%,0 100%)} 18%{clip-path:polygon(0 0,106% 0,99% 100%,0 100%)}
  21%{clip-path:polygon(0 0,0 0,0 100%,0 100%)} 100%{clip-path:polygon(0 0,0 0,0 100%,0 100%)}}

/* ---------- land ---------- */
.land{position:relative; z-index:4; background:var(--land)}
.sec{padding-block:clamp(3.5rem,9vw,7rem)}
.sec + .sec{border-top:1px solid var(--rule-soft)}
.sec-label{font:600 .74rem/1.4 var(--body); text-transform:uppercase; letter-spacing:.16em;
  color:var(--lav); margin-bottom:clamp(1.6rem,4vw,2.4rem); display:flex; align-items:center; gap:.6rem}
.sec-label::before{content:""; width:.38rem; height:.38rem; background:var(--amber); flex:none;
  clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%)}

.spec{background:var(--land2); border-block:1px solid var(--rule-soft); position:relative; z-index:4}
.spec .wrap{display:flex; flex-wrap:wrap; gap:.5rem 2.4rem; padding-block:1rem;
  font:500 .8rem/1.6 var(--body); color:var(--text3)}
.spec b{color:var(--lav); font-weight:600}

.proc .wrap{display:grid; gap:clamp(1.5rem,4vw,3rem); grid-template-columns:1fr}
.proc h2{font-size:clamp(1.9rem,5.5vw,3.2rem)}
.proc ol{list-style:none; margin:0; padding:0; counter-reset:n}
.proc li{counter-increment:n; display:grid; grid-template-columns:2.8rem 1fr; gap:1rem;
  padding-block:1.25rem; border-top:1px solid var(--rule-soft)}
.proc li::before{content:counter(n,decimal-leading-zero); font:600 .76rem/1.9 var(--mono); color:var(--lav)}
.proc li:last-child{border-bottom:1px solid var(--rule-soft)}
.proc h3{font-size:clamp(1.15rem,1.05rem + .5vw,1.4rem); margin-bottom:.35rem}
.proc p{color:var(--text2); font-size:.97rem; font-weight:350; max-width:52ch}

.cards{display:grid; gap:1rem; grid-template-columns:1fr}
.card{border:1px solid var(--rule-soft); background:var(--land2);
  padding:clamp(1.5rem,3vw,2.1rem); transition:.22s ease}
.card:hover{border-color:var(--rule); transform:translateY(-3px)}
.card h3{font-size:clamp(1.4rem,1.2rem + .8vw,1.9rem); margin-bottom:.75rem}
.card p{color:var(--text2); font-size:.98rem; line-height:1.6; font-weight:350}
.aside{margin-top:clamp(2.2rem,4vw,3rem); display:grid; gap:1.1rem; max-width:62ch}
.aside p{color:var(--text2); font-size:.98rem; font-weight:350}

.dl{background:radial-gradient(90% 120% at 80% 0%, rgba(120,74,157,.32) 0%, rgba(120,74,157,0) 60%), var(--panel);
  border-block:1px solid var(--rule)}
.dl h2{font-size:clamp(1.85rem,5.4vw,3.1rem); max-width:22ch}
.dl p{color:var(--text2); max-width:56ch; margin-top:1.3rem}
.dates{list-style:none; margin:clamp(1.9rem,4vw,2.7rem) 0 0; padding:0;
  border-top:1px solid var(--rule); max-width:44rem}
.dates li{display:flex; flex-wrap:wrap; gap:.3rem 1.5rem; justify-content:space-between;
  align-items:baseline; padding-block:1rem; border-bottom:1px solid var(--rule)}
.dates span{color:var(--text2); font-size:.95rem; max-width:34ch}
.dates time{font:700 clamp(1.05rem,1rem + .6vw,1.5rem)/1 var(--display);
  color:var(--lav); letter-spacing:-.022em; font-variant-numeric:tabular-nums}
.dl .btn-1{margin-top:clamp(1.9rem,4vw,2.5rem)}
.fineprint{margin-top:1.5rem; font:400 .82rem/1.55 var(--body); color:var(--text3)}

.work{display:grid; gap:1rem; grid-template-columns:1fr}
.work article{border:1px solid var(--rule-soft); padding:clamp(1.5rem,3vw,2.1rem);
  background:var(--land2); transition:.22s ease}
.work article:hover{border-color:var(--rule); transform:translateY(-3px)}
.work h3{font-size:clamp(1.25rem,1.1rem + .7vw,1.65rem); margin-bottom:.55rem}
.work .kind{font:500 .82rem/1.4 var(--body); color:var(--lav); margin-bottom:.8rem}
.work p{color:var(--text2); font-size:.96rem; font-weight:350}

/* brands strip: wordmarks stand in until real logo files are dropped in */
.brands{margin-top:clamp(2.5rem,5vw,3.5rem); padding-top:clamp(1.8rem,3.5vw,2.4rem);
  border-top:1px solid var(--rule-soft)}
.brands-label{font:600 .74rem/1.4 var(--body); text-transform:uppercase; letter-spacing:.16em;
  color:var(--text3); margin-bottom:1.4rem}
.brands ul{list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap;
  gap:clamp(1.4rem,4vw,3.2rem); align-items:center}
.brands li{font-family:var(--display); font-weight:700; letter-spacing:-.02em;
  font-size:clamp(1.05rem,1rem + .6vw,1.5rem); color:var(--text2); opacity:.72;
  transition:opacity .2s ease}
.brands li:hover{opacity:1}

.about .wrap{display:grid; gap:clamp(1.5rem,4vw,3rem)}
.about h2{font-size:clamp(1.75rem,4.8vw,2.7rem); max-width:18ch}
.about p{max-width:58ch; color:var(--text2); margin-top:1.1rem; font-weight:350}

.close{position:relative; overflow:hidden;
  background:radial-gradient(100% 130% at 50% 132%, rgba(157,112,200,.28) 0%, rgba(157,112,200,0) 60%),
    linear-gradient(180deg,var(--land) 0%,var(--dusk) 100%)}
.close h2{font-size:clamp(2.1rem,7vw,4.4rem); max-width:16ch; text-wrap:balance}
.close p{margin-top:1.3rem; color:var(--text2); max-width:46ch; font-weight:350}

footer{background:var(--dusk2); border-top:1px solid var(--rule-soft); padding-block:2rem 3rem; position:relative; z-index:4}
footer .wrap{display:flex; flex-wrap:wrap; gap:1rem 2.5rem; align-items:baseline;
  font-size:.88rem; color:var(--text3)}
footer .right{margin-left:auto}

@media (min-width:48rem){
  .proc .wrap{grid-template-columns:minmax(0,18rem) minmax(0,1fr); align-items:start}
  .proc li{grid-template-columns:3.2rem 1fr}
  .cards{grid-template-columns:repeat(3,1fr)}
  .work{grid-template-columns:repeat(2,1fr)}
  .about .wrap{grid-template-columns:minmax(0,1fr) minmax(0,1.2fr)}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{animation:none!important; transition:none!important}
  .rv,.ld,.milky,.stars,.range{opacity:1!important; transform:none!important}
  .vesper{opacity:1!important; transform:translate(50%,-50%)!important}
  .meteor{display:none}
  .rot .w{opacity:0}
  .rot .w:nth-child(1){opacity:1}
  .rot .w::before{clip-path:polygon(0 0,106% 0,99% 100%,0 100%)}
}

/* ============================================================
   MOBILE NAV
   Only engages once JS has confirmed itself by adding .js-nav to
   <body>. Without that class none of this applies and the nav is a
   plain wrapping list, which is a worse layout but a working one.
   ============================================================ */
.nav-toggle{display:none}

.js-nav .nav-toggle{
  display:inline-flex; align-items:center; gap:.55rem; margin-left:auto;
  background:none; border:1px solid var(--rule); color:var(--text);
  font:600 .92rem/1 var(--body); padding:.6rem .85rem; cursor:pointer;
  border-radius:2px; transition:border-color .16s ease, background-color .16s ease}
.js-nav .nav-toggle:hover{border-color:var(--lav); background:rgba(184,168,221,.08)}
.nav-toggle-bars{display:grid; gap:3px; width:16px}
.nav-toggle-bars i{display:block; height:1.5px; background:currentColor;
  transition:transform .2s ease, opacity .2s ease}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars i:nth-child(1){transform:translateY(4.5px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars i:nth-child(2){opacity:0}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars i:nth-child(3){transform:translateY(-4.5px) rotate(-45deg)}

.js-nav nav{
  display:none; flex-basis:100%; margin-left:0;
  flex-direction:column; gap:0; padding-top:.75rem}
.js-nav nav[data-open]{display:flex}
.js-nav nav a{
  padding:.85rem .2rem; border-bottom:1px solid var(--rule-soft);
  font-size:1.02rem; color:var(--text)}
.js-nav nav a:last-child{border-bottom:0}

/* Above the breakpoint the toggle disappears and the nav is a plain row
   again, regardless of whether it was left open on a narrow screen. */
@media (min-width:48rem){
  .js-nav .nav-toggle{display:none}
  .js-nav nav{display:flex !important; flex-direction:row; flex-basis:auto;
    margin-left:auto; gap:.4rem 1.6rem; padding-top:0}
  .js-nav nav a{padding:.2rem 0; border-bottom:1px solid transparent; font-size:.92rem;
    color:var(--text2)}
  .js-nav nav a:hover{color:var(--text); border-bottom-color:var(--lav)}
}

/* ============================================================
   CASE STUDIES
   ============================================================ */
.cs-hero{position:relative; padding-block:clamp(3.5rem,10vw,7rem) clamp(2.5rem,7vw,5rem)}
.cs-hero .eyebrow a{color:var(--lav); text-decoration:none;
  border-bottom:1px solid rgba(184,168,221,.35); padding-bottom:1px}
.cs-hero .eyebrow a:hover{color:var(--text); border-bottom-color:var(--text)}
.cs-hero h1{font-size:clamp(2.4rem,7.5vw,5rem); max-width:16ch}
.cs-hero .lede{max-width:46ch}

.cs-meta{display:grid; gap:1.1rem 2.5rem; grid-template-columns:repeat(auto-fit,minmax(9rem,auto));
  justify-content:start; margin:clamp(2rem,4vw,3rem) 0 0; padding-top:1.6rem;
  border-top:1px solid var(--rule-soft); max-width:52rem}
.cs-meta div{min-width:0}
.cs-meta dt{font:600 .7rem/1.4 var(--body); text-transform:uppercase; letter-spacing:.15em;
  color:var(--text3); margin-bottom:.35rem}
.cs-meta dd{margin:0; font-size:.98rem; color:var(--text)}
.cs-meta a{color:var(--lav)}

/* prose blocks inside a case study */
.cs-body{padding-block:clamp(2.5rem,7vw,5rem)}
.cs-body + .cs-body{padding-top:0}
.cs-body h2{font-size:clamp(1.7rem,4.6vw,2.7rem); max-width:20ch; margin-bottom:1.2rem}
.cs-body h3{font-size:clamp(1.2rem,1.1rem + .6vw,1.5rem); margin:2.2rem 0 .6rem}
.cs-body p{color:var(--text2); max-width:62ch; margin-bottom:1.1rem; font-weight:350}
.cs-body ul{color:var(--text2); max-width:62ch; margin:0 0 1.1rem; padding-left:1.2rem; font-weight:350}
.cs-body li{margin-bottom:.5rem}
.cs-body strong{font-weight:600; color:var(--text)}

.cs-pull{border-left:0; border-top:1px solid var(--rule); border-bottom:1px solid var(--rule);
  padding:clamp(1.6rem,4vw,2.4rem) 0; margin:clamp(2rem,5vw,3rem) 0; max-width:56rem}
.cs-pull blockquote{margin:0; font-family:var(--display); font-weight:400;
  font-size:clamp(1.25rem,1.1rem + 1vw,1.9rem); line-height:1.3; letter-spacing:-.02em; color:var(--text)}
.cs-pull figcaption{margin-top:1rem; font-size:.92rem; color:var(--text3)}

/* asset placeholders */
.shot{margin:clamp(1.8rem,4vw,2.8rem) 0; max-width:100%}
.shot-box{aspect-ratio:var(--shot-ratio,16/9); width:100%;
  border:1px dashed rgba(184,168,221,.34); background:
    repeating-linear-gradient(-45deg, rgba(184,168,221,.045) 0 12px, transparent 12px 24px),
    var(--land2);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:.4rem; text-align:center; padding:1.5rem; border-radius:2px}
.shot-dims{font:600 .78rem/1 var(--mono); color:var(--amber); letter-spacing:.02em}
.shot-label{font-family:var(--display); font-weight:700; letter-spacing:-.02em; color:var(--text);
  font-size:clamp(1rem,.95rem + .5vw,1.3rem); max-width:34ch}
.shot-note{font-size:.88rem; color:var(--text2); max-width:44ch; font-weight:350}
.shot-ratio{font:500 .72rem/1 var(--mono); color:var(--text3); margin-top:.3rem}
.shot-fig{margin:clamp(1.8rem,4vw,2.8rem) 0}
.shot-fig img{width:100%; height:auto; border-radius:2px; display:block}
.shot-fig figcaption{margin-top:.8rem; font-size:.9rem; color:var(--text3)}

.shot-pair{display:grid; gap:1rem; grid-template-columns:1fr; margin:clamp(1.8rem,4vw,2.8rem) 0}
.shot-pair .shot{margin:0}

.cs-next .work h3 a{text-decoration:none}
.cs-next .work h3 a:hover{color:var(--lav)}

/* work index */
.work-list{display:grid; gap:1rem; grid-template-columns:1fr}
.work-list a.wl{display:block; border:1px solid var(--rule-soft); background:var(--land2);
  padding:clamp(1.5rem,3vw,2.2rem); text-decoration:none; transition:.22s ease}
.work-list a.wl:hover{border-color:var(--rule); transform:translateY(-3px)}
.work-list .kind{font:500 .82rem/1.4 var(--body); color:var(--lav); margin-bottom:.7rem}
.work-list h2{font-family:var(--display); font-weight:800; letter-spacing:-.024em;
  font-size:clamp(1.4rem,1.2rem + .9vw,2rem); margin-bottom:.5rem; color:var(--text)}
.work-list p{color:var(--text2); font-size:.98rem; font-weight:350; max-width:56ch}

@media (min-width:48rem){
  .shot-pair{grid-template-columns:1fr 1fr}
  .work-list{grid-template-columns:repeat(2,1fr)}
}

/* case-study links inside the homepage work grid */
.work h3 a{text-decoration:none; color:inherit}
.work h3 a:hover{color:var(--lav)}

/* ============================================================
   PORTRAIT SHOTS
   A 900px-wide phone screenshot stretched across a 1200px column is
   both upscaled and absurdly tall. It never goes full width. Instead
   it sits at natural scale in a two-column block with prose beside
   it, which uses the space and reads as a deliberate figure.
   ============================================================ */
.shot-aside{display:grid; gap:clamp(1.5rem,4vw,3rem); align-items:center;
  margin:clamp(2rem,5vw,3.4rem) 0}
.shot-aside > .shot,
.shot-aside > .shot-fig{margin:0; max-width:340px; width:100%; justify-self:center}
.shot-aside .aside-copy h3{margin-top:0}
.shot-aside .aside-copy p{margin-bottom:.9rem}
.shot-aside .aside-copy p:last-child{margin-bottom:0}

@media (min-width:44rem){
  .shot-aside{grid-template-columns:minmax(0,320px) minmax(0,1fr)}
  .shot-aside > .shot,
  .shot-aside > .shot-fig{justify-self:start}
}

/* a portrait figure that is not paired with copy still stays sane */
.shot-fig.is-portrait,
.shot.is-portrait{max-width:340px}

/* ============================================================
   BRAND LOGO WALL
   Source SVGs carry no fill, so they render black. `brightness(0)
   invert(1)` knocks them to pure white regardless of what any one
   file declares, which is more reliable than assuming a fill value.
   ============================================================ */
.brands ul{display:grid; gap:clamp(1.5rem,3.5vw,2.75rem);
  grid-template-columns:repeat(2,minmax(0,1fr)); align-items:center; padding:0; margin:0; list-style:none}
.brands li{display:flex; align-items:center; justify-content:center}
.brands img{width:100%; height:auto; max-width:170px; aspect-ratio:2/1; object-fit:contain;
  filter:brightness(0) invert(1); opacity:.62; transition:opacity .2s ease}
.brands li:hover img{opacity:1}

@media (min-width:34rem){ .brands ul{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (min-width:60rem){ .brands ul{grid-template-columns:repeat(5,minmax(0,1fr))} }

/* ============================================================
   CONTACT FORM
   ============================================================ */
.form{max-width:34rem; margin-top:clamp(1.8rem,4vw,2.6rem)}
.hp{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}
.field{margin-bottom:1.4rem}
.field label{display:block; font:600 .88rem/1.4 var(--body); color:var(--text); margin-bottom:.45rem}
.field .opt{font-weight:400; color:var(--text3)}
.field input,
.field textarea{
  width:100%; font:400 1rem/1.5 var(--body); color:var(--text);
  background:rgba(184,168,221,.06); border:1px solid var(--rule);
  border-radius:2px; padding:.8rem .9rem; transition:border-color .16s ease, background-color .16s ease}
.field textarea{resize:vertical; min-height:8rem}
.field input:hover,
.field textarea:hover{border-color:rgba(184,168,221,.34)}
.field input:focus,
.field textarea:focus{background:rgba(184,168,221,.1); border-color:var(--lav)}
.field input::placeholder,
.field textarea::placeholder{color:var(--text3)}
.hint{margin:.45rem 0 0; font-size:.85rem; color:var(--text3); font-weight:350}

/* Native validation styling, but only after the field has been touched, so
   a required field is not shouted at before anyone has typed in it. */
.field input:user-invalid,
.field textarea:user-invalid{border-color:#e0736f}
.field input:user-invalid + .hint,
.field textarea:user-invalid + .hint{color:#e0a09d}

.form button{margin-top:.4rem; cursor:pointer; border:0; font-family:var(--body)}

/* ============================================================
   CONTACT SECTION
   One narrow column of fields in the left third of a wide screen
   reads as unfinished. The intro column carries what someone
   actually wants to know before they type: who reads it, when
   they hear back, and what happens if it is not a fit.
   ============================================================ */
.contact-grid{display:grid; gap:clamp(2.5rem,6vw,5rem); align-items:start}
.contact-intro h2{margin-bottom:1.2rem}
.contact-intro > p{color:var(--text2); max-width:44ch; font-weight:350}

.next-steps{list-style:none; margin:clamp(2rem,4vw,2.8rem) 0 0; padding:0; counter-reset:n;
  border-top:1px solid var(--rule-soft)}
.next-steps li{counter-increment:n; display:grid; grid-template-columns:2.2rem 1fr; gap:1rem;
  padding-block:1.15rem; border-bottom:1px solid var(--rule-soft)}
.next-steps li::before{content:counter(n,decimal-leading-zero);
  font:600 .74rem/1.9 var(--mono); color:var(--lav)}
.next-steps h3{font-family:var(--display); font-weight:700; letter-spacing:-.02em;
  font-size:clamp(1rem,.95rem + .35vw,1.18rem); margin-bottom:.25rem; color:var(--text)}
.next-steps p{color:var(--text2); font-size:.94rem; font-weight:350; margin:0; max-width:40ch}

.contact-direct{margin-top:clamp(1.6rem,3vw,2.2rem); color:var(--text2);
  font-size:.95rem; font-weight:350; line-height:1.7}
.contact-direct a{color:var(--lav)}

/* the form column carries a faint surface so it reads as a distinct
   place to act rather than more page */
.contact-form{background:rgba(184,168,221,.035); border:1px solid var(--rule-soft);
  border-radius:2px; padding:clamp(1.5rem,3.5vw,2.4rem)}
.contact-form .form{margin-top:0; max-width:none}

@media (min-width:56rem){
  .contact-grid{grid-template-columns:minmax(0,1fr) minmax(0,26rem)}
}
