/*
 * 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;
}

/* The three-steps diagram on /connect. Two flat-ground files; `darken` folds the light
   one's white into the section and `lighten` folds the dark one's near-black, so the
   picture sits on the page rather than in a slab. The theme swap is the hero backdrop's.
   The hide rules carry the figure's class too: `.steps-figure img` would otherwise outrank
   a bare class and show both files at once, which is what the first build did. */
.steps-figure {
  margin: 0 auto 36px;
  max-width: 620px;
}

.steps-figure img {
  display: block;
  width: 100%;
  height: auto;
}

.steps-figure .steps-figure__light {
  mix-blend-mode: darken;
}

.steps-figure .steps-figure__dark {
  display: none;
  mix-blend-mode: lighten;
}

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

:root[data-theme='dark'] .steps-figure .steps-figure__light {
  display: none;
}

:root[data-theme='dark'] .steps-figure .steps-figure__dark {
  display: block;
}

.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 sub-processor list is a table because a reviewer reads it as one: company, role,
   data, place, and the four have to line up so a row can be checked against a
   questionnaire. Four columns do not fit 390px, so the wrapper scrolls sideways and the
   page body does not; `min-width` keeps the columns readable rather than one word wide.
   The header treatment is `.compare`'s, so the two tables on the site read as one system. */
.legal .table-scroll {
  overflow-x: auto;
  margin: 24px 0 8px;
  border: 1px solid var(--page-border);
  border-radius: var(--radius-sm);
}

.legal table {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
}

.legal thead th {
  padding: 10px 14px;
  text-align: left;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--page-muted);
  background: var(--page-mid);
  border-bottom: 1px solid var(--page-border);
}

.legal tbody th,
.legal tbody td {
  padding: 12px 14px 14px;
  vertical-align: top;
  text-align: left;
  font-size: 14px;
  line-height: 1.5;
  border-bottom: 1px solid var(--page-border);
}

.legal tbody tr:last-child th,
.legal tbody tr:last-child td {
  border-bottom: none;
}

.legal tbody th {
  font-weight: 650;
  color: var(--page-text);
  width: 22%;
}

.legal tbody td {
  color: var(--page-text-2);
}

/* ── 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.
 */
/* ── 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;
}

/* The first line on the page. Sized so the headline still leads: smaller than the lede,
   heavier than it, and set in `--page-muted` — `--page-faint` measured 3.8–4.3:1 on the
   tinted backdrop, and one step darker clears AA on every sampled pixel of it. (The token
   comment above was written for white.) Not upper-cased: it is a sentence, and letter-
   spaced capitals at this length read as a label rather than a claim. */
.hero-kicker {
  font-size: 15px;
  font-weight: 600;
  color: var(--page-muted);
  margin-bottom: 14px;
  /* It fits on one line at 390 px as written; if it ever grows, this puts the break on the
     comma rather than mid-clause. */
  text-wrap: balance;
}

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

/* The hero, folded: the product flat at full width, cropped by the section's edge and
   not by a drawn window. The page continues into the product, which is the truth. The
   address is a caption above the figure, not chrome. On a phone the crop shortens
   instead of scaling the whole screen down to an unreadable grey rectangle. */
.hero-fold {
  max-width: 1080px;
  margin: 56px auto 0;
  padding: 0 24px;
  position: relative;
}

.hero-fold-url {
  display: block;
  font-size: 11.5px;
  color: var(--page-faint);
  text-align: right;
  margin-bottom: 8px;
}

.fold-shot {
  display: block;
  width: 100%;
  height: 620px;
  object-fit: cover;
  object-position: top;
  border-radius: 14px 14px 0 0;
  border: 1px solid var(--page-border-2);
  border-bottom: none;
  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);
}

.hero {
  padding-bottom: 0;
}

@media (max-width: 720px) {
  .fold-shot {
    height: 300px;
  }
}

/* ── Two records, one event ───────────────────────────────────────────────── */

/* Azure's record beside Kronikl's. The left is a quotation — Microsoft's published event
   schema, abridged — so it sits on the page's own ground, pale in light and sunk in
   dark, deliberately not product-coloured. The right is the product, dark in both. */
.records {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin: 8px 0 36px;
}

.record {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.record-h {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--page-faint);
  margin-bottom: 10px;
}

.record-body {
  flex: 1;
  margin: 0;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid var(--page-border);
  background: var(--page-bg);
  color: var(--page-text-2);
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.record-note {
  color: var(--page-faint);
  font-style: italic;
}

.record-foot {
  margin-top: 8px;
  font-size: 12.5px;
  color: var(--page-muted);
}

.record-card {
  flex: 1;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid var(--app-border-2);
  background: var(--app-bg);
  color: var(--app-text);
}

.record-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  line-height: 1.3;
}

.record-title .pill {
  font-size: 10px;
  padding: 2px 6px;
}

.record-meta {
  margin-top: 6px;
  font-size: 11px;
  color: var(--app-muted);
  overflow-wrap: anywhere;
}

.record-ab {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 16px 0 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--app-border);
  font-size: 10.5px;
  color: var(--app-muted);
}

.rrow {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 0;
  border-bottom: 1px solid var(--app-border);
}

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

.rrow code {
  font-family: var(--mono);
  font-size: 11px;
  color: #14b8a6;
  overflow-wrap: anywhere;
}

.rvals {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 13px;
}

.rvals s {
  color: var(--pim-text);
  text-decoration-color: rgba(248, 113, 113, 0.7);
}

.rvals em {
  font-style: normal;
  color: var(--crud-text);
}

.arrow {
  display: inline-block;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
  color: var(--app-muted);
}

.records-cap {
  grid-column: 1 / -1;
  text-align: center;
  font-size: 15.5px;
  font-weight: 600;
  color: var(--page-text);
  margin-top: 4px;
}

@media (max-width: 800px) {
  .records {
    grid-template-columns: 1fr;
  }
}

/* The cliff behind the problem section: a field of marks that thins and then stops.
   Textless, masked, two files, swapped like the hero backdrop. Kept faint: at full
   strength it reads as a chart and invites "a chart of what?". */
.why {
  position: relative;
}

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

.why-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: url('/assets/cliff-light.webp') center / cover no-repeat;
  opacity: 0.3;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 25%, #000 70%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 25%, #000 70%, transparent 100%);
}

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

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

/* ── Wide features: the scrubber life-size, the auditor's file twice the size ── */

.feature--wide {
  grid-template-columns: 1fr;
  gap: 28px;
}

.feature--wide .feature-copy {
  max-width: 720px;
}

.feature-figure--wide {
  padding: 20px;
}

.evidence-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  align-items: start;
}

.evidence-pair .app {
  font-size: 14px;
}

.evidence-pair .diff {
  font-size: 12.5px;
}

/* The product's own evidence text, selectable, cut where the events start and faded so
   the cut is visible. */
.evidence {
  margin: 0;
  padding: 16px 18px 40px;
  border-radius: 12px;
  border: 1px solid var(--app-border-2);
  background: var(--app-bg);
  color: var(--app-text);
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
}

@media (max-width: 900px) {
  .evidence-pair {
    grid-template-columns: 1fr;
  }
}

/* ── 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;
}

/* One scale for the three bars: Pro's 395 days (0085, thirteen months) is the full
   measure, and Azure's two windows are drawn against it. `--ret-full` is the only number
   the phone override changes. The 14-day bar comes out a sliver at this scale, which is
   the point; a minimum keeps it a shape rather than a hairline. */
.ret-track {
  --ret-full: 54%;
}

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

.ret-bar--activity {
  width: calc(var(--ret-full) * 90 / 395);
}

.ret-bar--graph {
  width: calc(var(--ret-full) * 14 / 395);
  min-width: 6px;
}

.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 395, in the same proportion as the
   Resource Graph bar above it. */
.ret-tick {
  position: absolute;
  left: calc(var(--ret-full) * 14 / 395);
  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-track {
    --ret-full: 70%;
  }

  /* "14 on Free · 13 months 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;
  }
}

/* ── Stacked sections: copy on top, the product full width beneath ──────────── */

/* Every product picture is shown at the page's full measure, because a screen at half
   width cannot be read from a desk. The copy is capped at a measure; the picture is not. */
.stack {
  display: grid;
  gap: 28px;
}

.stack-copy {
  max-width: 720px;
}

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

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

/* 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 {
  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;
}

.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;
}

/* ── Wireframes ───────────────────────────────────────────────────────────── */

/* A wireframe is a drawing of what a screen means. It carries only the strings that make
   the argument (a role name, a button label, a status) and translucent bars for
   everything else, so it stays true through a redesign and goes stale only when a fact
   changes. It sits on a generated plate — a textless dark ground with a faint blueprint
   grid and one soft bloom (public/assets/wire-plate.webp) — so it reads as a designed
   object and not as a screenshot; the words are real HTML on top, never generated. Two
   screens stay as real captures, the hero and the diff, because they are the proof; a
   script recaptures them (tools/capture-app.mjs). */
.wire {
  position: relative;
  border: 1px solid rgba(96, 130, 220, 0.35);
  border-radius: 14px;
  background: #0b1020 url('/assets/wire-plate.webp') center / cover no-repeat;
  padding: 24px 26px;
  color: #e8edf5;
  font-size: 14px;
  line-height: 1.45;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 30px 60px -24px rgba(15, 23, 42, 0.5),
    0 10px 20px -12px rgba(15, 23, 42, 0.3);
}

.wire--pane {
  max-width: 440px;
  margin: 0 auto;
  padding: 18px 20px;
  /* The pane is small, so the plate's bloom would sit under its labels; keep it in the
     bottom-right corner where nothing is written. */
  background-position: right bottom;
}

.wire p {
  margin: 0;
}

.wire b {
  font-weight: 700;
}

.wire-title {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
}

.wire-h {
  font-size: 15.5px;
  font-weight: 700;
  margin-top: 6px;
}

.wire-k {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--app-muted);
}

.wire-text {
  color: #c3cddd;
}

.wire-text--muted {
  color: var(--app-muted);
  font-size: 13px;
}

.wire-mono {
  font-family: var(--mono);
  font-size: 12px;
  color: #c3cddd;
  overflow-wrap: anywhere;
}

.wire-status {
  color: var(--crud-text);
  font-weight: 700;
}

.wire-tag {
  display: inline-block;
  align-self: flex-start;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 2px 7px;
  border-radius: 4px;
  color: var(--rbac-text);
  background: rgba(139, 92, 246, 0.18);
}

/* Grey bars stand in for text that does not carry the argument. */
.wire-line {
  display: block;
  height: 9px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.12);
  margin: 4px 0;
}

.wire-line--inline {
  display: inline-block;
  vertical-align: middle;
  margin: 0;
}

.wire-line--right {
  margin-left: auto;
}

.wire-line--22 {
  width: 22%;
}
.wire-line--30 {
  width: 30%;
}
.wire-line--40 {
  width: 40%;
}
.wire-line--45 {
  width: 45%;
}
.wire-line--50 {
  width: 50%;
}
.wire-line--55 {
  width: 55%;
}
.wire-line--60 {
  width: 60%;
}
.wire-line--70 {
  width: 70%;
}
.wire-line--75 {
  width: 75%;
}
.wire-line--80 {
  width: 80%;
}

.wire-row {
  display: grid;
  gap: 14px;
}

.wire-row--2 {
  grid-template-columns: 1fr 1fr;
}

.wire-row--4 {
  grid-template-columns: repeat(4, 1fr);
  margin-top: 6px;
}

.wire-card {
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-top-width: 3px;
  background: rgba(255, 255, 255, 0.03);
}

.wire-card--done {
  border-top-color: var(--crud);
}

.wire-card--now {
  border-top-color: var(--accent-solid);
  background: rgba(37, 99, 235, 0.16);
}

/*
 * Step one done, step two current. Both markers used to be filled discs — a green one
 * with a white tick, a blue one with a white numeral — which is the status-dot trope and
 * reads as machine chrome sitting on top of a drawing rather than as part of one. They
 * are now the marks themselves, in the drawing's own ink and the same size as each other.
 * The state is still on the cards: `--done` keeps its green top rule, `--now` its blue
 * rule and its tinted fill, so nothing that was legible stopped being legible.
 */
.wire-tick,
.wire-num {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  margin-bottom: 4px;
  color: #c3cddd;
}

.wire-tick::after {
  content: '';
  width: 10px;
  height: 5px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(-45deg);
}

.wire-banner {
  border: 1px solid rgba(245, 158, 11, 0.4);
  background: rgba(245, 158, 11, 0.1);
  color: #f0c473;
  border-radius: 8px;
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.wire-banner .wire-line {
  background: rgba(245, 158, 11, 0.22);
}

.wire-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.wire-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}

.wire-actions--tight {
  margin: 0;
  flex-shrink: 0;
}

.wire-btn {
  display: inline-block;
  padding: 7px 13px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  font-size: 13px;
  font-weight: 600;
  color: #e8edf5;
  background: rgba(255, 255, 255, 0.04);
}

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

.wire-btn--sm {
  padding: 5px 10px;
  font-size: 12px;
}

.wire-btn--right {
  margin-left: auto;
}

.wire-rule {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.wire-rule > div:first-child {
  min-width: 0;
  flex: 1;
}

.wire-dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 16px;
  margin: 8px 0 0;
  font-size: 13.5px;
}

.wire-dl dt {
  color: var(--app-muted);
}

.wire-dl dd {
  margin: 0;
  text-align: right;
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  .wire-row--2,
  .wire-row--4 {
    grid-template-columns: 1fr;
  }
  .wire-rule {
    flex-direction: column;
  }
}
