/* ==========================================================================
   Keli marketing site — page layer.

   The Modernist design system (_ds/modernist-…/styles.css) is the source of
   truth for tokens and components; nothing in that file is edited. This sheet
   holds the page-level patterns the site repeats, built from those tokens.
   ========================================================================== */

/* — Brand accent ————————————————————————————————————————————————————————
   Modernist ships a red accent. Keli runs the same system in blue, so the
   accent ramp is re-pointed here once rather than per page. Every step is
   defined (not just the ones currently referenced) so no red can leak through
   a component that reaches for a step the pages don't use directly. */
:root {
  --color-accent: #1f47e0;
  --color-accent-100: #eef1ff;
  --color-accent-200: #dbe2ff;
  --color-accent-300: #b9c7ff;
  --color-accent-400: #7f96f5;
  --color-accent-500: #1f47e0;
  --color-accent-600: #1839bd;
  --color-accent-700: #122c93;
  --color-accent-800: #0d2069;
  --color-accent-900: #0a1745;

  /* Mono scheme: accent-2 reads as accent (see the system readme). */
  --color-accent-2: #1f47e0;
  --color-accent-2-100: #eef1ff;
  --color-accent-2-200: #dbe2ff;
  --color-accent-2-300: #b9c7ff;
  --color-accent-2-400: #7f96f5;
  --color-accent-2-500: #1f47e0;
  --color-accent-2-600: #1839bd;
  --color-accent-2-700: #122c93;
  --color-accent-2-800: #0d2069;
  --color-accent-2-900: #0a1745;

  /* Page rhythm, lifted from the repeated values in the design export. */
  --page-max: 1200px;
  --page-gutter: clamp(20px, 5vw, 72px);
  --rule: 2px solid var(--color-divider);
  --ink-78: color-mix(in srgb, var(--color-text) 78%, transparent);
  --ink-70: color-mix(in srgb, var(--color-text) 70%, transparent);
  --ink-60: color-mix(in srgb, var(--color-text) 60%, transparent);
  --ink-55: color-mix(in srgb, var(--color-text) 55%, transparent);
}

html { scroll-behavior: smooth; }
body { margin: 0; text-wrap: pretty; }

a { color: var(--color-accent); }
a:hover { color: var(--color-accent-700); }

/* Labels that a screen reader needs but the composition deliberately leaves
   blank — empty table headers, repeated "Start" links in the pricing rows. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* — Shell ——————————————————————————————————————————————————————————————— */
.container {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 var(--page-gutter);
}

/* The nav rule runs the full viewport while its contents stay on the page
   grid, so the gutter grows with the leftover space either side of 1200px. */
.site-nav {
  padding-inline: max(
    var(--page-gutter),
    calc((100% - var(--page-max)) / 2 + var(--page-gutter))
  );
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--color-bg);
}
.site-nav--static { position: static; }
.nav a,
.btn { white-space: nowrap; }
/* A step up from the system's 18px, to give the brand a little more presence
   against the nav links. */
.nav-brand { font-size: 20px; }

/* The mark sits flush left of the wordmark, sized to the cap height so the
   two read as one lockup rather than an icon next to a word. */
.nav-brand a {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.nav-brand img {
  width: 20px;
  height: 20px;
  display: block;
  flex: none;
}
/* Optical, not metric: centring the two boxes leaves the wordmark reading a
   touch high against the mark, so nudge it down. A transform keeps this out
   of layout, so the nav bar height is untouched. */
.nav-brand-text { transform: translateY(2px); }
.nav a.btn-primary { color: var(--color-bg); }
.nav a.btn-primary:hover { color: var(--color-bg); background: var(--color-accent-600); }

.site-footer {
  padding: 56px 0;
  font-size: 13px;
  line-height: 28px;
  color: var(--ink-70);
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
}
.site-footer--ruled { border-top: var(--rule); }
.footer-meta { margin-left: auto; }

/* — Type ———————————————————————————————————————————————————————————————
   The negative left margin optically aligns the first glyph of a display
   heading with the body copy beneath it. */
.hero-title,
.page-title,
.docs-title,
.poster-title {
  letter-spacing: -0.02em;
  margin: 0 0 0 -0.058em;
}
.hero-title { font-size: clamp(42px, 6.2vw, 84px); line-height: clamp(44.5px, 6.57vw, 89px); }
.page-title { font-size: clamp(38px, 5vw, 64px); line-height: clamp(40px, 5.3vw, 68px); }
.docs-title { font-size: clamp(34px, 4vw, 48px); line-height: clamp(36px, 4.2vw, 52px); }
.hero-title > span,
.page-title > span,
.poster-title > span { display: block; }

.kicker {
  display: block;
  font-size: 13px;
  line-height: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin: 0 0 14px;
}
.kicker--muted { color: var(--ink-70); }

.section-title {
  font-size: 32px;
  line-height: 42px;
  letter-spacing: -0.015em;
  margin: 0 0 14px;
  max-width: 34ch;
}
.subsection-title {
  font-size: 25px;
  line-height: 28px;
  letter-spacing: -0.015em;
  margin: 0 0 28px;
}

.lead {
  font-size: 17px;
  line-height: 28px;
  max-width: 58ch;
  margin: 34px 0 0;
}
.body-text {
  font-size: 15.5px;
  line-height: 28px;
  margin: 0;
  color: var(--ink-78);
}
.measure-52 { max-width: 52ch; }
.measure-58 { max-width: 58ch; }

.note {
  font-size: 13px;
  line-height: 28px;
  color: var(--ink-70);
  margin: 14px 0 0;
}
.fineprint {
  font-size: 11px;
  color: var(--ink-55);
  margin-top: 4px;
}

/* — Sections ———————————————————————————————————————————————————————————— */
.section { padding: 84px 0 70px; }
.section--hero { padding: 112px 0 56px; }
.section--page-hero { padding: 84px 0 56px; }
.section--stats { padding: 70px 0; }
.section--last { padding-bottom: 98px; }

.actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 28px;
}
/* Modernist sets button labels flush left; a button wider than its label must
   not centre the text. */
.btn { justify-content: flex-start; }
.btn-icon { justify-content: center; }

/* — Stats band —————————————————————————————————————————————————————————— */
.stats {
  display: grid;
  grid-template-columns: repeat(4, auto);
  justify-content: space-between;
  gap: 42px 28px;
}
.stat-value {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: clamp(34px, 3.4vw, 48px);
  line-height: 56px;
  color: var(--color-accent);
  margin: 0 0 0 -0.045em;
}
.stat-label {
  font-size: 13px;
  line-height: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-70);
  margin: 14px 0 0;
}

/* — Numbered rows ——————————————————————————————————————————————————————— */
.step-row {
  display: grid;
  grid-template-columns: minmax(64px, 160px) minmax(0, 420px) minmax(0, 1fr);
  gap: 28px clamp(24px, 4vw, 72px);
  align-items: baseline;
  padding: 42px 0;
}
.step-row + .step-row { border-top: var(--rule); }

.install-row {
  display: grid;
  grid-template-columns: minmax(64px, 120px) minmax(0, 1fr);
  gap: 28px clamp(24px, 4vw, 72px);
  align-items: baseline;
  padding: 28px 0;
}
.install-row:first-of-type { padding-top: 0; }
.install-row + .install-row { border-top: var(--rule); }
.install-row:last-of-type { border-bottom: var(--rule); }

.step-num {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 15px;
  line-height: 28px;
  margin: 0;
}
.step-head {
  font-size: 24px;
  line-height: 28px;
  letter-spacing: -0.01em;
  margin: 0;
}
.install-head {
  font-size: 20px;
  line-height: 28px;
  margin: 0;
}

/* — Ask / outcome rows —————————————————————————————————————————————————— */
.ask-row {
  border-top: var(--rule);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px clamp(24px, 4vw, 72px);
  padding: 28px 0;
}
.ask-row:last-of-type { border-bottom: var(--rule); }
.ask-quote {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 20px;
  line-height: 28px;
  letter-spacing: -0.01em;
  margin: 0;
}
.ask-outcome { margin: 8px 0 0; }

/* — Card grid ——————————————————————————————————————————————————————————
   A 2px gap over a divider-coloured bed draws the grid rules, so the cells
   read as cut from one sheet rather than as floating cards. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 2px;
  background: var(--color-divider);
}
.card-grid .card {
  padding: 28px;
  background: var(--color-bg);
}
.card-grid .card-title { font-size: 19px; }
.card-grid .card-body { font-size: 14px; line-height: 24px; opacity: 1; color: var(--ink-78); }

/* — Boxes ——————————————————————————————————————————————————————————————— */
.panel { border: var(--rule); padding: 28px; }
.panel-title { font-size: 20px; line-height: 28px; margin: 0 0 14px; }
.panel-list { display: flex; flex-direction: column; gap: 2px; }
.panel-list .btn-block { margin-top: 0; }

/* Platforms that aren't downloadable yet: stated as rows, not as buttons —
   nothing here is clickable, so nothing should look like it is. */
.platform-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--color-divider);
}
.platform-list li {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-divider);
  font-size: 14px;
}
.platform-list .tag { margin-left: auto; }

.callout { border: var(--rule); padding: 20px 24px; }
.callout + .callout { margin-top: 14px; }
.callout-label {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin: 0 0 8px;
}
.callout-label--muted { color: var(--ink-60); }
.callout .body-text { color: var(--color-text); }

/* — Tables ——————————————————————————————————————————————————————————————
   Wide tables scroll rather than crush; the rules stay 2px either way. */
.table-wrap { overflow-x: auto; }
.table-wrap .table { min-width: 520px; }
.table .num { text-align: right; }

/* The leading cell of each body row is a row header for screen readers, but
   the design draws it as an ordinary bold cell — not as the uppercase label
   the system gives a column header. Undo the header styling for these only. */
.table tbody th {
  padding: var(--space-2);
  border-bottom: 1px solid var(--color-divider);
  text-align: left;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--color-text);
}

/* — Poster banner ———————————————————————————————————————————————————————
   The one place the accent runs as a field. */
.poster {
  background: var(--color-accent);
  color: var(--color-bg);
}
.poster .container { padding-block: 84px; }
.poster-title {
  font-size: clamp(34px, 4.2vw, 56px);
  line-height: clamp(36px, 4.45vw, 59.4px);
  letter-spacing: -0.015em;
}
.poster-actions { margin-top: 42px; }
.btn-on-accent {
  color: var(--color-bg);
  border: 1px solid var(--color-bg);
  padding: 8px 14.4px;
}
.btn-on-accent:hover {
  color: var(--color-bg);
  background: color-mix(in srgb, var(--color-bg) 16%, transparent);
}
.btn-on-accent:active {
  background: color-mix(in srgb, var(--color-bg) 26%, transparent);
}
.poster :focus-visible { outline-color: var(--color-bg); }

/* — App screenshot ——————————————————————————————————————————————————————
   The mock is authored at a fixed 1360×860 and scaled to whatever width the
   frame gets. site.js keeps --app-scale in step with the frame; the value
   below is the ratio at the full 1200px page width, used before script runs
   and if it never does. */
.app-frame {
  --app-scale: 0.88235;
  border: var(--rule);
  overflow: hidden;
  background: #fcfcfd;
  height: calc(860px * var(--app-scale));
}
.app-scale {
  width: 1360px;
  height: 860px;
  transform: scale(var(--app-scale));
  transform-origin: top left;
}

/* — Docs ————————————————————————————————————————————————————————————————— */
.docs-layout {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  gap: 0 clamp(24px, 4vw, 72px);
  align-items: start;
}
.docs-aside {
  position: sticky;
  top: 76px;
  padding: 56px 0;
}
.docs-toc {
  display: flex;
  flex-direction: column;
  border-top: var(--rule);
}
.docs-toc a {
  padding: 8px 0;
  border-bottom: 1px solid var(--color-divider);
  font-size: 14px;
  text-decoration: none;
  color: inherit;
}
.docs-toc a:hover,
.docs-toc a[aria-current='true'] { color: var(--color-accent); }
.docs-main {
  padding: 56px 0 84px;
  max-width: 68ch;
}
.docs-main .lead { margin-top: 28px; }
.docs-section + .docs-section { margin-top: 0; }
.docs-section .subsection-title { margin-bottom: 14px; }
.docs-section p + p { margin-top: 14px; }
.docs-section .body-text { color: var(--color-text); }
.docs-rule { margin: 42px 0; }

/* — Reveal on scroll ————————————————————————————————————————————————————
   site.js adds .is-revealed as sections come into view. The hidden state is
   only applied once the script confirms motion is welcome, so with JS off or
   reduced motion on, content is simply visible. */
.reveal-ready [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 620ms cubic-bezier(.22, .61, .36, 1),
    transform 620ms cubic-bezier(.22, .61, .36, 1);
}
.reveal-ready [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* — Responsive ——————————————————————————————————————————————————————————
   The desktop composition above is the design as delivered; these breakpoints
   only unwind the multi-column grids, which are authored at fixed canvas
   widths and have no small-screen form in the export. */
@media (max-width: 900px) {
  .docs-layout { grid-template-columns: minmax(0, 1fr); }
  .docs-aside { position: static; padding: 42px 0 0; }
  .docs-main { padding-top: 42px; }
  .step-row { grid-template-columns: minmax(56px, 96px) minmax(0, 1fr); }
  .step-row .step-body { grid-column: 2; }
}

@media (max-width: 760px) {
  .section { padding: 56px 0 42px; }
  .section--hero { padding: 64px 0 42px; }
  .section--page-hero { padding: 56px 0 42px; }
  .section--stats { padding: 42px 0; }
  .section--last { padding-bottom: 64px; }

  .site-nav { flex-wrap: wrap; gap: var(--space-3) var(--space-4); }
  .nav-brand { width: 100%; margin-right: 0; }

  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); justify-content: start; gap: 32px 24px; }

  .step-row,
  .install-row { grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 28px 0; }
  .step-row .step-body { grid-column: auto; }
  .step-num { line-height: 20px; }

  .ask-row { grid-template-columns: minmax(0, 1fr); }

  .hero-grid { grid-template-columns: minmax(0, 1fr) !important; }

  .poster .container { padding-block: 56px; }
  .poster-actions { margin-top: 28px; }

  .site-footer { padding: 42px 0; gap: 8px 28px; }
  .footer-meta { margin-left: 0; width: 100%; }
}

@media (max-width: 560px) {
  .card-grid { grid-template-columns: minmax(0, 1fr); }
  .actions .btn { width: 100%; }
}

@media print {
  .site-nav { position: static; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}
