/* ==========================================================================
   Attune Intelligence — Light Theme
   Brand: Montserrat (headings), Barlow (body)
   Colors: Cream bg, Navy text, Blue accent
   ========================================================================== */

:root {
  /* Brand palette */
  --black: #101820;
  --blue: #5C88DA;
  --blue-hover: #4A73C2;
  --green: #9EB356;
  --gray-dark: #63666A;
  --gray-mid: #B1B3B3;
  --gray-light: #D9D9D6;
  
  /* Semantic colors - Light mode */
  --bg-primary: #FDFBF7;
  --bg-secondary: #FFFFFF;
  --bg-tertiary: #F5F3EF;
  --text-primary: #101820;
  --text-secondary: #63666A;
  --text-muted: #8A8D8F;
  --accent: #5C88DA;
  --accent-hover: #4A73C2;
  --border: rgba(16, 24, 32, 0.08);
  --border-strong: rgba(16, 24, 32, 0.15);
  
  /* Typography */
  --font-heading: 'Montserrat', sans-serif;
  --font-subheading: 'Barlow Condensed', sans-serif;
  --font-body: 'Barlow', sans-serif;
  
  /* Type scale */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 2rem;
  --text-4xl: 2.5rem;
  --text-5xl: 3.25rem;
  --text-display: clamp(2.75rem, 6vw, 4.75rem);
  
  /* Spacing */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;
  --space-4xl: 6rem;
  --space-5xl: 8rem;
  
  /* Layout */
  --container-max: 1200px;
  --container-narrow: 680px;
  --nav-height: 64px;

  /* Radius scale — hierarchical, not uniform. Inputs are tightest, media the
     softest, pills fully round. Every rounded element pulls from this. */
  --radius-sm: 6px;    /* inputs, small chips */
  --radius-md: 8px;    /* buttons */
  --radius-lg: 12px;   /* cards, plates */
  --radius-xl: 16px;   /* large media, modals */
  --radius-pill: 999px;
  
  /* Motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 150ms;
  --duration-base: 300ms;
  --duration-slow: 500ms;
}

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-height) + 2rem);
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 400;
  line-height: 1.7;
  color: var(--text-primary);
  background: var(--bg-primary);
  -webkit-font-smoothing: antialiased;
}

/* Typography */
h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 300;
  letter-spacing: 0.1em;
  line-height: 1.3;
  margin: 0;
  color: var(--text-primary);
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }

h3 {
  font-family: var(--font-subheading);
  font-weight: 500;
  font-size: var(--text-xl);
  letter-spacing: 0.02em;
}

p { margin: 0 0 var(--space-lg); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}

a:hover { color: var(--accent-hover); }

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

/* Layout */
.container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--space-xl);
}

.container-narrow {
  max-width: var(--container-narrow);
}

/* Section headers */
.section-header {
  margin-bottom: var(--space-2xl);
}

/* A header sits close to the block it introduces: collapse the doubled gap
   when a split or roster follows immediately, and let the following block's
   own top margin go. */
.section-header + .split,
.section-header + .roster {
  margin-top: 0;
}

.section-header-center {
  text-align: center;
}

.eyebrow {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-sm);
}

/* ==========================================================================
   Navigation
   ========================================================================== */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--nav-height);
  background: rgba(253, 251, 247, 0.72);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid transparent;
  transition: background var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}

/* On scroll the bar lifts off the page: more opaque, a hairline, a soft shadow. */
.nav.scrolled {
  background: rgba(253, 251, 247, 0.86);
  border-bottom-color: var(--border);
  box-shadow: 0 1px 20px -8px rgba(16, 24, 32, 0.18);
}

.nav-inner {
  max-width: var(--container-max);
  height: 100%;
  margin: 0 auto;
  padding: 0 var(--space-xl);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.nav-logo {
  display: inline-flex;
  align-items: center;
}

.nav-logo img {
  height: 25px;
  width: auto;
  transition: opacity 150ms var(--ease-out);
}

.nav-logo:hover img { opacity: 0.72; }

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-xl);
}

/* Peer links: a thin underline grows in from the left on hover, matching the
   .text-cta treatment used across the site. The link keeps a steady hit area. */
.nav-links a:not(.nav-contact) {
  position: relative;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-secondary);
  padding: 0.35rem 0;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1.5px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: color var(--duration-fast) var(--ease-out),
              background-size 220ms var(--ease-out);
}

.nav-links a:not(.nav-contact):hover {
  color: var(--text-primary);
  background-size: 100% 1.5px;
}

/* The active page: darker text and a persistent short underline so the current
   location is always legible, without looking like a hover. */
.nav-links a[aria-current="page"] {
  color: var(--text-primary);
  background-size: 100% 1.5px;
}

/* Contact is the terminal action: a filled pill, rounded to match the brand's
   other pills, distinct from the peer links so the money action never reads as
   navigation. */
.nav-contact {
  margin-left: var(--space-sm);
  padding: 0.45rem 1.05rem;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: #fff !important;
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  box-shadow: 0 1px 2px rgba(16, 24, 32, 0.12);
  transition: background 150ms var(--ease-out),
              box-shadow 150ms var(--ease-out),
              transform 150ms var(--ease-out);
}

.nav-contact:hover {
  background: var(--accent-hover);
  color: #fff !important;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px -4px rgba(92, 136, 218, 0.5);
}

.nav-contact:active {
  transform: translateY(0);
}

/* Hamburger button: hidden on desktop, shown on mobile. Three bars that
   morph into an X when the drawer is open. */
.nav-toggle {
  display: none;
  position: relative;
  width: 44px;
  height: 44px;
  margin-right: calc(-1 * var(--space-sm));
  background: none;
  border: none;
  cursor: pointer;
  z-index: 1002;
}

.nav-toggle-bar,
.nav-toggle-bar::before,
.nav-toggle-bar::after {
  position: absolute;
  left: 50%;
  width: 22px;
  height: 2px;
  background: var(--text-primary);
  border-radius: 2px;
  transform: translateX(-50%);
  transition: transform 300ms var(--ease-out), opacity 200ms var(--ease-out);
}

.nav-toggle-bar {
  top: 50%;
  margin-top: -1px;
}

.nav-toggle-bar::before { content: ""; top: -7px; }
.nav-toggle-bar::after  { content: ""; top: 7px; }

.nav-open .nav-toggle-bar { background: transparent; }
.nav-open .nav-toggle-bar::before { transform: translateX(-50%) translateY(7px) rotate(45deg); }
.nav-open .nav-toggle-bar::after  { transform: translateX(-50%) translateY(-7px) rotate(-45deg); }

/* Dim overlay behind the open drawer. */
.nav-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(16, 24, 32, 0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms var(--ease-out);
}

@media (max-width: 640px) {
  .nav-toggle { display: inline-flex; align-items: center; justify-content: center; }

  .nav-overlay { display: block; }
  .nav-open .nav-overlay { opacity: 1; pointer-events: auto; }

  /* The links become a slide-out drawer from the right. */
  .nav-links {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(78vw, 320px);
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: var(--space-lg);
    padding: calc(var(--nav-height) + var(--space-2xl)) var(--space-xl) var(--space-2xl);
    background: var(--bg-primary);
    border-left: 1px solid var(--border);
    box-shadow: -8px 0 40px -16px rgba(16, 24, 32, 0.4);
    transform: translateX(100%);
    transition: transform 340ms var(--ease-out);
    z-index: 1001;
    overflow-y: auto;
  }

  .nav-open .nav-links { transform: translateX(0); }

  /* Links read larger in the drawer, comfortable tap targets. */
  .nav-links a:not(.nav-contact) {
    font-size: var(--text-lg);
    padding: var(--space-sm) 0;
  }

  .nav-contact {
    margin-left: 0;
    margin-top: var(--space-md);
    padding: 0.75rem 1.4rem;
    font-size: var(--text-sm);
  }
}

/* Lock body scroll while the drawer is open. */
body.nav-locked { overflow: hidden; }

/* ==========================================================================
   Buttons
   ========================================================================== */

/* Buttons, from first principles: flat at rest, one tonal shift on hover,
   a 1px lift for life, a deeper press on active. No shadow, no sweep, no arrow.
   Hierarchy comes from fill (primary) vs. hairline (secondary), nothing more. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.85rem 1.6rem;
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  border-radius: var(--radius-md);
  border: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background 150ms var(--ease-out),
              color 150ms var(--ease-out),
              box-shadow 150ms var(--ease-out),
              transform 150ms var(--ease-out);
}

.btn:active { transform: translateY(0); }

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

.btn-full { width: 100%; }

/* ---- Primary: filled. Hover darkens one step + 1px lift. Active darkens more. */
.btn-primary,
.btn-primary:hover,
.btn-primary:active {
  color: #fff;
}

.btn-primary {
  background: var(--accent);
}

.btn-primary:hover {
  background: var(--accent-hover);
  transform: translateY(-1px);
}

.btn-primary:active {
  background: #3f63aa;
}

/* ---- Secondary: hairline. Hover fills to a faint tint + 1px lift. ---- */
.btn-outline {
  background: transparent;
  color: var(--text-primary);
  box-shadow: inset 0 0 0 1px var(--border-strong);
}

.btn-outline:hover {
  background: rgba(92, 136, 218, 0.07);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  transform: translateY(-1px);
}

.btn-outline:active {
  background: rgba(92, 136, 218, 0.12);
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  padding: calc(var(--nav-height) + var(--space-4xl)) 0 var(--space-4xl);
  background: var(--bg-primary);
  overflow: hidden;
}

.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

/* Soften the field behind the text so the headline stays crisp. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(
    130% 100% at 12% 45%,
    rgba(253, 251, 247, 0.92) 0%,
    rgba(253, 251, 247, 0.55) 42%,
    rgba(253, 251, 247, 0) 78%
  );
  pointer-events: none;
}

.hero .container {
  position: relative;
  z-index: 2;
}

.hero-content {
  max-width: 780px;
}

.hero-mark {
  width: 52px;
  height: auto;
  margin-bottom: var(--space-2xl);
}

/* Small uppercase line above the headline — the Z-pattern anchor. */
.hero-eyebrow {
  font-family: var(--font-heading);
  font-size: var(--text-sm);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-bottom: var(--space-lg);
}

.hero h1 {
  font-size: var(--text-display);
  font-weight: 300;
  line-height: 1.08;
  letter-spacing: 0.06em;
  color: var(--text-primary);
  margin-bottom: var(--space-xl);
  text-wrap: balance;
}

/* The pun on the company name: a refined, understated script against the
   upright geometric caps of the rest of the headline. Brand blue. */
.hero h1 em.script {
  font-family: 'Sacramento', cursive;
  font-style: normal;
  font-weight: 400;
  text-transform: lowercase;
  letter-spacing: 0;
  font-size: 1.35em;
  color: var(--accent);
}

/* Emphasis inside body copy: brand blue, upright — not the headline script. */
.hero-statement em {
  font-style: normal;
  font-weight: 500;
  color: var(--accent);
}

/* Second paragraph carries the thesis — slightly quieter than the first. */
.hero-thesis {
  font-size: var(--text-base);
  color: var(--text-muted);
}

.hero-thesis em {
  color: var(--text-secondary);
}

.hero-statement {
  color: var(--text-secondary);
  font-size: var(--text-lg);
  line-height: 1.75;
  max-width: 54ch;
  margin-bottom: var(--space-lg);
}

.hero-statement.hero-thesis {
  margin-bottom: var(--space-2xl);
}

.hero-cta {
  display: flex;
  gap: var(--space-md);
  flex-wrap: wrap;
}

/* Scroll cue — a single cell nucleus that descends a hairline track and
   settles at the base, echoing the Voronoi seeds above: a seed finding its
   place in the substrate. Wordless. Fades once the user scrolls. */
.hero-scroll {
  position: absolute;
  left: 50%;
  bottom: var(--space-xl);
  transform: translateX(-50%);
  z-index: 2;
  transition: opacity 400ms var(--ease-out);
}

.hero-scroll-track {
  position: relative;
  display: block;
  width: 1px;
  height: 46px;
  /* The track fades in at the top and out at the bottom, so the line reads
     as depth rather than a hard rule. */
  background: linear-gradient(
    to bottom,
    rgba(16, 24, 32, 0) 0%,
    rgba(16, 24, 32, 0.16) 30%,
    rgba(16, 24, 32, 0.16) 70%,
    rgba(16, 24, 32, 0) 100%
  );
}

/* The nucleus: same dark, low-opacity dot as the Voronoi seeds. */
.hero-scroll-seed {
  position: absolute;
  top: 0;
  left: 50%;
  width: 5px;
  height: 5px;
  margin-left: -2.5px;
  border-radius: 50%;
  background: var(--accent);
  animation: hero-settle 2.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

/* Descend, settle at the base with a soft pause, fade, re-emerge at the top. */
@keyframes hero-settle {
  0%   { top: 2px;  opacity: 0; transform: scale(0.6); }
  18%  { opacity: 1; transform: scale(1); }
  62%  { top: 40px; opacity: 1; transform: scale(1); }
  78%  { top: 40px; opacity: 0; transform: scale(0.85); }  /* settle + fade */
  100% { top: 40px; opacity: 0; transform: scale(0.85); }  /* hold before restart */
}

.hero-scroll:hover .hero-scroll-seed {
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(92, 136, 218, 0.12);
}

/* Hidden once the user has begun scrolling (class toggled in JS). */
.hero-scroll.is-hidden {
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .hero-scroll-seed { animation: none; top: 20px; opacity: 0.7; }
}

/* ==========================================================================
   Research Section
   ========================================================================== */

.section-research {
  background: var(--bg-primary);
  padding: var(--space-5xl) 0;
}

.research-grid {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: var(--space-4xl);
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--space-xl);
  align-items: start;
}

.research-image {
  margin: 0;
}

.research-image img {
  width: 100%;
  border-radius: var(--radius-lg);
  box-shadow: 0 4px 24px rgba(16, 24, 32, 0.08);
}

.research-image figcaption {
  margin-top: var(--space-md);
  padding-left: var(--space-md);
  border-left: 2px solid var(--accent);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--text-muted);
  max-width: 52ch;
}

.research-content {
  padding-top: var(--space-md);
}

.research-body {
  margin-bottom: var(--space-2xl);
}

.research-body p {
  font-size: var(--text-lg);
  color: var(--text-secondary);
  line-height: 1.8;
}

/* Research as a full page: single column, figure centered and wide. */
.section-research-page {
  background: var(--bg-secondary);
  padding: var(--space-4xl) 0 var(--space-5xl);
}

.research-lead {
  max-width: 68ch;
  margin-bottom: var(--space-3xl);
}

.research-lead p {
  font-size: var(--text-lg);
  color: var(--text-secondary);
  line-height: 1.8;
}

.research-image-wide {
  max-width: 860px;
  margin: 0 auto var(--space-3xl);
}

.research-image-wide figcaption {
  max-width: none;
}

.research-outlook {
  max-width: 68ch;
  margin-top: var(--space-3xl);
  padding-top: var(--space-2xl);
  border-top: 1px solid var(--border);
}

.research-outlook h3 {
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-md);
}

.research-outlook p {
  color: var(--text-secondary);
  font-size: var(--text-lg);
  margin: 0;
}

.featured-paper {
  padding: var(--space-xl);
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-2xl);
  transition: border-color 200ms var(--ease-out);
}

.featured-paper:hover {
  border-color: var(--border-strong);
}

.paper-meta {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-sm);
}

.paper-venue {
  font-size: var(--text-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
}

.paper-sep {
  color: var(--gray-mid);
}

.paper-role {
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.paper-title {
  font-size: var(--text-xl);
  margin-bottom: var(--space-sm);
}

.paper-title a {
  color: var(--text-primary);
}

.paper-title a:hover {
  color: var(--accent);
}

.paper-authors {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-bottom: var(--space-md);
}

.paper-desc {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.7;
  margin-bottom: var(--space-lg);
}

/* Explicit read affordance. Arrow nudges on hover. */
.paper-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

.paper-cta::after {
  content: "\2192";
  font-family: var(--font-body);
  transition: transform 200ms var(--ease-out);
}

.paper-cta:hover::after {
  transform: translateX(3px);
}

.research-note {
  font-size: var(--text-sm);
  color: var(--text-muted);
  padding-left: var(--space-lg);
  border-left: 2px solid var(--border-strong);
}

/* ==========================================================================
   Shared: text CTA (arrow link) + "see more" row
   ========================================================================== */

/* A confident link with a forward arrow, pointing from a condensed home block
   to its full page. Quieter than the filled buttons (these are "learn more",
   not conversion actions) but sized and coloured to read clearly as a link. */
.text-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-family: var(--font-subheading);
  font-size: var(--text-xl);
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--accent);
  padding-bottom: 2px;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1.5px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size 250ms var(--ease-out), color 150ms var(--ease-out);
}

.text-cta::after {
  content: "\2192";
  font-family: var(--font-body);
  transition: transform 200ms var(--ease-out);
}

.text-cta:hover {
  color: var(--accent-hover);
  background-size: 100% 1.5px;   /* underline grows in from the left */
}

.text-cta:hover::after {
  transform: translateX(4px);
}

.section-more {
  margin-top: var(--space-2xl);
}

/* A single quiet line of proof under the Work stack. */
.work-proof {
  margin-top: var(--space-3xl);
  padding-top: var(--space-xl);
  border-top: 1px solid var(--border);
  max-width: 60ch;
  font-size: var(--text-base);
  color: var(--text-muted);
}
.work-proof + .section-more {
  margin-top: var(--space-lg);
}

/* CTA on the left, org link set apart on the right. */
.section-more-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-lg);
}

/* Org GitHub link as a clean chip, distinct from the arrow CTA. */
.gh-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.45em 0.9em;
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  transition: background 180ms var(--ease-out),
              border-color 180ms var(--ease-out),
              color 180ms var(--ease-out);
}

.gh-link svg { opacity: 0.85; flex-shrink: 0; }

.gh-link:hover {
  color: #fff;
  background: var(--text-primary);
  border-color: var(--text-primary);
}

/* ==========================================================================
   Moat band — the thesis, given a quiet spotlight.
   ========================================================================== */

.section-moat {
  background: var(--bg-tertiary);
  padding: var(--space-4xl) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.moat-thesis {
  font-family: var(--font-subheading);
  font-size: var(--text-3xl);
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-primary);
  margin-top: var(--space-md);
}

/* ==========================================================================
   Page hero — compact banner for inner pages (no Voronoi canvas).
   ========================================================================== */

.page-hero {
  padding: calc(var(--nav-height) + var(--space-4xl)) 0 var(--space-3xl);
  background: var(--bg-primary);
  border-bottom: 1px solid var(--border);
}

.page-hero .eyebrow {
  margin-bottom: var(--space-md);
}

.page-hero h1 {
  font-size: clamp(1.75rem, 6.5vw, var(--text-4xl));
  max-width: 18ch;
  text-wrap: balance;
}

.page-hero-lead {
  margin-top: var(--space-lg);
  font-size: var(--text-xl);
  color: var(--text-secondary);
  max-width: 60ch;
}

.page-hero-lead .script {
  font-family: 'Sacramento', cursive;
  font-size: 1.5em;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--accent);
  text-transform: none;
}

/* ==========================================================================
   Work Section
   ========================================================================== */

.section-work {
  background: var(--bg-primary);
  padding: var(--space-5xl) 0;
}

/* Lead statement — the thesis of the whole practice, given real weight. */
.approach {
  margin-bottom: var(--space-4xl);
}

.approach p {
  font-family: var(--font-subheading);
  font-size: var(--text-2xl);
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-primary);
  max-width: 24ch;
  margin-bottom: var(--space-lg);
}

.approach p + p {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: 400;
  line-height: 1.7;
  color: var(--text-secondary);
  max-width: 60ch;
}

.approach p:last-child {
  margin-bottom: 0;
}

/* Services — an ascending stack. The Work read as a single operation that
   rises from base matter (data, 01) to distilled intelligence (agents, 04).
   Rendered bottom-to-top: column-reverse puts 01 at the foot, 04 at the apex,
   while DOM order stays 01->04 for reading and accessibility. A continuous
   vertical axis threads the markers; weight lightens as the stack rises.
   The square markers and the apex diamond echo the logo's matter/quintessence. */
.services {
  list-style: none;
  margin: 0 0 var(--space-3xl);
  padding: 0;
  display: flex;
  flex-direction: column-reverse;   /* 01 renders at the bottom, 04 at the top */
  position: relative;
}

/* The axis: one hairline running the height of the stack, the spine of
   the operation. Drawn behind the markers. */
.services::before {
  content: "";
  position: absolute;
  left: calc(var(--service-axis) - 0.5px);
  top: var(--space-xl);
  bottom: var(--space-xl);
  width: 1px;
  background: linear-gradient(to top,
              var(--border-strong) 0%,
              var(--border) 70%,
              transparent 100%);
  z-index: 0;
}

:root { --service-axis: 22px; }

/* A traveling nucleus rides the axis upward, 01 -> 04, echoing the hero's
   scroll cue but ascending: a subtle, continuous cue that the stack reads
   from matter at the base to intelligence at the apex. */
.services-seed {
  position: absolute;
  left: calc(var(--service-axis) - 2.5px);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  z-index: 1;
  pointer-events: none;
  animation: services-rise 4.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

/* Rise from the base, settle at the apex with a soft pause, fade, re-emerge
   at the foot. bottom-anchored so the motion reads as climbing the stack. */
@keyframes services-rise {
  0%   { bottom: var(--space-xl); opacity: 0; transform: scale(0.6); }
  16%  { opacity: 0.9; transform: scale(1); }
  60%  { bottom: calc(100% - var(--space-xl) - 5px); opacity: 0.9; transform: scale(1); }
  76%  { bottom: calc(100% - var(--space-xl) - 5px); opacity: 0; transform: scale(0.85); }
  100% { bottom: calc(100% - var(--space-xl) - 5px); opacity: 0; transform: scale(0.85); }
}

@media (prefers-reduced-motion: reduce) {
  .services-seed { animation: none; opacity: 0; }
}

.service {
  position: relative;
  display: grid;
  grid-template-columns: calc(var(--service-axis) * 2) 1fr;
  gap: var(--space-xl);
  padding: var(--space-lg) 0;
  align-items: start;
}

.service + .service {
  border-top: 1px solid var(--border);
}

/* Marker sits centered on the axis: a small square (matter, bounded), graded
   from solid at the base to airy at the top. The apex is the blue diamond. */
.service-mark {
  grid-column: 1;
  grid-row: 1;
  justify-self: center;
  margin-top: 0.55rem;
  width: 11px;
  height: 11px;
  background: var(--text-primary);
  border: 1px solid var(--text-primary);
  z-index: 1;
  transition: transform 200ms var(--ease-out),
              background 200ms var(--ease-out);
}

/* Ascent: base is solid and heavy; each rung lighter and more open.
   Idle motion is graded by altitude, following the Great Work: dense matter
   at the foot barely stirs; each rung above loosens; the quintessence at the
   apex is the most alive. All slow, low-amplitude, and reduced-motion safe. */
.service-1 .service-mark {
  background: var(--text-primary);
  animation: matter-settle 7s var(--ease-out) infinite;
}
.service-2 .service-mark {
  background: rgba(16, 24, 32, 0.55);
  animation: matter-pulse 5.5s ease-in-out infinite;
}
.service-3 .service-mark {
  background: rgba(16, 24, 32, 0.25);
  animation: matter-shimmer 4.5s ease-in-out infinite;
}
.service-4 .service-mark { background: transparent; }

/* Quintessence: the distilled point at the top, rotated square = diamond,
   in brand blue, matching the logo's floating mark. It breathes a soft glow
   and turns almost imperceptibly, the only element that truly rises. */
.service-mark-apex {
  background: var(--accent) !important;
  border-color: var(--accent);
  transform: rotate(45deg);
  width: 12px;
  height: 12px;
  animation: quintessence 6s ease-in-out infinite;
}

/* 01 — matter barely breathes: a whisper of a density shift, no motion. */
@keyframes matter-settle {
  0%, 100% { box-shadow: 0 0 0 0 rgba(16, 24, 32, 0); }
  50%      { box-shadow: 0 0 0 1.5px rgba(16, 24, 32, 0.04); }
}

/* 02 — a slow pulse, matter just beginning to loosen. */
@keyframes matter-pulse {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.06); opacity: 0.9; }
}

/* 03 — a faint shimmer as the matter refines toward spirit. */
@keyframes matter-shimmer {
  0%, 100% { opacity: 0.7; transform: scale(0.98); }
  50%      { opacity: 1;   transform: scale(1.03); }
}

/* 04 — the quintessence: a soft breathing glow and the barest drift around
   its 45deg rest, never fully still. */
@keyframes quintessence {
  0%, 100% {
    transform: rotate(44deg) scale(1);
    box-shadow: 0 0 0 0 rgba(92, 136, 218, 0.22);
  }
  50% {
    transform: rotate(46deg) scale(1.04);
    box-shadow: 0 0 6px 1.5px rgba(92, 136, 218, 0.18);
  }
}

/* Hover intensifies a matter rung toward the accent, and pauses idle drift
   so the interaction reads cleanly. The apex is handled separately (it
   dissolves into the cell field), so exclude it here. */
.service:hover .service-mark:not(.service-mark-apex) {
  background: var(--accent);
  border-color: var(--accent);
  animation-play-state: paused;
  transform: scale(1.16) !important;
  box-shadow: 0 0 7px 1.5px rgba(92, 136, 218, 0.22) !important;
}

/* Apex is the one rung that comes alive. On hover the quintessence diamond
   dissolves and a living Voronoi field (generated + drifting in JS, echoing
   the hero) fades up across the card, faint enough to read over. */
.service-4 { position: relative; }

.service-mark-apex {
  transition: opacity 220ms var(--ease-out),
              transform 220ms var(--ease-out),
              background 200ms var(--ease-out);
}

/* Diamond -> field: the diamond quickly shrinks into its own point and fades
   as the field emerges from that same point. Fast in. */
.service-4:hover .service-mark-apex {
  opacity: 0;
  transform: rotate(45deg) scale(0.3);
}

/* The generated cell field spans the whole rung (bounded by the card) but
   grows out of the diamond: its transform-origin is the diamond's position,
   so on hover it blooms from that point outward to fill the card, then
   collapses back into it on leave. Fast, smooth, both directions. */
.apex-field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  opacity: 0;
  pointer-events: none;
  transform: scale(0.12);
  transform-origin: var(--service-axis) 1.05rem;   /* the diamond's point */
  transition: opacity 400ms var(--ease-out),
              transform 550ms var(--ease-out);
}

.service-4:hover .apex-field {
  opacity: 1;
  transform: scale(1);
}

/* Keep the rung's content above the field. */
.service-4 .service-num,
.service-4 .service-content {
  position: relative;
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  .service-mark,
  .service-mark-apex {
    animation: none !important;
  }
  /* No generated field; keep a quiet static hover cue on the diamond. */
  .apex-field { display: none; }
  .service-4:hover .service-mark-apex {
    opacity: 1;
    box-shadow: 0 0 8px 2px rgba(92, 136, 218, 0.35);
  }
}

/* Number rides just right of its marker; weight lightens up the stack. */
.service-num {
  grid-column: 2;
  grid-row: 1;
  font-family: var(--font-heading);
  font-size: var(--text-sm);
  font-weight: 400;
  letter-spacing: 0.15em;
  line-height: 1;
  margin-top: 0.5rem;
  color: var(--text-muted);
  transition: color 200ms var(--ease-out);
}

.service-1 .service-num { color: var(--text-secondary); }
.service-4 .service-num { color: var(--accent); }

.service:hover .service-num { color: var(--accent); }

.service-content {
  grid-column: 2;
  grid-row: 2;
  margin-top: var(--space-xs);
}

.service-content h3 {
  margin-bottom: var(--space-sm);
  color: var(--text-primary);
}

.service-content p {
  font-size: var(--text-base);
  color: var(--text-secondary);
  margin: 0;
  line-height: 1.6;
  max-width: 60ch;
}

/* How it works — quieter footnote, full width under the grid. */
.how-works,
.fit {
  max-width: 68ch;
}

.fit {
  margin-top: var(--space-3xl);
}

.how-works h3,
.fit h3 {
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-md);
}

.how-works p,
.fit p {
  color: var(--text-secondary);
  font-size: var(--text-lg);
  margin: 0;
}

/* Closing CTA — a natural next step after "what we do". */
.work-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-lg);
  margin-top: var(--space-3xl);
  padding-top: var(--space-2xl);
  border-top: 1px solid var(--border);
}

.work-cta p {
  font-family: var(--font-subheading);
  font-size: var(--text-2xl);
  font-weight: 500;
  color: var(--text-primary);
  margin: 0;
  max-width: 30ch;
}

/* ==========================================================================
   Open Source Section
   ========================================================================== */

.section-oss {
  background: var(--bg-secondary);
  padding: var(--space-5xl) 0;
}

.oss-intro,
.lab-intro {
  font-size: var(--text-lg);
  color: var(--text-secondary);
  max-width: 60ch;
  margin-bottom: var(--space-3xl);
}

.lab-outro {
  max-width: 60ch;
  margin-top: var(--space-3xl);
  padding-top: var(--space-2xl);
  border-top: 1px solid var(--border);
  color: var(--text-secondary);
}

.oss-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg);
}

.oss-card {
  display: flex;
  flex-direction: column;
  padding: var(--space-xl);
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: border-color 220ms var(--ease-out),
              transform 220ms var(--ease-out),
              box-shadow 220ms var(--ease-out);
}

.oss-card:hover {
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: 0 12px 32px -12px rgba(16, 24, 32, 0.18);
}

.oss-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-md);
}

.oss-card-head h3 {
  color: var(--text-primary);
  margin: 0;
}

.oss-status {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-heading);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
  white-space: nowrap;
}

/* Little pulsing dot so "coming soon" reads as active, not stalled. */
.oss-status::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--green);
  animation: oss-pulse 2.4s var(--ease-out) infinite;
}

@keyframes oss-pulse {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}

/* A live/steady status (a published series, not a pending build): solid dot,
   accent-coloured, no pulse. */
.oss-status-live {
  color: var(--accent);
}

.oss-status-live::before {
  animation: none;
  background: var(--accent);
}

/* A live repo: a real pill badge with the GitHub mark, signalling "shipped
   and clickable" rather than the pending green-dot status. */
.oss-badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.3em 0.7em;
  font-family: var(--font-heading);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-primary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: background 180ms var(--ease-out),
              border-color 180ms var(--ease-out),
              color 180ms var(--ease-out);
}

.oss-badge svg { opacity: 0.85; }

.oss-badge:hover {
  color: #fff;
  background: var(--text-primary);
  border-color: var(--text-primary);
}

.oss-card p {
  color: var(--text-secondary);
  font-size: var(--text-base);
  line-height: 1.6;
  margin: 0 0 var(--space-lg);
}

/* Tech stack tags — quiet, monospace, to signal what the repo is at a glance. */
.oss-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-lg);
  flex-grow: 1;
  align-content: flex-start;
}

.oss-tags span {
  font-family: ui-monospace, 'SF Mono', 'Menlo', monospace;
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--text-secondary);
  padding: 0.35em 0.7em;
  background: var(--bg-tertiary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  white-space: nowrap;
  transition: border-color 200ms var(--ease-out), color 200ms var(--ease-out);
}

.oss-card:hover .oss-tags span {
  border-color: var(--border-strong);
}

/* Inert until the repos are public — styled as a code path, not a link. */
.oss-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: ui-monospace, 'SF Mono', 'Menlo', monospace;
  font-size: 0.75rem;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
  padding-top: var(--space-md);
  word-break: break-all;
  transition: color 200ms var(--ease-out);
}

/* A leading terminal-style prompt glyph so the path reads as "a repo". */
.oss-link::before {
  content: "\2192";
  color: var(--gray-mid);
  flex-shrink: 0;
}

.oss-card:hover .oss-link {
  color: var(--text-secondary);
}

/* A live repo link (anchor) brightens to the accent on its own hover. */
a.oss-link:hover {
  color: var(--accent);
}

a.oss-link:hover::before {
  color: var(--accent);
}

/* "Coming soon" note: a status line, not a code path — drop the mono/arrow. */
.oss-link-soon {
  font-family: var(--font-body);
  font-style: italic;
  letter-spacing: 0;
}

.oss-link-soon::before {
  content: none;
}

/* ==========================================================================
   About Section
   ========================================================================== */

/* Home About sits on the tertiary tone so it rhymes with the Moat band:
   the page's two "conviction" moments share a look. */
.section-about {
  background: var(--bg-tertiary);
  padding: var(--space-5xl) 0;
}

/* On the dedicated About page the page-hero already carries the title,
   so the body needs a calmer top rhythm, and keeps the standard tone. */
.section-about-page {
  padding-top: var(--space-4xl);
  background: var(--bg-secondary);
}

.about-grid {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: var(--space-4xl);
  align-items: start;
}

.about-photo img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 50%;
  filter: grayscale(100%);
}

.about-content .section-header {
  margin-bottom: var(--space-lg);
}

.about-content p {
  color: var(--text-secondary);
  max-width: 520px;
}

.about-content p a {
  color: var(--accent);
  border-bottom: 1px solid transparent;
  transition: border-color 200ms var(--ease-out);
}

.about-content p a:hover {
  border-bottom-color: var(--accent);
}

/* Two paths out of the About teaser: the business, and the person. */
.about-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  margin-top: var(--space-xl);
}

/* Subsection labels on the /about page (What it is / Who it's for / Who runs it). */
.about-subhead {
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin: var(--space-xl) 0 var(--space-sm);
}

.about-subhead:first-child {
  margin-top: 0;
}

.social-links {
  display: flex;
  gap: var(--space-lg);
  margin-top: var(--space-xl);
}

.social-links a {
  color: var(--text-muted);
  transition: color var(--duration-fast);
}

.social-links a:hover {
  color: var(--accent);
}

/* Prominent link back to the personal site. Matches the .text-cta treatment
   for legibility, with an up-right arrow to signal it leaves the site. */
.about-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  margin-top: var(--space-xl);
  font-family: var(--font-subheading);
  font-size: var(--text-xl);
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--accent);
  padding-bottom: 2px;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1.5px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size 250ms var(--ease-out), color 150ms var(--ease-out);
}

.about-cta::after {
  content: "\2197";              /* up-right arrow: leaving the site */
  font-family: var(--font-body);
  transition: transform 200ms var(--ease-out);
}

.about-cta:hover {
  color: var(--accent-hover);
  background-size: 100% 1.5px;
}

.about-cta:hover::after {
  transform: translate(3px, -3px);
}

/* ==========================================================================
   Contact Section
   ========================================================================== */

.section-contact {
  background: var(--bg-primary);
  padding: var(--space-5xl) 0;
}

/* A warm lead-in under the heading, so the page closes with intent. */
.contact-lead {
  margin: var(--space-md) auto 0;
  max-width: 48ch;
  font-size: var(--text-lg);
  color: var(--text-secondary);
}

/* The form sits in a quiet card, a deliberate destination rather than
   fields floating on the page. */
.contact-form {
  margin-top: var(--space-2xl);
  padding: var(--space-2xl);
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: 0 8px 40px -20px rgba(16, 24, 32, 0.15);
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
}

.form-group {
  margin-bottom: var(--space-lg);
}

.form-group label {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-bottom: var(--space-sm);
}

.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  padding: 0.9rem 1.05rem;
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--text-primary);
  background: var(--bg-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color var(--duration-fast), box-shadow var(--duration-fast);
}

.form-group input::placeholder,
.form-group textarea::placeholder {
  color: var(--text-muted);
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(92, 136, 218, 0.12);
}

.form-group select {
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2363666A' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
}

.form-group textarea {
  resize: vertical;
  min-height: 140px;
}

/* Honeypot: kept out of view and out of the tab order, but not display:none
   (some bots skip hidden fields; this stays in the layout, just invisible). */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.cf-turnstile {
  margin-bottom: var(--space-lg);
}

.contact-form .btn-full {
  margin-top: var(--space-sm);
}

.contact-alt {
  text-align: center;
  margin-top: var(--space-xl);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* ==========================================================================
   CTA band — the shared close on every subpage. One canonical form lives on
   the homepage (#contact); subpages end on this band and send visitors there,
   so the form and its Turnstile/Lambda path exist in exactly one place.
   A quiet blue diamond (the quintessence mark) anchors it to the Work motif.
   ========================================================================== */

.cta-band {
  background: var(--bg-tertiary);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: var(--space-4xl) 0;
}

/* Copy and actions sit together, left-anchored, with a defined gap between
   them, so the button never slams to the far right leaving a cavern in the
   middle. The right edge is intentional whitespace. Actions align to the
   bottom of the copy, so the button lands on its closing line. */
.cta-band .container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  column-gap: var(--space-3xl);
  row-gap: var(--space-xl);
}

.cta-band-copy {
  flex: 1 1 30ch;
  max-width: 44ch;
}

/* The diamond mark, echoing the apex of the Work stack, set before the copy. */
.cta-band-copy::before {
  content: "";
  display: block;
  width: 12px;
  height: 12px;
  margin-bottom: var(--space-lg);
  background: var(--accent);
  transform: rotate(45deg);
}

.cta-band h2 {
  font-size: var(--text-3xl);
  line-height: 1.15;
  margin-bottom: var(--space-md);
}

.cta-band p {
  font-size: var(--text-lg);
  color: var(--text-secondary);
  margin: 0;
}

/* Button over email, stacked and left-aligned within the actions column. */
.cta-band-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
}

.cta-band-actions .btn { white-space: nowrap; }

/* The alternate email, quiet, sitting under the button. */
.cta-band-alt {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

@media (max-width: 720px) {
  .cta-band .container {
    flex-direction: column;
    align-items: stretch;
  }
  .cta-band-copy { flex: 1 1 auto; max-width: 100%; }
  .cta-band-actions { align-items: stretch; }
  .cta-band-actions .btn { text-align: center; }
}

/* ==========================================================================
   Testimonials — a rolling accordion. Each row is a person (face + name +
   role); one panel opens at a time to reveal the full quote. Hairline
   dividers, no colored chrome. The accent lives in the name and the toggle.
   ========================================================================== */
.section-testimonials {
  background: var(--bg-primary);
  padding: var(--space-5xl) 0;
}

/* A flat, editorial accordion: hairline rules, no boxes. The row is a name;
   opening it unfurls a large pull quote. The accent lives in the type. */
.accordion {
  max-width: 760px;
  border-top: 1px solid var(--border);
}

.tst {
  border-bottom: 1px solid var(--border);
}

.tst-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  padding: var(--space-xl) 0;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
}

.tst-head:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

.tst-face {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-pill);
  object-fit: cover;
  filter: grayscale(1);
  opacity: 0.75;
  transition: filter 300ms var(--ease-out), opacity 300ms var(--ease-out);
}

.tst-open .tst-face,
.tst-head:hover .tst-face { filter: grayscale(0); opacity: 1; }

.tst-who {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  flex: 1 1 auto;
}

.tst-name {
  font-family: var(--font-subheading);
  font-size: var(--text-2xl);
  font-weight: 500;
  letter-spacing: 0.005em;
  line-height: 1.15;
  color: var(--text-primary);
  transition: color 240ms var(--ease-out);
}

.tst-head:hover .tst-name,
.tst-open .tst-name { color: var(--accent); }

.tst-role {
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.4;
}

/* Toggle: a single hairline that rotates from + to just a horizontal rule. */
.tst-toggle {
  position: relative;
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  margin-left: var(--space-md);
}

.tst-toggle::before,
.tst-toggle::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  background: var(--gray-mid);
  transition: opacity 300ms var(--ease-out), background 240ms var(--ease-out);
}

.tst-toggle::before { width: 100%; height: 1px; transform: translate(-50%, -50%); }
.tst-toggle::after  { width: 1px; height: 100%; transform: translate(-50%, -50%); }

.tst-head:hover .tst-toggle::before,
.tst-head:hover .tst-toggle::after { background: var(--accent); }

.tst-open .tst-toggle::before { background: var(--accent); }
.tst-open .tst-toggle::after { opacity: 0; }

/* Panel animates open via grid-template-rows (auto-height, no magic max). */
.tst-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 450ms var(--ease-out);
}

.tst-open .tst-panel { grid-template-rows: 1fr; }

/* The blockquote is the sole grid child and must collapse to a true 0: keep
   ALL padding/margin off it so nothing peeks out when the row is closed. */
.tst-panel > blockquote {
  overflow: hidden;
  margin: 0;
  min-height: 0;
  padding: 0;
  max-width: 62ch;
}

/* Spacing lives on the paragraphs (inside the clipped track) instead. */
.tst-panel p {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: 400;
  line-height: 1.65;
  color: var(--text-secondary);
  padding-left: calc(48px + var(--space-lg));
}

.tst-panel p:first-child { padding-top: 0; }
.tst-panel p:last-of-type { padding-bottom: var(--space-2xl); }
.tst-panel p + p { margin-top: var(--space-lg); }

.tst-panel p:first-child::before {
  content: "\201C";
  color: var(--accent);
}

.tst-panel p:last-of-type::after {
  content: "\201D";
  color: var(--accent);
}

@media (max-width: 560px) {
  .tst-head { gap: var(--space-md); padding: var(--space-lg) 0; }
  .tst-face { width: 40px; height: 40px; }
  .tst-name { font-size: var(--text-xl); }
  .tst-panel p { font-size: var(--text-base, 1rem); padding-left: 0; }
}

/* ==========================================================================
   Subpage prose — shared rhythm for the expanded inner-page content.
   A measure that reads, a labelled subhead (uppercase eyebrow style), and a
   lead paragraph one step larger than body. Used across Work/Research/About.
   ========================================================================== */

.prose {
  max-width: 68ch;
}

.prose-lead p {
  font-size: var(--text-xl);
  line-height: 1.7;
  color: var(--text-secondary);
}

.prose p {
  color: var(--text-secondary);
  font-size: var(--text-lg);
  line-height: 1.8;
}

/* Section label: the uppercase accent used for inner subheads. Shares the
   look of .eyebrow but scoped to prose blocks so it can sit inline in flow. */
.prose-label,
.block-label {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-md);
}

/* A hairline divider carrying a small centered diamond, for separating the
   expanded sections of a subpage without a heavy rule. */
.rule-diamond {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  margin: var(--space-3xl) 0;
  color: var(--border-strong);
}

.rule-diamond::before,
.rule-diamond::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.rule-diamond span {
  width: 7px;
  height: 7px;
  background: var(--gray-mid);
  transform: rotate(45deg);
  flex-shrink: 0;
}

/* ==========================================================================
   Lab — rebuilt as three acts. The core layout primitive is .split, a
   full-width photo/text pairing that fills the page instead of leaving a dead
   right column. Nodes are stated once, in an authoritative roster.
   ========================================================================== */

/* Full-bleed hero image, edge to edge, short cinematic band. */
.lab-hero-figure {
  margin: 0;
}

.lab-hero-figure img {
  width: 100%;
  height: 52vh;
  min-height: 340px;
  max-height: 580px;
  object-fit: cover;
  object-position: center 42%;   /* keep the die centered when the band crops */
  display: block;
}

.lab-hero-figure figcaption {
  max-width: var(--container-max);
  margin: var(--space-md) auto 0;
  padding: 0 var(--space-xl);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--text-muted);
}

.lab-hero-figure figcaption b {
  font-weight: 500;
  color: var(--text-secondary);
}

/* ---- .split: the workhorse. A photo on one side, prose on the other, each
   filling half the width so no side sits empty. Alternate by adding
   .split--flip to swap sides. Vertically centered. ------------------------ */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4xl);
  align-items: start;
  margin: var(--space-3xl) 0;
}

.split--flip .split-media { order: 2; }

.split-media {
  margin: 0;
}

.split-media img {
  width: 100%;
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  display: block;
}

.split-media figcaption {
  margin-top: var(--space-sm);
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  line-height: 1.5;
  color: var(--text-muted);
}

.split-body h3 {
  font-family: var(--font-heading);
  font-weight: 300;
  font-size: var(--text-3xl);
  letter-spacing: 0.04em;
  color: var(--text-primary);
  margin-bottom: var(--space-md);
}

.split-body p {
  font-size: var(--text-lg);
  line-height: 1.75;
  color: var(--text-secondary);
}

.split-body p + p { margin-top: var(--space-md); }

/* ---- Node roster: every node stated once, compact, in one grid. Each is a
   name + arcana + role + one line of hardware. ---------------------------- */
.roster {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
  margin: var(--space-2xl) 0;
}

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

@media (max-width: 560px) {
  .roster { grid-template-columns: 1fr; }
}

.node {
  padding: var(--space-lg) var(--space-xl);
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: border-color 200ms var(--ease-out),
              box-shadow 200ms var(--ease-out),
              transform 200ms var(--ease-out);
}

.node:hover {
  border-color: var(--border-strong);
  box-shadow: 0 10px 30px -18px rgba(16, 24, 32, 0.28);
  transform: translateY(-2px);
}

.node-name {
  font-family: var(--font-subheading);
  font-size: var(--text-xl);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text-primary);
}

.node-arcana {
  display: block;
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0.1rem 0 var(--space-sm);
}

.node p {
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--text-secondary);
  margin: 0;
}

.node p b {
  color: var(--text-primary);
  font-weight: 500;
}

/* ---- The four agents: one faculty split four ways, a clean quartet. ------ */
.agents {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-lg);
  margin: var(--space-2xl) 0;
}

.agent {
  padding: var(--space-lg);
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: border-color 200ms var(--ease-out),
              box-shadow 200ms var(--ease-out),
              transform 200ms var(--ease-out);
}

.agent:hover {
  border-color: var(--border-strong);
  box-shadow: 0 10px 30px -18px rgba(16, 24, 32, 0.28);
  transform: translateY(-2px);
}

.agent-suit {
  font-family: var(--font-subheading);
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--text-primary);
}

.agent-element {
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
  margin: 0.15rem 0 var(--space-sm);
}

.agent p {
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--text-secondary);
  margin: 0;
}

/* In-development marker: a small dot + label, honest about what is wired. */
.wip {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  margin: 0 0 var(--space-md);
  font-family: var(--font-heading);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gray-dark);
}

.wip::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--green);
  animation: oss-pulse 2.4s var(--ease-out) infinite;
  flex-shrink: 0;
}

@media (max-width: 860px) {
  .split {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
    margin: var(--space-3xl) 0;
  }
  .split--flip .split-media { order: 0; }
  .agents { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 520px) {
  .agents { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  padding: var(--space-xl) 0;
  border-top: 1px solid var(--border);
  background: var(--bg-primary);
}

.footer-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.footer p {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin: 0;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-lg);
}

.footer a {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.footer a:hover {
  color: var(--accent);
}

/* Social icons sit at the end of the footer nav, set apart by a hairline. */
.footer-social {
  display: inline-flex;
  align-items: center;
  gap: var(--space-md);
  padding-left: var(--space-lg);
  border-left: 1px solid var(--border);
}

.footer-social a {
  display: inline-flex;
  color: var(--text-muted);
  transition: color 150ms var(--ease-out), transform 150ms var(--ease-out);
}

.footer-social a:hover {
  color: var(--accent);
  transform: translateY(-1px);
}

@media (max-width: 640px) {
  .footer-inner {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-md);
  }
}

/* ==========================================================================
   Animations
   ========================================================================== */

[data-animate] {
  opacity: 0;
  transform: translateY(24px);
}

[data-animate].is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1024px) {
  .research-grid {
    grid-template-columns: 1fr;
    gap: var(--space-2xl);
  }
  
  .research-image {
    order: -1;
    max-width: 600px;
  }
}

@media (max-width: 768px) {
  :root {
    --space-4xl: 4rem;
    --space-5xl: 5rem;
  }
  
  h1 { font-size: var(--text-2xl); }
  h2 { font-size: var(--text-xl); }
  
  .about-grid {
    grid-template-columns: 1fr;
    gap: var(--space-2xl);
  }
  
  .about-photo {
    max-width: 160px;
  }
  
  .oss-grid {
    grid-template-columns: 1fr;
  }
  
  .form-row {
    grid-template-columns: 1fr;
  }
  
  .footer-inner {
    flex-direction: column;
    gap: var(--space-md);
    text-align: center;
  }
}

@media (max-width: 480px) {
  .container {
    padding: 0 var(--space-lg);
  }
  
  .service {
    padding: var(--space-lg);
  }
  
  .service-num {
    font-size: var(--text-xs);
  }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  
  [data-animate] {
    opacity: 1;
    transform: none;
  }
}
