/* ============================================================
   HECinBox site styles, shared by every page.
   Palette and type match the application theme so the site and
   the product read as one piece of software.
   ============================================================ */
:root{
  --bg0:#eef0f5;
  --bg1:#ffffff;
  --bg2:#e1e6ee;
  --text:#0f1e3a;
  --muted:#475569;
  --dim:#64748b;
  --primary:#3c78af;
  --primary-hover:#306496;
  --primary-soft:rgba(60,120,175,.10);
  --border:#dbeafe;
  --border-strong:#93c5fd;
  --shadow-sm:0 1px 2px rgba(15,30,58,.05);
  --shadow:0 1px 3px rgba(15,30,58,.07),0 1px 2px rgba(15,30,58,.04);
  --shadow-md:0 4px 14px rgba(15,30,58,.10);
  --shadow-lg:0 18px 40px -18px rgba(15,30,58,.30);
  --r-sm:6px; --r-md:8px; --r-lg:12px;
  --grad:linear-gradient(135deg,#0f1e3a 0%,#3c78af 100%);
  /* The container grows with the display instead of stopping dead at one
     width, so a large monitor is not mostly empty margin. Side gutters scale
     with the viewport too. */
  --maxw:1180px;
  --gutter:clamp(20px,4vw,52px);
  --sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --mono:'JetBrains Mono','SF Mono',Menlo,Consolas,monospace;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;background:var(--bg0);color:var(--text);font-family:var(--sans);
  -webkit-font-smoothing:antialiased;line-height:1.65;
  display:flex;flex-direction:column;min-height:100vh;
}
img,svg{max-width:100%}
a{color:var(--primary);text-decoration:none}
a:hover{text-decoration:underline}
code,kbd,pre{font-family:var(--mono)}
h1,h2,h3{line-height:1.15;margin:0;letter-spacing:-.025em;font-weight:800}
h1{font-size:clamp(2rem,1.35rem + 2.7vw,3.5rem)}
h2{font-size:clamp(1.45rem,1.1rem + 1.5vw,2.3rem)}
h3{font-size:clamp(1rem,.97rem + .12vw,1.1rem);font-weight:700;letter-spacing:-.01em}
p{margin:0}
.wrap{width:100%;max-width:var(--maxw);margin:0 auto;padding-inline:var(--gutter)}
/* Showcase track. Text is capped at a readable line length, but a result map
   earns the extra width, so figures get their own wider container rather than
   being trapped in the prose column on a large display. */
.wrap-wide{max-width:min(2100px,95vw)}
main{flex:1 0 auto}
/* vertical only. Using the padding shorthand here would reset the side gutter
   .wrap sets, which pinned every subpage flush to the screen edge on mobile. */
.page{padding-top:clamp(38px,4vw,72px);padding-bottom:clamp(52px,5vw,92px)}
.lead{color:var(--muted);font-size:clamp(1rem,.96rem + .22vw,1.18rem)}
.eyebrow{
  display:inline-flex;align-items:center;gap:8px;font-size:.72rem;font-weight:700;
  letter-spacing:.15em;text-transform:uppercase;color:var(--primary);margin-bottom:14px;
}
.eyebrow::before{content:"";width:22px;height:2px;border-radius:2px;background:var(--primary)}
.page-head{max-width:62ch;margin-bottom:clamp(28px,3.2vw,48px)}
.page-head h1{margin-bottom:14px}

/* ============ nav ============ */
header.nav{
  position:sticky;top:0;z-index:60;background:rgba(238,240,245,.88);
  backdrop-filter:saturate(160%) blur(12px);-webkit-backdrop-filter:saturate(160%) blur(12px);
  border-bottom:1px solid var(--border);
}
.nav-in{display:flex;align-items:center;gap:16px;height:66px}
.brand{display:flex;align-items:center;gap:10px;font-weight:800;letter-spacing:-.03em;font-size:1.1rem;color:var(--text)}
.brand:hover{text-decoration:none}
.brand img{width:36px;height:36px;flex:0 0 36px;display:block}
.brand b{color:var(--primary)}
.tabs{display:flex;gap:2px;margin-left:auto;align-items:center}
.tabs a{
  padding:8px 13px;border-radius:var(--r-md);font-size:.9rem;color:var(--muted);font-weight:500;
  transition:.16s;white-space:nowrap;
}
.tabs a:hover{color:var(--text);background:var(--primary-soft);text-decoration:none}
.tabs a.on{color:var(--primary);background:var(--primary-soft);font-weight:650}
.burger{
  display:none;width:38px;height:38px;place-items:center;border-radius:var(--r-md);cursor:pointer;
  border:1px solid var(--border);background:var(--bg1);color:var(--muted);margin-left:auto;
}
/* the hamburger icon has fill:none strokes, so a tap in the gaps between the
   lines can miss the button on mobile. Make the whole button the target. */
.burger svg,.burger svg *{pointer-events:none}
.burger{touch-action:manipulation;-webkit-tap-highlight-color:transparent}

/* ============ buttons ============ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:12px 20px;border-radius:var(--r-md);font-weight:600;font-size:.94rem;font-family:inherit;
  border:1px solid transparent;cursor:pointer;transition:.18s;white-space:nowrap;
}
.btn:hover{text-decoration:none}
.btn-primary{background:var(--primary);color:#fff;box-shadow:var(--shadow-md)}
.btn-primary:hover{background:var(--primary-hover);transform:translateY(-1px)}
.btn-ghost{border-color:var(--border-strong);color:var(--text);background:var(--bg1);box-shadow:var(--shadow-sm)}
.btn-ghost:hover{background:var(--primary-soft);border-color:var(--primary)}
.btn-lg{padding:15px 28px;font-size:1rem}
.btns{display:flex;gap:12px;flex-wrap:wrap}
.pulse{width:8px;height:8px;border-radius:50%;background:#4ade80;box-shadow:0 0 0 0 rgba(74,222,128,.7);animation:pulse 2.2s infinite}
@keyframes pulse{70%{box-shadow:0 0 0 9px rgba(74,222,128,0)}100%{box-shadow:0 0 0 0 rgba(74,222,128,0)}}

/* ============ home hero ============ */
/* Two full screens: identity first, proof immediately after. svh keeps mobile
   browser chrome from pushing the buttons out of view. min-height, not height,
   so a short window still scrolls rather than clipping. */
.hero{
  display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:clamp(24px,3vw,56px);align-items:center;position:relative;
  min-height:calc(92vh - 66px);min-height:calc(92svh - 66px);
  padding:clamp(18px,1.8vw,32px) 0 clamp(46px,4.4vw,72px);
}
.hero h1{font-size:clamp(1.95rem,1.2rem + 2.7vw,3.6rem);max-width:18ch}
.hero .eyebrow{margin-bottom:clamp(14px,2.4vh,32px)}
.hero p{color:var(--muted);font-size:clamp(1.02rem,.96rem + .34vw,1.28rem);max-width:48ch;margin:clamp(16px,2.8vh,38px) 0 clamp(40px,15vh,200px)}
.hero-logo{display:flex;justify-content:flex-end}
.hero-logo img{width:clamp(210px,32vw,600px);height:auto;filter:drop-shadow(0 20px 38px rgba(15,30,58,.18))}
.shot{
  margin:0;border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;
  background:var(--bg1);box-shadow:var(--shadow-lg);
}
.shot figcaption{padding:14px 18px;border-top:1px solid var(--border);font-size:.85rem;color:var(--muted);text-align:center}

/* rotating result maps. Every slide sits in the same box and cross fades.
   contain, never cover: cropping would cut the colorbar off the edge. */
/* Aspect ratio drives the height, but cap it against the window so a wide
   short display still shows a whole map without scrolling. When the cap binds,
   the box narrows to keep its ratio, so centre it rather than leaving the slack
   all on one side. contain keeps the colorbar intact whichever constraint wins. */
.slides{position:relative;aspect-ratio:2.35/1;max-height:58vh;margin-inline:auto;background:var(--bg1)}
.slides img,.slides svg{
  position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  opacity:0;transition:opacity .9s ease;
}
.slides img.on,.slides svg.on{opacity:1}
.dots{
  position:absolute;left:0;right:0;bottom:10px;display:flex;justify-content:center;gap:7px;z-index:2;
}
.dots button{
  width:8px;height:8px;padding:0;border-radius:50%;cursor:pointer;border:none;position:relative;
  background:rgba(15,30,58,.28);transition:.2s;
}
/* the visible dot stays 8px, but a taller invisible hit zone makes it easy to
   tap on a phone. Kept narrow horizontally so neighbouring dots do not overlap. */
.dots button::before{content:"";position:absolute;top:-16px;bottom:-16px;left:-3px;right:-3px}
.dots button.on{background:var(--primary);width:22px;border-radius:5px}
.dots button:hover{background:rgba(15,30,58,.5)}
@media(max-width:760px){ .slides{aspect-ratio:16/10} }
.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,250px),1fr));gap:clamp(14px,1.4vw,20px);margin-bottom:10px}
.fact{background:var(--bg1);border:1px solid var(--border);border-radius:var(--r-lg);padding:20px 22px;box-shadow:var(--shadow-sm)}
.fact h3{margin-bottom:5px}
.fact p{color:var(--muted);font-size:.89rem}

/* a quiet nudge that the maps are one scroll away */
.scroll-cue{
  position:absolute;left:50%;bottom:18px;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:6px;
  color:var(--dim);font-size:.74rem;letter-spacing:.14em;text-transform:uppercase;font-weight:600;
}
.scroll-cue:hover{text-decoration:none;color:var(--primary)}
.scroll-cue svg{animation:nudge 1.9s ease-in-out infinite}
@keyframes nudge{0%,100%{transform:translateY(0)}50%{transform:translateY(5px)}}

/* The maps get a screen of their own, but only once the viewport is wide
   enough for the map to actually fill it. The box height comes from the
   container width, so on a narrow screen a full height section would wrap a
   small map in mostly empty space. */
.shot-screen{display:grid;align-content:center;gap:clamp(22px,2.6vw,44px)}
@media(min-width:1100px){
  .shot-screen{min-height:calc(100vh - 66px);min-height:calc(100svh - 66px)}
}

/* ============ cards ============ */
/* auto-fit rather than a fixed column count: the cards decide how many fit in
   the space available, so there is no width where the layout is awkward and no
   breakpoint to maintain. */
.grid{display:grid;gap:clamp(14px,1.4vw,22px)}
.g2{grid-template-columns:repeat(auto-fit,minmax(min(100%,330px),1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))}
.card{
  border:1px solid var(--border);border-radius:var(--r-lg);background:var(--bg1);padding:24px;
  box-shadow:var(--shadow-sm);transition:transform .2s,box-shadow .2s,border-color .2s;
}
.card:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:var(--border-strong)}
.card .ico{
  width:40px;height:40px;border-radius:var(--r-md);display:grid;place-items:center;margin-bottom:14px;
  background:var(--primary-soft);border:1px solid var(--border);color:var(--primary);
}
.card .ico svg{width:20px;height:20px}
.card h3{margin-bottom:6px}
.card p{color:var(--muted);font-size:.89rem}

/* ============ code ============ */
.code-wrap{position:relative;margin-bottom:26px}
.codebox{border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;background:var(--bg1);box-shadow:var(--shadow-sm)}
.code-tabs{display:flex;gap:4px;padding:9px 92px 9px 10px;border-bottom:1px solid var(--border);flex-wrap:wrap;background:var(--bg0)}
.code-tab{
  padding:6px 13px;border-radius:var(--r-md);font-size:.8rem;color:var(--dim);cursor:pointer;font-weight:600;
  transition:.16s;border:1px solid transparent;background:none;font-family:inherit;
}
.code-tab.on{background:var(--primary-soft);color:var(--primary);border-color:var(--border-strong)}
.code-tab:hover{color:var(--text)}
pre{margin:0;padding:20px 22px;overflow-x:auto;font-size:.82rem;line-height:1.85;background:var(--bg1);color:var(--text)}
pre .c{color:var(--dim)}
pre .k{color:var(--primary);font-weight:500}
pre .s{color:#0f766e}
.copy{
  position:absolute;top:10px;right:12px;z-index:3;font-size:.72rem;padding:6px 11px;border-radius:var(--r-sm);
  border:1px solid var(--border-strong);background:var(--bg1);color:var(--muted);cursor:pointer;
  transition:.16s;font-family:inherit;
}
.copy:hover{color:var(--primary);background:var(--primary-soft)}

/* ============ faq ============ */
.faq{border-top:1px solid var(--border)}
.faq-item{border-bottom:1px solid var(--border)}
.faq-q{
  width:100%;text-align:left;background:none;border:none;color:var(--text);font:inherit;font-weight:600;
  padding:20px 40px 20px 0;cursor:pointer;position:relative;font-size:1rem;
}
.faq-q::after{
  content:"";position:absolute;right:6px;top:26px;width:9px;height:9px;border-right:2px solid var(--primary);
  border-bottom:2px solid var(--primary);transform:rotate(45deg);transition:transform .25s;
}
.faq-item.open .faq-q::after{transform:rotate(-135deg)}
/* A fixed open ceiling rather than a measured pixel height. Measuring at
   click time went stale when the window was resized and the text rewrapped
   taller, and fr based collapsing would not reliably reach zero height. */
.faq-a{max-height:0;overflow:hidden;transition:max-height .35s ease;color:var(--muted);font-size:.93rem}
.faq-item.open .faq-a{max-height:60rem}
.faq-a > div{padding:0 0 20px}

/* ============ panels ============ */
.panel{
  background:var(--bg1);border:1px solid var(--border);border-radius:var(--r-lg);padding:32px;
  box-shadow:var(--shadow-sm);
}
.panel-center{text-align:center;padding:52px 34px}
.panel-center p{color:var(--muted);max-width:540px;margin:14px auto 28px}
.steps{margin:0;padding-left:20px;color:var(--muted);font-size:.93rem;line-height:2}
.note{color:var(--dim);font-size:.85rem;margin-top:18px}
.kv{list-style:none;margin:0;padding:0}
.kv li{display:flex;gap:14px;padding:12px 0;border-top:1px solid var(--border);font-size:.94rem;flex-wrap:wrap}
.kv li:first-child{border-top:none}
.kv b{min-width:120px;color:var(--dim);font-weight:600;font-size:.85rem;text-transform:uppercase;letter-spacing:.06em}

/* ============ footer ============ */
footer{border-top:1px solid var(--border);background:var(--bg1);padding:30px 0;flex-shrink:0}
.foot{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;font-size:.84rem;color:var(--dim)}
.foot a{color:var(--muted)}
.foot nav{display:flex;gap:16px;flex-wrap:wrap}

/* ============ responsive ============ */
@media(max-width:900px){
  .hero{grid-template-columns:1fr;gap:28px;padding:40px 0 34px}
  .hero-logo{justify-content:center;order:-1}
  .hero-logo img{width:min(210px,46%)}
}
@media(max-width:760px){
  .tabs{
    position:fixed;inset:66px 0 auto;flex-direction:column;align-items:stretch;gap:0;padding:8px 16px 18px;
    background:var(--bg1);border-bottom:1px solid var(--border);box-shadow:var(--shadow-md);display:none;
  }
  header.nav{backdrop-filter:none;-webkit-backdrop-filter:none;background:var(--bg0)}
  .tabs.open{display:flex}
  .tabs a{padding:13px 8px;font-size:1rem}
  .burger{display:grid}
  /* stacked buttons of different widths read as ragged, so fill the column */
  .hero .eyebrow{margin-bottom:14px}
  .hero p{margin:16px 0 clamp(28px,4vh,46px)}
  /* the absolute scroll cue collides with the stacked buttons on a phone, and
     a phone hero does not need to be pinned to a full screen */
  .hero{min-height:0}
  .scroll-cue{display:none}
  .btns{flex-direction:column;align-items:stretch}
  .btns .btn{width:100%}
  /* the gutter reserved for Copy pushes the third install tab onto its own
     line, so free it up and let the button sit under the code block */
  .code-tabs{padding-right:10px}
  .copy{position:static;display:block;width:100%;margin:10px 0 0}
  .panel{padding:24px}
  .panel-center{padding:36px 22px}
  /* short pairs fit beside their label while long ones wrap, which leaves the
     list ragged. Stack every one so they read consistently. */
  .kv li{flex-direction:column;gap:2px}
  .kv b{min-width:0}
  .foot{flex-direction:column;text-align:center}
  /* touch targets: a 22px tall footer link is easy to miss with a thumb */
  .burger{width:44px;height:44px}
  .foot nav{gap:2px}
  .foot nav a{display:inline-block;padding:11px 10px}
  .kv a{display:inline-block;padding:7px 0}
}
/* let the container breathe on big monitors instead of stranding content
   in a narrow column surrounded by empty space */
@media(min-width:1500px){ :root{--maxw:1360px} }
@media(min-width:1800px){ :root{--maxw:1560px} }
@media(min-width:2300px){ :root{--maxw:1760px} }

@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
