/* ============================================================
   SCROLL EFFECTS
   Styles used by scroll-fx.js. Everything except the progress bar
   is scoped under html.fx, which the script only adds when motion is
   allowed and GSAP loaded — so without JS the page renders as before.

   Scrubbed values are written as CSS variables (--fx-x, --fx-y, ...)
   and applied through the individual translate / rotate / scale
   properties. That leaves `transform` free for the existing hover
   effects and the blobs' floating keyframes.
   ============================================================ */

/* In-app browsers (html.inapp, set by scroll-fx.js) get no scroll effects
   and none of the costly blurs: their WebViews stutter on frosted glass
   over scrolling content and on animated blurred blobs. */
.inapp * { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
.inapp nav { background: rgba(13,13,10,0.94); }
/* Without the blur the blobs need a gradient that fades out inside the circle */
.inapp .blob {
  filter: none; animation: none;
  background: radial-gradient(closest-side, rgba(232,201,122,0.85), rgba(201,168,76,0.4) 45%, transparent);
}

/* Lenis drives scrolling, so native smooth scrolling must be off */
html.lenis { scroll-behavior: auto; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-stopped { overflow: clip; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* Thin gold reading-progress bar. Pure CSS scroll-driven animation
   where supported; scroll-fx.js scrubs it in other browsers. */
.fx-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, var(--gold-dim), var(--gold), var(--gold-light));
  transform-origin: 0 50%; transform: scaleX(0);
  z-index: 1000; pointer-events: none;
}
@supports (animation-timeline: scroll()) {
  .fx-progress { animation: fx-grow linear both; animation-timeline: scroll(root); }
}
@keyframes fx-grow { to { transform: scaleX(1); } }

/* Anything moved by the scroll. (No permanent will-change: GSAP's
   scrubbing promotes elements only while they actually move.) */
.fx .fx-move {
  translate: calc(var(--fx-x, 0) * 1px) calc(var(--fx-y, 0) * 1px);
  scale: var(--fx-s, 1);
}
/* Only the value and feature cards tilt in 3D */
.fx .values-grid .fx-move, .fx .features-grid .fx-move {
  rotate: x calc(var(--fx-rx, 0) * 1deg);
}
/* Cards carry `transition: all` for hover; keep it off the scrubbed
   properties or every scroll tick would lag behind by 0.4s. Padding is
   left out too: it changes at the 900px breakpoint, and a transition
   there would make ScrollTrigger measure the cards mid-animation. */
.fx .fx-move.fx-move {
  transition-property: transform, border-color, box-shadow, background;
}
/* ...except the philosophy rows, whose hover nudge is a padding change */
.fx .philosophy-item.fx-move { transition-property: padding; }
.fx .values-grid, .fx .features-grid { perspective: 1200px; }

/* Keyboard focus always shows the focused card in full, even if it is
   still mid-reveal at the bottom edge of the screen */
.fx .fx-move:focus-within {
  opacity: 1 !important; translate: none !important;
  rotate: none !important; scale: none !important;
}

/* Clean copy of an animated text, for screen readers only */
.fx-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Cards slide in from the sides; clip them per section (clip, unlike
   hidden, keeps position:sticky working) so phones never get a
   horizontal scroll while they are off-screen */
.fx section { overflow-x: clip; }

/* Words split by scroll-fx.js */
.fx .fx-word { display: inline-block; }
.fx .fx-mask .fx-word {
  overflow: hidden; vertical-align: top;
  /* room for descenders, Polish ogonki and italic overhang inside the clip */
  padding: 0 0.12em 0.3em 0.15em; margin: 0 -0.12em -0.3em -0.15em;
}
.fx .fx-word-i { display: inline-block; }

/* Eyebrow rule grows in (scaled, so no layout per frame) */
.fx .section-eyebrow::before { transform: scaleX(var(--fx-line, 1)); transform-origin: 0 50%; }

/* Hero layers drift at different speeds */
.fx .blob { translate: 0 calc(var(--fx-y, 0) * 1px); }
.fx .hero.fx-off .blob { animation-play-state: paused; }
.fx .hero-content { will-change: transform, opacity; }

/* Manifesto fills the screen while it is pinned */
.fx .manifesto {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
}

/* Protocol timeline: gold fill down the spine, nodes light up */
.fx .fx-spine-fill {
  position: absolute; inset: 0;
  background: linear-gradient(to bottom, var(--gold-light), var(--gold));
  transform-origin: 50% 0; transform: scaleY(0);
}
.fx .cc-node {
  scale: var(--fx-s, 1);
  box-shadow: 0 0 0 2px var(--cc-border-strong),
              0 0 calc(var(--fx-glow, 0) * 18px) calc(var(--fx-glow, 0) * 2px) rgba(201,168,76,0.55);
}

/* ============================================================
   ENCRYPTION DEMO
   A message leaves one device, crosses the wire as ciphertext and is
   decrypted on the other. Used on both pages. Static without JS;
   scroll-fx.js pins the section and plays the trip on scroll.
   ============================================================ */
.cipher-demo { background: var(--bg); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
/* While the whole section is pinned at the top, keep its heading clear
   of the fixed nav */
.fx .cipher-demo { padding-top: 7rem; }

.cd-stage {
  display: grid;
  grid-template-columns: minmax(0,1fr) minmax(0,1.3fr) minmax(0,1fr);
  align-items: center;
  gap: 1.5rem;
  margin-top: 3rem;
}

.cd-device {
  /* above the wire, so the packet slides out from under one device
     and into the other instead of covering the message */
  position: relative; z-index: 1;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.6rem 1.5rem;
  min-height: 170px;
}
.cd-label {
  font-size: 0.7rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 1rem;
}
.cd-msg {
  font-family: "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
  font-size: 0.85rem; line-height: 1.6; color: var(--text);
  overflow-wrap: anywhere;
}

.cd-wire { position: relative; height: 170px; }
.cd-wire-line {
  position: absolute; left: 0; right: 0; top: 50%; height: 1px;
  background: linear-gradient(to right, transparent, var(--gold-dim), transparent);
}
.cd-packet {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(100%, 260px);
  background: linear-gradient(rgba(201,168,76,0.06), rgba(201,168,76,0.06)), var(--bg3);
  border: 1px solid rgba(201,168,76,0.3);
  border-radius: 14px;
  padding: 0.8rem 1rem;
  box-shadow: 0 0 40px rgba(201,168,76,0.12);
}
.cd-packet-tag {
  display: block;
  font-size: 0.7rem; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 0.4rem;
}
.cd-cipher {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
  font-size: 0.72rem; line-height: 1.6; color: var(--gold-light);
  overflow-wrap: anywhere;
}
.cd-eye {
  position: absolute; left: 0; right: 0; bottom: 0;
  text-align: center;
  font-size: 0.7rem; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--text-dim);
}

.cd-caption {
  max-width: 640px; margin: 2.5rem auto 0;
  text-align: center; font-size: 0.9rem; line-height: 1.8; color: var(--text-dim);
}

/* Key exchange: two public halves meet and become the shared key.
   Only shown when the animation runs. */
.cd-keys { display: none; }
.fx .cd-keys {
  position: absolute; inset: 0 0 1.6rem;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.cd-key, .cd-shared {
  position: absolute;
  font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase;
  white-space: nowrap;
  padding: 0.45rem 0.9rem; border-radius: 100px;
  opacity: 0;
}
.cd-key { color: var(--gold); background: var(--bg3); border: 1px solid rgba(201,168,76,0.35); }
.cd-shared {
  color: var(--bg); background: var(--gold); font-weight: 600;
  box-shadow: 0 0 30px rgba(201,168,76,0.45);
}

/* On wide screens the keys meet right on the wire line */
@media (min-width: 761px) { .fx .cd-keys { inset: 0; } }

@media (max-width: 760px) {
  .cd-stage { grid-template-columns: 1fr; gap: 0.5rem; }
  .cd-device { min-height: 0; }
  .cd-wire { height: 150px; }
  .cd-wire-line {
    left: 50%; right: auto; top: 0; bottom: 1.6rem; width: 1px; height: auto;
    background: linear-gradient(to bottom, transparent, var(--gold-dim), transparent);
  }
  .cd-packet { top: 45%; }
}

/* ============================================================
   ANIMATED LOCK (home page)
   Drawn closed and glowing; scroll-fx.js starts it open and closes
   it as you scroll through the pinned section.
   ============================================================ */
.lock-section { background: var(--bg); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }

.lock-layout {
  display: grid; grid-template-columns: 1fr 1fr;
  align-items: center; gap: 3rem;
}
.lock-copy .section-sub { margin-bottom: 0; }

.lock-visual { position: relative; display: flex; flex-direction: column; align-items: center; }
/* also capped by screen height, so the pinned lock fits on landscape phones */
.lock-svg { width: min(100%, 380px, 55vh); height: auto; overflow: visible; }

.lock-shackle {
  fill: none; stroke: var(--gold); stroke-width: 16; stroke-linecap: round;
}
.lock-body {
  fill: var(--bg3); stroke: var(--gold); stroke-width: 2.5;
}
.lock-keyhole { fill: var(--gold-light); filter: drop-shadow(0 0 10px rgba(232,201,122,0.8)); }
.lock-ring { fill: none; stroke: var(--gold); stroke-width: 1; opacity: 0; transform-origin: 160px 185px; }
.lock-orbit-text { transform-origin: 160px 160px; }
.lock-orbit-text text {
  fill: var(--gold-dim);
  font-family: "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
  font-size: 11px; letter-spacing: 3px;
}

.lock-status {
  margin-top: 1rem; position: relative; height: 1.6rem; width: 12rem;
  font-size: 0.7rem; letter-spacing: 0.25em; text-transform: uppercase; text-align: center;
}
.lock-status > span { position: absolute; inset: 0; }
.lock-state-open { color: var(--text-dim); opacity: 0; }
.lock-state-closed { color: var(--gold); }

@media (max-width: 760px) {
  .lock-layout { grid-template-columns: 1fr; gap: 2rem; }
  .lock-svg { width: min(80%, 300px, 55vh); }
}
