/* ============================================================
   Criteria, shared stylesheet
   Extracted when the third page appeared (see CLAUDE.md).
   Holds: tokens for all three page tones, the bracket (used in 3 places
   only), the hairline row
   idiom, nav, buttons, atmosphere,
   section furniture, footer, reveals, reduced motion.
   Page-specific CSS stays inline in each page.
   ============================================================ */

/* ---------- tokens: light (default) ---------- */
:root{
  --paper:#FCFBF9;
  --paper-2:#F5F3EE;
  --ink:#171614;
  --ink-2:#5E5C57;
  --ink-3:#93908A;
  --rule:#DCD9D2;
  --rule-2:#EAE7E1;

  /* the spectrum, warm = human / not ready, cool = automated / ready */
  --w1:#E0653F;
  --w2:#E89A4C;
  --c1:#4E85B8;
  --c2:#5A5BA8;

  --nav-bg:rgba(252,251,249,.9);
  --grain:.04;
  --orb-op:1;
  --orb-invert:.24;

  /* the one tonal reversal allowed per page, near-black on a light page */
  --rev-bg:#171614;
  --rev-fg:#C7C4BE;
  --rev-strong:#FCFBF9;
  --rev-soft:#A3A09A;
  --rev-rule:rgba(252,251,249,.16);

  --measure:1240px;
  --ease:cubic-bezier(.22,.8,.25,1);
}

/* ---------- tokens: slate (the Products page) ----------
   The one page that carries a hue, and it is not a new one: the paper is an
   18% wash of --c2 (#5A5BA8) into the warm off-white. That is deliberate on
   two counts. It stays inside the existing spectrum rather than adding a
   fourth colour, and on the spectrum cool means productised and running,
   which is exactly what a product is, so the Products page sits at the cool
   end by argument, not by decoration.

   The ink stays the warm near-black. Warm ink on cool paper is what keeps
   this reading as Criteria rather than as the category default; do not cool
   the ink down to match the paper.

   This replaced a warm stone (#ECE9E0), which was a legible change of paper
   grade but not a distinctive one. */
html[data-theme="slate"]{
  --paper:#DFDEEA;
  --paper-2:#D2D1E1;
  --ink:#171614;
  --ink-2:#45444F;
  --ink-3:#5F5E72;
  --rule:#C3C2D3;
  --rule-2:#D5D4E2;

  --nav-bg:rgba(223,222,234,.9);
  --grain:.05;
  --orb-op:.95;
}

/* The banner carries the page's own tone. On slate the atmosphere is the
   cool end of the spectrum only, no warm orbs, so the hero reads as the
   same indigo as the paper beneath it instead of as the landing page's
   warm-to-cool wash. */
html[data-theme="slate"] .orb1{background:var(--c2)}
html[data-theme="slate"] .orb2{background:var(--c1)}
html[data-theme="slate"] .orb3{background:var(--c2)}
html[data-theme="slate"] .orb4{background:var(--c1)}

/* ---------- tokens: dark ----------
   Same roles, inverted values. The reversal tokens flip with them, so
   `.invert` still means "the single tonal exception on this page", on a
   dark page that block is the light one. */
html[data-theme="dark"]{
  --paper:#131211;
  --paper-2:#1C1A17;
  --ink:#F4F2ED;
  --ink-2:#A9A59C;
  --ink-3:#8A8579;
  --rule:#302D28;
  --rule-2:#221F1C;

  --nav-bg:rgba(19,18,17,.9);
  --grain:.055;
  --orb-invert:.16;

  --rev-bg:#F4F2ED;
  --rev-fg:#4A4842;
  --rev-strong:#131211;
  --rev-soft:#5E5C57;
  --rev-rule:rgba(19,18,17,.14);
}

/* ---------- base ---------- */
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  background:var(--paper);color:var(--ink);
  font-family:'Instrument Sans',system-ui,sans-serif;
  font-size:17px;line-height:1.65;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
/* grain overlay, what stops flat surfaces reading as a template */
body::after{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:60;opacity:var(--grain);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.wrap{max-width:var(--measure);margin:0 auto;padding:0 36px}
h1,h2,h3{font-family:'Figtree',sans-serif;font-weight:300;letter-spacing:-0.045em;line-height:1.02}
.mono{font-family:'IBM Plex Mono',monospace;font-size:10.5px;letter-spacing:0.17em;text-transform:uppercase;color:var(--ink-3)}
a{color:inherit;text-decoration:none}
:focus-visible{outline:1.5px solid var(--ink);outline-offset:3px}

/* ============ THE BRACKET ============
   The logo's mark. It is used sparingly and on purpose, in exactly three
   places on the site:
     1. the logo itself
     2. the active nav tab, the page you are in sits between the brackets
     3. the Company Brain diagram, where the context layer is held between them
   It is NOT a hover decoration. An earlier version put brackets on all 45
   cards plus every button, nav link, footer link and panel corner; at that
   density it read as a tic rather than an idea, and it was rejected. Anything
   that used to carry them now uses the hairline row below. Do not reintroduce
   brackets as a hover state. */

/* ---- HAIRLINE ROWS: the one hover idiom on the site ----
   The row carries a hairline (bottom for list rows, top for the two-column
   cards, whose height changes as they open); on hover the row slides 8px
   right and that rule darkens from --rule to --ink. Every list on the site:
   method stages, sectors, doors, builds, reliability layers, install steps,
   what-it-isn't. One gesture, one distance, one duration, everywhere. */
.hrow{transition:transform .5s var(--ease),border-color .4s var(--ease)}
.hrow:hover,.hrow:focus-within{transform:translateX(8px);border-color:var(--ink)}

/* ---- SPECIMEN CARDS: two per row, description opens on hover ----
   Same idiom as .hrow, in a two-column register. The first row of cards
   carries the heavy datum rule, the way .stages and .stack do. */
.svcs{display:grid;grid-template-columns:1fr 1fr;gap:0 44px;margin-top:76px;align-items:start}
.svc{
  position:relative;padding:24px 20px 28px 0;
  border-top:1px solid var(--rule);
  transition:transform .5s var(--ease),border-top-color .4s var(--ease);
}
.svc:nth-child(1),.svc:nth-child(2){border-top-color:var(--ink)}
.svc:hover,.svc:focus-within{transform:translateX(8px);border-top-color:var(--ink)}
.svc-n{
  display:block;font-family:'IBM Plex Mono',monospace;font-size:10.5px;
  letter-spacing:0.17em;text-transform:uppercase;color:var(--ink-3);
  margin-bottom:7px;transition:color .4s var(--ease);
}
.svc:hover .svc-n,.svc:focus-within .svc-n{color:var(--w1)}
.svc-t{
  display:block;font-family:'Figtree',sans-serif;font-weight:300;
  font-size:26px;letter-spacing:-0.04em;line-height:1.1;
}
/* description reveal: no opacity fade, on purpose. The text is solid and
   gets uncovered as the row opens, sliding up behind a clipping edge.
   grid-template-rows 0fr→1fr animates to the exact content height, which
   max-height can only approximate, so the easing stays even the whole way.
   Do not add opacity back here. */
.svc-d{
  display:grid;grid-template-rows:0fr;margin-top:0;
  transition:grid-template-rows .72s var(--ease),margin-top .72s var(--ease);
}
.svc-dc{overflow:hidden;min-height:0}
.svc-dc p{
  font-size:15.5px;line-height:1.55;color:var(--ink-2);
  transform:translateY(10px);
  transition:transform .72s var(--ease);
}
.svc:hover .svc-d,.svc:focus-within .svc-d{grid-template-rows:1fr;margin-top:14px}
.svc:hover .svc-dc p,.svc:focus-within .svc-dc p{transform:translateY(0)}
.svc:focus-visible{outline:none}

/* ============ THE DRAWING SYSTEM ============
   Every diagram on the site shares three stroke weights and nothing else.
   Six different widths had accumulated across the three figures, which is
   why they read as drawn rather than drafted.

   `non-scaling-stroke` is the important part. The figures use a 1160 unit
   viewBox and render at whatever the measure allows, around 856px on a
   laptop, so a 1 unit hairline was being drawn at 0.74 device pixels and
   antialiasing to grey. With this, a hairline is exactly one pixel at every
   viewport, which is the whole difference between a technical drawing and a
   blurry one.

   It is applied to static strokes only. The animated paths are normalised
   with pathLength="1" and their dash values are fractions of that, which
   non-scaling-stroke would reinterpret in device space and break. */
.d-hair{stroke-width:1;vector-effect:non-scaling-stroke}
.d-line{stroke-width:1.25;vector-effect:non-scaling-stroke}
.d-key{stroke-width:1.75;vector-effect:non-scaling-stroke}

/* node markers sit on top of the strokes they belong to, so they get a
   knockout in the paper colour behind them: the line stops at the node
   instead of running through it */
.d-knock{fill:var(--paper)}

/* ============ NAV ============ */
nav{position:sticky;top:0;z-index:50;background:var(--nav-bg);backdrop-filter:blur(10px);border-bottom:1px solid var(--rule)}
#prog{position:absolute;left:0;bottom:-1px;height:1px;background:var(--ink);width:0;transition:width .1s linear}
.navrow{display:flex;align-items:center;gap:40px;padding:18px 0}
.logo{display:flex;align-items:center;gap:10px;margin-right:auto}
.logo svg{display:block;color:var(--ink)}
.logo-txt{font-family:'Figtree',sans-serif;font-weight:400;font-size:20px;letter-spacing:-0.03em}
.lb{transition:transform .45s var(--ease)}
.lc{transition:transform .45s var(--ease);transform-origin:22px 22px}
.logo:hover .lb-l{transform:translateX(-3px)}
.logo:hover .lb-r{transform:translateX(3px)}
.logo:hover .lc{transform:scaleY(1.5)}
.navlinks{display:flex;gap:22px;font-size:15px;color:var(--ink-2)}
.navlinks a{position:relative;padding:2px 13px;transition:color .35s var(--ease)}
.navlinks a:hover{color:var(--ink)}
/* use 2 of 3: the page you are in is the thing held between the brackets.
   They sit at rest in the open position, this is a marker, not a gesture. */
.navlinks a[aria-current]{color:var(--ink);letter-spacing:.055em}
.navlinks a[aria-current]::before,.navlinks a[aria-current]::after{
  content:"";position:absolute;top:-1px;bottom:-1px;width:5px;
  border:1px solid currentColor;opacity:.9;
}
.navlinks a[aria-current]::before{left:0;border-right:0;transform:translateX(-5px) scaleY(1.18)}
.navlinks a[aria-current]::after{right:0;border-left:0;transform:translateX(5px) scaleY(1.18)}

.btn{display:inline-block;position:relative;background:var(--ink);color:var(--paper);
  padding:13px 26px;font-size:15px;border:1px solid var(--ink);border-radius:2px;
  transition:background .35s var(--ease),color .35s var(--ease),letter-spacing .45s var(--ease)}
.btn:hover{background:transparent;color:var(--ink);letter-spacing:.05em}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--rule)}
.btn-ghost:hover{border-color:var(--ink);background:transparent}

/* ============ HERO ATMOSPHERE ============ */
/* The orb timings are deliberately fast so movement is obvious within the
   first second. Don't slow them down, and keep the four periods different
   or the loop becomes visible. JS parallax lives on .atmos, the CSS
   animation on .field, keep that separation. */
.hero{padding:92px 0 72px;position:relative;overflow:hidden}
.atmos{position:absolute;inset:-25% -12%;pointer-events:none;z-index:0;
  opacity:var(--orb-op);
  transition:transform 1.6s var(--ease);will-change:transform}
.field{position:absolute;inset:0;animation:spin 26s linear infinite}
.orb{position:absolute;border-radius:50%;filter:blur(90px);will-change:transform,opacity}
.orb1{width:540px;height:540px;background:var(--w1);opacity:.20;top:4%;left:-4%;animation:d1 5.5s ease-in-out infinite alternate,pulse 4.2s ease-in-out infinite}
.orb2{width:460px;height:460px;background:var(--w2);opacity:.17;top:36%;left:24%;animation:d2 6.8s ease-in-out infinite alternate,pulse 5s ease-in-out infinite .5s}
.orb3{width:500px;height:500px;background:var(--c1);opacity:.18;top:-4%;right:10%;animation:d3 6.2s ease-in-out infinite alternate,pulse 4.6s ease-in-out infinite .9s}
.orb4{width:420px;height:420px;background:var(--c2);opacity:.15;top:42%;right:-2%;animation:d4 7.6s ease-in-out infinite alternate,pulse 5.4s ease-in-out infinite .2s}
@keyframes d1{50%{transform:translate(90px,-40px) scale(1.16)}100%{transform:translate(30px,60px) scale(1.05)}}
@keyframes d2{50%{transform:translate(-70px,55px) scale(1.12)}100%{transform:translate(50px,-30px) scale(1.02)}}
@keyframes d3{50%{transform:translate(-95px,70px) scale(1.18)}100%{transform:translate(-20px,-50px) scale(1.06)}}
@keyframes d4{50%{transform:translate(60px,-70px) scale(1.1)}100%{transform:translate(-45px,25px) scale(1.2)}}
@keyframes pulse{50%{opacity:.30}}
@keyframes spin{to{transform:rotate(360deg)}}
.hero .inner{position:relative;z-index:2}
/* Hero scale is set against sierra.ai, measured at 1440x900: their headline
   is 65px and their hero is 63% of the viewport. Ours was 132px and 85%,
   which read as a splash screen rather than a page. */
h1{font-size:clamp(40px,5.2vw,76px);max-width:14ch}
.hero .lede{font-size:19px;color:var(--ink-2);max-width:54ch;margin:30px 0 0;line-height:1.6}
.hero-actions{margin-top:32px}
.hero-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:32px}

/* ============ SECTION FURNITURE ============ */
section{padding:112px 0}
h2{font-size:clamp(34px,5vw,64px);max-width:17ch}
.sec-lede{font-size:19px;color:var(--ink-2);max-width:56ch;margin-top:28px}
.head-row{display:grid;grid-template-columns:180px 1fr;gap:48px;align-items:start}

.feature{display:grid;grid-template-columns:1fr 1fr;gap:96px;align-items:start}

/* ---- the single tonal reversal per page ----
   Exactly one .invert block per page. Adding a second weakens both. */
.invert{background:var(--rev-bg);color:var(--rev-fg);position:relative;overflow:hidden}
.invert .atmos .orb{opacity:var(--orb-invert);filter:blur(100px)}
.invert h2,.invert h3{color:var(--rev-strong)}
.invert .mono{color:var(--ink-3)}
.invert .sec-lede{color:var(--rev-soft)}
.invert .svc{border-top-color:var(--rev-rule)}
.invert .svc:nth-child(1),.invert .svc:nth-child(2){border-top-color:var(--rev-strong)}
.invert .svc:hover,.invert .svc:focus-within{border-top-color:var(--rev-strong)}
.invert .hrow{border-color:var(--rev-rule)}
.invert .hrow:hover,.invert .hrow:focus-within{border-color:var(--rev-strong)}
.invert .svc-t{color:var(--rev-strong)}
.invert .svc-dc p{color:var(--rev-soft)}
/* buttons inside the reversed block have to flip with it */
.invert .btn{background:var(--rev-strong);color:var(--rev-bg);border-color:var(--rev-strong)}
.invert .btn:hover{background:transparent;color:var(--rev-strong)}
.invert .btn-ghost{background:transparent;color:var(--rev-strong);border-color:var(--rev-rule)}
.invert .btn-ghost:hover{border-color:var(--rev-strong);background:transparent}
.quote{font-family:'Figtree',sans-serif;font-weight:300;font-size:clamp(30px,4vw,52px);line-height:1.08;letter-spacing:-0.045em;max-width:16ch;color:var(--rev-strong)}

.cta{text-align:center;padding:136px 0}
.cta h2{margin:0 auto;max-width:14ch}
.cta .sec-lede{margin:28px auto 0}

/* ============ FOOTER ============ */
footer{border-top:1px solid var(--rule);padding:72px 0 44px;font-size:14.5px;color:var(--ink-2)}
.fgrid{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:48px;margin-bottom:64px}
footer h4{font-family:'IBM Plex Mono',monospace;font-size:10.5px;letter-spacing:0.17em;text-transform:uppercase;color:var(--ink-3);font-weight:400;margin-bottom:20px}
footer li{list-style:none;margin-bottom:11px;position:relative}
footer a{position:relative;display:inline-block;transition:transform .4s var(--ease),color .3s var(--ease)}
footer a:hover{color:var(--ink);transform:translateX(8px)}
.fbot{display:flex;justify-content:space-between;padding-top:26px;border-top:1px solid var(--rule-2);font-size:13px;color:var(--ink-3);flex-wrap:wrap;gap:12px}

/* ============ REVEALS ============ */
.rv{opacity:0;transform:translateY(16px);transition:opacity .8s var(--ease),transform .8s var(--ease)}
.rv.on{opacity:1;transform:none}

/* Every new animation must be added to this block. */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .orb,.field{animation:none!important}
  .rv{opacity:1!important;transform:none!important;transition:none}
  .atmos{transition:none}
  .hrow:hover,.hrow:focus-within,.svc:hover,.svc:focus-within,footer a:hover{transform:none}
}

@media(max-width:900px){
  .wrap{padding:0 22px}
  .svcs{grid-template-columns:1fr;gap:0}
  .svc{padding:20px 0 24px}
  .svc:nth-child(2){border-top-color:var(--rule)}
  .invert .svc:nth-child(2){border-top-color:var(--rev-rule)}
  .svc-t{font-size:23px}
  .svc-d{grid-template-rows:1fr;margin-top:12px}
  .svc-dc p{transform:none}
  .head-row,.feature{grid-template-columns:1fr;gap:16px}
  .feature{gap:48px}
  .fgrid{grid-template-columns:1fr 1fr;gap:36px}
  section{padding:72px 0}
  .hero{padding:52px 0 44px}
  .cta{padding:88px 0}
  .orb{filter:blur(60px)}

  /* the tabs stay on the wordmark's row, at the right, at every width.
     They shrink and then scroll inside the row rather than dropping to a
     row of their own. */
  .navrow{gap:20px;padding:15px 0}
  .navlinks{gap:2px;font-size:13px;min-width:0;
    overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .navlinks::-webkit-scrollbar{display:none}
  .navlinks a{padding:2px 9px;white-space:nowrap}
  .navlinks a[aria-current]{letter-spacing:0}
}
