/* ==========================================================================
   Dawny Products — v3 stylesheet (dark gradient style)
   Shared by every page. Two page types:
     1. Landing  — one full screen, no scrolling, rotating message + background
     2. Content  — short dark gradient hero, then light readable body below
   ========================================================================== */

/* --- Design tokens ------------------------------------------------------- */
:root {
  /* Brand */
  --charcoal:     #242526;
  --ink-soft:     #3A3B3D;
  --warm-grey:    #74736F;
  --paper:        #FAF8F4;
  --white:        #FFFFFF;
  --hairline:     #E9E6E0;
  --petrol:       #0A5249;
  --petrol-mid:   #0F6E63;
  --petrol-tint:  #E5F0EE;
  --light-petrol: #7FC8BC;

  /* Text tiers on dark backgrounds */
  --on-dark:      #FFFFFF;
  --on-dark-82:   rgba(255,255,255,0.82);
  --on-dark-72:   rgba(255,255,255,0.72);
  --on-dark-65:   rgba(255,255,255,0.65);

  /* Type */
  --font-display: 'Libre Franklin', system-ui, sans-serif;
  --font-body:    'Source Sans 3', system-ui, sans-serif;

  /* Shadow — warm-neutral, never coloured */
  --shadow-card: 0 1px 3px rgba(36,37,38,0.06);
  --shadow-lift: 0 14px 40px rgba(36,37,38,0.10);

  /* Layout.
     Everything on the page starts at --gutter from the left edge, so the
     headline, the body text and the logo all share one left margin. Content
     is never centred in a narrower column — that's what caused the indent. */
  --gutter: clamp(24px, 5vw, 48px);
  --measure: 760px;   /* comfortable reading width for long-form text */

  /* How far the landing text sits ABOVE dead centre. The eye reads the visual
     centre of a space as slightly above the true middle, so mathematically
     centred text tends to look like it's sagging — more so here, where the
     stats row and the portrait both weight the bottom of the composition.

     >>> Turn this dial and hard-refresh: 0 = dead centre, 5vh = gentle lift
     (current), 10vh = distinctly high. Only applies on tall windows. <<< */
  --hero-lift: 15vh;

  /* The widest the site itself is ever allowed to get — and, since content is
     no longer centred in an inner column, this is also the content width.
     1440 is the standard desktop design canvas: wide enough to feel generous,
     tight enough that the header and cards still look composed. On anything
     wider the whole site is framed in the middle rather than stretched.

     >>> This is the one number to change if the site feels too wide or too
     narrow. Sensible alternatives: 1280 (tighter) or 1600 (more generous). <<< */
  --site-max: 1440px;
  --surround: #0E1010;  /* what shows either side of the frame */
}

/* --- Reset / base -------------------------------------------------------- */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }

/* Fills the screen behind the framed site on very wide monitors */
html { background: var(--surround); }

body {
  font-family: var(--font-body);
  background: var(--charcoal);
  color: var(--ink-soft);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;

  /* Cap the whole site and centre it. Below 1920 this does nothing at all —
     the site behaves exactly as before. Above it, the page stops growing and
     sits framed in the middle of the screen. */
  max-width: var(--site-max);
  margin-inline: auto;
  position: relative;
}
img { max-width: 100%; display: block; }
h1, h2, h3 { font-family: var(--font-display); margin: 0; }

/* The landing page is deliberately one screen — no scrolling.
   Only lock it when the window is tall enough to fit the content, so short
   windows (and landscape phones) can still scroll rather than clipping. */
@media (min-height: 640px) {
  body.landing { overflow: hidden; }
}

/* Keyboard focus must always be visible, on dark and on light. */
:focus-visible {
  outline: 3px solid var(--light-petrol);
  outline-offset: 3px;
  border-radius: 4px;
}

/* --- Animations ---------------------------------------------------------- */
@keyframes dp-kenburns { 0% { transform: scale(1.06); } 100% { transform: scale(1.14); } }
@keyframes dp-rise { 0% { opacity: 0; transform: translateY(18px); } 100% { opacity: 1; transform: translateY(0); } }

/* ==========================================================================
   Dark gradient stage — used by both page types
   ========================================================================== */
.stage { position: relative; overflow: hidden; background: var(--charcoal); }

.slide {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.6s ease;
  animation: dp-kenburns 18s ease-in-out infinite alternate;
}
.slide.is-active { opacity: 1; }

/* The four brand gradients. Also usable singly as a page-hero background. */
.grad-purple { background: radial-gradient(130% 120% at 22% 78%, #7b2ff7 0%, #4a1f8a 34%, #1c1233 64%, #060409 100%); }
.grad-pink   { background: radial-gradient(130% 120% at 80% 24%, #ff4d94 0%, #b3255f 32%, #3a1220 64%, #070405 100%); }
.grad-blue   { background: radial-gradient(130% 120% at 20% 30%, #2f7bff 0%, #1f4ab3 34%, #12213a 64%, #040609 100%); }
.grad-green  { background: radial-gradient(130% 120% at 80% 80%, #0F6E63 0%, #0A5249 34%, #14201f 64%, #060909 100%); }
/* Fifth gradient, added 2026-07-28 with the "AI in practice" message. Same
   recipe as the other four — bright hue, mid tone, dark, near-black — with its
   own focal position so it doesn't read as a repeat. Amber because the other
   four are cool or brand-petrol, so it's the one hue that's clearly distinct. */
.grad-amber  { background: radial-gradient(130% 120% at 68% 22%, #f0932b 0%, #a85c12 34%, #33200f 64%, #090705 100%); }

.scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(15,18,18,0.62) 0%, rgba(15,18,18,0.34) 40%, rgba(15,18,18,0.52) 78%, rgba(9,12,12,0.82) 100%);
}
.vignette {
  position: absolute; inset: 0;
  background: radial-gradient(120% 90% at 30% 45%, rgba(9,12,12,0.55) 0%, rgba(9,12,12,0) 60%);
}

/* ==========================================================================
   Navigation — sits over the dark hero on every page
   ========================================================================== */
.site-nav {
  position: absolute; top: 0; left: 0; right: 0; z-index: 30;
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
  padding: 22px var(--gutter);
}
.brand { display: flex; align-items: center; gap: 14px; text-decoration: none; }
.brand img { height: 46px; width: 46px; }
.brand span {
  font-family: var(--font-display);
  font-weight: 700; font-size: 15px; letter-spacing: 0.02em;
  color: var(--on-dark);
}
.nav-links { display: flex; align-items: center; gap: 34px; }
.nav-links a {
  font-family: var(--font-display);
  font-weight: 500; font-size: 14px;
  color: var(--on-dark-82);
  text-decoration: none;
  transition: color .16s ease;
}
.nav-links a:hover { color: var(--on-dark); }
/* Marks the page you're currently on */
.nav-links a[aria-current="page"] { color: var(--on-dark); border-bottom: 1.5px solid var(--light-petrol); padding-bottom: 3px; }

/* Hamburger — hidden on desktop, shown below 760px */
.nav-toggle {
  display: none;
  width: 46px; height: 46px;
  align-items: center; justify-content: center;
  background: rgba(255,255,255,0.10);
  border: 1px solid rgba(255,255,255,0.22);
  border-radius: 10px;
  cursor: pointer;
  padding: 0;
}
.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  content: ''; display: block;
  width: 20px; height: 2px;
  background: var(--on-dark);
  border-radius: 2px;
  transition: transform .2s ease, opacity .2s ease;
}
.nav-toggle span { position: relative; }
.nav-toggle span::before { position: absolute; top: -6px; }
.nav-toggle span::after  { position: absolute; top: 6px; }
/* Turns into an X when the menu is open */
.nav-toggle[aria-expanded="true"] span { background: transparent; }
.nav-toggle[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }

/* Full-screen mobile menu */
.nav-overlay {
  position: fixed; inset: 0; z-index: 25;
  display: none;
  flex-direction: column;
  align-items: center; justify-content: center;
  gap: 8px;
  background: rgba(9,12,12,0.94);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.nav-overlay.is-open { display: flex; }
.nav-overlay a {
  font-family: var(--font-display);
  font-weight: 600; font-size: 24px;
  color: var(--on-dark);
  text-decoration: none;
  padding: 14px 24px;
}
.nav-overlay a:hover { color: var(--light-petrol); }

@media (max-width: 760px) {
  .nav-links { display: none; }
  .nav-toggle { display: inline-flex; }
}

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 54px; padding: 0 26px;
  border-radius: 10px;
  font-family: var(--font-display);
  font-weight: 600; font-size: 16px;
  text-decoration: none; cursor: pointer;
  border: 0;
  transition: background .16s ease, border-color .16s ease, transform .16s ease, color .16s ease;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--petrol); color: var(--on-dark); }
.btn-primary:hover { background: var(--petrol-mid); color: var(--on-dark); }
.btn-secondary { background: transparent; color: var(--on-dark); border: 1.5px solid rgba(255,255,255,0.55); }
.btn-secondary:hover { background: rgba(255,255,255,0.12); border-color: rgba(255,255,255,0.85); }

/* On the green slide a petrol button all but disappears into the background,
   so the primary CTA flips to white-on-charcoal to stay clearly the main action. */
.stage.on-green .btn-primary { background: var(--white); color: var(--charcoal); }
.stage.on-green .btn-primary:hover { background: var(--petrol-tint); color: var(--charcoal); }

/* ==========================================================================
   Page type 1 — Landing (one screen, no scroll)
   ========================================================================== */
.landing-stage { width: 100%; height: 100vh; min-height: 640px; }

.portrait {
  position: absolute; z-index: 2;
  bottom: 0; right: 2%;
  height: 105%; max-width: 56%;
  object-fit: contain; object-position: bottom;
  pointer-events: none;
}

.landing-content {
  position: relative; z-index: 3;
  height: 100%;
  display: flex; flex-direction: column;
  /* Left-aligned, not centred — so the headline starts under the logo */
  margin: 0;
  padding: clamp(104px, 16vw, 132px) var(--gutter) 96px;

  /* "safe center" means centred while it fits, but never centred so hard that
     the message rides up over the logo and navigation. When there genuinely
     isn't room it falls back to sitting under the header. The plain `center`
     first is the fallback for browsers that don't know `safe`. */
  justify-content: center;
  justify-content: safe center;
}

/* Lift the text above dead centre — but only when the window is tall enough to
   give it away. The lift is a preference, not a promise: it's an empty spacer
   below the text that is allowed to shrink (flex: 0 1) so that a long message
   eats into the lift before it ever eats into the header.
   x2 because a spacer below centred content raises it by half its height. */
@media (min-height: 800px) {
  .landing-content::after {
    content: '';
    flex: 0 1 calc(var(--hero-lift) * 2);
    min-height: 0;
  }
}
/* Never let the message itself be squashed — the spacer gives way instead */
.landing-inner { flex: 0 0 auto; max-width: var(--measure); animation: dp-rise 0.9s ease both; }

/* The message block cross-fades when the slide changes */
.message { transition: opacity .5s ease, transform .5s ease; }
.message.is-fading { opacity: 0; transform: translateY(10px); }

.eyebrow {
  font-family: var(--font-display);
  font-weight: 600; font-size: 13px;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--on-dark-72);
  margin-bottom: 22px;
  display: flex; align-items: center; gap: 14px;
}
.eyebrow .rule { width: 34px; height: 1.5px; background: rgba(255,255,255,0.5); display: inline-block; flex: none; }

.landing-inner h1 {
  font-weight: 800;
  font-size: clamp(34px, 6.2vw, 66px);
  line-height: 1.03; letter-spacing: -0.025em;
  color: var(--on-dark);
  text-wrap: balance;
}
.lede {
  margin: 26px 0 0;
  font-size: clamp(16px, 1.9vw, 19px);
  line-height: 1.6;
  color: var(--on-dark-82);
  max-width: 560px;
}
.ctas { display: flex; gap: 14px; margin-top: 36px; flex-wrap: wrap; }

.stats { display: flex; gap: 52px; margin-top: 52px; flex-wrap: wrap; }
.stat .v { font-family: var(--font-display); font-weight: 800; font-size: 26px; color: var(--on-dark); }
.stat .l { font-size: 13.5px; color: var(--on-dark-65); margin-top: 2px; }

/* Slide dots + pause control */
.dots {
  position: absolute; z-index: 4;
  bottom: 40px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px;
}
.dot {
  width: 6px; height: 6px;
  border: 0; padding: 0; cursor: pointer;
  border-radius: 999px;
  background: rgba(255,255,255,0.4);
  transition: width .4s ease, background .4s ease;
}
.dot.is-active { width: 30px; background: var(--on-dark); }
.dots-pause {
  margin-left: 8px;
  background: none; border: 0; padding: 4px 8px;
  color: var(--on-dark-65);
  font-family: var(--font-display); font-size: 12px;
  cursor: pointer;
}
.dots-pause:hover { color: var(--on-dark); }

@media (max-width: 760px) {
  /* Portrait becomes a faint backdrop so the headline can run full width */
  .portrait {
    z-index: 1;
    right: auto; left: 50%; transform: translateX(-50%);
    height: 60%; width: auto; max-width: 92%;
    opacity: 0.32;
  }
  .stats { gap: 28px; margin-top: 36px; }
  .ctas .btn { flex: 1 1 auto; }
}

/* ==========================================================================
   Page type 2 — Content pages (dark hero, then light readable body)
   ========================================================================== */
.page-hero {
  width: 100%;
  min-height: 52vh;
  display: flex; align-items: flex-end;
  padding: 120px 0 0;
}
.page-hero__inner {
  position: relative; z-index: 3;
  width: 100%;
  margin: 0;
  padding: 0 var(--gutter) 56px;
  animation: dp-rise 0.7s ease both;
}
.page-hero h1 {
  font-weight: 800;
  font-size: clamp(32px, 5vw, 54px);
  line-height: 1.04; letter-spacing: -0.025em;
  color: var(--on-dark);
  text-wrap: balance;
  max-width: 16ch;
}
.page-hero .lede { max-width: 620px; }

/* --- Hero with a photo bleeding off the right (About) --------------------- */
.page-hero--portrait { min-height: 70vh; }

/* The photo fills the right of the hero and dissolves into the gradient down
   its left edge, so there's no hard rectangle. Same effect as the landing
   portrait, done with a mask because this is an ordinary photograph rather
   than a transparent cut-out. */
.hero-photo {
  position: absolute; z-index: 2;
  top: 0; right: 0; bottom: 0;
  width: 46%; height: 100%;
  object-fit: cover;
  /* The vertical figure is the one that matters: it shifts the photo up inside
     the frame so the whole head and neck are in shot. The blackboard formula
     losing its top is the deliberate trade — David's call. */
  object-position: 58% 72%;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,0.5) 26%, #000 62%);
          mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,0.5) 26%, #000 62%);
  pointer-events: none;
}
/* Keeps the headline off the photo */
.page-hero--portrait .page-hero__inner { max-width: 62%; }

/* A soft dark band across the top. Without it the navigation sits on the
   bright part of the photo and becomes unreadable. Sits above the photo
   (z-index 2) but below the nav (z-index 30). */
.page-hero--portrait::before {
  content: '';
  position: absolute; z-index: 3;
  top: 0; left: 0; right: 0; height: 210px;
  background: linear-gradient(to bottom, rgba(9,12,12,0.9) 0%, rgba(9,12,12,0.66) 38%, rgba(9,12,12,0) 100%);
  pointer-events: none;
}

/* The light half — where long-form content actually gets read */
.page-body {
  background: var(--paper);
  color: var(--ink-soft);
  font-size: 17px; line-height: 1.6;
}
/* Dark body — same colour as what shows either side of the framed site, with
   white text. Used on the About page. */
.page-body--dark { background: var(--surround); color: var(--on-dark-82); }
.page-body--dark :is(h2, h3, h4, dt, strong, .callout) { color: var(--on-dark); }
.page-body--dark .section-sub { color: var(--on-dark-65); }

/* Spans the frame, starting at the same left margin as the logo */
.wrap { margin: 0; padding: 64px var(--gutter); }
/* Long-form reading — capped for readability, but still flush left, not centred */
.wrap--narrow { max-width: calc(var(--measure) + var(--gutter) * 2); margin-inline: 0; }

.page-body h2 {
  font-size: 30px; font-weight: 700;
  letter-spacing: -0.01em; line-height: 1.12;
  color: var(--charcoal);
  margin: 0 0 8px;
}
.page-body h3 {
  font-size: 21px; font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--charcoal);
  margin: 0 0 8px;
}
.page-body p { margin: 0 0 18px; }
/* Breathing room above a heading that follows body content, so sections
   separate. A heading at the top of a .wrap keeps its flush margin. */
.page-body :is(p, ul, ol, dl, figure, blockquote, .grid-2, .grid-3) + h2 { margin-top: 46px; }
/* Links in the light body are petrol — but not buttons, which set their own
   colour and would otherwise end up petrol text on a petrol background. */
.page-body a:not(.btn) { color: var(--petrol); }
.page-body a:not(.btn):hover { color: var(--petrol-mid); }
.section-sub { color: var(--warm-grey); max-width: 60ch; margin: 0 0 32px; }

.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }

.card {
  background: var(--white);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  padding: 28px;
  box-shadow: var(--shadow-card);
  transition: box-shadow .18s ease, transform .18s ease;
  display: flex; flex-direction: column;
}
.card:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); }
.card p { font-size: 15.5px; }
.card__foot { margin-top: auto; padding-top: 16px; }

.pill {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 600; font-size: 12px; letter-spacing: 0.02em;
  color: var(--petrol); background: var(--petrol-tint);
  border-radius: 999px; padding: 4px 12px;
  margin-bottom: 14px;
  align-self: flex-start;
}
.meta { font-size: 13px; color: var(--warm-grey); margin: 0 0 10px; }

.text-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-display); font-weight: 600; font-size: 16px;
  color: var(--petrol); text-decoration: none;
}
.text-link:hover { color: var(--petrol-mid); }
.text-link .arrow { transition: transform .18s ease; }
.text-link:hover .arrow { transform: translateX(4px); }

/* --- Form ---------------------------------------------------------------- */
.field { margin-bottom: 18px; }
.field label {
  display: block;
  font-family: var(--font-display);
  font-weight: 600; font-size: 14px;
  color: var(--charcoal);
  margin-bottom: 7px;
}
.input {
  width: 100%;
  height: 54px;
  padding: 0 16px;
  font-family: var(--font-body); font-size: 16px;
  color: var(--charcoal);
  background: var(--white);
  border: 1.5px solid var(--hairline);
  border-radius: 10px;
}
.input:focus { outline: 3px solid var(--petrol-tint); border-color: var(--petrol); }
textarea.input { height: auto; min-height: 130px; padding: 14px 16px; line-height: 1.5; resize: vertical; }

/* Honeypot — hidden from people, catches spam bots that fill everything in */
.honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-panel {
  border-radius: 16px;
  padding: 22px 24px;
  font-size: 15.5px;
}
.form-panel--ok    { background: var(--petrol-tint); color: var(--charcoal); }
.form-panel--error { background: #FCEBEA; color: #7A2018; border: 1px solid #F0C4C0; }
.form-panel h3 { margin-bottom: 6px; }

/* A quiet note panel — used to flag "content coming" honestly */
.note {
  background: var(--petrol-tint);
  border-radius: 16px;
  padding: 20px 24px;
  color: var(--charcoal);
  font-size: 15.5px;
  max-width: 80ch;   /* stop the text running the full width of a big screen */
}

/* --- Text beside a picture (About page) -----------------------------------
   Reading column on the left at its normal width, image in the space that was
   otherwise empty on the right. Stretched rather than top-aligned, so the
   picture always finishes level with the text it belongs to. */
.with-figure {
  display: grid;
  grid-template-columns: minmax(0, var(--measure)) minmax(0, 1fr);
  gap: 56px;
  align-items: stretch;
}
.page-body .with-figure { margin-top: 46px; }
.page-body .with-figure:first-child { margin-top: 0; }
.with-figure > div > :last-child { margin-bottom: 0; }

/* Placeholder for a photo that hasn't been taken yet. Deliberately obvious —
   it must never be mistaken for a finished part of the page. Swap the whole
   .photo-slot element for an <img class="section-photo"> when the real photo
   exists. */
.photo-slot {
  min-height: 220px;
  border: 2px dashed #BFD4CF;
  border-radius: 16px;
  background: var(--petrol-tint);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 6px; padding: 24px; text-align: center;
}
.photo-slot strong {
  font-family: var(--font-display);
  font-weight: 700; font-size: 13px;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--petrol);
}
.photo-slot span { font-size: 14px; line-height: 1.45; color: var(--warm-grey); max-width: 34ch; }

/* What a real photo in that slot should look like */
.section-photo {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 16px;
  box-shadow: var(--shadow-lift);
}

/* An illustration rather than a photograph. Two differences from .section-photo:
   it keeps its own proportions instead of being cropped to the height of the
   text, and its left edge dissolves into the page rather than ending in a hard
   line. The fade is a mask to transparent, not a white overlay, so it always
   matches the page colour even if --paper changes. No shadow, because a shadow
   round a dissolving edge looks like a mistake. */
/* An illustration keeps its own height, so it's often taller than a short
   piece of text. Centring the text against it stops the section looking
   bottom-heavy with a pool of empty space under the words. */
.with-figure--illus > div { display: flex; flex-direction: column; justify-content: center; }
.section-illus {
  align-self: start;
  width: 100%; height: auto;
  border-radius: 0 16px 16px 0;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,0.5) 11%, #000 30%);
          mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,0.5) 11%, #000 30%);
}

/* --- Illustrations on a dark body: bleed, don't sit in a column -------------

   David's brief (2026-07-28): make them darker so white text stays readable
   over them, let them fill more of the section, keep all three a consistent
   size, and let the last third of the text overlap the picture — so the
   section reads as one continuous gradient from black into the artwork,
   rather than a text column next to a picture box.

   How it's done: the picture stops being a grid cell and becomes a layer.
   The section turns into a single-column block with the image positioned over
   its right-hand side, and the text sitting on top at a higher z-index. The
   text column is still capped at --measure, so where the two meet, the words
   run over the faded part of the picture. That overlap IS the effect.

   Consistency comes from `object-fit: cover` plus a full-height image: every
   picture fills the same shape whatever its own proportions, cropping rather
   than letterboxing. That's the "zoom in and expand" — the artwork is scaled
   up and trimmed, so a 4:3 illustration can fill a much wider space.

   --illus-reach  how far across the section the picture comes
   --illus-dim    brightness; lower = darker, so white text reads more easily
   ------------------------------------------------------------------------- */
.page-body--dark .with-figure--illus {
  --illus-reach: 68%;
  --illus-dim: 0.42;
  position: relative;
  display: block;               /* was a grid — the picture is a layer now */
  min-height: 460px;            /* the consistent size, whatever the text length */
  overflow: hidden;
  padding-block: 8px;
  margin-top: 32px;             /* halved from 64 — David's call, tighter stack */
  /* Subtly rounded on the RIGHT ONLY, where the picture meets the frame edge.
     Put on the section rather than the <img> so `overflow: hidden` does the
     clipping: that way the rounding survives even when --illus-zoom pushes the
     image out past the section edge, which a radius on the image itself would
     not. Left corners stay square — that side dissolves into the page anyway,
     so there's no edge there to round. */
  border-radius: 0 8px 8px 0;
  /* .wrap holds everything --gutter in from the frame edge. The picture is the
     one thing that shouldn't respect that: pulling the section's right edge out
     by exactly the gutter lets the artwork run to the edge of the site frame
     and bleed off it, instead of stopping short and reading as a panel. */
  margin-right: calc(var(--gutter) * -1);
}
.page-body--dark .with-figure--illus > div {
  position: relative; z-index: 2;
  max-width: var(--measure);
  min-height: 444px;            /* keeps short sections as tall as the picture */
  justify-content: center;
}
.page-body--dark .section-illus {
  position: absolute; z-index: 1;
  top: 0; right: 0; bottom: 0; left: auto;
  /* --illus-zoom enlarges the artwork without moving where it starts.
     The element is made wider by the zoom factor and the extra hangs off the
     right, where the section's `overflow: hidden` trims it. Because the crop is
     "cover", a wider box means a bigger scale, which means the artwork is taller
     than the band by more — and THAT is what buys extra room to raise the
     subject once --illus-focus has hit its 100% ceiling.

     Deliberately done by resizing the element rather than with `transform:
     scale()`: a transform would scale the fade mask too, dragging the soft left
     edge off the side and leaving a hard one. The left edge stays put here. */
  right: calc(var(--illus-reach) * (var(--illus-zoom, 1) - 1) * -1);
  width: calc(var(--illus-reach) * var(--illus-zoom, 1));
  height: 100%;
  object-fit: cover;
  /* Because the artwork is cropped rather than fitted, something has to decide
     WHICH part survives the crop. --illus-focus is that choice, set per picture
     on the <img> in about.html since it depends on where the subject sits in
     each one. It's the vertical focal point: 50% takes the middle, and a HIGHER
     number keeps more of the bottom of the artwork — which shifts the picture
     visually upward in its frame. */
  object-position: 50% var(--illus-focus, 50%);
  border-radius: 0;             /* it bleeds off the edge now, so nothing to round */
  filter: brightness(var(--illus-dim)) contrast(0.94) saturate(0.92);
  /* Left-to-right, and deliberately long and gradual: the picture is still
     ghosting in under the tail of the text at 30%, and only reaches full
     strength near its right-hand edge. A short fade would read as a soft-edged
     box; a long one reads as the page turning into the picture. */
  /* One mask only, left to right. A top-and-bottom fade was tried and David
     didn't like it — the picture keeps clean horizontal edges. */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,0.28) 22%, rgba(0,0,0,0.62) 46%, rgba(0,0,0,0.88) 72%, #000 100%);
          mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,0.28) 22%, rgba(0,0,0,0.62) 46%, rgba(0,0,0,0.88) 72%, #000 100%);
  pointer-events: none;
}

/* Text and picture stack until there's genuinely room for both side by side.
   The text column alone wants 760px (--measure) plus a 56px gap, so between
   760px and about 1080px the picture was being squeezed to a sliver — and
   since its left edge is faded, a sliver reads as "the image has vanished".
   Stacking it instead keeps it full width and readable. Deliberately a higher
   breakpoint than the site's usual 760px one, and it must sit after the rules
   it overrides. */
@media (max-width: 1080px) {
  .with-figure { grid-template-columns: 1fr; gap: 24px; }
  .photo-slot { aspect-ratio: 4 / 3; min-height: 0; }

  /* Once the layout goes vertical there's no "right-hand side" left to fade
     into, so the whole effect rotates: the gradient runs TOP TO BOTTOM instead
     of left to right. Text occupies the dark top of the block and the picture
     emerges beneath it, which is the same idea — page turning into artwork —
     read down the screen rather than across it. David's call, 2026-07-28.

     The picture is dimmed further here (0.34 vs 0.42) because the text now sits
     directly over the middle of it rather than over its faded tail. */
  .page-body--dark .with-figure--illus {
    --illus-dim: 0.34;
    min-height: 0;
    padding-bottom: 200px;      /* the strip where the picture comes through */
    /* Stacked, the picture wants the full width, so the section bleeds out
       through the gutter on BOTH sides rather than just the right. The text
       inside is pushed back in by the same amount so it keeps the page's one
       shared left margin. */
    margin-inline: calc(var(--gutter) * -1);
  }
  .page-body--dark .with-figure--illus > div { padding-inline: var(--gutter); }
  .page-body--dark .with-figure--illus > div {
    min-height: 0;
    max-width: 100%;
  }
  .page-body--dark .section-illus {
    left: 0; width: 100%; height: 100%;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.22) 26%, rgba(0,0,0,0.58) 54%, rgba(0,0,0,0.88) 78%, #000 100%);
            mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.22) 26%, rgba(0,0,0,0.58) 54%, rgba(0,0,0,0.88) 78%, #000 100%);
  }
}


/* Labelled facts — "Specialisations", "Track record", "Tools" and so on.
   A description list, so a screen reader hears each label with its value.
   Each dt/dd pair is wrapped in a div so the pairs can be laid out in
   columns without a label being split from its value. */
.facts { margin: 0; }
.facts dt {
  font-family: var(--font-display);
  font-weight: 700; font-size: 12px;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--petrol);
  margin: 0;
}
.facts dd { margin: 5px 0 0; }
h2 + .facts { margin-top: 26px; }
.facts--grid {
  display: grid;
  /* 460px is chosen so this settles on two columns at full width rather than
     three — three left a ragged hole in the bottom-right corner. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr));
  gap: 28px 56px;
}

/* A pull-quote — for the one line on a page that deserves to stand up */
.callout {
  border-left: 3px solid var(--petrol);
  padding-left: 26px;
  margin: 36px 0;
  font-family: var(--font-display);
  font-weight: 500; font-size: 21px; line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--charcoal);
  max-width: var(--measure);
}
.callout p { margin: 0 0 12px; }
.callout p:last-child { margin-bottom: 0; }

/* A plain run of text with no picture beside it, held to the reading width.
   Same cap as .callout and the text column of .with-figure, so a section
   without an illustration still lines up with the ones that have one. */
.prose { max-width: var(--measure); margin: 46px 0 0; }

/* Closing call to action — a tinted band across the foot of a content page */
.cta-band { background: var(--petrol-tint); }
.cta-band p { max-width: 60ch; }

/* On a dark body the pale tint is a disaster: .page-body--dark turns the text
   white, so white lands on near-white — measured at 1.16:1 on the live About
   page, against an accessible minimum of 4.5:1. Invisible, on the one element
   whose whole job is getting people to make contact.

   So on a dark body the band inverts: solid petrol instead of petrol tint. It
   still reads as "the tinted band", still uses a brand colour, and white text
   on it measures 9:1. It also gives the band something the pale version had for
   free — it stands out from the near-black page around it.

   The button then has to flip too, exactly as it does on the landing page's
   green slide: petrol-on-petrol would vanish, so the primary action goes white.
   Same problem, same fix, kept deliberately consistent. */
.page-body--dark .cta-band { background: var(--petrol); }
.page-body--dark .cta-band :is(h2, h3) { color: var(--on-dark); }
.page-body--dark .cta-band p { color: var(--on-dark-82); }
.page-body--dark .cta-band .btn-primary { background: var(--white); color: var(--charcoal); }
.page-body--dark .cta-band .btn-primary:hover { background: var(--petrol-tint); color: var(--charcoal); }

/* --- Footer -------------------------------------------------------------- */
.site-footer {
  background: var(--charcoal);
  color: var(--on-dark-65);
  font-size: 14px;
}
.site-footer .wrap { padding-block: 40px; display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.site-footer a { color: var(--on-dark-82); text-decoration: none; }
.site-footer a:hover { color: var(--on-dark); }

@media (max-width: 760px) {
  .grid-3, .grid-2 { grid-template-columns: 1fr; }
  .wrap { padding-block: 48px; }
  .page-hero { min-height: 44vh; padding-top: 104px; }
  .callout { font-size: 19px; padding-left: 20px; }

  /* On a phone the hero photo becomes a faint backdrop, the same trick the
     landing page uses, so the headline can run the full width */
  .page-hero--portrait { min-height: 56vh; }
  .page-hero--portrait .page-hero__inner { max-width: 100%; }
  .hero-photo {
    width: 100%;
    opacity: 0.34;
    /* The photo is portrait (1000x1333) stretched to the full window width, in
       a hero of fixed height — so the wider the window, the more of the bottom
       gets cropped. At 760px wide roughly 440px of picture is discarded. The
       face sits low in the frame, so anchoring near the top (16%) cut David off
       at the mouth anywhere above ~500px wide. 45% keeps the whole head in shot
       across the entire mobile range. */
    object-position: 50% 45%;
    -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
  }
}

/* ==========================================================================
   Respect "reduce motion" — some people get motion sickness from drifting
   backgrounds. The JS also stops auto-advancing when this is switched on.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .slide { animation: none; transition: none; }
  .landing-inner, .page-hero__inner { animation: none; }
  .message { transition: none; }
  * { scroll-behavior: auto !important; }
}
