:root {
  --navy: #00165B;
  --navy-deep: #000A33;
  --cobalt: #003DEE;
  --lilac: #AA88F8;
  --ink: #FFFFFF;
  --ink-soft: rgba(255, 255, 255, .66);
  --line: rgba(255, 255, 255, .14);
  --serif: 'Instrument Serif', 'Cormorant Garamond', Georgia, serif;
  --sans: 'Jost', 'Hanken Grotesk', system-ui, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, monospace;
  color-scheme: dark;
}
* { box-sizing: border-box; }
html, body { height: 100%; overflow: hidden; overscroll-behavior: none; }
html { background: var(--navy-deep); }
body {
  margin: 0; color: var(--ink); background: var(--navy-deep);
  font-family: var(--sans); font-weight: 300; -webkit-font-smoothing: antialiased;
  touch-action: none;
}
img, svg { display: block; }
a { color: inherit; }
::selection { background: var(--lilac); color: var(--navy-deep); }

/* ---------- the deck: one full-screen scene at a time ---------- */
.deck { position: fixed; inset: 0; overflow: hidden; background: var(--navy-deep); }
.panel-s {
  position: absolute; inset: 0; overflow: hidden;
  visibility: hidden; opacity: 0; pointer-events: none;
}
.panel-s.is-active { visibility: visible; opacity: 1; pointer-events: auto; }
/* The scene that just arrived settles from a slight push in its direction. */
.panel-s.is-entering .film-host { animation: settle 1.1s cubic-bezier(.16, 1, .3, 1) both; }
.deck[data-dir="up"] .panel-s.is-entering .film-host { animation-name: settle-up; }
@keyframes settle { from { transform: translateY(3.5vh) scale(1.04); } to { transform: none; } }
@keyframes settle-up { from { transform: translateY(-3.5vh) scale(1.04); } to { transform: none; } }
/* The scene that is leaving drifts away while the veil closes over it. */
.panel-s.is-leaving .film-host { transform: translateY(-2.5vh) scale(.97); transition: transform .26s cubic-bezier(.5, 0, .75, 0); }
.deck[data-dir="up"] .panel-s.is-leaving .film-host { transform: translateY(2.5vh) scale(.97); }
/* A dark veil hides the swap, so two scenes never show at once. */
.veil { position: fixed; inset: 0; z-index: 10; background: var(--navy-deep); opacity: 0; pointer-events: none; transition: opacity .26s cubic-bezier(.5, 0, .75, 0); }
.veil.is-closed { opacity: 1; }
.veil.is-opening { transition: opacity .48s cubic-bezier(.25, 1, .5, 1); }

/* ---------- films ---------- */
.film-host { position: absolute; inset: 0; overflow: hidden; background: var(--navy); }
.film-stage { position: absolute; left: 0; top: 0; width: 1920px; height: 1080px; transform-origin: 0 0; }
.film-layer { position: absolute; inset: 0; }
.film-fx { position: absolute; left: 0; top: 0; width: 1920px; height: 1080px; pointer-events: none; }
.film-lunar { --display: 'Cormorant Garamond', Georgia, serif; --sans: 'Jost', system-ui, sans-serif; }
.film-blueprint { --display: 'Instrument Serif', Georgia, serif; --sans: 'Hanken Grotesk', system-ui, sans-serif; --mono: 'JetBrains Mono', ui-monospace, monospace; }
.film-constellation { --display: 'Bodoni Moda', Georgia, serif; --sans: 'Jost', system-ui, sans-serif; }

/* Wide films on desktop, tall films on phones (the body gets .is-tall). */
body:not(.is-tall) .film-host.v-tall, body.is-tall .panel-s:not(.no-tall) .film-host.v-wide { display: none; }

/* Phone blueprint: on screens narrower than the film, the drawing and words
   shrink together (site.js sets --bpm-fit) and the grid reaches every edge. */
.film-blueprint_m .bpm-cam { scale: var(--bpm-fit, 1); }
/* The words sit beside the drawing, so they shrink about the same point (540, 1160). */
.film-blueprint_m .bpm-words { scale: var(--bpm-fit, 1); transform-origin: 450px 830px; }
.film-blueprint_m .bpm-grid { left: -700px; top: -700px; width: 2480px; height: 3320px; }

/* Phone Coming soon: the logo, wordmark and words shrink together about
   their own centre (site.js sets --soon-fit) so they sit calmly on screen. */
.film-constellation_m .m-gather-layer { scale: var(--soon-fit, 1); }

/* ---------- 1 · hero ---------- */
.hero { background: var(--navy-deep); }
.hero::after { content: ''; position: absolute; inset: auto 0 0; height: 30vh; background: linear-gradient(transparent, var(--navy-deep)); pointer-events: none; }
.scroll-cue {
  position: absolute; left: 50%; bottom: 28px; z-index: 2; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 14px; text-decoration: none;
  border: 0; padding: 8px 12px 0; background: none; cursor: pointer; font-family: inherit; font-weight: 300;
  font-size: 11px; letter-spacing: .4em; text-transform: uppercase; color: var(--ink-soft);
  opacity: 0; transition: opacity 1.2s .4s;
}
.scroll-cue i { width: 1px; height: 56px; background: linear-gradient(var(--lilac), transparent); transform-origin: top; animation: drip 2.2s cubic-bezier(.6, 0, .2, 1) infinite; }
@keyframes drip { 0% { transform: scaleY(0); opacity: 1; } 60% { transform: scaleY(1); opacity: 1; } 100% { transform: scaleY(1); opacity: 0; } }
.panel-s:not(.is-done) .scroll-cue { transition: none; }
.hero.is-done .scroll-cue, .craft.is-done .scroll-cue, .partners-s.is-done .scroll-cue { opacity: 1; }
.scroll-cue:hover, .scroll-cue:focus-visible { color: var(--ink); }
.scroll-cue:focus-visible { outline: 1px solid var(--lilac); outline-offset: 6px; border-radius: 4px; }

/* ---------- 3 · partners ---------- */
.partners-s { background: var(--navy); }

/* ---------- 2 · blueprint ---------- */
.craft { background: var(--navy); }

/* ---------- 3 · coming soon (finale) ---------- */
.finale { background: var(--navy); }
.finale::before { content: ''; position: absolute; inset: 0 0 auto; height: 18vh; z-index: 1; background: linear-gradient(var(--navy), transparent); pointer-events: none; }
.finale-foot {
  position: absolute; left: 0; right: 0; bottom: 28px; z-index: 2; text-align: center;
  display: flex; flex-direction: column; gap: 12px;
  opacity: 0; transform: translateY(10px);
}
.finale.is-done .finale-foot { opacity: 1; transform: none; transition: opacity 1.4s, transform 1.4s; }
.finale-foot p { margin: 0; }
/* The lilac rule sits under "Software Design & Development" (the film's own
   rule under "Coming soon" is hidden, so it never crosses this line). */
.finale .film-constellation .gather-rule { display: none !important; }
.finale-rule { display: block; width: 120px; height: 1px; margin: 2px auto 4px; background: var(--lilac); transform: scaleX(0); }
.finale.is-done .finale-rule { transform: scaleX(1); transition: transform 1.2s .3s cubic-bezier(.16, 1, .3, 1); }
.finale-note { font-size: 12px; letter-spacing: .5em; text-transform: uppercase; color: var(--ink-soft); }
.finale-copy { font-size: 11px; letter-spacing: .16em; color: rgba(255, 255, 255, .38); }
/* "Coming soon" in a clean, bold sans to match the wordmark. */
.finale .film-constellation h2.soon { font-family: 'Jost', system-ui, sans-serif; font-weight: 600; font-size: 64px; letter-spacing: .01em; line-height: 1; }

/* ---------- texture ---------- */
.grain {
  position: fixed; inset: -50%; z-index: 30; pointer-events: none; opacity: .07; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  animation: grain 1.2s steps(4) infinite;
}
@keyframes grain { 25% { transform: translate(-3%, 2%); } 50% { transform: translate(2%, -3%); } 75% { transform: translate(-1%, 3%); } }

/* ---------- small screens ---------- */
/* Phones: tuck the scroll cue lower so it never crowds the scene's last line. */
body.is-tall .scroll-cue { bottom: 10px; gap: 10px; }
body.is-tall .scroll-cue i { height: 40px; }
@media (max-width: 520px) {
  .finale-note { font-size: 10px; letter-spacing: .3em; padding: 0 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .grain, .scroll-cue i, .panel-s.is-entering .film-host { animation: none; }
  .panel-s.is-leaving .film-host { transform: none; }
}
