/* ============================================================
   fourfront events — type
   Self-hosted, latin subset only (the site is lang="en").
   Space Grotesk is a variable font: one file covers 300-700, so it is
   declared once with a weight range rather than shipped twice.
   Both faces are SIL Open Font License 1.1.
   ============================================================ */
@font-face{
  font-family:"Space Grotesk"; font-style:normal; font-weight:300 700; font-display:swap;
  src:url("assets/fonts/space-grotesk.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:"Martian Mono"; font-style:normal; font-weight:400; font-display:swap;
  src:url("assets/fonts/martian-mono.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================
   fourfront events — design tokens
   carbon + signal sampled from the logo. linen base.
   no border-radius anywhere: the square is the brand.
   ============================================================ */
:root{
  --carbon:  #1E1E1E;
  --signal:  #D64238;
  --signal-2:#A8322A;   /* pressed only, never a second accent */
  --signal-ink:#BE3129;  /* The red that can carry SMALL TEXT ON A LIGHT SURFACE, either as
                            the ground under light type or as the type itself. --signal is
                            #D64238 straight off the logo and manages only 3.93:1 either way,
                            which fails AA at 10px. This is the same hue darkened just enough
                            to clear it (5.04 on --lift, 4.35 on --linen). It is NOT a second
                            accent: marks, rules, bullets, the cursor and all large display
                            type stay --signal. It does not work on carbon (2.91) — see the
                            open item about the three labels that still fail. */
  --linen:   #E4E0D7;   /* base   */
  --panel:   #D5D0C4;   /* recessed */
  --lift:    #F3F0E9;   /* lifted surfaces + light ink on carbon */
  --slate:   #4A4741;
  --mute:    #5A5752;   /* 5.46 linen / 4.67 panel / 6.32 lift — all clear AA */

  /* the same colours as triplets, so anything can take alpha from a token */
  --carbon-rgb: 30,30,30;
  --signal-rgb: 214,66,56;
  --linen-rgb:  228,224,215;
  --lift-rgb:   243,240,233;

  --grot:"Space Grotesk",system-ui,-apple-system,sans-serif;
  --mono:"Martian Mono",ui-monospace,monospace;

  --ease:cubic-bezier(.22,.61,.36,1);
  --slow:cubic-bezier(.16,1,.3,1);
  /* type scale — derived from the sizes the design already used, not from an
     abstract ratio. Steps that had near-duplicates are collapsed (2.8/2.9/3.0
     became one; 2.2/2.4/2.4 became one; five small sizes became one); steps
     that were already unique keep their exact original value. */
  --t--1:.92rem;                       /* small copy      was .88 .9 .92 .94 .95 */
  --t-0: clamp(1rem,1.3vw,1.1rem);     /* body, lede      unchanged */
  --t-1: 1.5rem;                       /* card titles     unchanged */
  --t-2: clamp(1.4rem,3.15vw,2.35rem); /* component h3    was 2.2 / 2.4 / 2.4 */
  --t-3: clamp(1.6rem,3.8vw,2.9rem);   /* panel display   was 2.8 / 2.9 / 3.0 */
  --t-4: clamp(1.9rem,5.5vw,4.25rem);  /* section display was 4.1 / 4.4 */
  --t-5: clamp(2rem,6.6vw,5.2rem);     /* outlined words  unchanged */
  --t-6: clamp(2.7rem,8.2vw,6.6rem);   /* hero            unchanged */

  /* vertical rhythm (vh) and horizontal gaps (vw) are separate scales —
     one scale cannot serve both without distorting one of them. */
  --vr-1:clamp(8px,1.4vh,16px);
  --vr-2:clamp(13px,2.2vh,22px);
  --vr-3:clamp(34px,6vh,66px);
  --vr-4:clamp(48px,7.5vh,86px);
  --vr-5:clamp(84px,12vh,150px);
  --sp-1:clamp(6px,1.4vw,20px);
  --sp-2:clamp(12px,3vw,38px);
  --sp-3:clamp(22px,3.4vw,38px);
  --sp-4:clamp(24px,5vw,64px);

  /* optical tracking: tighter as type gets bigger */
  --track-xl:-.055em;   /* 4rem and up   */
  --track-lg:-.05em;    /* 2.4 – 4rem    */
  --track-md:-.038em;   /* 1.6 – 2.4rem  */
  --track-sm:-.028em;   /* 1.1 – 1.6rem  */
  --pad:clamp(20px,5vw,72px);
  --safe-b:0px;
  --nav-h:76px;
}
@supports (padding:max(0px,env(safe-area-inset-left))){
  :root{
    --pad:calc(clamp(20px,5vw,72px) + max(env(safe-area-inset-left),env(safe-area-inset-right)));
    --safe-b:env(safe-area-inset-bottom);
  }
}

*,*::before,*::after{ box-sizing:border-box; border-radius:0; }
html{ scroll-behavior:smooth; -webkit-text-size-adjust:100%; }
a,button,input,textarea,label,.chip,.cat,.card{ -webkit-tap-highlight-color:transparent; }
a,button,.chip{ touch-action:manipulation; }
body{
  margin:0; background:var(--linen); color:var(--carbon);
  font-family:var(--grot); font-weight:300; font-size:16px; line-height:1.6;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
body.is-locked{ overflow:hidden; }
a{ color:inherit; text-decoration:none; }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; }
:focus-visible{ outline:2px solid var(--signal); outline-offset:3px; }
::selection{ background:var(--signal); color:var(--lift); }
img{ max-width:100%; display:block; }

/* Grain, in two parts. The fixed layer below covers the whole page at paper strength.
   Carbon sections then add their own on top, screened rather than multiplied, because
   on a dark ground grain reads as haze in a beam rather than as tooth in paper. */
[data-surface="carbon"]::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.5;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.3'/%3E%3C/svg%3E");
  mix-blend-mode:screen;
}
[data-surface="carbon"]>*{ position:relative; z-index:1; }

/* grain: above all page content (max z-index 2), below all chrome (hud 700 / nav 800 / menu 790) */
body::after{
  content:""; position:fixed; inset:0; z-index:600; pointer-events:none; opacity:.38;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.22'/%3E%3C/svg%3E");
  mix-blend-mode:multiply;
}

/* ---------- surfaces ---------- */
[data-surface]{
  --surface:var(--linen); --on:var(--carbon);
  --rule:rgba(var(--carbon-rgb),.14); --rule-2:rgba(var(--carbon-rgb),.24);
  --dim:var(--slate); --lbl:var(--mute);
  position:relative; background:var(--surface); color:var(--on);
}
[data-surface="lift"]{ --surface:var(--lift); }
[data-surface="panel"]{ --surface:var(--panel); }
[data-surface="carbon"]{
  --surface:var(--carbon); --on:var(--lift);
  --rule:rgba(var(--lift-rgb),.16); --rule-2:rgba(var(--lift-rgb),.3);
  --dim:rgba(var(--lift-rgb),.62); --lbl:rgba(var(--lift-rgb),.44);
}
/* .s adds the standard section rhythm; .journey sets its own geometry */
.s{ padding:var(--vr-5) var(--pad); }

/* ---------- type ---------- */
h1,h2,h3,h4{ margin:0; font-weight:700; letter-spacing:var(--track-md); line-height:.96;
  text-transform:lowercase; text-wrap:balance; }
.h-xl{ font-size:var(--t-6); letter-spacing:var(--track-xl); }
.h-lg{ font-size:var(--t-4); letter-spacing:var(--track-lg); }
.h-md{ font-size:var(--t-3); letter-spacing:var(--track-md); }
p{ margin:0; text-wrap:pretty; }
.lede{ color:var(--dim); font-size:var(--t-0); max-width:46ch; line-height:1.62; }
.cueline{
  font-family:var(--mono); font-size:10px; font-weight:400; letter-spacing:.14em;
  text-transform:uppercase; color:var(--lbl); display:flex; align-items:center; gap:10px;
}
.sq{ width:9px; height:9px; background:var(--signal); flex:none; display:block; }
.label{ font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--lbl); }
.head{ display:flex; align-items:flex-end; justify-content:space-between; gap:24px; flex-wrap:wrap; margin-bottom:var(--vr-3); }
.head .stack{ display:flex; flex-direction:column; gap:16px; }

/* ---------- square cursor ---------- */
#cursor{ display:none; position:fixed; top:0; left:0; width:10px; height:10px; margin:-5px 0 0 -5px;
  background:var(--signal); z-index:950; pointer-events:none;
  transition:width .28s var(--ease), height .28s var(--ease), margin .28s var(--ease), background .28s, box-shadow .28s; }
#cursor.big{ width:30px; height:30px; margin:-15px 0 0 -15px; background:rgba(var(--signal-rgb),.28); box-shadow:inset 0 0 0 1px var(--signal); }
html.sqcursor{ cursor:none; }
html.sqcursor a, html.sqcursor button, html.sqcursor .cat, html.sqcursor .tbtn{ cursor:none; }
html.sqcursor input, html.sqcursor textarea{ cursor:text; }
@media (hover:hover) and (pointer:fine){ html.sqcursor #cursor{ display:block; } }

/* ---------- curtain ---------- */
#curtain{ position:fixed; inset:0; z-index:1000; background:var(--carbon); display:grid; place-items:center;
  transition:opacity .7s var(--ease), visibility .7s; }
#curtain.gone{ opacity:0; visibility:hidden; }
/* The mark itself — the red square from the wordmark. This used to be the 2x2 quad,
   which is a progress device elsewhere in the UI, not the logo; as the very first
   thing anyone sees it read as a brand mark, and the wrong one. */
#curtain .q{ display:block; width:22px; height:22px; background:var(--signal);
  animation:hold 1.6s var(--ease) infinite; }
@keyframes hold{ 0%,100%{ transform:scale(1); opacity:1 } 50%{ transform:scale(.72); opacity:.55 } }

/* ---------- nav ---------- */
.nav{ position:fixed; top:0; left:0; right:0; z-index:800; height:var(--nav-h);
  display:flex; align-items:center; justify-content:space-between; padding:0 var(--pad);
  transition:background .45s var(--ease), border-color .45s; border-bottom:1px solid transparent; }
.nav.solid{ background:rgba(var(--linen-rgb),.93); backdrop-filter:blur(14px); border-bottom-color:rgba(var(--carbon-rgb),.14); }
.nav .logo{ height:34px; width:auto; }
.nav-links{ display:flex; align-items:center; gap:32px; }
.nav-links a{ font-size:13.5px; color:var(--slate); position:relative; transition:color .3s; }
.nav-links a::after{ content:""; position:absolute; left:0; bottom:-7px; width:0; height:2px; background:var(--signal); transition:width .4s var(--ease); }
.nav-links a:hover{ color:var(--carbon); } .nav-links a:hover::after{ width:100%; }

.btn{ display:inline-flex; align-items:center; gap:10px; padding:15px 24px;
  font-family:var(--mono); font-size:10px; font-weight:400; letter-spacing:.14em; text-transform:uppercase;
  background:var(--signal-ink); color:var(--lift); border:1px solid var(--signal-ink);
  position:relative; overflow:hidden; transition:color .4s var(--ease); }
.btn::before{ content:""; position:absolute; inset:0; background:var(--carbon); transform:translateY(101%); transition:transform .45s var(--slow); }
.btn:hover::before{ transform:translateY(0); }
.btn span{ position:relative; }
.btn.ghost{ background:transparent; border-color:var(--rule-2); color:var(--dim); }
.btn.ghost::before{ background:var(--carbon); }
.btn.ghost:hover{ color:var(--lift); border-color:var(--carbon); }
[data-surface="carbon"] .btn.ghost::before{ background:var(--lift); }
[data-surface="carbon"] .btn.ghost:hover{ color:var(--carbon); border-color:var(--lift); }
.btn.lg{ padding:19px 30px; font-size:11px; }
/* pressed — slides the panel in for keyboard activation too, and is the only place --signal-2 appears */
.btn:not(.ghost):active::before{ background:var(--signal-2); transform:translateY(0); }

.burger{ display:none; width:34px; height:26px; position:relative; }
.burger i{ position:absolute; left:0; right:0; height:2px; background:var(--carbon); transition:transform .4s var(--ease); }
.burger i:nth-child(1){ top:7px; } .burger i:nth-child(2){ top:16px; }
.burger.x i:nth-child(1){ transform:translateY(4.5px) rotate(45deg); }
.burger.x i:nth-child(2){ transform:translateY(-4.5px) rotate(-45deg); }

.mobile-menu{ position:fixed; inset:0; z-index:790; background:var(--lift);
  padding:calc(var(--nav-h) + 26px) var(--pad) 34px; display:flex; flex-direction:column; justify-content:space-between;
  clip-path:inset(0 0 100% 0); transition:clip-path .75s var(--slow); visibility:hidden; }
.mobile-menu.open{ clip-path:inset(0 0 0 0); visibility:visible; }
.mobile-menu nav{ display:flex; flex-direction:column; gap:4px; }
.mobile-menu nav a{ font-size:clamp(2.2rem,10vw,3.4rem); font-weight:700; letter-spacing:var(--track-lg); display:flex; align-items:center; gap:14px; }
.mobile-menu nav a .sq{ width:8px; height:8px; }
.mobile-menu .foot{ display:flex; flex-direction:column; gap:16px; }

/* ---------- hud ---------- */
.hud{ position:fixed; left:var(--pad); bottom:22px; z-index:700; display:flex; align-items:center; gap:12px;
  font-family:var(--mono); font-size:9.5px; letter-spacing:.14em; text-transform:uppercase; color:var(--mute);
  pointer-events:none; opacity:0; transition:opacity .8s var(--ease); }
.hud.on{ opacity:1; }
/* the readout retires once the footer is in view — it is fixed to the bottom-left
   and would otherwise sit on top of the footer's closing line */
.hud.off{ opacity:0; }
.hud .quad{ display:grid; grid-template-columns:repeat(2,7px); grid-template-rows:repeat(2,7px); gap:2px; }
.hud .quad i{ background:rgba(var(--carbon-rgb),.28); display:block; transition:background .5s; }
.hud .quad i.on{ background:var(--signal); }
.hud .tc{ color:var(--carbon); }
.hud .sep{ color:rgba(var(--carbon-rgb),.28); }

/* ---------- hero ---------- */
.s.hero{
  min-height:100svh; display:flex; align-items:flex-end;
  padding-bottom:var(--vr-4); overflow:hidden;
}
/* the key light: one hard pool top-left, a red gel top-right */
.hero .light{ position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(40% 44% at 26% 6%, rgba(255,253,248,.98) 0%, rgba(255,253,248,.6) 44%, transparent 72%),
             radial-gradient(34% 38% at 86% 2%, rgba(var(--signal-rgb),.34), transparent 66%); }
/* falloff — this is what lets light read on a light ground */
.hero .vig{ position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(72% 76% at 34% 26%, transparent 42%, rgba(var(--carbon-rgb),.13) 78%, rgba(var(--carbon-rgb),.27) 100%); }
.beam{ position:absolute; top:-14%; height:112vh; transform-origin:50% 0; mix-blend-mode:multiply;
  clip-path:polygon(46% 0,54% 0,100% 100%,0 100%); filter:blur(22px); pointer-events:none; }
.beam.a{ left:-4%; width:38vw; background:linear-gradient(180deg, rgba(var(--carbon-rgb),.22), rgba(var(--carbon-rgb),.04) 58%, transparent 82%); animation:sway 19s ease-in-out infinite; }
.beam.b{ right:4%; width:34vw; background:linear-gradient(180deg, rgba(var(--signal-rgb),.3), rgba(var(--signal-rgb),.05) 56%, transparent 80%); animation:sway 25s ease-in-out infinite reverse; }
@keyframes sway{ 0%,100%{transform:rotate(-6deg)} 50%{transform:rotate(6deg)} }
.seatplan{ position:absolute; left:0; right:0; bottom:0; height:34vh; opacity:.26; pointer-events:none;
  background-image:radial-gradient(circle, rgba(var(--carbon-rgb),.75) .9px, transparent 1.1px); background-size:15px 12px;
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 60%,#000); mask-image:linear-gradient(180deg,transparent,#000 60%,#000); }
.hero-inner{ position:relative; z-index:2; width:100%; }
.hero h1{ max-width:15ch; margin-top:24px; }
.hero .row{ display:flex; align-items:flex-end; justify-content:space-between; gap:36px; flex-wrap:wrap; margin-top:34px; }
.hero .actions{ display:flex; gap:10px; flex-wrap:wrap; }
.word{ display:inline-block; overflow:hidden; vertical-align:bottom; }
.word>span{ display:inline-block; transform:translateY(105%); transition:transform 1s var(--slow); }
.ready .word>span{ transform:translateY(0); }

/* ---------- what we create ---------- */
.create{ overflow:hidden; }
.wash{ position:absolute; inset:0; opacity:0; transition:opacity .9s var(--ease); mix-blend-mode:multiply; pointer-events:none; }
.wash.on{ opacity:1; }
.wash.w1{ background:radial-gradient(48% 58% at 78% 16%, rgba(var(--signal-rgb),.34), transparent 66%); }
.wash.w2{ background:radial-gradient(46% 56% at 20% 24%, rgba(var(--carbon-rgb),.22), transparent 68%); }
.wash.w3{ background:radial-gradient(58% 64% at 52% 6%, rgba(var(--signal-rgb),.26), transparent 70%); }
.wash.w4{ background:radial-gradient(52% 52% at 88% 52%, rgba(var(--carbon-rgb),.24), transparent 66%); }
.wash.w5{ background:radial-gradient(60% 52% at 28% 90%, rgba(var(--signal-rgb),.3), transparent 68%); }
.wash.w6{ background:radial-gradient(50% 58% at 64% 24%, rgba(var(--signal-rgb),.36), transparent 62%); }
.wash.w7{ background:radial-gradient(70% 56% at 50% 50%, rgba(var(--carbon-rgb),.2), transparent 66%); }
.create-inner{ position:relative; z-index:2; }
.cat{ border-top:1px solid var(--rule); }
.cat:last-child{ border-bottom:1px solid var(--rule); }
.cat button{ width:100%; text-align:left; display:flex; align-items:baseline; gap:var(--sp-2);
  padding:var(--vr-2) 0; transition:opacity .45s var(--ease), padding-left .55s var(--slow); }
.cat .idx{ font-family:var(--mono); font-size:10px; letter-spacing:.1em; color:var(--lbl); width:30px; flex:none; }
/* outline by default; red floods it left to right, like a followspot finding it */
.cat .nm{ position:relative; display:inline-block; flex:none; white-space:nowrap;
  font-size:var(--t-4); font-weight:700; letter-spacing:var(--track-lg); line-height:1; }
.cat .base{ color:transparent; -webkit-text-stroke:1.3px rgba(var(--carbon-rgb),.55); transition:-webkit-text-stroke-color .55s var(--ease); }
.cat .fill{ position:absolute; left:0; top:0; color:var(--signal); white-space:nowrap;
  clip-path:inset(0 100% 0 0); transition:clip-path .78s var(--slow); }
.cat.active .fill{ clip-path:inset(0 0 0 0); }
.cat.active .base{ -webkit-text-stroke-color:rgba(var(--carbon-rgb),.16); }
.cat .desc{ margin-left:auto; text-align:right; max-width:32ch; font-size:var(--t--1); color:var(--dim); }
.cat .desc w{ display:inline-block; opacity:0; transform:translateY(9px);
  transition:opacity .5s var(--ease), transform .55s var(--slow); }
.cat.active .desc w{ opacity:1; transform:none; }
.create.hot .cat:not(.active) button{ opacity:.4; }
.cat.active button{ padding-left:var(--sp-1); }

/* ---------- four fronts ---------- */
.tabsplit{ display:grid; grid-template-columns:.9fr 1.1fr; gap:var(--sp-4); }
.tlist{ position:relative; border-left:1px solid var(--rule); }
.tlist .glide{ position:absolute; left:-2px; top:0; width:3px; background:var(--signal);
  transition:transform .62s var(--slow), height .62s var(--slow); }
.tbtn{ display:flex; align-items:center; gap:16px; width:100%; text-align:left;
  padding:var(--vr-2) 22px; transition:padding-left .5s var(--slow), opacity .4s var(--ease); }
.tbtn .n{ font-family:var(--mono); font-size:10px; letter-spacing:.14em; color:var(--lbl); transition:color .4s; }
.tbtn h3{ font-size:var(--t-2); letter-spacing:var(--track-md); transition:color .4s; }
.tbtn:not(.on){ opacity:.42; }
.tbtn.on{ padding-left:30px; }
.tbtn.on .n{ color:var(--on); }          /* the glide rule + quad carry the red here */
.tpanel{ position:relative; border:1px solid var(--rule); background:var(--lift); padding:var(--sp-3); min-height:320px; }
.tpanel .quad{ display:grid; grid-template-columns:repeat(2,14px); grid-template-rows:repeat(2,14px); gap:3px; margin-bottom:20px; }
.tpanel .quad i{ background:rgba(var(--carbon-rgb),.16); transition:background .5s var(--ease); }
.tpanel .quad i.on{ background:var(--signal); }
.tpanel h3{ font-size:var(--t-2); letter-spacing:var(--track-md); margin-bottom:4px; }
.tpanel .maskline{ overflow:hidden; }
.tpanel .maskline>span{ display:block; transform:translateY(105%); transition:transform .82s var(--slow); }
.tpanel.in .maskline>span{ transform:none; }
.tpanel ul{ list-style:none; margin:26px 0 0; padding:0; border-top:1px solid var(--rule); }
.tpanel li{ display:flex; align-items:center; gap:12px; padding:11px 0; border-bottom:1px solid var(--rule);
  font-size:var(--t--1); color:var(--dim); opacity:0; transform:translateY(10px);
  transition:opacity .5s var(--ease), transform .6s var(--slow); }
.tpanel li::before{ content:""; width:6px; height:6px; background:var(--signal); flex:none; }
.tpanel.in li{ opacity:1; transform:none; }

/* ---------- scale strip ---------- */
.strip{ display:flex; gap:12px; overflow-x:auto; scroll-snap-type:x proximity; scrollbar-width:none; cursor:grab; padding-bottom:12px; }
.strip::-webkit-scrollbar{ display:none; }
.strip.grabbing{ cursor:grabbing; scroll-snap-type:none; user-select:none; }
.card{ position:relative; flex:0 0 clamp(230px,29vw,360px); aspect-ratio:3/4; scroll-snap-align:start; overflow:hidden;
  border:1px solid var(--rule); display:flex; align-items:flex-end; padding:20px; }
/* Registered so the beam's position interpolates: an unregistered custom property
   jumps, which would snap the plan's mask back while the bloom eased away.       */
@property --mx{ syntax:"<number>"; inherits:true; initial-value:50; }
@property --my{ syntax:"<number>"; inherits:true; initial-value:40; }

/* ---- cue 04: the plan under the light ----
   Three layers per card. The ground gradient is fixed; the bloom is the beam and
   moves; the plan is a venue drawing (main.js) masked by that same beam, so you
   only ever see the part of the plot the light is currently on. The bloom sits on
   an oversized layer and moves by transform (compositor); only the plan's mask
   repaints. Resting positions are remapped from the original gradients, so the
   strip at rest looks exactly as it did before.                                  */
.card .field{ position:absolute; inset:0; }
.card .plan{ position:absolute; inset:0; pointer-events:none; opacity:.5;
  -webkit-mask-image:radial-gradient(46% 34% at calc(var(--mx,50) * 1%) calc(var(--my,40) * 1%), #000 0%, rgba(0,0,0,.5) 46%, transparent 72%);
          mask-image:radial-gradient(46% 34% at calc(var(--mx,50) * 1%) calc(var(--my,40) * 1%), #000 0%, rgba(0,0,0,.5) 46%, transparent 72%);
  transition:opacity .45s var(--ease); }
.card .plan svg{ display:block; width:100%; height:100%; }
/* Without mask support the plan would sit at full strength over the light field,
   which is the one outcome that looks broken. Hide it and keep the light. */
@supports not (mask-image:radial-gradient(#000,#000)){
  @supports not (-webkit-mask-image:radial-gradient(#000,#000)){
    .card .plan{ display:none; }
  }
}
.card .haze{ position:absolute; inset:-20%; pointer-events:none;
  background:radial-gradient(60% 44% at 50% 60%, rgba(var(--lift-rgb),.42), transparent 72%); }
.card .bloom{ position:absolute; inset:-26%; pointer-events:none; }
.card .bloom,.card .haze{ transition:transform .55s var(--slow); will-change:transform; }
.card{ transition:--mx .55s var(--slow), --my .55s var(--slow); }
.card.lit .bloom{ transition:transform .16s linear; }
.card.lit{ transition:--mx .16s linear, --my .16s linear; }
.card.lit .plan{ opacity:.72; }

/* the drawing itself — all plate colour lives here, never in the generated markup */
.plate .ink{ fill:none; stroke:rgba(var(--carbon-rgb),.85); stroke-width:1; }
.plate .faint{ fill:none; stroke:rgba(var(--carbon-rgb),.5); stroke-width:.8; }
.plate .dash{ fill:none; stroke:rgba(var(--carbon-rgb),.45); stroke-width:.8; stroke-dasharray:5 5; }
.plate .fill-faint{ fill:rgba(var(--carbon-rgb),.45); stroke:none; }
.plate .mark{ fill:var(--signal); stroke:none; }
.plate .mark-s{ fill:none; stroke:var(--signal); stroke-width:1.4; }
.plate .mark-fill{ fill:rgba(var(--signal-rgb),.2); stroke:var(--signal); stroke-width:1.2; }
.plate .beam{ fill:none; }

.card.c1 .field{ background:linear-gradient(180deg,#F1EDE4,#CFC9BC); }
.card.c1 .bloom{ background:radial-gradient(38.16% 27.63% at 50.0% 22.37%, rgba(var(--signal-rgb),.4), transparent 70%); }
.card.c1{ --lx:50; --ly:8; }
.card.c2 .field{ background:linear-gradient(180deg,#EBE7DE,#C6C1B4); }
.card.c2 .bloom{ background:radial-gradient(35.53% 26.32% at 31.58% 27.63%, rgba(var(--carbon-rgb),.3), transparent 70%); }
.card.c2{ --lx:22; --ly:16; }
.card.c3 .field{ background:linear-gradient(180deg,#F3EFE5,#D0C9B9); }
.card.c3 .bloom{ background:radial-gradient(46.05% 31.58% at 50.0% 80.26%, rgba(var(--signal-rgb),.36), transparent 70%); }
.card.c3{ --lx:50; --ly:96; }
.card.c4 .field{ background:linear-gradient(180deg,#EEEBE3,#C9C5B9); }
.card.c4 .bloom{ background:radial-gradient(30.26% 26.32% at 69.74% 31.58%, rgba(var(--carbon-rgb),.26), transparent 70%); }
.card.c4{ --lx:80; --ly:22; }
.card.c5 .field{ background:linear-gradient(180deg,#F0ECE3,#CBC6B8); }
.card.c5 .bloom{ background:radial-gradient(38.16% 28.95% at 25.0% 72.37%, rgba(var(--signal-rgb),.3), transparent 70%); }
.card.c5{ --lx:12; --ly:84; }
.card.c6 .field{ background:linear-gradient(180deg,#F4F0E6,#D2CBBB); }
.card.c6 .bloom{ background:radial-gradient(34.21% 26.32% at 59.21% 22.37%, rgba(var(--signal-rgb),.42), transparent 70%); }
.card.c6{ --lx:64; --ly:8; }

.card .lines{ position:absolute; inset:0; background-image:repeating-linear-gradient(90deg, rgba(var(--carbon-rgb),.07) 0 1px, transparent 1px 44px); }
.card .meta{ position:relative; }
.card h4{ font-size:var(--t-1); letter-spacing:var(--track-sm); margin-top:6px; }

/* ---------- worlds ---------- */
.worlds{ overflow:hidden; }
/* background-image is not an interpolable property, so the atmospheres are stacked
   and crossfaded on opacity rather than transitioned on background */
.world-bg{ position:absolute; inset:0; }
.world-bg i{ position:absolute; inset:0; opacity:0; transition:opacity 1s var(--ease); }
.world-bg i.on{ opacity:1; }
.worlds-inner{ position:relative; z-index:2; }
.tabs{ display:flex; gap:6px; flex-wrap:wrap; margin:28px 0 42px; }
.tab{ font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase; padding:13px 20px;
  border:1px solid var(--rule); color:var(--lbl); transition:.35s; }
.tab:hover{ color:var(--on); border-color:var(--on); }
.tab.on{ background:var(--signal-ink); border-color:var(--signal-ink); color:var(--lift); }
.tab.on:active{ background:var(--signal-2); border-color:var(--signal-2); }
.world-panel{ display:none; }
.world-panel.on{ display:block; animation:panelIn .8s var(--slow); }
@keyframes panelIn{ from{opacity:0; transform:translateY(20px)} to{opacity:1; transform:none} }
.world-grid{ display:grid; grid-template-columns:1.2fr .8fr; gap:var(--sp-4); align-items:end; }
.world-line{ font-size:var(--t-3); font-weight:700; letter-spacing:var(--track-lg); line-height:1.02; max-width:20ch; }
.specs{ border-top:1px solid var(--rule); }
.specs div{ display:flex; justify-content:space-between; gap:18px; padding:13px 0; border-bottom:1px solid var(--rule); }
.specs dt{ margin:0; font-family:var(--mono); font-size:10px; letter-spacing:.12em; text-transform:uppercase; color:var(--lbl); }
.specs dd{ margin:0; font-size:var(--t--1); text-align:right; }
.faders{ display:flex; align-items:stretch; gap:5px; height:56px; margin-top:32px; max-width:300px; }
.faders .ch{ flex:1; position:relative; background:rgba(var(--lift-rgb),.12); }
.faders .ch i{ position:absolute; left:-1px; right:-1px; height:4px; background:var(--lift);
  transition:bottom .9s var(--slow), background .5s var(--ease); }
.faders .ch.live i{ background:var(--signal); }

/* ---------- values ---------- */
.value{ display:flex; align-items:center; gap:18px; padding:var(--vr-1) 0; border-bottom:1px solid var(--rule); overflow:hidden; }
.value .w{ font-size:var(--t-5); font-weight:700; letter-spacing:var(--track-xl); line-height:1;
  color:transparent; -webkit-text-stroke:1.4px rgba(var(--carbon-rgb),.5); display:inline-block; transform:translateY(105%);
  transition:transform .95s var(--slow), color .6s var(--ease), -webkit-text-stroke-color .6s var(--ease); }
.value.in .w{ transform:none; }
.value:hover .w{ color:var(--signal); -webkit-text-stroke-color:transparent; }
/* Gecko renders -webkit-text-stroke about a fifth thinner than Blink/WebKit at the
   same value, so the outlined type reads light there. @supports -moz-appearance is
   Firefox-only and is the least bad way to target it. */
@supports (-moz-appearance:none){
  .cat .base{ -webkit-text-stroke-width:1.55px; }
  .value .w{ -webkit-text-stroke-width:1.7px; }
}

/* ---------- run of show ---------- */
.journey{ height:340vh; }
.jsticky{ position:sticky; top:0; height:100svh; overflow:hidden; display:flex; flex-direction:column; justify-content:center; }
.jhead{ padding:0 var(--pad); margin-bottom:40px; }
.jtrack{ display:flex; padding:0 var(--pad); will-change:transform; }
.stop{ flex:0 0 clamp(228px,25vw,330px); border-left:1px solid var(--rule); padding:0 24px; }
.stop:last-child{ border-right:1px solid var(--rule); }
.stop .tc{ font-family:var(--mono); font-size:10px; letter-spacing:.12em; color:var(--on); }  /* the dot carries the red */
.stop h3{ font-size:var(--t-2); letter-spacing:var(--track-md); margin:12px 0 10px; }
.stop p{ font-size:var(--t--1); color:var(--dim); max-width:23ch; }
.stop .dot{ width:10px; height:10px; border:1.5px solid var(--signal); margin-top:28px; transition:background .4s; }
.jbar{ margin:40px var(--pad) 0; height:2px; background:var(--rule); position:relative; }
.jbar i{ position:absolute; left:0; top:-4px; width:10px; height:10px; background:var(--signal); }
.journey.static{ height:auto; }
.journey.static .jsticky{ position:relative; height:auto; padding:var(--vr-5) 0; }
.journey.static .jtrack{ overflow-x:auto; scroll-snap-type:x mandatory; transform:none !important; scrollbar-width:none; }
.journey.static .jtrack::-webkit-scrollbar{ display:none; }
.journey.static .stop{ scroll-snap-align:start; }

/* ---------- brief ---------- */
.brief{ overflow:hidden; }
.brief .glowfield{ position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(46% 56% at 88% 4%, rgba(var(--signal-rgb),.16), transparent 68%); }
.brief-inner{ position:relative; z-index:2; max-width:980px; }
.jump{ display:block; height:0; scroll-margin-top:calc(var(--nav-h) + 20px); }
/* off-screen rather than display:none — some bots skip hidden fields */
.hp{ position:absolute; left:-9999px; top:auto; width:1px; height:1px; overflow:hidden; }

/* which flow you're in — plan a conversation, or price something */
.flowpick{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:26px; }
.fbtn{ font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  padding:13px 20px; border:1px solid rgba(var(--carbon-rgb),.22); color:var(--mute);
  background:rgba(255,253,248,.5); transition:.3s var(--ease); }
.fbtn:hover{ color:var(--carbon); border-color:var(--carbon); }
.fbtn.on{ background:var(--signal-ink); border-color:var(--signal-ink); color:var(--lift); }
.fbtn.on:active{ background:var(--signal-2); border-color:var(--signal-2); }

.bbar{ display:flex; align-items:center; gap:14px; margin-bottom:32px; }
.bbar .track{ flex:1; height:2px; background:rgba(var(--carbon-rgb),.16); position:relative; }
.bbar .track i{ position:absolute; inset:0 auto 0 0; width:0; background:var(--signal); transition:width .65s var(--slow); }
.step{ display:none; } .step.on{ display:block; animation:panelIn .6s var(--slow); }
.step h3{ font-size:var(--t-3); letter-spacing:var(--track-lg); margin:10px 0 28px; }
.chips{ display:flex; flex-wrap:wrap; gap:8px; }
.chip{ padding:14px 22px; border:1px solid rgba(var(--carbon-rgb),.22); font-size:.92rem; color:var(--slate);
  background:rgba(255,253,248,.55); transition:.3s var(--ease); }
.chip:hover{ color:var(--carbon); border-color:var(--carbon); transform:translateY(-2px); }
.chip.on{ background:var(--signal-ink); border-color:var(--signal-ink); color:var(--lift); }
.chip:active{ transform:translateY(0); }
.chip.on:active{ background:var(--signal-2); border-color:var(--signal-2); }
.field-in{ display:flex; flex-direction:column; gap:8px; margin-bottom:16px; }
.fieldset{ display:flex; flex-direction:column; }
.field-in label{ font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--mute); }
.field-in label i{ font-style:normal; color:var(--signal-ink); }
.step .help{ margin-top:14px; }

/* one message, under the question it belongs to */
.field-err{ min-height:0; margin-top:16px; font-family:var(--mono); font-size:10px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--signal-ink); opacity:0; transform:translateY(-4px);
  transition:opacity .3s var(--ease), transform .3s var(--slow); }
.field-err.on{ opacity:1; transform:none; }
#saved{ margin-left:auto; }
input,textarea{ width:100%; background:transparent; border:0; border-bottom:1.5px solid rgba(var(--carbon-rgb),.22);
  color:var(--carbon); font-family:var(--grot); font-size:1.05rem; font-weight:300; padding:10px 0; transition:border-color .35s; }
input::placeholder,textarea::placeholder{ color:var(--mute); }
input:focus,textarea:focus{ outline:none; border-bottom-color:var(--signal); }
textarea{ resize:vertical; min-height:92px; }
.grid2{ display:grid; grid-template-columns:1fr 1fr; gap:20px 32px; }
.stepnav{ display:flex; align-items:center; gap:16px; margin-top:34px; flex-wrap:wrap; }
.back{ font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--mute); transition:color .3s; }
.back:hover{ color:var(--carbon); }
.review{ display:none; } .review.on{ display:block; animation:panelIn .7s var(--slow); }
.review dl{ display:grid; grid-template-columns:auto 1fr; gap:11px 26px; margin-top:24px;
  border-top:1px solid rgba(var(--carbon-rgb),.16); padding-top:20px; }
.review dt{ font-family:var(--mono); font-size:10px; letter-spacing:.13em; text-transform:uppercase;
  color:var(--mute); padding-top:3px; }
.review dd{ margin:0; font-size:var(--t--1); }
/* every answer is a way back to its question */
.redit{ display:flex; align-items:baseline; gap:12px; width:100%; text-align:left; padding:0;
  color:var(--carbon); transition:color .3s var(--ease); }
.redit i{ font-style:normal; margin-left:auto; flex:none; font-family:var(--mono); font-size:9px;
  letter-spacing:.12em; text-transform:uppercase; color:var(--mute);
  border-bottom:1px solid rgba(var(--carbon-rgb),.28); transition:color .3s, border-color .3s; }
.redit:hover{ color:var(--signal-ink); }
.redit:hover i{ color:var(--signal-ink); border-color:var(--signal-ink); }
.ractions{ display:flex; gap:10px; flex-wrap:wrap; margin-top:28px; }

/* ---------- final + footer ---------- */
.final{ text-align:center; overflow:hidden; }
.final .glowfield{ position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(54% 68% at 50% 112%, rgba(var(--signal-rgb),.3), transparent 68%); }
.final-inner{ position:relative; z-index:2; display:flex; flex-direction:column; align-items:center; gap:22px; }
.final .actions{ display:flex; gap:10px; flex-wrap:wrap; justify-content:center; margin-top:6px; }
.footer{ padding:var(--vr-4) var(--pad) 28px; }
.footer .logo{ height:46px; width:auto; }
/* the contact column carries the most, follow carries one link — weight to suit */
.footer-grid{ display:grid; grid-template-columns:1.5fr .85fr 1.25fr .7fr; gap:36px; }
.footer h5{ font-family:var(--mono); font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--lbl); margin:0 0 15px; font-weight:400; }
.footer ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:9px; }
.footer li a{ font-size:var(--t--1); color:rgba(var(--lift-rgb),.72); transition:color .3s; }
/* "talk to us" in the hero lands here, so the two ways to reach a person lead */
#contact{ scroll-margin-top:calc(var(--nav-h) + 24px); }
.footer .contact li:nth-child(-n+3) a{ font-size:var(--t-0); color:var(--lift); }
.footer .contact li.sep{ margin-top:9px; padding-top:12px; border-top:1px solid var(--rule); }
.footer li a:hover{ color:var(--lift); }
.footer .ext{ margin-left:7px; font-size:.85em; opacity:.6; }
/* announced by screen readers, never drawn */
.vh{ position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap; border:0; }
.footer .tagline{ font-family:var(--mono); font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--lbl); margin-top:18px; display:flex; align-items:center; gap:9px; }
.footer-bottom{ display:flex; justify-content:space-between; align-items:center; gap:18px; flex-wrap:wrap;
  margin-top:var(--vr-4); padding-top:20px; border-top:1px solid var(--rule); }
.footer-bottom .sign{ font-size:1.3rem; font-weight:700; letter-spacing:var(--track-sm); }
.mobile-cta{ display:none; }

[data-reveal]{ opacity:0; transform:translateY(24px); transition:opacity .9s var(--ease), transform 1s var(--slow); }
[data-reveal].in{ opacity:1; transform:none; }
/* Progressive enhancement: where scroll-driven animation exists, reveals run on the
   compositor and main.js skips its IntersectionObserver entirely. Everywhere else the
   observer above is still the only thing driving them — this replaces nothing. */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    [data-reveal]{ animation:revealIn linear both; animation-timeline:view(); animation-range:entry 6% cover 28%; }
    @keyframes revealIn{ from{ opacity:0; transform:translateY(24px); } to{ opacity:1; transform:none; } }
  }
}

/* ---------- responsive ---------- */
@media (max-width:1080px){ .world-grid{ grid-template-columns:1fr; } }
@media (max-width:860px){
  .nav-links,.nav .btn{ display:none; }
  .burger{ display:block; }
  .hud{ display:none; }
  html.sqcursor{ cursor:auto; }
  .tabsplit{ grid-template-columns:1fr; }
  .tpanel{ min-height:0; }
  .cat button{ flex-wrap:wrap; }
  .cat .nm{ font-size:1.85rem; }
  .cat .desc{ margin-left:0; text-align:left; width:100%; max-width:none; display:none; }
  .cat.active .desc{ display:block; margin-top:8px; }
  .create.hot .cat:not(.active) button{ opacity:.55; }
  .grid2{ grid-template-columns:1fr; }
  .footer-grid{ grid-template-columns:1fr 1fr; gap:28px; }
  .hero{ padding-bottom:104px; }
  .mobile-cta{ display:flex; gap:8px; position:fixed; left:0; right:0; bottom:0; z-index:750;
    padding:11px var(--pad) calc(11px + var(--safe-b));
    background:rgba(var(--linen-rgb),.95); backdrop-filter:blur(12px); border-top:1px solid rgba(var(--carbon-rgb),.16); }
  .mobile-cta .btn{ flex:1; justify-content:center; }
  /* the hero already offers "plan an event"; showing it twice on one screen is
     noise. The bar rises once the hero is behind you. */
  .mobile-cta{ transform:translateY(110%); transition:transform .5s var(--slow); }
  .mobile-cta.up{ transform:none; }
  body{ padding-bottom:calc(62px + var(--safe-b)); }
  .mobile-menu{ padding-bottom:calc(34px + var(--safe-b)); }
}

/* ---------- narrow phones ---------- */
@media (max-width:560px){
  .footer-grid{ grid-template-columns:1fr; }
  .cat .nm{ font-size:1.7rem; }

  /* one CTA per row, full width — two ghost-width buttons side by side read as ragged */
  .hero .actions,.final .actions{ width:100%; }
  .hero .actions .btn,.final .actions .btn{ flex:1 1 100%; justify-content:center; }
  .hero .row{ gap:24px; }

  /* the brief: primary action first and full width, progress bar on its own line */
  .bbar{ flex-wrap:wrap; gap:10px 14px; }
  .bbar .track{ order:3; flex:1 0 100%; }
  .stepnav{ gap:12px; }
  .stepnav .btn.lg{ order:-1; flex:1 1 100%; justify-content:center; }
  #saved{ margin-left:0; flex:1 1 100%; }
  .ractions{ gap:8px; }
  .ractions .btn{ flex:1 1 100%; justify-content:center; }
  .chip{ padding:13px 18px; }
}

@media (max-width:400px){
  .cat .nm{ font-size:1.5rem; }
  .cat .idx{ width:22px; }
  .btn.lg{ padding:17px 22px; }
  .card{ flex-basis:min(78vw,260px); }
}

/* ---------- touch devices ---------- */
@media (hover:none){
  /* every footer link becomes a real target rather than a 14px line of text */
  .footer ul{ gap:0; }
  .footer li a{ display:flex; align-items:center; min-height:44px; }
  .footer .contact li.sep{ margin-top:6px; padding-top:8px; }
  .mobile-menu nav a{ min-height:56px; }

  /* a fixed, full-viewport multiply layer re-composites on every scroll frame,
     which is the single most expensive thing on this page for a phone. The
     per-section carbon grain stays — it scrolls with its section. */
  body::after{ display:none; }
  .card .bloom,.card .haze{ will-change:auto; }
}

/* ---------- short landscape ---------- */
@media (max-height:520px) and (orientation:landscape){
  .s.hero{ min-height:auto; padding-top:calc(var(--nav-h) + 28px); padding-bottom:32px; }
  .s{ padding-top:56px; padding-bottom:56px; }
}

@media (prefers-reduced-motion:reduce){
  *{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; scroll-behavior:auto !important; }
  .word>span{ transform:none !important; }
  [data-reveal]{ opacity:1; transform:none; }
  .value .w{ transform:none; }
  .card .bloom,.card .haze{ transform:none !important; will-change:auto; }
  #curtain .q{ animation:none; }
  .mobile-cta{ transition:none; }
  .card .plan{ opacity:.34;
    -webkit-mask-image:radial-gradient(62% 50% at 50% 44%, #000 0%, rgba(0,0,0,.55) 52%, transparent 80%);
            mask-image:radial-gradient(62% 50% at 50% 44%, #000 0%, rgba(0,0,0,.55) 52%, transparent 80%); }
}
