/* ============================================================
   AFRIKAN SPATIAL GRID — DESIGN SYSTEM

   Quiet and conventional on purpose. White ground, a soft tint
   for alternate bands, one near-black band, one green band. A
   single typeface, a single accent colour, hairline rules and
   soft radii. Nothing here should draw attention to itself —
   the work in the images and the project record is the content.

   Source imagery is 300-550px wide (extracted from the company
   profile), so figures are capped at native size and never
   upscaled. See the `plate` shortcode in eleventy.config.js.
   ============================================================ */

:root {
  /* --- Surface & ink --- */
  --white:      #FFFFFF;
  --tint:       #EFF4F0;
  --dark:       #0E1512;
  --ink:        #0F1714;
  --ink-2:      #26302B;
  --slate:      #57625C;
  --slate-2:    #626D67;   /* passes 4.5:1 on white AND on --tint */
  --rule:       #E3E8E5;
  --rule-2:     #C9D2CC;
  /* A neutral hover ground. Deliberately NOT --tint: the press bar sits
     directly on top of a .section--tint, and tinting it on hover erased the
     boundary between the two. */
  --wash:       #F5F6F5;

  /* --- Accent — one colour, used sparingly --- */
  --accent:      #1B5230;
  --accent-deep: #123A21;
  --accent-soft: #EAF1EC;

  /* --- Type --- */
  --f: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* --- Metrics --- */
  --shell: 1280px;
  --gutter: 22px;
  --sec: 72px;
  --r: 6px;
  --r-s: 4px;
  --r-pill: 999px;   /* buttons and chips only */
}

@media (min-width: 700px)  { :root { --gutter: 32px; --sec: 96px; } }
@media (min-width: 1100px) { :root { --sec: 112px; } }

*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--white);
  color: var(--slate);
  font-family: var(--f);
  font-size: 16px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  /* the off-canvas nav sits outside the viewport; clip rather than scroll */
  overflow-x: clip;
}

/* height:auto matters: an <img> carrying width/height attributes (which every
   image here does, to reserve layout space) otherwise keeps the attribute
   height as a presentational style while CSS overrides only the width — which
   stretched the hero photo vertically. */
img { max-width: 100%; height: auto; display: block; }
/* The `hidden` attribute has to win. A UA stylesheet's [hidden]{display:none}
   loses to ANY author rule that sets display, so `.entry { display: grid }`
   silently defeated the project filter, which hides entries by setting
   `hidden`. Keep this ahead of every component that sets its own display. */
[hidden] { display: none !important; }
a { color: inherit; text-decoration: none; }

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

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: #fff; padding: 12px 18px;
  font-size: 0.9rem; border-radius: 0 0 var(--r-s) 0;
}
.skip-link:focus { left: 0; }

/* ============================================================
   TYPE
   ============================================================ */

h1, h2, h3, h4 {
  color: var(--ink);
  margin: 0 0 0.5em;
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.025em;
}

h1 { font-size: clamp(2.25rem, 5vw, 3.5rem); line-height: 1.08; }
h2 { font-size: clamp(1.6rem, 3vw, 2.35rem); }
h3 { font-size: 1.16rem; letter-spacing: -0.015em; }
h4 { font-size: 1rem; letter-spacing: -0.01em; }

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }
strong { color: var(--ink-2); font-weight: 600; }
em { color: inherit; }

.lede {
  font-size: clamp(1.02rem, 1.3vw, 1.15rem);
  line-height: 1.62;
  max-width: 58ch;
}

/* Small green section label. The arrow is decorative. */
.kicker {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.005em;
  color: var(--accent);
  margin: 0 0 18px;
}
.kicker::before { content: '\2192'; margin-right: 0.55em; }
.kicker--plain::before { content: none; }
.kicker--muted { color: var(--slate-2); font-weight: 500; }

/* ============================================================
   LAYOUT PRIMITIVES
   ============================================================ */

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

.section { padding-block: var(--sec); }
.page-head + .section, .page-head + .section--tight { padding-top: calc(var(--sec) * 0.6); }
.section--tight { padding-block: calc(var(--sec) * 0.66); }
.section--tint { background: var(--tint); }
.section--dark { background: var(--dark); color: rgba(255,255,255,0.74); }
.section--dark h2, .section--dark h3, .section--dark h4 { color: #fff; }
.section--dark .kicker { color: #8FCBA3; }
.section--dark .link { color: #8FCBA3; }
.section--dark .link:hover { color: #fff; }

/* Section heading — kicker, headline, one line of context. */
.head { max-width: 62ch; margin-bottom: clamp(34px, 4vw, 52px); }
.head h2 { margin-bottom: 0.4em; }
.head p { font-size: 1.02rem; max-width: 56ch; }
/* ============================================================
   HEADER / NAV
   ============================================================ */

.site-header {
  position: sticky; top: 0; z-index: 100;
  border-bottom: 1px solid var(--rule);
}

/* The frosted backdrop lives on a pseudo-element, NOT on .site-header itself.
   backdrop-filter (like transform and filter) makes an element a containing
   block for position:fixed descendants — putting it on the header sized the
   fixed mobile nav panel to the 68px header instead of the viewport, clipping
   every item after the first. Do not move these two properties onto the
   header, or the mobile menu breaks. */
.site-header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
}

.nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 68px;
}

.brand { display: flex; align-items: center; gap: 11px; padding-block: 8px; }
.brand img { width: 40px; height: 40px; }
.brand-text { display: flex; flex-direction: column; gap: 3px; }
.brand-name {
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.1;
  letter-spacing: -0.025em;
  color: var(--ink);
  white-space: nowrap;
}
/* The motto sits under the name, in the same letterspaced caps as the
   footer. It is the widest part of the brand, so it drops out on narrow
   phones rather than crowding the menu button. */
.brand-suffix { font-weight: 500; color: var(--slate-2); }
.brand-motto {
  font-size: 0.61rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  line-height: 1;
  color: var(--accent);
  white-space: nowrap;
}
@media (max-width: 420px) { .site-header .brand-motto { display: none; } }

.nav-links { display: flex; align-items: center; gap: 32px; }
.nav-links a {
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--slate);
  padding-block: 6px;
  transition: color 0.15s ease;
}
.nav-links a:hover { color: var(--ink); }
.nav-links a.active { color: var(--ink); font-weight: 600; }
.nav-links .nav-cta {
  border: 1px solid var(--accent);
  border-radius: var(--r-pill);
  padding: 10px 19px;
  color: var(--accent);
  font-weight: 600;
}
.nav-links .nav-cta:hover { background: var(--accent); color: #fff; }

.nav-toggle {
  display: none;
  background: none; border: 0; cursor: pointer;
  width: 44px; height: 44px; padding: 10px;
  margin-right: -10px;
}
.nav-toggle span {
  display: block; width: 22px; height: 1.5px;
  background: var(--ink); margin: 5px 0;
  transition: transform 0.25s ease, opacity 0.2s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

@media (max-width: 900px) {
  .nav-toggle { display: block; }
  /* The panel is a child of the header, so it shares the header's stacking
     context and would paint over the brand and the close button. Lift both
     above it so the header stays usable while the menu is open. */
  .brand, .nav-toggle { position: relative; z-index: 101; }
  .nav-links {
    position: fixed; inset: 0;
    z-index: 99;
    background: var(--white);
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    padding: 90px var(--gutter) 40px;
    overflow-y: auto;
    transform: translateX(100%);
    visibility: hidden;
    /* visibility flips instantly on open so the panel is focusable in the
       same tick, and is held until the slide-out finishes on close. A
       transitioned visibility would still compute as hidden at t=0. */
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 0.3s;
  }
  .nav-links.open {
    transform: translateX(0);
    visibility: visible;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 0s;
  }
  .nav-links a {
    font-size: 1.08rem;
    padding: 18px 0;
    border-bottom: 1px solid var(--rule);
  }
  .nav-links a.active { color: var(--accent); }
  .nav-links .nav-cta {
    margin-top: 26px;
    text-align: center;
    padding: 16px;
    border: 1px solid var(--accent);
  }
}

body.nav-open { overflow: hidden; }

/* ============================================================
   BUTTONS & LINKS
   ============================================================ */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font-family: inherit;
  font-size: 0.94rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  padding: 13px 26px;
  min-height: 48px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-deep); }
.btn-ghost { border-color: var(--rule-2); color: var(--ink); }
.btn-ghost:hover { border-color: var(--ink); }
.btn-on-dark { background: #fff; color: var(--accent-deep); }
.btn-on-dark:hover { background: var(--accent-soft); }
.btn-ghost-on-dark { border-color: rgba(255,255,255,0.45); color: #fff; }
.btn-ghost-on-dark:hover { background: rgba(255,255,255,0.12); border-color: #fff; }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* A little smaller on phones, where two buttons side by side otherwise eat
   the full width. 44px is the floor — below that they stop being a reliable
   touch target. */
@media (max-width: 639px) {
  .btn { padding: 11px 21px; min-height: 44px; font-size: 0.9rem; }
}

.btn-row { display: flex; gap: 12px; flex-wrap: wrap; }

/* Inline text link with a trailing arrow. */
.link {
  display: inline-flex; align-items: center; gap: 0.45em;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--accent);
  transition: gap 0.16s ease, color 0.16s ease;
}
.link::after { content: '\2192'; }
.link:hover { color: var(--accent-deep); gap: 0.75em; }

/* ============================================================
   HERO
   ============================================================ */

.hero { position: relative; padding-block: clamp(52px, 7vw, 92px) clamp(48px, 6vw, 80px); }

/* A topographic contour wash — real iso-lines from a synthetic elevation
   field (see tools/generate-contours.py), which is the company's own output
   used as texture. Shared by the home hero and every inner page head, so
   the top of the site reads the same way throughout. Held at ~5% so it is
   paper grain, not pattern, and masked so it fades out before the band
   below. Decorative only. */
.hero::before, .page-head::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: url('/assets/img/contours.svg') center / cover no-repeat;
  opacity: 0.038;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
}
/* The page head sits on the tint, which eats a little of the line, so it
   runs a touch stronger than the hero's wash on white. */
.page-head::before { opacity: 0.046; }
/* Windows high-contrast strips background images anyway; be explicit. */
@media (forced-colors: active) {
  .hero::before, .page-head::before { display: none; }
}

.hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px 56px;
  align-items: center;
}
.hero h1 { max-width: 16ch; margin-bottom: 0.4em; }
.hero .lede { max-width: 52ch; }
.hero__actions { margin-top: 32px; }

/* A fixed box the photo fills. Cropped from the right (object-position: left)
   because the survey scale bar sits in the bottom-left corner and is the part
   of an orthomosaic export worth keeping. */
.hero__media img {
  width: 100%;
  aspect-ratio: 16 / 11;
  height: auto;
  object-fit: cover;
  object-position: left center;
  border: 1px solid var(--rule);
  border-radius: var(--r);
}

@media (min-width: 900px) {
  .hero__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr); }
}

/* Stacked, the hero reads as one block, so it wants less air above it and a
   tighter step down to the image than the two-column version does. */
@media (max-width: 639px) {
  .hero { padding-block: 48px 40px; }
  .hero__inner { gap: 28px; }
  .hero h1 { max-width: none; }
  .hero__actions { margin-top: 26px; }
  .hero__media img { aspect-ratio: 16 / 10; }
}

/* Stats — a plain row, no rules, no counters. */
.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px 24px;
  text-align: center;
}
.stats__val {
  font-size: clamp(1.75rem, 3.2vw, 2.35rem);
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.03em;
}
.stats__lbl { font-size: 0.88rem; color: var(--slate-2); margin-top: 8px; }
@media (min-width: 760px) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ============================================================
   FIGURES

   Plain rounded images with an optional quiet caption. Capped at
   native pixel width so a 380px survey export is never blown up
   to fill a 700px column.
   ============================================================ */

.plate { margin: 0; }
.plate img {
  width: 100%;
  height: auto;
  border-radius: var(--r-s);
  border: 1px solid var(--rule);
  background: var(--tint);
}
.plate--crop img { aspect-ratio: 4 / 3; object-fit: cover; }
.plate figcaption {
  margin-top: 10px;
  font-size: 0.82rem;
  color: var(--slate-2);
}
/* Flex rather than grid: each figure carries its own max-width (its native
   pixel size), so rigid equal columns would leave dead space beside the
   smaller ones. Figures grow to fill, stop at native size, and wrap. */
.plate-row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 18px;
}
.plate-row > .plate,
.field-strip > .plate { display: flex; flex-direction: column; }
.plate-row > .plate { flex: 1 1 230px; }
.plate-row > .plate figcaption,
.field-strip > .plate figcaption { margin-top: auto; padding-top: 10px; }

/* ============================================================
   CARD GRID — services, audiences, credentials
   ============================================================ */

.cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
}
@media (min-width: 640px) { .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 980px) { .cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 26px 24px;
  transition: border-color 0.16s ease;
}
.card h3 { margin: 0; }
.card p { font-size: 0.95rem; margin: 0; }
.card .link { margin-top: auto; padding-top: 14px; }
a.card:hover { border-color: var(--accent); }

/* A card with a thumbnail: the panel runs to the card's edges, so the padding
   moves off the card and onto the body. The panel is a fixed ratio with the
   image contained inside it, which keeps every card in the row the same height
   without cropping a portrait map or stretching a wide one. */
.card--media { padding: 0; overflow: hidden; }
/* The image is taken out of flow so the panel's height comes from the ratio
   alone. Left in flow, an intrinsically taller image (the portrait settlement
   map) outgrows aspect-ratio and every card in the row ends up a different
   height. 4:3 suits the mix: the maps are portrait, the photos landscape. */
.card__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--white);
  border-bottom: 1px solid var(--rule);
}
.card__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
/* Stands in where a capability has no exhibit of its own yet. Typographic on
   purpose — an empty panel reads as a broken image. */
.card__media--blank {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 3.5rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  color: var(--rule-2);
}
.card__body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
  padding: 24px;
}
.card__n {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.02em;
}

.section--tint .card { background: var(--white); }
.section--dark .card {
  background: rgba(255,255,255,0.045);
  border-color: rgba(255,255,255,0.1);
}
.section--dark .card p { color: rgba(255,255,255,0.68); }

/* Small green rule above a card heading, used on the dark band. */
.card__key {
  display: block; width: 24px; height: 2px;
  background: var(--accent);
  border-radius: 2px;
  margin-bottom: 6px;
}
.section--dark .card__key { background: #8FCBA3; }

/* ============================================================
   PROJECT LIST
   ============================================================ */

.project-list { display: grid; gap: 0; }

.entry {
  padding-block: clamp(34px, 4vw, 48px);
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px 44px;
  scroll-margin-top: 90px;
}
/* --first is set by the filter in main.js: once entries are hidden, the
   first one still showing is rarely :first-child, and without this it kept a
   rule and padding above it that belong between entries. */
.entry:first-child, .entry--first { border-top: 0; padding-top: 0; }
.entry__meta { display: flex; flex-direction: column; gap: 4px; }
.entry__loc { font-size: 0.85rem; font-weight: 600; color: var(--accent); }
.entry__date, .entry__scale { font-size: 0.82rem; color: var(--slate-2); }
.entry h3 { font-size: clamp(1.25rem, 2vw, 1.6rem); }
.entry__body p { max-width: 66ch; }
.entry__role { font-size: 0.88rem; color: var(--slate-2); margin-top: 12px; }
.entry__plates { margin-top: 24px; }

.entry--feature h3 { font-size: clamp(1.4rem, 2.5vw, 1.95rem); }

@media (min-width: 900px) {
  .entry { grid-template-columns: 200px minmax(0, 1fr); }
}

/* Compact secondary list */
.mini-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}
.mini-item {
  padding: 20px 0;
  border-bottom: 1px solid var(--rule);
}
.mini-item:first-child, .mini-list > .mini-item:nth-child(2) { border-top: 1px solid var(--rule); }
.mini-item h4 { margin-bottom: 4px; }
.mini-item p { font-size: 0.9rem; margin: 0; }
@media (max-width: 699px) {
  .mini-item:nth-child(2) { border-top: 0; }
}
@media (min-width: 700px) {
  .mini-list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 48px; }
}

/* Filter controls */
.filters {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin-bottom: 20px;
}
.filter-btn {
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 500;
  padding: 9px 18px;
  min-height: 42px;
  border: 1px solid var(--rule-2);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--slate);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}
.filter-btn:hover { border-color: var(--rule-2); color: var(--ink); }
.filter-btn[aria-pressed="true"] {
  background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 600;
}

.filter-count { font-size: 0.85rem; color: var(--slate-2); margin-bottom: 30px; }

/* ============================================================
   SERVICE DETAIL ROWS — plain alternating image / copy
   ============================================================ */

.svc {
  padding-block: clamp(40px, 5vw, 64px);
  border-bottom: 1px solid var(--rule);
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px 56px;
  align-items: center;
  scroll-margin-top: 90px;
}
.svc:first-child { padding-top: 0; }
.svc:last-child { border-bottom: 0; padding-bottom: 0; }
.svc__media { max-width: 520px; width: 100%; }
.svc__n { display: block; font-size: 0.85rem; font-weight: 600; color: var(--accent); margin-bottom: 10px; }
.svc h2 { font-size: clamp(1.45rem, 2.4vw, 2rem); }

@media (min-width: 880px) {
  .svc { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr); }
  .svc--flip .svc__media { order: 2; margin-left: auto; }
  /* a row with no image should run the full measure, not sit in one column */
  .svc--full { grid-template-columns: minmax(0, 1fr); }
  .svc--full .svc__copy { max-width: 70ch; }
}

.ticklist { list-style: none; padding: 0; margin: 20px 0 0; }
.ticklist li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 8px;
  font-size: 0.95rem;
}
.ticklist li::before {
  content: '';
  position: absolute; left: 2px; top: 11px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
}
/* ============================================================
   CLIENT LOGOS
   ============================================================ */

.clients { border-block: 1px solid var(--rule); }
.clients__inner { padding-block: clamp(40px, 5vw, 56px); }

.clients__delivered { text-align: center; }

/* Flex, not grid: with seven logos a four-column grid strands the last row
   of three against the left edge, while flex centres whatever the final row
   holds. The max-width is what forces the break at four — seven boxes would
   otherwise fit six-and-one across the 1280px shell. */
.clients__strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 30px 46px;
  max-width: 780px;
  margin: 26px auto 0;
}
/* The logos vary from 1:1 to 4.4:1, so constrain both axes and contain —
   a fixed height alone lets the wide wordmarks dominate the strip. */
.clients__strip img {
  height: 50px;
  width: 142px;
  object-fit: contain;
  object-position: center;
  opacity: 0.82;
  transition: opacity 0.18s ease;
}
.clients__strip img:hover { opacity: 1; }

/* Narrower caps step the row down to three logos, then two. Seven never
   divides evenly, so the last row always carries the remainder — centred. */
@media (max-width: 759px) {
  .clients__strip { gap: 26px 34px; max-width: 440px; }
  .clients__strip img { height: 44px; width: 124px; }
}
@media (max-width: 479px) {
  .clients__strip { gap: 24px 28px; max-width: 290px; }
  .clients__strip img { height: 40px; width: 118px; }
}

/* ============================================================
   PRESS
   ============================================================ */

/* Only a bottom rule: the clients strip above already closes with its own
   border-block, and two abutting 1px rules read as one heavy 2px line. */
.press-bar { border-bottom: 1px solid var(--rule); }
/* The link wraps the shell rather than being the shell, so its hover tint
   runs the full width of the bar instead of stopping at the 1280px column. */
.press-bar__link { display: block; transition: background-color 0.16s ease; }
.press-bar__link:hover { background: var(--wash); }
.press-bar__inner {
  display: flex; align-items: center; gap: 6px 24px;
  padding-block: clamp(20px, 2.4vw, 26px);
}

/* The magazine cover, cropped to its top so the drone and the pilot survive
   the crop and the cover's own headline (which the bar restates) does not. */
.press-bar__cover {
  flex: none;
  width: 56px; height: 76px;
  object-fit: cover;
  object-position: center top;
  border-radius: var(--r-s);
  border: 1px solid var(--rule);
}

.press-bar__copy { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 240px; }
.press-bar__kicker {
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--slate-2);
}
.press-bar__title { font-size: 1rem; color: var(--ink-2); }
.press-bar__title em { font-style: italic; }

.press-bar__cta {
  flex: none;
  display: inline-flex; align-items: center; gap: 0.45em;
  font-size: 0.92rem; font-weight: 600;
  color: var(--accent);
  transition: gap 0.16s ease;
}
.press-bar__cta::after { content: '\2192'; }
.press-bar__link:hover .press-bar__cta { gap: 0.75em; color: var(--accent-deep); }

/* Below the fold of a phone the cue would wrap onto its own line and read as
   a second link, so the whole bar being tappable carries it instead. */
@media (max-width: 620px) {
  .press-bar__cta { display: none; }
  .press-bar__inner { gap: 16px; }
}

/* Capped, not full-shell: against the 1280px shell the prose ran to about 110
   characters a line and the short right-hand column left a hole under it.
   A narrower cover and a real measure make the two columns finish together. */
.press-feature {
  display: grid;
  grid-template-columns: 1fr;
  gap: 30px 52px;
  align-items: start;
  max-width: 1000px;
}
@media (min-width: 860px) {
  .press-feature { grid-template-columns: minmax(0, 296px) minmax(0, 1fr); }
}

.press-feature__cover { margin: 0; }
.press-feature__cover img {
  width: 100%;
  border-radius: var(--r-s);
  border: 1px solid var(--rule);
}
.press-feature__cover figcaption {
  margin-top: 10px;
  font-size: 0.82rem;
  color: var(--slate-2);
}

.press-feature__body { max-width: 62ch; }

/* The one quotation in the piece, lifted out of the paragraph that used to
   bury it — it is also what gives the text column enough vertical rhythm to
   stand beside a tall magazine cover. */
.pull {
  margin: 26px 0;
  padding-left: 22px;
  border-left: 2px solid var(--accent);
}
.pull p {
  font-size: 1.18rem;
  line-height: 1.45;
  font-style: italic;
  color: var(--ink);
  margin-bottom: 10px;
}
.pull footer {
  font-size: 0.86rem;
  color: var(--slate-2);
}

/* ============================================================
   TEAM / CREDENTIALS / TIMELINE
   ============================================================ */

.team {
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px 44px;
  align-items: start;
}
.team__media { max-width: 280px; }
.team__role { font-size: 0.92rem; font-weight: 600; color: var(--accent); margin-bottom: 16px; }
@media (min-width: 800px) { .team { grid-template-columns: 280px minmax(0, 1fr); } }

.creds {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
}
@media (min-width: 760px) { .creds { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* Cards, so each mark gets a white panel of its own. The marks are three
   different shapes — a square crest, a wide wordmark, a roundel — and side by
   side in a 64px box they were too small to tell apart. */
.cred {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
}
.cred__mark {
  display: flex; align-items: center; justify-content: center;
  height: 140px;
  padding: 20px 26px;
  border-bottom: 1px solid var(--rule);
}
.cred__mark img {
  max-width: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}
/* Optical sizing. One shared height cap makes a 1:1 roundel look far smaller
   than a 3:1 wordmark, so each mark is capped to land on roughly the same
   area (~10-12k px²) instead of the same height. */
.cred__mark--wide img  { max-height: 58px; }   /* ISK wordmark, 3.1:1 */
.cred__mark--mid img   { max-height: 72px; }   /* KCAA wordmark, 2.3:1 */
.cred__mark--round img { max-height: 100px; }  /* LSB roundel, 1:1 */
/* Stands in until a credential's logo file is supplied. */
.cred__letters {
  font-weight: 700;
  font-size: 1.6rem;
  letter-spacing: 0.06em;
  color: var(--rule-2);
}
.cred__body { padding: 20px 22px 24px; }
.cred h3 { font-size: 1.02rem; margin-bottom: 0.3em; }
.cred p { font-size: 0.9rem; margin: 0; }

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li {
  display: grid;
  grid-template-columns: 68px minmax(0, 1fr);
  gap: 20px;
  padding: 20px 0;
  border-bottom: 1px solid var(--rule);
}
.timeline li:first-child { border-top: 1px solid var(--rule); }
.timeline .yr { font-size: 0.88rem; font-weight: 600; color: var(--accent); padding-top: 2px; }
.timeline h4 { margin-bottom: 3px; }
.timeline p { font-size: 0.9rem; margin: 0; }

.two-col {
  display: grid;
  grid-template-columns: 1fr;
  gap: 44px 56px;
}
@media (min-width: 880px) { .two-col { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.field-strip {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  margin-top: 32px;
}
@media (min-width: 560px) { .field-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ============================================================
   CTA BAND
   ============================================================ */

.cta { background: var(--accent); color: rgba(255,255,255,0.86); }
.cta__inner {
  padding-block: clamp(56px, 7vw, 84px);
  max-width: 60ch;
  margin-inline: auto;
  text-align: center;
}
.cta h2 { color: #fff; }
.cta p { color: rgba(255,255,255,0.84); font-size: 1.04rem; }
.cta .btn-row { margin-top: 30px; justify-content: center; }

/* ============================================================
   CONTACT
   ============================================================ */

.contact-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 44px 56px;
  align-items: start;
}
@media (min-width: 880px) { .contact-grid { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); } }

.form-card {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: clamp(24px, 3vw, 36px);
}

.field { margin-bottom: 18px; }
.field label {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink-2);
  margin-bottom: 7px;
}
.field input, .field select, .field textarea {
  width: 100%;
  padding: 13px 15px;
  min-height: 48px;
  border: 1px solid var(--rule-2);
  border-radius: var(--r-s);
  background: var(--white);
  color: var(--ink);
  font-family: inherit;
  font-size: 1rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(27, 82, 48, 0.14);
}
.field textarea { resize: vertical; min-height: 140px; }

.field-pair { display: grid; grid-template-columns: 1fr; gap: 0 18px; }
@media (min-width: 560px) { .field-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); } }


.notice {
  padding: 14px 16px; font-size: 0.93rem; margin-bottom: 20px;
  border: 1px solid; border-radius: var(--r-s);
}
.notice--ok { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-deep); }
.notice--err { background: #FBEBE8; border-color: #B4402A; color: #7E2D1E; }
.notice a { text-decoration: underline; color: inherit; }

.contact-block { padding: 18px 0; border-bottom: 1px solid var(--rule); }
.contact-block:first-child { border-top: 1px solid var(--rule); }
.contact-block h2 {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 6px;
  letter-spacing: 0;
}
.contact-block .val { font-size: 1rem; color: var(--ink); }
.contact-block a:hover { color: var(--accent); text-decoration: underline; }

.map { border-radius: var(--r); overflow: hidden; margin-top: 28px; border: 1px solid var(--rule); }
.map iframe { width: 100%; height: 280px; border: 0; display: block; }

/* ============================================================
   PAGE HEADER (interior pages)
   ============================================================ */

.page-head {
  position: relative;
  background: var(--tint);
  padding-block: clamp(44px, 5vw, 72px) clamp(44px, 5vw, 72px);
}
/* Lift the copy over the contour wash drawn by .page-head::before. */
.page-head > .shell { position: relative; z-index: 1; }
.page-head h1 { font-size: clamp(2rem, 4.2vw, 3.1rem); max-width: 20ch; }
.page-head .lede { max-width: 64ch; margin-top: 18px; }

/* ============================================================
   FOOTER
   ============================================================ */

.site-footer {
  background: var(--tint);
  border-top: 1px solid var(--rule);
  color: var(--slate);
  padding-block: clamp(48px, 6vw, 72px) 26px;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 38px;
  margin-bottom: 44px;
}
@media (min-width: 620px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 980px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1.2fr; gap: 40px; } }

/* The header's padding is there to make the sticky nav row 68px; in a footer
   column it would just be a dent above the tagline. */
.brand--footer { padding-block: 0; margin-bottom: 16px; }
.footer-tagline { font-size: 0.98rem; color: var(--ink-2); margin: 0; }

.site-footer h2 {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 14px;
  letter-spacing: 0;
}
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 9px; }
.site-footer li a { font-size: 0.93rem; color: var(--slate); }
.site-footer li a:hover { color: var(--accent); text-decoration: underline; }
.footer-contact li { font-size: 0.93rem; line-height: 1.6; }

.footer-bottom {
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 10px;
  padding-top: 22px;
  border-top: 1px solid var(--rule-2);
  font-size: 0.85rem;
  color: var(--slate-2);
}

/* ============================================================
   MOTION — one fade, no travel, no stagger.
   ============================================================ */

.reveal { opacity: 0; transition: opacity 0.5s ease; }
.reveal.in { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal { opacity: 1; }
}

/* ============================================================
   UTILITIES
   ============================================================ */

.stack > * + * { margin-top: 1em; }
.mt-l { margin-top: clamp(32px, 4vw, 48px); }
.mt-m { margin-top: 24px; }
.measure { max-width: 64ch; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
