/* ============================================================
   RESET & BASE
   ============================================================ */
* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg: #0d0f14;
  --ink: #f3f1ea;
  --ink-dim: rgba(243, 241, 234, 0.68);
  --accent: #e8b04b;
  --font-display: 'Space Grotesk', 'Segoe UI', sans-serif;
  --font-body: 'Inter', 'Segoe UI', sans-serif;
}

html {
  scroll-behavior: smooth;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  overflow-x: hidden;
  line-height: 1.5;
}

/* Filmic grain over the whole page — ties the hero illustration and the
   project panels together into one consistent, textured surface. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 300;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

a { color: inherit; text-decoration: none; }
ul { list-style: none; }
img { max-width: 100%; display: block; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
}

section { position: relative; }

/* ============================================================
   PROGRESS BAR
   ============================================================ */
.progress-bar {
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 0%;
  background: var(--accent);
  z-index: 200;
  transition: width 0.1s linear;
}

/* ============================================================
   HEADER / TOP NAV
   ============================================================ */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 28px 5vw;
  mix-blend-mode: difference;
}

.logo {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--ink);
}

.top-nav {
  display: flex;
  gap: 2.25rem;
}

.top-nav a {
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.85;
  transition: opacity 0.2s ease;
}

.top-nav a:hover { opacity: 1; }

.header-right {
  display: flex;
  align-items: center;
  gap: 1.75rem;
}

/* Language switch — a small EN / FR pill toggle. */
.lang-toggle {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid rgba(243, 241, 234, 0.4);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  line-height: 1;
  cursor: pointer;
}

.lang-toggle span {
  padding: 4px 7px;
  border-radius: 999px;
  opacity: 0.5;
  transition: opacity 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.lang-toggle span.is-active {
  opacity: 1;
  background: var(--accent);
  color: #0d0f14;
}

@media (max-width: 600px) {
  .site-header { padding: 16px 4.5vw; gap: 0.55rem; }
  .logo { font-size: 1rem; }
  .header-right { gap: 0.65rem; }
  .top-nav { gap: 0.7rem; }
  .top-nav a { font-size: 0.66rem; letter-spacing: 0.02em; }
  .lang-toggle { font-size: 0.58rem; }
  .lang-toggle span { padding: 4px 5px; }
}

@media (max-width: 430px) {
  .site-header { padding: 15px 4vw; gap: 0.4rem; }
  .header-right { gap: 0.5rem; }
  .top-nav { gap: 0.6rem; }
  .top-nav a { font-size: 0.62rem; }
}

/* Only the very narrowest screens fall back to a second row: the nav
   links drop below the logo / language toggle, right-aligned, so the
   header still never forces a horizontal scroll. */
@media (max-width: 340px) {
  .header-right { flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; }
  .top-nav { order: 2; flex-basis: 100%; justify-content: flex-end; gap: 0.9rem; }
}

/* ============================================================
   DOT NAVIGATION
   ============================================================ */
.dot-nav {
  position: fixed;
  right: 28px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.dot-nav .dot {
  position: relative;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(243, 241, 234, 0.35);
  transition: background 0.25s ease, transform 0.25s ease;
}

.dot-nav .dot::after {
  content: attr(data-label);
  position: absolute;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink);
  background: rgba(13, 15, 20, 0.85);
  padding: 4px 10px;
  border-radius: 4px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

.dot-nav .dot:hover::after { opacity: 1; }

.dot-nav .dot.active {
  background: var(--accent);
  transform: scale(1.3);
}

/* Category markers read as small squares rather than dots */
.dot-nav .dot-cat {
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: rgba(243, 241, 234, 0.55);
}
.dot-nav .dot-cat.active {
  background: var(--accent);
  transform: rotate(45deg) scale(1.25);
}

@media (max-width: 800px) {
  .dot-nav { display: none; }
}

/* ============================================================
   HERO — layered parallax (Firewatch style)
   ============================================================ */
.hero {
  position: relative;
  height: 100vh;
  height: 100svh; /* ignore the mobile URL bar so the hero doesn't resize mid-scroll */
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
}

.hero-sky {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #17182c 0%, #4b3f66 16%, #b3597a 42%, #f4845f 62%, #ffb26b 78%, #ffd39a 100%);
  z-index: 0;
}

.hero-layer {
  position: absolute;
  bottom: 0;
  left: -5%;
  width: 110%;
  height: 100%;
  z-index: 1;
}

/* Promote the parallax layers to their own compositor layer only while a
   scroll is actually in progress (JS adds .is-scrolling to <html> and
   removes it ~200ms after scrolling stops). Keeps an idle page — and a
   low-memory phone — from permanently holding ~20 full-screen GPU layers. */
html.is-scrolling .hero-layer,
html.is-scrolling .hero-content,
html.is-scrolling .project-bg,
html.is-scrolling .project-pattern,
html.is-scrolling .project-ghost {
  will-change: transform;
}

/* Firewatch-style layered ranges: flat angular peaks, each split into a
   warm sun-lit face and a cool shadow face. Ranges read cool and pale in
   the distance, then warm and darken toward the foreground, with one
   dominant sunlit peak in the mid ground. */
.mtn-far      { fill: #6f7099; }
.mtn-mid1-sh  { fill: #33566b; }
.mtn-mid1-lt  { fill: #5ea08f; }
.mtn-mid2-sh  { fill: #2b3a55; }
.mtn-mid2-lt  { fill: #c96a37; }
.mtn-mid2-fac { fill: #b0582f; }
.mtn-near     { fill: #1f2b3f; }
.mtn-near-lt  { fill: #6b4030; opacity: 0.55; }
.hero-trees g { fill: #141c2c; }

/* Star field — three independently-twinkling sub-layers plus a couple of
   bright, haloed stars, all masked so they only show in the upper
   (night-into-dusk) part of the sky. */
.hero-stars {
  top: 0;
  height: 66%;
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 45%, transparent 92%);
  mask-image: linear-gradient(to bottom, black 0%, black 45%, transparent 92%);
  overflow: visible;
}

/* Base layer: dense fine dust + a few brighter, softly-haloed stars. */
.hero-stars {
  background-repeat: no-repeat;
  background-image:
    radial-gradient(1.5px 1.5px at 8% 15%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 18% 40%, #fff, transparent),
    radial-gradient(1.7px 1.7px at 27% 10%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 38% 30%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 48% 8%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 58% 22%, #fff, transparent),
    radial-gradient(1.7px 1.7px at 68% 12%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 76% 34%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 85% 6%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 93% 26%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 12% 55%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 62% 48%, #fff, transparent),
    radial-gradient(3px 3px at 22% 18%, #fff 0%, rgba(255,255,255,0.35) 42%, transparent 72%),
    radial-gradient(3.4px 3.4px at 71% 24%, #fff 0%, rgba(255,236,214,0.4) 40%, transparent 72%),
    radial-gradient(2.6px 2.6px at 45% 40%, #fff 0%, rgba(214,224,255,0.4) 42%, transparent 74%);
  animation: twinkle 6s ease-in-out infinite;
}

/* Two more offset layers — different positions, sizes and twinkle rhythm
   so the field shimmers star-by-star instead of pulsing as one block. */
.hero-stars::before,
.hero-stars::after {
  content: "";
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
}

.hero-stars::before {
  background-image:
    radial-gradient(1.4px 1.4px at 5% 28%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 15% 8%, #fff, transparent),
    radial-gradient(1.6px 1.6px at 24% 46%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 33% 18%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 43% 33%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 53% 12%, #fff, transparent),
    radial-gradient(1.6px 1.6px at 64% 40%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 73% 18%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 82% 44%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 90% 14%, #fff, transparent),
    radial-gradient(1.4px 1.4px at 97% 36%, #fff, transparent);
  opacity: 0.85;
  animation: twinkle 4.2s ease-in-out infinite;
  animation-delay: -1.6s;
}

.hero-stars::after {
  background-image:
    radial-gradient(1.2px 1.2px at 10% 38%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 21% 24%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 30% 6%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 40% 50%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 51% 28%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 61% 16%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 70% 52%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 79% 30%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 88% 50%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 95% 20%, #fff, transparent);
  opacity: 0.7;
  animation: twinkle 5.3s ease-in-out infinite;
  animation-delay: -3.1s;
}

@keyframes twinkle {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 0.9; }
}

/* Shooting stars — a bright head with a tapering tail, streaking across
   on a long cycle so they stay a rare, pleasing surprise. */
.shooting-star {
  position: absolute;
  top: 12%;
  left: 8%;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 8px 2px rgba(255, 255, 255, 0.9);
  opacity: 0;
  transform: rotate(18deg);
  animation: shoot 11s ease-in infinite;
}
.shooting-star::before {
  content: "";
  position: absolute;
  top: 50%;
  right: 2px;
  width: 220px;
  height: 1.5px;
  transform: translateY(-50%);
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.9), transparent);
}
.shooting-star--2 {
  top: 26%;
  left: 44%;
  animation-duration: 17s;
  animation-delay: -7s;
}

@keyframes shoot {
  0%       { opacity: 0; transform: translate(0, 0) rotate(18deg); }
  3%       { opacity: 1; }
  12%      { opacity: 1; }
  18%      { opacity: 0; transform: translate(46vw, 20vh) rotate(18deg); }
  100%     { opacity: 0; transform: translate(46vw, 20vh) rotate(18deg); }
}

/* Clouds — flat cartoon shapes drifting slowly across the sky:
   pink body, white crest, mauve underside, loose swirl-line accents. */
.hero-clouds {
  top: 0;
  height: 80%;
}

.hero-clouds svg {
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 16px 24px rgba(90, 55, 100, 0.20));
}

.cc-body   { fill: #d98fae; }
.cc-hi     { fill: #f4eaf0; }
.cc-shadow { fill: #af6a8e; opacity: 0.55; }
.cc-lines path {
  stroke: rgba(255, 255, 255, 0.6);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}
.cc-lines-in path {
  stroke: rgba(150, 92, 122, 0.45);
  stroke-width: 1.6;
  vector-effect: non-scaling-stroke;
}

.cloud {
  transform-box: fill-box;
  transform-origin: center;
  will-change: transform;
}
.cloud-1 { animation: cloudDrift1 90s ease-in-out infinite; }
.cloud-2 { animation: cloudDrift2 120s ease-in-out infinite; }
.cloud-3 { animation: cloudDrift3 150s ease-in-out infinite; }
.cloud-4 { animation: cloudDrift1 108s ease-in-out infinite reverse; }
.cloud-5 { animation: cloudDrift2 168s ease-in-out infinite; }

@keyframes cloudDrift1 {
  0%, 100% { transform: translate(-32px, 0); }
  50%      { transform: translate(32px, -12px); }
}

@keyframes cloudDrift2 {
  0%, 100% { transform: translate(26px, 4px); }
  50%      { transform: translate(-26px, -10px); }
}

@keyframes cloudDrift3 {
  0%, 100% { transform: translate(-20px, 0); }
  50%      { transform: translate(22px, -8px); }
}

/* Birds — a couple of simple chevrons flying slow loops across the sky */
.hero-birds {
  top: 12%;
  height: 40%;
  overflow: visible;
}

.bird {
  position: absolute;
  width: 22px;
  height: 11px;
  opacity: 0.8;
  mix-blend-mode: difference;
}

.bird path { stroke: #fff; }

.bird-1 { top: 18%; animation: fly 34s linear infinite; }
.bird-2 { top: 32%; width: 16px; height: 8px; opacity: 0.65; animation: fly 42s linear infinite; animation-delay: -12s; }
.bird-3 { top: 22%; width: 14px; height: 7px; opacity: 0.6; animation: fly 50s linear infinite; animation-delay: -28s; }

@keyframes fly {
  0%   { transform: translate(-10vw, 0); }
  50%  { transform: translate(55vw, -3vh); }
  100% { transform: translate(120vw, 0); }
}

.hero-vignette {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 40%, transparent 45%, rgba(9, 10, 16, 0.45) 100%);
}

.hero-content {
  position: relative;
  z-index: 5;
  text-align: center;
  color: var(--ink);
  padding: 0 1.5rem;
}

.eyebrow {
  font-size: 0.8rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  opacity: 0.8;
  margin-bottom: 1rem;
}

.hero h1 {
  font-size: clamp(3rem, 9vw, 7rem);
  letter-spacing: -0.02em;
  text-shadow: 0 4px 30px rgba(0,0,0,0.35);
}

/* ---- Anagram title — "Marino" is "Romain" with the same six letters ----
   Each of the six letter identities gets its own hue, so the eye can see
   the same palette reappear, reshuffled, in the surname. */
.hero-title {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.32em;
}
.hero-title .name-word {
  display: inline-flex;
  white-space: nowrap;
}
.hero-title .ltr {
  display: inline-block;
}
.hero-title .ltr[data-l="r"] { color: #e8b04b; }
.hero-title .ltr[data-l="o"] { color: #67c8d6; }
.hero-title .ltr[data-l="m"] { color: #b49be8; }
.hero-title .ltr[data-l="a"] { color: #ee8a9e; }
.hero-title .ltr[data-l="i"] { color: #83ce9d; }
.hero-title .ltr[data-l="n"] { color: #edaa6a; }

.anagram-note {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  margin-top: 0.9rem;
  font-size: clamp(0.7rem, 1.2vw, 0.82rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.anagram-note b {
  font-weight: 600;
  color: rgba(255, 255, 255, 0.9);
}
.anagram-swap {
  display: inline-block;
  color: var(--accent);
  font-size: 1.15em;
  animation: anagramSwap 3.6s ease-in-out infinite;
}
.anagram-tail {
  letter-spacing: 0.1em;
  opacity: 0.75;
}
@keyframes anagramSwap {
  0%, 42%, 100% { transform: rotate(0); }
  50%, 92%      { transform: rotate(180deg); }
}

@media (max-width: 560px) {
  .anagram-tail { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .anagram-swap { animation: none; }
}

.hero-sub {
  margin-top: 1.25rem;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  color: rgba(255,255,255,0.85);
  max-width: 32rem;
  margin-left: auto;
  margin-right: auto;
}

.scroll-cue {
  position: absolute;
  bottom: 2.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.75);
}

.scroll-cue span {
  width: 1px;
  height: 34px;
  background: rgba(255,255,255,0.55);
  position: relative;
  overflow: hidden;
}

.scroll-cue span::after {
  content: '';
  position: absolute;
  top: -100%;
  left: 0;
  width: 100%;
  height: 100%;
  background: var(--accent);
  animation: scrollLine 2s ease-in-out infinite;
}

@keyframes scrollLine {
  0% { top: -100%; }
  60% { top: 100%; }
  100% { top: 100%; }
}

/* ============================================================
   ABOUT STRIP
   ============================================================ */
.about {
  padding: 9rem 8vw;
  background: var(--bg);
  display: flex;
  justify-content: center;
}

.about-inner {
  max-width: 42rem;
  text-align: center;
}

/* Stylised circular portrait — a slowly rotating gradient ring drawn from
   the portrait's own palette (deep teal backdrop, slate porthole, terracotta
   frame, warm skin), a soft matching glow and a dashed outer orbit. */
.about-avatar {
  --size: clamp(9rem, 24vw, 13rem);
  position: relative;
  width: var(--size);
  height: var(--size);
  margin: 0 auto 2.75rem;
  border-radius: 50%;
  isolation: isolate;
}

.about-avatar::before {
  content: "";
  position: absolute;
  inset: -7px;
  border-radius: 50%;
  background: conic-gradient(from 140deg, #2f4a57, #6b7482, #a16252, #d28e67, #2f4a57);
  box-shadow: 0 0 46px rgba(161, 98, 82, 0.3), 0 18px 40px -12px rgba(0, 0, 0, 0.65);
  z-index: -1;
  animation: avatarSpin 22s linear infinite;
}

.about-avatar::after {
  content: "";
  position: absolute;
  inset: -1.5rem;
  border-radius: 50%;
  border: 1px dashed rgba(243, 241, 234, 0.18);
  z-index: -2;
}

.about-avatar img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  border: 5px solid var(--bg);
  display: block;
}

/* Halo: two rings that expand and fade out, pulsing continuously once the
   About section has scrolled into view (also triggered on hover). */
.about-avatar-halo {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 2px solid rgba(210, 142, 103, 0.75);
  box-shadow: 0 0 22px rgba(210, 142, 103, 0.45);
  pointer-events: none;
  opacity: 0;
  z-index: -1;
}

.about-inner.in-view .about-avatar-halo,
.about-avatar:hover .about-avatar-halo {
  animation: aboutHalo 3s cubic-bezier(0.22, 0.61, 0.36, 1) infinite;
}
.about-inner.in-view .about-avatar-halo--2,
.about-avatar:hover .about-avatar-halo--2 {
  animation-delay: 1.5s;
}

@keyframes aboutHalo {
  0%   { opacity: 0.9; transform: scale(1); }
  50%  { opacity: 0; transform: scale(1.4); }
  100% { opacity: 0; transform: scale(1.4); }
}

@keyframes avatarSpin {
  to { transform: rotate(1turn); }
}

@media (prefers-reduced-motion: reduce) {
  .about-avatar::before { animation: none; }
  .about-avatar-halo { animation: none !important; }
}

.about-kicker {
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1rem;
}

.about h2 {
  font-size: clamp(1.75rem, 3.5vw, 2.75rem);
  margin-bottom: 1.25rem;
}

.about-text {
  color: var(--ink-dim);
  font-size: 1.05rem;
}

.about-harp {
  width: 1.25em;
  height: 1.25em;
  margin-left: 0.45em;
  vertical-align: -0.28em;
  color: var(--accent);
  opacity: 0.85;
}

/* ============================================================
   CV / CAREER TIMELINE — a horizontal history that scrolls
   sideways: work experience sits above the centre axis,
   study below it, both ordered left -> right by start date.
   The dot-nav + scroll-reveal pick this section up automatically
   (it has an id and a .reveal inner), so no JS changes needed.
   ============================================================ */
.career {
  padding: 8rem 0 8.5rem;
  background: var(--bg);
  overflow: hidden;
}

.career-inner { text-align: center; }

.career-inner > .about-kicker,
.career-inner > h2 { padding-left: 8vw; padding-right: 8vw; }

.career h2 {
  font-size: clamp(1.75rem, 3.5vw, 2.75rem);
  margin-bottom: 1.6rem;
}

/* Scroll viewport */
.timeline {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(232, 176, 75, 0.4) transparent;
}
.timeline::-webkit-scrollbar { height: 8px; }
.timeline::-webkit-scrollbar-track { background: transparent; }
.timeline::-webkit-scrollbar-thumb {
  background: rgba(232, 176, 75, 0.35);
  border-radius: 999px;
}

/* The rail: a flex row wider than the viewport, with the axis drawn
   as a full-width pseudo-element through the vertical centre. */
.timeline-track {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.75rem;
  width: max-content;
  padding: 0 max(8vw, 2.5rem);
}

.timeline-track::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  transform: translateY(-50%);
  background: linear-gradient(90deg,
    transparent,
    rgba(232, 176, 75, 0.55) 10%,
    rgba(232, 176, 75, 0.55) 90%,
    transparent);
}

/* One milestone column. Fixed height so the card can sit fully above
   (experience) or below (education) the centred node. */
.tl-item {
  position: relative;
  flex: 0 0 17.5rem;
  height: 35rem;
  display: flex;
  align-items: center;
  justify-content: center;
  scroll-snap-align: center;
}

.tl-node {
  position: relative;
  z-index: 2;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 5px rgba(232, 176, 75, 0.14), 0 0 16px rgba(232, 176, 75, 0.55);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.tl-item--edu .tl-node {
  background: #6ec8dc;
  box-shadow: 0 0 0 5px rgba(110, 200, 220, 0.14), 0 0 16px rgba(110, 200, 220, 0.55);
}

.tl-date {
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--font-display);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.tl-item--exp .tl-date { top: calc(50% + 1.1rem); }
.tl-item--edu .tl-date { bottom: calc(50% + 1.1rem); color: #8ed7e8; }

.tl-card {
  position: absolute;
  left: 0;
  right: 0;
  text-align: left;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.025));
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  padding: 1.05rem 1.15rem 1.2rem;
  transition: transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
.tl-item--exp .tl-card { bottom: calc(50% + 2.5rem); }
.tl-item--edu .tl-card { top: calc(50% + 2.5rem); }

/* Stalk pointing from the card toward its node. */
.tl-card::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 2px;
  height: 2.1rem;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.16);
}
.tl-item--exp .tl-card::after { top: 100%; }
.tl-item--edu .tl-card::after { bottom: 100%; }

.tl-item:hover .tl-card {
  transform: translateY(-4px);
  border-color: rgba(232, 176, 75, 0.5);
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, 0.75);
}
.tl-item--edu:hover .tl-card { border-color: rgba(110, 200, 220, 0.5); }
.tl-item:hover .tl-node { transform: scale(1.25); }

.tl-kind {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.5rem;
}
.tl-item--edu .tl-kind { color: #8ed7e8; }

.tl-card h3 {
  font-size: 1rem;
  line-height: 1.25;
  margin-bottom: 0.35rem;
}

.tl-card h3 sup { font-size: 0.62em; }

.tl-org {
  font-size: 0.82rem;
  color: var(--ink);
  opacity: 0.9;
  margin-bottom: 0.55rem;
}

.tl-note {
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--ink-dim);
}

.career-badges {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(0.9rem, 3vw, 1.9rem);
  max-width: 46rem;
  margin: 2.5rem auto 0;
  padding: 0 1.25rem;
}
.career-badges li { display: flex; }

/* Same surface language as the career timeline cards: a faint glass
   panel with a hairline edge that warms to the accent on hover. */
.cert-badge {
  --bs: clamp(3.75rem, 15vw, 5.75rem);
  position: relative;
  width: var(--bs);
  height: var(--bs);
  padding: 6px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.025));
  border: 1px solid rgba(255, 255, 255, 0.1);
  transition: transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}

.cert-badge img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: transparent;
  opacity: 0.85;
  display: block;
  transition: opacity 0.3s ease;
}

a.cert-badge:hover,
a.cert-badge:focus-visible {
  transform: translateY(-4px);
  border-color: rgba(232, 176, 75, 0.5);
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, 0.75);
}
a.cert-badge:hover img,
a.cert-badge:focus-visible img { opacity: 1; }

.cert-badge--toeic {
  flex-direction: column;
  gap: 0.12em;
  font-family: var(--font-display);
  line-height: 1;
  text-align: center;
}
.cert-toeic-name {
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--accent);
}
.cert-toeic-score {
  font-size: clamp(1.15rem, 5.5vw, 1.4rem);
  font-weight: 700;
  color: var(--ink);
}
.cert-toeic-max {
  font-size: 0.48rem;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
}

@media (prefers-reduced-motion: reduce) {
  a.cert-badge:hover, a.cert-badge:focus-visible { transform: none; }
}

@media (max-width: 620px) {
  .tl-item { flex-basis: 16rem; height: 36rem; }
  .tl-card { padding: 0.9rem 1rem 1rem; }
}

@media (prefers-reduced-motion: reduce) {
  .tl-card, .tl-node { transition: none; }
}

/* ============================================================
   SECTION STAR FIELD — faint, randomly-scattered stars that
   flash and fade independently behind the About and Career
   sections. Three sub-layers, each with its own scatter and
   twinkle rhythm, so the field shimmers star-by-star rather
   than pulsing as one block. Sits behind the content, which is
   lifted with position/z-index below.
   ============================================================ */
.about,
.career { position: relative; }

.about-inner,
.career-inner {
  position: relative;
  z-index: 1;
}

.section-stars {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background-repeat: no-repeat;
  background-image:
    radial-gradient(1.4px 1.4px at 6% 12%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 14% 61%, #fff, transparent),
    radial-gradient(1.6px 1.6px at 23% 33%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 31% 82%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 39% 19%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 47% 54%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 56% 8%,  #fff, transparent),
    radial-gradient(1.1px 1.1px at 63% 74%, #fff, transparent),
    radial-gradient(1.6px 1.6px at 71% 41%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 79% 88%, #fff, transparent),
    radial-gradient(1.4px 1.4px at 86% 26%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 93% 63%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 97% 15%, #fff, transparent);
  opacity: 0.14;
  animation: sectionTwinkleA 5.6s ease-in-out infinite;
}
.section-stars::before,
.section-stars::after {
  content: "";
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
}
.section-stars::before {
  background-image:
    radial-gradient(1.2px 1.2px at 9% 44%,  #fff, transparent),
    radial-gradient(1.1px 1.1px at 19% 17%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 27% 68%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 36% 37%, #fff, transparent),
    radial-gradient(1.4px 1.4px at 44% 91%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 53% 25%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 61% 58%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 69% 11%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 77% 49%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 84% 79%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 91% 33%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 96% 70%, #fff, transparent);
  opacity: 0.1;
  animation: sectionTwinkleB 7.3s ease-in-out infinite;
  animation-delay: -2.4s;
}
.section-stars::after {
  background-image:
    radial-gradient(1.1px 1.1px at 12% 29%, #fff, transparent),
    radial-gradient(1px 1px    at 22% 52%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 34% 9%,  #fff, transparent),
    radial-gradient(1px 1px    at 42% 64%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 51% 39%, #fff, transparent),
    radial-gradient(1px 1px    at 59% 84%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 67% 22%, #fff, transparent),
    radial-gradient(1px 1px    at 74% 57%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 82% 14%, #fff, transparent),
    radial-gradient(1px 1px    at 89% 46%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 95% 77%, #fff, transparent);
  opacity: 0.08;
  animation: sectionTwinkleC 9.1s ease-in-out infinite;
  animation-delay: -5.7s;
}

@keyframes sectionTwinkleA {
  0%, 100% { opacity: 0.14; }
  50%      { opacity: 0.55; }
}
@keyframes sectionTwinkleB {
  0%, 100% { opacity: 0.1; }
  50%      { opacity: 0.4; }
}
@keyframes sectionTwinkleC {
  0%, 100% { opacity: 0.08; }
  50%      { opacity: 0.28; }
}

@media (prefers-reduced-motion: reduce) {
  .section-stars,
  .section-stars::before,
  .section-stars::after { animation: none; }
}

/* ============================================================
   WORK CATEGORY DIVIDERS — a short dark strip that titles each
   group of project panels (Webapps / Games / Professional).
   ============================================================ */
.work-cat {
  padding: 7rem 8vw;
  background: var(--bg);
  display: flex;
  justify-content: center;
  text-align: center;
}

.work-cat-inner {
  max-width: 40rem;
}

.work-cat-index {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 0.75rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.9rem;
}

.work-cat h2 {
  font-size: clamp(2rem, 6vw, 3.75rem);
  letter-spacing: -0.01em;
  margin-bottom: 1rem;
}

.work-cat-inner p {
  color: var(--ink-dim);
  font-size: 1.02rem;
  max-width: 34rem;
  margin: 0 auto;
}

/* ============================================================
   PROJECT PANELS — full-bleed fixed-background parallax
   ============================================================ */
.project {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
}

.project-bg {
  position: absolute;
  top: -16%;
  left: 0;
  width: 100%;
  height: 132%;
  background-position: center;
  background-size: cover;
  z-index: 0;
}

/* Topographic contour-line texture — echoes the hero's mountain motif and
   gives every panel a bit of hand-drawn depth instead of a flat gradient. */
.project-pattern {
  position: absolute;
  top: -24%;
  left: 0;
  width: 100%;
  height: 148%;
  z-index: 1;
  opacity: 0.15;
  mix-blend-mode: overlay;
  background-repeat: repeat;
  background-size: 420px 420px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='420' viewBox='0 0 420 420'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='1'%3E%3Cpath d='M0,40 Q52,10 105,40 T210,40 T315,40 T420,40'/%3E%3Cpath d='M0,125 Q52,95 105,125 T210,125 T315,125 T420,125'/%3E%3Cpath d='M0,210 Q52,180 105,210 T210,210 T315,210 T420,210'/%3E%3Cpath d='M0,295 Q52,265 105,295 T210,295 T315,295 T420,295'/%3E%3Cpath d='M0,380 Q52,350 105,380 T210,380 T315,380 T420,380'/%3E%3C/g%3E%3C/svg%3E");
}

/* Giant ghost index number sitting behind the copy for editorial depth */
.project-ghost {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(9rem, 26vw, 22rem);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(243, 241, 234, 0.14);
  z-index: 1;
  pointer-events: none;
  user-select: none;
}

.project:nth-child(odd) .project-ghost { right: 2vw; }
.project:nth-child(even) .project-ghost { left: 2vw; }

.project-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(13,15,20,0.35) 0%, rgba(13,15,20,0.78) 100%);
  z-index: 2;
}

.project-content {
  position: relative;
  z-index: 3;
  width: min(34rem, 88vw);
  padding: 3rem;
  margin: 0 6vw;
}

.project-content.align-right { margin-left: auto; }
.project-content.align-left { margin-right: auto; }

.project-index {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 0.9rem;
  letter-spacing: 0.15em;
  color: var(--accent);
  margin-bottom: 1rem;
}

.project-title {
  font-size: clamp(2rem, 4vw, 3rem);
  margin-bottom: 1rem;
}

.project-desc {
  color: var(--ink-dim);
  margin-bottom: 1.5rem;
}

.project-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1.75rem;
}

.project-tags li {
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.35rem 0.75rem;
  border: 1px solid rgba(243,241,234,0.3);
  border-radius: 999px;
  color: var(--ink-dim);
}

.project-link {
  display: inline-block;
  font-weight: 500;
  font-size: 0.95rem;
  border-bottom: 1px solid var(--accent);
  color: var(--ink);
  padding-bottom: 2px;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.project-link:hover { opacity: 0.75; transform: translateX(4px); }

/* ============================================================
   UNDOSUS SUITE PANEL — one section, grouped app showcase
   ============================================================ */
/* Every project section shares a 100vh floor so they're all the same
   height. The panel content can still exceed one viewport (narrow screens,
   where the card grids stack), so the flex box top-aligns as a fallback and
   the content uses auto block margins: they centre it vertically when it
   fits and collapse to zero — pinning it below the 7rem gutter, never
   clipped — when it doesn't. */
.project--tall {
  align-items: flex-start;
  min-height: 100vh;
  height: auto;
  padding: 7rem 0;
}

.project--tall > .project-content {
  margin-top: auto;
  margin-bottom: auto;
}

.project-content--suite {
  width: min(72rem, 94vw);
  margin: 0 auto;
  padding: 3rem;
}

/* The intro copy sits on top; the three app cards form a responsive grid
   beneath it — the same visual language as the undosus.com homepage
   cards: a dark surface panel, a hairline gradient edge, a soft accent
   bloom, an icon tile, a mono eyebrow, chips and a tinted CTA button. */
.suite-grid {
  display: flex;
  flex-direction: column;
  gap: 2.75rem;
}

/* Wide screens: the dealt pile of app cards sits to the left of the
   intro copy. Source order is copy-then-deck (copy leads for reading
   order / no-CSS fallback), so swap them visually with `order`. */
@media (min-width: 900px) {
  .suite-grid {
    flex-direction: row;
    align-items: center;
    gap: 4rem;
  }
  .suite-grid .suite-deck {
    order: 1;
    flex: none;
    margin: 0;
  }
  .suite-grid .suite-copy {
    order: 2;
    flex: 1;
  }
}

.suite-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.1rem;
}

.suite-mark {
  flex-shrink: 0;
  width: 3rem;
  height: 3rem;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
}
.suite-mark svg { display: block; width: 100%; height: 100%; }

.suite-head .project-title { margin-bottom: 0; }
.suite-copy .project-index { margin-bottom: 0.6rem; }
.suite-copy .project-link { margin-top: 0.5rem; }
.suite-copy { max-width: 46rem; }

/* The three app cards sit in a stacked, offset pile — a dealt hand of
   cards. Each card behind the front one peeks up ~3.2rem (its icon tile
   shows) and is nudged aside and tilted. Hovering or focusing a card
   floats it to the top of the pile, straight and slightly enlarged;
   every hover move is upward, so the card never slides out from under
   the pointer (no flicker). Coarse-pointer / narrow screens get a plain
   readable column instead — see the fallback at the end of the block. */
.suite-deck {
  position: relative;
  width: min(19rem, 82vw);
  margin: 2rem auto 0.5rem;
  min-height: 37rem;
}

.suite-app {
  --c1: #a78bfa;
  --c2: #22d3ee;
  position: absolute;
  left: 50%;
  top: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  padding: 1.6rem;
  border-radius: 20px;
  background: #12161f;
  border: 1px solid rgba(255, 255, 255, 0.09);
  isolation: isolate;
  overflow: hidden;
  transition: transform 0.45s cubic-bezier(0.22, 0.9, 0.3, 1),
              filter 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}
.suite-app[data-app="beatsy"]  { --c1: #f97316; --c2: #fbbf24; }
.suite-app[data-app="sightly"] { --c1: #ec4899; --c2: #fb7185; }

/* Resting pile: front card lowest, the other two peeking above it. */
.suite-app:nth-child(1) { transform: translateX(-40%) translateY(11rem) rotate(-2deg);  z-index: 3; }
.suite-app:nth-child(2) { transform: translateX(-50%) translateY(5.5rem) rotate(1.5deg); z-index: 2; }
.suite-app:nth-child(3) { transform: translateX(-60%) translateY(0)      rotate(3.4deg); z-index: 1; }

/* Dim the cards not being read while the pile is active. */
.suite-deck:hover .suite-app:not(:hover):not(:focus-within),
.suite-deck:focus-within .suite-app:not(:hover):not(:focus-within) {
  filter: brightness(0.78) saturate(0.88);
}

/* Hairline gradient edge (mask-composite border trick). */
.suite-app::before {
  content: "";
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(140deg,
    color-mix(in srgb, var(--c1) 60%, transparent), transparent 42%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0.75;
  pointer-events: none;
}

/* Soft accent bloom, upper-right. */
.suite-app::after {
  content: "";
  position: absolute;
  top: -40%;
  right: -30%;
  width: 70%;
  height: 70%;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--c1) 60%, transparent), transparent 70%);
  filter: blur(12px);
  opacity: 0.3;
  z-index: -1;
  transition: opacity 0.35s ease;
}

/* Float the pointed-at card to the top of the pile — always an upward
   move, so the pointer stays over it. Placed after the :nth-child rules
   so it wins the equal-specificity tie. */
.suite-app:hover,
.suite-app:focus-within {
  transform: translateX(-50%) translateY(0) rotate(0deg) scale(1.03);
  z-index: 9;
  filter: none;
  border-color: color-mix(in srgb, var(--c1) 45%, rgba(255, 255, 255, 0.16));
  box-shadow: 0 30px 64px -22px color-mix(in srgb, var(--c1) 55%, transparent);
}
.suite-app:hover::after,
.suite-app:focus-within::after { opacity: 0.5; }

.suite-app-logo {
  display: block;
  width: 3rem;
  height: 3rem;
  flex-shrink: 0;
  border-radius: 14px;
  background: linear-gradient(155deg, #171c27, #0d1119);
  border: 1px solid rgba(255, 255, 255, 0.16);
  overflow: hidden;
  margin-bottom: 1.15rem;
}
.suite-app-logo svg { display: block; width: 100%; height: 100%; }

.suite-app-eyebrow {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c1);
  margin-bottom: 0.5rem;
}

.suite-app h4 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.35rem;
  color: var(--ink);
  margin-bottom: 0.6rem;
}

.suite-app > p {
  flex: 1;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--ink-dim);
}

.suite-app-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 1.15rem;
}
.suite-app-chips span {
  font-size: 0.72rem;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  background: #171c27;
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: var(--ink-dim);
}

.suite-app-link {
  margin-top: 1.4rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.8rem 1rem;
  border-radius: 12px;
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--c1) 20%, transparent),
    color-mix(in srgb, var(--c2) 15%, transparent));
  border: 1px solid color-mix(in srgb, var(--c1) 38%, rgba(255, 255, 255, 0.09));
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--ink);
  transition: gap 0.25s ease;
}
.suite-app-link svg { width: 15px; height: 15px; flex: none; transition: transform 0.25s ease; }
.suite-app-link:hover { gap: 1.1rem; }
.suite-app-link:hover svg { transform: translateX(3px); }

.project-desc a {
  color: var(--ink);
  border-bottom: 1px solid var(--accent);
}

@media (prefers-reduced-motion: reduce) {
  .suite-app, .suite-app::after, .suite-app-link, .suite-app-link svg { transition: none; }
}

/* Touch / narrow screens: the pile can't be hovered apart, so lay the
   cards out as a plain readable column. */
@media (hover: none), (max-width: 640px) {
  .suite-deck {
    width: min(22rem, 100%);
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 1.4rem;
  }
  .suite-app,
  .suite-app:nth-child(1),
  .suite-app:nth-child(2),
  .suite-app:nth-child(3) {
    position: static;
    width: 100%;
    transform: none;
  }
  .suite-deck:hover .suite-app:not(:hover):not(:focus-within),
  .suite-deck:focus-within .suite-app:not(:hover):not(:focus-within) { filter: none; }
  .suite-app:hover,
  .suite-app:focus-within { transform: translateY(-4px) scale(1); }
}

@media (max-width: 620px) {
  .project-content--suite { padding: 2rem 1.5rem; }
}

/* The swiper wrapper is transparent to layout except on mobile, where it
   becomes the positioning context for the swipe-hint arrow. */
.suite-swiper { display: contents; }

/* Mobile: the three app cards become a horizontal, snapping swipe
   carousel — exactly one card in view at a time. */
@media (max-width: 720px) {
  .project-content--suite { padding: 2rem 1.25rem; }
  .suite-swiper { display: block; position: relative; }
  .suite-deck {
    width: auto;
    max-width: none;
    min-height: 0;
    margin: 1.5rem 0 0;
    display: flex;
    flex-direction: row;
    gap: 1rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .suite-deck::-webkit-scrollbar { display: none; }
  .suite-app,
  .suite-app:nth-child(1),
  .suite-app:nth-child(2),
  .suite-app:nth-child(3) {
    position: static;
    transform: none;
    flex: 0 0 100%;
    max-width: none;
    scroll-snap-align: center;
  }
  /* the blurred corner bloom smudged into the gap between cards */
  .suite-app::after { display: none; }
  .suite-app:hover,
  .suite-app:focus-within { transform: none; }
  .suite-deck:hover .suite-app:not(:hover):not(:focus-within),
  .suite-deck:focus-within .suite-app:not(:hover):not(:focus-within) { filter: none; }
}

/* ============================================================
   GAMES PANEL — itch.io game-jam cards. Intro copy on top, a
   three-up grid of cover-art cards beneath it. Same surface
   language as the suite cards (dark panel, hairline edge, accent
   lift on hover) but each card is a single link, cover-art led.
   ============================================================ */
.project-content--games {
  width: min(72rem, 94vw);
  margin: 0 auto;
  padding: 3rem;
}

.games-head {
  max-width: 46rem;
  margin-bottom: 2.75rem;
}
.games-head .project-index { margin-bottom: 0.6rem; }
.games-head .project-desc { margin-bottom: 1rem; }
.games-head em { font-style: normal; color: var(--ink); }

.games-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem;
  font-family: var(--font-display);
  font-size: 0.9rem;
}
.games-links a {
  color: var(--ink);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 2px;
  transition: opacity 0.2s ease;
}
.games-links a:hover { opacity: 0.7; }

.games-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  list-style: none;
}

.game-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: 18px;
  background: #12161f;
  border: 1px solid rgba(255, 255, 255, 0.09);
  overflow: hidden;
  color: var(--ink);
  transition: transform 0.35s cubic-bezier(0.22, 0.9, 0.3, 1),
              border-color 0.35s ease, box-shadow 0.35s ease;
}
.game-card:hover,
.game-card:focus-visible {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--accent) 45%, rgba(255, 255, 255, 0.16));
  box-shadow: 0 26px 54px -24px color-mix(in srgb, var(--accent) 55%, transparent);
}

.game-card img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 63 / 50;
  object-fit: cover;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}

.game-card-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 1.4rem;
}

.game-card-genre {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.5rem;
}

.game-card h4 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.25rem;
  margin-bottom: 0.55rem;
}

.game-card p {
  flex: 1;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ink-dim);
}

.game-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 1.1rem;
}
.game-card-meta span {
  font-size: 0.7rem;
  padding: 0.28rem 0.58rem;
  border-radius: 999px;
  background: #171c27;
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: var(--ink-dim);
}

.game-card-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 1.2rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--accent);
}
.game-card-cta svg { width: 14px; height: 14px; flex: none; transition: transform 0.25s ease; }
.game-card:hover .game-card-cta svg { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .game-card, .game-card-cta svg { transition: none; }
  .game-card:hover, .game-card:focus-visible { transform: none; }
}

@media (max-width: 860px) {
  .games-grid { grid-template-columns: 1fr; max-width: 24rem; }
  .games-head { margin-bottom: 2rem; }
}

@media (max-width: 620px) {
  .project-content--games { padding: 2rem 1.5rem; }
}

.games-swiper { position: relative; }

/* Mobile: the cover-art cards become a horizontal, snapping swipe
   carousel — one card in view at a time, matching the Undosus suite. */
@media (max-width: 720px) {
  .project-content--games { padding: 2rem 1.25rem; }
  .games-grid {
    display: flex;
    grid-template-columns: none;
    max-width: none;
    gap: 1rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .games-grid::-webkit-scrollbar { display: none; }
  .games-grid > li {
    display: flex;
    flex: 0 0 100%;
    max-width: none;
    scroll-snap-align: center;
  }
  .games-grid > li > .game-card { width: 100%; }
}

/* Swipe affordance: a small accent chevron at the middle-right of each
   mobile carousel that fades in and out, nudging toward the next card.
   It disappears for good once the visitor scrolls the carousel (.is-scrolled). */
@media (max-width: 720px) {
  .suite-swiper::after,
  .games-swiper::after {
    content: "";
    position: absolute;
    top: 50%;
    right: -0.4rem;
    margin-top: -0.775rem;
    width: 1.55rem;
    height: 1.55rem;
    border-radius: 50%;
    background-color: rgba(13, 15, 20, 0.74);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23e8b04b' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 5l8 7-8 7'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 46% center;
    background-size: 56%;
    box-shadow: 0 0 10px 2px rgba(232, 176, 75, 0.3);
    pointer-events: none;
    z-index: 5;
    animation: swipeHint 2.4s ease-in-out infinite;
  }

  .suite-swiper.is-scrolled::after,
  .games-swiper.is-scrolled::after { display: none; }
}

@keyframes swipeHint {
  0%, 100% { opacity: 0; transform: translateX(2px); }
  20%      { opacity: 0.9; transform: translateX(0); }
  55%      { opacity: 0; transform: translateX(11px); }
}

@media (prefers-reduced-motion: reduce) {
  .suite-swiper::after,
  .games-swiper::after { animation: none; opacity: 0.55; transform: none; }
}

/* ============================================================
   CAREER — "tools & platforms" stack: square tiles grouped by
   category into horizontal, swipeable rows, sitting under the
   certification badges. Each row carries a small monospace
   category label ("badge"); the tiles are monochrome brand
   glyphs over a label, on a dark surface that lifts and tints
   to the accent on hover.
   ============================================================ */
/* Stacked column by default: one full-width category row after another.
   Each row shows all its tiles down to ~600px, then scrolls. */
.stack-cats {
  display: flex;
  flex-direction: column;
  gap: 1.35rem;
  max-width: 46rem;
  margin: 2.25rem auto 0;
  padding: 0 1.25rem;
}

/* Web view: enough width for two full category rows side by side, so
   the categories sit in a 2×2 grid with every tile visible (no clipping).
   Columns are sized to the widest row's content. */
@media (min-width: 1080px) {
  .stack-cats {
    display: grid;
    grid-template-columns: repeat(2, max-content);
    justify-content: center;
    align-items: start;
    column-gap: 2.5rem;
    max-width: none;
  }
}

.stack-cat-label {
  display: block;
  text-align: center;
  margin-bottom: 0.55rem;
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(243, 241, 234, 0.42);
}

.stack-swiper { position: relative; }

/* One category = one row that never wraps; it scrolls horizontally
   (touch-swipe / trackpad) when the tiles overrun the row width. */
.stack-row {
  list-style: none;
  display: flex;
  justify-content: safe center;
  gap: 0.7rem;
  margin: 0;
  padding: 0.15rem 0.15rem 0.55rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.stack-row::-webkit-scrollbar { display: none; }
.stack-row > .stack-tile {
  flex: 0 0 auto;
  scroll-snap-align: start;
}

.stack-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 5.4rem;
  height: 5.4rem;
  padding: 0.55rem;
  border-radius: 14px;
  background: rgba(18, 22, 31, 0.72);
  border: 1px solid rgba(243, 241, 234, 0.14);
  text-align: center;
  transition: transform 0.3s cubic-bezier(0.22, 0.9, 0.3, 1),
              border-color 0.3s ease, background 0.3s ease;
}
.stack-tile:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: rgba(18, 22, 31, 0.92);
}

.stack-ico {
  width: 1.6rem;
  height: 1.6rem;
  color: var(--ink);
  opacity: 0.9;
  transition: color 0.3s ease, opacity 0.3s ease;
}
.stack-ico svg { display: block; width: 100%; height: 100%; }
.stack-tile:hover .stack-ico { color: var(--accent); opacity: 1; }

.stack-tile > span:last-child {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.15;
  color: var(--ink-dim);
}

@media (prefers-reduced-motion: reduce) {
  .stack-tile { transition: none; }
  .stack-tile:hover { transform: none; }
}

@media (max-width: 620px) {
  .stack-tile { width: 4.7rem; height: 4.7rem; }
  .stack-ico { width: 1.4rem; height: 1.4rem; }
}

/* ============================================================
   MEALBOX PANEL — "rakugaki" doodle cards
   The vocabulary is lifted straight from the app's own hand-drawn
   skin: warm dot-grid paper, a border drawn twice by hand (dashed
   outer + tilted inner stroke), wobbly asymmetric radii, sparkle
   stickers, gentle tilts and Shantell Sans hand-lettering.
   ============================================================ */
.project-content--mealbox {
  width: min(62rem, 94vw);
  margin: 0 auto;
  padding: 3rem;
}

.mb-grid {
  display: flex;
  flex-direction: column-reverse;
  gap: 2.5rem;
}

@media (min-width: 880px) {
  .mb-grid {
    flex-direction: row;
    align-items: center;
    gap: 4rem;
  }
  .mb-copy  { flex: 1 1 auto; }
  .mb-stack { flex: 0 0 44%; }
}

/* Mobile: let the copy's children flow directly into the grid so the
   order becomes index → title → description → chips → link → card stack. */
@media (max-width: 879px) {
  .mb-grid { flex-direction: column; gap: 0; }
  .mb-copy { display: contents; }
  .mb-copy > .project-index { order: 1; }
  .mb-copy > .suite-head    { order: 2; }
  .mb-copy > .project-desc  { order: 3; }
  .mb-copy > .project-tags  { order: 4; }
  .mb-copy > .project-link  { order: 5; align-self: flex-start; }
  .mb-stack                 { order: 6; }
}

/* ---- the doodle card stack ---- */
.mb-stack {
  --rk-paper: #fffdf6;
  --rk-ink: #16181a;
  --rk-ink-soft: #4b5259;
  --rk-green: #2f9e64;
  --rk-green-200: #bce6cc;
  --rk-green-100: #dcf2e3;
  --rk-line: #e3ded1;
  --rk-font: 'Shantell Sans', 'Bradley Hand', 'Segoe Print', cursive;
  --rk-sparkle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0c1.1 6.6 4.8 10.3 12 12-7.2 1.7-10.9 5.4-12 12-1.1-6.6-4.8-10.3-12-12 7.2-1.7 10.9-5.4 12-12z'/%3E%3C/svg%3E");
  --rk-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232f9e64' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 13l5 6L20 5'/%3E%3C/svg%3E");
  position: relative;
  width: min(21rem, 82vw);
  margin: 2.75rem auto 6.5rem;
}

/* Stacked (mobile/tablet) layout: match the undosus panel's gap between the
   project link and the cards — its grid gap (2.75rem) plus deck margin
   (1.5rem) ≈ 4.25rem. The recipe card is nudged ~1.7rem above the stack's
   top edge, so add that back to keep the visible gap equal. */
@media (max-width: 879px) {
  .mb-stack { margin-top: 6rem; }
}

.mb-card {
  padding: 1.4rem 1.5rem 1.6rem;
  background-color: var(--rk-paper);
  background-image: radial-gradient(var(--rk-line) 1.3px, transparent 1.3px);
  background-size: 17px 17px;
  background-position: -8px -8px;
  border: 2px dashed var(--rk-green-200);
  border-radius: 22px 14px 20px 12px / 14px 20px 12px 22px;
  color: var(--rk-ink-soft);
  font-family: var(--rk-font);
  box-shadow: 0 26px 50px -18px rgba(0, 0, 0, 0.55);
}

/* second pen stroke — mirrored wobble, slight rotation */
.mb-card::before {
  content: "";
  position: absolute;
  inset: 7px;
  border: 2px solid var(--rk-green-200);
  border-radius: 12px 20px 14px 22px / 22px 14px 20px 12px;
  opacity: 0.5;
  transform: rotate(0.7deg);
  pointer-events: none;
}

/* twinkling sparkle scribble, upper-right */
.mb-card::after {
  content: "";
  position: absolute;
  top: 13px;
  right: 15px;
  width: 20px;
  height: 20px;
  background: var(--rk-green);
  -webkit-mask: var(--rk-sparkle) center / contain no-repeat;
  mask: var(--rk-sparkle) center / contain no-repeat;
  animation: mbTwinkle 3.4s ease-in-out infinite;
  pointer-events: none;
}

.mb-card--list {
  position: relative;
  z-index: 2;
  transform: rotate(-2.5deg);
}
.mb-card--recipe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 1;
  transform: translate(1.9rem, -1.7rem) rotate(5deg);
}
.mb-card--recipe::after { animation-delay: 1.1s; }

.mb-card-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 1rem;
}

.mb-badge {
  flex-shrink: 0;
  width: 2.3rem;
  height: 2.3rem;
  display: grid;
  place-items: center;
  color: #fff;
  background: var(--rk-green);
  border-radius: 62% 38% 55% 45% / 55% 52% 48% 45%;
  transform: rotate(-6deg);
  box-shadow: 0 0 0 3px var(--rk-paper), 0 0 0 5px var(--rk-green-200);
}
.mb-badge svg {
  width: 1.15rem;
  height: 1.15rem;
  transform: rotate(6deg);
}

.mb-card-head h4 {
  font-family: var(--rk-font);
  font-weight: 700;
  font-size: 1.2rem;
  color: var(--rk-ink);
}

.mb-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.mb-list li {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-size: 0.95rem;
  color: var(--rk-ink);
}
.mb-check {
  flex-shrink: 0;
  width: 1.2rem;
  height: 1.2rem;
  border: 2px dashed var(--rk-green);
  border-radius: 7px 4px 6px 3px / 3px 6px 4px 7px;
}
.mb-list li.done .mb-check {
  border-style: solid;
  background-color: var(--rk-green-100);
  background-image: var(--rk-check);
  background-size: 90% 90%;
  background-position: center;
  background-repeat: no-repeat;
}
.mb-list li.done span:last-child {
  text-decoration: line-through wavy var(--rk-green);
  color: var(--rk-ink-soft);
  opacity: 0.7;
}

.mb-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.mb-pill {
  font-size: 0.8rem;
  padding: 0.2rem 0.7rem;
  color: var(--rk-ink-soft);
  border: 1.5px dashed var(--rk-green);
  border-radius: 40px 16px 34px 18px / 18px 34px 16px 40px;
}

/* ---- ingredient-library ("pantry") card ----
   Peeks out to the lower-right of the pile: a hand-drawn search pill
   with a recipe count, over a two-column grid of ingredient tiles. */
.mb-card--pantry {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 3;
  transform: translate(2.75rem, 2.8rem) rotate(3deg);
}
.mb-card--pantry::after { animation-delay: 0.5s; }

/* Roomy viewports: fan the pantry card further out to the right so more
   of the two cards behind it stays visible. */
@media (min-width: 1024px) {
  .mb-card--pantry { transform: translate(5.5rem, 3.1rem) rotate(3deg); }
}

.mb-search {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.9rem;
  padding: 0.38rem 0.42rem 0.38rem 0.9rem;
  font-size: 0.82rem;
  color: var(--rk-ink-soft);
  border: 1.5px dashed var(--rk-green);
  border-radius: 40px 18px 34px 16px / 16px 34px 18px 40px;
}
.mb-count {
  flex-shrink: 0;
  min-width: 1.5rem;
  padding: 0.08rem 0.4rem;
  text-align: center;
  color: #fff;
  background: var(--rk-green);
  border-radius: 52% 45% 55% 48% / 48% 55% 45% 52%;
  font-size: 0.78rem;
}

.mb-pantry {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}
.mb-pantry li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  padding: 0.7rem 0.4rem;
  text-align: center;
  background: var(--rk-green-100);
  border: 1.5px dashed var(--rk-green-200);
  border-radius: 16px 10px 14px 8px / 8px 14px 10px 16px;
}
.mb-pantry-ico {
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  font-size: 1.1rem;
  line-height: 1;
  background: var(--rk-paper);
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--rk-green-200);
}
.mb-pantry-name {
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.15;
  color: var(--rk-ink);
}
.mb-pantry-sub {
  font-size: 0.68rem;
  color: var(--rk-ink-soft);
  opacity: 0.75;
}

@keyframes mbTwinkle {
  0%, 100% { opacity: 0.3; transform: scale(0.8) rotate(-8deg); }
  50%      { opacity: 0.9; transform: scale(1) rotate(12deg); }
}

@media (prefers-reduced-motion: reduce) {
  .mb-card::after { animation: none; opacity: 0.7; }
}

@media (max-width: 620px) {
  .project-content--mealbox { padding: 2rem 1.5rem; }
  /* Narrow screens: keep the card stack inside the padded column so it
     stays centred, and tuck the pantry card straight down so it stays
     within the panel and clear of the copy stacked below it. */
  .mb-stack { width: min(21rem, 100%); margin-bottom: 8rem; }
  .mb-card--recipe { transform: translate(1.2rem, -1.7rem) rotate(5deg); }
  .mb-card--pantry { transform: translate(0.4rem, 1.9rem) rotate(3deg); }
}

/* Distinct placeholder "mesh gradient" per project — layered radial
   highlights over a base linear-gradient, for a richer, less flat field
   than a single gradient. Swap for a real image later by replacing the
   whole background-image with url('../assets/your-image.jpg'). */
.proj-1 .project-bg {
  background-image:
    radial-gradient(at 18% 22%, rgba(150, 195, 230, 0.55) 0px, transparent 55%),
    radial-gradient(at 85% 8%, rgba(76, 126, 166, 0.65) 0px, transparent 50%),
    radial-gradient(at 15% 88%, rgba(15, 25, 38, 0.85) 0px, transparent 55%),
    radial-gradient(at 92% 92%, rgba(100, 150, 190, 0.4) 0px, transparent 55%),
    linear-gradient(155deg, #1f3a5f, #101c2c 75%);
}
.proj-2 .project-bg {
  background-image:
    radial-gradient(at 18% 20%, rgba(150, 225, 195, 0.5) 0px, transparent 55%),
    radial-gradient(at 86% 10%, rgba(76, 166, 132, 0.6) 0px, transparent 50%),
    radial-gradient(at 14% 90%, rgba(12, 28, 22, 0.85) 0px, transparent 55%),
    radial-gradient(at 90% 90%, rgba(100, 190, 155, 0.4) 0px, transparent 55%),
    linear-gradient(155deg, #1f3d33, #0d1b16 75%);
}
.proj-3 .project-bg {
  background-image:
    radial-gradient(at 20% 18%, rgba(230, 160, 190, 0.5) 0px, transparent 55%),
    radial-gradient(at 88% 12%, rgba(166, 76, 110, 0.6) 0px, transparent 50%),
    radial-gradient(at 12% 90%, rgba(30, 12, 22, 0.85) 0px, transparent 55%),
    radial-gradient(at 90% 88%, rgba(180, 100, 130, 0.4) 0px, transparent 55%),
    linear-gradient(155deg, #3d1f2e, #170d13 75%);
}
.proj-4 .project-bg {
  background-image:
    radial-gradient(at 20% 18%, rgba(230, 200, 150, 0.5) 0px, transparent 55%),
    radial-gradient(at 88% 10%, rgba(166, 132, 76, 0.6) 0px, transparent 50%),
    radial-gradient(at 14% 90%, rgba(30, 22, 12, 0.85) 0px, transparent 55%),
    radial-gradient(at 90% 88%, rgba(190, 155, 100, 0.4) 0px, transparent 55%),
    linear-gradient(155deg, #3d321f, #1c150c 75%);
}
.proj-5 .project-bg {
  background-image:
    radial-gradient(at 18% 20%, rgba(200, 165, 230, 0.5) 0px, transparent 55%),
    radial-gradient(at 86% 10%, rgba(122, 76, 166, 0.6) 0px, transparent 50%),
    radial-gradient(at 14% 90%, rgba(22, 12, 30, 0.85) 0px, transparent 55%),
    radial-gradient(at 90% 90%, rgba(160, 110, 195, 0.4) 0px, transparent 55%),
    linear-gradient(155deg, #2a1f3d, #130d1c 75%);
}
.proj-6 .project-bg {
  background-image:
    radial-gradient(at 18% 20%, rgba(150, 200, 230, 0.5) 0px, transparent 55%),
    radial-gradient(at 86% 10%, rgba(76, 132, 166, 0.6) 0px, transparent 50%),
    radial-gradient(at 14% 90%, rgba(12, 20, 30, 0.85) 0px, transparent 55%),
    radial-gradient(at 90% 90%, rgba(100, 160, 190, 0.4) 0px, transparent 55%),
    linear-gradient(155deg, #1f2e3d, #0c141d 75%);
}

/* ============================================================
   SCROLL-REVEAL
   ============================================================ */
.reveal {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.reveal.in-view {
  opacity: 1;
  transform: translateY(0);
}

/* ============================================================
   CONTACT
   ============================================================ */
.contact {
  min-height: 80vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 6rem 8vw;
  background: linear-gradient(180deg, var(--bg), #05060a);
}

.contact h2 {
  font-size: clamp(2rem, 5vw, 3.5rem);
  margin-bottom: 1.75rem;
}

.social-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  justify-content: center;
  margin-bottom: 3rem;
}

.social-links a {
  font-size: 0.95rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 3px;
  transition: color 0.2s ease;
}

.social-links a:hover { color: var(--ink); }

.footer-note {
  font-size: 0.8rem;
  color: rgba(243,241,234,0.4);
}

/* ============================================================
   CONTACT "CAVERN" — the harp is playable. Each string carries
   a note (C-major pentatonic); plucking it sounds the note via
   Web Audio and releases a luminescent mote that drifts up the
   cave. Strings + mote layer are built in js/main.js.
   ============================================================ */
.contact {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(115% 75% at 50% 118%, rgba(232, 176, 75, 0.12), transparent 62%),
    radial-gradient(85% 55% at 12% -8%, rgba(78, 96, 130, 0.16), transparent 55%),
    radial-gradient(80% 55% at 92% -4%, rgba(44, 62, 92, 0.16), transparent 55%),
    linear-gradient(180deg, var(--bg), #05060a);
}

.contact::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 180px 30px rgba(0, 0, 0, 0.55);
}

.contact-inner {
  position: relative;
  z-index: 2;
}

.harp-motes {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
}

.harp-mote {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff, var(--accent) 45%, rgba(232, 176, 75, 0) 72%);
  box-shadow: 0 0 12px 2px rgba(232, 176, 75, 0.55), 0 0 32px 8px rgba(232, 176, 75, 0.22);
  opacity: 0;
  will-change: transform, opacity;
  animation: moteFloat var(--dur, 7000ms) ease-out forwards;
}

@keyframes moteFloat {
  0%   { transform: translate(0, 0) scale(0.35); opacity: 0; }
  12%  { opacity: 1; }
  70%  { opacity: 0.9; }
  100% { transform: translate(var(--driftX, 0px), var(--rise, -220px)) scale(0.7); opacity: 0; }
}

@keyframes moteGlow {
  0%   { opacity: 0; transform: scale(0.5); }
  22%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1); }
}

.harp-play {
  margin: 0 auto 2.75rem;
  width: min(21rem, 72vw);
}

.harp-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  user-select: none;
  -webkit-user-select: none;
}

/* --- frame ------------------------------------------------- */
.harp-guide { fill: none; stroke: none; }

.harp-body { fill: url(#harpWood); stroke: none; }

.harp-seam {
  fill: none;
  stroke: rgba(232, 176, 75, 0.22);
  stroke-width: 1.3;
}

.harp-frame {
  fill: none;
  stroke: var(--accent);
  stroke-width: 5.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.harp-column { stroke-width: 7; }
.harp-neck   { stroke-width: 6; }
.harp-rib    { stroke-width: 3.6; opacity: 0.85; }
.harp-foot   { stroke-width: 7; }

.harp-foot-base {
  stroke: var(--accent);
  stroke-width: 7;
  stroke-linecap: round;
}

.harp-pin { fill: var(--accent); opacity: 0.8; }

/* --- strings ---------------------------------------------- */
.harp-string {
  fill: none;
  stroke: rgba(243, 241, 234, 0.30);
  stroke-width: 1.2;
  stroke-linecap: round;
  transition: stroke 0.28s ease, stroke-width 0.28s ease, filter 0.28s ease;
}

.harp-hit {
  stroke: transparent;
  stroke-width: 16;
  cursor: pointer;
  touch-action: none;
  outline: none;
}

.harp-str:hover .harp-string,
.harp-str:focus-within .harp-string {
  stroke: var(--accent);
  stroke-width: 2;
}

.harp-str:focus-within .harp-string {
  filter: drop-shadow(0 0 5px rgba(232, 176, 75, 0.8));
}

.harp-string.is-plucked {
  stroke: rgba(255, 255, 255, 0.95);
  stroke-width: 1.8;
  filter: drop-shadow(0 0 3px rgba(232, 176, 75, 0.75));
  transition: none;
}

.harp-hint {
  margin-bottom: 1rem;
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

@media (prefers-reduced-motion: reduce) {
  .harp-mote { animation-name: moteGlow; animation-duration: 2.6s; }
}

/* ============================================================
   RESPONSIVE / ACCESSIBILITY
   ============================================================ */
@media (max-width: 800px) {
  .project-content { margin: 0 auto; }
  .site-header { padding: 20px 6vw; }
  .project-ghost { opacity: 0.5; font-size: clamp(6rem, 34vw, 12rem); }
  .hero-birds { display: none; }
}

/* Phones: tighten the generous desktop padding so panels don't waste
   most of a narrow screen on empty margins. */
@media (max-width: 620px) {
  .project-content { width: min(34rem, 92vw); padding: 2rem 1.5rem; }
  .project--tall { padding: 4rem 0; }
  .about { padding: 6rem 8vw; }
  .career { padding: 6rem 0; }
  .work-cat { padding: 5rem 8vw; }
  .contact { padding: 5rem 8vw; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero-layer, .hero-content, .project-bg, .project-pattern, .project-ghost { transform: none !important; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .scroll-cue span::after,
  .hero-stars,
  .hero-stars::before,
  .hero-stars::after,
  .shooting-star,
  .cloud-1, .cloud-2, .cloud-3, .cloud-4, .cloud-5,
  .bird-1, .bird-2, .bird-3 {
    animation: none;
  }
  .shooting-star { display: none; }
}
