/* ==========================================================================
   Philippa Cutajar · philippacutajar.com

   Concept: one system, many brands.
   The chrome (grid, type, spacing, rhythm) never moves. The skin adopts each
   project's real brand colour. Every adopted colour is contrast-solved at
   build time in tools/colour.py, so the type always clears WCAG AA.

   1. Fonts
   2. Tokens
   3. Reset and base
   4. Layout primitives
   5. Header
   6. Type
   7. Buttons and links
   8. Hero
   9. Spectrum
   10. Project bands
   11. Sections
   12. CV
   13. Case study
   14. Footer
   15. Responsive
   ========================================================================== */

/* 1. Fonts ---------------------------------------------------------------- */

/* Archivo carries weight 400-800 and width 62-125% in one variable file, so
   the display voice comes from the width axis rather than a second family. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('/assets/fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('/assets/fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/geist-mono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/geist-mono-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* 2. Tokens --------------------------------------------------------------- */

:root {
  --ink: #0a0e14;
  --ink-raised: #131a24;
  --paper: #f2efe9;
  --paper-sunk: #e7e3d9;

  --on-dark: #f2efe9;
  --on-dark-soft: #9fabb9;
  --on-light: #0a0e14;
  --on-light-soft: #4d5663;

  /* Site default accent. Projects override --accent per band, always with a
     value solved against that band's ground. */
  --accent: #ff5a4f;
  --accent-on-light: #b03e37;

  --line-dark: rgb(242 239 233 / 15%);
  --line-light: rgb(10 14 20 / 14%);

  --font-sans: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  /* Width axis does the expressive work, so sizes stay disciplined. */
  --wide: 112%;
  --wide-soft: 106%;

  --fs-hero: clamp(2.5rem, 6.4vw, 6rem);
  --fs-display-1: clamp(2.125rem, 4.6vw, 4rem);
  --fs-display-2: clamp(1.75rem, 3.2vw, 2.875rem);
  --fs-display-3: clamp(1.375rem, 1.9vw, 1.75rem);
  --fs-lead: clamp(1.0625rem, 1.15vw, 1.3125rem);
  --fs-body: 1.0625rem;
  --fs-small: 0.9375rem;
  --fs-mono: 0.6875rem;

  --shell: 1340px;
  --gutter: clamp(20px, 5vw, 68px);
  --section-y: clamp(68px, 8vw, 124px);
  --radius: 4px;
  --ease: cubic-bezier(0.2, 0.75, 0.2, 1);
}

/* 3. Reset and base ------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  /* Grid and flex children cannot blow out their track. */
  min-width: 0;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

html,
body {
  max-width: 100%;
  overflow-x: clip;
}

body {
  background: var(--paper);
  color: var(--on-light);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

img,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3,
h4 {
  font-weight: 700;
  font-stretch: var(--wide-soft);
  letter-spacing: -0.032em;
  line-height: 1.04;
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

::selection {
  background: var(--accent);
  color: var(--ink);
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: fixed;
  top: -100px;
  left: var(--gutter);
  z-index: 300;
  padding: 14px 20px;
  background: var(--accent);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: top 0.15s ease;
}

.skip-link:focus {
  top: 12px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 4. Layout primitives ---------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: var(--section-y);
}

.section--tight {
  padding-block: clamp(44px, 5.5vw, 80px);
}

.section--ink {
  background: var(--ink);
  color: var(--on-dark);
}

.section--sunk {
  background: var(--paper-sunk);
}

/* Section header: mono index and label above, display heading below, with an
   optional action pinned to the baseline on the right. */
.head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 32px;
  margin-bottom: clamp(32px, 4vw, 52px);
}

.head--flush {
  margin-bottom: 0;
}

.head__label {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.rule {
  border: 0;
  border-top: 1px solid var(--line-light);
}

.on-dark .rule {
  border-top-color: var(--line-dark);
}

/* 5. Header --------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 200;
  background: var(--ink);
  color: var(--on-dark);
  border-bottom: 1px solid var(--line-dark);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: 11px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* The chip is the one piece of chrome that adopts the current project's
   colour, which is the whole idea stated in 10 pixels. */
.wordmark::before {
  content: '';
  width: 10px;
  height: 18px;
  background: var(--accent);
  transform: skew(-12deg);
  transition: background 0.5s var(--ease);
}

.site-nav {
  display: flex;
  gap: 2px;
}

.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 13px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
  border-bottom: 2px solid transparent;
  transition: color 0.18s ease, border-color 0.18s ease;
}

.site-nav a:hover {
  color: var(--on-dark);
}

.site-nav a[aria-current='page'] {
  color: var(--on-dark);
  border-bottom-color: var(--accent);
}

/* 6. Type ----------------------------------------------------------------- */

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-light-soft);
}

.on-dark .eyebrow {
  color: var(--on-dark-soft);
}

.eyebrow--accent {
  color: var(--accent-on-light);
}

/* Eyebrow sitting directly on a brand band. */
.eyebrow--band {
  color: var(--band-soft, currentColor);
}

.on-dark .eyebrow--accent {
  color: var(--accent);
}

.index {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--accent-on-light);
}

.on-dark .index {
  color: var(--accent);
}

.display-1 {
  font-size: var(--fs-display-1);
  font-stretch: var(--wide-soft);
}

.display-2 {
  font-size: var(--fs-display-2);
  font-stretch: var(--wide-soft);
}

.display-3 {
  font-size: var(--fs-display-3);
}

.lead {
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--on-light-soft);
  max-width: 58ch;
}

.on-dark .lead {
  color: var(--on-dark-soft);
}

.prose p {
  color: var(--on-light-soft);
  max-width: 66ch;
}

.prose p + p {
  margin-top: 1em;
}

.on-dark .prose p {
  color: var(--on-dark-soft);
}

/* 7. Buttons and links ---------------------------------------------------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 50px;
  padding: 0 24px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 1px solid transparent;
  border-radius: var(--radius);
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.12s ease;
}

.button--primary {
  background: var(--accent);
  color: var(--ink);
}

.button--primary:hover {
  filter: brightness(1.1);
}

/* Response: feedback on press, not just on release. A small, instant scale so a
   tap or click feels direct. (apple-design: kill latency, feedback lives on the
   press.) */
.button:active {
  transform: scale(0.97);
}

.text-link,
.pband__link,
.back-link {
  transition: opacity 0.12s ease;
}

.text-link:active,
.pband:active .pband__link,
.back-link:active {
  opacity: 0.6;
}

.button--line {
  border-color: var(--line-light);
  color: var(--on-light);
}

.button--line:hover {
  border-color: currentColor;
}

.on-dark .button--line {
  border-color: var(--line-dark);
  color: var(--on-dark);
}

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line-light);
  transition: border-color 0.18s ease;
}

.on-dark .text-link {
  border-bottom-color: var(--line-dark);
}

.text-link:hover {
  border-bottom-color: currentColor;
}

.text-link span,
.button span {
  transition: transform 0.2s var(--ease);
}

.text-link:hover span,
.button:hover span {
  transform: translateX(3px);
}

.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* 8. Hero ----------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: var(--on-dark);
  padding-block: clamp(56px, 7vw, 100px) clamp(48px, 6vw, 84px);
}

.hero::after {
  content: '';
  position: absolute;
  top: -45%;
  right: -12%;
  width: min(820px, 88%);
  aspect-ratio: 1;
  background: radial-gradient(circle, rgb(255 90 79 / 10%), transparent 70%);
  pointer-events: none;
}

.hero__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(24px, 3vw, 36px);
}

.hero__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
}

/* The width axis pushed to 112% is what stops this reading as a default
   grotesk headline. */
.hero__statement {
  font-size: var(--fs-hero);
  font-weight: 800;
  font-stretch: var(--wide);
  letter-spacing: -0.042em;
  line-height: 0.98;
  max-width: 15ch;
}

.hero__statement em {
  font-style: normal;
  color: var(--accent);
}

/* 9. Brand marquee ------------------------------------------------------- */

/* The multi-brand claim, shown rather than asserted. Every mark is an
   alpha-only mask filled with currentColor, so one asset works on any ground
   and the whole strip recolours from a single token. Marks are normalised by
   ink area at build time, not by height, so a wide lockup and a tall monogram
   carry the same optical weight. */
.marquee {
  position: relative;
  overflow: hidden;
  padding-block: clamp(26px, 3vw, 40px);
  background: var(--paper);
  border-bottom: 1px solid var(--line-light);
}

.marquee__label {
  display: block;
  margin-bottom: clamp(18px, 2vw, 26px);
  text-align: center;
}

.marquee__viewport {
  overflow: hidden;
}

.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee-scroll 52s linear infinite;
}

.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track {
  animation-play-state: paused;
}

.marquee__group {
  display: flex;
  align-items: center;
  gap: clamp(44px, 6vw, 92px);
  padding-right: clamp(44px, 6vw, 92px);
}

/* Two identical groups, so translating by half the track loops seamlessly. */
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.marquee__group > a,
.marquee__group > .marquee__item,
.marquee__logo {
  flex: none;
  display: block;
  width: clamp(120px, 13vw, 186px);
  height: clamp(44px, 4.6vw, 66px);
}

.marquee__group > a,
.marquee__group > .marquee__item {
  border-radius: 2px;
}

.marquee__logo {
  background: currentColor;
  color: var(--on-light-soft);
  -webkit-mask: var(--mark) center / contain no-repeat;
  mask: var(--mark) center / contain no-repeat;
  transition: color 0.25s var(--ease);
}

.marquee__logo:hover,
a:hover > .marquee__logo,
a:focus-visible > .marquee__logo {
  color: var(--on-light);
}

/* Fade the strip into the page at both ends so marks enter and leave rather
   than being chopped off at the edge. */
.marquee__viewport {
  -webkit-mask: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .marquee__track {
    animation: none;
  }
  .marquee__viewport {
    overflow-x: auto;
    -webkit-mask: none;
    mask: none;
  }
  /* The duplicate group exists only to make the loop seamless. */
  .marquee__group[aria-hidden='true'] {
    display: none;
  }
}

/* 10. Project bands ------------------------------------------------------- */

/* One band per project, full bleed in that brand's colour. Identical
   typographic furniture in every band: the system holds, the skin changes.
   --band-fg is solved per brand at build time. */
.pband {
  position: relative;
  background: var(--brand);
  color: var(--band-fg);
  padding-block: clamp(40px, 4.5vw, 68px);
}

.pband__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(24px, 5vw, 72px);
  align-items: center;
}

.pband--flip .pband__stage {
  order: 2;
}

/* Cover art is a mark on a flat ground that matches --brand exactly, so the
   image blends into the band with no frame at all. Verified by sampling every
   file: all eight have uniform borders and no transparency. */
.pband__stage img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: contain;
  transition: transform 0.6s var(--ease);
}

.pband:hover .pband__stage img {
  transform: scale(1.025);
}

.pband__info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
}

.pband__meta {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--band-soft, currentColor);
}

.pband__meta i {
  width: 26px;
  height: 1px;
  background: currentColor;
  font-style: normal;
}

.pband__title {
  font-size: var(--fs-display-1);
  font-weight: 700;
  font-stretch: var(--wide-soft);
  letter-spacing: -0.035em;
}

.pband__summary {
  max-width: 44ch;
  color: var(--band-soft, currentColor);
  font-size: var(--fs-lead);
  line-height: 1.5;
}

.pband__link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 1px solid currentColor;
}

.pband__link span {
  transition: transform 0.2s var(--ease);
}

.pband:hover .pband__link span {
  transform: translateX(3px);
}

/* The whole band is the click target; the visible link keeps the affordance. */
.pband__hit {
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* 11. Sections ------------------------------------------------------------ */

.capability-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 44px);
}

.capability {
  padding-top: 20px;
  border-top: 1px solid var(--line-light);
}

.on-dark .capability {
  border-top-color: var(--line-dark);
}

.capability h3 {
  font-size: var(--fs-display-3);
  margin-block: 14px 10px;
}

.capability p {
  color: var(--on-light-soft);
  font-size: var(--fs-small);
}

.on-dark .capability p {
  color: var(--on-dark-soft);
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 3vw, 48px);
}

.stat {
  padding-top: 20px;
  border-top: 1px solid var(--line-light);
}

.on-dark .stat {
  border-top-color: var(--line-dark);
}

.stat strong {
  display: block;
  font-size: clamp(2.75rem, 5.4vw, 4.75rem);
  font-weight: 800;
  font-stretch: var(--wide);
  letter-spacing: -0.045em;
  line-height: 0.95;
}

.stat span {
  display: block;
  margin-top: 12px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--on-light-soft);
}

.on-dark .stat span {
  color: var(--on-dark-soft);
}

/* 12. CV ------------------------------------------------------------------ */

.timeline {
  border-top: 1px solid var(--line-light);
}

.on-dark .timeline {
  border-top-color: var(--line-dark);
}

.timeline__item {
  display: grid;
  grid-template-columns: 128px minmax(0, 1fr) minmax(0, 1.25fr);
  gap: clamp(18px, 4vw, 52px);
  padding-block: clamp(24px, 3vw, 36px);
  border-bottom: 1px solid var(--line-light);
  align-items: start;
}

.on-dark .timeline__item {
  border-bottom-color: var(--line-dark);
}

.timeline__years {
  padding-top: 5px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.1em;
  color: var(--accent-on-light);
}

.on-dark .timeline__years {
  color: var(--accent);
}

.timeline__role h3 {
  font-size: var(--fs-display-3);
}

.timeline__org {
  display: block;
  margin-top: 7px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--on-light-soft);
}

.on-dark .timeline__org {
  color: var(--on-dark-soft);
}

.timeline__detail {
  color: var(--on-light-soft);
  font-size: var(--fs-small);
}

.on-dark .timeline__detail {
  color: var(--on-dark-soft);
}

.credential-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 2.5vw, 36px);
}

.credential {
  padding-top: 20px;
  border-top: 1px solid var(--line-light);
}

.on-dark .credential {
  border-top-color: var(--line-dark);
}

.credential h3 {
  font-size: 1.0625rem;
  line-height: 1.35;
  margin-block: 14px 8px;
}

.credential p {
  font-size: var(--fs-small);
  color: var(--on-light-soft);
}

.on-dark .credential p {
  color: var(--on-dark-soft);
}

.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
  gap: clamp(20px, 3vw, 40px);
}

.contact-item {
  padding-top: 20px;
  border-top: 1px solid var(--line-dark);
}

.contact-item a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 4px;
  font-size: var(--fs-lead);
  font-weight: 600;
  font-stretch: var(--wide-soft);
  border-bottom: 1px solid transparent;
  transition: border-color 0.18s ease;
}

.contact-item a:hover {
  border-bottom-color: currentColor;
}

/* 13. Case study ---------------------------------------------------------- */

/* The case study hero is the project's own brand colour, so arriving on the
   page drops you straight into that brand's world. */
.case-hero {
  position: relative;
  background: var(--brand);
  color: var(--band-fg);
  padding-block: clamp(56px, 8vw, 116px);
}

.case-hero__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
}

/* Sits above the project title so there is a way back that does not rely on
   the browser's own back button. Uses the band's solved muted colour. */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  margin-bottom: 4px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--band-soft, currentColor);
  transition: color 0.18s ease;
}

.back-link:hover {
  color: var(--band-fg, currentColor);
}

.back-link span {
  transition: transform 0.18s var(--ease);
}

.back-link:hover span {
  transform: translateX(-3px);
}

.case-hero h1 {
  font-size: var(--fs-hero);
  font-weight: 800;
  font-stretch: var(--wide);
  letter-spacing: -0.042em;
  line-height: 0.98;
}

.case-meta {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 22px;
  margin-top: clamp(28px, 4vw, 44px);
  padding-top: 26px;
  border-top: 1px solid currentColor;
}

.case-meta > div {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* Each field keeps its own column, so an empty Role/Scope/Gallery never lets the
   others shift left. The columns then line up on every case study. */
.case-meta > .m-discipline { grid-column: 1; }
.case-meta > .m-role       { grid-column: 2; }
.case-meta > .m-scope      { grid-column: 3; }
.case-meta > .m-gallery    { grid-column: 4; }

.case-meta dt {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--band-soft, currentColor);
}

.case-meta dd {
  font-size: var(--fs-small);
  font-weight: 600;
}

.case-meta dd a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  border-bottom: 1px solid currentColor;
}

.case-cover {
  background: var(--brand);
}

.case-cover img {
  width: 100%;
  height: min(48vh, 460px);
  object-fit: contain;
}

.case-block + .case-block {
  margin-top: clamp(32px, 4vw, 52px);
}

.case-block h2 {
  font-size: var(--fs-display-3);
  margin-bottom: 14px;
}

.case-body {
  display: grid;
  grid-template-columns: 176px minmax(0, 1fr);
  gap: clamp(28px, 5vw, 64px);
  align-items: start;
}

/* Draft marker. Removed per project once Pippa supplies final copy. */
.draft-note {
  margin-top: 16px;
  padding: 13px 16px;
  border-left: 2px solid var(--accent);
  background: rgb(255 90 79 / 9%);
  font-size: var(--fs-small);
  color: var(--on-dark-soft);
}

.next-project {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

/* 14. Footer -------------------------------------------------------------- */

.site-footer {
  background: var(--ink);
  color: var(--on-dark);
  padding-block: 0 26px;
}

.site-footer--bare {
  padding-block: 26px;
}

.site-footer--bare .footer-bottom {
  border-top: 0;
  padding-top: 0;
}

.footer-top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 30px;
  padding-block: clamp(40px, 5vw, 68px) clamp(34px, 4.5vw, 58px);
  border-top: 1px solid var(--line-dark);
}

.site-footer h2 {
  font-size: var(--fs-display-2);
  max-width: 16ch;
  margin-top: 14px;
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 30px;
  padding-top: 20px;
  border-top: 1px solid var(--line-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
}

.footer-bottom a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* 15. Responsive ---------------------------------------------------------- */

@media (max-width: 900px) {
  .capability-grid,
  .credential-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .timeline__item {
    grid-template-columns: 104px minmax(0, 1fr);
  }

  .timeline__detail {
    grid-column: 2;
  }

  .case-meta {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .case-meta > div { grid-column: auto; }

  .case-body {
    grid-template-columns: minmax(0, 1fr);
  }

  .pband__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
  }

  /* Stage always leads on narrow screens, whatever the desktop order. */
  .pband--flip .pband__stage {
    order: 0;
  }
}

@media (max-width: 640px) {
  .site-header__inner {
    min-height: 58px;
    gap: 6px;
  }

  .site-nav a {
    padding: 0 9px;
    letter-spacing: 0.08em;
  }

  .capability-grid,
  .credential-grid,
  .stat-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 22px;
  }

  .timeline__item {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
  }

  .timeline__detail {
    grid-column: 1;
  }

  .case-meta {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
  }
  .case-meta > div { grid-column: auto; }

  .action-row .button {
    flex: 1 1 100%;
  }

  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* --- Contact form -------------------------------------------------------- */

.contact-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: start;
}

.contact-side { display: grid; gap: 22px; }

.contact-form { display: grid; gap: 18px; }

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: 18px;
}

.field { display: grid; gap: 7px; }

.field label {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
}

.field .req { color: var(--accent); }
.field .opt { color: var(--on-dark-soft); text-transform: none; letter-spacing: 0; }

.field input,
.field select,
.field textarea {
  font: inherit;
  width: 100%;
  padding: 12px 14px;
  color: var(--on-dark);
  background: var(--ink-raised);
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  transition: border-color 0.15s ease;
}

.field textarea { min-height: 140px; resize: vertical; line-height: 1.55; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--on-dark-soft); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  border-color: var(--accent);
}
.field [aria-invalid='true'] { border-color: var(--accent); }

.field-error {
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--accent);
}

/* The honeypot is removed from view without display:none, which some bots
   check for, and is hidden from assistive technology by aria-hidden. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-note {
  padding: 14px 16px;
  border-left: 3px solid;
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: var(--fs-small);
}
.form-note--ok {
  border-color: #4ade80;
  background: rgb(74 222 128 / 10%);
  color: #b7f0cd;
}
.form-note--error {
  border-color: var(--accent);
  background: rgb(255 90 79 / 10%);
  color: #ffc9c4;
}

.form-foot {
  font-size: var(--fs-small);
  color: var(--on-dark-soft);
}

.draft-note {
  margin-top: 16px;
  padding: 13px 16px;
  border-left: 2px solid var(--accent);
  background: rgb(255 90 79 / 9%);
  font-size: var(--fs-small);
  color: var(--on-dark-soft);
}

@media (max-width: 860px) {
  .contact-layout { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Content blocks

   The block types an editor can add to any page. They borrow the existing
   rhythm and colour rather than introducing a second system: a page assembled
   from blocks should be indistinguishable from one that was designed.
   ========================================================================== */

.block-prose > .display-2 + .prose,
.block-prose > .display-2 + .block-bullets { margin-top: clamp(20px, 2.5vw, 32px); }

.block-bullets {
  list-style: none;
  max-width: 66ch;
  margin-top: clamp(18px, 2vw, 26px);
}
.block-bullets li {
  position: relative;
  padding-left: 26px;
  color: var(--on-light-soft);
}
.block-bullets li + li { margin-top: 0.7em; }
/* A rule rather than a bullet: it sits on the same grid as the rest of the
   page and does not fight the type. */
.block-bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 14px;
  height: 1px;
  background: var(--accent-on-light);
}
.on-dark .block-bullets li { color: var(--on-dark-soft); }
.on-dark .block-bullets li::before { background: var(--accent); }

/* --- Quote --------------------------------------------------------------- */

.block-quotes { display: grid; gap: clamp(32px, 4vw, 56px); }

.pullquote { max-width: 34ch; }
.pullquote blockquote p {
  font-size: clamp(22px, 2.6vw, 34px);
  font-weight: 500;
  font-stretch: var(--wide-soft);
  line-height: 1.28;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
/* The mark is decorative and sits outside the measure, so it never pushes the
   first line off the grid. */
.pullquote blockquote::before {
  content: "\201C";
  display: block;
  font-size: clamp(40px, 5vw, 64px);
  line-height: 0.8;
  color: var(--accent-on-light);
  margin-bottom: 0.1em;
}
.on-dark .pullquote blockquote::before { color: var(--accent); }

.pullquote figcaption {
  margin-top: clamp(16px, 2vw, 22px);
  padding-top: 14px;
  border-top: 1px solid var(--line-light);
  font-size: 14px;
}
.pullquote figcaption strong { display: block; font-weight: 700; }
.pullquote figcaption span { display: block; color: var(--on-light-soft); margin-top: 2px; }
.on-dark .pullquote figcaption { border-top-color: var(--line-dark); }
.on-dark .pullquote figcaption span { color: var(--on-dark-soft); }

@media (min-width: 900px) {
  .block-quotes { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
}

/* --- Call to action ------------------------------------------------------ */

.block-cta { max-width: 46ch; }
.block-cta .lead { margin-top: clamp(14px, 1.6vw, 20px); }
.block-cta .action-row { margin-top: clamp(24px, 3vw, 34px); }

/* --- Images -------------------------------------------------------------- */

.block-images { display: grid; gap: clamp(28px, 3.5vw, 48px); }

.block-figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 2px;
}
.block-figure figcaption {
  margin-top: 12px;
  font-size: 13.5px;
  color: var(--on-light-soft);
  max-width: 66ch;
}
.on-dark .block-figure figcaption { color: var(--on-dark-soft); }

/* --- Services -------------------------------------------------------------
   One service per band. The lead column carries the argument; the detail
   column carries the proof. Below the breakpoint they stack in that order,
   which is also the order they matter in.
   ------------------------------------------------------------------------- */

.service { display: grid; gap: clamp(28px, 4vw, 56px); align-items: start; }
.service__lead .display-2 { margin-top: 10px; }
.service__lead .lead { margin-top: clamp(14px, 1.6vw, 20px); }
.service__lead .prose { margin-top: clamp(16px, 2vw, 24px); }
.service__lead .action-row { margin-top: clamp(22px, 2.6vw, 30px); }

.service__detail { display: grid; gap: clamp(24px, 3vw, 40px); }
.service__col h3 {
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line-light);
  margin-bottom: 14px;
}
.on-dark .service__col h3 { border-bottom-color: var(--line-dark); }
.service__col .block-bullets { margin-top: 0; }

.service__steps { list-style: none; counter-reset: step; }
.service__steps li {
  display: flex; gap: 12px;
  color: var(--on-light-soft);
}
.service__steps li + li { margin-top: 0.85em; }
.service__steps li span {
  flex: none;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--accent-on-light);
  padding-top: 0.25em;
}

@media (min-width: 900px) {
  .service { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
  .service__detail { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
}

/* --- Journal ---------------------------------------------------------------
   A list, not a card grid. The date and reading time come first because they
   are what someone uses to decide, then the title does the work.
   -------------------------------------------------------------------------- */

.journal { list-style: none; }
.journal__item {
  position: relative;
  display: grid;
  gap: clamp(16px, 2.5vw, 32px);
  padding-block: clamp(28px, 3.5vw, 44px);
  border-top: 1px solid var(--line-light);
}
.journal__item:first-child { border-top: 0; padding-top: 0; }

/* One hit area over the whole row, with the visible text left selectable. */
.journal__hit { position: absolute; inset: 0; z-index: 1; }
.journal__item:hover .journal__title { color: var(--accent-on-light); }
.journal__item:focus-within { outline: 2px solid var(--accent-on-light); outline-offset: 8px; }
.journal__hit:focus-visible { outline: none; }

.journal__thumb { overflow: hidden; border-radius: 2px; }
.journal__thumb img { display: block; width: 100%; height: auto; }

.journal__meta {
  display: flex; gap: 8px; align-items: baseline;
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--on-light-soft);
}
.journal__title {
  margin-top: 10px;
  font-size: clamp(22px, 2.6vw, 32px);
  font-weight: 700; font-stretch: var(--wide-soft);
  letter-spacing: -0.02em; line-height: 1.15;
  text-wrap: balance;
  transition: color 120ms ease;
}
.journal__excerpt {
  margin-top: 10px; max-width: 62ch;
  color: var(--on-light-soft);
}
.journal__link {
  display: inline-block; margin-top: 14px;
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent-on-light);
}

@media (min-width: 700px) {
  .journal__item { grid-template-columns: 260px minmax(0, 1fr); align-items: start; }
  .journal__item:not(:has(.journal__thumb)) { grid-template-columns: minmax(0, 1fr); }
}

/* --- One article ---------------------------------------------------------- */

.hero--article .lead { margin-top: clamp(16px, 2vw, 24px); }
.article-body { max-width: 68ch; }
.article-body p { font-size: clamp(17px, 1.5vw, 19px); line-height: 1.65; }
.article-back {
  margin-top: clamp(40px, 5vw, 64px);
  padding-top: clamp(24px, 3vw, 32px);
  border-top: 1px solid var(--line-light);
}
