/* ============================================================
   Eduard — Portfolio
   Shared styles. Dark, mono, dotted halftone.
   ============================================================ */

/* ── PP Telegraf (display) — self-hosted ───────────────────── */
@font-face {
  font-family: "PP Telegraf";
  src: url("uploads/PPTelegraf-Ultralight.otf") format("opentype");
  font-weight: 200;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "PP Telegraf";
  src: url("uploads/PPTelegraf-UltralightOblique.otf") format("opentype");
  font-weight: 200;
  font-style: italic;
  font-display: block;
}
@font-face {
  font-family: "PP Telegraf";
  src: url("uploads/PPTelegraf-Regular.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "PP Telegraf";
  src: url("uploads/PPTelegraf-RegularOblique.otf") format("opentype");
  font-weight: 400;
  font-style: italic;
  font-display: block;
}
@font-face {
  font-family: "PP Telegraf";
  src: url("uploads/PPTelegraf-Ultrabold.otf") format("opentype");
  font-weight: 800;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "PP Telegraf";
  src: url("uploads/PPTelegraf-UltraboldOblique.otf") format("opentype");
  font-weight: 800;
  font-style: italic;
  font-display: block;
}
/* "Slanted" cuts also available if wanted — exposed as a separate family */
@font-face {
  font-family: "PP Telegraf Slanted";
  src: url("uploads/PPTelegraf-RegularSlanted.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "PP Telegraf Slanted";
  src: url("uploads/PPTelegraf-UltralightSlanted.otf") format("opentype");
  font-weight: 200;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "PP Telegraf Slanted";
  src: url("uploads/PPTelegraf-UltraboldSlanted.otf") format("opentype");
  font-weight: 800;
  font-style: normal;
  font-display: block;
}

:root {
  /* ── ashcamp.co · monochrome dark tokens ───────────────────── */
  --bg: #171715;            /* background */
  --bg-soft: #272725;       /* card / raised surface */
  --fg: #f5f5f4;            /* foreground */
  --fg-dim: #9c9c9b;        /* muted-foreground — secondary copy */
  --fg-faint: rgba(245, 245, 244, 0.30);
  --border: #434342;
  /* Red is reserved for the live / active status indicator only. */
  --accent: #ef4444;        /* destructive / status */
  --pill: rgba(245, 245, 244, 0.92);
  --pill-fg: #171715;

  /* type system */
  --font-mono: "JetBrains Mono", "Fragment Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-display: "PP Telegraf", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --radius: 8px;

  --grid-gutter: 32px;
  --grid-pad: 32px;

  /* mouse */
  --mx: 50vw;
  --my: 50vh;

  /* dotted halftone */
  --dot-size: 1.4px;
  --dot-step: 16px;
  --dot-color: rgba(245, 245, 244, 0.05);
  --dot-color-bright: rgba(245, 245, 244, 0.40);
  --dot-drift-dur: 28s;
  --reveal-radius: 220px;
}

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

html {
  scroll-behavior: smooth;
}

html, body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
  letter-spacing: 0.01em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body {
  min-height: 100vh;
  overflow-x: hidden;
}

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

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

/* (legacy CSS halftone + waves removed — now a WebGL canvas, see hero-grid.js) */

/* dashed frame — paired visually with the halftone bounds */
.frame {
  position: fixed;
  top: 16px;
  bottom: 16px;
  left: 30px;
  right: 30px;
  pointer-events: none;
  z-index: 45;
  /* top + sides stay fixed as the viewport chrome; the bottom edge is a
     separate scrollable element so it travels with the hero / between projects */
  border-top: 1px dashed var(--border);
  border-left: 1px dashed var(--border);
  border-right: 1px dashed var(--border);
}

/* internal vertical divider — splits the page into a narrow left column
   (for the nav links) and a wide right column for the main content.
   Sits just past the "Info" link so the whole nav lives inside the left column. */
.frame::before {
  content: "";
  position: absolute;
  top: -1px;
  /* height is capped by JS (startExpDivider) so the divider stops at the end
     of the Experience section instead of running through the CTA */
  height: var(--vline-h, 100vh);
  left: 360px;
  border-left: 1px dashed var(--border);
}

/* Scrollable bottom edges — one per 100vh "page". Sit inside the side margins
   of the fixed frame so they look like the bottom of each frame, but scroll
   away with their respective page. */
.frame-bottom {
  position: absolute;
  left: 30px;
  right: 30px;
  height: 0;
  border-top: 1px dashed var(--border);
  pointer-events: none;
  z-index: 44;
}

/* ============================================================
   Page chrome — nav + footer
   ============================================================ */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  padding: 36px 58px 22px 58px;
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 24px;
  font-size: 12px;
  letter-spacing: 0.08em;
}

.nav-left {
  display: flex;
  align-items: center;
  gap: 36px;
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--fg);
  padding: 4px 0;
  transition: opacity 0.2s ease;
}
.brand-mark:hover { opacity: 0.7; }

.brand-glyph .accent-dot {
  color: var(--accent);
  margin: 0 1px;
}

/* Image-based brand mark */
.brand-mark img {
  display: block;
  height: 18px;
  width: auto;
  filter: brightness(0) invert(1); /* force pure white from black source */
}
.brand-mark:hover img { opacity: 0.7; }

.nav-links {
  display: flex;
  gap: 28px;
}

.nav-link {
  position: relative;
  text-transform: uppercase;
  color: var(--fg);
  padding: 4px 0;
  transition: color 0.2s ease;
}

.nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--fg);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s cubic-bezier(0.65, 0, 0.35, 1);
}

.nav-link:hover { color: var(--fg); }
.nav-link:hover::after { transform: scaleX(1); }

.nav-clock {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-self: center;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}

.rec-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: rec-pulse 1.4s ease-in-out infinite;
}

@keyframes rec-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.85); }
}

.nav-cta {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.pill {
  background: var(--pill);
  color: var(--pill-fg);
  border-radius: 999px;
  padding: 10px 18px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: 0.12em;
  border: 1px solid transparent;
  transition: background 0.25s ease, transform 0.25s ease;
}

.pill:hover {
  background: var(--fg);
  transform: translateY(-1px);
}

.pill-icon {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--pill);
  color: var(--pill-fg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(0, 0, 0, 0.08);
  transition: background 0.25s ease, transform 0.25s ease;
}

.pill-icon:hover {
  background: var(--fg);
  transform: translateX(2px);
}

.nav-cta-group {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* footer pinned info */
.foot {
  position: absolute;
  top: calc(100vh - 76px);
  left: 0;
  right: 0;
  z-index: 40;
  padding: 22px 58px 36px 58px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-dim);
  pointer-events: none;
}

.foot-mid { justify-self: center; }
.foot-end { justify-self: end; }
.foot span { pointer-events: auto; }

/* ============================================================
   Main / page transition
   ============================================================ */

main {
  position: relative;
  z-index: 5;
  min-height: 100vh;
}

/* Fade applied to <main> so <body> stays transform-free.
   (A transform on body would break position:fixed for footer/marquee.) */
main.page-fade {
  animation: page-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes page-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* hidden hero variants must actually hide — .hero { display:flex } would otherwise win over UA [hidden]. */
.hero[hidden] { display: none !important; }

body.page-out, main.page-out {
  animation: page-out 0.4s ease both !important;
}

@keyframes page-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* ============================================================
   Hero variants
   ============================================================ */

.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Variant A — Ashcamp style: centered tagline over halftone face */
.hero-a {
  flex-direction: column;
  gap: 24px;
  justify-content: center;       /* vertical middle of the viewport/frame */
  align-items: flex-start;       /* hug the left divider */
  padding-left: 442px;           /* sit just past the vertical divider */
  padding-right: 30px;
}

/* Interactive shader wallpaper — fills the whole grid of the first screen:
   diagonal from the top-left corner (Index) to the bottom-right corner
   (Est. 2020). Bounded by the four frame borders; never bleeds past them. */
.hero-shader {
  position: absolute;
  top: 16px;                     /* top frame border */
  left: 30px;                    /* left frame border */
  right: 30px;                   /* right frame border */
  bottom: 16px;                  /* first bottom dashed line (100vh - 16) */
  z-index: 0;
  overflow: hidden;              /* never bleed past the grid lines */
}

.hero-shader > div,
.hero-shader [data-us-project],
.hero-shader [data-us-holder] {
  width: 100% !important;
  height: 100% !important;
}

/* the WebGL canvas must cover the entire grid, no letterboxing */
.hero-shader canvas {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  object-fit: cover !important;
}

/* remove the Unicorn Studio watermark/badge */
.hero-shader a[href*="unicorn"],
.hero-shader [class*="unicorn"],
.hero-shader [class*="watermark"],
.hero-shader [class*="badge"],
.hero-shader img[src*="unicorn"] {
  display: none !important;
  opacity: 0 !important;
  pointer-events: none !important;
}

.hero-a .portrait {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  opacity: 0.5;
  filter: grayscale(1) contrast(1.1);
}

.hero-a .tagline {
  position: relative;
  z-index: 2;
  font-size: 13px;
  line-height: 1.7;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-dim);
  max-width: 520px;
}

.hero-a .tagline .name {
  color: var(--fg);
  font-weight: 500;
}

/* Variant B — Big name takeover */
.hero-b {
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  padding: 0 48px 120px;
  gap: 28px;
}

.hero-b .bigname {
  font-family: var(--font-display);
  font-size: clamp(80px, 16vw, 240px);
  line-height: 0.86;
  letter-spacing: -0.04em;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--fg);
}

.hero-b .bigname .accent {
  color: var(--fg-dim);
}

.hero-b .meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 48px;
  width: 100%;
  max-width: 1000px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--fg-dim);
}

.hero-b .meta-label {
  color: var(--fg-faint);
  display: block;
  margin-bottom: 6px;
  font-size: 10px;
}

.hero-b .meta-val {
  color: var(--fg);
}

/* Variant C — Split: portrait left, copy right */
.hero-c {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  padding: 0 48px;
  align-items: center;
  min-height: 100vh;
}

.hero-c .portrait-card {
  position: relative;
  aspect-ratio: 4/5;
  max-height: 70vh;
  border: 1px dashed var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.hero-c .portrait-card .corner {
  position: absolute;
  width: 18px;
  height: 18px;
}
.hero-c .portrait-card .corner.tl { top: -1px; left: -1px; border-top: 1px solid var(--fg); border-left: 1px solid var(--fg); }
.hero-c .portrait-card .corner.tr { top: -1px; right: -1px; border-top: 1px solid var(--fg); border-right: 1px solid var(--fg); }
.hero-c .portrait-card .corner.bl { bottom: -1px; left: -1px; border-bottom: 1px solid var(--fg); border-left: 1px solid var(--fg); }
.hero-c .portrait-card .corner.br { bottom: -1px; right: -1px; border-bottom: 1px solid var(--fg); border-right: 1px solid var(--fg); }

.hero-c .copy h1 {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.4vw, 48px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 500;
  margin-bottom: 24px;
  text-wrap: pretty;
}

.hero-c .copy h1 .dim {
  color: var(--fg-dim);
}

.hero-c .copy .lede {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-dim);
  max-width: 420px;
  line-height: 1.7;
}

.hero-c .copy .stat-row {
  display: flex;
  gap: 40px;
  margin-top: 40px;
  border-top: 1px dashed var(--border);
  padding-top: 24px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.hero-c .copy .stat strong {
  display: block;
  font-size: 24px;
  letter-spacing: -0.02em;
  font-weight: 500;
  text-transform: none;
  margin-bottom: 4px;
}

.hero-c .copy .stat span {
  color: var(--fg-faint);
}

/* variant switcher */
.variant-switcher {
  position: fixed;
  bottom: 70px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  gap: 4px;
  background: rgba(20, 20, 20, 0.85);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.variant-switcher button {
  background: transparent;
  border: 0;
  color: var(--fg-dim);
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  transition: background 0.2s ease, color 0.2s ease;
}

.variant-switcher button.active {
  background: var(--fg);
  color: var(--bg);
}

.variant-switcher button:not(.active):hover {
  color: var(--fg);
}

/* ============================================================
   Marquee ticker
   ============================================================ */

.marquee {
  position: relative;
  z-index: 5;
  overflow: hidden;
  border-top: 1px dashed var(--border);
  border-bottom: 1px dashed var(--border);
  padding: 18px 0;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

.marquee-track {
  display: inline-flex;
  gap: 48px;
  white-space: nowrap;
  animation: marquee 40s linear infinite;
}

.marquee-track span {
  display: inline-flex;
  align-items: center;
  gap: 48px;
}

.marquee-track .star {
  color: var(--fg-faint);
}

@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* ============================================================
   Work grid (work.html)
   ============================================================ */

.work-wrap {
  padding: 0;
  position: relative;
  z-index: 5;
}
/* The hero's min-height (100vh) leaves 16px of empty space below its frame
   bottom line; pull the first project up by that much so its first image sits
   the same 32px below the top dashed line as every other project's does. */
.grid-projects #work .project:first-child { margin-top: -16px; }

.work-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  padding-bottom: 80px;
  border-bottom: 1px dashed var(--border);
  margin-bottom: 80px;
}

.work-head .eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--fg-dim);
}

.work-head h1 {
  font-family: var(--font-display);
  font-size: clamp(40px, 6vw, 96px);
  font-weight: 500;
  line-height: 0.92;
  letter-spacing: -0.03em;
  margin-top: 12px;
  text-transform: uppercase;
}

.work-head .count {
  font-size: 11px;
  color: var(--fg-faint);
  letter-spacing: 0.1em;
}

.project {
  /* Each project is its own framed viewport. The fixed chrome (frame border,
     foot text) stays put while content swaps inside. Image is inset 68px from
     the divider on the left, 68px from the frame on top and right. Project
     title/description top sits 8px below the image top. */
  min-height: 100vh;
  position: relative;
  padding: 0;
}

/* Project grid — toggleable dashed line that separates one project from the
   next. It sits 48px below the project's last image (matching the 48px stack
   inset above the images AND the 48px left/right inset from the grid lines, so
   vertical and horizontal spacing agree). The vertical grid lines already come
   from the global frame. */
.project-divider {
  display: none;
}
.grid-projects .project-divider {
  display: block;
  margin: 48px 30px 0;
  border-top: 1px dashed var(--border);
}

/* Sticky project info — native position:sticky (compositor-driven, no JS pin,
   no scroll jitter). The article is a 2-col grid: info column 438px, images
   right. padding-top replaces the old collapsed stack margin (48px rhythm). */
.project--cms {
  display: grid;
  grid-template-columns: 438px minmax(0, 1fr);
  align-items: start;
  align-content: start;
  padding-top: 48px;
}
.project--cms .project-info-col { grid-column: 1; grid-row: 1; align-self: stretch; }
.project--cms .project-info { position: sticky; top: 80px; }
.project--cms .project-stack { grid-column: 2; grid-row: 1; margin: 0 78px 0 0; }
.project--cms .project-divider { grid-column: 1 / -1; grid-row: 2; }

.project-info {
  position: absolute;
  top: 92px;        /* 16px frame-margin + 68px inset + 8px offset = 92 */
  left: 0;
  width: 360px;
  padding-left: 58px;
  padding-right: 30px;
}

/* ── First-in-view reveal — title, description, then pill fade up in sequence.
   Matches the recorded entrance: ~0.7s ease-out opacity + ~18px rise + a soft
   blur that resolves to crisp, with the pill trailing the copy by ~0.26s.
   Gated on motion preference so print / reduced-motion show final state. */
@media (prefers-reduced-motion: no-preference) {
  .project-info > h2,
  .project-info > p,
  .project-info > .catalogue-link,
  .project-info > .tag,
  .project-info > .tag-row {
    opacity: 0;
    transform: translateY(18px);
    filter: blur(6px);
    transition:
      opacity 0.7s cubic-bezier(0.22, 0.61, 0.36, 1),
      transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1),
      filter 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: opacity, transform, filter;
  }
  .project-info.reveal > h2 { transition-delay: 0s; }
  .project-info.reveal > p { transition-delay: 0.12s; }
  .project-info.reveal > .tag,
  .project-info.reveal > .tag-row { transition-delay: 0.26s; }
  .project-info.reveal > .catalogue-link { transition-delay: 0.1s; }
  .project-info.reveal > h2,
  .project-info.reveal > p,
  .project-info.reveal > .catalogue-link,
  .project-info.reveal > .tag,
  .project-info.reveal > .tag-row {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

.project-media {
  /* image inset 68px from divider (360px) on left, 68px from frame on top and right. */
  margin: 84px 98px 0 442px;
}

/* ── CMS-rendered project block (benchmark = GWM) ──────────────────────────
   Generated from the PROJECTS config in projects.js. The left info column
   (title / subtitle / pill) stays absolutely positioned + sticky; the media
   stack on the right is packed from the configured image ratios: a 3:2 fills
   its own row, 3:4 images pair two-per-row, a lone 3:4 takes half width. */
.project--cms .project-info {
  /* ─────────────── Tune the text + pill block here ───────────────
     Every value below is safe to change and applies to all projects.
     Children stack in a flex column; each --gap-* var sets the space
     above one element, so the junctions can differ. */
  --info-width: 342px;     /* text column ends before the 360px vertical line */
  --info-pad-top: 0px;     /* title top aligns with the image top  */
  --info-pad-left: 60px;   /* indent from the left grid line      */
  --info-pad-right: 24px;  /* gutter on the right of the column   */
  --desc-width: 294px;     /* description wrap width              */
  --gap-headline: 8px;     /* headline → catalogue link           */
  --gap-link: 16px;        /* catalogue link → description        */
  --gap-desc: 22px;        /* description → pill                  */

  display: flex;
  flex-direction: column;
  align-items: flex-start;

  width: var(--info-width);
  height: auto;
  padding: var(--info-pad-top) var(--info-pad-right) 0 var(--info-pad-left);
  line-height: 1.55;
}
.project--cms .project-info h2 {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1;
  margin: 0;
}
.project--cms .project-info p {
  font-family: var(--font-display);
  max-width: calc(var(--info-width) - var(--info-pad-left) - var(--info-pad-right));
  box-sizing: border-box;
  font-weight: 400;
  font-size: 13px;
  line-height: 1.4;
  width: var(--desc-width);
  color: var(--fg-dim);
  margin: var(--gap-link) 0 0;
}
.project--cms .tag--solid {
  background: rgb(38, 38, 39);
  color: rgb(176, 176, 175);
  border: none;
  border-radius: 999px;
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 10px;
  line-height: 1;
  padding: 6px 12px 7px;
}

/* GWM App → catalogue affordance (Work list, both surfaces) */
a.proj-title-link {
  color: inherit;
  text-decoration: none;
  transition: opacity 0.2s ease;
}
a.proj-title-link:hover { opacity: 0.66; }

.catalogue-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-dim);
  transition: color 0.25s ease, gap 0.25s ease;
}
.catalogue-link .arr { transition: transform 0.25s ease; }
.catalogue-link:hover { color: var(--fg); gap: 12px; }
.catalogue-link:hover .arr { transform: translate(2px, -2px); }

/* CMS list: each junction is its own margin so spacing can differ */
.project--cms .catalogue-link { margin: var(--gap-headline) 0 0; }
.project--cms .project-info .tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: var(--gap-desc);
}

.project-stack {
  margin: 48px 78px 0 438px;   /* 48px inset on all four sides (matches L/R gap to grid) */
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.project-stack .media-row {
  display: flex;
  gap: 12px;
}
.project-stack .slot {
  flex: 1 1 0;
  height: auto;                /* let aspect-ratio compute height from flex width */
  border-radius: 20px;
}
/* a lone 3:4 (odd one out) takes half width, left-aligned */
.project-stack .media-row--single-34 .slot {
  flex: 0 1 calc(50% - 6px);
}
/* image-slot theming for the dark canvas */
.project-stack image-slot { color: var(--fg-dim); }
.project-stack image-slot::part(frame) { background: var(--bg-soft); }

.project-info .pnum {
  font-size: 11px;
  color: var(--fg-faint);
  letter-spacing: 0.18em;
  margin-bottom: 24px;
}

.project-info h2 {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -0.01em;
  margin-bottom: 14px;
}

.project-info p {
  font-size: 13px;
  line-height: 1.55;
  color: var(--fg-dim);
  margin-bottom: 24px;
  max-width: 280px;
}

.tag {
  display: inline-block;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--fg-dim);
}

.project-info .meta-list {
  margin-top: 32px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--fg-dim);
}
.project-info .meta-list div {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px dashed var(--border);
  padding-bottom: 8px;
}
.project-info .meta-list span:first-child { color: var(--fg-faint); }

.project-media {
  position: relative;
  aspect-ratio: 16/10;
  border-radius: 4px;
  overflow: hidden;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  opacity: var(--media-op, 0.6);
  transition: opacity 0.6s ease;
}

.project-media.in-view {
  --media-op: 1;
}

.project-media .mockup {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* placeholder mockups (each project gets a different look) */
.mockup-gwm {
  /* raise the phone toward the top; stays horizontally centered */
  align-items: flex-start;
  padding-top: 28px;
  transform: translateY(-30px);
}
.mockup-gwm .phone {
  width: 30%;
  aspect-ratio: 9/19;
  background: #0a0a0a;
  border-radius: 32px;
  border: 1px solid rgba(255,255,255,0.1);
  position: relative;
  box-shadow: 0 40px 80px rgba(0,0,0,0.6);
}
.mockup-gwm .phone::before {
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: 26px;
  background: linear-gradient(180deg, #161616 0%, #0a0a0a 40%, #1a1a1a 100%);
}
.mockup-gwm .phone::after {
  content: "GWM";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: var(--fg);
  font-size: 14px;
  letter-spacing: 0.3em;
}

.mockup-aurora {
  background: linear-gradient(180deg, #08090b 0%, #14171e 100%);
  position: relative;
  overflow: hidden;
}
.mockup-aurora::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(60% 30% at 20% 80%, rgba(75, 200, 255, 0.18), transparent 70%),
    radial-gradient(50% 30% at 80% 20%, rgba(255, 80, 80, 0.16), transparent 70%);
  filter: blur(20px);
}
.mockup-aurora .console {
  position: relative;
  width: 70%;
  aspect-ratio: 16/9;
  background: rgba(10, 12, 16, 0.7);
  border: 1px solid rgba(255,255,255,0.08);
  backdrop-filter: blur(10px);
  border-radius: 6px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px;
  padding: 18px;
}
.mockup-aurora .console > div {
  border: 1px dashed rgba(255,255,255,0.15);
  border-radius: 4px;
  background: rgba(255,255,255,0.02);
}

.mockup-aiact {
  background: linear-gradient(135deg, #0a0a0a 0%, #1a1010 100%);
  position: relative;
}
.mockup-aiact .chart {
  width: 70%;
  aspect-ratio: 16/9;
  position: relative;
  background: rgba(255,255,255,0.02);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.mockup-aiact .bar {
  height: 6px;
  background: rgba(245, 245, 244, 0.85);
  border-radius: 999px;
  opacity: 0.85;
}
.mockup-aiact .bar:nth-child(2) { width: 65%; opacity: 0.6; }
.mockup-aiact .bar:nth-child(3) { width: 80%; opacity: 0.75; }
.mockup-aiact .bar:nth-child(4) { width: 45%; opacity: 0.35; }
.mockup-aiact .bar:nth-child(5) { width: 92%; opacity: 0.9; }
.mockup-aiact .bar:nth-child(6) { width: 30%; opacity: 0.2; }

/* ============================================================
   Info / contact page
   ============================================================ */

.info-wrap {
  padding: 140px 32px 160px;
  position: relative;
  z-index: 5;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: start;
}

.about-photo {
  aspect-ratio: 4/5;
  background: #1a1a1a;
  border: 1px dashed var(--border);
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.about-photo .placeholder-svg {
  width: 60%;
  opacity: 0.18;
}

.about-photo::after {
  content: "PHOTO";
  position: absolute;
  bottom: 16px;
  left: 16px;
  font-size: 10px;
  letter-spacing: 0.2em;
  color: var(--fg-faint);
}

.about-text {
  padding-top: 40px;
}

.about-text .eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--fg-dim);
  margin-bottom: 28px;
}

.about-text h1 {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.4vw, 48px);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin-bottom: 40px;
  text-wrap: pretty;
}

.about-text h1 .dim {
  color: var(--fg-dim);
}

.contact-list {
  margin-top: 56px;
  border-top: 1px dashed var(--border);
}

.contact-row {
  display: grid;
  grid-template-columns: 120px 1fr auto;
  align-items: center;
  padding: 22px 0;
  border-bottom: 1px dashed var(--border);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  transition: padding 0.3s ease;
  cursor: pointer;
}

.contact-row:hover {
  padding-left: 12px;
}

.contact-row .label {
  color: var(--fg-faint);
  font-size: 10px;
}

.contact-row .val {
  color: var(--fg);
  text-transform: none;
  letter-spacing: 0;
}

.contact-row .arrow {
  color: var(--fg-dim);
  transition: transform 0.3s ease, color 0.3s ease;
}

.contact-row:hover .arrow {
  transform: translateX(6px);
  color: var(--fg);
}

/* ============================================================
   Responsive
   ============================================================ */

@media (max-width: 900px) {
  .nav { grid-template-columns: 1fr 1fr; padding: 18px 20px; }
  .nav-clock { display: none; }
  .nav-links { gap: 18px; }
  .foot { padding: 18px 20px; font-size: 9px; grid-template-columns: 1fr 1fr; }
  .foot-mid { display: none; }
  .hero-c { grid-template-columns: 1fr; padding: 100px 20px 80px; }
  .hero-c .portrait-card { max-height: 50vh; }
  .hero-b { padding: 0 20px 100px; }
  .hero-b .meta { grid-template-columns: 1fr; gap: 20px; }
  .work-wrap { padding: 110px 20px 100px; }
  .work-head { flex-direction: column; align-items: flex-start; gap: 24px; }
  .project { grid-template-columns: 1fr; gap: 24px; margin-bottom: 80px; }
  .project-info { position: static; }
  .project--cms { padding-top: 0; }
  .project--cms .project-info,
  .project--cms .project-info-col,
  .project--cms .project-stack,
  .project--cms .project-divider { grid-column: auto; grid-row: auto; }
  .info-wrap { grid-template-columns: 1fr; padding: 110px 20px 100px; gap: 40px; }
  .contact-row { grid-template-columns: 80px 1fr auto; }
}
