@font-face{font-family:Manrope;src:url('assets/manrope.woff2') format('woff2');font-weight:200 800;font-display:swap}
@font-face{font-family:Space Grotesk;src:url('assets/space-grotesk.woff2') format('woff2');font-weight:300 700;font-display:swap}
@font-face{font-family:Fraunces;src:url('assets/fraunces.woff2') format('woff2');font-weight:100 900;font-display:swap}
:root{--yellow:#eee66b;--ink:#352a17;--paper:#f7f5e8;--muted:#726a4c;--accent:#5c49c8;--accent-dark:#4a37ad;--pad:clamp(22px,5vw,88px);--grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)' opacity='.15'/%3E%3C/svg%3E");--grain-dark:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='gd'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23gd)' opacity='.16'/%3E%3C/svg%3E");--grain-work:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='gw'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='20' intercept='-10'/%3E%3CfeFuncG type='linear' slope='20' intercept='-10'/%3E%3CfeFuncB type='linear' slope='20' intercept='-10'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23gw)' opacity='.85'/%3E%3C/svg%3E")}*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:calc(var(--hdr,92px) + 14px)}body{margin:0;background:var(--yellow);color:var(--ink);font-family:Manrope,sans-serif;font-size:17px;line-height:1.6}a{color:inherit;text-underline-offset:5px}a:focus-visible,summary:focus-visible{outline:3px solid currentColor;outline-offset:6px}::selection{background:var(--ink);color:var(--yellow)}.skip{position:absolute;left:20px;top:-100px;background:var(--paper);padding:12px;z-index:8}.skip:focus{top:10px}.header{position:fixed;inset:0 0 auto;z-index:6;color:var(--yellow);padding:22px 6%;display:flex;align-items:center;justify-content:space-between;transition:color .25s ease;transform:translateZ(0)}.header::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--yellow);opacity:0;transition:opacity .3s ease}.header::after{content:"";position:absolute;left:0;right:0;top:0;height:calc(100% + clamp(56px,7vh,96px));z-index:-2;pointer-events:none;background:linear-gradient(#0e1a21f2,#0e1a2155 64%,#0e1a2100);transition:opacity .3s ease}.wordmark{display:inline-block;line-height:0;text-decoration:none}.wordmark-inner{position:relative;display:inline-block}.wordmark-art{display:block;width:clamp(118px,12.4vw,186px);aspect-ratio:496.897/113.516;background:currentColor;-webkit-mask:url("assets/logo-chutney.svg") center/contain no-repeat;mask:url("assets/logo-chutney.svg") center/contain no-repeat}/* The dot is a full stop, so it is treated as one: its bottom edge is the
   baseline and it squashes against that line rather than through it. Every
   transform below scales from the baseline, which is what keeps the squash
   looking planted instead of like a shape growing in mid-air. */
.wordmark-dot{position:absolute;left:95.29%;top:56.65%;width:4.71%;height:20.63%;border-radius:18%;background:currentColor;transform-origin:50% 100%}
.wordmark-dot.is-bouncing{animation:dot-bounce .95s 1 both}
/* A hop with weight on it rather than a thing sliding up and down. It crouches,
   throws itself up thin, hangs at the top, lands fat, then bounces twice more at
   falling heights before settling. Squash and stretch does the work — the dot
   widens as it compresses and narrows as it stretches, so the eye reads mass and
   gravity rather than translation. Each segment carries its own timing function:
   explosive out of the push-off, decelerating all the way up, a real hang at the
   top, accelerating the whole way down. One curve across the whole animation is
   what made the old one feel mechanical. */
@keyframes dot-bounce{
  0%{transform:translateY(0) scale(1,1);animation-timing-function:cubic-bezier(.55,0,.85,.35)}
  7%{transform:translateY(0) scale(1.24,.74);animation-timing-function:cubic-bezier(.1,.85,.3,1)}
  13%{transform:translateY(-10%) scale(.82,1.24);animation-timing-function:cubic-bezier(.2,.65,.45,1)}
  28%{transform:translateY(-112%) scale(.93,1.1);animation-timing-function:cubic-bezier(.25,.6,.5,1)}
  40%{transform:translateY(-132%) scale(1,1);animation-timing-function:linear}
  45%{transform:translateY(-133%) scale(1,1);animation-timing-function:cubic-bezier(.45,0,.9,.45)}
  57%{transform:translateY(-46%) scale(.9,1.15);animation-timing-function:cubic-bezier(.6,0,.9,.6)}
  64%{transform:translateY(0) scale(1.32,.64);animation-timing-function:cubic-bezier(.1,.85,.35,1)}
  72%{transform:translateY(-34%) scale(.95,1.08);animation-timing-function:cubic-bezier(.3,.6,.5,1)}
  80%{transform:translateY(-40%) scale(1,1);animation-timing-function:cubic-bezier(.45,0,.9,.5)}
  86%{transform:translateY(0) scale(1.14,.86);animation-timing-function:cubic-bezier(.15,.8,.4,1)}
  91%{transform:translateY(-9%) scale(.98,1.03);animation-timing-function:cubic-bezier(.45,0,.9,.5)}
  95%{transform:translateY(0) scale(1.04,.96);animation-timing-function:cubic-bezier(.2,.7,.4,1)}
  100%{transform:translateY(0) scale(1,1)}
}.header .wordmark{flex-shrink:0}.header-solid .header,.page .header{color:var(--ink)}.header-solid .header nav,.page .header nav{color:var(--ink)}.header-solid .header::before,.page .header::before{opacity:1}.header-solid .header::after,.page .header::after{opacity:0}.header nav{display:flex;font-family:Manrope,sans-serif;align-items:center;gap:26px;font-size:16px;font-weight:600;letter-spacing:0;color:var(--paper)}.header nav a{text-decoration:none}.header nav a:hover{text-decoration:underline}.header .nav-cta{background:var(--accent);color:var(--paper);padding:13px 20px;border-radius:3px;text-decoration:none;font-size:14px;font-family:Manrope,sans-serif;font-weight:700;letter-spacing:.01em}.header .nav-cta:hover{background:var(--paper);color:var(--accent)}
.hero-scene{position:relative;isolation:isolate;min-height:650px;height:100svh;padding:0;overflow:clip;clip-path:inset(0);background:#101c24;color:var(--yellow)}.hero-backdrop{position:fixed;inset:0;height:100svh;z-index:-2;pointer-events:none;background:#101c24;contain:paint}.hero-art{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;z-index:-2}.hero-copy{position:absolute;left:6%;top:auto;bottom:calc(56px + clamp(22px,6vh,58px));width:48%;max-width:800px;z-index:1}.hero-scene h1{font-size:clamp(40px,4.5vw,84px);line-height:1.12;letter-spacing:-.035em;font-weight:600;margin:0}.hero-scene h1 span{display:block;margin-top:.4em}.hero-scene h1 em{font-style:italic}.hero-scene h1 .h1-dot{display:inline-block;margin-top:0;width:.115em;height:.115em;border-radius:18%;background:currentColor;margin-left:.04em;vertical-align:baseline}.hero-copy p{margin:clamp(18px,2.4vw,30px) 0 0;font-size:clamp(15px,1.5vw,21px);line-height:1.5;max-width:44ch;color:var(--paper)}#light{animation:window-on 1.5s ease-out .45s both}@keyframes window-on{from{opacity:0}to{opacity:1}}
.audience-bar{position:absolute;bottom:0;left:0;right:0;display:flex;align-items:center;background:var(--ink);color:var(--yellow);height:56px;overflow:hidden;z-index:2;font-family:Space Grotesk,Manrope,sans-serif;font-size:15px}.audience-track{display:flex;width:max-content;animation:audiences 110s linear infinite}.audience-track>span{display:flex;align-items:center;gap:40px;padding-right:40px;white-space:nowrap}.audience-track .audience-dot{display:inline-block;width:.44em;height:.44em;border-radius:18%;background:currentColor}@keyframes audiences{to{transform:translateX(-50%)}}.audience-bar:hover .audience-track,.audience-bar:focus-within .audience-track{animation-play-state:paused}

/* The artwork lands a beat after the copy: index.html puts .hero-copy before the
   hero-art.js tag, so the headline paints while the 1.58MB of SVG is still
   arriving, then this dissolves the city in behind it. Without it the artwork
   would snap on. No fill-mode, so nothing is applied once the half second is up
   and the fixed backdrop is not left promoted to its own layer. */
.hero-art{animation:hero-art-in .5s cubic-bezier(.2,.7,.3,1)}
@keyframes hero-art-in{from{opacity:0}}

.section{padding:90px var(--pad)}h2,h3,p{margin-top:0}h2{font-size:clamp(38px,5vw,76px);line-height:1.08;letter-spacing:-.035em;font-weight:700}h3{font-size:21px;letter-spacing:-.02em}.section-label{font-size:14px;margin-bottom:36px}
/* The work band is warm again, and darker than the brown it used to be: the heart
   of the old lamp is still there — #4a3a22 at the seam, exactly the brick light the
   page opened with — but it falls away faster, through --ink at 30% and #231a10 at
   60%, to a brown-black at 86% rather than stopping on ink. The band therefore reads
   as the same evening as the hero instead of a second one, and it is darker than the
   slate it replaces, which is what the cream serif captions below want: the tile is
   the only light object in the column.
   The second radial is the accent, and it is not text: one soft purple glow in the
   bottom-right corner at 15%, echoing the lit window in the hero. It is a corner
   light, sized 64% by 620px and pinned to 100% 100%, fading out by 76% — no tile
   ever sits inside it, and no purple word is ever set on this ground.
   The grain is its own tile, and on this band it is the point. Overlay multiplies
   the noise by the colour underneath, so the shared --grain-dark tile is all but
   invisible on a ground this dark: measured on the band, its luma spread was 0.4 of
   a level, which is to say nothing. --grain-work carries the same fractal noise at
   three octaves and a lower frequency — coarser, so it reads as film rather than
   static — pushed through a hard feComponentTransfer (slope 20, so the specks reach
   black and white instead of clustering at grey). Measured on the same patch the
   spread is near 6 levels and the mean is unchanged: the band is still the colour it
   was, only now it looks printed. */
.work{background-color:#140e07;background-image:var(--grain-work),radial-gradient(64% 620px at 100% 100%,rgba(92,73,200,.15) 0%,rgba(92,73,200,.05) 46%,rgba(92,73,200,0) 76%),radial-gradient(96% 760px at 50% -90px,#4a3a22 0%,var(--ink) 30%,#231a10 60%,#140e07 86%);background-size:160px 160px,auto,auto;background-blend-mode:overlay,normal,normal;color:var(--paper)}.section-heading{display:flex;align-items:end;justify-content:space-between;gap:40px;margin-bottom:48px}.section-heading h2{margin-bottom:0}.section-heading p{max-width:370px;margin-bottom:0}.work-cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(16px,2vw,28px)}.work-card{display:flex;flex-direction:column;text-decoration:none;color:inherit}.work-card-media{display:block;overflow:hidden;aspect-ratio:4/3;background:#00000012;border-radius:50% 50% 0 0/32% 32% 0 0}.work-card-media img{display:block;width:100%;height:100%;object-fit:cover;transform:translateZ(0);backface-visibility:hidden;transition:transform .6s cubic-bezier(.2,.7,.3,1)}.work-card:hover .work-card-media img{transform:translateZ(0) scale(1.04)}.work-card-type{font-family:Space Grotesk,Manrope,sans-serif;font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-top:14px}.work-card-name{display:block;font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(17px,1.6vw,23px);font-weight:650;letter-spacing:-.025em;line-height:1.15;margin-top:5px}.work-card-name .arrow{display:inline-block;margin-left:5px;font-family:Manrope,sans-serif;font-weight:400;font-size:.8em;transition:transform .25s ease}.work-card:hover .arrow{transform:translateX(4px)}.work .work-card-type{color:#f7f5e8a6}.work .link-more:hover{color:var(--yellow)}
/* The four tiles are windows on different floors. Each card opens with its number
   and a hairline — 01 to 04 in the same small caps and wide tracking as the eyebrow,
   in --yellow so the numbering belongs to the band's light rather than to its
   furniture — and the rule runs out to the card's edge, so the row reads as a plate
   list rather than four pictures that happen to be beside each other.
   The tiles then step down the band on a regular beat: 0, 48, 0, 48, never on a
   phone, where a stagger a thumb has to scroll past is just broken alignment.
   margin-top, not transform, so the section's own height accounts for the step and
   the lowest tile cannot land in the padding. Because the odd tiles share a top edge
   and the even tiles share one, the name is held to two lines from 561px up
   (min-height 2.3em) — the long name in 03 would otherwise close its panel a line
   below 01's and break the pair across the row.
   Stacked, nothing is held: there is no pair to line up, so a one-line name closes up.
   The caption is not a card of its own: it is the foot of the window. The arch ends and
   the panel begins on the same edge — no gap, no border, no radius, square to the floor
   — so the picture and its words are one block, and the block is where the light lands.
   At rest the panel is already lit: the accent, soft, washing down from the seam, behind
   the category and the name. Nothing has to be hovered to see that the tile is lit.
   The sentence waits under the name, closed to nothing. Hovering or tabbing opens the
   panel downward — the wash brightens, the sentence unfolds under the name and the panel
   grows with it, so the description is let out of the light that was already there. The
   glow is clipped by the panel's own edges and cannot reach the photograph above or the
   tile beside it, however the row is sized or scrolled under the pointer. Nothing here
   is underlined: the lift, the light and the opening panel are the affordance.
   A touch screen has no hover to wait for, so there the sentence is simply on and the
   panel never has to open. Reduced motion swaps every one of those moves for a cut.
   */
.work-card-inner{display:flex;flex-direction:column;flex:1}
.work-card-kicker{display:flex;align-items:center;gap:12px;margin-bottom:13px;font-family:Space Grotesk,Manrope,sans-serif;font-size:11px;font-weight:600;letter-spacing:.16em;line-height:1;text-transform:uppercase;color:var(--yellow)}
.work-card-kicker::after{content:"";flex:1;height:1px;background:currentColor;opacity:.32}
.work-card{position:relative}
/* The panel is the foot of the window: square, borderless, flush to the arch above it,
   filled from its top edge with the accent and clipped, so every move stays inside it. */
.work-card-caption{position:relative;display:flex;flex-direction:column;margin:0;padding:15px 16px 17px;overflow:hidden;border:0;border-radius:0;background-color:#171027}
.work-card-caption .work-card-type{margin-top:0}
.work-card-glow{position:absolute;left:0;right:0;top:0;height:100%;z-index:0;pointer-events:none;transform:translateZ(0);background:radial-gradient(122% 96% at 50% -10%,var(--accent) 0%,rgba(92,73,200,.32) 48%,rgba(92,73,200,0) 78%);opacity:.45;transition:opacity .5s ease}
.work-card-quote{position:relative;z-index:1;margin:0;max-height:0;overflow:hidden;opacity:0;font-family:Manrope,sans-serif;font-size:14.5px;font-weight:400;line-height:1.42;letter-spacing:normal;color:rgba(247,245,232,.86);transition:max-height .55s cubic-bezier(.2,.7,.3,1),margin-top .55s cubic-bezier(.2,.7,.3,1),opacity .4s ease}
.work-card-type,.work-card-name{position:relative;z-index:1}
.work-card:hover .work-card-glow,.work-card:focus-visible .work-card-glow{opacity:1}
.work-card:hover .work-card-quote,.work-card:focus-visible .work-card-quote{max-height:9em;margin-top:8px;opacity:1}
.work .work-card:hover .work-card-type,.work .work-card:focus-visible .work-card-type{color:rgba(247,245,232,.82)}
@media(hover:none),(max-width:768px){
  .work-card-caption{padding:14px 15px 15px}
  .work-card-quote{max-height:none;margin-top:8px;opacity:1}
  .work .work-cards{row-gap:34px}
}
/* Hover is the accent, the purple the buttons already use. On the index grid the light
   itself lives in the panel under the window — that is where it is let out and where it is
   kept — so those tiles cast no second purple shadow: the card lifts, the photograph zooms,
   the arrow nudges. One light per tile. The work index keeps the shadow it has always had,
   under the window, because those tiles have no panel of their own. */
.work-card{transition:transform .3s ease}
.work-card:hover{transform:translateY(-4px)}
.work-cards-lg .work-card-media{transition:box-shadow .35s ease}
.work-cards-lg .work-card:hover .work-card-media{box-shadow:0 18px 46px -16px rgba(92,73,200,.55)}
@media(min-width:561px){
  /* The name is held to two lines from here up, so the four panels attach to four windows
     at one height: 03's long name would otherwise end its panel a line below the rest. */
  .work-cards:not(.work-cards-lg)>.work-card .work-card-name{min-height:2.3em}
}
@media(min-width:901px){
  .work-cards:not(.work-cards-lg)>.work-card:nth-child(even){margin-top:48px}
}
/* Scroll entry: motion.js puts .is-reveal on <html>, which arms each tile 12px low
   and at 0 opacity; .is-in releases it, 70ms apart down the row. The class goes on
   the wrapper rather than the card so the card keeps its own hover transition, and
   nothing is armed at all without JavaScript — a tile that never arrives is worse
   than one that was never animated. */
.is-reveal .work-card-inner{opacity:0;transform:translateY(12px);transition:opacity .5s ease-out,transform .5s cubic-bezier(.2,.7,.3,1)}
.is-reveal .work-card:nth-child(2) .work-card-inner{transition-delay:.07s}
.is-reveal .work-card:nth-child(3) .work-card-inner{transition-delay:.14s}
.is-reveal .work-card:nth-child(4) .work-card-inner{transition-delay:.21s}
.is-reveal .work-card.is-in .work-card-inner{opacity:1;transform:none}

.services{background:var(--paper);display:grid;grid-template-columns:1fr 1fr;gap:9vw}.services-intro h2{max-width:440px}.services-intro>p{max-width:350px}.service-list{padding-top:10px}details{border-top:1px solid var(--ink)}details:last-child{border-bottom:1px solid var(--ink)}summary{list-style:none;cursor:pointer;font-size:clamp(20px,2vw,29px);letter-spacing:-.02em;display:flex;align-items:center;justify-content:space-between;gap:18px;padding:25px 0;font-weight:600}summary::-webkit-details-marker{display:none}summary span{font-size:28px;font-weight:400}details[open] summary span{transform:rotate(45deg)}details p{max-width:460px;margin:0 35px 28px 0;font-size:16px}.services summary:hover{color:var(--accent)}.work a:focus-visible,.services summary:focus-visible{outline-color:var(--accent)}.working{display:grid;grid-template-columns:1fr 1fr;gap:9vw}.working p{max-width:520px}.contact{background:var(--ink);color:var(--paper)}.contact h2{font-size:clamp(60px,10vw,155px);letter-spacing:-.04em;line-height:1;margin-bottom:70px}.contact h2 span{color:var(--yellow)}.contact-bottom{display:flex;align-items:start;justify-content:space-between;gap:clamp(28px,5vw,80px)}.contact-intro{flex:1 1 340px;max-width:400px}.enquiry{flex:1 1 400px;max-width:520px;display:grid;gap:16px;font-size:15px}.enquiry .field{display:grid;gap:7px}.enquiry label{font-family:Space Grotesk,Manrope,sans-serif;font-size:13px;font-weight:600;letter-spacing:.02em}.enquiry label span{font-weight:400;color:#f7f5e8b3}.enquiry .helper{max-width:none;margin:0;font-size:13px;color:#f7f5e8b3}.enquiry input,.enquiry textarea{width:100%;min-width:0;font:inherit;color:var(--paper);background:#f7f5e814;border:1px solid #f7f5e859;border-radius:3px;padding:11px 13px}.enquiry textarea{min-height:104px;resize:vertical}.enquiry input:hover,.enquiry textarea:hover{border-color:#f7f5e8a6}.enquiry input:focus-visible,.enquiry textarea:focus-visible,.enquiry button:focus-visible{outline:3px solid var(--yellow);outline-offset:3px}.enquiry input::placeholder{color:#f7f5e880}.enquiry input:-webkit-autofill{-webkit-text-fill-color:var(--paper);box-shadow:inset 0 0 0 999px var(--ink)}.enquiry button{justify-self:start;font-family:Space Grotesk,Manrope,sans-serif;font-size:15px;font-weight:650;padding:15px 26px;border:0;border-radius:3px;background:var(--yellow);color:var(--ink);cursor:pointer}.enquiry button:hover{background:var(--accent);color:var(--paper)}.enquiry button:disabled{opacity:.55;cursor:progress}.enquiry .consent{max-width:none;margin:0;font-size:12.5px;color:#f7f5e8b3}.enquiry .status{max-width:none;margin:0;font-size:14px}.enquiry .status:empty{display:none}.enquiry .status[data-state]{padding:11px 13px;border:1px solid currentColor;border-radius:3px}.enquiry .status[data-state=sent]{color:var(--yellow)}.enquiry .status[data-state=error]{color:var(--paper);border-color:var(--accent)}.enquiry .hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.contact-bottom p{max-width:370px;margin:0}.email{font-size:clamp(18px,2.3vw,35px);letter-spacing:-.02em;color:var(--yellow)}@media(min-width:1600px){body{max-width:1800px;margin:auto}.header{max-width:1800px;margin:auto}}@media(max-width:900px){.header nav{gap:18px}.header .nav-cta{max-width:none;padding:12px 16px;font-size:13px;line-height:1.3;white-space:nowrap}.hero-backdrop .hero-art{width:177.78%;max-width:none;left:-65%;height:100%}}
@media(max-width:700px){.hero-scene{min-height:700px}.hero-copy{left:7%;top:25%;bottom:auto;width:86%;max-width:460px}.hero-copy p{font-size:14.5px;line-height:1.45;margin-top:14px;max-width:none}.hero-scene h1{font-size:clamp(34px,8.8vw,61px);line-height:1.12}.hero-art{object-position:65% center}.hero-scene:after{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(#0b182299,transparent 75%)}.audience-track>span{gap:24px;padding-right:24px}.audience-bar{font-size:13px}.section{padding:55px var(--pad)}.section-heading,.contact-bottom{align-items:start;flex-direction:column;gap:28px}.services,.working{grid-template-columns:1fr;gap:25px}.section-heading{margin-bottom:30px}.section-heading p{font-size:15px}.contact h2{margin-bottom:40px}.email{overflow-wrap:anywhere}.working h2{margin-bottom:0}}
@media(max-width:380px){.contact h2{font-size:50px}.header{padding-left:4%;padding-right:4%;gap:8px}.header .wordmark-art{width:88px}.header nav{gap:8px;font-size:12px}.header .nav-cta{font-size:11px;padding:0 10px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}#light,.hero-art,.audience-track,.wordmark-dot,.wordmark-dot.is-bouncing{animation:none}.hero-backdrop{position:absolute}.audience-track{transform:none}.work-card{transition:none}.work-card:hover{transform:none}.work-card-media,.work-cards-lg .work-card-media{transition:none}.work-card:hover .work-card-media,.work-cards-lg .work-card:hover .work-card-media{box-shadow:none}.work-card-media img{transition:none}.work-card:hover .work-card-media img{transform:none}.work-card:hover .arrow{transform:none;transition:none}.work-card-glow,.work-card-quote,.work-card-caption{transition:none}.is-reveal .work-card-inner{opacity:1;transform:none;transition:none}}
/* ---- multi-page shell ---- */
.page{background:var(--yellow);padding-top:var(--hdr,92px)}.page .header nav{color:var(--ink)}.page-head{padding:clamp(10px,2vw,28px) var(--pad) clamp(34px,5vw,64px)}.page-head h1{font-size:clamp(40px,6vw,100px);line-height:1.03;letter-spacing:-.04em;margin:0 0 22px;max-width:18ch}.page-head .lede{font-size:clamp(16px,1.55vw,21px);line-height:1.5;max-width:54ch;margin:0}
/* ---- shared link and button ---- */
.link-more{font-family:Space Grotesk,Manrope,sans-serif;font-size:15px;font-weight:650;text-underline-offset:6px}.link-more:hover{color:var(--accent)}.button{display:inline-block;font-family:Space Grotesk,Manrope,sans-serif;font-size:15px;font-weight:650;text-decoration:none;background:var(--yellow);color:var(--ink);padding:15px 26px;border-radius:3px}.button:hover{background:var(--paper);color:var(--accent)}.chip{font-size:11px;border:1px solid;padding:3px 8px;border-radius:12px;font-weight:500;letter-spacing:0;vertical-align:middle;white-space:nowrap}
/* ---- home: two kinds of good website ---- */
.mission{position:relative;background:var(--yellow);overflow:clip;display:flow-root;padding:clamp(36px,4.6vw,68px) var(--pad) clamp(40px,5.2vw,76px)}.mission-photo{float:left;width:clamp(180px,25.5vw,344px);margin:0 clamp(20px,2.6vw,42px) clamp(12px,1.4vw,18px) 0;shape-outside:margin-box}.mission-photo img{display:block;width:100%;height:auto;aspect-ratio:1/1;object-fit:cover}.mission-lead{font-family:Fraunces,Georgia,serif;font-weight:380;font-size:clamp(27px,3.5vw,54px);line-height:1.14;letter-spacing:-.022em;margin:0 0 clamp(16px,2vw,28px);font-variation-settings:"opsz" 120,"SOFT" 0}.mission-statement{font-family:Fraunces,Georgia,serif;font-weight:380;font-size:clamp(21px,2.45vw,36px);line-height:1.3;letter-spacing:-.012em;margin:0;font-variation-settings:"opsz" 120,"SOFT" 0}/* The highlighter mark is a band drawn behind the text rather than a background
   on the inline box, so it survives a line break without cutting. It began on the
   mission lead and is now shared: the pricing heading marks one phrase with it, on
   the same yellow. */
.hl{white-space:nowrap;padding:0 .1em;background-image:linear-gradient(var(--paper),var(--paper));background-repeat:no-repeat;background-size:100% .62em;background-position:0 .41em;-webkit-box-decoration-break:clone;box-decoration-break:clone}.mission-more{margin:clamp(22px,2.6vw,34px) 0 0;clear:both}
/* ---- teasers ---- */
.section-more{margin:clamp(26px,3vw,40px) 0 0}.teaser{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:clamp(18px,4vw,60px);align-items:start;background:var(--paper)}.teaser h2{font-size:clamp(28px,3.4vw,52px);line-height:1.08;margin:0}.teaser p{max-width:48ch;margin:0 0 18px}.teaser .section-label{margin-bottom:16px}
/* ---- home: why chutney ---- */
/* Paper, with a grain on it. The prices below are flat yellow; two flat bands in a
   row — one cream, one yellow — read as the same value at the same size, and this
   one is meant to sit back. A 160px tile of fractal noise, greyscale, at 15%: fine
   enough to be tooth rather than cloud, shallow enough (12 levels off the cream at
   its darkest, measured off the rendered band) that it reads as paper rather than
   as dirt. The tile is --grain, shared with the cards in this band, where the 50%
   paper wash halves it again. */
.why{background-color:var(--paper);background-image:var(--grain);background-size:160px 160px;padding-block:clamp(46px,5.2vw,72px)}
.why-head{position:relative;display:flex;align-items:flex-end;justify-content:space-between;gap:clamp(18px,4vw,60px);margin-bottom:clamp(24px,3vw,40px)}
/* Nothing in the head runs under the stamp: the words reserve its width and the
   link keeps clear of it, at every width. */
.why-head-text{padding-right:clamp(78px,9vw,116px)}
/* The eyebrow: plain text, upper case, .14em apart, in --accent-dark rather than the
   ink — 11px tracked type is small enough that the ink would fight the heading, and
   the purple lets it sit under it as a label. No box, no tint, no hairline: the pill
   made it look like something to press. --accent-dark is the one purple in the kit
   that clears AAA at this size — 7.9:1 on the paper, 7.2:1 on the grain's darkest
   pixel — where --accent, at 5.9:1, only clears AA. */
.eyebrow{font-family:Space Grotesk,Manrope,sans-serif;font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;line-height:1;color:var(--accent-dark);margin:0 0 18px}
.why-head h2{font-size:clamp(28px,3.4vw,52px);line-height:1.08;letter-spacing:-.03em;margin:0;max-width:22ch;text-wrap:balance}
/* The mark under the italic: a marker stroke in the accent, drawn as the inline
   box's own background so it is cloned per line and survives a wrap, and tapered at
   both ends so it reads as a swipe rather than a rule. It sits below the descenders
   instead of behind the glyphs — the one way purple can meet ink and leave the
   words their full 12.8:1. The padding-bottom is what holds that .2em band clear of
   the g and the y.
   It is drawn at 100% here, in CSS, because with no JavaScript there is nothing to
   draw it and a heading that never finishes is worse than one that was never
   animated. motion.js arms it the moment it runs — .is-armed snaps the stroke back
   to 0% with the transition off, so nothing is seen rewinding — and then adds
   .in-view when the phrase reaches the middle of the viewport, which is the one
   transition that matters: 400ms on background-size, left to right, once. */
.hl-serif{font-family:Fraunces,Georgia,serif;font-style:italic;font-weight:420;letter-spacing:-.01em;font-variation-settings:"opsz" 96,"SOFT" 0;background-image:linear-gradient(90deg,#5c49c800,#5c49c8 4%,#5c49c8 96%,#5c49c800);background-repeat:no-repeat;background-position:0 100%;background-size:100% .2em;transition:background-size .4s cubic-bezier(.25,.7,.3,1);-webkit-box-decoration-break:clone;box-decoration-break:clone;padding-bottom:.13em}
.hl-serif.is-armed{background-size:0% .2em;transition:none}
.hl-serif.is-armed.in-view{background-size:100% .2em;transition:background-size .4s cubic-bezier(.25,.7,.3,1)}
.why-more{margin:0 clamp(78px,9vw,116px) 0 0;flex-shrink:0}
.why-more a{display:inline-block;padding:6px 0}
/* The stamp, upper right of the head: a rubber stamp in the accent, turned 12
   degrees off square. Decorative — aria-hidden in the markup — so the ring, the arc
   of type and the tick are one picture. Type is 8.4 units on a 100 unit viewBox and
   textLength pins it to the 232.5 circumference, so it closes exactly once whatever
   the font does. */
.why-stamp{position:absolute;top:0;right:0;width:clamp(74px,7.4vw,104px);color:var(--accent);transform:rotate(-12deg);transform-origin:60% 42%}
.why-stamp svg{display:block;width:100%;height:auto}
.why-stamp text{font-family:Space Grotesk,Manrope,sans-serif;font-size:8.4px;font-weight:600;letter-spacing:.06em;fill:currentColor}
/* Four short tiles: a 36px badge, a title, two or three lines. The mockups that
   used to top each card are gone on purpose — this band is read, not looked at, and
   the prices below are what should carry the weight of the page. A hairline edge
   was added with the shadow because a cream card on cream paper has nothing to sit
   against once the picture goes; the grain under it is the band's own tile behind a
   half-strength paper wash, so a card is paper that has been pressed rather than a
   picture of paper. 12px corners, since a card this small reads as a slip rather
   than a panel at 3px. Hover lifts it 3px and lights it from underneath in the
   band's own yellow rather than pressing a grey shadow onto it — the thin ink
   shadow that stays under the glow is what keeps the bottom edge defined, since a
   halo alone has nothing to do with the card's edge on cream.
   The halo is the site's own accent purple now, not the band's yellow. Yellow was
   right when the card was the only thing on the page asking to be pressed; with the
   work grid hovering in the same accent and the buttons already purple, one glow in
   two places does more than two glows in two colours. It is the accent at 25% with
   a 40px blur — light, not lacquer. */
.why-cards{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(14px,1.4vw,20px)}
.why-card{display:flex;flex-direction:column;gap:clamp(9px,1vw,12px);background-color:var(--paper);background-image:linear-gradient(#f7f5e880,#f7f5e880),var(--grain);background-size:auto,160px 160px;border:1px solid #352a171a;border-radius:12px;padding:clamp(16px,1.5vw,20px);box-shadow:0 14px 30px -18px #352a1738,0 2px 5px -3px #352a1720;transition:transform .18s ease,box-shadow .18s ease}
.why-card:hover{transform:translateY(-3px);box-shadow:0 12px 40px -12px rgba(92,73,200,.25),0 4px 12px rgba(53,42,23,.08)}
.why-badge{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:9px;background:var(--yellow);color:var(--ink)}
.why-badge.is-ink{background:var(--ink);color:var(--paper)}
.why-badge.is-accent{background:var(--accent);color:var(--paper)}
.why-badge svg{display:block;width:18px;height:18px}
.why-card h3{font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(17px,1.35vw,20px);font-weight:650;letter-spacing:-.025em;line-height:1.15;margin:0}
.why-card p{margin:0;font-size:clamp(14.5px,1.08vw,15.5px);line-height:1.5}
/* Four across needs 240px a card to stay readable, so the row folds to two below
   1024px and to one below 560px. */
@media(max-width:1023px){.why-cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:700px){.why-head{flex-direction:column;align-items:flex-start;gap:14px}.why-head-text{padding-right:clamp(70px,20vw,88px)}.why-more{margin:0}.why-stamp{width:clamp(66px,18vw,80px)}}
/* Below 560px the eyebrow and the heading both need the full measure — the tracked
   line is 212px on its own and the italic phrase wants one line — so the stamp
   leaves the corner and joins the flow under the heading, right-aligned, ahead of
   the services link. */
@media(max-width:560px){.why-cards{grid-template-columns:1fr;gap:clamp(10px,2vw,14px)}.why-head-text{padding-right:0}.why-stamp{position:static;order:1;align-self:flex-end;width:clamp(62px,17vw,76px)}.why-more{order:2}}
@media(prefers-reduced-motion:reduce){.why-card{transition:none}.why-card:hover{transform:none}.hl-serif,.hl-serif.is-armed,.hl-serif.is-armed.in-view{background-size:100% .2em;transition:none}}
/* ---- work page ---- */
.cases{background:var(--paper);padding-top:clamp(30px,4vw,56px)}.case{padding:clamp(34px,4.2vw,60px) 0;border-bottom:1px solid var(--ink)}.case:last-child{border-bottom:0;padding-bottom:0}.case-type{font-family:Space Grotesk,Manrope,sans-serif;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 10px}.case h2{display:flex;align-items:center;gap:14px;flex-wrap:wrap;font-size:clamp(32px,4.2vw,64px);line-height:1;letter-spacing:-.045em;margin:0 0 12px}.case-sub{font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(16px,1.7vw,22px);line-height:1.35;margin:0 0 clamp(22px,3vw,36px);max-width:42ch}.case-body{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(18px,2.6vw,42px);max-width:1180px}.case-body p{margin:0;font-size:clamp(15px,1.35vw,17px);line-height:1.6}.case-art{margin:clamp(22px,3vw,34px) 0 0;min-height:clamp(170px,20vw,280px);padding:20px}.case-note{font-size:12px;color:var(--muted);margin:14px 0 0}
/* ---- services page ---- */
/* The four lines under the hero open on air and a hairline of their own. Each row
   already carries its bottom rule; without a matching top one, and with no padding
   above it, "Show your work" read as an unruled stub pressed against the dark seam.
   The list now starts clear of the seam, then the line, then the row. */
.services-page{background:var(--paper);padding-top:clamp(30px,4.4vw,60px)}.service-block{display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);gap:clamp(14px,3.4vw,56px);padding:clamp(26px,3.2vw,44px) 0;border-bottom:1px solid var(--ink)}.service-block h2{font-size:clamp(23px,2.3vw,34px);line-height:1.16;letter-spacing:-.025em;margin:0}.service-block p{margin:0;max-width:54ch;font-size:clamp(15px,1.4vw,17px);line-height:1.6}
.services-page > .service-block:first-child{border-top:1px solid var(--ink)}
/* ---- contact page ---- */
.process{list-style:none;counter-reset:step;margin:0;padding:0;display:grid;gap:clamp(16px,2vw,26px);max-width:860px}.process li{counter-increment:step;display:grid;grid-template-columns:auto minmax(0,1fr);gap:clamp(14px,2vw,26px);padding-top:16px;border-top:1px solid var(--ink)}.process li::before{content:counter(step,decimal-leading-zero);font-family:Space Grotesk,Manrope,sans-serif;font-size:13px;font-weight:650;letter-spacing:.06em;color:var(--muted);padding-top:5px}.process p{margin:0;max-width:56ch;font-size:clamp(15px,1.4vw,17px)}.process strong{display:block;font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(17px,1.75vw,23px);letter-spacing:-.025em;margin-bottom:2px}.contact-details{display:flex;flex-wrap:wrap;gap:clamp(18px,4vw,60px);margin-top:clamp(30px,4vw,50px);font-size:14px}
/* ---- closing call to action ---- */
.cta{background:var(--ink);color:var(--paper);padding:clamp(46px,6vw,96px) var(--pad)}.cta h2{font-size:clamp(34px,5.2vw,80px);line-height:1.02;letter-spacing:-.04em;margin:0 0 18px;max-width:17ch}.cta p{max-width:46ch;margin:0 0 clamp(22px,3vw,32px)}.cta .actions{display:flex;flex-wrap:wrap;align-items:center;gap:18px 28px}.cta .button{background:var(--accent);color:var(--paper)}.cta .button:hover{background:var(--paper);color:var(--accent)}.cta .email{font-size:clamp(16px,1.8vw,24px)}
/* ---- about page ---- */
.faq{padding-top:0}.about-facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(18px,3vw,40px);margin-top:clamp(28px,3vw,44px);font-size:14px}.about-facts h3{font-family:Space Grotesk,Manrope,sans-serif;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:0 0 6px}.about-facts p{margin:0}
/* The story, told in two panes on the yellow. They are the same object: one ground,
   one radius, one shadow, so the photo and the words read as a pair rather than a
   picture with a caption attached to it. #140e07 is the dark the work band opens on,
   and the grain is the work band's own tile, recorded so it reads as a surface and
   not a flat fill. The photo keeps the wider share of the row: the words need a
   column, the window needs a room. */
.about-cards{display:grid;grid-template-columns:minmax(0,.84fr) minmax(0,1.16fr);gap:clamp(16px,2.2vw,28px);padding:0 var(--pad) clamp(32px,4.4vw,60px)}
.about-card{position:relative;border-radius:clamp(16px,1.6vw,24px);background-color:#140e07;background-image:var(--grain-work);background-size:160px 160px;background-blend-mode:overlay;color:var(--paper);box-shadow:0 26px 60px -34px rgba(53,42,23,.6)}
/* The glow is behind the window and inside the card's own edges, so it reads as light
   in the room rather than a halo round a picture: it peaks under the window and is
   still there in the card's padding, which is the only place it can be seen. The
   window also throws a short purple shadow of its own onto that padding, and carries a
   hairline, so its arch is legible even against a dark photograph. All of it is on the
   card, clipped with it, so nothing escapes onto the yellow. */
.about-photo{display:flex;flex-direction:column;margin:0;overflow:clip;isolation:isolate;padding:clamp(16px,2.2vw,30px)}
.about-photo::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;background:radial-gradient(70% 66% at 50% 46%,rgba(92,73,200,.42) 0%,rgba(92,73,200,.2) 55%,rgba(92,73,200,.06) 100%)}
/* The work grid's window, stood up: the same arch, portrait so the crop keeps the top
   radius away from the subject. It takes the card's height when the story beside it is
   taller, and falls back to 4/5 when it is not, which is every stacked width. */
.about-photo-arch{position:relative;z-index:1;flex:1 1 auto;aspect-ratio:4/5;overflow:hidden;border-radius:50% 50% 0 0/22% 22% 0 0;background:#0b0703;box-shadow:0 0 52px -6px rgba(92,73,200,.55),0 0 0 1px rgba(247,245,232,.12)}
.about-photo-arch img{display:block;width:100%;height:100%;object-fit:cover;object-position:3% 50%}
/* Biased left on purpose. The window stretches to the story's height, so between
   900px and 1200px it is 0.45-0.59 wide against the file's 0.8, and cover then
   shows only 57-72% of the width. Centred, that sliced the keyboard's wordmark
   and the side of his hair; taking the crop from the left edge keeps both whole,
   and at 1440 it moves the window by a few pixels that no one can see. */
.about-story{display:flex;flex-direction:column;justify-content:center;padding:clamp(24px,3.1vw,48px)}
.about-story h2{margin:0 0 clamp(12px,1.4vw,18px);font-size:clamp(26px,2.5vw,38px);line-height:1.1}
/* The second heading starts a new thought, so it gets a rule and the room above it
   that the first heading gets from the card's own padding. */
.about-story h2 ~ h2{margin-top:clamp(26px,2.8vw,38px);padding-top:clamp(22px,2.4vw,32px);border-top:1px solid rgba(247,245,232,.16)}
/* Paper at 84% rather than 100%: on a ground this dark, full paper shouts the body copy
   up to the weight of the headings, and it measures 12:1 either way. */
.about-story p{margin:0 0 clamp(12px,1.3vw,16px);font-size:clamp(15px,1.1vw,16.5px);line-height:1.62;color:rgba(247,245,232,.84);max-width:64ch}
.about-story p:last-child{margin-bottom:0}
/* How I work closes the story on a band of the same dark, so the pair above sits on
   the yellow between two edges of one colour. The single accent wash comes in from
   the right, where the quote stands; the rest of the band is the ground plus grain. */
.about-how{position:relative;overflow:clip;background-color:#140e07;background-image:var(--grain-work),radial-gradient(120% 620px at 55% -18%,rgba(92,73,200,.26) 0%,rgba(92,73,200,.07) 55%,rgba(92,73,200,0) 78%);background-size:160px 160px,auto;background-blend-mode:overlay,normal;color:var(--paper);padding:clamp(46px,5.6vw,88px) var(--pad)}
.about-how h2{margin:0 0 clamp(14px,1.6vw,22px);font-size:clamp(30px,3.4vw,54px)}
.about-how p{margin:0;max-width:60ch;font-size:clamp(15px,1.15vw,17px);line-height:1.6;color:rgba(247,245,232,.84)}
/* One line, set as large as the page will hold it: the quote is the end of the
   argument, not decoration on it. Fraunces at 120pt optical size is the same face the
   home page's statement is set in, and yellow on this dark measures 13:1. */
.about-quote{margin:clamp(30px,3.8vw,56px) 0 0;font-family:Fraunces,Georgia,serif;font-weight:380;font-size:clamp(32px,5.2vw,74px);line-height:1.06;letter-spacing:-.03em;color:var(--yellow);font-variation-settings:"opsz" 120,"SOFT" 0;text-wrap:balance}
.about-quote p{margin:0;font:inherit;color:inherit;letter-spacing:inherit;max-width:none}
/* ---- responsive ---- */
@media(max-width:900px){.mission-photo{float:none;width:min(100%,300px);margin:0 0 clamp(18px,3vw,26px)}.case-body,.teaser,.service-block{grid-template-columns:1fr}.page .header{padding:24px 6% 4px}.about-facts{gap:20px}.about-cards{grid-template-columns:1fr}.about-photo-arch{aspect-ratio:4/3;border-radius:50% 50% 0 0/32% 32% 0 0}}
@media(max-width:700px){.page-head h1{font-size:clamp(32px,8.6vw,52px)}.mission-lead{font-size:clamp(23px,6.4vw,32px)}.mission-statement{font-size:clamp(20px,5.4vw,26px)}.page{padding-top:var(--hdr,118px)}.header::after{height:calc(100% + 34px)}.process li{grid-template-columns:1fr;gap:4px}.process li::before{padding-top:0}.cta .actions{flex-direction:column;align-items:flex-start;gap:16px}.case h2{font-size:clamp(28px,8vw,44px)}}
/* One row on a phone. The bar used to wrap the links and the button onto two
   rows, and the nav's 230px cap then squeezed the button until its own label
   wrapped inside it: a 118px bar with 21px tap targets. The button carries a
   short label below 560px, the long one stays as its accessible name, every
   target is at least 44px, and the bar is 64px instead of 118px. */
.cta-short{display:none}
@media(max-width:700px){
  :root{--hdr:64px}
  .header{padding:10px 4.5%;align-items:center;gap:10px}
  .page .header{padding:10px 4.5%}
  .header .wordmark{display:inline-flex;align-items:center;min-height:44px}
  .header .wordmark-art{width:clamp(96px,25vw,118px)}
  .header nav{justify-content:flex-end;flex-wrap:nowrap;gap:clamp(8px,2.6vw,16px);font-size:13px;max-width:none}
  .header nav a{display:inline-flex;align-items:center;min-height:44px}
  .header .nav-cta{max-width:none;font-size:12px;padding:0 12px;min-height:44px;white-space:nowrap}
  .cta-full{display:none}
  .cta-short{display:inline}
}
@media(max-width:560px){
  .header .nav-cta{padding:0 10px}
}
/* At 320 the bar runs out of room: a 96px wordmark and the 4.5% gutter leave the nav
   about 185px for three links and the button, which want 205 — the CTA was cut off at
   the right edge on every page, with nothing to scroll to reach it. Tighten the gaps
   and the wordmark a shade; the type is already down to 13px and 12px here. */
@media(max-width:340px){
  .header,.page .header{gap:8px}
  .header .wordmark-art{width:84px}
  .header nav{gap:6px}
  .header .nav-cta{padding:0 8px}
}
.contact .form-head{font-size:clamp(26px,3vw,42px);letter-spacing:-.03em;line-height:1.05;margin-bottom:clamp(24px,3vw,40px)}.faq .service-list{padding-top:6px}
.contact-intro{max-width:460px}.enquiry-col{flex:1 1 400px;max-width:520px}.contact .process{max-width:none;margin-top:clamp(16px,2.2vw,28px)}.contact .process li{border-top-color:#f7f5e83d}.contact .process li::before{color:#f7f5e8a6}.contact .process strong{color:var(--paper)}.contact-intro .email{display:block;margin-top:clamp(20px,2.6vw,32px)}
/* ---- work index and single case studies ---- */
.work-index{background:var(--paper);padding-top:clamp(30px,4vw,56px)}.work-cards-lg{grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(20px,2.4vw,34px)}
.case-single{background:var(--paper);padding-top:clamp(30px,4vw,56px)}.case-single .case-body p{font-size:clamp(16px,1.45vw,18px)}
.page-head .section-label a{text-decoration:none}.page-head .section-label a:hover{text-decoration:underline}.page-head h1 .chip{font-size:clamp(11px,1.1vw,14px);margin-left:clamp(6px,.8vw,12px);vertical-align:middle;font-weight:500;letter-spacing:0}.case-note{max-width:70ch}
@media(max-width:700px){.case-single .case-body{grid-template-columns:1fr}}
@media(max-width:700px){.work-cards-lg{gap:14px}}
/* The homepage's four tiles. auto-fit with a 215px minimum decided the count
   from the width, which left the fourth card alone in a row of its own from
   about 960px down to 700px. Four across needs 4x215 plus gaps plus padding, so
   below 1080 they go two by two, and on a phone they stack. */
.work-cards:not(.work-cards-lg){grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:1080px){.work-cards:not(.work-cards-lg){grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.work-cards:not(.work-cards-lg){grid-template-columns:1fr}}
/* The work index has the same four cards at a larger size and had the same
   orphan: three across and one alone from about 1300px down. Four across needs
   roughly 1200px at this card size, so below that they go two by two, and one
   by one on a phone. */
@media(max-width:1199px){.work-cards-lg{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.work-cards-lg{grid-template-columns:1fr}}
/* ---- case study pages: figures, blocks, facts ---- */
.case-hero{margin:0 0 clamp(26px,3.4vw,46px)}
.case-hero img,.case-figure img{display:block;width:100%;height:auto;border:1px solid #352a1729;background:#352a170a}
.case-hero figcaption,.case-figure figcaption{font-size:13.5px;line-height:1.55;color:var(--muted);margin-top:11px;max-width:64ch}
.case-figure{margin:0}
/* A band is a figure that is wider than it is tall — a strip of page, a stepped
   list — so it reads better across the full container than squeezed into a
   column. It sits directly after the block it belongs to. */
.case-band{margin-top:clamp(20px,2.8vw,34px)}
.case-block{display:grid;grid-template-columns:minmax(0,.78fr) minmax(0,1.22fr);gap:clamp(24px,3.2vw,58px);align-items:start;margin-top:clamp(30px,4vw,52px);padding-top:clamp(28px,3.4vw,44px);border-top:1px solid #352a172e}
/* .case-block--flip puts the picture on the left and the argument on the right.
   The source order stays text-then-figure, so the reading order never changes —
   only the grid placement does. The column widths swap with it, or the text
   would end up in the wide column and the picture in the narrow one. */
.case-block--flip{grid-template-columns:minmax(0,1.22fr) minmax(0,.78fr)}
.case-block--flip>.case-text{order:2}
.case-block--flip>.case-figure{order:1}
/* A block with nothing to show reads as a wide paragraph, deliberately. */
.case-block--solo{display:block}
.case-block--solo .case-text{max-width:68ch}
/* Where a block has no screenshot, the second column carries the pieces of the
   job instead: one symbol and one name each. It is the quiet version of a figure
   — a diagram of what the work consisted of, without inventing a picture of it.
   The labels are the project's own scope, not a new list of services.
   The panel is centred against the text rather than stretched to its full height:
   these paragraphs run to 500px, and four tiles sharing that height would be
   slabs with a symbol lost in the corner of each. 132px is big enough to read as
   a card, small enough that the four still read as one object. */
.case-cards{list-style:none;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(132px,auto);gap:12px;margin:0;padding:0;align-self:center;align-content:start}
.case-cards li{display:flex;flex-direction:column;justify-content:center;gap:12px;min-width:0;padding:17px;border:1px solid #352a1729;border-radius:3px;background:#352a1708;font-size:14.5px;line-height:1.25;font-weight:600;letter-spacing:-.01em}
/* D:NA carries a line under each label: the four words on their own said what
   the work touched, not what it did. The label keeps the 14.5px weight the
   other studies use and the line sits under it at 12.5px in --muted, so the
   icon-plus-label still reads first. */
.case-card-text{display:grid;gap:3px;min-width:0}
.case-card-label{font-size:14.5px;line-height:1.25;font-weight:600;letter-spacing:-.01em}
.case-card-line{font-size:12.5px;line-height:1.4;font-weight:400;color:var(--muted)}
.case-cards svg{flex:none;width:26px;height:26px;color:var(--muted);fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
/* Two across needs about 200px a card before the longer labels wrap, and a
   wrapped card next to a short one looks broken. One column below that, where
   the tiles go back to the height of their own contents. */
@media(max-width:560px){.case-cards{grid-template-columns:1fr;grid-auto-rows:auto;align-self:start}.case-cards li{flex-direction:row;align-items:center;justify-content:flex-start;gap:12px;padding:13px 15px}}
.case-text{min-width:0}
.case-text h2{font-size:clamp(24px,2.7vw,38px);line-height:1.12;letter-spacing:-.03em;margin:0 0 clamp(12px,1.6vw,20px);max-width:28ch}
.case-text p{max-width:52ch;font-size:clamp(16px,1.45vw,18px)}
.case-text p+p{margin-top:1em}
.case-text p:last-child{margin-bottom:0}
/* Figures inside a two-column row are proof, not decoration: cap the very tall
   and very square ones so they sit beside the text instead of over it. */
.case-figure--square{max-width:min(100%,520px)}
@media(max-width:900px){.case-block{grid-template-columns:1fr;gap:clamp(20px,3vw,28px)}.case-block--flip{grid-template-columns:1fr}.case-block--flip>.case-text,.case-block--flip>.case-figure{order:0}.case-figure--square{max-width:100%}
/* Stacked, there is no second column to keep the measure short, so the cap has
   to do it on its own. 62ch is still a reading line, not a full-width one. */
.case-text p{max-width:62ch}}
.case-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:clamp(16px,2.4vw,34px);margin-top:clamp(30px,4vw,48px);padding-top:clamp(22px,2.6vw,32px);border-top:1px solid var(--ink);font-size:14px}
.case-facts h3{font-family:Space Grotesk,Manrope,sans-serif;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:0 0 6px}
.case-facts p{margin:0}
@media(max-width:700px){.case-text p,.case-hero figcaption,.case-figure figcaption{font-size:15.5px}}
/* ---- case study split hero: type on the left, screenshot in a browser shell ---- */
.case-head{display:grid;grid-template-columns:minmax(0,.94fr) minmax(0,1.06fr);gap:clamp(26px,3.6vw,56px);align-items:start;padding-bottom:clamp(26px,3.4vw,44px)}
.case-head h1{font-size:clamp(36px,4.9vw,80px);line-height:1.02;margin:0 0 clamp(14px,1.8vw,20px);max-width:15ch}
.case-head .lede{max-width:46ch}
.case-tags{list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin:clamp(16px,2vw,24px) 0 0;padding:0}
.case-tags li{font-family:Space Grotesk,Manrope,sans-serif;font-size:11.5px;line-height:1.25;letter-spacing:.07em;text-transform:uppercase;border:1px solid #352a1740;border-radius:999px;padding:5px 11px}
.case-detail{margin:clamp(14px,1.8vw,20px) 0 0;max-width:44ch;font-size:clamp(14.5px,1.25vw,16.5px);line-height:1.55}
.case-detail-label{display:block;font-family:Space Grotesk,Manrope,sans-serif;font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:#5b5138;margin-bottom:3px}
.browser{margin:0}
.browser-shell{border:1px solid #352a1733;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 24px 50px -28px #352a1759,0 3px 10px -4px #352a1721}
.browser-bar{display:flex;align-items:center;gap:7px;padding:11px 13px;background:#efece0;border-bottom:1px solid #352a1721}
.browser-dot{display:block;flex:0 0 auto;width:11px;height:11px;border-radius:50%}
.browser-dot--r{background:#ff5f56}.browser-dot--y{background:#ffbd2e}.browser-dot--g{background:#27c93f}
.browser-screen{display:block;line-height:0;background:#efece0}
.case-hero .browser-screen img{display:block;width:100%;height:clamp(210px,29vw,480px);object-fit:cover;object-position:top center;border:0;background:#efece0}
.case-head .case-hero{margin:0}
.case-head .case-hero figcaption{color:#4a3f28;max-width:54ch}
.case-head+.section.case-single{padding-top:clamp(24px,3vw,40px)}
@media(max-width:980px){.case-head{grid-template-columns:1fr;gap:clamp(22px,3vw,32px)}.case-head h1{font-size:clamp(34px,6.4vw,60px);max-width:20ch}.case-head .lede{max-width:52ch}.case-hero .browser-screen img{height:clamp(200px,44vw,380px)}}


/* ---- footer: full-bleed code stream behind an editorial grid ---- */
/* Replaces the old three-line flex footer. Everything footer-specific lives
   here so the earlier rules for it could be deleted outright. */
/* Top padding carries the fixed header's height as well as the band's own: at the
   document bottom the footer's top edge is inside the bar's zone, and without it
   the wordmark sat under the yellow strip on a phone. */
.footer{position:relative;isolation:isolate;overflow:clip;background:#1a150c;color:var(--paper);padding:calc(var(--hdr,92px) + clamp(34px,4.6vw,72px)) var(--pad) clamp(20px,2.4vw,30px)}
/* Layer 1: the studio's own CSS, markup and config scrolling behind the grid.
   aria-hidden and pointer-events:none in the markup, so it is texture only.
   Kept at 12% so the links always win without a scrim over it. Each column
   holds its own block of the site's CSS and markup, and the mask dissolves both
   edges so the loop seam is never on screen. */
.footer-stream{position:absolute;inset:0;z-index:-1;display:flex;align-items:flex-start;overflow:hidden;pointer-events:none;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;line-height:2.1;-webkit-mask-image:linear-gradient(to bottom,transparent,#000 16%,#000 74%,transparent);mask-image:linear-gradient(to bottom,transparent,#000 16%,#000 74%,transparent)}
.footer-stream-col{flex:1 1 0;min-width:0;overflow:hidden;white-space:pre;color:#f7f5e81f}
.footer-stream-col pre{margin:0;font:inherit;white-space:pre}
.footer-stream-col .c{color:#a4b2713d}
.footer-stream-col .k{color:#eee66b2b}
.footer-stream-col.is-live{animation:footer-stream linear infinite}
.footer-stream.is-paused .footer-stream-col{animation-play-state:paused}
@keyframes footer-stream{from{transform:translateY(0)}to{transform:translateY(calc(-100% / 3))}}
@media(prefers-reduced-motion:reduce){.footer-stream-col.is-live{animation:none}}
/* The switch. data-footer="plain" is the old footer: no stream and nothing for
   motion.js to build. Any other value, including none, keeps the code, so a page
   that forgets the attribute behaves as it did before. */
.footer[data-footer="plain"] .footer-stream{display:none}
/* Layer 2: the editorial grid over the top. */
/* Two nav columns, not four. The project names lived in the Work column and the
   service lines in the Services column; both went on 7 November 2026, along with
   the overflow-wrap that had been letting the mailto address break mid-word
   inside a narrow column. With the halves now even, the address fits on one line
   and .footer-email keeps it there. */
.footer-inner{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(28px,4vw,64px);align-items:start}
.footer .wordmark-art{width:clamp(190px,23vw,330px)}
.footer-tagline{font-size:clamp(24px,2.5vw,36px);line-height:1.1;letter-spacing:-.025em;font-weight:600;margin:clamp(18px,2.2vw,28px) 0 0;max-width:20ch}
.footer-sub{margin:clamp(10px,1.4vw,16px) 0 0;max-width:36ch;font-size:14.5px;line-height:1.55;color:#f7f5e8a6}
.footer-cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(20px,2.4vw,34px)}
.footer-col-title{font-family:Space Grotesk,Manrope,sans-serif;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:#f7f5e8b3;margin:0 0 12px}
.footer-cols ul{list-style:none;display:grid;gap:8px;margin:0;padding:0;font-size:14.5px;line-height:1.35}
.footer-cols li{min-width:0}
.footer-cols .footer-email{white-space:nowrap}
.footer-cols a{color:inherit;text-decoration:none}
.footer-cols a:hover{color:var(--yellow);text-decoration:underline;text-underline-offset:4px}
/* The footer mark is a link in there like the rest, so it answers with the same
   yellow. currentColor carries it into both halves of the logotype — the masked
   word and the dot that sits over it — so nothing has to be named twice. */
.footer .wordmark{transition:color .25s ease}
.footer .wordmark:hover{color:var(--yellow)}
.footer-bottom{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:clamp(10px,1.6vw,24px);margin-top:clamp(34px,4.2vw,60px);padding-top:clamp(14px,1.8vw,20px);border-top:1px solid #f7f5e826;font-size:12.5px;color:#f7f5e8a6}
.footer-bottom p{margin:0}
.footer-utils{list-style:none;display:flex;gap:20px;margin:0;padding:0}
.footer-utils a{color:inherit;text-decoration:none}
.footer-utils a:hover{color:var(--paper)}
@media(max-width:900px){.footer-inner{grid-template-columns:1fr;gap:clamp(26px,4vw,40px)}}
/* Between 701px and 900px the second and third stream columns are dropped rather
   than squeezed. A phone is the exception and gets two — see the 700px block. */
@media(min-width:701px) and (max-width:900px){.footer-stream-col:nth-child(n+2){display:none}}
/* Below 900px the wordmark is small enough to sit clear of the fixed bar at the
   document bottom, which the padding above it and the header's own height both
   allow for. Below 700px both the wordmark and the stream are set for a phone. */
@media(max-width:700px){
  /* The wordmark and the stream stay on a phone, smaller. The 158px of padding
     that used to sit above the text was reserved for a wordmark that was
     display:none, which is what left the blank gap at the bottom of every page.
     The gap is gone; the wordmark is back at 150–190px instead of 190–330px. */
  .footer{padding-top:clamp(42px,9vw,58px)}
  .footer .wordmark{display:inline-block}
  .footer .wordmark-art{width:clamp(150px,40vw,190px)}
  .footer-cols{grid-template-columns:1fr;gap:clamp(22px,5vw,30px)}
  .footer-bottom{justify-content:flex-start}
  /* Same monospace, same colours, a shorter snippet at a smaller size. Two
     columns, not one: the left one stays where it has always been, behind the
     wordmark and the links, and a second strip runs down the right-hand edge of
     the screen. The left block is capped at 31 characters and the strip is 116px
     wide at its narrowest, so at 320px the two clear each other and neither cuts
     a token: the strip's own block stops at 18. */
  .footer-stream{display:block;font-size:10.5px;line-height:1.8;max-height:600px}
  .footer-stream-col{position:absolute;top:0}
  .footer-stream-col:nth-child(1){left:0;width:100%}
  .footer-stream-col:nth-child(2){right:0;width:clamp(116px,30vw,190px)}
  /* A little more than the desktop 12%, because 10.5px monospace loses more of
     itself to the compositing than 11.5px does. Enough to read as code. */
  .footer-stream-col{color:#f7f5e826}
  .footer-stream-col .c{color:#a4b27147}
  .footer-stream-col .k{color:#eee66b3d}
}
/* A 568px-tall screen cannot hold this footer at its full rhythm: the content
   alone is about 530px, so at the document bottom the top of the footer is off
   screen and the wordmark would sit under the fixed bar. On those screens only,
   the footer tightens until it fits the viewport with the wordmark clear. */
@media(max-width:700px) and (max-height:600px){
  .footer{padding-top:30px;padding-bottom:14px}
  .footer .wordmark-art{width:132px}
  .footer-tagline{font-size:22px;margin-top:10px}
  .footer-sub{font-size:13px;line-height:1.4;margin-top:8px}
  .footer-inner{gap:16px}
  .footer-cols{gap:14px}
  .footer-bottom{margin-top:18px;padding-top:12px}
  .footer-stream{max-height:520px}
}

/* ---- phase 3, tentative: the pointer label over work cards ---- */
/* The label is created by motion.js and only appears for a mouse. It is small on
   purpose: a paper pill beside the pointer, not under it, so the real cursor is
   never covered and the card is never hidden. To remove the whole feature, delete
   this block, the "Phase 3, tentative" block at the end of motion.js, and the
   data-cursor attributes on .work-card. */
.cursor-label{position:fixed;left:0;top:0;z-index:7;pointer-events:none;font-family:Space Grotesk,Manrope,sans-serif;font-size:11px;line-height:1;letter-spacing:.09em;text-transform:uppercase;color:var(--ink);background:var(--paper);border-radius:999px;padding:8px 12px;opacity:0;box-shadow:0 4px 14px -6px #352a1759;transform:translate3d(-200px,-200px,0);transition:opacity .14s ease}
.cursor-label.is-on{opacity:1}
@media(hover:none),(pointer:coarse),(prefers-reduced-motion:reduce){.cursor-label{display:none!important}}


/* ---- pricing: one component, the homepage band and the services block ---- */
/* Everything inside the band is written by pricing.js from one config block, so
   no figure is stated twice. The cards take the treatment the why band's cards
   already have — cream on the yellow field, the same soft shadow, the same lift
   to 1.02 over 180ms — because they are the same kind of object: a sheet of paper
   on a yellow wall. The lift is off under reduced motion, as everywhere else. */
/* The wall behind the cards, on both pages: yellow, with a sea of dots drawn on it
   by texture-dots.js — a halftone grid whose dots swell and thin along diagonal
   fields, so the band reads as a surface the cards were set down on. The texture is
   a canvas rather than a repeating background because a repeating background can
   only repeat: one size of dot is graph paper, and prices on graph paper look like a
   plot. The band is the positioning context for that canvas, and nothing else in
   here is absolute, so nothing else moves. */
.pricing{position:relative;background-color:var(--yellow)}
/* position/inset/z-index as asked of the canvas: it fills the band, sits under the
   content, and takes no pointer. Width and height are percentages because a canvas
   is a replaced element — inset alone would leave it at its intrinsic 300x150. */
.pricing-dots{position:absolute;inset:0;z-index:0;width:100%;height:100%;pointer-events:none}
/* The band's own children have to be lifted over the canvas. A z-index of 0 is still
   a positioned box, so it paints above in-flow text and above the cards' own
   position:relative; these three rules are the whole of what keeps the figures,
   the notes and the VAT line readable on top of the texture. */
.pricing-head,.pricing-body,.pricing-vat{position:relative;z-index:1}
.pricing-head{display:flex;align-items:end;justify-content:space-between;gap:clamp(18px,4vw,60px);margin-bottom:clamp(24px,3.2vw,40px)}
.pricing-head h2{font-size:clamp(28px,3.4vw,52px);line-height:1.08;letter-spacing:-.03em;margin:0;max-width:22ch}
/* On the services page the band sits inside the section that holds the five
   things we do, and that section is cream. The band therefore runs the full width
   of the screen and carries the text column back in with the same padding, so the
   yellow reads as a band across the page rather than a block that lost its edges. */
.pricing-inline{margin-inline:calc(var(--pad) * -1);padding:clamp(30px,4.2vw,58px) var(--pad)}
.pricing-cards{list-style:none;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(16px,2vw,28px);margin:0;padding:0;align-items:stretch}
.plan{position:relative;z-index:1;display:flex;flex-direction:column;background:var(--paper);color:var(--ink);border-radius:3px;padding:clamp(18px,2vw,28px);box-shadow:0 24px 46px -22px #352a1747,0 2px 6px -3px #352a1724;transition:transform .18s ease,box-shadow .18s ease}
.plan:hover,.plan:focus-within{transform:scale(1.02);box-shadow:0 30px 54px -24px #352a1766,0 4px 10px -4px #352a1733}
/* Recommended is an eyebrow inside the card now, not a sticker hanging off its top
   edge: the plan name and the word share one baseline row, the way section four's
   eyebrow sits under its heading, and that row is in all three cards so the three
   names still line up across the row. It carries --accent-dark because that is the
   one purple that clears AAA at this size on paper — 7.9:1 — and because taking the
   accent off the middle button left the accent with nowhere else to live in this
   band. Below the flex row it wraps under the name rather than shrinking. */
.plan-head{display:flex;align-items:baseline;justify-content:space-between;gap:clamp(8px,1vw,14px);flex-wrap:wrap}
.plan-tab{margin:0;font-family:Space Grotesk,Manrope,sans-serif;font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;line-height:1;color:var(--accent-dark);white-space:nowrap}
/* The timeline line: a rule across the top of the card with a dot at its left
   end, so the card opens with when rather than with a number. */
.plan-top{position:relative;margin:0 0 clamp(12px,1.4vw,16px);padding:13px 0 0 15px;border-top:2px solid var(--ink);font-family:Space Grotesk,Manrope,sans-serif;font-size:12.5px;line-height:1.35;color:var(--muted)}
.plan-top::before{content:"";position:absolute;left:0;top:17px;width:7px;height:7px;border-radius:50%;background:var(--ink)}
.plan-name{font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(19px,1.7vw,23px);font-weight:650;letter-spacing:-.025em;line-height:1.15;margin:0}
.plan-price{display:flex;align-items:baseline;gap:7px;margin:8px 0 0}
.plan-from{font-size:13.5px;color:var(--muted)}
.plan-amount{font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(30px,3vw,40px);font-weight:650;letter-spacing:-.035em;line-height:1;font-variant-numeric:tabular-nums}
.plan-desc{margin:clamp(12px,1.4vw,16px) 0 0;font-size:15px;line-height:1.5}

/* Two dashed hairlines: one between the description and what is included, one
   between what is included and the button. Dashed because they divide a sheet of
   paper rather than a table. */
.plan-points{list-style:none;display:grid;gap:9px;margin:clamp(14px,1.6vw,20px) 0 0;padding:clamp(14px,1.6vw,18px) 0;border-top:1px dashed #352a1740;font-size:14.5px;line-height:1.5}
.plan-points li{position:relative;padding-left:17px}
.plan-points li::before{content:"";position:absolute;left:1px;top:.55em;width:5px;height:5px;border-radius:50%;background:var(--ink);opacity:.6}
/* margin-top:auto pins the button to the bottom of the tallest card in the row,
   so three cards of different lengths still line their buttons up. */
.plan-action{margin-top:auto;padding-top:clamp(15px,1.7vw,20px);border-top:1px dashed #352a1740}
/* All three buttons are the same ink fill now. The middle one used to carry the
   accent so the card argued for itself; instead the eyebrow above the name does the
   pointing, in a small piece of type rather than a slab of colour, so nothing on the
   row looks more pressable than the thing next to it. Hover is the accent on all
   three, which is what a link does everywhere else on the site. */
.plan-cta{display:flex;align-items:center;justify-content:center;min-height:46px;padding:0 18px;border-radius:3px;background:var(--ink);color:var(--paper);font-family:Space Grotesk,Manrope,sans-serif;font-size:14.5px;font-weight:650;text-decoration:none;text-align:center;transition:background .16s ease}
.plan-cta:hover{background:var(--accent)}
/* The site's focus ring is currentColor, which on an ink button with paper text
   would be paper on cream and therefore invisible. This control sets its own. */
.plan-cta:focus-visible{outline:3px solid var(--ink);outline-offset:3px}
.pricing-notes{display:grid;gap:7px;margin:clamp(22px,2.6vw,34px) 0 0;max-width:76ch;font-size:14.5px;line-height:1.55}
.pricing-notes p{margin:0}
/* The first note qualifies the timelines above it, so it sits closest and goes
   a size down: it is a footnote, not a third paragraph. It stays at ink rather
   than the muted tone — #726a4c on the yellow is 4.16:1, and a footnote nobody
   can read is not a footnote. */
.pricing-note.is-foot{font-size:13px}
/* The VAT line is a footnote underneath the figures, never a heading over them: below
   the cards and their notes, a size down, and at ink rather than the muted tone, for
   the same reason the note above is — #726a4c on the yellow is 4.16:1. */
.pricing-vat{margin:clamp(18px,2.2vw,28px) 0 0;font-size:13px;line-height:1.5;max-width:70ch}
.pricing-fallback{margin:0;max-width:58ch;font-size:15px;line-height:1.55}
@media(max-width:900px){
  /* Stacked, so the cards need a wider gap than the side-by-side row did to read as
     three separate sheets rather than one column. */
  .pricing-cards{grid-template-columns:1fr;gap:clamp(26px,5vw,34px)}
}
@media(prefers-reduced-motion:reduce){.plan{transition:none}.plan:hover,.plan:focus-within{transform:none}}


/* ---- services: the night banner -------------------------------------------
   The homepage keeps the illustration as live, parallaxed SVG. Services gets a
   still from the same drawing — one column of arched windows, one of them lit —
   because this page's job is reading, not looking, and 1.5 MB of markup behind a
   paragraph is a tax on the paragraph. Two crops, art-directed: the wide one puts
   the window right of centre so the H1 has dark facade to sit on, the tall one
   centres it above the type on a phone.

   background-position carries the same 61%/48% the crop was framed around, so the
   glow lands on the window at any viewport shape: a percentage position maps the
   image's own 61%/48% point onto the box's 61%/48% point, whatever cover has had
   to crop. */
.svc-hero{position:relative;isolation:isolate;overflow:clip;display:flex;min-height:calc(100svh - var(--hdr,92px));background:#101c24 url("assets/services-hero-wide.webp") 61% 48%/cover no-repeat;color:var(--paper);padding:clamp(20px,2.6vw,34px) var(--pad) clamp(44px,4.6vw,68px)}
/* The scrim. A warm-dark wash up from the bottom for the H1 and the lede, ink at
   94% on the bottom edge and gone by 74% of the height so the windows above stay
   windows; plus a shorter wash in from the left, because the type is over there.
   Neither reaches the lit window at 61%/48%. */
.svc-hero::before{content:"";position:absolute;inset:0;z-index:0;background:linear-gradient(to top,rgba(9,14,19,.94),rgba(9,14,19,.82) 16%,rgba(9,14,19,.46) 38%,rgba(9,14,19,.12) 58%,rgba(9,14,19,0) 74%),linear-gradient(to right,rgba(9,14,19,.66),rgba(9,14,19,.24) 38%,rgba(9,14,19,0) 62%)}
/* The one moving thing, and it is optional: the window breathing. Off under
   reduced motion, where the still stays still. */
.svc-hero-glow{position:absolute;left:61%;top:48%;width:clamp(120px,15vmin,230px);aspect-ratio:1;transform:translate(-50%,-50%);background:radial-gradient(circle,rgba(242,237,76,.22),rgba(242,237,76,.07) 46%,rgba(242,237,76,0) 70%);z-index:1;pointer-events:none;animation:svc-glow 6.5s ease-in-out infinite alternate}
@keyframes svc-glow{from{opacity:.45}to{opacity:1}}
.svc-hero-inner{position:relative;z-index:2;display:flex;flex-direction:column;justify-content:flex-end;width:100%;max-width:1560px;margin-inline:auto}
.svc-hero-foot{display:flex;align-items:flex-end;justify-content:space-between;gap:clamp(20px,4vw,64px)}
.svc-hero h1{margin:0;max-width:15ch;font-size:clamp(38px,4.9vw,84px);line-height:1.03;letter-spacing:-.04em;font-weight:700;color:var(--yellow)}
/* The lede and the button are a column of their own, standing on the same bottom
   edge as the H1 rather than centred against it. The air under them is the hero's
   own bottom padding (66px at 1440, 38px on a phone), so the pair floats inside
   the window instead of resting on the seam; the gap between them is the pause a
   lede takes before a button. */
.svc-hero-side{display:flex;flex-direction:column;align-items:flex-start;gap:clamp(16px,2vw,24px);max-width:36ch;padding-bottom:4px}
.svc-hero-lede{margin:0;font-size:clamp(15px,1.35vw,18px);line-height:1.5}
@media(max-width:700px){
  .svc-hero{min-height:80svh;background-image:url("assets/services-hero-tall.webp");background-position:50% 50%;padding-bottom:clamp(38px,7vw,50px)}
  .svc-hero-glow{left:50%;top:50%}
  .svc-hero-foot{flex-direction:column;align-items:flex-start;gap:clamp(16px,4vw,24px)}
  .svc-hero h1{max-width:none;font-size:clamp(30px,9vw,44px)}
  .svc-hero-side{max-width:none;padding-bottom:0}
}
@media(prefers-reduced-motion:reduce){.svc-hero-glow{animation:none}}

/* ---- services: the overview band ------------------------------------------
   The yellow band the page already had, kept because it is the one place the three
   prices sit side by side and a card needs a wall behind it. */
@media(max-width:900px){.pricing-overview .pricing-head{flex-direction:column;align-items:flex-start;gap:14px}}

/* ---- services: the three tiers --------------------------------------------
   Cream, yellow, cream. The marked tier is the one wall of yellow, so the page
   reads light, marked, light rather than dark-brown/yellow/dark-brown: the dark
   ground belongs to the extras band below, where it grounds the page instead of
   interrupting it. */
.svc-tier{padding:clamp(46px,6vw,88px) var(--pad)}
.svc-tier.is-paper{background:var(--paper)}
.svc-tier.is-yellow{background:var(--yellow)}
/* The heading row is a rule with the name at one end and when at the other, the
   same shape as the timeline line at the top of a card. */
.svc-tier-head{display:flex;align-items:baseline;justify-content:space-between;gap:clamp(12px,3vw,40px);flex-wrap:wrap;padding-bottom:clamp(10px,1.4vw,15px);border-bottom:1px solid var(--ink)}
.svc-tier-title{display:flex;align-items:baseline;gap:clamp(10px,1.4vw,16px);flex-wrap:wrap}
.svc-tier h2{margin:0;font-size:clamp(29px,3.7vw,56px);line-height:1.02;letter-spacing:-.04em}
.svc-tier-when{margin:0;font-family:Space Grotesk,Manrope,sans-serif;font-size:12px;font-weight:650;letter-spacing:.11em;text-transform:uppercase;line-height:1.4;opacity:.72}
.svc-tier-intro{margin:clamp(18px,2.2vw,26px) 0 0;max-width:60ch;font-size:clamp(16px,1.5vw,19px);line-height:1.5}
/* Three columns, not three cards. The intro directly above has already said what
   the tier is for; repeating that in three sheets of paper made the section read as
   a brochure rather than as an answer. One hairline closes the intro, and the three
   headings then stand on whatever ground their section already has — ink on cream,
   ink on yellow — with the type doing the separating: a name, a price, four lines.
   Nothing here is pressable, so nothing gets a radius, a shadow or a lift. */
.svc-cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(18px,2.6vw,40px);margin-top:clamp(24px,3vw,38px);padding-top:2rem;border-top:1px solid rgba(26,21,12,.15);align-items:start}
.svc-col{display:flex;flex-direction:column}
.svc-col-name{margin:0;font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(16px,1.35vw,18px);font-weight:650;letter-spacing:-.02em;line-height:1.2}
/* One size for all three prices, because they are not the same kind of number:
   "from £1,000" is the decision, "logo design from £600" is a footnote to the
   decision. Setting the long ones smaller would rank things the copy doesn't. */
.svc-col-price{margin:7px 0 0;font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(21px,1.85vw,26px);font-weight:650;letter-spacing:-.03em;line-height:1.15;font-variant-numeric:tabular-nums}
.svc-col-points{list-style:none;display:grid;gap:8px;margin:clamp(12px,1.4vw,16px) 0 0;padding:clamp(12px,1.4vw,16px) 0 0;border-top:1px solid rgba(26,21,12,.15);font-size:14px;line-height:1.5}
.svc-col-points li,.svc-how-list li{position:relative;padding-left:16px}
.svc-col-points li::before,.svc-how-list li::before{content:"";position:absolute;left:1px;top:.55em;width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.55}
/* The bold lead: the first few words do the scanning, the rest can be read. */
.svc-col-points strong,.svc-how-list strong,.svc-tier-intro strong{font-weight:650}
.svc-tier-foot{display:flex;align-items:center;justify-content:space-between;gap:clamp(16px,3vw,40px);flex-wrap:wrap;margin-top:clamp(20px,2.6vw,30px)}
.svc-tier-foot-note{margin:0;max-width:62ch;font-size:14px;line-height:1.5}
.svc-tier-foot .button{flex:0 0 auto}
/* Every tier's button is the ink one, not just the yellow tier's. A yellow button on
   the cream sections was a warm shape on a warm ground — the least pressable thing in
   the section — while the yellow tier had already solved it with the ink fill. One
   rule for all three, so the three closing buttons match the overview's. */
.svc-tier-foot .button{background:var(--ink);color:var(--paper)}
.svc-tier-foot .button:hover{background:var(--accent);color:var(--paper)}
/* The site's focus ring is currentColor, which on an ink button would be paper text
   on cream, so this control sets its own, as the plan cards do. */
.svc-tier-foot .button:focus-visible{outline:3px solid var(--ink);outline-offset:3px}
@media(max-width:900px){
  .svc-cols{grid-template-columns:1fr;gap:clamp(24px,5vw,32px)}
  .svc-tier-foot{flex-direction:column;align-items:flex-start;gap:18px}
}

/* ---- services: extras ------------------------------------------------------
   The one section that is not a choice between three things, and the one with no
   price list to compare: it sits on ink so the page stops floating, and the two
   cream sections either side of it still read as one page. Modules, not cards —
   hairlines and no shadows, so nothing here looks pressable. */
.svc-extras{background-color:var(--ink);background-image:var(--grain-dark);background-size:160px 160px;background-blend-mode:overlay;color:var(--paper);padding:clamp(46px,6vw,86px) var(--pad)}
.svc-extras-head{display:flex;align-items:baseline;justify-content:space-between;gap:clamp(14px,3vw,40px);flex-wrap:wrap;margin-bottom:clamp(22px,3vw,36px)}
.svc-extras h2{margin:0;font-size:clamp(28px,3.4vw,52px);line-height:1.05;letter-spacing:-.035em;color:var(--paper)}
.svc-extras-head p{margin:0;font-size:clamp(14px,1.3vw,16px)}
.svc-extras-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:0 clamp(16px,2.4vw,32px)}
.svc-extra{display:flex;flex-direction:column;gap:6px;padding:clamp(14px,1.6vw,20px) 0;border-top:1px solid #f7f5e82e}
.svc-extra-name{margin:0;font-family:Space Grotesk,Manrope,sans-serif;font-size:clamp(15px,1.25vw,17px);font-weight:650;letter-spacing:-.015em;line-height:1.25;color:var(--paper)}
.svc-extra-line{margin:0;font-size:13.5px;line-height:1.5;color:#f7f5e8c4}
.svc-extra-price{margin:auto 0 0;padding-top:10px;font-family:Space Grotesk,Manrope,sans-serif;font-size:13px;font-weight:650;letter-spacing:.02em;color:var(--yellow)}
@media(max-width:1023px){.svc-extras-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.svc-extras-grid{grid-template-columns:1fr}.svc-extras-head{flex-direction:column;align-items:flex-start;gap:10px}}

/* ---- services: hosting and the terms --------------------------------------
   Two more rows in the same shape as the jobs at the top of the page: the heading
   in the narrow column, the answer in the wide one. They are the questions asked
   after the price, so they follow the extras rather than sitting beside them. */
.svc-hosting,.svc-how{background:var(--paper)}
.svc-hosting{padding-bottom:clamp(24px,3vw,44px)}
.svc-how{padding-top:0}
.svc-how-list{list-style:none;margin:0;padding:0;display:grid;gap:12px;font-size:clamp(15px,1.4vw,17px);line-height:1.55}

/* Keep a direct route to the form when the process stacks above it. */
.enquiry-shortcut{display:none}
#enquiry-name{scroll-margin-top:calc(var(--hdr,100px) + 24px)}
.mission-statement + .mission-statement{margin-top:.7em}
@media(max-width:700px){.enquiry-shortcut{display:inline-flex;margin-top:24px}}

/* D:NA: show the publishing and booking work alongside the visual identity. */
.dna-publishing{padding:clamp(24px,3vw,42px);background:var(--yellow);border:1px solid #352a1729}
.dna-publishing ol{list-style:none;counter-reset:publish;padding:0;margin:22px 0}
.dna-publishing li{counter-increment:publish;position:relative;padding:18px 0 18px 42px;border-top:1px solid #352a1733}
.dna-publishing li:before{content:counter(publish,decimal-leading-zero);position:absolute;left:0;top:21px;font-size:13px}
.dna-publishing strong,.dna-publishing span{display:block}
.dna-publishing strong{font-size:22px;margin-bottom:8px}
.dna-publishing span,.dna-publishing-note{font-size:16px;line-height:1.6}
.dna-publishing-note{margin:0;border-top:1px solid #352a1733;padding-top:18px}
.dna-booking{grid-template-columns:minmax(0,1.3fr) minmax(0,.7fr)}
.dna-booking-shot{width:min(100%,350px);justify-self:center}
@media(max-width:900px){.dna-booking{grid-template-columns:1fr}}

.privacy-copy{max-width:900px;margin:auto}.privacy-copy h2{font-size:clamp(25px,3vw,38px);margin:36px 0 16px}.privacy-copy p{max-width:70ch}.privacy-copy a,.enquiry .consent a{text-decoration:underline;text-underline-offset:3px}
