/*
 * Mosaic — the public site.
 *
 * Dark, because the product is. Mosaic's own interface defaults to a near-black
 * working surface and its welcome screen draws the comparison as artwork on it;
 * a white marketing page in front of that was a different product's front door.
 *
 * The grammar: a faint grid you notice only once, a very large quiet headline
 * with exactly one word in the accent, pill buttons, and panels that are the
 * application's real surfaces rendered in markup rather than screenshotted.
 * Orange is spent on four things — the mark, one word, the verdicts, and the
 * one control that matters on each screen — and nowhere else.
 */

/*
 * Light, and flat.
 *
 * Two changes at once, and they support each other. On a dark page a gradient
 * is how a surface separates itself from the one behind it; on a light page a
 * hairline does that job better and a gradient reads as a smudge — so removing
 * them was not a cost of going light, it was most of the work of doing it well.
 *
 * The canvas is a warm off-white rather than #ffffff. Pure white against an
 * orange accent is harsh, and every hairline on it has to be darker than it
 * wants to be to register at all.
 *
 * The semantic colours are all darkened from their dark-theme values. This is
 * the part a light conversion usually gets wrong: #4ec27a is a perfectly good
 * green on #0b0b0d and unreadable on #faf9f7, and a verdict nobody can read is
 * worse than no colour at all.
 */
:root {
  --bg: #faf9f7;
  --bg-panel: #ffffff;
  --bg-raised: #f3f1ed;
  --bg-hover: #ebe8e2;

  --line: #e2ded6;
  --line-soft: #eeebe5;

  --text: #17171a;
  --text-soft: #55555e;
  --text-dim: #85858f;

  --accent: #c7491c;
  /* The mark and the buttons keep the brand orange; body text and small
     labels use `--accent` above, which is darkened to clear 4.5:1 on the
     canvas. Two values for one colour, because one of them has to be legible
     at 13px and the other has to look like the logo. */
  --accent-brand: #ff6c37;
  /*
   * The bright one, for headings.
   *
   * Three oranges rather than one, because they do three different jobs and
   * only one set of rules applies to each. `--accent-brand` is a fill with no
   * words on it — the mark, and the rule that appears under a card — so it
   * stays the full brand value. `--accent` is 4.54:1 and is what small text
   * has to use. This one is 3.08:1, the bar for large text, and is as bright
   * as an orange gets on this canvas and stays readable.
   *
   * No button uses any of them. A colour that is also every button is a colour
   * that has stopped signifying anything, and orange now means one thing here:
   * this is the part that matters.
   *
   * Worth stating plainly: the brand orange itself is 2.68:1 as text and fails
   * even the large-text bar. It was on the word "agree" in the hero, at the
   * one moment the sentence lands. Bright is not the same as legible, and the
   * difference between #ff6c37 and #ed6433 is much smaller than the difference
   * between reading it and not.
   */
  --accent-display: #ed6433;
  --accent-soft: #f0713d;
  --accent-wash: rgba(199, 73, 28, 0.09);

  --ok: #2c864d;
  --ok-wash: rgba(44, 134, 77, 0.11);
  --err: #cf3b32;
  --err-wash: rgba(207, 59, 50, 0.1);
  --warn: #a66912;
  --warn-wash: rgba(166, 105, 18, 0.12);

  /*
   * Four values that were written as literals and so could not be themed.
   *
   * Every one of them is a surface or a fill that has to invert with the
   * page — the sticky bar, the faint grid behind the hero, the primary
   * button and the shadow under a card. A colour hard-coded in a rule is a
   * colour a theme cannot reach, and each of these would have stayed put
   * while everything around it changed, which is how a converted page ends
   * up with one white rectangle in the middle of a dark one.
   */
  --nav-bg: rgba(250, 249, 247, 0.82);
  --grid-line: rgba(23, 23, 26, 0.035);
  --btn-fill: #17171a;
  --btn-fill-hover: #2e2e34;
  --btn-label: #ffffff;
  --btn-ghost-hover-line: #b9b3a8;
  --shadow-card: 0 18px 50px rgba(23, 23, 26, 0.09);

  /* Four the front page's diagrams needed and the palette had no name for: a
     line one step darker than `--line` for the edge of a node, the two status
     borders that go with `--ok-wash` and `--err-wash`, and the dot of the
     canvas field. Tokens rather than literals, because this page has a switch
     in its header. */
  --line-strong: #d9d4ca;
  --ok-line: #a8cdb6;
  --err-line: #eab6b2;
  --grid-dot: rgba(23, 23, 26, 0.055);

  --mono: 'Geist Mono', 'SF Mono', 'Cascadia Mono', ui-monospace, Menlo, Consolas, monospace;
  --radius: 10px;
  --radius-lg: 18px;
  --page: 1240px;
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family:
    Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.65;
  /* Geist carries no `cv*` alternates — those were Inter's, and asking a face
     for features it does not have is a line that only misleads whoever reads
     it next. What is wanted from it is the figures, which the numbers in the
     tables and the diagrams depend on to stay in column. */
  font-feature-settings: 'tnum' 1;
  -webkit-font-smoothing: antialiased;

  /* The grid. Noticed once and then not again, which is the whole intention —
     it gives the black a scale without asking to be looked at. */
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 84px 84px;
}

a {
  color: inherit;
}

.wrap {
  width: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 28px;
}

/* ---------------------------------------------------------------------------
   Type
   --------------------------------------------------------------------------- */

h1,
h2,
h3 {
  margin: 0;
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.035em;
}

h1 {
  font-size: clamp(2.9rem, 6.6vw, 5rem);
  letter-spacing: -0.045em;
}

h2 {
  font-size: clamp(2rem, 4.2vw, 3.2rem);
  letter-spacing: -0.04em;
}

h3 {
  font-size: 1.22rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}

p {
  margin: 0;
}

.lede {
  max-width: 56ch;
  color: var(--text-soft);
  font-size: clamp(1.06rem, 1.6vw, 1.28rem);
  line-height: 1.55;
}

.accent {
  /* Only ever on a heading; see `--accent-display`. */
  color: var(--accent-display);
}

.eyebrow {
  display: inline-block;
  margin-bottom: 18px;
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-panel);
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  color: var(--text-soft);
}

/* ---------------------------------------------------------------------------
   Nav
   --------------------------------------------------------------------------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--nav-bg);
  backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 200ms ease;
}

.nav.is-scrolled {
  border-bottom-color: var(--line);
}

.nav-inner {
  display: flex;
  align-items: center;
  gap: 30px;
  height: 70px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  font-size: 1.1rem;
  letter-spacing: -0.03em;
  text-decoration: none;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 30px;
  margin-left: auto;
}

/* Links only. Without the `:not`, this out-ranks every button rule — one class
   and an element beats one class — and quietly greys the text of the one
   control on the page that has to be read. */
.nav-links a:not(.btn) {
  color: var(--text-soft);
  text-decoration: none;
  font-size: 0.94rem;
  transition: color 140ms ease;
}

.nav-links a:not(.btn):hover {
  color: var(--text);
}

/* ---------------------------------------------------------------------------
   Buttons — pills
   --------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 28px;
  border: 1px solid transparent;
  border-radius: 999px;
  font: inherit;
  font-size: 1rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition:
    background 150ms ease,
    border-color 150ms ease,
    color 150ms ease;
}

.btn-primary {
  /*
   * Flat, and dark rather than orange.
   *
   * White on #ff6c37 is about 2.5:1 and fails at any size — so the accent
   * cannot be the fill of a button with white words on it. Near-black with
   * white words is 15:1 and reads as the primary action without needing a
   * gradient to look like a button.
   */
  background: var(--btn-fill);
  color: var(--btn-label);
}

.btn-primary:hover {
  background: var(--btn-fill-hover);
  color: var(--btn-label);
}

.btn-ghost {
  border-color: var(--line);
  color: var(--text);
  background: var(--bg-panel);
}

.btn-ghost:hover {
  border-color: var(--btn-ghost-hover-line);
  background: var(--bg-raised);
}

.btn-sm {
  padding: 9px 18px;
  font-size: 0.9rem;
}

/* ---------------------------------------------------------------------------
   Hero
   --------------------------------------------------------------------------- */

.hero {
  padding: clamp(60px, 9vw, 116px) 0 clamp(40px, 5vw, 64px);
}

.hero h1 {
  max-width: 17ch;
  margin-bottom: 26px;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 38px;
}

.hero-note {
  margin-top: 18px;
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--text-dim);
}

/* ---------------------------------------------------------------------------
   The application, rendered
   --------------------------------------------------------------------------- */

.exhibit {
  margin-top: clamp(48px, 7vw, 84px);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-panel);
  /* Far lighter: 55% black under a panel on #0b0b0d is a soft glow; on
     off-white it is a bruise. */
  box-shadow: var(--shadow-card);
}

.exhibit-bar {
  display: flex;
  align-items: center;
  gap: 26px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-raised);
  font-size: 0.8rem;
  color: var(--text-dim);
}

.stat {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
}

.stat b {
  font-family: var(--mono);
  font-size: 1rem;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.stat.ok b {
  color: var(--ok);
}
.stat.err b {
  color: var(--err);
}
.stat.warn b {
  color: var(--warn);
}

.exhibit-scroll {
  overflow-x: auto;
}

table.grid {
  width: 100%;
  min-width: 700px;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: 0.84rem;
}

table.grid th {
  padding: 11px 18px;
  border-bottom: 1px solid var(--line);
  color: var(--text-dim);
  font-weight: 500;
  text-align: left;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 0.7rem;
  white-space: nowrap;
}

table.grid td {
  padding: 12px 18px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--text-soft);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

table.grid td:first-child {
  color: var(--text);
}

table.grid tr:last-child td {
  border-bottom: none;
}

table.grid td.num {
  text-align: right;
}

.delta-down {
  color: var(--err);
  font-weight: 600;
}

.verdict {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.verdict.match {
  background: var(--ok-wash);
  color: var(--ok);
}
.verdict.diff {
  background: var(--err-wash);
  color: var(--err);
}
.verdict.missing {
  background: var(--warn-wash);
  color: var(--warn);
}
.verdict.unreachable {
  background: var(--err-wash);
  color: var(--err);
}

.row-diff {
  background: rgba(207, 59, 50, 0.05);
}
.row-unreachable {
  background: rgba(207, 59, 50, 0.032);
}

.exhibit-log {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 13px 20px;
  border-top: 1px solid var(--line);
  background: var(--bg-raised);
  font-size: 0.82rem;
  color: var(--text-soft);
}

.exhibit-log .summary {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--text-dim);
}

.exhibit-caption {
  margin-top: 18px;
  max-width: 64ch;
  font-size: 0.92rem;
  color: var(--text-dim);
}

/* ---------------------------------------------------------------------------
   Sections
   --------------------------------------------------------------------------- */

section {
  padding: clamp(72px, 10vw, 148px) 0;
}

.section-head {
  max-width: 60ch;
  margin-bottom: clamp(44px, 5.5vw, 72px);
}

.section-head h2 {
  margin-bottom: 20px;
}

/* A heading with one control on its right, as the reference does. */
.head-row {
  display: flex;
  align-items: flex-end;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: clamp(44px, 5.5vw, 72px);
}

.head-row h2 {
  flex: 1;
  min-width: 0;
  max-width: 18ch;
}

/* --------------------------------------------------------------------------- */

.cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}

.card {
  padding: 32px 32px 34px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
  transition:
    border-color 180ms ease,
    background 180ms ease;
}

.card:hover {
  border-color: #3a3a44;
  background: var(--bg-raised);
}

.card h3 {
  margin-bottom: 12px;
}

.card p {
  color: var(--text-soft);
  font-size: 1rem;
}

.card-mark {
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin-bottom: 20px;
  border-radius: 11px;
  background: var(--accent-wash);
  color: var(--accent);
}

/* --------------------------------------------------------------------------- */

/* A panel beside a list of what it does — the reference's second screen. */
.showcase {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: 26px;
  align-items: start;
}

.panel {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
  overflow: hidden;
}

.panel-head {
  padding: 13px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-raised);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.panel-body {
  padding: 20px;
  font-family: var(--mono);
  font-size: 0.84rem;
  color: var(--text-soft);
  line-height: 1.75;
}

.log-line {
  display: flex;
  align-items: baseline;
  gap: 10px;
  white-space: nowrap;
  overflow: hidden;
}

.log-line .host {
  color: var(--text);
  font-weight: 600;
}

.log-line .sep {
  opacity: 0.35;
}

.log-line.bad,
.log-line.bad .host {
  color: var(--err);
}

/* The stack of claims beside it. The open one is filled, the rest are quiet —
   a list you read down rather than a set of boxes you scan. */
.stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.stack-item {
  padding: 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-panel);
}

.stack-item h3 {
  font-size: 1.06rem;
}

.stack-item p {
  margin-top: 8px;
  color: var(--text-soft);
  font-size: 0.94rem;
}

.stack-item.is-open {
  border-color: var(--accent);
  background: var(--accent-wash);
}

.stack-item.is-open h3 {
  color: var(--accent);
}

/* --------------------------------------------------------------------------- */

.menu-mock {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 14px;
}

.menu-mock .group {
  padding: 10px 10px 4px;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.menu-mock .item {
  padding: 8px 10px;
  border-radius: var(--radius);
  font-size: 0.94rem;
  color: var(--text-soft);
}

.menu-mock .item.indent {
  margin-left: 14px;
  padding-left: 12px;
  border-left: 1px solid var(--line);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.menu-mock .item.on {
  background: var(--accent-wash);
  border-left-color: var(--accent);
  color: var(--accent);
  font-weight: 500;
}

/* --------------------------------------------------------------------------- */

.systems {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.system {
  padding: 9px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-panel);
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--text-soft);
}

/* --------------------------------------------------------------------------- */

.cta {
  text-align: center;
}

.cta h2 {
  margin: 0 auto 20px;
  max-width: 16ch;
}

.cta .lede {
  margin: 0 auto;
}

.cta-actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 36px;
}

/* ---------------------------------------------------------------------------
   The cases
   ---------------------------------------------------------------------------
   Named reconciliations rather than named customers. Somebody arriving here
   does not want to know that Mosaic compares tables; they want to know whether
   it does the thing they are already doing badly in a spreadsheet, and the
   fastest way to answer that is to list six of them.
   --------------------------------------------------------------------------- */

.cases {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}

.case {
  padding: 26px 26px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
  transition: border-color 180ms ease;
}

.case:hover {
  border-color: rgba(255, 108, 55, 0.42);
}

.case h3 {
  margin-bottom: 8px;
  font-size: 1.04rem;
}

.case p {
  color: var(--text-soft);
  font-size: 0.92rem;
  line-height: 1.5;
}

/* The two systems, with the join between them drawn rather than described. */
.case-pair {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 14px;
  padding-top: 13px;
  border-top: 1px solid var(--line-soft);
  font-family: var(--mono);
  font-size: 0.76rem;
}

.case-pair span {
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-raised);
  color: var(--text-soft);
  white-space: nowrap;
}

.case-pair span:first-child::after {
  content: '';
}

.case-pair::before {
  content: '';
  order: 1;
  width: 18px;
  height: 1px;
  flex: none;
  background: var(--accent);
  opacity: 0.55;
}

.case-pair span:last-child {
  order: 2;
}

/* ---------------------------------------------------------------------------
   Minis: what each step actually looks like
   ---------------------------------------------------------------------------
   A card that is four lines of prose asks to be read before it can be
   understood. Each one now carries a small true picture of the thing it
   describes — the sources list, the mapping, the assertion, the boundary —
   drawn in markup from the same tokens as the rest, so it is the product at
   small scale rather than an illustration of it.
   --------------------------------------------------------------------------- */

.mini {
  margin-top: 22px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  /*
   * White, like the card it sits in.
   *
   * It was a black wash — on a near-black page, sinking a box *below* the
   * surface is how you show something inset, and the card was lighter than the
   * page so the well read as a well. Inverted onto white the same wash is a
   * grey panel inside a white one, which reads as a different material rather
   * than a recess.
   *
   * So the border does the separating and the fill matches. The card is white,
   * the box is white, and the hairline between them is the whole distinction —
   * which is how paper does it.
   */
  background: var(--bg-panel);
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text-soft);
}

.mini-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 2px;
  white-space: nowrap;
}

.mini-row + .mini-row {
  border-top: 1px solid var(--line-soft);
}

.mini-row svg {
  flex: none;
  opacity: 0.85;
}

.mini-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--text);
}

.mini-tag {
  flex: none;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--bg-raised);
  font-size: 0.68rem;
  /* `--text-dim` is 3.24:1 on this tint, which is thin for a 0.68rem label
     nobody can guess from context — "REST" and "file" are the information. */
  color: var(--text-soft);
}

.mini-tag.on {
  background: var(--accent-wash);
  color: var(--accent);
}

/* The mapping: two column names and the join between them. The dashes are the
   picture — what a connector does is decide that those two are one thing. */
.mini-map {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 6px 10px;
}

.mini-map span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 5px 0;
}

.mini-map .to {
  color: var(--accent);
  opacity: 0.75;
}

.mini-map .right {
  text-align: right;
  /*
   * `--text-dim` is a 3.5:1 grey, which is fine for a timestamp beside
   * something and wrong for one half of a pair the reader is meant to compare.
   * Both column names carry equal weight here — that two names are one thing is
   * the whole point of the picture.
   */
  color: var(--text-soft);
}

/* The assertion, as the editor writes it: three controls and a consequence. */
.mini-rule {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.chip {
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--bg-raised);
  color: var(--text);
  font-size: 0.76rem;
}

.chip.value {
  border-color: rgba(255, 108, 55, 0.45);
  color: var(--accent);
}

.mini-then {
  margin-top: 12px;
  padding-top: 11px;
  border-top: 1px solid var(--line-soft);
  /* A sentence rather than a label, so it takes body-text contrast. */
  color: var(--text-soft);
  font-size: 0.74rem;
  white-space: normal;
  line-height: 1.6;
}

/* The boundary: what is inside the network, and the one arrow that is not
   drawn. */
.mini-net {
  padding: 14px 12px 12px;
  border: 1px dashed rgba(255, 108, 55, 0.4);
  border-radius: 10px;
  background: rgba(255, 108, 55, 0.045);
}

.mini-net-label {
  margin-bottom: 10px;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.mini-net-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.node {
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--bg-raised);
  font-size: 0.74rem;
  color: var(--text);
}

.node.self {
  border-color: var(--accent);
  color: var(--accent);
}

.wire {
  color: var(--text-dim);
}

.mini-out {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 11px;
  color: var(--text-dim);
  font-size: 0.74rem;
}

.mini-out s {
  text-decoration-color: var(--err);
  text-decoration-thickness: 1.5px;
}

/* ---------------------------------------------------------------------------
   The download page
   ---------------------------------------------------------------------------
   The artefact first: a mark, the version beside it, and one button. Somebody
   who has reached this page has already decided — what they need is the file
   and the two commands after it, not more argument.
   --------------------------------------------------------------------------- */

.dl-top {
  position: relative;
  padding: clamp(52px, 7vw, 88px) 0 clamp(56px, 7vw, 92px);
  border-bottom: 1px solid var(--line);
}

.dl-grid {
  display: grid;
  grid-template-columns: 224px minmax(0, 1fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}

.dl-side {
  position: sticky;
  top: 96px;
}

.dl-mark {
  margin-bottom: 26px;
}

.dl-mark svg {
  border-radius: 16px;
  box-shadow: 0 12px 40px rgba(255, 108, 55, 0.22);
}

/* Version, date, size — the four facts somebody checks before pressing a
   button, in the machine's own voice. */
.dl-meta {
  margin: 0 0 26px;
  padding: 0 0 22px;
  border-bottom: 1px solid var(--line);
}

.dl-meta > div {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 6px 0;
}

.dl-meta dt {
  color: var(--text-dim);
  font-size: 0.86rem;
}

.dl-meta dd {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.84rem;
  color: var(--text);
  text-align: right;
}

.dl-links {
  display: flex;
  flex-direction: column;
  gap: 11px;
}

.dl-links a {
  color: var(--text-soft);
  text-decoration: none;
  font-size: 0.92rem;
  transition: color 140ms ease;
}

.dl-links a:hover {
  color: var(--accent);
}

.dl-main h1 {
  font-size: clamp(2.3rem, 4.6vw, 3.4rem);
  margin-bottom: 20px;
}

/* The button and what it will give you, side by side, so the size and the
   filename are read as part of pressing it rather than as small print. */
.dl-action {
  margin: 34px 0 8px;
  min-height: 56px;
}

.dl-primary {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

.btn-lg {
  padding: 16px 32px;
  font-size: 1.06rem;
}

.dl-file {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dl-file-name {
  font-family: var(--mono);
  font-size: 0.88rem;
  color: var(--text);
}

.dl-file-meta {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text-dim);
}

.dl-waiting {
  font-family: var(--mono);
  font-size: 0.88rem;
  color: var(--text-dim);
}

.dl-extras {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 16px;
}

.dl-extra {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-panel);
  color: var(--text-soft);
  font-family: var(--mono);
  font-size: 0.78rem;
  text-decoration: none;
  transition: border-color 140ms ease;
}

.dl-extra:hover {
  border-color: var(--accent);
  color: var(--text);
}

.dl-extra span {
  color: var(--text-dim);
}

/* When there is nothing to download, the panel says so and offers the next
   best thing rather than a button that cannot work. */
.dl-empty {
  padding: 26px 28px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
}

.dl-empty p {
  color: var(--text-soft);
  font-size: 0.98rem;
}

.dl-empty p + p {
  margin-top: 10px;
}

.dl-empty .btn {
  margin-top: 20px;
}

.dl-facts {
  margin: 34px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 62ch;
}

.dl-facts li {
  padding-left: 18px;
  border-left: 2px solid var(--line);
  color: var(--text-soft);
  font-size: 0.96rem;
  line-height: 1.55;
}

.dl-facts strong {
  color: var(--text);
  font-weight: 600;
}

/* --------------------------------------------------------------------------- */

.specs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--line);
}

.spec {
  padding: 24px 26px;
  background: var(--bg-panel);
}

.spec dt {
  margin-bottom: 8px;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}

.spec dd {
  margin: 0;
  color: var(--text-soft);
  font-size: 0.95rem;
  line-height: 1.55;
}

/* --------------------------------------------------------------------------- */

.steps-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}

.step-card {
  padding: 28px 28px 30px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
}

.step-n {
  display: inline-block;
  margin-bottom: 18px;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--accent);
}

/* The command itself, given the weight of the thing you are meant to copy. */
.step-cmd {
  display: block;
  margin-bottom: 16px;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: 10px;
  /* A command is quoted material rather than a recess, so it keeps a tint —
     but the page's own off-white, not a black wash that turns grey. */
  background: var(--bg-raised);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.86rem;
  overflow-x: auto;
  white-space: nowrap;
}

.step-card p {
  color: var(--text-soft);
  font-size: 0.94rem;
  line-height: 1.55;
}

@media (max-width: 940px) {
  .dl-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .dl-side {
    position: static;
  }

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

/* ---------------------------------------------------------------------------
   Release list
   --------------------------------------------------------------------------- */

.releases {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.release {
  padding: 26px 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
}

.release-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 4px;
}

.release-head h3 {
  font-size: 1.2rem;
}

.tag {
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--accent-wash);
  color: var(--accent);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 600;
}

.release-date {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--text-dim);
}

.release-notes {
  margin: 14px 0 20px;
  color: var(--text-soft);
  font-size: 0.95rem;
  white-space: pre-wrap;
}

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

.asset {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-raised);
  text-decoration: none;
  transition:
    border-color 150ms ease,
    background 150ms ease;
}

.asset:hover {
  border-color: var(--accent);
  background: var(--bg-hover);
}

.asset-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 0.9rem;
  color: var(--text);
}

.asset-meta {
  flex: none;
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.notice {
  padding: 28px 30px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
  color: var(--text-soft);
}

code {
  padding: 2px 7px;
  border-radius: 5px;
  background: var(--bg-raised);
  font-family: var(--mono);
  font-size: 0.88em;
  color: var(--text);
}

.steps-plain {
  margin: 0;
  padding-left: 22px;
  max-width: 72ch;
  color: var(--text-soft);
}

.steps-plain li {
  margin-bottom: 12px;
}

/* ---------------------------------------------------------------------------
   Footer
   --------------------------------------------------------------------------- */

.foot {
  padding: 48px 0 60px;
  border-top: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 0.9rem;
}

.foot-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 22px;
}

.foot a {
  color: var(--text-soft);
  text-decoration: none;
}

.foot a:hover {
  color: var(--text);
}

.foot-links {
  display: flex;
  gap: 24px;
  margin-left: auto;
}

/* ---------------------------------------------------------------------------
   Narrow
   --------------------------------------------------------------------------- */

@media (max-width: 940px) {
  .cases {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

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

  .nav-links a:not(.btn) {
    display: none;
  }

  body {
    background-size: 56px 56px;
  }
}

@media (max-width: 680px) {
  .cases {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .btn,
  .card,
  .asset {
    transition: none;
  }
}

/* A section lifted a shade off the page, to break a long column of text into
   parts without drawing a rule across it. */
.section-tinted {
  background: var(--bg-panel);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* ---------------------------------------------------------------------------
   The category distinction
   ---------------------------------------------------------------------------
   Positioning is partly a claim about what you are not. Adjacent tools answer
   real questions and answer them well; none of them answers this one, and
   saying so plainly is a stronger argument than claiming to be better at
   somebody else's job.

   Drawn as a list of question/answer pairs rather than a feature matrix: a
   comparison table invites a reader to score columns, and the point here is
   that these are different questions rather than different scores.
   --------------------------------------------------------------------------- */

.compare {
  max-width: 780px;
  margin: 0 auto;
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  background: var(--bg-panel);
}

.compare-row {
  display: flex;
  align-items: baseline;
  gap: 18px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--line);
}

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

.compare-kind {
  flex: none;
  width: 190px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-dim);
}

.compare-q {
  font-size: 16px;
  line-height: 1.5;
  color: var(--text-soft);
}

/* The last row is the one the page is about, so it is the only one lit. */
.compare-row.is-us {
  background: var(--accent-wash);
}

.compare-row.is-us .compare-kind {
  color: var(--accent);
}

.compare-row.is-us .compare-q {
  color: var(--text);
}

.compare-row.is-us b {
  color: var(--accent);
  font-weight: 600;
}

@media (max-width: 640px) {
  .compare-row {
    flex-direction: column;
    gap: 4px;
    padding: 13px 16px;
  }

  .compare-kind {
    width: auto;
  }
}

/* ---------------------------------------------------------------------------
   The waiting list
   ---------------------------------------------------------------------------
   On the download page, under the button — or under the sentence explaining
   why there is no button yet, which is the case it was built for.

   Styled as a panel rather than as a strip of form. Somebody who came here for
   a package and found none is being asked for something instead of given
   something, and the least that transaction deserves is to look deliberate.
   --------------------------------------------------------------------------- */

.waitlist {
  margin: 30px 0 8px;
  padding: 24px 26px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
  max-width: 620px;
}

.waitlist-title {
  font-size: 1.22rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin-bottom: 8px;
}

.waitlist-lede {
  color: var(--text-soft);
  font-size: 0.94rem;
  line-height: 1.55;
  max-width: 52ch;
}

.waitlist-row {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}

.waitlist-row input {
  flex: 1;
  min-width: 0;
  height: 46px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.96rem;
}

.waitlist-row input::placeholder {
  color: var(--text-dim);
}

.waitlist-row input:focus-visible {
  outline: none;
  border-color: var(--accent-soft);
  box-shadow: 0 0 0 3px var(--accent-wash);
}

.waitlist-row .btn {
  flex: none;
  height: 46px;
}

.waitlist-note {
  margin-top: 12px;
  min-height: 1.2em;
  font-size: 0.87rem;
  line-height: 1.5;
  color: var(--text-dim);
}

.waitlist-note.is-ok {
  color: var(--ok);
}

.waitlist-note.is-err {
  color: var(--err);
}

/* Answered. The field and the button go rather than being disabled in place:
   a greyed-out form under a message saying you are on the list invites a
   second attempt at something already done. */
.waitlist.is-done .waitlist-row {
  display: none;
}

/* One field and one button do not fit side by side on a phone, and shrinking
   the button until they do produces a target nobody can hit. */
@media (max-width: 560px) {
  .waitlist-row {
    flex-direction: column;
  }

  .waitlist-row .btn {
    justify-content: center;
  }
}

/*
 * Present to the page, absent from the screen.
 *
 * Used for the labels this form does not draw and for the honeypot it hides.
 * `display: none` would do neither job: a screen reader skips it, so the
 * labels would be lost, and the robots this is meant to catch skip it too.
 */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------------------
   The flow: systems → one reconciliation → verdicts
   ---------------------------------------------------------------------------
   The page's one diagram, and the only thing on it a reader has to understand.
   Three columns joined by dashed runs, collapsing to a stack on a phone where
   the connectors would be drawing sideways across nothing.
   --------------------------------------------------------------------------- */

.flow-band {
  padding: clamp(28px, 5vw, 56px) 0 clamp(20px, 4vw, 40px);
}

.flow {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: center;
  gap: 0;
  padding: clamp(18px, 3vw, 30px);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
}

.flow-col {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.flow-cap {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.flow-stack {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.flow-node {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  font-size: 0.88rem;
  line-height: 1.3;
  color: var(--text);
}

/* The row that says the list does not end, which is the actual claim: no
   border, no fill, so it reads as a continuation rather than a fifth item. */
.flow-node.is-more {
  border-color: transparent;
  background: none;
  color: var(--text-dim);
  font-size: 0.82rem;
  padding-top: 2px;
}

.flow-node .dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.dot.db { background: #e0533a; }
.dot.erp { background: #2f6df6; }
.dot.api { background: #a66912; }
.dot.file { background: #2c864d; }

/* The middle: one thing, and it should look like one thing. */
.flow-col-mid {
  align-items: stretch;
}

.flow-core {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 22px 18px;
  border: 1px solid var(--accent-soft);
  border-radius: var(--radius-lg);
  background: var(--accent-wash);
  text-align: center;
}

.flow-core strong {
  font-size: 1.02rem;
  letter-spacing: -0.01em;
}

.flow-core span {
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text-soft);
  max-width: 22ch;
}

/* The joins. Three dashed runs rather than one, so the left column reads as
   many things entering one — which is the sentence the diagram is making. */
.flow-link {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: clamp(24px, 4vw, 56px);
  padding: 0 6px;
}

.flow-link span {
  height: 1px;
  border-top: 1px dashed var(--line);
}

.flow-node.is-out {
  gap: 10px;
  font-size: 0.86rem;
  color: var(--text-soft);
}

.flow-node.is-out .verdict {
  flex: none;
}

@media (max-width: 900px) {
  .flow {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  /* Rotated to point down the page rather than across it. */
  .flow-link {
    flex-direction: row;
    justify-content: center;
    width: auto;
    height: 20px;
    gap: 22px;
  }

  .flow-link span {
    width: 1px;
    height: 100%;
    border-top: none;
    border-left: 1px dashed var(--line);
  }
}

/* ---------------------------------------------------------------------------
   Deployment, as facts
   ---------------------------------------------------------------------------
   A grid rather than a paragraph, because these are six independent claims and
   a reader wants the one that answers their objection — not to read the other
   five to reach it.
   --------------------------------------------------------------------------- */

.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
}

.fact {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  gap: 3px 12px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
}

.fact-mark {
  grid-row: 1 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--accent-wash);
  color: var(--accent);
}

.fact strong {
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  align-self: end;
}

.fact-note {
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text-soft);
  align-self: start;
}

/* ---------------------------------------------------------------------------
   Dark
   ---------------------------------------------------------------------------
   Declared twice on purpose, and the duplication is the point.

   The first block answers the operating system: somebody whose machine is set
   to dark should get a dark page without being asked, because they have
   already said so once and asking again is the site not listening. It is
   guarded on `:not([data-theme='light'])`, so a reader who explicitly chose
   light keeps it on a dark machine.

   The second answers the toggle in the header, and has to exist separately
   because a media query cannot be overridden by a choice — without it, "dark"
   would be unreachable on a machine set to light.

   The palette is the product's own, one shade at a time: the same warm greys
   the application uses in dark mode, so somebody who downloads Mosaic after
   reading this page is not surprised by what opens. Four surfaces rather than
   one flat black, for the reason the app's dark mode gives at length — a 1px
   line at 12% is either invisible or a scratch, and a page built only from
   them reads as a void with text floating in it.

   The semantic colours all lighten. This is the half a conversion usually gets
   wrong in the other direction: #2c864d is a good green on #faf9f7 and nearly
   black on #17171a, and a verdict nobody can read is worse than no colour.
   --------------------------------------------------------------------------- */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;

    --bg: #19191b;
    --bg-panel: #212123;
    --bg-raised: #292928;
    --bg-hover: #313130;

    --line: #37373a;
    --line-soft: #2b2b2d;

    --text: #f2f0ea;
    --text-soft: #b5b2a8;
    --text-dim: #8a8780;

    /* The three oranges swap roles. On black the brand value is legible as
       text — 6.2:1 — so the darkened one is no longer needed and would read as
       rust; what needs care instead is the wash, which has to lift off the
       surface rather than sink into it. */
    --accent: #ff8a5e;
    --accent-brand: #ff6c37;
    --accent-display: #ff8a5e;
    --accent-soft: #ff6c37;
    --accent-wash: rgba(255, 108, 55, 0.14);

    --ok: #4ec27a;
    --ok-wash: rgba(78, 194, 122, 0.16);
    --err: #f2685f;
    --err-wash: rgba(242, 104, 95, 0.16);
    --warn: #e5a34a;
    --warn-wash: rgba(229, 163, 74, 0.16);

    --nav-bg: rgba(25, 25, 27, 0.82);
    --grid-line: rgba(255, 255, 255, 0.03);
    /* The primary button inverts with the page: near-white with dark words,
       which is 15:1 the other way round and still the loudest thing on the
       screen without borrowing the accent. */
    --btn-fill: #f2f0ea;
    --btn-fill-hover: #ffffff;
    --btn-label: #19191b;
    --btn-ghost-hover-line: #55554f;
    --line-strong: #55554f;
    --ok-line: #2f5c42;
    --err-line: #6b3733;
    --grid-dot: rgba(255, 255, 255, 0.055);
    --shadow-card: 0 18px 50px rgba(0, 0, 0, 0.45);
  }
}

:root[data-theme='dark'] {
  color-scheme: dark;

  --bg: #19191b;
  --bg-panel: #212123;
  --bg-raised: #292928;
  --bg-hover: #313130;

  --line: #37373a;
  --line-soft: #2b2b2d;

  --text: #f2f0ea;
  --text-soft: #b5b2a8;
  --text-dim: #8a8780;

  --accent: #ff8a5e;
  --accent-brand: #ff6c37;
  --accent-display: #ff8a5e;
  --accent-soft: #ff6c37;
  --accent-wash: rgba(255, 108, 55, 0.14);

  --ok: #4ec27a;
  --ok-wash: rgba(78, 194, 122, 0.16);
  --err: #f2685f;
  --err-wash: rgba(242, 104, 95, 0.16);
  --warn: #e5a34a;
  --warn-wash: rgba(229, 163, 74, 0.16);

  --nav-bg: rgba(25, 25, 27, 0.82);
  --grid-line: rgba(255, 255, 255, 0.03);
  --btn-fill: #f2f0ea;
  --btn-fill-hover: #ffffff;
  --btn-label: #19191b;
  --btn-ghost-hover-line: #55554f;
  --line-strong: #55554f;
  --ok-line: #2f5c42;
  --err-line: #6b3733;
  --grid-dot: rgba(255, 255, 255, 0.055);
  --shadow-card: 0 18px 50px rgba(0, 0, 0, 0.45);
}

/* ---------------------------------------------------------------------------
   The five steps
   ---------------------------------------------------------------------------
   Connect, understand, reconcile, investigate, explain — in a row, numbered,
   with a hairline running through the numbers. The line is the content: these
   are not five features a reader may pick from, they are one sequence, and the
   second one is the only one nobody else has.

   Five across on a wide window and two-up as it narrows. Never one column: a
   single stack of five reads as a feature list, which is the register this
   strip exists to avoid.
   --------------------------------------------------------------------------- */

.spine-band {
  padding: clamp(24px, 4vw, 48px) 0 clamp(8px, 2vw, 20px);
}

.spine {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.spine li {
  position: relative;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 0 clamp(12px, 2vw, 24px);
}

/* The rule between steps, drawn on the item rather than as a border on a
   container, so the first one has nothing to its left. */
.spine li + li::before {
  content: '';
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 0;
  border-left: 1px solid var(--line);
}

.spine-n {
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  color: var(--accent);
}

.spine strong {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text);
}

.spine li span:last-child {
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--text-soft);
}

/* Understand is the differentiator, so it is the one step the eye lands on.
   Marked with weight rather than with a colour fill — a highlighted card in a
   row of five reads as a promotion, and this is meant to read as the step the
   others depend on. */
.spine li:nth-child(2) .spine-n {
  font-weight: 600;
}

.spine li:nth-child(2) strong {
  color: var(--accent);
}

@media (max-width: 940px) {
  .spine {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 22px 0;
  }

  /* On two columns the rule has to fall on the left-hand edge of the right-hand
     item only, or every second row grows a line down its middle and the last
     row grows one out of nothing. */
  .spine li + li::before {
    display: none;
  }

  .spine li:nth-child(even)::before {
    display: block;
  }
}

@media (max-width: 520px) {
  .spine {
    grid-template-columns: minmax(0, 1fr);
  }

  .spine li {
    padding: 0;
  }

  .spine li:nth-child(even)::before {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
   What a column is called, what is in it, what it means
   ---------------------------------------------------------------------------
   Three panes and two arrows: the name, the values, the meaning. The whole
   argument of the page's differentiator fits in one picture, and it has to be a
   picture — "Mosaic understands the semantics of enterprise data" is a sentence
   nobody believes, and `CUST_GENDER → RETAIL, WEB, PARTNER → sales channel` is
   one nobody has to.

   Built from markup for the same reasons the result table is: it is text at
   every size, it takes the reader's theme, and the example can be corrected by
   editing it.
   --------------------------------------------------------------------------- */

.rosetta {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: stretch;
  margin-bottom: clamp(22px, 3vw, 38px);
  padding: clamp(18px, 3vw, 30px);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-panel);
}

.rosetta-col {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0 clamp(10px, 2vw, 22px);
}

.rosetta-cap {
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* The column name, set as the database writes it — including the shouting. Half
   the point of the example is that this string is all the schema offers. */
.rosetta-field {
  align-self: flex-start;
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--bg-raised);
  font-family: var(--mono);
  font-size: 0.94rem;
  color: var(--text);
}

.rosetta-values {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.rosetta-values span {
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-raised);
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text);
}

/* The answer, and the only thing on the row set in the accent: it is what the
   product produces and what the reader is meant to remember. */
.rosetta-meaning {
  align-self: flex-start;
  padding: 7px 13px;
  border: 1px solid var(--accent);
  border-radius: 9px;
  background: var(--accent-wash);
  font-family: var(--mono);
  font-size: 0.94rem;
  font-weight: 600;
  color: var(--accent);
}

.rosetta-note {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--text-soft);
}

.rosetta-note code {
  font-family: var(--mono);
  font-size: 0.92em;
  color: var(--text);
}

/* Three dashed runs, as the fleet diagram uses — one picture's grammar reused
   rather than a second one invented. */
.rosetta-step {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 12px;
  width: clamp(22px, 3.5vw, 48px);
  padding: 0 6px;
}

.rosetta-step span {
  height: 1px;
  border-top: 1px dashed var(--line);
}

@media (max-width: 940px) {
  .rosetta {
    grid-template-columns: minmax(0, 1fr);
    gap: 4px;
  }

  .rosetta-col {
    padding: 14px 0;
  }

  /* Rotated to point down the page rather than across it. */
  .rosetta-step {
    flex-direction: row;
    justify-content: center;
    width: auto;
    height: 18px;
    gap: 20px;
  }

  .rosetta-step span {
    width: 1px;
    height: 100%;
    border-top: none;
    border-left: 1px dashed var(--line);
  }
}

/* ---------------------------------------------------------------------------
   The switch
   ---------------------------------------------------------------------------
   In the header beside the download button, which is where every reader of a
   documentation site now looks for it. One control with two icons rather than
   three states: "follow the system" is what you get before touching it, and a
   third option to return to it is a setting rather than a switch.
   --------------------------------------------------------------------------- */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-panel);
  color: var(--text-soft);
  cursor: pointer;
  transition:
    border-color 0.15s ease,
    color 0.15s ease;
}

.theme-toggle:hover {
  border-color: var(--btn-ghost-hover-line);
  color: var(--text);
}

/* One of the two is drawn at a time. Both live in the markup so the swap is a
   class rather than a re-render, and so the button has something to show
   before any script has run. */
.theme-toggle .icon-moon {
  display: none;
}

:root[data-theme='dark'] .theme-toggle .icon-sun,
:root:not([data-theme='light']) .theme-toggle .icon-sun {
  display: none;
}

:root[data-theme='dark'] .theme-toggle .icon-moon,
:root:not([data-theme='light']) .theme-toggle .icon-moon {
  display: block;
}

/* Back the other way when the system is light and nothing has been chosen —
   the rule above is written for the dark default and would otherwise hide the
   sun on a light machine. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) .theme-toggle .icon-sun {
    display: block;
  }

  :root:not([data-theme='dark']) .theme-toggle .icon-moon {
    display: none;
  }
}
