/* Lematev — black / white / green.
   One accent colour, used only for money saved and healthy state. If green means four
   things it means nothing, so: green = saving, amber = warning, red = waste.

   Two themes, one token set. Nothing below this block references a raw colour, so the
   light theme is a redefinition of the tokens rather than a second stylesheet to keep
   in sync. The accent darkens in light mode -- #00d98a on white is about 1.7:1 and
   unreadable, #00875a clears 4.5:1 -- because a finance number nobody can read is not
   a design choice. */
:root {
  --bg:        #07090a;
  --surface:   #0e1113;
  --surface-2: #14181b;
  --line:      #1f2529;
  --line-soft: #171c1f;
  --text:      #f2f5f6;
  --muted:     #8a969c;
  --faint:     #5a666c;

  --green:     #00d98a;
  --green-dim: #0a7a51;
  --green-bg:  rgba(0, 217, 138, .10);
  --amber:     #f5b93d;
  --amber-bg:  rgba(245, 185, 61, .10);
  --red:       #ff5c5c;
  --red-bg:    rgba(255, 92, 92, .10);

  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif;
  --r: 10px;
  --shadow: none;
  color-scheme: dark;
}

/* Follow the operating system unless the viewer picked a theme themselves. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg:        #f6f8f8;
    --surface:   #ffffff;
    --surface-2: #f1f4f4;
    --line:      #dfe5e5;
    --line-soft: #ecf0f0;
    --text:      #0d1214;
    --muted:     #5a686e;
    --faint:     #8a979c;

    --green:     #00875a;
    --green-dim: #00a86e;
    --green-bg:  rgba(0, 135, 90, .09);
    --amber:     #9a6a00;
    --amber-bg:  rgba(154, 106, 0, .10);
    --red:       #c0392b;
    --red-bg:    rgba(192, 57, 43, .09);
    --shadow:    0 1px 2px rgba(13, 18, 20, .05);
    color-scheme: light;
  }
}

:root[data-theme="light"] {
  --bg:        #f6f8f8;
  --surface:   #ffffff;
  --surface-2: #f1f4f4;
  --line:      #dfe5e5;
  --line-soft: #ecf0f0;
  --text:      #0d1214;
  --muted:     #5a686e;
  --faint:     #8a979c;

  --green:     #00875a;
  --green-dim: #00a86e;
  --green-bg:  rgba(0, 135, 90, .09);
  --amber:     #9a6a00;
  --amber-bg:  rgba(154, 106, 0, .10);
  --red:       #c0392b;
  --red-bg:    rgba(192, 57, 43, .09);
  --shadow:    0 1px 2px rgba(13, 18, 20, .05);
  color-scheme: light;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg); color: var(--text);
  font-family: var(--sans); font-size: 14px; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* `clip`, not `hidden`. Both stop a full-bleed element from widening the page
     into a horizontal scrollbar, but `hidden` turns this into a scroll
     container and silently kills every `position: sticky` inside it -- the
     documentation's side navigation, among others. With `clip` on one axis the
     other stays `visible`, which is the whole reason the value exists. */
  overflow-x: clip;
}
a { color: var(--green); text-decoration: none; }
/* No underline on hover. The colour change already says the link is live, and
   an underline appearing under every link on the way past is visual noise.
   Focus keeps its outline, so keyboard navigation is unaffected. */
a:hover { opacity: .78; }

/* ---------- shell ---------- */
.top {
  display: flex; align-items: center; gap: 12px 16px; flex-wrap: wrap;
  padding: 12px 24px; border-bottom: 1px solid var(--line);
  background: var(--surface); position: sticky; top: 0; z-index: 20;
}
.logo { display: flex; align-items: center; gap: 9px; font-weight: 650; letter-spacing: -.2px; }
/* Two files rather than one recoloured by CSS: `content: url()` on an <img> is not
   reliable across engines, and a dark tile in a light header reads as a hole. Both are
   tiny and cached. */
.logo .mark { width: 24px; height: 24px; display: block; flex: none; }
/* Sizing belongs to .mark, not to .logo .mark: the footer sets its own box on
   .mark and the images inside it were falling back to their natural size. */
.mark img { width: 100%; height: 100%; display: block; }
/* The mark ships as two files, one per theme, and exactly one must ever be
   visible. These rules were scoped to .logo, so anywhere else the mark appears
   -- the page footer -- BOTH were displayed and the logo showed up twice. */
.mark .mark-light { display: none; }
:root[data-theme="light"] .mark .mark-dark { display: none; }
:root[data-theme="light"] .mark .mark-light { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .mark .mark-dark { display: none; }
  :root:not([data-theme="dark"]) .mark .mark-light { display: block; }
}
.top .sub {
  color: var(--faint); font-size: 12px; border-left: 1px solid var(--line);
  padding-left: 16px; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 34ch;
}
.top .spacer { flex: 1 1 auto; min-width: 0; }
.top .controls { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }

/* What gets dropped as the bar narrows, in order: the project label, then the in-page
   anchors. The controls are what people came to press, and a header that wraps onto
   three lines covers the content behind it. */
@media (max-width: 1080px) { .top .nav-link { display: none; } }
@media (max-width: 760px) { .top .sub { display: none; } }
@media (max-width: 620px) {
  .top { padding: 10px 16px; gap: 8px; }
  .top .controls { gap: 6px; }
  .seg.compact button { padding: 6px 8px; font-size: 11.5px; }
}

.wrap { max-width: 1320px; margin: 0 auto; padding: 24px; }
h2 { font-size: 13px; text-transform: uppercase; letter-spacing: .09em;
     color: var(--muted); font-weight: 600; margin: 34px 0 12px; }
h2:first-child { margin-top: 0; }
.hint { color: var(--faint); font-size: 12px; margin: -6px 0 12px; max-width: 78ch; }

/* ---------- controls ---------- */
select, input, button {
  font-family: var(--sans); font-size: 13px; color: var(--text);
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 8px; padding: 7px 10px;
}
input[type=range] { padding: 0; background: none; border: none; accent-color: var(--green); }
button { cursor: pointer; }
button:hover { border-color: var(--green-dim); }
button.primary { background: var(--green); color: #ffffff; border-color: var(--green);
                 font-weight: 650; }
:root:not([data-theme="light"]) button.primary { color: #04160f; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) button.primary { color: #ffffff; }
}
button.primary:hover { filter: brightness(1.08); }
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.seg button { border: none; border-radius: 0; background: transparent; padding: 7px 13px; }
.seg button[aria-pressed=true] { background: var(--green-bg); color: var(--green); }

/* ---------- cards ---------- */
.grid { display: grid; gap: 14px; }
/* Grid and flex items default to min-width:auto, so they refuse to shrink below their
   content and push the page sideways. Every wide table in here would do it. */
.grid > *, .two > *, .three > *, .card { min-width: 0; }
/* Six headline numbers read as two rows of three, not five-and-a-stray. */
.kpis { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
@media (min-width: 1040px) { .kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: 16px 18px; box-shadow: var(--shadow);
}
.card.pad-0 { padding: 0; overflow: hidden; }
.kpi .label { color: var(--muted); font-size: 11.5px; text-transform: uppercase;
              letter-spacing: .07em; }
.kpi .value { font-family: var(--mono); font-size: 29px; font-weight: 600;
              letter-spacing: -1px; margin: 7px 0 3px; }
.kpi .note { color: var(--faint); font-size: 12px; }
.kpi.good .value { color: var(--green); }
.kpi.warn .value { color: var(--amber); }
.kpi.bad  .value { color: var(--red); }

/* ---------- tables ---------- */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th {
  text-align: left; color: var(--muted); font-weight: 600; font-size: 11px;
  text-transform: uppercase; letter-spacing: .07em; padding: 11px 14px;
  border-bottom: 1px solid var(--line); background: var(--surface-2);
  position: sticky; top: 0;
}
th.num, td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
td { padding: 10px 14px; border-bottom: 1px solid var(--line-soft); }
tbody tr:last-child td { border-bottom: none; }
tbody tr.clickable { cursor: pointer; }
tbody tr.clickable:hover { background: var(--surface-2); }
/* Wide tables scroll inside their card rather than widening the page. */
.table-scroll { overflow-x: auto; max-width: 100%; }
.table-scroll > table, .table-scroll table { min-width: max-content; }

/* Any table that was not put in a scrolling wrapper by hand. A table with more
   columns than the card is wide does not shrink -- it is cut off, and the
   columns that disappear are the ones on the right, which here are the numbers.
   Wrapping every one by hand is a rule someone forgets on the next table, so
   this catches whatever was missed.

   display:block would break the column alignment, so the table stays a table
   and the cell that would overflow is allowed to scroll instead. */
.card > table, .drawer table, #recs table, #qualityImpact table {
  display: block; overflow-x: auto; max-width: 100%; white-space: nowrap;
}
/* display:block detaches the internal table layout, so give it back. */
.card > table > tbody, .card > table > thead,
.drawer table > tbody, .drawer table > thead,
#recs table > tbody, #recs table > thead,
#qualityImpact table > tbody, #qualityImpact table > thead {
  display: table; width: 100%; min-width: max-content;
}

/* The spend chart is an SVG with a fixed internal width; below that it was
   squashed rather than scrolled, which made the daily bars unreadable. */
#chart { overflow-x: auto; }
#chart > svg { min-width: 560px; }
.scroll { max-height: 460px; overflow: auto; max-width: 100%; }
.scroll > table { min-width: max-content; }

.mono { font-family: var(--mono); }
.muted { color: var(--muted); }
.faint { color: var(--faint); }
.green { color: var(--green); }
.amber { color: var(--amber); }
.red   { color: var(--red); }
.nowrap { white-space: nowrap; }

/* ---------- pills & bars ---------- */
.pill {
  display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px;
  font-weight: 600; border: 1px solid transparent; white-space: nowrap;
}
.pill.green { background: var(--green-bg); color: var(--green); border-color: var(--green-dim); }
.pill.amber { background: var(--amber-bg); color: var(--amber);
              border-color: color-mix(in srgb, var(--amber) 45%, transparent); }
.pill.red   { background: var(--red-bg);   color: var(--red);
              border-color: color-mix(in srgb, var(--red) 45%, transparent); }
.pill.grey  { background: var(--surface-2); color: var(--muted); border-color: var(--line); }

.bar { height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--green); }
.stack { display: flex; height: 26px; border-radius: 7px; overflow: hidden;
         border: 1px solid var(--line); }
.stack > i { display: block; }
.legend { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 11px; font-size: 12px; }
.legend span { display: flex; align-items: center; gap: 6px; color: var(--muted); }
.legend b { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }

/* ---------- comparison ---------- */
.compare th:first-child, .compare td:first-child { color: var(--muted); }
.compare td.with { color: var(--green); font-weight: 600; }
.compare tr.total td { border-top: 1px solid var(--line); font-weight: 650; }

/* ---------- alerts / recommendations ---------- */
.rec { display: flex; gap: 13px; padding: 14px 18px; border-bottom: 1px solid var(--line-soft); }
.rec:last-child { border-bottom: none; }
.rec .dot { width: 7px; height: 7px; border-radius: 50%; margin-top: 7px; flex: none; }
.rec .t { font-weight: 600; margin-bottom: 3px; }
.rec .d { color: var(--muted); font-size: 12.5px; }
.rec .a { color: var(--faint); font-size: 12.5px; margin-top: 5px; }
.rec .impact { margin-left: auto; font-family: var(--mono); font-weight: 650;
               white-space: nowrap; }

/* ---------- chart ---------- */
svg.chart { width: 100%; display: block; }
svg .axis { stroke: var(--line); stroke-width: 1; }
svg .grid-l { stroke: var(--line-soft); stroke-width: 1; }
svg text { fill: var(--faint); font-size: 10px; font-family: var(--mono); }

/* ---------- drawer ---------- */
.scrim { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 40; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(760px, 94vw);
  background: var(--surface); border-left: 1px solid var(--line); z-index: 41;
  overflow: auto; padding: 22px 24px 40px;
}
.drawer header { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 18px; }
.drawer h3 { margin: 0; font-size: 17px; }
.close { margin-left: auto; background: none; border: none; color: var(--muted);
         font-size: 20px; line-height: 1; cursor: pointer; }
.timeline { border-left: 2px solid var(--line); margin-left: 6px; padding-left: 16px; }
.step { margin-bottom: 14px; position: relative; }
.step::before { content: ""; position: absolute; left: -22px; top: 6px; width: 8px;
                height: 8px; border-radius: 50%; background: var(--green-dim); }
.step.bad::before { background: var(--red); }
.step .h { font-family: var(--mono); font-size: 12.5px; }
.step .b { color: var(--muted); font-size: 12px; }

.empty { padding: 30px; text-align: center; color: var(--faint); }
.two { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 14px; }
.three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
/* minmax(0, 1fr), not 1fr: a bare 1fr means minmax(auto, 1fr), and that `auto`
   floor is the column's MIN-CONTENT width. A wide table inside then pushes the
   column past the viewport even though it sits in an overflow-x:auto wrapper --
   the classic grid blowout. The wide breakpoint already had the minmax; the
   narrow one, where it actually matters, did not. */
@media (max-width: 920px) {
  .two, .three { grid-template-columns: minmax(0, 1fr); }
}

.keyrow { display: flex; gap: 8px; align-items: center; }
.keyrow input { flex: 1; font-family: var(--mono); font-size: 12px; }
footer { color: var(--faint); font-size: 12px; padding: 34px 0 10px;
         border-top: 1px solid var(--line); margin-top: 40px; }

/* ---------- calculator ---------- */
.calc {
  display: grid; grid-template-columns: minmax(0, 380px) minmax(0, 1fr);
  gap: 20px; align-items: start;
}
.calc > * { min-width: 0; }
@media (max-width: 900px) { .calc { grid-template-columns: minmax(0, 1fr); } }
/* A select sizes itself to its widest option, and the model names are long. Without
   this it widens its column and pushes the whole page sideways. */
.field select, .auth-card select { max-width: 100%; text-overflow: ellipsis; }
.field { margin-bottom: 15px; }
.field label { display: flex; justify-content: space-between; color: var(--muted);
               font-size: 12px; margin-bottom: 5px; }
.field label b { color: var(--text); font-family: var(--mono); }
.field input[type=number], .field select { width: 100%; }
.big {
  font-family: var(--mono); font-size: 40px; font-weight: 600; letter-spacing: -1.5px;
  color: var(--green); line-height: 1.1;
}
.hero { text-align: center; padding: 48px 24px 10px; }
.hero h1 { font-size: 34px; letter-spacing: -1px; margin: 0 0 10px; }
.hero p { color: var(--muted); max-width: 62ch; margin: 0 auto; font-size: 15px; }

/* ---------- header controls ---------- */
.top .seg + .seg, .top .seg + a { margin-left: 2px; }
.seg.compact button { padding: 7px 10px; font-size: 12px; }

/* ========================================================================
   Public pages: landing, auth, agent onboarding.
   ======================================================================== */
.section { padding: 76px 0; border-top: 1px solid var(--line-soft); }
.section:first-of-type { border-top: none; }
.section h2.big-h, h1.page-h {
  font-size: clamp(26px, 3.4vw, 40px); line-height: 1.12; letter-spacing: -1px;
  margin: 0 0 14px; text-transform: none; color: var(--text); font-weight: 680;
}
.section p.lede {
  color: var(--muted); font-size: 16.5px; max-width: 68ch; margin: 0 0 30px;
}
.eyebrow {
  display: inline-block; font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--green); background: var(--green-bg); border: 1px solid var(--green-dim);
  padding: 5px 11px; border-radius: 999px; margin-bottom: 20px; font-weight: 650;
}

/* hero */
.hero2 { padding: 70px 0 52px; }
.hero2 h1 {
  font-size: clamp(32px, 5.4vw, 60px); line-height: 1.04; letter-spacing: -2px;
  margin: 0 0 20px; max-width: 24ch; font-weight: 700;
}
.hero2 p.sub { color: var(--muted); font-size: 17.5px; max-width: 62ch; margin: 0 0 30px; }
.ctas { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.btn {
  display: inline-flex; align-items: center; gap: 8px; padding: 12px 20px;
  text-align: center;
  border-radius: 10px; font-size: 14.5px; font-weight: 640; cursor: pointer;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text);
  text-decoration: none;
}
.btn:hover { border-color: var(--green-dim); text-decoration: none; }
.btn-primary { background: var(--green); border-color: var(--green); color: #ffffff; }
:root:not([data-theme="light"]) .btn-primary { color: #04160f; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .btn-primary { color: #ffffff; }
}
.btn-primary:hover { filter: brightness(1.08); }
.btn-lg { padding: 14px 24px; font-size: 15.5px; }

/* code blocks */
pre.code {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px;
  padding: 16px 18px; overflow-x: auto; font-family: var(--mono); font-size: 13px;
  line-height: 1.62; margin: 0; color: var(--text);
}
pre.code .c { color: var(--faint); }
pre.code .k { color: var(--green); }
pre.code .s { color: var(--amber); }
pre.code .del { color: var(--red); text-decoration: line-through; opacity: .75; }
.code-head {
  display: flex; align-items: center; gap: 10px; padding: 9px 14px;
  border: 1px solid var(--line); border-bottom: none; border-radius: 10px 10px 0 0;
  background: var(--surface); font-size: 12px; color: var(--muted);
}
.code-head + pre.code { border-radius: 0 0 10px 10px; }
.code-head .spacer { flex: 1; }
.tabs { display: flex; gap: 2px; }
.tabs button {
  border: none; background: transparent; color: var(--muted); font-size: 12px;
  padding: 4px 10px; border-radius: 6px; cursor: pointer; font-family: var(--sans);
}
.tabs button[aria-pressed=true] { background: var(--green-bg); color: var(--green); }
.copy-btn { border: 1px solid var(--line); background: var(--surface-2); font-size: 11.5px;
            padding: 4px 10px; border-radius: 6px; }

/* feature / step grids */
.cols3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(258px, 100%), 1fr)); gap: 16px; }
.cols2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: 16px; }
.cols3 > *, .cols2 > * { min-width: 0; }
.feat { padding: 20px; border: 1px solid var(--line); border-radius: var(--r);
        background: var(--surface); }
.feat h3 { margin: 0 0 8px; font-size: 15.5px; }
.feat p { margin: 0; color: var(--muted); font-size: 14px; }
.step-n {
  width: 27px; height: 27px; border-radius: 8px; background: var(--green-bg);
  color: var(--green); border: 1px solid var(--green-dim); display: grid;
  place-items: center; font-family: var(--mono); font-size: 13px; font-weight: 700;
  margin-bottom: 13px;
}

/* screenshots */
.shots { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(380px, 100%), 1fr)); gap: 18px; }
.shots > * { min-width: 0; }
.shot { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
        background: var(--surface); }
.shot img { width: 100%; display: block; border-bottom: 1px solid var(--line); }
.shot figcaption { padding: 12px 15px; color: var(--muted); font-size: 13px; margin: 0; }

/* pricing */
.plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); gap: 14px; }
.plans > * { min-width: 0; }
.plan {
  border: 1px solid var(--line); border-radius: var(--r); padding: 20px 18px;
  background: var(--surface); display: flex; flex-direction: column;
}
.plan.featured { border-color: var(--green-dim); box-shadow: 0 0 0 1px var(--green-dim); }
.plan .tag {
  position: relative; top: -32px; margin-bottom: -22px; align-self: flex-start;
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  background: var(--green); color: #04160f; padding: 3px 9px; border-radius: 999px;
}
:root[data-theme="light"] .plan .tag { color: #fff; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .plan .tag { color: #fff; }
}
.plan h3 { margin: 0 0 4px; font-size: 16px; }
.plan .price { font-family: var(--mono); font-size: 27px; font-weight: 640;
               letter-spacing: -1px; margin: 10px 0 2px; }
.plan .price small { font-size: 12.5px; color: var(--faint); font-weight: 400;
                     letter-spacing: 0; }
.plan .desc { color: var(--muted); font-size: 13px; min-height: 36px; margin: 0 0 14px; }
.plan ul { list-style: none; padding: 0; margin: 0 0 18px; font-size: 13.5px;
           color: var(--muted); }
.plan li { padding: 5px 0 5px 20px; position: relative; }
.plan li::before {
  content: "✓"; position: absolute; left: 0; color: var(--green); font-weight: 700;
  font-size: 12px;
}
.plan .btn { margin-top: auto; justify-content: center; }

/* faq */
.faq details {
  border: 1px solid var(--line); border-radius: var(--r); padding: 0;
  background: var(--surface); margin-bottom: 10px;
}
.faq summary {
  cursor: pointer; padding: 16px 18px; font-weight: 620; font-size: 15px;
  list-style: none; display: flex; justify-content: space-between; gap: 14px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--green); font-family: var(--mono);
                      font-size: 17px; line-height: 1; }
.faq details[open] summary::after { content: "−"; }
.faq .a { padding: 0 18px 17px; color: var(--muted); font-size: 14.5px; margin: 0;
          max-width: 78ch; }

/* auth */
.auth-wrap { max-width: 450px; margin: 66px auto; padding: 0 22px; }
.auth-card { border: 1px solid var(--line); border-radius: 14px; padding: 30px 28px;
             background: var(--surface); box-shadow: var(--shadow); }
.auth-card h1 { font-size: 24px; margin: 0 0 8px; letter-spacing: -.6px; }
.auth-card > p { color: var(--muted); font-size: 14.5px; margin: 0 0 24px; }
.auth-card label { display: block; font-size: 12.5px; color: var(--muted);
                   margin: 0 0 6px; }
.auth-card input, .auth-card select { width: 100%; padding: 11px 13px; font-size: 14.5px; }
.auth-card .field { margin-bottom: 17px; }
.auth-card .btn { width: 100%; justify-content: center; margin-top: 6px; }
.auth-alt { text-align: center; margin: 20px 0 0; font-size: 13.5px; }
.notice {
  border: 1px solid var(--line); border-left: 3px solid var(--amber);
  background: var(--amber-bg); border-radius: 8px; padding: 12px 14px;
  font-size: 12.5px; color: var(--muted); margin: 0 0 22px;
}
.err { color: var(--red); font-size: 13px; margin: 12px 0 0; min-height: 18px; }

/* onboarding */
.onb { max-width: 900px; margin: 0 auto; padding: 34px 22px 80px; }
.onb-step { display: flex; gap: 18px; padding: 26px 0; border-top: 1px solid var(--line-soft); }
.onb-step:first-of-type { border-top: none; }
.onb-step .body { flex: 1; min-width: 0; }
.onb-step h3 { margin: 0 0 8px; font-size: 17.5px; letter-spacing: -.3px; }
.onb-step p { color: var(--muted); font-size: 14.5px; margin: 0 0 14px; max-width: 74ch; }
.keyfield {
  display: flex; gap: 8px; align-items: center; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px;
}
.keyfield code { flex: 1; font-family: var(--mono); font-size: 13px; overflow-x: auto;
                 white-space: nowrap; }
.pulse { display: inline-block; width: 8px; height: 8px; border-radius: 50%;
         background: var(--amber); animation: pulse 1.5s ease-in-out infinite; }
.pulse.on { background: var(--green); animation: none; }
@keyframes pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
.status-bar {
  display: flex; align-items: center; gap: 11px; padding: 14px 17px;
  border: 1px solid var(--line); border-radius: var(--r); background: var(--surface);
  margin-bottom: 26px;
}
.status-bar b { font-size: 14.5px; }
.status-bar .t { color: var(--muted); font-size: 13px; }
.aside {
  border-left: 3px solid var(--green-dim); background: var(--green-bg);
  padding: 12px 15px; border-radius: 0 8px 8px 0; color: var(--muted);
  font-size: 13.5px; margin: 0 0 14px; max-width: 74ch;
}
svg.flow { width: 100%; height: auto; display: block; }
svg.flow text { fill: var(--muted); font-family: var(--mono); font-size: 11px; }
svg.flow .box { fill: var(--surface-2); stroke: var(--line); }
svg.flow .gw { fill: var(--green-bg); stroke: var(--green-dim); }
svg.flow .arrow { stroke: var(--line); stroke-width: 1.5; fill: none; }
svg.flow .lbl { fill: var(--green); font-size: 10px; }

/* ========================================================================
   Public pages — shape language.

   Borrowed from a site the founder pointed at: a floating pill navbar, a live
   badge above the headline, fully-rounded buttons, generous radii, and one
   accent colour. Adapted rather than copied — the palette and the content stay
   Lematev's.

   Deliberately NO web font. A self-hosted deployment must not phone out to a
   font CDN, and the same stylesheet serves the dashboard that ships into a
   customer's VPC. The character comes from shape and spacing instead.
   ======================================================================== */

/* --- floating navbar (public pages only; the app keeps its dense header) --- */
.top--float {
  position: sticky; top: 14px; z-index: 30;
  margin: 14px auto 0; max-width: 1180px; width: calc(100% - 32px);
  border: 1px solid var(--line); border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  padding: 9px 10px 9px 18px; gap: 10px 14px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .28);
}
:root[data-theme="light"] .top--float { box-shadow: 0 6px 24px rgba(13, 18, 20, .07); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .top--float { box-shadow: 0 6px 24px rgba(13, 18, 20, .07); }
}
.top--float .seg { border-radius: 999px; }
.top--float .btn { padding: 9px 18px; }
/* On a phone the floating bar keeps the logo, the language switch and the one
   button people came to press. The theme control goes: with no stored choice the
   page already follows the operating system, so hiding it costs nothing. A header
   that wraps onto four lines costs the whole first screen. */
@media (max-width: 780px) {
  .top--float #themeSeg { display: none; }
  .top--float .nav-secondary { display: none; }
}
@media (max-width: 620px) {
  .top--float {
    border-radius: 22px; padding: 10px 10px 10px 14px; top: 8px;
    gap: 8px; flex-wrap: nowrap;
  }
  .top--float .logo { font-size: 15px; }
  .top--float .controls { gap: 6px; flex: 0 1 auto; min-width: 0; }
  .top--float .btn { padding: 9px 15px; font-size: 13px; white-space: nowrap; }
}

/* --- hero --- */
.hero3 { position: relative; text-align: center; padding: 74px 0 60px; }
.hero3::before {
  content: ""; position: absolute; left: 50%; top: -90px; translate: -50% 0;
  width: min(860px, 96vw); height: 460px; pointer-events: none; z-index: -1;
  background: radial-gradient(ellipse at center,
              color-mix(in srgb, var(--green) 16%, transparent) 0%, transparent 68%);
  filter: blur(22px);
}
.hero3 h1 {
  font-size: clamp(34px, 5.6vw, 62px); line-height: 1.03; letter-spacing: -2.2px;
  font-weight: 700; margin: 0 auto 20px; max-width: 17ch;
}
.hero3 p.sub {
  color: var(--muted); font-size: 17.5px; line-height: 1.55;
  max-width: 60ch; margin: 0 auto 32px;
}
.hero3 .ctas { justify-content: center; }
.hero3 .code-wrap { max-width: 660px; margin: 38px auto 0; text-align: left; }

/* --- live badge --- */
.badge-live {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 8px 16px 8px 13px; border-radius: 999px; margin-bottom: 24px;
  border: 1px solid var(--line); background: var(--surface);
  font-size: 13px; font-weight: 600; color: var(--muted); letter-spacing: -.1px;
}
.badge-live i {
  width: 8px; height: 8px; border-radius: 50%; background: var(--green);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--green) 22%, transparent);
  animation: blip 2.4s ease-in-out infinite;
}
@keyframes blip { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
  .badge-live i, .pulse { animation: none; }
}

/* Every auto-fit track above uses min(Npx, 100%) rather than a bare Npx: a grid whose
   minimum exceeds the viewport pushes the whole page sideways on a narrow screen. */

/* --- rounder cards on the public pages --- */
.feat, .plan, .shot, .faq details { border-radius: 18px; }
.btn { border-radius: 999px; }
.feat {
  padding: 24px 22px;
  transition: border-color .16s ease, transform .16s ease;
}
.feat:hover { border-color: color-mix(in srgb, var(--green) 45%, var(--line)); }
.ico {
  width: 40px; height: 40px; border-radius: 13px; display: grid; place-items: center;
  background: var(--green-bg); border: 1px solid var(--green-dim);
  margin-bottom: 15px; flex: none;
}
.ico svg { width: 19px; height: 19px; stroke: var(--green); fill: none;
           stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }

/* --- centred section headers on the public pages --- */
.section--center { text-align: center; }
.section--center p.lede { margin-left: auto; margin-right: auto; }
/* The heading and lede are centred; the content inside cards is not. A bullet list
   with centred text and a left-aligned tick reads as a mistake. */
.section--center .cols2, .section--center .cols3,
.section--center .plans, .section--center .shots { text-align: left; }

/* One large screenshot rather than a wall of thumbnails. Six small ones made a visitor
   squint at all of them and read none. */
.shot--hero {
  margin: 0; border-radius: 20px; overflow: hidden;
  border: 1px solid var(--line); background: var(--surface);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
}
:root[data-theme="light"] .shot--hero { box-shadow: 0 18px 44px rgba(13, 18, 20, .12); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .shot--hero { box-shadow: 0 18px 44px rgba(13, 18, 20, .12); }
}
.shot--hero img { width: 100%; display: block; border: none; }

/* ========================================================================
   Account menu.

   A profile button, not a hamburger. A hamburger means "site navigation", and a
   dashboard with one page has no navigation problem — it has an account-actions
   problem. People also look top-RIGHT for their account; a hamburger sits top-left
   and sends them the wrong way. And a hamburger would swallow the time-window
   selector, which has to stay visible because it changes every number on screen.
   ======================================================================== */
.avatar {
  width: 32px; height: 32px; border-radius: 50%; flex: none; cursor: pointer;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text);
  font-family: var(--sans); font-size: 12px; font-weight: 700; letter-spacing: .2px;
  display: grid; place-items: center; padding: 0;
}
.avatar:hover, .avatar[aria-expanded="true"] { border-color: var(--green-dim); }
.menu-wrap { position: relative; flex: none; }
.menu {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 60;
  min-width: 268px; max-width: calc(100vw - 24px); padding: 8px; border-radius: 14px;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 16px 44px rgba(0, 0, 0, .4);
}
:root[data-theme="light"] .menu { box-shadow: 0 16px 40px rgba(13, 18, 20, .14); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .menu { box-shadow: 0 16px 40px rgba(13, 18, 20, .14); }
}
.menu[hidden] { display: none; }
.menu .who { padding: 10px 12px 12px; border-bottom: 1px solid var(--line-soft);
             margin-bottom: 6px; }
.menu .who b { display: block; font-size: 14px; }
.menu .who span { color: var(--faint); font-size: 12px; font-family: var(--mono);
                  word-break: break-all; }
.menu a, .menu button.item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 12px; border-radius: 9px; font-size: 14px; color: var(--text);
  background: none; border: none; cursor: pointer; font-family: var(--sans);
  text-decoration: none;
}
.menu a:hover, .menu button.item:hover { background: var(--surface-2); text-decoration: none; }
.menu .row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px;
}
.menu .row span { color: var(--muted); font-size: 12.5px; }
.menu hr { border: none; border-top: 1px solid var(--line-soft); margin: 6px 0; }
.menu .danger { color: var(--red); }

/* Provider row, under the hero. The whole thesis is that this layer sits above
   any one provider, and that is the one claim a visitor cannot infer from the
   prose elsewhere on the page.

   It scrolls in CSS. No script: the content policy forbids inline JavaScript,
   and a marquee is not worth an external file. */
.providers { text-align: center; }
.providers-lead {
  font-size: 12px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--faint); margin: 0 0 30px; font-family: var(--mono);
}

/* The clipping box. Full-bleed out of the wrap, because a strip that stops at
   the text margin reads as a component; one that runs off both edges reads as
   something passing through. */
.providers-marquee {
  position: relative; overflow: hidden;
  width: 100vw; margin-left: calc(50% - 50vw);
  /* Fade rather than cut, so a logo is never sliced in half at the edge. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
}
.providers-track {
  display: flex; width: max-content;
  animation: providers-scroll 42s linear infinite;
}
/* Shifts by exactly one of the four copies, so the frame after the last is the
   first again and the seam is invisible. */
@keyframes providers-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-25%, 0, 0); }
}
.providers-marquee:hover .providers-track { animation-play-state: paused; }

.providers-row {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex: 0 0 auto; align-items: center; gap: 82px;
  /* Equal to the gap, always: this is what separates the last logo of one copy
     from the first of the next, so any difference reads as a stutter once per
     loop rather than as a wider row. */
  padding-right: 82px;
}
.providers-row li {
  display: inline-flex; align-items: center; gap: 17px; flex: 0 0 auto;
  font-size: 25px; font-weight: 600; letter-spacing: -.015em; color: var(--text);
  opacity: .72; transition: opacity .16s;
}
.providers-row li:hover { opacity: 1; }
.providers-row img {
  height: 56px; width: auto; display: block;
  /* These marks are drawn at very different weights; capping the width keeps a
     wide one from towering over a compact one. */
  max-width: 74px; object-fit: contain;
}
/* Black marks vanish on the dark theme. Inverting only those leaves the colour
   logos alone -- inverting everything would turn Google into a negative. */
:root[data-theme="dark"] .providers-row img[data-mono] { filter: invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .providers-row img[data-mono] { filter: invert(1); }
}
.providers-note { margin: 24px 0 0; }

@media (max-width: 640px) {
  .providers-row { gap: 46px; padding-right: 46px; }
  .providers-row li { font-size: 19px; gap: 12px; }
  .providers-row img { height: 38px; max-width: 50px; }
  .providers-track { animation-duration: 28s; }
}

/* An endlessly moving strip is exactly what this setting is asked to stop. It
   becomes a static, centred row -- the information was never in the movement. */
@media (prefers-reduced-motion: reduce) {
  .providers-marquee {
    width: auto; margin-left: 0;
    -webkit-mask-image: none; mask-image: none;
  }
  .providers-track { animation: none; width: auto; justify-content: center;
                     flex-wrap: wrap; }
  .providers-track .providers-row[aria-hidden="true"] { display: none; }
  .providers-row { flex-wrap: wrap; justify-content: center; gap: 22px 46px;
                   padding-right: 0; }
}

/* Documentation layout: a sticky list of sections beside the text.

   Below the breakpoint it becomes a horizontal strip that scrolls -- a sidebar
   folded above the content pushes the first paragraph off the screen, which is
   worse than no navigation at all. */
.wrap--docs {
  max-width: 1080px; display: grid; gap: 44px;
  grid-template-columns: 208px minmax(0, 1fr);
  align-items: start;
}
.doc-nav { position: sticky; top: 84px; align-self: start; }
.doc-nav-inner { display: flex; flex-direction: column; gap: 1px;
                 border-left: 1px solid var(--line-soft); }
.doc-nav a {
  padding: 7px 0 7px 14px; margin-left: -1px; font-size: 13.5px; line-height: 1.35;
  color: var(--muted); text-decoration: none; border-left: 2px solid transparent;
}
.doc-nav a:hover { color: var(--text); opacity: 1; }
.doc-nav a[aria-current="true"] {
  color: var(--text); font-weight: 600; border-left-color: var(--green);
}
/* Anchors land under the fixed header without this. */
.doc-h[id] { scroll-margin-top: 84px; }

@media (max-width: 900px) {
  .wrap--docs { grid-template-columns: 1fr; gap: 20px; }
  .doc-nav { position: static; margin: 0 -24px; padding: 0 24px;
             overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .doc-nav-inner { flex-direction: row; border-left: none;
                   border-bottom: 1px solid var(--line-soft); gap: 4px; }
  .doc-nav a { padding: 8px 12px; margin-left: 0; white-space: nowrap;
               border-left: none; border-bottom: 2px solid transparent; }
  .doc-nav a[aria-current="true"] { border-left-color: transparent;
                                    border-bottom-color: var(--green); }
}

/* The loader is the mark, with the chart bars moving.

   The foot and the upright stay still on purpose: together they are the letter
   L, and a letter that stretches while you wait stops being a letter. What
   moves is the two bars standing on the foot -- the part that already means
   "spend", in a mark whose whole idea is spend coming down. So the thing that
   animates is the thing the product measures.

   Drawn inline rather than loading brand/mark.svg, because an <img> cannot have
   its internals animated, and a loader that waits for a network round trip to
   appear is a loader that arrives after the thing it was covering. */
.loader { display: inline-flex; align-items: center; gap: 10px; color: var(--muted);
          font-size: 13px; }
.loader svg { width: 28px; height: 28px; display: block; flex: none; }
.loader--block { display: flex; justify-content: center; padding: 44px 0; }
.loader--lg svg { width: 44px; height: 44px; }

/* transform-box: fill-box makes the origin the shape's own bottom edge, so the
   bar grows out of the foot rather than from the middle of the canvas. */
.loader .bar {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: lmt-bar 1.1s ease-in-out infinite;
}
.loader .bar--2 { animation-delay: .18s; }

@keyframes lmt-bar {
  0%, 100% { transform: scaleY(.34); }
  45%      { transform: scaleY(1); }
}

/* The plate behind the mark, so it reads on both themes without two files. */
.loader .plate { fill: var(--surface-2); }
.loader .ink { fill: var(--green); }

@media (prefers-reduced-motion: reduce) {
  /* Height changes are the part that bothers people. A quiet fade still says
     "working" without anything moving. */
  .loader .bar { animation: lmt-fade 1.6s ease-in-out infinite; transform: none; }
  .loader .bar--2 { animation-delay: .3s; }
  @keyframes lmt-fade { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
}

/* Dimmed, not hidden: the layout stays put so it is obvious the period is the
   reason the numbers are absent, not that the page failed to load. */
.dimmed { opacity: .35; pointer-events: none; }

/* Calendar period picker. Rolling windows say how things are going; a month or
   a year says whether that period paid for itself. */
.period-wrap { position: relative; flex: none; }
.period-btn {
  display: flex; align-items: center; gap: 7px; padding: 7px 12px; font-size: 13px;
  border: 1px solid var(--line); border-radius: 9px; background: var(--surface);
  color: var(--text); cursor: pointer; font-family: var(--sans); white-space: nowrap;
}
.period-btn:hover { border-color: var(--green); }
.period-btn[aria-expanded="true"] { border-color: var(--green); }
.period-btn::after {
  content: ""; width: 5px; height: 5px; margin-left: 2px; flex: none;
  border-right: 1.4px solid var(--faint); border-bottom: 1.4px solid var(--faint);
  transform: rotate(45deg) translateY(-1px);
}
.period-pop {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 40; width: 268px;
  padding: 12px; background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow);
}
.period-pop[hidden] { display: none; }
.period-h { font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
            color: var(--faint); margin: 2px 0 7px; font-family: var(--mono); }
.period-h + .period-grid { margin-bottom: 12px; }
.period-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.period-grid.years { grid-template-columns: repeat(3, 1fr); }
.period-grid button {
  padding: 7px 4px; font-size: 12.5px; border: 1px solid transparent;
  border-radius: 7px; background: var(--surface-2); color: var(--text);
  cursor: pointer; font-family: var(--sans);
}
.period-grid button:hover { border-color: var(--green); }
.period-grid button[aria-pressed="true"] { background: var(--green); color: var(--bg); }
/* A period the plan does not keep is shown and disabled, not hidden: the reason
   it is unavailable is the plan, and that is worth seeing. */
.period-grid button[disabled] { opacity: .4; cursor: not-allowed; }
.period-grid button[disabled]:hover { border-color: transparent; }

/* Workspace list. One account can own several: a client, a product, a staging
   environment. Each keeps its own plan, limits and provider keys. */
.ws-list { display: grid; gap: 8px; margin-top: 14px; }
.ws-row {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 13px 14px; border: 1px solid var(--line); border-radius: 11px;
  background: var(--surface); cursor: pointer; font-family: var(--sans);
  color: var(--text); font-size: 14px;
}
.ws-row:hover { border-color: var(--green); background: var(--surface-2); }
.ws-row .nm { font-weight: 600; }
.ws-row .meta { color: var(--faint); font-size: 12px; margin-top: 2px; }
.ws-row .tag {
  margin-left: auto; font-size: 11px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--faint); font-family: var(--mono);
}
.ws-row[aria-current="true"] { border-color: var(--green); }
.ws-switch { padding: 4px 6px 8px; border-bottom: 1px solid var(--line-soft);
             margin-bottom: 6px; display: grid; gap: 2px; }
.ws-switch button {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 7px 8px; border-radius: 8px; border: none; background: none;
  cursor: pointer; font-family: var(--sans); font-size: 13px; color: var(--text);
}
.ws-switch button:hover { background: var(--surface-2); }
.ws-switch button[aria-current="true"] { color: var(--faint); cursor: default; }
.ws-switch button[aria-current="true"]:hover { background: none; }
.ws-switch .dot { width: 6px; height: 6px; border-radius: 50%; flex: none;
                  background: var(--green); }
.ws-switch .plus { width: 6px; flex: none; text-align: center; color: var(--faint);
                   font-family: var(--mono); line-height: 1; }
/* Capped rather than hidden: a free account has to be able to see that
   workspaces exist, and that another one is what the next plan buys. */
.ws-switch button[data-capped] { color: var(--muted); }
.ws-switch button[data-capped]::after {
  content: ""; width: 9px; height: 9px; margin-left: auto; flex: none;
  border: 1.2px solid var(--faint); border-radius: 2px; border-bottom-width: 4px;
}
.ws-switch button[aria-current="false"] .dot { background: var(--line); }

/* settings drawer reuses .drawer */
.setting { padding: 16px 0; border-top: 1px solid var(--line-soft); }
.setting:first-of-type { border-top: none; }
.setting label { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 4px; }
.setting p { color: var(--muted); font-size: 12.5px; margin: 0 0 10px; max-width: 62ch; }
.setting input, .setting select { width: 100%; max-width: 360px; }
.setting .inline { display: flex; align-items: center; gap: 10px; }
.setting .inline input[type=checkbox] { width: auto; }
.saved { color: var(--green); font-size: 13px; }

/* ========================================================================
   Landing modules.

   The page was eleven sections and six were the same card grid: one rhythm,
   repeated, which a reader stops seeing. These borrow the shapes that work on
   the competitors' pages — an eyebrow label, a stat strip in the hero, a
   bordered definition, feature blocks that each end in a small concrete data
   panel, a comparison table, a persistent bottom bar.

   One change of our own: their data panels show invented figures. Ours show
   output the engine actually produced, which is the whole argument.
   ======================================================================== */

/* --- eyebrow: a dash and small caps, so sections are scannable ---------- */
.eyebrow-line {
  display: flex; align-items: center; gap: 12px; margin-bottom: 14px;
  white-space: nowrap;
  font-size: 11.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--green);
}
.eyebrow-line::before {
  content: ""; width: 26px; height: 2px; background: var(--green); border-radius: 2px;
  flex: none;
}
@media (max-width: 460px) {
  .eyebrow-line { font-size: 10.5px; letter-spacing: .1em; gap: 9px; }
  .eyebrow-line::before { width: 18px; }
}

/* --- hero: left-aligned, short headline, numbers underneath ------------- */
/* `overflow: clip` rather than `hidden`: it stops the decorative glow from adding to
   the page's scroll width without turning the hero into a scroll container. The glow
   itself is also kept inside the element's own box — a positioned pseudo-element that
   sticks out to the left counts as horizontal overflow, which is what was pushing the
   whole page sideways on a narrow screen. */
/* Two columns above 960px, stacked below. The left column is the hero as it
   was; the right one holds the decision card.

   `align-items: center` rather than `start`: the card is shorter than the text
   column, and pinned to the top it left a hole under itself that read as a
   layout bug rather than as space. */
.hero4 {
  padding: 64px 0 52px; position: relative; overflow: clip;
  display: grid; gap: 56px;
  /* `start`, not `center`. The text column is taller than the diagram, so
     centring pushed the diagram down against the middle of a paragraph and left
     a hole above it. Aligned to the top it starts level with the headline,
     which is where the eye already is. */
  align-items: start;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
}
@media (max-width: 960px) {
  /* The card goes under the buttons, not above them: on a phone the first
     screenful has to be the promise and the way in, not a specimen. */
  .hero4 { grid-template-columns: 1fr; gap: 40px; }
}
.hero4::before {
  content: ""; position: absolute; left: 0; top: -60px;
  width: min(620px, 100%); height: 420px;
  pointer-events: none; z-index: -1; filter: blur(30px);
  background: radial-gradient(ellipse at center,
              color-mix(in srgb, var(--green) 13%, transparent) 0%, transparent 70%);
}
.hero4 h1 {
  font-size: clamp(38px, 6.4vw, 72px); line-height: .98; letter-spacing: -2.6px;
  font-weight: 700; margin: 0 0 22px; max-width: 15ch;
}
.hero4 p.sub { color: var(--muted); font-size: 18px; line-height: 1.5;
               max-width: 54ch; margin: 0 0 34px; }
/* A grid, not a wrapping flex row: with flex the third number dropped onto a second
   line on its own and the strip read as broken. It now goes three-across or
   one-per-row, never two-and-a-stray. */
.hero-stats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 26px 34px; margin-bottom: 34px; max-width: 640px;
}
@media (max-width: 640px) { .hero-stats { grid-template-columns: 1fr; gap: 18px; } }

/* On a phone the primary action goes full width. A button whose label wraps onto two
   lines reads as a mistake, and shortening the label further would cost the verb. */
@media (max-width: 520px) {
  .hero4 .ctas, .section .ctas { flex-direction: column; align-items: stretch; }
  .hero4 .ctas .btn, .section .ctas .btn { width: 100%; justify-content: center; }
}
.hero-stats .n {
  font-size: clamp(26px, 3.4vw, 34px); font-weight: 680; letter-spacing: -1.2px;
  line-height: 1.1; display: block;
}
.hero-stats .l { color: var(--muted); font-size: 13px; margin-top: 4px; display: block;
                 max-width: 16ch; }
.reassure {
  display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 20px;
  color: var(--faint); font-size: 12.5px;
}
.reassure span { display: flex; align-items: center; gap: 7px; }
.reassure span::before {
  content: ""; width: 4px; height: 4px; border-radius: 50%; background: var(--green);
}

/* --- bordered definition, for the paragraph a search engine reads ------- */
.definition {
  border-left: 3px solid var(--green); padding: 4px 0 4px 24px; max-width: 72ch;
}
.definition h2 { font-size: clamp(20px, 2.4vw, 26px); text-transform: none;
                 letter-spacing: -.6px; color: var(--text); margin: 0 0 12px; }
.definition p { color: var(--muted); font-size: 15.5px; margin: 0; }

/* --- feature block: label, claim, prose, then a small real panel -------- */
.block { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr));
         gap: 38px; align-items: center; }
.block > * { min-width: 0; }
.block h3 { font-size: clamp(21px, 2.6vw, 28px); letter-spacing: -.8px; margin: 0 0 12px;
            line-height: 1.15; }
.block p { color: var(--muted); font-size: 15px; margin: 0 0 16px; max-width: 54ch; }

.panel {
  border: 1px solid var(--line); border-radius: 16px; background: var(--surface);
  overflow: hidden; font-size: 13px;
}
.panel .ph {
  padding: 11px 16px; border-bottom: 1px solid var(--line); background: var(--surface-2);
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  display: flex; justify-content: space-between; gap: 12px;
}
.panel .pr {
  display: flex; justify-content: space-between; gap: 14px; padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.panel .pr:last-child { border-bottom: none; }
.panel .pr .k { color: var(--muted); }
.panel .pr .v { font-family: var(--mono); font-variant-numeric: tabular-nums;
                white-space: nowrap; }
.panel .pf { padding: 11px 16px; border-top: 1px solid var(--line);
             color: var(--faint); font-size: 11.5px; }
.panel .strike { text-decoration: line-through; opacity: .55; }

/* --- comparison table --------------------------------------------------- */
.cmp-wrap { border: 1px solid var(--line); border-radius: 16px; overflow-x: auto;
            background: var(--surface); }
.cmp { width: 100%; border-collapse: collapse; font-size: 14px; text-align: left;
       min-width: 560px; }
.cmp th { background: var(--surface-2); border-bottom: 1px solid var(--line);
          padding: 14px 18px; font-size: 11.5px; letter-spacing: .08em; }
.cmp th:last-child { color: var(--green); }
.cmp td { padding: 15px 18px; border-bottom: 1px solid var(--line-soft);
          vertical-align: top; }
.cmp td:first-child { color: var(--muted); width: 28%; }
.cmp td:nth-child(2) { color: var(--faint); }
.cmp td:last-child { color: var(--text); font-weight: 560; }
.cmp tr:last-child td { border-bottom: none; }
.cmp tr.fair td { background: var(--surface-2); }
.cmp tr.fair td:last-child { font-weight: 400; color: var(--muted); }

/* --- compact definitions rather than a fifth card grid ------------------ */
.defs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
        border: 1px solid var(--line); border-radius: 16px; overflow: hidden; }
.defs > div { padding: 24px 22px; border-right: 1px solid var(--line);
              background: var(--surface); }
.defs > div:last-child { border-right: none; }
@media (max-width: 900px) {
  .defs > div { border-right: none; border-bottom: 1px solid var(--line); }
  .defs > div:last-child { border-bottom: none; }
}
.defs .tag {
  display: inline-block; font-family: var(--mono); font-size: 10.5px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--green); background: var(--green-bg);
  border: 1px solid var(--green-dim); padding: 3px 9px; border-radius: 999px;
  margin-bottom: 12px;
}
.defs h3 { margin: 0 0 7px; font-size: 15.5px; }
.defs p { margin: 0; color: var(--muted); font-size: 13.5px; }
.conclusion {
  margin-top: 16px; padding: 20px 24px; border-radius: 16px;
  border: 1px solid var(--green-dim); background: var(--green-bg);
  font-size: 15.5px; max-width: 80ch;
}

/* --- trust as a checklist ----------------------------------------------- */
.checks { list-style: none; padding: 0; margin: 0; display: grid; gap: 18px;
          grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr)); }
.checks li { display: flex; gap: 13px; align-items: flex-start; }
.checks .ico { width: 28px; height: 28px; border-radius: 9px; margin: 0; }
.checks .ico svg { width: 15px; height: 15px; }
.checks b { display: block; font-size: 15px; margin-bottom: 4px; }
.checks span { color: var(--muted); font-size: 13.5px; }

body { padding-bottom: 0; }

/* Sections get a full-width hairline, so the page reads as chapters. */
.section { padding: 72px 0; border-top: 1px solid var(--line-soft); }


/* ---------- footer ----------
   One sentence and no links was not a footer. A visitor evaluating an infrastructure
   product looks here for the legal position and the security page before they look at
   the price. */
.site-footer { border-top: 1px solid var(--line); margin-top: 60px; padding: 48px 0 32px; }
.footer-grid {
  display: grid; gap: 34px;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
}
.footer-grid > * { min-width: 0; }
/* auto-fit with a 150px minimum still demanded 260 + 150 + gap on a phone and pushed
   the page sideways. Explicit breakpoints instead of a formula that cannot collapse. */
@media (max-width: 860px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .footer-grid { grid-template-columns: minmax(0, 1fr); gap: 26px; } }
.footer-brand { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; }
.footer-brand .mark { width: 24px; height: 24px; }
.footer-brand b { font-size: 16px; letter-spacing: -.2px; }
.site-footer p { color: var(--muted); font-size: 13.5px; margin: 0 0 8px; max-width: 42ch; }
.site-footer h4 {
  font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 13px; font-weight: 650;
}
.site-footer ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 9px; }
.site-footer ul a { color: var(--muted); font-size: 13.5px; }
.site-footer ul a:hover { color: var(--green); }
.footer-base {
  display: flex; flex-wrap: wrap; gap: 12px 22px; align-items: center;
  margin-top: 38px; padding-top: 22px; border-top: 1px solid var(--line-soft);
  color: var(--faint); font-size: 12.5px;
}
.footer-base .spacer { flex: 1; }

/* Keyboard users should not have to tab through the whole nav to reach the page. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--green); color: #04160f; padding: 10px 16px; border-radius: 0 0 10px 0;
  font-weight: 650; font-size: 14px;
}
.skip:focus { left: 0; text-decoration: none; }

/* ========================================================================
   Architecture panel — the page's centrepiece visual.

   Composition borrowed from Gravitee: one bordered stage, entity cards with an
   icon and a subtitle, status chips carrying a severity tag, and a before/after
   state you can flip. Their version drags; ours toggles, because a drag handle
   on a diagram this tall fights the page scroll on a phone.

   What differs: their chips list threats in the abstract. Ours carry figures the
   engine produced, and the "after" state shows what it actually did about each.
   ======================================================================== */
.stage {
  position: relative; border: 1px solid var(--line); border-radius: 20px;
  background: var(--surface); padding: 22px; overflow: hidden;
}
.stage-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 22px;
}
.state-pill {
  display: inline-flex; align-items: center; gap: 8px; padding: 6px 14px;
  border-radius: 999px; font-size: 11.5px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; border: 1px solid var(--line); background: var(--surface-2);
  color: var(--muted);
}
.state-pill i { width: 7px; height: 7px; border-radius: 50%; background: var(--red); }
.stage.after .state-pill i { background: var(--green); }
.stage.after .state-pill { color: var(--green); border-color: var(--green-dim);
                           background: var(--green-bg); }

.stage-lane { position: relative; z-index: 1; }
.lane-label {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint); margin: 0 0 12px;
}
.entities { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px,100%),1fr));
            gap: 10px; }
.entity {
  display: flex; align-items: center; gap: 11px; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--surface-2);
}
.entity .e-ico {
  width: 30px; height: 30px; border-radius: 9px; flex: none; display: grid;
  place-items: center; background: var(--surface); border: 1px solid var(--line);
}
.entity .e-ico svg { width: 15px; height: 15px; stroke: var(--muted); fill: none;
                     stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.entity b { display: block; font-size: 13.5px; line-height: 1.25; }
.entity span { color: var(--faint); font-size: 11.5px; font-family: var(--mono); }

/* status chips: a dot on the left, a severity tag on the right */
.chips { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(250px,100%),1fr));
         gap: 10px; }
.chip {
  display: flex; align-items: center; gap: 10px; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--surface-2);
  font-size: 13px;
}
.chip i { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--red); }
.chip .txt { flex: 1; min-width: 0; }
.chip .tag {
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 6px; border: 1px solid; white-space: nowrap;
}
.chip.bad i { background: var(--red); }
.chip.bad .tag { color: var(--red); border-color: color-mix(in srgb, var(--red) 45%, transparent);
                 background: var(--red-bg); }
.chip.warn i { background: var(--amber); }
.chip.warn .tag { color: var(--amber); border-color: color-mix(in srgb, var(--amber) 45%, transparent);
                  background: var(--amber-bg); }
.chip.good i { background: var(--green); }
.chip.good .tag { color: var(--green); border-color: var(--green-dim);
                  background: var(--green-bg); }

/* the gateway slab, only present in the "after" state */
.gw-slab {
  display: flex; align-items: center; gap: 14px; padding: 16px 18px; border-radius: 14px;
  border: 1px solid var(--green-dim); background: var(--green-bg);
}
.gw-slab .mark { width: 30px; height: 30px; }
.gw-slab b { font-size: 15px; letter-spacing: -.2px; display: block; }
.gw-slab span { color: var(--muted); font-size: 12.5px; }
.gw-slab .live {
  margin-left: auto; font-family: var(--mono); font-size: 10px; letter-spacing: .1em;
  color: var(--green); border: 1px solid var(--green-dim); border-radius: 999px;
  padding: 3px 9px; white-space: nowrap;
}

/* the wiring between lanes */
.wires { height: 54px; position: relative; margin: 6px 0; }
.wires svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.wires path { fill: none; stroke: var(--line); stroke-width: 1.5; }
.stage:not(.after) .wires path {
  stroke: color-mix(in srgb, var(--red) 38%, transparent); stroke-dasharray: 3 4;
}
.stage.after .wires path { stroke: var(--green-dim); stroke-dasharray: none; }

/* heading with the verbs picked out, the way Gravitee colours its claim */
.big-h .hl { color: var(--green); }

/* ---------- the spend chart ----------
   One panel, one question: is the gap widening? Everything else is chrome, so
   the grid is almost invisible and the band carries the colour. */
.chart-panel {
  border: 1px solid var(--line); border-radius: 18px; background: var(--surface);
  padding: 22px 24px 18px; margin-top: 26px;
}
.chart-head {
  display: flex; flex-wrap: wrap; gap: 12px 20px;
  align-items: baseline; justify-content: space-between; margin-bottom: 18px;
}
.chart-title { font-size: 14.5px; font-weight: 560; }
.chart-legend { display: flex; flex-wrap: wrap; gap: 16px; font-size: 12.5px; color: var(--muted); }
.chart-legend .lg { display: inline-flex; align-items: center; gap: 7px; }
.chart-legend i { width: 14px; height: 0; border-top: 2px solid currentColor; flex: none; }
.chart-legend .lg-base { color: var(--faint); }
.chart-legend .lg-base i { border-top-style: dashed; }
.chart-legend .lg-act { color: var(--green); }

.chart { height: 230px; }
.chart svg { width: 100%; height: 100%; display: block; overflow: visible; }
.chart .g    { stroke: var(--line-soft); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* An explicit tint rather than --green-bg: that token is near-white in light
   mode, and the gap is the whole message, so it has to read the same in both. */
.chart .band { fill: var(--green); fill-opacity: .13; stroke: none; }
.chart .paid { fill: var(--text); fill-opacity: .05; stroke: none; }
.chart .base { fill: none; stroke: var(--muted); stroke-width: 1.5; stroke-dasharray: 4 4;
               vector-effect: non-scaling-stroke; }
.chart .act  { fill: none; stroke: var(--green); stroke-width: 2;
               vector-effect: non-scaling-stroke; stroke-linejoin: round; }

.chart-axis {
  display: flex; justify-content: space-between; margin-top: 10px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--faint);
}
.chart-figs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  gap: 2px; margin-top: 22px; border-top: 1px solid var(--line-soft); padding-top: 20px;
}
.chart-figs > div { display: flex; flex-direction: column; gap: 4px; }
.chart-figs b { font-size: 25px; font-weight: 600; letter-spacing: -.02em; }
.chart-figs span { font-size: 12.5px; color: var(--muted); }
.chart-note { margin: 18px 0 0; font-size: 12px; color: var(--faint); max-width: 74ch; }

@media (max-width: 620px) {
  .chart-panel { padding: 18px 16px 16px; }
  .chart { height: 180px; }
  .chart-figs b { font-size: 21px; }
}

/* ---------- sign-in code ----------
   Six characters, spaced like the thing it is. A normal text input makes people
   check twice whether they typed five digits or six. */
.code-input {
  font-family: var(--mono); font-size: 27px; letter-spacing: .38em;
  text-align: center; padding: 14px 10px 14px 20px;
}
.code-input::placeholder { letter-spacing: .38em; opacity: .25; }

/* ---------- budget bar ----------
   Capped at 100% width even when spend is over: a bar spilling out of its track
   reads as a rendering bug, and the percentage above it already says 140%. */
.budget-state { display: flex; align-items: baseline; justify-content: space-between;
                gap: 12px; margin-bottom: 10px; }
.budget-bar { height: 8px; border-radius: 999px; background: var(--surface-2);
              overflow: hidden; }
.budget-bar i { display: block; height: 100%; background: var(--green);
                border-radius: 999px; transition: width .25s ease; }
.budget-bar.warn i { background: var(--amber); }
.budget-bar.over i { background: var(--red); }

/* ---------- key line + danger zone ---------- */
.keyline { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
           padding: 11px 14px; border: 1px solid var(--line); border-radius: 10px;
           background: var(--surface-2); word-break: break-all; }
.danger-zone { border-top: 1px solid var(--line); padding-top: 18px; margin-top: 4px; }
.btn-danger { background: var(--red); border-color: transparent; color: #fff; }
.btn-danger:hover { filter: brightness(1.08); }

/* ---------- model picker ----------
   A long single-column checkbox list pushes the save button off the drawer; two
   columns keeps the whole rule visible while you are writing it. */
.model-grid { display: grid; gap: 8px 18px;
              grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
              max-height: 260px; overflow-y: auto; padding: 4px 2px; }
.model-grid .inline { font-size: 13px; }

/* A jump-to-section menu item that only scrolls reads as broken when the target
   was already on screen. Two seconds of ring, then gone. */
@keyframes lematev-flash {
  from { box-shadow: 0 0 0 2px var(--green); }
  to   { box-shadow: 0 0 0 2px transparent; }
}
.flash { animation: lematev-flash 1.6s ease-out 1; }
@media (prefers-reduced-motion: reduce) { .flash { animation: none; } }

/* ================= motion =================
   Every rule here is a no-op under prefers-reduced-motion, and every animated
   element is fully visible before the script runs. A page whose content depends
   on JavaScript to become readable is a page that is blank when the script fails
   — so `.reveal` only does something once JS adds `.reveal-on` to <html>. */

.reveal-on .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .55s cubic-bezier(.22,.61,.36,1),
              transform .55s cubic-bezier(.22,.61,.36,1);
}
.reveal-on .reveal.in { opacity: 1; transform: none; }
/* Children stagger so a grid of cards arrives as a sequence rather than a slab. */
.reveal-on .reveal[data-stagger] > * {
  opacity: 0; transform: translateY(14px);
  transition: opacity .5s cubic-bezier(.22,.61,.36,1),
              transform .5s cubic-bezier(.22,.61,.36,1);
}
.reveal-on .reveal[data-stagger].in > * { opacity: 1; transform: none; }
.reveal-on .reveal[data-stagger].in > *:nth-child(2) { transition-delay: .07s; }
.reveal-on .reveal[data-stagger].in > *:nth-child(3) { transition-delay: .14s; }
.reveal-on .reveal[data-stagger].in > *:nth-child(4) { transition-delay: .21s; }
.reveal-on .reveal[data-stagger].in > *:nth-child(5) { transition-delay: .28s; }

/* --- screenshots: lift slightly, and only on a device that can hover -------- */
.shot { transition: transform .4s cubic-bezier(.22,.61,.36,1),
                    box-shadow .4s ease; }
@media (hover: hover) {
  .shot:hover { transform: translateY(-4px); }
}
.shot--wide { margin: 26px 0 0; }
.shot--wide img { width: 100%; height: auto; display: block; border-radius: 14px; }

/* --- plan cards: the featured one should feel picked up -------------------- */
.plan { transition: transform .28s cubic-bezier(.22,.61,.36,1),
                    border-color .28s ease, box-shadow .28s ease; }
@media (hover: hover) {
  .plan:hover { transform: translateY(-5px); border-color: var(--green-dim); }
  .plan.featured:hover { transform: translateY(-7px); }
}

/* --- buttons: press, don't wobble ----------------------------------------- */
.btn { transition: transform .12s ease, background .2s ease,
                   border-color .2s ease, filter .2s ease; }
.btn:active { transform: translateY(1px); }

/* --- the stage toggle gets a moving indicator rather than a hard swap ------ */
.stage .entity, .stage .chip {
  transition: opacity .35s ease, transform .35s cubic-bezier(.22,.61,.36,1);
}

/* --- counters hold their width so the layout does not jump while counting -- */
.counting { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .reveal-on .reveal,
  .reveal-on .reveal[data-stagger] > * { opacity: 1 !important; transform: none !important;
                                         transition: none !important; }
  .shot, .plan, .btn, .stage .entity, .stage .chip { transition: none !important; }
}


/* ---------- locked features ----------
   Greyed and labelled, never removed. A section that vanishes on a cheaper plan
   leaves the customer unable to tell whether the feature broke, has no data, or
   is not theirs — and it sells nothing. */
.card.locked { position: relative; }
.locked-note {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 20px 22px; border: 1px dashed var(--line); border-radius: 14px;
  background: var(--surface-2);
}
.locked-note .lock { width: 22px; height: 22px; flex: none; fill: none;
                     stroke: var(--muted); stroke-width: 1.6; }
.locked-note > div { flex: 1; min-width: 200px; }
.locked-note b { display: block; font-size: 14px; margin-bottom: 4px; }
.locked-note span { font-size: 13px; color: var(--muted); }
.locked-note .btn { flex: none; }

/* First and last name side by side: two full-width boxes for two short words
   makes a short form look long, and a long form is one people abandon. */
.field.two-up { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 420px) { .field.two-up { grid-template-columns: 1fr; } }

/* Long-form documentation: headings that separate without shouting, and a list
   where the term and its explanation sit on one line rather than in a card. */
.doc-h { font-size: 21px; margin: 44px 0 10px; text-transform: none;
         color: var(--text); letter-spacing: -.01em; }
.doc-h3 { font-size: 16.5px; margin: 32px 0 8px; text-transform: none;
          color: var(--text); }
.defs li { list-style: none; padding: 14px 0; border-bottom: 1px solid var(--line-soft); }
.defs li:last-child { border-bottom: none; }
.defs li b { display: block; margin-bottom: 4px; font-size: 14.5px; }
.defs li span { color: var(--muted); font-size: 13.5px; }

/* The plan you are already on: present, legible, and not offering itself. */
.plan.current { border-color: var(--green-dim); }
.plan button[disabled] { opacity: .55; cursor: default; }
.plan button { width: 100%; }

/* Footer without the link columns: a brand line, and the legal links on one
   row. A privacy page nobody can reach is a legal problem, not a design one. */
.site-footer .footer-base { display: flex; flex-wrap: wrap; gap: 8px 20px;
                            align-items: center; margin-top: 26px; }
.site-footer .footer-base a { color: var(--muted); }
.site-footer .footer-base a:hover { color: var(--text); }


/* ---------- the hero's routing diagram ----------
   Six providers, one hub, and a pulse travelling the wire that was chosen.

   What it is NOT: a decorative cluster of logos. The wires are the point --
   they say this layer sits IN the path and picks one, which is the difference
   between this product and a dashboard that reports on calls afterwards. */
.wires { width: 100%; max-width: 520px; justify-self: end; }
.wires svg { width: 100%; height: auto; display: block; overflow: visible; }
@media (max-width: 960px) { .wires { justify-self: center; max-width: 420px; } }

/* The hub: Lematev. Filled rather than outlined, so the eye starts here and
   follows the wires out rather than hunting for the centre. */
.wire-hub circle {
  fill: var(--surface); stroke: var(--green); stroke-width: 1.5;
  filter: drop-shadow(0 0 16px color-mix(in srgb, var(--green) 28%, transparent));
}

/* Light in both themes, and no filter anywhere near it.
   Three of these marks are solid black. Lightening them on the dark theme meant
   `filter: invert(1)` on an SVG <image>, which browsers apply inconsistently --
   and where it is not applied, black on a dark tile is nothing at all. A light
   tile is legible for every mark in every browser, and it makes the logos read
   as objects sitting on the page rather than as ink printed into it. */
.wire-node rect {
  fill: #f4f7f8; stroke: rgba(13, 18, 20, .10); stroke-width: 1;
}

/* The wire itself: a faint constant line, because the connection exists whether
   or not a call is travelling it right now. */
.wire {
  fill: none; stroke: var(--line); stroke-width: 1.5;
  stroke-linecap: round;
}

/* And the call. A short bright dash walking the whole path, one wire at a time
   -- six staggered copies of the same 7.2s animation, so at any moment roughly
   one route is lit. A simultaneous pulse on all six would say "we broadcast",
   which is the opposite of what this product does. */
.wires svg::after { content: none; }
.wire-pulse {
  fill: none; stroke: var(--green); stroke-width: 2.4; stroke-linecap: round;
  stroke-dasharray: 26 1000; stroke-dashoffset: 1000;
  animation: wire-travel 7.2s linear infinite;
  animation-delay: calc(var(--i) * 1.2s);
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--green) 70%, transparent));
}
@keyframes wire-travel {
  0%        { stroke-dashoffset: 1000; opacity: 0; }
  3%        { opacity: 1; }
  /* 480 is comfortably past the longest path, so every pulse finishes rather
     than stopping short of its tile. */
  17%       { stroke-dashoffset: 480; opacity: 1; }
  20%, 100% { stroke-dashoffset: 480; opacity: 0; }
}

/* The tile the pulse just reached, acknowledging it. Same timing, same stagger:
   the two read as one event rather than as two things that happen to move. */
.wire-node {
  /* The lift is on the group, so the logo rides with its tile. */
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .28));
}
:root[data-theme="light"] .wire-node { filter: drop-shadow(0 4px 10px rgba(13, 18, 20, .10)); }
.wire-node rect {
  animation: wire-land 7.2s ease-out infinite;
  animation-delay: calc(var(--i) * 1.2s);
}
@keyframes wire-land {
  0%, 15%   { stroke: rgba(13, 18, 20, .10); }
  19%       { stroke: var(--green); }
  34%, 100% { stroke: rgba(13, 18, 20, .10); }
}

/* Asked to stop, it stops: the wires and the tiles stay exactly where they are,
   and nothing moves. The picture still says everything it has to say -- the
   information was never in the motion. */
@media (prefers-reduced-motion: reduce) {
  .wire-pulse { animation: none; opacity: 0; }
  .wire-node rect { animation: none; }
}


/* ---------- text beside a screenshot, the screenshot running off the edge ----
   A screenshot that stops at the text margin reads as an illustration. One that
   runs past the edge of the page reads as a window onto something larger, which
   is what it is: these are crops of a real dashboard.

   Nothing clips here. The page is kept from widening by `overflow-x: clip` on
   the body -- see that rule for why it is `clip` and not `hidden`. Clipping on
   this section instead would cut the picture off at the text margin, which is
   exactly the bleed it is meant to allow. */
.split {
  display: grid; align-items: center; gap: 44px;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  /* Deliberately NOT clipping here. Clipping on the section would cut the image
     at the text margin, which is precisely the bleed it is supposed to allow;
     the page is kept from widening by `overflow-x: clip` on the body instead. */
}
.split-text { min-width: 0; }
.split .checks { margin-top: 22px; }

/* The bleed. 16vw past the column on the outer side only -- the inner edge has
   to stay put or the gap between text and picture closes. */
.shot--bleed {
  margin: 0; border: 1px solid var(--line); background: var(--surface);
  border-radius: 20px; overflow: hidden; min-width: 0;
  width: calc(100% + min(16vw, 190px)); justify-self: start;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .34);
}
.split--flip .shot--bleed {
  justify-self: end;
  margin-left: calc(min(16vw, 190px) * -1);
  width: calc(100% + min(16vw, 190px));
}
.shot--bleed img { width: 100%; display: block; border-bottom: none; }
:root[data-theme="light"] .shot--bleed { box-shadow: 0 18px 44px rgba(13, 18, 20, .12); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .shot--bleed { box-shadow: 0 18px 44px rgba(13, 18, 20, .12); }
}

@media (max-width: 900px) {
  /* One column, and no bleed at all. On a phone a picture running off the edge
     is just a picture with its right side missing. */
  .split { grid-template-columns: 1fr; gap: 28px; }
  .split--flip .shot--bleed,
  .shot--bleed { width: 100%; margin-left: 0; justify-self: stretch; }
  /* And the text comes first in both, whichever order the markup is in: the
     heading has to arrive before the thing it describes. */
  .split--flip .split-text { order: -1; }
}
