/* ==========================================================================
   Taylor Bosier — portfolio
   1. Tokens          5. Hero
   2. Reset & base    6. Sections
   3. Motion          7. Components
   4. Chrome (nav)    8. Responsive
   ========================================================================== */

/* 1. Tokens ============================================================== */

:root {
  color-scheme: light;

  /* Graphite: grey with a cool cast. One palette, picked and locked. */
  --bg:            #f6f7f9;
  --bg-elevated:   #ffffff;
  --bg-sunken:     #ebeef2;

  --ink:           #12161c;
  --ink-strong:    #05080c;
  --ink-muted:     #59636f;
  --ink-faint:     #8b96a3;

  --brand:         #47515f;
  --brand-strong:  #2a323c;
  --brand-soft:    #e7eaee;
  --on-brand:      #ffffff;
  --brand-glow:    rgba(71, 81, 95, 0.12);

  --line:          #dfe2e7;
  --line-strong:   #c7ccd3;

  --shadow-sm: 0 1px 2px rgba(12, 18, 26, 0.05);
  --shadow-md: 0 8px 24px -14px rgba(12, 18, 26, 0.2);
  --shadow-lg: 0 24px 60px -28px rgba(12, 18, 26, 0.26);

  --radius-sm: 8px;
  --radius:    14px;
  --radius-lg: 22px;
  --container: 1120px;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Fraunces", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-mono: "SFMono-Regular", ui-monospace, "JetBrains Mono", Menlo, Consolas, monospace;
  --ease: cubic-bezier(0.22, 0.85, 0.3, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.55s;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg:            #0d1014;
  --bg-elevated:   #161a20;
  --bg-sunken:     #07090c;

  --ink:           #e2e6ec;
  --ink-strong:    #f6f8fa;
  --ink-muted:     #97a2af;
  --ink-faint:     #6c7683;

  --brand:         #9ca8b6;
  --brand-strong:  #c6d0db;
  --brand-soft:    #1c212a;
  --on-brand:      #0d1014;
  --brand-glow:    rgba(156, 168, 182, 0.16);

  --line:          #232831;
  --line-strong:   #313844;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 8px 24px -14px rgba(0, 0, 0, 0.85);
  --shadow-lg: 0 24px 60px -28px rgba(0, 0, 0, 1);
}

/* 2. Reset & base ======================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  transition: background-color 0.4s var(--ease), color 0.4s var(--ease);
}

/* height:auto so the width/height attributes (which map to presentational
   height) can't override an aspect-ratio or fluid width. */
img { max-width: 100%; height: auto; display: block; }

a {
  color: var(--brand-strong);
  text-decoration-color: color-mix(in srgb, var(--brand) 35%, transparent);
  text-underline-offset: 0.22em;
  transition: color 0.2s var(--ease), text-decoration-color 0.2s var(--ease);
}
a:hover { color: var(--brand); text-decoration-color: currentColor; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--ink-strong);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0 0 0.6em;
  font-variation-settings: "SOFT" 0, "WONK" 0;
}

p { margin: 0 0 1.1em; }
ul { margin: 0; padding: 0; list-style: none; }

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

::selection { background: var(--brand-glow); color: var(--ink-strong); }

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

.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -120%);
  z-index: 200;
  background: var(--brand);
  color: var(--on-brand);
  padding: 0.7rem 1.2rem;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-weight: 600;
  text-decoration: none;
  transition: transform 0.25s var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); color: var(--on-brand); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* 3. Motion ============================================================== */

/* Scroll-reveal: elements start offset, JS adds .is-visible.
   The starting (hidden) state is scoped to .js — set by the inline script in
   each page's <head> — so that if the script never runs, nothing is hidden
   and the page still reads as plain content. */
.reveal {
  transition:
    opacity var(--dur) var(--ease-out),
    transform var(--dur) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

.js .reveal {
  opacity: 0;
  transform: translateY(22px);
  will-change: opacity, transform;
}
.js .reveal--left  { transform: translateX(-26px); }
.js .reveal--right { transform: translateX(26px); }
.js .reveal--scale { transform: translateY(14px) scale(0.97); }

.js .reveal.is-visible { opacity: 1; transform: none; }

/* Hero entrance: plays on load, no observer needed. */
@keyframes rise {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}
.js .rise {
  opacity: 0;
  animation: rise 0.9s var(--ease-out) forwards;
  animation-delay: var(--rise-delay, 0ms);
}

@keyframes pulse-ring {
  0%   { transform: scale(0.95); opacity: 0.55; }
  70%  { transform: scale(1.25); opacity: 0; }
  100% { transform: scale(1.25); opacity: 0; }
}

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

/* 4. Chrome ============================================================== */

.progress-bar {
  position: fixed;
  inset: 0 auto auto 0;
  height: 2px;
  width: 100%;
  transform: scaleX(var(--progress, 0));
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand), var(--brand-strong));
  z-index: 120;
  pointer-events: none;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease), box-shadow 0.35s var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header.is-stuck {
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-sm);
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 4.5rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--ink-strong);
  text-decoration: none;
  letter-spacing: -0.02em;
}
.brand__mark {
  display: grid;
  place-items: center;
  width: 2rem; height: 2rem;
  border-radius: 9px;
  background: linear-gradient(140deg, var(--brand), var(--brand-strong));
  color: var(--on-brand);
  font-size: 0.82rem;
  font-family: var(--font-sans);
  font-weight: 700;
  letter-spacing: 0.02em;
  flex: none;
  box-shadow: 0 4px 12px -4px var(--brand-glow);
  transition: transform 0.4s var(--ease);
}
.brand:hover .brand__mark { transform: rotate(-8deg) scale(1.06); }

.header-actions { display: flex; align-items: center; gap: 0.5rem; }

.nav { display: flex; align-items: center; gap: 0.75rem; }

.nav__list {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  position: relative;
}
.nav__link {
  position: relative;
  display: block;
  padding: 0.5rem 0.85rem;
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink-muted);
  text-decoration: none;
  transition: color 0.25s var(--ease);
  z-index: 1;
}
.nav__link:hover { color: var(--ink-strong); }
.nav__link[aria-current="true"] { color: var(--brand-strong); }

/* Sliding pill that tracks the active link. */
.nav__indicator {
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--brand-soft);
  transform: translateX(var(--x, 0px));
  width: var(--w, 0px);
  opacity: var(--o, 0);
  transition: transform 0.45s var(--ease), width 0.45s var(--ease), opacity 0.3s var(--ease);
  pointer-events: none;
  z-index: 0;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 2.4rem; height: 2.4rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg-elevated);
  color: var(--ink-muted);
  cursor: pointer;
  flex: none;
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease), transform 0.25s var(--ease), background-color 0.25s var(--ease);
}
.icon-btn:hover {
  color: var(--brand-strong);
  border-color: var(--line-strong);
  transform: translateY(-1px);
}
.icon-btn svg { width: 1.05rem; height: 1.05rem; }

.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun  { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

.nav-toggle { display: none; }
.nav-toggle svg { transition: transform 0.3s var(--ease); }
.nav-toggle[aria-expanded="true"] svg { transform: rotate(90deg); }

/* 5. Hero ================================================================ */

.hero {
  position: relative;
  isolation: isolate;
  padding-block: clamp(3.5rem, 11vh, 7rem) clamp(3rem, 9vh, 6rem);
  overflow: hidden;
}

/* A drafting grid rather than a gradient wash. The soft blurred gradient is
   the house style of every generated landing page going, and it was also the
   most expensive thing on the page: three blurred divs on keyframes pinned the
   whole page to 30fps. Two hairline gradients cost nothing and rasterise once. */
.hero__mesh {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.75;
  background-image:
    repeating-linear-gradient(90deg, var(--line) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(0deg, var(--line) 0 1px, transparent 1px 64px);
  -webkit-mask-image: radial-gradient(115% 95% at 72% 34%, #000 0%, transparent 72%);
  mask-image: radial-gradient(115% 95% at 72% 34%, #000 0%, transparent 72%);
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 3.75rem);
  align-items: center;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg-elevated) 70%, transparent);
  backdrop-filter: blur(6px);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-muted);
  margin-bottom: 1.4rem;
}
.status-dot {
  position: relative;
  width: 0.5rem; height: 0.5rem;
  border-radius: 50%;
  background: #2fa96b;
  flex: none;
}
.status-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid #2fa96b;
  animation: pulse-ring 2.4s var(--ease) infinite;
}

.hero__name {
  font-size: clamp(2.9rem, 8vw, 5.1rem);
  font-weight: 400;
  letter-spacing: -0.035em;
  margin-bottom: 0.35rem;
  font-variation-settings: "SOFT" 20, "WONK" 1;
}

.hero__role {
  font-family: var(--font-sans);
  font-size: clamp(1.05rem, 2.2vw, 1.3rem);
  font-weight: 600;
  color: var(--brand-strong);
  letter-spacing: -0.01em;
  margin-bottom: 1.1rem;
  text-wrap: balance;
}
.hero__role .sep { color: var(--ink-faint); font-weight: 400; margin-inline: 0.4rem; }

.hero__blurb {
  font-size: clamp(1rem, 1.6vw, 1.12rem);
  color: var(--ink-muted);
  max-width: 34rem;
  margin-bottom: 2rem;
}
.hero__blurb strong { color: var(--ink); font-weight: 600; }

.hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }

/* Portrait, ringed by a (3,5) torus knot.
   The two canvases sandwich the photo so the near pass goes in front of it
   and the far pass behind — that overlap is what gives it depth. */
.portrait {
  position: relative;
  justify-self: center;
  width: min(100%, 27rem);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  isolation: isolate;
}


.portrait__frame {
  position: relative;
  width: 78%;
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  transition: transform 0.6s var(--ease), box-shadow 0.6s var(--ease);
}
.portrait__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 14%;
  transition: transform 0.9s var(--ease);
}
.portrait:hover .portrait__frame { transform: translateY(-4px); box-shadow: var(--shadow-lg), 0 0 0 6px var(--brand-glow); }
.portrait:hover .portrait__frame img { transform: scale(1.04); }

.portrait__badge {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: 2%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.95rem;
  border-radius: 999px;
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.portrait__badge svg { width: 1rem; height: 1rem; color: var(--brand); flex: none; }

/* 6. Sections ============================================================ */

.section { padding-block: clamp(4rem, 10vh, 7rem); position: relative; }
.section--sunken { background: var(--bg-sunken); }
.section--bordered { border-top: 1px solid var(--line); }

.section__head { max-width: 46rem; margin-bottom: clamp(2.25rem, 5vw, 3.5rem); }

.section__label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 0.9rem;
}
.section__label::after {
  content: "";
  height: 1px;
  flex: 1;
  max-width: 5rem;
  background: linear-gradient(90deg, var(--line-strong), transparent);
}

.section__title {
  font-size: clamp(1.85rem, 4.2vw, 2.7rem);
  letter-spacing: -0.03em;
  margin-bottom: 0.5rem;
}
.section__intro { color: var(--ink-muted); font-size: 1.05rem; margin-bottom: 0; }

/* 7. Components ========================================================== */

/* --- Buttons --- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.72rem 1.35rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 0.92rem;
  font-weight: 600;
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.28s var(--ease), box-shadow 0.28s var(--ease),
              background-color 0.28s var(--ease), border-color 0.28s var(--ease), color 0.28s var(--ease);
}
.btn svg { width: 1.05rem; height: 1.05rem; flex: none; transition: transform 0.3s var(--ease); }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  background: linear-gradient(140deg, var(--brand), var(--brand-strong));
  color: var(--on-brand);
  box-shadow: 0 10px 24px -12px var(--brand-glow), inset 0 1px 0 rgba(255,255,255,0.18);
}
.btn--primary:hover { color: var(--on-brand); box-shadow: 0 16px 32px -14px var(--brand-glow); }
.btn--primary:hover svg { transform: translateY(2px); }

.btn--ghost {
  background: var(--bg-elevated);
  border-color: var(--line);
  color: var(--ink);
}
.btn--ghost:hover { border-color: var(--brand); color: var(--brand-strong); box-shadow: var(--shadow-md); }
.btn--ghost:hover svg { transform: translateX(3px); }

.btn--sm { padding: 0.5rem 1rem; font-size: 0.85rem; }

/* --- Metrics --- */
.metrics {
  display: grid;
  /* Auto-fit rather than a fixed four, so the band stays even when a metric is
     added or pulled. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}
.metric {
  background: var(--bg);
  padding: clamp(1.5rem, 3vw, 2.1rem) clamp(1rem, 2vw, 1.5rem);
  text-align: center;
  transition: background-color 0.35s var(--ease);
}
.metric:hover { background: var(--bg-elevated); }
.metric__value {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 4vw, 2.5rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--ink-strong);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.metric__label {
  display: block;
  font-size: 0.82rem;
  color: var(--ink-muted);
  margin-top: 0.4rem;
  text-wrap: balance;
}

/* --- About --- */
.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.5fr);
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}

.about__side {
  position: sticky;
  top: 6rem;
  padding: 1.5rem 1.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
}

/* Each fact is a hairline-ruled row with a small quiet label above the value,
   so the values line up as one readable column instead of a boxed table. */
.facts { display: grid; gap: 0; margin: 0; padding: 0; }

.fact {
  display: grid;
  gap: 0.12rem;
  padding-block: 0.85rem;
  border-top: 1px solid var(--line);
}
.fact:first-child { border-top: 0; padding-top: 0; }
.fact:last-child { padding-bottom: 0; }

.fact dt {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.fact dd {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--ink-muted);
}
.fact dd strong { color: var(--ink-strong); font-weight: 600; }

/* --- Timeline --- */
.timeline { position: relative; padding-left: clamp(1.75rem, 4vw, 2.75rem); }
.timeline::before {
  content: "";
  position: absolute;
  left: 0.3rem;
  top: 0.75rem;
  bottom: 0.75rem;
  width: 2px;
  background: linear-gradient(180deg, var(--brand), var(--line-strong) 70%, transparent);
  transform: scaleY(var(--draw, 0));
  transform-origin: 50% 0;
  transition: transform 1.4s var(--ease-out);
}

.role { position: relative; padding-bottom: clamp(2.25rem, 5vw, 3.25rem); }
.role:last-child { padding-bottom: 0; }

.role::before {
  content: "";
  position: absolute;
  left: calc(clamp(1.75rem, 4vw, 2.75rem) * -1 + 0.3rem - 5px);
  top: 0.55rem;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--brand);
  box-shadow: 0 0 0 4px var(--bg);
  transform: scale(0);
  transition: transform 0.5s var(--ease-out) 0.15s, background-color 0.3s var(--ease);
}
.role.is-visible::before { transform: scale(1); }
.role:hover::before { background: var(--brand); }

.role__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-bottom: 0.35rem;
}
.role__title { font-size: clamp(1.2rem, 2.4vw, 1.45rem); margin-bottom: 0; }
.role__dates {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  white-space: nowrap;
}
.role__org {
  font-weight: 600;
  color: var(--brand-strong);
  font-size: 0.98rem;
  margin-bottom: 1rem;
}
.role__org .place { color: var(--ink-faint); font-weight: 400; }

.role__list { display: grid; gap: 0.7rem; }
.role__list li {
  position: relative;
  padding-left: 1.35rem;
  color: var(--ink-muted);
  font-size: 0.97rem;
}
.role__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 6px; height: 6px;
  border-radius: 2px;
  background: var(--line-strong);
  transition: background-color 0.3s var(--ease);
}
.role:hover .role__list li::before { background: var(--brand); }
.role__list strong { color: var(--ink); font-weight: 600; }

/* --- Cards (projects) --- */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: clamp(1rem, 2.5vw, 1.5rem);
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 1.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease), border-color 0.4s var(--ease);
}
/* Cursor spotlight — JS feeds --mx / --my. */
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(18rem 18rem at var(--mx, 50%) var(--my, 0%), var(--brand-glow), transparent 70%);
  opacity: 0;
  transition: opacity 0.4s var(--ease);
  pointer-events: none;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--line-strong); }
.card:hover::before { opacity: 1; }
.card > * { position: relative; }

.card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}
.card__icon {
  display: grid;
  place-items: center;
  width: 2.6rem; height: 2.6rem;
  border-radius: 10px;
  background: var(--brand-soft);
  color: var(--brand-strong);
  flex: none;
  transition: transform 0.4s var(--ease);
}
.card__icon svg { width: 1.25rem; height: 1.25rem; }
.card:hover .card__icon { transform: rotate(-6deg) scale(1.08); }

.card__title { font-size: 1.15rem; margin-bottom: 0.5rem; }
.card__title a { color: inherit; text-decoration: none; }
.card__title a::after { content: ""; position: absolute; inset: 0; }
.card__title a:hover { color: var(--brand-strong); }

.card__desc { color: var(--ink-muted); font-size: 0.94rem; margin-bottom: 1.1rem; }
.card__foot { margin-top: auto; display: flex; flex-wrap: wrap; gap: 0.4rem; }

.tag {
  display: inline-block;
  padding: 0.22rem 0.6rem;
  border-radius: 6px;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: var(--ink-muted);
}

.card__link {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--brand-strong);
  text-decoration: none;
  flex: none;
}
.card__link svg { width: 0.95rem; height: 0.95rem; transition: transform 0.3s var(--ease); }
.card:hover .card__link svg { transform: translate(2px, -2px); }

/* A card that gets two columns once there is room for two columns. */
.card--feature { border-color: var(--line-strong); }
@media (min-width: 64rem) {
  .card--feature { grid-column: span 2; }
}

.card__meta { display: inline-flex; align-items: center; gap: 0.8rem; flex: none; }

.card__kicker {
  margin-left: 0.5rem;
  padding: 0.12rem 0.45rem;
  border-radius: 5px;
  background: var(--brand-soft);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brand-strong);
  vertical-align: 0.18em;
}

/* Star count. Live from the GitHub API, with the last known value in the
   markup so it reads correctly if the request never lands. */
.gh-stars {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-sunken);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  color: var(--ink-muted);
  text-decoration: none;
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}
.gh-stars:hover { color: var(--ink); border-color: var(--line-strong); }
.gh-stars svg { width: 0.8rem; height: 0.8rem; }

.card__desc code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  padding: 0.08rem 0.3rem;
  border-radius: 4px;
  background: var(--bg-sunken);
  color: var(--ink);
}

/* --- Pre-AI / Post-AI switch --- */
.era {
  display: flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--bg-sunken);
}
.era__btn {
  padding: 0.3rem 0.55rem;
  border: 0;
  border-radius: 7px;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.era__btn:hover { color: var(--ink-strong); }
.era__btn[aria-pressed="true"] {
  background: var(--bg-elevated);
  color: var(--brand-strong);
  box-shadow: var(--shadow-sm);
}

.era-view {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  grid-template-rows: auto 1fr;
  background: var(--bg);
}
.era-view[hidden] { display: none; }

.era-view__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem var(--gutter);
  border-bottom: 1px solid var(--line);
  background: var(--bg-elevated);
}
.era-view__bar p {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-muted);
  max-width: 60ch;
}
.era-view__bar strong { color: var(--ink-strong); font-weight: 600; }

.era-view__frame {
  width: 100%;
  height: 100%;
  border: 0;
  background: #fff;
}

/* --- Routing board --- */
.routing {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 16rem;
  gap: clamp(1rem, 2.5vw, 1.75rem);
  align-items: start;
}

.routing__board {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.routing__views {
  display: flex;
  gap: 0.25rem;
  padding: 0.55rem 0.6rem;
  border-bottom: 1px solid var(--line);
}
.routing__view {
  padding: 0.32rem 0.7rem;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-faint);
  cursor: pointer;
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.routing__view:hover { color: var(--brand-strong); background: var(--bg-sunken); }
.routing__view[aria-selected="true"] {
  color: var(--brand-strong);
  background: var(--brand-soft);
  border-color: color-mix(in srgb, var(--brand) 28%, transparent);
}

.routing__pane { position: relative; }
.routing__pane[hidden] { display: none; }

.routing__canvas,
.routing__assign {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
}

/* --- Run button ---
   Each panel rests on its finished figure, so this is the only thing on screen
   saying there is a run behind it. It sits in the control bar and stands in for
   the play button, which means nothing when the clock is already at the end. */
.runner {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  flex: none;
  padding: 0.42rem 0.85rem;
  border: 1px solid var(--brand-strong);
  border-radius: 999px;
  background: var(--brand);
  color: var(--on-brand);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.runner[hidden] { display: none; }
.runner:hover { background: var(--brand-strong); }
.runner:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.runner svg { width: 0.75rem; height: 0.75rem; flex: none; }
.runner__len {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 400;
  opacity: 0.72;
  padding-left: 0.35rem;
  border-left: 1px solid currentColor;
}
/* At rest the play button would only un-pause a clock sitting on the last
   frame, so the run button takes its place. */
.transport.is-armed .transport__btn--play { display: none; }

@media (max-width: 30rem) {
  .runner { font-size: 0.76rem; padding: 0.4rem 0.65rem; }
  .runner__len { display: none; }
}

/* --- data tables --- */
.routing__tables {
  display: grid;
  gap: 1.25rem;
  padding: 1rem 1.1rem 1.2rem;
  max-height: 32rem;
  overflow-y: auto;
}
.routing__table h3 {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 0.5rem;
}
.routing__table table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.routing__table th,
.routing__table td {
  padding: 0.4rem 0.6rem 0.4rem 0;
  text-align: left;
  font-size: 0.78rem;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.routing__table th {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.routing__table td {
  font-family: var(--font-mono);
  color: var(--ink-muted);
}
.routing__table tbody tr:hover td { color: var(--ink-strong); background: var(--bg-sunken); }
.routing__table tbody tr:last-child td { border-bottom: 0; }

.routing__key {
  position: absolute;
  left: 0.85rem;
  bottom: 0.7rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.9rem;
  font-size: 0.7rem;
  color: var(--ink-faint);
}
.routing__key li { display: flex; align-items: center; gap: 0.35rem; }
.key-mark { width: 9px; height: 9px; flex: none; }
.key-mark--depot  { background: var(--brand-strong); transform: rotate(45deg); }
.key-mark--pickup { background: var(--ink); border-radius: 50%; opacity: 0.75; }
.key-mark--drop   { border: 1.5px solid var(--ink); border-radius: 50%; opacity: 0.55; }
.key-mark--route  { height: 2px; width: 16px; background: var(--brand-strong); }

.routing__side {
  display: grid;
  gap: 1.1rem;
  padding: 1.1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
}

.routing__steps { display: grid; gap: 0.1rem; counter-reset: step; }
.routing__steps li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 0.4rem;
  border-radius: 8px;
  font-size: 0.82rem;
  color: var(--ink-faint);
  transition: color 0.3s var(--ease), background-color 0.3s var(--ease);
}
.routing__steps li span {
  display: grid;
  place-items: center;
  width: 1.3rem; height: 1.3rem;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  transition: border-color 0.3s var(--ease), background-color 0.3s var(--ease), color 0.3s var(--ease);
}
.routing__steps li[aria-current="true"] {
  color: var(--ink-strong);
  background: var(--brand-soft);
  font-weight: 600;
}
.routing__steps li[aria-current="true"] span {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}

.routing__stats { display: grid; gap: 0.1rem; margin: 0; }
.routing__stats > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding-block: 0.35rem;
  border-bottom: 1px dashed var(--line);
}
.routing__stats > div:last-child { border-bottom: 0; }
.routing__stats dt { font-size: 0.78rem; color: var(--ink-faint); }
.routing__stats dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-strong);
}

.routing__constraints {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0;
}
.routing__constraints span {
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-sunken);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--ink-muted);
}

.routing__replay { justify-content: center; }

/* --- Transport --- */
.transport {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.6rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg-elevated);
}
.transport[hidden] { display: none; }

.transport__btn {
  display: grid;
  place-items: center;
  width: 1.85rem; height: 1.85rem;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.transport__btn:hover { color: var(--brand-strong); border-color: var(--line-strong); background: var(--bg-sunken); }
.transport__btn svg { width: 0.95rem; height: 0.95rem; }

.transport__btn--play { color: var(--brand-strong); border-color: color-mix(in srgb, var(--brand) 30%, transparent); }
.transport__btn--play .i-play { display: none; }
.transport__btn--play.is-paused .i-play { display: block; }
.transport__btn--play.is-paused .i-pause { display: none; }

.transport__seek {
  flex: 1 1 3rem;
  min-width: 2.5rem;
  height: 4px;
  -webkit-appearance: none;
  appearance: none;
  border-radius: 999px;
  background: var(--line);
  cursor: pointer;
}
.transport__seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 13px; height: 13px;
  border-radius: 50%;
  background: var(--brand);
  border: 2px solid var(--bg-elevated);
  cursor: grab;
}
.transport__seek::-moz-range-thumb {
  width: 13px; height: 13px;
  border: 2px solid var(--bg-elevated);
  border-radius: 50%;
  background: var(--brand);
  cursor: grab;
}
.transport__seek:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* The clock must never wrap or clip: it is fixed width content, so it gets a
   reserved lane and the slider gives up the space instead. */
.transport__time {
  flex: 0 0 auto;
  min-width: 7.6rem;
  text-align: right;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
}

.transport__rate {
  flex: 0 0 auto;
  padding: 0.2rem 0.3rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-elevated);
  color: var(--ink-muted);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  cursor: pointer;
}
.transport__rate:hover { color: var(--brand-strong); border-color: var(--line-strong); }

/* --- Decision system tabs --- */
/* Without JavaScript the tabs cannot switch, so three of the four systems
   stay behind their `hidden` attribute -- 510 words, on a section whose own
   headline promises four. Show them all, stacked, and drop the tablist and
   the in-panel view switchers, which do nothing without a script. The
   canvases stay blank either way; the prose is the substance. Print does
   the same thing further down, for the same reason. */
html:not(.js) .systems__panel[hidden] { display: block; }
html:not(.js) .systems__tabs,
html:not(.js) .routing__views { display: none; }

.systems__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-bottom: 1.6rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--line);
}
.systems__tab {
  padding: 0.5rem 0.95rem;
  border: 1px solid transparent;
  border-radius: 9px;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-faint);
  cursor: pointer;
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.systems__tab:hover { color: var(--brand-strong); background: var(--bg-sunken); }
.systems__tab[aria-selected="true"] {
  color: var(--brand-strong);
  background: var(--brand-soft);
  border-color: color-mix(in srgb, var(--brand) 28%, transparent);
}
.systems__panel[hidden] { display: none; }

/* --- Decision system headings --- */
.system__title {
  font-size: clamp(1.1rem, 2.2vw, 1.3rem);
  letter-spacing: -0.02em;
  margin-bottom: 0.4rem;
}
/* The problem in plain words, before any of the machinery is named. A reader
   who stops here should still know what the tool is for. */
.system__lede {
  max-width: 48rem;
  margin: 0 0 0.7rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--brand);
  font-size: 1.04rem;
  line-height: 1.6;
  color: var(--ink);
}
.system__note {
  max-width: 48rem;
  margin-bottom: 1.5rem;
  font-size: 0.95rem;
  color: var(--ink-muted);
}
/* The disclosure on the Contracts panel, and the "why this is blank" note under
   the current role. Both exist to say something the surrounding copy cannot, so
   they are set apart rather than blended in. */
.system__note--flag,
.role__note {
  max-width: 48rem;
  margin: 0 0 1.5rem;
  padding: 0.75rem 0.95rem;
  border-left: 2px solid var(--ink-faint);
  border-radius: 0 var(--radius-sm, 6px) var(--radius-sm, 6px) 0;
  background: color-mix(in srgb, var(--ink-faint) 8%, transparent);
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--ink-muted);
}
.role__note {
  margin: 0.9rem 0 0;
}
.pricing__canvas,
.contracts__canvas,
.staffing__canvas,
.capacity__canvas {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
}
.figure-note {
  margin: 0;
  font-size: 0.76rem;
  line-height: 1.55;
  color: var(--ink-faint);
}

/* --- Skills --- */
.skills-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: clamp(1rem, 2.5vw, 1.5rem);
  align-items: start;
}
.skill-group {
  padding: 1.4rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  transition: border-color 0.35s var(--ease), transform 0.35s var(--ease);
}
.skill-group:hover { border-color: var(--line-strong); transform: translateY(-3px); }
.skill-group h3 {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 0.9rem;
}
.pills { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.pill {
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--bg);
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--ink);
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease), background-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.skill-note {
  margin-top: 0.9rem;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

.pill:hover {
  border-color: var(--brand);
  color: var(--brand-strong);
  background: var(--brand-soft);
  transform: translateY(-2px);
}

/* --- Blackboard (under Education) --- */
.blackboard {
  margin-top: clamp(1.5rem, 4vw, 2.5rem);
  padding: clamp(1rem, 2.5vw, 1.6rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
}
.blackboard__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.9rem;
  margin-bottom: 1rem;
}
.blackboard__title {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 2.2vw, 1.3rem);
  line-height: 1.25;
}
.blackboard__sub {
  margin-top: 0.3rem;
  max-width: 46ch;
  font-size: 0.86rem;
  color: var(--ink-muted);
}
.blackboard__controls { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; flex-wrap: wrap; }
.blackboard__tabs { display: flex; gap: 0.4rem; flex-shrink: 0; }
.bb-pause {
  padding: 0.36rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  font: inherit;
  font-size: 0.78rem;
  color: var(--ink-muted);
  cursor: pointer;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.bb-pause:hover { border-color: var(--line-strong); color: var(--ink); }
.bb-pause[hidden] { display: none; }
.bb-tab {
  padding: 0.36rem 0.8rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--bg);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--ink-muted);
  cursor: pointer;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease), background-color 0.25s var(--ease);
}
.bb-tab:hover { border-color: var(--line-strong); color: var(--ink); }
.bb-tab[aria-selected="true"] {
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand-strong);
}
.blackboard__canvas {
  display: block;
  width: 100%;
  height: clamp(260px, 34vw, 380px);
  border-radius: var(--radius-sm);
  background: var(--bg);
}
.blackboard__caption {
  margin-top: 0.85rem;
  min-height: 2.6em;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--ink-muted);
}
@media (max-width: 34rem) {
  .blackboard__controls { width: 100%; }
  .blackboard__tabs { flex: 1; }
  .bb-tab { flex: 1; min-width: 0; text-align: center; font-size: 0.74rem; padding: 0.36rem 0.45rem; }
}

/* --- Education --- */
.edu-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); gap: 1.25rem; }
.edu {
  display: flex;
  gap: 1rem;
  padding: 1.4rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  transition: transform 0.35s var(--ease), border-color 0.35s var(--ease);
}
.edu:hover { transform: translateY(-3px); border-color: var(--line-strong); }
.edu__icon {
  display: grid; place-items: center;
  width: 2.6rem; height: 2.6rem;
  border-radius: 10px;
  background: var(--brand-soft);
  color: var(--brand-strong);
  flex: none;
}
.edu__icon svg { width: 1.3rem; height: 1.3rem; }
.edu h3 { font-size: 1.05rem; margin-bottom: 0.15rem; }
.edu p { margin: 0; font-size: 0.9rem; color: var(--ink-muted); }
.edu .year { font-family: var(--font-mono); font-size: 0.78rem; color: var(--ink-faint); }

/* --- Contact --- */
.contact__card {
  position: relative;
  padding: clamp(2.5rem, 7vw, 4.5rem) clamp(1.5rem, 5vw, 3rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(60% 120% at 50% -10%, var(--brand-soft), transparent 70%),
    var(--bg-elevated);
  box-shadow: var(--shadow-md);
  text-align: center;
}
.contact__title { font-size: clamp(1.9rem, 4.5vw, 2.8rem); letter-spacing: -0.03em; }
.contact__text { color: var(--ink-muted); max-width: 34rem; margin-inline: auto; margin-bottom: 2rem; }
.contact__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; }

/* --- Footer --- */
.site-footer {
  border-top: 1px solid var(--line);
  padding-block: 2.25rem;
  font-size: 0.87rem;
  color: var(--ink-muted);
}
.site-footer .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.site-footer p { margin: 0; }
.social { display: flex; gap: 0.5rem; }
.social a {
  display: grid; place-items: center;
  width: 2.2rem; height: 2.2rem;
  border-radius: 8px;
  border: 1px solid var(--line);
  color: var(--ink-muted);
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.social a:hover { color: var(--brand-strong); border-color: var(--brand); transform: translateY(-2px); }
.social svg { width: 1.05rem; height: 1.05rem; }

/* --- Back to top --- */
.to-top {
  position: fixed;
  right: clamp(1rem, 3vw, 2rem);
  bottom: clamp(1rem, 3vw, 2rem);
  z-index: 90;
  opacity: 0;
  transform: translateY(12px) scale(0.9);
  pointer-events: none;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
  box-shadow: var(--shadow-md);
}
.to-top.is-shown { opacity: 1; transform: none; pointer-events: auto; }

/* --- Sub-page (CV) --- */
.page-hero { padding-block: clamp(3rem, 8vh, 5rem) clamp(1.5rem, 4vh, 2.5rem); }
.page-hero .section__title { margin-bottom: 0.5rem; }
.page-hero .hero__actions { margin-top: 1.5rem; }

.pdf-frame {
  width: 100%;
  height: min(80vh, 62rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-md);
}
.pdf-fallback {
  padding: 2.5rem 1.5rem;
  text-align: center;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  color: var(--ink-muted);
}

.error-page {
  min-height: 70vh;
  display: grid;
  place-content: center;
  text-align: center;
  gap: 0.5rem;
}
.error-page .code {
  font-family: var(--font-display);
  font-size: clamp(4rem, 16vw, 9rem);
  line-height: 1;
  color: var(--brand);
  letter-spacing: -0.04em;
  margin: 0;
}

/* 8. Responsive ========================================================== */

@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; }
  .portrait { order: -1; width: min(100%, 21rem); justify-self: start; }
  .about__grid { grid-template-columns: 1fr; }
  /* Nothing to stick to once the columns stack. */
  .about__side { position: static; }
  .routing { grid-template-columns: 1fr; }
  .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Nine lanes, a total, and three cost bars is thirteen stacked rows. At
     16/9 on a phone that is about fifteen pixels each, which is not a chart.
     The drawing is sized off the box, so giving it a taller box is the whole
     fix. Contracts needs the same treatment for the same reason: its settled
     dashboard draws the rebate owed near y=278, which falls outside a 16/9
     box once the canvas is phone width. */
  .capacity__canvas { aspect-ratio: 4 / 5; }
  .contracts__canvas { aspect-ratio: 4 / 5; }
  /* The staffing schedule is a grid thirty-two columns wide. Squaring it up
     rather than stretching it keeps the cells wide enough to carry a label. */
  .staffing__canvas { aspect-ratio: 1 / 1; }
}
@media (max-width: 520px) {
  .capacity__canvas { aspect-ratio: 3 / 4; }
  .contracts__canvas { aspect-ratio: 3 / 4; }
  .staffing__canvas { aspect-ratio: 4 / 5; }
}

/* THE MASTHEAD COLLAPSES AT 976px, NOT 720px.

   Laid out horizontally it needs about 965px: brand, six links, the
   résumé button, the era switch, the theme toggle and two gutters. The
   toggle used to appear only at 720, so every width from 721 to 964 --
   iPad portrait, a 768 or 900 pixel browser window, a small laptop --
   rendered the full desktop nav in a space it did not fit. Measured at
   768: 945px of header in a 753px viewport, the era and theme controls
   pushed off the right edge, and a horizontal scrollbar on the document.

   Keep this in step with NAV_BREAK in assets/js/main.js, which decides
   when to close the panel on resize and when to run the sliding
   indicator. */
@media (max-width: 976px) {
  /* Every rule that collapses the masthead is gated on .js, which main.js
     puts on <html>. The panel is hidden until a script adds .is-open, so
     ungated it would take the links away from anyone whose JavaScript did
     not run -- and widening this breakpoint from 720px would have done
     that at 721-976px, where the desktop row used to survive. Without .js
     the nav simply stays the ordinary inline row. */
  .js .nav-toggle { display: grid; }
  .era { display: none; }

  /* Anchored to the header rather than to a hardcoded 4.5rem offset.
     The header is sticky, so it is positioned and becomes this panel's
     containing block; top:100% then sits flush under it whatever height
     it happens to be. The old fixed 4.5rem assumed a 72px masthead and
     left a 16.6px strip of live page showing under a shorter one.

     max-height + scroll because the panel had neither: in a short
     landscape window (812x375) the last links sat below the fold, and a
     panel out of the document flow cannot be scrolled to. */
  .js .nav {
    position: absolute;
    inset: 100% 0 auto 0;
    max-height: calc(100vh - 4.5rem);
    max-height: calc(100dvh - 4.5rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.75rem var(--gutter) 1.25rem;
    background: var(--bg-elevated);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-lg);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s var(--ease), transform 0.3s var(--ease), visibility 0.3s;
  }
  .js .nav.is-open { opacity: 1; transform: none; visibility: visible; }

  .js .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .js .nav__link { padding: 0.85rem 0.5rem; font-size: 1rem; border-bottom: 1px solid var(--line); border-radius: 0; }
  .js .nav__list li:last-child .nav__link { border-bottom: 0; }
  .js .nav__indicator { display: none; }
  .js .nav .btn { margin-top: 0.9rem; justify-content: center; }

  /* Without JavaScript there is no toggle to press, so the links stay in
     the normal flow. The masthead is a single non-wrapping flex row, which
     at phone widths pushed the page out to 788px inside a 420px viewport,
     so let it wrap instead. Visible and slightly taller beats sideways
     scrolling, and beats no navigation at all. */
  html:not(.js) .site-header .container { flex-wrap: wrap; row-gap: 0.5rem; }
  html:not(.js) .header-actions { flex-wrap: wrap; row-gap: 0.5rem; }
  html:not(.js) .nav { max-width: 100%; }
  html:not(.js) .nav__list { flex-wrap: wrap; row-gap: 0.25rem; }
}

/* Genuinely phone-sized adjustments stay at 720. */
@media (max-width: 720px) {
  .role__head { flex-direction: column; }
  .portrait__badge { font-size: 0.75rem; padding: 0.45rem 0.75rem; }

  /* Sideways reveals would push past a narrow viewport before they settle. */
  .js .reveal--left, .js .reveal--right { transform: translateY(22px); }
}

@media (max-width: 460px) {
  .metrics { grid-template-columns: 1fr; }
  .hero__actions .btn { flex: 1 1 100%; justify-content: center; }
}

@media print {
  .site-header, .to-top, .progress-bar, .hero__mesh, .site-footer { display: none !important; }
  body { background: #fff; color: #000; }
}
