/* ==========================================================================
   Jaehyuk Choi — portfolio design system
   Editorial, cinematic dark, one accent. Game media carries the color.
   ========================================================================== */

/* -------------------------------------------------------------- 1. tokens */
:root {
  color-scheme: dark;

  /* ------------------------------------------------- theme (edit here) --
     These six semantic tokens are the whole palette. Everything else in
     this file is derived from them, so changing a value here restyles the
     entire site. */
  --color-background: #141416;
  --color-surface: #202023;
  --color-text: #f5f5f5;
  --color-text-muted: #a1a1aa;
  --color-accent: #c43d4b;
  --color-border: #38383d;

  /* Derived: a well behind media, a brighter border for controls, an
     accent hover, ink for text sitting on the accent, and a scrim for
     labels that overlap artwork. */
  --color-well: #1a1a1c;
  /* Interactive borders (buttons, chips) need 3:1 against the background to
     meet WCAG 1.4.11, so this is lighter than the plain divider colour. */
  --color-border-strong: #6b6b71;
  --color-accent-hover: #e05a65;
  /*
     The crimson is a fill colour, not a text colour: at 3.6:1 on the
     background it clears WCAG 1.4.11 for markers, rules and borders but not
     1.4.3 for words. Anything written in the accent uses this brighter tone
     instead, which reaches 5.1:1 on the background and 4.5:1 on a card.
     Keeping the two apart is what lets the deep crimson carry the buttons
     and markers while red type stays readable.
  */
  --color-accent-text: #e05a65;
  /* Labels sitting on a crimson fill: white clears 5.1:1 there. */
  --color-on-accent: #ffffff;
  --color-text-faint: #8b8b93;
  --color-scrim: rgba(20, 20, 22, 0.82);
  /* The softer half of the same scrim, for washing artwork back behind type. */
  --color-scrim-soft: rgba(20, 20, 22, 0.55);
  --color-hairline: rgba(245, 245, 245, 0.14);

  /* ---------------------------------------------- component aliases ----
     Kept so every existing rule keeps working; all of them resolve to the
     tokens above rather than to a colour of their own. */
  --paper: var(--color-background);
  --paper-sunk: var(--color-well);
  --paper-card: var(--color-surface);
  --ink-deep: var(--color-background);

  --ink: var(--color-text);
  --ink-soft: var(--color-text-muted);
  --ink-faint: var(--color-text-faint);
  --on-dark: var(--color-text);
  --on-dark-soft: var(--color-text-muted);

  --line: var(--color-border);
  --line-strong: var(--color-border-strong);
  --accent: var(--color-accent);
  --accent-deep: var(--color-accent-hover);
  --accent-text: var(--color-accent-text);

  /* type */
  --font-sans: 'Archivo', system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --fs-display: clamp(2.75rem, 8vw, 5.75rem);
  --fs-title: clamp(2.25rem, 5.5vw, 4.25rem);
  --fs-h2: clamp(1.625rem, 3vw, 2.25rem);
  --fs-h3: clamp(1.25rem, 2vw, 1.5rem);
  --fs-body: 1.0625rem;
  --fs-small: 0.875rem;
  --fs-label: 0.6875rem;

  /* space */
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --measure: 68ch;
  --container: 1180px;
  --section-gap: clamp(4rem, 9vw, 8rem);
}

/* --------------------------------------------------------------- 2. reset */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

p { margin: 0 0 1.1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

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

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 0;
}

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

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

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

/* ------------------------------------------------------------ 3. utilities */
.wrap {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.measure { max-width: var(--measure); }

.label {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

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

.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -4rem;
  z-index: 100;
  padding: 0.65rem 1rem;
  background: var(--ink-deep);
  color: var(--on-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 0.75rem; }

/* --------------------------------------------------------------- 4. header */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper); /* fallback for browsers without color-mix() */
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 4rem;
  padding-block: 0.75rem;
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  text-decoration: none;
  margin-right: auto;
}

.brand__name {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.brand__role {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 1.75rem);
}

.site-nav a {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-soft);
  padding-block: 0.35rem;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.site-nav a:hover { color: var(--ink); border-bottom-color: var(--accent); }
.site-nav a[aria-current='page'] { color: var(--color-accent-text); border-bottom-color: var(--color-accent); }

.site-nav a.nav-resume {
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
  color: var(--ink);
}
.site-nav a.nav-resume:hover {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--paper);
}

@media (max-width: 620px) {
  .site-header__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
  }
  .brand { margin-right: 0; }
  .brand__role { display: none; }
  .site-nav { gap: 1rem; flex-wrap: wrap; }
}

/* --------------------------------------------------------------- 5. buttons */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1.15rem;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn:hover {
  background: transparent;
  border-color: var(--accent);
  color: var(--accent-text);
}

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--color-on-accent);
}
.btn--primary:hover {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
  color: var(--color-on-accent);
}

.btn--ghost { border-color: transparent; padding-inline: 0; }
.btn--ghost:hover { background: transparent; color: var(--accent-text); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
}

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--accent-text);
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
}
.arrow-link span { transition: transform 0.18s ease; }
a:hover > .arrow-link span,
.arrow-link:hover span,
.card:hover .arrow-link span,
.card:focus-within .arrow-link span { transform: translateX(4px); }

/* ------------------------------------------------- 5b. cinematic hero */
/*
   Full-viewport opening sequence on the homepage only. Dark and self
   contained: its colours come from the global palette. The entrance is pure CSS and runs without JavaScript; hero.js only
   feeds --scroll, --mx and --my for the parallax and the scroll hand-off.
   Timing lives in --cine-beat — raise it to slow the whole sequence down.
*/
.cine {
  --cine-bg: var(--color-background);
  --cine-ink: var(--color-text);
  --cine-soft: var(--color-text-muted);
  --cine-accent: var(--color-accent);
  --cine-beat: 0.9s;
  --scroll: 0;
  --mx: 0;
  --my: 0;

  position: relative;
  display: grid;
  grid-template-rows: 1fr auto;
  min-height: calc(100vh - var(--header-h, 4rem)); /* fallback */
  min-height: calc(100svh - var(--header-h, 4rem));
  padding-block: clamp(2rem, 6vw, 4rem) 0;
  overflow: clip;
  background: var(--cine-bg);
  color: var(--cine-ink);
  isolation: isolate;
}

/* Existing project artwork, dimmed right down to read as atmosphere. */
.cine__backdrop {
  position: absolute;
  inset: -6%;
  z-index: -1;
  opacity: 0;
  animation: cine-backdrop calc(var(--cine-beat) * 2.4) ease-out 0.15s both;
}

.cine__backdrop img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.45) contrast(1.05);
  transform: scale(calc(1.06 + var(--scroll) * 0.12))
    translate3d(calc(var(--mx) * -10px), calc(var(--my) * -10px), 0);
  transition: transform 0.9s cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* Keeps the type legible over the artwork without a decorative gradient wash. */
.cine__backdrop::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 35%, var(--color-scrim-soft), var(--cine-bg) 78%);
}

.cine__stage {
  display: flex;
  flex-direction: column;
  justify-content: center;
  transform: translate3d(calc(var(--mx) * 6px), calc(var(--scroll) * -7vh), 0)
    scale(calc(1 - var(--scroll) * 0.06));
  opacity: calc(1 - var(--scroll) * 1.15);
  transition: transform 0.7s cubic-bezier(0.2, 0.7, 0.3, 1);
  will-change: transform, opacity;
}

/* -- the name ----------------------------------------------------------- */
.cine__name {
  margin: 0;
  font-size: clamp(3.25rem, 15vw, 11.5rem);
  font-weight: 800;
  line-height: 0.86;
  letter-spacing: -0.045em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Each line is a mask its text slides up into. */
.cine__line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;
}

.cine__reveal {
  display: block;
  transform: translateY(110%);
  animation: cine-rise calc(var(--cine-beat) * 1.3) cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: calc(0.12s + var(--i, 0) * var(--cine-beat) * 0.16);
}

.cine__role {
  margin: clamp(1rem, 2.5vw, 1.75rem) 0 0;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: clamp(0.75rem, 1.5vw, 1rem);
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--color-accent-text);
}

.cine__say {
  max-width: 44ch;
  margin: clamp(1.25rem, 3vw, 2rem) 0 0;
  font-size: clamp(1rem, 1.5vw, 1.1875rem);
  color: var(--cine-soft);
  opacity: 0;
  animation: cine-fade var(--cine-beat) ease-out both;
  animation-delay: calc(var(--cine-beat) * 0.85);
}

.cine__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  opacity: 0;
  animation: cine-fade var(--cine-beat) ease-out both;
  animation-delay: calc(var(--cine-beat) * 1.05);
}

.cine-btn {
  display: inline-flex;
  align-items: center;
  padding: 0.75rem 1.35rem;
  border: 1px solid var(--color-border-strong);
  color: var(--cine-ink);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-decoration: none;
  transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.cine-btn:hover {
  background: transparent;
  border-color: var(--cine-accent);
  color: var(--color-accent-text);
}
.cine-btn--primary {
  background: var(--cine-accent);
  border-color: var(--cine-accent);
  color: var(--color-on-accent);
  font-weight: 500;
}
.cine-btn--primary:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
  color: var(--color-on-accent);
}
.cine :focus-visible { outline-color: var(--color-accent-text); }

/* -- foot: scroll cue + marquee ----------------------------------------- */
.cine__foot {
  padding-bottom: clamp(1.25rem, 3vw, 2rem);
  opacity: 0;
  animation: cine-fade var(--cine-beat) ease-out both;
  animation-delay: calc(var(--cine-beat) * 1.25);
}

.cine__foot-inner {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 5vw, 4rem);
}

.cine__scroll {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--cine-soft);
}
.cine__scroll:hover { color: var(--cine-ink); }
.cine__scroll i {
  width: 1px;
  height: 2.25rem;
  background: linear-gradient(to bottom, var(--cine-accent), transparent);
  animation: cine-cue 2.4s ease-in-out infinite;
  transform-origin: top;
}

.cine__marquee {
  flex: 1;
  overflow: hidden;
  border-top: 1px solid var(--color-hairline);
  padding-top: 0.875rem;
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}

.cine__track {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  width: max-content;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--cine-soft);
  /* Duration is set per page from the keyword count, so the scroll speed stays
     the same however long the strip is. */
  animation: cine-marquee var(--marquee-duration, 34s) linear infinite;
}

/* Small crimson separator. The glyph is not in IBM Plex Mono, so symbol fonts
   lead the stack to stop it falling back to a missing-character box. */
.cine__track i {
  font-family: 'Segoe UI Symbol', 'Apple Symbols', 'Noto Sans Symbols 2', var(--font-mono), sans-serif;
  font-size: 0.5625rem;
  font-style: normal;
  line-height: 1;
  color: var(--cine-accent);
}

/* The header sits transparent over the dark hero, then returns to paper. */
.site-header--ghost {
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
}
.site-header--ghost .brand__name,
.site-header--ghost .site-nav a[aria-current='page'] { color: var(--color-accent-text); }
.site-header--ghost .brand__role,
.site-header--ghost .site-nav a { color: var(--color-text-muted); }
.site-header--ghost .site-nav a:hover { color: var(--color-text); }
.site-header--ghost .nav-resume { border-color: var(--color-border-strong); }
.site-header--ghost .nav-resume:hover {
  background: var(--color-text);
  border-color: var(--color-text);
  color: var(--color-background);
}

@keyframes cine-rise {
  from { transform: translateY(110%); }
  to { transform: translateY(0); }
}
@keyframes cine-fade {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes cine-backdrop {
  from { opacity: 0; }
  to { opacity: 0.22; }
}
@keyframes cine-marquee {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(-50%, 0, 0); }
}
@keyframes cine-cue {
  0%, 100% { transform: scaleY(0.35); opacity: 0.5; }
  50% { transform: scaleY(1); opacity: 1; }
}

@media (max-width: 640px) {
  /* Shorter, simpler entrance and no wasted vertical space on phones. */
  .cine { --cine-beat: 0.62s; }
  .cine__name { font-size: clamp(2.75rem, 17vw, 5rem); }
  .cine__foot-inner { flex-direction: column; align-items: flex-start; gap: 1rem; }
  .cine__marquee { width: 100%; }
  .cine__actions { gap: 0.5rem; }
  .cine-btn { padding: 0.65rem 1rem; }
}

/* Reduced motion: the finished composition, no movement at all. */
@media (prefers-reduced-motion: reduce) {
  .cine__backdrop { opacity: 0.22; animation: none; }
  .cine__backdrop img { transform: none; transition: none; }
  .cine__stage { transform: none; opacity: 1; transition: none; }
  .cine__reveal,
  .cine__say,
  .cine__actions,
  .cine__foot {
    animation: none;
    opacity: 1;
    transform: none;
  }
  .cine__track { animation: none; }
  .cine__scroll i { animation: none; opacity: 0.8; transform: none; }
}

/* ---------------------------------------------------------------- 6. hero */
.hero {
  padding-block: clamp(3rem, 8vw, 6rem) clamp(2.5rem, 6vw, 4.5rem);
  border-bottom: 1px solid var(--line);
}

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

.hero__name {
  font-size: var(--fs-display);
  font-weight: 800;
  letter-spacing: -0.035em;
  margin-bottom: 0.4em;
}

.hero__title {
  display: block;
  font-family: var(--font-mono);
  font-size: clamp(0.75rem, 1.4vw, 0.875rem);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin-bottom: 1.5rem;
}

.hero__intro {
  max-width: 56ch;
  font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
  color: var(--ink-soft);
  margin-bottom: 2rem;
}

.hero__facts {
  border-top: 2px solid var(--ink);
  padding-top: 0.875rem;
}
.hero__facts li {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--ink-soft);
  padding-block: 0.4rem;
  border-bottom: 1px solid var(--line);
}

@media (max-width: 860px) {
  .hero__grid { grid-template-columns: 1fr; align-items: start; }
}

/* ------------------------------------------------------------- 7. sections */
.section { padding-block: var(--section-gap); }
.section + .section { padding-top: 0; }

.section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding-bottom: 1.25rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
  border-bottom: 2px solid var(--ink);
}

.section__title {
  font-size: var(--fs-h2);
  font-weight: 700;
}

.section__note {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--ink-faint);
}

/* -------------------------------------------------------- 8. project cards */
/*
   One card component for every project listing on the site: Featured Projects
   and More projects on the homepage, and each section of the Work page.

   Information on the left at 55%, artwork on the right at 45%. Both are
   ordinary grid tracks that grow with their content — no fixed heights, no
   absolute positioning for anything that carries meaning, and nothing hidden,
   so a long title or an extra highlight makes the card taller instead of
   spilling out of it.
*/
.card-grid {
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
}

.card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 55fr) minmax(0, 45fr);
  grid-template-areas: 'body media';
  align-items: stretch;
  background: var(--paper-card);
  border: 1px solid var(--line);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.18s ease, transform 0.18s ease;
}

/*
   The whole card is clickable, but the anchor is the title: its ::after is
   stretched over the card. The card itself is an <article>, so a real link
   inside it — an award's source — is not trapped in a nested <a>.
*/
.card__link {
  color: inherit;
  text-decoration: none;
}
.card__link::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* Links inside the card sit above that overlay so they stay clickable. */
.card__body a:not(.card__link) {
  position: relative;
  z-index: 2;
}

.card--link:hover {
  border-color: var(--line-strong);
  transform: translateY(-2px);
}

/* ------------------------------------------------------------- information */
.card__body {
  grid-area: body;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.5rem;
  padding: clamp(1.25rem, 2.5vw, 2.25rem);
  min-width: 0;
  /* Lets the highlights below size themselves against this column rather than
     against the viewport, which says nothing about how wide the column is. */
  container: card-info / inline-size;
}

/* "01 — USC Games": the project number and the studio it was made at. */
.card__eyebrow {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.card__index { color: var(--accent-text); }
.card__eyebrow .card__org::before { content: '—'; margin-right: 0.5rem; }

.card__org { margin: 0; }

.card__flag {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-text);
}

.card__title {
  margin: 0;
  font-size: clamp(1.375rem, 2vw, 1.75rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  transition: color 0.18s ease;
}
.card--link:hover .card__title { color: var(--accent-text); }

.card__roles {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.5;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}

.card__summary {
  margin: 0;
  max-width: 54ch;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-soft);
}

.card__more {
  align-self: flex-start;
  margin-top: 0.375rem;
}
.card--static { cursor: default; }

/* Featured projects: the same layout and the same order, one size up. */
.card--feature .card__body {
  gap: 0.625rem;
  padding: clamp(1.5rem, 3vw, 2.75rem);
}
.card--feature .card__title { font-size: clamp(1.75rem, 3vw, 2.5rem); }
.card--feature .card__roles { font-size: 0.8125rem; }
.card--feature .card__summary { font-size: var(--fs-body); }

/* ----------------------------------------------------------------- artwork */
/*
   The artwork sits on a plate with a fixed 16:9 ratio, centred in the column.
   Keeping the ratio on the plate rather than on the column means a card that
   grows taller than its artwork — a long title, an extra highlight — gains
   quiet space either side of the plate instead of stretching the artwork's
   well into a tall empty box around it.

   The image is pinned to the plate's four edges and fitted inside, so it is
   never given a width of its own: it can never end up floating at its own
   small natural size, and it is never stretched out of shape.
*/
.card__media {
  grid-area: media;
  display: flex;
  align-items: center;
  min-width: 0;
  border-left: 1px solid var(--line);
}

.card__plate {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--paper-sunk);
}

/* Box art and portrait key art get a squarer plate rather than being left
   floating in the middle of a wide one. */
.card__media--upright .card__plate { aspect-ratio: 4 / 3; }

.card__plate img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  transition: transform 0.4s cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* Opt in per project (fit: 'cover' in the content file) when the artwork can
   safely fill the frame — when nothing important sits against its edges. */
.card__media--cover .card__plate img { object-fit: cover; }
.card--link:hover .card__plate img { transform: scale(1.03); }

.card__badge {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  background: var(--color-scrim);
  color: var(--on-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.3rem 0.55rem;
}

/* No artwork yet: one full-width text column with an accent rule. */
.card--text {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: 'body';
  border-left: 3px solid var(--accent);
}
.card--text .card__body { padding-block: clamp(1.5rem, 3vw, 2.25rem); }
.card--text .card__summary { max-width: 62ch; }

/*
   Tablet and below: two columns leave both the text and the artwork too
   narrow, so the card stacks — artwork on top, information underneath, both
   at full width.
*/
@media (max-width: 900px) {
  .card {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'media'
      'body';
  }
  .card__media {
    border-left: 0;
    border-bottom: 1px solid var(--line);
  }
  .card--feature .card__title { font-size: clamp(1.625rem, 4vw, 2.125rem); }
  .card--text { grid-template-areas: 'body'; }
}

/* -------------------------------------------------------- 10. project page */
.breadcrumb {
  padding-block: 1.5rem 0;
}
.breadcrumb a {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-decoration: none;
}
.breadcrumb a:hover { color: var(--accent-text); }

.project-head {
  padding-block: clamp(1.75rem, 4vw, 3rem) clamp(1.5rem, 3vw, 2.25rem);
}

.project-head__eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin-bottom: 1rem;
}

.project-head__title {
  font-size: var(--fs-title);
  font-weight: 800;
  letter-spacing: -0.035em;
  margin-bottom: 0.75rem;
}

.project-head__subtitle {
  max-width: 52ch;
  font-size: clamp(1.0625rem, 1.6vw, 1.25rem);
  color: var(--ink-soft);
  margin-bottom: 1.75rem;
}

.spec {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 1.25rem 2rem;
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--line);
  padding-block: 1.25rem;
  margin: 0;
}

.spec div { min-width: 0; }

.spec dt {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 0.35rem;
}

.spec dd {
  margin: 0;
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.45;
}

.project-cover {
  margin-block: clamp(1.75rem, 4vw, 2.75rem);
  background: var(--paper-sunk);
  border: 1px solid var(--line);
}
.project-cover img,
.project-cover video { width: 100%; height: auto; margin-inline: auto; }

.prose { max-width: var(--measure); }
.prose p { color: var(--ink-soft); }
.prose p:first-of-type { color: var(--ink); font-size: 1.1875rem; }

/* work blocks */
.block {
  padding-block: clamp(2.25rem, 5vw, 3.5rem);
  border-top: 1px solid var(--line);
}

.block__head {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  gap: 0 1rem;
  align-items: baseline;
  margin-bottom: 1.25rem;
}

.block__index {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--ink-faint);
}

.block__title {
  font-size: var(--fs-h3);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.block__subtitle {
  grid-column: 2;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--accent-text);
  margin-top: 0.35rem;
}

.block__body { max-width: var(--measure); }
.block__note {
  font-size: var(--fs-small);
  color: var(--ink-faint);
  font-style: italic;
}

.bullets { display: grid; gap: 0.625rem; }
.bullets li {
  position: relative;
  padding-left: 1.5rem;
  color: var(--ink-soft);
}
.bullets li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 0.5rem;
  height: 1px;
  background: var(--color-border-strong);
}

@media (min-width: 720px) {
  .block__body { margin-left: 4.5rem; }
  .block__media { margin-left: 4.5rem; }
}

/* media */
.media-grid {
  display: grid;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  margin-top: 1.75rem;
}
.media-grid--multi { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }

.media figure { margin: 0; }
.media img,
.media video {
  width: 100%;
  height: auto;
  background: var(--paper-sunk);
  border: 1px solid var(--line);
}
.media figcaption {
  margin-top: 0.625rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--ink-faint);
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
}

/* ------------------------------------------------ 10a. case-study blocks */
/*
   Three optional pieces a project block can carry, all of them content-driven
   and all of them drawn in CSS so there is no diagram image to keep in sync
   with the writing:

     diagram — a numbered chain of stages that closes back on itself
     parts   — lettered sub-sections inside one block
     frames  — one small card per design decision, with labelled rows

   They live in `.block__wide`, which gets the full column instead of the
   reading measure `.block__body` is held to.
*/

.block__head--plain { grid-template-columns: minmax(0, 1fr); }
.block__head--plain .block__subtitle { grid-column: 1; }

/* `mediaFirst` puts the artwork above the writing, so the text needs the
   space the media grid would otherwise have given it. */
.block__media + .block__body { margin-top: clamp(1.5rem, 3vw, 2.25rem); }

/* The caveat that closes a block, after its diagram, sub-sections or frames. */
.block__footnote {
  margin-top: clamp(1.25rem, 2.5vw, 1.75rem);
  max-width: var(--measure);
}

/* Blocks above the main write-up carry no index column, so nothing is
   indented to make room for one — see the 720px rule at the end of this
   group. Their top rule is what separates them from the overview. */

/* ------------------------------------------------------------ loop diagram */
.loop { margin-top: 1.75rem; }

.loop__steps {
  display: grid;
  gap: 2.75rem 0;
  list-style: none;
  margin: 0;
  padding: 0;
}

.loop__step {
  position: relative;
  padding: 1.25rem 1.25rem 1.375rem;
  background: var(--paper-card);
  border: 1px solid var(--line);
  border-top: 2px solid var(--accent);
}

/* The connector between two stages: down the page when stacked, across the
   gap once the chain runs horizontally. */
.loop__step::after {
  content: '\2193';
  position: absolute;
  left: 50%;
  bottom: -2.1rem;
  transform: translateX(-50%);
  font-size: 1.125rem;
  line-height: 1;
  color: var(--accent-text);
}
.loop__step:last-child::after { content: none; }

.loop__index {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--ink-faint);
  margin-bottom: 0.5rem;
}

.loop__title {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.loop__text {
  margin-top: 0.5rem;
  font-size: var(--fs-small);
  color: var(--ink-soft);
}

/* The bar that closes the loop back to the first stage. */
.loop__return {
  margin-top: 1.5rem;
  padding: 0.75rem 1rem;
  border: 1px dashed var(--line-strong);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  text-align: center;
}
.loop__return span::before {
  content: '\21BA';
  margin-right: 0.5rem;
  color: var(--accent-text);
}

.loop__note {
  margin-top: 1.25rem;
  max-width: var(--measure);
  font-size: var(--fs-small);
  color: var(--ink-soft);
}

/* The chain only turns horizontal once each stage still has room to read.
   Below this it stays stacked, with the arrows pointing down the page.
   `grid-auto-flow: column` keeps it on one line for any number of stages, so
   an arrow never ends up pointing at a wrapped row. */
@media (min-width: 1000px) {
  .loop__steps {
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 0 2.25rem;
  }
  .loop__step::after {
    content: '\2192';
    left: auto;
    right: -2.25rem;
    bottom: auto;
    top: 50%;
    width: 2.25rem;
    text-align: center;
    transform: translateY(-50%);
  }
}

/* -------------------------------------------------------- sub-sections */
.parts {
  display: grid;
  gap: clamp(1.75rem, 3vw, 2.5rem);
  margin-top: 1.75rem;
}

.part {
  border-top: 1px solid var(--line);
  padding-top: 1.25rem;
}

/* One step below `.block__title`, which is `--fs-h3`. */
.part__title {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -0.015em;
}

.part__mark {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--accent-text);
}

.part__body {
  display: grid;
  gap: 0.875rem;
  max-width: var(--measure);
  margin-top: 0.875rem;
}
.part__body p { color: var(--ink-soft); }

/* ---------------------------------------------------- reasoning frames */
.frames {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  margin-top: 1.75rem;
}

.frame {
  background: var(--paper-card);
  border: 1px solid var(--line);
  padding: 1.375rem 1.25rem;
}

.frame__title {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  padding-bottom: 0.875rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--line);
}

.frame__rows {
  display: grid;
  gap: 0.875rem;
  margin: 0;
}

.frame__rows dt {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-text);
}

.frame__rows dd {
  margin: 0.3rem 0 0;
  font-size: var(--fs-small);
  color: var(--ink-soft);
}

@media (min-width: 720px) {
  .block__wide { margin-left: 4.5rem; }
  .showcase .block__body,
  .showcase .block__media,
  .showcase .block__wide { margin-left: 0; }
}

/* --------------------------------------------------- project highlights */
/*
   Awards, ratings and milestones — the same component on a card and in the
   Results section of a project page, so the data lives in one place. Flat by
   design: a label, a small crimson marker per row, and nothing else. No badges,
   no boxes, no borders inside borders.
*/
.highlights {
  width: 100%;
  margin-top: 0.25rem;
}

.highlights__label {
  margin: 0 0 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.highlights__list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: clamp(1rem, 2vw, 1.75rem);
  row-gap: 0.4rem;
}

/*
   Two columns once the information column is genuinely wide enough for two
   readable ones — and one column below that, at any screen size. The query is
   against the column itself, so it stays right whether the card is side by
   side or stacked, and there is no breakpoint to keep in sync with the card.
*/
@container card-info (min-width: 30rem) {
  .highlights--compact .highlights__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* A project with one highlight gets a row, not half a row. */
  .highlights--compact .highlight:only-child { grid-column: 1 / -1; }
}

.highlight {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  min-width: 0;
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1.45;
  color: var(--color-text);
}

/* Small crimson marker, drawn in CSS so there is no icon font to load. */
.highlight::before {
  content: '';
  flex: none;
  width: 0.375rem;
  height: 0.375rem;
  background: var(--color-accent);
  transform: translateY(-0.1em);
}

/* An achievement reads as one phrase: never break a word across lines, and
   never strand a single word on a line of its own. */
.highlight__text {
  /* Takes the rest of the row rather than its own natural width, so it stays
     beside its marker instead of wrapping under it. */
  flex: 1 1 0;
  min-width: 0;
  overflow-wrap: normal;
  hyphens: none;
  text-wrap: balance;
}

.highlight a {
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.highlight a:hover { color: var(--color-accent-text); border-bottom-color: var(--color-accent); }

/* Detail page only: a quiet caption at the end of the row, against the rule. */
.highlight__cat {
  flex: none;
  padding-left: 1rem;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-text-faint);
}

/* Detail-page variant: one column, roomier rows, a rule between them. */
.highlights--page { margin-top: 0; }
.highlights--page .highlights__list {
  grid-template-columns: minmax(0, 1fr);
  row-gap: 0;
}
.highlights--page .highlight {
  padding-block: 0.875rem;
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-body);
  font-weight: 600;
}
.highlights--page .highlight:first-child { border-top: 1px solid var(--color-border); }

/* outcomes */
.outcomes li {
  display: flex;
  gap: 0.75rem;
  padding-block: 0.75rem;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-weight: 600;
}
.outcomes li::before {
  content: '★';
  color: var(--accent-text);
  font-size: 0.875rem;
  line-height: 1.7;
}

/* project pager */
.pager {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding-block: 2.5rem;
  border-top: 1px solid var(--line);
  margin-top: clamp(2.5rem, 5vw, 4rem);
}
.pager a {
  text-decoration: none;
  max-width: 20rem;
}
.pager .label { display: block; margin-bottom: 0.3rem; }
.pager strong {
  font-size: 1.125rem;
  letter-spacing: -0.02em;
}
.pager a:hover strong { color: var(--accent-text); }
.pager__next { text-align: right; margin-left: auto; }

/* --------------------------------------------------- 10b. video containers */
.video {
  position: relative;
  background: var(--ink-deep);
  border: 1px solid var(--line);
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

.video__frame,
.video__el {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.video__el { object-fit: contain; background: var(--ink-deep); }

/* Click-to-play poster */
.video__play {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  color: var(--on-dark);
}

.video__play img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s cubic-bezier(0.2, 0.7, 0.3, 1), opacity 0.2s ease;
}
.video__play:hover img { transform: scale(1.02); opacity: 0.9; }

.video__button {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 4.25rem;
  height: 4.25rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--color-on-accent);
  padding-left: 3px;
  box-shadow: 0 2px 16px rgba(0, 0, 0, 0.35);
  transition: background-color 0.18s ease, transform 0.18s ease;
}
.video__play:hover .video__button { background: var(--accent-deep); transform: translate(-50%, -50%) scale(1.06); }

.video__label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2.5rem 1.25rem 1rem;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: left;
  background: linear-gradient(to top, var(--color-scrim), transparent);
}

/* A local file inside a section keeps its own proportions. */
.video--file { aspect-ratio: auto; }
.video--file .video__el { height: auto; }

/* ------------------------------------------------------------- 11. about */
/* About Me: circular portrait beside name, role and biography. */
.bio {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
}

.bio__photo {
  width: clamp(7.5rem, 14vw, 11rem);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--paper-sunk);
  border: 1px solid var(--line);
}
.bio__photo img { width: 100%; height: 100%; object-fit: cover; }

.bio__name {
  font-size: clamp(1.75rem, 3.2vw, 2.5rem);
  font-weight: 800;
  letter-spacing: -0.03em;
}

.bio__role {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0.5rem 0 1rem;
}

.bio__intro {
  max-width: 62ch;
  font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
  color: var(--ink-soft);
  margin: 0;
}

@media (max-width: 640px) {
  .bio { grid-template-columns: 1fr; gap: 1.25rem; }
}

/* Education & Awards strip */
.credentials {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: clamp(2rem, 4vw, 2.75rem);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  border-top: 1px solid var(--line);
}

.credentials .label { display: block; margin-bottom: 0.875rem; }

.credentials__list { display: grid; gap: 0.75rem; }

.credentials__list li { font-size: var(--fs-small); line-height: 1.5; }
.credentials__list strong { display: block; font-size: 1rem; letter-spacing: -0.015em; }

.credentials__division,
.credentials__degree,
.credentials__period { display: block; color: var(--ink-soft); }
.credentials__period { font-family: var(--font-mono); font-size: 0.75rem; color: var(--ink-faint); }

.award {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr);
  gap: 0.625rem;
  align-items: start;
}
.award__icon { color: var(--accent); margin-top: 0.15rem; }
.award__text strong { display: inline; }
.award__standing { color: var(--ink); font-weight: 600; }
.award__standing::before { content: ' · '; color: var(--ink-faint); font-weight: 400; }
.award__project::before { content: ' · '; color: var(--ink-faint); }
.award__project a { color: var(--accent-text); text-decoration: none; border-bottom: 1px solid transparent; }
.award__project a:hover { border-bottom-color: currentColor; }

/* Text-led: a wide reading column beside a narrower list column. */
.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
@media (max-width: 860px) { .about-grid { grid-template-columns: 1fr; } }

.about-grid__lead p {
  font-size: clamp(1.125rem, 1.7vw, 1.3125rem);
  line-height: 1.6;
  color: var(--ink);
  max-width: 46ch;
}

.about-grid .label { display: block; margin-bottom: 1rem; }

.about-skills {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  border-top: 1px solid var(--line);
}
.about-skills .label { display: block; margin-bottom: 1rem; }

.def-list { display: grid; gap: 1rem; }
.def-list li {
  display: grid;
  grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
  gap: 0.25rem 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line);
}
.def-list strong { font-weight: 700; }
.def-list span { color: var(--ink-soft); font-size: var(--fs-small); }

/* Stacked label-over-detail, for the narrow column beside the bio. */
.def-list--tight li {
  grid-template-columns: 1fr;
  gap: 0.15rem;
  padding-bottom: 0.875rem;
}

/* Full-width CV rows. */
.def-list--wide { gap: 0; }
.def-list--wide li {
  grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  align-items: baseline;
  gap: 0.25rem 2.5rem;
  padding-block: 1.125rem;
  border-bottom: 1px solid var(--line);
}
.def-list--wide li:first-child { border-top: 1px solid var(--line); }
.def-list--wide strong { font-size: 1.125rem; letter-spacing: -0.02em; }
.def-list--wide span { font-size: var(--fs-body); }

@media (max-width: 560px) {
  .def-list li,
  .def-list--wide li { grid-template-columns: 1fr; }
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.chips li {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
}

/* One compact line of hobbies under the professional interests list. */
.about-personal {
  margin-top: clamp(1.5rem, 3vw, 2rem);
  padding-top: clamp(1rem, 2vw, 1.25rem);
  border-top: 1px solid var(--color-border);
}
.about-personal p {
  margin: 0;
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  line-height: 1.6;
}

/* ------------------------------------------------- 11b. publications */
.pubs__group {
  display: grid;
  grid-template-columns: minmax(0, 6rem) minmax(0, 1fr);
  gap: 0 clamp(1.5rem, 4vw, 3rem);
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--color-border);
}
.pubs__group:first-of-type { border-top: 0; padding-top: 0; }

.pubs__year {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  color: var(--color-text-faint);
  padding-top: 0.35rem;
}

.pubs__list { display: grid; gap: clamp(1.5rem, 3vw, 2rem); }

.pub__title {
  /* Long academic titles wrap freely — nothing here truncates them. */
  font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -0.015em;
  text-wrap: pretty;
  margin-bottom: 0.4rem;
}
.pub__title a {
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.pub__title a:hover {
  color: var(--color-accent-text);
  border-bottom-color: var(--color-accent);
}

.pub__authors,
.pub__venue {
  margin: 0;
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--color-text-muted);
}
.pub__venue { color: var(--color-text-faint); }

.pub__link {
  display: inline-block;
  margin-top: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--color-accent-text);
  border-bottom: 1px solid transparent;
}
.pub__link:hover { border-bottom-color: currentColor; }

@media (max-width: 640px) {
  /* Year becomes a heading above its papers instead of a side column. */
  .pubs__group { grid-template-columns: 1fr; gap: 0.875rem; }
  .pubs__year { padding-top: 0; }
}

/* ------------------------------------------------------------ 12. contact */
.contact {
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  color: var(--on-dark);
  padding-block: clamp(3.5rem, 8vw, 6rem);
  margin-top: var(--section-gap);
}
.contact .label { color: var(--on-dark-soft); }

.contact__title {
  font-size: clamp(2rem, 5vw, 3.25rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  margin-block: 1rem 1.5rem;
  max-width: 18ch;
}

.contact__email {
  display: inline-block;
  font-size: clamp(1.125rem, 2.6vw, 1.75rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--on-dark);
  text-decoration: none;
  border-bottom: 2px solid var(--accent);
  padding-bottom: 0.15rem;
}
.contact__email:hover { color: var(--accent-text); }

.contact__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
  margin-top: 2rem;
}
.contact__links .btn {
  border-color: var(--color-border-strong);
  color: var(--on-dark);
}
.contact__links .btn:hover {
  background: var(--on-dark);
  border-color: var(--on-dark);
  color: var(--ink-deep);
}

.site-footer {
  background: var(--ink-deep);
  color: var(--on-dark-soft);
  border-top: 1px solid var(--color-hairline);
  padding-block: 1.5rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
}
.site-footer .wrap {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.site-footer a { color: var(--on-dark-soft); }

/* ----------------------------------------------------------- 13. 404 page */
.error-page {
  padding-block: clamp(4rem, 12vw, 9rem);
  text-align: center;
}
.error-page h1 {
  font-size: var(--fs-display);
  font-weight: 800;
  margin-bottom: 1rem;
}
.error-page p { color: var(--ink-soft); margin-bottom: 2rem; }
.error-page .btn-row { justify-content: center; }
