/* ==========================================================================
   Mohammad Kiyan — portfolio
   Design tokens first, then base, layout, components, pages, responsive.
   ========================================================================== */

:root {
  --bg: #0a0a14;
  --bg-alt: #0d0d1a;
  --bg-raised: #121222;

  --text: #ecebf7;
  --text-2: #c6c3da;
  --muted: #928fae;
  --dim: #5c5975;

  --accent: #8b7cf6;
  --accent-2: #a78bfa;
  --accent-3: #6d5ce8;
  --accent-soft: #c9c2ff;
  --cyan: #7dd3fc;

  --ok: #4ade80;
  --warn: #fbbf24;
  --stop: #f87171;

  --line: rgba(148, 132, 255, 0.14);
  --line-2: rgba(148, 132, 255, 0.2);
  --line-3: rgba(148, 132, 255, 0.3);
  --line-strong: rgba(148, 132, 255, 0.6);
  --wash: rgba(139, 124, 246, 0.08);

  /* Project-timeline rail: lit behind the active node, dim ahead of it. */
  --rail-lit: rgba(139, 124, 246, 0.45);
  --rail-dim: rgba(148, 132, 255, 0.12);

  --sans: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --shell: 1160px;
  --gutter: clamp(18px, 5vw, 48px);
  --nav-h: 71px;

  /* Touch chrome: 56px header + 52px section-chip rail. The card headers stick
     just under the header row, which is the only part that scrolls away. */
  --chrome-h: 56px;
  --chip-h: 52px;
  --tabbar-h: 58px;
  /* Project cards go edge-to-edge on touch; sticky/full-bleed children cancel
     this padding with a negative margin, so it has to be one number. */
  --card-pad: clamp(16px, 4vw, 24px);

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 20px;

  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* --------------------------------------------------------------- base --- */

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  min-height: 100vh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}

/* Horizontal rails (project pills, section chips, thumbnail strips) scroll by
   touch or trackpad; the bar itself is noise on top of a 118px-tall strip. */
[data-rail] { scrollbar-width: none; }
[data-rail]::-webkit-scrollbar { display: none; }

/* height:auto is load-bearing — the width/height attributes on <img> are
   presentational hints, and without this the literal height wins over every
   aspect-ratio rule below. The attributes stay for CLS reservation. */
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
button { font-family: inherit; }

/* Components below set explicit `display`, which would otherwise beat the
   UA stylesheet's [hidden] rule and leak unfinished slots into the page. */
[hidden] { display: none !important; }

::selection { background: rgba(139, 124, 246, 0.4); }

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

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  padding: 12px 20px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  border-radius: 0 0 var(--r-sm) 0;
}
.skip-link:focus { left: 0; }

.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;
}

/* ----------------------------------------------------------- keyframes --- */

@keyframes mkPulse {
  0%, 100% { opacity: 0.5; transform: scale(1); }
  50% { opacity: 0.9; transform: scale(1.12); }
}
@keyframes mkBlink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}
@keyframes mkDrift {
  0%, 100% { transform: translate(0, 0); }
  50% { transform: translate(30px, -24px); }
}
@keyframes mkSheetUp {
  from { transform: translateY(101%); }
  to { transform: translateY(0); }
}

/* ------------------------------------------------------------- layout --- */

.shell {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.shell--narrow { max-width: 860px; }
.shell--tight { max-width: 760px; }

.section {
  padding-block: clamp(64px, 9vw, 110px);
  border-top: 1px solid rgba(148, 132, 255, 0.08);
}
.section--alt { background: var(--bg-alt); }

.eyebrow {
  margin: 0 0 10px;
  font: 500 13px var(--mono);
  color: var(--accent-2);
  letter-spacing: 0.14em;
}

.section-title {
  margin: 0 0 40px;
  font-size: clamp(27px, 5.4vw, 40px);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

.grad-text {
  background: linear-gradient(100deg, var(--accent-2) 10%, var(--cyan) 90%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.lede {
  margin: 0;
  max-width: 560px;
  font-size: 17px;
  line-height: 1.65;
  color: var(--muted);
  text-wrap: pretty;
}

/* ---------------------------------------------------------------- nav --- */

.progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 12px rgba(139, 124, 246, 0.8);
  z-index: 100;
  transition: width 0.1s linear;
}

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 18px var(--gutter);
  background: rgba(10, 10, 20, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(148, 132, 255, 0.1);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  flex: none;
}
.brand__mark {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: var(--r-sm);
  background: linear-gradient(135deg, var(--accent), var(--accent-3));
  font: 700 14px var(--mono);
  color: #fff;
  box-shadow: 0 0 18px rgba(139, 124, 246, 0.45);
}
.brand__name {
  font: 600 15px var(--sans);
  color: var(--text);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 28px;
}
.nav__link {
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
  transition: color 0.2s;
  white-space: nowrap;
}
.nav__link:hover { color: var(--accent-2); }
.nav__link[aria-current="page"] {
  color: var(--accent-2);
  font-weight: 600;
}

/* ------------------------------------------------------- touch chrome --- */

/* Below the desktop breakpoint the top bar splits in two: a 56px identity row
   that slides away as you scroll down, and a section-chip rail that stays put.
   Both live in one transform so the chips end up flush against the viewport
   top rather than jumping. Hidden entirely on desktop — see the media query. */
.chrome {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 90;
  display: none;
  background: rgba(10, 10, 20, 0.86);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid rgba(148, 132, 255, 0.1);
  transition: transform 0.3s var(--ease);
}
.chrome.is-collapsed { transform: translateY(calc(-1 * var(--chrome-h))); }

.chrome__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: var(--chrome-h);
  padding-inline: 16px;
}
.chrome__bar .brand__mark { width: 30px; height: 30px; font-size: 13px; }
.chrome__bar .brand__name { font-size: 14px; }
.chrome__cta {
  height: 38px;
  padding: 0 15px;
  border-radius: 9px;
  font-size: 12px;
}

.chiprail {
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--chip-h);
  padding-inline: 16px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  border-top: 1px solid rgba(148, 132, 255, 0.08);
}
.chiprail__link {
  display: inline-flex;
  align-items: center;
  flex: none;
  height: 44px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.03);
  color: #8a87a6;
  text-decoration: none;
  white-space: nowrap;
  scroll-snap-align: start;
  font: 600 12px var(--mono);
  letter-spacing: 0.04em;
  transition: all 0.25s;
}
.chiprail__link[aria-current="true"] {
  background: rgba(139, 124, 246, 0.24);
  border-color: rgba(148, 132, 255, 0.55);
  color: #d3ccff;
  box-shadow: 0 0 16px rgba(139, 124, 246, 0.26);
}
.chiprail__link:active { transform: scale(0.94); }

/* ---------------------------------------------------------- tab bar --- */

.tabbar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 95;
  display: none;
  /* auto-columns, not a fixed 4: the CV tab stays hidden until the PDF exists
     and the remaining tabs should still fill the bar. */
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  background: rgba(10, 10, 20, 0.9);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-top: 1px solid rgba(148, 132, 255, 0.12);
  padding-bottom: env(safe-area-inset-bottom);
}
/* Keeps the last section clear of the fixed bar. */
.tabbar-spacer { display: none; height: calc(72px + env(safe-area-inset-bottom)); }

.tabbar__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--tabbar-h);
  text-decoration: none;
  color: #6e6b88;
  transition: color 0.2s, transform 0.1s;
}
.tabbar__link[aria-current="page"] { color: var(--accent-2); }
.tabbar__link:active { transform: scale(0.92); }
.tabbar__label {
  font: 600 10px var(--mono);
  letter-spacing: 0.04em;
}

/* Icons are drawn from spans so the bar carries no image requests. */
.tabbar__icon {
  width: 15px; height: 15px;
  display: grid;
  place-items: center;
}
.tabbar__icon--grid {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 2.5px;
}
.tabbar__icon--grid span {
  background: currentColor;
  border-radius: 1.5px;
}
.tabbar__icon--lines {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-block: 1px;
}
.tabbar__icon--lines span {
  height: 2.5px;
  background: currentColor;
  border-radius: 1.5px;
}
.tabbar__icon--lines span:last-child { width: 62%; }
.tabbar__icon--ring {
  border: 2.5px solid currentColor;
  border-radius: 50%;
}
.tabbar__icon--down { font: 700 15px var(--mono); line-height: 1; }

/* ------------------------------------------------------------ buttons --- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 28px;
  border: 1px solid transparent;
  border-radius: 10px;
  font: 600 15px var(--sans);
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s, background 0.2s, border-color 0.2s;
}

.btn--primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-3));
  color: #fff;
  box-shadow: 0 4px 28px rgba(139, 124, 246, 0.4);
}
.btn--primary:hover {
  box-shadow: 0 6px 40px rgba(139, 124, 246, 0.65);
  transform: translateY(-2px);
}

.btn--ghost {
  border-color: var(--line-3);
  color: var(--text);
  background: transparent;
  font-weight: 500;
}
.btn--ghost:hover {
  border-color: var(--line-strong);
  background: var(--wash);
}

.btn--mono {
  padding: 9px 18px;
  border-radius: var(--r-sm);
  border-color: rgba(148, 132, 255, 0.35);
  color: var(--accent-soft);
  font: 500 13px var(--mono);
  background: var(--wash);
}
.btn--mono:hover {
  background: rgba(139, 124, 246, 0.2);
  box-shadow: 0 0 20px rgba(139, 124, 246, 0.35);
  border-color: rgba(148, 132, 255, 0.7);
}

/* Selectable chip — used by project tabs, post filters, contact topics. */
.chip {
  padding: 12px 24px;
  border: 1px solid var(--line-2);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  color: var(--muted);
  font: 600 14px var(--sans);
  cursor: pointer;
  transition: all 0.2s;
}
.chip:hover { color: var(--text-2); border-color: var(--line-3); }
.chip[aria-selected="true"],
.chip[aria-pressed="true"] {
  background: linear-gradient(135deg, var(--accent), var(--accent-3));
  border-color: transparent;
  color: #fff;
  box-shadow: 0 0 24px rgba(139, 124, 246, 0.4);
}
.chip--sm { padding: 9px 18px; font: 500 13px var(--sans); border-radius: 9px; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 14px;
  border: 1px solid rgba(148, 132, 255, 0.25);
  border-radius: 100px;
  background: var(--wash);
  font: 500 12px var(--mono);
  color: var(--accent-2);
}
.badge__dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 8px rgba(74, 222, 128, 0.8);
}

.tag {
  padding: 6px 12px;
  border: 1px solid rgba(148, 132, 255, 0.18);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.04);
  font: 500 12px var(--mono);
  color: var(--accent-soft);
}

/* -------------------------------------------------------------- cards --- */

.card {
  padding: 28px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.02);
  transition: border-color 0.25s, box-shadow 0.25s, transform 0.25s;
}
.card--lift:hover {
  border-color: rgba(148, 132, 255, 0.45);
  box-shadow: 0 0 34px rgba(139, 124, 246, 0.15);
  transform: translateY(-4px);
}
.card--glow {
  border-color: rgba(148, 132, 255, 0.16);
  background: linear-gradient(160deg, rgba(139, 124, 246, 0.07), rgba(139, 124, 246, 0.02));
  box-shadow: 0 0 50px rgba(139, 124, 246, 0.08);
}

.quote {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin: 0;
  padding: 32px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.02);
}
.quote__mark {
  font: 700 34px Georgia, "Times New Roman", serif;
  color: var(--accent);
  line-height: 0.6;
}
.quote__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--text-2);
  text-wrap: pretty;
}
/* Long quotes stretch every card in their row, so they start clamped. Only
   with JS — without it there'd be no way to open them again. */
:root:not(.no-js) .quote:not(.is-open) .quote__text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 6;
  line-clamp: 6;
  overflow: hidden;
}
.quote__toggle {
  align-self: flex-start;
  margin-top: -8px;
  padding: 0;
  border: 0;
  background: none;
  font: 500 13px var(--mono);
  color: var(--accent-soft);
  cursor: pointer;
  transition: color 0.2s;
}
.quote__toggle:hover { color: var(--text); }
.quote__by {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  font: 500 13px var(--mono);
  color: var(--dim);
}
.quote__avatar {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
}

/* Quotes are paragraphs, not skill chips — they need a wider minimum than
   .grid-4 gives, or six of them shred into unreadable columns. */
.grid-quotes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 16px;
}

/* --------------------------------------------------------------- hero --- */

.hero {
  position: relative;
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 64px;
  align-items: center;
  max-width: var(--shell);
  margin-inline: auto;
  padding: clamp(114px, 17vw, 168px) var(--gutter) clamp(66px, 9vw, 120px);
  min-height: 78vh;
}

.hero__orbs {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: visible;
}
.hero__orb {
  position: absolute;
  border-radius: 50%;
}
.hero__orb--a {
  top: -60px; right: 2%;
  width: min(420px, 78vw); aspect-ratio: 1;
  background: radial-gradient(closest-side, rgba(139, 124, 246, 0.22), transparent);
  animation: mkPulse 7s ease-in-out infinite;
  /* .hero__orbs is deliberately overflow:visible so orb--b can hang off the
     bottom-left. That leaves this one free to pulse its 12% past the right
     edge and rock the phone sideways once every seven seconds — so it grows
     inward from a pinned right edge instead. */
  transform-origin: right center;
}
.hero__orb--b {
  bottom: -40px; left: -8%;
  width: min(360px, 70vw); aspect-ratio: 1;
  background: radial-gradient(closest-side, rgba(125, 211, 252, 0.1), transparent);
  animation: mkDrift 11s ease-in-out infinite;
}
.hero__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(148, 132, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(148, 132, 255, 0.05) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 30%, transparent 75%);
  mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 30%, transparent 75%);
}

.hero__body { position: relative; z-index: 2; }

.hero__role {
  margin: 28px 0 14px;
  font: 500 14px var(--mono);
  color: var(--muted);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.hero__name {
  margin: 0 0 20px;
  font-size: clamp(40px, 10vw, 66px);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.02em;
}

.hero__typed {
  min-height: 32px;
  font: 500 clamp(15px, 3.7vw, 19px) var(--mono);
  color: var(--accent-soft);
  margin-bottom: 24px;
}
.hero__prompt { color: var(--dim); }
.hero__caret {
  display: inline-block;
  width: 10px; height: 22px;
  background: var(--accent-2);
  vertical-align: middle;
  margin-left: 3px;
  animation: mkBlink 1.1s infinite;
}

.hero__blurb {
  margin: 0 0 40px;
  max-width: 520px;
  font-size: 17px;
  line-height: 1.65;
  color: var(--muted);
  text-wrap: pretty;
}

.hero__cta {
  display: flex;
  gap: 14px;
  margin-bottom: 56px;
  flex-wrap: wrap;
}

.stats {
  display: flex;
  gap: 40px;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
}
.stats__num {
  font: 700 26px var(--sans);
  color: var(--text);
}
.stats__label {
  font: 400 12px var(--mono);
  color: var(--dim);
  margin-top: 2px;
}

.hero__aside {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
}

.portrait {
  position: relative;
  padding: 10px;
  border: 1px solid rgba(148, 132, 255, 0.25);
  border-radius: 24px;
  background: rgba(139, 124, 246, 0.05);
  box-shadow: 0 0 60px rgba(139, 124, 246, 0.18);
}
.portrait__frame {
  position: relative;
  width: 340px;
  aspect-ratio: 340 / 420;
  border-radius: var(--r-lg);
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(139, 124, 246, 0.28), transparent 70%),
    linear-gradient(160deg, #16162a, #0d0d1a);
  display: grid;
  place-items: center;
}
.portrait__img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.portrait__monogram {
  font: 700 84px var(--mono);
  letter-spacing: 0.04em;
  background: linear-gradient(140deg, var(--accent-2), var(--cyan));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  user-select: none;
}
.portrait__tagline {
  position: absolute;
  bottom: -16px;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  padding: 8px 16px;
  border: 1px solid var(--line-3);
  border-radius: 100px;
  background: var(--bg-raised);
  font: 500 clamp(9.5px, 2.6vw, 12px) var(--mono);
  color: var(--accent-2);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
}

/* --------------------------------------------------------------- work --- */

/* Project timeline — the tablist for the eight project panels, drawn as a
   left-to-right rail. Segments behind the active node are lit and its dot is
   haloed, so the row reads as progress rather than as six equal buttons.
   Below the desktop breakpoint the same markup collapses into a pill rail.  */
.ptl {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  margin: 12px 0 10px;
}

.ptl__node {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  text-align: center;
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.25s;
}
.ptl__node:hover,
.ptl__node[aria-selected="true"] { opacity: 1; }

.ptl__num {
  margin-bottom: 10px;
  font: 500 10px var(--mono);
  letter-spacing: 0.18em;
  color: var(--dim);
  transition: color 0.35s;
}

.ptl__text {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Fixed height so the rail below lands on one line whatever the name wraps to. */
  height: 58px;
  padding-inline: 10px;
  gap: 5px;
}
.ptl__name {
  font: 600 15px var(--sans);
  letter-spacing: -0.01em;
  color: var(--text-2);
  transition: color 0.35s, text-shadow 0.35s;
}
.ptl__role {
  font: 400 11px var(--mono);
  color: #7d7a96;
  transition: color 0.35s;
}

.ptl__rail {
  display: flex;
  align-items: center;
  width: 100%;
  height: 18px;
  margin-top: 14px;
}
.ptl__seg {
  flex: 1;
  height: 1px;
  background: var(--rail-dim);
  transition: background 0.35s;
}
.ptl__dot {
  width: 8px; height: 8px;
  flex: none;
  border: 1px solid rgba(148, 132, 255, 0.35);
  border-radius: 50%;
  background: var(--bg-alt);
  transition: all 0.35s;
}
.ptl__drop {
  width: 1px;
  height: 36px;
  background: transparent;
  transition: background 0.35s;
}

/* --- active --- */
.ptl__node[aria-selected="true"] .ptl__num { color: var(--accent-2); }
.ptl__node[aria-selected="true"] .ptl__name {
  color: #f4f2ff;
  text-shadow: 0 0 22px rgba(139, 124, 246, 0.55);
}
.ptl__node[aria-selected="true"] .ptl__role { color: var(--accent-2); }
.ptl__node[aria-selected="true"] .ptl__dot {
  width: 12px; height: 12px;
  border-color: transparent;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(139, 124, 246, 0.16), 0 0 18px 2px rgba(139, 124, 246, 0.7);
}
.ptl__node[aria-selected="true"] .ptl__drop {
  background: linear-gradient(180deg, rgba(139, 124, 246, 0.7), rgba(139, 124, 246, 0));
}
.ptl__node[aria-selected="true"] .ptl__seg--l { background: var(--rail-lit); }

/* --- already passed: any node with the selected one still ahead of it --- */
.ptl__node:has(~ [aria-selected="true"]) .ptl__seg { background: var(--rail-lit); }
.ptl__node:has(~ [aria-selected="true"]) .ptl__dot {
  border-color: transparent;
  background: rgba(139, 124, 246, 0.55);
}

/* --- the rail fades out at both ends instead of stopping mid-air --- */
.ptl__node:first-child .ptl__seg--l {
  background: linear-gradient(90deg, transparent, var(--rail-dim));
}
.ptl__node:last-child .ptl__seg--r {
  background: linear-gradient(90deg, var(--rail-dim), transparent);
}
.ptl__node:first-child[aria-selected="true"] .ptl__seg--l,
.ptl__node:first-child:has(~ [aria-selected="true"]) .ptl__seg--l {
  background: linear-gradient(90deg, transparent, var(--rail-lit));
}

.project[hidden] { display: none; }

.project {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: 48px;
  padding: 44px;
  border: 1px solid rgba(148, 132, 255, 0.16);
  border-radius: var(--r-xl);
  background: linear-gradient(160deg, rgba(139, 124, 246, 0.07), rgba(139, 124, 246, 0.02));
  box-shadow: 0 0 50px rgba(139, 124, 246, 0.08);
}

.project__head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.project__name { margin: 0; font-size: clamp(21px, 4.7vw, 28px); font-weight: 700; }
.project__role { font: 500 12px var(--mono); color: var(--dim); }
.project__kicker {
  margin: 0 0 22px;
  font: 500 14px var(--mono);
  color: var(--accent-2);
}
.project__summary {
  margin: 0 0 26px;
  font-size: 16px;
  line-height: 1.7;
  color: var(--muted);
  text-wrap: pretty;
}

.bullets {
  margin: 0 0 28px;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 12px;
}
.bullets li {
  display: flex;
  gap: 12px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-2);
}
.bullets li::before {
  content: "▸";
  color: var(--accent-2);
  font-family: var(--mono);
  flex: none;
}

/* Only earns its place where the list is clamped — see the touch block. */
.bullets-more {
  display: none;
  align-items: center;
  min-height: 44px;
  margin: -8px 0 22px;
  padding: 0 18px;
  border: 1px solid var(--line-3);
  border-radius: 10px;
  background: var(--wash);
  color: var(--accent-soft);
  font: 500 13px var(--mono);
  cursor: pointer;
}
.bullets-more:active { transform: scale(0.95); background: rgba(139, 124, 246, 0.18); }

.metrics { display: flex; gap: 12px; flex-wrap: wrap; }
.metric {
  padding: 14px 20px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: rgba(139, 124, 246, 0.1);
}
.metric__num { font: 700 20px var(--sans); }
.metric__label { font: 400 11px var(--mono); color: var(--muted); }

.project__note {
  margin: 18px 0 0;
  font: 400 12px var(--mono);
  color: var(--dim);
  text-wrap: pretty;
}

/* Availability pill in the project header. Live ones link to the product. */
.status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  align-self: center;
  padding: 4px 11px;
  border: 1px solid;
  border-radius: 100px;
  font: 500 11px var(--mono);
  letter-spacing: 0.02em;
  white-space: nowrap;
  text-decoration: none;
}
.status::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.status--live {
  color: var(--ok);
  border-color: rgba(74, 222, 128, 0.35);
  background: rgba(74, 222, 128, 0.08);
}
.status--live::before { box-shadow: 0 0 8px rgba(74, 222, 128, 0.8); }
a.status--live:hover { border-color: rgba(74, 222, 128, 0.7); }
.status--down {
  color: var(--stop);
  border-color: rgba(248, 113, 113, 0.35);
  background: rgba(248, 113, 113, 0.08);
}

/* Caveat about the live product — sits between the kicker and the summary. */
.callout {
  display: flex;
  gap: 12px;
  margin: -6px 0 24px;
  padding: 12px 16px;
  border: 1px solid;
  border-left-width: 3px;
  border-radius: var(--r-md);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-2);
  text-wrap: pretty;
}
.callout__label {
  flex: none;
  padding-top: 2px;
  font: 600 11px var(--mono);
  letter-spacing: 0.08em;
}
.callout--info {
  border-color: rgba(125, 211, 252, 0.28);
  border-left-color: var(--cyan);
  background: rgba(125, 211, 252, 0.06);
}
.callout--info .callout__label { color: var(--cyan); }
.callout--warn {
  border-color: rgba(251, 191, 36, 0.28);
  border-left-color: var(--warn);
  background: rgba(251, 191, 36, 0.06);
}
.callout--warn .callout__label { color: var(--warn); }

.project__aside {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}

.shot {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border: 1px solid rgba(148, 132, 255, 0.25);
  border-radius: var(--r-md);
  cursor: zoom-in;
  background: var(--bg-alt);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.45);
  transition: border-color 0.25s, box-shadow 0.25s;
}
.shot:hover {
  border-color: var(--line-strong);
  box-shadow: 0 8px 50px rgba(139, 124, 246, 0.3);
}

.label {
  margin: 0 0 12px;
  font: 500 12px var(--mono);
  color: var(--dim);
  letter-spacing: 0.1em;
}

.stack { display: flex; flex-wrap: wrap; gap: 8px; }

.tour {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 8px;
  padding-top: 32px;
  border-top: 1px solid rgba(148, 132, 255, 0.12);
}
.tour__bar {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  flex-wrap: wrap;
}
.tour__meta { margin: 0; font: 400 12px var(--mono); color: var(--dim); }

.thumbs {
  display: grid;
  /* auto-fill against a floor, not a per-gallery column count: the six tours
     run 8–11 shots and this keeps the thumbnails one size across all of them.
     The floor also stops the nowrap labels dictating column widths. */
  grid-template-columns: repeat(auto-fill, minmax(94px, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.thumbs > li { min-width: 0; }
.thumb {
  padding: 2px;
  border: 1px solid rgba(148, 132, 255, 0.15);
  border-radius: 9px;
  background: none;
  cursor: pointer;
  opacity: 0.65;
  transition: all 0.2s;
  width: 100%;
  min-width: 0;
}
.thumb:hover { opacity: 1; }
.thumb[aria-selected="true"] {
  border-color: rgba(148, 132, 255, 0.75);
  box-shadow: 0 0 16px rgba(139, 124, 246, 0.35);
  background: rgba(139, 124, 246, 0.1);
  opacity: 1;
}
.thumb img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: 7px;
  background: var(--bg-alt);
}
.thumb__label {
  display: block;
  font: 500 10px var(--mono);
  padding: 5px 4px 3px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--dim);
}
.thumb[aria-selected="true"] .thumb__label { color: var(--accent-soft); }

/* ------------------------------------------------------------- skills --- */

.grid-4 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 216px), 1fr));
  gap: 16px;
}
.skill__title {
  margin: 0 0 16px;
  font: 600 13px var(--mono);
  color: var(--accent-2);
  letter-spacing: 0.08em;
}
.skill__list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 15px;
  color: var(--text-2);
}

/* --------------------------------------------------------- experience --- */

.timeline {
  display: grid;
  grid-template-columns: 150px 28px 1fr;
  gap: 0 20px;
}
.timeline__when {
  font: 500 clamp(10px, 2.5vw, 13px) var(--mono);
  color: var(--dim);
  padding-top: 4px;
  text-align: right;
}
.timeline__rail {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.timeline__dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: rgba(139, 124, 246, 0.5);
  flex: none;
  margin-top: 5px;
}
.timeline__dot--now {
  background: var(--accent);
  box-shadow: 0 0 12px rgba(139, 124, 246, 0.8);
}
.timeline__line {
  width: 1px;
  flex: 1;
  background: rgba(148, 132, 255, 0.15);
}
.timeline__line--lit {
  background: linear-gradient(rgba(148, 132, 255, 0.4), rgba(148, 132, 255, 0.1));
}
.timeline__item { padding-bottom: 44px; }
.timeline__item:last-child { padding-bottom: 0; }
.timeline__role { margin: 0 0 4px; font-size: clamp(17px, 3.9vw, 20px); font-weight: 600; text-wrap: pretty; }
.timeline__meta {
  margin: 0 0 10px;
  font: 500 12px var(--mono);
  color: var(--accent-2);
}
.timeline__desc {
  margin: 0;
  font-size: 15px;
  line-height: 1.65;
  color: var(--muted);
  text-wrap: pretty;
}

/* -------------------------------------------------------------- about --- */

.prose p {
  margin: 0 0 20px;
  font-size: 18px;
  line-height: 1.75;
  text-wrap: pretty;
}
.prose p:first-of-type { color: var(--text-2); }
.prose p:last-child { margin-bottom: 0; color: var(--muted); }
.prose em {
  font-style: normal;
  color: var(--accent-2);
}

/* ------------------------------------------------------------ contact --- */

.cta-band {
  position: relative;
  padding: clamp(76px, 10vw, 130px) var(--gutter) 60px;
  border-top: 1px solid rgba(148, 132, 255, 0.08);
  overflow: hidden;
  text-align: center;
}
.cta-band__halo {
  position: absolute;
  left: 50%; top: -120px;
  transform: translateX(-50%);
  width: min(640px, 92vw); height: 380px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(139, 124, 246, 0.16), transparent);
  pointer-events: none;
}
.cta-band__inner { position: relative; }
.cta-band__row {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin-bottom: 64px;
  flex-wrap: wrap;
}

.colophon {
  margin: 0;
  padding-top: 28px;
  border-top: 1px solid rgba(148, 132, 255, 0.08);
  font: 400 12px var(--mono);
  color: var(--dim);
}

.footer {
  border-top: 1px solid rgba(148, 132, 255, 0.08);
  padding: 40px var(--gutter);
  text-align: center;
}
.footer p { margin: 0; font: 400 12px var(--mono); color: var(--dim); }
.footer a { color: var(--muted); text-decoration: none; }
.footer a:hover { color: var(--accent-2); }

/* ------------------------------------------------------------ subpage --- */

.page-head {
  position: relative;
  max-width: var(--shell);
  margin-inline: auto;
  padding: clamp(96px, 16vw, 168px) var(--gutter) clamp(30px, 6vw, 56px);
}
.page-head__halo {
  position: absolute;
  top: -40px; right: 0;
  /* Fixed px here overflows the viewport on phones and creates a sideways scroll. */
  width: min(420px, 80vw);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(139, 124, 246, 0.16), transparent);
  pointer-events: none;
  animation: mkPulse 7s ease-in-out infinite;
  /* mkPulse scales to 1.12, which from the default centre pushes ~6% of the
     width past `right: 0` — enough to rock the page sideways on a phone every
     seven seconds. Pinning the origin lets it breathe inward instead. */
  transform-origin: right center;
}
.page-head__title {
  margin: 0 0 18px;
  font-size: clamp(34px, 8.6vw, 56px);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.02em;
}

/* -------------------------------------------------------------- posts --- */

.filters {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  max-width: var(--shell);
  margin-inline: auto;
  padding: 0 var(--gutter) 40px;
}

.featured {
  display: grid;
  grid-template-columns: 1fr 0.9fr;
  gap: 44px;
  align-items: center;
  padding: 40px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-xl);
  background: linear-gradient(160deg, rgba(139, 124, 246, 0.09), rgba(139, 124, 246, 0.02));
  box-shadow: 0 0 50px rgba(139, 124, 246, 0.1);
  text-decoration: none;
  color: inherit;
  transition: all 0.25s;
}
.featured:hover {
  border-color: rgba(148, 132, 255, 0.5);
  box-shadow: 0 0 60px rgba(139, 124, 246, 0.22);
  transform: translateY(-3px);
}
.featured__tagrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}
.featured__title {
  margin: 0 0 14px;
  font-size: clamp(24px, 3.4vw, 32px);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
}
.featured__desc {
  margin: 0 0 26px;
  font-size: 16px;
  line-height: 1.7;
  color: var(--muted);
  text-wrap: pretty;
}
.featured__img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--r-md);
  border: 1px solid rgba(148, 132, 255, 0.25);
  background: var(--bg-alt);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.45);
}

.posts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 264px), 1fr));
  gap: 16px;
}

.post {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.02);
  overflow: hidden;
  transition: border-color 0.25s, box-shadow 0.25s, transform 0.25s;
}
.post:hover {
  border-color: rgba(148, 132, 255, 0.45);
  box-shadow: 0 0 34px rgba(139, 124, 246, 0.15);
  transform: translateY(-4px);
}
.post[hidden] { display: none; }
.post__media {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-bottom: 1px solid var(--line);
  background: var(--bg-alt);
}
.post__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 24px;
  flex: 1;
}
.post__meta-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.post__type {
  padding: 4px 10px;
  border-radius: 6px;
  font: 600 10px var(--mono);
  letter-spacing: 0.08em;
  color: var(--accent-2);
  background: rgba(167, 139, 250, 0.14);
  border: 1px solid rgba(167, 139, 250, 0.35);
}
.post__meta { font: 400 11px var(--mono); color: var(--dim); }
.post__title {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.post__desc {
  margin: 0;
  font-size: 14px;
  line-height: 1.65;
  color: var(--muted);
  text-wrap: pretty;
  flex: 1;
}
.post__link { align-self: flex-start; margin-top: 6px; }

/* ------------------------------------------------------- contact page --- */

.contact-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: 24px;
  align-items: start;
}
.channels {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.channel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 24px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.02);
  text-decoration: none;
  transition: all 0.25s;
}
.channel:hover {
  border-color: rgba(148, 132, 255, 0.45);
  box-shadow: 0 0 30px rgba(139, 124, 246, 0.14);
  transform: translateY(-2px);
}
.channel__name { margin: 0 0 2px; font: 600 15px var(--sans); color: var(--text); }
.channel__handle { margin: 0; font: 400 12px var(--mono); color: var(--dim); }
.channel__arrow { font: 500 16px var(--mono); color: var(--accent-2); }

.email-card {
  padding: 28px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  background: linear-gradient(160deg, rgba(139, 124, 246, 0.09), rgba(139, 124, 246, 0.02));
  box-shadow: 0 0 40px rgba(139, 124, 246, 0.08);
}
.email-card__label {
  margin: 0 0 6px;
  font: 600 11px var(--mono);
  color: var(--dim);
  letter-spacing: 0.12em;
}
.email-card__addr {
  display: block;
  margin: 0 0 16px;
  font: 600 19px var(--sans);
  color: var(--text);
  text-decoration: none;
  word-break: break-all;
}
.email-card__addr:hover { color: var(--accent-2); }
.email-card__actions { display: flex; gap: 10px; flex-wrap: wrap; }

.facts {
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.02);
  display: grid;
  gap: 14px;
  margin: 0;
}
.facts__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  font-size: 14px;
}
.facts__row + .facts__row {
  padding-top: 14px;
  border-top: 1px solid rgba(148, 132, 255, 0.1);
}
.facts__key {
  font: 500 12px var(--mono);
  color: var(--dim);
  letter-spacing: 0.08em;
}
.facts__val { color: var(--text-2); text-align: right; margin: 0; }

.form-card {
  padding: 36px;
  border: 1px solid rgba(148, 132, 255, 0.16);
  border-radius: var(--r-xl);
  background: linear-gradient(160deg, rgba(139, 124, 246, 0.07), rgba(139, 124, 246, 0.02));
  box-shadow: 0 0 50px rgba(139, 124, 246, 0.08);
}
.form-card__title { margin: 0 0 6px; font-size: 24px; font-weight: 700; letter-spacing: -0.01em; }
.form-card__note { margin: 0 0 28px; font-size: 14px; line-height: 1.6; color: var(--muted); }

.field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.field__label {
  font: 500 12px var(--mono);
  color: var(--muted);
  letter-spacing: 0.06em;
}
.field__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

input,
textarea {
  padding: 13px 16px;
  border: 1px solid rgba(148, 132, 255, 0.22);
  border-radius: 10px;
  background: rgba(10, 10, 20, 0.6);
  color: var(--text);
  font: 400 15px var(--sans);
  transition: border-color 0.2s, box-shadow 0.2s;
  width: 100%;
}
textarea { line-height: 1.6; resize: vertical; }
input::placeholder,
textarea::placeholder { color: var(--dim); }
input:focus,
textarea:focus {
  outline: none;
  border-color: rgba(148, 132, 255, 0.65);
  box-shadow: 0 0 0 3px rgba(139, 124, 246, 0.18);
}

.form-card__submit {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.form-hint { font: 400 12px var(--mono); color: var(--dim); }

/* ----------------------------------------------------------- lightbox --- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(6, 6, 14, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 36px;
  border: 0;
  max-width: 100%;
  max-height: 100%;
  width: 100%;
  height: 100%;
}
.lightbox:not([open]) { display: none; }
.lightbox::backdrop { background: rgba(6, 6, 14, 0.7); }

/* Drag handle for the touch sheet — meaningless on the desktop overlay. */
.lightbox__grip {
  display: none;
  width: 42px;
  height: 4px;
  flex: none;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: rgba(148, 132, 255, 0.45);
  cursor: grab;
}
.lightbox__img {
  max-width: 100%;
  max-height: calc(100% - 60px);
  width: auto;
  object-fit: contain;
  border-radius: var(--r-md);
  border: 1px solid var(--line-3);
  box-shadow: 0 24px 90px rgba(0, 0, 0, 0.7);
}
.lightbox__bar {
  display: flex;
  align-items: center;
  gap: 18px;
  font: 500 13px var(--mono);
  color: var(--muted);
  flex-wrap: wrap;
  justify-content: center;
}
.lightbox__label { color: var(--accent-2); }
.lightbox__meta {
  display: flex;
  align-items: center;
  gap: 12px;
}
.lightbox__btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 16px;
  border: 1px solid var(--line-3);
  border-radius: var(--r-sm);
  background: rgba(139, 124, 246, 0.1);
  color: var(--accent-soft);
  cursor: pointer;
  font: 500 13px var(--mono);
}
.lightbox__btn:hover { background: rgba(139, 124, 246, 0.22); }
.lightbox__close {
  position: absolute;
  top: 20px; right: 24px;
}

/* ------------------------------------------------------------- reveal --- */

[data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
[data-reveal].is-visible,
.no-js [data-reveal] {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------- responsive --- */

/* Below 1180px the site swaps its whole navigation model: the desktop bar is
   replaced by a collapsing header plus a bottom tab bar, and the project deck
   turns into a swipeable single-column stack. One breakpoint, because these
   pieces only make sense together — a half-applied version strands the user
   with no way to reach the other pages. */
@media (max-width: 1179px) {
  html { scroll-padding-top: calc(var(--chrome-h) + var(--chip-h) + 8px); }

  .nav { display: none; }
  .chrome { display: block; }
  .tabbar { display: grid; }
  .tabbar-spacer { display: block; }

  /* ---- hero ---- */
  .hero {
    grid-template-columns: 1fr;
    gap: clamp(34px, 5vw, 64px);
  }
  .hero__aside { justify-items: start; }
  .stats { gap: clamp(16px, 3vw, 40px); }
  .portrait__frame { width: min(340px, 74vw); }

  /* ---- project timeline collapses to a swipeable pill rail ---- */
  .ptl {
    display: flex;
    gap: 10px;
    margin: 4px calc(-1 * var(--gutter)) 20px;
    padding: 2px var(--gutter);
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
  }
  .ptl__num,
  .ptl__rail,
  .ptl__drop { display: none; }

  .ptl__node {
    flex: none;
    justify-content: center;
    min-height: 52px;
    padding-inline: 18px;
    border: 1px solid rgba(148, 132, 255, 0.16);
    border-radius: 13px;
    background: rgba(255, 255, 255, 0.03);
    scroll-snap-align: start;
    opacity: 1;
    transition: background 0.25s, border-color 0.25s, box-shadow 0.25s, transform 0.1s;
  }
  .ptl__node:active { transform: scale(0.95); }
  .ptl__node[aria-selected="true"] {
    border-color: transparent;
    background: linear-gradient(135deg, var(--accent), var(--accent-3));
    box-shadow: 0 4px 22px rgba(139, 124, 246, 0.42);
  }

  .ptl__text {
    height: auto;
    align-items: flex-start;
    padding-inline: 0;
    gap: 3px;
  }
  .ptl__name,
  .ptl__role { white-space: nowrap; }
  .ptl__name { font-size: 14px; }
  .ptl__role { font-size: 10px; }
  .ptl__node[aria-selected="true"] .ptl__name { color: #fff; text-shadow: none; }
  .ptl__node[aria-selected="true"] .ptl__role { color: rgba(255, 255, 255, 0.72); }

  /* ---- project card: one column, screenshot first ---- */
  .project {
    display: flex;
    flex-direction: column;
    gap: 26px;
    padding: var(--card-pad);
    padding-bottom: calc(var(--card-pad) + 6px);
    border-radius: 18px;
    box-shadow: none;
    /* Horizontal drags belong to the swipe handler; vertical ones stay with
       the browser, so reading the card never has to wait on a gesture. */
    touch-action: pan-y;
  }
  /* The screenshot is the fastest way to recognise a project on a phone, so it
     leads; the prose that needs the wide column follows. */
  .project__aside { order: -1; gap: 18px; }

  /* Full-bleed sticky header — sits directly under the collapsing chrome row
     so you always know which project the scrolling text belongs to. */
  .project__head {
    position: sticky;
    top: calc(var(--chrome-h) - 2px);
    z-index: 6;
    gap: 3px 12px;
    margin: 0 calc(-1 * var(--card-pad)) 12px;
    padding: 12px var(--card-pad);
    background: rgba(16, 16, 30, 0.93);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid rgba(148, 132, 255, 0.12);
  }

  /* Six-bullet lists push the metrics off-screen on a phone. Clamp, fade, and
     let the reader ask for the rest. */
  .bullets {
    margin-bottom: 18px;
    max-height: 164px;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(#000 56%, transparent);
    mask-image: linear-gradient(#000 56%, transparent);
  }
  .project.is-expanded .bullets {
    margin-bottom: 28px;
    max-height: none;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .bullets-more { display: inline-flex; }

  /* ---- product tour: grid of thumbnails becomes a snapping strip ---- */
  .tour {
    gap: 12px;
    margin-top: 0;
    padding-top: 22px;
  }
  .thumbs {
    display: flex;
    gap: 10px;
    margin-inline: calc(-1 * var(--card-pad));
    padding: 2px var(--card-pad) 6px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    /* Restates what the strip does. touch-action intersects down the ancestor
       chain, so the pan-y on .project above can reach in and freeze a nested
       scroller; declaring it on the scroll container itself is what stops that. */
    touch-action: pan-x;
  }
  .thumbs > li {
    flex: 0 0 118px;
    scroll-snap-align: start;
  }

  /* ---- lightbox becomes a bottom sheet ---- */
  .lightbox {
    inset: auto 0 0 0;
    height: auto;
    max-height: 88dvh;
    justify-content: flex-start;
    gap: 14px;
    padding: 10px 16px calc(18px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--line-3);
    border-radius: 22px 22px 0 0;
    background: var(--bg-raised);
    box-shadow: 0 -20px 60px rgba(0, 0, 0, 0.65);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    animation: mkSheetUp 0.34s var(--ease);
    touch-action: none;
  }
  .lightbox::backdrop {
    background: rgba(6, 6, 14, 0.74);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .lightbox__grip { display: block; }
  /* The grip, the backdrop and a downward drag all close it. */
  .lightbox__close { display: none; }
  .lightbox__img {
    width: 100%;
    max-height: 54dvh;
    object-fit: contain;
    background: var(--bg);
  }
  .lightbox__bar {
    width: 100%;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: nowrap;
  }
  .lightbox__btn {
    justify-content: center;
    flex: none;
    width: 46px; height: 46px;
    padding: 0;
    border-radius: var(--r-md);
    font-size: 17px;
  }
  .lightbox__btn:active { transform: scale(0.92); background: rgba(139, 124, 246, 0.24); }
  .lightbox__btn-label { display: none; }
  .lightbox__meta {
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    text-align: center;
  }
  .lightbox__label {
    max-width: 100%;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .lightbox__counter { font-size: 11px; color: var(--dim); }

  /* ---- subpages ---- */
  .contact-grid { grid-template-columns: 1fr; gap: 18px; }
  .featured { grid-template-columns: 1fr; gap: 28px; }
  /* Cover above copy, matching the project cards. */
  .featured__img { order: -1; }
  .filters {
    flex-wrap: nowrap;
    padding-bottom: 34px;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
  }
  .filters .chip {
    flex: none;
    scroll-snap-align: start;
    min-height: 44px;
  }
}

@media (max-width: 820px) {
  .timeline { grid-template-columns: 20px 1fr; }
  .timeline__when {
    grid-column: 2;
    text-align: left;
    padding-top: 0;
    margin-bottom: 6px;
  }
  .timeline__rail { grid-row: span 2; }
  .timeline__item { grid-column: 2; }
}

@media (max-width: 700px) {
  .field__row { grid-template-columns: 1fr; }
  .form-card { padding: 24px 20px; }
  .btn { padding: 13px 22px; font-size: 14px; }
  .hero__cta .btn { flex: 1 1 auto; }
  .facts__row { flex-direction: column; align-items: flex-start; gap: 4px; }
  .facts__val { text-align: left; }
}

/* Motion is decoration here — drop all of it when the OS asks. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
  .hero__caret { animation: none; }
  .lightbox { animation: none; }
  /* Snap points fight a reduced-motion preference on every rail. */
  .ptl, .thumbs, .chiprail, .filters { scroll-snap-type: none; }
}

@media print {
  .nav, .chrome, .tabbar, .tabbar-spacer, .progress, .lightbox,
  .hero__orbs, .cta-band__halo, .page-head__halo { display: none !important; }
  /* Every project matters on paper, not just the one that happened to be open. */
  .project[hidden] { display: block !important; }
  .ptl, .bullets-more { display: none !important; }
  .bullets { max-height: none !important; -webkit-mask-image: none !important; mask-image: none !important; }
  body { background: #fff; color: #000; }
}
