@charset "UTF-8";
/* ==================================================================
   Fusionki — app.css
   Type scale, motion durations and effect parameters are injected as
   custom properties by index.php from setting/config.php. Nothing in
   this file hardcodes a value the administrator is allowed to change.
   ================================================================== */

/* ---------- Self-hosted faces. See assets/fonts/README.md --------- */
@font-face{
  font-family:'Familjen Grotesk';
  src:url('../fonts/familjen-grotesk-latin-ext.woff2') format('woff2');
  font-weight:400 700; font-style:normal; font-display:swap;
  unicode-range:U+0000-00FF,U+0100-024F,U+0259,U+1E00-1EFF,U+2000-206F,U+2190-21BB,U+2212;
}
@font-face{
  font-family:'Inter';
  src:url('../fonts/inter-latin-ext.woff2') format('woff2');
  font-weight:400 600; font-style:normal; font-display:swap;
  unicode-range:U+0000-00FF,U+0100-024F,U+0259,U+1E00-1EFF,U+2000-206F,U+2212;
}
@font-face{
  font-family:'JetBrains Mono';
  src:url('../fonts/jetbrains-mono-latin-ext.woff2') format('woff2');
  font-weight:400 500; font-style:normal; font-display:swap;
  unicode-range:U+0000-00FF,U+0100-024F,U+2000-206F,U+2212;
}

/* ==================================================================
   TOKENS
   ================================================================== */
:root{
  /* --paper, --paper-lift, --paper-rgb, --ink, --ink-2, --ink-3, --ink-rgb,
     --signal-ink, --rule and --rule-soft are all emitted by index.php from
     setting/config.php -> theme.background. See lib/theme.php. The fallbacks
     below are the level-50 values, so this stylesheet is still correct if it
     is ever opened on its own. */
  --paper:#E9ECE8;
  --paper-lift:#F3F5F1;
  --paper-rgb:233,236,232;
  --ink:#131A19;            /* 13.9:1 on --paper  */
  --ink-2:#4C5854;          /* 7.4:1  on --paper  */
  --ink-3:#6C7873;          /* 4.6:1  on --paper — AA for text, used at >=14px */
  --ink-rgb:19,26,25;
  --rule:rgba(19,26,25,0.14);
  --rule-soft:rgba(19,26,25,0.07);

  --signal:#0FB88A;
  --signal-ink:#0A7A5B;     /* 4.6:1 on --paper — the accent when it carries text */
  --signal-lift:#52E3B8;
  --cool:#86B4FF;
  --cool-ink:#2F62C4;
  --warm:#FFCE94;
  --warm-ink:#8A5A12;

  /* spacing scale — every margin and padding uses a step */
  --s1:.25rem; --s2:.5rem;  --s3:.75rem; --s4:1rem;   --s5:1.5rem;
  --s6:2rem;   --s7:3rem;   --s8:4.5rem; --s9:7rem;   --s10:9.5rem;

  --nav-h:5.75rem;
  --radius:.375rem;
  --tap:2.75rem;            /* 44px minimum touch target */

  --ease:cubic-bezier(.22,.85,.25,1);
  --spring:cubic-bezier(.24,1.18,.32,1);

  /* overridden by index.php from setting/config.php */
  --dur-fast:.28s; --dur:.45s; --dur-slow:.8s;
  --wordmark-ms:1900ms;
}

*,*::before,*::after{margin:0;padding:0;box-sizing:border-box;}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;}
body{
  font-family:var(--font-body);
  font-size:var(--fs-body);
  line-height:var(--lh-body);
  background:var(--paper);
  color:var(--ink);
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
h1,h2,h3{font-family:var(--font-display);font-weight:600;
  line-height:var(--lh-heading);letter-spacing:var(--ls-heading);}
h1{font-size:var(--fs-h1);} h2{font-size:var(--fs-h2);} h3{font-size:var(--fs-h3);}
p{max-width:62ch;}
a{color:inherit;}
img,svg{max-width:100%;}
::selection{background:rgba(15,184,138,.22);}

:focus-visible{outline:2px solid var(--ink);outline-offset:3px;border-radius:2px;}
.skip{
  position:absolute;left:var(--s4);top:-4rem;z-index:200;
  background:var(--ink);color:var(--paper);padding:var(--s3) var(--s4);
  border-radius:var(--radius);text-decoration:none;
  transition:transform var(--dur-fast) var(--ease);
}
.skip:focus{transform:translateY(5rem);}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}

.mono{font-family:var(--font-mono);font-size:var(--fs-mono);
  letter-spacing:.15em;text-transform:uppercase;color:var(--ink-3);}
.mono b{color:var(--signal-ink);font-weight:500;}

/* faint measurement grid over the whole page */
body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:
    linear-gradient(var(--rule-soft) 1px,transparent 1px),
    linear-gradient(90deg,var(--rule-soft) 1px,transparent 1px);
  background-size:6rem 6rem;
  -webkit-mask-image:radial-gradient(120% 90% at 50% 18%,#000 18%,transparent 74%);
          mask-image:radial-gradient(120% 90% at 50% 18%,#000 18%,transparent 74%);
}

/* configurable background effect canvas (off by default) */

/* The mark's own styles now live in assets/css/marks.css, so the site, the
   admin panel and the meeting client all animate from one source. Loading
   three copies is how they drift apart. */

/* ==================================================================
   KINETIC WORDMARK
   ================================================================== */
.kw{
  display:inline-flex;perspective:1100px;transform-style:preserve-3d;
  background:none;border:0;padding:0;color:inherit;cursor:pointer;
  font-family:var(--font-display);font-weight:600;letter-spacing:-.03em;
  min-height:var(--tap);align-items:center;
}
.kw span{
  display:inline-block;white-space:pre;
  transition:transform calc(var(--wordmark-ms) * .34) var(--spring),
             opacity var(--dur-fast) ease, filter var(--dur-fast) ease;
  will-change:transform,opacity;backface-visibility:hidden;
}
.kw.pulling span{transition-timing-function:cubic-bezier(.62,0,.86,.28);}
.nav-kw{font-size:var(--wordmark-size,var(--fs-navmark));color:var(--wordmark-color,var(--ink));
  opacity:var(--wordmark-opacity,1);text-shadow:var(--wordmark-shadow,none);}
.hero-kw{font-size:var(--fs-wordmark);font-weight:700;letter-spacing:-.045em;line-height:.9;}

/* cinematic layer the mark flies into */
#stagecurtain{
  position:fixed;inset:0;z-index:150;pointer-events:none;
  display:grid;place-items:center;
  background:radial-gradient(60% 60% at 50% 50%,rgba(var(--paper-rgb),.94),rgba(var(--paper-rgb),0));
  opacity:0;transition:opacity var(--dur) ease;
}
#stagecurtain.on{opacity:1;}
#curtainmark{
  width:min(34vmin,17rem);height:min(34vmin,17rem);
  transform:scale(.2);opacity:0;
  transition:transform calc(var(--wordmark-ms) * .42) var(--spring),
             opacity calc(var(--wordmark-ms) * .26) ease;
}
#stagecurtain.on #curtainmark{transform:scale(1);opacity:1;}

/* ==================================================================
   NAV
   ================================================================== */
.nav{
  position:fixed;inset:0 0 auto 0;z-index:60;height:var(--nav-h);
  display:flex;align-items:center;padding:0 var(--s6);
  transition:background var(--dur) ease,box-shadow var(--dur) ease;
}
.nav.solid{
  background:rgba(var(--paper-rgb),.86);
  -webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);
  box-shadow:0 1px 0 var(--rule);
}
.nav-inner{width:100%;max-width:86rem;margin:0 auto;
  display:flex;align-items:center;justify-content:space-between;gap:var(--s5);}
.brand{display:flex;align-items:center;gap:var(--s3);text-decoration:none;}
.brand > a{display:flex;align-items:center;text-decoration:none;}
.brand .mark{width:var(--logo-size,2.75rem);height:var(--logo-size,2.75rem);
  opacity:var(--logo-opacity,1);filter:drop-shadow(var(--logo-shadow,none));}
/* the ribbon mark carries type, so it needs more room than the others */
.brand .mark--eclipsefusionki{width:calc(var(--logo-size,2.75rem) * 1.27);
  height:calc(var(--logo-size,2.75rem) * 1.27);}
.nav-links{display:flex;align-items:center;gap:var(--s5);}
.nav-links a{
  font-size:var(--fs-nav);font-weight:500;color:var(--ink-2);text-decoration:none;
  padding:var(--s2) 0;min-height:var(--tap);display:inline-flex;align-items:center;
  transition:color var(--dur-fast) ease;
}
.nav-links a:hover{color:var(--ink);}
.nav-cta{
  border:1px solid var(--ink);border-radius:999px;padding:0 var(--s5) !important;
  white-space:nowrap;
  color:var(--ink) !important;
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);
}
.nav-cta:hover{background:var(--ink);color:var(--paper) !important;}
.nav-toggle{display:none;}

/* ==================================================================
   HERO
   ================================================================== */
.hero{
  position:relative;z-index:2;min-height:100svh;isolation:isolate;
  display:flex;flex-direction:column;justify-content:center;
  padding:calc(var(--nav-h) + var(--s6)) var(--s6) var(--s6);
}
.hero-inner{position:relative;z-index:2;width:100%;max-width:86rem;margin:0 auto;}

/* the instrument band: the trace and its readout live here and nowhere else */
.hero-band{position:relative;z-index:2;width:100%;max-width:86rem;
  margin:var(--s6) auto 0;
  height:calc(clamp(9rem,22vh,14rem) * var(--band-scale,1));flex:0 0 auto;
  pointer-events:none;}
.hero-band .readout{pointer-events:auto;}
/* The instrument runs behind the whole hero, not in a box beside it — the
   drawing and the sentence occupy the same space, which is the point.
   What makes that readable rather than noisy is the veil: a mask that holds
   the drawing at a fraction of its strength across the column the copy sits
   in, and lets it come to full strength in the open air to the right and
   below. So the line passes *behind* the words instead of through them, and
   the eye still lands on the text first. */
#trace{
  filter:drop-shadow(var(--hero-shadow,none));
  position:absolute;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;
  /* No CSS mask here. A mask on an element this large promotes it to its own
     composited layer and makes the browser re-composite the whole hero on
     every frame — a large part of what made scrolling feel heavy. The veil is
     drawn into the canvas instead: one gradient fill in destination-out at
     the end of each frame, which costs nothing and can follow the layout
     (horizontal beside the copy on a wide screen, vertical below it on a
     narrow one). See size() in assets/js/app.js. */
}
.hero-top{
  display:flex;justify-content:space-between;gap:var(--s4);flex-wrap:wrap;
  border-bottom:1px solid var(--rule);padding-bottom:var(--s3);margin-bottom:var(--s7);
}
.hero h1{margin:0 0 var(--s5);}
.hero-kw-line{display:block;margin-bottom:var(--s2);}
.hero-tagline{display:block;font-size:var(--fs-h2);color:var(--ink);max-width:22ch;}

/* the 40–50 word answer block, directly under the H1 */
.snippet{
  border-left:2px solid var(--signal);padding-left:var(--s4);
  max-width:48ch;color:var(--ink-2);font-size:var(--fs-lede);margin:0;
}
/* the snippet block and the lede sit side by side so the hero still fits
   one screen once the wordmark is at full size */
.hero-lede{display:grid;grid-template-columns:repeat(auto-fit,minmax(18rem,1fr));
  gap:var(--s7);align-items:start;}
.hero-lede--single{grid-template-columns:minmax(0,1fr);}
.hero-lede--single > div{display:flex;flex-direction:column;gap:var(--s2);}
.hero-lede--single > div > p{max-width:56ch;margin-bottom:var(--s4);}
.hero-lede > div > p{max-width:38ch;color:var(--ink-2);font-size:var(--fs-lede);
  margin-bottom:var(--s5);}
.hero-actions{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center;}

.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:var(--tap);padding:0 var(--s5);border-radius:999px;
  font-family:var(--font-body);font-size:var(--fs-nav);font-weight:500;
  text-decoration:none;border:1px solid transparent;cursor:pointer;
  transition:transform var(--dur-fast) var(--ease),background var(--dur-fast) ease,
             border-color var(--dur-fast) ease,color var(--dur-fast) ease;
}
.btn-solid{background:var(--ink);color:var(--paper);}
.btn-solid:hover{background:var(--signal-ink);transform:translateY(-2px);}
.btn-line{border-color:var(--rule);color:var(--ink);background:rgba(var(--paper-rgb),.55);}
.btn-line:hover{border-color:var(--ink);transform:translateY(-2px);}

.hint{
  display:inline-flex;align-items:center;gap:var(--s2);margin-top:var(--s4);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);
  transition:opacity var(--dur-slow) ease;
}
.hint.gone{opacity:0;}
.hint i{width:.375rem;height:.375rem;border-radius:50%;background:var(--signal);
  animation:blink 1.9s ease-in-out infinite;}
@keyframes blink{0%,100%{opacity:1;}50%{opacity:.2;}}

.readout{
  position:absolute;inset:auto 0 0 0;z-index:2;
  display:flex;justify-content:space-between;align-items:center;
  gap:var(--s4);flex-wrap:wrap;border-top:1px solid var(--rule);padding-top:var(--s3);
}
.readout span{display:inline-flex;gap:var(--s2);align-items:center;}

/* morph state indicator: instrument  ->  sensor mesh */
.morph-state{display:inline-flex;align-items:center;gap:var(--s2);}
.morph-bar{width:3.5rem;height:2px;background:var(--rule);position:relative;overflow:hidden;}
.morph-bar i{position:absolute;inset:0 auto 0 0;width:100%;background:var(--signal);
  transform:scaleX(var(--morph,0));transform-origin:left center;
  transition:transform .3s linear;}

/* ==================================================================
   SPINE
   ================================================================== */
.spine{position:fixed;left:var(--s5);top:50%;z-index:40;
  transform:translateY(-50%);opacity:0;pointer-events:none;
  transition:opacity var(--dur) ease;}
.spine.show{opacity:1;pointer-events:auto;}
.spine-track{position:relative;width:1px;height:15rem;background:var(--rule);}
.spine-fill{position:absolute;inset:0 auto auto 0;width:1px;height:100%;
  background:var(--signal);transform:scaleY(var(--p,0));transform-origin:top center;
  transition:transform .18s linear;}
.spine-dots{position:absolute;inset:0;display:flex;flex-direction:column;
  justify-content:space-between;align-items:center;}
.spine-dot{
  width:var(--tap);height:var(--tap);background:none;border:0;cursor:pointer;
  display:grid;place-items:center;position:relative;
}
.spine-dot::before{
  content:"";width:.44rem;height:.44rem;border-radius:50%;
  background:var(--paper);border:1px solid var(--ink-3);
  transition:background var(--dur-fast),border-color var(--dur-fast),transform var(--dur-fast) var(--spring);
}
.spine-dot[aria-current="true"]::before{background:var(--signal);border-color:var(--signal);transform:scale(1.5);}
.spine-dot em{
  position:absolute;left:100%;top:50%;transform:translateY(-50%) translateX(-.25rem);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.14em;
  text-transform:uppercase;font-style:normal;color:var(--ink-2);white-space:nowrap;
  background:var(--paper);padding:var(--s1) var(--s2);opacity:0;
  transition:opacity var(--dur-fast) ease,transform var(--dur-fast) var(--ease);
}
.spine-dot:hover em,.spine-dot:focus-visible em{opacity:1;transform:translateY(-50%) translateX(0);}

/* ==================================================================
   READING HIERARCHY
   Four deliberate levels, so a visitor scanning the page always knows
   where to enter and never meets a wall of one grey.

     tag      mono, uppercase, accent — where am I
     h2       display, tight — what is this about
     p:first  lede size, --ink-2 — the claim, sized to be read
     p        body, --ink-2 — the support, sized to be skimmed

   The accent carries the eye down the page: it appears on the section
   tag, on the first letters of the lede, and on the legend dot. Nowhere
   else, so it never stops meaning "look here".
   ================================================================== */
.state-copy .tag,.section-head .mono,.contact-side > .mono{
  display:inline-block;color:var(--signal-ink);
  padding-bottom:var(--s2);margin-bottom:var(--s4);
  border-bottom:1px solid color-mix(in srgb,var(--signal) 40%,transparent);
}
.state-copy h2,.section-head h2{margin-bottom:var(--s5);}

/* The first paragraph of a section is the claim; give it the room to be
   read, and let the ones after it be scanned. */
.state-copy p:first-of-type,.section-head p{
  font-size:var(--fs-lede);color:var(--ink-2);max-width:44ch;
}
.state-copy p + p{margin-top:var(--s4);font-size:var(--fs-body);max-width:52ch;}

/* One accent-coloured opening phrase per section is enough to pull the eye
   in without turning the page into a highlighter. */
.state-copy p:first-of-type::first-line{color:var(--ink);}

/* ==================================================================
   STATE SECTIONS
   ================================================================== */
.state{position:relative;z-index:2;display:flex;align-items:center;
  padding:var(--s9) var(--s6);border-top:1px solid var(--rule);min-height:100svh;}
.state-grid{width:100%;max-width:86rem;margin:0 auto;display:grid;
  grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
  gap:var(--s8);align-items:center;}
.state-copy{max-width:29rem;}
/* shrink-wrapped by the hierarchy block above; the rule that set
   display:block here made the underline span the whole column, which
   read as a divider rather than as a label */
.state-copy h2{margin-bottom:var(--s4);}
.state-copy p{color:var(--ink-2);}
.state-copy p + p{margin-top:var(--s3);}
.state-copy p.mono{font-size:var(--fs-mono);line-height:1.8;margin-top:var(--s5);}

.legend{list-style:none;margin-top:var(--s5);border-top:1px solid var(--rule);}
.legend li{display:flex;align-items:center;gap:var(--s3);padding:var(--s3) 0;
  border-bottom:1px solid var(--rule-soft);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.06em;
  text-transform:none;color:var(--ink-2);}
.legend i{width:.9rem;height:2px;border-radius:2px;background:var(--ink-3);flex:0 0 auto;}
.legend i.sig{background:var(--signal);}
.legend i.cool{background:var(--cool);}
.legend i.warm{background:var(--warm);}
.legend i.dot{width:.44rem;height:.44rem;border-radius:50%;}

.stage{position:relative;border:1px solid var(--rule);border-radius:var(--radius);
  background:linear-gradient(180deg,var(--paper-lift),transparent);padding:var(--s4);}
.stage::before,.stage::after{content:"";position:absolute;width:.44rem;height:.44rem;
  border:1px solid var(--ink-3);opacity:.5;}
.stage::before{top:-1px;left:-1px;border-right:0;border-bottom:0;}
.stage::after{bottom:-1px;right:-1px;border-left:0;border-top:0;}
.stage svg,.stage canvas{display:block;width:100%;height:auto;}
.stage figcaption{display:flex;justify-content:space-between;gap:var(--s3);flex-wrap:wrap;
  margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--rule);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);}
.stage figcaption b{color:var(--signal-ink);font-weight:500;}

.flowline{fill:none;stroke-width:1.6;}
.flow-a{stroke:var(--signal);} .flow-b{stroke:var(--cool);}
.flow-out{stroke:var(--ink);stroke-dasharray:5 5;opacity:.75;}
.pip-a{fill:var(--signal);} .pip-b{fill:var(--cool);}
.merge-node{fill:var(--ink);} .merge-halo{fill:var(--signal);opacity:.16;}
.node-pulse{transform-box:fill-box;transform-origin:center;
  animation:nodePulse 2.4s ease-in-out infinite;}
@keyframes nodePulse{0%,100%{opacity:.55;transform:scale(.9);}50%{opacity:1;transform:scale(1.12);}}

.rung{stroke:var(--rule);stroke-width:1.4;fill:none;transition:stroke var(--dur-fast);}
.rung.lit{stroke:var(--signal);stroke-width:2;}
.step-box{fill:var(--paper-lift);stroke:var(--rule);stroke-width:1;
  transition:fill var(--dur-fast),stroke var(--dur-fast);}
.step-box.lit{fill:var(--paper-lift);stroke:var(--signal);}
.step-label{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.1em;
  fill:var(--ink-2);text-transform:uppercase;transition:fill var(--dur-fast);}
.step-label.lit{fill:var(--ink);}
.retry-path{stroke:var(--warm-ink);stroke-width:1.4;fill:none;stroke-dasharray:4 4;
  opacity:0;transition:opacity var(--dur-fast);}
.retry-path.on{opacity:1;}

.cand{transition:opacity var(--dur-slow) ease,y var(--dur-slow) var(--ease),
  height var(--dur-slow) var(--ease),fill var(--dur) ease;}
.band{fill:var(--signal);opacity:.14;transition:x var(--dur-slow) var(--ease),width var(--dur-slow) var(--ease);}
.pointer-line{stroke:var(--ink);stroke-width:1.4;transition:x1 var(--dur-slow) var(--ease),x2 var(--dur-slow) var(--ease);}

input[type=range]{width:100%;min-height:var(--tap);accent-color:var(--signal);}

/* ==================================================================
   SERVICES / FAQ / CONTACT
   ================================================================== */
.section{position:relative;z-index:2;max-width:86rem;margin:0 auto;padding:var(--s9) var(--s6);}
.section-head{max-width:38rem;margin-bottom:var(--s7);}
.section-head h2{margin:var(--s4) 0;}
.section-head p{color:var(--ink-2);}

.cap-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(17rem,1fr));
  border-top:1px solid var(--rule);}
.cap{position:relative;padding:var(--s6) var(--s5) var(--s7);
  border-bottom:1px solid var(--rule);border-right:1px solid var(--rule);overflow:hidden;}
.cap:last-child{border-right:0;}
.cap::after{content:"";position:absolute;left:0;bottom:-1px;height:1px;width:100%;
  background:var(--signal);transform:scaleX(0);transform-origin:left center;
  transition:transform var(--dur-slow) var(--ease);}
.cap:hover::after,.cap:focus-within::after{transform:scaleX(1);}
.cap h3{margin:var(--s4) 0 var(--s3);}
.cap p{color:var(--ink-2);font-size:var(--fs-small);}
.cap-ix{font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.16em;
  color:var(--ink-3);text-transform:uppercase;}

.faq-list{border-top:1px solid var(--rule);max-width:52rem;}
.faq-item{border-bottom:1px solid var(--rule);}
.faq-q{
  width:100%;min-height:var(--tap);background:none;border:0;cursor:pointer;
  display:flex;align-items:center;justify-content:space-between;gap:var(--s4);
  padding:var(--s5) 0;text-align:left;color:var(--ink);
  font-family:var(--font-display);font-size:var(--fs-h3);font-weight:600;
}
.faq-q .chev{flex:0 0 auto;width:.9rem;height:.9rem;position:relative;}
.faq-q .chev::before,.faq-q .chev::after{
  content:"";position:absolute;inset:50% 0 auto 0;height:1.5px;background:var(--ink-2);
  transition:transform var(--dur) var(--ease);}
.faq-q .chev::after{transform:rotate(90deg);}
.faq-q[aria-expanded="true"] .chev::after{transform:rotate(0deg);}
.faq-a{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--dur) var(--ease);}
.faq-q[aria-expanded="true"] + .faq-a{grid-template-rows:1fr;}
.faq-a > div{overflow:hidden;}
.faq-a p{color:var(--ink-2);padding-bottom:var(--s5);}

.contact-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(19rem,1fr));
  gap:var(--s8);align-items:start;}

/* The left column carries three separate things — an invitation, the facts,
   and who you are writing to — and it sits opposite a form. Each fact is
   therefore built in exactly the shape of a field on that form: a small mono
   label above, the value below it, a hairline underneath. The two columns
   then share one rhythm instead of being two designs facing each other. */
.contact-side h2{margin:var(--s4) 0;}
.contact-lead{color:var(--ink-2);max-width:36ch;font-size:var(--fs-lede);}
.contact-lead a{color:var(--signal-ink);text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--signal) 45%,transparent);}
.contact-lead a:hover{border-bottom-color:var(--signal);}

.contact-facts{margin-top:var(--s7);opacity:var(--contact-opacity,1);}
.contact-facts > div{box-shadow:var(--contact-shadow,none);}
.contact-facts > div{padding:0 0 var(--s3);margin-bottom:var(--s5);
  border-bottom:1px solid var(--rule);}
.contact-facts > div:last-child{margin-bottom:0;}
.contact-facts dt{
  font-family:var(--font-mono);
  font-size:var(--contact-label-size,var(--fs-mono));
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--contact-label-color,var(--ink-3));
  margin-bottom:var(--s3);
}
.contact-facts dd{
  font-size:var(--contact-value-size,var(--fs-body));
  color:var(--contact-value-color,var(--ink));
  line-height:1.3;
}
.contact-facts dd a{color:inherit;text-decoration:none;
  border-bottom:1px solid transparent;
  min-height:var(--tap);display:inline-flex;align-items:center;
  transition:border-color .2s var(--ease),color .2s var(--ease);}
.contact-facts dd a:hover{color:var(--signal-ink);border-bottom-color:var(--signal);}

.contact-org{display:grid;gap:2px;margin-top:var(--s7);padding-top:var(--s4);
  border-top:1px solid var(--rule);
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);}
.contact-org span:first-child{color:var(--ink-2);}

.form{position:relative;}
.f-row{position:relative;border-bottom:1px solid var(--rule);padding:var(--s4) 0 var(--s2);}
.f-row label{position:absolute;top:var(--s4);left:0;
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);pointer-events:none;
  transition:transform var(--dur-fast) var(--ease),color var(--dur-fast) ease;}
.f-row.filled label,.f-row:focus-within label{transform:translateY(-1rem) scale(.86);
  transform-origin:left center;color:var(--signal-ink);}
.f-row input,.f-row textarea,.f-row select{
  width:100%;border:0;background:none;outline:none;resize:none;color:var(--ink);
  font-family:var(--font-body);font-size:var(--fs-body);padding-top:var(--s2);
  min-height:var(--tap);}
.f-row.invalid{border-bottom-color:#B3261E;}
.f-row .err{display:block;color:#B3261E;font-size:var(--fs-mono);
  font-family:var(--font-mono);margin-top:var(--s1);}
.hp{position:absolute!important;left:-9999px;width:1px;height:1px;overflow:hidden;}
.form-notice{margin-top:var(--s5);padding:var(--s3) var(--s4);
  border-left:2px solid #B3261E;background:var(--paper-lift);
  color:var(--ink);font-size:var(--fs-small);max-width:none;}
.form-notice code{font-family:var(--font-mono);font-size:var(--fs-mono);color:var(--ink-3);}
.form-foot{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s4);margin-top:var(--s6);flex-wrap:wrap;}
.form-body{transition:opacity var(--dur) ease,transform var(--dur) ease;}
.form.busy .form-body{opacity:0;transform:translateY(-.5rem);pointer-events:none;}
.form-state{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:flex-start;justify-content:center;gap:var(--s4);
  opacity:0;pointer-events:none;transition:opacity var(--dur) ease .15s;}
.form.busy .form-state{opacity:1;}
.form-state p{font-family:var(--font-display);font-size:var(--fs-h3);font-weight:500;}
.form-state .mark{width:2.5rem;height:2.5rem;}

/* ==================================================================
   FOOTER + LANGUAGE SWITCHER
   The switcher has no border. It starts flush with the page colour on
   the left and resolves into the page blue on the right, lifting into
   a curve that ends in a single shadow — so it reads as a fold in the
   paper rather than a control pasted on top of it.
   ================================================================== */
.foot{position:relative;z-index:2;border-top:1px solid var(--rule);padding:var(--s6);}
.foot-inner{max-width:86rem;margin:0 auto;display:flex;flex-wrap:wrap;
  align-items:center;justify-content:space-between;gap:var(--s4);}
.foot-legal{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;
  /* the switcher is the last thing on the line and the only coloured one,
     so it reads as the control and the links read as text */
  justify-content:flex-end;}
.foot-legal .lang{margin-left:var(--s2);}
.foot-legal{opacity:var(--foot-legal-opacity,1);text-shadow:var(--foot-legal-shadow,none);}
.foot-legal a,.legal-note{font-size:var(--foot-legal-size,var(--fs-mono));
  color:var(--foot-legal-color,var(--ink-3));}
.foot-legal > .mono{font-size:var(--foot-legal-size,var(--fs-mono));
  color:var(--foot-legal-color,var(--ink-3));}
.foot-inner > .mono{opacity:var(--foot-brand-opacity,1);text-shadow:var(--foot-brand-shadow,none);
  font-size:var(--foot-brand-size,var(--fs-mono));
  color:var(--foot-brand-color,var(--ink-3));}
.foot-meet{display:inline-flex;align-items:center;gap:var(--s2);
  color:var(--signal-ink) !important;}
.foot-meet i{width:.5rem;height:.5rem;border-radius:50%;background:var(--signal);
  box-shadow:0 0 0 0 color-mix(in srgb,var(--signal) 60%,transparent);
  animation:meetPulse 2.6s ease-out infinite;}
@keyframes meetPulse{
  0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--signal) 55%,transparent);}
  70%{box-shadow:0 0 0 .42rem transparent;}
  100%{box-shadow:0 0 0 0 transparent;}
}
.foot-legal a{text-decoration:none;
  min-height:var(--tap);display:inline-flex;align-items:center;
  transition:color var(--dur-fast) ease;}
.foot-legal a:hover{color:var(--ink);}

.lang{position:relative;}

/* The switcher and the back-to-top button are the same object mirrored.
   Each starts flush with the paper — no border, no shadow, exactly the page
   colour — and only then resolves into the page blue, lifting into a curve
   that ends in a single shadow at the far edge. */
.lang-btn,.totop{
  display:inline-flex;align-items:center;gap:var(--s2);
  min-height:var(--tap);border:0;cursor:pointer;color:var(--ink);
  font-family:var(--font-mono);letter-spacing:.1em;
  text-transform:uppercase;
  transition:transform var(--dur) var(--spring),box-shadow var(--dur) ease,
             filter var(--dur) ease,opacity var(--dur) ease;
}
.lang-btn{
  /* the first stop is the page itself, so the left edge has nothing to see */
  background:linear-gradient(90deg,
      var(--lang-from,var(--paper)) 0%,
      var(--lang-from,var(--paper)) 14%,
      color-mix(in srgb,var(--lang-to,var(--cool)) 20%,var(--lang-from,var(--paper))) 48%,
      color-mix(in srgb,var(--lang-to,var(--cool)) 58%,var(--lang-from,var(--paper))) 78%,
      var(--lang-to,var(--cool)) 100%);
  padding:calc(var(--s1) * var(--lang-btn-scale,1)) calc(var(--s4) * var(--lang-btn-scale,1))
          calc(var(--s1) * var(--lang-btn-scale,1)) calc(var(--s2) * var(--lang-btn-scale,1));
  min-height:calc(var(--tap) * var(--lang-btn-scale,1));
  border-radius:0 999px 999px 0 / 0 58% 999px 0;
  /* offset far enough right that nothing falls under the flat left edge */
  box-shadow:var(--lang-btn-shadow,.9rem .3rem .8rem -.7rem rgba(var(--ink-rgb),.45));
  transform-origin:left center;
}
.lang-btn:hover,.lang-btn[aria-expanded="true"]{
  transform:translateY(-2px) rotate(-.5deg);
  box-shadow:1.1rem .45rem 1rem -.7rem rgba(var(--ink-rgb),.52);
  filter:saturate(1.12);
}
.lang-btn{font-size:var(--lang-text-size,var(--fs-mono));opacity:var(--lang-btn-opacity,1);}
.lang-btn .lang-lab{opacity:var(--lang-flag-opacity,1);}
.lang-btn:active{transform:none;}
.lang-flag{opacity:var(--lang-flag-opacity,1);box-shadow:var(--lang-flag-shadow,none);
  width:var(--lang-flag-w,1.25rem);height:var(--lang-flag-h,.84rem);
  border-radius:2px;flex:0 0 auto;
  box-shadow:0 0 0 1px var(--rule);
  transition:transform var(--dur) var(--spring);}
.lang-btn:hover .lang-flag{transform:translateX(2px) scale(1.06);}
.lang-caret{width:.42rem;height:.42rem;border-right:1.4px solid var(--ink);
  border-bottom:1.4px solid var(--ink);transform:rotate(45deg) translateY(-2px);
  transition:transform var(--dur) var(--ease);}
.lang-btn[aria-expanded="true"] .lang-caret{transform:rotate(225deg) translateY(-2px);}

/* ---------- back to top: the same gradient, mirrored ---------- */
.totop{
  position:fixed;right:0;bottom:var(--s8);z-index:80;
  background:linear-gradient(270deg,
      var(--paper) 0%,
      var(--paper) 14%,
      color-mix(in srgb,var(--top-to,var(--cool)) 20%,var(--paper)) 48%,
      color-mix(in srgb,var(--top-to,var(--cool)) 58%,var(--paper)) 78%,
      var(--top-to,var(--cool)) 100%);
  font-size:calc(var(--fs-mono) * var(--top-scale,1));
  min-height:calc(var(--tap) * var(--top-scale,1));
  padding:calc(var(--s1) * var(--top-scale,1)) calc(var(--s3) * var(--top-scale,1))
          calc(var(--s1) * var(--top-scale,1)) calc(var(--s5) * var(--top-scale,1));
  border-radius:999px 0 0 999px / 999px 0 0 58%;
  box-shadow:-.9rem .3rem .8rem -.7rem rgba(var(--ink-rgb),.45);
  transform-origin:right center;
  opacity:0;pointer-events:none;transform:translateX(1.5rem);
}
.totop.show{opacity:var(--top-opacity,1);pointer-events:auto;transform:none;}
.totop:hover{transform:translateY(-2px) rotate(.5deg);
  box-shadow:-1.1rem .45rem 1rem -.7rem rgba(var(--ink-rgb),.52);
  filter:saturate(1.12);}
.totop:active{transform:none;}
.totop i{width:.44rem;height:.44rem;border-left:1.4px solid var(--ink);
  border-top:1.4px solid var(--ink);transform:rotate(45deg) translateY(1px);
  transition:transform var(--dur) var(--ease);}
.totop:hover i{transform:rotate(45deg) translateY(-1px);}
/* stand clear of the consent card while it is open */
body.consent-open .totop{bottom:calc(var(--s8) + 11rem);}

/* Three shapes for the back-to-top control.
   tab   — a fold in the paper, mirroring the language switcher exactly
   pill  — a detached lozenge, floating clear of the edge
   notch — a chamfered instrument key, squared with one cut corner */
/* The opacity setting must scale the SHOWN state, not replace the hidden
   one. Writing `.totop{opacity:var(--top-opacity)}` after `.totop.show`
   overrode the hide entirely and pinned the button on screen — same
   specificity, later in the file, so it won. It belongs on .show. */
.totop--tab{border-radius:999px 0 0 999px / 999px 0 0 58%;
  box-shadow:var(--top-shadow,none);}
.totop--pill{right:var(--s5);border-radius:999px;
  padding:calc(var(--s1) * var(--top-scale,1)) calc(var(--s4) * var(--top-scale,1));
  box-shadow:0 .6rem 1.4rem -.7rem rgba(var(--ink-rgb),.45);}
.totop--pill:hover{box-shadow:0 .8rem 1.8rem -.7rem rgba(var(--ink-rgb),.55);}
.totop--notch{border-radius:0;
  clip-path:polygon(0.7rem 0, 100% 0, 100% 100%, 0 100%, 0 0.7rem);
  box-shadow:-.9rem .3rem .8rem -.7rem rgba(var(--ink-rgb),.45);}

.lang-menu{
  position:absolute;right:0;bottom:calc(100% + var(--s2));min-width:12rem;
  background:var(--paper-lift);border:1px solid var(--rule);border-radius:var(--radius);
  box-shadow:0 1rem 2rem -1rem rgba(var(--ink-rgb),.4);
  padding:var(--s2);list-style:none;z-index:70;
  opacity:0;transform:translateY(.4rem) scale(.98);pointer-events:none;
  transform-origin:bottom right;
  transition:opacity var(--dur-fast) ease,transform var(--dur) var(--spring);
}
.lang-menu.open{opacity:1;transform:none;pointer-events:auto;}
.lang-menu li + li{margin-top:2px;}
.lang-menu a{
  display:flex;align-items:center;gap:var(--s3);min-height:var(--tap);
  padding:0 var(--s3);border-radius:var(--radius);text-decoration:none;
  font-family:var(--font-mono);font-size:var(--fs-mono);letter-spacing:.1em;
  color:var(--ink-2);transition:background var(--dur-fast) ease,color var(--dur-fast) ease;
}
.lang-menu a:hover,.lang-menu a:focus-visible{background:rgba(134,180,255,.22);color:var(--ink);}
.lang-menu a[aria-current="true"]{color:var(--ink);font-weight:500;}
.lang-menu svg{width:1.5rem;height:1rem;border-radius:2px;flex:0 0 auto;
  box-shadow:0 0 0 1px var(--rule);}

/* ==================================================================
   CONSENT
   ================================================================== */
.grecaptcha-badge{visibility:hidden !important;}
.legal-note{width:100%;margin-top:var(--s4);padding-top:var(--s3);
  border-top:1px solid var(--rule-soft);
  font-size:var(--fs-mono);font-family:var(--font-mono);letter-spacing:.06em;
  color:var(--ink-3);text-transform:none;max-width:none;}
.legal-note a{color:var(--ink-2);}

.consent{
  position:fixed;left:var(--s4);right:var(--s4);bottom:var(--s4);z-index:90;
  max-width:34rem;margin-left:auto;
  background:var(--paper-lift);border:1px solid var(--rule);border-radius:var(--radius);
  padding:var(--s5);box-shadow:0 1.5rem 3rem -1.5rem rgba(var(--ink-rgb),.45);
  transform:translateY(1.5rem);opacity:0;pointer-events:none;
  transition:opacity var(--dur) ease,transform var(--dur) var(--ease);
}
.consent.show{opacity:1;transform:none;pointer-events:auto;}
.consent h2{font-size:var(--fs-h3);margin-bottom:var(--s3);}
.consent p{font-size:var(--fs-small);color:var(--ink-2);margin-bottom:var(--s4);}
.consent-actions{display:flex;gap:var(--s3);flex-wrap:wrap;}

/* ==================================================================
   REVEAL
   ================================================================== */
.reveal{opacity:0;transform:translateY(1.2rem);
  transition:opacity var(--dur-slow) ease,transform var(--dur-slow) var(--ease);}
.reveal.in{opacity:1;transform:none;}

/* ==================================================================
   RESPONSIVE — audited at 320 / 375 / 414 / 768 / 1024 / 1280 / 1440
   ================================================================== */
@media (max-width:64rem){
  .state-grid{grid-template-columns:1fr;gap:var(--s6);}
  .spine{display:none;}
}
@media (max-width:56rem){
  :root{--nav-h:4.75rem;}
  .nav{padding:0 var(--s4);}
  .nav-links{gap:var(--s4);}
  .nav-links a:not(.nav-cta){display:none;}
  .nav-cta{padding:0 var(--s4) !important;font-size:var(--fs-mono);
    letter-spacing:.06em;text-transform:uppercase;}
  /* Below this the mark, the wordmark and an uppercase call to action no
     longer fit on one line, and body{overflow-x:hidden} hides the fact by
     clipping the button rather than scrolling. The mark alone identifies the
     site here — FUSIONKI is set enormous immediately below it. */
  .nav-kw{display:none;}
  .brand{gap:0;}
  .hero{padding:calc(var(--nav-h) + var(--s5)) var(--s4) var(--s9);}
  .readout span:nth-child(n+3){display:none;}
  .hero-band{height:calc(clamp(7rem,18vh,10rem) * var(--band-scale,1));}

  .state,.section{padding:var(--s8) var(--s4);}
  .state{min-height:auto;}
  .hero-lede{gap:var(--s5);}
  .cap{border-right:0;}
  .foot{padding:var(--s5) var(--s4);}
  .foot-inner{gap:var(--s3);}
}
@media (max-width:24rem){
  .hero-top span:last-child{display:none;}
  .lang-btn{padding-right:var(--s4);}
}

/* ==================================================================
   REDUCED MOTION — respected everywhere, including JS loops, which
   read the same query before they start.
   ================================================================== */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;}
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important;}
  .reveal{opacity:1;transform:none;}
  #trace{display:none;}
}

/* ==================================================================
   PRINT
   ================================================================== */
@media print{
  #trace,.spine,.consent,.nav,.stage{display:none !important;}
  body{background:#fff;color:#000;}
}
