/* ==========================================================================
   Tokens.

   Colour is reserved for what the visitor can act on. Cloud Blue #0176D3 is
   kept for buttons and links, because it is the product's own accent and the
   buyer lands in the app five minutes later - but the surfaces around it are
   neutral greys rather than the blue tints they used to be. A page that is
   blue everywhere gives an action no way to stand out.

   Orange is the one colour from outside that system, and it is reserved: an
   unfilled site.config.json value and nothing else. Anything warm on this page
   is therefore unfinished copy, at a glance and without reading it.

   There is no dark theme. The site rendered navy for anyone whose system asked
   for dark, which is not what a product page should do to a first-time visitor
   arriving from a listing; one light document is the whole palette.

   What carries the contemporary feel is therefore not colour but depth, space
   and type: layered shadows tinted with the ink rather than pure black, a
   translucent masthead, generous section rhythm and a fluid type scale.
   ========================================================================== */
:root {
  --paper: #ffffff;
  --paper-sunken: #f7f7f8;
  --paper-raised: #ffffff;
  /* The masthead and the carousel arrows sit *over* content and let it show
     through, so they need a translucent paper rather than an opaque one. */
  --paper-veil: rgba(255, 255, 255, 0.78);
  --sky: #f4f5f6;
  --sky-strong: #eceef0;

  --ink: #1c1d1f;
  --ink-body: #3f4143;
  --ink-soft: #5a5c5f;
  /* The lightest grey that still clears 4.5:1 on --sky-strong, the darkest surface
     faint text ever lands on. Lighter and captions fail on the tinted bands. */
  --ink-faint: #6c6c6e;
  --rule: #e6e7e9;
  --rule-strong: #c4c6c9;
  /* The border of the secondary button, and the one grey with a contrast floor to
     respect: WCAG 1.4.11 asks 3:1 for the boundary of a control, and --rule-strong
     measures 1.71 on paper. #85888C is the lightest grey that still clears 3:1 on
     every surface a button can land on, sky-strong included. */
  --rule-action: #85888c;

  --accent: #0176d3;
  --accent-hover: #014486;
  --accent-text: #014486;
  --accent-text-hover: #032d60;
  --accent-ink: #ffffff;
  /* Callout ground. Neutral like every other surface: a callout is something to
     read, not something to click, and a blue panel competes with the buttons. */
  --accent-wash: #f4f5f6;

  /* The masthead wordmark, and nothing else. --ink stopped being navy because navy
     headings tinted the whole page before a button was seen; one word in the masthead is
     a brand signature, not a page tint, so it keeps Midnight. */
  --brand-ink: #032d60;

  --footer-bg: #1c1d1f;
  --footer-ink: #ffffff;
  --footer-soft: #a9abae;
  --footer-rule: #3a3c3f;

  --flag-bg: #fef1e3;
  --flag-rule: #fe9339;
  --flag-ink: #8c4b02;

  /* Shadows are tinted with the ink rather than pure black, and every one of them
     is two layers: a tight contact shadow that seats the element, and a wide soft
     one that lifts it. A single blurred black shadow is what makes a card look
     like a 2012 card. */
  --shadow-hair: 0 1px 2px rgba(17, 19, 22, 0.05);
  --shadow-card:
    0 1px 2px rgba(17, 19, 22, 0.04), 0 4px 14px rgba(17, 19, 22, 0.05);
  --shadow-raised:
    0 2px 4px rgba(17, 19, 22, 0.05), 0 16px 36px rgba(17, 19, 22, 0.1);
  /* The one coloured shadow, and only under the primary action: it reads as the
     button glowing rather than as a grey box, which is what separates the single
     thing to click from everything around it. */
  --shadow-action:
    0 1px 2px rgba(1, 68, 134, 0.24), 0 8px 20px rgba(1, 118, 211, 0.22);

  --display:
    Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
    sans-serif;
  --body:
    Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
    sans-serif;
  --mono:
    ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --measure: 68ch;
  --wrap: 1140px;
  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  --header-h: 4.5rem;
  /* One rhythm for the whole page. A section is the same height everywhere, so
     the eye learns the beat instead of meeting a new gap on every band. */
  --section: clamp(3.5rem, 6vw, 6rem);
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  /* The carousel dots and the table of contents are in-page anchors and the
     masthead is sticky, so a jump would otherwise land the target underneath it. */
  scroll-padding-top: calc(var(--header-h) + 1rem);
}
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-body);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

::selection {
  background: var(--sky-strong);
  color: var(--ink);
}

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.025em;
  color: var(--ink);
  text-wrap: balance;
  margin: 0 0 0.5em;
}
h1 {
  font-size: clamp(2.5rem, 1.5rem + 3.9vw, 4rem);
  letter-spacing: -0.035em;
}
h2 {
  font-size: clamp(1.7rem, 1.2rem + 1.8vw, 2.5rem);
  letter-spacing: -0.03em;
}
h3 {
  font-size: 1.12rem;
  font-weight: 600;
  letter-spacing: -0.012em;
}

p,
li,
dd,
td {
  color: var(--ink-body);
  /* Stops the one-word last line that makes a paragraph look unfinished. */
  text-wrap: pretty;
}
p {
  margin: 0 0 1.15em;
}
strong {
  color: var(--ink);
  font-weight: 600;
}

a {
  color: var(--accent-text);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.15s var(--ease);
}
a:hover {
  color: var(--accent-text-hover);
  text-decoration-thickness: 2px;
}
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

.wrap {
  width: min(100% - 2.5rem, var(--wrap));
  margin-inline: auto;
}
.measure {
  max-width: var(--measure);
}
.muted {
  color: var(--ink-faint);
  font-size: 0.9rem;
}
.center {
  text-align: center;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 0.6rem 1rem;
  background: var(--accent);
  color: var(--accent-ink);
  z-index: 20;
}
.skip:focus {
  left: 0;
}

/* ------------------------------------------------------------- masthead --- */
/* Translucent rather than solid: the page slides *under* the bar instead of
   disappearing behind a white block, which is what makes a sticky header read as
   a layer rather than as a lid. The opaque fallback matters — without it the bar
   would be see-through on a browser with no backdrop-filter. */
.site-header {
  border-bottom: 1px solid var(--rule);
  background: var(--paper-veil);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  position: sticky;
  top: 0;
  z-index: 10;
}
@supports not (
  (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))
) {
  .site-header {
    background: var(--paper);
  }
}
.header-inner {
  display: flex;
  align-items: center;
  gap: 1rem 1.5rem;
  min-height: var(--header-h);
  flex-wrap: wrap;
  padding-block: 0.5rem;
}
/* A wordmark and no mark: with nothing beside it the word carries the masthead on its
   own, so it is set a little larger and tighter than a label would be. */
.brand {
  display: inline-flex;
  align-items: center;
  font-family: var(--display);
  font-size: 1.28rem;
  font-weight: 700;
  color: var(--brand-ink);
  text-decoration: none;
  letter-spacing: -0.035em;
}
.site-header nav {
  display: flex;
  align-items: center;
  gap: 0.35rem 0.4rem;
  flex-wrap: wrap;
  margin-left: auto;
}
.site-header nav a:not(.btn) {
  font-size: 0.925rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  padding: 0.45rem 0.85rem;
  border-radius: var(--radius-pill);
  transition:
    background-color 0.15s var(--ease),
    color 0.15s var(--ease);
}
.site-header nav a:not(.btn):hover {
  color: var(--accent-text);
  background: var(--sky);
}
.site-header nav a[aria-current] {
  color: var(--accent-text);
  background: var(--sky-strong);
  font-weight: 600;
}
.nav-cta {
  margin-left: 0.6rem;
}

.nav-toggle {
  display: none;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-left: auto;
  padding: 0;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-hair);
  cursor: pointer;
}
.nav-toggle .nav-toggle-close,
.nav-toggle[aria-expanded="true"] .nav-toggle-open {
  display: none;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-close {
  display: block;
}
/* The collapsed menu exists only once the script has claimed the toggle; the
   html attribute is what the script sets, so a page without it keeps the wrapped
   navigation and never hides a link it cannot show again. */
@media (max-width: 47.99rem) {
  html[data-nav-js] .nav-toggle {
    display: grid;
    flex: none;
  }
  /* The brand and the toggle share the first line whatever the length of the
     name, so the toggle is never pushed to a line of its own. */
  html[data-nav-js] .brand {
    flex: 1 1 0;
    min-width: 0;
  }
  html[data-nav-js] .brand span {
    overflow-wrap: anywhere;
  }
  html[data-nav-js] #site-nav {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0.15rem;
    margin: 0.25rem 0 0.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--rule);
  }
  html[data-nav-js] #site-nav.is-open {
    display: flex;
  }
  html[data-nav-js] #site-nav a:not(.btn) {
    padding: 0.7rem 0.85rem;
    font-size: 1rem;
  }
  html[data-nav-js] .nav-cta {
    margin: 0.6rem 0 0;
    justify-content: center;
  }
}

/* --------------------------------------------------------------- blocks --- */
section > .wrap {
  padding-block: var(--section);
}
.hero > .wrap {
  padding-block: clamp(4rem, 8vw, 7rem) clamp(2.5rem, 4.5vw, 3.75rem);
}
/* A hero and the section under it both pay the full rhythm, which on a page with
   no tinted band between them stacks into a gap wide enough to read as a missing
   block. A section that carries its own ground keeps its padding — there the space
   is what separates the two surfaces. */
.hero + section:not(.sunken) > .wrap {
  padding-top: clamp(1.75rem, 3vw, 2.75rem);
}

/* Two layers rather than one band: a wide radial that pools behind the headline
   and fades before it reaches the edges, over a vertical fade to paper. A flat
   full-width tint reads as a stripe glued to the top of the page; this reads as
   light. The dot grid on top is masked to the same pool so it fades with it. */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background:
    radial-gradient(
      75rem 32rem at 50% -14rem,
      var(--sky-strong) 0%,
      transparent 62%
    ),
    linear-gradient(180deg, var(--sky) 0%, var(--paper) 74%);
}
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(var(--rule-strong) 1px, transparent 1.5px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(
    60rem 26rem at 50% -6rem,
    var(--ink) 0%,
    transparent 70%
  );
  mask-image: radial-gradient(
    60rem 26rem at 50% -6rem,
    var(--ink) 0%,
    transparent 70%
  );
  opacity: 0.55;
  pointer-events: none;
}
.hero-center .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.hero-center .lead {
  margin-inline: auto;
}
.hero-center .actions {
  justify-content: center;
}
.sunken {
  background: var(--paper-sunken);
  border-block: 1px solid var(--rule);
}

/* The label above a section heading. A plain line of small caps rather than a chip:
   the hero used to carry a bordered pill and it read as a template badge, so the pill
   went and this is what the family settled on. Do not give it a background. */
.kicker {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin-bottom: 0.9rem;
}
.section-head {
  max-width: 60ch;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.section-head.center {
  margin-inline: auto;
  text-align: center;
}
.section-head h2:last-child,
.section-head .lead {
  margin-bottom: 0;
}
.section-head .lead {
  margin-top: 0.75rem;
}
.section-head.center .lead {
  margin-inline: auto;
}
.lead {
  font-size: clamp(1.12rem, 1rem + 0.5vw, 1.35rem);
  color: var(--ink-soft);
  max-width: 58ch;
  line-height: 1.5;
  letter-spacing: -0.01em;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2.25rem;
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.8rem 1.6rem;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  transition:
    background-color 0.15s var(--ease),
    border-color 0.15s var(--ease),
    box-shadow 0.15s var(--ease),
    transform 0.15s var(--ease),
    color 0.15s var(--ease);
}
.btn:active {
  transform: translateY(1px);
}
.btn-sm {
  padding: 0.55rem 1.1rem;
  font-size: 0.875rem;
}
.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  box-shadow: var(--shadow-action);
}
.btn-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--accent-ink);
  text-decoration: none;
}
.btn-ghost {
  border-color: var(--rule-action);
  color: var(--accent-text);
  background: var(--paper-raised);
  box-shadow: var(--shadow-hair);
}
.btn-ghost:hover {
  background: var(--sky);
  color: var(--accent-text-hover);
  border-color: var(--accent);
  text-decoration: none;
}

/* The line of facts under the hero buttons. Plain text with a tick, not chips:
   three chips next to two buttons would be five pills in a row. */
.trust {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem 1.75rem;
  margin: 2.25rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.9rem;
  color: var(--ink-soft);
}
.trust li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--ink-soft);
}
.trust svg {
  width: 1rem;
  height: 1rem;
  color: var(--accent-text);
  flex: none;
}

.grid {
  display: grid;
  gap: 1.5rem;
  align-items: stretch;
}
.grid-3 {
  grid-template-columns: repeat(auto-fit, minmax(265px, 1fr));
}
.grid-4 {
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.grid-2 {
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: clamp(2.5rem, 4vw, 3.75rem);
  align-items: center;
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.75rem;
  box-shadow: var(--shadow-card);
  transition:
    box-shadow 0.2s var(--ease),
    border-color 0.2s var(--ease),
    transform 0.2s var(--ease);
}
.card:hover {
  box-shadow: var(--shadow-raised);
  border-color: var(--rule-strong);
  transform: translateY(-3px);
}
.card h3 {
  margin-top: 0;
}
.card p:last-child {
  margin-bottom: 0;
}
a.card {
  color: inherit;
  text-decoration: none;
}
a.card:hover {
  color: inherit;
}
.card-more {
  margin-top: auto;
  padding-top: 1rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent-text);
}
a.card:hover .card-more {
  color: var(--accent-text-hover);
}

/* A tinted square holding an icon or a step number. Sky, not accent: the tile
   sits on every card, and a blue tile on every card is the "blue everywhere" this
   palette exists to avoid. */
.icon-tile {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-bottom: 1.15rem;
  border-radius: var(--radius-sm);
  background: var(--sky);
  color: var(--accent-text);
  font-family: var(--display);
  font-size: 1.05rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.icon-tile svg {
  width: 1.4rem;
  height: 1.4rem;
}

/* Ink, not accent. A figure is something to read, and a page where the numbers
   are the same blue as the button gives the button nothing to win. The size and
   the tight tracking are what make it a headline instead. */
.stat {
  font-family: var(--display);
  font-size: clamp(2.2rem, 1.8rem + 1.4vw, 2.9rem);
  line-height: 1;
  font-weight: 700;
  color: var(--ink);
  margin: 0;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.045em;
}
.stat-list {
  display: grid;
  border-top: 1px solid var(--rule);
}
.stat-list > div {
  display: grid;
  grid-template-columns: minmax(7.5rem, auto) 1fr;
  align-items: baseline;
  gap: 0.35rem 1.25rem;
  padding: 1.35rem 0;
  border-bottom: 1px solid var(--rule);
}
.stat-list .muted {
  margin: 0;
  font-size: 0.95rem;
}
@media (max-width: 480px) {
  .stat-list > div {
    grid-template-columns: 1fr;
  }
}

/* A call-to-action panel: the one section that is a card rather than a band, so
   the last thing on the home page is a distinct object rather than another stripe. */
.cta-panel {
  position: relative;
  overflow: hidden;
  padding: clamp(2.5rem, 5vw, 4.5rem) clamp(1.5rem, 4vw, 3rem);
  text-align: center;
  background:
    radial-gradient(
      40rem 16rem at 50% 120%,
      var(--sky-strong) 0%,
      transparent 70%
    ),
    var(--paper-sunken);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.cta-panel .lead {
  margin-inline: auto;
}
.cta-panel .actions {
  justify-content: center;
  margin-top: 1.75rem;
}

/* ---------------------------------------------------------------- prose --- */
.prose {
  max-width: var(--measure);
  min-width: 0;
}
.prose h2 {
  margin-top: 3rem;
  padding-top: 1.85rem;
  border-top: 1px solid var(--rule);
}
/* The rule over a heading separates it from the text above it, and the first
   heading on a page has none: the line would float under the hero as a divider
   dividing nothing. */
.prose h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}
.prose h3 {
  margin-top: 2.1rem;
}
.prose ul,
.prose ol {
  padding-left: 1.25rem;
}
.prose li {
  margin-bottom: 0.45rem;
}
.prose > :last-child {
  margin-bottom: 0;
}

/* The reading column and its table of contents. One column on a phone, where the
   contents sit above the text as a closed disclosure; two from 64rem, where the
   contents follow the reader down the page. */
.prose-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2rem clamp(2.5rem, 5vw, 5rem);
  align-items: start;
}
.toc {
  font-size: 0.9rem;
  /* Source order puts the contents after the article so a screen reader meets the
     text first; on one column it is shown first, where a list of what follows is
     of some use, rather than after the text it lists. */
  order: -1;
}
.toc summary {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  list-style: none;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 0.5rem 0;
}
.toc summary::-webkit-details-marker {
  display: none;
}
.toc summary::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s var(--ease);
}
.toc[open] summary::after {
  transform: translateY(1px) rotate(-135deg);
}
.toc ol {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
  border-left: 1px solid var(--rule);
}
.toc li {
  margin: 0;
}
.toc a {
  display: block;
  padding: 0.4rem 0 0.4rem 1rem;
  margin-left: -1px;
  color: var(--ink-soft);
  text-decoration: none;
  border-left: 2px solid transparent;
  transition:
    color 0.15s var(--ease),
    border-color 0.15s var(--ease);
}
.toc a:hover {
  color: var(--ink);
  border-color: var(--rule-strong);
}
.toc a[aria-current] {
  color: var(--accent-text);
  border-color: var(--accent);
  font-weight: 600;
}
@media (min-width: 64rem) {
  .prose-layout {
    grid-template-columns: minmax(0, var(--measure)) minmax(13rem, 16rem);
    justify-content: space-between;
  }
  .toc {
    order: 0;
    position: sticky;
    top: calc(var(--header-h) + 1.5rem);
    max-height: calc(100vh - var(--header-h) - 3rem);
    overflow-y: auto;
  }
  .toc summary {
    pointer-events: none;
  }
  .toc summary::after {
    display: none;
  }
}

dl.facts {
  display: grid;
  grid-template-columns: minmax(10rem, max-content) 1fr;
  gap: 0.7rem 2rem;
  margin: 1.6rem 0;
}
dl.facts dt {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-top: 0.35em;
}
dl.facts dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 560px) {
  dl.facts {
    grid-template-columns: 1fr;
    gap: 0.2rem;
  }
  dl.facts dd {
    margin-bottom: 0.85rem;
  }
}

.table-scroll {
  overflow-x: auto;
  margin: 1.6rem 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-hair);
}
table {
  border-collapse: collapse;
  width: 100%;
  min-width: 480px;
  font-size: 0.93rem;
  font-variant-numeric: tabular-nums;
}
th,
td {
  text-align: left;
  padding: 0.85rem 1.1rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
thead th {
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
  background: var(--paper-sunken);
}
tbody th {
  color: var(--ink);
  font-weight: 600;
  white-space: nowrap;
}
/* Only the body's last row: a bare "tr:last-child" also matches the header row,
   which is the last row of its thead, and strips the line under the headings. */
tbody tr:last-child :is(td, th) {
  border-bottom: none;
}

.callout {
  border-left: 4px solid var(--rule-strong);
  background: var(--accent-wash);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1.25rem 1.45rem;
  margin: 1.8rem 0;
}
.callout p:last-child {
  margin-bottom: 0;
}

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

/* Unfilled site.config.json values. The only warm colour on the site, so an
   unreplaced placeholder cannot be mistaken for finished copy. */
.todo {
  display: inline;
  background: var(--flag-bg);
  border-bottom: 2px solid var(--flag-rule);
  color: var(--flag-ink);
  padding: 0.05em 0.35em;
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 0.82em;
}

/* --------------------------------------------------------------- footer --- */
.site-footer {
  background: var(--footer-bg);
  color: var(--footer-soft);
  margin-top: var(--section);
}
.site-footer p,
.site-footer li {
  color: var(--footer-soft);
}
.site-footer .muted {
  color: var(--footer-soft);
}
.site-footer a {
  color: var(--footer-ink);
}
.site-footer a:hover {
  color: var(--footer-ink);
}
.footer-grid {
  display: grid;
  grid-template-columns: minmax(255px, 1fr) 1.6fr;
  gap: 3rem;
  padding-block: 3.75rem 2.4rem;
}
@media (max-width: 760px) {
  .footer-grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
}
.footer-brand {
  font-family: var(--display);
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--footer-ink);
  margin-bottom: 0.6rem;
  letter-spacing: -0.03em;
}
.footer-about p {
  font-size: 0.9rem;
  max-width: 40ch;
}
.footer-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(135px, 1fr));
  gap: 1.8rem;
}
.footer-links h3 {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--footer-ink);
  font-weight: 600;
  margin-bottom: 0.9rem;
}
.footer-links ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.footer-links li {
  margin-bottom: 0.55rem;
}
.footer-links a {
  color: var(--footer-soft);
  text-decoration: none;
  font-size: 0.9rem;
}
.footer-links a:hover {
  color: var(--footer-ink);
  text-decoration: underline;
}
.footer-links a[aria-current] {
  color: var(--footer-ink);
  font-weight: 600;
}
.footer-bottom {
  border-top: 1px solid var(--footer-rule);
  padding-block: 1.5rem 2.4rem;
}
.footer-bottom p {
  font-size: 0.82rem;
  margin-bottom: 0.5rem;
}
.footer-bottom p:last-child {
  margin-bottom: 0;
}

/* ----------------------------------------------------------------- demo --- */
.demo {
  margin: 0;
  max-width: 900px;
}

/* One box for all three states, so the placeholder occupies exactly the space the
   real player will take and the page does not reflow when the video lands. */
.demo-frame {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--ink);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-raised);
}
video.demo-frame {
  object-fit: contain;
}
iframe.demo-frame {
  border: 0;
}

.demo-facade,
.demo-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1.5rem;
  text-align: center;
  background-color: var(--paper-raised);
  background-size: cover;
  background-position: center;
}
.demo-empty {
  background: repeating-linear-gradient(
    135deg,
    var(--paper-raised),
    var(--paper-raised) 11px,
    var(--sky) 11px,
    var(--sky) 22px
  );
  border-style: dashed;
  border-color: var(--rule-strong);
  box-shadow: none;
}
.demo-empty p:first-child {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--ink);
  margin: 0;
}

.demo-play {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  padding: 0.75rem 1.6rem 0.75rem 1.3rem;
  color: var(--accent-ink);
  background: var(--accent);
  border: 0;
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-action);
  transition:
    background-color 0.15s var(--ease),
    transform 0.15s var(--ease);
}
.demo-play:hover {
  background: var(--accent-hover);
}
.demo-play:active {
  transform: translateY(1px);
}
.demo-play svg {
  margin-right: -0.15rem;
}

.demo-consent {
  max-width: 46ch;
  margin: 0;
  font-size: 0.83rem;
  color: var(--ink-faint);
}
.demo-consent code {
  font-family: var(--mono);
  font-size: 0.92em;
  color: var(--ink-soft);
}

.demo figcaption {
  margin-top: 1rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.6rem;
  align-items: baseline;
}
.demo-meta {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- carousel --- */
/* A screenshot of a dense Salesforce page is unreadable at 900px, so this figure
   takes the full wrap width where the video player did not need to. */
.demo-wide {
  max-width: none;
}

.carousel {
  position: relative;
  /* Lets the arrows be placed from the strip's own width, which is what the
     image height derives from. */
  container-type: inline-size;
}

/* scroll-snap carries the whole interaction: the strip is swipeable, scrollable and
   reachable by keyboard before any script runs. The arrows only automate what the
   container already does, which is why they ship hidden and are revealed by the script. */
.carousel-track {
  display: flex;
  gap: 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.carousel-track::-webkit-scrollbar {
  display: none;
}

.carousel-slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  min-width: 0;
}

/* A window around the screenshot rather than a bare bitmap: the bar says "this is
   an application" before the eye has read a pixel of the page inside it. */
.frame {
  overflow: hidden;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-raised);
}
.frame-bar {
  display: flex;
  gap: 0.4rem;
  padding: 0.7rem 0.9rem;
  background: var(--paper-sunken);
  border-bottom: 1px solid var(--rule);
}
.frame-bar i {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--rule-strong);
}
.frame img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.carousel-text {
  margin-top: 1.25rem;
  max-width: 60ch;
}
.carousel-text h3 {
  font-family: var(--display);
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 0.35rem;
}
.carousel-text p {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* Glass rather than a white disc: the arrow sits on top of the screenshot, and a
   solid button there punches a hole in the image it is meant to steer. It is
   centred on the image, not on the slide: the bar above is 2rem tall and the
   image is 9/16 of the strip's width, so half of that is 9/32. The percentage is
   the fallback for a browser without container units. */
.carousel-arrow {
  position: absolute;
  top: 40%;
  top: calc(2rem + 100cqi * 9 / 32);
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 2.9rem;
  height: 2.9rem;
  cursor: pointer;
  color: var(--ink);
  background: var(--paper-veil);
  backdrop-filter: saturate(160%) blur(10px);
  -webkit-backdrop-filter: saturate(160%) blur(10px);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-raised);
  transition:
    background-color 0.15s var(--ease),
    color 0.15s var(--ease),
    opacity 0.2s var(--ease);
}
@supports not (
  (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))
) {
  .carousel-arrow {
    background: var(--paper-raised);
  }
}
.carousel-prev {
  left: 0.9rem;
}
.carousel-next {
  right: 0.9rem;
}
.carousel-arrow:hover:not(:disabled) {
  background: var(--paper-raised);
  color: var(--accent-text);
}
.carousel-arrow:disabled {
  opacity: 0;
  pointer-events: none;
}

.carousel-dots {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1.25rem;
}
/* The hit area stays finger-sized while the mark itself stays discreet. */
.carousel-dot {
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
}
.carousel-dot span {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-pill);
  background: var(--rule-strong);
  transition:
    width 0.2s var(--ease),
    background-color 0.2s var(--ease);
}
.carousel-dot:hover span {
  background: var(--ink-faint);
}
.carousel-dot[aria-current="true"] span {
  background: var(--accent);
  width: 1.5rem;
}

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

@media (max-width: 40rem) {
  .carousel-arrow {
    display: none;
  }
  .carousel-track {
    gap: 0.9rem;
  }
}
