/* ===== Custom properties ===== */
:root {
  --bg-light: #f5f5f7;
  --bg-dark: #000000;
  --text-dark: #1d1d1f;
  --text-light: #f5f5f7;
  --text-light-muted: rgba(245, 245, 247, 0.7);
  --text-dark-muted: rgba(29, 29, 31, 0.7);
  --accent: #c9822c;
  --accent-on-light: #96621f; /* darker copper for text on the light bg — #c9822c is only 2.87:1 there, fails WCAG AA */
  --accent-contrast: #ffffff;

  --font-system: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --section-padding-y: clamp(3rem, 6vw, 6rem);
  --section-gap: clamp(1.5rem, 3vw, 3rem);
  /* Was a flat 1120px (1280px past 1440px, then frozen forever) — on
     external/Windows monitors that report their true CSS-pixel width
     (no Retina-style downscaling like macOS applies), that left a huge
     static gap on either side. This keeps growing, bounded, instead. */
  --container-width: clamp(1120px, 1000px + 20vw, 1600px);
  --container-padding-x: clamp(1.5rem, 5vw, 4rem);

  --headline-size: clamp(2.25rem, 5.5vw, 4.5rem);
  --section-heading-size: clamp(1.75rem, 4vw, 3rem);
  --body-size: clamp(1.0625rem, 1.2vw, 1.25rem);
}

/* ===== Reset ===== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
body {
  position: relative;
  margin: 0;
  font-family: var(--font-system);
  background: var(--bg-light);
  color: var(--text-dark);
  font-size: var(--body-size);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p, ul { margin: 0; }
ul { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

/* ===== Skip link ===== */
.skip-link {
  position: absolute;
  top: -100%;
  left: 1rem;
  background: var(--text-dark);
  color: var(--text-light);
  padding: 0.75rem 1.25rem;
  border-radius: 0.5rem;
  z-index: 100;
  transition: top 0.2s ease;
}
.skip-link:focus {
  top: 1rem;
}

/* ===== Focus states ===== */
a:focus-visible,
button:focus-visible {
  outline: 3px solid var(--accent-on-light);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ===== Site nav ===== */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem clamp(1.5rem, 5vw, 4rem);
  background: rgba(245, 245, 247, 0.8);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(29, 29, 31, 0.08);
}
.site-nav__brand {
  display: flex;
  align-items: center;
}
.site-nav__brand-mark {
  width: 2rem;
  height: 2rem;
  display: block;
  border-radius: 7px;
}
.site-nav__links {
  display: flex;
  gap: clamp(0.75rem, 2vw, 1.75rem);
}
.site-nav__links a {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text-dark-muted);
  transition: color 0.2s ease;
  white-space: nowrap;
}
.site-nav__links a:hover { color: var(--accent-on-light); }
.site-nav__links a { position: relative; }
.site-nav__links a.is-active { color: var(--text-dark); }
.site-nav__links a.is-active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.35rem;
  height: 2px;
  border-radius: 1px;
  background: var(--accent-on-light);
}
/* Reading-progress "signal" along the bottom edge of the sticky nav;
   script.js feeds --scroll-progress (0–1) from the scroll position. */
.site-nav__progress {
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 100%;
  height: 2px;
  background: var(--accent);
  transform: scaleX(var(--scroll-progress, 0));
  transform-origin: left center;
  pointer-events: none;
}
.site-nav__resume {
  font-size: 0.875rem;
  font-weight: 600;
  padding: 0.5rem 1.1rem;
  border-radius: 999px;
  background: var(--text-dark);
  color: var(--bg-light);
  white-space: nowrap;
  transition: background 0.2s ease;
}
.site-nav__resume:hover { background: var(--accent-on-light); }

.site-nav__toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
}
.site-nav__toggle-bar {
  display: block;
  width: 100%;
  height: 2px;
  background: var(--text-dark);
  border-radius: 1px;
}

@media (max-width: 639px) {
  .site-nav__toggle { display: inline-flex; order: 1; }
  /* justify-content: space-between (from .site-nav) doesn't truly center
     the brand mark here — the hamburger and Resume button are different
     widths, so splitting the remaining space evenly shifts the middle
     item toward whichever side is narrower. Taking it out of flex flow
     and centering it against the nav bar itself guarantees the true
     midpoint regardless of how wide either side item is. */
  .site-nav__brand {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
  .site-nav__resume { order: 3; }
  .site-nav__links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    display: flex;
    flex-direction: column;
    max-height: 0;
    overflow: hidden;
    background: var(--bg-light);
    border-bottom: 1px solid rgba(29, 29, 31, 0.08);
    transition: max-height 0.3s ease;
  }
  .site-nav__links[data-open="true"] { max-height: 28rem; }
  .site-nav__links a {
    padding: 0.75rem clamp(1.5rem, 5vw, 4rem);
  }
  .site-nav__links a.is-active { color: var(--accent-on-light); }
  .site-nav__links a.is-active::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .site-nav__links { transition: none; }
}

/* ===== Layout helpers ===== */
header.hero,
main > section,
footer#contact {
  position: relative;
  z-index: 1;
  padding: var(--section-padding-y) var(--container-padding-x);
  max-width: var(--container-width);
  margin: 0 auto;
  scroll-margin-top: 4.5rem;
}

main > section > *:not(.projects-bg-waveform) {
  position: relative;
  z-index: 1;
}

/* ===== Decorative background: infinite circuit board =====
   A faint, static circuit-trace pattern (.site-bg-wave) tiles behind the
   whole page — one absolutely-positioned SVG sized to the full document,
   so it reads as one continuous board rather than resetting per section.
   A second, brighter copy of the same traces (.site-bg-wave-active) is
   masked to a soft circle that eases toward the cursor (see script.js) and
   has its dash animation running continuously — so the "signal" is always
   flowing, but only visible in the small halo you're exploring with the
   pointer. The dark Projects section paints its own solid background over
   both and keeps its separate waveform motif for contrast. */
.site-bg-wave {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.projects-bg-waveform {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.circuit-trace {
  fill: none;
  stroke: var(--accent-on-light);
  stroke-width: 1.25;
  stroke-linecap: round;
  opacity: 0.07;
}
.circuit-via {
  fill: var(--accent-on-light);
  opacity: 0.11;
}
/* A brighter, animated copy of the circuit traces, revealed only in a soft
   radius around the cursor via a mask — signals appear to run through the
   board only where you're exploring. */
.site-bg-wave-active {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s ease;
  -webkit-mask-image: radial-gradient(110px circle at var(--cursor-x, 50%) var(--cursor-y, 50%), black 0%, transparent 100%);
  mask-image: radial-gradient(110px circle at var(--cursor-x, 50%) var(--cursor-y, 50%), black 0%, transparent 100%);
}
.site-bg-wave-active.is-active { opacity: 1; }
.circuit-trace-active {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-dasharray: 6 11;
  opacity: 0.6;
  animation: circuit-flow 2.6s linear infinite;
}
.circuit-via-active {
  fill: var(--accent);
  opacity: 0.7;
}
@keyframes circuit-flow {
  to { stroke-dashoffset: -170; }
}
@media (hover: none), (pointer: coarse) {
  .site-bg-wave-active { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .site-bg-wave-active { display: none; }
  .circuit-trace-active { animation: none; }
}
.waveform-pattern-path {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  opacity: 0.16;
  stroke-dasharray: 12 8;
  animation: wave-drift 14s linear infinite;
}
@keyframes wave-drift {
  to { stroke-dashoffset: -200; }
}
@media (prefers-reduced-motion: reduce) {
  .waveform-pattern-path {
    animation: none;
  }
}

main > section + section,
footer#contact {
  margin-top: var(--section-gap);
}

/* ===== Hero ===== */
header.hero {
  position: relative;
  min-height: 90vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 1.5rem;
}
.status-pill {
  display: inline-block;
  width: fit-content;
  padding: 0.5rem 1.25rem;
  border-radius: 999px;
  background: rgba(201, 130, 44, 0.12);
  color: var(--accent-on-light);
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: 0.01em;
}
header.hero h1 {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  max-width: clamp(20ch, 90%, 42ch);
}
.hero-greeting {
  font-size: var(--headline-size);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.05;
  background: var(--bg-light);
  padding: 0.1em 0.35em;
  border-radius: 12px;
}
.hero-tagline {
  font-size: clamp(1.5rem, 2.6vw, 2.25rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--text-dark-muted);
  background: var(--bg-light);
  padding: 0.1em 0.35em;
  border-radius: 12px;
}
.hero-subtitle {
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  color: var(--text-dark-muted);
  background: var(--bg-light);
  padding: 0.15em 0.5em;
  border-radius: 999px;
}
.hero-headshot {
  width: 9rem;
  height: 9rem;
  border-radius: 50%;
  object-fit: cover;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
  margin-top: 0.5rem;
}

/* ===== Buttons (hero, videos, contact) ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  border-radius: 999px;
  border: 1.5px solid var(--text-dark);
  background: var(--bg-light);
  color: var(--text-dark);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.btn:hover { border-color: var(--accent-on-light); color: var(--accent-on-light); }
.btn--primary {
  background: var(--text-dark);
  color: var(--bg-light);
  border-color: var(--text-dark);
}
.btn--primary:hover {
  background: var(--accent-on-light);
  border-color: var(--accent-on-light);
  color: var(--accent-contrast);
}
/* .btn sets display, which would otherwise beat the [hidden] attribute. */
.btn[hidden] { display: none; }

/* ===== Icon links (GitHub / LinkedIn / YouTube / Email) ===== */
.icon-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.hero-icon-links { justify-content: center; }
.icon-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  color: var(--text-dark);
  background: var(--bg-light);
  border: 1.5px solid rgba(29, 29, 31, 0.15);
  transition: color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.icon-links a:hover {
  color: var(--accent-on-light);
  border-color: var(--accent-on-light);
  transform: translateY(-2px);
}
.icon {
  width: 1.25rem;
  height: 1.25rem;
}
@media (prefers-reduced-motion: reduce) {
  .icon-links a:hover { transform: none; }
}

/* ===== At-a-glance strip (case-study headers) =====
   Same value-over-label pattern as .project-stats, in the light palette. */
.glance {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem clamp(1.5rem, 4vw, 3rem);
  margin-top: 1.5rem;
  padding: 1.25rem clamp(1.25rem, 3vw, 2.25rem);
  background: var(--bg-light);
  border: 1px solid rgba(29, 29, 31, 0.08);
  border-radius: 16px;
  text-align: left;
}
.glance li {
  display: flex;
  flex-direction: column;
  padding-left: 0.9rem;
  border-left: 2px solid rgba(150, 98, 31, 0.35);
}
.glance__value {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--accent-on-light);
  font-variant-numeric: tabular-nums;
}
.glance__label {
  font-size: 0.875rem;
  color: var(--text-dark-muted);
}

/* ===== Section headings ===== */
main > section h2,
footer#contact h2 {
  display: inline-block;
  font-size: var(--section-heading-size);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 2rem;
  background: var(--bg-light);
  padding: 0.1em 0;
  border-radius: 12px;
}
/* Projects section has its own solid dark background painted over the
   circuit pattern already (see .projects-section below) — the light-bg
   knockout above would hide this heading's light-colored text entirely. */
.projects-section > h2 {
  background: none;
  /* Dark section skips the light-bg knockout pill entirely, so the
     inline-block shrink-to-fit sizing has no job left here — worse, it
     breaks the margin:auto centering shared with .projects-container
     (auto margins don't resolve on inline-level boxes), leaving the
     heading flush-left while the container centers. Block fixes both. */
  display: block;
}

/* ===== About ===== */
.about-layout {
  display: grid;
  grid-template-columns: minmax(200px, 300px) 1fr;
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
}
.about-photo {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: 16px;
  background: rgba(29, 29, 31, 0.05);
}
.about-text p {
  max-width: 65ch;
  background: var(--bg-light);
  padding: 0.5em 0;
  border-radius: 12px;
}
.about-text p + p { margin-top: 1.5rem; }
.about-text a {
  color: var(--accent-on-light);
  font-weight: 600;
  border-bottom: 1.5px solid currentColor;
  transition: color 0.2s ease;
}
.about-text a:hover { color: var(--text-dark); }
@media (max-width: 767px) {
  .about-layout {
    grid-template-columns: 1fr;
  }
  .about-photo {
    max-width: 280px;
    margin: 0 auto;
  }
}
/* Fallback until graduation.jpg is supplied — the inline onerror handler on
   .about-photo (index.html) adds this class and removes the broken <img>,
   so a missing photo collapses back to a single readable text column
   instead of showing a broken-image icon on the live site. */
.about-layout--no-photo {
  grid-template-columns: 1fr;
}

/* ===== Tag chips (shared) ===== */
.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.tag-list li,
.tag-chip {
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  background: rgb(232, 232, 234);
  font-size: 0.9375rem;
}
.projects-section .tag-chip {
  background: rgba(245, 245, 247, 0.1);
  color: var(--accent);
  border: 1px solid rgba(201, 130, 44, 0.4);
}

/* ===== Featured Projects (dark section) ===== */
.projects-section {
  max-width: none;
  width: 100%;
  background: var(--bg-dark);
  color: var(--text-light);
  padding: var(--section-padding-y) 0;
}
.projects-section > h2,
.projects-section > .projects-container {
  max-width: var(--container-width);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--container-padding-x);
  padding-right: var(--container-padding-x);
}
.projects-container {
  display: flex;
  flex-direction: column;
  gap: clamp(1.25rem, 2.5vw, 2rem);
}
.projects-section a:focus-visible,
.projects-section summary:focus-visible {
  outline-color: var(--accent); /* the light-bg copper is too dark on black */
}
.project-feature,
.project-card {
  background: #0d0d0f; /* opaque: the section's waveform motif stays behind the cards */
  border: 1px solid rgba(245, 245, 247, 0.12);
  border-radius: 20px;
  transition: border-color 0.3s ease;
}
.project-feature:hover,
.project-card:hover { border-color: rgba(201, 130, 44, 0.55); }
.project-feature {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
  padding: clamp(1.25rem, 3vw, 2.5rem);
}
.project-feature__visual {
  margin: 0;
  padding: clamp(0.75rem, 2vw, 1.5rem);
  border-radius: 14px;
  background: rgba(245, 245, 247, 0.03);
  border: 1px solid rgba(245, 245, 247, 0.08);
}
.project-feature h3 {
  font-size: clamp(1.625rem, 3vw, 2.375rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.15;
  margin-bottom: 0.75rem;
}
@media (max-width: 899px) {
  .project-feature { grid-template-columns: 1fr; }
}
.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
}
.project-card {
  display: flex;
  flex-direction: column;
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
}
.project-card h3 {
  font-size: 1.375rem;
  font-weight: 600;
  line-height: 1.25;
  margin-bottom: 0.6rem;
}
.project-kicker {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.6rem;
}
.project-summary {
  font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
  color: var(--text-light-muted);
  margin-bottom: 1.5rem;
  max-width: 60ch;
}
.project-card .project-summary {
  font-size: 1rem;
  margin-bottom: 1.25rem;
}
.project-bullets {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
  max-width: 65ch;
}
.project-bullets li {
  position: relative;
  padding-left: 1.25rem;
}
.project-bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}
/* Headline numbers (bugs found, assertions, coverage) — big copper values
   with a muted label underneath, each hung off a thin accent rule. */
.project-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem clamp(1.5rem, 4vw, 3rem);
  margin-bottom: 1.75rem;
}
.project-stats li {
  display: flex;
  flex-direction: column;
  padding-left: 0.9rem;
  border-left: 2px solid rgba(201, 130, 44, 0.5);
}
.project-stat__value {
  font-size: clamp(1.75rem, 3.2vw, 2.5rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.project-stat__label {
  font-size: 0.875rem;
  color: var(--text-light-muted);
}
.project-stats--compact {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin-bottom: 1.25rem;
}
.project-stats--compact .project-stat__value { font-size: 1.75rem; }
@media (max-width: 559px) {
  .project-stats:not(.project-stats--compact) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.project-feature .tag-list { margin-bottom: 1.75rem; }
.project-card .tag-list { margin-bottom: 1.25rem; }
.project-card .tag-chip {
  font-size: 0.8125rem;
  padding: 0.3rem 0.75rem;
}
.project-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
}
/* Keeps every card's links on one baseline however long its text runs. */
.project-card .project-links { margin-top: auto; }
.project-links__more {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
}
.project-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 1.2rem;
  border-radius: 999px;
  background: var(--accent);
  color: #000000;
  font-weight: 600;
  transition: background 0.2s ease;
}
.project-cta:hover { background: #dd9545; }
.project-link {
  display: inline-block;
  color: var(--accent);
  font-weight: 600;
  border-bottom: 1.5px solid transparent;
  transition: border-color 0.2s ease;
}
.project-link:hover { border-color: var(--accent); }
.project-link--video::before {
  content: "";
  display: inline-block;
  border-style: solid;
  border-width: 0.35em 0 0.35em 0.6em;
  border-color: transparent transparent transparent currentColor;
  margin-right: 0.5em;
  vertical-align: 0.05em;
}

/* "What I built" disclosure on the compact cards */
.project-details { margin-bottom: 1.25rem; }
.project-details summary {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  list-style: none;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--text-light);
}
.project-details summary::-webkit-details-marker { display: none; }
.project-details summary::before {
  content: "";
  width: 0.45em;
  height: 0.45em;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
  transition: transform 0.2s ease;
}
.project-details[open] summary::before { transform: rotate(45deg); }
.project-details .project-bullets {
  margin: 1rem 0 0;
  font-size: 0.9375rem;
  color: var(--text-light-muted);
}

/* ===== Diagrams (inline SVG, drawn for the dark project panels) ===== */
.diagram {
  display: block;
  width: 100%;
  height: auto;
}
.diagram text {
  font-family: var(--font-system);
  text-anchor: middle;
}
.diagram .dg-label {
  text-anchor: start;
  fill: rgba(245, 245, 247, 0.55);
  font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.dg-group {
  fill: none;
  stroke: rgba(245, 245, 247, 0.28);
  stroke-width: 1.25;
  stroke-dasharray: 5 5;
}
.dg-group--inner { stroke: rgba(245, 245, 247, 0.18); }
.dg-box {
  fill: rgba(245, 245, 247, 0.06);
  stroke: rgba(245, 245, 247, 0.45);
  stroke-width: 1.25;
}
.dg-box--dut {
  fill: rgba(201, 130, 44, 0.14);
  stroke: var(--accent);
  stroke-width: 1.75;
}
.dg-text {
  fill: var(--text-light);
  font-size: 13px;
  font-weight: 500;
}
.dg-text--strong {
  fill: var(--accent);
  font-size: 17px;
  font-weight: 700;
}
.dg-sub {
  fill: rgba(245, 245, 247, 0.6);
  font-size: 10.5px;
}
.dg-wire {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
}
.dg-arrowhead { fill: var(--accent); }
.dg-badge {
  fill: rgba(201, 130, 44, 0.18);
  stroke: var(--accent);
  stroke-width: 1;
}
.dg-badge-text {
  fill: var(--accent);
  font-size: 11px;
  font-weight: 600;
}
.dg-callout {
  fill: var(--accent);
  font-size: 13px;
  font-weight: 700;
}

/* ===== Videos ===== */
main > section h2:has(+ .section-intro) { margin-bottom: 0.75rem; }
.section-intro {
  max-width: 60ch;
  margin-bottom: 2rem;
  color: var(--text-dark-muted);
  background: var(--bg-light);
  padding: 0.25em 0;
  border-radius: 12px;
}
.video-grid {
  display: grid;
  /* Fixed column counts (3 / 2 / 1) so cards fill rows evenly instead of
     a lone card dangling on its own row. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
}
.video-card {
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid rgba(29, 29, 31, 0.08);
  border-radius: 16px;
  overflow: hidden;
}
/* The thumbnail link and the iframe that replaces it on click share one
   16:9 box, so the card doesn't jump when the player loads. hqdefault
   thumbnails are 4:3 with letterbox bars; object-fit crops them off. */
.video-thumb,
.video-frame {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--bg-dark);
  border: 0;
}
.video-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}
.video-thumb:hover img { transform: scale(1.03); }
/* Card clips overflow (for the rounded corners), which would also clip
   the default outside focus ring — draw it inset instead. */
.video-thumb:focus-visible { outline-offset: -3px; }
.video-thumb__play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4rem;
  height: 2.75rem;
  transform: translate(-50%, -50%);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.75);
  transition: background 0.2s ease;
}
.video-thumb__play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-35%, -50%);
  border-style: solid;
  border-width: 0.6rem 0 0.6rem 1rem;
  border-color: transparent transparent transparent #ffffff;
}
.video-thumb:hover .video-thumb__play,
.video-thumb:focus-visible .video-thumb__play { background: var(--accent-on-light); }
.video-card__body { padding: 1.25rem 1.5rem 1.5rem; }
.video-card__topic {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent-on-light);
  margin-bottom: 0.5rem;
}
.video-card h3 {
  font-size: 1.1875rem;
  font-weight: 600;
  line-height: 1.3;
  margin-bottom: 0.6rem;
}
.video-card__body p:not(.video-card__topic) {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--text-dark-muted);
}
.video-card sup { line-height: 0; }
@media (max-width: 999px) {
  .video-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 639px) {
  .video-grid { grid-template-columns: 1fr; }
}
/* Newest video: thumbnail beside the text, above the grid of earlier ones.
   The thumbnail stretches to the row height (cropping via object-fit) so a
   long description never leaves blank bands above and below it. */
.video-card--feature {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  margin-bottom: clamp(1.25rem, 2.5vw, 2rem);
}
.video-card--feature > .video-thumb,
.video-card--feature > .video-frame { align-self: stretch; }
.video-card--feature .video-card__body {
  align-self: center;
  padding: clamp(1.5rem, 3vw, 2.5rem);
}
.video-card--feature h3 {
  font-size: clamp(1.375rem, 2.4vw, 1.75rem);
  line-height: 1.25;
  margin-bottom: 0.85rem;
}
.video-card--feature .video-card__body p:not(.video-card__topic) { font-size: 1rem; }
@media (max-width: 799px) {
  .video-card--feature { grid-template-columns: 1fr; }
}
.videos-cta { margin-top: 2rem; }
@media (prefers-reduced-motion: reduce) {
  .video-thumb img { transition: none; }
  .video-thumb:hover img { transform: none; }
}

/* ===== About: capability cards, toolbox, journey ===== */
.subheading {
  display: inline-block;
  font-size: clamp(1.25rem, 2.2vw, 1.625rem);
  font-weight: 600;
  margin: clamp(3rem, 6vw, 4.5rem) 0 1.5rem;
  background: var(--bg-light);
  padding: 0.1em 0;
  border-radius: 10px;
}
.capabilities,
.journey { scroll-margin-top: 4.5rem; }
.capability-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
  gap: 1.25rem;
}
.capability-card {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  background: #ffffff;
  border: 1px solid rgba(29, 29, 31, 0.08);
  border-radius: 16px;
}
.capability-card__icon {
  width: 2.25rem;
  height: 2.25rem;
  padding: 0.45rem;
  margin-bottom: 1rem;
  border-radius: 10px;
  background: rgba(201, 130, 44, 0.12);
  color: var(--accent-on-light);
}
.capability-card h4 {
  margin: 0 0 0.4rem;
  font-size: 1.125rem;
  font-weight: 600;
}
.capability-card p {
  margin-bottom: 1rem;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--text-dark-muted);
}
.capability-card .tag-list { gap: 0.4rem; }
.capability-card .tag-list li {
  padding: 0.3rem 0.7rem;
  font-size: 0.8125rem;
}
.toolbox {
  display: grid;
  gap: 0.75rem;
  margin: 1.25rem 0 0;
  padding: 1.25rem 1.5rem;
  font-size: 0.9375rem;
  background: var(--bg-light);
  border: 1px dashed rgba(29, 29, 31, 0.2);
  border-radius: 16px;
}
.toolbox div {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
}
.toolbox dt {
  min-width: 10.5rem;
  font-weight: 600;
}
.toolbox dd {
  flex: 1 1 20rem;
  margin: 0;
  color: var(--text-dark-muted);
}

/* Journey: a horizontal rail with copper "vias" on desktop, vertical on
   narrow screens. The rail is the list's ::before; each step's dot is the
   step's own ::before, painted after (so above) the rail. */
.journey-rail {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.journey-rail::before {
  content: "";
  position: absolute;
  top: 7px;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(to right, rgba(150, 98, 31, 0.3), var(--accent-on-light));
}
.journey-step {
  position: relative;
  padding-top: 1.85rem;
  scroll-margin-top: 4.5rem;
}
.journey-step::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--bg-light);
  border: 2px solid var(--accent-on-light);
}
.journey-step--now::before {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 5px rgba(201, 130, 44, 0.2);
}
.journey-step > * {
  width: fit-content;
  background: var(--bg-light);
  border-radius: 8px;
}
.journey-step__when {
  margin-bottom: 0.35rem;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-on-light);
}
.journey-step h4 {
  margin: 0 0 0.25rem;
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.3;
}
.journey-step__where {
  margin-bottom: 0.5rem;
  font-size: 0.9375rem;
  color: var(--text-dark-muted);
}
.journey-step__note {
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--text-dark-muted);
}
.journey-step__note a {
  color: var(--accent-on-light);
  font-weight: 600;
  border-bottom: 1.5px solid currentColor;
}
@media (max-width: 899px) {
  .journey-rail {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }
  .journey-rail::before {
    top: 0;
    bottom: 0;
    left: 7px;
    right: auto;
    width: 2px;
    height: auto;
    background: linear-gradient(to bottom, rgba(150, 98, 31, 0.3), var(--accent-on-light));
  }
  .journey-step { padding: 0 0 0 2.25rem; }
}

/* ===== Contact / footer ===== */
footer#contact {
  text-align: left;
}
footer#contact p {
  max-width: 55ch;
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  margin-bottom: 2rem;
  background: var(--bg-light);
  padding: 0.5em 0;
  border-radius: 12px;
}
.contact-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-bottom: 2.5rem;
}
.contact-actions .icon-links { margin-left: 0.25rem; }
footer#contact .footer-meta {
  width: fit-content;
  max-width: none;
  margin-bottom: 0;
  padding: 0.25em 0;
  font-size: 0.9375rem;
  color: var(--text-dark-muted);
  border-radius: 8px;
}
.footer-meta a {
  color: var(--accent-on-light);
  font-weight: 600;
}

/* ===== Case-study pages (projects/*.html) =====
   One readable column on a solid sheet, so long-form text never sits on
   the circuit pattern; the board stays visible in the margins. */
.case {
  position: relative;
  z-index: 1;
  max-width: calc(780px + 2 * var(--container-padding-x));
  margin: 0 auto;
  padding: clamp(2rem, 5vw, 3.5rem) var(--container-padding-x) clamp(2.5rem, 6vw, 4rem);
  background: var(--bg-light);
}
.case-back {
  display: inline-flex;
  gap: 0.4rem;
  margin-bottom: 1.75rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--accent-on-light);
}
.case-back:hover { color: var(--text-dark); }
.case .project-kicker { color: var(--accent-on-light); }
.case-hero h1 {
  margin-bottom: 1rem;
  font-size: clamp(2rem, 4.5vw, 3.25rem);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.case-lede {
  max-width: 62ch;
  margin-bottom: 1.75rem;
  font-size: clamp(1.125rem, 1.8vw, 1.3125rem);
  color: var(--text-dark-muted);
}
.case-hero .glance {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  margin: 0 0 1.5rem;
}
.case-hero .tag-list { margin-bottom: 1.75rem; }
.case-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.case-section { margin-top: clamp(2.75rem, 6vw, 4rem); }
.case-section h2 {
  margin-bottom: 1rem;
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.case-section h3 {
  margin-bottom: 0.75rem;
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.3;
}
.case-section p { max-width: 68ch; }
.case-section p + p,
.case-section .table-wrap + p { margin-top: 1rem; }
.case code {
  padding: 0.1em 0.35em;
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
  background: rgba(29, 29, 31, 0.06);
}
.case-list {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  max-width: 68ch;
}
.case-list li {
  position: relative;
  padding-left: 1.25rem;
}
.case-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-on-light);
}
.case-figure {
  margin: 1.5rem 0;
  padding: clamp(1rem, 3vw, 2rem);
  border-radius: 16px;
  background: var(--bg-dark);
}
.case-figure .diagram {
  max-width: 580px;
  margin: 0 auto;
}
.case-figure figcaption {
  margin-top: 1rem;
  font-size: 0.875rem;
  color: var(--text-light-muted);
}
.table-wrap {
  margin: 1.25rem 0;
  overflow-x: auto;
  background: #ffffff;
  border: 1px solid rgba(29, 29, 31, 0.1);
  border-radius: 12px;
}
.case-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}
.case-table th,
.case-table td {
  padding: 0.7rem 1rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid rgba(29, 29, 31, 0.08);
}
.case-table th {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-dark-muted);
  background: rgba(29, 29, 31, 0.03);
}
.case-table tbody tr:last-child td { border-bottom: 0; }
.case-table td:first-child { min-width: 9rem; }
.result-bug {
  font-weight: 600;
  color: var(--accent-on-light);
  white-space: nowrap;
}
.bug-card {
  margin-top: 1.25rem;
  padding: clamp(1.25rem, 3vw, 1.75rem);
  background: #ffffff;
  border: 1px solid rgba(29, 29, 31, 0.08);
  border-left: 4px solid var(--accent);
  border-radius: 14px;
}
.bug-card__tag {
  margin-bottom: 0.35rem;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-on-light);
}
.bug-card dl {
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  gap: 0.6rem 1rem;
  margin: 1rem 0 0;
  font-size: 0.9375rem;
}
.bug-card dt { font-weight: 600; }
.bug-card dd {
  margin: 0;
  color: var(--text-dark-muted);
}
.bug-card > p:not(.bug-card__tag) {
  font-size: 0.9375rem;
  color: var(--text-dark-muted);
}
@media (max-width: 599px) {
  .bug-card dl {
    grid-template-columns: 1fr;
    gap: 0.2rem;
  }
  .bug-card dd { margin-bottom: 0.6rem; }
}
.case pre {
  margin: 1.25rem 0 0;
  padding: 1rem 1.25rem;
  overflow-x: auto;
  border-radius: 10px;
  background: var(--bg-dark);
  color: #e9e9ec;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8125rem;
  line-height: 1.6;
}
.case pre code {
  padding: 0;
  background: none;
  font-size: inherit;
}
.case-video {
  max-width: 560px;
  margin-top: 1.25rem;
}
.case-next {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1.25rem 2rem;
  margin-top: clamp(3rem, 6vw, 4.5rem);
  padding-top: 2rem;
  border-top: 1px solid rgba(29, 29, 31, 0.1);
}
.case-next a {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-weight: 600;
  color: var(--text-dark);
}
.case-next a:last-child { text-align: right; margin-left: auto; }
.case-next a:hover { color: var(--accent-on-light); }
.case-next small {
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dark-muted);
}
/* Line the contact footer up with the case-study column. */
main:has(.case) + footer#contact {
  max-width: calc(780px + 2 * var(--container-padding-x));
  margin-top: 0;
}

/* ===== Responsive ===== */
@media (max-width: 767px) {
  header.hero { min-height: 80vh; }
}

/* ===== Reveal on scroll =====
   [data-reveal] content is visible by default so a no-JS visitor sees
   everything. The hidden baseline only applies once html.js confirms
   script executed (set synchronously in <head>, see index.html) — an
   IntersectionObserver (script.js) then adds .is-visible as each element
   scrolls into view. */
html.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
html.js [data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  html.js [data-reveal] { transition: opacity 0.4s ease; transform: none; }
}

/* Hero elements are already in view at load, so they all "intersect"
   almost immediately — stagger them with transition-delay to preserve the
   sequential build-in (headline, then pill, then subtitle, then links). */
html.js .hero-headshot[data-reveal] { transition-delay: 0s; }
html.js header.hero h1[data-reveal] { transition-delay: 0.15s; }
html.js .status-pill[data-reveal] { transition-delay: 0.3s; }
html.js .hero-subtitle[data-reveal] { transition-delay: 0.35s; }
html.js .hero-actions[data-reveal] { transition-delay: 0.4s; }
html.js .hero-icon-links[data-reveal] { transition-delay: 0.45s; }
@media (prefers-reduced-motion: reduce) {
  html.js .hero-headshot[data-reveal],
  html.js header.hero h1[data-reveal],
  html.js .status-pill[data-reveal],
  html.js .hero-subtitle[data-reveal],
  html.js .hero-actions[data-reveal],
  html.js .hero-icon-links[data-reveal] { transition-delay: 0s; }
}
