:root {
  --linen: #F7F4EE; --chalk: #FCFBF9; --stone: #EDE9E1; --sand: #D9D4CC;
  --clay:  #B5614A; --ink:   #2C2925; --taupe: #544E47; --sage: #8A9E8C;
  /* Jost, and only Jost.

     Cormorant Garamond was the display face for the whole build. It is
     gone: Christopher's call, after the Work page was rebuilt without
     it. Two tokens are kept rather than one so that every rule that
     reaches for --display still works and a second face can come back
     in one line if it is ever wanted. */
  --display: 'Jost', system-ui, sans-serif;
  --body:    'Jost', system-ui, sans-serif;
  --gutter:  clamp(1.25rem, 5vw, 5.5rem);
  --max:     1680px;

  /* Reading measure for long-form prose.
     The body copy carried max-width: 78ch, which sounds safe and is
     not: ch is the width of a zero, noticeably wider than the average
     lowercase letter, so 78ch rendered as a hundred real characters a
     line. Measured off the page rather than assumed, 55ch lands at
     about seventy - the range the eye can track without losing its
     place on the return sweep. */
  --measure: 55ch;

  /* Design tokens. These existed as scattered literals - eight
     transition durations, two easing curves, five radius values doing
     the same job. Defined once here so the site stays consistent as
     it changes. */
  --r-sm:  10px;   /* small thumbnails, chips */
  --r-md:  20px;   /* cards, tiles, images */
  --r-lg:  28px;   /* heroes, large panels */
  --r-pill: 999px;

  --ease: cubic-bezier(.16, 1, .3, 1);
  --t-fast: .25s;  /* colour and opacity changes */
  --t-mid:  .45s;  /* movement, lifts */
  --t-slow: 1.1s;  /* image scale, cross-fades */

  --shadow-soft:  0 10px 30px -14px rgba(44, 41, 37, .18);
  --shadow-lift:  0 18px 44px -18px rgba(44, 41, 37, .24);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0 }
/* scroll-padding-top keeps an anchor jump from landing underneath the
   header bar. 78px is the shrunk bar plus a little air - the bar is
   always shrunk by the time a jump happens, because a jump means you
   had already scrolled. */
html { font-size: 112.5%; scroll-behavior: smooth; scroll-padding-top: 78px; -webkit-font-smoothing: antialiased; overflow-x: clip }
body { background: var(--linen); color: var(--ink); font-family: var(--body);
       font-size: clamp(.95rem, .9rem + .25vw, 1.05rem); line-height: 1.75; position: relative; padding-bottom: 64px }
/* Subtle grain — a texture signal, not a decoration. Fixed so it never
   scrolls or interferes with layout. Opacity-only (no blend-mode) —
   blend modes on a full-viewport fixed layer force continuous
   recompositing under scroll/animation, a real, measurable cost that
   isn't worth it for something this subtle. */
body::after {
  content: ''; position: fixed; inset: 0; z-index: 9999; pointer-events: none;
  opacity: .025;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
a { color: inherit; text-decoration: none }
img { max-width: 100%; height: auto; display: block }
::selection { background: var(--clay); color: var(--chalk) }
:focus-visible { outline: 2px solid var(--clay); outline-offset: 3px }
.skip-link { position: absolute; left: -9999px; z-index: 999; background: var(--clay); color: var(--chalk); padding: .6rem 1.2rem }
.skip-link:focus { left: 1rem; top: 1rem }
.eyebrow { font-size: 1rem; letter-spacing: .22em; text-transform: uppercase; font-weight: 500; color: var(--clay) }
.s-hero .eyebrow { display: inline-block; background: var(--clay); color: var(--chalk); padding: .5rem 1rem }


/* ── Nav ── */
/* Fixed, not sticky, and the slot behind it holds the space.
   A sticky bar stays in the document's flow, so the moment it got
   shorter on scroll everything below moved up by the difference and
   the page jumped under the reader - which is why the collapsing
   header was taken out once already. Fixed bar plus a slot of
   constant height means the bar can shrink and nothing else moves.
   The slot's height is written by script from the bar's own
   measurement; the value here is the starting point and the answer if
   script never runs. */
.nav-slot { height: 106px }
.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between;
       gap: 1.5rem; padding: 1rem var(--gutter); background: var(--chalk);
       backdrop-filter: blur(14px) saturate(1.2); border-bottom: 1px solid var(--sand);
       transition: padding var(--t-fast) var(--ease) }
/* Logged in, the WordPress toolbar owns the top of the window. A
   sticky bar was pushed down by it; a fixed one has to be told. */
body.admin-bar .nav { top: 32px }
@media screen and (max-width: 782px) { body.admin-bar .nav { top: 46px } }
/* Measuring the bar means taking the shrink off for one frame. Nothing
   should animate while that happens. */
.nav.is-measuring, .nav.is-measuring * { transition: none !important }

.mark { display: flex; align-items: center; gap: .7rem }
.mark-logo-img { height: 72px; width: auto; max-width: 280px; object-fit: contain; object-position: left center }
.ring-mark { color: var(--clay); flex: none; object-fit: contain }
.mark .ring-mark { width: 58px; height: 58px }
/* The ring beside an uploaded logo is the scrolled state, and waits. */
.mark-ring { display: none }
.mark-txt { display: flex; flex-direction: column; line-height: 1 }
.mark-txt b { font-family: var(--display); font-weight: 400; font-size: 1.4rem; letter-spacing: .24em; text-transform: uppercase }
.mark-txt span { font-size: .64rem; letter-spacing: .26em; text-transform: uppercase; opacity: .55; margin-top: .35rem;
       max-height: 20px; transition: max-height var(--t-fast) var(--ease), opacity var(--t-fast) ease, margin-top var(--t-fast) var(--ease); overflow: hidden }

/* Scrolled: down to the mark alone.
   The logo is 30% larger than it was, which is a lot of bar to carry
   for the whole page. Once somebody has started reading, the mark is
   enough to say whose site this is and get them home. */
.nav.is-tight { padding-top: .7rem; padding-bottom: .7rem }
.nav.is-tight .mark-logo-img { display: none }
.nav.is-tight .mark-ring { display: block }
.nav.is-tight .mark .ring-mark { width: 40px; height: 40px }
.nav.is-tight .mark-txt b { font-size: 1.15rem }
.nav.is-tight .mark-txt span { max-height: 0; opacity: 0; margin-top: 0 }
@media (prefers-reduced-motion: reduce) {
  .nav, .mark-logo-img, .mark .ring-mark, .mark-txt span { transition: none }
}
.nav-links { display: flex; gap: 1.4rem; list-style: none; font-size: .64rem; letter-spacing: .16em; text-transform: uppercase }


/* Language switcher. Sits at the end of the main menu and prints
   nothing at all until a second language exists. */
.lang-switch { display: flex; align-items: center; gap: .35rem; letter-spacing: .1em }
.lang-switch a { opacity: .55; transition: opacity var(--t-fast) }
.lang-switch a:hover { opacity: 1 }
.lang-switch-on { color: var(--clay) }
.lang-switch-sep { opacity: .3 }
/* A language this particular page has no version in. Dimmed and not a
   link, rather than a link that quietly takes you somewhere else. */
.lang-switch-off { opacity: .28; cursor: default }
/* In the drawer, EN / ES would otherwise inherit the drawer's display
   size - clamp(1.8rem, 6vw, 2.8rem) - and arrive the size of a heading.
   It is a switch, not a menu item. */
.drawer-links .lang-switch { gap: .5rem; margin-top: 1.25rem; padding-top: 1.25rem; border-top: 1px solid var(--sand) }
.drawer-links .lang-switch a,
.drawer-links .lang-switch span { font-family: var(--body); font-size: .78rem; font-weight: 500; letter-spacing: .14em; padding: 0; border: 0 }


/* Services dropdown - WordPress outputs .sub-menu natively for any
   nested nav item, this just gives it somewhere real to display
   instead of an unstyled, always-visible nested list. */
.nav-links li { position: relative }
.nav-links .sub-menu { list-style: none; position: absolute; top: 100%; left: 0; min-width: 220px;
       background: var(--chalk); border: 1px solid var(--sand); box-shadow: 0 12px 24px -8px rgba(44,41,37,.18);
       padding: .5rem 0; opacity: 0; visibility: hidden; transform: translateY(-6px); transition: opacity var(--t-fast), transform var(--t-fast), visibility var(--t-fast) }
.nav-links li.menu-item-has-children:hover .sub-menu,
.nav-links li.menu-item-has-children:focus-within .sub-menu { opacity: 1; visibility: visible; transform: translateY(0) }
.nav-links .sub-menu li { display: block }
.nav-links .sub-menu a { display: block; padding: .7rem 1.2rem; color: var(--ink); white-space: nowrap; letter-spacing: .1em; opacity: .8 }
.nav-links .sub-menu a:hover { background: var(--linen); opacity: 1; color: var(--clay) }
.nav-links a { opacity: .75; transition: opacity var(--t-fast) }
.nav-links a:hover { opacity: 1; color: var(--clay) }
.nav-right { display: flex; align-items: center; gap: 1rem }
.nav-tel { font-size: .68rem; letter-spacing: .1em; opacity: .85 }
.nav-cta { font-size: .64rem; letter-spacing: .18em; text-transform: uppercase; font-weight: 500;
           border: 1px solid var(--ink); padding: .65rem 1.2rem; transition: background var(--t-fast), color var(--t-fast); white-space: nowrap }
.nav-cta:hover { background: var(--clay); border-color: var(--clay); color: var(--chalk) }
.burger { display: none; background: none; border: 0; color: inherit; cursor: pointer; padding: .4rem }
.burger span { display: block; width: 22px; height: 1px; background: currentColor; margin: 5px 0; transition: transform var(--t-mid), opacity var(--t-fast) }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg) }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0 }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg) }

/* The menu starts below the header bar rather than underneath it, and
   "safe center" is what stops a menu taller than the window from
   centring itself half off the top, where it cannot be scrolled back
   to. Both were exposed by the larger logo: the first item was sitting
   behind the bar. Browsers that do not know "safe" keep plain centre,
   which is the old behaviour and no worse. */
.drawer { position: fixed; inset: 0; z-index: 99; background: var(--chalk); display: flex; flex-direction: column;
          justify-content: center; justify-content: safe center; gap: .5rem;
          padding: calc(var(--nav-tall, 110px) + .75rem) var(--gutter) 2rem; transform: translateY(-100%);
          transition: transform var(--t-mid) var(--ease); overflow: auto }
.drawer[aria-hidden="false"] { transform: translateY(0) }
.drawer-links { list-style: none; display: flex; flex-direction: column; gap: .4rem }
.drawer-links .sub-menu { list-style: none; padding-left: 1.5rem; display: flex; flex-direction: column; gap: 0 }
.drawer-links .sub-menu a { font-family: var(--body); font-size: 1rem; font-weight: 400; padding: .5rem 0; border: 0; color: var(--taupe) }
.drawer-links a, .drawer-cta { font-family: var(--display); font-size: clamp(1.8rem, 6vw, 2.8rem); font-weight: 300;
                                padding: .3rem 0; border-bottom: 1px solid var(--sand); display: block }
.drawer-cta { color: var(--clay) }

/* The phone action bar. Hidden by default and switched on at the mobile
   breakpoint, which is what the rule down in the responsive section has
   always assumed. The default was never written, so a fixed dark bar sat
   across the bottom of every desktop page, covering the last 57px of the
   footer on all of them. */
.mbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 90; display: none; grid-template-columns: 1fr 1.3fr 1fr;
        background: var(--ink); border-top: 1px solid var(--taupe) }
.mbar a { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 1rem .5rem; font-size: .62rem;
          letter-spacing: .14em; text-transform: uppercase; font-weight: 500; color: var(--chalk) }
.mbar a + a { border-left: 1px solid var(--taupe) }
.mbar .primary { background: var(--clay) }
.mbar--back { grid-template-columns: 1fr 1.3fr }
.mbar-back { display: flex; align-items: center; gap: .4rem }
.mbar-navlabel { display: block; font-size: .56rem; letter-spacing: .16em; opacity: .8; margin-bottom: .2rem }
.mbar-navcat { display: block; font-size: .72rem; letter-spacing: .04em; text-transform: none; font-family: var(--display); font-weight: 400 }


/* Native page transitions — browser-native, zero JS for the base
   cross-fade. Browsers without support simply ignore this and get a
   normal page load, so it's pure upside with no fallback needed. */
@view-transition { navigation: auto; }

/* Case study navigation specifically gets a slide-up-from-bottom
   motion instead of the default cross-fade — closer to a "sheet"
   feeling, scoped only to this one type of navigation via the JS
   below. Falls back to the normal cross-fade everywhere this isn't
   supported. */
html:active-view-transition-type(case-study-nav)::view-transition-old(root) { animation: none; opacity: 1 }
html:active-view-transition-type(case-study-nav)::view-transition-new(root) { animation: cardamom-sheet-in .45s var(--ease) both }
@keyframes cardamom-sheet-in { from { transform: translateY(3%); opacity: 0 } to { transform: none; opacity: 1 } }

/* ── Buttons / forms (shared) ── */

.btn { display: inline-block; cursor: pointer; font-family: var(--body); font-size: .68rem; letter-spacing: .2em;
       text-transform: uppercase; font-weight: 500; padding: .9rem 1.7rem; border: 1px solid var(--clay);
       background: var(--clay); color: var(--chalk); transition: background var(--t-fast), color var(--t-fast) }
.btn:hover { background: transparent; color: var(--ink) }
.btn.solid { background: var(--clay); color: var(--chalk); border-color: var(--clay) }
.s-brief .btn:hover { color: var(--chalk); border-color: var(--chalk) }
.btn.solid:hover { background: var(--ink); border-color: var(--ink) }
.field { position: relative; margin-bottom: 1rem }
.field label { display: block; font-size: .58rem; letter-spacing: .22em; text-transform: uppercase; color: var(--clay); margin-bottom: .3rem }
.field input, .field select, .field textarea { width: 100%; background: transparent; border: 0; border-bottom: 1px solid var(--sand);
       color: inherit; font-family: var(--body); font-size: .95rem; padding: .7rem 0 }
.field select option { background: var(--chalk); color: var(--ink) }
.field textarea { resize: vertical; min-height: 60px }
.consent { display: flex; gap: .6rem; align-items: flex-start; font-size: .72rem; line-height: 1.5; margin-bottom: 1rem; color: var(--taupe) }
.consent a { border-bottom: 1px solid currentColor }
.chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .3rem }
.chip { cursor: pointer }
.chip input { position: absolute; opacity: 0; width: 0; height: 0 }
.chip span { display: block; font-size: .62rem; letter-spacing: .1em; text-transform: uppercase;
             border: 1px solid var(--sand); color: var(--taupe); padding: .5rem .8rem; transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast) }
.chip input:checked + span { background: var(--clay); border-color: var(--clay); color: var(--chalk) }

/* Dark-context override — Brief section sits on a dark cover background,
   these same form classes need light-on-dark colors there instead. */
.s-brief .field input, .s-brief .field select, .s-brief .field textarea { border-bottom-color: rgba(252,251,249,.3) }
.s-brief .field select option { background: var(--ink); color: var(--chalk) }
.s-brief .consent { color: rgba(252,251,249,.75) }
.s-brief .chip span { border-color: rgba(252,251,249,.35); color: var(--chalk) }
.form-note { font-size: .66rem; opacity: .6 }
.brief-actions { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 1rem }
.act { display: inline-flex; align-items: center; gap: .5rem; font-size: .68rem; letter-spacing: .18em; text-transform: uppercase;
       font-weight: 500; padding: .8rem 1.4rem; border: 1px solid var(--sand); color: var(--taupe); transition: background var(--t-fast), color var(--t-fast) }
.act:hover { background: var(--clay); color: var(--chalk) }
.s-brief .act, .s-hero .act { border-color: rgba(252,251,249,.4); color: inherit }
.act:hover { background: var(--clay) }


/* ══════════════════════════════
   HOMEPAGE SECTIONS
   ══════════════════════════════ */

/* Hero */
.s-hero { position: relative; min-height: 90vh; display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden; color: var(--chalk);
          background: linear-gradient(180deg,#2C2925 0%,#544E47 34%,#B5614A 72%,#D9D4CC 100%); background-size: cover; background-position: center }
.s-hero-eyebrow-wrap { position: relative; z-index: 2; width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter) }
.s-hero-bg { position: absolute; inset: 0; z-index: 0 }
.s-hero-bg-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity var(--t-slow) ease }
.s-hero-bg-img.is-active { animation: cardamom-kenburns 22s ease-in-out infinite alternate }
@keyframes cardamom-kenburns { from { transform: scale(1) translate(0,0) } to { transform: scale(1.08) translate(-1.5%,-1%) } }
@media (prefers-reduced-motion: reduce) { .s-hero-bg-img.is-active { animation: none } }
.s-hero-bg-img.is-active { opacity: 1 }
.s-hero-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0 }
.s-hero-overlay { position: absolute; inset: 0; background: linear-gradient(180deg,rgba(44,41,37,.6) 0%,rgba(44,41,37,.16) 38%,rgba(44,41,37,.76) 100%) }
.s-hero-in { position: relative; z-index: 2; width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter) clamp(2.5rem,6vh,5rem) }
/* The triad. It was an h1 and is now a p; every rule that styled it
   follows it across, so nothing on screen moves. */
.s-hero .s-hero-triad { font-family: var(--display); font-weight: 300; font-size: clamp(2.5rem,7vw,6rem); line-height: 1.05; margin: 1rem 0 1.2rem; letter-spacing: -.022em }
/* The descriptor is the h1 now, so it has to shed the heading weight
   and the tight tracking that every h1 on the site picks up, and put
   back the small-caps treatment an eyebrow has always had. */
h1.s-hero-descriptor { margin: 0; font-size: 1rem; font-weight: 500; letter-spacing: .22em;
       text-transform: uppercase; color: var(--clay) }
.s-hero-support { max-width: 55ch; font-size: 1rem; line-height: 1.8; margin-bottom: 1.6rem; opacity: .95 }
/* The hero had a button label saved in the settings that nothing
   printed, so the first thing anyone sees had no way out of it. */
.s-hero-cta { margin-top: .4rem; display: flex; align-items: center; gap: clamp(1rem,2vw,1.6rem); flex-wrap: wrap }
/* Quiet second route, for anyone who does not need convincing. */
.s-hero-cta-alt { font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; font-weight: 500;
       color: var(--chalk); border-bottom: 1px solid rgba(252,251,249,.35); padding-bottom: 2px;
       transition: border-color var(--t-fast) }
.s-hero-cta-alt:hover { border-bottom-color: var(--chalk) }
@media (max-width: 700px) { .s-hero-cta-alt { color: var(--clay); border-bottom-color: rgba(181,97,74,.4) } }

.s-scroll-prompt { position: absolute; left: 50%; bottom: 2rem; transform: translateX(-50%); z-index: 2;
       display: flex; flex-direction: column; align-items: center; gap: .4rem; color: var(--chalk); opacity: .8;
       font-size: .6rem; letter-spacing: .18em; text-transform: uppercase; transition: opacity var(--t-fast) }
.s-scroll-prompt:hover { opacity: 1 }
.s-scroll-arrow { font-size: 1rem; animation: cardamom-scroll-bounce 2s ease-in-out infinite }

/* Mobile — eyebrow moves to the very top, image becomes a clean landscape
   photo with no text on top of it, headline/support/CTA sit below in
   normal flow. Desktop is completely unaffected by this block. */
@media (max-width: 700px) {
  .s-hero { display: block; min-height: 0; background: var(--linen) }
  .s-hero-eyebrow-wrap { padding: 1.5rem var(--gutter) 1rem; text-align: center }
  .s-hero .eyebrow { background: none; color: var(--clay); padding: 0 }
  .s-hero-bg, .s-hero-video { position: relative; inset: auto; aspect-ratio: 4/3; width: 100%; z-index: auto }
  .s-hero-overlay { display: none }
  .s-hero-in { position: relative; padding: 1.75rem var(--gutter) 2.5rem; color: var(--ink) }
  .s-hero .s-hero-triad { color: var(--clay) }
  .s-hero-support { opacity: 1; color: var(--taupe) }
  .s-scroll-prompt { display: none }
}
@keyframes cardamom-scroll-bounce { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(6px) } }
@media (prefers-reduced-motion: reduce) { .s-scroll-arrow { animation: none } }

/* Why */
.s-why { padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-why-in { max-width: 900px; margin: 0 auto; text-align: center }
.s-why-body { font-family: var(--display); font-style: italic; font-size: clamp(1.2rem,2.2vw,1.6rem); line-height: 1.6; margin-top: .8rem; color: var(--taupe) }

/* Statement */
.s-statement { max-width: var(--max); margin: 0 auto; padding: clamp(3rem,8vh,5rem) var(--gutter); position: relative }
.s-statement[style*="background-image"] { max-width: 100%; background-color: var(--linen) }
.s-statement[style*="background-image"]::before { content: ''; position: absolute; inset: 0; background: color-mix(in srgb, var(--linen) 30%, transparent) }
.s-statement[style*="background-image"] .s-statement-grid { position: relative; z-index: 1; max-width: var(--max); margin: 0 auto }
.s-statement-grid { display: grid; grid-template-columns: 1fr 2.2fr; gap: clamp(2rem,6vw,5rem) }
.s-meta { position: relative; display: flex; flex-direction: column; justify-content: center; min-height: 240px; padding: 2rem; overflow: hidden }
.s-meta-bg-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity var(--t-slow) ease }
.s-meta-bg-img.is-active { opacity: 1 }
.s-meta-overlay { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(44,41,37,.82) 0%, rgba(44,41,37,.4) 55%, rgba(44,41,37,.05) 100%) }
.s-meta-content { position: relative; z-index: 2; display: flex; flex-direction: column; gap: 1.5rem }
.s-meta span { display: block; font-size: .6rem; letter-spacing: .22em; text-transform: uppercase; color: var(--sage); margin-bottom: .3rem }
.s-meta b { font-family: var(--display); font-size: 1.4rem; font-weight: 400; color: var(--ink) }
.s-meta:has(.s-meta-bg-img) b, .s-meta:has(.s-meta-bg-img) span { color: var(--chalk) }
.s-meta:has(.s-meta-bg-img) span { opacity: .85 }
.s-statement h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.6rem,3vw,2.6rem); line-height: 1.25; margin: .6rem 0 1.2rem }
.s-body { max-width: 60ch; margin-bottom: 1rem; color: var(--taupe); line-height: 1.85 }

/* Who Are You */
.s-who { background: var(--chalk); border-block: 1px solid var(--sand); padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-who-in { max-width: var(--max); margin: 0 auto }
.s-who h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.6rem,3vw,2.4rem); margin: .5rem 0 1.5rem }
.s-who-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 1px; background: var(--sand); border: 0; border-radius: var(--r-md); overflow: hidden }
.s-who-card { background: var(--chalk); padding: clamp(1.3rem,2vw,1.8rem); display: block }
.s-who-card h3 { font-family: var(--display); font-weight: 400; font-size: clamp(1.05rem,1.6vw,1.3rem); margin-bottom: .6rem }
.s-who-card p { font-size: .88rem; line-height: 1.7; color: var(--taupe) }
.s-who-card:hover { background: var(--linen) }
.s-who-cta { display: inline-block; margin-top: .8rem; font-size: .6rem; letter-spacing: .18em; text-transform: uppercase;
             font-weight: 500; color: var(--clay); border-bottom: 1px solid var(--clay); padding-bottom: .2rem }
@media (max-width: 1024px) { .s-who-grid { grid-template-columns: repeat(2,1fr) } }
@media (max-width: 560px) { .s-who-grid { grid-template-columns: 1fr } }

/* Offerings */
.s-offerings { scroll-margin-top: 90px; background: var(--ink); color: var(--chalk); padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-offerings-in { max-width: var(--max); margin: 0 auto }
.s-offerings-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: clamp(1.5rem,3vw,2.5rem); margin-top: 1.5rem }
.s-offering-img { aspect-ratio: 3/2; overflow: hidden; margin-bottom: 1.1rem; background: var(--taupe); border-radius: var(--r-md) }
.s-offering-img img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t-mid) ease }
.s-offering:hover .s-offering-img img { transform: scale(1.05) }
.s-offering-n { font-size: .6rem; color: var(--sage); display: block; margin-bottom: .5rem }
.s-offering h3 { font-family: var(--display); font-weight: 400; font-size: clamp(1.1rem,1.6vw,1.4rem); margin-bottom: .6rem }
.s-offering p { font-size: .88rem; line-height: 1.75; opacity: .85 }
.s-offering-cta { display: inline-block; margin-top: 1rem; font-size: .66rem; letter-spacing: .16em; text-transform: uppercase; color: var(--clay); filter: brightness(1.4); transition: opacity var(--t-fast) }
.s-offering-cta:hover { opacity: .7 }
@media (max-width: 900px) { .s-offerings-grid { grid-template-columns: repeat(2,1fr) } }
@media (max-width: 560px) { .s-offerings-grid { grid-template-columns: 1fr } }

/* Network — one unified atmospheric section, click-through to /network/,
   with Planner Support woven in directly beneath, same section. */
.s-network { padding: clamp(3rem,8vh,5rem) var(--gutter); scroll-margin-top: 90px }
.s-network-in { max-width: var(--max); margin: 0 auto }
.s-network h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.6rem,3vw,2.4rem); margin: .5rem 0 1rem }
.s-network-foot { margin-top: 1.5rem; color: var(--taupe); font-size: .9rem }

.network-atmosphere { position: relative; display: block; width: 100%; aspect-ratio: 21/9; min-height: 640px; overflow: hidden;
       background: var(--ink); margin-top: 2rem; text-decoration: none; cursor: pointer; border-radius: var(--r-md) }
.network-atmosphere-bg { position: absolute; inset: 0 }
.atmos-bg-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 2s ease }
.atmos-bg-img.is-active { opacity: 1; animation: cardamom-kenburns 22s ease-in-out infinite alternate }
@media (prefers-reduced-motion: reduce) { .atmos-bg-img.is-active { animation: none } }
.network-atmosphere-overlay { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(44,41,37,.88) 0%, rgba(44,41,37,.55) 45%, rgba(44,41,37,.35) 100%) }
.network-atmosphere:hover .network-atmosphere-overlay { background: linear-gradient(90deg, rgba(44,41,37,.92) 0%, rgba(44,41,37,.65) 45%, rgba(44,41,37,.4) 100%) }
.network-atmosphere-list { position: relative; z-index: 2; list-style: none; padding: clamp(2rem,5vw,3.5rem);
       display: flex; flex-direction: column; gap: .6rem; max-width: 320px }
.network-atmosphere-list li { font-family: var(--display); font-weight: 300; font-size: clamp(1.2rem,2.4vw,1.7rem);
       color: var(--chalk); opacity: .45; transition: opacity var(--t-mid) ease }
.network-atmosphere:hover .network-atmosphere-list li { opacity: .75 }
.network-atmosphere-words { position: absolute; inset: 0; z-index: 1; pointer-events: none }
.pop-word { position: absolute; font-family: var(--display); font-style: italic; color: var(--chalk); opacity: 0;
       font-size: clamp(1.05rem,1.8vw,1.5rem); text-shadow: 0 2px 12px rgba(0,0,0,.75), 0 1px 3px rgba(0,0,0,.9); transition: opacity var(--t-slow) ease; font-weight: 500 }
.pop-word.is-visible { opacity: .92 }
.network-atmosphere-cta { display: inline-flex; align-items: center; gap: .4rem; font-size: .72rem; letter-spacing: .16em; text-transform: uppercase;
       color: var(--chalk); background: var(--clay); padding: .9rem 1.6rem; transition: background var(--t-fast); margin-top: 1.2rem }
.network-atmosphere-cta:hover { background: var(--taupe) }
@media (max-width: 700px) { .network-atmosphere-cta { display: flex; justify-content: center; width: fit-content; margin-inline: auto } }
@media (max-width: 700px) { .network-atmosphere { aspect-ratio: 4/3; min-height: 480px } .network-atmosphere-list { max-width: 100% } }

.s-planner-band { margin-top: clamp(3rem,7vh,4.5rem); padding-top: clamp(2.5rem,6vh,4rem); border-top: 1px solid var(--sand) }
.s-planner-in { max-width: 720px; margin: 0 auto; text-align: center }
.s-planner-in h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.7rem,3.2vw,2.6rem); margin: .6rem 0 1.2rem }
.s-planner-body { font-size: 1.05rem; color: var(--taupe); line-height: 1.8; margin-bottom: 1.6rem }

/* Story */
.s-story { background: var(--linen); padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-story-head { max-width: var(--max); margin: 0 auto clamp(1.5rem,4vh,2.5rem) }
.s-story-head h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.6rem,3vw,2.4rem); margin: .5rem 0 0 }
.s-story-grid { max-width: var(--max); margin: 0 auto; display: grid; grid-template-columns: 1fr 1.2fr; gap: clamp(2rem,5vw,4rem); align-items: start }
.s-story-media { width: 100%; aspect-ratio: 3/2; min-height: 280px; overflow: hidden; background: var(--sand); border-radius: var(--r-md) }
.s-story-media img, .s-story-media video { width: 100%; height: 100%; object-fit: cover; display: block }
.s-timeline { display: flex; flex-direction: column; gap: 1.3rem; border-left: 2px solid var(--sand); padding-left: 1.3rem }
.s-tl-item b { display: block; font-size: .6rem; letter-spacing: .2em; text-transform: uppercase; color: var(--clay); margin-bottom: .3rem }
.s-tl-item p { color: var(--taupe); line-height: 1.7 }
@media (max-width: 860px) { .s-story-grid { grid-template-columns: 1fr } .s-story-media { min-height: 220px } }

/* Track Record */
.s-track { background: var(--stone); padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-track-in { max-width: var(--max); margin: 0 auto }
.s-track h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.6rem,3vw,2.4rem); margin: .5rem 0 1.5rem }
.s-stats { display: grid; grid-template-columns: repeat(4,1fr); gap: 1px; background: var(--sand); border: 0; border-radius: var(--r-md); overflow: hidden }
.s-stats div { background: var(--chalk); padding: clamp(1.1rem,1.8vw,1.6rem) }
.s-stats b { display: block; font-family: var(--display); font-size: clamp(1.6rem,2.6vw,2.2rem); font-weight: 400 }
.s-stats span { display: block; font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; color: var(--sage); margin-top: .5rem }
@media (max-width: 700px) { .s-stats { grid-template-columns: repeat(2,1fr) } }

/* Trusted By */
.s-trust { padding: clamp(2.5rem,6vh,3.5rem) var(--gutter); text-align: center; border-bottom: 1px solid var(--sand) }
.s-trust-names { font-family: var(--display); font-size: clamp(1.1rem,2vw,1.5rem); color: var(--taupe); margin-top: .8rem }

/* Testimonials */
.s-quotes { background: var(--ink); color: var(--chalk); padding: clamp(3rem,8vh,5rem) var(--gutter); scroll-margin-top: 90px }
.s-quotes-in { max-width: var(--max); margin: 0 auto }
/* This section runs on the dark ground, so the shared section head
   needs its colours flipped or the heading disappears into it. */
.s-quotes .section-head h2 { color: var(--chalk) }
.s-quotes .section-head p  { color: rgba(252,251,249,.75) }
/* The quotes box grows to fit the longest quote.
   It had a fixed aspect-ratio with the slides absolutely positioned
   inside it and overflow hidden, so a quote longer than the box simply
   had its last lines cut off - which is what was happening to the first
   testimonial on a phone, and to any of them on a narrow laptop. The
   slides now stack in one grid cell: they still cross-fade, the box is
   as tall as the tallest of them, and min-height keeps the wide
   cinematic shape when the quotes are short. Height is the same for
   every slide, so moving between them does not make the page jump. */
.quote-atmosphere { position: relative; display: grid; width: 100%; min-height: clamp(320px, 38vw, 560px); overflow: hidden; background: var(--taupe); margin-top: 2rem; border-radius: var(--r-md) }
.quote-slide { grid-area: 1 / 1; position: relative; opacity: 0; pointer-events: none; transition: opacity var(--t-mid) ease }
.quote-slide.is-active { opacity: 1; pointer-events: auto }
.quote-slide-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover }
.quote-slide-overlay { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(44,41,37,.82) 0%, rgba(44,41,37,.4) 55%, rgba(44,41,37,.1) 100%) }
.quote-slide-text { position: relative; z-index: 2; height: 100%; display: flex; flex-direction: column; justify-content: center; padding: clamp(1.5rem,4vw,3rem); max-width: 560px }
.quote-slide-text blockquote { font-family: var(--display); font-style: italic; font-size: clamp(1.05rem,1.8vw,1.3rem); line-height: 1.75; color: var(--chalk); margin-bottom: 1rem }
.quote-slide-text cite { display: block; font-size: .62rem; letter-spacing: .2em; text-transform: uppercase; color: var(--sage); font-style: normal; margin-bottom: .8rem }
.quote-slide-link { font-size: .62rem; letter-spacing: .16em; text-transform: uppercase; color: var(--clay); filter: brightness(1.4) }
@media (max-width: 700px) { .quote-atmosphere { min-height: 300px } }
.s-quotes-scroll::-webkit-scrollbar { height: 6px }
.s-quotes-scroll::-webkit-scrollbar-thumb { background: rgba(252,251,249,.2) }

/* Planning Note */
.s-planning { background: var(--stone); padding: clamp(2.5rem,6vh,3.5rem) var(--gutter); text-align: center }
.s-planning-in { max-width: 800px; margin: 0 auto }
.s-planning p { font-family: var(--display); font-style: italic; font-size: clamp(1.05rem,2vw,1.4rem); line-height: 1.5 }

/* Brief */
.s-brief { background: linear-gradient(180deg,#2C2925 0%,#544E47 55%,#B5614A 120%); color: var(--chalk); padding: clamp(3rem,8vh,5rem) var(--gutter); scroll-margin-top: 90px }
.s-brief-in { max-width: var(--max); margin: 0 auto }
.s-brief-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem,5vw,4rem); align-items: start }
.s-brief h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.8rem,3.5vw,2.8rem); margin: .5rem 0 1rem }
.s-body-light { max-width: 48ch; opacity: .92; line-height: 1.8 }
@media (max-width: 900px) { .s-brief-grid { grid-template-columns: 1fr } }


/* ══════════════════════════════
   SHARED CONTENT PAGES (blog, case studies, legal, 404)
   ══════════════════════════════ */

.pg-head { max-width: var(--max); margin: 0 auto; padding: clamp(3rem,9vh,6rem) var(--gutter) clamp(1.5rem,3vh,2rem);
       text-align: center }

/* Statement / brief containers - referenced in page-planner-support.php
   but never actually defined anywhere in this stylesheet, which is why
   everything sat flush against the browser edge with no padding and
   the form never gridded into columns. */
.statement { max-width: var(--max); margin: 0 auto; padding: clamp(1.5rem,4vh,3rem) var(--gutter) clamp(3rem,7vh,5rem) }
.statement-grid { display: grid; gap: clamp(1.5rem,3vw,3rem) }
.brief { position: relative; background: var(--stone) }
.brief-img { position: absolute; inset: 0; opacity: .92 }
.brief-in { position: relative; max-width: var(--max); margin: 0 auto; padding: clamp(3rem,8vh,5rem) var(--gutter); color: var(--chalk) }
.brief-in .field label { color: var(--clay) }
.brief-in .field input, .brief-in .field select, .brief-in .field textarea { border-bottom-color: rgba(252,251,249,.3) }
.brief-in .field select option { background: var(--ink); color: var(--chalk) }
.brief-in .consent { color: rgba(252,251,249,.75) }
.brief-grid { display: grid; gap: clamp(2rem,5vw,4rem); align-items: start }
@media (max-width: 860px) { .brief-grid { grid-template-columns: 1fr !important } }
.pg-head h1 { font-family: var(--display); font-weight: 300; font-size: clamp(2rem,4.4vw,3.2rem); line-height: 1.15; margin: .8rem 0 .6rem }
.pg-head h1 em { font-style: italic; color: var(--clay) }
.s-statement h2 em, .s-network h2 em, .s-story h2 em, .s-track h2 em { font-style: italic; color: var(--clay) }
.s-brief h2 em { font-style: italic; color: var(--clay); filter: brightness(1.4) }
.pg-head p { max-width: 60ch; margin-inline: auto; color: var(--taupe) }
.pg-subtitle { font-size: 1.05rem; color: var(--taupe); max-width: 58ch; margin: .4rem auto 0 }
.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter) clamp(4rem,10vh,7rem) }
.blog-recent-label { margin: 2rem 0 1rem; color: var(--clay) }
.blog-recent-scroll { display: flex; gap: 1.2rem; overflow-x: auto; padding-bottom: 1.4rem; margin-bottom: 1rem;
       scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch }
.blog-recent-card { flex: none; width: clamp(200px,42vw,260px); scroll-snap-align: start }
.blog-recent-img { aspect-ratio: 3/2; overflow: hidden; background: var(--sand); margin-bottom: .7rem; border-radius: var(--r-md) }
.blog-recent-img img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t-mid) ease }
.blog-recent-card:hover .blog-recent-img img { transform: scale(1.05) }
.blog-recent-card h3 { font-family: var(--display); font-weight: 400; font-size: 1.05rem; color: var(--ink); margin-top: .4rem }
.card-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: clamp(1.4rem,3vw,2.2rem) }
/* No box. The image carries the card and text sits directly on the
   page, matching the tile language rather than sitting in a bordered
   rectangle. */
.card { background: none; border: 0; padding: 0; display: flex; flex-direction: column; gap: .7rem;
       transition: opacity var(--t-fast), transform var(--t-mid) var(--ease) }
.card--hover:hover { transform: translateY(-5px) }
/* Capability entries with no page behind them. No lift, no cursor
   change, no hover colour - nothing that suggests a click. */
.card--static { cursor: default }
.card--static .card-link { cursor: default }
.card-link { display: flex; flex-direction: column; gap: .7rem }
.card-img { position: relative; aspect-ratio: 3/2; overflow: hidden; background: var(--sand); border-radius: var(--r-md) }
.card-img img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t-mid) ease }
.card--hover:hover .card-img img { transform: scale(1.06) }
.card-view { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
       background: rgba(44,41,37,.55); color: var(--chalk); font-size: .68rem; letter-spacing: .16em; text-transform: uppercase;
       opacity: 0; transition: opacity var(--t-fast) }
.card--hover:hover .card-view { opacity: 1 }
.card .tag { font-size: .58rem; letter-spacing: .2em; text-transform: uppercase; color: var(--sage) }
.card-tags { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap }
.tag--practice { color: var(--clay); border: 1px solid var(--clay); padding: .15rem .5rem; border-radius: var(--r-pill) }
.card h3 { font-family: var(--display); font-weight: 400; font-size: clamp(1.15rem,1.6vw,1.4rem); transition: color var(--t-fast) }
.card--hover:hover h3 { color: var(--clay) }
.card.is-hidden { display: none }
.network-section.is-hidden { display: none }
.network-section { margin-bottom: 3.5rem; container-type: inline-size }
.network-section h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.5rem,2.6vw,2.1rem); margin-bottom: 1rem; color: var(--clay) }

/* Filter bar — Work / Blog category filtering, client-side */
/* Work / Blog filter bar — sticky, toggleable, unchanged from before.
   Kept entirely separate from Network's jump pills below (different
   class) specifically so the two can never collide or share CSS
   again the way they accidentally did during the Network rebuild. */
.filter-bar { display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem; margin-bottom: clamp(1.5rem,3vw,2.2rem);
       position: sticky; top: 0; z-index: 40; background: var(--linen); padding: .8rem 0; transition: box-shadow var(--t-fast) }
.filter-bar.is-docked { box-shadow: 0 8px 16px -12px rgba(44,41,37,.25) }
.filter-pill { font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; font-weight: 500;
       border: 1px solid var(--sand); background: transparent; color: var(--taupe); padding: .55rem 1.2rem;
       border-radius: var(--r-pill); cursor: pointer; transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast) }
.filter-pill:hover { border-color: var(--clay) }
.filter-pill.is-active { background: var(--clay); border-color: var(--clay); color: var(--chalk) }
.filter-select { display: none; width: 100%; padding: .8rem 1rem; border: 1px solid var(--sand); background: var(--chalk);
       color: var(--ink); font-family: var(--body); font-size: .85rem; margin-bottom: 1.5rem }
@media (max-width: 700px) {
  .filter-bar { display: none }
  .filter-select { display: block; position: sticky; top: 0; z-index: 40 }
}

/* Network page — plain jump-link pills, genuinely separate from the
   above. No sticky positioning of their own (the terracotta sticky
   bar handles that job for Network), no is-active state to fight
   over. This is what fixed the vibration bug for Network specifically. */
.network-jump-pills { display: flex; flex-wrap: wrap; gap: .6rem; margin: 0 0 2rem }

/* Category page sidebar layout - desktop only. Pills stack left and
   stay in view while the content scrolls independently on the right.
   Mobile is untouched: the pills stay as the original horizontal row
   above the content, same as every other page on the site. */
@media (min-width: 901px) {
  .network-category-layout { display: grid; grid-template-columns: 220px 1fr; gap: clamp(2rem,4vw,3.5rem); align-items: start }
  .network-category-layout .network-jump-pills { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: .5rem; margin: 0;
         position: sticky; top: 190px; max-height: calc(100vh - 220px); overflow-y: auto; padding-right: .5rem }
  .network-category-layout .network-jump-pills .filter-pill { text-align: left }
  .network-category-scroll { min-width: 0 }
  /* Sub-item content scrolls in its own fixed-height box, independent
     of page length - a category with a photo-heavy sub-item and one
     with a single line of text both fit the same space. */
  .network-content-panel { max-height: calc(100vh - 220px); overflow-y: auto; border: 1px solid var(--sand); border-radius: var(--r-md); padding: 0 1.5rem }
}
.network-jump-pills .filter-pill { border: 1px solid var(--sand); background: var(--chalk); color: var(--ink); transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast) }
.network-jump-pills .filter-pill:hover { background: var(--linen); border-color: var(--clay) }
.network-jump-pills .filter-pill.is-current { background: var(--linen); border-color: var(--clay); color: var(--clay); font-weight: 500; pointer-events: none }

.network-category-media--video { position: relative; aspect-ratio: 16/9; overflow: hidden; background: var(--ink) }
.network-category-media--video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0 }

/* Real case studies linked from this category's sub-items - a genuine
   gallery on the category's own page now, not one buried link per item. */
.network-cs-gallery { margin-top: clamp(2rem,5vh,3rem); padding-top: clamp(2rem,5vh,3rem); border-top: 1px solid var(--sand) }
.work-see-all { margin-top: 1.5rem }

/* Parent category's own gallery - moved down here from the old
   top-of-page hero position, so the page opens clean (title,
   subtitle, description, pills) with images available further down
   rather than blocking the top. A real grid now, not a single
   cross-fading slot, since a gallery means seeing several at once. */
.network-parent-gallery { margin-top: clamp(2rem,5vh,3rem); padding-top: clamp(2rem,5vh,3rem); border-top: 1px solid var(--sand) }
.network-parent-gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1rem; margin-top: 1rem }
.network-parent-gallery-grid img { width: 100%; aspect-ratio: 3/2; object-fit: cover; border-radius: var(--r-md); cursor: pointer; transition: opacity var(--t-fast), transform var(--t-mid) var(--ease) }
.network-parent-gallery-grid img:hover { opacity: .85 }

/* Gallery lightbox - click a thumbnail to see it full-size, with
   prev/next between the category's other images. */
.lightbox { position: fixed; inset: 0; z-index: 300; background: rgba(44,41,37,.95); display: flex; align-items: center; justify-content: center }
.lightbox[hidden] { display: none }
.lightbox-img { max-width: 88vw; max-height: 88vh; object-fit: contain }
.lightbox-close { position: absolute; top: 1.5rem; right: 1.5rem; width: 44px; height: 44px; border-radius: 50%;
       background: rgba(252,251,249,.1); border: 1px solid rgba(252,251,249,.3); color: var(--chalk); font-size: 1.6rem;
       line-height: 1; cursor: pointer; transition: background var(--t-fast) }
.lightbox-close:hover { background: var(--clay); border-color: var(--clay) }
.lightbox-prev, .lightbox-next { position: absolute; top: 50%; transform: translateY(-50%); width: 52px; height: 52px; border-radius: 50%;
       background: rgba(252,251,249,.1); border: 1px solid rgba(252,251,249,.3); color: var(--chalk); font-size: 1.8rem;
       cursor: pointer; transition: background var(--t-fast) }
.lightbox-prev:hover, .lightbox-next:hover { background: var(--clay); border-color: var(--clay) }
.lightbox-prev { left: 1.5rem }
.lightbox-next { right: 1.5rem }
@media (max-width: 700px) { .lightbox-prev, .lightbox-next { width: 40px; height: 40px; font-size: 1.4rem } }
.network-parent-gallery .network-category-media--video { margin-top: 1rem; max-width: 720px }
.network-cs-gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1rem; margin-top: 1rem }
.network-cs-card { display: block; padding: 1.4rem 1.6rem; background: var(--chalk); border: 0; border-radius: var(--r-md); box-shadow: var(--shadow-soft);
       font-family: var(--display); font-size: 1.05rem; color: var(--clay); font-weight: 500; transition: border-color var(--t-fast), background var(--t-fast) }
.network-cs-card:hover { border-color: var(--clay); background: var(--linen) }

/* Network overview - light tile grid, each linking out to its own
   dedicated category page. Cross-fade kept per instruction, since this
   is a spaced-out grid, not a dense wall of simultaneous motion. */
/* Asymmetric tile layout. A 12-column grid lets tiles take different
   widths and sit at different vertical offsets, so the eye moves
   diagonally rather than scanning uniform rows. Aspect ratios vary by
   position too - a wide tile shouldn't be the same shape as a narrow
   one. Everything collapses to a single column on mobile, where
   asymmetry stops helping and just wastes space. */
.network-tile-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: clamp(1.5rem,3vw,2.5rem) clamp(1.5rem,3vw,2.5rem);
       grid-auto-flow: row dense; align-items: start;
       padding: clamp(2rem,5vh,3rem) 0 clamp(4rem,9vh,7rem) }

/* The six-tile rhythm that used to live here (7/5 spans, alternating
   1:1, 16:10 and 21:9 crops) was the most magazine-like thing on the
   site. Every tile is now the same width and the same crop. */
.network-tile-grid > .network-tile { grid-column: span 4 }
@media (max-width: 900px) { .network-tile-grid > .network-tile { grid-column: 1 / -1 } }

/* Pull-quote filling the negative space beside the narrow tiles.
   Desktop only - on mobile there's no dead space to fill, and it
   would just add length. */
.network-grid-quote { display: none }

/* Same quote treatment on the individual category pages, where it
   sits full width between the hero and the sub-item list rather than
   inside a grid. */
.network-page-quote { margin: clamp(2.5rem,6vh,4rem) 0; padding: 0; max-width: 22ch }
.network-page-quote p { font-family: var(--display); font-weight: 300; font-style: italic;
       font-size: clamp(1.8rem,3.6vw,3rem); line-height: 1.25; color: var(--clay); margin: 0 }
@media (min-width: 901px) {
  /* Explicitly placed rather than flowed. Sitting in the flow meant
     it consumed a slot and pushed every following tile out of the
     alternating rhythm; pinning it to specific columns lets it fill
     the gap beside the narrow tile while the tiles keep their own
     pattern untouched. */
  .network-grid-quote { display: flex; align-items: center; grid-column: span 5; margin: 0; padding: 0 clamp(1rem,2vw,2rem) }
  .network-grid-quote p { font-family: var(--display); font-weight: 300; font-style: italic;
         font-size: clamp(1.8rem,3.2vw,2.8rem); line-height: 1.3; color: var(--clay); margin: 0 }
}
.network-tile { display: block; text-decoration: none; transition: transform var(--t-mid) var(--ease); margin-bottom: 0 }
.network-tile:hover { transform: translateY(-6px) }
.network-tile-media { position: relative; aspect-ratio: 3/2; overflow: hidden; background: var(--sand); border-radius: var(--r-md) }
/* Slow zoom on the image itself while the tile lifts - two speeds
   moving together reads as considered rather than snappy. */
.network-tile-media .network-hero-img { transition: transform var(--t-fast) var(--ease) }
.network-tile:hover .network-tile-media .network-hero-img { transform: scale(1.04) }
.network-tile-media--empty { position: absolute; inset: 0; background: linear-gradient(135deg, var(--sand) 0%, var(--stone) 100%) }
/* Faded scrim - bottom-up, dark enough for white text to stay
   readable over any photo without needing to know the image content
   in advance. Same legibility problem this project has hit before
   with text-over-image, solved the same proven way. */
.network-tile-scrim { position: absolute; inset: 0; background: linear-gradient(to top, rgba(44,41,37,.85) 0%, rgba(44,41,37,.15) 55%, rgba(44,41,37,0) 100%) }
.network-tile-text { position: absolute; left: 0; right: 3.2rem; bottom: 0; padding: 1.4rem }
.network-tile-text h2 { font-family: var(--display); font-weight: 500; color: var(--chalk); font-size: clamp(1.4rem,2.4vw,1.8rem); margin-bottom: .3rem }
.network-tile-text p { font-size: .88rem; color: rgba(252,251,249,.85); line-height: 1.5 }
.network-tile-arrow { position: absolute; right: 1.2rem; bottom: 1.4rem; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
       border-radius: 50%; background: rgba(252,251,249,.15); border: 1px solid rgba(252,251,249,.4); color: var(--chalk); font-size: 1rem;
       transition: background var(--t-fast), transform var(--t-fast) }
.network-tile:hover .network-tile-arrow { background: var(--clay); border-color: var(--clay); transform: translateX(3px) }
@media (max-width: 900px) { .network-tile-grid { grid-template-columns: repeat(2, 1fr) } }
@media (max-width: 600px) { .network-tile-grid { grid-template-columns: 1fr } }
@media (max-width: 700px) { .network-jump-pills { display: none } } /* mobile uses the sticky bar's hamburger instead */

/* Skeleton loading — a soft pulse while a real photo is still
   downloading, rather than blank space or a jarring pop-in. Applies
   generically wherever a real uploaded image loads, not styled per
   component. */
@keyframes cardamom-shimmer { 0% { background-position: -200% 0 } 100% { background-position: 200% 0 } }
.img-loading {
  background-image: linear-gradient(90deg, var(--sand) 25%, var(--stone) 50%, var(--sand) 75%);
  background-size: 200% 100%;
  animation: cardamom-shimmer 1.6s ease-in-out infinite;
}
.img-loading img { opacity: 0 }
.img-loaded img { opacity: 1; transition: opacity var(--t-mid) ease }
@media (prefers-reduced-motion: reduce) { .img-loading { animation: none } }

/* ═══ Network page — full-width intro ═══ */
.network-hero { max-width: var(--max); margin: 0 auto; padding: clamp(3.5rem,10vh,6rem) var(--gutter) clamp(2rem,5vh,3rem) }
.network-hero h1 { font-family: var(--display); font-weight: 500; color: var(--ink); font-size: clamp(2.4rem,5.5vw,4.2rem); line-height: 1.05; margin: .8rem 0 1.4rem }
.network-hero-body { font-size: clamp(1.1rem,1.8vw,1.4rem); color: var(--taupe); line-height: 1.7; max-width: 62ch }

.network-pillar-nav { max-width: var(--max); margin: 0 auto clamp(2.5rem,6vh,4rem); padding: 0 var(--gutter);
       display: grid; grid-template-columns: repeat(3,1fr); gap: clamp(.8rem,1.5vw,1.2rem) }
/* Borderless, curved, and lifting on hover - matches the tile
   language below rather than sitting as bordered rectangles above it. */
.network-pillar-link { display: block; padding: 1.4rem 1.8rem; border: 0; border-radius: var(--r-md); background: var(--chalk);
       transition: background var(--t-fast), transform var(--t-mid) var(--ease), box-shadow var(--t-mid) }
.network-pillar-link:hover { background: var(--stone); transform: translateY(-3px); box-shadow: 0 10px 30px -12px rgba(44,41,37,.18) }
.network-pillar-label { display: block; font-size: .78rem; color: var(--taupe); margin-bottom: .4rem }
.network-pillar-name { display: block; font-family: var(--display); font-size: 1.15rem; color: var(--clay); font-weight: 500;
       transition: transform var(--t-mid) var(--ease) }
.network-pillar-link:hover .network-pillar-name { transform: translateX(4px) }
@media (max-width: 860px) { .network-pillar-nav { grid-template-columns: 1fr } }

/* Behind the Scenes → How we help pointer. Matches the pillar link
   styling used on the Network overview, with a rule above it so it
   reads as separate from the sub-item list rather than part of it. */
.network-pillar-pointer { display: block; padding: 1.6rem 1.8rem; border: 0; border-radius: var(--r-md); box-shadow: var(--shadow-soft); background: var(--chalk);
       margin-top: clamp(2rem,5vh,3rem); transition: border-color var(--t-fast), background var(--t-fast) }
.network-pillar-pointer:hover { border-color: var(--clay); background: var(--linen) }
.network-pillar-pointer-label { display: block; font-size: .82rem; color: var(--taupe); margin-bottom: .5rem }
.network-pillar-pointer-name { display: block; font-family: var(--display); font-size: clamp(1.05rem,1.8vw,1.25rem); color: var(--clay); font-weight: 500; line-height: 1.5 }

/* ═══ Sticky bar — terracotta, matches the accordion bars, hidden
   until scrolled past the hero. No positioning logic that watches or
   reacts to anything else's size — this is what fixed the vibration. ═══ */
.network-sticky-bar { position: fixed; top: 84px; left: 0; right: 0; z-index: 95; display: flex; align-items: center; gap: 1rem;
       background: var(--chalk); color: var(--ink); padding: 1rem var(--gutter); border-bottom: 1px solid var(--sand);
       opacity: 0; transform: translateY(-100%); transition: opacity var(--t-fast) ease, transform var(--t-fast) ease; pointer-events: none }
.network-sticky-bar.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto }
.network-sticky-current { font-family: var(--display); font-size: clamp(1.4rem,3vw,1.9rem); font-weight: 700 }
/* The Work pages borrow the sticky bar purely to carry the hamburger,
   so it has nothing to show on desktop where the pills are visible. */
/* The Work pages borrow the bar purely to carry the hamburger, so it has
   nothing to show on desktop where the pills are visible.
   Sticky rather than fixed: fixed took the bar out of the flow and it sat
   over the page heading. Sticky reserves its own height, so the clearance
   is always exactly right instead of a hardcoded guess that breaks when
   the label's font size clamps differently. */
/* Centred to sit under the page heading, which is centred. The Network's
   own pills stay left - they live in a column beside the content. */
.network-jump-pills--work { justify-content: center; margin-bottom: 3rem }
.network-sticky-bar--nav { display: none }

/* ═══ The Work category nav ═══════════════════════════════════════
   One row of links, visible at every width, stuck below the header as
   you scroll. It replaced a hamburger that hid these same five links
   behind a bar repeating the heading you were already under. ═══ */
/* Sits at the foot of the page now, so it is a destination rather than
   a bar to get past: no sticking, no border across the content, and a
   heading that says what the row is for. */
.work-nav {
  padding: clamp(3rem, 7vh, 4.5rem) 0 clamp(3.5rem, 8vh, 5rem);
  border-top: 1px solid var(--sand);
  background: var(--linen);
}
.work-nav-head {
  margin: 0 0 1.4rem;
  padding-inline: var(--gutter);
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.3rem, 2.4vw, 1.75rem);
  color: var(--ink);
  text-align: center;
}
.work-nav-rail {
  display: flex; align-items: center; justify-content: center;
  gap: .4rem; padding: 0 var(--gutter);
  overflow-x: auto; scrollbar-width: none;
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
}
.work-nav-rail::-webkit-scrollbar { display: none }
.work-nav-item {
  flex: 0 0 auto; scroll-snap-align: center;
  padding: .5rem 1.05rem; border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: .74rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--taupe); white-space: nowrap; text-decoration: none;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.work-nav-item:hover { color: var(--ink); border-color: var(--sand) }
.work-nav-item.is-current { color: var(--clay); border-color: var(--clay); background: var(--chalk) }
.work-nav-item:focus-visible { outline: 2px solid var(--clay); outline-offset: 2px }

@media (max-width: 760px) {
  /* Left-aligned so the first link starts at the gutter rather than
     floating mid-rail, and padded at the end so the last one can scroll
     clear of the edge. */
  .work-nav-rail { justify-content: flex-start; padding-right: calc(var(--gutter) + 1rem) }
  /* The edges fade instead of chopping a word in half, so a row that
     continues past the screen looks like it continues rather than like
     something has gone wrong. */
  .work-nav-rail {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 1.5rem, #000 calc(100% - 1.5rem), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 1.5rem, #000 calc(100% - 1.5rem), transparent 100%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .work-nav-rail { scroll-behavior: auto }
}
.network-sticky-hamburger { display: none; flex-direction: column; justify-content: center; gap: 4px; width: 24px; height: 24px; background: none; border: 0; cursor: pointer; padding: 0 }
.network-sticky-hamburger span { display: block; width: 100%; height: 2px; background: var(--ink); transition: transform var(--t-fast), opacity var(--t-fast) }
.network-sticky-hamburger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg) }
.network-sticky-hamburger[aria-expanded="true"] span:nth-child(2) { opacity: 0 }
.network-sticky-hamburger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg) }
@media (max-width: 700px) { .network-sticky-hamburger { display: flex } }

.network-jump-menu[hidden] { display: none }
.network-jump-menu:not([hidden]) { position: fixed; top: 155px; left: 0; right: 0; z-index: 94; background: var(--ink); display: flex; flex-direction: column; max-height: calc(100vh - 155px); overflow-y: auto }
.network-jump-item { background: none; border: 0; border-bottom: 1px solid rgba(252,251,249,.12); color: var(--chalk);
       font-family: var(--display); font-size: 1.1rem; text-align: left; padding: 1rem var(--gutter); cursor: pointer }
.network-jump-item:hover { background: rgba(252,251,249,.06) }

/* ═══ Accordion — terracotta bars, one open at a time, closes as you
   scroll into the next one. Used at the sub-item level, inside each
   parent category's section. */
.network-subitem-row { padding: clamp(1.5rem,3vw,2.2rem) 0; border-bottom: 1px solid var(--sand) }

/* Desktop tab bar — built by JS, sits under the parent title as a
   real menu. Mobile is completely untouched: this only ever renders
   on desktop widths, using the exact same underlying markup mobile
   already uses. */
.network-tab-bar { display: none }
@media (min-width: 861px) {
  /* 62px is the height of the header bar once it has shrunk, which is
     the only state it is ever in by the time this bar sticks. It was
     84px, measured off the old bar, and is now off by the difference. */
  .network-tab-bar { display: flex; flex-wrap: wrap; gap: .6rem; max-width: var(--max); margin: 0 auto 2rem; padding: .8rem var(--gutter);
         position: sticky; top: 62px; z-index: 30; background: var(--linen) }
  .network-tab-bar .network-subitem-pill { cursor: pointer; border: 0; background: color-mix(in srgb, var(--clay) 45%, var(--chalk)); transition: background var(--t-fast) }
  .network-tab-bar .network-subitem-pill:hover { background: color-mix(in srgb, var(--clay) 70%, var(--chalk)) }
  .network-tab-bar .network-subitem-pill.is-active { background: var(--clay) }
  /* Inside the category page's content panel specifically, pills
     stack vertically instead of wrapping horizontally - and sticky
     positioning is dropped, since it was tuned for the old
     full-length page's own scroll, not a small internal scroll box. */
  .network-content-panel .network-tab-bar { flex-direction: column; align-items: stretch; position: static; padding: 1.5rem 0 1rem; margin: 0; background: transparent }
  .network-content-panel .network-tab-bar .network-subitem-pill { text-align: left }
  /* Original inline pill (mobile's label) hidden on desktop - the tab
     bar version above is the only one shown, avoiding a duplicate name */
  .network-subitem-row > .network-subitem-pill { display: none }
  .network-subitem-row { border-bottom: 0; padding: 0 }
}

.network-subitem-pill { display: inline-block; background: var(--clay); color: var(--chalk); font-family: var(--display);
       font-weight: 500; font-size: clamp(1rem,1.8vw,1.25rem); padding: .6rem 1.4rem; border-radius: var(--r-pill); margin-bottom: 1.2rem }
.network-subitem-subtitle { font-size: clamp(1.05rem,1.9vw,1.3rem); color: var(--ink); font-weight: 600; line-height: 1.5; margin-bottom: 1rem }

/* Stacked list (category page) - everything always visible, no
   click-to-reveal. Pills restyled as plain terracotta titles since
   they're not interactive here - a filled pill shape implies
   "clickable", which would be misleading. */
/* Sub-items on a category page. Previously a plain vertical stack -
   every item the same width, one after another. Now a 12-column grid
   with alternating widths so the page has real rhythm rather than
   reading as a list. Collapses to single column on mobile. */
.network-subitem-list--stacked { display: grid; grid-template-columns: repeat(12, 1fr); gap: clamp(2rem,4vw,3.5rem) clamp(1.5rem,3vw,2.5rem); align-items: start }
.network-subitem-list--stacked .network-subitem-row { margin-bottom: 0; grid-column: 1 / -1 }
.network-subitem-list--stacked .network-subitem-content { display: block }
.network-subitem-list--stacked .network-subitem-pill { display: block; background: none; color: var(--clay);
       font-size: clamp(1.2rem,2.2vw,1.5rem); font-weight: 500; padding: 0; border-radius: 0; margin-bottom: .8rem }

@media (min-width: 861px) {
  .network-subitem-list--stacked .network-subitem-pill { display: block }
  /* Alternating rhythm: wide, narrow, narrow, wide. Items with a
     photo get more room; text-only ones sit narrower. */
  .network-subitem-list--stacked > .network-subitem-row:nth-of-type(4n+1) { grid-column: span 7 }
  .network-subitem-list--stacked > .network-subitem-row:nth-of-type(4n+2) { grid-column: span 5 }
  .network-subitem-list--stacked > .network-subitem-row:nth-of-type(4n+3) { grid-column: span 5 }
  .network-subitem-list--stacked > .network-subitem-row:nth-of-type(4n+4) { grid-column: span 7 }
  /* Media items get a taller frame when narrow, wider when wide. */
  .network-subitem-list--stacked > .network-subitem-row--media:nth-of-type(4n+2) .network-subitem-content,
  .network-subitem-list--stacked > .network-subitem-row--media:nth-of-type(4n+3) .network-subitem-content { min-height: 340px }
  /* A final item with nothing to pair with stretches full width
     rather than leaving an obvious gap beside it. */
  .network-subitem-list--stacked > .network-subitem-row:last-of-type:nth-of-type(odd) { grid-column: 1 / -1 }
}
@media (max-width: 860px) {
  .network-subitem-list--stacked > .network-subitem-row { grid-column: 1 / -1 }
}
.network-accordion-desc { font-size: clamp(1rem,1.6vw,1.2rem); color: var(--taupe); line-height: 1.7; max-width: 62ch }

/* Text-only items (no photo yet) — a deliberately different, larger
   treatment instead of a half-width column with an empty gap next to
   it. Meant to look like an intentional choice, not a missing image. */
.network-subitem-row--textonly .network-subitem-content { display: block }
.network-subitem-row--textonly .network-accordion-desc { font-size: clamp(1.3rem,2.4vw,1.8rem); max-width: 52ch; color: var(--ink); font-family: var(--display); font-weight: 400; font-style: italic; line-height: 1.55;
       border-left: 3px solid var(--clay); padding: .3rem 0 .3rem 1.8rem }

/* Sub-item with its own image - text overlaid on it, same scrim
   pattern as the parent header, not a separate block below the text.
   flex + flex-end anchors text to the bottom, where the scrim is
   darkest - matches the parent header exactly, fixes text sitting on
   the lighter top of the scrim where it read as "cut off". */
.network-subitem-row--media .network-subitem-content { display: flex; align-items: flex-end; position: relative; overflow: hidden; border-radius: var(--r-md);
       min-height: 280px; padding: 2rem 2.2rem }
.network-subitem-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover }
.network-subitem-scrim { position: absolute; inset: 0; background: linear-gradient(to top, rgba(44,41,37,.92) 15%, rgba(44,41,37,.5) 55%, rgba(44,41,37,.05) 100%) }
.network-subitem-row--media .network-subitem-text { position: relative; z-index: 2 }
.network-subitem-row--media .network-subitem-subtitle { color: var(--chalk) }
.network-subitem-row--media .network-accordion-desc { color: rgba(252,251,249,.9); font-family: var(--display); font-style: italic; font-size: clamp(1.2rem,2.2vw,1.6rem); line-height: 1.55 }
.network-subitem-row--media .network-gallery-link { color: var(--chalk); text-decoration: underline }

/* Gallery — one sub-item's own photos (cycles automatically if it has
   more than one). Genuinely one image block now, not a row of several
   different sub-items — so no horizontal scroll here at any width. */
.network-subitem-content { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem,3vw,3rem); align-items: center;
       padding: clamp(1.5rem,3vw,2rem) clamp(1.2rem,3vw,2rem) clamp(2rem,4vw,3rem) }
.network-subitem-text { min-width: 0 }
.network-gallery-img { aspect-ratio: 3/2; overflow: hidden; background: var(--sand); position: relative; border-radius: var(--r-md) }
.network-gallery-img--empty { background: linear-gradient(135deg, var(--sand) 0%, var(--stone) 100%) }
.network-gallery-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity var(--t-fast) ease }
.network-gallery-photo.is-active { opacity: 1 }
.network-gallery-link { display: inline-block; margin-top: 1rem; font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; color: var(--clay); font-weight: 500 }
.network-gallery-link:hover { text-decoration: underline }
@media (max-width: 800px) {
  .network-subitem-content { grid-template-columns: 1fr }
  .network-gallery-img { order: -1 } /* image first on mobile, text follows - reads better stacked */
}

/* ═══ Parent category — a real section: title, body, and its own
   visual. Not an accordion itself; its sub-items below are what
   accordion. No text ever sits on top of the image — heading and
   body are on the plain page background, image is clean underneath. ═══ */
.network-category-section { padding-top: clamp(3rem,7vh,5rem); scroll-margin-top: 130px }
.network-category-section:first-of-type { padding-top: 0 }
.network-category-head { margin-bottom: 2rem; max-width: var(--max); margin-left: auto; margin-right: auto; padding: 0 var(--gutter) }
.network-category-head h2 { font-family: var(--display); font-weight: 500; color: var(--clay); font-size: clamp(2.4rem,5vw,3.6rem);
       margin-bottom: 1rem; padding-bottom: 1rem; border-bottom: 3px solid var(--clay); display: inline-block }

/* Parent header with a faded, cross-fading photo or video behind the
   title/subtitle/description. A real reversal of the earlier "clean,
   image-free top" decision, made deliberately after reviewing a
   preview - not an oversight. */
.network-category-head--media { position: relative; overflow: hidden; min-height: 420px; display: flex; align-items: flex-end; justify-content: center;
       padding: clamp(2rem,4vw,3.2rem) clamp(1.5rem,4vw,3rem); margin-bottom: 2rem; border-radius: var(--r-lg) }
.network-category-head-bg { position: absolute; inset: 0 }
.network-category-head-bg img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity var(--t-fast) ease }
.network-category-head-bg img.is-active { opacity: 1 }
.network-category-head-bg--video { background: var(--ink) }
.network-category-head-bg--video iframe { position: absolute; top: 50%; left: 50%; width: 100%; height: 100%; min-width: 177.78vh; min-height: 56.25vw;
       transform: translate(-50%,-50%); pointer-events: none; border: 0 }
.network-category-head-scrim { position: absolute; inset: 0; background: linear-gradient(to top, rgba(44,41,37,.94) 15%, rgba(44,41,37,.55) 55%, rgba(44,41,37,.1) 100%) }
/* Centred, to match the page headings everywhere else. */
.network-category-head-content { position: relative; z-index: 2; max-width: 62ch;
       margin-inline: auto; text-align: center }
.network-category-head-content h1, .network-category-head-content h2, .network-category-head-content h3 { font-family: var(--display); font-weight: 400; font-size: clamp(1.9rem,3.6vw,2.8rem); margin-bottom: .8rem }

/* Work overview redesign - heroes only, each a real link to its full
   category page. Text scales down from the single-category page's
   version since these are compact, stacked entry points, not a
   destination in themselves. */
/* The two Work sections - "what we've done" and "what we do". */
/* Each category on the Work page: one hero, then two links splitting
   client work from capability pieces. Sits under the parent category
   rather than splitting the whole page in two. */
/* Two stacked sections on a category page, each a horizontal rail.
   Uses native scroll-snap rather than JS - works with touch swipe,
   trackpad, and keyboard out of the box, and degrades to a plain
   scrollable row if anything fails. */
.work-section { margin-bottom: clamp(3rem,7vh,5rem) }
.work-section + .work-section { margin-top: clamp(3rem,8vh,6rem) }
/* Section heads have to stay clearly above the entry titles below
   them - the stacked layout gives each entry a much larger heading
   than the old cards did. */
/* Section heads use the shared .section-head defined further down. */

/* ═══ The work, as cards ═════════════════════════════════════════════
   Each entry used to be a full-width band - picture one side, words the
   other - stacked down the page with a large gap between them. One
   entry filled a screen, so two pieces of work were never visible at
   once and the page read as a long scroll rather than a body of work.

   A card grid shows four or six together, which is the point: the
   quantity is part of what is being said.
   ═══════════════════════════════════════════════════════════════════ */
.work-stories {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(290px, 100%), 1fr));
  gap: clamp(1.6rem, 3vw, 2.4rem) clamp(1.4rem, 2.4vw, 2rem);
  align-items: start;
}
/* Four columns under one case study left three empty cells beside it.
   The track count follows the card count up to four, so a short run
   fills its row instead of sitting against a block of paper - and the
   cards grow a little rather than stretching to half a screen, which is
   the shape this replaced. */
/* A lone card is centred. Left-aligned it put the whole of its row's
   empty half against the right edge, which is the blank space this
   whole change is about; centred, what is left over is symmetrical and
   reads as a decision. */
.work-stories.is-1 { grid-template-columns: minmax(0, 620px); justify-content: center }
.work-stories.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) }
.work-stories.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) }
.work-stories.is-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) }
/* One card is a card, not a billboard: the picture keeps a sane size
   and the words keep their measure. */
.work-stories.is-1 .work-story-body h3 { font-size: clamp(1.5rem, 2.6vw, 2rem) }
.work-stories.is-1 .work-story-sub,
.work-stories.is-2 .work-story-sub { font-size: 1rem }

.work-story {
  display: flex;
  flex-direction: column;
  gap: .85rem;
}
/* The hidden attribute loses to any rule that sets display, and the
   line above sets display. Without this the filter marked seven cards
   hidden and all seven stayed on the screen - correct in the DOM,
   wrong on the page, and silent either way. */
.work-story[hidden] { display: none }

.work-story-media {
  overflow: hidden;
  border-radius: var(--r-md);
  background: var(--stone);
}
.work-story-media img {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover;
  display: block;
  transition: transform var(--t-slow) var(--ease);
}
.work-story-media a { display: block }
.work-story:hover .work-story-media img { transform: scale(1.04) }

.work-story-body { display: flex; flex-direction: column; align-items: flex-start; gap: .5rem }
.work-story-body h3 {
  font-family: var(--display); font-weight: 400; color: var(--ink);
  /* Smaller than the old band headline: a card is a quarter of the
     width, and the display size that worked across half a screen
     wrapped to four lines here. */
  font-size: clamp(1.25rem, 1.9vw, 1.55rem); line-height: 1.2;
}
.work-story-body h3 a { transition: color var(--t-fast) }
.work-story-body h3 a:hover { color: var(--clay) }
.work-story-sub { color: var(--taupe); font-size: .92rem; line-height: 1.6 }
/* Category entries carry a description under the subtitle; case study
   entries only have the subtitle, so this simply never renders there. */
.work-story-desc { color: var(--taupe); font-size: .88rem; line-height: 1.6 }
.work-story-link {
  font-size: .72rem; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 500; color: var(--clay); margin-top: .35rem;
  border-bottom: 1px solid transparent; transition: border-color var(--t-fast);
}
.work-story-link:hover { border-bottom-color: var(--clay) }

/* Capability entries often have no image. As cards they would be a row
   of short paragraphs floating in space, so they get a surface to sit
   on and keep their place in the same grid. */
.work-story--textonly {
  padding: clamp(1.2rem, 2.4vw, 1.6rem);
  border: 1px solid var(--sand);
  border-radius: var(--r-md);
  background: var(--chalk);
}
.work-story--textonly .work-story-body h3 { font-size: clamp(1.15rem, 1.7vw, 1.4rem) }

@media (max-width: 980px) {
  .work-stories.is-3,
  .work-stories.is-4 { grid-template-columns: repeat(2, minmax(0, 1fr)) }
}
@media (max-width: 620px) {
  /* One per row rather than two cramped ones: below this the pictures
     stop being large enough to be worth showing. */
  .work-stories,
  .work-stories.is-1,
  .work-stories.is-2,
  .work-stories.is-3,
  .work-stories.is-4 { grid-template-columns: 1fr; gap: 2rem }
}

.work-split-link--single { grid-column: 1 / -1 }
.work-category { margin-bottom: clamp(3rem,7vh,5rem) }
.work-split-links { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: clamp(.8rem,1.5vw,1.2rem); margin-top: 1.2rem }
.work-split-link { display: block; padding: 1.3rem 1.6rem; background: var(--chalk); border-radius: var(--r-md);
       box-shadow: var(--shadow-soft); text-decoration: none;
       transition: transform var(--t-mid) var(--ease), box-shadow var(--t-mid), background var(--t-fast) }
.work-split-link:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); background: var(--stone) }
.work-split-label { display: block; font-size: .78rem; color: var(--taupe); margin-bottom: .35rem }
.work-split-count { display: block; font-family: var(--display); font-size: 1.15rem; color: var(--clay); font-weight: 500 }
.work-filter-note { margin-top: 1.2rem; font-size: .85rem }
.work-filter-note a { color: var(--clay); border-bottom: 1px solid currentColor; padding-bottom: .1rem }
.work-hero-link { display: block; text-decoration: none; color: inherit; margin-bottom: 1.5rem }
.work-overview-hero { min-height: 220px !important; transition: transform var(--t-fast) var(--ease) }
.work-hero-link:hover .work-overview-hero { transform: translateY(-3px) }
.work-overview-hero .network-category-head-content h2,
.work-overview-hero .network-category-head-content h3 { font-size: clamp(1.8rem,3.4vw,2.4rem) }
.work-overview-hero-content { display: flex; justify-content: space-between; align-items: flex-end; gap: 2rem; flex-wrap: wrap; width: 100%; max-width: none }
.work-hero-cta { font-size: .78rem; letter-spacing: .06em; white-space: nowrap; border-bottom: 1px solid currentColor; padding-bottom: .2rem; flex: none }
.network-category-head--media .work-hero-cta { color: var(--chalk) }
.network-category-head:not(.network-category-head--media) .work-hero-cta { color: var(--clay) }
@media (max-width: 700px) { .work-overview-hero-content { align-items: flex-start } }
.network-category-head--media .network-category-head-content h2,
.network-category-head--media .network-category-head-content h3 { color: var(--chalk); border-bottom: 0; padding-bottom: 0; display: block }
.network-category-head:not(.network-category-head--media) .network-category-head-content h2,
.network-category-head:not(.network-category-head--media) .network-category-head-content h3 { color: var(--clay) }
.network-category-head--media .network-category-head-content h1 { color: var(--chalk) }
.network-category-head:not(.network-category-head--media) .network-category-head-content h1 { color: var(--clay) }
.network-category-head--media .network-category-subtitle { color: var(--chalk); font-weight: 500 }
.network-category-head--media .network-category-desc { color: rgba(252,251,249,.85) }
.network-category-subtitle { font-size: clamp(1.1rem,2vw,1.4rem); color: var(--ink); font-weight: 600; line-height: 1.5; max-width: 62ch; margin-bottom: .8rem }
.network-category-desc { font-size: clamp(1rem,1.6vw,1.15rem); color: var(--taupe); line-height: 1.75; max-width: 62ch }
/* Breaks out of .wrap's narrower max-width - genuinely full viewport
   width, not constrained to the site's normal content column. Standard
   full-bleed technique, no HTML restructuring needed. */
.network-category-media { position: relative; width: 100vw; margin-left: calc(50% - 50vw); aspect-ratio: 21/9; overflow: hidden; background: var(--sand); margin-top: 1.5rem; margin-bottom: 2rem }

/* Within the category page's sidebar layout, the hero no longer sits
   in a full-width section - it's inside the narrower right-hand
   column now, so the old full-viewport breakout has to be cancelled
   here specifically, without touching the Work page's own still-
   correct full-width version of this same class. */
.network-category-scroll .network-category-media { width: 100%; margin-left: 0 }
.network-hero-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity var(--t-slow) ease }
.network-hero-img.is-active { opacity: 1 }
@media (max-width: 700px) { .network-category-media { aspect-ratio: 4/3 } }

.psp-intro { font-size: clamp(1rem,1.7vw,1.15rem); color: var(--taupe); line-height: 1.8; max-width: 66ch; margin-bottom: 1.2rem }

/* Three-step process. Numbers sit in circles to the left of each
   step, so the sequence reads at a glance. */
/* The steps, set as an index — same device as the four offerings on the
   home page, so a sequence looks like a sequence wherever it appears.
   The numbers lost their filled circles: a ruled row already says
   "one of several in order", and the discs were doing that job twice. */
.psp-steps {
  list-style: none; padding: 0;
  margin: 1.8rem 0 0; max-width: 62ch;
  border-bottom: 1px solid var(--sand);
}
.psp-steps li {
  display: grid;
  grid-template-columns: 2.8rem minmax(0, 1fr);
  gap: 0 clamp(.9rem, 2vw, 1.4rem);
  align-items: baseline;
  padding: clamp(1.1rem, 2.6vh, 1.7rem) 0;
  border-top: 1px solid var(--sand);
}
.psp-step-n {
  font-family: var(--body);
  font-size: .78rem;
  letter-spacing: .14em;
  color: var(--clay);
}
.psp-steps h3 {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(1.3rem, 2.4vw, 1.75rem);
  line-height: 1.15; color: var(--ink);
  margin: 0 0 .45rem;
}
.psp-steps p { font-size: .97rem; color: var(--taupe); line-height: 1.7; margin: 0 }
.psp-cta { margin-top: clamp(2rem,4vh,3rem); text-align: center }




/* Contact: WhatsApp as a first option, not a footnote. It is how most
   of this business is actually done, and it was the last link on the
   page, below the form and below the phone number. */
.contact-choice { max-width: 640px; margin: clamp(2rem,5vh,3rem) auto 0; text-align: center }
.contact-choice-wa { display: inline-flex; align-items: center; gap: .6rem }
.contact-choice-icon { display: inline-flex; line-height: 0 }
.contact-choice-note { margin-top: .7rem; font-size: .85rem; color: var(--taupe) }
/* A rule with the words sitting in the gap, so the form reads as the
   alternative rather than the only way through. */
.contact-choice-or { position: relative; margin-top: clamp(1.8rem,4vh,2.5rem) }
.contact-choice-or::before { content: ''; position: absolute; top: 50%; left: 0; right: 0;
       height: 1px; background: var(--sand) }
.contact-choice-or span { position: relative; background: var(--linen); padding: 0 1rem;
       font-size: .62rem; letter-spacing: .2em; text-transform: uppercase; color: var(--taupe) }
.contact-choice + .contact-form-wrap { margin-top: clamp(1.5rem,3vh,2rem) }

/* Honeypot. Positioned off-screen rather than display:none, which
   some bots check for and skip; real people never see or tab to it. */
.cardamom-hp { position: absolute !important; left: -9999px !important;
       width: 1px; height: 1px; overflow: hidden }

/* Office hours: footer column and the contact page's Direct block. */
.f-hours-label { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--sand);
       font-size: .62rem; letter-spacing: .2em; text-transform: uppercase; color: var(--clay) }
.f-hours { list-style: none; margin-top: .4rem }
.f-hours li { font-size: .82rem; color: var(--taupe); line-height: 1.8 }
.f-hours-note { color: var(--clay) }
.contact-hours { margin-top: 1.5rem; padding-top: 1.2rem; border-top: 1px solid var(--sand) }
.contact-hours h3 { font-family: var(--display); font-weight: 400; font-size: 1.1rem; color: var(--ink) }
.contact-hours-for { font-size: .62rem; letter-spacing: .2em; text-transform: uppercase;
       color: var(--clay); margin-bottom: .5rem }
.contact-hours p { color: var(--taupe); line-height: 1.8 }
.contact-hours-note { color: var(--clay) }

/* Contact page: the form and the direct details now follow the three
   steps directly, with the wizard gone from between them. */
.contact-form-wrap { max-width: 640px; margin: clamp(2rem,5vh,3rem) auto 0 }
.contact-details { max-width: 640px; margin: clamp(2.5rem,6vh,3.5rem) auto 0;
       padding-top: clamp(1.5rem,4vh,2.5rem); border-top: 1px solid var(--sand) }

/* Same three steps on the contact page, above the form.
   Matched to the form's width so the two read as one flow. */
.contact-steps { max-width: 640px; margin: clamp(1.5rem,4vh,2.5rem) auto clamp(2rem,5vh,3rem) }
/* Service boxes: a card per service, presentation only. */
.psp-boxes { display: grid; gap: clamp(.7rem,1.4vw,1rem); margin: 1.2rem 0 2.5rem;
       grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)) }
.psp-box { display: flex; align-items: center; gap: 1rem;
       padding: 1rem clamp(1rem,2vw,1.3rem); background: var(--chalk);
       border: 1px solid var(--sand); border-radius: var(--r-md) }

.psp-box-img { flex: none; width: 48px; height: 48px; overflow: hidden; border-radius: var(--r-sm); background: var(--stone) }
.psp-box-img img { width: 100%; height: 100%; object-fit: cover }
.psp-box-body { flex: 1 }
.psp-box-name { display: block; font-weight: 500; color: var(--ink) }
.psp-box-desc { display: block; font-size: .85rem; color: var(--taupe); margin-top: .2rem; line-height: 1.55 }

.psp-group-label { margin-top: 2rem; text-align: center }
.psp-how .psp-steps { margin-inline: auto }
.psp-intro-wrap { text-align: center }
.psp-intro-wrap .psp-intro { margin-inline: auto }

.card p { font-size: .9rem; line-height: 1.75; color: var(--taupe) }
.card-subtitle { font-size: 1.05rem; font-style: italic; color: var(--sage); margin-top: -.4rem }
.card blockquote { font-family: var(--display); font-style: italic }
.card cite { font-style: normal; font-size: .65rem; letter-spacing: .12em; text-transform: uppercase; color: var(--clay) }
/* Centred, so it sits under the centred page heading rather than
   hugging the left gutter beneath it. */
.entry-body { max-width: var(--measure); margin-inline: auto }
.entry-body p { margin-bottom: 1rem; line-height: 1.85; color: var(--taupe) }
.entry-body h2 { font-family: var(--display); font-weight: 400; font-size: 1.4rem; margin: 2rem 0 .8rem }
.entry-hero { aspect-ratio: 3/2; overflow: hidden; border-radius: var(--r-md); margin-bottom: 2rem; background: var(--sand) }
.entry-hero img { width: 100%; height: 100%; object-fit: cover }
.pullquote { font-family: var(--display); font-style: italic; font-size: 1.3rem; margin: 2rem 0; padding-left: 1.5rem; border-left: 2px solid var(--clay) }
.pullquote-cite { display: block; font-size: .7rem; letter-spacing: .12em; text-transform: uppercase; color: var(--clay); margin-bottom: 1.5rem }
.cs-facts { display: flex; flex-wrap: wrap; gap: 2rem; padding: 1.5rem 0; margin: 1.5rem 0 2rem; border-top: 1px solid var(--sand); border-bottom: 1px solid var(--sand) }
.cs-fact { display: flex; flex-direction: column; gap: .3rem }
.cs-fact-label { font-size: .62rem; letter-spacing: .18em; text-transform: uppercase; color: var(--clay); font-weight: 500 }
.cs-fact-value { font-size: 1rem; color: var(--ink) }
.cs-partner-link { color: var(--clay); border-bottom: 1px solid transparent; transition: border-color var(--t-fast) }
.cs-partner-link:hover { border-bottom-color: currentColor }
.cs-body-label { font-family: var(--display); font-weight: 400; font-size: 1.4rem; color: var(--ink); margin-bottom: 1rem }
/* Repeating image + text sections between the main content and the
   final gallery - one image, one block of text, repeated in order. */
.cs-section { margin: 2.5rem 0 }
.cs-section-img { width: 100%; aspect-ratio: 3/2; object-fit: cover; border-radius: var(--r-md); margin-bottom: 1.2rem }
.cs-section-text { color: var(--taupe); line-height: 1.85; max-width: 62ch }
.cs-services { background: var(--stone); border-left: 2px solid var(--clay); padding: 1.5rem 1.8rem; margin-top: 2.5rem }
.cs-services-label { font-size: .62rem; letter-spacing: .18em; text-transform: uppercase; color: var(--clay); font-weight: 500; margin-bottom: .8rem }
.cs-services-list { list-style: none; display: flex; flex-wrap: wrap; gap: .6rem }
.cs-services-list li { font-size: .88rem; color: var(--chalk); background: var(--clay); border: 1px solid var(--clay); padding: .4rem .8rem }
.breadcrumbs { max-width: var(--max); margin: 0 auto; padding: 1rem var(--gutter) 0; font-size: .7rem; color: var(--sage) }
.breadcrumbs a { color: var(--taupe) }
.breadcrumbs span { margin: 0 .35rem }


/* ── Content Portal ── */
.portal-login { max-width: 380px }
.portal-error { color: var(--clay); font-size: .85rem; margin-bottom: 1rem }
.portal-welcome { font-size: .9rem; color: var(--taupe); margin-bottom: .3rem }
.portal-welcome a { color: var(--clay) }
.portal-note { font-size: .82rem; color: var(--sage); margin-bottom: 2rem }
.portal-form { max-width: 560px }
.portal-form select { width: 100%; background: transparent; border: 0; border-bottom: 1px solid var(--sand);
       color: var(--ink); font-family: var(--body); font-size: .95rem; padding: .7rem 0 }
#pStatus { color: var(--clay); margin-top: .8rem }

/* ── About timeline strip ── */
/* ── About: What you come to Cardamom for ── */
.wycf-section { margin-top: 3.5rem; padding-top: 2.5rem; border-top: 1px solid var(--sand) }
.wycf-grid { display: grid; grid-template-columns: repeat(2,1fr); gap: 2rem; margin-top: 1.2rem }
.wycf-item h3 { font-family: var(--display); font-weight: 400; font-size: 1.3rem; margin-bottom: .4rem }
.wycf-subtitle { font-size: 1.05rem; font-style: italic; color: var(--sage); margin-bottom: .5rem }
.wycf-item p:not(.wycf-subtitle) { color: var(--taupe); line-height: 1.8 }
@media (max-width: 700px) { .wycf-grid { grid-template-columns: 1fr } }

/* ── About timeline — vertical, alternating sides, connecting line ── */
.about-timeline { position: relative; margin-top: 3rem; padding-left: 0 }
.about-timeline::before { content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 1px;
       background: var(--sand); transform: translateX(-50%) }
.atl-item { position: relative; display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center;
       margin-bottom: 4rem }
.atl-item:nth-child(even) .atl-media { order: 2 }
.atl-item:nth-child(even) .atl-caption { order: 1; text-align: right }
.atl-item::before { content: ''; position: absolute; left: 50%; top: 50%; width: 10px; height: 10px;
       background: var(--clay); border-radius: 50%; transform: translate(-50%,-50%); z-index: 1 }
.atl-media img { width: 100%; aspect-ratio: 3/2; object-fit: cover; background: var(--sand) }
.atl-caption { padding: 0 2rem }
.atl-title { font-family: var(--display); font-weight: 400; font-size: 1.4rem; color: var(--ink); margin-bottom: .3rem }
.atl-subtitle { font-size: 1.05rem; font-style: italic; color: var(--clay); margin-bottom: .6rem }
.atl-body { font-size: .92rem; color: var(--taupe); line-height: 1.75 }
@media (max-width: 780px) {
  .about-timeline::before { left: 20px }
  .atl-item, .atl-item:nth-child(even) { grid-template-columns: 1fr; gap: 1rem; padding-left: 3rem }
  .atl-item .atl-media, .atl-item:nth-child(even) .atl-media { order: 1 }
  .atl-item .atl-caption, .atl-item:nth-child(even) .atl-caption { order: 2; text-align: left; padding: 0 }
  .atl-item::before { left: 20px }
}

/* ── Scroll reveal — generic, reusable sitewide ──────────────────────
   Visible is the default state. Everything below only ever hides
   something inside .js-reveal, a class the page puts on <html> before
   the first paint and takes off again if the script that does the
   revealing never started. Written the other way round - hidden by
   default, script to undo it - any failure in that script empties the
   site: full-height pages with nothing drawn in them and no error to
   explain it. An animation is worth having; it is not worth the
   content. ── */
.reveal { opacity: 1; transform: none }

.js-reveal .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
}
.js-reveal .reveal.is-visible { opacity: 1; transform: none }

/* Scroll-driven reveal — native CSS, browser-driven directly off scroll
   position instead of a JS IntersectionObserver. Where the browser
   supports it, this takes over entirely and can't stutter on a busy
   page. Where it doesn't, the JS .is-visible system above still runs
   exactly as before — this is pure enhancement, not a replacement
   that needs a fallback path written separately. */
@supports (animation-timeline: view()) {
  @keyframes cardamom-reveal { from { opacity: 0; transform: translateY(24px) } to { opacity: 1; transform: none } }
  .js-reveal .reveal {
    animation: cardamom-reveal linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 30%;
    transition: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  @supports (animation-timeline: view()) { .js-reveal .reveal { animation: none; opacity: 1; transform: none } }
}

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

/* ── Brief Builder — collapsible sections with ticket-style items ── */
.brief-builder { border-top: 1px solid var(--sand) }
.bb-section { border-bottom: 1px solid var(--sand) }
.bb-toggle { width: 100%; display: flex; align-items: center; justify-content: space-between; text-align: left;
       background: none; border: 0; padding: 1.2rem 0; cursor: pointer; font: inherit }
.bb-toggle h3 { font-family: var(--display); font-weight: 400; font-size: 1.15rem; color: var(--ink) }
.bb-arrow { font-size: 1.3rem; color: var(--clay); transition: transform var(--t-fast) }
.bb-toggle[aria-expanded="true"] .bb-arrow { transform: rotate(90deg) }
.bb-tickets { display: flex; flex-wrap: wrap; gap: .6rem; padding: 0 0 1.4rem }
.ticket { position: relative; cursor: pointer }
.ticket input { position: absolute; opacity: 0; width: 0; height: 0 }
.ticket span { display: block; font-size: .82rem; border: 1px solid var(--sand); border-radius: var(--r-sm); padding: .55rem 1rem;
       color: var(--taupe); transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast) }
.ticket span::before { content: '+'; display: inline-block; margin-right: .4rem; color: var(--clay); font-weight: 500 }
.ticket input:checked + span { background: var(--clay); border-color: var(--clay); color: var(--chalk) }
.ticket input:checked + span::before { content: '✓' }
.bb-summary { font-size: .88rem; color: var(--taupe); margin-top: 1.2rem; padding: .8rem 1rem; background: var(--stone) }
.bb-summary span { color: var(--clay); font-weight: 500 }
/* Native Gallery block on the 6 gallery pages — no theme.json exists
   for automatic block-editor styling, so this fills the gap. */
.network-gallery-page .wp-block-gallery { display: grid; grid-template-columns: repeat(3,1fr); gap: 1rem; margin: 2rem 0; list-style: none }
.network-gallery-page .wp-block-gallery figure { margin: 0 }
.network-gallery-page .wp-block-gallery img { width: 100%; height: auto; display: block; aspect-ratio: 3/2; object-fit: cover; border-radius: var(--r-md); cursor: zoom-in }
@media (max-width: 700px) { .network-gallery-page .wp-block-gallery { grid-template-columns: repeat(2,1fr) } }

/* Lightbox */
.cardamom-lightbox { position: fixed; inset: 0; z-index: 300; background: rgba(44,41,37,.95); display: none;
       align-items: center; justify-content: center }
.cardamom-lightbox.is-open { display: flex }
.lb-img { max-width: 88vw; max-height: 85vh; object-fit: contain }
.lb-close, .lb-prev, .lb-next { position: absolute; background: none; border: 0; color: var(--chalk); cursor: pointer;
       font-size: 2rem; line-height: 1; padding: .5rem 1rem; opacity: .75; transition: opacity var(--t-fast) }
.lb-close:hover, .lb-prev:hover, .lb-next:hover { opacity: 1 }
.lb-close { top: 1rem; right: 1.5rem; font-size: 2.4rem }
.lb-prev { left: 1rem; top: 50%; transform: translateY(-50%) }
.lb-next { right: 1rem; top: 50%; transform: translateY(-50%) }

/* ── Who We Serve ── */
.s-wws { max-width: var(--max); margin: 0 auto; padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-wws h2 { font-family: var(--display); font-weight: 500; font-size: clamp(2.6rem,5.5vw,4.4rem); line-height: 1.1; margin: .8rem 0 2.6rem }
.wws-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: clamp(1.5rem,4vw,2.5rem) }
.wws-head { display: flex; align-items: center; gap: .9rem; padding-bottom: 1rem; margin-bottom: 1.1rem; border-bottom: 1px solid var(--sand) }
.wws-icon { color: var(--clay); flex: none; display: flex }
.wws-icon svg { width: 30px; height: 30px }
.wws-head h3 { font-family: var(--display); font-weight: 500; font-size: 1.65rem; color: var(--ink) }
.wws-list { list-style: none; display: flex; flex-direction: column; gap: .7rem }
.wws-list li { font-size: 1.08rem; color: var(--taupe) } /* deliberately plain — no color/underline that reads as a link */
.wws-btn { margin-top: 2.2rem }
@media (max-width: 780px) { .wws-grid { grid-template-columns: 1fr } }
/* ── Work Slider (Homepage) — atmospheric fade, dots for control, no
   auto-advance. Manually selected case studies only. ── */
/* Homepage work categories: a plain grid of image tiles and names.
   Deliberately flat - no alternation, no numbering, no body copy. The
   full treatment is on the Work pages; this is a way in. */
.s-work-categories { padding: clamp(3rem,8vh,5rem) 0 }

/* Shared centred section head. Used here and anywhere else a section
   needs a heading in the same shape. */
.section-head { text-align: center; margin-bottom: clamp(1.8rem,4vh,2.8rem) }
.section-head h2 { font-family: var(--display); font-weight: 300;
       font-size: clamp(1.8rem,3.2vw,2.5rem); line-height: 1.2; margin: .4rem 0 .3rem }
.section-head h2 em { font-style: italic; color: var(--clay) }
.section-head p { max-width: 58ch; margin-inline: auto; color: var(--taupe) }

/* Tiles carry their title inside the image. Used for the case study
   grid on the Work page and the category grid on the homepage. */
/* Flex, not grid, so an odd count fills its row.
   With five categories a three-column grid left a hole in the second
   row. Here the last row's tiles grow to take the space instead. */
.work-tiles { display: flex; flex-wrap: wrap; gap: clamp(1rem,2vw,1.6rem) }
.work-tile { display: block; flex: 1 1 clamp(260px, 30%, 340px); min-width: 0 }
.work-tile.is-hidden { display: none }
/* A set height, not a ratio. Letting the last row's tiles grow wide
   made them tall too, so the second row towered over the first.
   Fixing the height keeps every row level whatever the count. */
.work-tile-img { position: relative; overflow: hidden; border-radius: var(--r-md);
       background: var(--stone); height: clamp(190px, 19vw, 260px) }
.work-tile-img img { width: 100%; height: 100%; object-fit: cover;
       transition: transform var(--t-slow) var(--ease) }
.work-tile:hover .work-tile-img img { transform: scale(1.04) }

/* The scrim carries the text, so it has to hold up over a bright
   photo as well as a dark one. Weighted to the bottom, where the
   title sits, rather than dimming the whole picture. */
.work-tile-scrim { position: absolute; inset: 0;
       background: linear-gradient(to top, rgba(44,41,37,.82) 0%, rgba(44,41,37,.35) 45%, rgba(44,41,37,0) 80%) }
.work-tile-text { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
       padding: clamp(1rem,2vw,1.5rem) }
.work-tile-text h3 { font-family: var(--display); font-weight: 400; color: var(--chalk);
       font-size: clamp(1.15rem,1.7vw,1.45rem); line-height: 1.2 }
.work-tile-cat { display: block; margin-top: .3rem;
       font-size: .62rem; letter-spacing: .2em; text-transform: uppercase; color: rgba(252,251,249,.7) }
.work-tile--static { cursor: default }

/* ═══ Our Work: the band across the top ═══
   The page opened on a quarter-screen of cream with a paragraph in the
   middle of it. Same words, now on something. */

.work-hero { position: relative; min-height: clamp(540px, 78vh, 860px);
       display: flex; align-items: flex-end; overflow: hidden;
       border-radius: 0 0 var(--r-lg) var(--r-lg); background: var(--stone) }
.work-hero-bg { position: absolute; inset: 0 }
.work-hero-img, .work-hero-video { position: absolute; inset: 0; width: 100%; height: 100%;
       object-fit: cover }
.work-hero-img { opacity: 0; transition: opacity var(--t-slow) ease }
.work-hero-img.is-active { opacity: 1 }
.work-hero-scrim { position: absolute; inset: 0;
       background: linear-gradient(to top, rgba(44,41,37,.82) 0%, rgba(44,41,37,.42) 42%, rgba(44,41,37,.12) 100%) }

.work-hero-in { position: relative; z-index: 2; width: 100%;
       padding-top: clamp(3rem,10vh,6rem); padding-bottom: clamp(2.5rem,7vh,4.5rem) }
.work-hero .eyebrow { color: rgba(252,251,249,.8) }
/* The display face, not the body one. A page heading that arrives in
   the interface font reads as a dialog, not a page. */
.work-hero h1 { font-family: var(--display); font-weight: 400; letter-spacing: -.005em;
       font-size: clamp(2.4rem, 5.2vw, 4.6rem); line-height: 1.04;
       color: var(--chalk); margin: .12em 0 .3em; max-width: 16ch }
.work-hero h1 em { color: var(--chalk); opacity: .78 }
.work-hero-intro { color: rgba(252,251,249,.88); max-width: 52ch; margin: 0 }

/* No picture anywhere on the site yet. A grey rectangle with a caption
   is worse than no rectangle, so it becomes a typographic band. */
.work-hero.is-bare { background: var(--linen); min-height: 0; border-radius: 0 }
.work-hero.is-bare .work-hero-in { padding-top: clamp(2rem,7vh,4rem) }
.work-hero.is-bare .eyebrow { color: var(--taupe) }
.work-hero.is-bare h1 { color: var(--ink) }
.work-hero.is-bare h1 em { color: var(--clay); opacity: 1 }
.work-hero.is-bare .work-hero-intro { color: var(--taupe) }

/* ═══ Work sub-types ═══
   The narrower thing someone arrives asking for, set apart from the
   paragraph above it the way a pulled quote is: a rule down the side,
   the name in the display face, the line beside it. Not links - they
   have no pages of their own, and underlining something that does not
   go anywhere is a promise the page cannot keep. */

/* Each one on its own surface, rather than hanging off a hairline in a
   row. Under a hero they were read as a caption; as callouts they are
   the thing the page is checking you came for. */
.work-callouts {
  list-style: none; padding: 0; margin: 1.3rem 0 0;
  /* A hairline-joined strip rather than separate cards with a coloured
     left edge each: one block of related things, not five of them. */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: 1px; background: var(--sand); border: 1px solid var(--sand);
}
.work-callout {
  position: relative;
  padding: clamp(.9rem, 1.7vw, 1.15rem) clamp(.95rem, 1.8vw, 1.2rem);
  background: var(--chalk); color: var(--taupe);
}
/* An h3 now, so it inherits the heading weight and tracking set at the
   top of the stylesheet and has to put its own margins back. */
.work-callout-name { display: block; margin: 0; font-family: var(--display); font-weight: 400;
       letter-spacing: -.01em;
       color: var(--ink); font-size: clamp(1.05rem,1.5vw,1.3rem); line-height: 1.2 }
.work-callout-line { display: block; margin-top: .3rem; font-size: .88rem; line-height: 1.55 }
/* The link through needs air after the last callout, or it reads as a
   fourth one. */
.work-callouts + .work-story-link { margin-top: 1.4rem }

/* On a category's own page they have the full width and sit under the
   hero as their own band. */
.work-callouts--page {
  margin: clamp(1.4rem,3.5vh,2.2rem) 0;
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
}
/* Short runs would otherwise stretch one callout across the page. */
.work-callouts.is-1 { grid-template-columns: minmax(0, 340px) }
.work-callouts.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) }
.work-callouts.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) }
.work-callouts.is-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) }
/* Inside a panel there is less room, so they go two across at most. */
.work-callouts--panel { margin-top: 0; grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr)) }
/* Three across rather than two and an orphan on a row of its own. Four
   goes two by two, which has no orphan either. */
.work-callouts--panel.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) }
.work-callouts--panel.is-4 { grid-template-columns: repeat(2, minmax(0, 1fr)) }

@media (max-width: 760px) {
  .work-callouts,
  .work-callouts.is-2,
  .work-callouts.is-3,
  .work-callouts.is-4 { grid-template-columns: 1fr }
  .work-callouts.is-1 { grid-template-columns: minmax(0, 1fr) }
}

/* ═══ Our Work: the categories ═══

   Three shapes, one markup. Everything they share is here; what makes
   each one itself is in its own block below. Whichever is kept, the
   other two go by deleting their block. */

.work-cats-set { display: flex; flex-wrap: wrap; gap: clamp(1rem, 1.6vw, 1.4rem) }

/* Picture, then name underneath it.

   The name used to sit ON the photograph, over a dark gradient, with
   the subtitle under it and a count badge in the corner. That is the
   single most dated thing a page can do with a picture, and it put
   three pieces of information on a tile whose only job is to be
   chosen from. Name under the picture, on paper, in one line. */
.work-cat-item { position: relative; display: block; padding: 0; border: 0;
       background: none; font: inherit; text-align: left; color: inherit;
       cursor: pointer; -webkit-appearance: none; appearance: none }
.work-cat-item:focus-visible { outline: 2px solid var(--clay); outline-offset: 3px }

.work-cat-img { display: block; overflow: hidden; background: var(--stone);
       border: 1px solid var(--sand) }
.work-cat-img img { width: 100%; height: 100%; object-fit: cover; display: block;
       transition: transform var(--t-slow) var(--ease) }
.work-cat-item:hover .work-cat-img img { transform: scale(1.04) }

/* The rule over the name is what carries the weighting, so it sits
   tight to the picture - the negative margin eats the image border. */
.work-cat-label { display: flex; align-items: baseline; justify-content: space-between;
       gap: .8rem; margin-top: -1px; padding-top: .75rem; border-top: 3px solid var(--sand);
       transition: border-color var(--t-fast) }
.work-cat-name { display: block; font-weight: 300; color: var(--ink);
       font-size: clamp(1.1rem, 1.5vw, 1.35rem); line-height: 1.06; letter-spacing: -.02em }
.work-cat-toggle { flex: none; font-size: 1.1rem; line-height: 1; color: var(--taupe);
       transition: color var(--t-fast) }
.work-cat-toggle::before { content: "+" }
.work-cat-item[aria-expanded="true"] .work-cat-toggle::before { content: "\2013" }
.work-cat-item[aria-expanded="true"] .work-cat-toggle { color: var(--clay) }
.work-cat-item[aria-expanded="true"] .work-cat-label,
.work-cat-item.is-chosen .work-cat-label { border-top-color: var(--ink) }

/* No photograph for this one yet: paper inside the frame rather than a
   grey rectangle. The name is underneath either way, so nothing has to
   change colour to stay readable. */
.work-cat-item.is-bare .work-cat-img { background: var(--chalk) }

/* The write-up. */
.work-cat-panel { flex: 1 0 100%; scroll-margin-top: 100px }
.work-cat-panel .cd-drawer-in { border: 0; border-radius: 0; background: none;
       display: grid; gap: clamp(1.4rem,3vw,2.8rem); align-items: start }
.work-cat-panel.is-open .cd-drawer-in { background: var(--chalk); border: 1px solid var(--sand);
       padding: clamp(1.3rem,2.6vw,2rem) }
@media (min-width: 860px) {
  .work-cat-panel .cd-drawer-in { grid-template-columns: minmax(0,1fr) minmax(0,1.25fr) }
}
.work-cat-panel-text p { color: var(--taupe); margin: 0 0 .9rem }
.work-cat-panel-text .cd-drawer-lede { color: var(--ink); font-size: clamp(1rem,1.3vw,1.12rem);
       line-height: 1.5 }
.work-cat-panel .cd-drawer-close { top: .4rem; right: .4rem }
.work-cat-panel .work-story-link { display: inline-block; margin-top: .4rem }

/* ── The row ──
   One row of tiles, with the write-up opening underneath it. The row
   used to behave as an accordion - every tile shrank when the row was
   hovered and the one under the pointer grew - so the thing you were
   reaching for moved as you reached for it. */
/* Five equal shares.

   They were weighted for a while - brand and corporate wider, with a
   larger name and a clay rule - which did say which work was being
   pushed, but it also said the other three mattered less to anyone
   whose event was one of them. Even is the call now. The weighting
   lived in three rules and a per-category admin setting; all of it has
   gone rather than being left switched off, because a control that
   changes nothing is worse than no control. */
.work-cats-set--columns .work-cat-item { flex: 1 1 0; min-width: 0 }
.work-cats-set--columns .work-cat-img { height: clamp(210px, 21vw, 300px) }

@media (max-width: 860px) {
  /* One per row: the names are what is being chosen between, and two
     across left them two words wide. */
  .work-cats-set--columns .work-cat-item { flex: 1 1 100% }
  .work-cats-set--columns .work-cat-img { height: 180px }
}

/* The chooser had two other shapes - full-width bands, and a feature
   mosaic - with a switch between them for logged-in users while it was
   being decided. Columns won. The rules for the other two were removed
   at the time but their continuation lines were left behind: four
   orphaned declarations and three stray closing braces sitting at the
   top level of the stylesheet.

   That was not harmless. A stray declaration at the top level is read
   as the beginning of a selector, and the parser keeps reading until it
   finds an opening brace - so the wreckage swallowed the selector of
   whatever rule came next. That rule was the work grid, which is why it
   had no effect on the page however it was written. */

/* ═══ Our Work: the work itself ═══ */

/* A grid of equal cards.

   This was a justified run: one height per row, widths flexing to fill
   it, variety in the widths. With five pieces of work the last row had
   nothing to justify against, so two cards stretched to half a screen
   each and the page read as a few long horizontal bands rather than a
   body of work. Equal cards in fixed columns hold their shape whatever
   the count, and the filter can drop a card without the rest resizing
   around the hole. */
.work-mosaic {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: clamp(1rem, 2vw, 1.6rem);
  align-items: start;
}
/* Same rule as the category pages: the track count follows the card
   count up to four, so the "What we do" pair does not sit in a row with
   two empty cells after it. */
.work-mosaic.is-1 { grid-template-columns: minmax(0, 620px); justify-content: center }
.work-mosaic.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) }
.work-mosaic.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) }
.work-mosaic.is-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) }
.work-mosaic > .cd-card { min-width: 0 }
.work-mosaic .cd-card-img { aspect-ratio: 4 / 3; height: auto }
/* A wider card gets a shallower picture, or two cards across the page
   become two tall slabs. */
.work-mosaic.is-1 .cd-card-img,
.work-mosaic.is-2 .cd-card-img { aspect-ratio: 16 / 9 }

@media (max-width: 980px) {
  .work-mosaic.is-3,
  .work-mosaic.is-4 { grid-template-columns: repeat(2, minmax(0, 1fr)) }
}
@media (max-width: 620px) {
  .work-mosaic.is-1,
  .work-mosaic.is-2,
  .work-mosaic.is-3,
  .work-mosaic.is-4 { grid-template-columns: 1fr }
  .work-mosaic.is-1 .cd-card-img,
  .work-mosaic.is-2 .cd-card-img { aspect-ratio: 4 / 3 }
}

/* A piece of work with no picture. Type on paper, not a grey hole. */
.cd-card--work.is-bare .cd-card-img { background: var(--chalk); border: 1px solid var(--sand) }
.cd-card--work.is-bare .cd-card-scrim { display: none }
.cd-card--work.is-bare .cd-card-title { color: var(--ink) }
.cd-card--work.is-bare .cd-card-tag { color: var(--taupe) }
.cd-card--work.is-bare .cd-card-chev { border-color: var(--taupe) }

/* The write-up opens across the full width of the row the card is in.
   Script moves it there; this is what makes it span. */
.work-mosaic .cd-drawer { grid-column: 1 / -1 }
.work-section { margin-top: clamp(3rem,8vh,5rem); padding-top: clamp(2rem,5vh,3rem);
       border-top: 1px solid var(--sand) }
.work-section > .work-mosaic { margin-top: clamp(1.2rem,3vh,2rem) }

/* ═══ The chooser at the top of Our Work ═══ */

.work-cats { margin-top: clamp(1.4rem,3.5vh,2.2rem) }
/* .wrap carries 100px of bottom padding for the end of a page. There
   are two of them inside this section - one round the head, one round
   the write-up - and both were spending it in the middle of it. */
.work-cats > .wrap { padding-bottom: 0 }
.work-cats > .wrap:last-child { padding-bottom: clamp(1.5rem,4vh,2.5rem) }
.work-cats-head { display: flex; align-items: baseline; justify-content: space-between;
       gap: 1rem; margin-bottom: clamp(.5rem,1.2vw,.8rem); min-height: 1.4rem }
.work-cats-line { margin: 0; color: var(--ink);
       font-family: var(--display); font-size: clamp(1.15rem,2vw,1.5rem); line-height: 1.2 }

/* Kept in the markup for the no-script route back, and for the script
   to read the archive URL off. Never shown: pressing the chosen
   category again, or Escape, is the way back. */
.work-cats-all { position: absolute; width: 1px; height: 1px; overflow: hidden;
       clip-path: inset(50%); white-space: nowrap }

/* How much work is behind each one. A number, not a claim. */
.cd-card-count { position: absolute; top: .9rem; right: .9rem; z-index: 3;
       min-width: 1.6rem; padding: .15rem .45rem; border-radius: var(--r-pill);
       background: rgba(252,251,249,.9); color: var(--ink);
       font-size: .66rem; font-variant-numeric: tabular-nums; text-align: center }
.cd-grid--cats.is-flat .cd-card-count { position: absolute; background: var(--stone) }

.cd-card.is-chosen .cd-card-img { box-shadow: 0 0 0 2px var(--clay) }
.cd-grid--cats.is-flat .cd-card.is-chosen .cd-card-cap {
       box-shadow: 0 0 0 2px var(--clay); border-color: transparent }

/* Filtering. The attribute does the hiding so it works with no script
   at all; the fade is for the cards that stay. */
.cd-card[hidden] { display: none }
.cd-grid--work .cd-card { animation: cd-card-in var(--t-mid) var(--ease) both }
@keyframes cd-card-in { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
@media (prefers-reduced-motion: reduce) { .cd-grid--work .cd-card { animation: none } }

.cd-grid-empty { grid-column: 1 / -1; margin: 0; color: var(--taupe) }

/* ═══ The expanding grid ═══
   Used by the Work categories and by the work itself. Big pictures in
   a real CSS grid; clicking one opens a card that spans the full width
   under the row it belongs to, so nothing reflows around it. The card
   is moved into position by script - see cardamom.js. */

.cd-grid { display: grid; gap: clamp(1rem,2vw,1.6rem);
       grid-template-columns: repeat(3, minmax(0, 1fr)) }
.cd-grid--cats { grid-template-columns: repeat(4, minmax(0, 1fr)) }
@media (max-width: 1100px) {
  .cd-grid, .cd-grid--cats { grid-template-columns: repeat(2, minmax(0, 1fr)) }
}
@media (max-width: 560px) {
  .cd-grid { grid-template-columns: minmax(0, 1fr) }
  .cd-grid--cats { grid-template-columns: repeat(2, minmax(0, 1fr)) }
}

/* position:relative here, not on the image: the caption is a sibling of
   the picture, so the card is what it has to sit inside. */
.cd-card { position: relative; display: block; width: 100%; height: 100%;
       padding: 0; border: 0; background: none; font: inherit; text-align: left;
       cursor: pointer; color: inherit; -webkit-appearance: none; appearance: none }
.cd-card:focus-visible { outline: 2px solid var(--clay); outline-offset: 4px }

/* The picture carries the page, so it gets the room. A ratio rather
   than a height: every tile crops the same way at every width. */
.cd-card-img { position: relative; display: block; overflow: hidden;
       border-radius: var(--r-md); background: var(--stone); aspect-ratio: 4 / 5 }
.cd-grid--work .cd-card-img { aspect-ratio: 4 / 3 }
.cd-card-img img { width: 100%; height: 100%; object-fit: cover; display: block;
       transition: transform var(--t-slow) var(--ease) }
.cd-card:hover .cd-card-img img { transform: scale(1.04) }

/* Weighted to the bottom, where the name sits, rather than dimming the
   whole picture. */
.cd-card-scrim { position: absolute; inset: 0;
       background: linear-gradient(to top, rgba(44,41,37,.78) 0%, rgba(44,41,37,.28) 46%, rgba(44,41,37,0) 78%) }

.cd-card-cap { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
       display: block; padding: clamp(.9rem,1.8vw,1.3rem); padding-right: 2.6rem }
.cd-card-title { display: block; font-family: var(--display); font-weight: 400;
       color: var(--chalk); font-size: clamp(1.1rem,1.6vw,1.4rem); line-height: 1.18 }
.cd-card-sub { display: block; margin-top: .3rem; color: rgba(252,251,249,.8);
       font-size: .78rem; line-height: 1.4 }
.cd-card-tag { display: block; margin-top: .35rem; font-size: .62rem;
       letter-spacing: .2em; text-transform: uppercase; color: rgba(252,251,249,.7) }

/* The one mark that says a picture does something other than link. */
.cd-card-chev { position: absolute; right: 1rem; bottom: 1.25rem;
       width: 9px; height: 9px; border-right: 1.5px solid var(--chalk);
       border-bottom: 1.5px solid var(--chalk); transform: rotate(45deg);
       transform-origin: 70% 70%; transition: transform var(--t-mid) var(--ease) }
.cd-card[aria-expanded="true"] .cd-card-chev { transform: rotate(-135deg) }
.cd-card[aria-expanded="true"] .cd-card-img { box-shadow: 0 0 0 2px var(--clay) }

/* A category with no hero image yet. A scrim over an empty grey box
   reads as a photo that failed to load, so it gets flat sand and dark
   type instead - plainly a label, not a broken picture. */
.cd-card--cat.is-empty .cd-card-img { background: var(--sand) }
.cd-card--cat.is-empty .cd-card-scrim { display: none }
.cd-card--cat.is-empty .cd-card-title { color: var(--ink) }
.cd-card--cat.is-empty .cd-card-sub { color: var(--taupe) }
.cd-card--cat.is-empty .cd-card-chev { border-color: var(--taupe) }

/* No photos anywhere in the row. There is no picture to put a caption
   on, so the caption becomes the card: a bordered surface the height of
   its own words. It still has to read as something you can press. */
.cd-grid--cats.is-flat .cd-card-img { display: none }
.cd-grid--cats.is-flat .cd-card-cap { position: static; height: 100%;
       background: var(--chalk); border: 1px solid var(--sand);
       border-radius: var(--r-md); padding: clamp(1rem,2vw,1.4rem);
       padding-bottom: clamp(2rem,3.6vw,2.4rem);
       transition: border-color var(--t-fast) var(--ease) }
.cd-grid--cats.is-flat .cd-card:hover .cd-card-cap { border-color: var(--taupe) }
.cd-grid--cats.is-flat .cd-card[aria-expanded="true"] .cd-card-cap {
       box-shadow: 0 0 0 2px var(--clay); border-color: transparent }

/* ── The card that opens ──
   display:none while parked, so a closed one adds no gap row to the
   grid. Script sets .is-ready a frame before .is-open so there is
   something to animate from. */
.cd-drawer { grid-column: 1 / -1; display: none; scroll-margin-top: 100px }
.cd-drawer.is-ready { display: grid; grid-template-rows: 0fr;
       transition: grid-template-rows var(--t-mid) var(--ease) }
.cd-drawer.is-open { grid-template-rows: 1fr }

/* The animated box cannot carry the padding - a box with padding never
   collapses past it - so the surface and the padding are a child. */
.cd-drawer-in { overflow: hidden; visibility: hidden; opacity: 0;
       transition: opacity var(--t-fast) var(--ease), visibility var(--t-mid) }
.cd-drawer.is-open .cd-drawer-in { visibility: visible; opacity: 1; transition-delay: .07s }

.cd-drawer-in { position: relative; background: var(--chalk);
       border: 1px solid var(--sand); border-radius: var(--r-md) }
.cd-drawer.is-open .cd-drawer-in { padding: clamp(1.4rem,3vw,2.2rem) }
.cd-drawer-in { display: grid; gap: 0 clamp(1.5rem,4vw,3rem) }
@media (min-width: 820px) {
  .cd-drawer-in { grid-template-columns: minmax(0,.9fr) minmax(0,1.1fr); align-items: start }
  /* A card whose body is a couple of chips and a link has nothing to
     fill a second column with, so it does not get one. */
  .cd-drawer--brief .cd-drawer-in { grid-template-columns: minmax(0, 1fr) }
  .cd-drawer--brief .cd-drawer-body { margin-top: 1.1rem }
}

.cd-drawer-head h2 { font-family: var(--display); font-weight: 400; color: var(--ink);
       font-size: clamp(1.5rem,2.8vw,2.1rem); line-height: 1.12; margin: 0 0 .35rem }
.cd-drawer-lede { color: var(--ink); margin: 0 }
.cd-drawer-meta { margin: .5rem 0 0; font-size: .62rem; letter-spacing: .2em;
       text-transform: uppercase; color: var(--taupe) }
.cd-drawer-body p { color: var(--taupe); margin: 0 0 .9rem }
@media (max-width: 819px) { .cd-drawer-body { margin-top: 1rem } }

.cd-drawer-tags { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem;
       margin: 0 0 1rem; padding: 0 }
.cd-drawer-tags li { font-size: .66rem; letter-spacing: .14em; text-transform: uppercase;
       color: var(--taupe); border: 1px solid var(--sand); border-radius: 999px;
       padding: .28rem .7rem }
.cd-drawer-body .work-story-link { display: inline-block }

/* A plain × in the corner. Hit area well past the glyph. */
.cd-drawer-close { position: absolute; top: .55rem; right: .55rem;
       width: 38px; height: 38px; border: 0; border-radius: 50%; background: none;
       cursor: pointer; padding: 0 }
.cd-drawer-close::before, .cd-drawer-close::after { content: ""; position: absolute;
       left: 50%; top: 50%; width: 13px; height: 1.5px; background: var(--taupe);
       transform-origin: center }
.cd-drawer-close::before { transform: translate(-50%,-50%) rotate(45deg) }
.cd-drawer-close::after  { transform: translate(-50%,-50%) rotate(-45deg) }
.cd-drawer-close:hover { background: var(--sand) }
.cd-drawer-close:focus-visible { outline: 2px solid var(--clay); outline-offset: 2px }

@media (prefers-reduced-motion: reduce) {
  .cd-drawer.is-ready, .cd-drawer-in, .cd-card-chev, .cd-card-img img { transition: none }
}

/* Category write-ups, under the tiles. These carry the SEO narrative
   that used to live on the category pages, and they follow the same
   filter as the tiles above them. */
.work-notes { margin-top: clamp(3rem,7vh,5rem); padding-top: clamp(2rem,5vh,3rem);
       border-top: 1px solid var(--sand) }
.work-notes.is-hidden { display: none }
.work-note { max-width: 62ch; margin-inline: auto; text-align: center }
.work-note.is-hidden { display: none }
.work-note + .work-note { margin-top: clamp(2rem,5vh,3rem) }
.work-note h2 { font-family: var(--display); font-weight: 400; color: var(--ink);
       font-size: clamp(1.4rem,2.4vw,1.9rem); margin-bottom: .3rem }
.work-note-sub { color: var(--ink); margin-bottom: .5rem }
.work-note p { color: var(--taupe) }
.work-note .work-story-link { display: inline-block; margin-top: .9rem }

.work-practice-item.is-hidden { display: none }
.work-section.is-hidden { display: none }
/* Three zones on this page. Each needs its own air, or the "What we
   do" heading reads as part of the category note above it. */
.work-notes + .work-section { margin-top: clamp(3rem,7vh,5rem);
       padding-top: clamp(2rem,5vh,3rem); border-top: 1px solid var(--sand) }

.work-categories-cta { margin-top: clamp(2rem,5vh,3rem); text-align: center }

/* ── Back link ──
   One shape everywhere: case studies, blog posts, network categories
   and work categories all use this, in the same place on the page. */
.backlink-wrap { max-width: var(--max); margin: 0 auto; padding: clamp(1.2rem,3vh,2rem) var(--gutter) 0 }
.wrap > .backlink-wrap { padding-inline: 0 }
.backlink { display: inline-flex; align-items: center; gap: .5rem;
       font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; font-weight: 500;
       color: var(--clay); transition: color var(--t-fast) }
.backlink:hover { color: var(--ink) }
.backlink-arrow { transition: transform var(--t-fast) var(--ease) }
.backlink:hover .backlink-arrow { transform: translateX(-3px) }

/* ── Footer logo ── */
.f-logo { display: inline-flex; align-items: center; gap: .7rem }
/* Same 30% increase as the header bar, so the two read as one logo at
   one size rather than two guesses at it. */
.f-logo-img { height: 72px; width: auto; max-width: 320px; object-fit: contain; object-position: left center }
.f-logo .ring-mark { width: 55px; height: 55px }

.s-work-slider { max-width: var(--max); margin: 0 auto; padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-work-slider h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.6rem,3vw,2.6rem); margin: .6rem 0 2rem }
.work-atmosphere { position: relative; width: 100%; aspect-ratio: 21/9; min-height: 340px; overflow: hidden; background: var(--ink); margin-bottom: 1.5rem; border-radius: var(--r-md) }
.work-slide { position: absolute; inset: 0; display: block; opacity: 0; pointer-events: none; transition: opacity var(--t-mid) ease }
.work-slide.is-active { opacity: 1; pointer-events: auto }
.work-slide-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover }
.work-slide-overlay { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(44,41,37,.82) 0%, rgba(44,41,37,.4) 55%, rgba(44,41,37,.1) 100%) }
.work-slide-text { position: relative; z-index: 2; height: 100%; display: flex; flex-direction: column; justify-content: center; padding: clamp(1.5rem,4vw,3rem); max-width: 480px }
.work-slide-text .tag { display: inline-block; background: var(--clay); color: var(--chalk); font-size: .62rem; letter-spacing: .14em; text-transform: uppercase; padding: .35rem .7rem; margin-bottom: .8rem; width: fit-content }
.work-slide-text h3 { font-family: var(--display); font-weight: 300; color: var(--chalk); font-size: clamp(1.6rem,3vw,2.4rem); margin-bottom: .5rem }
.work-slide-text .card-subtitle { color: rgba(252,251,249,.85); font-size: 1rem; margin: 0 0 .8rem }
.work-slide-services { list-style: none; display: flex; flex-wrap: wrap; gap: .5rem }
.work-slide-services li { font-size: .72rem; color: var(--chalk); background: var(--clay); padding: .3rem .7rem }
.atmos-wrap { position: relative }
.atmos-arrows { position: absolute; inset: 0; display: flex; align-items: center; justify-content: space-between; padding: 0 1rem; pointer-events: none; z-index: 4 }
.atmos-arrow { pointer-events: auto; width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(252,251,249,.5); background: rgba(44,41,37,.4);
       color: var(--chalk); font-size: 1.5rem; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background var(--t-fast), border-color var(--t-fast) }
.atmos-arrow:hover { background: var(--clay); border-color: var(--clay) }
@media (max-width: 700px) {
  /* Arrows move to their own row below the image entirely, rather than
     floating over it — this guarantees no overlap with the caption no
     matter how long it runs, instead of trying to carve out just
     enough space for it. Safe now because .atmos-arrows is a sibling
     of the image box, not nested inside its clipped, fixed-ratio area. */
  .atmos-arrows { position: static; padding: .8rem 0 0; justify-content: center; gap: 1rem }
  .work-slide-text, .quote-slide-text { max-width: 100% }
  /* The scrim fades out to the right, which is right when the text sits
     in the left half. On a phone it runs the full width, so the last
     words of every line were landing on the bright part of the photo.
     Straight down instead, darkest where the words are. */
  .quote-slide-overlay { background: linear-gradient(180deg, rgba(44,41,37,.55) 0%, rgba(44,41,37,.8) 55%, rgba(44,41,37,.9) 100%) }
}
@media (max-width: 700px) { .work-atmosphere { aspect-ratio: 4/3; min-height: 300px } }

.s-planner { background: var(--stone); border-block: 1px solid var(--sand); padding: clamp(3rem,8vh,5rem) var(--gutter) }
.s-planner-in { max-width: 720px; margin: 0 auto; text-align: center }
.s-planner-in h2 { font-family: var(--display); font-weight: 300; font-size: clamp(1.6rem,3vw,2.4rem); margin: .6rem 0 1.2rem }
.s-planner-body { font-size: 1rem; color: var(--taupe); line-height: 1.8; margin-bottom: 1.6rem }

/* ── Contact wizard ── */
.wizard { max-width: 640px; margin: 0 auto 1rem; padding: clamp(2rem,5vw,3rem); background: var(--chalk); border: 0; border-radius: var(--r-lg); box-shadow: var(--shadow-soft); position: relative }
.wizard-progress { display: flex; gap: .5rem; margin-bottom: 2rem }
.wizard-dot { width: 28px; height: 3px; background: var(--sand); transition: background var(--t-fast) }
.wizard-dot.is-active, .wizard-dot.is-done { background: var(--clay) }
.wizard-step h2 { font-family: var(--display); font-weight: 400; font-size: clamp(1.4rem,2.6vw,1.9rem); color: var(--ink); margin-bottom: 1.4rem }
.wizard-hint { font-size: .82rem; color: var(--sage); margin: -.8rem 0 1.2rem; font-style: italic }
.wizard-options { display: flex; flex-direction: column; gap: .7rem }
.wizard-options--multi { flex-direction: row; flex-wrap: wrap }
.wizard-opt { text-align: left; background: var(--linen); border: 0; border-radius: var(--r-sm); padding: 1rem 1.3rem;
       font-family: var(--body); font-size: .95rem; color: var(--ink); cursor: pointer; transition: border-color var(--t-fast), background var(--t-fast) }
.wizard-options--multi .wizard-opt { flex: none; text-align: center }
.wizard-opt:hover { border-color: var(--clay) }
.wizard-opt.is-selected { background: var(--clay); border-color: var(--clay); color: var(--chalk) }
.wizard-continue { margin-top: 1.6rem }
.wizard-back { position: absolute; top: clamp(2rem,5vw,3rem); right: clamp(2rem,5vw,3rem); background: none; border: 0;
       font-size: .75rem; letter-spacing: .08em; color: var(--sage); cursor: pointer }
.wizard-summary { font-size: .95rem; color: var(--taupe); line-height: 1.8; margin-bottom: 1.6rem }
.wizard-next-hint { font-size: 1rem; font-weight: 500; color: var(--ink); margin-bottom: 1rem }
.wizard-edit-link { background: none; border: 0; padding: 0; font-size: .78rem; color: var(--taupe); text-decoration: underline; cursor: pointer }
.wizard-edit-link:hover { color: var(--clay) }
.wizard-skip { text-align: center; margin-top: 1.2rem; font-size: .85rem }
.wizard-skip a { color: var(--sage); border-bottom: 1px solid var(--sand) }
.wizard-specific-group { margin-bottom: 1.6rem }
.wizard-specific-group h4 { font-family: var(--display); font-weight: 400; font-size: 1.05rem; color: var(--clay); margin-bottom: .7rem }
.wizard-options--small .wizard-opt { padding: .6rem .9rem; font-size: .85rem }
.wizard-specific-actions { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 1rem }
@media (max-width: 560px) { .wizard-options--multi { flex-direction: column } .wizard-options--multi .wizard-opt { text-align: left } }

.contact-grid { display: grid; grid-template-columns: 1fr 1.3fr; gap: clamp(2rem,5vw,4rem); align-items: start }
.contact-details h2 { font-family: var(--display); font-weight: 400; font-size: 1.3rem; margin-bottom: 1rem }
.contact-details p { margin-bottom: .6rem }
.contact-details a { color: var(--clay) }
.contact-details a.btn { color: var(--chalk) }
@media (max-width: 860px) { .contact-grid { grid-template-columns: 1fr } }

/* ── FAQ ── */
.faq-cat-title { font-family: var(--display); font-weight: 400; font-size: 1.4rem; color: var(--clay);
                  margin: 2.5rem 0 1rem }
.faq-cat-title:first-child { margin-top: 0 }
.faq-group { border-top: 1px solid var(--sand) }
.faq-item { border-bottom: 1px solid var(--sand) }
.faq-q { width: 100%; display: flex; align-items: center; justify-content: space-between; text-align: left;
         background: none; border: 0; padding: 1.1rem 0; cursor: pointer; font: inherit; font-size: 1rem; color: var(--ink) }
.faq-arrow { font-size: 1.3rem; color: var(--clay); transition: transform var(--t-fast); flex: none; margin-left: 1rem }
.faq-q[aria-expanded="true"] .faq-arrow { transform: rotate(90deg) }
.faq-a { padding: 0 0 1.3rem; color: var(--taupe); line-height: 1.8; display: none }
.faq-a.is-open { display: block }
/* Real animated height to/from auto — genuinely new CSS capability.
   Base rule above (display:none / block) works in every browser as
   the functional fallback; this just makes it smooth where possible. */
@supports (height: calc-size(auto, size)) {
  .faq-a { display: block; height: 0; overflow: hidden; padding-bottom: 0; transition: height var(--t-fast) var(--ease) }
  .faq-a.is-open { height: calc-size(auto, size); padding-bottom: 1.3rem }
}
@media (prefers-reduced-motion: reduce) {
  @supports (height: calc-size(auto, size)) { .faq-a { transition: none } }
}
.faq-a p { margin-bottom: 1rem }
.faq-img { max-width: 320px; margin-bottom: 1rem }
.faq-img img { width: 100%; height: auto }
footer { background: var(--chalk); border-top: 1px solid var(--sand) }
.f-in { max-width: var(--max); margin: 0 auto; padding: clamp(3rem,7vh,5rem) var(--gutter) }
.f-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr; gap: 2.5rem }
.f-lede { font-size: .88rem; max-width: 42ch; margin-top: 1.2rem; color: var(--taupe) }
.f-grid h4, .f-grid .f-coltitle { font-size: .6rem; letter-spacing: .24em; text-transform: uppercase; color: var(--clay); font-weight: 500; margin-bottom: 1rem }
.f-grid ul { list-style: none; display: flex; flex-direction: column; gap: .6rem; font-size: .9rem }
.f-grid a:hover { color: var(--clay) }
.f-mark { font-family: var(--display); font-size: 1.05rem; letter-spacing: .24em; text-transform: uppercase }
.f-base { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem; margin-top: clamp(2.5rem,6vh,4rem);
          padding-top: 1.4rem; border-top: 1px solid var(--sand); font-size: .62rem; letter-spacing: .1em; color: var(--sage) }
.f-legal { font-size: .6rem; color: var(--sage); opacity: .75; margin-top: .8rem; line-height: 1.6 }
.f-credit { font-size: .6rem; letter-spacing: .06em; color: var(--sage); opacity: .6; margin-top: .6rem }
.f-legal a { border-bottom: 1px solid var(--sand) }


/* ══════════════════════════════
   RESPONSIVE
   ══════════════════════════════ */

@media (max-width: 1024px) {
  .s-statement-grid { grid-template-columns: 1fr }
  .card-grid { grid-template-columns: repeat(2,1fr) }
  .f-grid { grid-template-columns: 1fr }
}
@media (max-width: 860px) {
  .nav-links, .nav-tel, .nav-cta { display: none }
  .burger { display: block }
  .mbar { display: grid }
  /* Keep the enlarged logo clear of the hamburger on a phone. The
     height is unchanged; only how wide it is allowed to run. */
  .mark-logo-img { max-width: 56vw }
  .f-logo-img { max-width: 72vw }
}
@media (max-width: 640px) { .card-grid { grid-template-columns: 1fr } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: .01ms !important } }

/* Desktop tab panel visibility — placed last on purpose, so it
   reliably wins over the text-only row's own display:block (defined
   earlier, unscoped to any width) as well as the base display:none
   above. Without this being last, a text-only sub-item's content
   would show regardless of whether its tab is actually active. */
@media (min-width: 861px) {
  .network-subitem-row .network-subitem-content { display: none }
  .network-subitem-row.is-active-tab .network-subitem-content { display: grid }
  .network-subitem-row--textonly.is-active-tab .network-subitem-content { display: block }
  .network-subitem-row--media.is-active-tab .network-subitem-content { display: block }
}

/* Join the network - suppliers/partners, genuinely separate section
   from the client-facing CTA above it. */
.network-join { background: var(--stone); border-top: 1px solid var(--sand) }
.network-join-in { max-width: 720px; margin: 0 auto; padding: clamp(4rem,10vh,7rem) var(--gutter); text-align: center }
.network-join-in h2 { font-family: var(--display); font-weight: 400; color: var(--ink); font-size: clamp(1.8rem,3.4vw,2.8rem); margin: .8rem 0 1.2rem }
.network-join-body { font-size: 1rem; color: var(--taupe); line-height: 1.8; margin-bottom: 2.2rem }
.network-join-in .inline-form { text-align: left; max-width: 480px; margin: 0 auto }


/* ═══ Stacked sub-item layout overrides ═══
   These must come last. The desktop tab system hides sub-item content
   by default (display:none), and that rule sits later in this file -
   so these overrides only work if they come after it. Media items use
   flex so text anchors to the bottom of the scrim; text-only items
   stay block. */
@media (min-width: 861px) {
  .network-subitem-list--stacked .network-subitem-row--textonly .network-subitem-content { display: block }
  .network-subitem-list--stacked .network-subitem-row--media .network-subitem-content { display: flex; align-items: flex-end }
}

/* ═══ Tap targets ════════════════════════════════════════════════════
   A finger is about 9mm across; these links render 14-25px tall, so on
   a phone the footer was a column of near-misses and the inline "see
   the work" style links were worse. The targets grow, the type does
   not: padding is invisible, so nothing about the layout changes, it
   just stops being a game of accuracy.

   Pointer-coarse rather than a width query: it is the input device
   that makes this necessary, not the screen size, so a touch laptop
   gets it and a narrow desktop window does not.
   ═══════════════════════════════════════════════════════════════════ */
@media (pointer: coarse) {
  .f-grid li { margin-block: 0 }
  .f-grid li > a,
  .f-legal a {
    display: inline-block;
    padding-block: .55rem;
  }
  /* Inline uppercase CTAs - "see the work", "more on this" and the
     rest - sit in running content, so they get room without being
     turned into blocks that break the line they live on. */
  .s-hero-cta-alt,
  .s-offering-cta,
  .s-who-cta,
  .work-story-link,
  .card-link {
    padding-block: .6rem;
  }
  /* The language switch and the breadcrumb: small, and both the kind of
     thing you reach for one-handed on a phone. */
  .lang-switch a,
  .breadcrumbs a {
    display: inline-block;
    padding-block: .5rem;
  }
}

/* ═══ Where two spacings meet ════════════════════════════════════════
   The closing CTA brings its own generous top padding, and the content
   block above it brought a bottom margin, and the wrap around that
   brought a bottom padding. Three separate pieces of breathing room,
   none of them wrong on its own, stacking into 162px of nothing
   between the last piece of work and the thing we want you to do.
   Whoever is last defers to whoever is next.
   ═══════════════════════════════════════════════════════════════════ */
.wrap:has(+ .s-brief) { padding-bottom: 0 }
.wrap:has(+ .s-brief) > :last-child { margin-bottom: 0 }

/* ═══ The planning step, opened out ══════════════════════════════════
   Step 2 is where the whole page turns - it is the planning stage -
   and it used to end at "you get a quotation" while the eleven things
   you actually receive sat on another page. They are shown here under
   the two headings they are already filed under in the admin.

   Indented under the step rather than set apart as its own section:
   this is detail belonging to step 2, and the numbered spine should
   keep reading as three steps, not five.
   ═══════════════════════════════════════════════════════════════════ */
.contact-steps.has-detail { max-width: 760px }

.step-detail {
  margin-top: 1.1rem;
  padding: 1.2rem 1.3rem 1.1rem;
  border: 1px solid var(--sand);
  border-radius: var(--r-md);
  background: var(--chalk);
}
.step-detail-lead {
  margin: 0 0 1.35rem;
  font-family: var(--display);
  font-size: 1.15rem;
  color: var(--ink);
}
.step-set + .step-set { margin-top: 1.1rem }
.step-set-label {
  margin: 0 0 .5rem;
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--clay);
}
.step-set-list {
  display: flex; flex-wrap: wrap; gap: .4rem;
  margin: 0; padding: 0; list-style: none;
}
.step-set-list li {
  padding: .34rem .75rem;
  border: 1px solid var(--sand);
  border-radius: var(--r-pill);
  background: var(--linen);
  font-size: .82rem;
  color: var(--taupe);
}
.step-detail-foot { margin: 1.1rem 0 0; font-size: .82rem }
.step-detail-foot a {
  color: var(--clay);
  border-bottom: 1px solid rgba(181,97,74,.35);
  transition: border-color var(--t-fast);
}
.step-detail-foot a:hover { border-bottom-color: var(--clay) }

@media (max-width: 700px) {
  .step-detail { padding: 1rem 1rem .95rem }
  .step-set-list { gap: .35rem }
  .step-set-list li { font-size: .78rem }
}

/* The pointer from step 2 to the page that lists what you can ask for. */
.step-more { margin: .6rem 0 0; font-size: .85rem }
.step-more a {
  color: var(--clay);
  border-bottom: 1px solid rgba(181,97,74,.35);
  transition: border-color var(--t-fast);
}
.step-more a:hover { border-bottom-color: var(--clay) }

/* Present to a screen reader, absent on screen. Used where the visual
   design makes a heading unnecessary but the page structure still needs
   one — three numbered steps announce themselves to the eye, and to
   nothing else. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ═══ The index ══════════════════════════════════════════════════════
   A numbered list of things in the order you meet them: rule, number,
   name, what it is, where it goes. Borrowed structure, Cardamom's own
   type and colour — Cormorant for the names, not a grotesque, because
   the serif is what makes it this brand's list rather than a generic
   editorial one.

   This section sits on --ink, so everything here is set for a dark
   ground: chalk names, a lightened clay for the numbers, and rules at
   low-opacity chalk rather than sand, which is a light-background
   colour and vanished against it.
   ═══════════════════════════════════════════════════════════════════ */
.s-index {
  list-style: none;
  /* Capped and centred. The section spans 1680px, which on a wide
     screen left the destination stranded a foot away from the name it
     belonged to, with nothing in between. */
  max-width: 1180px;
  margin: clamp(2rem, 5vh, 3rem) auto 0;
  padding: 0;
  border-bottom: 1px solid rgba(252, 251, 249, .18);
}
.s-index-row { border-top: 1px solid rgba(252, 251, 249, .18) }

.s-index-in {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0 clamp(1rem, 3vw, 2.5rem);
  padding: clamp(1.5rem, 3.5vh, 2.4rem) 0;
  text-decoration: none;
  color: inherit;
  transition: background var(--t-fast) var(--ease);
}
/* The row is the target, so the whole band lifts rather than the words
   inside it. Bleeding the tint past the gutter keeps the rules meeting
   the edge of the column the way they do without it. */
a.s-index-in:hover {
  background: rgba(252, 251, 249, .05);
  box-shadow: -1.1rem 0 0 rgba(252, 251, 249, .05), 1.1rem 0 0 rgba(252, 251, 249, .05);
}

.s-index-n {
  font-family: var(--body);
  font-size: .78rem;
  letter-spacing: .14em;
  /* The brand clay is too dark to read on ink; this is the same hue
     lifted until it holds against it. */
  color: #D08A72;
  padding-top: .5rem;
}

.s-index-name {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  line-height: 1.1;
  color: var(--chalk);
  margin: 0;
  transition: color var(--t-fast) var(--ease);
}
a.s-index-in:hover .s-index-name { color: #E8A68E }

.s-index-body {
  margin: .7rem 0 0;
  max-width: 54ch;
  font-size: .94rem;
  line-height: 1.7;
  color: rgba(252, 251, 249, .66);
}

.s-index-cta {
  display: flex;
  align-items: center;
  gap: .7rem;
  white-space: nowrap;
  color: rgba(252, 251, 249, .62);
  transition: color var(--t-fast) var(--ease);
}
.s-index-cta-label {
  font-size: .68rem;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.s-index-arrow {
  font-size: 1.15rem;
  line-height: 1;
  transition: transform var(--t-mid) var(--ease);
}
a.s-index-in:hover .s-index-cta { color: #E8A68E }
a.s-index-in:hover .s-index-arrow { transform: translate(3px, -3px) }
a.s-index-in:focus-visible { outline: 2px solid #D08A72; outline-offset: -4px }

@media (max-width: 760px) {
  /* The destination moves under the name: three columns at this width
     leaves the name four words wide and the label clipped. */
  .s-index-in {
    grid-template-columns: 2.6rem minmax(0, 1fr);
    gap: 0 1rem;
    padding: 1.4rem 0;
  }
  /* Wrapping allowed here: "Talk to us about logistics" is wider than
     a phone, and nowrap pushed it off the edge. */
  .s-index-cta { grid-column: 2; margin-top: .9rem; white-space: normal }
  .s-index-body { font-size: .9rem }
  a.s-index-in:hover { background: none; box-shadow: none }
}
@media (prefers-reduced-motion: reduce) {
  .s-index-arrow { transition: none }
}

/* ═══ The cookie bar ══════════════════════════════════════════════
   Present only when something has been configured that needs asking
   about. A strip at the foot of the page rather than a sheet over the
   middle of it: it has to be answered before anything loads, but it is
   not more important than what the visitor came to read.

   The two buttons are the same size and sit on the same row. Refusing
   as a link in small type under a large Accept is the pattern the AEPD
   has repeatedly ruled against, and it would be dishonest here anyway.
   ═══════════════════════════════════════════════════════════════════ */
.cd-consent {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
  background: var(--chalk); border-top: 1px solid var(--sand);
  box-shadow: 0 -10px 30px rgba(44,41,37,.08);
}
.cd-consent[hidden] { display: none }
.cd-consent-in {
  max-width: 1180px; margin: 0 auto;
  padding: clamp(1rem, 2.4vw, 1.4rem) clamp(1.2rem, 4vw, 2.5rem);
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(1rem, 3vw, 2.5rem); flex-wrap: wrap;
}
.cd-consent-text {
  margin: 0; max-width: 62ch; color: var(--taupe);
  font-size: .88rem; line-height: 1.65;
}
.cd-consent-text a { color: var(--clay); border-bottom: 1px solid currentColor; padding-bottom: 1px }
.cd-consent-buttons { display: flex; gap: .6rem; flex-shrink: 0 }
.cd-consent-btn {
  font: inherit; font-size: .72rem; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 500; cursor: pointer;
  /* 48px tall: the same tap target as everything else that matters. */
  padding: 0 1.4rem; min-height: 48px;
  border: 1px solid var(--ink); border-radius: var(--r-sm);
  background: none; color: var(--ink);
  transition: background var(--t-fast), color var(--t-fast);
}
.cd-consent-btn:hover { background: var(--stone) }
.cd-consent-btn--yes { background: var(--clay); border-color: var(--clay); color: var(--chalk) }
.cd-consent-btn--yes:hover { background: var(--ink); border-color: var(--ink) }
.cd-consent-btn:focus-visible { outline: 2px solid var(--clay); outline-offset: 3px }

@media (max-width: 860px) {
  /* Script lifts this clear of the phone action bar, which is fixed to
     the same edge and is not a fixed height. */
  .cd-consent-in { flex-direction: column; align-items: stretch; gap: 1rem }
  .cd-consent-buttons > * { flex: 1 }
}

/* ═══ Our Work, 2026 ══════════════════════════════════════════════
   Sans throughout, left-aligned, structural. The serif display face is
   switched off for this page with one token rather than with a hundred
   font-family declarations, so putting it back - or taking it off the
   rest of the site - is one line either way.
   ═══════════════════════════════════════════════════════════════════ */
/* The Work pages carried this on their own while the rest of the site
   was still serif. The face is now the site default, so what is left
   here is the weight and tracking that a sans display needs and a serif
   does not - applied everywhere, because everywhere is sans now. */
h1, h2, h3 { font-weight: 300; letter-spacing: -.022em }
/* An italic serif said "emphasis" on its own. A sans italic at display
   size just looks slanted, so the emphasised half of a heading takes
   the clay instead. */
h1 em, h2 em, h3 em { font-style: normal; color: var(--clay) }

/* ── The band at the top ── */
.work-head { padding: clamp(2rem, 5vh, 3rem) 0 clamp(1.4rem, 3.5vh, 2rem) }
.work-head-in { display: grid; gap: clamp(1.4rem, 3.5vw, 3.5rem); align-items: end }
@media (min-width: 900px) {
  .work-head-in { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) }
}
.work-head-title {
  margin: 0; font-weight: 200; line-height: 1.0; letter-spacing: -.028em;
  /* Half the old hero's size on purpose: the event types under it are
     what the page is for, and a headline that fills the window means
     the first thing anyone sees is a sentence. */
  font-size: clamp(2.1rem, 4vw, 3.4rem); max-width: 19ch;
}
.work-head-aside { display: flex; flex-direction: column; gap: .9rem }
.work-head-support { margin: 0; color: var(--taupe); line-height: 1.6; max-width: 38ch }
.work-head-facts { margin: 0; display: flex; gap: 1.25rem; color: var(--taupe);
       font-size: .7rem; letter-spacing: .12em; text-transform: uppercase }
.work-head-facts span[aria-hidden] { color: var(--sand) }

/* ── Section headings ──
   A label and a line of context on one row with a rule under them.
   Replaces the centred heading with a subtitle beneath it, which was
   most of what made this read as a magazine. */
.work-sec-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  padding-bottom: clamp(.8rem, 1.6vw, 1.1rem);
  border-bottom: 1px solid var(--ink);
  margin-bottom: clamp(1.4rem, 3vh, 2rem);
}
.work-sec-head h2 { margin: 0; font-family: var(--body); font-size: .78rem; font-weight: 400;
       letter-spacing: .22em; text-transform: uppercase; color: var(--ink) }
.work-sec-head span { font-size: .7rem; letter-spacing: .14em; text-transform: uppercase;
       color: var(--taupe) }

/* The category label over a card title, in place of the tag pills. */
.work-story-cat { margin: 0 0 .1rem; font-size: .64rem; letter-spacing: .2em;
       text-transform: uppercase; color: var(--clay) }

/* ── What we do, as an index ── */
.work-index { margin-top: -.4rem }
.work-index-row {
  display: grid; grid-template-columns: 3.2rem minmax(0, 1fr) 1.5rem;
  gap: .4rem 1.5rem; align-items: center;
  padding: clamp(1.1rem, 2.4vh, 1.6rem) 0;
  border-bottom: 1px solid var(--sand);
  color: inherit; text-decoration: none;
  transition: background var(--t-fast);
}
@media (min-width: 860px) {
  .work-index-row { grid-template-columns: 3.2rem minmax(0, 1fr) minmax(0, 1fr) 1.5rem }
}
a.work-index-row:hover { background: var(--chalk) }
/* Sage, not clay: these are not client work, and the marker is the
   cheapest way to say so without a second heading. */
.work-index-n { font-size: .75rem; color: var(--sage); letter-spacing: .08em }
.work-index-name { min-width: 0; font-size: clamp(1.2rem, 2vw, 1.6rem); font-weight: 300;
       letter-spacing: -.022em; line-height: 1.12; color: var(--ink) }
.work-index-line { font-size: .85rem; line-height: 1.55; color: var(--taupe) }
.work-index-arrow { text-align: right; color: var(--taupe); transition: transform var(--t-fast) var(--ease) }
a.work-index-row:hover .work-index-arrow { transform: translateX(3px) }
@media (max-width: 859px) {
  /* Every cell placed by hand. Left to auto-placement the line and the
     arrow landed in the name's track and squeezed it to 27 pixels,
     which pushed the row - and the page - 54 pixels wider than the
     phone it was on. */
  .work-index-row { grid-template-columns: 2.4rem minmax(0, 1fr) 1.2rem; row-gap: .35rem }
  .work-index-n    { grid-column: 1; grid-row: 1 }
  .work-index-name { grid-column: 2; grid-row: 1 }
  .work-index-arrow { grid-column: 3; grid-row: 1 }
  .work-index-line { grid-column: 2; grid-row: 2 }
}

/* The head and the types band are one block: .wrap carries 100px of
   bottom padding for the end of a page, and three of them stacked here
   put a screen of nothing between the headline and the tiles. */
.work-head > .wrap { padding-top: 0; padding-bottom: 0 }
.work-head + .work-cats { margin-top: clamp(1.6rem, 3.5vh, 2.4rem) }
.work-cats .work-sec-head { margin-bottom: clamp(1.1rem, 2.4vh, 1.5rem) }

/* ── What is being shown, while a type is open ── */
.work-sec-head { position: relative }
.work-filter-note {
  display: inline-flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; color: var(--taupe);
}
.work-filter-note[hidden] { display: none }
.work-filter-note strong { color: var(--clay); font-weight: 500 }
.work-filter-clear {
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  cursor: pointer; background: none; color: var(--ink);
  border: 1px solid var(--sand); border-radius: var(--r-sm);
  padding: 0 .8rem; min-height: 36px;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.work-filter-clear:hover { background: var(--chalk); border-color: var(--taupe) }
.work-filter-clear:focus-visible { outline: 2px solid var(--clay); outline-offset: 2px }
/* The aside and the note occupy the same slot: one is the standing
   description of the run, the other is what has happened to it. */
.work-sec-head:has(.work-filter-note:not([hidden])) .work-sec-aside { display: none }

/* The index number is replaced by the event type when the entry has
   one, so a filtered run does not count 01, 04, 07. */
.work-index-n { white-space: nowrap; font-size: .64rem; letter-spacing: .16em; text-transform: uppercase }
.work-index-row[hidden] { display: none }
@media (min-width: 860px) {
  .work-index-row { grid-template-columns: 8.5rem minmax(0, 1fr) minmax(0, 1fr) 1.5rem }
}
@media (max-width: 859px) {
  .work-index-row { grid-template-columns: minmax(0, 1fr) 1.2rem }
  .work-index-n    { grid-column: 1; grid-row: 1; color: var(--sage) }
  .work-index-name { grid-column: 1; grid-row: 2 }
  .work-index-arrow { grid-column: 2; grid-row: 2 }
  .work-index-line { grid-column: 1; grid-row: 3 }
}

/* What we do now leads the pair, so it does not carry the top rule and
   the space that separated it from a section above it. */
.work-section--lead { margin-top: clamp(1.6rem, 4vh, 2.4rem); padding-top: 0; border-top: 0 }

/* A work section sitting under an open event type on a phone. It is
   inside the chooser's own wrap now, which already has the gutter, so
   it sheds the page padding and takes a rule above instead of the gap
   that separated it from the section before it. */
@media (max-width: 860px) {
  .work-section.is-under-type {
    margin: clamp(1.4rem, 3.5vh, 2rem) 0 0;
    padding-top: clamp(1.2rem, 3vh, 1.6rem);
    border-top: 1px solid var(--sand);
  }
  .work-section.is-under-type:first-of-type { border-top: 0; padding-top: 0 }
}

@media (max-width: 860px) {
  /* Stacked under one open type, the two sections sit close enough
     together that two "showing / show everything" controls read as a
     duplicate rather than as a control for each run. The first one
     speaks for both. */
  .work-section.is-under-type ~ .work-section.is-under-type .work-filter-note { display: none }
  .work-section.is-under-type .work-index { margin-bottom: 0 }
  .work-section.is-under-type .work-index-row:last-child { border-bottom: 0 }
}


/* ── Legal, privacy and cookies ──────────────────────────────────────
   One long document, so it is set for reading rather than for scanning:
   a single narrow measure, generous leading, and tables that carry a
   rule between rows instead of a box around every cell. The width comes
   from --measure, the same one the long-form prose uses, so this does
   not become a second answer to the same question. */
.legal-page { padding-block: clamp(2rem, 6vh, 3.5rem) clamp(3rem, 9vh, 5rem) }
.legal-head { max-width: var(--measure); margin-bottom: clamp(2rem, 5vh, 3rem) }
.legal-head h1 { font-size: clamp(1.9rem, 4vw, 2.9rem); margin: .5rem 0 1rem }
.legal-lede { color: var(--taupe); max-width: var(--measure) }
.legal-jump { display: flex; flex-wrap: wrap; gap: 1.2rem; margin-top: 1.4rem;
       padding-top: 1.2rem; border-top: 1px solid var(--sand);
       font-size: .64rem; letter-spacing: .18em; text-transform: uppercase }
.legal-jump a { color: var(--clay) }

/* The prose keeps the reading measure; the tables do not. A
   four-column processing table squeezed into 55 characters is unusable,
   and it is reference material rather than something read line by line,
   so it gets the room it needs. */
.legal-body p, .legal-list, .legal-h2, .legal-h3, .legal-body > p { max-width: var(--measure) }
.legal-body p, .legal-list { color: var(--taupe); line-height: 1.75; margin-bottom: 1rem }
.legal-h2 { font-size: clamp(1.4rem, 2.6vw, 1.9rem); font-weight: 300; margin: clamp(2.6rem, 7vh, 4rem) 0 1rem;
       padding-top: clamp(1.6rem, 4vh, 2.2rem); border-top: 1px solid var(--sand) }
.legal-body > .legal-h2:first-child { margin-top: 0; padding-top: 0; border-top: 0 }
.legal-h3 { font-size: .74rem; letter-spacing: .18em; text-transform: uppercase; font-weight: 500;
       color: var(--ink); margin: 2rem 0 .7rem }
.legal-list { padding-left: 1.1rem }
.legal-list li { margin-bottom: .45rem }

/* The anchor the footer links to. The header bar is fixed, so a bare
   id would land under it; html has scroll-padding-top for exactly this,
   and the empty span keeps the target off the heading itself so the
   heading's own top margin is not what gets scrolled to. */
.legal-anchor { display: block; height: 0; overflow: hidden }

/* A table wider than the phone scrolls sideways on its own rather than
   pushing the whole page sideways. The four-column processing table is
   the one that needs it. */
.legal-table-wrap { overflow-x: auto; margin: 0 0 1.4rem; max-width: min(100%, 940px);
       border-block: 1px solid var(--sand); -webkit-overflow-scrolling: touch }
/* The two-column tables are labelled facts, not data: the label column
   is sized so "Registered address" does not wrap onto two lines. */
.legal-table--facts th { width: 12rem }
.legal-table { width: 100%; border-collapse: collapse; font-size: .82rem; line-height: 1.55; min-width: 420px }
.legal-table th, .legal-table td { text-align: left; vertical-align: top; padding: .7rem .8rem;
       border-bottom: 1px solid var(--sand); color: var(--taupe) }
.legal-table tr:last-child th, .legal-table tr:last-child td { border-bottom: 0 }
.legal-table th { color: var(--ink); font-weight: 500 }
.legal-table tr:first-child th { background: var(--linen) }

/* An answer nobody has given yet. Marked rather than hidden: a privacy
   policy with a quiet blank in it is worse than one that says plainly
   which line is still open. */
.legal-gap { color: var(--clay); border-bottom: 1px dashed currentColor; white-space: nowrap }

/* Administrators only - see the template. */
.legal-warn { max-width: var(--measure); margin-bottom: 2rem; padding: 1rem 1.1rem;
       background: #FBF3E4; border-left: 4px solid #8A5A1E; color: #5C4418; font-size: .86rem; line-height: 1.6 }
.legal-warn a { color: #8A5A1E; text-decoration: underline }

.legal-updated { max-width: var(--measure); margin-top: clamp(2.5rem, 6vh, 3.5rem);
       padding-top: 1.2rem; border-top: 1px solid var(--sand);
       font-size: .64rem; letter-spacing: .18em; text-transform: uppercase; color: var(--taupe) }

/* On a phone the legal tables stop being tables.
   Four columns inside 350 pixels is a sideways scroll with no visible
   handle, and the fourth column - the legal basis, which is the part
   that matters - was the one off the edge. Each row becomes a short
   block instead, with the column name printed above its value from the
   data-label the renderer writes. The two-column fact tables already
   read as label-then-value, so they only lose their columns. */
@media (max-width: 700px) {
  .legal-table-wrap { overflow-x: visible; border: 0 }
  .legal-table { display: block; min-width: 0 }
  .legal-table tr { display: block; padding: 1rem 0; border-bottom: 1px solid var(--sand) }
  .legal-table tr:last-child { border-bottom: 0 }
  .legal-table:not(.legal-table--facts) tr:first-child { display: none }
  .legal-table td, .legal-table th { display: block; width: auto; padding: 0 0 .5rem; border: 0; background: none }
  .legal-table tr td:last-child, .legal-table tr th:last-child { padding-bottom: 0 }
  .legal-table td[data-label]::before { content: attr(data-label); display: block;
         font-size: .58rem; letter-spacing: .16em; text-transform: uppercase;
         color: var(--ink); margin-bottom: .2rem }
  .legal-table--facts th { width: auto; font-size: .58rem; letter-spacing: .16em; text-transform: uppercase }
}
