/* ============================================================
   GanttAI, Minimal Mono
   White · near-black · one restrained green. Flat, sharp, spacious.
   Display: Archivo · Body: Inter Tight · Data/labels: IBM Plex Mono
   ============================================================ */

:root{
  --bg:#ffffff;
  --bg-soft:#fafafa;
  --ink:#0a0b0a;
  --ink-2:#1c211f;
  --soft:#343b39;
  --mute:#555c5a;
  --faint:#828a87;
  --line:#d7dad6;
  --line-2:#bcc1bd;

  --green:#0f8a5f;
  --green-d:#0b6b4a;
  --green-t:#eef7f2;

  --amber:#b7791f;
  --red:#c0392b;

  /* surfaces and foregrounds, named so a theme is a swap not a rewrite */
  --card:#ffffff;          /* panels, inputs, chips: anything raised off --bg */
  --on-ink:#ffffff;        /* text sitting on an --ink fill */
  --on-green:#ffffff;      /* text sitting on a --green fill */
  --ink-h:#000000;         /* primary button, hovered */
  --wash:rgba(10,11,10,.022);   /* the soft section band */
  --track:rgba(10,11,10,.045);  /* empty gantt bar */
  --bar:rgba(255,255,255,.88);  /* nav and footer, translucent */
  --paper:#ffffff;         /* printed-document art: white in both themes */

  --disp:'Archivo',system-ui,-apple-system,sans-serif;
  --body:'Inter Tight',system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  --r:8px;
  --r-lg:12px;
  --maxw:1180px;
  --ease:cubic-bezier(.22,.61,.36,1);
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;scroll-padding-top:84px;-webkit-text-size-adjust:100%}
html{background:var(--bg)}
body{
  background:transparent;color:var(--soft);font-family:var(--body);
  line-height:1.65;-webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
::selection{background:var(--green-t);color:var(--ink)}

h1,h2,h3,h4{font-family:var(--disp);color:var(--ink);letter-spacing:-.032em;line-height:1.05;font-weight:800;text-wrap:balance}
h1{font-size:clamp(2rem,7.4vw,4.3rem)}
/* a headline with a full sentence in it needs a smaller step, or it sets
   three words to a line and pushes the whole hero down the page */
.h1--long{font-size:clamp(1.85rem,4.6vw,3.05rem);line-height:1.08}
h2{font-size:clamp(1.5rem,4.6vw,2.6rem);font-weight:700}
h3{font-size:1.04rem;font-weight:700;letter-spacing:-.015em;line-height:1.25}
p{text-wrap:pretty}

.wrap{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 28px}
.wrap--narrow{max-width:var(--maxw)}   /* FAQ sits on the same rails as everything else */

/* ---------- Labels ---------- */
.eyebrow{
  display:inline-block;font-family:var(--mono);font-size:.71rem;font-weight:500;
  letter-spacing:.15em;text-transform:uppercase;color:var(--green-d);
}
.eyebrow--green{color:var(--green-d)}   /* small uppercase text needs the darker green to clear AA */
.hl{color:var(--green)}

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:var(--body);font-weight:600;font-size:.94rem;letter-spacing:-.01em;
  padding:12px 22px;border-radius:var(--r);border:1px solid transparent;cursor:pointer;
  transition:background .16s var(--ease),color .16s,border-color .16s,transform .16s;
  white-space:nowrap;
}
.btn.lg{padding:14px 28px;font-size:1rem}
.btn.block{width:100%}
.btn-primary{background:var(--ink);color:var(--on-ink)}
.btn-primary:hover{background:var(--ink-h);transform:translateY(-1px)}
.btn-green{background:var(--green);color:var(--on-green)}
.btn-green:hover{background:var(--green-d);transform:translateY(-1px)}
.btn-ghost{color:var(--ink);border-color:var(--line-2);background:var(--card)}
.btn-ghost:hover{border-color:var(--ink);transform:translateY(-1px)}
.btn-link{color:var(--ink);padding:8px 4px;font-weight:600}
.btn-link:hover{color:var(--green)}
.btn-link .arw{transition:transform .18s var(--ease)}
.btn-link:hover .arw{transform:translateX(3px)}

/* ---------- Nav ---------- */
main,.foot{position:relative;z-index:1}
.nav{position:sticky;top:0;z-index:60;background:var(--bar);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.nav__in{display:flex;align-items:center;justify-content:space-between;height:64px;gap:24px}
.brand{display:inline-flex;align-items:center;gap:0;font-family:var(--disp);font-weight:800;font-size:1.2rem;color:var(--ink);letter-spacing:-.045em}
.brand img{width:26px;height:26px;margin-right:9px}
.brand span{color:var(--green)}
.nav__links{display:flex;gap:26px}
.nav__links a{font-size:.9rem;font-weight:500;color:var(--soft);position:relative;padding:4px 0}
.nav__links a::after{content:"";position:absolute;left:0;bottom:-2px;height:1.5px;width:0;background:var(--ink);transition:width .22s var(--ease)}
.nav__links a:hover{color:var(--ink)}
.nav__links a:hover::after,.nav__links a.active::after{width:100%}
.nav__links a.active{color:var(--ink)}
.nav__cta{display:flex;align-items:center;gap:10px}

/* The audience menu. Home and About have one primary button and it asks a
   question rather than answering it, so it opens rather than navigates. */
.nav__menu{position:relative}
.nav__menu .btn i{
  display:inline-block;width:7px;height:7px;margin-left:8px;vertical-align:1px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg) translate(-1px,-1px);transition:transform .18s var(--ease);
}
.nav__menu.is-open .btn i{transform:rotate(-135deg) translate(-2px,-2px)}
.nav__drop{
  position:absolute;top:calc(100% + 10px);right:0;min-width:290px;z-index:60;
  background:var(--card);border:1px solid var(--line);border-radius:6px;
  box-shadow:0 14px 40px rgba(10,20,16,.13);overflow:hidden;
}
.nav__drop a{
  display:block;padding:13px 16px;border-bottom:1px solid var(--line-2);
  transition:background .16s var(--ease);
}
.nav__drop a:last-child{border-bottom:0}
.nav__drop a:hover,.nav__drop a:focus-visible{background:var(--bg-soft)}
.nav__drop b{display:block;font-size:.93rem;font-weight:600;color:var(--ink)}
.nav__drop span{
  display:block;margin-top:2px;font-family:var(--mono);font-size:.66rem;
  letter-spacing:.04em;color:var(--mute);
}
@media(max-width:900px){ .nav__menu{display:none} }
.nav__mobcta{display:none}
/* The three bars are 16px tall and 22px wide. The padding is what carries the
   button up to a 44px hit area, which is the smallest target a thumb can be
   expected to find, and this is the only way to open the menu on a phone. */
.nav__tog{display:none;flex-direction:column;gap:5px;background:none;border:0;cursor:pointer;padding:14px 11px}
.nav__tog span{width:22px;height:2px;background:var(--ink);border-radius:2px;transition:.25s}
.nav__tog[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav__tog[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav__tog[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* ---------- Hero ---------- */
.hero{padding:88px 0 76px;border-bottom:1px solid var(--line)}
.hero__grid{display:grid;grid-template-columns:1.05fr .95fr;gap:64px;align-items:center}
[data-audience="gc"] .hero__grid{grid-template-columns:.86fr 1.14fr;gap:52px}
.hero__copy{max-width:640px}
.hero h1{margin:18px 0 22px}
.hero .lead{font-size:1.16rem;color:var(--soft);max-width:52ch}
.hero .lead b{color:var(--ink);font-weight:600}
.hero__actions{display:flex;gap:12px;flex-wrap:wrap;margin:30px 0 24px}
.hero__meta{display:flex;gap:24px;flex-wrap:wrap;font-family:var(--mono);font-size:.73rem;color:var(--mute)}
/* With no buttons between them, the meta line needs the air the buttons
   used to provide, or it reads as a fourth line of the lead. */
.lead + .hero__meta{margin-top:28px}
.hero__meta span{position:relative;padding-left:15px}
.hero__meta span::before{content:"\00b7";position:absolute;left:0;color:var(--green)}
/* Home and About carry no hero art, so a left-set column leaves a wide empty
   half beside it and the page opens off balance. With nothing to sit next to,
   the copy takes the middle and the buttons sit under it. */
.hero--solo .hero__copy{max-width:820px;margin:0 auto;text-align:center}
.hero--solo .lead{max-width:64ch;margin-left:auto;margin-right:auto}
.hero--solo .hero__actions,.hero--solo .hero__meta{justify-content:center}

/* Home asks nothing in the hero: the two audience buttons live in the section
   below and in the closing block, and repeating them here was the third time
   the same choice appeared before the fold. What is left is a cue that there
   is more, which is the only thing the hero still has to say. */
.hero__more{
  display:grid;place-items:center;width:44px;height:44px;margin:38px auto 0;
  border:1px solid var(--line);border-radius:50%;color:var(--mute);
  transition:color .2s var(--ease),border-color .2s var(--ease),transform .2s var(--ease);
  animation:heroNudge 2.6s ease-in-out infinite;
}
.hero__more svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.hero__more:hover{color:var(--green);border-color:var(--green);animation-play-state:paused;transform:translateY(2px)}
@keyframes heroNudge{
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(5px)}
}
@media(prefers-reduced-motion:reduce){ .hero__more{animation:none} }


/* ---------- Sections ---------- */
.sec{padding:84px 0;border-bottom:1px solid var(--line)}
.sec--soft{background:var(--wash)}
.sec--flush{border-bottom:0}
.sec__head{max-width:660px;margin-bottom:46px}
.sec__head .eyebrow{margin-bottom:14px}
.sec__head h2{margin-bottom:14px}
.sec__head p{font-size:1.04rem;color:var(--soft)}
.sec__head--center{margin-left:auto;margin-right:auto;text-align:center}

/* ---------- Icons, tiny, quirky, re-animate every time they enter view ---------- */
.ic{
  width:34px;height:34px;border:1px solid var(--line-2);border-radius:var(--r);
  display:grid;place-items:center;color:var(--green);background:var(--card);flex:none;
  transform-origin:50% 80%;backface-visibility:hidden;
  transition:transform .2s var(--ease),border-color .18s var(--ease),color .18s var(--ease);
}
.ic svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* solid glyphs lifted from the app (Review, Compare), same shapes the
   product uses, so the site and the sidebar agree */
.ic--solid svg{fill:currentColor;stroke:none}
.ic--lg.ic--solid svg{width:22px;height:22px}   /* solid glyphs carry more detail, so give them room */
.ic--lg{width:40px;height:40px}
.ic--lg svg{width:19px;height:19px}

/* always visible, hover swells it, entry and clicks set the glyph off */
.ic{opacity:1;cursor:pointer}
@media(hover:hover) and (pointer:fine){
  .ic:hover{transform:scale(1.12)}
}

/* --- the animation pool: entry and click both draw from this ---
   Every one runs on the glyph inside, so the hover scale on .ic is left
   alone and nothing jumps, and every one starts and ends at rest without
   ever touching opacity. An icon is never invisible, at any moment. */
.ic svg{transform-origin:50% 50%}
.ic svg.tk{animation-duration:.55s;animation-timing-function:var(--ease);animation-fill-mode:both}
.ic svg.tk-bounce{animation-name:tkBounce}
.ic svg.tk-wiggle{animation-name:tkWiggle}
.ic svg.tk-pop{animation-name:tkPop}
.ic svg.tk-spin{animation-name:tkSpin}
.ic svg.tk-squish{animation-name:tkSquish}
.ic svg.tk-shiver{animation-name:tkShiver}
.ic svg.tk-flip{animation-name:tkFlip}
.ic svg.tk-nod{animation-name:tkNod}
@keyframes tkBounce{
  0%,100%{transform:none}30%{transform:translateY(-6px) scale(1.14)}
  55%{transform:translateY(1px) scale(.92)}78%{transform:translateY(-2px) scale(1.05)}
}
@keyframes tkWiggle{
  0%,100%{transform:none}18%{transform:rotate(-18deg)}36%{transform:rotate(14deg)}
  54%{transform:rotate(-9deg)}72%{transform:rotate(5deg)}86%{transform:rotate(-2deg)}
}
@keyframes tkPop{
  0%,100%{transform:none}34%{transform:scale(1.38)}60%{transform:scale(.86)}82%{transform:scale(1.09)}
}
@keyframes tkSpin{0%{transform:none}70%{transform:rotate(374deg)}100%{transform:rotate(360deg)}}
@keyframes tkSquish{
  0%,100%{transform:none}28%{transform:scale(1.3,.74)}52%{transform:scale(.82,1.22)}
  76%{transform:scale(1.08,.94)}
}
@keyframes tkShiver{
  0%,100%{transform:none}
  12%,36%,60%{transform:translateX(-3px) rotate(-4deg)}
  24%,48%,72%{transform:translateX(3px) rotate(4deg)}
}
@keyframes tkFlip{0%{transform:none}100%{transform:rotateY(360deg)}}
@keyframes tkNod{
  0%,100%{transform:none}25%{transform:translateY(-5px) rotate(-11deg)}
  50%{transform:translateY(2px) rotate(9deg)}75%{transform:translateY(-1px) rotate(-4deg)}
}

/* icons never animate from a hover, see the pool above */

/* ---------- Feature grid ---------- */
.grid{display:grid;gap:0;border:1px solid var(--line)}
.grid--3{grid-template-columns:repeat(3,1fr)}
.grid--4{grid-template-columns:repeat(4,1fr)}
.cell{padding:30px 26px;border-right:1px solid var(--line);border-bottom:1px solid var(--line)}
.grid--3 .cell:nth-child(3n){border-right:0}
.grid--3 .cell:nth-last-child(-n+3){border-bottom:0}
.grid--4 .cell:nth-child(4n){border-right:0}
.grid--4 .cell:nth-last-child(-n+4){border-bottom:0}
.cell h3{margin:16px 0 8px}
.cell p{font-size:.92rem;color:var(--soft)}
.cell:hover{background:var(--bg-soft)}

/* ---------- IO flow (inputs -> outputs) ---------- */
.io{display:grid;grid-template-columns:1fr auto 1fr;gap:34px;align-items:stretch}
.io__col{border:1px solid var(--line);padding:26px}
.io__label{display:flex;align-items:center;gap:9px;font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--mute);margin-bottom:20px}
.io__label b{color:var(--ink);font-weight:500}
.io__list{list-style:none;display:grid;gap:12px}
.io__list li{display:flex;align-items:center;gap:12px;font-size:.94rem;color:var(--ink);font-weight:500}
.io__list .ic{width:32px;height:32px;border-radius:6px}
.io__list .ic svg{width:15px;height:15px}
.io__mid{display:grid;place-items:center;position:relative;padding:0 4px}
.io__arrow{position:absolute;top:0;bottom:0;left:50%;width:1px;background:var(--line-2)}
/* The step between the two columns, so it points at the one it feeds. A tag
   with a head on it says that; a lozenge just sits there. */
.io__badge{
  position:relative;z-index:1;
  background:var(--ink);color:var(--on-ink);font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;
  text-transform:uppercase;padding:8px 26px 8px 14px;white-space:nowrap;
  border-radius:3px 0 0 3px;
  clip-path:polygon(0 0, calc(100% - 13px) 0, 100% 50%, calc(100% - 13px) 100%, 0 100%);
}
.io__col--out{background:var(--bg-soft)}

/* ---------- Steps ---------- */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:34px}
.step__n{font-family:var(--mono);font-size:.74rem;letter-spacing:.12em;color:var(--green)}
.step h3{margin:12px 0 8px}
.step p{font-size:.93rem}
.steps--rows{grid-template-columns:1fr;gap:0}
.steps--rows .step{
  display:grid;grid-template-columns:34px 1fr;gap:20px;padding:20px 0;align-items:start;
  position:relative;border-bottom:0;
}
/* the numerals read as a numbered flow: a badge per step, joined by a rule */
.steps--rows .step__n{
  width:34px;height:34px;border:1px solid var(--line-2);border-radius:50%;
  display:grid;place-items:center;background:var(--card);color:var(--ink);
  font-size:.72rem;letter-spacing:.04em;padding:0;position:relative;z-index:1;
}
.steps--rows .step:not(:last-child)::before{
  content:"";position:absolute;left:17px;top:48px;bottom:-6px;width:1px;background:var(--line-2);
}
.steps--rows .step h3{margin-top:6px}
/* the questions people actually ask, shown as prompts */
.asks{list-style:none;margin:12px 0 0;display:grid;gap:7px}
.asks li{
  position:relative;padding:7px 12px 7px 29px;font-size:.88rem;color:var(--ink);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);line-height:1.45;
}
.asks li::before{
  content:"";position:absolute;left:12px;top:13px;width:9px;height:9px;border-radius:50%;
  border:1.5px solid var(--green);
}
.sec--soft .asks li{background:var(--card)}
.step__foot{margin-top:12px;font-size:.88rem!important;color:var(--mute)!important}

/* ---------- Stats ---------- */
.stats{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line)}
.stat{padding:28px 24px;border-right:1px solid var(--line)}
.stat:last-child{border-right:0}
.stat__n{font-family:var(--disp);font-weight:800;font-size:2.5rem;color:var(--ink);letter-spacing:-.04em;display:block;font-variant-numeric:tabular-nums}
.stat__n i{font-style:normal;font-size:1.2rem;color:var(--green)}
.stat__l{font-family:var(--mono);font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;color:var(--mute);margin-top:8px;display:block;line-height:1.5}
/* The fourth tile answers "what does it work with", which is not a quantity.
   It keeps the weight of a figure without pretending to be one, so the row
   still reads as a row. */
.stat__n--txt{font-size:1.5rem;letter-spacing:-.02em;line-height:1.5}
.stat--fmt .stat__l{text-transform:none;letter-spacing:.02em;font-size:.72rem}

/* The numbers make the case, so the two ways on sit directly under them
   rather than in a section of their own further down. */
.statscta{margin-top:46px;text-align:center}
.statscta h2{margin:0 0 10px}
.statscta p{color:var(--soft);margin:0 auto 26px;max-width:56ch}
.statscta .cta__actions{justify-content:center}

/* ---------- Split (GC vs Sub) ---------- */
.split{display:grid;grid-template-columns:1fr 1fr;border:1px solid var(--line)}
/* Three features, not two products with a note underneath. The agent earns a
   column of its own here, which is also the only honest place for it: it is
   not a third audience, it is the one thing both audiences share. */
.split--3{grid-template-columns:repeat(3,1fr)}
.split--3 .split__card{padding:34px 28px}
.split--3 .ic--lg{margin-bottom:16px}
/* The agent has no page of its own to send anyone to, so its column is not
   a link. It keeps the frame and drops the hover and the button. */
.split__card--flat{cursor:default}
.split__card--flat:hover{background:transparent}
.split__card{padding:40px 34px;border-right:1px solid var(--line);display:flex;flex-direction:column;transition:background .2s}
.split__card:last-child{border-right:0}
.split__card:hover{background:var(--bg-soft)}
.split__tag{font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--green)}
.split__card h3{font-size:1.6rem;font-weight:800;letter-spacing:-.035em;margin:14px 0 10px}
.split__card > p{font-size:.98rem;margin-bottom:22px}
.split__list{list-style:none;display:grid;gap:10px;margin-bottom:28px}
.split__list li{position:relative;padding-left:20px;font-size:.93rem;color:var(--soft)}
.split__list li::before{content:"";position:absolute;left:0;top:.62em;width:7px;height:1.5px;background:var(--green)}
.split__foot{margin-top:auto}

/* ---------- Demo blocks (Review / Compare) ---------- */
.demo{display:grid;grid-template-columns:1.45fr 1fr;gap:52px;align-items:stretch}
.demo + .demo{margin-top:72px;padding-top:72px;border-top:1px solid var(--line)}
.demo--flip{grid-template-columns:1fr 1.45fr}   /* the media keeps the wide column either way */
.demo--flip .demo__media{order:2}
.demo--flip .demo__copy{order:1}
.demo__copy{display:flex;flex-direction:column;justify-content:center;min-width:0}
.demo__copy h2{margin:12px 0 12px;font-size:clamp(1.4rem,2.6vw,2rem)}
.demo__copy > p{font-size:1.02rem;margin-bottom:22px}
.demo__media{
  border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--bg-soft);
  display:flex;flex-direction:column;min-width:0;
  transform-origin:50% 50%;will-change:transform;
  transition:transform .45s var(--ease),box-shadow .45s var(--ease);
}
/* while the cursor is over it the panel follows in real time, so the easing
   comes off; it eases back into place on the way out */
.demo__media.is-tilting{transition:box-shadow .3s var(--ease);box-shadow:0 26px 50px -28px rgba(10,11,10,.35)}
.demo__media .peek{flex:1;display:flex;flex-direction:column}
/* rows take up the slack, but only so far: past that the density stops
   reading as a schedule. Whatever is left sits below them, with the chat
   and the heat map pinned to the foot of the panel. */
.demo__media .peek__rows{flex:0 1 auto;align-content:space-between;max-height:520px}
.demo__media .peek__chat,.demo__media .peek__heat{margin-top:auto}
.demo__media .peek>*:last-child{margin-top:auto}   /* whatever closes a panel sits on its floor */
/* ...unless the rows themselves close it. Pinning those to the floor leaves
   the panel empty above them, which reads as a loading state rather than a
   schedule, so they stretch instead. */
.demo__media .peek>.peek__rows:last-child{margin-top:0;flex:1 1 auto}
.demo__media .pk__checks+.pk__heatlab{margin-top:14px}
.how__actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:56px}
.demo__media img{width:100%;display:block}
.demo__bar{display:flex;align-items:center;gap:6px;padding:10px 14px;border-bottom:1px solid var(--line);background:var(--card)}
.demo__bar i{width:9px;height:9px;border-radius:50%;background:var(--line-2);display:block}
.demo__bar span{margin-left:8px;font-family:var(--mono);font-size:.7rem;color:var(--mute)}
.demo__actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:30px;justify-content:center}

/* ---------- Messy PDF (subs hero) ---------- */
.messy{position:relative;--base-tf:rotate(-1.6deg);transform:rotate(-1.6deg);will-change:transform;transition:transform .45s var(--ease)}
.messy svg{
  width:100%;height:auto;display:block;border:1px solid var(--line-2);background:var(--card);
  box-shadow:0 30px 60px -40px rgba(10,11,10,.5);transition:box-shadow .3s var(--ease);
}
.messy.is-tilting{transition:none}
.messy.is-tilting svg{box-shadow:0 40px 70px -38px rgba(10,11,10,.6)}
.messy__stamp{
  position:absolute;top:16px;right:-10px;transform:rotate(8deg);
  font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--red);border:2px solid var(--red);padding:5px 10px;border-radius:3px;background:rgba(255,255,255,.9);
}

/* ---------- Testimonials ---------- */
.quotes{
  display:grid;grid-template-columns:repeat(4,1fr);
  gap:1px;background:var(--line);border:1px solid var(--line);
}
.quote{padding:28px 22px;border:0;background:var(--card);display:flex;flex-direction:column}
.quotes .quote:nth-child(3n){border-right:0}
.quotes .quote:nth-last-child(-n+3){border-bottom:0}
.quote blockquote{font-size:1rem;color:var(--ink);line-height:1.55;margin-bottom:20px;flex:1;font-weight:500}
.quote figcaption{display:flex;align-items:center;gap:11px}
.quote__av{width:34px;height:34px;border-radius:50%;background:var(--ink);color:var(--on-ink);display:grid;place-items:center;font-family:var(--mono);font-size:.7rem;flex:none}
.quote__who{font-size:.86rem;line-height:1.4}
.quote__who b{color:var(--ink);display:block;font-weight:600}
.quote__who span{color:var(--mute);font-size:.8rem}

/* ---------- Trusted-by logos ---------- */
.logos{text-align:left}
.logos__label{font-family:var(--mono);font-size:.71rem;letter-spacing:.15em;text-transform:uppercase;color:var(--green-d);font-weight:500;margin-bottom:26px}
/* one full-width band, edge to edge with the stats grid above it */
.logos__row{display:grid;grid-template-columns:repeat(5,1fr);align-items:stretch;border:1px solid var(--line)}
.logo{
  font-family:var(--disp);font-weight:700;font-size:1.02rem;letter-spacing:-.02em;color:var(--ink);
  border:0;border-right:1px solid var(--line);border-radius:0;padding:30px 18px;background:var(--card);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;min-width:0;
  transition:border-color .2s,transform .2s;
}
.logo:last-child{border-right:0}
.logo:hover{background:var(--bg-soft);transform:none}
.logo em{font-style:normal;font-family:var(--mono);font-size:.64rem;letter-spacing:.12em;text-transform:uppercase;color:var(--mute);font-weight:400}

/* ---------- FAQ ---------- */
.faq{border-top:1px solid var(--line)}
.faq__i{border-bottom:1px solid var(--line)}
.faq__i summary{
  cursor:pointer;list-style:none;display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:22px 2px;font-family:var(--disp);font-weight:700;font-size:1.04rem;color:var(--ink);letter-spacing:-.015em;
}
.faq__i summary::-webkit-details-marker{display:none}
.faq__i summary::after{content:"+";font-family:var(--mono);font-size:1.2rem;color:var(--green);transition:transform .25s var(--ease);line-height:1}
.faq__i[open] summary::after{transform:rotate(45deg)}
.faq__i p{padding:0 2px 22px;font-size:.96rem;color:var(--soft);max-width:74ch}
.faq__i p b{color:var(--ink);font-weight:600}

/* ---------- Formats strip ---------- */
.fmts{display:flex;gap:10px;flex-wrap:wrap;margin-top:20px}
.fmt{font-family:var(--mono);font-size:.72rem;letter-spacing:.06em;color:var(--ink);border:1px solid var(--line-2);border-radius:5px;padding:6px 11px;background:var(--card)}

/* ---------- CTA ---------- */
.cta{padding:96px 0}
.cta__in{max-width:760px}
.cta__in .eyebrow{margin-bottom:14px}
.cta__in h2{margin-bottom:14px}
.cta__in p{font-size:1.06rem;margin-bottom:30px}
.cta__actions{display:flex;gap:12px;flex-wrap:wrap}
.cta__note{margin-top:18px;font-family:var(--mono);font-size:.72rem;color:var(--mute)}

/* The other audience's way in. A trial is the wrong first step for someone
   who did not write the schedule, so the free comparison sits here instead
   of taking a third button next to the two that are already there. */
/* The free comparison is the way in for the half of the audience that did not
   write the schedule. It spent a round as a sentence with a link in it and read
   like a footnote, so it is a button again, sitting next to the demo. */

/* Home answers the three questions everyone asks, then hands off. */
.faq__more{margin-top:22px;font-size:.9rem;color:var(--mute)}
.faq__more a{color:var(--ink);border-bottom:1px solid var(--line-2)}
.faq__more a:hover{border-bottom-color:var(--green)}

/* The layer that spans both product cards, so it reads as neither one's. As a
   line of prose under the cards it read as a footnote, which is the one thing
   a third feature must not do, so it gets a card of its own: full width,
   centred, sitting square under the two it belongs to. */
.both{
  margin-top:-1px;border:1px solid var(--line);padding:34px 30px 36px;text-align:center;
}
.both__tag{
  display:block;font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--green);margin-bottom:12px;
}
.both h3{font-size:1.5rem;font-weight:800;letter-spacing:-.035em;margin:0 0 10px}
.both p{margin:0 auto;max-width:62ch;font-size:1rem;line-height:1.65;color:var(--soft)}

/* Summary cards point at the block that explains them, rather than
   repeating it. */
.cell__more{margin-top:12px;font-size:.88rem!important}
.cell__more a{color:var(--green-d);font-weight:500}

/* ---------- Footer ---------- */
.foot{border-top:1px solid var(--line);padding:52px 0 0}
.foot__grid{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:34px;padding-bottom:34px}
.foot__brand p{margin-top:12px;font-size:.9rem;color:var(--mute);max-width:30ch}
.foot__tag{font-family:var(--mono);font-size:.8rem!important;letter-spacing:.04em;color:var(--soft)!important}
.foot__col h4{font-family:var(--mono);font-size:.7rem;letter-spacing:.13em;text-transform:uppercase;color:var(--ink);font-weight:500;margin-bottom:14px}
.foot__col a{display:block;font-size:.9rem;color:var(--soft);padding:5px 0}
.foot__col a:hover{color:var(--green)}
/* mirrors the nav bar at the top: full-bleed rule, 64px, same type */
.foot__bar{border-top:1px solid var(--line);background:var(--bar);backdrop-filter:blur(10px);margin-top:34px}
.foot__bot{
  display:flex;justify-content:space-between;align-items:center;gap:14px;
  height:64px;font-family:var(--body);font-size:.9rem;font-weight:500;color:var(--soft);
}


/* ---------- Equal-height dark bands ----------
   Three black sections on one page read as three different slabs when
   each is sized by its own copy. Giving them a shared floor and centring
   the contents makes the light/dark alternation feel like a rhythm
   rather than an accident. The floor is a minimum, so a section that
   genuinely needs more room still grows. */
/* Set on a page with no background scenery behind the bands. The value is
   the tallest band's natural height, so the others rise to meet it rather
   than the tall one being squeezed. */
/* The two dark bands on About match heights so the page reads as having a
   rhythm rather than two unrelated dark blocks. The roles section is the
   exception: it is a collapsed list, so holding it to the world scene's
   height padded it with dead space that made two short postings look like an
   empty page. It sizes to its content and keeps a floor. */
.page-flat{--band-h:1015px}
#roles.sec--band{min-height:0}

.sec--band{display:flex;align-items:center;min-height:var(--band-h,640px)}
.sec--band > .wrap{width:100%}

/* Below the breakpoint the bands are already far taller than the floor and
   equalising them would only open dead space, so each takes its own height. */
@media(max-width:980px){ .sec--band{min-height:0;display:block} }


/* ---------- Zoom-out: the three-part argument ----------
   Numbered rather than iconed, these are parts of one position, and
   the order is the argument: build it better, make it readable, meet
   the industry where it already is. */
/* Wider than a normal section head so the headline sets in two lines
   instead of three, this section has to share a height with simpler
   ones, and the saving comes out of wrapping rather than out of words. */
/* A real gap, not a typographic one. The panels used to start 30px under the
   lead, which left the map no open band anywhere in the section and buried
   every project marker. This is the room the markers live in. */
#bigger-picture .sec__head{max-width:820px;margin-bottom:72px}

/* Blocks, not rules. Hairline dividers and the map's graticule crossed each
   other behind the text and neither read; a panel per point separates them
   and gives the copy its own ground to sit on. */
/* Pulled in from the full column width. The panels used to run the whole
   measure and the map ran underneath them, which left the projects with
   nowhere to be seen; giving back a strip on either side is what lets the
   markers sit on open water. */
.prongs{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;max-width:min(900px,62vw);margin:0 auto}
.bigger__end{max-width:min(900px,62vw);margin-left:auto;margin-right:auto}
/* Nearly solid, these read as three cards dropped on top of the map. The
   blur does the legibility work, so the fill can come most of the way down
   and let the coastline carry on underneath. */
.prong{
  padding:20px 22px 22px;border-radius:5px;border:1px solid rgba(255,255,255,.06);
  background:rgba(16,20,19,.39);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
}
.prong__n{
  display:block;font-family:var(--mono);font-size:.72rem;letter-spacing:.14em;
  color:var(--green);margin-bottom:12px;
}
.prong h3{font-size:1.14rem;font-weight:700;letter-spacing:-.02em;margin-bottom:9px}
.prong p{color:var(--soft);font-size:.95rem;line-height:1.68;margin:0}

/* ---------- World scene: ten live projects ----------
   The same three problems, on ten jobs that share nothing else. Split
   across two layers on purpose: the map lines sit behind the copy at the
   same weight as the crane line-art on the other pages, while the dots
   and their labels sit above it, a label buried under a paragraph reads
   as a rendering fault, not as texture. Both layers use the same 2:1 box,
   so pins placed by the projection land on the coastline they belong to. */
#bigger-picture{position:relative;overflow:hidden}
#bigger-picture > .wrap{position:relative;z-index:2}

.wmap,.wpins{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none}
.wmap{z-index:0}
.wpins{z-index:1}
.wgeo{position:relative;width:100%;aspect-ratio:var(--wratio,2);max-height:100%;
  transform-origin:50% 50%;will-change:transform}

.wmap__svg{position:absolute;inset:0;width:100%;height:100%;fill:none}
.wmap__svg path{vector-effect:non-scaling-stroke}
/* Same line as the crane on the other pages: hairline, round joins, quiet
   enough to sit under type. It used to be twice this weight, which turned
   every simplified corner into a visible facet and made the copy fight it. */
.wmap__grid path{stroke:var(--ink);stroke-width:.5;opacity:.06}
.wmap__eq{stroke:var(--green);stroke-width:.5;opacity:.1}
.wmap__land path{
  stroke:var(--ink);stroke-width:.7;opacity:.3;
  stroke-linejoin:round;stroke-linecap:round;
}

/* The pin is the coordinate itself, a zero-size anchor. It used to be a
   flex row holding the dot and its label, which meant translate(-50%) centred
   the label too and pushed the dot sideways by half its width. The error grew
   with the length of the label and vanished on mobile, where labels are not
   rendered at all. */
.wpin{position:absolute;width:0;height:0}
/* A cross rather than a dot, in a light neutral: the green dots vanished
   against the green 01/02/03 numerals. The box is the hit target, the marker
   is drawn inside it, and the stroke thickens and thins instead of pulsing
   outward, the same heartbeat without a halo to bleed into the copy. */
.wpin__dot{
  position:absolute;left:-11px;top:-11px;width:22px;height:22px;
  pointer-events:auto;
}
.wpin__dot::before,.wpin__dot::after{
  content:'';position:absolute;left:50%;top:50%;
  width:11px;height:1.4px;border-radius:1px;background:#e6ebe8;
  animation:wx 3.2s ease-in-out infinite;animation-delay:var(--d,0s);
}
.wpin__dot::before{transform:translate(-50%,-50%) rotate(45deg)}
.wpin__dot::after{transform:translate(-50%,-50%) rotate(-45deg)}
@keyframes wx{
  0%,100%{height:1.2px;opacity:.62}
  50%{height:2.6px;opacity:1}
}
.wpin:hover .wpin__dot::before,.wpin:hover .wpin__dot::after{
  background:var(--green);animation-play-state:paused;height:2.2px;opacity:1;
}

.wpin__tag{
  position:absolute;left:14px;top:0;transform:translateY(-50%);
  display:block;font-family:var(--mono);font-size:.56rem;line-height:1.5;
  letter-spacing:.04em;white-space:nowrap;color:var(--soft);opacity:.5;
  padding:5px 8px;border-radius:2px;
  background:transparent;border:1px solid transparent;
  transition:opacity .18s ease,background-color .18s ease,border-color .18s ease;
}
.wpin--l .wpin__tag{left:auto;right:14px;text-align:right}
.wpin__tag b{display:block;font-weight:500;color:var(--ink);opacity:.72}
.wpin__tag em{display:block;font-style:normal;color:var(--green);opacity:.62}

/* Hidden by worldmap.js when it would land on the copy, until you go
   looking for it, at which point it gets a chip to stay legible. */
.wpin.is-hushed .wpin__tag{opacity:0}
/* marker landed in the headline or the lead, where nothing hides it */
.wpin.is-off{visibility:hidden}
.wpin:hover{z-index:3}
.wpin:hover .wpin__tag{
  opacity:1;background:#0f1211;border-color:var(--line-2);
}
.wpin:hover .wpin__tag b{opacity:1}
.wpin:hover .wpin__tag em{opacity:.9}

@media(max-width:1100px){ .wpin__tag{display:none} }

/* On a narrow screen the map is a 2:1 strip inside a section four times its
   height, so centring it strands it mid-column on top of a paragraph. Below
   this width it stops being a backdrop and becomes a band above the copy,
   with the section opening up to make room. Both layers take the same
   position so the dots stay on their coastlines. */
@media(max-width:980px){
  /* The band is half as tall as it is wide, so the space reserved above the
     copy has to track that rather than be a fixed number, and the band is
     capped so it does not eat the section on a tablet. */
  #bigger-picture{padding-top:calc(112px + min(38.4vw,199px))}
  .wmap,.wpins{inset:84px 0 auto 0;place-items:start center;opacity:.9}
  .wgeo{max-height:none;max-width:520px}
}
@media(prefers-reduced-motion:reduce){ .wpin__dot{animation:none} }


/* ---------- Open roles ----------
   Stacked and collapsed, the same affordance as the FAQ: the titles and
   terms are the list, the detail is there when someone wants it. Nothing
   here counts the roles, so adding or dropping one changes nothing else. */
.roles{border-top:1px solid var(--line);counter-reset:role}
.role{border-bottom:1px solid var(--line);counter-increment:role}
.role > summary{
  display:flex;align-items:center;gap:16px;justify-content:space-between;
  padding:22px 2px;cursor:pointer;list-style:none;
}
.role > summary::-webkit-details-marker{display:none}
.role > summary::after{
  content:"+";flex:none;font-family:var(--mono);font-size:1.2rem;line-height:1;
  color:var(--green);transition:transform .25s var(--ease);
}
.role[open] > summary::after{transform:rotate(45deg)}
.role > summary:hover h3{color:var(--green)}
.role__head{display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;min-width:0}
.role__head::before{
  content:counter(role,decimal-leading-zero);
  font-family:var(--mono);font-size:.72rem;letter-spacing:.14em;color:var(--green);
}
.role h3{
  font-size:1.24rem;font-weight:700;letter-spacing:-.02em;margin:0;
  transition:color .18s ease;
}
.role__sub{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--mute);margin:0;
}
.role__body{padding:0 2px 26px;max-width:78ch}
.role p{color:var(--soft);font-size:.95rem;line-height:1.68;margin:0 0 14px}
.role__list{list-style:none;margin:0;padding:0}
.role__list li{
  position:relative;padding-left:18px;margin-bottom:7px;
  color:var(--soft);font-size:.9rem;line-height:1.55;
}
.role__list li::before{
  content:'';position:absolute;left:0;top:.62em;
  width:6px;height:1px;background:var(--green);
}


/* ---------- Join-our-mission modal ----------
   Reuses the demo modal's shell and fields; only the shape differs, one
   column, sized to its content rather than to a calendar. */
/* The card is centred with auto margins inside a scrolling flex box rather
   than by place-items. Centring an item that is taller than its container
   clips the overflow above the fold and there is no way to scroll back up
   to it, which is what happened once the roles form grew a field. */
.jm{display:flex;overflow-y:auto;overscroll-behavior:contain;place-items:stretch}
.jm .dm__scrim{position:fixed}
/* .dm__card is declared later in this file and pins a height, so these have
   to out-specify it or the card stays locked to the viewport and its lower
   half is unreachable. */
.jm .dm__card{
  max-width:560px;width:100%;
  height:auto;max-height:none;overflow:visible;margin:auto;
}
.jm__head{padding:26px 26px 0}
.jm__head h3{font-size:1.3rem;font-weight:800;letter-spacing:-.03em;margin:9px 0 8px;line-height:1.2}
.jm__form{padding:20px 26px 26px}
.jm__opt{text-transform:none;letter-spacing:0;color:var(--mute)}
.jm__file{padding:8px 11px;font-size:.86rem;color:var(--soft);cursor:pointer}
.jm__file::file-selector-button{
  font:inherit;font-size:.82rem;margin-right:12px;cursor:pointer;color:var(--ink);
  background:transparent;border:1px solid var(--line-2);border-radius:2px;padding:5px 11px;
}
.jm__file::file-selector-button:hover{border-color:var(--ink)}
.jm .dm__in.is-bad{border-color:#d24b4b}
textarea#jmWhy{height:74px}
.roles__cta{
  display:flex;flex-direction:column;align-items:center;gap:13px;
  margin-top:40px;text-align:center;
}
.roles__hint{font-size:.88rem;line-height:1.55;color:var(--mute);max-width:52ch}
@media(max-width:860px){
  .roles__cta .btn,.bigger__cta .btn{width:100%;justify-content:center}
}

.jm__send{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:20px}
.jm__note{margin:0;font-size:.85rem;line-height:1.5}
.jm__note.is-ok{color:var(--green-d)}
.jm__note.is-bad{color:#d24b4b}
@media(max-width:520px){
  .jm__head{padding:22px 18px 0}
  .jm__form{padding:16px 18px 22px}
  .jm__send .btn{width:100%;justify-content:center}
}


@media(max-width:860px){
  .role > summary{padding:18px 2px}
  .role__head{gap:4px 14px}
  .ct{grid-template-columns:1fr;gap:34px}
  .ct__send .btn{width:100%;justify-content:center}
}


/* A row, not a stack. Centred and stacked, the closing line, the button and
   the note under it ran to four hundred pixels of mostly empty panel with the
   map hidden behind it. Side by side it says the same thing in a third of the
   height, and the world gets that height back. */
.bigger__end{
  margin-top:22px;padding:22px 26px;border-radius:5px;
  background:rgba(16,20,19,.62);backdrop-filter:blur(6px);
  display:grid;grid-template-columns:1fr auto;gap:30px;align-items:center;text-align:left;
}
.bigger__end > p{
  font-size:1.02rem;line-height:1.5;letter-spacing:-.015em;
  color:var(--ink);max-width:56ch;margin:0;
}
.bigger__cta{display:flex;flex-direction:column;align-items:flex-start;gap:9px}
.bigger__hint{font-size:.8rem;line-height:1.5;color:var(--mute);max-width:34ch;margin:0}

@media(max-width:980px){
  .bigger__end{grid-template-columns:1fr;gap:18px;text-align:center}
  .bigger__cta{align-items:center}
  .bigger__hint{max-width:none}
  .prongs{grid-template-columns:1fr;gap:10px}
  .prong{padding:22px 20px 24px}
  .bigger__cta{gap:18px}
  .bigger__cta .btn{width:100%;justify-content:center}
  .bigger__hint{max-width:none}
}


/* ---------- Home base: CN Tower, drawn in wireframe ---------- */
/* hairline at any size, the stroke never scales with the drawing */
.cnt{display:block;width:100%;height:auto;stroke-width:1}
.cnt path{vector-effect:non-scaling-stroke}
.loc{display:inline-flex;align-items:center;gap:9px;color:var(--ink);font-weight:500}
.loc .cnt{width:auto;height:22px;flex:none;color:var(--ink);stroke-width:1.2}
.loc .cnt__d{display:none}   /* the pod band closes up at this size */

/* One section, two halves, each running top to bottom: on the left the
   photograph and who he is, on the right where the company is and the tower.
   Both columns lead with their image or their heading and finish with prose,
   so the two halves scan the same way. */
/* Four things reading left to right: the portrait, who he is, where we are,
   the tower. Each half puts its picture on the outside and its words on the
   inside, so the two blocks face each other across the middle instead of
   both starting at their own left edge. */
/* The founder half carries a photograph and a paragraph, the location half a
   heading and two lines, so an even split squeezed the one that had things
   to say. Both hang from the top: with the tower matched to the photograph's
   height, "Chirag Soni" and "Based in Toronto" start on the same line. */
.home{display:grid;grid-template-columns:1.18fr .82fr;gap:52px;align-items:start}
.home__where{display:flex;flex-direction:row;align-items:flex-start;gap:30px}
.home__tower{order:2;flex:none}
.home__tower{flex:none;width:125px;color:var(--ink);cursor:pointer}
.loc{cursor:pointer}
.loc:hover .cnt,.home__tower:hover .cnt{color:var(--green-d)}

/* --- easter egg: maple leaves, black and white --- */
.mleaf{position:fixed;inset:0;z-index:9998;pointer-events:none;overflow:hidden}
.mleaf i{
  position:absolute;width:var(--sz);height:var(--sz);color:var(--tone);
  animation-name:mlFall;animation-timing-function:cubic-bezier(.3,.5,.5,1);animation-fill-mode:both;
}
.mleaf svg{width:100%;height:100%;display:block}
@keyframes mlFall{
  0%{transform:translate3d(0,0,0) rotate(0);opacity:0}
  8%{opacity:1}
  85%{opacity:1}
  100%{transform:translate3d(var(--dx),var(--dy),0) rotate(var(--rot));opacity:0}
}
.home__copy h3,.founder h3{font-size:1.55rem;font-weight:800;letter-spacing:-.03em;margin:11px 0 12px}
.home__copy p,.founder p{color:var(--soft);font-size:.96rem;line-height:1.65;max-width:48ch;margin:0}

/* --- founder ---
   Photograph then prose, side by side. Stacked, the paragraph sat a full
   photograph's height below the face it belongs to and the pair stopped
   reading as one thing. */
.founder{display:flex;align-items:flex-start;gap:30px}
.founder__body{min-width:0}
/* His words, so they are set as his words: the opening quote hangs into the
   margin, or the first line looks indented against the name above it. */
.founder__said{text-indent:-.42em}
/* The two halves start with the same label in the same place, so they take
   the same treatment: inline-block by default leaves the founder's sitting on
   a text baseline while the location's does not, which is where the seven
   pixels between the two headings came from. */
.founder .eyebrow,.home__copy .eyebrow{display:block;margin:0 0 8px;line-height:1.3}
/* Two photographs in one frame, the same size as each other because they
   swap in place. Black and white and nothing else: the source carried a
   vignette baked into the file, which is what the dark corners at the foot of
   it were, and it has been re-cropped clean rather than masked over. */
.founder__photo{flex:none;width:250px;aspect-ratio:1;position:relative;overflow:hidden}
.founder__photo img{
  position:absolute;inset:0;width:100%;height:100%;display:block;
  object-fit:cover;object-position:50% 50%;
  filter:grayscale(1) contrast(1.04);
  /* No crossfade. Two photographs this different overlap into a double
     exposure at any speed, and a shorter fade only makes the moment harder
     to catch, not less wrong. It cuts. */
  opacity:0;
}
.founder__photo img.is-on{opacity:1}
/* one image only: it holds the frame open and never fades */
.founder__photo.is-single img{position:relative;opacity:1;transition:none}

/* shown only while assets/founder.jpg is missing */
.founder__photo.is-empty{
  aspect-ratio:1;border-radius:50%;background:
    radial-gradient(circle at 50% 34%,var(--line-2) 0 20%,transparent 21%),
    radial-gradient(ellipse 44% 30% at 50% 92%,var(--line-2) 0 60%,transparent 61%),
    var(--line);
  -webkit-mask-image:radial-gradient(circle at 50% 50%,#000 52%,transparent 82%);
          mask-image:radial-gradient(circle at 50% 50%,#000 52%,transparent 82%);
}
.founder h3{margin-bottom:2px}
.founder__role{font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;color:var(--mute);margin-bottom:14px!important}
/* What he did before this. The quote is an opinion, and an opinion carries
   further when the reader knows it was earned on the jobs it describes. */


/* ---------- Reveal ---------- */
.rv{opacity:0;transform:translateY(14px);transition:opacity .55s var(--ease),transform .55s var(--ease)}
.rv.in{opacity:1;transform:none}
.rv[data-d="1"]{transition-delay:.07s}
.rv[data-d="2"]{transition-delay:.14s}
.rv[data-d="3"]{transition-delay:.21s}

/* ---------- Responsive ---------- */
@media(max-width:960px){
  .hero__grid,.demo,.io{grid-template-columns:1fr;gap:40px}
  .demo--flip .demo__media{order:0}
  .demo--flip .demo__copy{order:0}
  .io__mid{display:none}
  .grid--3,.grid--4,.quotes{grid-template-columns:repeat(2,1fr)}
  .grid--3 .cell:nth-child(3n),.grid--4 .cell:nth-child(4n),.quotes .quote:nth-child(3n){border-right:1px solid var(--line)}
  .grid--3 .cell:nth-child(2n),.grid--4 .cell:nth-child(2n),.quotes .quote:nth-child(2n){border-right:0}
  .grid--3 .cell:nth-last-child(-n+3),.grid--4 .cell:nth-last-child(-n+4),.quotes .quote:nth-last-child(-n+3){border-bottom:1px solid var(--line)}
  .stats{grid-template-columns:repeat(2,1fr)}
  .stat:nth-child(2n){border-right:0}
  .split,.steps{grid-template-columns:1fr}
  .split__card{border-right:0;border-bottom:1px solid var(--line)}
  .foot__grid{grid-template-columns:1fr 1fr}
}
/* The full nav stops fitting well before 700px: brand + three links + two
   buttons need ~800px, so it was spilling past the viewport between the two. */
@media(max-width:860px){
  .nav__links,.nav__cta{display:none}
  .nav__tog{display:flex;margin-right:-11px}   /* pull the new padding back off the edge */
}

@media(max-width:700px){
  .nav__in{height:58px;gap:12px}
  .brand{font-size:1.08rem}
  .brand img{width:23px;height:23px;margin-right:7px}
  .nav__links.open{
    display:flex;flex-direction:column;gap:0;position:absolute;top:58px;left:0;right:0;
    background:var(--card);border-bottom:1px solid var(--line);padding:6px 24px 18px;
    box-shadow:0 18px 30px -22px rgba(10,11,10,.35);max-height:calc(100vh - 58px);overflow-y:auto;
  }
  .nav__links.open a{padding:14px 0;border-bottom:1px solid var(--line);font-size:1rem}
  .nav__links.open .nav__mobcta{display:flex;flex-direction:column;gap:9px;padding-top:14px}
  .nav__mobcta .btn{width:100%}

  .grid--3,.grid--4,.quotes,.stats,.foot__grid,.io,.split,.steps{grid-template-columns:1fr}
  .pk__cards{grid-template-columns:repeat(2,1fr)}
  .cell,.stat,.quote,.split__card{border-right:0!important}
  .home{grid-template-columns:1fr;gap:34px}
  .home__where{flex-direction:column;text-align:center;gap:20px}
  .home__tower{width:52px}
  .home__copy p{margin:0 auto}
  .home{grid-template-columns:1fr;gap:44px}
  .founder,.home__where{flex-direction:column;align-items:flex-start;gap:22px}
  .home__tower{order:0}
  .founder__photo{width:100%;max-width:300px}
  .founder__copy p{margin:0 auto}
  .logos__row{grid-template-columns:repeat(2,1fr)}
  .logo{border-bottom:1px solid var(--line);border-right:1px solid var(--line)}
  .logo:nth-child(2n){border-right:0}
  .logo:last-child{grid-column:1/-1;border-right:0;border-bottom:0}
  .wrap{padding:0 20px}
  .hero{padding:36px 0 40px}
  .hero__grid{gap:32px}
  .hero .lead{font-size:1.02rem}
  .hero__actions{gap:10px;margin:22px 0 18px}
  .hero__actions .btn{flex:1 1 auto;justify-content:center}
  .hero__meta{gap:14px;font-size:.68rem}
  .sec{padding:46px 0}
  .sec__head{margin-bottom:26px}
  .cta{padding:52px 0}
  .cta__actions .btn{flex:1 1 auto}
  .cell{padding:22px 20px}
  .step{padding:0}
  .steps{gap:26px}
  .demo{gap:30px}
  .demo__actions .btn{flex:1 1 auto}
  .logo{min-width:0;flex:1 1 42%}
  .logos__row{gap:10px}
  .faq__i summary{font-size:.98rem;padding:18px 0}
  .messy{transform:none;max-width:340px;margin:0 auto}
  .mock__row{grid-template-columns:96px 1fr}
  .mock__prompt{font-size:.68rem}
  .peek__row{grid-template-columns:104px 1fr}
  .io__col{padding:20px}
  .foot__grid{gap:24px}
}
@media(max-width:420px){
  .hero__meta span{padding-left:0}
  .hero__meta span::before{content:none}
  .fmt{font-size:.66rem;padding:5px 8px}
  .gachat__body{height:38vh;min-height:200px}
}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .rv{opacity:1!important;transform:none!important;transition:none!important}
  /* no transforms, but icons still greet you with a soft fade */
  .ic svg.tk{animation:none}
  .ic:hover{transform:none}
  /* decorative loops off; make sure nothing stays stuck invisible */
  .mock__caret::after,.gam--typing i,.gachat__launch,.gachat__panel,
  .gachat__dot,.gachat__dot::after{animation:none!important;transition:none!important}
  .gb::after{animation:none!important;transform:none!important;opacity:1!important}
  .flag{animation:none!important;opacity:1!important;transform:none!important}
}

/* ============================================================
   Product mockups, hero "generate" panel + Review / Compare peeks
   (Peeks are drop-in replaceable with real GIFs.)
   ============================================================ */
.mock{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--card);box-shadow:0 30px 60px -46px rgba(10,11,10,.55);will-change:transform;transition:transform .45s var(--ease),box-shadow .45s var(--ease)}
.mock.is-tilting{transition:box-shadow .3s var(--ease);box-shadow:0 40px 70px -40px rgba(10,11,10,.6)}
.mock__bar{display:flex;align-items:center;gap:6px;padding:10px 14px;border-bottom:1px solid var(--line);background:var(--bg-soft)}
.mock__bar i{width:9px;height:9px;border-radius:50%;background:var(--line-2);display:block}
/* Flex items will not shrink below their own text unless told to, and these
   labels never wrap, so on a narrow phone the title bar sets a width floor
   that the whole page then has to honour. On the GC hero that floor was 336px
   against a 320px screen, which is a horizontal scrollbar on the whole page,
   from a strip of fake window chrome. */
.mock__bar span{margin-left:8px;font-family:var(--mono);font-size:.7rem;color:var(--mute);
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:420px){
  /* Ellipsis alone is not enough once two labels are competing. The path is
     decoration; the health pill is the one that says something and generate.js
     keeps it current, so the path is what goes. */
  .mock__bar span:not(.gen2__health){display:none}
}
.mock__body{padding:18px}
.mock__prompt{border:1px solid var(--line-2);border-radius:var(--r);padding:13px 14px;font-family:var(--mono);font-size:.74rem;color:var(--ink);line-height:1.6;background:var(--card)}
.mock__caret::after{content:"";display:inline-block;width:7px;height:1em;background:var(--green);margin-left:3px;vertical-align:-2px;animation:blink 1.1s steps(1) infinite}
@keyframes blink{0%,50%{opacity:1}51%,100%{opacity:0}}
.mock__out{margin-top:16px;display:grid;gap:7px}
.mock__row{display:grid;grid-template-columns:118px 1fr;align-items:center;gap:10px}
.mock__row > span:first-child{font-size:.7rem;color:var(--soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gb{position:relative;height:9px;background:rgba(10,11,10,.05);border-radius:3px;display:block}
.gb::after{
  content:"";position:absolute;top:0;height:9px;border-radius:3px;background:var(--ink);
  left:calc(var(--s) * 1%);width:calc(var(--w) * 1%);transform-origin:left;
  animation:gbIn .6s var(--ease) both;
}
.mock__row:nth-child(1) .gb::after{animation-delay:.15s}
.mock__row:nth-child(2) .gb::after{animation-delay:.25s;background:var(--green)}
.mock__row:nth-child(3) .gb::after{animation-delay:.35s}
.mock__row:nth-child(4) .gb::after{animation-delay:.45s;background:var(--green)}
.mock__row:nth-child(5) .gb::after{animation-delay:.55s}
.mock__row:nth-child(6) .gb::after{animation-delay:.65s;background:var(--green)}
.mock__row:nth-child(7) .gb::after{animation-delay:.75s}
.mock__row:nth-child(8) .gb::after{animation-delay:.85s;background:var(--green)}
@keyframes gbIn{from{transform:scaleX(0);opacity:0}to{transform:scaleX(1);opacity:1}}
.mock__foot{display:flex;gap:14px;flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.tick{font-family:var(--mono);font-size:.68rem;color:var(--green)}

/* ---- Peek (Review / Compare) ---- */
.peek{padding:20px;background:var(--card)}
.peek__rows{display:grid;gap:9px;align-content:start}
.peek__row{display:grid;grid-template-columns:132px 1fr;align-items:center;gap:10px;position:relative}
.peek__t{font-size:.72rem;color:var(--soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.peek__bar{position:relative;height:10px;background:var(--track);border-radius:3px;display:block;grid-column:2}
.peek__bar::after{
  content:"";position:absolute;top:0;height:10px;border-radius:3px;background:var(--ink);
  left:calc(var(--s) * 1%);width:calc(var(--w) * 1%);
}
.peek__bar--ghost::after{background:transparent;border:1px dashed var(--faint);height:10px;box-sizing:border-box}
.peek__bar--new{background:transparent;margin-top:-10px}
.peek__bar--new::after{background:var(--ink);opacity:.9}
.peek__bar--moved::after{background:var(--green)}
.pk__cards{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-bottom:14px}
.pk__card{border:1px solid var(--line);border-radius:6px;padding:8px 8px 9px;background:var(--card)}
.pk__card span{display:block;font-family:var(--mono);font-size:.5rem;letter-spacing:.06em;text-transform:uppercase;color:var(--mute);line-height:1.3}
.pk__card b{display:block;font-family:var(--disp);font-size:1.02rem;font-weight:800;letter-spacing:-.03em;color:var(--ink);margin-top:4px}
.pk__card--warn b{color:var(--red)}

.peek__legend{display:flex;gap:16px;margin-bottom:14px;font-family:var(--mono);font-size:.66rem;color:var(--mute)}
.peek__legend span{display:inline-flex;align-items:center;gap:6px}
.sw{width:14px;height:8px;border-radius:2px;display:inline-block}
.sw--base{border:1px dashed var(--faint)}
.sw--new{background:var(--ink)}
/* --- Review mock: a live schedule you can query --- */
.peek__tools{display:flex;align-items:center;gap:7px;margin-bottom:14px;flex-wrap:wrap}
.pk__search{
  display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line-2);border-radius:5px;
  padding:5px 9px;font-family:var(--mono);font-size:.62rem;color:var(--soft);background:var(--card);flex:1;min-width:96px;
}
.pk__search b{color:var(--mute);font-weight:400}
.pk__chip{border:1px solid var(--line-2);border-radius:999px;padding:4px 10px;font-family:var(--mono);font-size:.58rem;color:var(--soft)}
.pk__chip--on{background:var(--ink);border-color:var(--ink);color:var(--on-ink)}
.pk__zoom{font-family:var(--mono);font-size:.58rem;color:var(--mute);border:1px solid var(--line);border-radius:5px;padding:4px 8px}
.peek__row--mine .peek__t{color:var(--ink);font-weight:500}
.peek__row--mine .peek__bar::after{background:var(--green)}
.peek__chat{margin-top:16px;padding-top:14px;border-top:1px solid var(--line);display:grid;gap:8px;justify-items:start}
.pk__q{
  justify-self:end;background:var(--ink);color:var(--on-ink);border-radius:12px 12px 3px 12px;
  padding:8px 12px;font-size:.72rem;max-width:80%;
}
.pk__a{
  background:var(--bg-soft);border:1px solid var(--line);border-radius:12px 12px 12px 3px;
  padding:9px 12px;font-size:.72rem;color:var(--soft);max-width:88%;
}
.pk__file{
  display:inline-flex;align-items:center;gap:7px;margin-top:8px;background:var(--card);
  border:1px solid var(--line-2);border-radius:6px;padding:6px 9px;
  font-family:var(--mono);font-size:.62rem;color:var(--ink);
}
.pk__file b{background:var(--green);color:var(--on-green);border-radius:3px;padding:1px 4px;font-size:.52rem;font-weight:500}
.pk__hi{color:var(--ink);font-weight:600}

/* --- Compare mock: the resource heat map --- */
/* GC panels: the generate prompt and the DCMA check board */
.pk__prompt{
  font-family:var(--mono);font-size:.74rem;line-height:1.5;color:var(--soft);
  background:var(--bg-soft);border:1px solid var(--line);border-left:2px solid var(--green);
  border-radius:6px;padding:10px 12px;margin-bottom:12px}
.pk__checks{
  display:grid;grid-template-columns:1fr;gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:8px;overflow:hidden}
.pk__check{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  background:var(--card);padding:7px 11px}
.pk__check span{font-size:.76rem;color:var(--soft)}
.pk__check b{font-family:var(--mono);font-size:.6rem;letter-spacing:.08em;color:var(--green-d)}
.pk__check--warn b{color:#b06a00}

.peek__heat{margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.pk__heatlab{font-family:var(--mono);font-size:.58rem;letter-spacing:.08em;text-transform:uppercase;color:var(--mute)}
.pk__heatgrid{display:grid;grid-template-columns:repeat(8,1fr);gap:4px;margin-top:8px}
.pk__heatgrid i{
  height:24px;border-radius:3px;display:grid;place-items:center;
  font-family:var(--mono);font-size:.62rem;font-style:normal;font-weight:500;
  background:color-mix(in srgb,var(--green) calc(var(--v) * 100%),#eef1ef);
  color:var(--ink);
}

.peek__flags{display:grid;gap:7px;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.flag{
  display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:.68rem;color:var(--ink);
  border:1px solid var(--line-2);border-radius:5px;padding:6px 9px;background:var(--card);justify-self:start;
  opacity:0;animation:flagIn .5s var(--ease) forwards;
}
.flag b{width:14px;height:14px;border-radius:3px;background:var(--amber);color:#fff;display:grid;place-items:center;font-size:.6rem}
.flag--1{animation-delay:.5s}.flag--2{animation-delay:.9s}.flag--3{animation-delay:1.3s}
@keyframes flagIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.peek__deltas{display:flex;gap:8px;flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.delta{font-family:var(--mono);font-size:.68rem;color:var(--ink);border:1px solid var(--line-2);border-radius:5px;padding:6px 9px;background:var(--card)}
.delta--late{color:var(--red);border-color:rgba(192,57,43,.35)}

/* ============================================================
   Website agent, mirrors the in-app chatbot (fixed bottom-right
   card, collapsible header, bot/user bubble shapes, input + send)
   restyled to the Minimal Mono palette.
   ============================================================ */
.gachat{
  position:fixed;right:20px;bottom:20px;z-index:9999;font-family:var(--body);
  transition:transform .28s var(--ease);
}
/* steps up out of the way once the footer bar is on screen */
.gachat.is-lifted{transform:translateY(-74px)}

/* launcher */
.gachat__launch{
  display:inline-flex;align-items:center;gap:10px;background:var(--ink);color:var(--on-ink);border:0;cursor:pointer;
  padding:13px 18px;border-radius:999px;font-family:var(--body);font-weight:600;font-size:.92rem;
  box-shadow:0 14px 30px -12px rgba(10,11,10,.55);transition:transform .18s var(--ease),background .18s;
}
.gachat__launch:hover{transform:translateY(-2px);background:var(--ink-h)}
.gachat__launch svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.gachat__dot{
  width:7px;height:7px;border-radius:50%;background:var(--green);flex:none;
  position:relative;animation:gaPulse 2.2s var(--ease) infinite;
}
/* the ring that breathes outward, so it reads as "someone is here" */
.gachat__dot::after{
  content:"";position:absolute;inset:0;border-radius:50%;background:var(--green);
  animation:gaRing 2.2s var(--ease) infinite;
}
@keyframes gaPulse{
  0%,100%{box-shadow:0 0 0 3px rgba(15,138,95,.25)}
  50%{box-shadow:0 0 0 4px rgba(15,138,95,.4)}
}
@keyframes gaRing{
  0%{transform:scale(1);opacity:.55}
  70%{transform:scale(3.2);opacity:0}
  100%{transform:scale(3.2);opacity:0}
}
.gachat.is-open .gachat__launch{opacity:0;pointer-events:none;transform:scale(.9)}

/* panel */
.gachat__panel{
  position:absolute;right:0;bottom:0;width:370px;max-width:calc(100vw - 40px);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;
  box-shadow:0 26px 60px -24px rgba(10,11,10,.4);
  display:flex;flex-direction:column;
  opacity:0;transform:translateY(12px) scale(.98);pointer-events:none;
  transition:opacity .22s var(--ease),transform .22s var(--ease);
}
.gachat__panel.is-open{opacity:1;transform:none;pointer-events:auto}
.gachat__head{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:12px 14px;border-bottom:1px solid var(--line);background:var(--card);
}
.gachat__id{display:flex;align-items:center;gap:10px}
/* The mark itself, not a green blob standing in for it. */
.gachat__av{
  width:30px;height:30px;border-radius:50%;flex:none;
  object-fit:contain;background:var(--bg-soft);padding:4px;
}
.gachat__id b{display:block;font-family:var(--disp);font-size:.98rem;color:var(--ink);letter-spacing:-.02em;line-height:1.2}
.gachat__id em{font-style:normal;font-family:var(--mono);font-size:.64rem;letter-spacing:.06em;text-transform:uppercase;color:var(--mute)}
.gachat__arrow{
  width:30px;height:30px;border-radius:50%;border:0;cursor:pointer;background:var(--green);color:var(--on-green);
  display:grid;place-items:center;transition:background .16s;
}
.gachat__arrow:hover{background:var(--green-d)}
.gachat__arrow svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

.gachat__body{height:44vh;max-height:400px;min-height:260px;overflow-y:auto;padding:14px;background:var(--bg-soft)}
.gam{padding:10px 13px;font-size:.9rem;line-height:1.55;margin:0 0 10px;word-wrap:break-word;max-width:90%}
.gam b{font-weight:600}
.gam--bot{background:var(--green);color:var(--on-green);border-radius:2px 14px 14px 14px}
.gam--bot b{color:var(--on-green)}
.gam--user{background:var(--card);color:var(--ink);border:1px solid var(--line-2);border-radius:14px 14px 2px 14px;max-width:82%;margin-left:auto}
.gam--typing{display:inline-flex;gap:5px;align-items:center;padding:12px 14px}
.gam--typing i{width:6px;height:6px;border-radius:50%;background:rgba(255,255,255,.85);animation:gaBlink 1s infinite}
.gam--typing i:nth-child(2){animation-delay:.15s}
.gam--typing i:nth-child(3){animation-delay:.3s}
@keyframes gaBlink{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
.gacta{
  display:inline-block;margin-top:10px;background:var(--card);color:var(--green);border-radius:6px;
  padding:7px 11px;font-size:.8rem;font-weight:600;
}
.gacta:hover{background:var(--green-t)}

.gachat__chips{display:flex;gap:7px;flex-wrap:wrap;padding:0 14px 4px;background:var(--bg-soft)}
/* How many questions are left is state, not something the assistant said, so
   it sits above the conversation as a strip rather than inside it as a bubble.
   As a bubble it was green and centred and read like an answer. */
.gachat__warn{
  margin:0;padding:9px 14px;background:var(--bg-soft);border-bottom:1px solid var(--line);
  font-family:var(--mono);font-size:.63rem;letter-spacing:.04em;color:var(--mute);
  display:flex;align-items:center;gap:8px;
}
.gachat__warn::before{
  content:"";flex:none;width:6px;height:6px;border-radius:50%;background:var(--green);
}

/* Spent its questions: the field stays visible so the panel does not appear
   broken, but it cannot be typed into and the hand-off is the last word. */
.gachat__input.is-done{opacity:.55}
.gachat__input.is-done input{cursor:not-allowed}
.gachip{
  font-family:var(--body);font-size:.78rem;color:var(--ink);background:var(--card);border:1px solid var(--line-2);
  border-radius:999px;padding:7px 12px;cursor:pointer;transition:border-color .16s,background .16s;
}
.gachip:hover{border-color:var(--green);background:var(--green-t)}

.gachat__input{display:flex;gap:6px;padding:10px;border-top:1px solid var(--line);background:var(--card)}
.gachat__input input{
  flex:1;border:1px solid var(--line-2);border-radius:6px;padding:10px 12px;
  font-family:var(--body);font-size:.9rem;color:var(--ink);background:var(--card);
}
.gachat__input input:focus{outline:none;border-color:var(--green)}
.gachat__send{
  width:40px;height:40px;border-radius:6px;border:0;background:var(--green);color:var(--on-green);cursor:pointer;
  display:grid;place-items:center;transition:background .16s;flex:none;
}
.gachat__send:hover{background:var(--green-d)}
.gachat__send svg{width:18px;height:18px;fill:currentColor;stroke:none}
.gachat__foot{padding:0 14px 12px;font-family:var(--mono);font-size:.63rem;color:var(--mute);background:var(--card);text-align:center}

@media(max-width:520px){
  .gachat{right:14px;bottom:14px}
  .gachat__panel{width:calc(100vw - 28px)}
  .gachat__launchtxt{display:none}
  .gachat__launch{padding:14px}
}
@media(prefers-reduced-motion:reduce){
  .gachat__panel,.gachat__launch{transition:none}
  .gam--typing i{animation:none}
}

/* ============================================================
   Book-a-demo modal, one page: who you are on the left, live
   availability on the right, one black book button at the bottom.
   ============================================================ */
.dm{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:16px;font-family:var(--body)}
.dm[hidden]{display:none}
.dm__scrim{position:absolute;inset:0;background:rgba(10,11,10,.55);backdrop-filter:blur(3px);animation:dmFade .2s var(--ease)}
@keyframes dmFade{from{opacity:0}to{opacity:1}}
.dm__card{
  position:relative;background:var(--card);border-radius:var(--r-lg);width:100%;max-width:1040px;
  height:min(760px,calc(100vh - 32px));height:min(760px,calc(100dvh - 32px));
  display:flex;flex-direction:column;overflow:hidden;
  box-shadow:0 40px 90px -30px rgba(10,11,10,.6);animation:dmIn .28s var(--ease) both;
}
@keyframes dmIn{from{opacity:0;transform:translateY(16px) scale(.985)}to{opacity:1;transform:none}}
.dm__x{
  position:absolute;top:12px;right:12px;width:30px;height:30px;border:0;background:transparent;
  color:var(--mute);cursor:pointer;border-radius:6px;font-size:20px;line-height:1;z-index:2;
}
.dm__x:hover{background:var(--bg-soft);color:var(--ink)}

.dm__grid{flex:1;min-height:0;display:grid;grid-template-columns:minmax(330px,410px) 1fr}
.dm__right{display:flex;flex-direction:column;min-height:0;min-width:0;padding:18px 22px 20px}

/* the case for the call, across the whole width, so the form and the
   calendar below it start and end at the same height */
.dm__head{
  flex:none;display:flex;align-items:center;gap:34px;padding:20px 26px;
  background:var(--bg-soft);border-bottom:1px solid var(--line);
}
.dm__headl{flex:1;min-width:0;padding-right:34px}
.dm__head h3{font-size:1.24rem;font-weight:800;letter-spacing:-.03em;margin:7px 0 8px;line-height:1.2}
.dm__stats{display:flex;flex:none;width:min(50%,430px)}
.dm__stats div{flex:1;border:0;border-left:1px solid var(--line-2);padding:2px 12px;text-align:left}
.dm__stats div:first-child{border-left:0;padding-left:0}
.dm__stats b{display:block;font-family:var(--disp);font-size:1.34rem;font-weight:800;color:var(--ink);letter-spacing:-.03em;line-height:1.1}
.dm__stats b i{font-style:normal;font-size:.62em;color:var(--green);margin-left:3px;letter-spacing:-.01em}
.dm__stats span{display:block;font-family:var(--mono);font-size:.56rem;text-transform:uppercase;letter-spacing:.04em;color:var(--mute);margin-top:4px;line-height:1.35}
.dm__hook{font-size:.85rem;line-height:1.5;color:var(--soft);margin:0;max-width:62ch}
.dm__hook b{color:var(--ink);font-weight:600}

.dm__form{
  min-height:0;min-width:0;display:flex;flex-direction:column;padding:20px 24px;background:var(--card);
  border-right:1px solid var(--line);overflow:visible;
}
.dm__lab{display:block;font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;color:var(--soft);margin-bottom:8px}
.dm__in{
  width:100%;border:1px solid var(--line-2);border-radius:var(--r);padding:10px 13px;
  font-family:var(--body);font-size:.94rem;color:var(--ink);background:var(--card);
}
.dm__in:focus{outline:none;border-color:var(--ink)}
.dm__in::placeholder{color:var(--faint)}
textarea.dm__in{resize:none;height:92px;line-height:1.45}
.dm__field{margin-bottom:16px;flex:none;min-width:0}
.dm__field:last-child{margin-bottom:0}
.dm__field[hidden]{display:none}
.dm__reassure{margin-top:auto;padding-top:16px;border-top:1px solid var(--line);font-size:.86rem;color:var(--mute)}
/* multi-select: trigger + inline checkbox list (in flow, so nothing clips it) */
.dm__ms{position:relative}
.dm__msbtn{
  display:flex;align-items:center;justify-content:space-between;gap:10px;text-align:left;
  cursor:pointer;color:var(--faint);padding-right:36px;
}
.dm__msbtn.on{color:var(--ink)}
.dm__msbtn::after{
  content:"";position:absolute;right:14px;top:18px;width:8px;height:8px;pointer-events:none;
  border-right:1.5px solid var(--soft);border-bottom:1.5px solid var(--soft);
  transform:translateY(-70%) rotate(45deg);transition:transform .18s var(--ease);
}
.dm__msbtn.open::after{transform:translateY(-20%) rotate(-135deg)}
.dm__msbtn.open{border-color:var(--ink)}
.dm__msbtn span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dm__msmenu{
  position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:5;
  border:1px solid var(--line-2);border-radius:var(--r);background:var(--card);
  overflow-y:auto;padding:5px;
  box-shadow:0 18px 38px -14px rgba(10,11,10,.28);
}
.dm__msmenu[hidden]{display:none}
.dm__msopt{
  display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:6px;cursor:pointer;
  font-size:.88rem;color:var(--ink);line-height:1.3;
}
.dm__msopt:hover{background:var(--bg-soft)}
.dm__msopt.on{background:var(--green-t)}
.dm__msopt input{accent-color:var(--green-d);width:15px;height:15px;flex:none;cursor:pointer}

/* the calendar column */
.dm__calhead{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex:none;padding-right:34px}
.dm__calhead .dm__lab{margin-bottom:10px}
.dm__sync{font-family:var(--mono);font-size:.62rem;letter-spacing:.06em;color:var(--green-d);white-space:nowrap}
.dm__cal{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;flex:1;min-height:0;background:var(--bg-soft)}
.dm__cal iframe{display:block;border:0;width:100%;height:100%}
/* Free-plan colour fallback, see TINT_WITHOUT_PAID_PLAN in js/demo.js.
   Solved so Calendly's #0069ff lands on #008a5f, a shade off our #0f8a5f.
   hue-rotate and saturate matrices have rows summing to 1, so white, black
   and every grey come through untouched. */
.dm__cal.tint iframe{filter:hue-rotate(-59.5deg) saturate(.8)}
.dm__cal.nudge{border-color:var(--green);box-shadow:0 0 0 3px var(--green-t)}
.dm__cal{transition:border-color .25s var(--ease),box-shadow .25s var(--ease)}
.dm__foot.done .dm__note{color:var(--green-d);font-weight:500}
.dm__fallback{padding:28px 24px;text-align:center;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center}
.dm__fallback h4{font-size:1.05rem;margin-bottom:8px}
.dm__fallback p{font-size:.9rem;color:var(--soft);margin:0 0 18px;max-width:36ch}

.dm__foot{
  display:flex;align-items:center;justify-content:space-between;gap:16px;flex:none;
  padding:13px 22px;border-top:1px solid var(--line);background:var(--card);
}
.dm__note{font-family:var(--mono);font-size:.66rem;letter-spacing:.04em;color:var(--mute)}
.dm__foot .btn{min-width:180px;text-align:center}

/* ---------- "We'll do it for you", two schedules in, report back ---------- */
.fc__card{max-width:720px;height:auto;max-height:calc(100dvh - 32px)}
.fc .dm__head{display:block}
.fc__body{padding:20px 26px;display:grid;gap:14px;overflow:auto}
.fc__row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.fc__drop{
  position:relative;border:1px dashed var(--line-2);border-radius:var(--r);padding:16px 14px;
  background:var(--bg-soft);text-align:center;cursor:pointer;transition:.16s var(--ease);
}
.fc__drop input{position:absolute;inset:0;opacity:0;cursor:pointer;width:100%;height:100%}
.fc__drop:hover,.fc__drop.over{border-color:var(--ink);background:var(--card)}
.fc__drop.has{border-style:solid;border-color:var(--green);background:var(--green-t)}
.fc__n{
  display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;
  border:1px solid var(--line-2);background:var(--card);font-family:var(--mono);font-size:.6rem;color:var(--ink);
}
.fc__drop b{display:block;margin-top:8px;font-size:.94rem;color:var(--ink)}
.fc__hint{display:block;font-size:.8rem;color:var(--mute);margin-top:2px}
.fc__file{display:block;font-family:var(--mono);font-size:.66rem;color:var(--green-d);margin-top:7px;word-break:break-all}
.fc__err{color:var(--red);font-size:.86rem;margin:0}
.fc__done{text-align:center;padding:26px 10px}
.fc__tick{
  display:inline-grid;place-items:center;width:42px;height:42px;border-radius:50%;
  background:var(--green);color:var(--on-green);font-size:1.2rem;margin-bottom:12px;
}
.fc__done h4{font-size:1.15rem;margin-bottom:6px}
.fc__done p{color:var(--soft);font-size:.94rem;max-width:44ch;margin:0 auto}
@media(max-width:640px){
  .fc__row{grid-template-columns:1fr}
  .fc__card{height:100dvh;max-height:none}
}

body.dm-open{overflow:hidden}

/* short viewports: shed the decorative rows before anything can overflow */
@media(max-height:800px){
  .dm__hook{display:none}          /* metrics stay, the prose goes first */
  .dm__form{padding-bottom:16px}
  .dm__field{margin-bottom:12px}
}
@media(max-height:700px){
  .dm__head{padding:15px 26px}
  .dm__head h3{font-size:1.12rem}
  .dm__stats div{padding:7px 5px}
  .dm__stats b{font-size:1.08rem}
  .dm__form{padding:14px 24px}
  .dm__reassure{display:none}
  textarea.dm__in{height:66px}
  .dm__field{margin-bottom:12px}
}
@media(max-height:640px){
  .dm__stats{display:none}
}
@media(max-height:560px){
  .dm .eyebrow{display:none}
  .dm__head h3{font-size:1.04rem}
}

/* one column: form on top, calendar takes the rest */
@media(max-width:860px){
  .dm{padding:0;place-items:stretch}
  .dm__card{max-width:none;border-radius:0;height:100vh;height:100dvh}
  .dm__grid{grid-template-columns:1fr;grid-template-rows:auto 1fr}
  .dm__form{border-right:0}
  .dm__right{padding:14px 20px 16px}
  .dm__head{display:block;padding:16px 20px 14px}
  .dm__head h3{font-size:1.1rem}
  .dm__stats{width:100%;margin-top:12px}
  .dm__stats div{padding:7px 4px}
  .dm__stats b{font-size:1.05rem}
  .dm__stats span{font-size:.5rem}
  .dm__hook{display:none}
  .dm__form{padding:12px 20px}
  .dm__reassure{display:none}
  .dm__field{margin-bottom:10px}
  textarea.dm__in{height:60px}
  .dm__cal{min-height:250px}
  .dm__foot{padding:11px 20px;gap:10px}
  .dm__note{display:none}
  .dm__foot .btn{min-width:0;flex:1}
}
@media(max-width:860px) and (max-height:720px){
  .dm__stats{display:none}
  .dm__head{padding:13px 20px 11px}
  .dm__form{padding:12px 20px}
  .dm__field{margin-bottom:9px}
  .dm__lab{margin-bottom:5px}
  textarea.dm__in{height:44px}
  .dm__cal{min-height:190px}
}

/* ============================================================
   Decorative construction line-art, one fixed layer behind the
   whole site. Brand-green, very low contrast, and masked clear of
   the text column so it never competes with the copy.

   One ink, one weight, one strength, on all four pages and over
   both backgrounds. Every scene is a single-colour wireframe: no
   part of any machine is picked out in a stronger green, because
   the pages sit next to each other in a nav and any drawing that
   pulls harder than the others reads as a different site. The
   two places the numbers differ, the light-ink copy inside the
   black bands and the whole of the dark-theme GC page, are
   matched by eye-contrast rather than by literal value, see the
   note on .scene--invert.
   ============================================================ */
.scene--fixed{
  position:fixed;inset:0;z-index:0;pointer-events:none;
  color:var(--green);opacity:.075;
}
.scene--fixed svg{position:absolute;right:-3%;bottom:0;height:97%;width:auto;max-width:none}
.scene--crane{
  -webkit-mask-image:linear-gradient(95deg,transparent 0%,transparent 30%,rgba(0,0,0,.35) 46%,rgba(0,0,0,.8) 62%,#000 76%);
          mask-image:linear-gradient(95deg,transparent 0%,transparent 30%,rgba(0,0,0,.35) 46%,rgba(0,0,0,.8) 62%,#000 76%);
}

/* Scenes drawn as options and kept, on no page at present. The frame is an
   elevation like the crane, so it fades the same way; the plan fills the width
   and fades from the left instead, since a drawing cropped down one side reads
   as a drawing, not as a mistake. */
.scene--frame{
  -webkit-mask-image:linear-gradient(95deg,transparent 0%,transparent 26%,rgba(0,0,0,.35) 44%,rgba(0,0,0,.8) 60%,#000 74%);
          mask-image:linear-gradient(95deg,transparent 0%,transparent 26%,rgba(0,0,0,.35) 44%,rgba(0,0,0,.8) 60%,#000 74%);
}
.scene--plan{
  -webkit-mask-image:linear-gradient(90deg,transparent 0%,rgba(0,0,0,.3) 28%,rgba(0,0,0,.75) 52%,#000 72%);
          mask-image:linear-gradient(90deg,transparent 0%,rgba(0,0,0,.3) 28%,rgba(0,0,0,.75) 52%,#000 72%);
}

/* The excavator sits low and works to the left, so it fades from the left
   like the crane does and keeps its full height: cropping the tracks would
   leave the arm floating. Also on no page at present. */
.scene--excav{
  -webkit-mask-image:linear-gradient(95deg,transparent 0%,transparent 18%,rgba(0,0,0,.35) 38%,rgba(0,0,0,.8) 56%,#000 72%);
          mask-image:linear-gradient(95deg,transparent 0%,transparent 18%,rgba(0,0,0,.35) 38%,rgba(0,0,0,.8) 56%,#000 72%);
}
/* the barrel is the heavy part of a ram, the rod the thin one: a weight
   difference, not a colour one */
.scene--excav .exRamBb,.scene--excav .exRamSb,.scene--excav .exRamKb{stroke-width:3.4;opacity:.9}

/* The tipper is the crane's twin: same fade across the same angle, same single
   weight of line, no part of it picked out in a stronger colour, so home reads
   as one drawing and sits at the same distance behind the copy as the crane
   does on the subcontractors page. */
.scene--tipper{
  -webkit-mask-image:linear-gradient(95deg,transparent 0%,transparent 24%,rgba(0,0,0,.35) 42%,rgba(0,0,0,.8) 60%,#000 74%);
          mask-image:linear-gradient(95deg,transparent 0%,transparent 24%,rgba(0,0,0,.35) 42%,rgba(0,0,0,.8) 60%,#000 74%);
}
/* Pulled in from the right edge, and lifted off the foot of the viewport far
   enough that the whole machine sits inside the white headline band at the top
   of the page. This 22% is only the value before scenery.js runs: the band's
   depth is set by its copy, not by the window, so a percentage of the viewport
   can only be right at one window height. floorToBand() measures the seam and
   overwrites `bottom` in px. See the note there. */
.scene--tipper svg{right:9%;bottom:22%;height:80%}

/* the spool is wider and more central than the crane, so the fade starts
   further left */
.scene--spool{
  -webkit-mask-image:linear-gradient(95deg,transparent 0%,transparent 12%,rgba(0,0,0,.3) 30%,rgba(0,0,0,.75) 50%,#000 68%);
          mask-image:linear-gradient(95deg,transparent 0%,transparent 12%,rgba(0,0,0,.3) 30%,rgba(0,0,0,.75) 50%,#000 68%);
}

@media(max-width:960px){
  .scene--fixed svg{right:-20%;height:88%}
}
@media(max-width:700px){
  .scene--fixed{opacity:.06}
  .scene--fixed svg{right:-46%;height:74%}
  .scene--crane{
    -webkit-mask-image:linear-gradient(100deg,transparent 0%,transparent 22%,rgba(0,0,0,.6) 46%,#000 68%);
            mask-image:linear-gradient(100deg,transparent 0%,transparent 22%,rgba(0,0,0,.6) 46%,#000 68%);
  }
}


/* ============================================================
   Inverted band, the GC generate pipeline.
   The stylesheet is token-driven, so the section rescopes the
   palette and everything inside follows. Only the handful of
   rules that hardcode white need an explicit flip.
   ============================================================ */
.sec--dark{
  --bg:#0a0b0a;      --bg-soft:#151917;
  --ink:#f6f8f7;     --ink-2:#e4e9e7;
  --soft:#bcc4c1;    --mute:#949c99;   --faint:#767e7b;
  --line:#272d2b;    --line-2:#3b4441;
  --green:#3ecf8e;   --green-d:#3ecf8e; --green-t:#12241c;
  --card:#101413;  --on-ink:#0a0b0a;  --wash:rgba(255,255,255,.03);
  --track:rgba(255,255,255,.08);
  background:#0a0b0a;color:var(--soft);border-bottom-color:#0a0b0a;
}
.sec--dark h1,.sec--dark h2,.sec--dark h3,.sec--dark h4{color:var(--ink)}
.sec--dark .btn-primary{background:#f6f8f7;color:#0a0b0a}
/* Hovering used to hand this button the card colour, which on a dark band is
   very nearly the background: the button appeared to vanish under the cursor.
   It goes green instead, so the response is a change of colour, not of
   presence. */
.sec--dark .btn-primary:hover{background:var(--green);color:#07130d}
.sec--dark .btn-ghost{background:transparent;color:var(--ink);border-color:var(--line-2)}
.sec--dark .btn-ghost:hover{border-color:var(--ink)}
.sec--dark .peek__bar{background:rgba(255,255,255,.07)}
.sec--dark .pk__check{background:#131715}
.sec--dark .pk__q{background:#f6f8f7;color:#0a0b0a}
.sec--dark .pk__a{background:#131715;border-color:var(--line)}
.sec--dark .pk__file{background:#0a0b0a;border-color:var(--line-2);color:var(--soft)}
.sec--dark .pk__file b{background:var(--green);color:#0a0b0a}
.sec--dark .delta{background:#131715;border-color:var(--line-2);color:var(--soft)}
.sec--dark .step__n{background:#131715;border-color:var(--line-2);color:var(--ink)}

/* ---- the pipeline: one input, three outputs ---- */
.gen{margin-top:8px}
.gen__in{border:1px solid var(--line-2);border-radius:var(--r-lg);background:#101413;padding:20px 22px 18px}
.gen__inbar{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:14px}
.gen__lab{font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--green)}
.gen__chips{display:flex;gap:6px;flex-wrap:wrap}
.gen__chips i{
  font-style:normal;font-family:var(--mono);font-size:.66rem;color:var(--mute);
  border:1px solid var(--line-2);border-radius:999px;padding:3px 9px}
.gen__prompt{
  font-family:var(--mono);font-size:.92rem;line-height:1.6;color:var(--ink);
  border-left:2px solid var(--green);padding:2px 0 2px 14px}
.gen__caret{display:inline-block;width:8px;height:1.05em;background:var(--green);
  vertical-align:-2px;margin-left:4px;animation:genCaret 1.1s steps(1) infinite}
@keyframes genCaret{0%,49%{opacity:1}50%,100%{opacity:0}}
.gen__go{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:16px;
  border-top:1px solid var(--line);padding-top:14px}
.gen__btn{
  font:600 .82rem/1 var(--body);border:1px solid var(--green);
  background:var(--green);color:var(--on-green);
  border-radius:var(--r);padding:9px 18px}
.gen__meta{font-family:var(--mono);font-size:.72rem;color:var(--mute)}

/* the manifold: stem down, split, three drops */
.gen__pipe{display:grid;grid-template-columns:repeat(3,1fr);height:42px;position:relative}
.gen__pipe::before{content:"";position:absolute;left:16.667%;right:16.667%;top:21px;height:1px;background:var(--line-2)}
.gen__pipe::after{content:"";position:absolute;left:50%;top:0;width:1px;height:21px;background:var(--line-2)}
.gen__pipe i{position:relative}
.gen__pipe i::after{content:"";position:absolute;left:50%;top:21px;width:1px;height:21px;background:var(--line-2)}

.gen__out{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.gen__card{
  border:1px solid var(--line-2);border-radius:var(--r-lg);background:#101413;
  padding:16px 16px 18px;display:flex;flex-direction:column}
.gen__ct{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding-bottom:11px;margin-bottom:13px;border-bottom:1px solid var(--line)}
.gen__ct b{font-family:var(--disp);font-size:1rem;color:var(--ink);letter-spacing:-.01em}
.gen__ct span{font-family:var(--mono);font-size:.66rem;color:var(--mute)}
.gen__card .peek__rows{flex:1;align-content:space-between}   /* 14 bars fill the card, like the 14 checks beside them */
.gen__card .peek__row{grid-template-columns:92px 1fr;gap:8px}
.gen__card .peek__t{font-size:.68rem}
.gen__card .pk__checks{border-color:var(--line-2)}
.gen__card .peek__chat{display:grid;gap:8px;margin-top:0;padding-top:0;border-top:0}
.gen__deltas{display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;padding-top:14px}

.steps--4{grid-template-columns:repeat(4,1fr);gap:26px;margin-top:52px}

@media(max-width:960px){
  .gen__out{grid-template-columns:1fr;gap:14px}
  .gen__pipe{grid-template-columns:1fr;height:26px}
  .gen__pipe::before{display:none}
  .gen__pipe i:not(:first-child)::after{display:none}
  .gen__pipe i::after{top:0;height:26px}
  .steps--4{grid-template-columns:1fr 1fr;gap:22px}
}
@media(max-width:560px){ .steps--4{grid-template-columns:1fr} }


/* ============================================================
   Dark theme. Only the palette changes: every rule above already
   speaks in tokens, so nothing here needs to restate layout.
   Set on <html data-theme="dark"> before first paint.
   ============================================================ */
:root[data-theme="dark"]{
  --bg:#0a0b0a;
  --bg-soft:#121514;
  --ink:#f6f8f7;
  --ink-2:#e4e9e7;
  --soft:#bcc4c1;
  --mute:#949c99;
  --faint:#767e7b;
  --line:#252b29;
  --line-2:#3a4340;

  --green:#3ecf8e;
  --green-d:#5bd9a0;
  --green-t:#12241c;

  --amber:#e0a34a;
  --red:#e0685c;

  --card:#101413;
  --on-ink:#0a0b0a;
  --on-green:#06231a;
  --ink-h:#ffffff;
  --wash:rgba(255,255,255,.028);
  --track:rgba(255,255,255,.07);
  --bar:rgba(10,11,10,.82);
  --paper:#ffffff;
}
:root[data-theme="dark"] body{color:var(--soft)}
/* Dark theme resolves --green to #3ecf8e already, so the GC page only needs
   the alpha to match the light-ink band copy on the other three. See the note
   on .scene--invert for where .08 comes from. */
:root[data-theme="dark"] .scene--fixed{opacity:.08}
@media(max-width:700px){
  :root[data-theme="dark"] .scene--fixed{opacity:.06}
}

/* The GC band is already the inverted one. In dark it would vanish, so it
   drops its overrides and reads as a raised panel instead. */
:root[data-theme="dark"] .sec--dark{
  --bg:#0a0b0a; --bg-soft:#121514; --ink:#f6f8f7; --soft:#bcc4c1;
  --mute:#949c99; --faint:#767e7b; --line:#252b29; --line-2:#3a4340;
  --green:#3ecf8e; --green-d:#5bd9a0;
  background:rgba(255,255,255,.022);border-bottom-color:var(--line);
}
:root[data-theme="dark"] .sec--dark .btn-primary{background:var(--ink);color:var(--on-ink)}
:root[data-theme="dark"] .sec--dark .pk__check{background:var(--card)}
:root[data-theme="dark"] .sec--dark .pk__a{background:var(--card)}
:root[data-theme="dark"] .sec--dark .pk__q{background:var(--ink);color:var(--on-ink)}

/* The hero art is a printed page, not UI. Paper stays paper, and the ink on
   it stays dark, or the whole "they sent you a PDF" idea falls apart. */
:root[data-theme="dark"] .messy{color:#0a0b0a}
:root[data-theme="dark"] .messy svg{box-shadow:0 30px 70px -30px rgba(0,0,0,.85)}

/* ---- the switch ---- */
.nav__theme{
  width:34px;height:34px;flex:none;display:grid;place-items:center;cursor:pointer;
  background:transparent;border:1px solid var(--line-2);border-radius:8px;color:var(--soft);
  transition:color .18s var(--ease),border-color .18s var(--ease)}
.nav__theme:hover{color:var(--ink);border-color:var(--ink)}
.nav__theme svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.nav__theme .i-sun{display:none}
:root[data-theme="dark"] .nav__theme .i-sun{display:block}
:root[data-theme="dark"] .nav__theme .i-moon{display:none}
@media(max-width:860px){ .nav__theme{margin-left:0;margin-right:4px} }


/* ============================================================
   GC hero: the generate card. Assets in, brief typed, schedule
   drawn with its logic links. The brief is a real field.
   ============================================================ */
.gen2 .mock__bar{gap:6px}
.gen2__health{
  margin-left:auto;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  font-family:var(--mono);font-size:.64rem;letter-spacing:.04em;color:var(--mute);
  opacity:0;transform:translateY(-3px);transition:opacity .35s var(--ease),transform .35s var(--ease)}
.gen2__health.is-on{opacity:1;transform:none}
.gen2__health b{color:var(--green);font-size:.78rem;line-height:1}
.gen2__health em{font-style:normal;color:var(--green);font-weight:600}

.gen2__lab{
  display:block;font-family:var(--mono);font-size:.62rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--faint);margin:0 0 9px}
.gen2__lab + .gen2__lab,.gen2__assets + .gen2__lab{margin-top:16px}

.gen2__assets{display:flex;flex-wrap:wrap;gap:7px}
.gen2 .ast{
  display:inline-flex;align-items:center;gap:7px;padding:6px 10px;border-radius:6px;
  border:1px dashed var(--line-2);color:var(--mute);font-size:.72rem;
  opacity:.45;transition:opacity .3s var(--ease),border-color .3s var(--ease),color .3s var(--ease)}
.gen2 .ast.is-on{opacity:1;border-style:solid;border-color:var(--green);color:var(--ink)}
.gen2 .ast svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;color:var(--green);flex:none}
.gen2 .ast b{font-family:var(--mono);font-size:.6rem;color:var(--faint);font-weight:400}

.gen2__in{
  width:100%;display:block;resize:none;overflow:hidden;
  border:1px solid var(--line-2);border-radius:var(--r);padding:11px 12px;
  font-family:var(--mono);font-size:.76rem;line-height:1.6;color:var(--ink);
  background:var(--bg-soft);transition:border-color .2s var(--ease)}
.gen2__in:focus{outline:none;border-color:var(--green)}
.gen2.is-typing .gen2__in{border-color:var(--green)}

.gen2__go{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:12px}
.gen2__btn{
  font:600 .82rem/1 var(--body);cursor:pointer;border:1px solid var(--line-2);
  background:var(--card);color:var(--ink);border-radius:var(--r);padding:9px 18px;
  transition:background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease)}
.gen2__btn.is-ready{background:var(--green);border-color:var(--green);color:var(--on-green)}
.gen2__btn.is-ready:hover{background:var(--green-d);border-color:var(--green-d)}
.gen2__meta{font-family:var(--mono);font-size:.68rem;color:var(--mute)}
.gen2__meta b{color:var(--ink);font-weight:500;font-variant-numeric:tabular-nums}
.gen2__meta span{color:var(--line-2)}

.gen2__sched{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
.gen2__sched svg{width:100%;height:auto;display:block}
.gsT{font-family:var(--body);font-size:9.5px;fill:var(--soft)}
.gsTrack{fill:var(--track)}
.gsBar{fill:var(--ink);transform-box:fill-box;transform-origin:left center;
  animation:gsGrow .5s var(--ease) both}
.gsBar.is-end{fill:var(--green)}
.gsLink{fill:none;stroke:var(--line-2);stroke-width:1;
  stroke-dasharray:220;stroke-dashoffset:220;animation:gsDraw .55s var(--ease) forwards}
.gsLink.is-2{stroke-dasharray:2 3;animation:none;stroke-dashoffset:0;opacity:.5}
@keyframes gsGrow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes gsDraw{to{stroke-dashoffset:0}}

@media(prefers-reduced-motion:reduce){
  .gsBar,.gsLink{animation:none;transform:none;stroke-dashoffset:0}
}
@media(max-width:900px){
  [data-audience="gc"] .hero__grid{grid-template-columns:1fr}
}


/* ---- pipeline cards: hidden until their turn to load ---- */
.gen__card .gl{opacity:0;transform:translateY(5px)}
.gen__card .gl--in{opacity:1;transform:none;
  transition:opacity .32s var(--ease),transform .32s var(--ease)}
.gen__ct{position:relative}
.gen__card.is-waiting .gen__ct span{opacity:.35}
.gen__card.is-filling .gen__ct span::after{
  content:"";display:inline-block;width:5px;height:5px;border-radius:50%;
  background:var(--green);margin-left:7px;vertical-align:1px;
  animation:glPulse .9s ease-in-out infinite}
@keyframes glPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.7)}}
.gen__card.is-done .gen__ct span{opacity:1}

/* the hero button presses itself on the opening run */
.gen2__btn.is-press{transform:translateY(1px) scale(.97)}
.gen2__btn.is-busy{opacity:.7;pointer-events:none}
.gen2__btn{transition:background .2s var(--ease),color .2s var(--ease),
  border-color .2s var(--ease),transform .12s var(--ease),opacity .2s var(--ease)}
.gsT{animation:gsFade .3s var(--ease) both}
@keyframes gsFade{from{opacity:0}to{opacity:1}}

@media(prefers-reduced-motion:reduce){
  .gen__card .gl{opacity:1;transform:none}
  .gsT{animation:none}
}

/* the card lists what flagged plus a few passes; the rest is a count */
.pk__check--rest span{color:var(--faint);font-style:italic}

/* Dependency links over the pipeline schedule card. The card is captioned
   logic-linked, so the logic has to actually read: --line-2 is a border
   colour and at one pixel on the card's near-black it disappeared. These
   get their own tone, bright enough to follow, still under the bars. */
.peek__wrap{position:relative}
.pk__links{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}
.gen__card{--dep:#7c8a85}
.pk__link{fill:none;stroke:var(--dep,var(--line-2));stroke-width:1;vector-effect:non-scaling-stroke}
.pk__arrow{fill:var(--dep,var(--line-2));stroke:none}

/* which inputs this run actually used */
.gen__chips i{transition:color .25s var(--ease),border-color .25s var(--ease),opacity .25s var(--ease);opacity:.4}
.gen__chips i.is-on{opacity:1;color:var(--ink);border-color:var(--green)}

.gsArrow{fill:var(--line-2);stroke:none;animation:gsFade .3s var(--ease) both}

/* what we can honestly say about who has used it */
.proof{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line)}
.proof__i{padding:26px 24px;border-right:1px solid var(--line);display:flex;flex-direction:column;gap:9px}
.proof__i:last-child{border-right:0}
.proof__k{font-family:var(--disp);font-weight:800;font-size:1.24rem;letter-spacing:-.03em;color:var(--ink)}
.proof__l{font-size:.86rem;line-height:1.55;color:var(--mute)}
.proof__tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:auto;padding-top:11px}
.proof__tags i{font-style:normal;font-family:var(--mono);font-size:.6rem;letter-spacing:.04em;
  color:var(--soft);border:1px solid var(--line-2);border-radius:999px;padding:3px 8px}
@media(max-width:900px){
  .proof{grid-template-columns:1fr 1fr}
  .proof__i:nth-child(2n){border-right:0}
  .proof__i:nth-child(-n+2){border-bottom:1px solid var(--line)}
}
@media(max-width:560px){
  .proof{grid-template-columns:1fr}
  .proof__i{border-right:0;border-bottom:1px solid var(--line)}
  .proof__i:last-child{border-bottom:0}
}

/* ============================================================
   About: the two audience bands. GCs run dark and subs light,
   matching each product page, so the About page reads as a map
   of the site rather than a decorative stripe.
   ============================================================ */
.aud{display:grid;grid-template-columns:1.05fr .95fr;gap:56px;align-items:center}
.aud--flip .aud__art{order:-1}
.aud__copy h2{margin:12px 0 14px}
.aud__copy p{font-size:1.02rem;max-width:52ch}
.aud__list{list-style:none;display:grid;gap:9px;margin:22px 0 28px}
.aud__list li{position:relative;padding-left:22px;font-size:.94rem;color:var(--soft)}
.aud__list li::before{
  content:"";position:absolute;left:0;top:.62em;width:9px;height:1.5px;background:var(--green)}

.aud__art{
  border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);
  padding:20px 22px 18px;display:flex;flex-direction:column;gap:14px}
.aud__lab{font-family:var(--mono);font-size:.66rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--green)}
.aud__bars{display:grid;gap:10px}
.aud__bars i{
  position:relative;display:block;height:10px;border-radius:3px;background:var(--track)}
.aud__bars i::after{
  content:"";position:absolute;top:0;height:10px;border-radius:3px;background:var(--ink);
  left:calc(var(--s) * 1%);width:calc(var(--w) * 1%)}
.aud__bars--mine i::after{background:var(--line-2)}
.aud__bars--mine i.mine::after{background:var(--green)}
.aud__note{font-family:var(--mono);font-size:.68rem;color:var(--mute)}

@media(max-width:860px){
  .aud{grid-template-columns:1fr;gap:32px}
  .aud--flip .aud__art{order:0}
}

/* The light-ink twin of the scene, shown only through the black bands so the
   machine keeps running across the seam instead of disappearing into them. */
/* the black band, lifted onto its own layer so the scene can sit on top of it */
.scene--bandfill{background:#0a0b0a;z-index:-1;opacity:1}
body.has-bandfill .sec--dark{background:transparent}

/* Matched to the light side by contrast, not by value. --green at .075 over
   white lands at 1.10:1; this green at .08 over #0a0b0a lands at 1.11:1, so
   the drawing keeps the same presence crossing the seam instead of flaring.
   White ink at .16, which is what this was, measures 1.53:1, which is why the
   machine used to jump out of the black bands and sit on the copy. The GC page
   is dark end to end and runs the same pair of numbers, below. Change one of
   the three and the pages stop matching, so change all three. */
.scene--invert{color:#3ecf8e;opacity:.08}
.scene--invert.scene--crane{-webkit-mask-image:none;mask-image:none}
@media(max-width:700px){
  /* the base layer softens to .06 on phones; this follows it down */
  .scene--invert{opacity:.06}
}



/* ---------- Dependency links on the schedule preview ----------
   The no-script fallback only. Once generate.js runs it rewrites the rows
   and draws the real network as SVG, links and arrowheads and all four
   relationship types. This keeps the card from reading as a bar chart in
   the moment before that happens. */
.peek__rows{--dep-h:26px}          /* bar-to-bar gap: rows are taller than bars
                                      because of the label, so this is measured
                                      rather than assumed from the row gap */
@media(max-width:860px){ .peek__rows{--dep-h:17px} }
.peek__bar--dep::before{
  content:"";position:absolute;pointer-events:none;
  left:calc(var(--p) * 1%);
  width:calc((var(--s) - var(--p)) * 1%);
  top:calc(-1 * var(--dep-h));height:var(--dep-h);
  border-left:1px solid var(--dep,var(--line-2));
  border-bottom:1px solid var(--dep,var(--line-2));
}

/* One required input and four that are not. A label inside the card broke the
   line it sat on, so the prompt carries a marker and the explanation waits at
   the foot of the column, where a footnote belongs. */
.gen2__lab em{
  font-style:normal;font-family:var(--mono);font-size:.58rem;letter-spacing:.08em;
  text-transform:uppercase;font-weight:400;margin-left:6px;color:var(--mute);
}
.io__star{color:var(--green-d);font-weight:600}
sup.io__star{margin-left:2px;font-size:.7em;top:-.4em}
.io__foot{
  margin:16px 0 0;font-family:var(--mono);font-size:.68rem;letter-spacing:.02em;color:var(--mute);
}
/* The optional four, set apart by weight and a gap rather than by a sentence
   introducing them: the footnote already says what they are, and saying it
   twice was the redundancy. */
.io__list--opt{margin-top:18px}
.io__list--opt li{color:var(--soft);font-weight:400}
