/* =====================================================================
   ENCODEX — CONTACT (MONOLITH v8.0)
   ---------------------------------------------------------------------
   The gate. A live Three.js hero (one Sentinel unit receiving the
   visitor in front of the slab-door — src/contact.js) followed by a
   conversion document: the brief, the protocol (with the intake-path
   instrument), the founder's letter — signed — and the close.

   Extends site.css: same tokens, chrome, buttons, fields, panels.
   Everything here is either the hero apparatus or contact-specific
   composition.
   ===================================================================== */

/* the hero runs full-bleed under the fixed top bar */
body.page-contact { padding-top: 0; }

/* =====================================================================
   HERO — the gate
   ===================================================================== */
.ct-hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 540px;
  overflow: hidden;
  background: var(--bg);
}

/* the canvas mount — parallaxed + faded by src/contact.js on scroll-out */
.ct-stage {
  position: absolute;
  inset: 0;
  background: var(--bg);
  will-change: transform, opacity;
}
.ct-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
  /* NOTE: no touch-action lock — the page under the canvas must scroll */
}

/* no-WebGL fallback: the intro film's robot close-up stands in */
.ct-poster {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) brightness(0.72);
}
body.ct-nogl .ct-poster { display: block; }
body.ct-nogl .ct-stage { display: none; }

/* legibility scrim — the landing's cinematic vignette, verbatim */
.ct-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(3, 4, 6, 0.7) 0%, rgba(3, 4, 6, 0) 13%),
    radial-gradient(ellipse 100% 72% at 50% 105%, rgba(3, 4, 6, 0.85) 0%, rgba(3, 4, 6, 0.42) 48%, rgba(3, 4, 6, 0) 76%),
    linear-gradient(to top, rgba(3, 4, 6, 0.55) 0%, rgba(3, 4, 6, 0) 24%),
    var(--lens-vignette, none); /* the composer grade's lens vignette — see site.css */
}

/* ---- title card: centered, lower third — the landing's film-title
       reveal (rise out of a soft blur, slow and damped, staggered) ---- */
.ct-card {
  position: absolute;
  left: 50%;
  bottom: clamp(88px, 12vh, 150px);
  transform: translateX(-50%);
  width: min(880px, 92vw);
  text-align: center;
  z-index: 2;
}
.ct-card > * {
  transition:
    opacity 1.7s ease,
    transform 1.7s cubic-bezier(0.16, 0.6, 0.2, 1),
    filter 1.7s ease;
}
/* pre-state exists only while the controller is alive (html.js — see the
   watchdog in contact.html); no-JS and failed-JS render everything settled */
html.js .ct-card > * {
  opacity: 0;
  transform: translateY(16px);
  filter: blur(9px);
}
html.js body.ct-in .ct-card > * { opacity: 1; transform: none; filter: none; }
body.ct-in .ct-eyebrow { transition-delay: 0.1s; }
body.ct-in .ct-rule { transition-delay: 0.3s; }
body.ct-in .ct-title { transition-delay: 0.5s; }
body.ct-in .ct-sub { transition-delay: 0.95s; }
body.ct-in .ct-cta { transition-delay: 1.35s; }

.ct-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 20px;
  font: 500 10px var(--f-mono);
  letter-spacing: 0.22em;
  color: #aeb6c2;
}
.ct-eyebrow::before {
  content: '';
  width: 5px;
  height: 5px;
  background: var(--hi);
  box-shadow: 0 0 7px rgba(237, 241, 245, 0.9);
  animation: pulse 3.6s ease-in-out infinite;
}
.ct-rule {
  width: 90px;
  height: 1px;
  margin: 0 auto 28px;
  background: linear-gradient(to right, transparent, #aeb6c2, transparent);
}
.ct-title {
  margin: 0 0 24px;
  font-family: var(--f-disp);
  font-weight: 400;
  font-size: clamp(23px, 3.6vw, 50px);
  line-height: 1.24;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-wrap: balance;
  background: linear-gradient(to bottom, #ffffff 30%, #8e99a7 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.ct-sub {
  margin: 0 auto 36px;
  max-width: 56ch;
  font-family: var(--f-text);
  font-weight: 400;
  font-size: clamp(13.5px, 1.2vw, 16px);
  line-height: 1.7;
  letter-spacing: 0.05em;
  color: #97a1af;
}
.ct-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 13px;
  flex-wrap: wrap;
}
/* hero buttons sit on the live scene — give the ghost a touch of body */
.ct-cta .btn.ghost { background: rgba(10, 13, 18, 0.4); }

/* ---- scroll cue: a hairline the current travels (S1), then the word ---- */
.ct-cue {
  position: absolute;
  left: 50%;
  bottom: 58px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  z-index: 2;
  transition: opacity 1.4s ease 2.2s;
}
html.js .ct-cue { opacity: 0; }
html.js body.ct-in .ct-cue { opacity: 1; }
.ct-cue:hover span { color: #cfd6dd; }
.ct-cue i {
  position: relative;
  width: 1px;
  height: 30px;
  background: rgba(174, 182, 194, 0.28);
  overflow: hidden;
}
.ct-cue i::after {
  content: '';
  position: absolute;
  left: 0;
  top: -40%;
  width: 100%;
  height: 40%;
  background: linear-gradient(to bottom, transparent, var(--hi));
  animation: cueDrop 3.4s cubic-bezier(0.6, 0, 0.3, 1) infinite;
}
@keyframes cueDrop {
  0% { top: -42%; opacity: 0; }
  12% { opacity: 1; }
  46% { top: 102%; opacity: 1; }
  58%, 100% { top: 102%; opacity: 0; }
}
.ct-cue span {
  font: 500 8.5px var(--f-mono);
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  color: var(--txt-3);
}
@media (max-height: 620px) { .ct-cue { display: none; } }

/* =====================================================================
   DOCUMENT — shared rhythm for the sections below the fold
   ===================================================================== */

/* scroll-staged reveal (site.css .rise is load-staged; these are
   viewport-staged — settled by src/contact.js as each enters). The
   hidden pre-state is gated on html.js so copy is never trapped. */
.io-rise {
  transition:
    opacity 1.1s ease,
    transform 1.1s cubic-bezier(0.16, 0.6, 0.2, 1),
    filter 1.1s ease;
}
html.js .io-rise:not(.is-in) {
  opacity: 0;
  transform: translateY(18px);
  filter: blur(8px);
}
.io-rise.d1 { transition-delay: 0.1s; }
.io-rise.d2 { transition-delay: 0.2s; }
.io-rise.d3 { transition-delay: 0.3s; }

/* section separator that runs the current (S1) once, on arrival */
.rule-x {
  position: relative;
  height: 1px;
  margin: clamp(56px, 9vh, 84px) 0;
  border: 0;
  background: var(--line);
  overflow: hidden;
}
.rule-x::after {
  content: '';
  position: absolute;
  top: 0;
  left: -22%;
  width: 22%;
  height: 100%;
  background: linear-gradient(to right, transparent, #cfd6dd, transparent);
  opacity: 0;
}
.rule-x.is-in::after { animation: ruleCurrent 1.2s cubic-bezier(0.5, 0, 0.3, 1) 1 forwards; }
@keyframes ruleCurrent {
  0% { left: -22%; opacity: 1; }
  100% { left: 102%; opacity: 1; }
}

/* the four steps break 4-up → 2×2 → stacked, never 3+1 */
.process .step { flex-basis: 200px; }

/* anchor jumps land clear of the fixed top bar */
main section[id] { scroll-margin-top: 78px; }

/* section header — mono label left, quiet spec meta right */
.sec-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  margin: 0 0 26px;
}
.sec-head .section-label { margin: 0; }
.sec-head .sec-meta {
  font: 400 9px var(--f-mono);
  letter-spacing: 0.16em;
  color: var(--txt-4);
  white-space: nowrap;
}
@media (max-width: 560px) { .sec-head .sec-meta { display: none; } }

/* contact display line — between page-title and card-title in the scale */
.ct-disp {
  margin: 0 0 22px;
  font-family: var(--f-disp);
  font-weight: 400;
  font-size: clamp(22px, 3.2vw, 40px);
  line-height: 1.3;
  letter-spacing: 0.03em;
  text-wrap: balance;
  background: linear-gradient(to bottom, #ffffff 34%, #8e99a7 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* =====================================================================
   01 — THE BRIEF
   ===================================================================== */
.ct-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 14px;
  align-items: start;
}
@media (max-width: 860px) { .ct-grid { grid-template-columns: 1fr; } }

/* site.css only stamps refs on cards — the form panel carries one too */
.panel > .ref {
  position: absolute;
  top: 12px;
  right: 20px;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.12em;
  color: var(--txt-4);
}

.ct-form { padding: 30px 30px 28px; }
.ct-form-cta { margin-top: 24px; }
.ct-form-note {
  margin: 18px 0 0;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.18em;
  color: var(--txt-4);
  transition: color 0.4s ease;
}
.ct-form.is-sent .ct-form-note { color: var(--txt-2); }

.ct-aside { display: grid; gap: 14px; }

.ct-include { padding: 26px 26px 10px; }
.ct-item {
  padding: 16px 2px 16px 0;
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: 52px 1fr;
  gap: 14px;
  align-items: baseline;
}
.ct-item .n {
  font: 400 9.5px var(--f-mono);
  letter-spacing: 0.18em;
  color: var(--txt-4);
}
.ct-item .t {
  display: block;
  font-family: var(--f-disp);
  font-size: 13px;
  letter-spacing: 0.05em;
  color: var(--txt);
  margin-bottom: 7px;
}
.ct-item .d {
  display: block;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--txt-3);
}

.ct-direct { padding: 26px 26px 24px; }
.ct-direct .dl { margin: 0; }

.ct-clocks { padding: 22px 26px 24px; }
.ct-clocks .section-label { margin-bottom: 14px; }

/* =====================================================================
   04 — THE CLOSE
   ===================================================================== */
.ct-close {
  padding: clamp(44px, 7vh, 72px) clamp(24px, 6vw, 72px);
  text-align: center;
}
.ct-close .ct-disp { margin-bottom: 16px; }
.ct-close .lead {
  max-width: 52ch;
  margin: 0 auto 8px;
}
.ct-close .cta-row {
  justify-content: center;
  margin-top: 34px;
}
.ct-close .foot-note {
  display: block;
  margin-top: 30px;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--txt-4);
}

/* terminus — one quiet line */
.ct-term {
  margin-top: clamp(56px, 9vh, 84px);
  text-align: center;
}
.ct-term p {
  margin: 0;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.22em;
  color: var(--txt-4);
}

/* =====================================================================
   Reduced motion — everything settles instantly
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .ct-card > *, .io-rise { transition: none; }
  .ct-cue { display: none; }
  .rule-x.is-in::after { animation: none; }
  .ct-stage { transform: none !important; opacity: 1 !important; }
}

/* =====================================================================
   ===== v8 ============================================================
   ---------------------------------------------------------------------
   02 — the intake-path instrument (protocol figure), 03 — the founder's
   letter with the self-drawing signature, 04 — close adjustments.
   All motion is CSS-only, slow and damped; the reduced-motion block at
   the end of this file freezes every figure at its final, legible state.
   ===================================================================== */

/* ---------------------------------------------------------------------
   02 · PROTOCOL — FIG-01 · THE INTAKE PATH
   One dial (four positions), one line (four stations), one gate.
   --------------------------------------------------------------------- */
.ct-proto-fig {
  margin: 0 0 14px;
  padding: 28px 30px 22px;
}
.ct-proto-row {
  display: flex;
  align-items: center;
  gap: clamp(20px, 4vw, 44px);
}
.ip-dial {
  flex: 0 0 auto;
  width: 84px;
  height: auto;
}
.ip-svg {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  height: auto;
}
.ct-proto-fig figcaption {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font: 400 9px var(--f-mono);
  letter-spacing: 0.18em;
  color: var(--txt-4);
}
@media (max-width: 640px) {
  .ip-dial { display: none; }
  .ct-proto-fig { padding: 24px 20px 18px; }
}

/* stroke grammar — identical hands to the services figures */
.ct-proto-fig svg :is(path, circle, rect) {
  fill: none;
  stroke: #59636f;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.ct-proto-fig svg .ghost { stroke: #242c37; }
.ct-proto-fig svg .hi { stroke: #dfe5ec; }
.ct-proto-fig svg .dot { fill: #59636f; stroke: none; }
.ct-proto-fig svg .hi-f { fill: #eef2f6; stroke: none; }
.ct-proto-fig svg .dash { stroke-dasharray: 2.5 6; }
.ct-proto-fig svg text {
  fill: #59636f;
  stroke: none;
  font: 500 10px var(--f-mono);
  letter-spacing: 0.18em;
}

/* draw-on-reveal: the instrument inks itself in when the row arrives.
   No JS → no pre-state → the drawing is simply there, complete. */
html.js .ct-proto-fig .d {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 2.2s cubic-bezier(0.16, 0.6, 0.2, 1);
}
html.js .ct-proto-fig .d2 { transition-delay: 0.4s; }
html.js .ct-proto-fig .d3 { transition-delay: 0.9s; }
html.js .ct-proto-fig.is-in .d { stroke-dashoffset: 0; }

/* the loop — one pulse walks the stations, the gate answers. 12s. */
.ip-carrier {
  opacity: 0;
  animation: ipTravel 12s cubic-bezier(0.5, 0, 0.25, 1) infinite;
}
@keyframes ipTravel {
  0%   { transform: translateX(76px); opacity: 0; }
  2%   { opacity: 1; }
  5%   { transform: translateX(76px); }
  13%  { transform: translateX(212px); }
  22%  { transform: translateX(212px); }
  30%  { transform: translateX(348px); }
  39%  { transform: translateX(348px); }
  47%  { transform: translateX(484px); }
  55%  { transform: translateX(484px); }
  63%  { transform: translateX(540px); opacity: 1; }
  66%  { transform: translateX(540px); opacity: 0; }
  100% { transform: translateX(540px); opacity: 0; }
}

/* stations light as the pulse reaches them, dim for the reset */
.ip-lit { opacity: 0; animation: 12s ease infinite; }
.ip-lit1 { animation-name: ipLit1; }
.ip-lit2 { animation-name: ipLit2; }
.ip-lit3 { animation-name: ipLit3; }
.ip-lit4 { animation-name: ipLit4; }
@keyframes ipLit1 { 0% { opacity: 0; } 3% { opacity: 1; } 88% { opacity: 1; } 94%, 100% { opacity: 0; } }
@keyframes ipLit2 { 0%, 11% { opacity: 0; } 14% { opacity: 1; } 88% { opacity: 1; } 94%, 100% { opacity: 0; } }
@keyframes ipLit3 { 0%, 28% { opacity: 0; } 31% { opacity: 1; } 88% { opacity: 1; } 94%, 100% { opacity: 0; } }
@keyframes ipLit4 { 0%, 45% { opacity: 0; } 48% { opacity: 1; } 88% { opacity: 1; } 94%, 100% { opacity: 0; } }

/* the seam — a resting ember that ignites when the pulse arrives */
.ip-seam { opacity: 0.3; animation: ipSeam 12s ease infinite; }
@keyframes ipSeam {
  0%, 60% { opacity: 0.3; }
  65%     { opacity: 1; }
  86%     { opacity: 1; }
  96%, 100% { opacity: 0.3; }
}
.ip-seamglow { stroke-width: 4; opacity: 0; animation: ipSeamGlow 12s ease infinite; }
@keyframes ipSeamGlow {
  0%, 60% { opacity: 0; }
  66%     { opacity: 0.3; }
  84%     { opacity: 0.3; }
  94%, 100% { opacity: 0; }
}

/* the slabs part — a few pixels, damped, then close for the reset */
.ip-door-l { animation: ipDoorL 12s cubic-bezier(0.16, 0.6, 0.2, 1) infinite; }
.ip-door-r { animation: ipDoorR 12s cubic-bezier(0.16, 0.6, 0.2, 1) infinite; }
@keyframes ipDoorL {
  0%, 62% { transform: translateX(0); }
  72%     { transform: translateX(-5px); }
  84%     { transform: translateX(-5px); }
  94%, 100% { transform: translateX(0); }
}
@keyframes ipDoorR {
  0%, 62% { transform: translateX(0); }
  72%     { transform: translateX(5px); }
  84%     { transform: translateX(5px); }
  94%, 100% { transform: translateX(0); }
}

/* the dial — four positions, stepped in time with the stations */
.ip-needle {
  transform: rotate(-120deg);
  transform-origin: 45px 45px;
  animation: ipDial 12s cubic-bezier(0.16, 0.6, 0.2, 1) infinite;
}
@keyframes ipDial {
  0%, 11%  { transform: rotate(-120deg); }
  14%      { transform: rotate(-40deg); }
  28%      { transform: rotate(-40deg); }
  31%      { transform: rotate(40deg); }
  45%      { transform: rotate(40deg); }
  48%      { transform: rotate(120deg); }
  88%      { transform: rotate(120deg); }
  94%, 100% { transform: rotate(-120deg); }
}

/* the loop holds until the figure is actually on stage */
html.js .ct-proto-fig:not(.is-in)
  :is(.ip-carrier, .ip-lit, .ip-seam, .ip-seamglow, .ip-door-l, .ip-door-r, .ip-needle) {
  animation: none;
}

/* ---------------------------------------------------------------------
   03 · THE FOUNDER — the plate and the letter, signed
   --------------------------------------------------------------------- */
.ct-founder {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: 14px;
  align-items: start;
}
@media (max-width: 860px) { .ct-founder { grid-template-columns: 1fr; } }

/* the plate — notched panel, corner-cut brackets at the open corners */
.ct-plate { padding: 28px 26px 26px; }
.ct-plate::before,
.ct-plate::after {
  content: '';
  position: absolute;
  width: 13px;
  height: 13px;
  border: 1px solid #242c37;
  pointer-events: none;
}
.ct-plate::before { top: 9px; left: 9px; border-right: 0; border-bottom: 0; }
.ct-plate::after { bottom: 9px; right: 9px; border-left: 0; border-top: 0; }
.ct-plate .dl { grid-template-columns: 1fr; gap: 0; }
.ct-plate .dl dt {
  padding: 14px 0 6px;
  border-top: 1px solid var(--line);
}
.ct-plate .dl dd {
  padding: 0 0 14px;
  font: 500 11px var(--f-mono);
  letter-spacing: 0.14em;
  color: var(--txt);
}

/* the letter */
.ct-letter { padding: clamp(30px, 4.5vw, 50px) clamp(26px, 5vw, 58px) 40px; }
.ct-letter-head {
  margin: 0 0 26px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
  font: 500 10px var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--txt-3);
}
.ct-letter > p:not(.ct-letter-head) {
  margin: 0 0 18px;
  max-width: 62ch;
  font-size: 15px;
  line-height: 1.8;
  letter-spacing: 0.01em;
  color: var(--txt-2);
}

/* the signature — drawn by hand when the letter arrives, then still */
.ct-sig { margin-top: 34px; }
.ct-sig-svg {
  display: block;
  width: min(300px, 82%);
  height: auto;
  margin-left: -6px;
}
.ct-sig-svg .s {
  fill: none;
  stroke: #dfe5ec;
  stroke-width: 1.3;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.ct-sig-svg .s3 { stroke: #97a1af; stroke-width: 1; }
.ct-sig-dot { fill: #eef2f6; stroke: none; }
html.js .ct-letter .ct-sig-svg .s {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
}
html.js .ct-letter .ct-sig-svg .s1 { transition: stroke-dashoffset 1.25s cubic-bezier(0.4, 0, 0.3, 1) 0.2s; }
html.js .ct-letter .ct-sig-svg .s2 { transition: stroke-dashoffset 1.05s cubic-bezier(0.4, 0, 0.3, 1) 1.35s; }
html.js .ct-letter .ct-sig-svg .s3 { transition: stroke-dashoffset 0.5s cubic-bezier(0.4, 0, 0.3, 1) 2.3s; }
html.js .ct-letter .ct-sig-dot {
  opacity: 0;
  transition: opacity 0.6s ease 2.7s;
}
html.js .ct-letter.is-in .ct-sig-svg .s { stroke-dashoffset: 0; }
html.js .ct-letter.is-in .ct-sig-dot { opacity: 1; }
.ct-sig-name {
  margin: 12px 0 0;
  font: 500 9.5px var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--txt-2);
}
.ct-sig-loc {
  margin: 7px 0 0;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.22em;
  color: var(--txt-4);
}

/* ---------------------------------------------------------------------
   Reduced motion — extends the house block above. Every v8 figure
   freezes at its final, legible state: line drawn, stations lit,
   seam bright, slabs parted, dial at position four, signature signed.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .ct-proto-fig svg *,
  .ct-sig-svg *,
  .ct-sig-dot {
    animation: none !important;
    transition: none !important;
  }
  html.js .ct-proto-fig .d,
  html.js .ct-letter .ct-sig-svg .s { stroke-dashoffset: 0; }
  html.js .ct-letter .ct-sig-dot { opacity: 1; }
  .ip-carrier { opacity: 0; }
  .ip-lit { opacity: 1; }
  .ip-seam { opacity: 1; }
  .ip-seamglow { opacity: 0.3; }
  .ip-door-l { transform: translateX(-5px); }
  .ip-door-r { transform: translateX(5px); }
  .ip-needle { transform: rotate(120deg); }
}
