/* =========================================================================
   Muhammad Ahmad — portfolio design system
   Single stylesheet, no framework. Dark-first with a light theme via tokens.
   ========================================================================= */

/* ---------- Tokens ---------- */
:root {
  --bg:            #fbfbfa;
  --bg-elev:       #ffffff;
  --surface:       #ffffff;
  --surface-2:     #f4f4f2;
  --border:        rgba(16, 20, 30, 0.11);
  --border-strong: rgba(16, 20, 30, 0.19);

  --text:          #14161a;
  --text-muted:    #565b63;
  --text-faint:    #646a74;

  --accent:        #1f6f8b;
  --accent-2:      #6b5bbd;
  --accent-soft:   rgba(31, 111, 139, 0.10);
  --accent-line:   linear-gradient(120deg, #1f6f8b 0%, #3d6fa6 55%, #6b5bbd 100%);
  --ok:            #2e6b50;
  --bad:           #9c4221;
  --bad-soft:      rgba(156, 66, 33, 0.07);
  --bad-line:      rgba(156, 66, 33, 0.30);
  --ok-soft:       rgba(46, 107, 80, 0.09);
  --ok-line:       rgba(46, 107, 80, 0.32);
  --on-accent:     #ffffff;

  /* ground-dependent effects, so components stop hard-coding them */
  --glow-a:    rgba(31, 111, 139, .10);
  --glow-b:    rgba(107, 91, 189, .09);
  --spot:      rgba(16, 20, 30, .055);
  --btn-glow:   0 10px 26px -14px rgba(16, 20, 30, .5);
  --btn-glow-h: 0 16px 34px -14px rgba(16, 20, 30, .58);

  --shadow-sm: 0 1px 2px rgba(20, 25, 45, .07);
  --shadow-md: 0 12px 32px -16px rgba(20, 25, 45, .20);
  --shadow-lg: 0 32px 70px -30px rgba(20, 25, 45, .24);

  --radius:    14px;
  --radius-lg: 22px;
  --maxw:      1160px;
  --nav-h:     68px;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

html[data-theme="dark"] {
  --bg:            #08090c;
  --bg-elev:       #0d0f15;
  --surface:       #11141c;
  --surface-2:     #161a24;
  --border:        rgba(255, 255, 255, 0.09);
  --border-strong: rgba(255, 255, 255, 0.16);

  --text:          #e8eaf0;
  --text-muted:    #969db0;
  --text-faint:    #6b7285;

  --accent:        #22d3ee;
  --accent-2:      #a78bfa;
  --accent-soft:   rgba(34, 211, 238, 0.12);
  --accent-line:   linear-gradient(120deg, #22d3ee 0%, #818cf8 55%, #a78bfa 100%);
  --ok:            #34d399;
  --bad:           #e0a08a;
  --bad-soft:      rgba(224, 160, 138, 0.09);
  --bad-line:      rgba(224, 160, 138, 0.32);
  --ok-soft:       rgba(52, 211, 153, 0.11);
  --ok-line:       rgba(52, 211, 153, 0.35);
  --on-accent:     #05070a;

  --glow-a:    rgba(34, 211, 238, .14);
  --glow-b:    rgba(167, 139, 250, .13);
  --spot:      rgba(255, 255, 255, .10);
  --btn-glow:   0 10px 26px -12px rgba(34, 211, 238, .8);
  --btn-glow-h: 0 16px 34px -12px rgba(34, 211, 238, .9);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-md: 0 12px 32px -12px rgba(0, 0, 0, .7);
  --shadow-lg: 0 32px 70px -24px rgba(0, 0, 0, .8);
}

/* ---------- Cross-page view transitions (progressive enhancement; unsupported browsers just navigate normally) ---------- */
@view-transition {
  navigation: auto;
}
::view-transition-old(root), ::view-transition-new(root) {
  animation-duration: .32s;
  animation-timing-function: cubic-bezier(.2, .7, .2, 1);
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) {
    animation: none !important;
  }
}

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 16px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Ambient glow behind the page — subtle, fixed, non-interactive */
body::before {
  content: "";
  position: fixed;
  inset: -30% -10% auto -10%;
  height: 70vh;
  background:
    radial-gradient(60% 60% at 20% 0%, var(--glow-a), transparent 70%),
    radial-gradient(50% 50% at 80% 10%, var(--glow-b), transparent 70%);
  pointer-events: none;
  z-index: 0;
}


/* height:auto so intrinsic width/height attributes don't fight aspect-ratio */
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 {
  margin: 0;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 650;
}
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

::selection { background: var(--accent); color: var(--on-accent); }

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

.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 24px;
  position: relative;
  z-index: 1;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--on-accent);
  padding: 10px 16px;
  z-index: 999;
  font-weight: 600;
}
.skip-link:focus { left: 12px; top: 12px; }

/* ---------- Header ---------- */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  z-index: 100;
  transition: background .25s ease, border-color .25s ease, backdrop-filter .25s 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(--border);
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 650;
  letter-spacing: -0.02em;
  font-size: 15px;
}
.brand-mark {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  background: var(--accent-line);
  color: var(--on-accent);
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.04em;
  box-shadow: 0 0 0 1px var(--border-strong);
}
.brand-sub { color: var(--text-faint); font-weight: 450; }

.nav { display: flex; align-items: center; gap: 0; }
.nav a {
  padding: 8px 13px;
  font-size: 14px;
  color: var(--text-muted);
  border-radius: 8px;
  transition: color .18s ease, background .18s ease;
  white-space: nowrap;
}
.nav a:hover { color: var(--text); background: var(--surface-2); }
.nav a.active { color: var(--text); }
.nav a.active::after {
  content: "";
  display: block;
  height: 2px;
  margin-top: 4px;
  border-radius: 2px;
  background: var(--accent-line);
}

.header-actions { display: flex; align-items: center; gap: 8px; }

.icon-btn {
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: color .18s ease, border-color .18s ease, transform .18s ease;
}
.icon-btn:hover { color: var(--text); border-color: var(--border-strong); transform: translateY(-1px); }
.icon-btn svg { width: 17px; height: 17px; }

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

.nav-toggle { display: none; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 20px;
  border-radius: 11px;
  font-size: 14.5px;
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .18s ease, box-shadow .18s ease, background .18s ease, border-color .18s ease, color .18s ease;
  font-family: inherit;
  white-space: nowrap;
}
.btn svg { width: 17px; height: 17px; flex: none; }
.btn-primary {
  background: var(--accent-line);
  color: var(--on-accent);
  box-shadow: var(--btn-glow);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: var(--btn-glow-h); }
.btn-ghost {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
}
.btn-ghost:hover { border-color: var(--border-strong); transform: translateY(-2px); background: var(--surface-2); }
.btn-sm { padding: 8px 14px; font-size: 13.5px; border-radius: 9px; }

/* ---------- Section scaffolding ---------- */
.section { padding: 104px 0; position: relative; }
.section-alt { background: var(--bg-elev); border-block: 1px solid var(--border); }

.section-head { max-width: 720px; margin-bottom: 48px; }
.section-head.center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}
.eyebrow::before {
  content: "";
  width: 22px;
  height: 1px;
  background: var(--accent);
  opacity: .7;
}
.section-head.center .eyebrow::before { display: none; }

.section-head h2 {
  font-size: clamp(28px, 4vw, 40px);
  margin-bottom: 14px;
}
.section-head p { color: var(--text-muted); font-size: 16.5px; }

/* ---------- Hero ---------- */
.hero {
  padding: calc(var(--nav-h) + 30px) 0 70px;
  position: relative;
  overflow: hidden;
}
.hero-grid {
  display: grid;
  grid-template-columns: 1.35fr 0.75fr;
  gap: 48px;
  align-items: center;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 14px 6px 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 26px;
}
.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 0 rgba(52, 211, 153, .55);
  animation: pulse 2.4s infinite;
}
@keyframes pulse {
  70%  { box-shadow: 0 0 0 8px rgba(52, 211, 153, 0); }
  100% { box-shadow: 0 0 0 0 rgba(52, 211, 153, 0); }
}

.hero h1 {
  font-size: clamp(40px, 6.4vw, 66px);
  line-height: 1.03;
  letter-spacing: -0.035em;
  margin-bottom: 18px;
}
.grad {
  background: var(--accent-line);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-role {
  font-size: clamp(18px, 2.4vw, 23px);
  font-weight: 550;
  color: var(--text);
  margin-bottom: 18px;
  min-height: 1.5em;
}
.hero-role .rotator { color: var(--accent); }
.caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  background: var(--accent);
  vertical-align: -0.15em;
  margin-left: 2px;
  animation: blink 1s step-end infinite;
}
@keyframes blink { 50% { opacity: 0; } }

.hero-lede {
  color: var(--text-muted);
  font-size: 17px;
  max-width: 60ch;
  margin-bottom: 30px;
}
.hero-lede strong { color: var(--text); font-weight: 600; }

.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 28px; margin-bottom: 34px; }

.hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  font-size: 13.5px;
  color: var(--text-faint);
  border-top: 1px solid var(--border);
  padding-top: 22px;
}
.hero-meta span { display: inline-flex; align-items: center; gap: 7px; }
.hero-meta svg { width: 15px; height: 15px; color: var(--accent); }

/* Hero photo */
.hero-photo { position: relative; }

/* ---------- Hero field ----------
   A live node network behind the portrait that reacts to the pointer. It draws
   in --accent read from the theme, so it follows the toggle, and renders a
   single static frame under reduced motion. */
.hero-field {
  /* A canvas is a replaced element: with height:auto the browser uses its
     intrinsic size and ignores the bottom offset, so the box is stated
     explicitly instead of as four insets. */
  position: absolute;
  top: -70%;
  left: -14%;
  width: 128%;
  height: 200%;
  z-index: 0;
  pointer-events: none;
}
.hero-photo .photo-frame { position: relative; z-index: 1; }
.photo-frame {
  position: relative;
  border-radius: var(--radius-lg);
  padding: 1px;
  background: linear-gradient(150deg, var(--border-strong), transparent 45%, var(--border-strong));
  box-shadow: var(--shadow-lg);
}
.photo-frame img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: 50% 42%;
  border-radius: calc(var(--radius-lg) - 1px);
  display: block;
}
.photo-caption {
  position: absolute;
  left: 14px;
  bottom: 14px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border-radius: 999px;
  font-size: 12.5px;
  color: #eef1f6;
  background: rgba(8, 9, 12, .62);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, .14);
}
.photo-caption svg { width: 14px; height: 14px; color: var(--accent); }

.float-card {
  position: absolute;
  right: -14px;
  bottom: -22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 13px 16px;
  box-shadow: var(--shadow-md);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
  color: var(--text-muted);
  animation: float 6s ease-in-out infinite;
}
.float-card b { color: var(--accent); font-weight: 600; }
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}

/* ---------- Stats ---------- */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}
.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 26px 24px;
  position: relative;
  overflow: hidden;
  transition: transform .22s ease, border-color .22s ease;
}
.stat::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--accent-line);
  opacity: 0;
  transition: opacity .22s ease;
}
.stat:hover { transform: translateY(-4px); border-color: var(--border-strong); }
.stat:hover::after { opacity: 1; }
.stat-num {
  font-size: clamp(30px, 4vw, 40px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: 10px;
  background: var(--accent-line);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stat-label { font-size: 14px; color: var(--text-muted); }
.stat-label b { color: var(--text); font-weight: 600; display: block; margin-bottom: 2px; }

/* ---------- About ---------- */
.about-grid {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 56px;
  align-items: start;
}
.about-body p { color: var(--text-muted); font-size: 16.5px; }
.about-body strong { color: var(--text); font-weight: 600; }

.info-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 8px 22px;
  box-shadow: var(--shadow-md);
}
.info-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 15px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14.5px;
}
.info-row:last-child { border-bottom: 0; }
.info-row svg { width: 17px; height: 17px; color: var(--accent); flex: none; margin-top: 3px; }
.info-row .k { color: var(--text-faint); min-width: 92px; flex: none; }
/* min-width:0 lets the flex item shrink; a mail address is one unbreakable
   token, so without overflow-wrap it pushes straight out of the card. */
.info-row .v { color: var(--text); font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.info-row a:hover { color: var(--accent); }

/* ---------- Reference scroller ----------
   Zeeshan's leads as a full citation because it names the systems in the grid
   above. The other eight run as a horizontal scroller: each quote is clamped
   to a readable depth and links to about.html, where all nine sit in full.
   The track scrolls natively, so it drags on touch and the arrows are an
   enhancement rather than the only way through. It also creeps leftward on
   its own; any interaction stops that drift and it resumes shortly after. */
.revs { margin-top: 38px; }
.revs-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 14px;
}
.revs-k {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0;
}
.revs-nav { display: flex; gap: 8px; }
.revs-btn {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: border-color .18s ease, color .18s ease, opacity .18s ease;
}
.revs-btn svg { width: 15px; height: 15px; }
.revs-btn:hover { border-color: var(--accent); color: var(--text); }
.revs-btn[disabled] { opacity: .32; cursor: default; }
.revs-btn[disabled]:hover { border-color: var(--border-strong); color: var(--text-muted); }

.revs-track {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  /* No scroll snapping. The drift advances scrollLeft a pixel at a time, and
     any snapping re-aligns each write to the nearest card boundary, so a
     one-pixel step lands back where it started and the rail never moves. */
  /* No scroll-behavior here on purpose: the drift writes scrollLeft every
     frame, and a smooth behaviour would restart an animation each time and
     stall it. The arrows ask for smooth explicitly when they scroll. */
  padding: 4px 4px 16px;
  scrollbar-width: thin;
}
.revs-track::-webkit-scrollbar { height: 6px; }
.revs-track::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 99px; }

.rev-card {
  flex: none;
  width: 392px;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: 22px 24px 20px;
  transition: border-color .18s ease, transform .18s ease;
}
.rev-card:hover { border-color: var(--border-strong); transform: translateY(-3px); }
.rev-mark {
  font-size: 34px;
  line-height: .7;
  color: var(--border-strong);
  margin-bottom: 8px;
}
.rev-body {
  color: var(--text-muted);
  font-size: 14.5px;
  line-height: 1.62;
  /* A fixed seven-line box rather than -webkit-line-clamp: the clamp counts
     line boxes of a -webkit-box, and with several <p> children inside a
     stretching flex item it mismeasured and let the text run over the
     footer. A height in em is exact and the fade shows there is more. */
  height: 11.34em;
  overflow: hidden;
  flex: none;
  -webkit-mask-image: linear-gradient(180deg, #000 78%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 78%, transparent 100%);
}
.rev-body p { margin: 0 0 10px; }
.rev-body p:last-child { margin-bottom: 0; }

.rev-foot { display: flex; align-items: center; gap: 11px; margin-top: 18px; }
.rev-foot p { margin: 0; }
.citation figcaption p { margin: 0; }
.rev-ini {
  width: 36px; height: 36px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-muted);
}
.rev-id { display: flex; flex-direction: column; min-width: 0; }
.rev-who { font-size: 14px; font-weight: 600; color: var(--text); }
.rev-role { font-size: 12px; color: var(--text-faint); }
.rev-when { margin-left: auto; font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); white-space: nowrap; }

.rev-more {
  margin-top: 14px;
  align-self: flex-start;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}
.rev-more:hover { text-decoration: underline; }

@media (max-width: 560px) {
  .rev-card { width: 85vw; }
}


/* ---------- Technology ticker ----------
   The old marquee was a row of bare product names, which is the one thing
   every template does. Each item here carries the system it actually ran in,
   so the strip states something rather than decorating.

   Two rows travel in opposite directions at different speeds, which reads as
   depth instead of a conveyor belt. Each track holds two identical runs and
   shifts by exactly one, so the loop has no seam. Hover pauses both. Under
   reduced motion the animation is dropped and the rows become scrollers. */
.ticker {
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 16px 0;
  display: grid;
  gap: 10px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.tick-row { overflow: hidden; }
.tick-track { display: flex; width: max-content; }
.tick-row.to-left  .tick-track { animation: tick-left  64s linear infinite; }
.tick-row.to-right .tick-track { animation: tick-right 82s linear infinite; }
@keyframes tick-left  { from { transform: translateX(0); }    to { transform: translateX(-50%); } }
@keyframes tick-right { from { transform: translateX(-50%); } to { transform: translateX(0); } }
.ticker:hover .tick-track { animation-play-state: paused; }

.tick {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 0 22px;
  white-space: nowrap;
  border-right: 1px solid var(--border);
}
.tick b {
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: .01em;
}
.tick p {
  margin: 0;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-faint);
  opacity: .78;
}
.tick-row.to-right .tick b { color: var(--text-faint); }

@media (max-width: 700px) {
  .tick { padding: 0 15px; }
  .tick b { font-size: 11.5px; }
  .tick p { font-size: 9.5px; }
}
@media (prefers-reduced-motion: reduce) {
  .tick-row { overflow-x: auto; }
  .tick-track { animation: none; }
}

/* ---------- Page link ----------
   "All twelve systems" was plain text doing a page jump with nothing to say
   so. The arrow points out of the box, the convention for leaving the page. */
.page-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 26px;
  padding: 11px 18px;
  border: 1px solid var(--border-strong);
  border-radius: 99px;
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  transition: border-color .18s ease, background .18s ease, transform .18s ease;
}
.page-link svg { width: 15px; height: 15px; color: var(--accent); transition: transform .18s ease; }
.page-link:hover { border-color: var(--accent); transform: translateY(-2px); }
.page-link:hover svg { transform: translate(2px, -2px); }

/* Source note under the references. */
.rq-source { font-size: 13px; color: var(--text-faint); margin: 18px 0 0; }

/* ---------- Twelve-systems rail ----------
   The track holds two identical runs and shifts by exactly -50%, so the loop
   is seamless. It pauses on hover and on keyboard focus, and under reduced
   motion the animation is dropped and the rail becomes an ordinary horizontal
   scroller, which is also the fallback for touch. */
.rail-wrap { margin-top: 36px; }
.rail-label {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 12px;
}
.rail {
  position: relative;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.rail-track {
  display: flex;
  gap: 14px;
  width: max-content;
  animation: rail-scroll 54s linear infinite;
}
@keyframes rail-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-50% - 7px)); }
}
.rail:hover .rail-track,
.rail:focus-within .rail-track { animation-play-state: paused; }

.rail-card {
  flex: none;
  width: 248px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 14px 16px 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color .18s ease, transform .18s ease;
}
.rail-card:hover { border-color: var(--accent); transform: translateY(-3px); }
.rail-card p { margin: 0; }
.rail-no {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  color: var(--text-faint);
}
.rail-name { font-size: 14.5px; font-weight: 600; color: var(--text); letter-spacing: -.01em; }
.rail-meta { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); }
.rail-tag {
  margin-top: 6px;
  align-self: flex-start;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 99px;
  padding: 3px 8px;
}

@media (prefers-reduced-motion: reduce) {
  .rail { overflow-x: auto; -webkit-mask-image: none; mask-image: none; }
  .rail-track { animation: none; }
}

/* Still live: .led-stack captions the timeline entries on about.html, and
   .inline-link styles prose links across every page. The rest of the old
   ledger and marquee rules went with the sections they styled. */
.led-stack {
  font-family: var(--mono); font-size: 11px; color: var(--text-faint);
  margin: 10px 0 0;
}
.inline-link { color: var(--accent); border-bottom: 1px solid var(--accent-soft); }
.inline-link:hover { border-bottom-color: var(--accent); }

/* ---------- Career spine ----------
   Roles only. Study and research sit in their own block beneath, so the
   "five years" claim on the heading can only be read as paid work.

   The axis carries a lit segment that tracks scroll position: a gradient that
   grows from the top with a glowing head at its leading edge, so the line
   fills as the reader moves down it. The whole effect is one element and one
   custom property, and it is simply never updated under reduced motion. */
.spine { position: relative; padding-left: 52px; }
.spine-axis {
  position: absolute;
  left: 7px; top: 6px; bottom: 6px;
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--border-strong) 4%, var(--border-strong) 96%, transparent);
}
.spine-lit,
.axis-lit {
  position: absolute;
  left: -1px; top: 0;
  width: 3px;
  height: var(--lit, 0%);
  border-radius: 99px;
  background: linear-gradient(180deg, transparent, var(--accent) 18%, var(--accent-2, var(--accent)));
  box-shadow: 0 0 10px -1px var(--accent);
  opacity: .9;
}
.spine-lit::after,
.axis-lit::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 0;
  width: 9px; height: 9px;
  border-radius: 50%;
  transform: translate(-50%, 50%);
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--glow-a), 0 0 14px 2px var(--accent);
}

.sp-year { margin: 16px 0 6px; }
.sp-year p {
  margin: 0 0 0 -52px;
  display: inline-block;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  color: var(--text-faint);
  background: var(--bg);
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 99px;
}

.sp-item { position: relative; padding: 8px 0 18px; }
.sp-card { position: relative; }
.sp-dot {
  position: absolute;
  left: -52px; top: 28px;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--border-strong);
}
.sp-item.is-now .sp-dot {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--glow-a);
}

.sp-card {
  /* This is an <a>. Without an explicit display it lays out inline and the
     border breaks into a fragment per line box. */
  display: block;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 18px 20px;
  transition: border-color .18s ease, transform .18s ease;
}
.sp-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.sp-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.sp-card::after {
  content: "\2197";              /* ↗ : this card opens its full entry */
  position: absolute;
  right: 16px; top: 14px;
  font-size: 14px;
  line-height: 1;
  color: var(--accent);
  opacity: 0;
  transition: opacity .18s ease, transform .18s ease;
}
.sp-card:hover::after,
.sp-card:focus-visible::after { opacity: 1; transform: translate(2px, -2px); }
.sp-when { font-family: var(--mono); font-size: 11px; color: var(--text-faint); margin: 0 0 6px; }
.sp-when em {
  font-style: normal;
  margin-left: 8px;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: 99px;
  font-size: 9.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.sp-card h3 { font-size: 16.5px; line-height: 1.3; margin: 0 0 3px; letter-spacing: -.015em; }
.sp-org  { color: var(--text-muted); font-size: 13.5px; margin: 0; }
.sp-line { color: var(--text-muted); font-size: 14px; margin: 10px 0 0; max-width: 74ch; }
.sp-stack { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); margin: 10px 0 0; }

/* ---------- Education, kept apart from the career axis ---------- */
.edu-head { margin-top: 44px; padding-top: 30px; border-top: 1px solid var(--border); }
.edu-head h3 { font-size: clamp(19px, 2vw, 24px); letter-spacing: -.02em; margin: 10px 0 0; }

.edu {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 34px;
  margin-top: 26px;
}
.edu-line { color: var(--text-muted); font-size: 14px; margin: 0 0 14px; }
.edu-line:last-child { margin-bottom: 0; }
.edu-line strong { color: var(--text); font-weight: 600; }

@media (max-width: 720px) {
  .spine { padding-left: 34px; }
  .spine-axis { left: 5px; }
  .sp-year p { margin-left: -34px; }
  .sp-dot { left: -34px; }
  .edu { grid-template-columns: 1fr; gap: 24px; }
}

/* ---------- Stack constellation ----------
   Nodes are positioned in percentages and the wire layer uses a 0-100 viewBox
   with preserveAspectRatio="none", so both share one coordinate space and the
   endpoints stay glued to the nodes at every width. non-scaling-stroke keeps
   the lines even when that box is stretched non-uniformly.
   Below 820px the graph is unreadable, so it is dropped and the ledger beneath
   carries the same information in full. */
.constel {
  position: relative;
  aspect-ratio: 16 / 7;
  margin-bottom: 14px;
  background:
    radial-gradient(58% 70% at 20% 32%, var(--glow-a), transparent 68%),
    radial-gradient(52% 64% at 80% 68%, var(--glow-b), transparent 68%);
  overflow: visible;
}
.constel-wires { position: absolute; inset: 0; width: 100%; height: 100%; }
.cw {
  stroke: var(--border-strong);
  stroke-width: 1;
  opacity: .55;
  transition: stroke .18s ease, opacity .18s ease;
}
.constel.is-tracing .cw { opacity: .14; }
.constel.is-tracing .cw.lit { opacity: 1; stroke: var(--accent); }

.cl-tag {
  position: absolute;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-faint);
  opacity: .8;
  pointer-events: none;
}
.cl-ai { left: 3%;  top: 4%; }
.cl-be { left: 40%; top: 4%; }
.cl-da { left: 72%; top: 4%; }
.cl-in { left: 20%; bottom: 4%; }

.cnode {
  position: absolute;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px 5px 7px;
  border: 1px solid var(--border-strong);
  border-radius: 99px;
  background: var(--bg-elev);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .18s ease, color .18s ease, opacity .18s ease, box-shadow .18s ease;
}
.cnode::before {
  content: "";
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-faint);
  flex: none;
  transition: background .18s ease;
}
.cnode.w2 { font-size: 12.5px; }
.cnode.w2::before { width: 9px; height: 9px; }
.cnode.w3 { font-size: 13.5px; font-weight: 500; }
.cnode.w3::before { width: 11px; height: 11px; background: var(--accent); }

.cnode:hover,
.cnode:focus-visible { border-color: var(--accent); color: var(--text); outline: none; }
.constel.is-tracing .cnode { opacity: .3; }
.constel.is-tracing .cnode.lit { opacity: 1; }
.constel.is-tracing .cnode.src {
  opacity: 1;
  border-color: var(--accent);
  color: var(--text);
  box-shadow: 0 0 0 4px var(--glow-a);
}
.constel.is-tracing .cnode.lit::before,
.constel.is-tracing .cnode.src::before { background: var(--accent); }

.constel-read {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-faint);
  margin: 0 0 26px;
  min-height: 1.5em;
}
.constel-read b { color: var(--text); font-weight: 600; }
.constel-read span { color: var(--text-faint); }

@media (max-width: 820px) {
  .constel, .constel-read { display: none; }
}

/* ---------- Experience timeline ---------- */
.timeline { position: relative; padding-left: 30px; }
.timeline > .axis-lit { left: 5px; }
.timeline::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: linear-gradient(180deg, var(--accent), var(--accent-2), transparent);
  opacity: .45;
}
.tl-item { position: relative; padding-bottom: 46px; }
.tl-item:last-child { padding-bottom: 0; }
.tl-item::before {
  content: "";
  position: absolute;
  left: -30px;
  top: 7px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--accent);
}
.tl-item.is-current::before { background: var(--accent); box-shadow: 0 0 0 5px var(--accent-soft); }

.tl-period {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--accent);
  letter-spacing: .04em;
  margin-bottom: 6px;
}
.tl-item h3 { font-size: 19px; margin-bottom: 4px; }
.tl-org { color: var(--text-muted); font-size: 14.5px; margin-bottom: 14px; }
.tl-item ul { margin: 0 0 16px; padding-left: 0; list-style: none; }
.tl-item li {
  position: relative;
  padding-left: 20px;
  margin-bottom: 9px;
  color: var(--text-muted);
  font-size: 15px;
}
.tl-item li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: .68em;
  width: 6px;
  height: 1.5px;
  background: var(--accent);
  opacity: .8;
}
.tl-item li strong { color: var(--text); font-weight: 600; }

.promo-note {
  display: inline-flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-muted);
  background: var(--accent-soft);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 12px;
  margin-bottom: 14px;
}
.promo-note svg { width: 14px; height: 14px; flex: none; margin-top: 3px; color: var(--accent); }

.tags { display: flex; flex-wrap: wrap; gap: 7px; }
.tags span {
  font-family: var(--mono);
  font-size: 11.5px;
  padding: 4px 9px;
  border-radius: 6px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-faint);
}

.edu-grid { display: grid; gap: 18px; }
.edu-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px 24px;
  transition: border-color .2s ease, transform .2s ease;
}
.edu-card:hover { border-color: var(--border-strong); transform: translateY(-3px); }
.edu-card h3 { font-size: 16.5px; margin-bottom: 4px; }
.edu-card .tl-period { margin-bottom: 8px; }
.edu-card p { color: var(--text-muted); font-size: 14.5px; }
.exp-columns { display: grid; grid-template-columns: 1.5fr 1fr; gap: 60px; align-items: start; }
.col-title {
  font-size: 13px;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--text-faint);
  margin-bottom: 26px;
}

/* ---------- Skills ---------- */
.skills-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.skill-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 26px 24px;
  transition: transform .22s ease, border-color .22s ease, box-shadow .22s ease;
}
.skill-card:hover {
  transform: translateY(-4px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}
.skill-card.featured { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); background: linear-gradient(180deg, var(--accent-soft), transparent 60%), var(--surface); }
.skill-head { display: flex; align-items: center; gap: 11px; margin-bottom: 18px; }
.skill-head svg { width: 19px; height: 19px; color: var(--accent); }
.skill-head h3 { font-size: 16px; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  font-size: 13px;
  padding: 5px 11px;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-muted);
  transition: color .18s ease, border-color .18s ease;
}
.skill-card:hover .chip { color: var(--text); }

/* ---------- Projects ---------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 34px;
}
.filter-btn {
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 13.5px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: all .18s ease;
}
.filter-btn:hover { color: var(--text); border-color: var(--border-strong); }
.filter-btn.active {
  background: var(--accent-line);
  color: var(--on-accent);
  border-color: transparent;
  font-weight: 600;
}

.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 22px;
  align-items: stretch;
}
.project-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  position: relative;
  transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease, opacity .25s ease;
}
.project-card:hover {
  transform: translateY(-6px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-lg);
}
.project-card.is-hidden { display: none; }
.project-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity .25s ease;
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%), var(--spot), transparent 60%);
}
.project-card.is-tilting {
  transition: border-color .25s ease, box-shadow .25s ease, opacity .25s ease;
  box-shadow: var(--shadow-lg);
}
.project-card.is-tilting::after { opacity: 1; }
@media (hover: none), (pointer: coarse) {
  .project-card::after { display: none; }
}

.project-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.project-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}
.project-card:hover .project-thumb img { transform: scale(1.045); }
.project-kind {
  position: absolute;
  top: 12px;
  left: 12px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(8, 9, 12, .68);
  border: 1px solid rgba(255, 255, 255, .14);
  color: #e8eaf0;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.project-live {
  position: absolute;
  top: 12px;
  right: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(16, 185, 129, .14);
  border: 1px solid rgba(16, 185, 129, .4);
  color: #34d399;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.project-live::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #34d399;
  box-shadow: 0 0 0 3px rgba(52, 211, 153, .22);
}

.project-body { padding: 22px 24px 24px; display: flex; flex-direction: column; flex: 1; }
.project-body h3 { font-size: 18px; margin-bottom: 9px; }
.project-body > p { color: var(--text-muted); font-size: 14.5px; margin-bottom: 16px; }
.project-metric {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--accent);
  margin-bottom: 16px;
}
.project-body .tags { margin-bottom: 20px; }
.project-link {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  width: fit-content;
}
.project-link svg { width: 15px; height: 15px; transition: transform .2s ease; }
.project-link:hover { color: var(--accent); }
.project-link:hover svg { transform: translateX(4px); }

/* ---------- Testimonials ---------- */
.quote-grid {
  columns: 3;
  column-gap: 20px;
}
.quote-card {
  break-inside: avoid;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
  margin-bottom: 20px;
  transition: border-color .2s ease, transform .2s ease;
}
.quote-card:hover { border-color: var(--border-strong); transform: translateY(-3px); }
.quote-mark { font-size: 34px; line-height: 1; color: var(--accent); opacity: .5; font-family: Georgia, serif; }
.quote-card p { color: var(--text-muted); font-size: 14.5px; margin: 8px 0 18px; }
.quote-author { display: flex; align-items: center; gap: 12px; }
.quote-author img { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; border: 1px solid var(--border); }
.quote-author h4 { font-size: 14.5px; }
.quote-author span { font-size: 12.5px; color: var(--text-faint); }
.quote-author .quote-role { display: block; line-height: 1.45; }
.quote-author .quote-date {
  display: block;
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-faint);
  opacity: .72;
}

/* Monogram stands in where there is no photograph. Pulling a recommender's
   picture off LinkedIn is not ours to do. */
/* Two classes deep on purpose: `.quote-author span` sets colour and size for
   the role and date, and would otherwise win on specificity over a bare
   `.quote-avatar` and render the monogram grey. */
.quote-author .quote-avatar {
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font: 600 13px/1 var(--mono);
  letter-spacing: .03em;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--border);
}

/* Long recommendations are clamped for reading, never cut in the markup.
   The full text is always in the DOM, so nothing is quoted out of context. */
.quote-body { position: relative; }
.quote-body.is-clamped {
  max-height: 15.5em;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
}
.quote-expand {
  background: none;
  border: 0;
  padding: 0;
  margin: 0 0 18px;
  cursor: pointer;
  font: 600 12.5px var(--font);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.quote-expand:hover { text-decoration: underline; }
.quote-expand::after {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .2s ease;
}
.quote-expand[aria-expanded="true"]::after { transform: translateY(1px) rotate(-135deg); }

.quote-card:target {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.rec-actions { display: flex; justify-content: center; margin-top: 8px; }
.rec-source {
  text-align: center;
  margin-top: 18px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-faint);
}
.rec-source a { color: var(--text-muted); }
.rec-source a:hover { color: var(--accent); }

/* ---------- Contact ---------- */
.contact-card {
  background:
    radial-gradient(90% 130% at 12% 0%, var(--accent-soft), transparent 62%),
    var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 54px clamp(28px, 5vw, 60px);
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 48px;
  align-items: center;
  box-shadow: var(--shadow-lg);
}
.contact-card h2 { font-size: clamp(26px, 3.6vw, 36px); margin-bottom: 14px; }
.contact-card > div > p { color: var(--text-muted); margin-bottom: 26px; }
/* The email is the primary action and takes its own row, so the two
   secondary buttons stay together underneath instead of one of them
   stranding beside the long address. */
.contact-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.contact-secondary { display: flex; flex-wrap: wrap; gap: 12px; }
.contact-list { display: grid; gap: 4px; }

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--border);
  padding: 34px 0;
  position: relative;
  z-index: 1;
}
.site-footer .container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
}
.site-footer p { color: var(--text-faint); font-size: 13.5px; }
.footer-links { display: flex; gap: 8px; }

.to-top {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 90;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: all .25s ease;
}
.to-top.show { opacity: 1; visibility: visible; transform: none; }

/* ---------- Detail pages ---------- */
.page-hero { padding: calc(var(--nav-h) + 64px) 0 0; }
.crumbs {
  display: flex;
  gap: 8px;
  align-items: center;
  font-size: 13.5px;
  color: var(--text-faint);
  margin-bottom: 18px;
}
.crumbs a:hover { color: var(--accent); }
.page-hero h1 { font-size: clamp(30px, 4.6vw, 46px); margin-bottom: 16px; }
.page-hero .lede { color: var(--text-muted); font-size: 17px; max-width: 65ch; margin-bottom: 22px; }

.detail-grid {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 46px;
  align-items: start;
  padding: 56px 0 104px;
}
.detail-figure {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: 22px;
  margin-bottom: 36px;
}
.detail-body h2 { font-size: 24px; margin: 34px 0 14px; }
.detail-body h2:first-child { margin-top: 0; }
.detail-body h3 { font-size: 17px; margin: 24px 0 10px; color: var(--accent); }
.detail-body p, .detail-body li { color: var(--text-muted); font-size: 16px; }
.detail-body ul { padding-left: 0; list-style: none; margin: 0 0 18px; }
.detail-body ul li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 10px;
}
.detail-body ul li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: .7em;
  width: 7px;
  height: 1.5px;
  background: var(--accent);
}
.detail-body strong { color: var(--text); font-weight: 600; }

.detail-aside {
  position: sticky;
  top: calc(var(--nav-h) + 24px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 26px;
  box-shadow: var(--shadow-md);
}
.detail-aside h3 { font-size: 13px; font-family: var(--mono); text-transform: uppercase; letter-spacing: .12em; color: var(--text-faint); margin-bottom: 18px; }
.aside-row { padding: 12px 0; border-bottom: 1px solid var(--border); font-size: 14.5px; }
.aside-row:last-of-type { border-bottom: 0; }
.aside-row .k { display: block; color: var(--text-faint); font-size: 12.5px; margin-bottom: 3px; }
.aside-row .v { color: var(--text); }

/* ---------- Scroll reveal ---------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .6s cubic-bezier(.2, .7, .3, 1), transform .6s cubic-bezier(.2, .7, .3, 1);
}
.reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition-duration: .01ms !important; }
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }
}

/* ---------- Responsive ---------- */
@media (max-width: 1040px) {
  .hero-grid { grid-template-columns: 1fr; gap: 44px; }
  .hero-photo { max-width: 620px; }
  .about-grid { grid-template-columns: 1fr; gap: 36px; }
  .exp-columns { grid-template-columns: 1fr; gap: 48px; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
  .skills-grid { grid-template-columns: repeat(2, 1fr); }
  .quote-grid { columns: 2; }
  .contact-card { grid-template-columns: 1fr; gap: 32px; }
  .detail-grid { grid-template-columns: 1fr; gap: 32px; }
  .detail-aside { position: static; }
}

@media (max-width: 820px) {
  .nav-toggle { display: grid; }
  .nav {
    position: fixed;
    inset: var(--nav-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 14px 20px 22px;
    background: var(--bg-elev);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: all .22s ease;
  }
  .nav.open { transform: none; opacity: 1; visibility: visible; }
  .nav a { padding: 12px 10px; font-size: 15px; }
  .nav a.active::after { display: none; }
  .brand-sub { display: none; }
  .header-cta { display: none; }
  .section { padding: 76px 0; }
  .hero { padding: calc(var(--nav-h) + 48px) 0 64px; }
  .float-card { display: none; }
  .quote-grid { columns: 1; }
  .timeline { padding-left: 26px; }
  .tl-item::before { left: -26px; }
}

@media (max-width: 560px) {
  .container { padding: 0 18px; }
  .stats-grid { grid-template-columns: 1fr; }
  .skills-grid { grid-template-columns: 1fr; }
  .project-grid { grid-template-columns: 1fr; }
  .hero-actions .btn { flex: 1 1 auto; }
}

/* ---------- Language switch (EN | DE) ---------- */
.lang-switch {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 2px;
  overflow: hidden;
}
.lang-switch a {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--text-faint);
  padding: 5px 10px;
  border-radius: 999px;
  line-height: 1;
  transition: color .18s ease, background .18s ease;
}
.lang-switch a:hover { color: var(--text); }
/* The active edition is the current page, so it reads as a state, not a link. */
.lang-switch a.active {
  color: var(--on-accent);
  background: var(--accent-line);
}
@media (max-width: 720px) {
  .lang-switch a { padding: 5px 8px; font-size: 11px; }
}

/* ---------- Evidence chips ----------
   A claim with a source behind it is green and clickable. A claim without one
   stays plain. The asymmetry is the point, so the green is reserved and never
   used decoratively. */
.evidence {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 22px;
}
.ev-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 7px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-muted);
  transition: border-color .18s ease, transform .18s ease;
}
.ev-chip b { color: var(--text); font-weight: 600; }
.ev-chip .src { color: var(--text-faint); }
a.ev-chip:hover { border-color: var(--text); transform: translateY(-1px); }

.ev-chip.is-verified {
  border-color: var(--ok-line);
  background: var(--ok-soft);
  color: var(--ok);
}
.ev-chip.is-verified b,
.ev-chip.is-verified .src { color: var(--ok); }
.ev-chip.is-verified .src { opacity: .75; }
.ev-chip.is-verified::before { content: "✓"; font-size: 10.5px; }
a.ev-chip.is-verified:hover { border-color: var(--ok); }

@media (max-width: 600px) {
  .ev-chip { font-size: 10.5px; padding: 6px 10px; }
}

/* ---------- Claim-led fold ----------
   The headline is the pitch, not the name. The name carries in the header,
   the title and the footer; a visitor who reads one line should read the
   argument, not the label. */
.hero h1.hero-claim {
  font-size: clamp(31px, 4.1vw, 50px);
  line-height: 1.07;
  letter-spacing: -0.034em;
  max-width: none;
  margin-bottom: 20px;
  text-wrap: balance;
}

/* The rotator moves below the lede and stops competing with the claim.
   "I build X" twice over read as a stutter. */
.hero-role { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.hero-role-k {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.scroll-cue {
  margin-top: 30px;
  padding-top: 18px;
  border-top: 1px dashed var(--border-strong);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--text-faint);
  display: flex;
  align-items: center;
  gap: 9px;
}
.scroll-cue b { color: var(--text-muted); font-weight: 500; }

@media (max-width: 720px) {
  .hero h1.hero-claim { max-width: none; }
}

/* ---------- Project thumbnails: the system, drawn ----------
   Inline SVG rather than an <img>, so the diagram reads from the same tokens
   as the page and follows the light/dark toggle. One grammar across all six:
   slate marks the control point, green the trusted output, rust the caught
   failure. Colour encodes state and is never decorative. */
.project-thumb .tn {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--surface-2);
}
.tn .n     { fill: var(--surface); stroke: var(--border-strong); stroke-width: 1; }
.tn .n-acc { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1; stroke-opacity: .7 }
.tn .n-ok  { fill: var(--ok-soft);  stroke: var(--ok);  stroke-width: 1; stroke-opacity: .65 }
.tn .n-bad { fill: var(--bad-soft); stroke: var(--bad); stroke-width: 1; stroke-opacity: .65 }
.tn .lbl   { font: 600 9.5px var(--mono); fill: var(--text); letter-spacing: .07em }
.tn .lbl-a { font: 600 9.5px var(--mono); fill: var(--accent); letter-spacing: .07em }
.tn .lbl-o { font: 600 9.5px var(--mono); fill: var(--ok); letter-spacing: .07em }
.tn .lbl-b { font: 600 9.5px var(--mono); fill: var(--bad); letter-spacing: .07em }
.tn .sub   { font: 400 7.5px var(--mono); fill: var(--text-faint); letter-spacing: .04em }
.tn .eye   { font: 600 8.5px var(--mono); fill: var(--text-faint); letter-spacing: .16em }
.tn .cap   { font: 600 8.5px var(--mono); fill: var(--text-muted); letter-spacing: .1em }
.tn .w     { stroke: var(--border-strong); fill: none; stroke-width: 1 }
.tn .w-a   { stroke: var(--accent); fill: none; stroke-width: 1; stroke-opacity: .6 }
.tn .w-o   { stroke: var(--ok);  fill: none; stroke-width: 1; stroke-opacity: .55 }
.tn .w-b   { stroke: var(--bad); fill: none; stroke-width: 1; stroke-opacity: .55 }

/* the shape name, so the set reads as a system rather than six one-offs */
.project-shape {
  position: absolute; left: 14px; bottom: 12px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--accent);
}

/* the long tail: present, but not competing with the six */
.also { border-top: 1px solid var(--border); margin-top: 34px; padding-top: 10px; }
.also-row {
  display: grid; grid-template-columns: 1fr auto; gap: 20px;
  padding: 13px 0; border-bottom: 1px solid var(--border);
  align-items: baseline;
}
.also-row .t { font-size: 15px; font-weight: 600; }
.also-row .t span {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint); font-weight: 400; margin-left: 9px;
}
.also-row .d { color: var(--text-muted); font-size: 13.5px; margin: 3px 0 0; max-width: 62ch; }
.also-row .l { font-family: var(--mono); font-size: 11px; color: var(--accent); white-space: nowrap; }
@media (max-width: 620px) {
  .also-row { grid-template-columns: 1fr; gap: 6px; }
}

/* evidence links on a project card */
.project-ev { display: flex; flex-wrap: wrap; gap: 14px; margin: 0 0 14px; }
.project-ev a {
  font-family: var(--mono); font-size: 11px; color: var(--accent);
  border-bottom: 1px solid var(--accent-soft);
}
.project-ev a:hover { border-bottom-color: var(--accent); }
.project-card h3 .record-org {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint); font-weight: 400;
  margin-left: 8px; white-space: nowrap;
}

/* the diagrams are drawn 400x250, so the thumb box matches rather than
   letterboxing them inside a 16:9 frame */
.project-thumb { aspect-ratio: 8 / 5; }

/* Two up, not three.
   The diagrams are the argument, and at a three-column width they render at
   0.89 scale, which drops the sub-labels to 6.6px and makes the thing they
   are meant to communicate unreadable. Two columns puts them back above 1.3x
   their drawn size. */
@media (min-width: 900px) {
  .project-grid { grid-template-columns: repeat(2, 1fr); gap: 26px; }
}

/* ---------- Recommendations as citation ----------
   The lead reference names the exact systems in the grid above it, so it is
   presented as corroboration rather than praise: a source attached to a
   claim, which is the same argument the evidence chips make. */
.citation {
  margin: 0 0 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: 26px 30px 22px;
}
.citation-flag {
  margin: 0 0 16px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ok);
  display: flex;
  align-items: center;
  gap: 9px;
}
.citation-flag::before { content: "✓"; font-size: 12px; }

.citation blockquote { margin: 0; padding: 0; }
.citation blockquote p {
  font-size: clamp(17px, 1.9vw, 21px);
  line-height: 1.52;
  letter-spacing: -.012em;
  color: var(--text);
  margin: 0 0 14px;
  max-width: 62ch;
}
.citation blockquote p:last-child { margin-bottom: 0; }

/* the phrase that does the corroborating, marked so the eye lands on it */
.citation mark {
  background: var(--ok-soft);
  color: inherit;
  box-shadow: 0 0 0 3px var(--ok-soft);
  border-radius: 2px;
  text-decoration: underline;
  text-decoration-color: var(--ok-line);
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
}

.citation figcaption {
  padding: 18px 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
}
.citation figcaption .who { font-size: 15.5px; font-weight: 600; color: var(--text); }
.citation figcaption .role { font-size: 13.5px; color: var(--text-muted); }
.citation figcaption .when {
  font-family: var(--mono); font-size: 11px; color: var(--text-faint);
}

@media (max-width: 620px) {
  .citation { padding: 20px 18px 18px; }
  .citation-flag { font-size: 10px; letter-spacing: .1em; }
  .citation figcaption { padding: 14px 0 0; }
}

/* ---------- Stats carry their source ----------
   A number with nowhere to go is an assertion. Each stat is now a link to the
   case study that proves it, which is the same contract as the evidence chips. */
a.stat { display: block; text-decoration: none; color: inherit; }
.stat-src {
  display: block;
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: .62;
  transition: opacity .2s ease;
}
a.stat:hover .stat-src,
a.stat:focus-visible .stat-src { opacity: 1; }

/* ---------- Stack as runs, not a badge wall ----------
   Six cards of chips was the thing every portfolio does. These are plain
   lines: faster to scan, and the claim in the section head is that each one
   appears in a system above. */
.stack-list { border-top: 1px solid var(--border); }
.stack-row {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: 32px;
  padding: 18px 0;
  border-bottom: 1px solid var(--border);
  align-items: baseline;
}
.stack-k {
  margin: 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--accent);
}
.stack-v { margin: 0; color: var(--text-muted); font-size: 15px; max-width: 72ch; }

/* ---------- Contact facts read as a spec sheet ---------- */
.contact-list .info-row {
  display: grid;
  grid-template-columns: 112px 1fr;
  gap: 16px;
  align-items: baseline;
}
.contact-list .info-row .k {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.contact-list .info-row .v a { color: var(--accent); }
.contact-list .info-row .v a:hover { text-decoration: underline; }

@media (max-width: 760px) {
  .stack-row { grid-template-columns: 1fr; gap: 6px; }
  .contact-list .info-row { grid-template-columns: 1fr; gap: 3px; }
}
