/*
 * kronikl.io — landing page styles.
 *
 * Tokens are the brand's own sheet, `apps/web/design/landing-mockup/src/index.css`,
 * copied verbatim. The product's `apps/web/src/styles.css` reads from the same source;
 * if a value here disagrees with one there, the mockup wins and both get corrected.
 *
 * Two things this file does that the mockup does not:
 *
 * 1. **Fonts are self-hosted.** The mockup `@import`s Google Fonts. `apps/web` already
 *    refuses to, and the reason it gives is written for exactly the reader this page is
 *    for: "what third parties does your app talk to" is the first question in an
 *    enterprise security review, and a governance vendor whose *marketing* page phones
 *    a CDN has answered it badly before the reviewer reaches the product. Same
 *    typefaces, same origin, no third-party request on this page at all.
 *
 * 2. **Dark is a first-class ground, not an inversion.** The mockup is light-only with
 *    dark product surfaces embedded in it. Here `prefers-color-scheme` and an explicit
 *    toggle both work, and the embedded product surfaces stay dark in both — they are
 *    renderings of a dark-default product, and re-tinting them would misrepresent it.
 */

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono-variable.woff2') format('woff2-variations');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

/* ── Tokens ────────────────────────────────────────────────────────────────── */

:root {
  /* The one arrow this site draws, and it is drawn rather than typed. The character was
     U+2192, which neither shipped font contains — `inter-variable.woff2` here is
     byte-identical to the product's, measured from its cmap — so every arrow was rendered
     by whatever the visitor's operating system offered. A mask rather than a
     background-image, so `color` still controls it. Nothing uses it today; keep it, and
     use it, rather than typing the character back in. */
  --arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E");
  color-scheme: light;

  /* Page ground — the mockup's --page-* palette. */
  --page-bg: #ffffff;
  --page-mid: #f7f8fa;
  --page-sunk: #fafafa;
  --page-border: #e5e7eb;
  --page-border-2: #d1d5db;
  --page-text: #111827;
  --page-text-2: #374151;
  /*
   * One deviation from the brand sheet, measured rather than guessed. The mockup's
   * `--page-muted: #6B7280` and `--page-faint: #9CA3AF` give 4.83:1 and 2.39:1 against
   * white; the faint one carries the plan footnotes, the "vs. them"
   * column and the footer, all at 11–13px, and 2.39:1 is not a near miss. Both greys
   * move one step darker, keeping the same two-step hierarchy and clearing WCAG AA on
   * every ground this page uses (7.1:1 and 4.55:1 at worst).
   */
  --page-muted: #4b5563;
  --page-faint: #6b7280;

  /* Accent. */
  --accent: #2563eb;
  --accent-h: #1d4fd1;
  --accent-2: #7c3aed;
  --accent-wash: #eff6ff;
  --accent-wash-border: #dbeafe;
  --accent-on-wash: #1d4ed8;

  /* Product surfaces — the app is dark, and stays dark inside this page. */
  --app-bg: #0a0d14;
  --app-surface: #111620;
  --app-surface-2: #161c2a;
  --app-border: #1e2a3d;
  --app-border-2: #253347;
  --app-text: #e8edf5;
  /*
   * The product's own `--muted` (#5A6A84) and `--muted2` (#3D4F68) are 3.3:1 and 2.2:1
   * on these surfaces. Inside the product that is a question for the product; on a
   * marketing page the same values would be 10px text nobody can read, so both are
   * lifted to clear AA while staying the same hue. If the product's palette is ever
   * corrected, take its values back — that is the direction the copying goes.
   */
  --app-muted: #8a99b2;
  --app-faint: #75869f;

  /* One colour per change type. Identical to change_events.change_type in the product;
     do not introduce a second palette. */
  --crud: #10b981;
  --policy: #f59e0b;
  --rbac: #8b5cf6;
  --pim: #ef4444;

  /*
   * Same four hues, lightened, for the two that fail as *text* on their own 12% wash
   * (violet 3.5:1, red 4.0:1 at 9.5px). Borders, dots and rules keep the canonical
   * value; only the label text uses these, so the one-colour-per-change-type mapping
   * survives intact.
   */
  --crud-text: #34d399;
  --policy-text: #fbbf24;
  --rbac-text: #a78bfa;
  --pim-text: #f87171;

  /*
   * Filled surfaces — buttons, the beta badge, the skip link. Fixed rather than
   * `var(--accent)`, because the dark theme lightens the accent so it reads on a dark
   * ground, and white on that lighter blue is 3.6:1. White on this is 5.2:1 in both
   * themes, and a primary call to action is the last thing that should fail contrast.
   */
  --accent-solid: #2563eb;
  --accent-solid-h: #1d4fd1;

  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --shell: 1120px;
  --radius: 10px;
  --radius-sm: 6px;

  --note-bg: #fffbeb;
  --note-border: #fde68a;
  --note-text: #854d0e;
}

/*
 * Dark ground. Defined once and applied by both the media query and the explicit
 * attribute, so the toggle wins in both directions and the default follows the OS.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;
    --page-bg: #0a0d14;
    --page-mid: #111620;
    --page-sunk: #0d111a;
    --page-border: #1e2a3d;
    --page-border-2: #253347;
    --page-text: #e8edf5;
    --page-text-2: #c3cddd;
    /* Same measurement, same conclusion: 3.3:1 for the faint grey is a fail. */
    --page-muted: #9aa7bd;
    --page-faint: #7d8da8;
    --accent: #4b83f0;
    --accent-h: #6b9bf5;
    --accent-wash: rgba(37, 99, 235, 0.12);
    --accent-wash-border: rgba(37, 99, 235, 0.28);
    --accent-on-wash: #8fb4f7;
    --note-bg: rgba(245, 158, 11, 0.1);
    --note-border: rgba(245, 158, 11, 0.32);
    --note-text: #f0c473;
  }
}

/*
 * Dark theme.
 *
 * One rule governs the whole block, and it is the one the first version broke: **elevation
 * must mean the same thing in both themes.** In light, a surface that sits above the page
 * is lighter than its ground. In dark it must also be lighter than its ground — not
 * darker, and never identical.
 *
 * What went wrong: `--page-bg` and `--app-bg` were both #0a0d14, so the product figures —
 * the only images on this page proving the product exists — sat on a ground of their own
 * colour, separated by one hairline, under a shadow that is invisible on black. The
 * audience most likely to be reading in dark is an Azure administrator, and for them the
 * page's proof stopped looking like a product. Meanwhile the pricing cards rendered
 * DARKER than the band containing them, so the two objects at the decision point receded
 * instead of rising.
 */
:root[data-theme='dark'] {
  color-scheme: dark;
  --page-bg: #0a0d14;
  --page-mid: #111620;
  --page-sunk: #0d111a;
  --page-border: #1e2a3d;
  --page-border-2: #253347;
  --page-text: #e8edf5;
  --page-text-2: #c3cddd;
  --page-muted: #9aa7bd;
  --page-faint: #7d8da8;
  --accent: #4b83f0;
  --accent-h: #6b9bf5;
  --accent-wash: rgba(37, 99, 235, 0.12);
  --accent-wash-border: rgba(37, 99, 235, 0.28);
  --accent-on-wash: #8fb4f7;
  --note-bg: rgba(245, 158, 11, 0.1);
  --note-border: rgba(245, 158, 11, 0.32);
  --note-text: #f0c473;
}

/*
 * The figures become objects again: a ground one step above the page, a brighter ring,
 * and a top highlight doing the work the drop shadow cannot do on a near-black ground.
 */
:root[data-theme='dark'] .app {
  background: var(--app-surface);
  border-color: var(--app-border-2);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 18px 48px rgba(0, 0, 0, 0.55);
}

/* Cards and plans rise rather than sink, matching light-theme behaviour. */
:root[data-theme='dark'] .card,
:root[data-theme='dark'] .plan,
:root[data-theme='dark'] .compare-group {
  background: var(--page-mid);
  border-color: var(--page-border-2);
}

:root[data-theme='dark'] section.alt .card,
:root[data-theme='dark'] section.alt .compare-group {
  /* Inside a raised band, rise one step further so the card still reads as an object. */
  background: #161c2a;
}

:root[data-theme='dark'] .plan--featured {
  background: #161c2a;
}

/* On a near-black ground a 1px hairline border is nearly invisible; the secondary button
   needs a ring the eye can actually find. */
:root[data-theme='dark'] .btn--secondary {
  border-color: var(--page-border-2);
}

/* ── Reset ─────────────────────────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body,
h1,
h2,
h3,
h4,
p,
ul,
ol,
li,
figure,
dl,
dd {
  margin: 0;
  padding: 0;
}

ul,
ol {
  list-style: none;
}

img,
svg {
  display: block;
  max-width: 100%;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--page-bg);
  color: var(--page-text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

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

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}

.mono {
  font-family: var(--mono);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 100;
  background: var(--accent-solid);
  color: #fff;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.15s;
}

.skip-link:focus {
  top: 12px;
}

/* ── Layout ────────────────────────────────────────────────────────────────── */

.shell {
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 24px;
}

.shell--narrow {
  max-width: 780px;
}

.shell--mid {
  max-width: 920px;
}

/*
 * ── The seam ───────────────────────────────────────────────────────────────
 *
 * Every boundary between two arguments on this page is the brand mark, stretched.
 *
 * `kronikl-mark.svg` is two vertical strokes at x=164 and x=348, the second offset 36px
 * downward, joined by a rule at their midpoint, with a filled dot at each junction and
 * the later one at 80% opacity. Read it once and it stops being a logo: it is the same
 * object at two moments, joined, with the newer state marked. It is the product's entire
 * thesis as a glyph, and it was being used at 26px in the header and nowhere else.
 *
 * So the section rule takes the mark's own geometry, laid on its side: a hairline that
 * carries a dot at each end, in the mark's gradient, the second dot lighter — before on
 * the left, after on the right. Scrolling the page crosses that seam eight times, and the
 * page performs the argument it is making instead of only describing it.
 *
 * It is one pseudo-element and no markup, which is the point. A device that costs a
 * wrapper per section would not survive the next edit.
 */
section {
  padding: 84px 0;
  border-top: 1px solid var(--page-border);
  position: relative;
  /* The header is sticky, so an anchored jump would otherwise land underneath it. */
  scroll-margin-top: 58px;
}

section::before,
section::after {
  content: '';
  position: absolute;
  top: -3.5px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  /* Centred on the seam and hard-edged against it — the mark's circles sit ON the rule,
     not beside it. */
  background: var(--accent);
}

/* Before, at the start of the measure. */
section::before {
  left: max(24px, calc(50vw - 620px));
}

/* After: the same point, later, and lighter — the mark's own 0.8 on its second circle,
   in the second stop of its gradient. */
section::after {
  right: max(24px, calc(50vw - 620px));
  background: var(--accent-2, #7c3aed);
  opacity: 0.8;
}

/* The hero opens the page; it has no argument before it to be joined to. */
.hero::before,
.hero::after {
  display: none;
}

@media (prefers-reduced-motion: no-preference) {
  section::before,
  section::after {
    transition: opacity 0.3s ease;
  }
}

section.alt {
  background: var(--page-mid);
}

.section-head {
  text-align: center;
  max-width: 620px;
  margin: 0 auto 48px;
}

.section-head h2 + .lede {
  margin-top: 14px;
}

h1 {
  /* The headline is two sentences and its whole power is the beat between them. Left to
     wrap naturally at 390px it broke as "Somebody changed it. Nobody / remembers who." —
     the pause landing inside the second sentence instead of between them. `balance`
     alone did not fix it, so the two beats are marked up and the break is made explicit
     below where the line is too narrow to hold one. */
  text-wrap: balance;
  font-size: clamp(34px, 6vw, 56px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.03em;
}

h2 {
  font-size: clamp(26px, 3.6vw, 32px);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h3 {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.35;
}

.lede {
  font-size: 17px;
  line-height: 1.65;
  color: var(--page-muted);
}

.lede--stacked {
  margin-bottom: 18px;
}

.lede--loose {
  margin-bottom: 32px;
}

code {
  font-family: var(--mono);
  font-size: 0.9em;
}

.fine {
  font-size: 13px;
  color: var(--page-faint);
}

/* ── Buttons ───────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 22px;
  border-radius: var(--radius-sm);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition:
    background 0.15s,
    border-color 0.15s,
    color 0.15s;
}

.btn--primary {
  background: var(--accent-solid);
  color: #fff;
}

.btn--primary:hover {
  background: var(--accent-solid-h);
}

.btn--secondary {
  background: transparent;
  color: var(--page-text);
  border-color: var(--page-border-2);
}

.btn--secondary:hover {
  border-color: var(--page-border-2);
  background: var(--page-mid);
}

.btn--sm {
  padding: 8px 16px;
  font-size: 14px;
}

.btn--block {
  width: 100%;
}

/* ── Header ────────────────────────────────────────────────────────────────── */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--page-bg) 90%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--page-border);
}

.site-header .shell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 58px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: var(--page-text);
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.03em;
  flex-shrink: 0;
}

.site-nav ul {
  display: flex;
  gap: 26px;
}

.site-nav a {
  font-size: 14px;
  font-weight: 500;
  color: var(--page-muted);
  text-decoration: none;
}

.site-nav a:hover {
  color: var(--page-text);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--page-border);
  background: transparent;
  color: var(--page-muted);
  cursor: pointer;
}

.theme-toggle:hover {
  color: var(--page-text);
  border-color: var(--page-border-2);
}

.theme-toggle .icon-dark {
  display: none;
}

:root[data-theme='dark'] .theme-toggle .icon-dark {
  display: block;
}

:root[data-theme='dark'] .theme-toggle .icon-light {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .theme-toggle .icon-dark {
    display: block;
  }
  :root:not([data-theme='light']) .theme-toggle .icon-light {
    display: none;
  }
}

/*
 * ── Mobile navigation ──────────────────────────────────────────────────────
 *
 * The nav used to be `display: none` below 860px with nothing in its place, on a page
 * that is 14,522px tall on a phone. A visitor who wanted the price had one option:
 * scroll seventeen screens. Most do not.
 *
 * A hamburger would be the reflex and it is the wrong instrument here. This page has four
 * destinations, all on one document; a menu would hide four links behind a tap and a
 * panel, to save a row that is 36px tall. The chips stay visible instead — the
 * destinations are the navigation, and on a marketing page the reader should never have
 * to ask where they can go.
 *
 * It scrolls horizontally rather than wrapping, so the header height is identical at
 * every width and the sticky offset below stays honest.
 */
@media (max-width: 860px) {
  .site-header .shell {
    flex-wrap: wrap;
    gap: 0 16px;
    padding-bottom: 8px;
  }

  .site-nav {
    order: 3;
    width: 100%;
    overflow-x: auto;
    /* `overflow-x: auto` makes the y axis clip too, and the focus ring sits 3px outside
       a chip. Padding gives it room; the negative margin gives the padding back. */
    padding: 5px 0;
    margin: -5px 0;
    /* Momentum on iOS, and no scrollbar eating 8px of a 390px screen. */
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .site-nav::-webkit-scrollbar {
    display: none;
  }

  .site-nav ul {
    gap: 8px;
    padding-bottom: 2px;
  }

  .site-nav a {
    display: inline-flex;
    align-items: center;
    /* 36px tall, so the row is a comfortable tap without the header eating the hero. */
    min-height: 36px;
    padding: 0 12px;
    white-space: nowrap;
    border: 1px solid var(--page-border);
    border-radius: 999px;
    background: var(--page-bg);
  }
}

/*
 * The header CTA stays visible at every width, and this rule is the reason it now says
 * so explicitly rather than being absent.
 *
 * It used to be `display: none` below 520px. The header is sticky, so hiding it left a
 * phone visitor with no way to act between the hero button and the pricing section —
 * about thirteen thousand pixels, sixteen phone screens, of a page whose entire job is
 * to get that click. Somebody persuaded by the security section had to scroll back to
 * the top or keep going to the end.
 *
 * It shrinks instead. A narrower button that is present converts; a comfortable one that
 * is absent does not.
 */
@media (max-width: 520px) {
  .header-actions .btn {
    /* 44px minimum, which is the touch target, not a preference. It was 37px — a thumb
       miss on a moving train, and it is the only persistent action on the page. Padding
       gives horizontally, never vertically. */
    min-height: 44px;
    padding: 0 14px;
    font-size: 13px;
  }

  /* The theme toggle yields first. On a 390px header there is room for the brand and one
     action, and the one action should be the one that earns money. */
  .theme-toggle {
    display: none;
  }

  /* …and that action is the visitor's door, not the returning customer's. */
  .header-signin-btn {
    display: none;
  }
  .header-connect-btn {
    display: inline-flex;
  }
  .nav-signin {
    display: list-item;
  }
}

.header-connect-btn,
.nav-signin {
  display: none;
}

/* ── Hero ──────────────────────────────────────────────────────────────────── */

.hero {
  border-top: none;
  /* A floor under the frame, so its shadow renders before the section rule instead of
     ending on a hard line. */
  padding: 88px 0 84px;
  text-align: center;
  position: relative;
}

.hero h1 {
  margin-bottom: 20px;
}

.hero .lede {
  font-size: 18px;
  max-width: 600px;
  margin: 0 auto 32px;
}

.badge-beta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--accent-wash);
  border: 1px solid var(--accent-wash-border);
  border-radius: 20px;
  padding: 4px 14px 4px 6px;
  margin-bottom: 28px;
  font-size: 13px;
  color: var(--accent-on-wash);
}

.badge-beta b {
  /* Fixed, not `var(--accent)`: the dark theme lightens the accent for legibility on a
     dark ground, and white on that lighter blue is 3.6:1 — a fail at 11px. */
  background: #2563eb;
  color: #fff;
  border-radius: 20px;
  padding: 2px 9px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
}

.cta-row {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

/*
 * On a phone the two buttons stack, and stacked they were sized by their label: the
 * secondary ("Read the security section first", 263px) came out 36% WIDER than the
 * primary ("Connect your tenant", 194px). The last thing a thumb met at the end of the
 * page was the button that does not convert.
 *
 * Equal width removes the accident, and the primary stays first in source order so it is
 * also first under the thumb.
 */
/* One beat per line, so the pause falls where the sentence does. Above this width the
   headline fits its natural rhythm and the browser is left alone. */
@media (max-width: 560px) {
  h1 .beat {
    display: block;
  }

  .cta-row {
    flex-direction: column;
    align-items: stretch;
  }

  .cta-row .btn {
    width: 100%;
    min-height: 48px;
  }
}

.hero-figure {
  max-width: 1080px;
  margin: 56px auto 0;
  padding: 0 24px;
  position: relative;
}

/* ── Problem cards ─────────────────────────────────────────────────────────── */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
}

.card {
  background: var(--page-bg);
  border: 1px solid var(--page-border);
  border-radius: var(--radius);
  padding: 24px;
}

/*
 * Inter, not mono — and this is the page's own typographic rule being applied, not a
 * preference.
 *
 * The split everywhere else is exact: Inter for what a person wrote, JetBrains Mono for
 * what a machine recorded — resource ids, timestamps, counts, CSV headers. "90 days",
 * "14 days" and "Nobody." are none of those. They are the argument, phrased by us.
 *
 * Setting them in mono also broke them typographically: monospace puts a full character
 * cell between "90" and "days", and leaves the full stop in "Nobody." floating a space
 * away from the word it belongs to. The rule was being applied as decoration — mono as a
 * costume for "technical" — which is exactly what it exists to avoid.
 */
.card .stat {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--page-text);
  margin-bottom: 10px;
}

.card p {
  font-size: 15px;
  color: var(--page-muted);
}

/* A card whose "stat" slot is a short label rather than a number. */
.card .stat--label {
  font-size: 15px;
  letter-spacing: -0.01em;
}

/* ── Steps ─────────────────────────────────────────────────────────────────── */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 32px;
  counter-reset: step;
}

.step h3 {
  margin: 12px 0 8px;
}

.step p {
  font-size: 14.5px;
  color: var(--page-muted);
}

.step-n {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--accent-wash);
  border: 1px solid var(--accent-wash-border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  color: var(--accent-on-wash);
}

/* ── Feature blocks ────────────────────────────────────────────────────────── */

.features {
  display: flex;
  flex-direction: column;
  gap: 88px;
}

.feature {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 48px;
  align-items: center;
}

.feature h2,
.feature .feature-h {
  font-size: clamp(24px, 3vw, 28px);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
  margin-bottom: 14px;
}

.feature > div > p {
  font-size: 15px;
  color: var(--page-muted);
  line-height: 1.7;
  margin-bottom: 18px;
}

.feature-figure {
  min-width: 0;
}

@media (min-width: 900px) {
  .feature--flip .feature-copy {
    order: 2;
  }
  .feature--flip .feature-figure {
    order: 1;
  }
}

.ticks {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.ticks li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 14.5px;
  color: var(--page-text-2);
  line-height: 1.5;
}

.ticks svg {
  flex-shrink: 0;
  margin-top: 4px;
}

/* ── Comparison ────────────────────────────────────────────────────────────── */

.compare {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

.compare-group {
  background: var(--page-mid);
  border: 1px solid var(--page-border);
  border-radius: var(--radius);
  overflow: hidden;
}

section.alt .compare-group {
  background: var(--page-bg);
}

.compare-group > h3 {
  padding: 14px 18px;
  background: var(--page-bg);
  border-bottom: 1px solid var(--page-border);
  font-size: 13px;
}

section.alt .compare-group > h3 {
  background: var(--page-mid);
}

/* A real table, because this is a comparison and the two sides have to line up.
 *
 * It was a definition list where both answers ran inline with an arrow between them, and
 * at every width narrow enough to wrap — which was most of them — the two sides became one
 * sentence of blue prose. Nothing said which half was whose. The column headers say it
 * once at the top, the tint carries it down the column, and `table-layout: fixed` keeps
 * the two halves the same width whatever the text does. */
.compare table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.compare thead th {
  width: 50%;
  padding: 9px 14px;
  text-align: left;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--page-muted);
  border-bottom: 1px solid var(--page-border);
}

.compare th.mine,
.compare td.mine {
  background: var(--accent-wash);
  border-left: 1px solid var(--accent-wash-border);
}

.compare thead th.mine {
  color: var(--accent-on-wash);
}

/* The criterion is a heading for the pair under it, not a third column: at 300px there is
   no room for one, and the label reads better above the two answers than beside them. It
   takes the header band's ground so the table reads as label, pair, label, pair, and the
   tinted half stays legible as a column between them. */
.compare tbody th {
  padding: 10px 14px;
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  color: var(--page-text-2);
  background: var(--page-bg);
}

section.alt .compare tbody th {
  background: var(--page-mid);
}

.compare tbody td {
  padding: 11px 14px 13px;
  vertical-align: top;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--page-faint);
}

.compare tbody td.mine {
  color: var(--page-text);
  font-weight: 600;
}

/* One tbody per criterion, so the row group is real for a screen reader; the separator
   sits between groups, not inside them. */
.compare tbody + tbody tr.criterion th {
  border-top: 1px solid var(--page-border);
}

/* ── Trust ─────────────────────────────────────────────────────────────────── */

.trust {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 16px;
}

.trust li {
  background: var(--page-bg);
  border: 1px solid var(--page-border);
  border-radius: var(--radius);
  padding: 20px 22px;
  display: flex;
  gap: 15px;
  align-items: flex-start;
}

.trust svg {
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--accent);
}

.trust h3 {
  font-size: 14.5px;
  margin-bottom: 6px;
}

.trust p {
  font-size: 13.5px;
  color: var(--page-muted);
  line-height: 1.6;
}

/* ── Pricing ───────────────────────────────────────────────────────────────── */

.plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 20px;
}

.plan {
  border: 1px solid var(--page-border);
  border-radius: var(--radius);
  padding: 26px;
  background: var(--page-sunk);
  display: flex;
  flex-direction: column;
}

.plan--featured {
  border: 2px solid var(--accent);
  background: var(--page-bg);
  box-shadow: 0 8px 32px rgba(37, 99, 235, 0.12);
}

.plan h3 {
  font-size: 16px;
  font-weight: 800;
  margin-bottom: 4px;
}

.plan .amount {
  /* Inter, not mono: a price is our number, not a machine's — the same rule the problem
     section's "90 days" follows, and for the same reason. */
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--page-text);
}

.plan .per {
  font-size: 13px;
  color: var(--page-faint);
  margin-left: 4px;
}

.plan > p {
  font-size: 13px;
  color: var(--page-muted);
  margin: 6px 0 20px;
}

.plan ul {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-bottom: 22px;
  flex: 1;
}

.plan li {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  font-size: 13.5px;
  color: var(--page-text-2);
}

.plan li svg {
  flex-shrink: 0;
  margin-top: 4px;
}

.note {
  background: var(--note-bg);
  border: 1px solid var(--note-border);
  color: var(--note-text);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  font-size: 13.5px;
  line-height: 1.6;
}

.note strong {
  font-weight: 700;
}

.note--spaced {
  margin-top: 24px;
}

.alerts-figure {
  margin-top: 24px;
}

/* ── FAQ ───────────────────────────────────────────────────────────────────── */

.faq {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.faq details {
  background: var(--page-bg);
  border: 1px solid var(--page-border);
  border-radius: 8px;
}

.faq summary {
  padding: 15px 18px;
  cursor: pointer;
  font-size: 14.5px;
  font-weight: 600;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: '';
  flex-shrink: 0;
  width: 9px;
  height: 9px;
  border-right: 1.6px solid var(--page-faint);
  border-bottom: 1.6px solid var(--page-faint);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.2s;
}

.faq details[open] summary::after {
  transform: rotate(225deg) translate(-2px, -2px);
}

.faq .answer {
  padding: 0 18px 16px;
  font-size: 14px;
  color: var(--page-muted);
  line-height: 1.7;
}

.faq .answer p + p {
  margin-top: 10px;
}

/* ── Final CTA + footer ────────────────────────────────────────────────────── */

.final {
  text-align: center;
}

.final h2 {
  font-size: clamp(28px, 4vw, 34px);
  margin: 18px 0 14px;
}

.final img {
  margin: 0 auto;
}

.site-footer {
  background: var(--page-mid);
  border-top: 1px solid var(--page-border);
  padding: 40px 0 28px;
}

.footer-cols {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 32px;
  margin-bottom: 32px;
}

.footer-cols h2 {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--page-faint);
  margin-bottom: 13px;
}

.footer-cols ul {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.footer-cols a {
  font-size: 13.5px;
  color: var(--page-muted);
  text-decoration: none;
}

.footer-cols a:hover {
  color: var(--page-text);
}

.footer-brand p {
  font-size: 13px;
  color: var(--page-faint);
  max-width: 230px;
  line-height: 1.6;
  margin-top: 10px;
}

.footer-base {
  border-top: 1px solid var(--page-border);
  padding-top: 18px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12px;
  color: var(--page-faint);
}

/* ── Legal pages ───────────────────────────────────────────────────────────────
 * privacy.html, and anything of the same shape later. Long-form prose is the one
 * thing the marketing page has none of: the reset zeroes every margin and strips
 * list markers, which is right for a page built out of cards and wrong for a
 * document meant to be read top to bottom.
 *
 * Deliberately not a `.prose` catch-all that styles bare elements globally — this
 * is scoped to `.legal` so it cannot reach into the interface drawings, whose
 * `<p>` and `<ul>` are laid out by hand.
 */

.legal {
  border-top: none;
  padding-top: 56px;
}

.legal h1 {
  font-size: clamp(30px, 5vw, 40px);
  margin-bottom: 16px;
}

.legal .updated {
  padding-bottom: 28px;
  border-bottom: 1px solid var(--page-border);
}

.legal h2 {
  font-size: 20px;
  margin: 44px 0 14px;
  scroll-margin-top: 74px;
}

.legal p {
  color: var(--page-text-2);
  margin-bottom: 14px;
}

.legal ul {
  list-style: disc;
  padding-left: 22px;
  margin-bottom: 14px;
}

.legal li {
  color: var(--page-text-2);
  margin-bottom: 9px;
}

.legal li:last-child {
  margin-bottom: 0;
}

.legal strong {
  color: var(--page-text);
  font-weight: 650;
}

.legal code {
  /* The surrounding text is 16px; monospace at the same size reads a step larger. */
  font-size: 0.88em;
  color: var(--page-text);
  background: var(--page-mid);
  border: 1px solid var(--page-border);
  border-radius: 4px;
  padding: 1px 5px;
  white-space: nowrap;
}

/* ── The consent table ─────────────────────────────────────────────────────────
 * connect.html only, and the counterpart of the inline styles in the product's
 * `ConsentPermissions.tsx`. Same two columns, same hierarchy: our name for the
 * permission leads, Microsoft's exact string sits under it in the quiet grey, and
 * the reason takes the right-hand column.
 *
 * The reset strips list markers and zeroes margins for the card-built marketing
 * page, so this is scoped rather than styling bare `table` — the interface
 * drawings further down are laid out by hand and must not inherit any of it.
 * ─────────────────────────────────────────────────────────────────────────────*/

/* A safety net, not the mobile strategy. Below 640px the table stops being a table
   (see the end of this block) and there is nothing left to scroll; this only catches
   the awkward middle widths where two columns still fit but barely. It matters that
   the scroll is trapped here rather than escaping to the body — sideways scroll on
   the document is the one thing this page must never do. */
.perms-scroll {
  overflow-x: auto;
  margin-top: 24px;
}

.perms {
  width: 100%;
  min-width: 460px;
  border-collapse: collapse;
  text-align: left;
}

.perms th {
  padding: 0 16px 10px 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--page-faint);
  border-bottom: 1px solid var(--page-border-2);
}

.perms td {
  padding: 13px 16px 13px 0;
  vertical-align: top;
  font-size: 14px;
  line-height: 1.6;
  color: var(--page-muted);
  border-bottom: 1px solid var(--page-border);
}

/* Microsoft's exact string, set in the face the consent screen will show it in: this
   column exists to be held up against another window and compared character by
   character. It used to carry our own friendlier name with Microsoft's underneath,
   which said every row twice; Microsoft's is the one that has to match. */
.perms td:first-child {
  width: 46%;
}

.perm {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--page-text);
}

/* The two sentences after the table. A list, because they are separate claims and
   running them together as a paragraph invites skipping the first — which is the one
   this whole page exists to land. */
.settles {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 28px;
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--page-muted);
}

/*
 * On a phone the table stops being a table and each permission becomes a block.
 *
 * The obvious alternative — leave it two columns inside the scroller — was tried and
 * looked fine in a screenshot, because a screenshot of a scroll container and a
 * screenshot of a truncated table are the same picture. In a hand it is not fine: the
 * reason column starts off-screen, so the answer to "why does it want that" is behind a
 * horizontal drag on the one page whose entire purpose is that somebody reads it.
 *
 * And this page in particular gets forwarded. The trust statements end with "if that is
 * not you, send them this page", so a fair share of its readers meet it as a link in a
 * message from a colleague, on a phone, having never heard of us.
 *
 * The header row is hidden rather than removed, so it still names the columns for a
 * screen reader while the sighted reader gets the name and the reason stacked in the
 * order they read them.
 */
@media (max-width: 640px) {
  .perms {
    min-width: 0;
  }

  .perms thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .perms tr {
    display: block;
    padding: 15px 0;
    border-bottom: 1px solid var(--page-border);
  }

  .perms tr:last-child {
    border-bottom: none;
    padding-bottom: 0;
  }

  .perms td {
    display: block;
    width: auto;
    padding: 0;
    border-bottom: none;
  }

  .perms td:first-child {
    width: auto;
    margin-bottom: 7px;
  }
}

/* ── Product surfaces ──────────────────────────────────────────────────────────
 * Static renderings of the real interface, drawn in HTML rather than shipped as
 * screenshots. Reasons, in order: the real captures in
 * apps/web/design/screenshots/ are of a live customer tenant and contain its name,
 * resource ids, and user accounts; they are 70 KB–1.1 MB each; and they cannot
 * reflow on a phone. These are marked aria-hidden and every fact they show is
 * restated in the prose beside them.
 * ─────────────────────────────────────────────────────────────────────────────*/

.app {
  background: var(--app-bg);
  border: 1px solid var(--app-border);
  border-radius: 12px;
  overflow: hidden;
  color: var(--app-text);
  font-size: 13px;
  line-height: 1.4;
  /* The hero centres its text; the interface inside it must not inherit that. */
  text-align: left;
}

.app p {
  margin: 0;
}

.app-bar {
  background: var(--app-surface);
  border-bottom: 1px solid var(--app-border);
  padding: 11px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  /* `.app` clips its overflow, so a bar that cannot wrap loses its right-hand badge
     entirely on a narrow screen rather than scrolling it. */
  flex-wrap: wrap;
}

.app-bar > div {
  min-width: 0;
}

.app-bar .path {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--app-faint);
}

.app-bar .who {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--app-muted);
}

.app-title {
  font-size: 13px;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.app-sub {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--app-muted);
  margin-top: 2px;
  /* `Microsoft.Authorization/roleAssignments/write` has no space to break at, and `.app`
     clips its overflow: without this it ends "…/writ" on a phone. */
  overflow-wrap: anywhere;
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  padding: 12px;
}

/*
 * Three columns, not four. The product has four change types, and the fourth — PIM —
 * is not collecting reliably yet. Showing a PIM count here would be a claim the page
 * makes nowhere else. Restore the fourth card when the PIM collectors are fixed.
 */
.stat-row--3 {
  grid-template-columns: repeat(3, 1fr);
}

.metric {
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: 8px;
  padding: 9px 11px;
}

.metric .k {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--app-muted);
  display: flex;
  align-items: center;
  gap: 5px;
}

.metric .k::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.metric .n {
  font-family: var(--mono);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.04em;
  margin-top: 3px;
}

.metric.crud {
  border-top: 2px solid var(--crud);
}
.metric.crud .k {
  color: var(--crud-text);
}
.metric.policy {
  border-top: 2px solid var(--policy);
}
.metric.policy .k {
  color: var(--policy-text);
}
.metric.rbac {
  border-top: 2px solid var(--rbac);
}
.metric.rbac .k {
  color: var(--rbac-text);
}
.metric.pim {
  border-top: 2px solid var(--pim);
}
.metric.pim .k {
  color: var(--pim-text);
}

.day-divider {
  padding: 6px 14px;
  background: var(--app-surface-2);
  border-top: 1px solid var(--app-border);
  border-bottom: 1px solid var(--app-border);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--app-faint);
}

.event {
  display: flex;
  gap: 12px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--app-border);
  border-left: 2px solid transparent;
}

.event:last-child {
  border-bottom: none;
}

.event.flag {
  border-left-color: var(--pim);
  background: rgba(239, 68, 68, 0.05);
}

.event .t {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--app-muted);
  width: 42px;
  flex-shrink: 0;
  text-align: right;
}

.event .body {
  min-width: 0;
  flex: 1;
}

.event .body > span {
  display: block;
}

.event .body > .tags {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
}

.event .title {
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.event .meta {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--app-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pill {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 1px 5px;
  border-radius: 3px;
}

.pill.crud {
  color: var(--crud-text);
  background: rgba(16, 185, 129, 0.12);
}
.pill.policy {
  color: var(--policy-text);
  background: rgba(245, 158, 11, 0.12);
}
.pill.rbac {
  color: var(--rbac-text);
  background: rgba(139, 92, 246, 0.12);
}
.pill.pim {
  color: var(--pim-text);
  background: rgba(239, 68, 68, 0.12);
}

.op {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--app-muted);
}

.hidden-note {
  padding: 8px 14px;
  border-top: 1px solid var(--app-border);
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--app-muted);
  display: flex;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}

/* Scrubber + diff */

.scrubber {
  padding: 14px 18px;
  background: var(--app-surface);
  border-bottom: 1px solid var(--app-border);
  position: relative;
}

.scrubber ol {
  display: flex;
  justify-content: space-between;
  position: relative;
}

.scrubber ol::before {
  content: '';
  position: absolute;
  top: 6px;
  left: 8px;
  right: 8px;
  height: 1px;
  background: var(--app-border-2);
}

.scrubber li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  position: relative;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--app-faint);
}

.scrubber .dot {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 2px solid var(--app-faint);
  background: var(--app-bg);
}

.scrubber li.a .dot {
  border-color: var(--accent);
  background: var(--accent);
}

.scrubber li.b .dot {
  border-color: var(--accent-2);
  background: var(--accent-2);
}

.scrubber li.a,
.scrubber li.b {
  color: var(--app-text);
}

.diff-head {
  padding: 9px 14px;
  background: var(--app-surface-2);
  border-bottom: 1px solid var(--app-border);
  display: flex;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 12px;
  font-weight: 600;
}

.diff-head span {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  color: var(--app-muted);
}

.diff {
  font-family: var(--mono);
  font-size: 11.5px;
  overflow-x: auto;
}

.diff div {
  display: flex;
  gap: 8px;
  padding: 4px 14px;
  border-bottom: 1px solid var(--app-border);
  white-space: nowrap;
}

.diff div:last-child {
  border-bottom: none;
}

.diff .sign {
  width: 10px;
  flex-shrink: 0;
  color: var(--app-faint);
}

.diff .key {
  color: #14b8a6;
}

.diff .sep {
  color: var(--app-muted);
}

.diff .val {
  color: var(--app-muted);
}

.diff .rm {
  background: rgba(239, 68, 68, 0.07);
}
.diff .rm .sign,
.diff .rm .val {
  color: var(--pim-text);
}
.diff .add {
  background: rgba(16, 185, 129, 0.07);
}
.diff .add .sign,
.diff .add .val {
  color: var(--crud-text);
}

.diff .suppressed {
  color: var(--app-faint);
  font-style: italic;
  white-space: normal;
}

/* PIM panel */

.pim-panel .row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--app-border);
}

.pim-panel .row:last-child {
  border-bottom: none;
}

.pim-panel .who {
  flex: 1;
  min-width: 0;
}

.pim-panel .name {
  font-size: 12px;
  font-weight: 600;
}

.pim-panel .role {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--pim-text);
}

.pim-panel .when {
  text-align: right;
  flex-shrink: 0;
  font-family: var(--mono);
  font-size: 11px;
}

.pim-panel .when small {
  display: block;
  font-size: 10px;
  color: var(--app-muted);
}

.avatar {
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
}

.count-pill {
  font-size: 10px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 20px;
  background: rgba(239, 68, 68, 0.14);
  color: var(--pim-text);
}

/* Alert card */

.alert-card {
  margin-top: 16px;
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: 10px;
  padding: 12px 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--app-text);
}

.alert-card--inset {
  margin: 12px;
  border-radius: 8px;
}

.alert-card h4 {
  margin: 0 0 8px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--app-faint);
}

.alert-card .line {
  display: flex;
  gap: 9px;
  padding: 5px 0;
  border-top: 1px solid var(--app-border);
  align-items: baseline;
}

.alert-card .line:first-of-type {
  border-top: none;
}

.alert-card .state {
  font-size: 9.5px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 3px;
  flex-shrink: 0;
}

.alert-card .state.fired {
  color: var(--pim-text);
  background: rgba(239, 68, 68, 0.14);
}

.alert-card .state.indet {
  color: var(--policy-text);
  background: rgba(245, 158, 11, 0.14);
}

.alert-card .reason {
  color: var(--app-muted);
  white-space: normal;
}

/*
 * The sign-in link.
 *
 * Deliberately not a button. It sits beside the primary CTA and must not compete with
 * it: a returning customer is looking for this word and will find it, while a first-time
 * visitor should see one obvious thing to press. Two buttons side by side would make the
 * page ask a question it does not need to ask.
 */
.header-signin {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--page-muted);
  padding: 8px 4px;
  white-space: nowrap;
  transition: color 0.12s;
}

.header-signin:hover {
  color: var(--page-text);
}

@media (max-width: 380px) {
  /* Below this the brand, the link and the button cannot share a row without the button
     losing its label. The returning customer keeps the nav chips and the footer; the
     visitor keeps the action. */
  .header-signin {
    display: none;
  }
}

/*
 * The three trust points.
 *
 * A plain list rather than cards. Cards were the wrong container here: six of them at
 * identical weight read as a wall to be skimmed past, and the reset's own advice is that
 * same-size cards of heading-plus-text are the lazy page structure. Three short items on
 * a rule read as three answers.
 */
.trust-list {
  list-style: none;
  display: grid;
  gap: 0;
  max-width: 640px;
  margin: 0 auto;
}

.trust-list li {
  padding: 22px 0;
  border-top: 1px solid var(--page-border);
}

.trust-list li:last-child {
  border-bottom: 1px solid var(--page-border);
}

.trust-list h3 {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 6px;
}

.trust-list p {
  font-size: 14px;
  color: var(--page-muted);
  line-height: 1.6;
}

.trust-list code {
  font-family: var(--mono);
  font-size: 12.5px;
  background: var(--page-mid);
  border: 1px solid var(--page-border);
  border-radius: 4px;
  padding: 1px 5px;
}

/* ── /get-started: the step rail ──────────────────────────────────────────
 *
 * That page was built as a single `section.legal` — the container this file documents as
 * being for long-form prose, i.e. the privacy page. That one choice is why it read as a
 * wall: one section means no brand seam, no alt bands, and none of the components
 * /connect uses. What follows composes `.step-n`, `.ticks`, `.faq` and `.trust-list`
 * rather than introducing anything, which is why it still looks like the rest of the site.
 *
 * Adds no tokens and overrides no existing rule.
 */
/*
 * SPINE — what would be added to apps/landing/src/styles.css.
 *
 * Nothing here overrides an existing rule. `.step-n`, `.ticks`, `.faq`, `.trust-list`,
 * `.fine`, `section.alt` and the seam are used exactly as they already exist; these are
 * the four new blocks the treatment needs (spine, routes, needs, and a smaller h2).
 *
 * ~90 lines. No new tokens, no new colours, no dependency.
 */

/* ── The rail ─────────────────────────────────────────────────────────────── */

.spine {
  display: flex;
  flex-direction: column;
}

.spine-step {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 0 24px;
  padding-bottom: 44px;
}

.spine-step:last-child {
  padding-bottom: 0;
}

/* The rule that makes three headings into one sequence. It is the numeral's own column,
   drawn from below the numeral to the bottom of the step — so it stops at the last one
   rather than trailing into the next section. */
.spine-rail {
  position: relative;
  display: flex;
  justify-content: center;
}

.spine-rail::after {
  content: '';
  position: absolute;
  top: 40px;
  bottom: -44px;
  width: 1px;
  background: var(--page-border-2);
}

.spine-step:last-child .spine-rail::after {
  display: none;
}

.spine-body > h2,
h2.spine-h2 {
  /* 20px, the same size `.legal h2` already uses for a document heading — the marketing
     h2 at 26–32px is for a section that owns a whole band, and a step does not. */
  font-size: 20px;
  margin-bottom: 12px;
  scroll-margin-top: 74px;
}

h2.spine-h2 {
  margin-bottom: 20px;
}

/* A measure, not a column width. The rail sits in a 920px shell so the two route cards
   have room; prose set to that width would be 110 characters a line. */
.spine-body > p,
.spine-claims,
.needs,
.needs-tail {
  max-width: 640px;
}

.spine-body p {
  color: var(--page-text-2);
  line-height: 1.7;
}

.spine-body > p + p {
  margin-top: 14px;
}

/* ── The two routes in step 3 ─────────────────────────────────────────────── */

.routes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
  margin: 18px 0 4px;
}

.route {
  border: 1px solid var(--page-border);
  border-radius: var(--radius);
  background: var(--page-bg);
  padding: 20px;
}

.route h3 {
  margin-bottom: 8px;
}

.route p {
  font-size: 14.5px;
  color: var(--page-muted);
}

/* ── The three claims after the branch ────────────────────────────────────── */

.spine-claims {
  max-width: none;
  margin-top: 24px;
}

.spine-claims li {
  padding: 16px 0;
}

.spine-claims p {
  font-size: 14.5px;
}

/* ── What you will need ───────────────────────────────────────────────────── */

.needs li {
  font-size: 16px;
  line-height: 1.6;
}

/* "Nothing else. No subscription to deploy into…" is a claim the buyer is looking for,
   so it is not small print. Muted, full size. */
.needs-tail {
  margin-top: 18px;
  font-size: 15.5px;
  color: var(--page-muted);
  line-height: 1.7;
}

/* On a phone the rail costs 56px of a 342px measure. It narrows rather than being
   dropped: the numbered sequence is the whole treatment. */
@media (max-width: 560px) {
  .spine-step {
    grid-template-columns: 26px 1fr;
    gap: 0 14px;
  }

  .spine-rail .step-n {
    width: 26px;
    height: 26px;
    font-size: 12px;
  }

  .spine-rail::after {
    top: 34px;
  }
}

/* ── The 2026-09 refresh ──────────────────────────────────────────────────────
 *
 * The category standard, played straight (PRODUCT.md, standing preference). Everything
 * below is additive: no token changes, no rule above this line overridden except the
 * two hero measurements edited in place. Four generated rasters ship with the page and
 * every one of them is textless atmosphere or a metaphor — the drawings above are still
 * the only proof of the product on screen.
 */

/* Backdrops. A CSS background rather than an <img>, because the two themes want two
   different files and the explicit toggle must win over the OS preference — a <picture>
   with a media query cannot see `data-theme`. The mask fades the image into the page so
   there is never an edge to notice. */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: url('/assets/hero-light.webp') center top / cover no-repeat;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .hero-bg {
    background-image: url('/assets/hero-dark.webp');
  }
}

:root[data-theme='dark'] .hero-bg {
  background-image: url('/assets/hero-dark.webp');
}

.hero-copy,
.hero-figure {
  position: relative;
  z-index: 1;
}

.hero .lede {
  font-size: 19px;
  max-width: 640px;
}

.hero .fine {
  margin-top: 2px;
  /* `--page-faint` measured 3.8–4.3:1 on the tinted backdrop; one step darker clears AA
     on every sampled pixel of it. The token comment above was written for white. */
  color: var(--page-muted);
}

.btn--lg {
  padding: 14px 26px;
  font-size: 16px;
  min-height: 48px;
}

/* The browser frame around the hero drawing. The frame is chrome the visitor already
   knows, which is the whole reason the category ships it: it says "this is the product"
   without a caption. One soft, offset shadow; no halo. */
.frame {
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--page-border-2);
  background: var(--app-bg);
  box-shadow:
    0 30px 60px -20px rgba(15, 23, 42, 0.35),
    0 12px 24px -12px rgba(15, 23, 42, 0.2);
}

.frame .app {
  border: none;
  border-radius: 0;
}

/* Edge's chrome, in the dark theme the product ships in: a tab strip, then a toolbar of
   back / forward / refresh, an address bar with a lock, and the tools at the right. All
   drawn in CSS so it is 1 KB and recolours with the product surfaces. */
.frame-tabs {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 40px;
  padding: 6px 10px 0;
  background: var(--app-bg);
}

.frame-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 12px 0 10px;
  min-width: 200px;
  border-radius: 8px 8px 0 0;
  background: var(--app-surface-2);
  color: var(--app-text);
  font-size: 12px;
  font-weight: 500;
}

.frame-tab img {
  border-radius: 3px;
}

.frame-tab > span {
  flex: 1;
  white-space: nowrap;
}

.frame-tab-x,
.frame-tab-new {
  position: relative;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.frame-tab-x::before,
.frame-tab-x::after,
.frame-tab-new::before,
.frame-tab-new::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 1.5px;
  background: var(--app-muted);
  transform: translate(-50%, -50%) rotate(45deg);
}

.frame-tab-x::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

.frame-tab-new {
  margin-bottom: 9px;
}

.frame-tab-new::before {
  transform: translate(-50%, -50%);
}

.frame-tab-new::after {
  transform: translate(-50%, -50%) rotate(90deg);
}

.frame-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 40px;
  padding: 0 10px;
  background: var(--app-surface-2);
  border-bottom: 1px solid var(--app-border);
}

.frame-nav,
.frame-tools {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
}

.frame-nav i,
.frame-tools i {
  position: relative;
  display: block;
  width: 14px;
  height: 14px;
}

/* Back and forward: a chevron each, drawn from two borders. */
.frame-back::before,
.frame-fwd::before {
  content: '';
  position: absolute;
  top: 3px;
  left: 4px;
  width: 7px;
  height: 7px;
  border-left: 1.6px solid var(--app-muted);
  border-bottom: 1.6px solid var(--app-muted);
  transform: rotate(45deg);
}

.frame-fwd::before {
  left: 2px;
  transform: rotate(-135deg);
  border-color: var(--app-faint);
}

/* Refresh: an open ring with a gap. */
.frame-refresh::before {
  content: '';
  position: absolute;
  inset: 1px;
  border: 1.6px solid var(--app-muted);
  border-radius: 50%;
  border-right-color: transparent;
  transform: rotate(-20deg);
}

.frame-url {
  flex: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 28px;
  max-width: none;
  margin: 0;
  padding: 0 12px;
  border-radius: 14px;
  background: var(--app-bg);
  border: 1px solid var(--app-border);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--app-text);
  text-align: left;
}

/* The lock: a body and a shackle. */
.frame-lock {
  position: relative;
  width: 10px;
  height: 12px;
  flex-shrink: 0;
}

.frame-lock::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0;
  width: 4px;
  height: 6px;
  border: 1.4px solid var(--app-muted);
  border-bottom: none;
  border-radius: 4px 4px 0 0;
}

.frame-lock::after {
  content: '';
  position: absolute;
  left: 0;
  top: 5px;
  width: 10px;
  height: 7px;
  border-radius: 2px;
  background: var(--app-muted);
}

/* Tools: two quiet glyphs and a profile disc. */
.frame-tools i::before {
  content: '';
  position: absolute;
  inset: 2px;
  border: 1.5px solid var(--app-faint);
  border-radius: 3px;
}

.frame-tools .frame-avatar::before {
  inset: 0;
  border: none;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

@media (max-width: 560px) {
  .frame-tab {
    min-width: 0;
  }
  .frame-tools i:not(.frame-avatar) {
    display: none;
  }
}

/* The hero drawing at the page's full measure: bigger type in the rows, so the five
   events read from a normal viewing distance rather than as texture. */
.hero-figure .app {
  font-size: 14px;
}

.hero-figure .event .title {
  font-size: 13.5px;
}

.hero-figure .event .meta {
  font-size: 11.5px;
}

.hero-figure .metric .n {
  font-size: 24px;
}

/* ── The retention graphic ────────────────────────────────────────────────── */

/* Three rows, two channels. Length is duration and it is true at every width — the
   track is 90 days long, so Kronikl's Pro bar and Activity Log's are the same length,
   because they are. The second channel is the argument: whether the configuration is
   kept. A previous version put the day-count inside the bar and widened the 14-day bar
   on a phone so the label would fit, which drew Free's window as a third of Pro's. */
.retention {
  display: grid;
  gap: 14px;
  margin: 0 auto 36px;
  max-width: 860px;
}

.ret-head,
.ret-row {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr) 240px;
  gap: 6px 18px;
  align-items: center;
}

.ret-head {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--page-faint);
  padding-bottom: 4px;
  border-bottom: 1px solid var(--page-border);
}

.ret-label {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--page-text-2);
  text-align: right;
}

.ret-row--kronikl .ret-label {
  color: var(--page-text);
  font-weight: 800;
}

.ret-track {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 36px;
}

.ret-bar {
  display: block;
  height: 22px;
  border-radius: 6px;
  background: var(--page-border-2);
  flex-shrink: 0;
}

.ret-bar--90 {
  width: 62%;
}

.ret-bar--14 {
  width: calc(62% * 14 / 90);
}

.ret-bar--pro {
  background: var(--accent-solid);
}

.ret-days {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--page-text);
  white-space: nowrap;
}

/* Free's window on Kronikl's bar: a mark at 14 of 90, in the same proportion as the
   Resource Graph bar above it. */
.ret-tick {
  position: absolute;
  left: calc(62% * 14 / 90);
  top: 4px;
  bottom: 4px;
  border-left: 2px solid rgba(255, 255, 255, 0.9);
  margin-left: -1px;
}

.ret-config {
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--page-muted);
  display: flex;
  gap: 8px;
  align-items: flex-start;
}

.ret-config::before {
  content: '';
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin-top: 2px;
  border-radius: 50%;
  border: 1.5px solid var(--page-border-2);
}

.ret-config--yes {
  color: var(--page-text);
  font-weight: 600;
}

.ret-config--yes::before {
  border-color: var(--accent-solid);
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 8.5l2.5 2.5L12 5.5' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")
      center / 12px no-repeat,
    var(--accent-solid);
}

.why-copy {
  max-width: 680px;
  margin: 0 auto;
  display: grid;
  gap: 14px;
  font-size: 16px;
  line-height: 1.7;
  color: var(--page-text-2);
}

@media (max-width: 720px) {
  .ret-head {
    display: none;
  }

  .ret-row {
    grid-template-columns: 1fr;
    gap: 4px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--page-border);
  }

  .ret-row:last-child {
    border-bottom: none;
  }

  .ret-label {
    text-align: left;
  }

  .ret-bar--90 {
    width: 70%;
  }

  .ret-bar--14 {
    width: calc(70% * 14 / 90);
  }

  .ret-tick {
    left: calc(70% * 14 / 90);
  }

  /* "14 on Free · 90 on Pro" does not fit beside a 70% bar on a 342px measure. */
  .ret-days {
    white-space: normal;
    line-height: 1.2;
    font-size: 13px;
  }
}

/* ── Two-column sections: copy beside a plate ─────────────────────────────── */

.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 56px;
  align-items: center;
}

.split-copy h2 {
  margin-bottom: 12px;
}

@media (min-width: 900px) {
  .split--flip .split-copy {
    order: 2;
  }
  .split--flip .split-figure {
    order: 1;
  }
}

/* A product picture: a flat, front-on capture of the product's own screen, on a corner
   radius with a hairline and a soft offset shadow, so its edge reads as an object's edge
   and not as a cut. Never tilted and never passed through an image model — a styling
   pass rewrote the product's own name inside the first version. Every one is a real
   screen from the seeded local instance, with alt text that says what it shows. */
.shot {
  width: 100%;
  height: auto;
  border-radius: 14px;
  box-shadow:
    0 30px 60px -24px rgba(15, 23, 42, 0.32),
    0 10px 20px -12px rgba(15, 23, 42, 0.18);
}

.feature-figure .shot,
.split-figure .shot {
  border: 1px solid rgba(15, 23, 42, 0.12);
  background: var(--app-bg);
}

.feature-figure .shot--tall {
  max-width: 420px;
  margin: 0 auto;
  display: block;
}

.frame-shot {
  display: block;
  width: 100%;
  height: auto;
  background: var(--app-bg);
}

.steps--stacked {
  grid-template-columns: 1fr;
  gap: 22px;
}

.steps--stacked .step {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 16px;
  align-items: start;
}

.steps--stacked .step h3 {
  margin: 4px 0 6px;
}

.trust-list--left {
  margin: 0;
  max-width: none;
}

/* ── Feature figures on tinted plates ─────────────────────────────────────── */

.feature-figure {
  padding: 28px;
  border-radius: 18px;
  background: var(--accent-wash);
}

.feature-figure--rbac {
  background: rgba(139, 92, 246, 0.1);
}

.feature-figure--crud {
  background: rgba(16, 185, 129, 0.1);
}

.feature-figure--export {
  background: var(--accent-wash);
}

.feature-figure .app {
  box-shadow:
    0 24px 48px -20px rgba(15, 23, 42, 0.35),
    0 0 0 1px rgba(0, 0, 0, 0.04);
}

@media (max-width: 560px) {
  .feature-figure {
    padding: 14px;
    border-radius: 14px;
  }
}

/* ── The close ────────────────────────────────────────────────────────────── */

.final {
  position: relative;
  padding: 120px 0;
}

/* The mirrored backdrop must not clip the seam's dots at the section's top edge, so the
   image is clipped on its own rather than by the section. */
.final-bg {
  overflow: hidden;
}

.final .shell {
  position: relative;
  z-index: 1;
}

.final-bg {
  transform: scaleY(-1);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 100%);
}

/* One paragraph between two illustrated sections wants less air than a section that
   carries a figure; at the standard 84px it read as unfinished. */
.alerts {
  padding: 48px 0;
}

/* The head's standing 48px bottom margin is for the figure that follows it; here nothing
   does, and it left twice the air below the paragraph as above the heading. */
.alerts .section-head {
  margin-bottom: 0;
}

/* ── Browser surfaces ─────────────────────────────────────────────────────── */

::selection {
  background: var(--accent-wash-border);
  color: var(--page-text);
}

a {
  text-underline-offset: 3px;
}

.diff,
.metric .n,
.event .t,
.plan .amount {
  font-variant-numeric: tabular-nums;
}
