/* Site styles — mirrors the design system components. Tokens live in tokens.css. */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:calc(90px + var(--header-strip-h))}
body{margin:0;background:var(--surface-page);color:var(--text-primary);font-family:var(--font-body);-webkit-font-smoothing:antialiased}
a{color:var(--link)}a:hover{color:var(--link-hover)}
img{max-width:100%}
h1,h2,h3,p{margin:0}
[hidden]{display:none!important}

/* Buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;text-decoration:none;border:0;cursor:pointer;font-family:var(--font-body);border-radius:var(--radius-pill);line-height:1.2;white-space:nowrap;padding:16px 28px;font-size:var(--text-body-md);font-weight:var(--weight-semibold);background:var(--button-primary-bg);color:var(--button-primary-fg);transition:opacity .15s ease,transform .15s ease}
.btn:hover{opacity:.88;color:var(--button-primary-fg)}.btn:active{transform:translateY(1px)}
.btn--secondary,.btn--secondary:hover{background:var(--button-secondary-bg);color:var(--button-secondary-fg)}
.btn--nav,.btn--nav:hover{background:var(--button-nav-bg);color:var(--color-white)}
.btn--ghost,.btn--ghost:hover{background:transparent;color:var(--text-on-brand);padding:10px 4px}
.btn--sm{padding:12px 22px;font-size:var(--text-body-sm);font-weight:var(--weight-medium)}
.btn--lg{padding:18px 30px;font-size:var(--text-body-lg)}
.btn--ghost.btn--lg{padding:10px 4px}

/* Type helpers */
.eyebrow{font-family:var(--font-eyebrow);font-size:var(--text-eyebrow);font-weight:var(--weight-semibold);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;line-height:1.4;color:var(--text-accent)}
.eyebrow--sm{font-size:var(--text-eyebrow-sm)}
.eyebrow--dark{color:var(--text-accent-on-inverse)}
.eyebrow--brand{color:var(--text-on-brand-muted)}
.heading{display:flex;flex-direction:column;gap:12px}
.heading--body{gap:18px}
.heading h2{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h2);line-height:var(--leading-heading);text-wrap:pretty;color:var(--text-primary)}
.heading p{font-size:var(--text-body-lg);line-height:var(--leading-body);color:var(--text-secondary)}
.heading--dark h2{color:var(--text-on-inverse)}.heading--dark p{color:var(--text-on-inverse-muted)}

/* Logo: assets/logo.svg#logo via <use>, so it takes the text colour */
.wordmark{display:inline-flex;align-items:center;color:var(--text-primary);line-height:0}
.wordmark:hover{color:var(--text-primary)}
.wordmark svg{display:block;height:var(--logo-h);width:auto;fill:currentColor;overflow:visible} /* the letters touch the box edges; see logo.svg */
.wordmark--sm svg{height:var(--logo-h-sm)}

/* Header: a white bar with rounded top corners under a navy strip. The strip is the sticky header's own top
   padding, so the corners always have it behind them. js/nav.js hides the whole header (.is-hidden) while you
   scroll down and brings it back on any scroll up; hiding moves the sticky offset above the viewport, so near
   the top of the page the header simply scrolls away with it. */
.site-header{position:sticky;top:0;z-index:20;background:var(--color-navy-700);padding-top:var(--header-strip-h);border-bottom:1px solid var(--border-subtle);transition:top .3s ease}
.site-header.is-hidden{top:calc(-1 * var(--header-h, 120px))}
@media (prefers-reduced-motion:reduce){.site-header{transition:none}}
.site-header__bar{display:flex;justify-content:space-between;align-items:center;padding:var(--header-pad-y) var(--page-gutter);background:var(--surface-card);border-radius:var(--radius-lg) var(--radius-lg) 0 0}
.nav-links{display:flex;gap:var(--space-36);align-items:center}
.nav-link{text-decoration:none;color:var(--text-primary);font-size:var(--text-body-sm);font-weight:var(--weight-medium)}
.nav-link:hover{color:var(--text-accent)}
.nav-toggle{display:none;width:44px;height:44px;align-items:center;justify-content:center;flex-direction:column;gap:5px;border:1px solid var(--border-subtle);border-radius:var(--radius-pill);background:var(--surface-card);cursor:pointer;padding:0}
.nav-toggle span{display:block;width:18px;height:2px;border-radius:2px;background:var(--text-primary);transition:transform .2s,opacity .2s}
.nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
.nav-panel{display:none;flex-direction:column;gap:4px;padding:8px var(--page-gutter) 24px;border-top:1px solid var(--border-subtle);background:var(--surface-card)}
.nav-panel .nav-link{font-size:var(--text-body-md);padding:12px 0;border-bottom:1px solid var(--border-subtle)}

/* Hero */
.hero{background:var(--gradient-brand);padding:var(--hero-pad-top) var(--page-gutter) 0;display:flex;flex-direction:column;gap:56px}
.hero__copy{display:flex;flex-direction:column;gap:28px;max-width:var(--measure-hero)}
.hero h1{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-display);line-height:var(--leading-display);color:var(--text-on-brand);text-wrap:balance}
.hero__lead{font-size:var(--text-lead);line-height:var(--leading-body-tight);color:var(--text-on-brand-muted);max-width:var(--measure-lead)}
.hero__actions{display:flex;gap:16px;align-items:center;flex-wrap:wrap}
.hero__media{position:relative;height:var(--hero-image-h);border-radius:var(--radius-lg) var(--radius-lg) 0 0;overflow:hidden}
.hero__parallax{position:absolute;inset:0}
.hero__media.is-parallax .hero__parallax{inset:-9% 0;will-change:transform}
.hero__image{width:100%;height:100%;object-fit:cover;display:block}
/* Load-in, CSS only so nothing waits on JS: the copy rises in turn, the eyebrow's letters spread to their
   tracking, the photo fades in and settles from a slight zoom. js/hero.js adds the scroll parallax. */
.hero__copy>*{animation:hero-rise 700ms cubic-bezier(.22,1,.36,1) both}
.hero__copy>:nth-child(2){animation-delay:90ms}
.hero__copy>:nth-child(3){animation-delay:180ms}
.hero__copy>:nth-child(4){animation-delay:270ms}
.hero__copy>.eyebrow{animation:hero-track 1200ms cubic-bezier(.22,1,.36,1) both}
.hero__media{animation:hero-fade 900ms ease-out 300ms both}
.hero__image{animation:hero-settle 2200ms cubic-bezier(.22,1,.36,1) 300ms both}
@keyframes hero-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes hero-track{from{opacity:0;letter-spacing:0}to{opacity:1;letter-spacing:var(--tracking-eyebrow)}}
@keyframes hero-fade{from{opacity:0}to{opacity:1}}
@keyframes hero-settle{from{transform:scale(1.08)}to{transform:none}}
@media (prefers-reduced-motion:reduce){.hero__copy>*,.hero__media,.hero__image{animation:none!important}}

/* Clients: white logo PNGs in two centred rows, as laid out on the intro-deck slide.
   Each img's --w and the gaps are slide units; --u scales them so the wider row (~880
   units) fills the band, capped at 1.2px per unit. Below 720px the rows wrap freely. */
.clients{background:var(--surface-inverse);color:var(--text-on-inverse);padding:40px var(--page-gutter);display:flex;flex-direction:column;gap:var(--space-30);container-type:inline-size;overflow:clip}
.clients .eyebrow{text-align:center;padding-left:var(--tracking-eyebrow)} /* padding offsets the trailing letter-spacing */
.clients__list{--u:clamp(.6px,100cqi / 880,1.2px);--gap:75.5;display:flex;flex-wrap:wrap;justify-content:center;align-items:center;row-gap:calc(13 * var(--u));list-style:none;margin:0;padding:0}
.clients__list li{margin-inline:calc(var(--gap) / 2 * var(--u))}
.clients__break ~ li{--gap:53.5}
.clients__list .clients__break{flex-basis:100%;height:0;margin:0}
.clients__list img{display:block;width:calc(var(--w) * var(--u));height:auto}
/* Focus pull: js/reveal.js hides the logos (.is-armed), then plays this once when the band is
   40% in view (.is-playing). --i is each logo's order. Without JS, or with reduced motion, logos just show. */
.clients__list.is-armed li:not(.clients__break){opacity:0}
.clients__list.is-playing li:not(.clients__break){opacity:1;animation:clients-focus 900ms cubic-bezier(.22,1,.36,1) calc(var(--i, 0) * 80ms) both}
@keyframes clients-focus{from{opacity:0;filter:blur(10px);transform:scale(1.18)}to{opacity:1;filter:blur(0);transform:none}}
@media (prefers-reduced-motion:reduce){.clients__list li:not(.clients__break){opacity:1!important;animation:none!important}}

/* Sections */
.section{padding:var(--section-pad-y) var(--page-gutter);display:flex;flex-direction:column;gap:48px}
.section--flush-top{padding-top:0}
.section--white{background:var(--surface-card)}
.section--dark{background:var(--surface-inverse)}
.split{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--grid-gap-split);padding:var(--section-pad-y) var(--page-gutter)}
.about__body{display:flex;flex-direction:column;gap:20px;font-size:var(--text-body-lg);line-height:var(--leading-body-loose);color:var(--text-secondary)}

/* Feature card */
.feature{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));background:var(--surface-card);border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--border-subtle)}
.feature--image-right>.feature__media{order:2}
.feature__media{height:var(--feature-image-h);overflow:hidden} /* clips the photo's settle so it can't spill into the text */
.feature__media img{width:100%;height:100%;object-fit:cover;display:block}
.feature__body{padding:var(--feature-pad);display:flex;flex-direction:column;justify-content:center;gap:18px}
.feature__meta{font-size:var(--text-meta);font-weight:var(--weight-bold);color:var(--text-accent)}
.feature h3{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h3);line-height:var(--leading-snug);text-wrap:pretty}
.feature p{font-size:var(--text-body);line-height:var(--leading-body);color:var(--text-secondary)}

/* Service + CTA cards */
.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-28)}
.service{display:flex;flex-direction:column;gap:16px}
.service img{width:100%;height:var(--service-image-h);object-fit:cover;border-radius:var(--radius-md);display:block}
.service h3{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h6);line-height:var(--leading-snug)}
.service p{font-size:var(--text-body-md);line-height:var(--leading-body);color:var(--text-secondary)}
.cta-card{display:flex;flex-direction:column;justify-content:center;align-items:flex-start;gap:18px;padding:40px;border-radius:var(--radius-md);background:var(--gradient-brand);min-height:240px}
.cta-card h3{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h4);line-height:var(--leading-cta);color:var(--text-on-brand);text-wrap:pretty}

/* Hubs */
.grid-hubs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-16)}
.hub{display:flex;flex-direction:column;gap:10px;padding:28px;border-radius:var(--radius-md);background:var(--surface-inverse-raised);color:var(--text-on-inverse)}
.hub__code{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h5)}
.hub__region{font-size:var(--text-small);color:var(--text-on-inverse-muted)}
/* Scroll-ins (js/reveal.js arms them, then plays each once when it comes into view): each featured work card
   rises as its photo settles from a slight zoom; the three hubs rise in turn, like the hero copy. */
.feature.is-armed{opacity:0}
.feature.is-playing{opacity:1;animation:feature-rise 800ms cubic-bezier(.22,1,.36,1) backwards} /* backwards, not both: holding the end state would pin transform and block the hover lift */
.feature.is-playing .feature__media img{animation:feature-settle 1600ms cubic-bezier(.22,1,.36,1) both}
.grid-hubs.is-armed .hub{opacity:0}
.grid-hubs.is-playing .hub{opacity:1;animation:hero-rise 700ms cubic-bezier(.22,1,.36,1) calc(var(--i, 0) * 90ms) both}
@keyframes feature-rise{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
@keyframes feature-settle{from{transform:scale(1.05)}to{transform:none}}
/* Featured work cards lift a little with a soft shadow under the mouse (not on touch, where it would stick after a tap) */
.feature{transition:transform .35s cubic-bezier(.22,1,.36,1),box-shadow .35s cubic-bezier(.22,1,.36,1)}
@media (hover:hover){.feature:hover{transform:translateY(-6px);box-shadow:var(--shadow-card-hover)}}
@media (prefers-reduced-motion:reduce){.feature,.grid-hubs .hub{opacity:1!important;animation:none!important}.feature__media img{animation:none!important}.feature{transition:box-shadow .35s ease}.feature:hover{transform:none}}

/* Team */
.grid-5{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--space-20)}
.team{display:flex;flex-direction:column;gap:10px;padding:28px;background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
.team__name{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h6)}
.team__bio{font-size:var(--text-body-sm);line-height:var(--leading-body-tight);color:var(--text-secondary)}

/* Contact */
.contact{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);align-items:start;gap:var(--space-48);margin:0 var(--page-gutter) var(--page-gutter);padding:var(--contact-pad-y) var(--contact-pad);border-radius:var(--radius-xl);background:var(--gradient-brand)}
.contact__copy{display:flex;flex-direction:column;gap:14px}
.contact h2{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h2-xl);line-height:var(--leading-heading);color:var(--text-on-brand)}
.contact__copy p{font-size:var(--text-body-xl);line-height:var(--leading-body-tight);color:var(--text-on-brand-muted)}

/* Contact form */
.contact-form{display:flex;flex-direction:column;gap:var(--space-16)}
.contact-form__row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-16)}
.field{display:flex;flex-direction:column;gap:var(--space-10)}
.field__label{font-size:var(--text-body-sm);font-weight:var(--weight-semibold);color:var(--text-on-brand)}
.field__optional{font-weight:var(--weight-regular);color:var(--text-on-brand-muted)}
.field__input{width:100%;font-family:var(--font-body);font-size:var(--text-body-md);line-height:var(--leading-body);color:var(--text-primary);background:var(--surface-card);border:var(--border-width) solid var(--border-subtle);border-radius:var(--radius-md);padding:var(--space-10) var(--space-18)}
.field__input:focus-visible{outline:2px solid var(--color-navy-900);outline-offset:2px}
.field__input[aria-invalid="true"]{border-color:var(--color-navy-900)}
.field__input--area{min-height:120px;resize:vertical}
.field__error{font-size:var(--text-small);font-weight:var(--weight-semibold);color:var(--text-on-brand)}
.field__error:empty{display:none}
.contact-form__trap{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}
.contact-form__captcha:empty{display:none}
.contact-form__footer{display:flex;align-items:center;gap:var(--space-20);flex-wrap:wrap}
.contact-form__footer .btn[disabled]{opacity:.6;cursor:default;transform:none}
.contact-form__status{font-size:var(--text-body-sm);font-weight:var(--weight-medium);line-height:var(--leading-body-tight);color:var(--text-on-brand)}
.contact-form__status:empty{display:none}
.contact-done{display:flex;flex-direction:column;gap:var(--space-14);align-self:center}
.contact-done h3{font-family:var(--font-heading);font-weight:var(--weight-bold);font-size:var(--text-h4);line-height:var(--leading-cta);color:var(--text-on-brand)}
.contact-done h3:focus{outline:none}
.contact-done p{font-size:var(--text-body-xl);line-height:var(--leading-body-tight);color:var(--text-on-brand-muted)}

/* Footer */
.site-footer{display:flex;justify-content:space-between;align-items:center;gap:var(--space-16);padding:32px var(--page-gutter);border-top:1px solid var(--border-subtle);font-size:var(--text-small);color:var(--text-tertiary)}

@media (max-width:1024px){
.grid-3{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid-5{grid-template-columns:repeat(3,minmax(0,1fr))}
.nav-links{display:none}.nav-toggle{display:inline-flex}
.nav-panel[data-open="true"]{display:flex}
}
@media (max-width:860px){
.split,.feature{grid-template-columns:minmax(0,1fr)}
.feature--image-right>.feature__media{order:0}
.contact{grid-template-columns:minmax(0,1fr)}
/* the eyebrow wraps here, and spreading its letters would re-wrap it and push the headline down mid-animation */
.hero__copy>.eyebrow{animation:hero-rise 700ms cubic-bezier(.22,1,.36,1) both}
}
@media (max-width:720px){
.grid-3,.grid-5,.contact-form__row{grid-template-columns:minmax(0,1fr)}
.site-footer{flex-direction:column;align-items:center;text-align:center}
.clients__list{--u:.7px;--gap:44;row-gap:24px}
.clients__break ~ li{--gap:44}
.clients__list .clients__break{display:none}
}
@media (max-width:480px){.grid-hubs{grid-template-columns:minmax(0,1fr)}}
