/*
Theme Name: DFAV Large Image Specialists
Theme URI: https://dataflowav.co.uk
Author: Dataflow AV
Description: Editorial theme for Dataflow AV — large image specialists. Company story, services, case studies, team, group brands and accreditations.
Version: 1.9.49
Requires at least: 6.0
Tested up to: 6.8
Requires PHP: 7.4
License: GPL-2.0-or-later
Text Domain: dfav
*/

:root{
  --bg:#FDFEFF; --bg-2:#9ACD32; --bg-3:#8CBE28;
  --fg:#2C3137; --fg-2:#4E545B; --fg-3:#6D747B;
  --rule:rgba(44,49,55,.14); --rule-2:rgba(44,49,55,.28);
  --brand:#9ACD32; --brand-text:#3E5A0B;
  --accent:#B02D95; --accent-soft:rgba(176,45,149,.12); --accent-lit:#DE7CCB;
  --brand-lit:#D6F189;
  --deep:#FDFEFF; --deep-2:#FDFEFF; --deep-fg:#2C3137; --deep-fg-2:#4E545B;
  --display:"Archivo","Helvetica Neue",Arial,sans-serif;
  --body:"Karla","Helvetica Neue",Arial,sans-serif;
  --gut:clamp(20px,4.2vw,64px);
  --rail:clamp(0px,11vw,158px);
}

*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--body);
  font-size:16.5px;line-height:1.62;-webkit-font-smoothing:antialiased}
img,svg,video{max-width:100%;display:block}
a{color:inherit}
h1,h2,h3{font-family:var(--display);font-weight:700;line-height:1.06;
  letter-spacing:-.012em;text-wrap:balance;margin:0}
p{margin:0}
:focus-visible{outline:2.5px solid var(--brand);outline-offset:3px}

.wrap{max-width:1360px;margin:0 auto;padding-inline:var(--gut)}
.spread{position:relative;padding-block:clamp(64px,9vw,130px);border-top:1px solid var(--rule)}
.spread--deep{background:var(--deep);color:var(--deep-fg);border-top:none}
.spread--deep .kicker{color:var(--brand)}
.spread--tint{background:var(--bg-2)}
/* full brand green bands: darken the ink that sits directly on them,
   and reset it inside the white tiles so cards keep the neutral palette */
.spread--tint{color:#FFFFFF;
  --fg:#FFFFFF;--fg-2:#20290B;--fg-3:#33400F;--accent:#FFFFFF;
  --rule:rgba(255,255,255,.55);--rule-2:rgba(255,255,255,.75)}
.spread--tint .folio__mark{color:#FFFFFF}
.spread--tint .svc__n{color:#FFFFFF}
.spread--tint .svc__row:hover h3{color:rgba(255,255,255,.82)}
.spread--tint .grid9{fill:#FFFFFF}
.spread--tint .more a{color:#FFFFFF;border-bottom-color:#FFFFFF}
.spread--tint .more a:hover{color:#FFFFFF;opacity:.82}
.spread--tint .card,.spread--tint .acc>div,.spread--tint .tl>div,.spread--tint .brands>a,
.spread--tint .qa>div,.spread--tint .form{
  color:#2C3137;
  --fg:#2C3137;--fg-2:#4E545B;--fg-3:#6D747B;--accent:#B02D95;
  --rule:rgba(44,49,55,.14);--rule-2:rgba(44,49,55,.28)}
.spread--tint .more a{border-bottom-color:#2B380F}
.spread--tint .thesis blockquote em{color:#FFFFFF;font-weight:600}
/* a green button on a green band is invisible — go dark, as the closing band does */
.spread--tint .btn{background:#15180F;color:#F4F5F0}
.spread--tint .btn--ghost{background:#FDFEFF;color:#15180F;box-shadow:none}
.spread--tint .btn--ghost:hover{background:#FFFFFF}

.h2{font-family:var(--display);font-size:clamp(30px,4.6vw,60px);letter-spacing:-.032em;
  line-height:1.01;font-weight:800;max-width:30ch;text-wrap:balance}
.h2 em{font-style:normal;font-weight:800;color:var(--accent)}
.spread--tint .h2 em{color:#2E2136}

/* folio rail with the 3x3 mark motif */
.folio{display:grid;grid-template-columns:var(--rail) 1fr;gap:clamp(0px,2.2vw,34px);
  align-items:start}
.folio__mark{font-family:var(--body);font-size:13px;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase;color:var(--fg-2);padding-top:clamp(2px,.7vw,11px);display:flex;
  flex-direction:row;align-items:center;gap:11px;padding-right:14px;line-height:1.35;
  overflow-wrap:break-word;min-width:0}
.spread--deep .folio__mark{color:var(--deep-fg-2)}
.folio__mark .n{color:var(--accent);font-weight:500}
.spread--deep .folio__mark .n{color:var(--brand)}
.grid9{width:25px;height:25px;flex:none;fill:var(--brand)}
/* The section's name rides down the page with you. These sections run for
   several screens, and once the name had scrolled away there was nothing left
   saying which one you were in. The mark has the gutter to itself, so it can
   stay there without ever crossing the words. It lets go when its section
   ends, which is how you know you have left it. */
@media(min-width:861px){
  .spread .folio__mark{position:sticky;
    top:calc(var(--head,96px) + clamp(30px,3.4vw,52px));
    align-self:start;z-index:3}
}
@media(max-width:860px){.folio{grid-template-columns:1fr;gap:16px}
  .folio__mark{flex-direction:row;align-items:center;gap:14px;padding-top:0}}

.kicker{font-family:var(--body);font-size:12px;font-weight:600;letter-spacing:.22em;
  text-transform:uppercase;color:var(--accent);margin-bottom:1.5em}

/* header */
.top{position:sticky;top:0;z-index:60;background:color-mix(in srgb,var(--bg) 90%,transparent);
  backdrop-filter:blur(14px);border-bottom:1px solid var(--rule)}
/* WordPress pins its own bar over the top of the page for a signed in editor and
   pushes the document down to make room. Sticking to 0 would send the header up
   underneath it on the first scroll, which is why the logo appeared to slide up
   and touch the top of the screen. Stick below the bar instead. Visitors never
   see the bar, so nothing changes for them. */
body.admin-bar .top{top:32px}
@media screen and (max-width:782px){body.admin-bar .top{top:46px}}
.top__in{display:flex;align-items:center;gap:clamp(12px,1.9vw,28px);
  height:clamp(118px,10.2vw,148px);max-width:1360px;margin:0 auto;padding-inline:var(--gut)}
.brandlink{flex:none;display:block}
/* the logo file carries more transparent space below its ink than above, so
   centring the box leaves the ink sitting high — measured at 31px clear above
   and 34px below. This nudges it down until the two match, and because the row
   is centred the margin only shifts it by half, hence twice the difference.
   The header's own height is untouched. */
.brandlink img{height:clamp(78px,7.4vw,108px);width:auto}
.brandlink > img,.brandlink .brandmark{
  margin-top:calc(clamp(78px,7.4vw,108px) * 0.0275)}
.brandmark{position:relative;display:block}
.only-dark{display:none}

.nav{display:flex;gap:clamp(16px,2.1vw,32px);margin-left:auto;align-items:center;
  font-family:var(--body);font-weight:600}
.nav a{position:relative;font-size:16.5px;text-decoration:none;color:var(--fg-2);letter-spacing:.01em;
  padding:6px 0;border-bottom:1.5px solid transparent;transition:color .18s,border-color .18s}
.nav a + a::before{content:"";position:absolute;left:calc(-1 * clamp(8px,1.05vw,16px));
  top:50%;translate:0 -50%;width:1px;height:16px;background:var(--rule-2)}
.nav a:hover{color:var(--fg);border-bottom-color:var(--brand)}
.tel{font-family:var(--body);font-size:21px;font-weight:600;color:var(--fg);
  text-decoration:none;white-space:nowrap;letter-spacing:.005em;
  border-bottom:2px solid var(--brand);padding-bottom:3px;transition:color .18s}
.tel:hover{color:var(--brand-text)}
.btn{display:inline-flex;align-items:center;white-space:nowrap;background:var(--brand);color:#15180F;
  font-family:var(--body);font-weight:600;font-size:15px;letter-spacing:.02em;
  text-decoration:none;padding:.8em 1.35em;border-radius:2px;
  transition:transform .16s,filter .16s}
.btn:hover{filter:brightness(1.07);transform:translateY(-1px)}
.btn--ghost{background:transparent;color:var(--fg);box-shadow:inset 0 0 0 1.5px var(--rule-2)}
.hero .btn--ghost,.spread--deep .btn--ghost,.pagehero .btn--ghost{color:#FFFFFF;
  box-shadow:inset 0 0 0 1.5px var(--rule-2)}
.btn--sm{font-size:13px;padding:.62em 1.05em;letter-spacing:.04em}
@media(max-width:1150px){.nav,.tel{display:none}
  /* the links are what pushed this side of the row over to the right; with them
     gone the button and the menu have to do it themselves, or they sit stranded
     in the middle of the header */
  .top__in > .btn{margin-left:auto}
  /* and at 13px the button was being read at arm's length on a phone */
  .top .btn--sm{font-size:15px;padding:.74em 1.2em;letter-spacing:.03em}}
@media(max-width:560px){.brandlink img{height:62px}.top__in{height:100px}}


/* hero: slow drifting light, behind the artwork */
.hero__aura{position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(48% 62% at 76% 20%,rgba(154,205,50,.50),transparent 64%),
    radial-gradient(40% 54% at 16% 86%,rgba(222,0,130,.26),transparent 66%);
  animation:aura 16s ease-in-out infinite alternate}
.hero__aura--b{background:
    radial-gradient(38% 50% at 92% 78%,rgba(222,0,130,.20),transparent 62%),
    radial-gradient(44% 56% at 40% 8%,rgba(154,205,50,.28),transparent 66%);
  animation:aura-b 22s ease-in-out infinite alternate}
@keyframes aura{to{transform:translate3d(-4%,3%,0) scale(1.10)}}
@keyframes aura-b{to{transform:translate3d(5%,-3%,0) scale(1.06)}}

/* hero */
.hero{position:relative;overflow:hidden;background:var(--deep);color:var(--deep-fg);
  padding-block:clamp(60px,8.5vw,116px) clamp(40px,5vw,64px)}
.hero__bg{position:absolute;inset:0;background-size:cover;background-position:center;
  opacity:.9}
/* the film sits over the still and under everything else, so the still acts as
   the poster and as the fallback when a browser will not autoplay */
.hero__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:.9;z-index:0;pointer-events:none}
/* the drifting light field is the background when there is no film; over one it
   would sit on top of the picture and tint the whole thing aubergine, so it goes */
.hero--film .hero__canvas{display:none}
/* and the scrim over film is neutral rather than aubergine, weighted to the side
   the words are on and gone by two thirds across, so most of the frame is the
   footage itself at full strength */
/* Not a wash across the frame but a pool of shade behind the words, falling
   away in every direction. Outside its reach the film is at full strength,
   which is most of the picture: the top edge, the right two thirds and the
   foot of the frame are untouched. The type is held up by a tight halo of its
   own rather than by darkening everything it sits in front of. */
.hero.hero--film::before{
  background:radial-gradient(118% 92% at 4% 40%,rgba(0,0,0,.74) 0%,
    rgba(0,0,0,.52) 32%,rgba(0,0,0,.16) 58%,rgba(0,0,0,0) 74%)}
.hero--film h1,.hero--film .hero__grid p{
  text-shadow:0 1px 2px rgba(0,0,0,.85),0 2px 10px rgba(0,0,0,.72),
    0 6px 34px rgba(0,0,0,.55)}
/* a rule marks the block instead, the same green the site uses to point at things */
.hero--film .hero__say{position:relative}
.hero--film .hero__say::before{content:"";position:absolute;
  left:calc(-1 * clamp(14px,1.9vw,30px));top:-6px;bottom:-6px;width:4px;
  background:var(--brand);border-radius:2px}
/* footage is lightest at the foot of the frame, where the figures sit, so the
   film is weighted down under them as well as across the headline */
.hero.hero--film::after{content:"";position:absolute;inset:auto 0 0;height:52%;
  z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,0) 55%,rgba(0,0,0,.18) 100%)}
@media(prefers-reduced-motion:reduce){.hero__video{display:none}}
.hero__bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(100deg,var(--deep) 4%,color-mix(in srgb,var(--deep) 82%,transparent) 46%,color-mix(in srgb,var(--deep) 55%,transparent))}
.hero__in{position:relative}
/* the light field drifts bright; this keeps white type legible over it */
.hero::before,.pagehero:not(.pagehero--brand)::before{content:"";position:absolute;inset:0;
  pointer-events:none;z-index:1;
  background:linear-gradient(100deg,rgba(28,19,34,.80) 0%,rgba(28,19,34,.62) 38%,
             rgba(28,19,34,.22) 68%,rgba(28,19,34,0) 88%)}
.hero__in,.pagehero .wrap,.hero__grain,.pagehero__grain{z-index:2}
.hero h1{font-size:clamp(36px,6.2vw,88px);letter-spacing:-.02em;max-width:16ch;
  font-weight:800;line-height:1.02}
.hero__grid{display:grid;grid-template-columns:1fr min(44ch,40%);
  gap:clamp(22px,4vw,60px);align-items:end;margin-top:clamp(26px,3.4vw,44px)}
@media(max-width:900px){.hero__grid{grid-template-columns:1fr}}
.hero p{color:var(--deep-fg-2);font-size:clamp(16px,1.45vw,18.5px);max-width:56ch}
.hero__cta{display:flex;gap:12px;flex-wrap:wrap;margin-top:26px}

.stats{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:1px;
  background:var(--rule);margin-top:clamp(40px,5vw,72px);position:relative}
.stats>div{background:var(--deep);padding:22px clamp(14px,1.6vw,24px)}
/* over film the row sits on glass rather than solid aubergine: the footage
   carries through it, and the blur behind the type keeps the figures crisp
   whichever frame happens to be showing */
.hero--film .stats{background:rgba(255,255,255,.18)}
.hero--film .stats>div{background:rgba(0,0,0,.52);
  backdrop-filter:blur(16px) saturate(118%);-webkit-backdrop-filter:blur(16px) saturate(118%)}
@supports not ((backdrop-filter:blur(2px)) or (-webkit-backdrop-filter:blur(2px))){
  .hero--film .stats>div{background:rgba(0,0,0,.72)}}
/* phones get the plain aubergine: a landscape film shows about a quarter of its
   frame at that width and is not worth the download, so the picture goes too
   and the light field carries the hero on its own */
@media(max-width:720px){
  .hero--film .hero__video,.hero--film .hero__bg{display:none}
  .hero--film .hero__canvas{display:block}
  .hero--film h1,.hero--film .hero__grid p{text-shadow:none}
  .hero--film .hero__say::before{display:none}
  .hero.hero--film::after{display:none}
  .hero.hero--film::before{
    background:linear-gradient(100deg,rgba(28,19,34,.80) 0%,rgba(28,19,34,.62) 38%,
      rgba(28,19,34,.22) 68%,rgba(28,19,34,0) 88%)}
  /* back to exactly what the row looks like on the aubergine today */
  .hero--film .stats{background:rgba(255,255,255,.26)}
  .hero--film .stats>div{background:rgba(30,21,36,.62);
    backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
}
.stats dt{font-family:var(--body);font-size:13px;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--deep-fg-2);margin:0 0 .9em}
.stats dd{margin:0;font-family:var(--display);font-weight:700;white-space:nowrap;
  font-size:clamp(20px,2.3vw,31px);letter-spacing:-.012em;line-height:1.05}
.stats dd small{font-size:.46em;font-weight:600;letter-spacing:0;color:var(--brand)}
@media(max-width:900px){.stats{grid-auto-flow:row;grid-template-columns:1fr 1fr}
  /* three of them on a tablet leaves one on its own: it takes the whole row
     rather than sitting beside an empty cell */
  .stats>div:last-child:nth-child(odd){grid-column:1 / -1}}
@media(max-width:520px){.stats{grid-auto-flow:row;grid-template-columns:1fr}}

/* ---------- the scroll cue ----------
   A laptop shows the hero and nothing else, so the fold lands on its bottom
   edge. This straddles that edge, half on the film and half on the white
   below, which reads as an edge to go past rather than an ornament. */
.u-hide{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}
.scrollcue{position:relative;z-index:4;height:0;display:flex;justify-content:center;
  pointer-events:none}
.scrollcue__btn{--cue:clamp(48px,4.2vw,62px);pointer-events:auto;position:absolute;
  top:calc(var(--cue) / -2);width:var(--cue);height:var(--cue);border-radius:999px;
  background:var(--accent);color:#FFFFFF;display:grid;place-items:center;
  /* a hairline so the top half still has an edge where the footage is darkest */
  box-shadow:0 0 0 1px rgba(255,255,255,.22),0 10px 26px rgba(30,21,36,.34);
  transition:transform .45s cubic-bezier(.34,1.4,.5,1),background .3s ease,
    color .3s ease,opacity .4s ease,visibility .4s}
.scrollcue__btn svg{width:46%;height:46%;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round;overflow:visible}
.scrollcue__btn:hover{background:#2E2136;transform:translateY(5px)}
.scrollcue__btn:focus-visible{outline:2px solid var(--brand);outline-offset:5px}
/* the pair falls, one behind the other, and starts again */
@media(prefers-reduced-motion:no-preference){
  .scrollcue__btn svg path{animation:cuefall 1.6s cubic-bezier(.45,0,.5,1) infinite;
    transform-box:fill-box;transform-origin:50% 50%}
  .scrollcue__btn svg path:last-child{animation-delay:.2s}
  .scrollcue__btn:hover svg path{animation-duration:1s}}
/* it never disappears entirely — the pair keeps falling rather than blinking */
@keyframes cuefall{
  0%{opacity:.28;transform:translateY(-3px)}
  32%{opacity:1;transform:translateY(-1px)}
  66%{opacity:1;transform:translateY(1.3px)}
  100%{opacity:.28;transform:translateY(3.4px)}}
/* the moment the page moves it has done its job */
.has-scrolled .scrollcue__btn{opacity:0;visibility:hidden;transform:translateY(12px)}

/* thesis */
.thesis{display:grid;grid-template-columns:1.1fr 1fr;gap:clamp(26px,5vw,72px);align-items:start}
@media(max-width:900px){.thesis{grid-template-columns:1fr}}
.thesis blockquote{margin:0;font-family:var(--body);font-weight:600;
  font-size:clamp(26px,3.4vw,44px);line-height:1.16;letter-spacing:-.022em}
.thesis blockquote em{font-style:normal;color:var(--accent);font-weight:500}
.thesis__body{display:flex;flex-direction:column;gap:1.05em;color:var(--fg-2);padding-top:.4em}

/* media block */
.media{position:relative;overflow:hidden;border-radius:3px;background:var(--deep-2);
  margin-top:clamp(28px,4vw,52px)}
.media img{display:block;width:100%;height:auto;object-fit:cover;aspect-ratio:21/9}
.media__note{position:absolute;left:0;bottom:0;padding:clamp(16px,2.2vw,30px);
  display:flex;align-items:center;gap:14px}
.play{width:52px;height:52px;border-radius:50%;background:var(--brand);flex:none;
  display:grid;place-items:center}
.play svg{width:15px;height:15px;fill:#15180F;margin-left:2px}
.media__note span{font-family:var(--body);font-weight:600;font-size:11.5px;letter-spacing:.2em;
  text-transform:uppercase;color:#FFFFFF;text-shadow:0 1px 6px rgba(0,0,0,.55)}

/* services */
.svc{border-top:1px solid var(--rule)}
.svc__row{display:grid;grid-template-columns:34px 1.15fr 1.6fr;gap:clamp(14px,3vw,44px);
  padding:clamp(22px,2.7vw,36px) 0;border-bottom:1px solid var(--rule);align-items:baseline}
@media(max-width:820px){.svc__row{grid-template-columns:30px 1fr;gap:12px}
  .svc__row p{grid-column:2}}
.svc__n{font-family:var(--body);font-weight:600;font-size:12.5px;color:var(--fg-3);letter-spacing:.1em;
  display:flex;align-items:center}
.svc__ico{width:32px;height:32px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;display:block}

.svc__row h3{font-size:clamp(21px,2.5vw,33px);letter-spacing:-.028em;font-weight:700}
.svc__row p{color:var(--fg-2);font-size:16.5px;max-width:56ch}
.svc__row:hover h3{color:var(--accent)}

/* work */
.work{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(14px,1.6vw,22px)}
@media(max-width:1180px){.work{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.work{grid-template-columns:1fr}}

/* team */
.team{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,64px);align-items:start}
@media(max-width:900px){.team{grid-template-columns:1fr}}
.team__list{display:flex;flex-direction:column;border-top:1px solid var(--rule)}
.team__list div{padding:18px 0;border-bottom:1px solid var(--rule);
  display:flex;gap:18px;align-items:baseline}
.team__list b{font-family:var(--body);font-weight:600;font-size:17px;min-width:19ch}
.team__list span{color:var(--fg-2);font-size:15.5px}
@media(max-width:560px){.team__list div{flex-direction:column;gap:4px}}

/* group: the homepage and The group page now show the same three cards, built
   by one function and styled with the brand card rules further down. The plain
   list that used to sit here has gone rather than been left behind unused. */

/* accreditations */
.acc{display:grid;grid-template-columns:repeat(auto-fill,minmax(205px,1fr));
  gap:1px;background:var(--rule);border:1px solid var(--rule)}
.acc>div{background:var(--bg);padding:24px 22px;display:flex;flex-direction:column;gap:7px}
.acc__name{font-family:var(--body);font-weight:600;font-size:23px;letter-spacing:.01em}
.acc__cat{font-family:var(--body);font-weight:600;font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--brand-text)}
.acc__rel{font-size:14px;color:var(--fg-3)}

/* timeline */
.tl{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--rule);
  border:1px solid var(--rule);margin-top:clamp(24px,3vw,40px)}
@media(max-width:900px){.tl{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.tl{grid-template-columns:1fr}}
.tl>div{background:var(--bg);padding:24px 22px;display:flex;flex-direction:column;gap:9px}
.tl__yr{font-family:var(--body);font-weight:600;font-size:clamp(26px,3.1vw,38px);
  letter-spacing:-.035em;color:var(--accent);line-height:1;font-variant-numeric:tabular-nums}
.tl p{font-size:15.5px;color:var(--fg-2)}

/* cta + footer */
.cta{background:var(--brand);color:#15180F}
.cta h2{font-size:clamp(30px,5vw,72px);letter-spacing:-.02em;max-width:17ch;
  font-weight:800;line-height:1.02}
.cta p{font-size:clamp(16px,1.45vw,19px);color:rgba(21,24,15,.76);max-width:56ch;margin-top:18px}
.cta .btn{background:#15180F;color:#F4F5F0}
.cta .btn--ghost{background:transparent;color:#15180F;box-shadow:inset 0 0 0 1.5px rgba(21,24,15,.42)}
.cta .btn--ghost:hover{box-shadow:inset 0 0 0 1.5px rgba(21,24,15,.8)}
.cta__row{display:flex;gap:16px;flex-wrap:wrap;margin-top:28px;align-items:center}
.cta__tel{font-family:var(--body);font-weight:600;font-size:15px;color:#15180F;text-decoration:none;
  border-bottom:1.5px solid rgba(21,24,15,.4);padding-bottom:2px;letter-spacing:.02em}

footer{background:var(--deep-2);color:var(--deep-fg-2);border-top:1px solid var(--rule);padding-block:clamp(38px,4vw,56px) clamp(30px,3.2vw,44px);font-size:15px}
.foot{display:grid;grid-template-columns:1.5fr repeat(3,1fr);gap:clamp(20px,3vw,40px)}
@media(max-width:860px){.foot{grid-template-columns:1fr 1fr}}
footer h4{font-family:var(--body);font-size:12.5px;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent);margin:0 0 16px}
footer ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
footer a{text-decoration:none;color:var(--deep-fg-2)}
footer a:hover{color:var(--accent)}
/* the column headings lead to their own page, and say so on the way past:
   a rule grows out from the left rather than the whole label changing colour,
   which would collide with the accent the headings are already set in */
footer h4 a{color:inherit;position:relative;display:inline-block;padding-bottom:3px}
footer h4 a::after{content:"";position:absolute;left:0;bottom:0;height:1px;width:100%;
  background:currentColor;transform:scaleX(0);transform-origin:0 50%;
  transition:transform .32s cubic-bezier(.22,.61,.36,1)}
footer h4 a:hover{color:inherit}
footer h4 a:hover::after,footer h4 a:focus-visible::after{transform:scaleX(1)}
footer h4 a:focus-visible{outline:2px solid currentColor;outline-offset:3px}
@media(prefers-reduced-motion:reduce){footer h4 a::after{transition:none}}
/* the legal line lives under the mark rather than in a rule-off row of its own */
.foot__legal{margin-top:clamp(18px,2.2vw,28px);font-family:var(--body);font-weight:600;
  font-size:12.5px;letter-spacing:.04em;color:var(--fg-3);line-height:1.7}
.foot__legal span{display:block}

.demo{background:var(--fg);color:var(--bg);font-family:var(--body);font-weight:600;font-size:12px;
  letter-spacing:.12em;text-transform:uppercase;text-align:center;padding:10px var(--gut)}
.note{margin-top:20px;color:var(--fg-3);font-size:14.5px}
.intro{max-width:70ch;color:var(--fg-2);font-size:17px;margin-bottom:2.2em}
.more{margin-top:clamp(26px,3vw,40px)}
.more a{font-family:var(--body);font-weight:600;font-size:14.5px;letter-spacing:.06em;text-transform:uppercase;
  text-decoration:none;color:var(--fg);border-bottom:2px solid var(--brand);padding-bottom:5px;
  transition:color .18s}
.more a:hover{color:var(--accent)}

@media(prefers-reduced-motion:reduce){*{animation-duration:.001ms!important;transition-duration:.001ms!important}}

/* ---------- page level (templates beyond the home page) ---------- */
.skip{position:absolute;left:-9999px;top:0;background:var(--brand);color:#15180F;
  padding:12px 18px;z-index:200;font-family:var(--display)}
.skip:focus{left:0}

.burger{display:none;margin-left:14px;width:42px;height:42px;background:none;
  border:1px solid var(--rule-2);border-radius:2px;cursor:pointer;
  flex-direction:column;gap:5px;align-items:center;justify-content:center}
.burger span{display:block;width:18px;height:1.5px;background:var(--fg)}
.mobilenav{display:none;border-top:1px solid var(--rule);padding:18px var(--gut) 26px}
.mobilenav ul{list-style:none;margin:0 0 16px;padding:0;display:flex;flex-direction:column;gap:2px}
.mobilenav a{display:block;padding:11px 0;text-decoration:none;font-family:var(--display);
  font-size:18px;border-bottom:1px solid var(--rule)}
/* The menu button has to appear at exactly the width the links disappear at.
   It was doing so 70px later, which left a band where the site had no
   navigation at all. */
@media(max-width:1150px){.burger{display:flex;width:44px;height:44px;margin-left:12px}
  .mobilenav:not([hidden]){display:block}}

.pagehead{padding-block:clamp(46px,6vw,86px) clamp(30px,4vw,54px);background:var(--bg)}
.pagehead h1{font-size:clamp(36px,6.6vw,92px);letter-spacing:-.045em;max-width:16ch;line-height:.96}
.pagehead__lede{margin-top:1em;max-width:60ch;color:var(--fg-2);
  font-size:clamp(17px,1.6vw,20px)}
.pagehead--brand{background:var(--brand);color:#15180F}
.pagehead--brand .kicker{color:rgba(21,24,15,.62)}
.pagehead--brand .btn{background:#15180F;color:#F4F5F0}

.prose{max-width:68ch;color:var(--fg-2);display:flex;flex-direction:column;gap:1.05em}
.prose--tight{gap:.8em;font-size:15.5px}
.prose h2,.prose h3{color:var(--fg);margin-top:.6em}
.prose h2{font-size:clamp(23px,2.6vw,32px)}
.prose h3{font-size:clamp(19px,2vw,24px)}
.prose ul,.prose ol{margin:0;padding-left:1.3em;display:flex;flex-direction:column;gap:.5em}
.prose a{color:var(--fg);text-decoration:underline;text-decoration-color:var(--brand);
  text-underline-offset:3px}
.prose img{border-radius:3px;margin-block:.4em}
.prose blockquote{margin:0;padding-left:20px;border-left:3px solid var(--brand);
  font-family:var(--body);font-weight:600;font-size:clamp(20px,2.2vw,27px);
  line-height:1.24;color:var(--fg)}

.svcfull{display:flex;flex-direction:column;border-top:1px solid var(--rule)}
.svcfull__item{display:grid;grid-template-columns:34px 1fr;gap:clamp(14px,3vw,44px);
  padding:clamp(24px,3vw,40px) 0;border-bottom:1px solid var(--rule)}
.svcfull__item h2{font-size:clamp(23px,2.8vw,36px);font-weight:800;letter-spacing:-.03em;
  margin-bottom:.55em}
@media(max-width:640px){.svcfull__item{grid-template-columns:1fr;gap:10px}}

.team__list--full b{min-width:22ch}

.filters{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:clamp(24px,3vw,38px)}
.filters__item{font-family:var(--body);font-weight:600;font-size:13.5px;letter-spacing:.06em;
  text-decoration:none;padding:.5em 1em;border:1px solid var(--rule-2);border-radius:99px;
  color:var(--fg-2);transition:border-color .18s,color .18s}
.filters__item:hover{border-color:var(--accent);color:var(--accent)}
.filters__item.is-on{background:var(--fg);color:var(--bg);border-color:var(--fg)}

.work--archive{grid-template-columns:repeat(3,1fr)}
@media(max-width:1180px){.work--archive{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.work--archive{grid-template-columns:1fr}}

.pager{margin-top:clamp(28px,3.4vw,46px)}
.pager .nav-links{display:flex;gap:8px;flex-wrap:wrap;font-family:var(--display)}
.pager a,.pager .current{padding:.5em .95em;border:1px solid var(--rule-2);border-radius:2px;
  text-decoration:none;font-size:14px}
.pager .current{background:var(--fg);color:var(--bg);border-color:var(--fg)}

.casehero{position:relative;overflow:hidden;background:#2E2136;color:#FFFFFF;
  padding-block:clamp(64px,9vw,130px) clamp(40px,5vw,66px)}
.casehero__bg{position:absolute;inset:0}
.casehero__bg img{width:100%;height:100%;object-fit:cover;opacity:.9}
.casehero__bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(46,33,54,.94) 6%,rgba(46,33,54,.72) 52%,rgba(46,33,54,.42))}
.casehero__in{position:relative}
.casehero .kicker{color:var(--brand)}
.casehero h1{font-size:clamp(29px,4.4vw,58px);letter-spacing:-.018em;max-width:20ch;
  font-weight:800;color:#FFFFFF}
.casehero__lede{margin-top:1em;max-width:58ch;color:rgba(255,255,255,.84);
  font-size:clamp(17px,1.6vw,20px)}

.casemeta{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--rule);
  border:1px solid var(--rule);margin-top:clamp(28px,3.4vw,44px);max-width:68ch}
@media(max-width:560px){.casemeta{grid-template-columns:1fr}}
.casemeta>div{background:var(--bg);padding:20px 22px}
.casemeta dt{font-family:var(--body);font-weight:600;font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--accent);margin-bottom:.7em}
.casemeta dd{margin:0;font-size:16px}

.acc__logo{max-height:44px;width:auto;object-fit:contain;margin-bottom:4px}
.h2--narrow{max-width:24ch;margin-bottom:.62em}
.h2 + .prose,.h2 + .acc,.h2 + .tl{margin-top:clamp(24px,2.6vw,38px)}
.h2--tight{max-width:13ch}
.h2--wide{max-width:30ch}
.team__intro{margin-top:1.2em;color:var(--fg-2);max-width:52ch}
.media.media--team img{aspect-ratio:2.35/1;object-position:50% 100%}
.media video{display:block;width:100%;height:auto;object-fit:cover;aspect-ratio:21/9}
.folio__mark--cta{color:#FFFFFF}
.folio__mark--cta .grid9{fill:#FFFFFF}

/* the mark simply fades up once the footer arrives */
.foot__logo{display:block;height:clamp(78px,7.4vw,108px);
  /* the artwork sits inside transparent space, so lift it until its first ink
     lines up with the column headings beside it */
  margin-top:calc(clamp(78px,7.4vw,108px) * -0.047)}
.foot__logo img{height:100%;width:auto}
.js .foot__logo img{opacity:0;transition:opacity .75s ease}
.js .foot__logo.is-in img{opacity:1}
@media(prefers-reduced-motion:reduce){
  .js .foot__logo img{opacity:1;transition:none}}

/* ---------- who we are: mark-as-mosaic instead of a showreel ---------- */
.who{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,4.2vw,68px);align-items:start}
@media(max-width:980px){.who{grid-template-columns:1fr}}
.who__text{display:flex;flex-direction:column;gap:1.5em}
.who__text blockquote{margin:0;font-family:var(--body);font-weight:600;
  font-size:clamp(25px,3.2vw,42px);line-height:1.16;letter-spacing:-.022em}
.who__text blockquote em{font-style:normal;color:var(--accent);font-weight:500}
.who__body{display:flex;flex-direction:column;gap:1.05em;color:var(--fg-2)}
.mosaic{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);
  gap:clamp(6px,.9vw,12px);height:100%;min-height:clamp(300px,32vw,500px)}
.mosaic>*{overflow:hidden;border-radius:2px;margin:0;min-height:0}
@media(max-width:980px){.mosaic{grid-template-rows:auto;height:auto;min-height:0}
  .mosaic>*{aspect-ratio:1}}
.mosaic img{width:100%;height:100%;object-fit:cover;display:block}
.mosaic .fill{background:var(--brand)}
.mosaic .fill--accent{background:var(--accent)}
.mosaic .fill--mark{background:var(--bg-2);display:grid;place-items:center}
.mosaic .fill--mark svg{width:44%;height:44%;fill:var(--brand)}

/* case study cards */
.card{display:flex;flex-direction:column;background:var(--bg);border:1px solid var(--rule);
  border-radius:var(--r-2);overflow:hidden;text-decoration:none;
  transition:border-color .25s,transform .3s cubic-bezier(.22,.61,.36,1),box-shadow .3s}
.card:hover{border-color:var(--brand);transform:translateY(-3px);
  box-shadow:0 14px 36px rgba(44,49,55,.13)}
.card h3{transition:color .2s}
.card:hover h3{color:var(--accent)}
.card__img{aspect-ratio:4/3.1;overflow:hidden;background:var(--deep-2)}
.card__img img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1.1s cubic-bezier(.22,.61,.36,1)}
.card:hover .card__img img{transform:scale(1.04)}
.card__body{padding:20px 22px 24px;display:flex;flex-direction:column;gap:10px;flex:1}
.card__tag{font-family:var(--body);font-weight:600;font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--accent)}
.card h3{font-size:clamp(20px,1.7vw,25px);font-weight:700;letter-spacing:-.028em;line-height:1.1}
.card p{font-size:14.5px;color:var(--fg-2)}
.card__scope{margin-top:auto;padding-top:15px;border-top:1px solid var(--rule);
  font-size:14.5px;color:var(--fg-2);line-height:1.45}
.card__scope b{display:block;font-family:var(--body);font-weight:600;font-size:11px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--accent);margin-bottom:5px}
.card:focus-visible{outline:none;border-color:var(--brand);transform:translateY(-3px);
  box-shadow:0 0 0 3px var(--accent),0 14px 36px rgba(44,49,55,.13)}
.card:focus-visible h3{color:var(--accent)}

/* ---------- work: featured film above the cards ---------- */
.work__film{position:relative;overflow:hidden;border-radius:3px;background:var(--deep-2);
  margin-bottom:clamp(20px,2.6vw,34px)}
.work__film img,.work__film video{display:block;width:100%;height:auto;object-fit:cover;
  aspect-ratio:21/9}
.work__film .media__note{position:absolute;left:0;bottom:0}

/* scope reads as tags, not as more copy */


/* ---------- team: one clean row of disciplines ---------- */
.disciplines{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:clamp(16px,2vw,32px);
  margin-top:clamp(28px,3.4vw,46px)}
@media(max-width:1100px){.disciplines{grid-auto-flow:row;grid-template-columns:repeat(3,1fr)}}
@media(max-width:720px){.disciplines{grid-auto-flow:row;grid-template-columns:repeat(2,1fr)}}
@media(max-width:460px){.disciplines{grid-auto-flow:row;grid-template-columns:1fr}}
.disciplines>div{border-top:2px solid var(--accent);padding-top:15px;
  display:flex;flex-direction:column;gap:7px}
.disciplines b{font-family:var(--body);font-weight:600;font-size:17px;letter-spacing:-.01em}
.disciplines span{font-size:15px;color:var(--fg-2)}
.team__lede{max-width:62ch;color:var(--fg-2);margin-top:1.1em;font-size:17px}

/* ---------- accreditations as logo plates ---------- */
.acc{grid-template-columns:repeat(auto-fill,minmax(186px,1fr))}
.acc>div{padding:26px 18px 20px;align-items:center;text-align:center;gap:10px}
.acc__plate{height:56px;display:grid;place-items:center;width:100%}
.acc__plate img{max-height:56px;width:auto;object-fit:contain}
.acc__name{font-family:var(--body);font-weight:600;font-size:22px;letter-spacing:.01em;
  color:var(--fg)}
.acc__cat{font-family:var(--body);font-weight:600;font-size:10.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--brand-text)}
.acc__rel{font-size:13px;color:var(--fg-3)}

/* ---------- motion system ---------- */
.hero__canvas{position:absolute;inset:-8%;width:116%;height:116%;
  filter:blur(26px) saturate(1.3);opacity:.95;pointer-events:none}
.hero{border-bottom:1px solid var(--rule)}
.hero__grain{opacity:.55}
.hero__grain{position:absolute;inset:0;pointer-events:none;opacity:.55;
  background:repeating-linear-gradient(180deg,rgba(44,49,55,.045) 0 1px,transparent 1px 3px)}

/* header condenses and reports progress */
.top{transition:height .25s ease,box-shadow .25s ease}
.top.is-scrolled{box-shadow:0 1px 18px rgba(44,49,55,.10)}
.progress{position:absolute;left:0;right:0;bottom:-1px;height:2px;background:transparent}
.progress__fill{height:100%;background:var(--accent);transform-origin:0 50%;
  transform:scaleX(0);will-change:transform}
.nav a.is-active{color:var(--fg);border-bottom-color:var(--accent)}

/* reveal, applied by script only to what starts below the fold */
.js .pre{opacity:0;transform:translate3d(0,22px,0);transition:none}
.spread .folio>div,.spread .folio__mark{
  transition:opacity .62s cubic-bezier(.22,.61,.36,1),transform .62s cubic-bezier(.22,.61,.36,1)}
.spread .folio__mark{transition-delay:.06s}

/* cards and tiles gain a little life */

.mosaic>*{transition:transform .18s linear}
.acc>div{transition:transform .25s,border-color .25s}
.acc>div:hover{transform:translateY(-3px)}
.disciplines>div{transition:border-color .25s}
.disciplines>div:hover{border-top-color:var(--brand)}
.svc__row{transition:background .25s}
.svc__row:hover{background:rgba(255,255,255,.10)}
.spread:not(.spread--tint) .svc__row:hover{background:rgba(44,49,55,.035)}
.stats dd{font-variant-numeric:tabular-nums}

@media(prefers-reduced-motion:reduce){
  .js .pre{opacity:1;transform:none}
}

/* ---------- softer geometry throughout ---------- */
:root{--r:22px;--r-2:16px;--r-3:12px}
.card,.work__film,.media,.acc>div,.tl>div,.casehero__bg img{border-radius:var(--r-2)}
.btn{border-radius:999px;gap:.55em}
.filters__item{border-radius:999px}
.acc{background:none;border:none;gap:clamp(10px,1.2vw,16px)}
.acc>div{border:1px solid var(--rule);background:var(--bg)}
.tl{background:none;border:none;gap:clamp(10px,1.2vw,16px)}
.tl>div{border:1px solid var(--rule)}
.spread--tint .acc>div,.spread--tint .tl>div{border-color:rgba(255,255,255,.35)}

/* ---------- who we are: the statement leads, everything else supports it ---------- */
.who{display:block}
/* the statement that opens a block: display face, full width, level with the folio label */
.say,.who__say{margin:0 0 clamp(30px,3.8vw,58px);
  font-family:var(--display);font-weight:800;letter-spacing:-.032em;line-height:1.01;
  font-size:clamp(30px,4.6vw,60px);max-width:30ch;text-wrap:balance}
.say em,.who__say em{font-style:normal;font-weight:800;color:var(--accent)}
/* on a brand green band the accent resolves to white, so pick the deep house colour */
.spread--tint .say em,.spread--tint .who__say em{color:#2E2136}
.who__grid{display:grid;grid-template-columns:1.04fr .96fr;
  gap:clamp(28px,4.2vw,68px);align-items:start}
@media(max-width:980px){.who__grid{grid-template-columns:1fr}}
.who__text{display:flex;flex-direction:column;gap:1.5em}
.who__body{display:flex;flex-direction:column;gap:1.05em;color:var(--fg-2)}
.who__body p:first-child{font-size:clamp(17px,1.55vw,20px);color:var(--fg);font-weight:500}
/* three flat claims, set in the display face so the block keeps its voice */
.who__claims{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:clamp(14px,1.8vw,26px);
  margin-top:clamp(26px,3vw,40px);padding-top:clamp(18px,2vw,26px);
  border-top:1px solid var(--rule)}
@media(max-width:560px){.who__claims{grid-auto-flow:row;grid-template-columns:1fr;gap:14px}}
.who__claims b{display:block;font-family:var(--display);font-weight:800;letter-spacing:-.02em;
  font-size:clamp(19px,1.75vw,23px);line-height:1.05}
.who__claims span{display:block;margin-top:6px;font-size:14.5px;color:var(--fg-2);line-height:1.4}
/* the image pushes in as the block is read, and again on hover */
.panel img{transition:transform 7.4s cubic-bezier(.19,.52,.26,1)}
.panel.is-zoomed img{transform:scale(1.14)}
#who:hover .panel img,.spread:hover .panel img{transform:scale(1.18)}
.panel{transition:box-shadow .6s ease,transform .6s cubic-bezier(.22,.61,.36,1)}
#who:hover .panel,.spread:hover .panel{transform:translateY(-4px);
  box-shadow:0 26px 60px rgba(30,21,36,.26)}
@media(prefers-reduced-motion:reduce){
  .panel.is-zoomed img,#who:hover .panel img,.spread:hover .panel img{transform:none}
  #who:hover .panel,.spread:hover .panel{transform:none}}

.panel{position:relative;border-radius:var(--r);overflow:hidden;aspect-ratio:4/4.4;
  background:var(--deep-2);box-shadow:0 26px 64px rgba(44,49,55,.20)}
.panel img{width:100%;height:100%;object-fit:cover;display:block}
.panel::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(24,17,28,.86) 0%,rgba(24,17,28,.45) 26%,transparent 58%)}
.panel__tag{position:absolute;left:clamp(18px,2.2vw,28px);top:clamp(18px,2.2vw,28px);z-index:2;
  background:var(--brand);color:#15180F;border-radius:999px;padding:.6em 1.1em;
  font-family:var(--body);font-size:11.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase}
.panel__foot{position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:clamp(22px,3vw,38px);display:flex;align-items:flex-end;
  justify-content:space-between;gap:20px}
.panel__fig{font-family:var(--body);font-weight:600;color:#FFFFFF;line-height:.82;
  font-size:clamp(54px,7vw,96px);letter-spacing:-.05em;font-variant-numeric:tabular-nums;
  display:block}
.panel__cap{font-family:var(--body);font-weight:600;font-size:12px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--brand);display:block;margin-top:12px}
.panel__note{display:flex;flex-direction:column;gap:5px;text-align:right;
  font-family:var(--body);font-weight:600;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:#FFFFFF;white-space:nowrap}
@media(max-width:980px){.panel{aspect-ratio:4/3.2}}
@media(max-width:560px){.panel__foot{flex-direction:column;align-items:flex-start;gap:14px}
  .panel__note{text-align:left;flex-direction:row;gap:14px}}

/* ---------- work: featured film above the cards ---------- */
.work__film{position:relative;overflow:hidden;border-radius:3px;background:var(--deep-2);
  margin-bottom:clamp(20px,2.6vw,34px)}
.work__film img,.work__film video{display:block;width:100%;height:auto;object-fit:cover;
  aspect-ratio:21/9}
.work__film .media__note{position:absolute;left:0;bottom:0}

/* scope reads as tags, not as more copy */


/* ---------- team: one clean row of disciplines ---------- */
.disciplines{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:clamp(16px,2vw,32px);
  margin-top:clamp(28px,3.4vw,46px)}
@media(max-width:1100px){.disciplines{grid-auto-flow:row;grid-template-columns:repeat(3,1fr)}}
@media(max-width:720px){.disciplines{grid-auto-flow:row;grid-template-columns:repeat(2,1fr)}}
@media(max-width:460px){.disciplines{grid-auto-flow:row;grid-template-columns:1fr}}
.disciplines>div{border-top:2px solid var(--accent);padding-top:15px;
  display:flex;flex-direction:column;gap:7px}
.disciplines b{font-family:var(--body);font-weight:600;font-size:17px;letter-spacing:-.01em}
.disciplines span{font-size:15px;color:var(--fg-2)}
.team__lede{max-width:62ch;color:var(--fg-2);margin-top:1.1em;font-size:17px}

/* ---------- accreditations as logo plates ---------- */
.acc{grid-template-columns:repeat(auto-fill,minmax(186px,1fr))}
.acc>div{padding:26px 18px 20px;align-items:center;text-align:center;gap:10px}
.acc__plate{height:56px;display:grid;place-items:center;width:100%}
.acc__plate img{max-height:56px;width:auto;object-fit:contain}
.acc__name{font-family:var(--body);font-weight:600;font-size:22px;letter-spacing:.01em;
  color:var(--fg)}
.acc__cat{font-family:var(--body);font-weight:600;font-size:10.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--brand-text)}
.acc__rel{font-size:13px;color:var(--fg-3)}

/* ---------- motion system ---------- */
.hero__canvas{position:absolute;inset:-8%;width:116%;height:116%;
  filter:blur(26px) saturate(1.3);opacity:.95;pointer-events:none}
.hero{border-bottom:1px solid var(--rule)}
.hero__grain{opacity:.55}
.hero__grain{position:absolute;inset:0;pointer-events:none;opacity:.55;
  background:repeating-linear-gradient(180deg,rgba(44,49,55,.045) 0 1px,transparent 1px 3px)}

/* header condenses and reports progress */
.top{transition:height .25s ease,box-shadow .25s ease}
.top.is-scrolled{box-shadow:0 1px 18px rgba(44,49,55,.10)}
.progress{position:absolute;left:0;right:0;bottom:-1px;height:2px;background:transparent}
.progress__fill{height:100%;background:var(--accent);transform-origin:0 50%;
  transform:scaleX(0);will-change:transform}
.nav a.is-active{color:var(--fg);border-bottom-color:var(--accent)}

/* reveal, applied by script only to what starts below the fold */
.js .pre{opacity:0;transform:translate3d(0,22px,0);transition:none}
.spread .folio>div,.spread .folio__mark{
  transition:opacity .62s cubic-bezier(.22,.61,.36,1),transform .62s cubic-bezier(.22,.61,.36,1)}
.spread .folio__mark{transition-delay:.06s}

/* cards and tiles gain a little life */

.mosaic>*{transition:transform .18s linear}
.acc>div{transition:transform .25s,border-color .25s}
.acc>div:hover{transform:translateY(-3px)}
.disciplines>div{transition:border-color .25s}
.disciplines>div:hover{border-top-color:var(--brand)}
.svc__row{transition:background .25s}
.svc__row:hover{background:rgba(255,255,255,.10)}
.spread:not(.spread--tint) .svc__row:hover{background:rgba(44,49,55,.035)}
.stats dd{font-variant-numeric:tabular-nums}

@media(prefers-reduced-motion:reduce){
  .js .pre{opacity:1;transform:none}
}

/* ---------- softer geometry throughout ---------- */
:root{--r:22px;--r-2:16px;--r-3:12px}
.card,.work__film,.media,.acc>div,.tl>div,.casehero__bg img{border-radius:var(--r-2)}
.btn{border-radius:999px;gap:.55em}
.filters__item{border-radius:999px}
.acc{background:none;border:none;gap:clamp(10px,1.2vw,16px)}
.acc>div{border:1px solid var(--rule);background:var(--bg)}
.tl{background:none;border:none;gap:clamp(10px,1.2vw,16px)}
.tl>div{border:1px solid var(--rule)}
.spread--tint .acc>div,.spread--tint .tl>div{border-color:rgba(255,255,255,.35)}

/* headings announce themselves more clearly on arrival */
.spread .h2,.spread h2{transition:opacity .82s cubic-bezier(.19,.66,.28,1) .08s,
  transform .82s cubic-bezier(.19,.66,.28,1) .08s}

/* ---------- small tweaks ---------- */
.more a{position:relative;display:inline-block;overflow:hidden;border-bottom:none;padding-bottom:6px}
.more a::after{content:"";position:absolute;left:0;bottom:0;height:2px;width:100%;
  background:var(--brand)}
/* a light travels the rule whenever the pointer is anywhere in the block */
.more a::before{content:"";position:absolute;left:0;bottom:0;height:2px;width:36%;z-index:2;
  background:linear-gradient(90deg,transparent,var(--accent),transparent);
  transform:translateX(-130%)}
.spread:hover .more a::before,.cta:hover .more a::before,.more a:hover::before{
  animation:moreRun 2.9s cubic-bezier(.42,0,.58,1) infinite}
@keyframes moreRun{
  0%{transform:translateX(-130%)}
  58%{transform:translateX(320%)}
  100%{transform:translateX(320%)}}
.spread--tint .more a::after{background:#FFFFFF}
.spread--tint .more a::before{background:linear-gradient(90deg,transparent,#20290B 42%,#20290B 58%,transparent)}
@media(prefers-reduced-motion:reduce){.more a::before{animation:none!important}}

/* sections sit flat, separated by a hairline only where both are light */
.spread{position:relative;border-top:1px solid var(--rule)}
.spread--tint,.spread--tint + .spread,.cta{border-top:none}

/* ---------- accreditations: the tight grid, sharpened ---------- */
.acc{display:grid;grid-template-columns:repeat(4,1fr);
  gap:1px;background:var(--rule);border:1px solid var(--rule);
  border-radius:var(--r-2);overflow:hidden}
.acc>div{background:var(--bg);border:none;border-radius:0;padding:26px 18px 22px;
  align-items:center;text-align:center;gap:9px;position:relative;
  transition:background .28s ease}
@media(max-width:900px){.acc{grid-template-columns:repeat(2,1fr)}}
@media(max-width:520px){.acc{grid-template-columns:1fr}}

.acc>div::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;
  background:var(--brand);transform:scaleX(0);transform-origin:50% 0;
  transition:transform .3s cubic-bezier(.22,.61,.36,1)}
.acc>div:hover{background:#F4FAE6;transform:none}
.acc>div:hover::before{transform:scaleX(1)}
.acc>div:hover .acc__cat{color:var(--brand-text)}
.spread--tint .acc>div{border-color:transparent}

/* ---------- staggered entrances for grid children ---------- */
.js .stagger{opacity:0;transform:translate3d(0,26px,0);transition:none}
.work .card,.disciplines>div,.acc>div,.tl>div,.brands>a,.svc__row{
  transition:opacity .6s cubic-bezier(.22,.61,.36,1) calc(var(--i,0) * 55ms),
             transform .6s cubic-bezier(.22,.61,.36,1) calc(var(--i,0) * 55ms),
             background .28s,border-color .25s,box-shadow .3s}

@media(prefers-reduced-motion:reduce){
  .js .stagger{opacity:1;transform:none}
}


/* hero runs dark: aubergine ground, light type */
.hero{background:#2E2136;color:#FFFFFF}
.hero h1{color:#FFFFFF}
.hero p{color:rgba(255,255,255,.84)}
.hero__bg::after{background:linear-gradient(100deg,#2E2136 6%,rgba(46,33,54,.86) 52%,rgba(46,33,54,.62))}
.hero__grain{background:repeating-linear-gradient(180deg,rgba(255,255,255,.05) 0 1px,transparent 1px 3px)}
.hero .btn--ghost{color:#FFFFFF;box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.42)}
.hero .btn--ghost:hover{box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.75)}
.stats{background:rgba(255,255,255,.26)}
.stats>div{background:rgba(30,21,36,.62);backdrop-filter:blur(10px)}
.stats dt{color:rgba(255,255,255,.94)}
/* the four labels carry the accent, lifted enough to hold at 13px on a dark
   ground — the brand magenta itself only reaches 2.8:1 down there */
.hero .stats dt{color:var(--accent-lit)}
.stats dd{color:#FFFFFF}
.stats dd small{color:var(--brand)}

/* ---------- anchor targets clear the sticky header ---------- */
.spread,.hero,.cta,footer,.offercard{scroll-margin-top:120px}
body.admin-bar .spread,body.admin-bar .hero,body.admin-bar .cta,body.admin-bar footer,
body.admin-bar .offercard{
  scroll-margin-top:152px}
@media(max-width:1080px){.spread,.hero,.cta,footer,.offercard{scroll-margin-top:92px}}

/* ---------- lazy images fade in rather than pop ---------- */
.media img,.work__film img{opacity:1;transition:opacity .5s ease}
/* a card image zooms on hover, so it has to keep its transform transition here
   or this rule replaces it and the zoom snaps */
.card__img img{opacity:1;transition:opacity .5s ease,
  transform 1.1s cubic-bezier(.22,.61,.36,1)}
/* the who-we-are panel pushes in slowly, so it keeps its own long transition */
.panel img{opacity:1;transition:opacity .5s ease,
  transform 7.4s cubic-bezier(.19,.52,.26,1)}
.js img[loading="lazy"]:not(.is-loaded){opacity:0}
.js img[loading="lazy"].is-loaded{opacity:1}

/* ---------- keyboard focus matches hover, so tabbing is legible ---------- */
.acc>div:focus-within::before{transform:scaleX(1)}

/* ---------- back to top ---------- */
.totop{position:fixed;right:clamp(14px,2vw,26px);bottom:clamp(14px,2vw,26px);z-index:70;
  width:46px;height:46px;border-radius:50%;border:1px solid var(--rule-2);
  background:var(--bg);color:var(--fg);display:grid;place-items:center;cursor:pointer;
  opacity:0;pointer-events:none;transform:translateY(10px);
  transition:opacity .3s,transform .3s,border-color .2s;
  box-shadow:0 8px 24px rgba(44,49,55,.16)}
.totop.is-on{opacity:1;pointer-events:auto;transform:none}
.totop:hover{border-color:var(--brand)}
.totop svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}

/* ---------- mobile contact bar ---------- */
.callbar{position:fixed;left:0;right:0;bottom:0;z-index:65;display:none;gap:8px;
  padding:10px clamp(12px,3vw,20px) calc(10px + env(safe-area-inset-bottom));
  background:color-mix(in srgb,var(--bg) 94%,transparent);backdrop-filter:blur(14px);
  border-top:1px solid var(--rule)}
.callbar a{flex:1;justify-content:center;text-align:center}
@media(max-width:720px){
  .callbar{display:flex}
  body{padding-bottom:76px}
  .totop{bottom:calc(76px + 12px)}
}

.stats dt,.stats dd{transition:opacity .65s ease,transform .65s cubic-bezier(.22,.61,.36,1)}
.js .stats dt.is-held,.js .stats dd.is-held{opacity:0;transform:translate3d(0,10px,0);
  transition:none}
@media(prefers-reduced-motion:reduce){
  .js .stats dt.is-held,.js .stats dd.is-held{opacity:1;transform:none}}

/* ---------- inner page heroes ---------- */
.pagehero{position:relative;overflow:hidden;background:#2E2136;color:#FFFFFF;
  padding-block:clamp(72px,9vw,132px) clamp(56px,7vw,96px)}
.pagehero__bg{position:absolute;inset:0}
.pagehero__bg img{width:100%;height:100%;object-fit:cover;opacity:.92}
.pagehero__bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(46,33,54,.95) 4%,rgba(46,33,54,.74) 50%,rgba(46,33,54,.44))}
.pagehero__grain{position:absolute;inset:0;pointer-events:none;opacity:.5;
  background:repeating-linear-gradient(180deg,rgba(255,255,255,.05) 0 1px,transparent 1px 3px)}
.pagehero .wrap{position:relative}
.pagehero .kicker{color:var(--brand)}
.pagehero h1{font-size:clamp(34px,5.6vw,80px);letter-spacing:-.02em;line-height:1.02;
  font-weight:800;max-width:17ch;color:#FFFFFF}
.pagehero__lede{margin-top:1.1em;max-width:56ch;color:rgba(255,255,255,.84);
  font-size:clamp(17px,1.7vw,21px)}
.pagehero--brand{background:var(--brand);color:#15180F}
.pagehero--brand h1{color:#15180F}
.pagehero--brand .kicker{color:rgba(21,24,15,.62)}
.pagehero--brand .pagehero__lede{color:rgba(21,24,15,.78)}
.pagehero__row{display:flex;gap:16px;flex-wrap:wrap;align-items:center;margin-top:30px}
.pagehero--brand .btn{background:#15180F;color:#F4F5F0}

/* ---------- alternating image and text ---------- */
.feature{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,4.4vw,76px);align-items:center}
.feature + .feature{margin-top:clamp(40px,5vw,80px)}
/* a lone feature opens a section: top align it so the heading sits level with the folio label */
.folio > div > .feature:only-child{align-items:start}
.feature__media{position:relative;border-radius:var(--r);overflow:hidden;aspect-ratio:4/3.3;
  box-shadow:0 22px 52px rgba(44,49,55,.18)}
.feature__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1.1s cubic-bezier(.22,.61,.36,1)}
.feature:hover .feature__media img{transform:scale(1.04)}
.feature__media span{position:absolute;left:16px;bottom:16px;z-index:2;
  background:var(--brand);color:#15180F;border-radius:999px;padding:.5em .95em;line-height:1;
  font-family:var(--body);font-size:10.5px;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase}
.feature h2{font-size:clamp(27px,3.4vw,46px);letter-spacing:-.032em;font-weight:800;
  margin-bottom:.6em}
.feature .prose{max-width:52ch}
@media(max-width:900px){.feature{grid-template-columns:1fr}
  .feature--flip .feature__media{order:0}}
.feature--flip .feature__media{order:2}

/* the page opens on its first sentence rather than on a block of body copy, the
   way the homepage opens each section on a statement. Only a step up in size, so
   a longer opening paragraph than the one shipped still holds together. */
#our-story .folio > div > .prose:first-child > p:first-child{
  font-family:var(--display);font-weight:700;letter-spacing:-.02em;color:var(--fg);
  font-size:clamp(20px,2.2vw,29px);line-height:1.24;max-width:30ch}

/* ---------- the story blocks take four shapes in turn ----------
   Five identical rows of picture and paragraph is a long scroll with nothing to
   hold on to. Every shape below keeps the same 4:3.3 picture, so one crop still
   serves all of them; what changes is width, side, alignment and overlap. */

/* Two rules do most of the work here.

   The picture stretches to whatever height the words beside it need, so a block
   with three paragraphs no longer leaves its text running on past the bottom of
   a picture that stopped short. Its own 4:3.3 sets the minimum, so a short block
   is unchanged; anything longer simply gives a taller picture.

   And the widths only ever differ by a little. Sending one column down to four
   tenths of the page made that block's measure look like a mistake next to the
   others, so every shape now keeps its text between roughly 46 and 54 per cent. */
.feature{align-items:stretch}
.feature__text{position:relative}
/* the picture is sized by the row rather than by its own ratio. Left on an aspect
   ratio it widened itself to match the taller height and pushed the page sideways;
   a floor under the height does the same job and cannot overflow. */
#our-story .feature__media{aspect-ratio:auto;min-height:clamp(300px,28vw,430px)}

/* 01 leads: a slightly larger picture and a heading a size up */
.feature--lead{grid-template-columns:1.18fr 1fr}
.feature--lead h2{font-size:clamp(30px,4.2vw,56px)}

/* the picture shrinks to a column and the measure widens beside it, top aligned
   so the block reads as a note against a picture rather than another pairing */
.feature--column{grid-template-columns:1fr 1.18fr}
.feature--column .prose{max-width:58ch}

/* the picture runs wide, the measure beside it narrows. Nothing overlaps: the
   text card sitting over the picture covered whoever stood at that edge of it */
/* order places the text in the first column, so the wider track is the second */
.feature--bleed{grid-template-columns:1fr 1.18fr}
.feature--bleed .feature__media{order:2}
.feature--bleed .feature__text{order:1}

/* more air around the two that carry the most, less between the pair that read
   as a spread, so the scroll has a beat to it rather than a metronome */
.feature--lead + .feature{margin-top:clamp(56px,6.6vw,110px)}
.feature--bleed{margin-top:clamp(56px,6.6vw,110px)}
.feature--bleed + .feature{margin-top:clamp(56px,6.6vw,110px)}

/* each block arrives on its own rather than the whole section at once */
.js #our-story .feature{transition:opacity .6s cubic-bezier(.22,.61,.36,1),
  transform .6s cubic-bezier(.22,.61,.36,1)}

@media(max-width:900px){
  .feature--lead,.feature--column,.feature--bleed{grid-template-columns:1fr;
    gap:clamp(28px,4.4vw,76px)}
  /* stacked, there is no text beside it to match, so the picture goes back to
     the shape it was cropped to */
  #our-story .feature__media{aspect-ratio:4/3.3;min-height:0}
  /* the picture leads on a phone whatever shape the block takes: the reset for a
     flipped block was declared above the rule it undoes, so it never applied */
  .feature--flip .feature__media{order:0}
  .feature--bleed .feature__media{order:0}
}
@media(prefers-reduced-motion:reduce){
  .js #our-story .feature{transition:none}
}

/* ---------- services as cards ---------- */
.svccards{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(14px,1.8vw,24px)}
@media(max-width:820px){.svccards{grid-template-columns:1fr}}
.svccard{background:var(--bg);border:1px solid var(--rule);border-radius:var(--r-2);
  padding:clamp(24px,2.4vw,34px);display:flex;flex-direction:column;gap:11px;
  transition:border-color .25s,transform .3s cubic-bezier(.22,.61,.36,1),box-shadow .3s}
.svccard:hover{border-color:var(--brand);transform:translateY(-3px);
  box-shadow:0 16px 40px rgba(44,49,55,.13)}
.svccard__ico{width:48px;height:48px;border-radius:50%;background:var(--brand);flex:none;
  display:grid;place-items:center;margin-bottom:4px}
.svccard__ico svg{width:23px;height:23px;fill:none;stroke:#15180F;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.svccard h2{font-family:var(--body);font-size:clamp(20px,2vw,26px);font-weight:600;
  letter-spacing:-.025em;line-height:1.15;color:var(--fg)}
.svccard p{font-size:15.5px;color:var(--fg-2)}
.svccard p + p{margin-top:2px}
.spread--tint .svccard{color:#2C3137;--fg:#2C3137;--fg-2:#4E545B;--fg-3:#6D747B;
  --accent:#B02D95;--rule:rgba(44,49,55,.14);--rule-2:rgba(44,49,55,.28)}

.filters{align-items:center}
.filters__label{display:inline-flex;align-items:center;gap:9px;margin-right:6px;
  font-family:var(--body);font-size:11.5px;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--fg-3);white-space:nowrap}
.filters__label svg{width:16px;height:16px;fill:none;stroke:var(--accent);stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.filters__item{cursor:pointer}
.work--archive .card{transition:opacity .35s ease,transform .35s cubic-bezier(.22,.61,.36,1),
  border-color .25s,box-shadow .3s}
.card.is-filtered,.case.is-filtered,.runband.is-filtered{display:none}
.filters__count{font-family:var(--body);font-weight:600;font-size:12.5px;color:var(--fg-3);
  margin-left:auto;white-space:nowrap}
.pagehero .btn--ghost{color:#FFFFFF;box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.45)}
.pagehero .btn--ghost:hover{box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.85)}
.pagehero--brand .btn--ghost{background:transparent;color:#15180F;
  box-shadow:inset 0 0 0 1.5px rgba(21,24,15,.45)}
.pagehero--brand .btn--ghost:hover{box-shadow:inset 0 0 0 1.5px rgba(21,24,15,.85)}
.pagehero--brand{position:relative;overflow:hidden}
.pagehero--brand::after{content:"";position:absolute;right:-2%;top:50%;translate:0 -50%;
  width:min(46%,540px);aspect-ratio:1;opacity:.17;pointer-events:none;
  background-image:radial-gradient(circle,#15180F 2px,transparent 2.6px);
  background-size:clamp(22px,2.4vw,34px) clamp(22px,2.4vw,34px);
  -webkit-mask-image:radial-gradient(circle at 60% 50%,#000 32%,transparent 72%);
  mask-image:radial-gradient(circle at 60% 50%,#000 32%,transparent 72%)}
@media(max-width:900px){.pagehero--brand::after{display:none}}

/* ---------- the people ---------- */
.people{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(16px,2vw,28px);
  margin-top:clamp(28px,3.4vw,46px)}
@media(max-width:1100px){.people{grid-template-columns:repeat(3,1fr)}}
@media(max-width:760px){.people{grid-template-columns:repeat(2,1fr)}}
@media(max-width:420px){.people{grid-template-columns:1fr}}

.person{display:flex;flex-direction:column;gap:14px;text-decoration:none}
.person__portrait{position:relative;aspect-ratio:3/3.6;border-radius:var(--r-2);
  overflow:hidden;display:grid;place-items:center;
  box-shadow:0 12px 30px rgba(44,49,55,.14);transition:box-shadow .35s,transform .35s
  cubic-bezier(.22,.61,.36,1)}
.person:hover .person__portrait{transform:translateY(-5px);
  box-shadow:0 22px 48px rgba(44,49,55,.24)}
.person__portrait img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1s cubic-bezier(.22,.61,.36,1)}
.person:hover .person__portrait img{transform:scale(1.05)}
.person__mono{font-family:var(--body);font-weight:600;letter-spacing:.06em;
  font-size:clamp(34px,3.6vw,52px);color:rgba(255,255,255,.94);line-height:1;
  transition:transform .5s cubic-bezier(.22,.61,.36,1)}
.person:hover .person__mono{transform:scale(1.08)}
.person__portrait::after{content:"";position:absolute;inset:auto 0 0 0;height:4px;
  background:var(--brand);transform:scaleX(0);transform-origin:0 50%;
  transition:transform .4s cubic-bezier(.22,.61,.36,1)}
.person:hover .person__portrait::after{transform:scaleX(1)}

.person__name{font-family:var(--body);font-weight:600;font-size:clamp(17px,1.5vw,20px);
  letter-spacing:-.015em;color:var(--fg);line-height:1.2}
.person__role{font-family:var(--body);font-size:11.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent);margin-top:5px;display:block}
.spread--tint .person__name{color:#FFFFFF}
.spread--tint .person__role{color:#FFFFFF;opacity:.82}
.spread--tint .person__portrait{box-shadow:0 12px 30px rgba(21,24,15,.22)}

/* monogram grounds, rotating through the palette */
.person:nth-child(5n+1) .person__portrait{background:linear-gradient(150deg,#3B2A45,#8E2A6E)}
.person:nth-child(5n+2) .person__portrait{background:linear-gradient(150deg,#2E2136,#C21A6B)}
.person:nth-child(5n+3) .person__portrait{background:linear-gradient(150deg,#46620F,#9ACD32)}
.person:nth-child(5n+4) .person__portrait{background:linear-gradient(150deg,#5C2E63,#E0417F)}
.person:nth-child(5n+5) .person__portrait{background:linear-gradient(150deg,#233118,#6E9A16)}
/* on a brand green band the two green grounds vanish — swap them for plum */
.spread--tint .person:nth-child(5n+3) .person__portrait{background:linear-gradient(150deg,#2A2033,#6E2A80)}
.spread--tint .person:nth-child(5n+5) .person__portrait{background:linear-gradient(150deg,#3A1F2E,#A32463)}
/* hovering the mark lifts it; the grid keeps its own quiet rhythm */
.brandlink{position:relative;
  transition:transform .35s cubic-bezier(.22,.61,.36,1)}
.brandlink:hover,.brandlink:focus-visible{transform:translateY(-2px)}
/* Light crossing the grid on the diagonal. Each square of the artwork has an
   element sitting exactly over it in a paler green, and the five diagonals of
   a three by three grid come up a fifth of a second apart, which reads as a
   ripple rather than as a sequence of lamps.

   The geometry below is measured off the logo file itself: columns at 24, 148
   and 271 and rows at 120, 244 and 367 of its 1500 by 581 canvas, each square
   82 across, with a pixel of bleed all round so no edge of the original shows
   through the lit one. Percentages rather than pixels, so it holds at every
   size the header renders the mark at. Replace the artwork and these stop
   lining up, which is why a logo uploaded in Customizer gets no ripple. */
.brandmark .bm{position:absolute;display:block;background:var(--brand-lit);
  opacity:0;pointer-events:none;
  animation:markRipple 9s linear infinite}
.bm--c0{left:1.5333%;width:5.6000%}
.bm--c1{left:9.8000%;width:5.6000%}
.bm--c2{left:18.0000%;width:5.6667%}
.bm--r0{top:20.4819%;height:14.4578%}
.bm--r1{top:41.8244%;height:14.4578%}
.bm--r2{top:62.9948%;height:14.4578%}
/* These carry the .brandmark prefix so they weigh the same as the rule above.
   Without it the shorthand there, which sets a delay of its own, outranked them
   and all nine squares lit together as one pulse instead of rippling.

   A seventh of a second between diagonals, against a crest that lasts about
   four tenths. Because each square stays lit roughly three times as long as it
   takes the next to start, the lit squares overlap and the crest reads as one
   thing travelling rather than five lamps taking turns. Cross the whole grid
   in under a second, then nothing for eight. */
.brandmark .bm--w0{animation-delay:0s}
.brandmark .bm--w1{animation-delay:.14s}
.brandmark .bm--w2{animation-delay:.28s}
.brandmark .bm--w3{animation-delay:.42s}
.brandmark .bm--w4{animation-delay:.56s}
/* shaped as a bell rather than a square pulse: up in a tenth of a second,
   down over a quarter, which is how light passing over something behaves */
@keyframes markRipple{
  0%{opacity:0}
  0.8%{opacity:.55}
  1.5%{opacity:1}
  2.6%{opacity:.55}
  4.4%{opacity:0}
  100%{opacity:0}}
@media(prefers-reduced-motion:reduce){
  .brandlink:hover{transform:none}
  .brandmark .bm{animation:none;opacity:0}}
.nav a{white-space:nowrap}

/* ---------- navigation: sliding indicator ---------- */
.nav{position:relative}
.nav a{border-bottom:none!important;position:relative}
.nav__ind{position:absolute;bottom:2px;left:0;height:2px;width:0;background:var(--accent);
  border-radius:2px;opacity:0;pointer-events:none;
  transition:transform .4s cubic-bezier(.22,.61,.36,1),width .4s cubic-bezier(.22,.61,.36,1),
             opacity .25s,background .25s}
.nav__ind.is-live{opacity:1}
.nav a.is-active{color:var(--fg)}

/* ---------- navigation: preview panels ---------- */

/* ---------- sticky section rail ---------- */
.railnav{position:fixed;left:10px;top:50%;z-index:60;
  display:none;flex-direction:column;gap:1px;padding:12px 10px;border-radius:16px;
  opacity:0;visibility:hidden;transform:translateY(-50%) translateX(-12px);
  transition:background .28s ease,box-shadow .28s ease,opacity .35s ease,
             transform .35s cubic-bezier(.22,.61,.36,1),visibility .35s}
.railnav.is-visible{opacity:1;visibility:visible;transform:translateY(-50%)}
@media(min-width:1320px){.railnav{display:flex}}
/* the labels are always on show now, so the rail carries its own quiet ground:
   without one the type would sit straight over a brand green band or a
   photograph and stop being readable half way down the page */
.railnav{background:color-mix(in srgb,var(--bg) 95%,transparent);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  box-shadow:0 1px 0 rgba(44,49,55,.05),0 10px 26px rgba(44,49,55,.07)}
.railnav:hover,.railnav:focus-within{
  background:color-mix(in srgb,var(--bg) 96%,transparent);
  box-shadow:0 14px 36px rgba(44,49,55,.14)}
/* the marker sits in a fixed slot, so the live one can widen without shunting
   its label out of line with the rest */
.railnav a{display:grid;grid-template-columns:46px 1fr;align-items:center;gap:11px;
  text-decoration:none;padding:6px 4px;justify-items:start}
.railnav i{display:block;position:relative;overflow:hidden;width:18px;height:3px;
  border-radius:3px;background:var(--rule-2);
  flex:none;transition:width .32s cubic-bezier(.22,.61,.36,1),background .28s}
.railnav a:hover i{background:var(--fg-2);width:26px}
/* the live marker widens into a track and fills as you move through that section */
.railnav a.is-on i{width:46px;background:rgba(176,45,149,.22)}
.railnav i::after{content:"";position:absolute;inset:0;border-radius:3px;
  background:var(--accent);transform-origin:0 50%;transform:scaleX(0);
  transition:transform .18s linear}
.railnav a.is-on i::after{transform:scaleX(var(--p,0))}
/* every section is named all the time; the one you are in is the loud one */
.railnav span{font-family:var(--body);font-size:10.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--fg-2);white-space:nowrap;opacity:1;
  transition:color .25s ease,opacity .25s ease}
.railnav a:hover span{color:var(--fg)}
.railnav a.is-on span{color:var(--accent);font-weight:800;letter-spacing:.15em;
  font-size:11.5px}
.railnav a:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:6px}
/* arriving at a section: the marker pulses once so the eye catches it */
/* arriving at a section: a shine crosses the marker and the whole rail wakes for a moment */
@keyframes railShine{
  0%{transform:translateX(-110%)}
  100%{transform:translateX(130%)}}
@keyframes railHalo{
  0%{filter:drop-shadow(0 0 0 rgba(176,45,149,0))}
  35%{filter:drop-shadow(0 0 7px rgba(176,45,149,.95))}
  100%{filter:drop-shadow(0 0 0 rgba(176,45,149,0))}}
@keyframes railLabel{
  0%{opacity:0;transform:translateX(-10px)}
  30%{opacity:1;transform:none}
  100%{opacity:1;transform:none}}
.railnav a.is-arriving i::before{content:"";position:absolute;inset:0;z-index:3;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.95),transparent);
  animation:railShine .85s ease-out 1 both}
.railnav a.is-arriving i{animation:railHalo .85s ease-out 1 both}
.railnav a.is-arriving span{animation:railLabel .75s ease-out}
@media(prefers-reduced-motion:reduce){.railnav i,.railnav span{transition:none;animation:none}}
/* the section you are inside stays lit while one of its blocks is live */
.railnav a.is-within i{background:var(--rule-2);width:30px}
.railnav a.is-within span{color:var(--fg);font-weight:700}

/* a block listed under the section it belongs to */
.railnav a.is-sub{padding-left:16px}
.railnav a.is-sub i{width:12px}
.railnav a.is-sub:hover i{width:18px}
.railnav a.is-sub.is-on i{width:34px}
.railnav a.is-sub span{font-size:9.8px;letter-spacing:.12em;color:var(--fg-3)}
.railnav a.is-sub:hover span{color:var(--fg-2)}
.railnav a.is-sub.is-on span{font-size:10.5px}

/* Names that would reach across the text: the rail keeps to its markers and
   gives them when it is pointed at. Wider windows simply show them. */
/* below this the gutter is too slim for even the markers to clear the text */
/* the page steps right by whatever the rail needs and by nothing otherwise;
   the footer has no rail beside it, so it keeps the even gutter */
@media(min-width:1320px){
  .wrap{padding-left:calc(var(--gut) + var(--railpush,0px))}
  /* the rail is not beside the opening screen or the footer, so those keep the
     even gutter — a page that stepped right before the rail appeared would
     look like a mistake */
  .hero .wrap,.pagehero .wrap,.casehero .wrap,footer .wrap{padding-left:var(--gut)}
}
@media(max-width:1399px){.railnav--long{display:none}}
.railnav.is-measuring,.railnav.is-measuring *{transition:none !important}
.railnav--long a{gap:0;transition:gap .3s cubic-bezier(.22,.61,.36,1)}
.railnav--long span{max-width:0;opacity:0;overflow:hidden;text-overflow:ellipsis;
  transition:color .25s ease,opacity .25s ease,
             max-width .3s cubic-bezier(.22,.61,.36,1)}
.railnav--long:hover a,.railnav--long:focus-within a{gap:11px}
.railnav--long:hover span,.railnav--long:focus-within span{max-width:32ch;opacity:1}
@media(min-width:1560px){
  .railnav--long a{gap:11px}
  .railnav--long span{max-width:10ch;opacity:1}}
@media(min-width:1760px){.railnav--long span{max-width:19ch}}
@media(prefers-reduced-motion:reduce){.railnav--long a,.railnav--long span{transition:none}}

/* ---------- our work: asymmetric gallery ---------- */
.gal{display:grid;grid-template-columns:repeat(12,1fr);gap:clamp(10px,1.4vw,20px)}
.gal figure{margin:0;position:relative;overflow:hidden;border-radius:var(--r-2);
  background:var(--deep-2);display:block;text-decoration:none}
.gal img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1s cubic-bezier(.22,.61,.36,1)}
.gal a:hover img{transform:scale(1.05)}
.gal figcaption{position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:clamp(16px,1.8vw,26px);
  background:linear-gradient(to top,rgba(24,17,28,.92) 0%,rgba(24,17,28,.66) 46%,transparent)}
.gal figcaption b{display:block;font-family:var(--body);font-weight:600;font-size:10.5px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--brand);margin-bottom:7px}
.gal figcaption span{display:block;font-family:var(--display);
  font-size:clamp(17px,1.7vw,23px);letter-spacing:-.03em;line-height:1.12;color:#FFFFFF}
.gal figcaption em{font-style:normal;display:block;margin-top:9px;font-size:13.5px;
  color:rgba(255,255,255,.74)}
.gal a{display:block;text-decoration:none;position:relative;overflow:hidden;
  border-radius:var(--r-2);transition:transform .35s cubic-bezier(.22,.61,.36,1),box-shadow .35s}
.gal a:hover{transform:translateY(-3px);box-shadow:0 20px 44px rgba(44,49,55,.20)}
.gal a:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent)}
.g-a{grid-column:span 7;aspect-ratio:16/10}
.g-b{grid-column:span 5;aspect-ratio:4/3.4}
.g-c{grid-column:span 5;aspect-ratio:4/3.4}
.g-d{grid-column:span 7;aspect-ratio:16/10}
@media(max-width:900px){.g-a,.g-b,.g-c,.g-d{grid-column:span 12;aspect-ratio:16/10}}

/* ---------- gallery captions: pink titles, services divided by hairlines ---------- */
.gal figcaption span{color:#EC82C6}
.gal figcaption em{display:flex;flex-wrap:wrap;row-gap:6px;margin-top:11px;font-style:normal}
.gal figcaption em i{font-style:normal;font-size:12.5px;line-height:1.15;
  color:rgba(255,255,255,.82);padding:0 11px;border-left:1px solid rgba(255,255,255,.5)}
.gal figcaption em i:first-child{padding-left:0;border-left:none}

/* ---------- in-section calls to action ---------- */
/* the link, the two actions and the invitation that close a band */
.tailrow{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-start;
  gap:clamp(14px,1.8vw,26px);margin-top:clamp(26px,3vw,40px)}
.tailrow .more{margin-top:0;margin-right:clamp(2px,.6vw,10px)}
.lead{display:grid;grid-template-columns:1.05fr 1fr;gap:clamp(24px,4vw,64px);
  align-items:start;margin-bottom:clamp(34px,4vw,58px)}
@media(max-width:900px){.lead{grid-template-columns:1fr;gap:18px}}
.lead h2{font-size:clamp(27px,3.4vw,46px);letter-spacing:-.03em;max-width:15ch}
.lead__body p{font-size:16.5px;color:var(--fg-2);max-width:54ch}
.lead__body p + p{margin-top:1.05em}
.spread--tint .lead__body p{color:#20290B}

/* a closing invitation: heading, copy, then the two actions */
.invite{margin-top:clamp(30px,3.4vw,48px);padding-top:clamp(26px,3vw,40px);
  border-top:1px solid var(--rule)}
.invite h3{font-family:var(--display);font-weight:800;letter-spacing:-.018em;
  font-size:clamp(24px,2.6vw,36px);line-height:1.05}
.invite p{margin-top:14px;max-width:58ch;font-size:16.5px;color:var(--fg-2)}
.invite__row{display:flex;flex-wrap:wrap;gap:16px;margin-top:clamp(20px,2.2vw,28px)}
@media(max-width:600px){.invite__row .btn{flex:1 1 auto;justify-content:center}}
.spread--tint .invite p{color:#20290B}
@media(max-width:600px){.tailrow{gap:14px}.tailrow .btn{flex:1 1 auto;justify-content:center}}

/* email in the header and the closing band */
.mailtop{font-family:var(--body);font-weight:600;font-size:13.5px;color:var(--fg-2);
  text-decoration:none;white-space:nowrap;border-bottom:2px solid var(--accent);
  padding-bottom:3px;transition:color .2s}
.mailtop:hover{color:var(--accent)}
@media(max-width:1420px){.mailtop{display:none}}
.cta__mail{font-family:var(--body);font-weight:600;font-size:clamp(15px,1.4vw,18px);
  color:#15180F;text-decoration:none;border-bottom:2px solid rgba(21,24,15,.45);
  padding-bottom:3px}

/* ---------- contact page ---------- */
.contact{display:grid;grid-template-columns:1.42fr .88fr;gap:clamp(28px,4vw,64px);align-items:start}
@media(max-width:980px){.contact{grid-template-columns:1fr}}
.form{background:#F4F7EC;border:1px solid var(--rule);border-radius:4px;padding:clamp(22px,2.7vw,40px)}
.form h2{font-size:clamp(23px,2.5vw,34px);letter-spacing:-.018em}
.form__note{margin-top:.75em;color:var(--fg-2);font-size:15.5px;max-width:48ch}
.form__grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:26px}
.form__grid .f--wide{grid-column:1/-1}
@media(max-width:620px){.form__grid{grid-template-columns:1fr}}
.f label{display:block;font-family:var(--body);font-weight:600;font-size:12px;
  letter-spacing:.09em;text-transform:uppercase;color:var(--fg-3);margin-bottom:7px}
.f input,.f select,.f textarea{width:100%;font-family:var(--body);font-size:16px;color:var(--fg);
  background:#FFFFFF;border:1px solid var(--rule-2);border-radius:3px;padding:.78em .9em;line-height:1.4}
.f textarea{min-height:148px;resize:vertical}
.f input:focus,.f select:focus,.f textarea:focus{outline:none;border-color:#6E9420;
  box-shadow:0 0 0 3px rgba(154,205,50,.34)}
.form__consent{display:flex;gap:11px;align-items:flex-start;margin-top:20px;font-size:14.5px;color:var(--fg-2)}
.form__consent input{margin-top:4px;width:17px;height:17px;accent-color:var(--brand);flex:none}
.form__send{margin-top:24px;display:flex;gap:18px;align-items:center;flex-wrap:wrap}
.form__send .btn{background:var(--fg);color:#FDFEFF}
.form__small{font-size:13.5px;color:var(--fg-3)}
.hp{position:absolute!important;left:-9999px;width:1px;height:1px;overflow:hidden}
.notice{border-left:3px solid #6E9420;background:rgba(154,205,50,.18);border-radius:0 3px 3px 0;
  padding:15px 20px;margin-bottom:24px;font-size:15.5px;color:var(--fg)}
.notice--warn{border-left-color:var(--accent);background:var(--accent-soft)}
.aside__block{border-top:1px solid var(--rule);padding-top:20px;margin-top:26px}
.aside__block:first-child{border-top:none;padding-top:0;margin-top:0}
.aside__block h3{font-size:15px;font-weight:800;letter-spacing:.02em}
.aside__block p{font-size:15.5px;color:var(--fg-2);margin-top:8px}
/* the address is the answer to the heading above it, so it is set in the
   display face and a line to itself rather than running on as a sentence */
.aside__addr{display:block;font-style:normal;margin-top:10px;
  font-family:var(--display);font-weight:700;letter-spacing:-.012em;
  font-size:clamp(15.5px,1.4vw,17px);line-height:1.42;color:var(--fg)}
.aside__addr span{display:block}
.aside__addr + p{margin-top:12px}
.aside__big{font-family:var(--display);font-weight:800;font-size:clamp(20px,2vw,27px);
  letter-spacing:-.015em;color:var(--fg);margin-top:9px;display:inline-block;text-decoration:none;
  border-bottom:2px solid var(--brand);line-height:1.25}
.aside__big:hover{color:var(--brand-text)}
.steps{counter-reset:s;margin:12px 0 0;padding:0}
.steps li{list-style:none;counter-increment:s;position:relative;padding-left:42px;
  margin-top:14px;font-size:15.5px;color:var(--fg-2);line-height:1.5}
.steps li::before{content:counter(s,decimal-leading-zero);position:absolute;left:0;top:2px;
  font-family:var(--display);font-weight:800;font-size:12px;letter-spacing:.06em;
  color:var(--brand-text);background:rgba(154,205,50,.24);border-radius:2px;padding:3px 6px}
.qa{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:clamp(16px,2vw,26px);margin-top:4px}
@media(max-width:860px){.qa{grid-auto-flow:row;grid-template-columns:1fr}}
.qa>div{background:#FDFEFF;border:1px solid var(--rule);border-radius:4px;padding:clamp(20px,2.2vw,30px)}
.qa h3{font-size:20.5px;letter-spacing:-.02em;font-weight:700}
.qa p{margin-top:11px;font-size:15.5px;color:var(--fg-2)}

/* where a brand green band runs straight into the closing band, mark the join */
.spread--tint + .cta{border-top:2px solid rgba(255,255,255,.62)}

/* arriving at a section: the nine squares light up in sequence and the label slides in,
   so the folio confirms where you are without you having to look for it */
.grid9 rect{transform-box:fill-box;transform-origin:50% 50%}
.folio__mark.is-live rect{animation:gridPop .62s cubic-bezier(.3,1.4,.5,1) both}
.folio__mark.is-live rect:nth-child(1){animation-delay:0ms}
.folio__mark.is-live rect:nth-child(2){animation-delay:55ms}
.folio__mark.is-live rect:nth-child(4){animation-delay:55ms}
.folio__mark.is-live rect:nth-child(3){animation-delay:110ms}
.folio__mark.is-live rect:nth-child(5){animation-delay:110ms}
.folio__mark.is-live rect:nth-child(7){animation-delay:110ms}
.folio__mark.is-live rect:nth-child(6){animation-delay:165ms}
.folio__mark.is-live rect:nth-child(8){animation-delay:165ms}
.folio__mark.is-live rect:nth-child(9){animation-delay:220ms}
@keyframes gridPop{
  0%{transform:scale(.15);opacity:.25}
  55%{transform:scale(1.35);opacity:1}
  100%{transform:scale(1);opacity:1}}
.folio__mark span{display:inline-block}
.folio__mark.is-live span{animation:folioLabel .7s cubic-bezier(.22,.61,.36,1) .18s both}
@keyframes folioLabel{
  0%{opacity:0;transform:translateX(-14px)}
  100%{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){
  .folio__mark.is-live rect,.folio__mark.is-live span{animation:none}}

/* the year figures arrive one after another once the heading is behind you;
   the cards themselves stay put */
.js .tl__yr{opacity:0;transform:translate3d(0,14px,0);
  transition:opacity 1.15s cubic-bezier(.22,.61,.36,1),transform 1.15s cubic-bezier(.22,.61,.36,1)}
.js .tl.is-lit .tl__yr{opacity:1;transform:none}
.tl.is-lit>div:nth-child(1) .tl__yr{transition-delay:0ms}
.tl.is-lit>div:nth-child(2) .tl__yr{transition-delay:380ms}
.tl.is-lit>div:nth-child(3) .tl__yr{transition-delay:760ms}
.tl.is-lit>div:nth-child(4) .tl__yr{transition-delay:1140ms}
.tl.is-lit>div:nth-child(5) .tl__yr{transition-delay:1520ms}
.tl.is-lit>div:nth-child(6) .tl__yr{transition-delay:1900ms}
.tl.is-lit>div:nth-child(7) .tl__yr{transition-delay:2280ms}
.tl.is-lit>div:nth-child(8) .tl__yr{transition-delay:2660ms}
@media(prefers-reduced-motion:reduce){
  .js .tl__yr{opacity:1;transform:none;transition:none}}

/* ---------- what we offer: six cards, the badge punched through the image edge ---------- */
.offergrid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2.1vw,30px)}
/* the services page runs two across, as its cards always have */
.offergrid--two{grid-template-columns:repeat(2,1fr)}
@media(max-width:760px){.offergrid--two{grid-template-columns:1fr}}
.offergrid--two .offercard__img{aspect-ratio:4/2.1}
.offergrid--two .offercard p + p{margin-top:.15em}
.offercard .prose{display:flex;flex-direction:column;gap:.7em;text-align:center}
.offercard .prose p{font-size:15.5px;line-height:1.5;color:var(--ink-2);
  transition:color .5s ease}
@media(max-width:1040px){.offergrid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:640px){.offergrid{grid-template-columns:1fr}}

.offercard{--card:#FDFEFF;--ink:#22262B;--ink-2:#4E545B;--tag:rgba(255,255,255,.34);
  position:relative;display:flex;flex-direction:column;text-decoration:none;
  background:var(--card);color:var(--ink);border-radius:var(--r);overflow:hidden;
  box-shadow:0 10px 26px rgba(30,21,36,.10);
  transition:background .5s ease,color .5s ease,transform .5s cubic-bezier(.22,.61,.36,1),
             box-shadow .5s ease}
/* the house magenta, the same ink as the emphasis words in the statements */
.offercard:hover,.offercard:focus-visible{--card:#B02D95;--ink:#FFFFFF;--ink-2:rgba(255,255,255,.90);
  --tag:rgba(255,255,255,.62);transform:translateY(-6px);
  box-shadow:0 30px 64px rgba(120,20,100,.34);outline:none}

.offercard__top{position:relative}
.offercard__img{overflow:hidden;aspect-ratio:4/2.5;background:#2E2136}
.offercard__img img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 5.5s cubic-bezier(.19,.52,.26,1)}
.offercard:hover .offercard__img img{transform:scale(1.14)}

.offercard__badge{position:absolute;left:50%;bottom:0;transform:translate(-50%,50%);
  width:clamp(56px,5vw,68px);aspect-ratio:1;border-radius:999px;z-index:2;
  display:grid;place-items:center;background:var(--brand);color:#1B2408;
  box-shadow:0 0 0 8px var(--card),0 8px 18px rgba(30,21,36,.22);
  transition:box-shadow .5s ease,transform .45s cubic-bezier(.34,1.4,.5,1)}
/* the badge drops a little further out of the image as the card turns */
.offercard:hover .offercard__badge{transform:translate(-50%,50%) translateY(16px) scale(1.06)}
.offercard__badge .svc__ico{width:56%;height:56%;stroke-width:1.6}

.offercard__body{display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:.7em;flex:1;
  padding:calc(clamp(56px,5vw,68px) * .5 + clamp(26px,2.8vw,36px)) clamp(22px,2.4vw,30px)
          clamp(22px,2.4vw,30px)}
.offercard h3{font-family:var(--display);font-weight:800;letter-spacing:-.028em;line-height:1.04;
  font-size:clamp(20px,1.95vw,25px);color:var(--ink);transition:color .5s ease}
.offercard p{font-size:15.5px;line-height:1.5;color:var(--ink-2);transition:color .5s ease}
.offercard__more{margin-top:auto;padding-top:clamp(14px,1.6vw,20px);
  display:inline-flex;align-items:center;gap:.5em;
  font-family:var(--body);font-weight:600;font-size:12.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink);transition:color .5s ease}
.offercard__more{position:relative;padding-bottom:9px;align-self:center}
.offercard__more::before{content:"";position:absolute;left:0;bottom:0;height:2px;
  width:100%;background:var(--brand);transform-origin:50% 50%;transform:scaleX(.5);
  transition:transform .45s cubic-bezier(.22,.61,.36,1)}
.offercard:hover .offercard__more::before{transform:scaleX(1)}
/* on the What we offer page the card is the destination, so the label carries the
   one link the card has, and needs the underline suppressed the card used to give it */
a.offercard__more{text-decoration:none}
a.offercard__more:focus-visible{outline:2px solid var(--brand);outline-offset:5px;border-radius:3px}

@media(prefers-reduced-motion:reduce){
  .offercard,.offercard__img img,.offercard__badge,.offercard__more::before{
    transition:none}
  .offercard:hover{transform:none}
  .offercard:hover .offercard__img img{transform:none}
  .offercard:hover .offercard__badge{transform:translate(-50%,50%)}}

/* ---------- our work: one lead case at scale, three beneath ---------- */
/* ---------- one case study, shown in depth rather than padded out ----------
   Four tiles with one project in them reads as a portfolio somebody has not
   finished filling. While there is a single case study it runs full width with
   its figures and two more photographs under it, which reads as depth. */
.fp__lede{max-width:56ch;margin-top:clamp(14px,1.6vw,22px);
  font-size:clamp(16.5px,1.55vw,19px);line-height:1.55;color:var(--fg-2)}
.fp__lede + .fp__lede{margin-top:.9em}
.fp__lede + .case{margin-top:clamp(22px,2.6vw,38px)}

.fp__facts{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  gap:clamp(16px,2vw,30px);margin-top:clamp(22px,2.6vw,38px)}
.fp__facts>div{border-top:2px solid var(--rule);padding-top:16px}
.fp__facts b{display:block;font-family:var(--display);font-weight:800;
  font-size:clamp(26px,3vw,42px);letter-spacing:-.032em;line-height:1}
.fp__facts b small{font-size:.46em;font-weight:700;letter-spacing:.02em;margin-left:.15em}
.fp__facts span{display:block;margin-top:.6em;font-size:14.5px;line-height:1.45;color:var(--fg-2)}
@media(max-width:760px){.fp__facts{grid-auto-flow:row}}

/* the first picture sets the height of the row and the second matches it, so a
   landscape frame and an upright one sit together without either being squeezed */
.fp__strip{display:grid;grid-template-columns:1.42fr 1fr;
  gap:clamp(12px,1.5vw,22px);margin-top:clamp(16px,1.9vw,26px)}
.fp__strip figure{margin:0;border-radius:var(--r-2);overflow:hidden;
  background:var(--deep-2);box-shadow:0 12px 30px rgba(44,49,55,.13)}
.fp__strip figure:first-child{aspect-ratio:4/3}
.fp__strip img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1.1s cubic-bezier(.22,.61,.36,1)}
.fp__strip figure:hover img{transform:scale(1.05)}
@media(max-width:640px){.fp__strip{grid-template-columns:1fr}
  .fp__strip figure:last-child{aspect-ratio:1}}

/* the lead card carried a scrim heavy enough to read as a dark tile, nearly nine
   tenths black for most of its height. The words sit in the lower left, so the
   cover is shaped to that corner and the rest of the photograph is seen. */
.case--lead .case__media::after{
  background:
    linear-gradient(to top,rgba(20,13,24,.93) 0%,rgba(20,13,24,.74) 22%,
      rgba(20,13,24,.34) 50%,rgba(20,13,24,0) 76%),
    linear-gradient(to right,rgba(20,13,24,.66) 0%,rgba(20,13,24,.30) 38%,
      rgba(20,13,24,0) 64%)}

.cases{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(12px,1.5vw,22px)}
.cases .case--lead{grid-column:1 / -1}
@media(max-width:900px){.cases{grid-template-columns:1fr}}

.case{position:relative;display:block;overflow:hidden;text-decoration:none;
  border-radius:var(--r);background:#2E2136;color:#FFFFFF;
  /* portrait, so the photograph carries the card rather than a strip of it */
  aspect-ratio:4/5;
  transition:transform .5s cubic-bezier(.22,.61,.36,1),box-shadow .5s ease}
.case--lead{aspect-ratio:21/9}
@media(max-width:900px){.case{aspect-ratio:4/4.2}.case--lead{aspect-ratio:16/10}}
.case:hover,.case:focus-visible{transform:translateY(-5px);
  box-shadow:0 30px 66px rgba(30,21,36,.34);outline:none}

.case__media{position:absolute;inset:0}
.case__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 5s cubic-bezier(.19,.52,.26,1)}
.case:hover .case__media img{transform:scale(1.09)}
.case__media::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(20,13,24,.96) 2%,rgba(20,13,24,.88) 36%,
    rgba(20,13,24,.58) 68%,rgba(20,13,24,.12) 100%);
  transition:opacity .5s ease}
.case:hover .case__media::after{opacity:.86}

.case__in{position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:clamp(20px,2.4vw,34px);display:flex;flex-direction:column;
  align-items:flex-start;gap:.55em}
.case--lead .case__in{max-width:min(720px,66%);padding:clamp(24px,3vw,44px)}
/* a solid chip, so the sector reads whatever the photograph is doing behind it */
.case__kick{font-family:var(--body);font-weight:600;font-size:10.5px;letter-spacing:.18em;
  text-transform:uppercase;color:#15180F;background:var(--brand);
  padding:.44em .78em;border-radius:999px;line-height:1;
  transition:background .45s ease,color .45s ease}
.case:hover .case__kick{background:#FFFFFF}
.case h3{font-family:var(--display);font-weight:800;letter-spacing:-.03em;line-height:1.02;
  font-size:clamp(21px,2.1vw,28px);color:#FFFFFF;
  transition:transform .45s cubic-bezier(.22,.61,.36,1)}
.case--lead h3{font-size:clamp(28px,3.6vw,50px)}

/* ---------- narrow screens: the words decide how tall the card is ----------
   The card was a fixed shape with the caption hung off its bottom edge and left
   to find its own height. On a wide screen a title is two lines and there is
   room to spare. On a phone the same title runs to five, the caption grows
   taller than the card, and because it is anchored at the bottom the excess
   leaves through the TOP — which is how the first word of a heading ends up
   sliced off above the picture rather than spilling below it.

   So below this width the card stops being a fixed shape: the picture becomes
   the background, the caption sits in normal flow at the foot, and the card is
   never shorter than what is in it. The caption also stops being held to two
   thirds of the width, which on a phone was only making the heading wrap more. */
@media(max-width:760px){
  .case,.case--lead{aspect-ratio:auto;min-height:clamp(330px,86vw,440px);
    display:flex;flex-direction:column;justify-content:flex-end}
  .case__in,.case--lead .case__in{position:relative;left:auto;right:auto;bottom:auto;
    width:100%;max-width:none;padding:clamp(20px,5vw,28px)}
  /* the general card first, the lead card after it: both selectors carry the
     same weight, so whichever is written last would win on order alone */
  .case h3{font-size:clamp(21px,5.4vw,27px);line-height:1.06}
  .case--lead h3{font-size:clamp(25px,6.4vw,34px);line-height:1.06}
  /* five services at eleven and a half pixels is three lines of dividers on a
     phone, so they run as one wrapped line at a size that fits */
  .case__svcs i{font-size:10.5px;padding:0 8px}
}
.case:hover h3{transform:translateY(-2px)}
.case__svcs{display:flex;flex-wrap:wrap;row-gap:5px;margin-top:.25em}
.case__svcs i{font-style:normal;font-family:var(--body);font-weight:600;font-size:11.5px;
  letter-spacing:.06em;line-height:1.15;color:rgba(255,255,255,.86);
  padding:0 10px;border-left:1px solid rgba(255,255,255,.45)}
.case__svcs i:first-child{padding-left:0;border-left:none}

/* the label's rule is replaced rather than grown: one bar leaves, another arrives */
.case__link{position:relative;overflow:hidden;display:inline-block;margin-top:.5em;
  padding-bottom:7px;font-family:var(--body);font-weight:600;font-size:12px;
  letter-spacing:.16em;text-transform:uppercase;color:#FFFFFF}
.case__link::after,.case__link::before{content:"";position:absolute;left:0;bottom:0;
  width:100%;height:2px;background:var(--brand)}
.case__link::after{transform:translateX(0);transition:transform .38s ease-in}
.case__link::before{transform:translateX(-101%);transition:transform .38s ease-out}
.case:hover .case__link::after,.case:focus-visible .case__link::after{transform:translateX(101%)}
.case:hover .case__link::before,.case:focus-visible .case__link::before{transform:translateX(0)}

/* each case wipes up into view, one after another */
.js .case.pre-wipe{clip-path:inset(0 0 100% 0)}
.case{clip-path:inset(0 0 0 0);
  transition:transform .5s cubic-bezier(.22,.61,.36,1),box-shadow .5s ease,
             clip-path 1.05s cubic-bezier(.22,.61,.36,1) calc(var(--i,0) * 150ms)}
@media(prefers-reduced-motion:reduce){
  .js .case.pre-wipe{clip-path:none}
  .case,.case__media img,.case h3{transition:none}
  .case:hover{transform:none}
  .case:hover .case__media img{transform:none}}

/* ---------- sector filter: a control bar you cannot miss ---------- */
.filters{align-items:center;gap:10px;padding-bottom:clamp(18px,2.2vw,28px);
  border-bottom:1px solid var(--rule);margin-bottom:clamp(24px,3vw,40px)}
.filters__label{font-size:12px;letter-spacing:.18em;font-weight:700;color:var(--fg);
  margin-right:10px}
.filters__label svg{width:18px;height:18px;stroke:var(--brand);stroke-width:2}
.filters__item{position:relative;overflow:hidden;font-family:var(--body);font-weight:700;
  font-size:14.5px;letter-spacing:.03em;text-transform:none;
  padding:.62em 1.25em;border:2px solid var(--fg);border-radius:999px;
  color:var(--fg);background:transparent;isolation:isolate;
  transition:color .3s ease,border-color .3s ease,transform .3s cubic-bezier(.22,.61,.36,1)}
/* the fill sweeps up from the bottom rather than simply switching colour */
.filters__item::before{content:"";position:absolute;inset:0;z-index:-1;
  background:var(--brand);transform:translateY(101%);
  transition:transform .34s cubic-bezier(.22,.61,.36,1)}
.filters__item:hover{color:#15180F;border-color:var(--brand);transform:translateY(-2px)}
.filters__item:hover::before{transform:translateY(0)}
.filters__item.is-on{background:var(--accent);border-color:var(--accent);color:#FFFFFF}
.filters__item.is-on::before{background:var(--accent);transform:translateY(0)}
.filters__item:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(176,45,149,.4)}
.filters__count{margin-left:auto;font-size:13px;font-weight:700;color:var(--fg-2);
  letter-spacing:.02em}
@media(max-width:700px){
  .filters{gap:8px}
  .filters__item{font-size:13.5px;padding:.55em 1.05em}
  .filters__count{margin-left:0;width:100%}}

/* the pager follows the filter bar's language */
.pager .nav-links{gap:10px}
.pager a,.pager .current{font-family:var(--body);font-weight:700;font-size:14.5px;
  padding:.55em 1.1em;border:2px solid var(--fg);border-radius:999px;
  transition:background .28s ease,color .28s ease,border-color .28s ease,transform .28s ease}
.pager a:hover{background:var(--brand);border-color:var(--brand);color:#15180F;
  transform:translateY(-2px)}
.pager .current{background:var(--accent);border-color:var(--accent);color:#FFFFFF}

/* ---------- accreditations: each plate turns to show what it is ---------- */
.acc{overflow:visible;background:none;border:none;border-radius:0;
  gap:clamp(9px,1.1vw,15px)}
/* The perspective has to be short relative to the plate or the turn does not
   read as a turn: at 1100px a 250px plate barely narrows until it is most of
   the way round, so it looks like a white panel sitting still with its edge
   twitching. At this distance the near edge comes forward and the far edge
   falls away, and the plate still never grows past its own slot. */
.acc>div{position:relative;background:transparent;border:none;padding:0;
  perspective:520px;min-height:clamp(122px,11.5vw,158px)}
/* the one that is turning paints above the plates either side of it */
.acc>div.is-flipped,.acc>div.is-hover,.acc>div.is-returning{z-index:2}
/* The plate used to be a flat panel, and hovering it tinted that panel. Now it
   is only the holder for the two faces, so a background on it paints a flat
   rectangle sitting still in the slot while the faces turn over the top of it —
   which is exactly what it looked like. It stays transparent, hovered or not.
   The category on the reverse keeps its green for the same reason: the hover
   colour was written for a white panel and is unreadable on the dark face. */
.acc>div,.acc>div:hover{background:transparent}
.acc>div:hover .acc__cat{color:var(--brand)}
.acc>div::before{display:none}
.acc__flip{position:absolute;inset:0;transform-style:preserve-3d;
  /* the resting rule governs the return, so it can run slower than the turn out;
     a symmetric ease keeps the middle of the rotation from whipping past */
  transition:transform 2.8s cubic-bezier(.45,.05,.45,.95)}
.acc>div.is-flipped .acc__flip{transform:rotateY(180deg);
  transition:transform 2s cubic-bezier(.45,.05,.45,.95)}
/* Turning one by hand. The idle cycle is a slow drift in the background; a
   plate under the pointer has to answer straight away, and come straight back
   when the pointer leaves, so both directions run at their own speed. */
.acc>div.is-hover .acc__flip{transform:rotateY(180deg)}
.acc>div.is-hover .acc__flip,
.acc>div.is-returning .acc__flip{transition:transform .7s cubic-bezier(.32,.72,.3,1)}
/* No shadow on either face. A shadow cast by a face that is being rotated in
   3D is composited against the layer behind it rather than the green band, and
   shows as a pale rectangle sitting still inside the plate's slot while the
   plate turns over it. */
.acc__face{position:absolute;inset:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:8px;text-align:center;padding:20px 16px;border-radius:var(--r-3);
  border:1px solid var(--rule);background:var(--bg)}
.acc__face--back{transform:rotateY(180deg);background:#2E2136;border-color:#2E2136}
.acc__name{font-family:var(--display);font-weight:800;letter-spacing:-.022em;
  font-size:clamp(20px,1.9vw,26px);color:var(--fg);line-height:1.05}
/* the homepage grid is a shortlist, and says so before you count the plates */
.acc__lede{max-width:70ch;color:var(--fg-2);font-size:17px;line-height:1.62;
  margin:clamp(18px,1.8vw,26px) 0 clamp(26px,2.8vw,40px)}


/* Every supplied logo is cut to one canvas by tools/gen_logo.py — trimmed to its
   ink, then scaled so the ink covers the same area on every brand. So the plate
   only has to hold one box and the marks line up on their own: a long wordmark
   sits low and wide, a square mark sits taller, and the two carry equal weight.
   Matching raw heights instead would leave the wordmarks looking twice the size. */
.acc__plate{width:min(100%,178px);aspect-ratio:420/148;display:grid;place-items:center;
  margin:0 auto;height:auto}
.acc__logo,.acc__plate img{display:block;width:100%;height:100%;max-height:none;
  object-fit:contain;margin:0}
/* the reverse is the proud bit: what it is, and that we hold it */
.acc__face--back .acc__cat{font-family:var(--display);font-weight:800;letter-spacing:-.02em;
  text-transform:none;font-size:clamp(18px,1.75vw,24px);line-height:1.05;color:var(--brand)}
/* the reverse carries anything from two words to a full sentence, so the
   display type steps down a tier or two rather than running off the plate */
.acc__face--back .acc__cat--long{font-size:clamp(15px,1.42vw,19px)}
.acc__face--back .acc__cat--xlong{font-size:clamp(13px,1.2vw,16px);
  letter-spacing:-.012em;line-height:1.14}
.acc__face--back .acc__rel{font-family:var(--body);font-weight:700;font-size:10.5px;
  letter-spacing:.2em;text-transform:uppercase;color:#FFFFFF;
  border-top:1px solid rgba(255,255,255,.35);padding-top:9px;margin-top:2px}
.spread--tint .acc>div .acc__face{border-color:rgba(255,255,255,.35)}
.spread--tint .acc>div .acc__face--back{border-color:#2E2136}
@media(prefers-reduced-motion:reduce){
  .acc__flip{transition:none}
  .acc>div.is-flipped .acc__flip{transform:none}
  .acc>div.is-hover .acc__flip{transform:rotateY(180deg);transition:none}
  .acc>div.is-returning .acc__flip{transition:none}}

/* ==========================================================================
   The case study page. The homepage devices, taken further: a reader who has
   clicked into a project has already said they are interested, so the page can
   hold a full bleed picture for longer, set type larger and move more.
   ========================================================================== */

.cs{--ink:#FDFEFF;--deep:#1A1220}

/* ---- opening: the picture holds the whole frame, the title sits in it ---- */
.cs-hero{position:relative;min-height:min(92vh,880px);display:flex;align-items:flex-start;
  overflow:hidden;background:#1A1220;isolation:isolate}
.cs-hero__bg{position:absolute;inset:-6% 0 -6% 0;z-index:0;will-change:transform}
.cs-hero__bg img{width:100%;height:100%;object-fit:cover;display:block}
/* The shade follows the words. They sit at the top of the frame, so the heavy
   end of the gradient is at the top with them, and enough is left at the foot
   to hold the scroll cue and to stop the picture ending on a hard edge. */
.cs-hero::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to bottom,rgba(16,10,22,.92) 0%,rgba(16,10,22,.70) 30%,
    rgba(16,10,22,.26) 62%,rgba(16,10,22,.46) 100%)}
.cs-hero__in{position:relative;z-index:2;width:100%;
  padding-block:clamp(40px,5.4vw,84px) clamp(48px,7vw,110px)}
/* A short title in a wide measure sits small in a full height frame and stops
   carrying the picture. The measure is tight enough to force two or three lines
   whatever the title says, and the shadow is there to hold the type off a busy
   photograph rather than to be seen. */
.cs-hero h1{color:#FFF;font-size:clamp(42px,7.4vw,108px);line-height:.95;
  letter-spacing:-.035em;max-width:15ch;font-weight:800;
  text-shadow:0 2px 28px rgba(10,6,14,.5)}
/* The emphasised words take the lighter magenta, not the brand one. Measured
   over this hero the brand magenta reaches about 3.1 to 1 against the shaded
   picture, which is at the floor for type this size and under it on a light
   photograph. The lighter tone holds around 6.8 and still reads as the same
   colour. Set upright: the italic was doing nothing the colour does not. */
.cs-hero h1 em{font-style:normal;color:var(--accent-lit)}
.cs-hero__lede{color:rgba(255,255,255,.90);max-width:52ch;margin-top:clamp(18px,2vw,28px);
  font-size:clamp(17px,1.75vw,22px);line-height:1.5}
.cs-chip{display:inline-block;background:var(--brand);color:#1B2408;border-radius:999px;
  padding:.5em 1.05em;font-family:var(--body);font-weight:700;font-size:11.5px;
  letter-spacing:.18em;text-transform:uppercase;margin-bottom:1.1em}
.cs-hero__cue{position:absolute;left:0;right:0;bottom:18px;z-index:2;text-align:center;
  color:rgba(255,255,255,.5);font-family:var(--body);font-size:11px;letter-spacing:.24em;
  text-transform:uppercase}
.cs-hero__cue span{display:block;width:1px;height:34px;margin:10px auto 0;
  background:linear-gradient(rgba(255,255,255,.6),transparent);
  animation:cs-cue 2.4s ease-in-out infinite}
@keyframes cs-cue{0%,100%{transform:scaleY(.35);opacity:.35}50%{transform:scaleY(1);opacity:1}}
/* The words are at the top and the cue at the foot, so they no longer collide
   and the extra bottom padding that kept them apart has gone. The cue itself
   still goes below a laptop: nobody needs telling to scroll on a phone. */
@media(max-width:1023px){.cs-hero__cue{display:none}}

/* ---- the standfirst: one paragraph at statement size, then the body ---- */
.cs-open{padding-block:clamp(48px,6.5vw,104px)}
.cs-open__grid{display:grid;grid-template-columns:1.15fr 1fr;gap:clamp(28px,5vw,90px);
  align-items:end}
.cs-open__lead > p{font-family:var(--display);font-weight:700;letter-spacing:-.022em;
  font-size:clamp(22px,2.6vw,34px);line-height:1.2;color:var(--fg)}
.cs-open__lead > p + p{margin-top:.6em}
/* the quieter column settles on the rule above the figures rather than hanging
   in white space at the top, which read as an afterthought */
.cs-open__side{align-self:end}
.cs-open__side p{color:#2E2136;line-height:1.62}
.cs-open__side p + p{margin-top:1em}
@media(max-width:860px){.cs-open__grid{grid-template-columns:1fr}
  .cs-open__side{align-self:start}}

/* ---- the figures: the one place on the site numerals run this large ---- */
.cs-figs{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  gap:clamp(18px,2.4vw,40px);margin-top:clamp(34px,4.2vw,64px);
  border-top:2px solid var(--rule);padding-top:clamp(22px,2.6vw,34px)}
.cs-figs b{display:block;font-family:var(--display);font-weight:800;line-height:.9;
  letter-spacing:-.04em;font-size:clamp(44px,6.4vw,92px);color:var(--fg);
  font-variant-numeric:tabular-nums}
.cs-figs b small{font-size:.30em;font-weight:700;letter-spacing:-.01em;margin-left:.12em;
  color:var(--brand)}
.cs-figs > div > span{display:block;margin-top:.7em;font-size:14.5px;line-height:1.45;
  color:#2E2136;max-width:22ch}
/* the numeral itself must not pick up the caption size below it */
.cs-figs b > span{font:inherit;display:inline}
@media(max-width:720px){.cs-figs{grid-auto-flow:row;gap:24px}}

/* ---- a dark band: text and picture, the picture bleeding to the edge ---- */
.cs-band{background:var(--deep);color:var(--ink);padding-block:clamp(52px,7vw,112px);
  overflow:hidden}
.cs-band h2{color:#FFF;font-size:clamp(28px,3.9vw,54px);letter-spacing:-.03em;line-height:1.04;
  max-width:18ch}
/* an emphasised word in a heading on the dark band: the lighter magenta, for
   the same reason the opening uses it, and upright like every other one */
.cs-band h2 em{font-style:normal;color:var(--accent-lit)}
.cs-band p{color:rgba(255,255,255,.80);line-height:1.64;max-width:60ch}
.cs-band p + p{margin-top:1.05em}
.cs-band__grid{display:grid;grid-template-columns:1fr 1.05fr;gap:clamp(28px,4.6vw,80px);
  align-items:center}
/* the figure is always written first, so the flip has to push it past the words */
.cs-band--flip .cs-band__fig{order:2}
.cs-band__fig{margin:0;border-radius:var(--r);overflow:hidden;
  box-shadow:0 30px 70px rgba(0,0,0,.42)}
.cs-band__fig img{width:100%;height:100%;object-fit:cover;display:block;
  transform:scale(1.06);transition:transform 8s cubic-bezier(.19,.52,.26,1)}
.cs-band.is-in .cs-band__fig img{transform:scale(1)}
/* the same band on the page's own white, for its turn in the run */
.cs-band--light{background:var(--bg);color:var(--fg)}
.cs-band--light h2{color:var(--fg)}
.cs-band--light h2 em{color:var(--accent)}
.cs-band--light p{color:var(--fg-2)}
.cs-band--light a{color:var(--fg)}
.cs-band--light li{color:var(--fg-2)}
/* a heavy black shadow is what holds the picture off the dark ground; on white
   it would read as dirt under the frame, so it lightens with the band */
.cs-band--light .cs-band__fig{box-shadow:0 24px 54px rgba(44,49,55,.16)}

.cs-band__body{padding-block:clamp(6px,1vw,16px)}
.cs-band__body > * + *{margin-top:1.05em}
@media(max-width:900px){.cs-band__grid{grid-template-columns:1fr}
  .cs-band--flip .cs-band__fig{order:0}}

/* ---- the quote: the loudest thing on the page ---- */
.cs-quote{background:var(--brand);color:#15180F;padding-block:clamp(52px,7.4vw,120px)}
.cs-quote blockquote{margin:0;font-family:var(--display);font-weight:800;
  font-size:clamp(28px,4.6vw,66px);line-height:1.02;letter-spacing:-.035em;max-width:20ch}
.cs-quote--deep{background:var(--deep);color:#FFF}
/* Emphasis inside a quote is a colour rather than a slant. On the dark version
   that colour is the brand green. On the green one it used to be aubergine,
   which measures as a different colour and looks like the same one: against
   near black on lime nobody could see which word was lifted. Magenta is the
   site's own emphasis colour everywhere else and is the only thing on this band
   that reads as a highlight rather than as more black. It sits at three to one
   against the lime, which is the floor for type this size and no lower than the
   quote ever gets, since the smallest it sets is twenty eight pixels. */
.cs-quote blockquote em{font-style:normal;color:var(--accent)}
.cs-quote--deep blockquote em{font-style:normal;color:var(--brand)}

/* ---- a picture the full width of the window, with a line under it ---- */
/* a film in a section sits in the same frame its photograph would have, so a
   case study can mix the two without the page changing shape around them */
.cs-film__v{display:block;width:100%;height:100%;object-fit:cover}
.cs-wide .cs-film__v{aspect-ratio:21/9}
.cs-band__fig .cs-film__v{aspect-ratio:4/3}
@media(max-width:720px){.cs-wide .cs-film__v{aspect-ratio:16/9}}

/* A full width picture belongs to the section named underneath it, not to the
   one that happens to finish above it. Nothing in the markup says so — the only
   thing a reader has to go on is the space around it, and that space used to be
   even, which left the picture looking like the end of the block before.

   So it is made uneven. The section above is given extra room below itself, in
   its own colour rather than as a margin, because a margin here would show the
   page white and put a bright seam between two dark blocks. The heading below
   is pulled up close. Picture and heading then read as one thing. */
.cs .spread:has(+ .cs-wide){padding-bottom:calc(clamp(48px,6.5vw,104px) + clamp(30px,3.8vw,68px))}
.cs-wide + .cs-text{padding-top:clamp(18px,2vw,30px)}

/* a figure carries a browser margin of its own, which on a picture meant to
   run edge to edge shows as a white strip down both sides */
.cs-wide{position:relative;overflow:hidden;background:#1A1220;margin:0}
.cs-wide img{width:100%;display:block;aspect-ratio:21/9;object-fit:cover;
  transform:scale(1.08);transition:transform 9s cubic-bezier(.19,.52,.26,1)}
.cs-wide.is-in img{transform:scale(1)}
/* Once the picture is being tracked it moves with the page rather than settling
   on arrival, the same behaviour the band pictures carry elsewhere. The frame
   holds the shape and the picture is hung taller than it, so there is room to
   drift inside without an edge ever showing. The travel is deliberately shorter
   than the band version: this frame is wide and shallow, and the same movement
   that reads well on a tall picture looks like a slipped print on this one. */
.cs-wide{aspect-ratio:21/9}
.cs-wide img.is-tracked{position:absolute;left:0;right:0;top:-10%;
  width:100%;height:120%;aspect-ratio:auto;object-fit:cover;
  transform:translate3d(0,calc(var(--y,0) * 0.42%),0) scale(var(--z,1));
  transition:none;will-change:transform}
.cs-wide figcaption{position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:clamp(18px,2.6vw,38px);color:rgba(255,255,255,.92);
  font-family:var(--body);font-size:13.5px;letter-spacing:.02em;
  background:linear-gradient(to top,rgba(16,10,22,.86),rgba(16,10,22,0))}
/* A 21:9 picture is only 140 points tall on a phone, and a caption of any
   length covers most of it. Below this the caption drops out of the picture
   and sits under it on the figure's own dark ground, and the picture is given
   a squarer crop so there is something to look at. */
@media(max-width:720px){
  .cs-wide{aspect-ratio:16/9}
  .cs-wide img{aspect-ratio:16/9}
  .cs-wide figcaption{position:static;background:none;
    padding:14px var(--gut) 18px;font-size:13px;line-height:1.55;
    color:rgba(255,255,255,.86)}}

/* ---- what the room is used for ---- */
.cs-uses{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;
  margin-top:clamp(24px,3vw,40px)}
.cs-uses div{border:1px solid var(--rule);border-radius:var(--r-3);
  padding:clamp(14px,1.6vw,20px);font-family:var(--body);font-weight:600;font-size:14.5px;
  line-height:1.35;transition:border-color .3s ease,transform .3s ease,background .3s ease}
.cs-uses div:hover{border-color:var(--brand);transform:translateY(-3px);
  background:rgba(154,205,50,.08)}
@media(max-width:900px){.cs-uses{grid-template-columns:repeat(2,1fr)}}
@media(max-width:520px){.cs-uses{grid-template-columns:1fr}}

/* ---- the calls to action, one part way down and one at the end ---- */
.cs-cta{background:var(--deep);color:#FFF;padding-block:clamp(44px,5.6vw,86px)}
/* A hairline was not enough. On the same aubergine as the section above, the
   ask still read as that section's closing line. It is a different kind of
   thing from the narrative around it, so it is drawn as its own object: a
   lifted surface with the brand spine down its edge, and real air on both
   sides. The band it sits in stops carrying the separation on its own. */
.cs-cta--slim{padding-block:clamp(44px,5.4vw,84px)}
.cs-cta--slim .cs-cta__in{
  background:linear-gradient(118deg,#26192F 0%,#1F1528 58%,#261B30 100%);
  border:1px solid rgba(255,255,255,.085);
  border-left:4px solid var(--brand);
  border-radius:3px;
  box-shadow:0 18px 44px rgba(0,0,0,.34);
  padding:clamp(26px,3.1vw,42px) clamp(24px,3.2vw,48px);
  gap:clamp(20px,2.6vw,40px)}
.cs-cta--slim h2{max-width:22ch}
/* Both this and the band above it are the deep aubergine, so without a line
   the ask reads as the last paragraph of the section before it rather than as
   its own invitation. A hairline is enough; a different colour would make it
   shout over the section it is meant to follow. */
.cs-band + .cs-cta:not(.cs-cta--slim),.cs-text--dark + .cs-cta:not(.cs-cta--slim),
.cs-cta + .cs-cta:not(.cs-cta--slim){border-top:1px solid rgba(255,255,255,.10)}

/* the finale arrives after a dark band, and #120D18 against #1A1220 is not a
   change anyone can see — a thin lit edge gives it the moment of arrival */
.cs-band + .fin,.cs-text--dark + .fin,.cs-cta + .fin{
  box-shadow:inset 0 1px 0 rgba(154,205,50,.34)}
.cs-cta__in{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:clamp(18px,2.6vw,40px)}
.cs-cta h2{color:#FFF;font-size:clamp(24px,3.2vw,44px);letter-spacing:-.028em;max-width:20ch}
.cs-cta p{color:rgba(255,255,255,.78);max-width:46ch;margin-top:.7em;line-height:1.55}
.cs-cta .btn{flex:none}

/* ---- reveals: everything arrives, nothing pops ----
   The class that hides a block is added by the script, never by the stylesheet.
   Written the other way round, a script that fails to run leaves whole sections
   of the page invisible, which is exactly what happened the first time. */
.cs-up.cs-pre{opacity:0;transform:translate3d(0,26px,0)}
.cs-up.is-in{opacity:1;transform:none;
  transition:opacity .7s cubic-bezier(.22,.61,.36,1),transform .7s cubic-bezier(.22,.61,.36,1)}
@media(prefers-reduced-motion:reduce){
  .cs-up.cs-pre{opacity:1;transform:none}
  .cs-band__fig img,.cs-wide img{transform:none;transition:none}
  .cs-hero__cue span{animation:none}
}

/* the opening reads as two columns: a statement, then the rest beside it */
.cs-open__grid > div{min-width:0}
.cs-open__grid p{margin:0}
.cs-plain{max-width:66ch}
.cs-prose{margin-top:1.2em}
/* a list inside a plain section becomes the row of things the room is used for */
.cs-prose ul{list-style:none;padding:0;display:grid;grid-template-columns:repeat(4,1fr);
  gap:10px;max-width:none;width:min(100%,1100px)}
.cs-prose ul li{border:1px solid var(--rule);border-radius:var(--r-3);
  padding:clamp(14px,1.6vw,20px);font-family:var(--body);font-weight:600;font-size:14.5px;
  line-height:1.35;transition:border-color .3s ease,transform .3s ease,background .3s ease}
/* no hover state. A panel that lifts under the pointer is telling somebody it
   will take them somewhere, and none of these go anywhere. */
@media(max-width:900px){.cs-prose ul{grid-template-columns:repeat(2,1fr)}}
@media(max-width:520px){.cs-prose ul{grid-template-columns:1fr}}

/* a list inside a dark band gets the same tiles, in the band's own colours */
.cs-band ul{list-style:none;padding:0;display:grid;grid-template-columns:repeat(2,1fr);
  gap:10px;max-width:none}
.cs-band ul li{border:1px solid rgba(255,255,255,.20);border-radius:var(--r-3);
  padding:clamp(12px,1.4vw,18px);font-family:var(--body);font-weight:600;font-size:14px;
  line-height:1.35;color:rgba(255,255,255,.92);
  transition:border-color .3s ease,transform .3s ease,background .3s ease}
.cs-band ul li:hover{border-color:var(--brand);transform:translateY(-3px);
  background:rgba(154,205,50,.12)}
@media(max-width:520px){.cs-band ul{grid-template-columns:1fr}}

/* a run of text with no picture takes the ground the section before it did not,
   so two pale sections never sit together however the piece is written */
.cs-text--dark{background:var(--deep);color:var(--ink)}
.cs-text--dark h2,.cs-text--dark .h2{color:#FFF}
.cs-text--dark .h2 em{color:var(--brand)}
.cs-text--dark .prose{color:rgba(255,255,255,.82)}
.cs-text--dark .prose ul li{border-color:rgba(255,255,255,.20);color:rgba(255,255,255,.92)}
.cs-text--dark .prose a{color:#FFF}

/* ---------- what the room is used for ----------
   Written in the editor as an ordinary bulleted list with the name of each use
   in bold. Two columns, ruled rather than boxed, each with its mark in a lime
   disc. Nothing here responds to the pointer: these are things the room does,
   not places to go.

   The arrival is three movements one behind the other. The rows rise and fade
   in turn, the discs land a beat later on a curve that overshoots slightly, and
   then each mark draws itself. Every stroke is normalised to a length of one by
   the markup, so a single rule draws all of them at the same rate whatever
   shape they are. */
.im{display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(30px,4vw,70px);
  margin-top:clamp(28px,3.2vw,48px);max-width:none;
  width:min(1120px,calc(100vw - 2 * var(--gut)))}
.im__row{display:grid;grid-template-columns:clamp(46px,4.2vw,58px) 1fr;
  gap:0 clamp(15px,1.7vw,22px);align-items:start;
  padding:clamp(19px,2.1vw,28px) 0;border-top:1px solid rgba(255,255,255,.15)}
.im__mark{display:grid;place-items:center;width:clamp(46px,4.2vw,58px);aspect-ratio:1;
  border-radius:999px;background:var(--brand);position:relative}
/* the halo sits behind the disc and lifts it off the band */
.im__mark::after{content:"";position:absolute;inset:-7px;border-radius:999px;z-index:0;
  background:radial-gradient(circle,rgba(154,205,50,.30),rgba(154,205,50,0) 70%)}
.im__mark svg{position:relative;z-index:1;width:54%;height:54%;fill:none;stroke:#1A1220;
  stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.cs-prose .im h3{font-family:var(--display);font-weight:700;letter-spacing:-.02em;
  font-size:17.5px;line-height:1.2;color:#FFF;margin:0}
.cs-prose .im p{font-size:14.5px;line-height:1.55;color:rgba(255,255,255,.74);
  margin:.5em 0 0;max-width:44ch}
@media(max-width:860px){.im{grid-template-columns:1fr}}

/* on a light band the marks keep the lime disc but the words turn over */
.cs-text:not(.cs-text--dark) .im__row{border-top-color:var(--rule)}
.cs-text:not(.cs-text--dark) .cs-prose .im h3{color:var(--fg)}
.cs-text:not(.cs-text--dark) .cs-prose .im p{color:var(--fg-2)}

.js .im__row{opacity:0;transform:translateY(16px);
  transition:opacity .62s ease,transform .62s cubic-bezier(.22,.61,.36,1);
  transition-delay:calc(var(--i) * 85ms)}
.js .im.is-in .im__row{opacity:1;transform:none}
.js .im__mark{transform:scale(.72);
  transition:transform .6s cubic-bezier(.34,1.45,.5,1);
  transition-delay:calc(var(--i) * 85ms + 90ms)}
.js .im.is-in .im__mark{transform:scale(1)}
.js .im__mark svg *{stroke-dasharray:1;stroke-dashoffset:1;
  transition:stroke-dashoffset .9s cubic-bezier(.4,0,.2,1);
  transition-delay:calc(var(--i) * 85ms + 230ms)}
.js .im.is-in .im__mark svg *{stroke-dashoffset:0}
@media(prefers-reduced-motion:reduce){
  .js .im__row,.js .im__mark,.js .im__mark svg *{
    transition:none;opacity:1;transform:none;stroke-dashoffset:0}}

/* ---------- the finale ----------
   The last section of a case study, given the shape of an ending rather than
   of another chapter: the picture full width, the closing line over it at
   statement size, the detail in two quiet columns underneath.

   The shade over the picture is weighted to the side the words sit on and
   thins out across the frame, so the type has something to sit against without
   the photograph being flattened into a background. */
/* The words set the height of this band and the picture fills whatever that
   turns out to be. The other way round — a picture at a fixed shape with the
   words laid over it — looks identical until somebody puts a long paragraph in
   the slot, and then the type runs straight out of the frame above and below.
   A closing line should be short, but the layout cannot be the thing that
   insists on it. */
/* The band carries the same left to right fall as the scrim over the film, so
   that when there is no picture yet — poster still loading, or a browser that
   will not render the video — the cushion under the words sits on a graded
   ground instead of reading as a black rectangle on a flat one. */
.fin{position:relative;isolation:isolate;
  background:linear-gradient(105deg,#0B0710 0%,#140E1B 46%,#221833 100%);
  min-height:clamp(380px,44vw,680px);display:flex;align-items:center}
.fin__bleed{margin:0;position:absolute;inset:0;z-index:0}
.fin__bleed img,.fin__bleed .cs-film__v{width:100%;height:100%;display:block;
  object-fit:cover;aspect-ratio:auto}
/* The film is the point of this band, so the scrim only has to carry the words
   on the left and then get out of the way. The old one held .93 at the edge and
   .78 a third of the way across, which put the room at 40% of its own
   brightness — measured against the still, this keeps 86% of it while the
   statement stays above 3:1 across all but a fraction of a percent of its box,
   and the shadow below covers that. */
/* One gradient, running the whole width and reaching nothing at the far edge.
   The previous attempt put a soft shape behind the words and faded it out
   around two thirds across — which is a visible shape the moment the frame
   behind it is smooth, like open sky. Anything that finishes inside the picture
   has an edge, however soft it is made; only a ramp that ends where the picture
   ends has none. The many stops are there to keep the ramp smooth rather than
   banded. */
.fin__bleed::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,
    rgba(9,6,13,.88) 0%,rgba(9,6,13,.82) 10%,rgba(9,6,13,.72) 20%,
    rgba(9,6,13,.60) 30%,rgba(9,6,13,.47) 40%,rgba(9,6,13,.35) 50%,
    rgba(9,6,13,.24) 61%,rgba(9,6,13,.15) 72%,rgba(9,6,13,.08) 83%,
    rgba(9,6,13,.03) 92%,rgba(9,6,13,0) 100%)}
.fin__over{position:relative;z-index:2;width:100%;
  padding-block:clamp(52px,6.4vw,104px)}
/* At eleven and a half pixels this was a caption under a statement set at
   seventy six, and it simply disappeared. It is the only thing naming the
   section, so it gets a size that survives the company it keeps and a lit rule
   in front of it to hold its ground. */
.fin__kicker{display:flex;align-items:center;gap:clamp(12px,1.2vw,18px);
  font-family:var(--body);font-weight:800;
  font-size:clamp(13px,1.15vw,16px);letter-spacing:.24em;text-transform:uppercase;
  color:var(--brand);margin-bottom:clamp(18px,2.2vw,32px)}
.fin__kicker::before{content:"";flex:none;width:clamp(30px,3.4vw,54px);height:3px;
  background:var(--brand);border-radius:2px}
.fin__kicker em{font-style:normal;color:#FFFFFF}
.fin__say{font-family:var(--display);font-weight:800;letter-spacing:-.034em;
  line-height:1.02;font-size:clamp(28px,5vw,76px);margin:0;color:#FFFFFF;max-width:17ch;
  text-shadow:0 1px 3px rgba(8,5,12,.42),0 3px 30px rgba(8,5,12,.62)}
.fin__say em{font-style:normal;color:var(--brand)}
.fin__say--long{font-size:clamp(25px,3.5vw,52px);max-width:22ch;line-height:1.08}
.fin__say--xlong{font-size:clamp(22px,2.6vw,38px);max-width:30ch;line-height:1.18;
  letter-spacing:-.018em;font-weight:700}

/* the supporting columns share the class for the background only: they take
   none of the band's height, centring or layering */
.fin--after{background:var(--bg);padding-block:clamp(32px,4vw,58px);
  min-height:0;display:block;align-items:initial}
.fin--after::after{content:none}
/* One paragraph per cell, not CSS columns. Columns balance by line and
   break-inside:avoid stops a paragraph splitting, so three paragraphs land as
   one and two with a hole in the bottom corner, and the split moves every time
   the copy is edited. A grid gives each paragraph its own column, the row ends
   level whatever the editor puts in, and the count follows the width. */
.fin__cols{display:grid;max-width:1160px;
  grid-template-columns:repeat(auto-fit,minmax(258px,1fr));
  gap:clamp(20px,2.4vw,32px) clamp(26px,3.4vw,54px)}
.fin__cols p{margin:0;color:var(--fg-2);font-size:15.5px;line-height:1.62}
/* A 21:9 frame is barely tall enough for a phone to carry a statement across
   it, so below a tablet the words come out from under the picture and sit on
   the dark ground beneath it. */
@media(max-width:720px){
  .fin{min-height:clamp(320px,90vw,520px)}
  .fin__bleed::after{background:linear-gradient(176deg,rgba(9,6,13,.80) 0%,rgba(9,6,13,.62) 34%,
    rgba(9,6,13,.50) 58%,rgba(9,6,13,.62) 82%,rgba(9,6,13,.78) 100%)}
  .fin__kicker{gap:10px}}

/* sector and role, set as a small record at the foot of the piece */
.cs-meta__list{display:grid;grid-auto-flow:column;grid-auto-columns:max-content;
  gap:clamp(28px,4vw,72px);margin:0}
.cs-meta__list dt{font-family:var(--body);font-weight:600;font-size:11.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--fg-3)}
.cs-meta__list dd{margin:.5em 0 0;font-family:var(--display);font-weight:700;
  font-size:clamp(17px,1.7vw,21px)}
@media(max-width:640px){.cs-meta__list{grid-auto-flow:row;gap:20px}}

/* ==========================================================================
   The run of bands. One thing to a screen, full width, the picture running
   past the words on whichever side it sits and swapping sides as you go.
   Used by What we offer and by Who we are: on both, the page it replaced was
   a grid of cards, and nothing in this run is a card.
   ========================================================================== */

.runopen{padding-block:clamp(56px,7vw,110px)}
/* The text beside the heading starts level with the HEADING, not with the small
   label above it. The label is only a marker for the section and lining a
   paragraph up with it leaves the paragraph floating above the sentence it
   belongs to. The left column is dissolved into the grid so the label takes a
   row of its own and the heading and the paragraph share the next one, which
   holds however long either of them runs. */
.runopen__grid{display:grid;grid-template-columns:1fr 1fr;
  column-gap:clamp(28px,5vw,80px);row-gap:0;align-items:start}
.runopen__grid > div:first-child{display:contents}
.runopen__grid > div:first-child > .kicker{grid-column:1;grid-row:1;margin-top:0}
.runopen__grid > div:first-child > .h2{grid-column:1;grid-row:2;margin-top:0}
.runopen__grid > .runopen__text{grid-column:2;grid-row:2}
.runopen__text > p:first-child{margin-top:0}
.runopen__text p{color:var(--fg-2);line-height:1.62;font-size:17px}
.runopen__text p + p{margin-top:1em}
/* stacked, it is one column again and the rows simply follow each other */
/* ---------- the same opening, stacked, with a picture beside it ----------
   The other pages that use this grid put the heading on the left and the words
   on the right, which reads well when the words are the whole point. Here the
   words run straight down under their own heading and a photograph takes the
   second column, so the section says what the page is and shows it at the same
   time. Without a picture set it is a single column and nothing is left empty. */
.runopen__grid--stack > div:first-child{display:block}
.runopen__grid--stack{grid-template-columns:1fr;align-items:center}
/* The heading takes a row of its own across the left column, and the paragraphs
   and the picture share the row under it. The picture is then the height of the
   copy and nothing else: it starts level with the first line of text rather than
   with the label above the heading, which would leave it hanging past the words
   at the bottom. */
/* the space under the heading is the row gap, not a margin on the paragraphs:
   a margin would push the words down inside the row while the picture stretched
   to the whole of it, and the two would start level by about 26 pixels out */
.runopen__grid--stack{grid-template-columns:1fr;align-items:start;
  row-gap:clamp(16px,1.9vw,26px)}
.runopen__grid--pic{grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);
  column-gap:clamp(30px,4.6vw,78px);align-items:stretch}
.runopen__grid--stack > .runopen__head{grid-column:1;grid-row:1;display:block}
.runopen__grid--stack > .runopen__text{grid-column:1;grid-row:2;max-width:58ch}
.runopen__grid--pic > .runopen__fig{grid-column:2;grid-row:2;align-self:stretch}
.runopen__head > .h2{margin-top:clamp(8px,1vw,14px)}
.runopen__grid--stack:not(.runopen__grid--pic) > .runopen__text{max-width:74ch}
.runopen__fig{margin:0;border-radius:var(--r-3);overflow:hidden;background:var(--w1);
  position:relative;min-height:clamp(210px,23vw,340px)}
.runopen__fig img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:88% 50%;aspect-ratio:auto;display:block;
  transform:scale(1.02);transition:transform 1.1s cubic-bezier(.22,.61,.36,1)}
.runopen__fig:hover img{transform:scale(1.06)}
/* the same travel the service bands and the full width case study pictures
   make: cut taller than the frame and moved through it as the frame rides up,
   because a scale on its own is almost invisible while scrolling. The script
   adds the class and drives the two values; without it the picture simply
   sits there and still zooms on hover. */
.runopen__fig img.is-tracked,
.runopen__fig:hover img.is-tracked{
  height:128%;top:-14%;bottom:auto;
  transform:translate3d(0,calc(var(--y,0) * 1%),0) scale(var(--z,1));
  transition:none;will-change:transform}
/* stacked, it goes back to a shape of its own: there is nothing beside it to
   match, and a picture stretched to a column's height on a phone is a crop
   nobody chose */
@media(max-width:860px){
  .runopen__grid--pic{grid-template-columns:1fr}
  .runopen__grid--stack > .runopen__head,
  .runopen__grid--stack > .runopen__text,
  .runopen__grid--pic > .runopen__fig{grid-column:1;grid-row:auto}
  .runopen__fig{order:9;min-height:0}
  .runopen__fig img,.runopen__fig img.is-tracked{position:static;height:auto;
    aspect-ratio:6/5;object-position:center;transform:none;top:auto}
  .runopen__grid--stack > .runopen__text,
  .runopen__grid--stack:not(.runopen__grid--pic) > .runopen__text{max-width:none}
}

@media(max-width:860px){
  .runopen__grid{grid-template-columns:1fr;row-gap:clamp(20px,3vw,30px)}
  .runopen__grid > div:first-child > .kicker,
  .runopen__grid > div:first-child > .h2,
  .runopen__grid > .runopen__text{grid-column:1;grid-row:auto}
  .runopen__grid > div:first-child > .kicker{margin-bottom:14px}
}

/* the index: six numbered lines, the whole row live */
.runindex{list-style:none;margin:clamp(40px,4.6vw,72px) 0 0;padding:0;
  border-top:2px solid var(--rule)}
.runindex li{border-bottom:1px solid var(--rule)}
.runindex a{display:grid;grid-template-columns:clamp(54px,5vw,84px) 1fr auto;
  align-items:baseline;gap:clamp(12px,1.6vw,26px);text-decoration:none;
  padding-block:clamp(13px,1.5vw,20px);position:relative;
  transition:padding-left .3s cubic-bezier(.22,.61,.36,1)}
.runindex b{font-family:var(--display);font-weight:800;font-size:clamp(15px,1.5vw,19px);
  letter-spacing:-.02em;color:var(--accent);font-variant-numeric:tabular-nums}
.runindex span{font-family:var(--display);font-weight:700;letter-spacing:-.022em;
  font-size:clamp(19px,2.3vw,31px);line-height:1.1;color:var(--fg);
  transition:color .25s ease}
.runindex a::after{content:"";width:clamp(22px,2.4vw,38px);height:2px;
  background:var(--rule-2);align-self:center;
  transition:width .3s cubic-bezier(.22,.61,.36,1),background .25s ease}
.runindex a:hover{padding-left:clamp(8px,1vw,16px)}
.runindex a:hover::after{width:clamp(38px,4.4vw,72px);background:var(--brand)}
.runindex a:hover span{color:var(--accent)}
.runindex a:focus-visible{outline:2.5px solid var(--brand);outline-offset:4px;border-radius:4px}

/* one service: picture to the outer edge, words in the column beside it */
.runband{position:relative;overflow:hidden;
  padding-block:clamp(52px,6.6vw,104px);border-top:1px solid var(--rule)}
.runband--dark{background:#2E2136;color:#FFFFFF;border-top:none;
  --fg:#FFFFFF;--fg-2:rgba(255,255,255,.80);--rule:rgba(255,255,255,.18);
  --rule-2:rgba(255,255,255,.34)}
.runband__grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.04fr);
  gap:clamp(30px,4.4vw,74px);align-items:stretch}
/* the picture takes the height of the words beside it, so the band has no dead
   ground above and below it */
.runband__fig{margin:0;position:relative;border-radius:var(--r-3);overflow:hidden;
  background:#2E2136;min-height:clamp(300px,34vw,520px)}
.runband__fig img{width:100%;height:100%;object-fit:cover;display:block;
  position:absolute;inset:0;
  transform:scale(1.02);transition:transform 1.1s cubic-bezier(.22,.61,.36,1)}
.runband:hover .runband__fig img{transform:scale(1.06)}
/* While the script is driving the picture from the scroll position it follows
   that and nothing else: a transition here would lag a frame behind every move,
   and the hover zoom would fight it.

   A scale on its own is almost invisible while scrolling, because the whole
   frame grows a fraction of a percent per frame and nothing passes anything
   else. So the picture is cut taller than its frame and travels through it as
   well, which is the movement the eye actually reads. The overhang is 28% and
   the travel never exceeds 9% of the picture, so no edge can come into view. */
.runband__fig img.is-tracked,
.runband:hover .runband__fig img.is-tracked{
  height:128%;top:-14%;bottom:auto;
  transform:translate3d(0,calc(var(--y,0) * 1%),0) scale(var(--z,1));
  transition:none;will-change:transform}
/* The picture runs past the text on whichever side it sits. On a window near
   the site's own width that reaches the edge of the screen; on a very wide one
   it stops at a sensible overhang rather than growing to twice the width of the
   words beside it. Capping it also keeps the negative margin small, which a
   browser is far happier painting inside a band that clips its overflow. */
.runband{--bleed:min(calc((100vw - min(100vw,1360px)) / 2 + var(--gut)),150px)}
.runband__fig{margin-left:calc(-1 * var(--bleed));
  transform:translateZ(0)}
.runband--flip .runband__fig{order:2;margin-left:0;
  margin-right:calc(-1 * var(--bleed))}

.runband__body{min-width:0}
/* the number and the section's own name, the same words the index and the menu
   use, above a heading that says it differently */
.runband__n{display:flex;align-items:baseline;gap:.75em;
  font-family:var(--display);font-weight:800;line-height:1.35;
  font-size:clamp(13px,1.3vw,16px);letter-spacing:.2em;color:var(--brand);
  margin-bottom:.9em;font-variant-numeric:tabular-nums}
.runband__n i{font-style:normal;text-transform:uppercase;letter-spacing:.2em;
  min-width:0;display:flex;align-items:baseline;gap:.75em}
.runband__n b{font:inherit;letter-spacing:inherit}
/* a short rule between the two, which shortens rather than wraps */
.runband__n i::before{content:"";flex:none;width:18px;height:2px;
  background:currentColor;align-self:center;opacity:.6;transform-origin:0 50%}

/* ---------- the green mark arrives as you reach its band ----------
   The number lands first, the rule draws out from it, then the name follows
   the rule in. It runs once, it is over inside three quarters of a second,
   and anyone who has asked for less movement never sees it: the mark is
   simply there, as it was before. */
.mark-pre b{opacity:0;transform:translateY(7px)}
.mark-pre i{opacity:0;transform:translateX(-8px)}
.mark-pre i::before{transform:scaleX(0)}
.mark-in b{opacity:1;transform:none;
  transition:opacity .42s ease,transform .52s cubic-bezier(.22,.61,.36,1)}
.mark-in i::before{transform:scaleX(1);
  transition:transform .42s cubic-bezier(.22,.61,.36,1) .14s}
.mark-in i{opacity:1;transform:none;
  transition:opacity .44s ease .28s,transform .52s cubic-bezier(.22,.61,.36,1) .28s}
/* the small label at the head of a section does the same, more quietly */
.kicker.mark-pre{opacity:0;transform:translateY(7px)}
.kicker.mark-in{opacity:1;transform:none;
  transition:opacity .45s ease,transform .55s cubic-bezier(.22,.61,.36,1)}
.runband--dark .runband__n{color:var(--brand)}
.runband h2{font-family:var(--display);font-weight:800;letter-spacing:-.032em;
  line-height:1.02;font-size:clamp(28px,3.8vw,54px);color:var(--fg)}
.runband__lede{margin-top:.62em;font-family:var(--display);font-weight:700;
  letter-spacing:-.018em;line-height:1.24;font-size:clamp(17px,1.85vw,24px);
  color:var(--accent);max-width:26ch}
.runband--dark .runband__lede{color:var(--brand)}
.runband__prose{margin-top:clamp(16px,1.8vw,26px);max-width:52ch}
.runband__prose p{color:var(--fg-2);line-height:1.62}
.runband__prose p + p{margin-top:.9em}
/* a list inside a service is what that service covers */
.runband__prose ul{list-style:none;margin:clamp(18px,2vw,28px) 0 0;padding:0;
  display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(16px,2vw,30px);
  border-top:1px solid var(--rule)}
/* the square is a column of its own rather than an absolute guess, and sits on
   the middle of the first line whether the item wraps or not */
.runband__prose ul li{display:grid;grid-template-columns:7px minmax(0,1fr);
  gap:0 11px;align-items:start;
  padding-block:clamp(9px,1vw,13px);
  border-bottom:1px solid var(--rule);font-size:14.5px;line-height:1.4;
  color:var(--fg-2)}
.runband__prose ul li::before{content:"";width:7px;height:7px;border-radius:2px;
  background:var(--brand);margin-top:.46em}
@media(max-width:560px){.runband__prose ul{grid-template-columns:1fr}}

/* what we did on that project: the same run as a list inside a band */
.runband__scope{display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(16px,2vw,30px);
  margin-top:clamp(18px,2vw,28px);border-top:1px solid var(--rule)}
.runband__scope i{font-style:normal;display:grid;grid-template-columns:7px minmax(0,1fr);
  gap:0 11px;align-items:start;padding-block:clamp(9px,1vw,13px);
  border-bottom:1px solid var(--rule);font-size:14.5px;line-height:1.4;color:var(--fg-2)}
.runband__scope i::before{content:"";width:7px;height:7px;border-radius:2px;
  background:var(--brand);margin-top:.46em}
@media(max-width:560px){.runband__scope{grid-template-columns:1fr}}

/* the heading links through to the project */
.runband h2 a{text-decoration:none;color:inherit;
  background-image:linear-gradient(var(--brand),var(--brand));
  background-repeat:no-repeat;background-position:0 100%;background-size:0 3px;
  transition:background-size .34s cubic-bezier(.22,.61,.36,1)}
.runband h2 a:hover{background-size:100% 3px}
.runband__fig a{display:block;height:100%}

.runband__cta{display:inline-block;margin-top:clamp(20px,2.3vw,32px);
  font-family:var(--body);font-weight:700;font-size:12px;letter-spacing:.16em;
  text-transform:uppercase;text-decoration:none;color:var(--fg);
  position:relative;padding-bottom:8px}
.runband__cta::before{content:"";position:absolute;left:0;bottom:0;right:0;height:2px;
  background:var(--brand);transform:scaleX(.36);transform-origin:0 50%;
  transition:transform .32s cubic-bezier(.22,.61,.36,1)}
.runband__cta:hover::before{transform:scaleX(1)}
.runband__cta:focus-visible{outline:2.5px solid var(--brand);outline-offset:5px;border-radius:3px}

/* ---------- the points arrive one at a time, then the link ----------
   The list is the part of a band worth reading slowly, so it is dealt one
   item at a time as the reader reaches it rather than being there all at
   once. The link follows the last point in, and its rule then sweeps out
   and back three times — the same movement it makes on hover, so it reads
   as an invitation rather than as a new piece of decoration. It stops of
   its own accord, and hovering ends it early. */
.js .runband__prose ul > li,
.js .runband__cta{transition:opacity .5s ease calc(var(--i,0) * .11s),
  transform .55s cubic-bezier(.22,.61,.36,1) calc(var(--i,0) * .11s)}
.js .runband__prose ul > li.li-pre,
.js .runband__cta.li-pre{opacity:0;transform:translate3d(0,12px,0);transition:none}
/* The rule under the link draws out to full width once and stays there, then a
   gleam runs along it twice. Everything travels the same way the reader does,
   left to right: nothing retreats back the way it came. */
@keyframes ctadraw{from{transform:scaleX(0)}to{transform:scaleX(1)}}
/* the gleam travels left to right: with the band oversized, a FALLING
   background-position walks the bright stop forward across the rule */
@keyframes ctagleam{from{background-position:165% 0}to{background-position:55% 0}}
.js .runband__cta.cta-pulse::before{
  transform:scaleX(1);
  background:linear-gradient(90deg,var(--brand) 0 41%,var(--accent) 50%,
    var(--brand) 59% 100%);
  background-size:220% 100%;background-position:165% 0;background-repeat:no-repeat;
  animation:ctadraw .55s cubic-bezier(.22,.61,.36,1) both,
    ctagleam .92s cubic-bezier(.36,0,.32,1) .7s 2 both}
.js .runband__cta.cta-pulse:hover::before{animation:none;transform:scaleX(1)}
/* once the rule is full width, hover has to say something else */
.js .runband__cta.cta-pulse:hover{color:var(--accent)}
@media(prefers-reduced-motion:reduce){
  .js .runband__prose ul > li,
  .js .runband__cta{opacity:1;transform:none;transition:none}
  .js .runband__cta.cta-pulse::before{animation:none;transform:scaleX(.36)}}

@media(max-width:860px){
  .runband__grid{grid-template-columns:1fr;gap:clamp(22px,4vw,34px)}
  .runband__fig,.runband--flip .runband__fig{order:-1;margin-left:calc(-1 * var(--gut));
    margin-right:calc(-1 * var(--gut));border-radius:0}
}

/* how a project runs: a numbered run rather than a row of tiles */
.svc-steps{list-style:none;margin:clamp(30px,3.4vw,52px) 0 0;padding:0;counter-reset:st;
  border-top:2px solid var(--rule)}
.svc-steps li{counter-increment:st;display:grid;
  grid-template-columns:clamp(52px,5vw,82px) minmax(0,22ch) minmax(0,1fr);
  gap:clamp(12px,1.8vw,30px);align-items:baseline;
  padding-block:clamp(16px,1.9vw,26px);border-bottom:1px solid var(--rule)}
.svc-steps li::before{content:counter(st,decimal-leading-zero);
  font-family:var(--display);font-weight:800;font-size:clamp(15px,1.5vw,19px);
  letter-spacing:-.02em;color:var(--accent);font-variant-numeric:tabular-nums}
.svc-steps b{font-family:var(--display);font-weight:800;letter-spacing:-.024em;
  line-height:1.1;font-size:clamp(18px,2vw,27px);color:var(--fg)}
.svc-steps span{color:var(--fg-2);line-height:1.55;font-size:15.5px}
@media(max-width:720px){
  .svc-steps li{grid-template-columns:clamp(44px,9vw,58px) 1fr;gap:6px 14px}
  .svc-steps span{grid-column:2}
}

/* the opening paragraphs above the people */
.team-intro{max-width:64ch;margin-top:clamp(18px,2vw,28px)}
.team-intro p{color:var(--fg-2);line-height:1.62;font-size:17px}
.team-intro p + p{margin-top:1em}
.team-intro + .people,
.team-intro + .disciplines,
.team-intro + .work{margin-top:clamp(30px,3.4vw,52px)}

/* ---------- the group brand cards ----------
   Three near white panels in a row on a near white page give the eye no edge
   to catch, so the row reads as one pale block however good the logos are.
   Each card takes a wash of its own brand's colour behind the logo and a spine
   of that colour down its full left edge: the wash gives the picture area a
   field, and the spine draws a hard vertical the eye catches from anywhere on
   the page. The kicker and the visit line pick the same colour up at the
   bottom, so the card is tied together top to bottom without a heavy block of
   colour anywhere in it.

   The colour is typed into each brand's own fields. The spine uses it exactly
   as supplied, because a rule carries no type. The words use a copy worked out
   in PHP and darkened only as far as it takes to clear 4.5:1 against the page,
   since some brand colours are bright and an 11 pixel kicker in one of them is
   a line nobody can read.

   The picture here is a logo rather than a photograph, so it is fitted inside
   the frame instead of cropped to fill it. How large each mark sits is set by
   the transparent margin baked into its file, which is where the three marks
   are matched to one another by weight — a judgement no stylesheet can make. */
.h2 + .work--archive{margin-top:clamp(26px,3vw,44px)}
.work--archive + .more{margin-top:clamp(24px,2.6vw,38px)}
.card--brand{position:relative}
.card--brand .card__img{background:var(--w1);
  background:linear-gradient(152deg,var(--w1) 0%,var(--w2) 62%,#FFFFFF 100%);
  transition:background .45s ease}
.card--brand:hover .card__img{
  background:linear-gradient(152deg,var(--w1h) 0%,var(--w2h) 62%,#FFFFFF 100%)}
.card--brand .card__img img{object-fit:contain}
.card--brand:hover{border-color:var(--col)}

/* the spine. It sits above the wash and is clipped by the card's own radius */
.card--brand::before{content:"";position:absolute;left:0;top:0;bottom:0;width:6px;
  z-index:4;background:var(--col);transition:width .3s ease}
.card--brand:hover::before{width:10px}
.card--brand .card__body{padding-left:26px}

/* the brand colour picked up again in the words under the picture */
.card--brand .card__tag{color:var(--band)}
.card--brand .card__scope b{color:var(--band)}
.card--brand .card__go{display:flex;align-items:center;gap:9px;
  color:var(--band);font-weight:600}
.card--brand .card__go svg{width:17px;height:17px;flex:none;fill:none;
  stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
  transition:transform .35s cubic-bezier(.22,.61,.36,1)}
.card--brand:hover h3{color:var(--band)}
.card--brand:hover .card__go svg{transform:translateX(5px)}
@media(prefers-reduced-motion:reduce){
  .card--brand .card__img,.card--brand::before,
  .card--brand .card__go svg{transition:none}}
