/* ---------------------------------------------------------------------------
   The site's bones: the editorial page
   ---------------------------------------------------------------------------
   Every page loads this first: the palette in both themes, the type, the
   buttons, the bar, the footer and the cookie banner. A page then brings its
   own pieces — `home.css` for the home page, `site.css` for the inner pages,
   `docs/docs.css` for the documentation.

   The direction is mockup D on the "DataMosaic Landing Mockups" canvas (Nov
   2026), "We make your job different": a near-white sheet ruled into columns,
   headlines in Geist at its regular weight and drawn tight, black pill
   buttons, flat grey cards, and the product shown in real screens rather
   than described. One accent — the brand orange — and only where a sentence
   turns on it.

   No gradients. The one exception is the grainy orange-to-purple stage the
   home page plays its real screens on (`.stage-grad` in `home.css`), in two
   places and nowhere else.

   Light is the page it is drawn on. Dark is the same design at night, chosen
   by the visitor's system or the switch in the footer; the head of every page
   sets `data-theme` before anything is painted, so no rule here waits for a
   media query.

   The older names (`--bg-panel`, `--bg-raised`, `--font-display`, `--serif`…)
   are kept beside the new ones, because `site.css`, `flow.css`, the blog, the
   scorecards and the pages' inline styles are written in them. `--serif` no
   longer names a serif: the headlines it set are Geist now, like the rest.
   --------------------------------------------------------------------------- */

/* --- the typefaces --------------------------------------------------------- */

/* Geist and Geist Mono, served from this site (`fonts/`, under the SIL Open
   Font License in `fonts/OFL.txt`, from @fontsource-variable 5.3.0) rather
   than from Google Fonts, so a page load sends nobody's address to a third
   party. One variable file per face covers every weight the site uses; Latin
   Extended is fetched only by a page that has a character from it. The URLs
   are relative to this file, so the blog's share images, drawn from disk,
   find them too. */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('fonts/geist-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('fonts/geist-latin-ext-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('fonts/geist-mono-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('fonts/geist-mono-latin-ext-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --bg: #fcfcfb;
  --panel: #ffffff;
  --card: #f4f4f2;
  --side: #fafaf9;
  --seg: #f1f1ef;
  --line: #e4e4e1;
  --line-soft: #ececea;
  --text: #0a0a0a;
  /* Body copy beside a headline: a step softer than the ink, never grey. */
  --text-body: #3f3f46;
  --text-soft: #52525b;
  /* The inner pages and the docs set whole paragraphs in it, and it has to
     read at 4.5:1 on the paper. */
  --text-dim: #6b6b74;
  --brand: #ff6c37;
  --accent: #c7491c;
  /* The dot beside a section's label, and a difference in a table. */
  --spot: #f05a22;
  /* The marker under a phrase, and the wash behind a quiet highlight. */
  --wash: rgba(255, 108, 55, 0.27);
  --accent-wash: rgba(199, 73, 28, 0.09);
  --ok: #2c864d;
  --err: #cf3b32;
  --warn: #b46a00;
  --warn-dot: #e59a1a;
  --violet: #5a46d2;
  --btn: #111111;
  --btn-text: #ffffff;
  --paper: #ffffff;
  --paper-ink: #161616;
  --paper-rule: #cfccc4;
  --slip-shade: rgba(17, 17, 17, 0.22);
  --dot: rgba(17, 17, 17, 0.11);
  --row-hl: #fbf6ef;
  --chrome-dot: #d9d4ca;
  --shadow-k: 0.28;
  --shadow-win: 0 40px 90px -40px rgba(17, 17, 17, 0.35);
  --shadow-pop: 0 26px 60px -18px rgba(17, 17, 17, 0.32);

  --bg-panel: var(--panel);
  --bg-raised: var(--card);
  --accent-brand: var(--brand);

  /* The dark ground a section can still be set on, in either theme. */
  --ink: #0c0d0d;
  --ink-raised: #191d1c;
  --ink-line: #2a302e;
  --ink-text: #f4f3f0;
  --ink-soft: #a8ada9;

  --sans: 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --serif: var(--sans);
  --mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-display: 'Geist';
  --font-ui: 'Geist';
  --font-mono: var(--mono);

  --r-sm: 8px;
  --r: 14px;
  --r-lg: 20px;
  --r-xl: 22px;

  /* The column the page is ruled into: 1180px of sheet, its content 32px in
     from each rule on a wide screen and 16px on a phone. */
  --measure: 1180px;
  --gutter: clamp(16px, 3vw, 32px);

  font-synthesis-weight: none;
  color-scheme: light;
}

:root[data-theme='dark'] {
  --bg: #0f1110;
  --panel: #171a19;
  --card: #141716;
  --side: #131615;
  --seg: #1f2321;
  --line: #2a2f2d;
  --line-soft: #222725;
  --text: #f4f3f0;
  --text-body: #c9cdca;
  --text-soft: #b3b8b4;
  --text-dim: #868b87;
  --accent: #ff8a5c;
  --spot: #ff7a45;
  --wash: rgba(255, 108, 55, 0.3);
  --accent-wash: rgba(255, 108, 55, 0.13);
  --ok: #4ec27a;
  --err: #ff6b63;
  --warn: #f0b04a;
  --warn-dot: #f0b04a;
  --violet: #9187ff;
  --btn: #f4f3f0;
  --btn-text: #0f1110;
  --paper: #ecebe6;
  --paper-rule: #b9b6ae;
  --slip-shade: rgba(0, 0, 0, 0.55);
  --dot: rgba(244, 243, 240, 0.09);
  --row-hl: #1d1b17;
  --chrome-dot: #34403c;
  --shadow-k: 1;
  --shadow-win: 0 40px 90px -40px rgba(0, 0, 0, 0.8);
  --shadow-pop: 0 26px 60px -18px rgba(0, 0, 0, 0.75);
  --ink: #070808;
  color-scheme: dark;
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

a {
  color: inherit;
}

button {
  font: inherit;
  color: inherit;
}

::selection {
  background: var(--brand);
  color: #fff;
}

/* --- type ---------------------------------------------------------------- */

/* One face, Geist, for the headlines and the product alike. The headlines are
   what carry the voice: the regular weight, large, drawn tight — never bold.
   A heavier weight is kept for the small labels that name a thing. */
h1,
h2,
h3 {
  margin: 0;
  text-wrap: balance;
}

h1,
h2,
.display {
  font-family: var(--sans);
  font-weight: 400;
  letter-spacing: -0.035em;
  line-height: 1.1;
}

h1 {
  letter-spacing: -0.045em;
  line-height: 1.02;
}

h3 {
  font-family: var(--sans);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.3;
}

p {
  margin: 0;
  text-wrap: pretty;
}

/* The marker under the phrase a sentence turns on. One per section at most. */
mark {
  color: inherit;
  background: none;
  box-shadow: inset 0 -0.32em 0 var(--wash);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  padding: 0 0.04em;
}

.wrap {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.ico {
  width: 1em;
  height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

.glyph {
  width: 1em;
  height: 1em;
  fill: currentColor;
  flex: none;
}

/* What a section is about, in a word, above its headline. A dot in the
   accent when the section is one of the product's parts. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font: 400 16px/1.4 var(--sans);
  color: var(--text-dim);
}

.eyebrow .dot {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  background: var(--spot);
}

.link {
  color: var(--text);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  text-underline-offset: 3px;
}

.link:hover {
  text-decoration-color: currentColor;
}

/* --- buttons --------------------------------------------------------------- */

/* One action, in ink: a black pill on paper, a paper one at night. The orange
   is kept for the sentence a page turns on, so the thing to press never
   competes with the thing to read. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 22px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--btn);
  color: var(--btn-text);
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease;
}

.btn:hover {
  background: color-mix(in srgb, var(--btn) 84%, var(--bg));
}

.btn:active {
  background: var(--btn);
}

.btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}

.btn .ico {
  width: 16px;
  height: 16px;
  stroke-width: 2;
}

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

.btn-lg {
  padding: 14px 24px;
  font-size: 16px;
}

/* The other way: a paper pill with a rule round it, never a second black
   button. `.btn.ghost` is the older name for the same thing. */
.btn-ghost,
.btn.ghost {
  border-color: var(--line);
  background: var(--panel);
  color: var(--text);
}

.btn-ghost:hover,
.btn.ghost:hover {
  border-color: var(--text-dim);
  background: var(--panel);
}

.btn-ink {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.06);
  color: var(--ink-text);
}

/* Small print under a call to action: the objection, answered before it. */
.reassure {
  margin-top: 14px;
  font-size: 13.5px;
  color: var(--text-dim);
}

/* --- the bar --------------------------------------------------------------- */

.bar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--line-soft);
}

.bar .wrap {
  display: flex;
  align-items: center;
  gap: 40px;
  height: 64px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-right: auto;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.035em;
  text-decoration: none;
}

/* In the bar the links sit beside the name and the two buttons at the far
   end, so the name gives up the space it takes in the footer. */
.bar .brand {
  margin-right: 0;
}

/* The application's own mark: an orange square with a white M. */
.brand img {
  width: 22px;
  height: 22px;
}

.bar nav {
  display: flex;
  flex: 1;
  align-items: center;
  --nav-gap: 26px;
  gap: var(--nav-gap);
  font-size: 14px;
  color: var(--text);
}

.bar nav a {
  text-decoration: none;
  white-space: nowrap;
}

.bar nav a:hover {
  color: var(--text-soft);
}

.bar nav a[aria-current='page'] {
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-decoration-thickness: 2px;
  text-underline-offset: 8px;
}

/* Log in, as a paper pill: the first of the two buttons at the far end. */
.bar nav .login {
  margin-left: auto;
  margin-right: calc(8px - var(--nav-gap));
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
}

.bar nav .login:hover {
  border-color: var(--text-dim);
  color: var(--text);
}

.bar nav .btn {
  color: var(--btn-text);
}

/* The Resources menu: the blog and the scorecards. No script — it opens while
   the pointer is over it or the focus is inside it (a tab, a click, a tap), and
   closes the moment either leaves. The panel's top padding is the bridge the
   pointer crosses from the word to the card. */
.menu {
  position: relative;
}

.menu-button {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  white-space: nowrap;
  cursor: pointer;
}

.menu-button:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 4px;
  border-radius: 4px;
}

.menu-button .chev {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.15s ease;
}

.menu:hover .menu-button,
.menu:focus-within .menu-button,
.menu.is-current .menu-button {
  color: var(--text);
}

.menu:hover .chev,
.menu:focus-within .chev {
  transform: rotate(180deg);
}

.menu-panel {
  position: absolute;
  top: 100%;
  left: 50%;
  z-index: 50;
  display: none;
  padding-top: 12px;
  transform: translateX(-50%);
}

.menu:hover .menu-panel,
.menu:focus-within .menu-panel {
  display: block;
}

.menu-card {
  display: grid;
  gap: 2px;
  width: 310px;
  padding: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-pop);
}

.bar nav .menu-card a {
  display: grid;
  gap: 2px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  color: var(--text);
  white-space: normal;
}

.bar nav .menu-card a:hover,
.bar nav .menu-card a:focus-visible,
.bar nav .menu-card a[aria-current='page'] {
  background: var(--card);
  outline: none;
}

.menu-card b {
  font-size: 14.5px;
  font-weight: 500;
}

.menu-card span {
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-dim);
}

.menu-label {
  margin: 8px 12px 2px;
  font: 500 12px var(--sans);
  color: var(--text-dim);
}

/* --- the footer ------------------------------------------------------------ */

footer.site {
  margin-top: 150px;
  padding: 56px 0 40px;
  border-top: 1px solid var(--line-soft);
  background: var(--panel);
  font-size: 14px;
}

.foot-grid {
  display: grid;
  grid-template-columns: 2.2fr 1fr 1fr 1fr 1fr;
  gap: 32px;
}

.foot-grid p {
  margin: 14px 0 0;
  color: var(--text-soft);
}

.foot-grid p.small {
  font-size: 13px;
  color: var(--text-dim);
}

.foot-grid h5 {
  margin: 4px 0 14px;
  font: 500 14px var(--sans);
  color: var(--text);
}

.foot-grid ul {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

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

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

.foot-grid ul a:hover,
.foot-grid ul a[aria-current='page'] {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.foot-base {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 54px;
  padding-top: 22px;
  border-top: 1px solid var(--line-soft);
  font-size: 13px;
  color: var(--text-dim);
}

/* Where `consent.js` puts "Cookie settings": the way to withdraw sits on every
   page, beside the copyright, where somebody looking for it will look. */
.foot-legal {
  display: flex;
  gap: 18px;
  margin-right: auto;
}

/* A button, because it does something rather than going somewhere — drawn as
   the words beside it, because that is what it is to somebody reading the row. */
.consent-open {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.consent-open:hover {
  color: var(--text);
}

.consent-open:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: 4px;
}

/* The switch between light and dark. It shows where it would take you: the
   moon on the paper, the sun at night. */
.theme {
  display: inline-grid;
  place-items: center;
  padding: 6px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--text-soft);
  cursor: pointer;
}

.theme:hover {
  background: var(--seg);
  color: var(--text);
}

.theme:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.theme svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.theme .sun,
:root[data-theme='dark'] .theme .moon {
  display: none;
}

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

/* --- a system's mark ------------------------------------------------------- */

/* A tile carrying one kind of system, drawn by `marks.js`. These stand for
   kinds of system rather than products — a page that lines up other companies'
   logos is making a claim about them. */
.mark {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--panel);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}

.mark svg {
  width: 26px;
  height: 26px;
}

.mark-label {
  margin-top: 8px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-dim);
  text-align: center;
}

/* ---------------------------------------------------------------------------
   The cookie banner
   ---------------------------------------------------------------------------
   A bar across the foot of the window, on the page's own measure: the words
   on the left, the two answers at the right edge. Nothing is withheld until it
   is answered — the site works the same either way — so it covers the last
   strip of the page and not the page. Built by `consent.js`, which is why it
   is styled here: every page loads this file and none contains the markup.
   --------------------------------------------------------------------------- */

.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  padding: 18px 0;
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel) 94%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: 0 -18px 50px -24px rgb(0 0 0 / calc(0.75 * var(--shadow-k)));
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-soft);
  opacity: 0;
  transform: translateY(100%);
  visibility: hidden;
  transition:
    opacity 260ms ease,
    transform 320ms cubic-bezier(0.2, 0.7, 0.2, 1),
    visibility 0s linear 320ms;
}

.consent.is-open {
  opacity: 1;
  transform: none;
  visibility: visible;
  transition-delay: 0s;
}

.consent-in {
  display: flex;
  align-items: center;
  gap: 18px 40px;
}

.consent-words {
  flex: 1;
  min-width: 0;
  display: grid;
  gap: 4px;
  max-width: 78ch;
}

.consent-title {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
}

.consent a {
  color: var(--text);
  text-underline-offset: 3px;
  white-space: nowrap;
}

/* One size for both, side by side — see `build` in `consent.js`. */
.consent-actions {
  flex: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.consent-actions .btn {
  min-width: 116px;
  padding: 10px 18px;
  font-size: 14.5px;
}

/* --- narrower ---------------------------------------------------------------- */

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

  .foot-grid > div:first-child {
    grid-column: span 2;
  }
}

/* Six links and a button: between a phone and a laptop they need closer
   spacing, or the links run into the name — and below 760 one of them has to
   go. Docs goes, since it is in the footer and is not where a first visit
   starts. */
@media (max-width: 860px) {
  .bar .wrap {
    gap: 18px;
  }

  .bar nav {
    --nav-gap: 16px;
  }
}

@media (max-width: 760px) {
  .bar nav a.hide-s[href='/docs'] {
    display: none;
  }
}

@media (max-width: 760px) {
  .consent {
    padding: 16px 0 18px;
  }

  .consent-in {
    flex-direction: column;
    align-items: stretch;
  }
}

@media (max-width: 640px) {
  :root {
    --gutter: 16px;
  }

  .bar .wrap {
    gap: 16px;
  }

  .bar nav {
    --nav-gap: 16px;
  }

  .bar nav .hide-s {
    display: none;
  }

  .foot-grid {
    grid-template-columns: 1fr;
  }

  .foot-grid > div:first-child {
    grid-column: auto;
  }

  .foot-base {
    flex-wrap: wrap;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}
