/* ============================================================
   Vishnu Vekaria — portfolio
   Graphite: monochrome near-black ground, no accent hue.
   Instrument Serif display / Geist body / Geist Mono utility.
   ============================================================ */

/* ---------- fonts (self-hosted, latin subsets) ---------- */

@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-italic-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("../fonts/geist-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("../fonts/geist-mono-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens ---------- */

:root {
  /* Graphite. No accent hue — hierarchy comes from weight, scale and spacing,
     which leaves the portrait and the two status colours as the only hues on
     the page. Every ambient glow, plate and hairline reads from this block, so
     changing the palette means changing here and nowhere else. */
  --ground: #0b0b0c;
  --ground-2: #141416;
  --ground-3: #1e1e21;
  --ground-veil: rgba(11, 11, 12, 0.86);

  --accent: #f2f0ec;
  --accent-soft: rgba(242, 240, 236, 0.5);

  --glow: rgba(242, 240, 236, 0.06);
  --glow-deep: rgba(120, 120, 128, 0.16);
  --plate: rgba(120, 120, 128, 0.16);
  --featured: #1c1c1f;
  --edge: rgba(242, 240, 236, 0.14);
  --stroke-fallback: rgba(242, 240, 236, 0.14);

  --ink-bright: #ffffff;
  --ink: #eceae6;
  --ink-soft: #9c9a96;
  --ink-faint: #7f7d79; /* 4.8:1 on --ground; anything darker fails AA at label sizes */
  --rule: rgba(242, 240, 236, 0.16);
  --rule-faint: rgba(242, 240, 236, 0.08);

  /* semantic state — deliberately the only saturated colour that ships */
  --live: #7fd8a4;
  --wip: #e8c87a;
  --danger: #e36b7a;

  --serif: "Instrument Serif", Georgia, "Times New Roman", serif;
  --sans: "Geist", "Segoe UI", system-ui, -apple-system, sans-serif;
  --mono: "Geist Mono", ui-monospace, Consolas, "Cascadia Mono", monospace;

  --max: 1120px;
  --radius: 10px;
  --header-h: 64px;
}

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

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--ground);
  color: var(--ink);
  font: 400 16px/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a {
  color: inherit;
  text-decoration: none;
}

p {
  margin: 0 0 1rem;
}

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

h1,
h2,
h3 {
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: 0.005em;
  margin: 0;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.4rem, 6vw, 4.2rem);
}
h2 {
  font-size: clamp(1.7rem, 3.4vw, 2.4rem);
}
h3 {
  font-size: 1.35rem;
}

em {
  font-family: var(--serif);
  font-style: italic;
  color: var(--ink-bright);
}

strong {
  font-weight: 600;
  color: var(--ink);
}

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

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

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--accent);
  color: var(--ground);
  padding: 0.5rem 1rem;
  font-family: var(--mono);
  font-size: 0.8rem;
}
.skip-link:focus {
  left: 0;
}

.container {
  width: min(100% - 40px, var(--max));
  margin-inline: auto;
}

.section {
  position: relative;
  padding: clamp(56px, 9vw, 96px) 0;
}
.section.compact {
  padding-top: 24px;
}

/* mono utility label */
.eyebrow {
  display: block;
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.9rem;
}

.muted {
  color: var(--ink-soft);
}

/* ---------- header: ticker + nav ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--ground-veil);
  backdrop-filter: blur(14px) saturate(130%);
  border-bottom: 1px solid var(--rule);
}

.ticker {
  display: grid;
  grid-template-rows: 1fr;
  overflow: hidden;
  border-bottom: 1px solid var(--rule-faint);
  transition: grid-template-rows 0.35s ease, opacity 0.35s ease, border-color 0.35s ease;
}
.site-header.scrolled .ticker {
  grid-template-rows: 0fr;
  opacity: 0;
  border-bottom-color: transparent;
}
.ticker-track {
  display: flex;
  width: max-content;
  min-height: 0;
  animation: marquee 30s linear infinite;
}
.ticker-track span {
  display: inline-block;
  white-space: nowrap;
  padding: 0.35rem 1.5rem 0.35rem 0;
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent-soft);
}
@keyframes marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

.nav {
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.brand {
  font-family: var(--serif);
  font-size: 1.15rem;
  letter-spacing: 0.01em;
  color: var(--ink);
}

nav ul {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0;
  padding: 0;
}

nav ul.desktop a {
  display: inline-block;
  padding: 0.45rem 0.85rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border-radius: 999px;
  transition: color 0.2s ease;
}
nav ul.desktop a:hover {
  color: var(--ink-bright);
}
nav ul.desktop a.active {
  color: var(--accent);
}

nav a.pill {
  border: 1px solid var(--accent);
  color: var(--accent);
  border-radius: 999px;
  padding: 0.45rem 1.05rem;
  margin-left: 8px;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: background 0.2s ease, color 0.2s ease;
}
nav a.pill:hover,
nav a.pill.active,
nav ul.desktop a.pill:hover,
nav ul.desktop a.pill.active {
  background: var(--accent);
  color: var(--ground);
}

/* hamburger */
.hamburger {
  display: none;
  width: 42px;
  height: 42px;
  border: 1px solid var(--rule);
  background: transparent;
  border-radius: 8px;
  cursor: pointer;
  position: relative;
}
.hamburger span,
.hamburger span::before,
.hamburger span::after {
  content: "";
  position: absolute;
  left: 11px;
  right: 11px;
  height: 1.5px;
  background: var(--ink);
  transition: transform 0.25s ease, top 0.25s ease;
}
.hamburger span {
  top: 20px;
}
.hamburger span::before {
  left: 0;
  right: 0;
  top: -6px;
}
.hamburger span::after {
  left: 0;
  right: 0;
  top: 6px;
}
.hamburger[aria-expanded="true"] span {
  background: transparent;
}
.hamburger[aria-expanded="true"] span::before {
  top: 0;
  transform: rotate(45deg);
}
.hamburger[aria-expanded="true"] span::after {
  top: 0;
  transform: rotate(-45deg);
}

.mobile {
  display: none;
}

.nav-overlay {
  position: fixed;
  inset: 0;
  background: rgba(6, 4, 8, 0.6);
  z-index: 40;
}

/* ---------- hero (home) ---------- */

.hero {
  position: relative;
  min-height: calc(100svh - var(--header-h) - 30px);
  overflow: hidden;
}

.hero::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -12%;
  width: 70vw;
  height: 60%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 100%, var(--glow-deep), var(--glow) 55%, transparent 75%);
  pointer-events: none;
}

/* Wordmark sits left, figure sits right. Centring the figure meant it covered
   the middle of the name; offsetting both lets the wordmark read in full while
   the figure still breaks its last letter. */
.wordmark {
  position: absolute;
  left: 4%;
  right: auto;
  top: 38%;
  z-index: 1;
  transform: translateY(-50%);
  margin: 0;
  text-align: left;
  font-size: clamp(3.2rem, 12.5vw, 11.5rem);
  font-family: var(--serif);
  line-height: 0.82;
  letter-spacing: 0.02em;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--accent-soft);
  user-select: none;
  white-space: nowrap;
  will-change: transform;
  animation: wordmarkIn 1s cubic-bezier(0.2, 0.7, 0.2, 1) 0.1s both;
}
@supports not (-webkit-text-stroke: 1px black) {
  .wordmark {
    color: var(--stroke-fallback);
  }
}

/* The figure is a background-removed cut-out: no frame, no crop.
   It stands in front of the wordmark, lit from behind and fading into the ground. */
/* Sized by height so the full figure always fits the hero, whatever the
   source image's aspect ratio — width follows from it. */
.portrait {
  position: absolute;
  right: 3%;
  left: auto;
  bottom: 0;
  transform: none;
  height: min(80%, 620px);
  width: auto;
  max-width: 46vw;
  margin: 0;
  z-index: 2;
  will-change: transform;
  animation: rise 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) 0.4s both;
}
/* spotlight behind the figure, so it reads as lit rather than pasted on */
.portrait::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 6%;
  width: 150%;
  aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(
    circle,
    var(--glow) 0%,
    var(--glow-deep) 38%,
    transparent 68%
  );
  z-index: -1;
  pointer-events: none;
}
.portrait img {
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  display: block;
  filter: brightness(0.94) contrast(1.06) saturate(0.95)
    drop-shadow(0 26px 44px rgba(0, 0, 0, 0.62));
  /* feet dissolve into the page instead of being sliced off */
  -webkit-mask-image: linear-gradient(180deg, #000 76%, transparent 98%);
  mask-image: linear-gradient(180deg, #000 76%, transparent 98%);
}
/* initials plate shown if the photo is missing */
.portrait.no-photo {
  width: clamp(240px, 28vw, 360px);
  aspect-ratio: 4 / 5;
  border-radius: 999px 999px 0 0;
  border: 1px solid var(--rule);
  border-bottom: 0;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 24%, var(--ground-3), var(--ground-2) 70%);
}
.portrait.no-photo img,
.portrait.no-photo::before {
  display: none;
}
.portrait .plate {
  display: none;
}
.portrait.no-photo .plate {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 4rem;
  color: var(--accent-soft);
}

.hero-copy {
  position: absolute;
  left: 4%;
  bottom: clamp(1.5rem, 5vw, 3.5rem);
  width: min(44%, 480px);
  z-index: 3;
  animation: fadeUp 0.8s ease 0.7s both;
}
.hero-copy .lab {
  display: block;
  font-family: var(--mono);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.5rem;
}
.hero-copy p {
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0;
}

.hero-stats {
  display: flex;
  gap: clamp(1.2rem, 3vw, 2.4rem);
  margin-top: 1.4rem;
}
.hero-stats div {
  text-align: left;
}
.hero-stats b {
  display: block;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.7rem;
  line-height: 1;
  color: var(--ink-bright);
  font-variant-numeric: tabular-nums;
}
.hero-stats span {
  font-family: var(--mono);
  font-size: 0.56rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

@keyframes wordmarkIn {
  from {
    opacity: 0;
    letter-spacing: 0.09em;
  }
  to {
    opacity: 1;
    letter-spacing: 0.02em;
  }
}
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(9%);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

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

.page-hero {
  padding-top: clamp(48px, 8vw, 88px);
  padding-bottom: clamp(24px, 4vw, 40px);
}
.page-hero h1 {
  max-width: 16ch;
}
.page-hero .muted {
  max-width: 58ch;
  margin-top: 1rem;
  font-size: 1.02rem;
}

/* ---------- bento ---------- */

.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

.tile {
  position: relative;
  background: var(--ground-2);
  border: 1px solid var(--rule-faint);
  border-radius: var(--radius);
  padding: 1.15rem 1.25rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 0.8rem;
  transition: transform 0.25s cubic-bezier(0.2, 0.7, 0.2, 1), border-color 0.25s ease, background 0.25s ease;
}
a.tile:hover,
a.tile:focus-visible {
  transform: translateY(-3px);
  border-color: var(--rule);
  background: var(--ground-3);
}

.tile .k {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.tile .v {
  font-size: 0.95rem;
  font-weight: 500;
  line-height: 1.4;
  color: var(--ink);
}
.tile .num {
  font-family: var(--serif);
  font-size: 2.6rem;
  line-height: 1;
  color: var(--ink-bright);
  font-variant-numeric: tabular-nums;
}

.tile.wide {
  grid-column: span 2;
}

.tile.featured {
  grid-column: span 2;
  grid-row: span 2;
  background: linear-gradient(150deg, var(--featured) 0%, var(--ground-2) 62%);
  border-color: var(--edge);
  padding: 1.5rem;
}
.tile.featured .title {
  font-family: var(--serif);
  font-size: clamp(1.7rem, 3vw, 2.3rem);
  color: var(--ink);
  margin: 0.5rem 0 0.4rem;
}
.tile.featured .sub {
  color: var(--ink-soft);
  font-size: 0.92rem;
  max-width: 40ch;
  margin: 0;
}
.thumb {
  margin-top: 1rem;
  border: 1px solid var(--rule-faint);
  border-radius: 8px;
  overflow: hidden;
  background: var(--ground);
}
.thumb .thumb-bar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--rule-faint);
}
.thumb .thumb-bar i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ground-3);
}
.thumb .thumb-bar .url {
  margin-left: 0.4rem;
  font-family: var(--mono);
  font-size: 0.58rem;
  color: var(--ink-faint);
  letter-spacing: 0.04em;
}
.thumb blockquote {
  margin: 0;
  padding: 1.2rem 1.2rem 1.35rem;
  font-family: var(--serif);
  font-size: 1.15rem;
  line-height: 1.3;
  color: var(--ink-bright);
}

.tile.identity {
  grid-row: span 2;
  padding: 0;
  overflow: hidden;
  min-height: 260px;
  background: radial-gradient(ellipse at 50% 84%, var(--plate), var(--ground-2) 68%);
}
/* cover, not contain: a bust crop is wider than this tile, so fitting it would
   leave dead space above the head. Filling and cropping the sides keeps the face large. */
.tile.identity img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 12%;
  filter: brightness(0.94) contrast(1.05) saturate(0.95);
  -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent 97%);
  mask-image: linear-gradient(180deg, #000 72%, transparent 97%);
}
.tile.identity .cap {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 2.2rem 1.1rem 0.9rem;
  background: linear-gradient(180deg, transparent, var(--ground-veil) 62%);
}
.tile.identity .cap .v {
  font-family: var(--serif);
  font-size: 1.15rem;
  font-weight: 400;
}

.status-dot {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.82rem;
  font-weight: 500;
}
.status-dot::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}
.status-dot.live {
  color: var(--live);
}
.status-dot.wip {
  color: var(--wip);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.chip {
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  border: 1px solid var(--rule-faint);
  border-radius: 999px;
  padding: 0.18rem 0.55rem;
  white-space: nowrap;
}

.tile-link-row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

/* ---------- buttons & links ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.62rem 1.25rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  background: transparent;
  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.btn:hover {
  border-color: var(--accent);
  color: var(--ink-bright);
}
.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--ground);
}
.btn.primary:hover {
  background: var(--ink-bright);
  border-color: var(--ink-bright);
  color: var(--ground);
}

/* inline-flex + min-height keeps standalone links at the 24px minimum
   pointer target size (WCAG 2.5.8) without changing how they look */
.text-link {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  font-family: var(--mono);
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.text-link:hover {
  color: var(--ink-bright);
  border-color: var(--ink-bright);
}

.arrow {
  width: 0.85em;
  height: 0.85em;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  flex: none;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-top: 1.6rem;
}

/* ---------- bands (looking-for / cta) ---------- */

.band {
  border-top: 1px solid var(--rule-faint);
  border-bottom: 1px solid var(--rule-faint);
  background: var(--ground-2);
}
.band .inner {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 3rem;
  align-items: center;
  padding: clamp(2.2rem, 5vw, 3.5rem) 0;
}
.band h2 {
  max-width: 20ch;
}
.band p {
  color: var(--ink-soft);
  margin: 0;
}

.cta-card {
  text-align: center;
  padding: clamp(2.5rem, 6vw, 4.5rem) 1rem;
}
.cta-card h2 {
  font-size: clamp(2rem, 4.6vw, 3.2rem);
  max-width: 22ch;
  margin-inline: auto;
}
.cta-card p {
  color: var(--ink-soft);
  max-width: 52ch;
  margin: 1rem auto 0;
}
.cta-card .hero-actions {
  justify-content: center;
}

/* ---------- project case tiles ---------- */

.cases {
  display: grid;
  gap: 16px;
}

.case {
  background: var(--ground-2);
  border: 1px solid var(--rule-faint);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 2rem);
  transition: border-color 0.25s ease;
}
.case:hover {
  border-color: var(--rule);
}
.case.featured-case {
  background: linear-gradient(150deg, var(--featured) 0%, var(--ground-2) 58%);
  border-color: var(--edge);
}

.case-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.1rem;
}
.case-head h2 {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
}
.case-head .meta {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.case-head .when {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.case-body {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.4rem;
  margin-bottom: 1.2rem;
}
.case-body div dt {
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.4rem;
}
.case-body div dd {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--ink-soft);
}
.case-body {
  margin-block-start: 0;
}
dl.case-body {
  margin-block: 0 1.2rem;
}

.case-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

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

.about-grid {
  display: grid;
  grid-template-columns: minmax(250px, 360px) 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
/* Bare cut-out, no frame — matching the hero. A bordered plate here would read
   as a different design language one scroll below the unframed figure. */
.about-portrait {
  position: sticky;
  top: calc(var(--header-h) + 40px);
  margin: 0;
  border: 0;
  border-radius: 0;
  background: none;
  overflow: visible;
}
/* Width stays at 100%: the hero's copy of this glow is clipped by
   .hero { overflow: hidden }, but nothing clips it here, so bleeding past the
   portrait pushed the document 9px wide and gave mobile a horizontal scroll. */
.about-portrait::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 46%;
  width: 100%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, var(--glow-deep) 0%, transparent 72%);
  z-index: -1;
  pointer-events: none;
}
.about-portrait img {
  width: 100%;
  height: auto;
  object-fit: contain;
  filter: brightness(0.96) contrast(1.05) saturate(0.95)
    drop-shadow(0 20px 34px rgba(0, 0, 0, 0.55));
  -webkit-mask-image: linear-gradient(180deg, #000 84%, transparent 99%);
  mask-image: linear-gradient(180deg, #000 84%, transparent 99%);
}
.about-prose {
  max-width: 62ch;
}
.about-prose p {
  color: var(--ink-soft);
  margin-bottom: 1.2rem;
}
.about-prose h2 {
  margin: 2.4rem 0 1rem;
}
.about-prose h2:first-child {
  margin-top: 0;
}

.skill-groups {
  display: grid;
  gap: 1.1rem;
  margin-top: 1.4rem;
}
.skill-groups .row {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 1rem;
  align-items: baseline;
  border-bottom: 1px solid var(--rule-faint);
  padding-bottom: 1.1rem;
}
.skill-groups .row:last-child {
  border-bottom: 0;
}
.skill-groups .row > span {
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

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

.contact-grid {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 16px;
  align-items: start;
}

.panel {
  background: var(--ground-2);
  border: 1px solid var(--rule-faint);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 2rem);
}

.clean-list {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
}
.clean-list li {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--rule-faint);
  color: var(--ink-soft);
  font-size: 0.92rem;
}
.clean-list li:last-child {
  border-bottom: 0;
}

.contact-note {
  margin-top: 1.2rem;
  font-size: 0.88rem;
  color: var(--ink-soft);
}
.contact-note a {
  color: var(--accent);
}
.contact-note a:hover {
  color: var(--ink-bright);
}

form label {
  display: block;
  font-family: var(--mono);
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 1.3rem 0 0.4rem;
}
form label:first-of-type {
  margin-top: 0.4rem;
}

form input,
form textarea {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 0.55rem 2px;
  color: var(--ink);
  font: 400 0.98rem/1.5 var(--sans);
  transition: border-color 0.2s ease;
}
form input::placeholder,
form textarea::placeholder {
  color: var(--ink-faint);
}
form input:focus,
form textarea:focus {
  outline: none;
  border-bottom-color: var(--accent);
}
form input.invalid,
form textarea.invalid {
  border-bottom-color: var(--danger);
}
form textarea {
  min-height: 120px;
  resize: vertical;
}

.error {
  display: none;
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--danger);
  margin-top: 0.35rem;
}
.error.show {
  display: block;
}

form .btn {
  margin-top: 1.6rem;
}
form .btn.sending {
  opacity: 0.65;
  pointer-events: none;
}

.popup-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(6, 4, 8, 0.72);
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.popup-box {
  background: var(--ground-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  max-width: 380px;
  width: 100%;
  padding: 1.8rem;
  text-align: center;
}
.popup-box h2 {
  font-size: 1.5rem;
  margin-bottom: 0.5rem;
}
.popup-box.success h2 {
  color: var(--live);
}
.popup-box.error h2 {
  color: var(--danger);
}
.popup-box p {
  color: var(--ink-soft);
  font-size: 0.92rem;
}
.popup-box button {
  margin-top: 0.6rem;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink);
  border-radius: 999px;
  padding: 0.5rem 1.6rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}
.popup-box button:hover {
  border-color: var(--accent);
  color: var(--ink-bright);
}

/* ---------- footer ---------- */

footer {
  border-top: 1px solid var(--rule);
  padding: 2.2rem 0 2.8rem;
}
.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.footer-inner p {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}
.social {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem clamp(0.9rem, 4vw, 1.4rem);
}
.social a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: color 0.2s ease;
}
.social a:hover {
  color: var(--accent);
}

/* ---------- reveal on scroll ---------- */

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.reveal.active {
  opacity: 1;
  transform: none;
}
.reveal-delay-1 {
  transition-delay: 0.08s;
}
.reveal-delay-2 {
  transition-delay: 0.16s;
}

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

@media (max-width: 1000px) {
  .hero-copy {
    width: min(48%, 400px);
  }
  .case-body {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

@media (max-width: 860px) {
  .hero {
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding-top: clamp(2rem, 8vw, 4rem);
  }
  .wordmark {
    position: static;
    transform: none;
    order: 1;
    font-size: clamp(3.4rem, 14vw, 6rem);
  }
  .portrait {
    position: static;
    transform: none;
    order: 2;
    margin-top: -1.5rem; /* tuck the figure up into the wordmark */
    height: auto;
    width: min(78vw, 360px);
    max-width: 78vw;
    animation-name: fadeUp; /* desktop 'rise' ends on translateX(-50%), which mis-centres a static figure */
  }
  .portrait img {
    height: auto;
    width: 100%;
  }
  .portrait.no-photo {
    margin-top: 1.4rem;
  }
  .hero-copy {
    position: static;
    order: 3;
    width: min(100% - 40px, 480px);
    margin-top: 1.8rem;
    text-align: center;
  }
  .hero-stats {
    justify-content: center;
  }
  .hero-stats div {
    text-align: center;
  }
  .band .inner {
    grid-template-columns: 1fr;
    gap: 1.4rem;
  }
  .about-grid {
    grid-template-columns: 1fr;
  }
  .about-portrait {
    position: static;
    max-width: 320px;
  }
  .contact-grid {
    grid-template-columns: 1fr;
  }
}

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

@media (max-width: 720px) {
  nav ul.desktop {
    display: none;
  }
  .hamburger {
    display: block;
  }
  .mobile {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--ground-2);
    border-bottom: 1px solid var(--rule);
    transform: translateY(-8px);
    opacity: 0;
    transition: transform 0.24s ease, opacity 0.24s ease;
  }
  .mobile.show {
    transform: none;
    opacity: 1;
  }
  .mobile ul {
    flex-direction: column;
    align-items: stretch;
    padding: 0.6rem 20px 1rem;
    gap: 0;
  }
  .mobile a {
    display: block;
    padding: 0.8rem 0.4rem;
    font-family: var(--mono);
    font-size: 0.78rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-soft);
    border-bottom: 1px solid var(--rule-faint);
  }
  .mobile a.active {
    color: var(--accent);
  }
  body.nav-open {
    overflow: hidden;
  }
}

@media (max-width: 520px) {
  .bento {
    grid-template-columns: 1fr;
  }
  /* Every spanning tile must be reset here. A span-2 item in a single-column
     grid creates an implicit second column sized to content, which overflows
     the container — this is why span lives in a class, not an inline style. */
  .tile.featured,
  .tile.identity,
  .tile.wide {
    grid-column: auto;
    grid-row: auto;
  }
  .tile.identity {
    min-height: 320px;
  }
  .hero-actions .btn {
    width: 100%;
    justify-content: center;
  }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .wordmark,
  .portrait,
  .hero-copy {
    animation: none;
  }
  .ticker-track {
    animation: none;
  }
  .ticker {
    transition: none;
  }
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .tile,
  a.tile:hover {
    transition: none;
    transform: none;
  }
}
