/* ============================================================
   Vitrine — dark terminal aesthetic for a PL/systems researcher
   JetBrains Mono (mono/UI) + Space Grotesk (display)
   ============================================================ */

:root {
  /* base palette (dark) */
  --bg:        oklch(0.165 0.006 264);
  --bg-soft:   oklch(0.195 0.007 264);
  --surface:   oklch(0.225 0.008 264);
  --surface-2: oklch(0.255 0.009 264);
  --border:    oklch(0.305 0.012 264);
  --border-soft: oklch(0.265 0.010 264);
  --text:      oklch(0.935 0.008 250);
  --muted:     oklch(0.665 0.013 255);
  --faint:     oklch(0.505 0.013 258);

  /* accent — set by Tweaks, default terminal mint. derivatives via color-mix */
  --accent:     oklch(0.84 0.145 152);
  --accent-dim:  color-mix(in oklab, var(--accent) 16%, transparent);
  --accent-line: color-mix(in oklab, var(--accent) 36%, transparent);

  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --font-display: "Space Grotesk", var(--font-mono);

  --maxw: 1080px;
  --pad: clamp(20px, 5vw, 64px);
  --radius: 6px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; scroll-padding-top: 88px; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* subtle dot grid in the page background */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background-image: radial-gradient(oklch(0.5 0.01 264 / 0.10) 1px, transparent 1px);
  background-size: 26px 26px;
  pointer-events: none;
  z-index: 0;
}

/* optional scanline texture (toggle via Tweaks → .scanlines on body) */
body.scanlines::after {
  content: "";
  position: fixed;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    transparent 0 2px,
    oklch(0 0 0 / 0.045) 2px 3px
  );
  pointer-events: none;
  z-index: 9998;
  mix-blend-mode: multiply;
}

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

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

/* ---------- shared layout ---------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding-inline: var(--pad);
  position: relative;
  z-index: 1;
}

.eyebrow {
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--accent);
  text-transform: lowercase;
  display: flex;
  align-items: center;
  gap: 8px;
}
.eyebrow::before { content: "##"; color: var(--faint); }

.mono-dim { color: var(--faint); }
.accent { color: var(--accent); }

/* blinking cursor */
.cursor {
  display: inline-block;
  width: 0.12em;
  height: 0.82em;
  background: var(--accent);
  margin-left: 0.12em;
  translate: 0 0.06em;
  animation: blink 1.05s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .cursor { animation: none; }
}

/* ============================================================
   Top status bar
   ============================================================ */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: oklch(0.165 0.006 264 / 0.78);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-soft);
}
.topbar-inner {
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--muted);
  white-space: nowrap;
}
.dot { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px var(--accent-line); }
.brand b { color: var(--text); font-weight: 500; }

/* polyphonic logo — recolor inline svg to accent */
.brand-logo { display: inline-flex; align-items: center; line-height: 0; }
.brand-logo svg { height: 26px; width: auto; display: block; filter: drop-shadow(0 0 7px var(--accent-line)); }
.brand-logo svg path,
.brand-logo svg rect { fill: var(--accent) !important; }

.nav { display: flex; align-items: center; gap: 4px; }
.nav a {
  font-size: 13px;
  color: var(--muted);
  padding: 7px 12px;
  border-radius: var(--radius);
  transition: color .18s, background .18s;
  position: relative;
}
.nav a::before { content: ""; }
.nav a:hover { color: var(--text); background: var(--surface); }
.nav a.active { color: var(--accent); }
.nav a.active::before { content: "▸ "; color: var(--accent); }

/* ============================================================
   Hero
   ============================================================ */
.hero { padding-top: clamp(64px, 12vh, 140px); padding-bottom: clamp(56px, 10vh, 120px); position: relative; }
.hero > .reveal { position: relative; z-index: 1; }

/* ---- PCB board texture behind the hero (toggled via Tweaks) ---- */
/* board sits as a full-bleed texture behind the hero (toggled via Tweaks) */
.hero-bg {
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.hero-bg img {
  width: 100%; height: 100%;
  object-fit: contain;
  object-position: 50% 50%;
  display: block;
  transform: scale(1.2) translate(23%, 0%);
  transform-origin: 50% 50%;
  transition: transform 0.45s cubic-bezier(.22,.7,.2,1);
  will-change: transform;
  filter: brightness(var(--pcb-bright, 1.3));
}
.hero-bg::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, var(--bg) 40%, color-mix(in oklch, var(--bg) 52%, transparent) 62%, transparent 90%),
    linear-gradient(0deg, var(--bg) 1%, color-mix(in oklch, var(--bg) 38%, transparent) 26%, transparent 68%, var(--bg) 100%);
}
body.pcb-tinted .hero-bg { opacity: 0.92; }
body.pcb-grayscale .hero-bg { opacity: 0.82; }
body.pcb-grayscale .hero-bg img { filter: grayscale(1) brightness(calc(var(--pcb-bright, 1) * 1.02)); }
/* the board carries its own etched octopus — hide the big hero logo when it's shown */
body.pcb-tinted .hero-logo,
body.pcb-grayscale .hero-logo { display: none; }

@media (max-width: 900px) {
  .hero-bg img { object-position: 78% 46%; }
  body.pcb-tinted .hero-bg { opacity: 0.6; }
  body.pcb-grayscale .hero-bg { opacity: 0.52; }
}

/* ---- phone: discrete board strip at the top that gradient-fades out just under the name ---- */
@media (max-width: 640px) {
  .hero-bg {
    bottom: auto;
    height: 270px;            /* spans the top of the hero down to just under the name */
    width: 100vw;
    /* feather EVERY edge with a soft gradient mask — no hard borders */
    -webkit-mask-image:
      linear-gradient(180deg, transparent 0, #000 16%, #000 52%, transparent 100%),
      linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
    -webkit-mask-composite: source-in;
            mask-image:
      linear-gradient(180deg, transparent 0, #000 16%, #000 52%, transparent 100%),
      linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
            mask-composite: intersect;
  }
  .hero-bg img {
    object-fit: cover;
    object-position: 50% 38%;
    transform: scale(1.08) !important;   /* static on phones */
    transition: none;
  }
  .hero-bg::after { display: none; }     /* the mask handles the fade */
  body.pcb-tinted .hero-bg { opacity: 0.42; }   /* discrete */
  body.pcb-grayscale .hero-bg { opacity: 0.36; }
}
.hero-logo {
  position: absolute;
  z-index: 1;
  right: clamp(-20px, 3vw, 70px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 0;
  pointer-events: none;
  line-height: 0;
}
.hero-logo svg {
  height: clamp(220px, 32vw, 380px);
  width: auto;
  display: block;
  opacity: 1;
}
.hero-logo svg path,
.hero-logo svg rect { fill: oklch(0.225 0.008 264) !important; }

/* ---- living logo: only the 3 inner bars pulse like an equalizer.
   The animated variant is used ONLY in the launch splash; the inline
   header/hero logos are the exact, static original icon. ---- */

@media (prefers-reduced-motion: reduce) {
  .lp-bar animate { display: none; }
}

/* ---- launch splash: plays the equalizer logo once, then fades ---- */
.splash {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--bg);
  animation: splash-out 0.6s ease 1.9s forwards;
}
.splash svg {
  height: clamp(96px, 16vh, 150px);
  width: auto;
  display: block;
  filter: drop-shadow(0 0 16px var(--accent-line));
  animation: splash-pop 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
}
.splash svg path,
.splash svg rect { fill: var(--accent) !important; }
@keyframes splash-pop {
  from { opacity: 0; transform: scale(0.86); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes splash-out {
  to { opacity: 0; visibility: hidden; }
}
.splash.done { display: none; }
@media (prefers-reduced-motion: reduce) {
  .splash { animation-delay: 0.4s; }
  .splash svg { animation: none; }
}
@media (max-width: 900px) {
  .hero-logo { right: -10px; top: clamp(40px, 8vh, 90px); transform: none; }
  .hero-logo svg { height: clamp(180px, 46vw, 300px); }
}
.hero-prompt {
  font-size: 13px;
  color: var(--faint);
  margin-bottom: 22px;
}
.hero-prompt .accent { color: var(--accent); }
.hero h1 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(40px, 8vw, 84px);
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--text);
  margin-bottom: 18px;
}
.hero .tagline {
  font-size: clamp(15px, 2.1vw, 19px);
  color: var(--muted);
  max-width: 56ch;
  margin-bottom: 14px;
}
.hero .tagline .accent { color: var(--accent); }
.hero .bio {
  font-size: 15px;
  color: var(--faint);
  max-width: 62ch;
  line-height: 1.75;
  margin-bottom: 34px;
}
.hero .bio b { color: var(--muted); font-weight: 500; }

.links { display: flex; flex-wrap: wrap; gap: 10px; }
.lnk {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--muted);
  border: 1px solid var(--border);
  background: var(--bg-soft);
  padding: 9px 14px;
  border-radius: var(--radius);
  transition: all .18s;
}
.lnk .br { color: var(--faint); }
.lnk:hover {
  color: var(--text);
  border-color: var(--accent-line);
  background: var(--surface);
  transform: translateY(-1px);
}
.lnk:hover .br { color: var(--accent); }

/* ============================================================
   Section scaffolding
   ============================================================ */
section.block { padding-block: clamp(48px, 9vh, 96px); }
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px 16px;
  margin-bottom: 36px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border-soft);
}
.section-head h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(24px, 4vw, 34px);
  letter-spacing: -0.01em;
}
.section-head .count { font-size: 13px; color: var(--faint); white-space: nowrap; }

/* "under construction" beacon on the Projects title */
.section-head h2 .wip {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  color: oklch(0.82 0.12 55);
  border: 1px solid oklch(0.82 0.12 55 / 0.4);
  background: oklch(0.82 0.12 55 / 0.1);
  padding: 3px 9px 3px 8px;
  border-radius: 100px;
  vertical-align: middle;
  margin-left: 12px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: help;
}
.section-head h2 .wip::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: oklch(0.82 0.12 55);
  box-shadow: 0 0 0 0 oklch(0.82 0.12 55 / 0.6);
  animation: wipPulse 1.8s ease-out infinite;
}
@keyframes wipPulse {
  0%   { box-shadow: 0 0 0 0 oklch(0.82 0.12 55 / 0.55); }
  70%  { box-shadow: 0 0 0 7px oklch(0.82 0.12 55 / 0); }
  100% { box-shadow: 0 0 0 0 oklch(0.82 0.12 55 / 0); }
}
@media (prefers-reduced-motion: reduce) { .section-head h2 .wip::before { animation: none; } }

/* projects legend */
.proj-legend { display: flex; gap: 16px; font-size: 12px; color: var(--faint); white-space: nowrap; }
.proj-legend .lg-item { display: inline-flex; align-items: center; gap: 7px; }
.proj-legend .dot { width: 8px; height: 8px; box-shadow: none; }
.proj-legend .dot.research { background: var(--accent); }
.proj-legend .dot.personal { background: oklch(0.82 0.12 55); }


/* ============================================================
   Publications — master / detail
   ============================================================ */
.pub-layout {
  display: grid;
  grid-template-columns: 1fr 0.82fr;
  gap: 40px;
  align-items: start;
}

.filters { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 22px; }
.chip {
  font-size: 12px;
  color: var(--muted);
  border: 1px solid var(--border-soft);
  background: transparent;
  padding: 5px 11px;
  border-radius: 100px;
  cursor: pointer;
  white-space: nowrap;
  font-family: var(--font-mono);
  transition: all .16s;
}
.chip:hover { color: var(--text); border-color: var(--border); }
.chip.on { color: var(--bg); background: var(--accent); border-color: var(--accent); }

.year-group { margin-bottom: 26px; }
.year-label {
  font-size: 12px;
  color: var(--faint);
  letter-spacing: 0.1em;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.year-label::after { content: ""; flex: 1; height: 1px; background: var(--border-soft); }

.pub {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 1px solid transparent;
  border-left: 2px solid var(--border-soft);
  padding: 14px 16px;
  border-radius: 0 var(--radius) var(--radius) 0;
  cursor: pointer;
  font-family: var(--font-mono);
  color: var(--text);
  transition: background .16s, border-color .16s, transform .16s;
}
.pub + .pub { margin-top: 4px; }
.pub:hover, .pub.sel {
  background: var(--bg-soft);
  border-left-color: var(--accent);
}
.pub.sel { background: var(--surface); }
.pub .pub-title {
  font-size: 15px;
  line-height: 1.4;
  color: var(--text);
  margin-bottom: 6px;
}
.pub:hover .pub-title, .pub.sel .pub-title { color: var(--accent); }
.pub .pub-meta { font-size: 12.5px; color: var(--muted); }
.pub .pub-meta .venue { color: var(--text); }
.pub .pub-meta .ptype { color: var(--faint); }

/* foot row with small link buttons */
.pub-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 10px;
}
.pub-link {
  font-size: 12px;
  color: var(--accent);
  border: 1px solid var(--accent-line);
  background: var(--accent-dim);
  padding: 3px 9px;
  border-radius: 4px;
  cursor: pointer;
  transition: background .15s, color .15s;
  font-family: var(--font-mono);
  white-space: nowrap;
}
.pub-link:hover { background: var(--accent); color: var(--bg); }
.pub-foot-hint {
  margin-left: auto;
  font-size: 11px;
  color: var(--faint);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity .16s, transform .16s;
}
.pub:hover .pub-foot-hint, .pub.sel .pub-foot-hint { opacity: 1; transform: none; }

/* generated cover card — preview for papers without a poster/thumb */
.figph.cover {
  aspect-ratio: 4 / 3;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 0;
  padding: 22px 22px 18px;
  background:
    linear-gradient(135deg, var(--surface), var(--bg-soft));
  border: 1px solid var(--border-soft);
}
.figph.cover::before { content: none; }
.figph.cover .cover-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 12px;
}
.figph.cover .cover-venue { color: var(--accent); letter-spacing: 0.04em; }
.figph.cover .cover-year { color: var(--faint); }
.figph.cover .cover-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
  line-height: 1.28;
  color: var(--text);
  margin-top: 14px;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-wrap: balance;
}
.figph.cover .cover-auth {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 8px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.figph.cover .cover-rule {
  height: 1px;
  background: var(--border-soft);
  margin: auto 0 10px;
}
.figph.cover .cover-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 10.5px;
  color: var(--faint);
}
.figph.cover .cover-tags span { color: var(--faint); }
.figph.cover .cover-go {
  margin-left: auto;
  color: var(--accent);
  opacity: 0;
  transition: opacity .16s;
}
a.figph.cover { cursor: pointer; text-decoration: none; }
a.figph.cover:hover { border-color: var(--accent-line); }
a.figph.cover:hover .cover-go { opacity: 1; }
a.figph.cover:hover .cover-title { color: var(--accent); }

/* paper title link in preview */
.preview h3 .pv-titlelink {
  color: inherit;
  text-decoration: none;
  transition: color .16s;
}
.preview h3 .pv-titlelink:hover { color: var(--accent); }
.preview h3 .pv-titlego { color: var(--faint); font-weight: 400; }
.preview h3 .pv-titlelink:hover .pv-titlego { color: var(--accent); }

/* poster thumbnail in preview */
.figph.has-poster {
  display: block;
  aspect-ratio: 4 / 3;
  padding: 0;
  background: #fff;
  cursor: zoom-in;
}
.figph.has-poster::before { content: none; }
.figph.has-poster img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
  transition: transform .35s cubic-bezier(.2,.7,.2,1);
}
.figph.has-poster:hover img { transform: scale(1.03); }
.figph.has-poster .figcap {
  position: absolute;
  left: 10px;
  bottom: 10px;
  z-index: 2;
  max-width: none;
  overflow: visible;
  background: oklch(0.165 0.006 264 / 0.82);
  color: var(--accent);
  backdrop-filter: blur(2px);
}
.pub .pub-authors { font-size: 12.5px; color: var(--faint); margin-top: 3px; }
.pub .pub-authors .me { color: var(--muted); border-bottom: 1px solid var(--accent-line); }

/* detail / preview pane */
.preview {
  position: sticky;
  top: 88px;
  border: 1px solid var(--border);
  background: linear-gradient(180deg, var(--bg-soft), var(--bg));
  border-radius: var(--radius);
  overflow: hidden;
  min-height: 360px;
}
.preview-bar {
  height: 34px;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 13px;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface);
}
.preview-bar i { width: 9px; height: 9px; border-radius: 50%; background: var(--border); display: inline-block; }
.preview-bar i:first-child { background: var(--faint); }
.preview-bar span { margin-left: auto; font-size: 11px; color: var(--faint); }

.preview-body { padding: 20px; }

/* figure placeholder */
.figph {
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  border: 1px solid var(--border-soft);
  background:
    repeating-linear-gradient(45deg,
      oklch(0.275 0.010 264) 0 9px,
      oklch(0.215 0.008 264) 9px 18px);
  display: flex;
  align-items: flex-end;
  padding: 10px;
  margin-bottom: 16px;
  position: relative;
  overflow: hidden;
}
.figph::before {
  content: "▦";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 30px;
  color: oklch(0.5 0.012 264);
}
.figph .figcap {
  font-size: 11px;
  color: var(--muted);
  background: oklch(0.165 0.006 264 / 0.9);
  padding: 3px 8px;
  border-radius: 4px;
  position: relative;
  z-index: 1;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.preview h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 18px;
  line-height: 1.3;
  margin-bottom: 8px;
}
.preview .pv-meta { font-size: 12.5px; color: var(--muted); margin-bottom: 14px; }
.preview .pv-meta .venue { color: var(--accent); }
.preview .abstract { font-size: 13.5px; color: var(--muted); line-height: 1.7; margin-bottom: 16px; }
.preview .abstract.todo {
  color: var(--accent);
  font-style: italic;
  border: 1px dashed var(--accent-line);
  background: var(--accent-dim);
  padding: 10px 12px;
  border-radius: var(--radius);
}
.preview .pv-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.pv-tag { font-size: 11px; color: var(--faint); border: 1px solid var(--border-soft); padding: 3px 8px; border-radius: 100px; }

.pv-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.btn {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--muted);
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 7px 12px;
  border-radius: var(--radius);
  cursor: pointer;
  transition: all .16s;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn:hover { color: var(--text); border-color: var(--accent-line); }
.btn.primary { color: var(--bg); background: var(--accent); border-color: var(--accent); font-weight: 500; }
.btn.primary:hover { filter: brightness(1.08); }

.preview-empty {
  display: grid;
  place-items: center;
  text-align: center;
  height: 100%;
  min-height: 320px;
  padding: 30px;
  color: var(--faint);
  font-size: 13px;
}
.preview-empty .blk { color: var(--accent); }

/* ============================================================
   Projects
   ============================================================ */
.proj-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}
.card {
  border: 1px solid var(--border);
  background: var(--bg-soft);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color .2s, transform .2s, background .2s;
}
.card:hover { border-color: var(--accent-line); transform: translateY(-3px); background: var(--surface); }
.card .figph { aspect-ratio: 2 / 1; margin: 0; border-radius: 0; border: none; border-bottom: 1px solid var(--border-soft); }
.card .figph.has-photo::before { content: none; }
.card .figph.has-photo { padding: 0; }
.card .figph.has-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .35s cubic-bezier(.2,.7,.2,1);
}
.card:hover .figph.has-photo img { transform: scale(1.03); }
.card .figph.fit-contain { background: #fff; }
.card .figph.fit-contain img { object-fit: contain; }
.card:hover .figph.fit-contain img { transform: none; }

/* clickable project image */
a.figph { cursor: pointer; display: block; position: relative; }
a.figph::after {
  content: "open ↗";
  position: absolute;
  right: 10px; bottom: 10px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text);
  background: oklch(0.165 0.006 264 / 0.82);
  border: 1px solid var(--border-soft);
  padding: 3px 8px;
  border-radius: 5px;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .18s, transform .18s;
  pointer-events: none;
}
.card:hover a.figph::after { opacity: 1; transform: translateY(0); }

/* research / personal beacon on the image */
.proj-kind {
  position: absolute;
  top: 10px; left: 10px;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  padding: 4px 9px 4px 8px;
  border-radius: 100px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  backdrop-filter: blur(3px);
  background: oklch(0.165 0.006 264 / 0.7);
  border: 1px solid var(--border);
}
.proj-kind::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
}
.proj-kind.research { color: var(--accent); border-color: var(--accent-line); }
.proj-kind.research::before { background: var(--accent); box-shadow: 0 0 7px var(--accent); }
.proj-kind.personal { color: oklch(0.82 0.12 55); border-color: oklch(0.82 0.12 55 / 0.4); }
.proj-kind.personal::before { background: oklch(0.82 0.12 55); box-shadow: 0 0 7px oklch(0.82 0.12 55); }

.card-body { padding: 18px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.card h3 { font-family: var(--font-display); font-weight: 600; font-size: 18px; }
.status {
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 100px;
  border: 1px solid var(--border);
  color: var(--muted);
}
.status.active { color: var(--accent); border-color: var(--accent-line); }
.card p { font-size: 13.5px; color: var(--muted); line-height: 1.65; flex: 1; }
.tags { display: flex; flex-wrap: wrap; gap: 6px; }
.tag { font-size: 11px; color: var(--faint); }
.tag::before { content: "#"; color: var(--accent); opacity: .7; }
.card-links { display: flex; gap: 14px; padding-top: 6px; border-top: 1px solid var(--border-soft); }
.card-links a { font-size: 12.5px; color: var(--muted); transition: color .16s; }
.card-links a:hover { color: var(--accent); }
.card-links a::before { content: "→ "; color: var(--faint); }

/* ============================================================
   Footer
   ============================================================ */
footer.foot {
  border-top: 1px solid var(--border-soft);
  padding-block: 40px;
  margin-top: 40px;
}
.foot-inner { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 14px; font-size: 12.5px; color: var(--faint); }
.foot-inner a:hover { color: var(--accent); }

/* toast */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  translate: -50% 0;
  background: var(--accent);
  color: var(--bg);
  font-size: 13px;
  font-weight: 500;
  padding: 9px 18px;
  border-radius: var(--radius);
  z-index: 9999;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .2s, transform .2s;
  pointer-events: none;
}
.toast.show { opacity: 1; transform: none; }

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 860px) {
  .pub-layout { grid-template-columns: 1fr; }
  .preview { position: static; }
  .proj-grid { grid-template-columns: 1fr; }
  .nav a:not(.cv) { display: none; }
  .pub-foot-hint { display: none; }
}

/* ============================================================
   Mobile bottom sheet (preview on tap)
   ============================================================ */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 200;
  visibility: hidden;
  pointer-events: none;
}
.sheet.open { visibility: visible; pointer-events: auto; }
.sheet::before {
  content: "";
  position: absolute;
  inset: 0;
  background: oklch(0 0 0 / 0.6);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity .25s;
}
.sheet.open::before { opacity: 1; }
.sheet-panel {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 90vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--bg);
  border-top: 1px solid var(--border);
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -20px 50px oklch(0 0 0 / 0.5);
  transform: translateY(100%);
  transition: transform .3s cubic-bezier(.2,.8,.2,1);
  padding-bottom: env(safe-area-inset-bottom, 8px);
}
.sheet.open .sheet-panel { transform: none; }
.sheet-grip {
  width: 40px;
  height: 4px;
  border-radius: 100px;
  background: var(--border);
  margin: 10px auto 4px;
}
.sheet-close {
  position: sticky;
  top: 0;
  z-index: 2;
  display: block;
  margin: 0 0 0 auto;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--muted);
  background: var(--bg);
  border: none;
  padding: 8px 16px;
  cursor: pointer;
}
.sheet-close:hover { color: var(--accent); }
.sheet .preview {
  border: none;
  border-radius: 0;
  background: transparent;
  min-height: 0;
}
.sheet .preview-bar { background: var(--surface); }
@media (prefers-reduced-motion: reduce) {
  .sheet-panel { transition: none; }
  .sheet::before { transition: none; }
}
