/* buffup.ai marketing — tokens.
   Palette, type steps and shadow ramp are lifted verbatim from mission control
   (buffup/app/src/index.css) so the public site and the product read as one
   system. Michael: "keep the same general color scheme". */
:root{
  color-scheme:light;
  --bg:#F2F2F7; --card:#FFFFFF; --ink:#17171A;
  --label-2:#6A6A72; --label-3:#6B6B73; --hint:#A8A8B0;
  --border:#E4E4EA; --hair:#EBEBF0; --hair-strong:#D6D6DC; --sunk:#EDEDF2;
  --primary:#0B69D4; --primary-press:#0A5CBB; --tint:#EAF2FD;
  /* Brand and action are the same blue again. The isolation the CTA needs is
     not bought with hue: on a customer's site the button sits inside OUR
     near-black sticky bar, which already separates it from their page, and it
     earns attention there with light and motion instead (see site.css .keep).
     Blue measures 5.27:1 for its white label, 4.72:1 against this page and
     3.4:1 against the dark bar, so it clears both text and control-edge
     contrast on every surface it appears on. */
  --ok:#177D4C; --ok-wash:#E8F6EF;
  --wait:#9A6206; --wait-wash:#FCF2E3;
  --stop:#C6362E; --stop-wash:#FCEDEC;

  --radius:13px; --radius-sm:9px; --radius-lg:20px;
  --lift-1:0 1px 1.5px oklch(20% .02 265/.05), 0 3px 10px -4px oklch(20% .02 265/.07);
  --lift-2:0 2px 4px oklch(20% .02 265/.06), 0 16px 36px -14px oklch(20% .02 265/.18);
  --lift-pop:0 4px 10px oklch(20% .02 265/.09), 0 34px 76px -26px oklch(20% .02 265/.32);

  --sans:-apple-system,BlinkMacSystemFont,"SF Pro Text","Helvetica Neue",Arial,sans-serif;
  --display:Outfit,-apple-system,sans-serif;
  --mono:PlexMono,ui-monospace,SFMono-Regular,Menlo,monospace;

  /* Six steps, same ladder as the product, plus two marketing-scale sizes. */
  --t-mega:clamp(2.6rem,7vw,5.5rem);
  --t-display:clamp(1.9rem,3.6vw,3rem);
  --t-metric:26px; --t-mark:23px; --t-head:16px; --t-body:13.5px; --t-cap:12px;
  --t-lede:clamp(1rem,1.4vw,1.2rem);

  --ease:cubic-bezier(.23,1,.32,1);
  --ease-soft:cubic-bezier(.4,0,.2,1);
}
@font-face{font-family:Outfit;src:url(/sites/_assets/fonts/outfit-800.woff2)format("woff2");font-weight:800;font-display:swap}
@font-face{font-family:Outfit;src:url(/sites/_assets/fonts/outfit-600.woff2)format("woff2");font-weight:600;font-display:swap}
@font-face{font-family:PlexMono;src:url(/sites/_assets/fonts/plexmono-500.woff2)format("woff2");font-weight:500;font-display:swap}

*,*::before,*::after{box-sizing:border-box}
html,body{overflow-x:clip}
html{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--ink);font:400 var(--t-body)/1.55 var(--sans);
     -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
h1,h2,h3{font-family:var(--display);font-weight:800;font-style:normal;letter-spacing:-.035em;
         line-height:1.03;margin:0;text-wrap:balance;overflow-wrap:anywhere}
p{margin:0}
a{color:inherit}
img{max-width:100%;display:block}
.wrap{width:min(1120px,100% - 2.5rem);margin-inline:auto}
.lede{font-size:var(--t-lede);line-height:1.5;color:var(--label-2);max-width:58ch;text-wrap:pretty}
.eyebrow{font:500 var(--t-cap)/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--label-3)}

/* A fact we do not have yet must be impossible to miss and impossible to ship.
   publish_gate.py refuses to deploy while any of these remain. */
.needs{background:var(--stop-wash);color:var(--stop);border:1px dashed var(--stop);
       border-radius:5px;padding:.05em .4em;font:500 var(--t-cap)/1.3 var(--mono);white-space:nowrap}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5em;height:44px;
     padding:0 1.25rem;border:0;border-radius:var(--radius-sm);background:var(--primary);
     color:#fff;font:500 var(--t-head)/1 var(--sans);text-decoration:none;cursor:pointer;
     transition:background-color .15s var(--ease),transform .12s var(--ease)}
@media (hover:hover){.btn:hover{background:var(--primary-press)}}
.btn:active{transform:scale(.97)}
.btn:focus-visible{outline:2px solid var(--primary);outline-offset:3px}
.btn.ghost{background:transparent;color:var(--ink);box-shadow:inset 0 0 0 1px var(--hair-strong)}
@media (hover:hover){.btn.ghost:hover{background:var(--card)}}

/* Progressive enhancement, not decoration-first. Content is VISIBLE by default;
   it is only hidden once JS has proven it is running and can reveal it again.

   html.js was not enough. That class is set by an inline script in the head,
   so it proves Javascript is ENABLED - not that reveal.js arrived. With JS on
   and that one file blocked (ad blocker, network blip, parse error) every
   .rise element stayed at opacity 0 and the page rendered with no hero at all.
   Measured 2026-09-14: hero ink 23,173px normally, 0px with reveal.js blocked,
   and its own two-second failsafe could not help because it lives in the file
   that did not load. The arming class is set BY reveal.js now, as its first
   statement, so nothing is hidden unless the thing that reveals it is running.
   Hiding first and revealing with script means a failed bundle, a blocked
   script or an observer that never fires leaves a blank page - which is exactly
   what the first version of this did. */
html.rise-armed .rise{opacity:0;transform:translate3d(0,14px,0)}
html.rise-armed .rise.in{opacity:1;transform:none;
  transition:opacity .5s var(--ease),transform .5s var(--ease)}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  html.rise-armed .rise,html.rise-armed .rise.in{opacity:1;transform:none;transition:none}
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
