/* ============================================================
   ASTRA — original creative-studio site inspired by lusion.co
   ============================================================ */

/* ---------------- typefaces ----------------
   Latin faces carry the display voice; the CJK faces are subset down to the
   ~320 glyphs this site renders (rebuild via tools/subset-fonts.py after any
   copy edit, or new characters will drop to a system fallback). */

/* Latin fallback for anyone not on an Apple device. Inter is the closest
   open face to SF Pro: same tall x-height and open apertures, so the two
   sit at nearly the same optical size and the layout does not reflow. */
@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans SC";
  src: url("../fonts/noto-sans-sc-300.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans SC";
  src: url("../fonts/noto-sans-sc-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
/* Noto Sans SC carries no kana at all, so Japanese needs its own face or every
   hiragana and katakana falls back to whatever the OS happens to have. */
@font-face {
  font-family: "Noto Sans JP";
  src: url("../fonts/noto-sans-jp-300.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans JP";
  src: url("../fonts/noto-sans-jp-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
/* Hangul is in neither of the faces above, so Korean needs a third family. */
@font-face {
  font-family: "Noto Sans KR";
  src: url("../fonts/noto-sans-kr-300.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("../fonts/noto-sans-kr-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

:root {
  --bg: #0b0d16;
  --ink: #eceae4;
  --muted: rgba(236, 234, 228, 0.55);
  --faint: rgba(236, 234, 228, 0.14);
  /* one restrained champagne gold carries every accent on the site */
  --accent: #c9a86b;
  /* same red as the astronaut's mission stripes */
  --cursor: #e04545;
  /* Two curves for the whole site. Both start almost instantly and brake
     hard, which is what makes interface motion read as snappy rather than
     floaty. --ease drives interface feedback, --ease-long drives reveals. */
  --ease: cubic-bezier(0.4, 0, 0.1, 1);
  --ease-long: cubic-bezier(0.35, 0, 0, 1);
  /* One family runs the whole site — nav, body, headings alike — with the
     weight ceiling held at 500. Mono is the utility voice for meta labels. */
  /* Apple's own faces come first, so Mac and iOS visitors render in the real
     SF Pro and PingFang straight from their own machine. Those files cannot be
     self-hosted -- Apple's licence covers mock-ups of Apple-platform UI only --
     so everyone else falls through to Inter and Source Han. */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
          "Inter", "PingFang SC", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  /* Headlines prefer the display cut, which is tracked tighter by design. */
  --display: "SF Pro Display", -apple-system, BlinkMacSystemFont,
             "Inter", "PingFang SC", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  /* The tiny tracked-out labels stay on a self-hosted face on purpose: a bare
     ui-monospace would resolve differently on every OS and they are too small
     to survive that much variation. */
  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
}

/* Japanese swaps the CJK tail of the stack: PingFang and Source Han SC would
   either miss the kana or render kanji in mainland forms. */
body[data-lang="ja"] {
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
          "Inter", "Hiragino Sans", "Noto Sans JP", "Yu Gothic", sans-serif;
  --display: "SF Pro Display", -apple-system, BlinkMacSystemFont,
             "Inter", "Hiragino Sans", "Noto Sans JP", "Yu Gothic", sans-serif;
}

body[data-lang="ko"] {
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
          "Inter", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", sans-serif;
  --display: "SF Pro Display", -apple-system, BlinkMacSystemFont,
             "Inter", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", sans-serif;
}

/* ---------------- per-character headline reveal ----------------
   Each glyph sits in a clipping mask so it can rise from below. The masks
   need a little vertical slack or descenders get sheared off. */

.ch {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.ch > span {
  display: inline-block;
  transform: translateY(110%);
  transition: transform 0.62s var(--ease-long);
  will-change: transform;
}
/* holds a Latin word's glyph masks together so a line never breaks mid-word */
.wd { white-space: nowrap; }
body.ready .hero__title .ch > span,
.statpanel.on .ch > span,
.levelcard.show .ch > span,
[data-reveal].is-in .ch > span { transform: translateY(0); }

/* Utility voice: every small tracked label and piece of metadata runs in the
   mono, which keeps the sans reserved for headlines and prose. */
.hero__meta, .hero__foot, .section-label,
.credits__services-head, .footer__lead, .footer__grid h5, .footer__small,
.hud__mission-tag, .hud__hint, .levelcard__tag, .levelcard__en,
.titlecard__eyebrow, .nav__menu, .btn-pill, .pill em, .bizrail__item em,
.menu-overlay__list em, .preloader__label, .skip {
  font-family: var(--mono);
}

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

html { scrollbar-width: none; }
html::-webkit-scrollbar, body::-webkit-scrollbar { display: none; }

html, body { overscroll-behavior: none; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  user-select: none;
  -webkit-user-select: none;
}

body.loading { overflow: hidden; height: 100vh; }

a { color: inherit; text-decoration: none; }
ul { list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; }

a, button, .project-item, [data-scroll] { cursor: pointer; }

/* ---------------- custom cursor ----------------
   Only on real pointers: touch devices keep the native behaviour and the
   element stays hidden. The dot is pinned to the pointer, the ring lags a
   few frames behind, which is what gives the motion its weight. */

.cursor { display: none; }

@media (hover: hover) and (pointer: fine) {
  body, a, button, .project-item, [data-scroll] { cursor: none; }

  .cursor {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s var(--ease);
  }
  body.ready .cursor { opacity: 1; }

  .cursor-dot,
  .cursor-ring,
  .cursor-burst {
    position: absolute;
    top: 0;
    left: 0;
    border-radius: 50%;
    will-change: transform;
  }

  /* Click feedback in the DOM layer: a ring that expands and thins out. The
     screen-space shockwave in the water carries the same click, so the two
     land together.

     The click position arrives as custom properties so the keyframe can own
     the transform outright -- mixing it with a JS-written transform on the same
     element would scale the translation along with the ring. */
  .cursor-burst {
    width: 26px;
    height: 26px;
    margin: -13px 0 0 -13px;
    border: 1px solid var(--cursor);
    opacity: 0;
  }
  .cursor-burst.on { animation: cursorBurst 0.6s var(--ease) forwards; }
  @keyframes cursorBurst {
    0% {
      opacity: 0.9;
      border-width: 2px;
      transform: translate3d(var(--bx, 0), var(--by, 0), 0) scale(0.35);
    }
    100% {
      opacity: 0;
      border-width: 0.5px;
      transform: translate3d(var(--bx, 0), var(--by, 0), 0) scale(3.2);
    }
  }

  .cursor-dot {
    width: 6px;
    height: 6px;
    margin: -3px 0 0 -3px;
    background: var(--cursor);
  }

  .cursor-ring {
    width: 34px;
    height: 34px;
    margin: -17px 0 0 -17px;
    border: 1px solid var(--cursor);
    /* scale/opacity animate on hover, translate is written every frame by JS */
    transition: width 0.35s var(--ease), height 0.35s var(--ease),
                margin 0.35s var(--ease), opacity 0.35s var(--ease),
                background 0.35s var(--ease);
  }

  /* over anything clickable the ring opens up and fills faintly */
  body.cursor-hot .cursor-ring {
    width: 56px;
    height: 56px;
    margin: -28px 0 0 -28px;
    background: rgba(224, 69, 69, 0.12);
  }
  body.cursor-hot .cursor-dot { opacity: 0; }

  /* pressed: the ring snaps in */
  body.cursor-down .cursor-ring {
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
  }
}

/* Static fallback when WebGL is unavailable */
body.no-webgl {
  background:
    radial-gradient(1200px 700px at 70% 20%, #1d2440 0%, transparent 60%),
    radial-gradient(900px 600px at 20% 80%, #241a2e 0%, transparent 55%),
    var(--bg);
}

/* ---------------- fixed layers ---------------- */

#webgl {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
}
body.no-webgl #webgl { display: none; }

.noise {
  position: fixed;
  inset: -50%;
  z-index: 40;
  pointer-events: none;
  opacity: 0.055;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.scroll-content {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 1;
  will-change: transform;
}

/* ---------------- preloader ---------------- */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 900;
  background: #07080d;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.55s var(--ease), visibility 0s linear 0.55s;
}
body.ready .preloader { transform: translateY(-100%); visibility: hidden; }

.preloader__inner { text-align: center; width: min(70vw, 520px); }

.preloader__count {
  font-size: clamp(5rem, 16vw, 12rem);
  font-weight: 500;
  letter-spacing: -0.04em;
  line-height: 1;
}
.preloader__count::after { content: "%"; font-size: 0.35em; vertical-align: super; color: var(--accent); }

.preloader__bar {
  height: 1px;
  background: var(--faint);
  margin: 2.2rem 0 1.2rem;
  overflow: hidden;
}
.preloader__bar span {
  display: block;
  height: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}

.preloader__label {
  font-size: 0.68rem;
  letter-spacing: 0.35em;
  color: var(--muted);
}

/* ---------------- navigation ---------------- */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.6rem 3rem;
  mix-blend-mode: difference;
}

.nav__brand {
  font-size: 1.3rem;
  font-weight: 500;
  letter-spacing: 0.02em;
}
.nav__brand sup { font-size: 0.55em; font-weight: 400; }

.nav__right { display: flex; align-items: center; gap: 1.6rem; }

/* ---------------- language switch ----------------
   Sits inside the nav, so it inherits mix-blend-mode: difference and stays
   legible over both the dark 3D stage and any lighter frame behind it. */

.langswitch { display: flex; align-items: center; gap: 0.15rem; }
.langswitch button {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  line-height: 1;
  padding: 0.75em 0.7em;
  color: var(--muted);
  border-radius: 999px;
  transition: color 0.3s var(--ease), background 0.3s var(--ease);
}
.langswitch button.on { color: var(--ink); background: rgba(236, 234, 228, 0.12); }
@media (hover: hover) and (pointer: fine) {
  .langswitch button:hover { color: var(--ink); }
}

.nav__menu {
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  font-weight: 500;
  padding: 0.6em 0;
}
.nav__menu-close { display: none; }
body.menu-open .nav__menu-open { display: none; }
body.menu-open .nav__menu-close { display: inline; }

.btn-pill {
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  font-weight: 500;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 0.85em 1.7em;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}
.btn-pill:hover { background: #fff; color: #000; }

/* ---------------- menu overlay ---------------- */

.menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(9, 10, 17, 0.97);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 8vw;
  transform: translateY(-102%);
  transition: transform 0.45s var(--ease);
}
body.menu-open .menu-overlay { transform: translateY(0); }

.menu-overlay__list li { overflow: hidden; border-bottom: 1px solid var(--faint); }

.menu-overlay__list a {
  display: block;
  font-family: var(--display);
  font-size: clamp(2.6rem, 9vw, 7rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.25;
  padding: 0.6rem 0;
  transform: translateY(110%);
  transition: transform 0.5s var(--ease), color 0.3s;
}
body.menu-open .menu-overlay__list li:nth-child(1) a { transform: translateY(0); transition-delay: 0.10s; }
body.menu-open .menu-overlay__list li:nth-child(2) a { transform: translateY(0); transition-delay: 0.17s; }
body.menu-open .menu-overlay__list li:nth-child(3) a { transform: translateY(0); transition-delay: 0.24s; }
body.menu-open .menu-overlay__list li:nth-child(4) a { transform: translateY(0); transition-delay: 0.31s; }

.menu-overlay__list a:hover { color: var(--accent); }
.menu-overlay__list em {
  font-style: normal;
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.3em;
  vertical-align: super;
  margin-right: 1.4rem;
  color: var(--muted);
}

.menu-overlay__foot {
  position: absolute;
  bottom: 2.4rem;
  left: 8vw;
  font-size: 0.68rem;
  letter-spacing: 0.35em;
  color: var(--muted);
}

/* ---------------- hero ---------------- */

.hero {
  position: relative;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 7.5rem 3rem 2.6rem;
  pointer-events: none; /* let the astronaut receive drags */
}

.hero__meta {
  display: flex;
  justify-content: space-between;
  font-size: 0.7rem;
  letter-spacing: 0.32em;
  color: var(--muted);
}

.hero__title {
  font-family: var(--display);
  font-size: clamp(3rem, 10.5vw, 9rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 0.94;
  text-align: center;
}

/* the glyph masks do the clipping now, so the line no longer needs to */
.hero__title .line { display: block; }
.hero__title .line > span { display: inline-block; }

.hero__foot {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  font-size: 0.7rem;
  letter-spacing: 0.32em;
  color: var(--muted);
  opacity: 0;
  transition: opacity 0.6s ease 0.95s;
}
body.ready .hero__foot { opacity: 1; }

.hero__hint { animation: pulse 2.6s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }

/* Hero statement: small line / giant line / small line. These must stay
   direct-child selectors — the headline is split into per-glyph spans, and a
   descendant match would compound font-size once per nesting level. */
.hero__title .line:nth-child(1) > span,
.hero__title .line:nth-child(3) > span {
  font-family: var(--mono);
  font-size: 0.13em;
  letter-spacing: 0.34em;
  font-weight: 400;
  color: var(--muted);
}

.hero__claim {
  margin-top: 1.8rem;
  text-align: center;
  /* keeps the last word from dropping alone onto its own line when the copy
     wraps -- the four languages all break at different widths */
  text-wrap: balance;
  font-size: 0.86rem;
  font-weight: 400;
  letter-spacing: 0.2em;
  color: rgba(236, 234, 228, 0.72);
  opacity: 0;
  transition: opacity 0.6s ease 0.8s;
}
body.ready .hero__claim { opacity: 1; }

.hero__pills {
  margin-top: 1.7rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.7rem;
  pointer-events: auto;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.6s var(--ease) 1s, transform 0.6s var(--ease) 1s;
}
body.ready .hero__pills { opacity: 1; transform: translateY(0); }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.6em 1.1em;
  border: 1px solid rgba(236, 234, 228, 0.2);
  border-radius: 999px;
  background: rgba(8, 10, 18, 0.55);
  backdrop-filter: blur(5px);
  cursor: pointer;
  color: var(--ink);
  transition: border-color 0.3s, transform 0.3s var(--ease), background 0.3s;
}
.pill:hover { border-color: var(--pc); transform: translateY(-3px); background: rgba(12, 15, 26, 0.75); }
.pill i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--pc);
  box-shadow: 0 0 9px var(--pc);
  flex: none;
}
.pill span { font-size: 0.72rem; letter-spacing: 0.02em; text-align: left; font-weight: 500; }
.pill span em {
  display: block;
  font-style: normal;
  font-weight: 400;
  font-size: 0.54rem;
  letter-spacing: 0.24em;
  color: var(--muted);
  margin-top: 2px;
}

/* shared service colours (match the 3D beam colours) */
/* the four services no longer carry their own hue — one gold reads calmer */
.pill--c0, .statpanel--c0, .bizrail__item--c0, .svc--c0,
.pill--c1, .statpanel--c1, .bizrail__item--c1, .svc--c1,
.pill--c2, .statpanel--c2, .bizrail__item--c2, .svc--c2,
.pill--c3, .statpanel--c3, .bizrail__item--c3, .svc--c3,
.pill--c4, .statpanel--c4, .bizrail__item--c4, .svc--c4 { --pc: var(--accent); }

/* AI FDE is the lead service: same palette, just carried at full strength
   while the other four sit back a step. */
.pill--lead {
  border-color: rgba(201, 168, 107, 0.5);
  background: rgba(201, 168, 107, 0.09);
}
.pill--lead i { transform: scale(1.35); box-shadow: 0 0 12px var(--accent); }
.pill--lead span { color: var(--ink); }
.bizrail__item--lead span { color: var(--ink); }
.svc--lead { border-color: rgba(201, 168, 107, 0.34); }
.svc--lead::before { height: 4px; opacity: 1; }

/* ---------------- tunnel journey ---------------- */

.journey { height: 450vh; pointer-events: none; }

.journey-captions {
  position: fixed;
  inset: 0;
  z-index: 30;
  pointer-events: none;
}
.journey-captions .cap {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 90vw;
  transform: translate(-50%, -50%);
  text-align: center;
  font-size: clamp(1.6rem, 4.5vw, 3.2rem);
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1.3;
  opacity: 0;
  will-change: transform, opacity;
  text-shadow: 0 0 34px rgba(0, 0, 0, 0.6);
}

.flash {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: #fff;
  opacity: 0;
  pointer-events: none;
}

/* ---------------- marquee ---------------- */

.marquee {
  border-top: 1px solid var(--faint);
  border-bottom: 1px solid var(--faint);
  padding: 1.1rem 0;
  overflow: hidden;
  background: rgba(11, 13, 22, 0.55);
  backdrop-filter: blur(2px);
}

.marquee__track {
  display: flex;
  width: max-content;
  white-space: nowrap;
  animation: marquee 22s linear infinite;
  font-family: var(--display);
  font-size: clamp(1.4rem, 3.6vw, 2.6rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  color: rgba(236, 234, 228, 0.3);
}
/* the lead service is the one thing in the strip that reads at full strength */
.marquee__track b {
  font-weight: 500;
  color: var(--accent);
}
@keyframes marquee { to { transform: translateX(-50%); } }

/* ---------------- sections shared ---------------- */

section, footer { position: relative; }

.section-label {
  font-size: 0.7rem;
  letter-spacing: 0.32em;
  color: var(--accent);
  margin-bottom: 3.2rem;
}

[data-reveal] {
  opacity: 0;
  transform: translateY(64px);
  transition: opacity 0.7s var(--ease-long), transform 0.75s var(--ease-long);
  will-change: opacity, transform;
}
[data-reveal].is-in { opacity: 1; transform: translateY(0); }

/* ---------------- about ---------------- */

.about { padding: 22vh 6vw; }

.about__text {
  font-size: clamp(1.5rem, 3.4vw, 3.1rem);
  font-weight: 500;
  line-height: 1.28;
  letter-spacing: -0.015em;
  max-width: 22em;
}

.about__stats {
  display: flex;
  gap: 12vw;
  margin-top: 5.5rem;
  flex-wrap: wrap;
}
.about__stats strong {
  display: block;
  font-size: clamp(2.4rem, 6vw, 4.6rem);
  font-weight: 500;
  letter-spacing: -0.03em;
}
.about__stats span {
  font-size: 0.66rem;
  letter-spacing: 0.3em;
  color: var(--muted);
}

/* ---------------- works ---------------- */

.works { padding: 10vh 6vw 16vh; }

.works__list { border-top: 1px solid var(--faint); }

.project-item {
  position: relative;
  display: grid;
  grid-template-columns: 5rem 1fr auto 3rem;
  align-items: center;
  gap: 2rem;
  padding: 2.1rem 0.5rem;
  border-bottom: 1px solid var(--faint);
  transition: padding-left 0.5s var(--ease), background 0.5s var(--ease);
}
.project-item:hover { padding-left: 2.2rem; background: rgba(236, 234, 228, 0.04); }

.project-item__idx {
  font-size: 0.72rem;
  letter-spacing: 0.25em;
  color: var(--muted);
  transition: color 0.4s;
}
.project-item:hover .project-item__idx { color: var(--accent); }

.project-item h3 {
  font-size: clamp(1.8rem, 5.6vw, 4.8rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
  transition: transform 0.5s var(--ease);
}
.project-item:hover h3 { transform: skewX(-6deg); }

.project-item__tags {
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  color: var(--muted);
  white-space: nowrap;
}

.project-item__arrow {
  font-size: 1.5rem;
  opacity: 0;
  transform: translate(-8px, 8px);
  transition: opacity 0.4s, transform 0.5s var(--ease);
  color: var(--accent);
}
.project-item:hover .project-item__arrow { opacity: 1; transform: translate(0, 0); }

/* ---------------- services ---------------- */

.services { padding: 6vh 6vw 18vh; }

.services__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3rem;
}

.services__col {
  border-top: 1px solid var(--faint);
  padding-top: 1.6rem;
}
.services__col h4 {
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  margin-bottom: 1.6rem;
}
.services__col li {
  font-size: 0.95rem;
  color: var(--muted);
  padding: 0.45rem 0;
  border-bottom: 1px dashed rgba(236, 234, 228, 0.08);
}

/* ---------------- footer ---------------- */

.footer {
  padding: 14vh 6vw 4vh;
  border-top: 1px solid var(--faint);
  background: linear-gradient(to bottom, transparent, rgba(5, 6, 10, 0.85) 40%);
}

.footer__lead {
  font-size: 0.8rem;
  letter-spacing: 0.32em;
  color: var(--muted);
  margin-bottom: 1.4rem;
}

.footer__big {
  display: inline-block;
  font-family: var(--display);
  font-size: clamp(3.6rem, 13vw, 11rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 0.94;
  color: var(--ink);
  transition: color 0.5s var(--ease);
}
.footer__big i {
  font-style: normal;
  color: var(--accent);
}
.footer__big:hover { color: var(--accent); }

.footer__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3rem;
  margin: 7rem 0 5rem;
}
.footer__grid h5 {
  font-size: 0.66rem;
  letter-spacing: 0.3em;
  color: var(--muted);
  margin-bottom: 1rem;
}
.footer__grid a, .footer__grid p {
  display: block;
  font-size: 1rem;
  padding: 0.2rem 0;
  transition: color 0.3s;
}
.footer__grid a:hover { color: var(--accent); }

.footer__small {
  font-size: 0.68rem;
  color: rgba(236, 234, 228, 0.35);
  letter-spacing: 0.06em;
  border-top: 1px solid var(--faint);
  padding-top: 1.6rem;
  line-height: 1.8;
}

body.is-dragging #webgl { cursor: grabbing; }

/* ---------------- chapters runway ---------------- */

/* five levels now share this runway, so it grows to keep each one the same
   physical scroll length it had when there were four */
.chapters { height: 1100vh; pointer-events: none; }

.cap__sub {
  display: block;
  font-size: 0.4em;
  letter-spacing: 0.3em;
  color: var(--muted);
  margin-top: 0.6em;
}

/* ---------------- cinema letterbox ---------------- */

.letterbox { position: fixed; inset: 0; z-index: 70; pointer-events: none; }
.letterbox__bar {
  position: absolute;
  left: 0;
  right: 0;
  height: 12vh;
  background: #000;
  transition: transform 0.5s var(--ease);
}
.letterbox__bar--top { top: 0; transform: translateY(-101%); }
.letterbox__bar--bottom { bottom: 0; transform: translateY(101%); }
body.cinema .letterbox__bar { transform: translateY(0); }

/* ---------------- movie title card ---------------- */

.titlecard {
  position: fixed;
  inset: 0;
  z-index: 72;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
  opacity: 0;
}
.titlecard__eyebrow {
  font-size: 0.7rem;
  letter-spacing: 0.5em;
  color: var(--muted);
  margin-bottom: 1.4rem;
}
.titlecard__main {
  font-family: var(--display);
  font-size: clamp(3.4rem, 11vw, 9.5rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  background: linear-gradient(100deg, #f5f2ea 30%, #ffd98a 50%, #f5f2ea 70%);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: sheen 3.2s linear infinite;
}
@keyframes sheen { to { background-position: -220% 0; } }
.titlecard__sub {
  font-size: clamp(0.78rem, 1.5vw, 1rem);
  font-weight: 300;
  letter-spacing: 0.42em;
  color: var(--ink);
  margin-top: 1.5rem;
  opacity: 0.8;
}

/* ---------------- skip button ---------------- */

.skip {
  position: fixed;
  right: 3rem;
  bottom: 15vh;
  z-index: 75;
  font-size: 0.75rem;
  letter-spacing: 0.25em;
  color: var(--ink);
  border: 1px solid rgba(236, 234, 228, 0.4);
  border-radius: 999px;
  padding: 0.7em 1.5em;
  background: rgba(10, 12, 20, 0.5);
  backdrop-filter: blur(4px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s, background 0.3s;
}
.skip.on { opacity: 1; pointer-events: auto; }
.skip:hover { background: rgba(236, 234, 228, 0.15); }

/* ---------------- game HUD ---------------- */

#filmfx {
  position: fixed;
  inset: 0;
  z-index: 57;
  pointer-events: none;
  background-repeat: repeat;
  opacity: 0.55;
  box-shadow: inset 0 0 18vmax rgba(0, 0, 0, 0.42);
}

#speedfx {
  position: fixed;
  inset: 0;
  z-index: 58;
  pointer-events: none;
  opacity: 0;
  background:
    radial-gradient(ellipse 62% 58% at 50% 50%, transparent 58%, rgba(4, 8, 18, 0.72) 100%),
    radial-gradient(ellipse 40% 36% at 50% 50%, transparent 70%, rgba(125, 249, 255, 0.06) 100%);
  transition: opacity 0.12s linear;
}

.hud {
  position: fixed;
  inset: 0;
  z-index: 65;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.6s;
  font-family: Consolas, "SF Mono", "Cascadia Mono", "Segoe UI", monospace;
}
.hud.on { opacity: 1; }

.hud__mission {
  position: absolute;
  top: 5.4rem;
  left: 3rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.hud__mission-tag {
  font-size: 0.62rem;
  letter-spacing: 0.35em;
  color: var(--accent);
}
.hud__mission-text {
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  border-left: 2px solid var(--accent);
  padding-left: 0.7em;
}
.hud__mission-echo {
  font-style: normal;
  color: var(--muted);
  margin-left: 0.2em;
}

.hud__map {
  position: absolute;
  left: 3rem;
  bottom: 3rem;
  display: flex;
  gap: 0.7rem;
  align-items: center;
}
/* label lives in CSS content, so it switches off the body language flag */
body[data-lang="en"] .hud__map::before { content: "STATIONS"; }
body[data-lang="ja"] .hud__map::before { content: "拠点"; }
body[data-lang="ko"] .hud__map::before { content: "거점"; }
.hud__map::before {
  content: "星站";
  font-size: 0.6rem;
  letter-spacing: 0.3em;
  color: var(--muted);
  margin-right: 0.4rem;
}
.hud__map i {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 1px solid rgba(236, 234, 228, 0.4);
  transition: background 0.5s, box-shadow 0.5s;
}
.hud__map i.lit {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 10px rgba(255, 90, 31, 0.9);
}

.hud__hint {
  position: absolute;
  left: 50%;
  bottom: 8vh;
  transform: translateX(-50%);
  font-size: 0.72rem;
  letter-spacing: 0.3em;
  color: var(--ink);
  background: rgba(10, 12, 20, 0.55);
  border: 1px solid rgba(236, 234, 228, 0.2);
  border-radius: 999px;
  padding: 0.7em 1.6em;
  opacity: 0;
  transition: opacity 0.4s;
}
.hud__hint.on { opacity: 1; animation: pulse 2.4s ease-in-out infinite; }


/* ------------- level service billboards (centre-screen type) ------------- */

/* The astronaut parks in one third of the frame during a level, so the type
   takes the opposite half instead of fighting him for the centre. */
.statpanel {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  padding: 0 5vw;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}
.statpanel > * { max-width: min(46vw, 33rem); }
/* clears the business rail pinned to the right edge */
.statpanel--right { align-items: flex-end; text-align: right; padding-right: 12vw; }
/* directional scrim: darkest under the type, clear over the astronaut */
.statpanel::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(4, 6, 12, 0.55) 0%, rgba(4, 6, 12, 0.26) 26%, rgba(4, 6, 12, 0) 52%);
}
.statpanel--right::before {
  background: linear-gradient(270deg, rgba(4, 6, 12, 0.55) 0%, rgba(4, 6, 12, 0.26) 26%, rgba(4, 6, 12, 0) 52%);
}
.statpanel > * {
  position: relative;
  transform: translateY(28px);
  transition: transform 0.55s var(--ease);
}
.statpanel > *:nth-child(2) { transition-delay: 0.06s; }
.statpanel > *:nth-child(3) { transition-delay: 0.12s; }
.statpanel > *:nth-child(4) { transition-delay: 0.18s; }
.statpanel > *:nth-child(5) { transition-delay: 0.24s; }
.statpanel.on { opacity: 1; }
.statpanel.on > * { transform: translateY(0); }
.statpanel.on .statpanel__cta { pointer-events: auto; }
/* a level intro card is playing: clear the billboard instantly rather than
   cross-fading two stacks of centre-screen type over each other */
body.cardflash .statpanel { opacity: 0; transition: none; }

.statpanel__tag {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 400;
  letter-spacing: 0.26em;
  color: var(--pc, var(--accent));
  margin-bottom: 1.2rem;
}
.statpanel__tag::before {
  content: '';
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--pc, var(--accent));
  box-shadow: 0 0 10px var(--pc, var(--accent));
  margin-right: 0.7em;
  vertical-align: 1px;
}
.statpanel__big {
  font-family: var(--display);
  text-wrap: balance;
  font-size: clamp(2.5rem, 5.4vw, 4.5rem);
  font-weight: 400;
  line-height: 0.98;
  letter-spacing: -0.028em;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.85), 0 6px 44px rgba(0, 0, 0, 0.6);
}
/* no bold anywhere: the accent word separates by colour, not by weight */
.statpanel__big i {
  font-style: normal;
  font-weight: 500;
  color: var(--pc, var(--accent));
}
.statpanel__lead {
  margin-top: 1.35rem;
  font-size: 0.85rem;
  font-weight: 300;
  line-height: 2.05;
  letter-spacing: 0.02em;
  color: rgba(236, 234, 228, 0.92);
  text-shadow: 0 1px 5px rgba(0, 0, 0, 0.92), 0 2px 14px rgba(0, 0, 0, 0.7);
}
.statpanel__chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 1.3rem 0 0;
  padding: 0;
}
.statpanel--right .statpanel__chips { justify-content: flex-end; }
.statpanel__chips li {
  border: 1px solid rgba(236, 234, 228, 0.2);
  background: rgba(8, 10, 18, 0.52);
  backdrop-filter: blur(5px);
  border-radius: 999px;
  padding: 0.46rem 1.05rem;
  font-size: 0.66rem;
  font-weight: 300;
  letter-spacing: 0.1em;
  color: rgba(236, 234, 228, 0.9);
}
.statpanel__chips li::before {
  content: '';
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--pc, var(--accent));
  margin-right: 0.6em;
  vertical-align: 2px;
}
.statpanel__cta {
  display: inline-block;
  font-family: var(--mono);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.95);
  margin-top: 1.7rem;
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--pc, var(--accent));
  border-bottom: 1px solid currentColor;
  padding-bottom: 3px;
  transition: opacity 0.3s;
}
.statpanel__cta:hover { opacity: 0.7; }

/* ---------------- level intro card ---------------- */

.levelcard {
  position: fixed;
  inset: 0;
  z-index: 71;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
  opacity: 0;
}
.levelcard.show { animation: levelIn 2.2s var(--ease) forwards; }
@keyframes levelIn {
  0% { opacity: 0; }
  9% { opacity: 1; }
  76% { opacity: 1; }
  100% { opacity: 0; }
}
.levelcard__tag {
  font-size: 0.7rem;
  letter-spacing: 0.55em;
  color: var(--accent);
  margin-bottom: 1.1rem;
}
.levelcard__name {
  font-family: var(--display);
  font-size: clamp(2.4rem, 6.4vw, 5rem);
  font-weight: 400;
  letter-spacing: 0.1em;
  /* tight shadow carries the letters over a bright set without dimming it */
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.9), 0 8px 44px rgba(0, 0, 0, 0.65);
}
.levelcard.show .levelcard__name { animation: levelName 2.2s var(--ease); }
@keyframes levelName {
  0% { transform: scale(1.1); letter-spacing: 0.26em; }
  30%, 100% { transform: scale(1); letter-spacing: 0.1em; }
}
.levelcard__en {
  margin-top: 1rem;
  font-size: 0.74rem;
  letter-spacing: 0.44em;
  color: var(--muted);
}

/* ---------------- business rail ---------------- */

.bizrail {
  position: fixed;
  right: 1.3rem;
  top: 50%;
  transform: translateY(-50%);
  z-index: 66;
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s;
}
.bizrail.on { opacity: 1; pointer-events: auto; }
.bizrail__item {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.65rem;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.bizrail__item span {
  text-align: right;
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  color: var(--muted);
  opacity: 0.55;
  transition: opacity 0.3s, color 0.3s;
}
.bizrail__item span em {
  display: block;
  font-style: normal;
  font-size: 0.48rem;
  letter-spacing: 0.34em;
  opacity: 0.75;
  margin-top: 2px;
}
.bizrail__item i {
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid rgba(236, 234, 228, 0.42);
  transition: background 0.3s, border-color 0.3s, box-shadow 0.3s;
}
.bizrail__item:hover span { opacity: 1; color: var(--ink); }
.bizrail__item.done i { background: rgba(236, 234, 228, 0.55); border-color: transparent; }
.bizrail__item.active i { background: var(--pc); border-color: var(--pc); box-shadow: 0 0 11px var(--pc); }
.bizrail__item.active span { opacity: 1; color: var(--ink); }

/* ---------------- end credits ---------------- */

/* A film roll: the section is tall, the stage pins to the viewport, and the
   track inside is pushed upward by scroll so the copy passes line by line.
   The content is the business itself -- a mock cast list of invented names
   read as a roster of strangers and said nothing. */

.credits {
  position: relative;
  height: 360vh;
  padding: 0;
}

/* Pinned from script, not by position:sticky -- the page scrolls by
   transforming .scroll-content, and a transformed ancestor leaves sticky
   without a scrollport to stick to. */
.credits__stage {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  overflow: hidden;
  will-change: transform;
}

.credits__bar {
  position: absolute;
  left: 0;
  right: 0;
  height: 13vh;
  background: #000;
  z-index: 2;
  pointer-events: none;
}
/* the page is already black, so a hairline is what makes the frame read */
.credits__bar--top { top: 0; border-bottom: 1px solid rgba(236, 234, 228, 0.1); }
.credits__bar--bot { bottom: 0; border-top: 1px solid rgba(236, 234, 228, 0.1); }

/* sits inside the top bar, clear of both the fixed nav and the moving track */
.credits__label {
  position: absolute;
  top: 8.2vh;
  left: 0;
  right: 0;
  z-index: 3;
  margin: 0;
  text-align: center;
}

/* the edges dissolve, so lines arrive and leave instead of popping */
.credits__viewport {
  position: absolute;
  inset: 0;
  -webkit-mask-image: linear-gradient(to bottom, transparent 7%, #000 27%, #000 73%, transparent 93%);
  mask-image: linear-gradient(to bottom, transparent 7%, #000 27%, #000 73%, transparent 93%);
}

.credits__roll {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 0 6vw;
  text-align: center;
  will-change: transform;
}

.credits__intro {
  max-width: 880px;
  margin: 0 auto;
  text-align: center;
}

.credits__present {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.42em;
  color: var(--muted);
  margin-bottom: 2.4rem;
}

.credits__wholabel {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.4em;
  color: var(--muted);
  margin: 2.2rem 0 1.1rem;
}

.credits__who {
  font-size: 0.92rem;
  font-weight: 300;
  line-height: 2;
  letter-spacing: 0.04em;
  color: rgba(236, 234, 228, 0.78);
  text-wrap: balance;
}

/* Only claims the site already makes elsewhere -- nothing invented here.
   Set as credit rows: figure left of the gutter, what it counts on the right. */
.credits__proof {
  list-style: none;
  max-width: 1040px;
  margin: 15vh auto 0;
  padding: 0;
  border: 0;
}
.credits__proof li {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 3rem;
  align-items: baseline;
  margin-bottom: 2.6rem;
}
.credits__proof strong {
  grid-column: 1;
  display: block;
  text-align: right;
  font-family: var(--display);
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.credits__proof span {
  grid-column: 2;
  display: block;
  text-align: left;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  line-height: 1.8;
  color: rgba(236, 234, 228, 0.7);
  margin: 0;
}

/* the five services as a cast list rather than a card grid */
.credits__services { max-width: 820px; margin: 12vh auto 0; }
.credits__services-head {
  text-align: center;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.42em;
  color: var(--muted);
  margin-bottom: 4.5rem;
}
.credits__services-grid { display: block; }

.credits__roll .svc {
  display: block;
  max-width: 820px;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 3.6rem;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  overflow: visible;
  transform: none;
}
.credits__roll .svc::before { display: none; }
.credits__roll .svc em { display: none; }
.credits__roll .svc p {
  text-align: center;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.24em;
  color: var(--muted);
  margin: 0 0 0.55rem;
}
.credits__roll .svc h4 {
  text-align: center;
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.9vw, 1.45rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  margin: 0;
}
.credits__roll .svc span {
  display: block;
  max-width: 42rem;
  margin: 0.5rem auto 0;
  text-align: center;
  font-size: 0.78rem;
  line-height: 1.85;
  color: rgba(236, 234, 228, 0.48);
}
.credits__roll .svc--lead h4 { color: var(--accent); }

/* In English the mono code and the name are the same words, so the gutter
   carries the running number instead of saying it twice. */
body[data-lang="en"] .credits__roll .svc p { display: none; }
body[data-lang="en"] .credits__roll .svc em {
  display: block;
  text-align: center;
  font-style: normal;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.24em;
  color: var(--muted);
}

/* the last card rests in the middle of the frame when the roll runs out */
.credits__fin { margin-top: 20vh; padding-bottom: 8vh; }
.credits__finmark {
  font-family: var(--display);
  font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  font-weight: 400;
  letter-spacing: 0.02em;
}
.credits__finmark i {
  font-style: normal;
  font-family: var(--mono);
  font-size: 0.4em;
  letter-spacing: 0.2em;
  vertical-align: super;
  color: var(--accent);
}
.credits__fintext {
  margin-top: 1.7rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.62em;
  color: var(--muted);
}
.svc {
  position: relative;
  display: block;
  border: 1px solid rgba(236, 234, 228, 0.14);
  border-radius: 10px;
  padding: 1.6rem 1.35rem 1.5rem;
  background: rgba(10, 12, 20, 0.5);
  overflow: hidden;
  transition: transform 0.4s var(--ease), border-color 0.4s;
}
.svc::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--pc);
  opacity: 0.9;
}
.svc:hover { transform: translateY(-6px); border-color: rgba(236, 234, 228, 0.32); }
.svc em { font-style: normal; font-size: 0.62rem; letter-spacing: 0.32em; color: var(--pc); }
.svc h4 {
  font-size: 1.32rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  margin: 0.75rem 0 0.4rem;
}
.svc p {
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.2em;
  color: var(--muted);
  margin-bottom: 0.9rem;
}
.svc span {
  display: block;
  font-size: 0.76rem;
  font-weight: 300;
  line-height: 2;
  color: rgba(236, 234, 228, 0.74);
}

/* The end sections keep their own translucent backgrounds and float over the
   fading 3D canvas, so they need no colour overrides here. The nav needs none
   either: mix-blend-mode: difference inverts it against whatever passes under. */

/* ---------------- hover system ----------------
   Gated to devices that can actually hover, otherwise touch users get stuck
   in a hover state after every tap. Everything here runs on --ease so the
   feedback lands within 0.3-0.45s. */

@media (hover: hover) and (pointer: fine) {

  /* service pills: gold wipes up from the base, dot flares */
  .pill { position: relative; overflow: hidden; will-change: transform; }
  .pill > * { position: relative; z-index: 1; }
  .pill::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--pc);
    opacity: 0.14;
    transform: translateY(101%);
    transition: transform 0.42s var(--ease);
  }
  .pill:hover::after { transform: translateY(0); }
  .pill:hover i { transform: scale(1.5); box-shadow: 0 0 16px var(--pc); }
  .pill i { transition: transform 0.35s var(--ease), box-shadow 0.35s; }
  .pill:hover em { color: var(--pc); }
  .pill em { transition: color 0.3s; }

  /* rail: the whole row slides toward its label and the dot fills */
  .bizrail__item { transition: transform 0.35s var(--ease); will-change: transform; }
  .bizrail__item:hover { transform: translateX(-7px); }
  .bizrail__item span,
  .bizrail__item em { transition: color 0.3s; }
  .bizrail__item:hover span { color: var(--ink); }
  .bizrail__item:hover em { color: var(--pc); }
  .bizrail__item i { transition: transform 0.35s var(--ease), background 0.3s, box-shadow 0.3s; }
  .bizrail__item:hover i {
    transform: scale(1.7);
    background: var(--pc);
    box-shadow: 0 0 14px var(--pc);
  }

  /* recap cards: lift, and a soft wash rises behind the copy */
  .svc { will-change: transform; }
  .svc::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: linear-gradient(180deg, transparent 30%, rgba(201, 168, 107, 0.09));
    opacity: 0;
    transition: opacity 0.42s var(--ease);
  }
  .svc > * { position: relative; z-index: 1; }
  .svc:hover::after { opacity: 1; }
  .svc:hover h4 { color: var(--pc); }
  .svc h4 { transition: color 0.32s; }

  /* links: an underline wipes in from the left rather than blinking on */
  .footer__grid a,
  .statpanel__cta {
    position: relative;
    border-bottom: 0;
  }
  .footer__grid a::after,
  .statpanel__cta::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: -3px;
    width: 100%;
    height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.4s var(--ease);
  }
  .statpanel__cta::after { transform: scaleX(1); }
  .footer__grid a:hover::after { transform: scaleX(1); }
  .statpanel__cta:hover::after { transform-origin: right; transform: scaleX(0); }

  /* menu: entries step aside as the pointer passes */
  .menu-overlay__list a { transition: transform 0.42s var(--ease), color 0.3s; }
  .menu-overlay__list a:hover { transform: translateX(22px); }

  .skip { transition: color 0.3s, letter-spacing 0.35s var(--ease); }
  .skip:hover { color: var(--accent); letter-spacing: 0.24em; }
}

/* ---------------- magnetic ---------------- */

.magnetic { transition: transform 0.45s var(--ease); will-change: transform; }

/* ---------------- responsive ---------------- */

@media (max-width: 768px) {
  /* The nav has five things in it at 390px wide. Everything shrinks and is
     pinned to one line; without nowrap the brand, MENU and the CTA all wrapped
     and the bar grew to double height. */
  .nav { padding: 0.9rem 1rem; }
  .nav__right { gap: 0.35rem; }
  .nav__brand, .nav__menu, .btn-pill, .langswitch button { white-space: nowrap; }
  .nav__brand {
    font-size: 1.05rem;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .nav__menu {
    font-size: 0.6rem;
    letter-spacing: 0.1em;
    padding: 0 0.3em;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .btn-pill {
    font-size: 0.6rem;
    letter-spacing: 0.1em;
    padding: 0 0.9em;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .langswitch button {
    font-size: 0.56rem;
    letter-spacing: 0.06em;
    padding: 0 0.42em;
    min-height: 44px;
  }

  .hero { padding: 6.5rem 1.4rem 2rem; }
  /* two columns of tracked-out mono do not fit side by side on a phone --
     side by side they used to overlap into each other */
  .hero__meta {
    flex-direction: column;
    gap: 0.45rem;
    letter-spacing: 0.24em;
    font-size: 0.6rem;
  }
  .hero__foot { flex-direction: column; gap: 0.8rem; align-items: flex-start; }

  /* The two eyebrow lines are sized off the headline, so on a 390px screen they
     fell to ~6px of tracked-out mono sitting on top of the astronaut. Pin them
     to a readable size and lift the contrast off the artwork behind them. */
  .hero__title .line:nth-child(1) > span,
  .hero__title .line:nth-child(3) > span {
    font-size: 0.58rem;
    letter-spacing: 0.2em;
    color: rgba(236, 234, 228, 0.78);
  }
  .hero__title { text-shadow: 0 2px 14px rgba(4, 6, 12, 0.9), 0 6px 40px rgba(4, 6, 12, 0.7); }
  .hero__claim {
    margin-top: 1.3rem;
    font-size: 0.8rem;
    letter-spacing: 0.12em;
    line-height: 1.7;
    text-shadow: 0 1px 8px rgba(4, 6, 12, 0.95);
  }

  /* HUD: the mission line and the percentage were colliding mid-screen */
  .hud__mission { top: 4.6rem; left: 1.4rem; right: 1.4rem; gap: 0.25rem; }
  .hud__mission-text { font-size: 0.72rem; line-height: 1.45; }
  .hud__mission-tag { font-size: 0.55rem; letter-spacing: 0.28em; }
  /* the native-language echo is what pushes these lines to a second row */
  .hud__mission-echo { display: none; }
  /* bottom row: stations sit clear of the hint on small screens */
  .hud__map { left: 1.4rem; bottom: 3rem; gap: 0.5rem; }
  .hud__hint {
    bottom: 8.5rem;
    font-size: 0.55rem;
    letter-spacing: 0.18em;
    max-width: 82vw;
    text-align: center;
    line-height: 1.6;
    padding: 0.7em 1.2em;
  }

  .about { padding: 16vh 7vw; }
  .about__stats { gap: 2.4rem; }

  .works { padding: 8vh 7vw 12vh; }
  .project-item { grid-template-columns: 2.6rem 1fr; row-gap: 0.5rem; }
  .project-item__tags { grid-column: 2; }
  .project-item__arrow { display: none; }

  .services__grid, .footer__grid { grid-template-columns: 1fr; }

  .hero__pills { gap: 0.45rem; }
  .pill { padding: 0.55em 0.9em; }
  .pill span em { display: none; }
  .bizrail { display: none; }
  /* no room to split the frame on a phone: recentre and scrim the whole thing */
  .statpanel { padding: 0 1.4rem; align-items: center; text-align: center; }
  .statpanel--right { align-items: center; text-align: center; }
  .statpanel > * { max-width: none; }
  .statpanel::before, .statpanel--right::before {
    background: radial-gradient(ellipse 84% 44% at 50% 52%, rgba(4, 6, 12, 0.6), rgba(4, 6, 12, 0) 80%);
  }
  .statpanel__lead { font-size: 0.78rem; }
  .statpanel__chips { justify-content: center; }
  .statpanel--right .statpanel__chips { justify-content: center; }
  .statpanel__chips li { padding: 0.36rem 0.8rem; font-size: 0.62rem; }
  /* the CTA was a 17px-tall line of text: too small to hit with a thumb.
     min-height is what actually guarantees the 44px target -- padding in em
     units tracks the tiny font size and never gets there on its own. */
  .statpanel__cta {
    margin-top: 1.3rem;
    padding: 0 1.5em;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    border: 1px solid currentColor;
    border-bottom-width: 1px;
    border-radius: 999px;
  }
  .pill { min-height: 44px; padding: 0 0.95em; }
  .footer__grid a { display: inline-flex; align-items: center; min-height: 44px; }
  .skip { min-height: 44px; padding: 0 1.4em; display: inline-flex; align-items: center; }
  .credits__who { font-size: 0.84rem; line-height: 1.95; }
  .credits__wholabel { margin-top: 1.8rem; letter-spacing: 0.28em; }

  /* no room for a gutter: the roll stacks each credit instead */
  .credits__proof { margin-top: 9vh; }
  .credits__proof li { display: block; margin-bottom: 2.1rem; }
  .credits__proof strong { text-align: center; }
  .credits__proof span { text-align: center; letter-spacing: 0.14em; margin-top: 0.4rem; }

  .credits__services { margin-top: 10vh; }
  .credits__services-head { margin-bottom: 3rem; letter-spacing: 0.3em; }
  .credits__roll .svc { display: block; margin-bottom: 2.8rem; }
  .credits__roll .svc p { text-align: center; }
  body[data-lang="en"] .credits__roll .svc em { text-align: center; }
  .credits__roll .svc h4 { text-align: center; margin-top: 0.4rem; }
  .credits__roll .svc span { text-align: center; }

  .credits__fin { margin-top: 12vh; }
}
