/* =========================================================================
   SITE SHELL for Squarespace-mirror pages (/innit, /work, /design/…)
   Nav rules are the v4-nav rules from src/v4-styles.css verbatim, plus the
   :root tokens they depend on. The nav is forced static (in-flow) so it never
   covers the first section. Footer mirrors the homepage footer ribbon.
   ========================================================================= */

:root{
  --v4-ink:#0E0F0E;
  --v4-ink-2:#1C1E1C;
  --v4-paper:#F2EEE6;
  --v4-paper-2:#EBE6D8;
  --v4-paper-3:#E0DAC8;
  --v4-mute:#84817A;
  --v4-line:#D2CBB9;
  --v4-line-soft:#E4DEC9;
  --v4-accent:#B9583C;     /* burnt copper, more saturated than v3 */
  --v4-accent-hi:#D86A48;
  --v4-night:#0B0C0A;
  --serif: 'Newsreader', 'Source Serif Pro', Georgia, serif;
  --sans: 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --mono: 'Barlow Condensed', 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, sans-serif;
  --ease-soft: cubic-bezier(.22,.61,.36,1);
}

@keyframes pulse-dot{0%,100%{opacity:1}50%{opacity:.35}}

/* Neutralise Squarespace theme typography/link styling inside the shell */
.site-shell-nav,.site-shell-footer{
  font-family:var(--sans);font-size:16px;line-height:1.4;letter-spacing:0;text-transform:none;
  color:var(--v4-ink);box-sizing:border-box;
}
.site-shell-nav *,.site-shell-footer *{box-sizing:border-box}
.site-shell-nav a,.site-shell-footer a{color:inherit;text-decoration:none;background:none}
.site-shell-nav a:hover,.site-shell-footer a:hover{text-decoration:none}

/* =========================================================================
   NAV — slim, sticky  (verbatim from v4-styles.css)
   ========================================================================= */
.v4-nav{
  position:sticky;top:0;left:0;right:0;z-index:50;
  display:flex;align-items:center;justify-content:space-between;
  padding:18px 40px;
  background:rgba(var(--zn-cream-rgb,242,238,230),0.85);
  backdrop-filter:saturate(140%) blur(14px);
  -webkit-backdrop-filter:saturate(140%) blur(14px);
  border-bottom:1px solid transparent;
  transition:border-color .3s ease, padding .3s ease;
}
.v4-nav.is-scrolled{border-bottom-color:var(--v4-line-soft);padding:12px 40px}
.v4-nav-brand{display:flex;align-items:center;gap:12px;font-family:var(--serif);font-size:18px;letter-spacing:-.01em}
.v4-nav-mark{
  width:28px;height:28px;border-radius:50%;
  background:var(--v4-ink);color:var(--v4-paper);
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.04em;
  position:relative;overflow:hidden;
}
.v4-nav-mark::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  background:radial-gradient(circle at 30% 30%, rgba(var(--zn-hilite-rgb,255,255,255),0.18), transparent 60%);
  pointer-events:none;
}
.v4-nav-brand-name{font-weight:500}
/* Photo variant — for an img inside the nav-mark circle */
.v4-nav-mark-photo{background:var(--v4-paper-2, #ecebe5)}
.v4-nav-mark-photo > img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center 30%;
  border-radius:50%;
  z-index:1;
}
.v4-nav-brand-text{display:inline}
.v4-nav-brand-sub{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--v4-mute);margin-left:2px}
.v4-nav-brand-sub::before{content:" · "}
.v4-nav-links{display:flex;gap:28px;align-items:center}
.v4-nav-link{
  font-family:var(--mono);font-size:var(--zn-label,12px);letter-spacing:var(--zn-label-track,.08em);text-transform:uppercase;color:var(--v4-ink-2);
  position:relative;padding:6px 0;cursor:pointer;
}
.v4-nav-link::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:left;transition:transform .35s var(--ease-soft);
}
.v4-nav-link:hover::after,.v4-nav-link.is-on::after{transform:scaleX(1)}
.v4-nav-cta{
  display:inline-flex;align-items:center;gap:10px;
  padding:10px 18px;border-radius:99px;
  background:var(--v4-ink);color:var(--v4-paper);
  font-family:var(--mono);font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  white-space:nowrap;flex-shrink:0;
  transition:background .25s ease, transform .35s var(--ease-soft);
}
.v4-nav-cta:hover{background:var(--v4-accent);transform:translateY(-1px)}
.v4-nav-cta-dot{width:6px;height:6px;border-radius:50%;background:#7AB48A;box-shadow:0 0 8px rgba(var(--zn-led-green-rgb,122,180,138),0.7);animation:pulse-dot 2s ease-in-out infinite;flex-shrink:0}
/* The nav is three short links and the brand — no CTA pill — so the links stay
   visible all the way down instead of vanishing under 900px. They tighten
   progressively; the brand sub-label is what gives up space, not the links.
   Mirrors src/v4-styles.css, which the React pages use. */
@media (max-width:900px){
  /* `.v4-nav.is-scrolled` (0,2,0) out-specifies a bare `.v4-nav` here, and the
     shell pages hard-code is-scrolled — so the mobile padding must match it. */
  .v4-nav,.v4-nav.is-scrolled{padding:14px 20px;gap:16px}
  .v4-nav-links{gap:18px;flex-shrink:0}
  /* B15: the links no longer step down to 10.5 / 10px on phones — the 12px label token
     is the floor at every width; only the gap tightens. */
  .v4-nav-link{white-space:nowrap}
}
@media (max-width:640px){
  .v4-nav-brand-sub{display:none}
  .v4-nav-links{gap:14px}
}
@media (max-width:520px){
  /* Nav: brand shrinks so logo + Work/About/Contact hold one line at 360px */
  .v4-nav,.v4-nav.is-scrolled{padding:12px 14px;gap:10px}
  .v4-nav-brand{gap:9px;flex:0 1 auto;min-width:0}
  .v4-nav-mark{width:32px;height:32px;flex-shrink:0}
  .v4-nav-brand-text{display:flex;flex-direction:column;gap:2px;min-width:0;line-height:1.2}
  .v4-nav-brand-name{white-space:nowrap;font-size:17px}
  .v4-nav-brand-sub{margin-left:0}
  .v4-nav-brand-sub::before{content:""}
}

/* In-flow on sqs pages: never overlays the first Squarespace section. The
   .v4-nav rule above is `position:sticky`; the important flag wins the cascade. */
.site-shell-nav{position:static !important;background:var(--v4-paper)}
.site-shell-nav .v4-nav-brand > span{display:inline}
@media (max-width:520px){.site-shell-nav .v4-nav-brand > span{display:flex;flex-direction:column;gap:2px;min-width:0;line-height:1.2}}
/* the brand-sub is inside the brand span on sqs pages; keep the "· " separator only when inline */
.site-shell-nav .v4-nav-cta{color:var(--v4-paper);background:var(--v4-ink)} /* `.site-shell-nav a{background:none}` (0,1,1) out-specifies `.v4-nav-cta` (0,1,0) → pill lost its ink fill, paper text on paper */
.site-shell-nav .v4-nav-cta:hover{background:var(--v4-accent)}

/* =========================================================================
   FOOTER — paper-2 band, serif spine line, condensed meta (consistent with
   the homepage footer ribbon)
   ========================================================================= */
.site-shell-footer{
  position:relative;z-index:1;
  background:var(--v4-paper-2);color:var(--v4-ink);
  border-top:1px solid var(--v4-line);
  padding:36px 40px;
}
.site-shell-footer-inner{
  display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;
  max-width:1400px;margin:0 auto;
}
.site-shell-footer-back{
  font-family:var(--mono);font-size:var(--zn-label,12px);letter-spacing:var(--zn-label-track,.08em);text-transform:uppercase;color:var(--v4-ink-2);
  position:relative;padding:6px 0;white-space:nowrap;
}
.site-shell-footer-back::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:left;transition:transform .35s var(--ease-soft);
}
.site-shell-footer-back:hover::after{transform:scaleX(1)}
.site-shell-footer-spine{
  font-family:var(--serif);font-style:italic;font-size:clamp(22px,2.6vw,34px);line-height:1.05;
  letter-spacing:-.022em;color:var(--v4-ink);font-variation-settings:"opsz" 60;
  flex:1;text-align:center;
}
.site-shell-footer-meta{
  font-family:var(--mono);font-size:var(--zn-label,12px);letter-spacing:var(--zn-label-track,.08em);text-transform:uppercase;color:var(--v4-mute);white-space:nowrap;
}
@media (max-width:900px){
  .site-shell-footer{padding:32px 20px}
  .site-shell-footer-inner{justify-content:center}
  .site-shell-footer-spine{flex:0 1 100%;order:-1}
}

/* =========================================================================
   FIRST SECTION CLEARANCE — Squarespace overlays a transparent header and pads
   the first section by the measured header height (zco 99.48px / sg 106.58px on
   desktop; 80.175px fallback at ≤799px). Our nav is in-flow, so the first section
   gets (header height − nav height) to keep the reference band height and the
   content's y position.
   ========================================================================= */
:root{--site-shell-nav-h:53px;--sqs-header-height:100px}
body[data-archive="zco"]{--sqs-header-height:99.48px}
body[data-archive="sg"]{--sqs-header-height:106.58px}
/* mobile: the Squarespace mobile header is taller than the 80.175px CSS fallback — calibrated against the
   390px reference screenshots (zco: first content row 151px on /innit, 146px on /work; sg: measured likewise) */
@media only screen and (pointer: coarse) and (max-width: 1024px), screen and (max-width: 799px){
  body[data-archive="zco"]{--sqs-header-height:100px}
  body[data-archive="sg"]{--sqs-header-height:86px}
}
/* The nav is in-flow, so this must equal its REAL rendered height or the first
   section's compensation padding is wrong. Re-measured after the nav CTA pill was
   removed (the pill, not the links, used to set the nav's height):
   >900px 53.09px (padding 12/40) - ≤900px 57px (padding 14/20, and 12/14 under 520). */
@media (max-width:900px){:root{--site-shell-nav-h:57px}}
main.sqs-sections > .page-section:first-child:not(.content-collection):not(.gallery-section):not(.user-items-list-section){
  padding-top:max(0px, calc(var(--sqs-header-height) - var(--site-shell-nav-h)));
}
/* vh-height first sections: site.css puts min-height 33/66/100vh on the section itself and the overlay header
   sat INSIDE that box. With the in-flow nav the box must shrink by the nav height, otherwise the band ends
   (nav + 33vh) below the reference and the vertically-centred content sits ~20px too low. */
main.sqs-sections > .page-section:first-child.section-height--small:not(.content-collection):not(.gallery-section):not(.user-items-list-section){min-height:calc(33vh - var(--site-shell-nav-h))}
main.sqs-sections > .page-section:first-child.section-height--medium:not(.content-collection):not(.gallery-section):not(.user-items-list-section){min-height:calc(66vh - var(--site-shell-nav-h))}
main.sqs-sections > .page-section:first-child.section-height--large:not(.content-collection):not(.gallery-section):not(.user-items-list-section){min-height:calc(100vh - var(--site-shell-nav-h))}
/* B19: on phones the case-page header band (the .zn-headnav-host first section) sat 31px lower than the
   v2 .cs-head — titles at y 122-157 against 91 — because the desktop header-height compensation was
   still in force. Cap the clearance at 12px (nav 51 + 12 + the 3.3vmax content padding = 91) and range
   the content from the top instead of centring it in the 33vh floor, so a short band (sherpa) lands at
   the same line and the chevrons at the band foot sit clear of the credit. */
@media (max-width:720px){
  main.sqs-sections > .page-section.zn-headnav-host:first-child:not(.content-collection):not(.gallery-section):not(.user-items-list-section){padding-top:12px;align-items:flex-start}
}

/* =========================================================================
   zn-theme — work-index ground opt-in
   sqs/zco/sqs-base.css hardcodes body{background:rgb(242,238,230)} and is on
   the do-not-touch list, so the ported shell cannot follow a palette on its
   own. The /work grid is OUR markup, not ported artwork, so it opts in here.
   The 36 case studies deliberately do NOT: their bodies are ported Squarespace
   layouts with their own section colours, and they keep the original cream
   ground under every palette. They still get themed nav and footer chrome.
   Gated on data-zn-pal, so with no theme active this matches nothing.
   ========================================================================= */
html[data-zn-pal]:not([data-zn-pal="0"]) body[data-slug="work"]{
  background:var(--v4-paper);
}
html[data-zn-pal]:not([data-zn-pal="0"]) body[data-slug="work"] .section-background,
html[data-zn-pal]:not([data-zn-pal="0"]) body[data-slug="work"] .section-border{
  background:var(--v4-paper);
}

/* --- zn nav: centred tagline (retarget_sqs_nav.py) --- */
.v4-nav,.v4-nav.is-scrolled{display:grid;grid-template-columns:1fr auto 1fr;align-items:center}
.v4-nav-tagline{
  justify-self:center;text-align:center;
  font-family:var(--mono);font-size:var(--zn-label,12px);letter-spacing:var(--zn-label-track,.08em);text-transform:uppercase;
  color:var(--v4-mute);white-space:nowrap;
}
.v4-nav-links{justify-self:end}
/* A4: the tagline is ~445px wide and the 1fr auto 1fr grid leaves it touching the Work link
   between 901 and ~1060px, so it hides below 1100 (was 900); the two-column grid goes with it. */
@media (max-width:1100px){
  .v4-nav,.v4-nav.is-scrolled{grid-template-columns:auto 1fr}
  .v4-nav-tagline{display:none}
}
/* --- end zn nav --- */

/* --- zn press --- */
/* One quote, one source, one fact. Emitted by _tools/add_press.py on the
   case pages with public evidence on record. Tokens only. */
.zn-press{
  position:relative;z-index:1;
  background:var(--v4-paper-2);color:var(--v4-ink);
  padding:96px 40px;
  font-family:var(--sans);line-height:1.5;letter-spacing:0;text-transform:none;
  box-sizing:border-box;
}
.zn-press *{box-sizing:border-box;margin:0}
.zn-press-inner{
  display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:48px 80px;align-items:end;
  max-width:1400px;margin:0 auto;
}
.zn-press-quote p{
  font-family:var(--serif);font-weight:400;font-size:clamp(26px,2.6vw,36px);line-height:1.12;
  letter-spacing:-.015em;color:var(--v4-ink);text-wrap:balance;max-width:22ch;
  font-variation-settings:"opsz" 48;
}
.zn-press-src{
  margin-top:20px;font-family:var(--mono);font-size:var(--zn-label,12px);letter-spacing:var(--zn-label-track,.08em);text-transform:uppercase;
  color:var(--v4-mute);line-height:1.2;
}
.zn-press-src a,.zn-press-fact-src{color:inherit;text-decoration:none;border-bottom:1px solid var(--v4-line)}
.zn-press-src a:hover,.zn-press-fact-src:hover{color:var(--v4-accent);border-color:var(--v4-accent)}
.zn-press-fact{
  font-size:17px;line-height:1.5;color:var(--v4-ink);max-width:36ch;
}
.zn-press-num{
  display:block;font-family:var(--serif);font-weight:500;font-size:40px;line-height:1;
  letter-spacing:-.02em;margin-bottom:8px;color:var(--v4-ink);font-variation-settings:"opsz" 48;
}
.zn-press-fact-src{font-size:13px;color:var(--v4-mute);white-space:nowrap}
@media (max-width:900px){
  .zn-press{padding:72px 20px}
  .zn-press-inner{grid-template-columns:minmax(0,1fr);gap:40px}
}
/* --- end zn press --- */


/* --- zn wall --- */
/* Scroll-driven screen wall, emitted by _tools/build_screen_wall.py in place of the
   Squarespace screenshot galleries. Rows of cards drift at three rates as the band
   crosses the viewport; phone screens stand up as they enter. Motion is
   animation-timeline: view() on the compositor where supported and a small scroll
   handler (sqs/zn-wall.js) writing --p where not; both give the same transform at
   the same scroll position. Nothing moves unless the reader scrolls. Reduced motion
   is a static grid. Each row carries --n (its card count) and --x0/--x1 (drift in
   vw); the drift is clamped to the row's real overflow, so no row ever shows its
   end, and a row narrower than the viewport sits centred. Tokens only; the band
   sits on the page ground. */
.zn-wall{
  position:relative;z-index:1;
  --card:clamp(220px,26vw,520px);--gap:clamp(14px,1.6vw,24px);
  --phone:clamp(132px,14vw,240px);--pgap:clamp(18px,2.4vw,36px);
  padding:clamp(64px,8vw,120px) 0 clamp(72px,9vw,130px);
  overflow-x:hidden;overflow-x:clip;
  background:transparent;color:var(--v4-ink);
  font-family:var(--sans);line-height:1.4;letter-spacing:0;text-transform:none;
  box-sizing:border-box;
}
.zn-wall *{box-sizing:border-box;margin:0}
.zn-wall img{display:block;max-width:100%}
.zn-wall-inner{max-width:1400px;margin:0 auto clamp(28px,3.4vw,44px);padding:0 40px}
.zn-wall-label{
  font-family:var(--mono);font-size:var(--zn-label,12px);letter-spacing:var(--zn-label-track,.08em);text-transform:uppercase;
  color:var(--v4-mute);line-height:1.2;
}
.zn-wall-rows{display:flex;flex-direction:column;gap:var(--gap)}
.zn-wall--phones .zn-wall-rows{gap:clamp(28px,3.4vw,56px)}
/* frames */
.zn-wall-row{
  --w:calc(var(--n,8) * var(--card) + (var(--n,8) - 1) * var(--gap));
  --over:max(0px,calc(var(--w) - 100vw));
  display:flex;gap:var(--gap);width:max-content;
  margin-left:max(0px,calc((100vw - var(--w)) / 2));will-change:transform;
  transform:translate3d(clamp(calc(-1 * var(--over)),var(--x0),0px),0,0);
}
.zn-wall-card{
  flex:0 0 auto;width:var(--card);aspect-ratio:var(--zn-wall-ar,16/9);
  border-radius:6px;overflow:hidden;background:var(--v4-paper-3);
  box-shadow:0 0 0 1px var(--v4-line-soft);
  box-shadow:0 0 0 1px var(--v4-line-soft),0 22px 44px -26px color-mix(in srgb,var(--v4-ink) 42%,transparent);
}
.zn-wall-card img{width:100%;height:100%;object-fit:cover;object-position:top}
.zn-wall-js .zn-wall-card{opacity:0;transform:translateY(18px);transition:opacity .8s var(--ease-soft),transform .8s var(--ease-soft)}
.zn-wall-js .zn-wall-card.is-in{opacity:1;transform:none}
/* phones */
.zn-wall--phones{perspective:1400px;perspective-origin:50% 40%}
.zn-wall-phones{
  --w:calc(var(--n,12) * var(--phone) + (var(--n,12) - 1) * var(--pgap));
  --over:max(0px,calc(var(--w) - 100vw));
  display:flex;align-items:flex-start;gap:var(--pgap);width:max-content;
  margin-left:max(0px,calc((100vw - var(--w)) / 2));transform-style:preserve-3d;will-change:transform;
  transform:translate3d(clamp(calc(-1 * var(--over)),var(--x0),0px),0,0);
}
.zn-wall-phone{
  flex:0 0 auto;width:var(--phone);padding:clamp(6px,.7vw,10px);
  border-radius:clamp(20px,2.4vw,32px);background:var(--v4-night);
  box-shadow:0 34px 54px -30px var(--v4-ink);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--v4-paper) 10%,transparent),0 34px 54px -30px color-mix(in srgb,var(--v4-ink) 60%,transparent);
  transform-origin:50% 60%;transform:translate3d(0,var(--dy),0) rotateY(var(--ry));
}
.zn-wall-screen{aspect-ratio:var(--zn-wall-ar,9/16);border-radius:clamp(14px,1.7vw,22px);overflow:hidden;background:var(--v4-paper)}
.zn-wall-screen img{width:100%;height:100%;object-fit:cover;object-position:top}
.zn-wall-js .zn-wall-phone{opacity:0;transition:opacity .9s var(--ease-soft)}
.zn-wall-js .zn-wall-phone.is-in{opacity:1}
/* motion A: CSS scroll-driven, on the compositor */
@supports (animation-timeline: view()){
  .zn-wall-row,.zn-wall-phones{animation:zn-wall-drift linear both;animation-timeline:view();animation-range:entry 0% exit 100%}
  .zn-wall-phone{animation:zn-wall-stand linear both;animation-timeline:view();animation-range:entry 0% cover 38%}
}
@keyframes zn-wall-drift{
  from{transform:translate3d(clamp(calc(-1 * var(--over)),var(--x0),0px),0,0)}
  to{transform:translate3d(clamp(calc(-1 * var(--over)),var(--x1),0px),0,0)}
}
@keyframes zn-wall-stand{
  from{transform:translate3d(0,calc(var(--dy) + 56px),-120px) rotateY(var(--ry)) rotateX(16deg)}
  to{transform:translate3d(0,var(--dy),0) rotateY(var(--ry)) rotateX(0deg)}
}
/* motion B: zn-wall.js writes --p (0..1 view progress) where A is missing */
html[data-zn-wall-motion="js"] .zn-wall-row,
html[data-zn-wall-motion="js"] .zn-wall-phones{animation:none;transform:translate3d(clamp(calc(-1 * var(--over)),calc(var(--x0) + (var(--x1) - var(--x0)) * var(--p,0)),0px),0,0)}
html[data-zn-wall-motion="js"] .zn-wall-phone{animation:none;transform:translate3d(0,calc(var(--dy) + 56px * (1 - var(--p,0))),calc(-120px * (1 - var(--p,0)))) rotateY(var(--ry)) rotateX(calc(16deg * (1 - var(--p,0))))}
@media (prefers-reduced-motion:reduce){
  .zn-wall-row,.zn-wall-phones{animation:none !important;transform:translate3d(clamp(calc(-1 * var(--over)),calc((var(--x0) + var(--x1)) / 2),0px),0,0) !important}
  .zn-wall-phone{animation:none !important;transform:translate3d(0,var(--dy),0) rotateY(var(--ry)) !important;opacity:1 !important;transition:none !important}
  .zn-wall-card{opacity:1 !important;transform:none !important;transition:none !important}
}
@media (max-width:900px){ .zn-wall-inner{padding:0 20px} }
/* --- end zn wall --- */


/* --- zn cs --- */
/* cs case-study sections inside the Squarespace-mirror pages, emitted by
   _tools/apply_copy_layers.py. Same rules as build_case_v2.py, scoped. */
main.sqs-sections > .cs-lsd, main.sqs-sections > .cs-story, main.sqs-sections > .cs-credits{
  --cs-shadow:0 28px 90px -6px color-mix(in srgb, var(--v4-ink) 40%, transparent),
              0 6px 16px color-mix(in srgb, var(--v4-ink) 10%, transparent);
  --cs-shadow-pop:0 32px 70px -4px color-mix(in srgb, var(--v4-ink) 52%, transparent),
                  0 10px 24px color-mix(in srgb, var(--v4-ink) 14%, transparent);
  --cs-white:#FFFFFF;
  --cs-plate-a:var(--v4-paper-2); --cs-plate-b:var(--v4-paper-3);
  --cs-brand-a:var(--v4-paper-2); --cs-brand-b:var(--v4-paper-3);
  display:block; position:relative; z-index:1; box-sizing:border-box;
  margin:0; background:var(--v4-paper); color:var(--v4-ink);
  font-family:var(--sans); font-size:17px; line-height:1.8; font-weight:400; font-style:normal;
  letter-spacing:0; text-transform:none;
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
}
main.sqs-sections > .cs-lsd *, main.sqs-sections > .cs-story *, main.sqs-sections > .cs-credits *{ box-sizing:border-box }
main.sqs-sections > .cs-story img, main.sqs-sections > .cs-story video{ display:block; max-width:100%; height:auto; border:0 }
/* ------------------------------------------------------------------- LSD */
.sqs-sections .cs-lsd{ padding:clamp(56px,8.3vw,120px) clamp(20px,6.9vw,100px) clamp(64px,8.6vw,124px) }
.sqs-sections .cs-lsd.is-night{ background:var(--v4-night); color:#F2EEE6 }
.sqs-sections .cs-lsd-grid{
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  column-gap:clamp(32px,8.7vw,125px); max-width:1240px; margin:0 auto;
}
.sqs-sections .cs-lsd-k{
  margin:0; font-family:var(--sans); font-weight:600; color:inherit;
  font-size:clamp(24px,2.38vw,34.3px); line-height:1.34; letter-spacing:-.01em; text-transform:none;
}
.sqs-sections .cs-lsd p{ margin:0; font-size:17px; line-height:1.8; font-weight:400; color:inherit }
/* ----------------------------------------------------------------- STORY */
.sqs-sections .cs-story{ padding:clamp(56px,5.6vw,80px) 0 }
.sqs-sections .cs-story.is-night{ background:var(--v4-night); color:#F2EEE6 }
.sqs-sections .cs-story-grid{ display:grid; align-items:center; max-width:1440px; margin:0 auto }
.sqs-sections .cs-story.is-right .cs-story-grid{
  grid-template-columns:minmax(0,501fr) minmax(0,601fr);
  column-gap:clamp(40px,12.5vw,181px); padding-left:clamp(20px,10.9vw,157px);
}
.sqs-sections .cs-story.is-left .cs-story-grid{
  grid-template-columns:minmax(0,771fr) minmax(0,387fr);
  column-gap:clamp(32px,4.7vw,68px); padding-right:clamp(20px,14.9vw,214px);
}
.sqs-sections .cs-story.is-left .cs-text{ order:2 }
.sqs-sections .cs-story.is-left .cs-media{ order:1 }
.sqs-sections .cs-text{ min-width:0 }
.sqs-sections .cs-eyebrow{
  margin:0 0 20px; font-family:var(--mono); font-size:13.5px; line-height:1.3; font-weight:400;
  letter-spacing:.12em; text-transform:uppercase; color:var(--v4-mute);
}
.sqs-sections .is-night .cs-eyebrow{ color:#F2EEE6; opacity:.62 }
.sqs-sections .cs-headline{
  margin:0; font-family:var(--serif); font-weight:400; color:inherit;
  font-size:clamp(29px,2.98vw,43px); line-height:1.316; letter-spacing:-.02em; text-transform:none;
  text-wrap:balance;
}
.sqs-sections .cs-headline em{ font-style:italic; color:var(--v4-accent) }
.sqs-sections .is-night .cs-headline em{ color:var(--v4-accent-2, var(--v4-accent)) }
.sqs-sections .cs-body{ margin:34px 0 0; font-size:17px; line-height:1.8; font-weight:400; max-width:501px; color:inherit }
.sqs-sections .cs-stack{ max-width:1440px; margin:0 auto }
.sqs-sections .cs-text.is-center{ text-align:center; max-width:680px; margin:0 auto; padding:0 20px }
.sqs-sections .cs-text.is-center .cs-body{ margin-left:auto; margin-right:auto }
.sqs-sections .cs-stack > .cs-inset, .sqs-sections .cs-stack > .cs-bleed{ margin-top:40px }
.sqs-sections .cs-inset{ padding:0 clamp(20px,3vw,43px) }
.sqs-sections .cs-two{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:clamp(20px,4.2vw,61px); padding:0 clamp(20px,4.2vw,60px); align-items:stretch }
/* B4: a pair shares one height — the shorter plate stretches and its media centres on it */
.sqs-sections .cs-two .cs-media.is-inset{ display:flex; align-items:center }
/* --------------------------------------------------------- MEDIA + PLATE */
.sqs-sections .cs-media{ position:relative; min-width:0 }
.sqs-sections .cs-media::before{ background:var(--cs-plate) }
.sqs-sections .cs-media figure{ margin:0; position:relative; z-index:1 }
.sqs-sections .cs-media.is-inset figure[style]{ margin:0 auto }
.sqs-sections .cs-media figure > img, .sqs-sections .cs-media figure > video{ width:100%; box-shadow:var(--cs-shadow) }
.sqs-sections .cs-media.is-paper{ --cs-plate:linear-gradient(180deg, var(--cs-plate-a), var(--cs-plate-b)) }
.sqs-sections .cs-media.is-brand{ --cs-plate:linear-gradient(180deg, var(--cs-brand-a), var(--cs-brand-b)) }
.sqs-sections .cs-media.is-white{ --cs-plate:var(--cs-white) }
.sqs-sections .cs-media.is-corner{ padding:0 12% 12% 0 }
.sqs-sections .cs-media.is-corner::before{ content:""; position:absolute; top:14%; left:14%; right:0; bottom:0 }
.sqs-sections .cs-media.is-corner figure > img, .sqs-sections .cs-media.is-corner figure > video{ box-shadow:var(--cs-shadow-pop) }
.sqs-sections .cs-media.is-inset{ padding:7% }
.sqs-sections .cs-media.is-inset::before{ content:""; position:absolute; inset:0 }
.sqs-sections .cs-media.is-float{ padding:0 }
.sqs-sections .cs-media.is-flat figure > img, .sqs-sections .cs-media.is-flat figure > video{ box-shadow:none }
.sqs-sections .cs-media.is-alpha figure > img{ box-shadow:none; filter:drop-shadow(0 22px 34px color-mix(in srgb, var(--v4-ink) 32%, transparent)) }
.sqs-sections .cs-media.is-round figure > img, .sqs-sections .cs-media.is-round figure > video{ border-radius:20px }
.sqs-sections .cs-trio{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:5%; padding:7% 8% }
.sqs-sections .cs-trio::before{ content:""; position:absolute; inset:0 }
.sqs-sections .cs-trio > figure:nth-child(2){ transform:translateY(-4%) }
.sqs-sections .cs-trio.is-even > figure:nth-child(2){ transform:none }
.sqs-sections .cs-bleed .cs-media{ width:100% }
.sqs-sections .cs-story.is-full{ padding-bottom:0 }
/* --------------------------------------------------------------- CREDITS */
.sqs-sections .cs-credits{ padding:82px clamp(20px,10.9vw,157px) 80px }
.sqs-sections .cs-credits-grid{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  column-gap:clamp(24px,3vw,44px); max-width:1126px; margin:0 auto;
}
.sqs-sections .cs-credit strong{ display:block; font-weight:700; font-size:17px; line-height:1.8; color:inherit }
.sqs-sections .cs-credit p{ margin:15px 0 0; font-size:17px; line-height:1.8; font-weight:400; color:inherit }
/* ------------------------------------------ FLUID-ENGINE GRID OVERRIDES */
/* A block moved out of a fluid-engine grid leaves its rows behind. The tool
   re-flows the survivors through these variables so the hole closes. */
@media (max-width:767px){
  .sqs-sections .fe-block[style*="--zn-ga-m"]{ grid-area:var(--zn-ga-m) }
  .sqs-sections .fluid-engine[style*="--zn-rows-m"]{ grid-template-rows:repeat(var(--zn-rows-m),minmax(24px,auto)) }
}
@media (min-width:768px){
  .sqs-sections .fe-block[style*="--zn-ga-d"]{ grid-area:var(--zn-ga-d) }
  .sqs-sections .fluid-engine[style*="--zn-rows-d"]{ grid-template-rows:repeat(var(--zn-rows-d),minmax(calc(var(--container-width) * var(--row-height-scaling-factor)),auto)) }
}
/* ------------------------------------------------------------ RENDER TAG */
.sqs-sections .zn-render-tag{
  position:absolute; left:14px; bottom:14px; z-index:3;
  font-family:var(--mono); font-size:var(--zn-label,12px); line-height:1.3; font-weight:600;
  letter-spacing:var(--zn-label-track,.08em); text-transform:uppercase;
  color:var(--v4-paper); background:color-mix(in srgb, var(--v4-ink) 72%, transparent);
  padding:6px 10px; border-radius:3px; pointer-events:none;
}
/* ------------------------------------------------------------ RESPONSIVE */
@media (max-width:1023px){
  .sqs-sections .cs-story.is-right .cs-story-grid, .sqs-sections .cs-story.is-left .cs-story-grid{
    grid-template-columns:minmax(0,1fr); padding:0; row-gap:40px;
  }
  .sqs-sections .cs-story.is-left .cs-text, .sqs-sections .cs-story.is-right .cs-text{ order:1; padding:0 clamp(20px,6vw,40px) }
  .sqs-sections .cs-story.is-left .cs-media, .sqs-sections .cs-story.is-right .cs-media{ order:2 }
  .sqs-sections .cs-story.is-right .cs-media.is-corner, .sqs-sections .cs-story.is-left .cs-media.is-corner{ padding:0 8% 10% 6% }
  .sqs-sections .cs-story.is-right .cs-media.is-corner::before, .sqs-sections .cs-story.is-left .cs-media.is-corner::before{ left:18%; top:12% }
  .sqs-sections .cs-story.is-right .cs-media.is-corner figure[style], .sqs-sections .cs-story.is-left .cs-media.is-corner figure[style]{ width:64% !important }
  .sqs-sections .cs-story.is-right .cs-media.is-inset, .sqs-sections .cs-story.is-left .cs-media.is-inset{ padding:7% }
  .sqs-sections .cs-story.is-right .cs-media.is-float, .sqs-sections .cs-story.is-left .cs-media.is-float{ padding:0 clamp(20px,6vw,40px) }
}
@media (max-width:900px){
  .sqs-sections .cs-credits-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); row-gap:32px }
}
@media (max-width:767px){
  main.sqs-sections > .cs-lsd, main.sqs-sections > .cs-story, main.sqs-sections > .cs-credits{ font-size:16px }
  .sqs-sections .cs-lsd{ padding:56px 23px 64px }
  .sqs-sections .cs-lsd-grid{ grid-template-columns:minmax(0,1fr); row-gap:24px }
  .sqs-sections .cs-lsd p, .sqs-sections .cs-body, .sqs-sections .cs-credit strong, .sqs-sections .cs-credit p{ font-size:16px }
  .sqs-sections .cs-body{ margin-top:24px }
  .sqs-sections .cs-two{ grid-template-columns:minmax(0,1fr); row-gap:40px }
  .sqs-sections .cs-trio{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:6%; padding:8% 7% }
  .sqs-sections .cs-trio > figure:nth-child(2){ transform:none }
  .sqs-sections .cs-trio > figure:nth-child(3){ grid-column:1 / -1; width:47%; justify-self:center }
}
@media (max-width:480px){
  .sqs-sections .cs-credits-grid{ grid-template-columns:minmax(0,1fr) }
  .sqs-sections .cs-credits{ padding:64px 23px 64px }
}
@media (prefers-reduced-motion:reduce){ .sqs-sections .cs-trio > figure:nth-child(2){ transform:none } }
/* --- end zn cs --- */


/* --- zn no-hide --- */
/* Squarespace's export runs `animation:hideContent 2s` on every section's content-wrapper
   while it waits for animation JS the port never loads: two blank seconds on every load.
   The motion layer (zn-motion) owns build-ins now. */
.page-section > .content-wrapper, .page-section .content-wrapper{ animation:none !important; opacity:1 !important; }
/* --- end zn no-hide --- */

/* --- zn pill --- */
/* Pointer-following highlight on the pill CTAs (pattern audit 20, 2026-09-13). /sqs/zn-nav.js
   writes --mx / --my on pointermove, as a percentage of the pill's own box; the highlight is a
   radial gradient in a ::after layer between the pill's fill and its text, so nothing transforms
   and nothing moves while the pointer is still. 180ms ease in and out. currentColor at low alpha,
   so it reads on an ink pill and on a paper one alike. Fine pointers only; off under reduced
   motion. The work filter pills (.zn-filter-pill) keep their own rules in the work page. */
.v5-cta,.zn-pill,.v5-footer-cta,.v4-nav-cta,.v5-practice-header-jump a{position:relative;overflow:hidden;isolation:isolate}
.v5-cta::after,.zn-pill::after,.v5-footer-cta::after,.v4-nav-cta::after,.v5-practice-header-jump a::after{
  content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  background:radial-gradient(circle 72px at var(--mx,50%) var(--my,50%),color-mix(in srgb,currentColor 18%,transparent),transparent 100%);
  opacity:0;transition:opacity .18s ease;
}
@media (hover:hover) and (pointer:fine){
  .v5-cta:hover::after,.zn-pill:hover::after,.v5-footer-cta:hover::after,.v4-nav-cta:hover::after,.v5-practice-header-jump a:hover::after{opacity:1}
}
@media (prefers-reduced-motion:reduce){
  .v5-cta::after,.zn-pill::after,.v5-footer-cta::after,.v4-nav-cta::after,.v5-practice-header-jump a::after{display:none}
}
/* --- end zn pill --- */

/* --- zn view transitions --- */
/* Cross-document view transitions (pattern 1): the clicked tile's hero travels into the
   case masthead; the page ground crossfades. Same-origin navigations only; browsers
   without support fall back to a plain load. Names are set per element: the tile side
   in sqs/zn-tiles.js on pageswap, the case side below (v2 pages) or in zn-motion.js. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root){ animation-duration:.42s; animation-timing-function:cubic-bezier(.22,.61,.36,1); }
::view-transition-group(case-hero){ animation-duration:.62s; animation-timing-function:cubic-bezier(.22,.61,.36,1); }
::view-transition-old(case-hero){ animation:none; opacity:0; }
::view-transition-new(case-hero){ animation:none; }
main.cs .cs-hero > img, main.cs .cs-hero > video, main.cs .cs-hero picture img{ view-transition-name:case-hero; }
@media (prefers-reduced-motion:reduce){ ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*){ animation:none !important; } }
/* --- end zn view transitions --- */

/* --- zn headnav --- */
/* Header-level project arrows, emitted by _tools/add_headnav.py. Thin strokes,
   nearly headline height, at the gutters, centred on the header section. */
.zn-headnav-host{ position:relative }
.zn-headnav{
  position:absolute; top:50%; z-index:5;
  display:flex; align-items:center; justify-content:center;
  width:56px; height:88px; margin-top:-44px;
  color:var(--v4-ink); opacity:.55; text-decoration:none; background:none;
  transition:opacity .25s ease, transform .35s var(--ease-soft, cubic-bezier(.22,.61,.36,1));
}
.zn-headnav svg{ display:block; width:24px; height:56px }
.zn-headnav-prev{ left:24px }
.zn-headnav-next{ right:24px }
.zn-headnav-next svg{ transform:scaleX(-1) }
.zn-headnav:hover,.zn-headnav:focus-visible{ opacity:1; color:var(--v4-accent); text-decoration:none; background:none }
.zn-headnav-prev:hover{ transform:translateX(-4px) }
.zn-headnav-next:hover{ transform:translateX(4px) }
.zn-headnav:focus{ outline:none }
.zn-headnav:focus-visible{ outline:2px solid var(--v4-accent); outline-offset:4px; border-radius:4px }
/* Portal-template masts range their text from the 60px gutter, so the arrows sit
   inside the gutter itself (56px wide box at 0). */
main.pc .zn-headnav-prev, main.pcs .zn-headnav-prev{ left:2px }
main.pc .zn-headnav-next, main.pcs .zn-headnav-next{ right:2px }
@media (max-width:900px){
  .zn-headnav{ width:40px; height:64px; margin-top:-32px }
  .zn-headnav svg{ width:16px; height:38px }
  .zn-headnav-prev{ left:6px } .zn-headnav-next{ right:6px }
  main.pc .zn-headnav-prev, main.pcs .zn-headnav-prev{ left:2px }
  main.pc .zn-headnav-next, main.pcs .zn-headnav-next{ right:2px }
}
@media (max-width:720px){
  /* phones: titles run edge to edge, so the arrows drop to the foot of the header band */
  .zn-headnav{ top:auto; bottom:6px; margin-top:0; height:44px }
  .zn-headnav svg{ width:14px; height:32px }
}
@media (prefers-reduced-motion:reduce){ .zn-headnav{ transition:none } .zn-headnav:hover{ transform:none } }
/* --- end zn headnav --- */

/* --- zn projnav --- */
/* Bottom-of-page project navigation on the case studies: BACK / INDEX / NEXT.
   Emitted by _tools/add_projnav.py (and _tools/build_portal_case.py for pages
   built there). Tokens only, no literals, so the band follows the palette. */
.zn-projnav{
  position:relative;z-index:1;
  background:var(--v4-paper);color:var(--v4-ink);
  border-top:1px solid var(--v4-line);
  padding:64px 40px;
  font-family:var(--sans);font-size:16px;line-height:1.4;letter-spacing:0;text-transform:none;
  box-sizing:border-box;
}
.zn-projnav *{box-sizing:border-box}
.zn-projnav-inner{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px;
  max-width:1400px;margin:0 auto;
}
.zn-projnav-card{
  display:flex;flex-direction:column;align-items:flex-start;gap:10px;min-width:0;
  color:inherit;text-decoration:none;background:none;
}
.zn-projnav-card:hover{text-decoration:none;background:none}
.zn-projnav-label{
  font-family:var(--mono);font-size:var(--zn-label,12px);letter-spacing:var(--zn-label-track,.08em);text-transform:uppercase;
  color:var(--v4-mute);line-height:1.2;
}
.zn-projnav-name{
  position:relative;display:inline-block;max-width:100%;
  font-family:var(--serif);font-weight:500;font-size:clamp(22px,2.4vw,34px);line-height:1.05;
  letter-spacing:-.018em;color:var(--v4-ink);font-variation-settings:"opsz" 48;
  overflow-wrap:anywhere;text-wrap:balance;
  transition:color .25s ease;
}
.zn-projnav-name::after{
  content:"";position:absolute;left:0;right:0;bottom:-4px;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:left;transition:transform .35s var(--ease-soft, cubic-bezier(.22,.61,.36,1));
}
.zn-projnav-card:hover .zn-projnav-name{color:var(--v4-accent)}
.zn-projnav-card:hover .zn-projnav-name::after{transform:scaleX(1)}
.zn-projnav-cat{font-family:var(--sans);font-size:13px;line-height:1.4;color:var(--v4-mute)}
.zn-projnav-card:focus{outline:none}
.zn-projnav-card:focus-visible{outline:2px solid var(--v4-accent);outline-offset:4px}
.zn-projnav-back{text-align:left;align-items:flex-start}
.zn-projnav-index{text-align:center;align-items:center}
.zn-projnav-index .zn-projnav-name::after{transform-origin:center}
.zn-projnav-next{text-align:right;align-items:flex-end}
.zn-projnav-next .zn-projnav-name::after{transform-origin:right}
@media (max-width:900px){
  .zn-projnav{padding:64px 20px}
}
@media (max-width:720px){
  /* Stacked: NEXT first, then INDEX, then BACK. Everything ranges left and a
     hairline separates the cards, echoing the band's own top rule. */
  .zn-projnav-inner{grid-template-columns:minmax(0,1fr);gap:0}
  .zn-projnav-card{padding:24px 0;text-align:left;align-items:flex-start}
  .zn-projnav-next{order:1;padding-top:0}
  .zn-projnav-index{order:2;border-top:1px solid var(--v4-line)}
  .zn-projnav-back{order:3;border-top:1px solid var(--v4-line);padding-bottom:0}
  .zn-projnav-index .zn-projnav-name::after,
  .zn-projnav-next .zn-projnav-name::after{transform-origin:left}
}
@media (prefers-reduced-motion:reduce){
  .zn-projnav-name,.zn-projnav-name::after{transition:none}
}
/* --- end zn projnav --- */
