/*
  EKKO site foundation, shared by every page: tokens, the rem scaling model, reset, type helpers, rules, the chevron
  band, CTA boxes, and the site header (logo, nav, "Let’s Talk", mobile menu). The header markup is rendered into
  each page by /build.py; its behaviour lives in /shared/site.js (<ekko-header>).

  SCALING MODEL: the Figma frames are 1440px wide. 1rem = 100vw / 144 (10px at 1440), so every measurement is Figma
  px / 10 in rem and pages keep their proportions at any width. Phones (max-width 767px) use 1rem = 100vw / 39
  (10px at 390).
*/
:root{
  --story-hero-h:80.83rem;                /* case-study hero height (story.css); page transitions frame images to it */
  /* Colour. The site is dark; html[data-mode="light"] (below) flips the ground, the type and the boxes. Red never
     changes, and neither does anything set over a photo or on red (the nav over the hero, white on red): those keep literal colours. */
  --bg:#000;                              /* page and section grounds */
  --fg:#fff;                              /* type, rules, outlines */
  --fg-rgb:255 255 255;                   /* the same, for translucent use: rgb(var(--fg-rgb) / .25) */
  --box:#fff;                             /* the boxes that stand out from the ground (btn-box, cta-box, arrow tiles) */
  --on-box:#000;                          /* type on them */
  --red:#ff1a00;
  --grey:#a6a6a6;
  --grey-2:#9a9a9a;
  --grey-3:#b7b7b7;                      /* figure captions */
  --rule:1px;
  --well:#1a1a1a;                        /* ground behind photos while they load, and initials tiles, on black */
  --pattern:url("/home-assets/chevron-pattern.svg");
}
/* Light mode (a test: ?mode=light, set before the first paint by site.js). Greys are darker, not mirrored: #a6a6a6
   on white is 2.4:1. */
html[data-mode="light"]{
  --bg:#fff;--fg:#000;--fg-rgb:0 0 0;--box:#000;--on-box:#fff;
  --grey:#6b6b6b;--grey-2:#6b6b6b;--grey-3:#6b6b6b;--well:#ededed;
  color-scheme:light;
}
/* White single-colour icons drawn for the black ground (the clients arrows, the sparkle) are drawn black instead.
   (arrow-black.svg is red, despite its name: it stays.) */
html[data-mode="light"] img:is([src$="arrow-right.svg"],[src$="icon-sparkles.svg"]){filter:invert(1)}
*,*::before,*::after{box-sizing:border-box}
html{
  font-size:calc(100vw / 144);           /* 1rem = 10px @ 1440 */
  -webkit-text-size-adjust:100%;
  overflow-x:clip;
}
/* Smooth in-page scrolling (the skip link, #top), but only once the page has loaded (site.js adds .smooth): a link
   that opens a page at a #section then lands on it at once instead of gliding down from the top, and a reload or
   Back keeps the browser's own scroll restore. Never with reduced motion. */
@media (prefers-reduced-motion:no-preference){html.smooth{scroll-behavior:smooth}}
body{
  margin:0;
  background:var(--bg);
  color:var(--fg);
  font-family:Inter,system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:clip;
}
img{display:block}
:where(img[width][height]){height:auto}   /* build.py writes each image's size for its aspect ratio; any CSS size still wins */
a{color:inherit;text-decoration:none}
h1,h2,h3,h4,p,ul{margin:0;font-weight:400}
ul{padding:0;list-style:none}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
:focus-visible{outline:.2rem solid var(--red);outline-offset:.2rem}
[hidden]{display:none!important}                    /* a component's own display never overrides hidden */
.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* Type helpers */
.cal{font-family:"Cal Sans",Inter,sans-serif;font-weight:400}
.h-section{font-size:8.9rem;line-height:9rem;letter-spacing:-.178rem}
.body-lg{font-size:2.6rem;line-height:3rem;letter-spacing:.0016rem}
.cover{width:100%;height:100%;object-fit:cover}
/* Teaser type: an article or project title with its one-line summary (homepage Insights bar, post list) */
.t-teaser{font-family:"Cal Sans",Inter,sans-serif;font-weight:400;font-size:3.8rem;line-height:4rem;letter-spacing:.076rem}
.t-summary{font-size:2rem;line-height:2.3rem}

/* Rules */
.rule-b{border-bottom:var(--rule) solid var(--fg)}
.rule-t{border-top:var(--rule) solid var(--fg)}

/* Pill button (nav + approach) */
.pill{
  display:grid;place-items:center;
  width:18.6rem;height:3.9rem;
  border:.2rem solid var(--fg);border-radius:10rem;
  font-size:1.4rem;font-weight:500;letter-spacing:.028rem;
  transition:background .25s,color .25s;
}
.pill:hover{background:var(--fg);color:var(--bg)}

/* White/black CTA boxes with a diagonal arrow */
.cta-box{position:absolute;background:var(--box);color:var(--on-box);overflow:hidden}
.cta-box span{position:absolute;font-weight:500;font-size:2.4rem;line-height:2.6rem;letter-spacing:.0014rem}
.cta-box img{position:absolute;width:4.55rem;height:4.6rem;transition:transform .35s cubic-bezier(.16,1,.3,1)}
.cta-box:hover img{transform:translate(.4rem,-.4rem)}

/* White box button: black label + red diagonal arrow, 66px tall, at least 155px wide, the label 23px in from the left
   and the arrow 23px in from the right (Figma header 170:92, labelled "Skip the Sell" there, and Partnerships
   "Let’s talk" 172:458 — the same component).
   <a class="btn-box" href="…"><span>Let’s Talk</span><img src="/home-assets/arrow-skip.svg" alt=""></a> */
.btn-box{display:inline-flex;align-items:center;justify-content:space-between;gap:1.5rem;min-width:15.5rem;height:6.6rem;padding:0 2.33rem;background:var(--box);color:var(--on-box);font-size:1.6rem;font-weight:500;transition:background .3s ease,color .3s ease}
.btn-box img{width:1.89rem;height:1.92rem;transition:transform .35s cubic-bezier(.16,1,.3,1)}
.btn-box:hover img{transform:translate(.3rem,-.3rem)}

/* Section title: a Cal Sans section heading opening a section, 116px below the rule above it and 79px above what
   follows (Insights "Recent", Partnerships "How it works"). <h2 class="section-title cal h-section">…</h2> */
.section-title{padding:11.6rem 4rem 7.9rem}

/* Red label + white arrow box pair (Figma 63:802 "View work"; Partnerships "Let’s Talk"). Wrapper sets the layout:
   <a class="cta|view-work"><span class="cta__label">…</span><span class="cta__arrow"><img src="/home-assets/arrow-red.svg" alt=""></span></a> */
.cta__label{width:17.32rem;background:var(--red);text-align:left;padding:1.19rem 0 0 2rem;font-weight:500;font-size:2.4rem;line-height:2.6rem;letter-spacing:.0014rem}
.cta__arrow{width:5rem;height:5rem;background:var(--box);display:grid;place-items:center}
.cta__arrow img{width:2.09rem;height:2.12rem;transition:transform .35s cubic-bezier(.16,1,.3,1)}

/* Chevron band */
.band{
  position:relative;
  background:var(--bg) var(--pattern) -0.7rem 0 / 143.44rem 24.96rem no-repeat;
}
.band h2{position:absolute;left:3.83rem}
/* Brand tile: the header logo blown up to fill a square of any size: red ground, the EKKO mark at the logo's
   proportional offset (Figma 83:13 on Team, 158:1138 on Work). <div class="brand-tile"><img src="/home-assets/ekko-mark.svg" alt="EKKO"></div> */
.brand-tile{position:relative;background:var(--red)}
.brand-tile img{position:absolute;left:27.72%;top:20.61%;width:49.52%;height:auto}
/* Mark: a white line-art glyph (/shared/marks/*.svg) centred on the positioned box it sits in (photo bands, the
   homepage "What we do" states). --w is its Figma width (px / 10; 183px if unset), its height follows the SVG, and
   --x nudges it off centre. Half size on phones.
   <img class="mark" src="/shared/marks/strategy.svg" alt="" style="--w:38rem"> */
.mark{position:absolute;left:50%;top:50%;width:var(--w,18.3rem);height:auto;transform:translate(calc(-50% + var(--x,0rem)),-50%);pointer-events:none}
/* Section-head band: a 285px band with the title low on the left (homepage Work and Insights, Work page Case studies).
   A page can retune it with --band-h (height) and --band-x / --band-y (title position); phones always use 140px. */
.band--head{height:var(--band-h,28.52rem);background-position:-0.7rem 1.85rem}
.band--head h2{left:var(--band-x,3.91rem);top:var(--band-y,11.43rem)}


/* ───────────────────────── SITE HEADER (<ekko-header>) ───────────────────────── */
ekko-header{display:contents}
.site-header{position:fixed;top:0;left:0;right:0;height:0;z-index:60;pointer-events:none;color:#fff}
.site-header > *{pointer-events:auto}
/* Skip link: the first stop for the keyboard. Off-screen until focused, then a white box (the .btn-box look) over the
   logo's corner; it jumps to <main id="main"> (build.py gives every page's main that id). */
.skip-link{position:absolute;left:4rem;top:1.6rem;z-index:2;padding:1.4rem 2rem;background:var(--box);color:var(--on-box);font-size:1.6rem;font-weight:500;line-height:2rem;translate:0 -12rem}
.skip-link:focus{translate:0 0}
.logo{position:absolute;left:4.04rem;top:3.92rem;width:6.6rem;height:6.6rem;background:var(--red)}   /* Figma header 170:77 */
.logo svg{position:absolute;left:1.83rem;top:1.36rem;width:3.27rem;height:3.75rem}
/* Nav (Figma 113:1795–1803): links on a frosted strip, then the white "Let’s Talk" box flush against it. */
.nav{position:absolute;right:4rem;top:3.92rem;display:flex;align-items:center;height:6.6rem}
.nav__links{
  display:flex;align-items:center;justify-content:center;gap:3.4rem;width:52.5rem;height:100%;
  background:var(--veil,rgba(0,0,0,.06));-webkit-backdrop-filter:blur(2.5rem);backdrop-filter:blur(2.5rem);
  transition:background-color .35s ease;
  font-size:1.6rem;font-weight:500;letter-spacing:.032rem;
}
.nav__links a{padding:.4rem 0;border-bottom:.15rem solid transparent;transition:border-color .25s,color .3s ease}
.nav__links a:hover{border-color:currentColor}
/* NavInk sets .is-ink on the link strip (all its links together) and on the button, each as a whole. */
.nav__links a[aria-current]{border-color:currentColor}             /* the page you're on, underlined like a hover */
.nav__links.is-ink a,html.pt-ink .nav__links a{color:#000}   /* pt-ink: on a page transition's white, until its wipe */
.talk{width:17.5rem;height:100%;box-shadow:inset 0 0 0 1px rgba(0,0,0,.12)}   /* a .btn-box, fixed at Figma's 175px; always white (NavInk leaves it alone), the faint edge keeps the box visible on white */
/* Mobile menu (hidden on desktop) */
.mnav,.menu-btn{display:none}


/* ═════════════════════════ PHONES ═════════════════════════ */
@media (max-width:767px){
  html{font-size:calc(100vw / 39)}                                   /* 1rem = 10px @ 390 */
  section[id],ekko-footer[id]{scroll-margin-top:8.8rem}                   /* anchor jumps land below the header bar */
  .h-section{font-size:4.8rem;line-height:5rem;letter-spacing:-.096rem}
  .body-lg{font-size:1.8rem;line-height:2.5rem}
  .t-teaser{font-size:2.6rem;line-height:3rem;letter-spacing:.05rem}
  .t-summary{font-size:1.6rem;line-height:2.2rem;color:var(--grey)}
  .band--head{height:14rem;background-position:-0.7rem 0}
  .band--head h2{left:2rem;top:auto;bottom:2.8rem}
  .btn-box{min-width:0;height:5rem;padding:0 1.8rem;gap:1.2rem}
  .mark{width:calc(var(--w,18.3rem) * .5);transform:translate(calc(-50% + var(--x,0rem) * .5),-50%)}
  .section-title{padding:6.4rem 2rem 3.2rem}
  .cta__label{width:15rem;padding:1.2rem 0 0 1.6rem;font-size:2rem;line-height:2.2rem}
  .cta__arrow{width:4.8rem;height:4.8rem}

  /* header + menu. Once past the page's [data-hero] a black bar fades in behind the logo and Menu pill. */
  .site-header::before{content:"";position:absolute;left:0;right:0;top:0;height:8.8rem;background:var(--bg);opacity:0;transition:opacity .35s ease}
  .scrolled .site-header::before{opacity:1}
  .menu-open .site-header::before{opacity:0}
  html.pt-on .site-header::before{opacity:0}     /* page transition: no black bar over the white (Safari tints its status bar from it) */
  .logo{left:2rem;top:2rem;width:4.8rem;height:4.8rem}
  .logo svg{left:1.33rem;top:.99rem;width:2.38rem;height:2.73rem}
  .nav{display:none}
  .menu-btn{
    display:flex;align-items:center;gap:.9rem;position:absolute;right:2rem;top:2.6rem;height:3.6rem;padding:0 1.5rem 0 1.7rem;
    border:.15rem solid var(--fg);border-radius:10rem;background:var(--bg);color:var(--fg);font-size:1.3rem;font-weight:500;letter-spacing:.03rem;
  }
  .menu-btn__icon{position:relative;width:1.4rem;height:1rem}
  .menu-btn__icon::before,.menu-btn__icon::after{content:"";position:absolute;left:0;width:100%;height:.15rem;background:currentColor;transition:transform .5s cubic-bezier(.16,1,.3,1),top .5s cubic-bezier(.16,1,.3,1)}
  .menu-btn__icon::before{top:.15rem}
  .menu-btn__icon::after{top:.7rem}
  .menu-open .menu-btn__icon::before{top:.42rem;transform:rotate(45deg)}
  .menu-open .menu-btn__icon::after{top:.42rem;transform:rotate(-45deg)}
  .mnav{
    display:flex;flex-direction:column;position:fixed;inset:0;padding:12rem 2rem 4rem;background:var(--bg);color:var(--fg);
    clip-path:inset(0 0 100% 0);visibility:hidden;
    transition:clip-path .6s cubic-bezier(.76,0,.24,1),visibility 0s .6s;
  }
  .menu-open .mnav{clip-path:inset(0);visibility:visible;transition-delay:0s}
  .mnav ul{border-top:var(--rule) solid rgb(var(--fg-rgb) / .25)}
  .mnav li{border-bottom:var(--rule) solid rgb(var(--fg-rgb) / .25)}
  .mnav li a,.mnav .pill{opacity:0;transform:translateY(1.2rem);transition:opacity .3s ease,transform .5s cubic-bezier(.16,1,.3,1)}
  .mnav li a{display:block;padding:1.4rem 0;font-family:"Cal Sans",Inter,sans-serif;font-size:4.4rem;line-height:5rem}
  .mnav .pill{margin-top:4rem;width:18rem;height:4.4rem;font-size:1.4rem}
  .menu-open .mnav li a,.menu-open .mnav .pill{opacity:1;transform:none;transition-delay:calc(.25s + var(--i, 0) * .06s)}
  .menu-open .mnav .pill{transition-delay:.45s}
  .mnav li a[aria-current]{color:var(--red)}

}

/* Back (or Forward) to a page (site.js; the Transition 4 prototype's Back): the page you were on fades to black, then
   this one fades back up from the black, growing from where the homepage had sunk to (about .85) to full size.
   Overrides the page-transition bridge's hold below. */
html:active-view-transition-type(back)::view-transition{background:var(--bg)}
html:active-view-transition-type(back)::view-transition-old(root){animation:pt-to-black .45s cubic-bezier(.4,0,.2,1) both}
html:active-view-transition-type(back)::view-transition-new(root){animation:pt-home-up .9s cubic-bezier(.33,0,.2,1) .45s both}
@keyframes pt-to-black{to{opacity:0}}
@keyframes pt-home-up{from{opacity:0;transform:scale(.85)}}

/* Page transition (/shared/page-transition.js). The white screen and its red word, as the departing page's box (.pt-box,
   .pt-word) and as the arriving page's first-frame stand-in (html.pt-arriving::after, set up by site.js): one rule, so
   the hand-off between them can't drift. --pt-fs is the word size as a fraction of the screen width.
   While the departing page's white owns the screen the page itself turns white too (html.pt-white). So does the
   arriving page, under its white, until the wipe starts (desktop; phones keep black for the status bar): if Chrome
   shows a frame before it has painted everything (a busy browser, at a high pixel ratio), the gap is white like the
   screen, not a black flash. (Scrolling is locked by the script, EKKO.scrollLock, not here.) */
html.pt-white,html.pt-white body{background:#fff}
@media (min-width:768px){
  html.pt-ink,html.pt-ink body{background:#fff}
}
.pt-box,.pt-veil,html.pt-arriving::after{position:fixed;top:0;left:0;width:100%;height:100vh;height:100lvh}
.pt-box{z-index:59;background:#fff;overflow:hidden;display:grid;place-items:center}
.pt-box .pt-word{will-change:transform}
/* The title card (phones and touch screens, word links): the word over the page, which fades to and from its own
   ground (page-transition.js), never white, so Safari's bars never change colour. An arriving page is held at 0 under
   the word until it fades up; the header stays. */
.pt-box--card{background:none}
html.pt-card.pt-arriving::after{background:var(--bg)}
html.pt-card body > :not(ekko-header):not(.pt-box){opacity:0}
.pt-veil{z-index:58;background:var(--bg);pointer-events:none}
/* Image mode: the image at its natural size, placed by transform (page-transition.js); first frame: the same image,
   cover-fit to the screen. */
.pt-box--image{display:block;background:#000}
.pt-img{position:absolute;left:0;top:0;max-width:none;transform-origin:0 0;will-change:transform}
html.pt-arriving--image::after{content:"";height:var(--pt-fit-h,100lvh);background:#000 var(--pt-image) var(--pt-pos,50% 50%)/cover no-repeat}   /* framed as the last page left it */
/* Until page-transition.js has the image decoded and in place, nothing but the header paints. Under the bridge (below)
   none of this shows; it's the fallback where there's no bridge (older Safari): the browser keeps the last page's frame
   until this page's first meaningful paint, which is then the image itself, not a black screen with only the header. */
html.pt-hold body > :not(ekko-header){visibility:hidden}   /* the header stays put, as it was on the last page */
/* Close (Figma 348:64): on a page an image transition brought in, the way back to the card it came from
   (page-transition.js). On the page, over the hero, so it scrolls away with it; in the Share tab's column. White box,
   red X, as the drawer and snackbar close. Under the contact drawer; while an arrival's image settles it's raised
   level with it (.pt-close--over), so it fades in over the image rather than after it. */
.pt-close{position:absolute;z-index:50;left:10.93rem;top:16.91rem;display:grid;place-items:center;width:5rem;height:5rem;background:#fff;color:var(--red)}
.pt-close svg{width:1.87rem;height:1.87rem;fill:none;stroke:currentColor;stroke-width:2.6;transition:rotate .35s cubic-bezier(.16,1,.3,1)}
.pt-close:hover svg{rotate:90deg}
.pt-close:focus-visible{outline:.2rem solid #fff;outline-offset:.3rem}
.pt-close--over{z-index:59}
@media (max-width:767px){.pt-close{left:2rem;top:11.2rem;width:4.4rem;height:4.4rem}}
/* Across the navigation itself, the browser keeps the last page's final frame up: a cross-document view transition,
   switched on (@view-transition, added by EKKO.ptBridge in site.js) only on the two pages of a page transition, so
   no other navigation has one. It holds that snapshot, untouched, over the new page until page-transition.js says the
   new page has drawn its own copy of that frame (its font loaded, its image decoded), then drops it: the two frames
   match, so nothing blinks however long the new page takes. 3s is only the backstop.
   The new page stays fully drawn underneath (not at opacity 0, which Chrome may not paint ahead), so when the
   snapshot goes the live page is already painted. Plain stacking, no blend: the snapshot covers it exactly.
   site.js also makes the arriving page render-blocking until it's fully read (link rel=expect), so even when a browser
   skips the bridge its first frame is complete: header, white and word. */
::view-transition-old(root),::view-transition-new(root){animation:pt-bridge 3s step-end both;mix-blend-mode:normal}
::view-transition-old(root){z-index:1}
@keyframes pt-bridge{from,to{opacity:1}}
html.pt-arriving::after{content:var(--pt-word);z-index:59;display:grid;place-items:center;background:#fff;
  font-size:calc(var(--pt-fs) * 100vw)}
.pt-word,html.pt-arriving::after{font-family:"Cal Sans",Inter,sans-serif;font-weight:400;line-height:1;letter-spacing:-.02em;
  white-space:nowrap;color:#ff1a00}
