/* ============================================================
   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;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  user-select: none;
  white-space: nowrap;
  will-change: transform;
  animation: wordmarkIn 1s cubic-bezier(0.2, 0.7, 0.2, 1) 0.1s both;
}
.wordmark-first {
  font-family: var(--mono);
  font-size: clamp(0.7rem, 1.6vw, 0.95rem);
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: clamp(0.4rem, 1.2vw, 0.9rem);
}
.wordmark-last {
  display: block;
  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);
}
@supports not (-webkit-text-stroke: 1px black) {
  .wordmark-last {
    color: var(--stroke-fallback);
  }
}

/* Corner labels borrowed from the poster-style hero reference: quiet,
   mono-set marks that flank the portrait without competing with the copy. */
.hero-tags {
  position: absolute;
  top: clamp(1.75rem, 7vw, 3.25rem);
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.hero-tags-left {
  left: 4%;
  padding-left: 0.9rem;
  border-left: 1px solid var(--rule);
  text-align: left;
}
.hero-tags-right {
  right: 3%;
  padding-right: 0.9rem;
  border-right: 1px solid var(--rule);
  text-align: right;
}

/* 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: 1%;
  left: auto;
  bottom: 0;
  transform: none;
  height: min(92%, 700px);
  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;
}
/* The wordmark's font-size (and thus its right edge) grows with the
   viewport up to a clamp ceiling, then plateaus — a single fixed
   percentage for the portrait's offset can't track that without either
   overlapping the copy at narrow widths or opening a huge dead gap at
   wide ones. These two bands approximate the needed curve: a near-linear
   ramp while the wordmark is still growing, then a fixed left edge
   (calc(100% - Npx) grows the offset 1:1 with viewport width) once it
   has plateaued. Tuned and verified against real layout measurements at
   861–2200px, not just eyeballed. */
@media (min-width: 1000px) {
  .portrait {
    right: calc(61.65vw - 566.8px);
  }
}
@media (min-width: 1440px) {
  .portrait {
    right: calc(100% - 1119px);
  }
}
/* 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);
  }
  .hero-tags {
    display: none;
  }
  .wordmark {
    position: static;
    transform: none;
    order: 1;
    align-items: center;
    text-align: center;
  }
  .wordmark-last {
    font-size: clamp(3.4rem, 14vw, 6rem);
  }
  .wordmark-first {
    font-size: 0.7rem;
  }
  .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;
  }
  /* The nav element still counts as a flex item in .nav even with its
     content hidden/absolute, so space-between leaves a gap centred on it
     instead of pushing the hamburger flush right. Taking it out of flow
     removes it from that calculation; .mobile's own absolute positioning
     is anchored to .site-header (sticky), not to this element, so it's
     unaffected. */
  nav[aria-label="Primary"] {
    position: absolute;
  }
  .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;
  }
}
