:root {
  --bg: #ffffff;
  --stone: #44403c;        /* stone-700 */
  --stone-soft: #78716c;   /* stone-500 */
  --stone-line: #e7e5e4;   /* stone-200 */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --menu-speed: 1s;     /* how fast the menu slides in/out — the one knob */
  --page-fade: 0.3s;   /* how fast a page fades in on load */
}

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

html,
body {
  height: 100%;
}

html {
  scroll-behavior: smooth; /* gentle glide when jumping to the music section */
}

body {
  background: var(--bg);
  color: var(--stone);
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Code", monospace;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ── Cycling photo background ────────────────────── */
/* Two stacked layers behind everything; background.js crossfades them by
   opacity (GPU-composited, cheap) every few minutes and recolours the page ink
   to match each photo. The scrim steadies text contrast over the photos. */
.bg {
  position: fixed;
  inset: 0;
  z-index: -1;       /* behind the deck (z-index 0) and all content */
  overflow: hidden;
  background: var(--bg); /* fallback if a photo is slow to load */
}
.bg-layer {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0;
  will-change: opacity;
  transition: opacity 1.8s var(--ease);
}
.bg-scrim {
  position: absolute;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.34);
  transition: background-color 1.8s var(--ease);
}

/* let the photos show through the page chrome */
.deck,
.panel,
.hero,
body > main.page {
  background: transparent;
}

/* ── Hamburger toggle ───────────────────────────── */
.menu-toggle {
  position: fixed;
  top: 28px;
  left: 28px;
  z-index: 30;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 28px;
  height: 18px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
}

.menu-toggle .bar {
  display: block;
  width: 100%;
  height: 1.5px;
  background: var(--stone);
  border-radius: 2px;
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease);
}

/* animate to an X when open */
.menu-toggle.open .bar:nth-child(1) {
  transform: translateY(8.25px) rotate(45deg);
}
.menu-toggle.open .bar:nth-child(2) {
  opacity: 0;
}
.menu-toggle.open .bar:nth-child(3) {
  transform: translateY(-8.25px) rotate(-45deg);
}

/* ── Social links (top-right) ───────────────────── */
.social {
  position: fixed;
  top: 28px;
  right: 28px;
  z-index: 9;            /* under the overlay, so it dims when the menu opens */
  display: flex;
  align-items: center;
  gap: 24px;
  height: 18px;          /* match the hamburger so both sit on the same line */
}
.social a {
  display: inline-flex;
  color: var(--stone-soft);
  transition: color 0.3s var(--ease);
}
.social a:hover {
  color: var(--stone);
}
.social svg {
  display: block;
  width: 22px;
  height: 22px;
}

/* ── Overlay ────────────────────────────────────── */
.overlay {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(2px);
  opacity: 0;
  visibility: hidden;
  transition: opacity calc(var(--menu-speed) * 0.9) var(--ease),
    visibility calc(var(--menu-speed) * 0.9) var(--ease);
}
.overlay.open {
  opacity: 1;
  visibility: visible;
}

/* ── Slide-in menu ──────────────────────────────── */
.menu {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 25;
  width: min(340px, 82vw);
  height: 100%;
  padding: 120px 40px 40px;
  background: transparent;
  transform: translateX(-100%);
  transition: transform var(--menu-speed) var(--ease);
}
.menu.open {
  transform: translateX(0);
}

.menu-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 13px;
}

.menu-list li {
  opacity: 0;
  transform: translateX(-12px);
  transition: opacity calc(var(--menu-speed) * 0.9) var(--ease),
    transform calc(var(--menu-speed) * 0.9) var(--ease);
  /* closing: unwind with a reverse stagger (last item leaves first),
     mirroring the open so the close feels just as smooth */
  transition-delay: calc((4 - var(--i)) * 0.06s);
}
.menu.open .menu-list li {
  opacity: 1;
  transform: translateX(0);
  /* stagger each item as the panel opens */
  transition-delay: calc(0.18s + var(--i) * 0.07s);
}

.menu-list a {
  color: var(--stone-soft);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 300;
  letter-spacing: 0.02em;
  transition: color 0.25s var(--ease);
}
.menu-list a:hover,
.menu-list a[aria-current="page"] {
  color: var(--stone);
}

.menu-list .menu-name {
  color: var(--stone);
  font-size: 1.35rem;
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* ── Hero ───────────────────────────────────────── */
.hero {
  position: relative;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.blob {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.blob-back {
  z-index: 0; /* behind the title — the far half of the wireframe */
}

.blob-front {
  z-index: 2; /* in front of the title — the near half, so the name sits inside */
}

.hero-title {
  position: relative;
  z-index: 1;
  font-size: clamp(1.8rem, 6vw, 3.4rem);
  font-weight: 300;
  letter-spacing: -0.02em;
  color: var(--stone);
  user-select: none;          /* can't highlight/select the text */
  -webkit-user-select: none;  /* Safari */
  cursor: default;            /* keep the arrow cursor, not the text I-beam */
}

/* Edge cues — a labelled floating arrow on each edge of the hero, pointing the
   way to another page (and the music section below). Same motif all round. */
.edge-cue {
  position: absolute;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--stone-soft);
  text-decoration: none;
  transition: color 0.25s var(--ease);
}
.edge-cue:hover {
  color: var(--stone);
}
.edge-cue-label {
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* bottom edge — On Repeat */
.edge-cue--down {
  left: 50%;
  bottom: 34px;
  flex-direction: column;
  animation: cue-down 2.4s var(--ease) infinite;
}
@keyframes cue-down {
  0%, 100% { transform: translate(-50%, 0); opacity: 0.6; }
  50%      { transform: translate(-50%, 7px); opacity: 1; }
}

/* top edge — Projects */
.edge-cue--up {
  left: 50%;
  top: 34px;
  flex-direction: column;
  animation: cue-up 2.4s var(--ease) infinite;
}
@keyframes cue-up {
  0%, 100% { transform: translate(-50%, 0); opacity: 0.6; }
  50%      { transform: translate(-50%, -7px); opacity: 1; }
}

/* left edge — About */
.edge-cue--left {
  left: 28px;
  top: 50%;
  flex-direction: row;
  animation: cue-left 2.4s var(--ease) infinite;
}
@keyframes cue-left {
  0%, 100% { transform: translate(0, -50%); opacity: 0.6; }
  50%      { transform: translate(-7px, -50%); opacity: 1; }
}

/* right edge — Experience */
.edge-cue--right {
  right: 28px;
  top: 50%;
  flex-direction: row;
  animation: cue-right 2.4s var(--ease) infinite;
}
@keyframes cue-right {
  0%, 100% { transform: translate(0, -50%); opacity: 0.6; }
  50%      { transform: translate(7px, -50%); opacity: 1; }
}

/* ── Spatial deck (Prezi-style panels) ──────────── */
/* Home sits at the centre; About / Projects / Experience / Music are panels
   laid out left / up / right / down around it on one big plane. Navigating
   slides the plane so the chosen panel fills the viewport — the same seamless
   motion in every direction. */
.deck {
  position: fixed;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}
.plane {
  position: absolute;
  inset: 0;
  transition: transform 0.85s var(--ease);
  will-change: transform;
}
.panel {
  position: absolute;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
#home       { left: 0;      top: 0;      }
#about      { left: -100vw; top: 0;      }
#projects   { left: 0;      top: -100vh; }
#experience { left: 100vw;  top: 0;      }
#music      { left: 0;      top: 100vh;  }

/* tall panels scroll inside themselves; the back cue (a sibling) stays pinned */
.panel-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* ── Page cross-fade (through white) ────────────── */
/* A full-screen white "curtain" above everything. On load it starts opaque
   and fades out, so the whole page (UI included) reveals from white. On
   navigating away, script.js adds .leaving to fade it back to white before
   the browser actually loads the next page — so the two pages cross-fade
   through white. pointer-events stay off so it never blocks clicks. */
.fade-curtain {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--bg);
  pointer-events: none;
  opacity: 0;
  animation: curtain-out var(--page-fade) var(--ease) both;
}
.fade-curtain.leaving {
  animation: curtain-in var(--page-fade) var(--ease) forwards;
}

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

/* ── Experience page ────────────────────────────── */
/* Let the page grow taller than the viewport so it scrolls naturally;
   the fixed stars / menu / toggle stay put while the list scrolls. */
.page {
  position: relative;
  z-index: 1;
  min-height: 100%;
  max-width: 720px;
  margin: 0 auto;
  padding: 132px 32px 96px;
}

.page-title {
  font-size: clamp(1.6rem, 5vw, 2.6rem);
  font-weight: 300;
  letter-spacing: -0.02em;
  color: var(--stone);
  margin-bottom: 20px;
}

/* meshing gear motif tucked under the heading */
.gears {
  display: block;
  width: 70%;
  height: 150px;
  margin-bottom: 44px;
}

.xp-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.xp-item {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 24px;
  padding-bottom: 40px;
  border-bottom: 1px solid var(--stone-line);
}
.xp-item:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.xp-period {
  color: var(--stone-soft);
  font-size: 0.82rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  padding-top: 0.35em;
}

.xp-role {
  font-size: 1.1rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--stone);
}

.xp-org {
  margin-top: 4px;
  color: var(--stone-soft);
  font-size: 0.95rem;
  font-weight: 300;
}

.xp-desc {
  margin-top: 12px;
  color: var(--stone-soft);
  font-size: 0.92rem;
  font-weight: 300;
  line-height: 1.7;
}

/* bulleted accomplishments — same muted type as .xp-desc, with a thin dash
   marker that fits the minimalist look */
.xp-points {
  margin-top: 12px;
  padding-left: 1.2em;
  list-style: none;
  color: var(--stone-soft);
  font-size: 0.92rem;
  font-weight: 300;
  line-height: 1.7;
}
.xp-points li {
  position: relative;
}
.xp-points li + li {
  margin-top: 10px;
}
.xp-points li::before {
  content: "—";
  position: absolute;
  left: -1.2em;
  color: var(--stone-line);
}

@media (max-width: 560px) {
  .xp-item {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .xp-period {
    padding-top: 0;
  }
}

/* ── Projects page ──────────────────────────────── */
.proj-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.proj-item {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 24px;
  padding-bottom: 40px;
  border-bottom: 1px solid var(--stone-line);
}
.proj-item:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

/* left rail: external links */
.proj-links {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 0.35em;
}
.proj-links a {
  color: var(--stone-soft);
  text-decoration: none;
  font-size: 0.82rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  transition: color 0.25s var(--ease);
}
.proj-links a:hover {
  color: var(--stone);
}

.proj-name {
  font-size: 1.1rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--stone);
}

.proj-tagline {
  margin-top: 4px;
  color: var(--stone-soft);
  font-size: 0.95rem;
  font-weight: 300;
}

.proj-desc {
  margin-top: 12px;
  color: var(--stone-soft);
  font-size: 0.92rem;
  font-weight: 300;
  line-height: 1.7;
}

/* tech-stack chips — thin outlined tags in the muted palette */
.proj-stack {
  margin-top: 16px;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.proj-stack li {
  border: 1px solid var(--stone-line);
  border-radius: 999px;
  padding: 3px 10px;
  color: var(--stone-soft);
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.02em;
}

@media (max-width: 560px) {
  .proj-item {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .proj-links {
    flex-direction: row;
    gap: 18px;
    padding-top: 0;
  }
}

/* ── About page ─────────────────────────────────── */
.about-text {
  max-width: 60ch;
  color: var(--stone-soft);
  font-size: 0.95rem;
  font-weight: 300;
  line-height: 1.85;
}
.about-text p + p {
  margin-top: 1.4em;
}
.about-text strong {
  color: var(--stone);
  font-weight: 500;
}

/* ── Music page (Spotify widget) ────────────────── */
.page-lead {
  color: var(--stone-soft);
  font-size: 0.92rem;
  font-weight: 300;
  line-height: 1.7;
  margin-bottom: 40px;
  max-width: 52ch;
}

.sp-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
}

.sp-col-title {
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stone-soft);
  margin-bottom: 14px;
}

.sp-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sp-embed {
  width: 100%;
  height: 80px;
  border: 0;
  border-radius: 12px;
  display: block;
}

.sp-updated {
  margin-top: 36px;
  color: var(--stone-soft);
  font-size: 0.72rem;
  font-weight: 300;
  letter-spacing: 0.02em;
}
.sp-empty {
  color: var(--stone-soft);
  font-size: 0.9rem;
  font-weight: 300;
}

@media (max-width: 560px) {
  .sp-grid {
    grid-template-columns: 1fr;
    gap: 36px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition-duration: 0.001s !important;
    animation-duration: 0.001s !important;
  }
  html {
    scroll-behavior: auto;
  }
}
