:root {
  color-scheme: light dark;
  --bg: #ffffff;
  --text: #1a1d21;
  --text-sub: #5a6169;
  --rule: #e3e6ea;
  --rule-2: #c9ced4;
  --link: #0b5bd3;
  --fill-bg: #fff3c4;
  --fill-text: #6b4e00;
  --fill-rule: #e0b400;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #15181c;
    --text: #e6e8eb;
    --text-sub: #9aa2ab;
    --rule: #2a2f36;
    --rule-2: #3c434c;
    --link: #79aaff;
    --fill-bg: #3d3005;
    --fill-text: #f0d37a;
    --fill-rule: #8a6d00;
  }
}

:root[data-theme='dark'] {
  --bg: #15181c;
  --text: #e6e8eb;
  --text-sub: #9aa2ab;
  --rule: #2a2f36;
  --rule-2: #3c434c;
  --link: #79aaff;
  --fill-bg: #3d3005;
  --fill-text: #f0d37a;
  --fill-rule: #8a6d00;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 48px 16px 96px;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.65 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  -webkit-text-size-adjust: 100%;
}

main {
  max-width: 44rem;
  margin: 0 auto;
}

h1 {
  margin: 0 0 4px;
  font-size: 1.9rem;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

h2 {
  margin: 2.4rem 0 0.6rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
  font-size: 1.2rem;
  line-height: 1.3;
}

h2:first-of-type {
  border-top: none;
  padding-top: 0;
}

p,
ul,
table {
  margin: 0 0 1rem;
}

ul {
  padding-left: 1.3rem;
}

li {
  margin-bottom: 0.45rem;
}

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

strong {
  font-weight: 600;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.94rem;
  display: block;
  overflow-x: auto;
}

th,
td {
  padding: 9px 12px;
  border: 1px solid var(--rule);
  text-align: left;
  vertical-align: top;
}

th {
  background: color-mix(in srgb, var(--rule) 45%, transparent);
  font-weight: 600;
}

code {
  padding: 1px 5px;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: color-mix(in srgb, var(--rule) 35%, transparent);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.88em;
}

.meta {
  margin: 0 0 2rem;
  padding: 14px 16px;
  border: 1px solid var(--rule);
  border-radius: 4px;
  color: var(--text-sub);
  font-size: 0.94rem;
}

.meta div + div {
  margin-top: 4px;
}

/* Deliberately loud: an unfilled placeholder must be impossible to publish by
   accident. Delete the span and leave the value. */
.fill {
  padding: 1px 6px;
  border: 1px solid var(--fill-rule);
  border-radius: 3px;
  background: var(--fill-bg);
  color: var(--fill-text);
  font-weight: 600;
  font-size: 0.9em;
}

footer {
  margin-top: 3rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  color: var(--text-sub);
  font-size: 0.9rem;
}

footer a {
  margin-right: 1rem;
}

.index-list {
  list-style: none;
  padding: 0;
}

.index-list li {
  margin-bottom: 1.1rem;
}

.index-list a {
  font-size: 1.05rem;
  font-weight: 600;
}

.index-list span {
  display: block;
  color: var(--text-sub);
  font-size: 0.94rem;
}

/* ---------------------------------------------------------------------------
   Site additions. Everything above this line is the stylesheet the legal pages
   use, copied verbatim so the two properties look like one company. Add here
   rather than editing above, so a change to the legal styles can be pulled in
   by replacing the top half.
   --------------------------------------------------------------------------- */

:root {
  --blue: #1a52d0;
  --blue-soft: #e8eefc;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --blue: #579dff;
    --blue-soft: #1c2434;
  }
}

:root[data-theme='dark'] {
  --blue: #579dff;
  --blue-soft: #1c2434;
}

/* Site navigation. A text row, not a chrome bar: this is four pages, and a
   header that looks like an application frame would oversell it. */
.nav {
  max-width: 44rem;
  margin: 0 auto 2.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.1rem;
  font-size: 0.94rem;
}

.nav .brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-right: auto;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  letter-spacing: -0.01em;
}

.nav .brand svg {
  display: block;
  width: 22px;
  height: 22px;
}

.nav a:not(.brand) {
  color: var(--text-sub);
  text-decoration: none;
}

.nav a:not(.brand):hover,
.nav a[aria-current='page'] {
  color: var(--text);
  text-decoration: underline;
}

/* The one line that has to land. Larger than body copy, not a billboard. */
.lede {
  margin: 0 0 1.4rem;
  font-size: 1.22rem;
  line-height: 1.45;
  letter-spacing: -0.01em;
}

.lede strong {
  color: var(--blue);
  font-weight: 600;
}

/* The state machine, and anything else that is a sequence rather than prose. */
.flow {
  margin: 0 0 1rem;
  padding: 14px 16px;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: color-mix(in srgb, var(--rule) 18%, transparent);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.88rem;
  line-height: 1.8;
  overflow-x: auto;
}

/* A claim with its evidence underneath. Used for the trust section, where the
   point is that each line is checkable rather than asserted. */
.claims {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
}

.claims li {
  margin-bottom: 1rem;
  padding-left: 1.1rem;
  border-left: 2px solid var(--blue);
}

.claims strong {
  display: block;
}

.claims span {
  color: var(--text-sub);
  font-size: 0.94rem;
}

/* Where a screenshot goes. Deliberately obvious, same reasoning as `.fill`. */
.shot {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 190px;
  margin: 0 0 1rem;
  padding: 16px;
  border: 1px dashed var(--fill-rule);
  border-radius: 4px;
  background: var(--fill-bg);
  color: var(--fill-text);
  font-size: 0.92rem;
  font-weight: 600;
  text-align: center;
}

/* --- Documentation --------------------------------------------------------- */

/* Secondary navigation, inside the docs set only. Sits under the page title so
   the primary nav stays the site's and this stays the section's. */
.subnav {
  margin: 0 0 2rem;
  padding: 12px 16px;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: color-mix(in srgb, var(--rule) 18%, transparent);
  font-size: 0.94rem;
}

.subnav a {
  margin-right: 1.1rem;
  white-space: nowrap;
}

.subnav a[aria-current='page'] {
  color: var(--text);
  font-weight: 600;
  text-decoration: none;
}

/* Numbered procedures. The whole point of the docs set, so they get real
   spacing rather than list defaults: each step is a thing you do and stop. */
ol.steps {
  margin: 0 0 1.4rem;
  padding-left: 1.6rem;
  counter-reset: none;
}

ol.steps > li {
  margin-bottom: 0.9rem;
  padding-left: 0.2rem;
}

/* The bold opener of a step is a lead-in, not a heading. Most of these steps
   continue straight out of it ("If it persists, send the diagnostic text"),
   so giving it its own line stranded the rest of the sentence underneath,
   and left six items starting a line with a comma. Inline; the steps whose
   opener is a whole sentence read the same either way. */
ol.steps > li > strong:first-child {
  display: inline;
}

ol.steps p {
  margin: 0.35rem 0 0;
}

ol.steps ul {
  margin: 0.4rem 0 0;
}

/* A UI label quoted from the product. Distinct from <code>, which is for
   scopes and identifiers: this is something you click or read on screen. */
.ui {
  padding: 1px 5px;
  border: 1px solid var(--rule-2);
  border-radius: 3px;
  background: var(--bg);
  font-weight: 600;
  font-size: 0.93em;
  white-space: nowrap;
}

/* An aside that is genuinely worth stopping for. Used sparingly; if every
   paragraph is a note, none of them is. */
.note {
  margin: 0 0 1.2rem;
  padding: 12px 16px;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--blue);
  border-radius: 0 4px 4px 0;
  background: var(--blue-soft);
  font-size: 0.96rem;
}

.note p {
  margin: 0;
}

.note p + p {
  margin-top: 0.6rem;
}

.note strong:first-child {
  color: var(--blue);
}

/* The index cards on the documentation hub. */
.cards {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
  display: grid;
  gap: 0.9rem;
}

.cards li {
  margin: 0;
  padding: 14px 16px;
  border: 1px solid var(--rule);
  border-radius: 4px;
}

.cards a {
  font-size: 1.05rem;
  font-weight: 600;
  text-decoration: none;
}

.cards a:hover {
  text-decoration: underline;
}

.cards span {
  display: block;
  margin-top: 0.25rem;
  color: var(--text-sub);
  font-size: 0.94rem;
}

/* Screenshot slot that names the file it is waiting for. */
.shot code {
  display: block;
  margin-top: 0.5rem;
  border-color: var(--fill-rule);
  background: transparent;
  color: var(--fill-text);
  font-weight: 400;
}

/* Screenshots. Bordered because the app's own background is dark and would
   otherwise bleed into a dark page with no edge. */
img.shot-img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 0 0.4rem;
  border: 1px solid var(--rule-2);
  border-radius: 4px;
}

figure {
  margin: 0 0 1.4rem;
}

figcaption {
  color: var(--text-sub);
  font-size: 0.9rem;
}

/* --- Wide media -------------------------------------------------------------

   A screenshot of a three-column application does not fit a 44rem reading
   column. The first set was captured 1568px wide and displayed in 672px -- a
   2.3x downscale, which is the whole reason every label in them was
   unreadable. Resolution was never the problem; the column was.

   These break out of the text column so a screenshot renders near the width it
   was captured at, while prose stays at a readable measure.

   `--sbw` is the scrollbar width, written by walk.js on load. Without JS it
   stays 0 and `overflow-x: clip` absorbs the dozen pixels of error instead of
   producing a horizontal scrollbar.
   --------------------------------------------------------------------------- */

body {
  overflow-x: clip;
}

.wide,
.walk {
  --w: min(var(--rail), calc(100vw - var(--sbw, 0px) - 2rem));
  width: var(--w);
  margin-left: calc((100% - var(--w)) / 2);
}

figure.wide {
  margin-bottom: 1.6rem;
  /* Centre the contents rather than stretching them. A shot narrower than the
     breakout container -- the action row, the panel, the sidebar -- then draws
     at its own pixel size instead of being upscaled to fill 1140px, which is
     how screenshot text goes soft. `img.shot-img` caps at max-width: 100%, so
     the wider shots still shrink to fit. */
  display: flex;
  flex-direction: column;
  align-items: center;
}

figure.wide figcaption {
  max-width: 44rem;
}

/* --- Walkthrough ------------------------------------------------------------

   A step-through of one procedure: the stage shows the current screenshot, the
   rail lists every step.

   Written to work without JavaScript. The markup is an ordinary sequence of
   figures, which is a perfectly good stacked walkthrough on its own; walk.js
   folds it into a stepper and does nothing if it never runs. That also keeps
   the page printable and keeps every step's text in the DOM, so Ctrl+F and a
   screen reader both still find a step that is not currently on screen.
   --------------------------------------------------------------------------- */

.walk {
  margin-top: 1.6rem;
  margin-bottom: 2rem;
}

/* Before enhancement, and forever if JS never runs: plain stacked figures. */
.walk > .walk-step {
  margin: 0 0 1.4rem;
}

.walk.is-enhanced {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 17rem;
  gap: 0 1.6rem;
  align-items: start;
}

@media (max-width: 54rem) {
  .walk.is-enhanced {
    grid-template-columns: minmax(0, 1fr);
  }
}

.walk-stage {
  grid-column: 1;
  min-width: 0;
}

.walk.is-enhanced .walk-step {
  margin: 0;
}

.walk.is-enhanced .walk-step[hidden] {
  display: none;
}

/* Bound to the step, not to the stage, because the stage only exists once
   walk.js has run. Without it these are plain figures at their natural 1240px,
   which overflows the column -- the no-JS path has to be styled too, or it is
   not really a fallback. */
.walk-step img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule-2);
  border-radius: 5px;
}

/* The caption under the stage repeats the active step, so the image is never
   orphaned from its explanation when the rail wraps below on a narrow screen. */
.walk-stage figcaption {
  margin-top: 0.55rem;
  color: var(--text-sub);
  font-size: 0.9rem;
}

/* The rail. Every step's text, always present. */
.walk-rail {
  grid-column: 2;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: walkstep;
  border-left: 1px solid var(--rule);
}

@media (max-width: 54rem) {
  .walk-rail {
    grid-column: 1;
    margin-top: 1.2rem;
  }
}

.walk-rail li {
  counter-increment: walkstep;
  margin: 0;
}

.walk-rail button {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0.5rem 0.7rem 0.5rem 1rem;
  border: 0;
  border-left: 2px solid transparent;
  margin-left: -1px;
  background: none;
  color: var(--text-sub);
  font: inherit;
  font-size: 0.89rem;
  line-height: 1.45;
  text-align: left;
  cursor: pointer;
}

.walk-rail button::before {
  content: counter(walkstep) ". ";
  font-variant-numeric: tabular-nums;
  opacity: 0.65;
}

.walk-rail button:hover {
  color: var(--text);
  background: color-mix(in srgb, var(--text) 4%, transparent);
}

.walk-rail button:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: -2px;
}

.walk-rail li.is-current button {
  border-left-color: var(--link);
  color: var(--text);
  font-weight: 600;
}

/* Controls. */
.walk-nav {
  grid-column: 1;
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-top: 0.9rem;
}

.walk-nav button {
  padding: 0.32rem 0.8rem;
  border: 1px solid var(--rule-2);
  border-radius: 4px;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.88rem;
  cursor: pointer;
}

.walk-nav button:hover:not(:disabled) {
  border-color: var(--link);
  color: var(--link);
}

.walk-nav button:disabled {
  opacity: 0.4;
  cursor: default;
}

.walk-count {
  color: var(--text-sub);
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
}

/* Print: no stepper, every step on the page. */
@media print {
  .walk.is-enhanced {
    display: block;
  }

  .walk.is-enhanced .walk-step[hidden] {
    display: block !important;
  }

  .walk-nav,
  .walk-rail {
    display: none;
  }
}

/* ===========================================================================
   Design pass.

   Everything above line ~190 is shared verbatim with the legal pages so the
   two properties look like one company, and the note there says to add below
   rather than edit above. So this is a layer, not a rewrite: the rules here
   override the shared base, and the whole block can be copied to the legal
   stylesheet to bring it along.

   The problems it fixes, in order of how much they cost a first-time reader:
   nothing anchored the eye (h2 was only 20% larger than body text, separated
   by a hairline); the navigation said one thing at the top of the page and a
   different thing in a box underneath it; a 44rem column left most of a
   desktop screen empty with no way to see what was on the page; and the four
   words the product is built on were rendered as a code sample.
   =========================================================================== */

:root {
  /* The outer rail. The header, the breakout figures and the contents panel
     all measure from this, so the page has one outer edge instead of three.
     Before this existed the header was a 34rem half-width, the figures were
     1140px and the column was 44rem, and at 2134px that put the header at
     500, the figures at 560 and the text at 708: three left edges, none of
     them shared, which is what made the top of the page look askew. */
  --rail: 1140px;
  --accent: #1a52d0;
  --surface: #f7f8fa;
  --surface-2: #eceff4;
  --hairline: #e4e8ee;
  --r: 10px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --accent: #579dff;
    --surface: #1a1e24;
    --surface-2: #222832;
    --hairline: #272d35;
  }
}

:root[data-theme='dark'] {
  --accent: #579dff;
  --surface: #1a1e24;
  --surface-2: #222832;
  --hairline: #272d35;
}

/* --- Reading ---------------------------------------------------------------
   17px over 16px and a looser leading. The measure stays near 66 characters,
   which is the point of the 44rem column: the extra size buys legibility
   without widening the line. */

body {
  padding: 0 16px 120px;
  font-size: 17px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

h1 {
  font-size: clamp(2.1rem, 1.5rem + 2vw, 2.7rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  margin-bottom: 0.5rem;
}

/* Space is a better section separator than a rule. The hairline was carrying
   the whole job of "a new section starts here", because the heading itself
   was barely larger than the paragraph under it. Give the heading real size
   and the rule becomes clutter. */
h2 {
  margin: 3.4rem 0 1rem;
  padding-top: 0;
  border-top: 0;
  font-size: 1.5rem;
  line-height: 1.25;
  letter-spacing: -0.015em;
}

h2:first-of-type {
  margin-top: 2.6rem;
}

h3 {
  margin: 2.2rem 0 0.6rem;
  font-size: 1.08rem;
  line-height: 1.35;
}

p {
  margin: 0 0 1.15rem;
}

li {
  margin-bottom: 0.55rem;
}

main a {
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

/* --- Header ----------------------------------------------------------------
   One row that lists every section, so no page has to repeat its navigation
   in a box under the title. Sticky, because a reader four screens into
   Troubleshooting should be able to leave without scrolling back. */

.nav {
  position: sticky;
  top: 0;
  z-index: 20;
  max-width: none;
  margin: 0 -16px 2.8rem;
  /* The 16px is the body padding the negative margins above cancel out, so
     the header's content lands on the same line as a breakout figure rather
     than 16px outside it. The percentage resolves against body's content
     box, which is what the figures measure from too. */
  padding: 0.6rem calc(16px + max(0px, 50% - var(--rail) / 2));
  gap: 0.2rem;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--hairline);
}

.nav .brand {
  margin-right: auto;
  padding: 0.35rem 0.1rem;
  font-size: 1rem;
}

.nav a:not(.brand) {
  padding: 0.35rem 0.6rem;
  border-radius: 7px;
  color: var(--text-sub);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.12s ease, color 0.12s ease;
}

.nav a:not(.brand):hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}

.nav a[aria-current="page"] {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 600;
  text-decoration: none;
}

@media (max-width: 52rem) {
  /* Six links plus the brand wrap to two rows here, and 95px of permanently
     parked header on a 700px-tall screen is too much to pay. Let it scroll
     away; a phone reader scrolls anyway. */
  .nav {
    position: static;
    margin-bottom: 2rem;
    padding-left: 16px;
    padding-right: 16px;
    font-size: 0.87rem;
  }
  .nav a:not(.brand) {
    padding: 0.3rem 0.42rem;
  }
  h1, h2, h3, [id] {
    scroll-margin-top: 1rem;
  }
}

/* The second navigation bar: every doc page carried one, directly under a
   title that already said the same word. */
.subnav {
  display: none;
}

/* --- Lede and hero ---------------------------------------------------------- */

.lede {
  margin: 0 0 1.8rem;
  font-size: 1.3rem;
  line-height: 1.45;
  color: var(--text-sub);
}

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

/* The home page has to say what this is, and show it, before a reader decides
   whether to keep going.

   Centred, because the screenshot underneath is a breakout figure centred on
   the rail, and a left-aligned hero over it gave the top of the page two
   left edges 148px apart. Everything above the fold now shares one vertical
   axis. The prose below stays left-aligned, where ragged-right is worth more
   than symmetry. */
.hero {
  margin: 0 0 2rem;
  text-align: center;
}

.hero .lede {
  max-width: 34rem;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 1.5rem;
  font-size: 1.45rem;
  line-height: 1.35;
  color: var(--text);
  letter-spacing: -0.015em;
}

.hero .lede strong {
  color: var(--accent);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  margin: 0 0 2.4rem;
}

.btn {
  display: inline-block;
  padding: 0.6rem 1.15rem;
  border: 1px solid transparent;
  border-radius: 8px;
  background: var(--accent);
  color: #ffffff;
  font-size: 0.97rem;
  font-weight: 600;
  text-decoration: none;
  transition: filter 0.12s ease, background 0.12s ease;
}

.btn:hover {
  filter: brightness(1.08);
  text-decoration: none;
}

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

.btn-ghost:hover {
  background: var(--surface-2);
  filter: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .btn:not(.btn-ghost) {
    color: #0d1117;
  }
}

:root[data-theme='dark'] .btn:not(.btn-ghost) {
  color: #0d1117;
}

/* --- The four phases -------------------------------------------------------
   The product in four words, so it gets to be a designed object rather than a
   line of monospace in a grey box. Numbered, because the order is the claim. */

.phases {
  list-style: none;
  counter-reset: phase;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.7rem;
  margin: 0 0 1.6rem;
  padding: 0;
}

@media (max-width: 40rem) {
  .phases {
    grid-template-columns: repeat(2, 1fr);
  }
}

.phases li {
  counter-increment: phase;
  margin: 0;
  padding: 0.85rem 0.9rem 0.95rem;
  border: 1px solid var(--hairline);
  border-radius: var(--r);
  background: var(--surface);
}

.phases li::before {
  content: counter(phase);
  display: block;
  margin-bottom: 0.4rem;
  font-variant-numeric: tabular-nums;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.06em;
}

.phases b {
  display: block;
  font-size: 0.97rem;
  letter-spacing: -0.005em;
}

.phases span {
  display: block;
  margin-top: 0.2rem;
  color: var(--text-sub);
  font-size: 0.87rem;
  line-height: 1.45;
}

/* The state machine stays monospace, because it is a machine, but it loses
   the code-sample box. */
.flow {
  margin: 0 0 1.4rem;
  padding: 0.8rem 1rem;
  border: 1px solid var(--hairline);
  border-radius: var(--r);
  background: var(--surface);
  color: var(--text-sub);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  line-height: 1.9;
}

/* --- Tables ----------------------------------------------------------------
   Rules between rows, nothing else. A full grid plus a filled header row made
   every table look like a spreadsheet export. */

th,
td {
  padding: 0.7rem 0.9rem 0.7rem 0;
  border: 0;
  border-bottom: 1px solid var(--hairline);
}

th {
  padding-bottom: 0.5rem;
  background: none;
  border-bottom: 1px solid var(--rule-2);
  color: var(--text-sub);
  font-size: 0.76rem;
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

tbody tr:last-child td {
  border-bottom: 0;
}

/* --- Inline bits -----------------------------------------------------------
   A UI label turns up several times per sentence in places. Bordered and
   filled, a row of them reads as a row of buttons; a tint and a little weight
   says "this is a thing on the screen" without shouting. */

.ui {
  /* Tight horizontal padding on purpose. A chip is often followed straight
     away by a comma or a full stop, and roomy padding leaves the punctuation
     visibly stranded: "expands into All runs , In flight and Records ." */
  padding: 0.08em 0.28em;
  border: 0;
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 600;
  font-size: 0.92em;
}

code {
  padding: 0.12em 0.4em;
  border: 0;
  border-radius: 4px;
  background: var(--surface-2);
  font-size: 0.86em;
}

/* --- Cards -----------------------------------------------------------------
   The hub index. Two across on a wide screen, because four full-width boxes
   stacked in a 44rem column is a list pretending to be a grid. */

.cards {
  grid-template-columns: repeat(2, 1fr);
  gap: 0.8rem;
}

@media (max-width: 40rem) {
  .cards {
    grid-template-columns: 1fr;
  }
}

.cards li {
  position: relative;
  padding: 1rem 1.1rem 1.1rem;
  border: 1px solid var(--hairline);
  border-radius: var(--r);
  background: var(--surface);
  transition: border-color 0.12s ease, background 0.12s ease;
}

.cards li:hover {
  border-color: var(--accent);
  background: var(--surface-2);
}

.cards a {
  font-size: 1.02rem;
}

/* The whole card is the target, not just the four words of the title. */
.cards a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.cards span {
  margin-top: 0.35rem;
  font-size: 0.92rem;
  line-height: 1.55;
}

/* --- Notes and steps -------------------------------------------------------- */

.note {
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r) var(--r) 0;
  background: var(--surface);
  font-size: 0.97rem;
}

.note strong:first-child {
  color: var(--text);
}

ol.steps > li {
  margin-bottom: 1.1rem;
}

ol.steps > li::marker {
  color: var(--text-sub);
  font-variant-numeric: tabular-nums;
}

/* --- On this page ----------------------------------------------------------
   Built by site.js from the headings and parked in the margin a centred
   column leaves empty, but only when there is room. Pure addition: no page
   markup changes, and nothing moves if the script never runs. */

.toc {
  position: fixed;
  top: 7.5rem;
  /* Just outside the rail, so it clears the breakout figures whatever the
     rail is set to. */
  left: calc(50% + var(--rail) / 2 + 1.75rem);
  width: 200px;
  max-height: calc(100vh - 11rem);
  overflow-y: auto;
  font-size: 0.87rem;
  line-height: 1.45;
}

.toc .toc-title {
  margin: 0 0 0.6rem;
  font-size: 0.74rem;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-sub);
}

.toc ol {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--hairline);
}

.toc li {
  margin: 0;
}

.toc a {
  display: block;
  padding: 0.28rem 0 0.28rem 0.85rem;
  margin-left: -1px;
  border-left: 1px solid transparent;
  color: var(--text-sub);
  text-decoration: none;
}

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

.toc a.is-current {
  border-left-color: var(--accent);
  color: var(--text);
  font-weight: 600;
}

/* Only when there is genuinely room for a third column beside a 1000px
   figure. Below this the figures take the space back instead. */
@media (max-width: 1479px) {
  .toc {
    display: none;
  }
}

@media (min-width: 1480px) {
  :root {
    --rail: 1000px;
  }
}

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

footer {
  margin-top: 4.5rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--hairline);
}

footer a {
  margin-right: 1.2rem;
  color: var(--text-sub);
  text-decoration: none;
}

footer a:hover {
  color: var(--text);
  text-decoration: underline;
}

.foot-legal {
  margin-top: 0.9rem;
  color: var(--text-sub);
  font-size: 0.86rem;
}

/* --- Focus ------------------------------------------------------------------
   One visible ring everywhere. The walkthrough is keyboard-driven, and a docs
   site is exactly where someone tabs rather than clicks. */

/* The header is sticky, so an anchor jump has to clear it. */
h1, h2, h3, [id] {
  scroll-margin-top: 5.5rem;
}

html {
  scroll-behavior: smooth;
}

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

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --- Telling the two side lists apart --------------------------------------
   The walkthrough rail and the contents panel ended up in the same visual
   language: a vertical list of muted labels against a hairline, with an
   accent bar on the current one. On start.html they sit a few pixels apart
   and read as two tables of contents competing with each other.

   The contents panel keeps the hairline idiom, because that is what it is.
   The rail becomes a solid panel, because it belongs to the picture beside
   it rather than to the page. */

.walk-rail {
  padding: 0.35rem;
  border-left: 0;
  border: 1px solid var(--hairline);
  border-radius: var(--r);
  background: var(--surface);
}

.walk-rail button {
  margin-left: 0;
  padding: 0.5rem 0.7rem;
  border: 0;
  border-radius: 7px;
  transition: background 0.12s ease, color 0.12s ease;
}

.walk-rail button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.walk-rail li.is-current button {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--text);
  font-weight: 600;
}

.walk-rail button::before {
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.walk-nav {
  margin-top: 0.9rem;
}

.walk-nav button {
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--rule-2);
  border-radius: 7px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
}

.walk-nav button:hover:not(:disabled) {
  background: var(--surface-2);
}

.walk-nav button:disabled {
  opacity: 0.4;
  cursor: default;
}

.walk-count {
  color: var(--text-sub);
  font-size: 0.87rem;
}


/* --- The brand mark ---------------------------------------------------------
   The mark in the nav was drawn in currentColor, so it came out as two tones
   of the site's text colour: near-black here, near-white in dark mode, and
   matching neither Jira nor the app.

   The app's icon carries its colour in the file rather than inheriting it
   (static/icons/runphase-icon.svg: Jira renders a module icon as an image,
   which cannot resolve currentColor). Its treads are Jira's own icon grey
   and the leading step is Atlassian blue. Those are the values below, so the
   mark reads the same in this nav as it does in the Jira sidebar, which is
   where most people meet it first.

   Set here rather than on the paths, so the eight copies of the inline SVG
   do not each need editing, and so dark mode stays in the stylesheet.
   --------------------------------------------------------------------------- */

.brand svg path:first-of-type {
  fill: #44546f;
  opacity: 1;
}

.brand svg path:last-of-type {
  fill: var(--accent);
  opacity: 1;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .brand svg path:first-of-type {
    fill: #9fadbc;
  }
}

:root[data-theme='dark'] .brand svg path:first-of-type {
  fill: #9fadbc;
}


/* ===========================================================================
   Signal — the visual identity

   The site was clean and anonymous: one system font stack, one blue, grey.
   Nothing about it could only belong to this product. This gives it a display
   face used at real size, a tighter type scale, and an amber that is spent
   only on risk.

   Chosen over two alternatives. A mono-and-dark "console" treatment read as
   the developer-tool genre rather than as this product, and a serif "record"
   treatment was truer to the immutable-record idea but too quiet to carry a
   home page.

   Both faces are served from this repository, not from Google Fonts. The site
   makes no third-party request today, and a product whose claim is that
   nothing leaves Atlassian should not hand every visitor's IP address to a
   font CDN. The cost is 82 KB of woff2 and keeping fonts/ in step between
   this repo and the legal one.
   =========================================================================== */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('fonts/archivo-var-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2044, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/plex-sans-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2044, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/plex-sans-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2044, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

:root {
  --display: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --text-face: 'Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  /* Reserved for risk and nothing else. Never decoration. */
  --risk: #b45309;
}

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

:root[data-theme='dark'] { --risk: #e8a33d; }

body {
  font-family: var(--text-face);
}

/* --- Display type ----------------------------------------------------------
   Archivo at weight 800 with tight tracking. The scale is deliberately wide:
   a 3.4rem h1 against a 17px body is the whole reason the page now has a
   first impression. Headings get `text-wrap: balance` so a two-word orphan
   never ends a line. */

h1, h2, h3, .brand, .btn, .phases b, .cards a, .walk-rail button, .toc-title {
  font-family: var(--display);
}

h1 {
  font-size: clamp(2.3rem, 1.3rem + 3.4vw, 3.5rem);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

h2 {
  font-size: clamp(1.45rem, 1.2rem + 0.95vw, 1.95rem);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.03em;
  margin-top: 3.8rem;
  text-wrap: balance;
}

h3 {
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.brand {
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* --- Hero ------------------------------------------------------------------
   Bigger, with more air under it than the old treatment had. */

.hero {
  margin-bottom: 2.6rem;
}

.hero .lede {
  font-family: var(--text-face);
  font-size: clamp(1.1rem, 1rem + 0.6vw, 1.4rem);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: -0.005em;
  margin-top: 1.1rem;
  margin-bottom: 1.8rem;
}

.hero .lede strong {
  font-weight: 600;
}

/* --- Buttons ---------------------------------------------------------------
   The primary action is ink, not blue. Blue is the product's own accent and
   it is already doing work inside every screenshot on the page; spending it
   on the button as well left the hero with two competing blues. Ink against
   the page is the stronger contrast anyway, and it inverts cleanly in dark
   mode. */

.btn {
  padding: 0.85rem 1.4rem;
  border-radius: 4px;
  border-width: 1.5px;
  background: var(--text);
  color: var(--bg);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.btn:hover {
  filter: none;
  opacity: 0.86;
}

.btn-ghost {
  background: transparent;
  border-color: var(--text);
  color: var(--text);
}

.btn-ghost:hover {
  background: var(--surface-2);
  opacity: 1;
}

/* --- The four phases -------------------------------------------------------
   Cards become ruled columns. A top rule and a number reads as a sequence;
   four rounded boxes read as four unrelated things. */

.phases {
  gap: 1.6rem 1.4rem;
}

/* Four columns inside a 44rem reading column gave each one about 160px, and
   a phase description wrapped to six lines. The phases are a designed object
   like the figures are, so they take the rail too. */
@media (min-width: 60rem) {
  .phases {
    --w: min(var(--rail), calc(100vw - var(--sbw, 0px) - 2rem));
    width: var(--w);
    margin-left: calc((100% - var(--w)) / 2);
  }
}

.phases li {
  padding: 0.75rem 0 0;
  border: 0;
  border-top: 2px solid var(--text);
  border-radius: 0;
  background: none;
}

.phases li::before {
  margin-bottom: 0.3rem;
  font-family: var(--display);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text-sub);
}

.phases b {
  font-size: 1.08rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  margin-bottom: 0.2rem;
}

/* --- Risk ------------------------------------------------------------------
   The one place amber is allowed. `.risk` marks a genuine warning; the app
   uses the same colour on a Risk: MEDIUM banner, so the site and the product
   agree about what amber means. */

.risk {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--risk);
}

.risk::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--risk);
  flex: none;
}

/* --- Small type ------------------------------------------------------------
   Plex Sans sets uppercase micro-labels a little tighter than the system
   stack did, so the table headers and the contents title need the tracking
   put back. */

th {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: 0.08em;
}

.toc-title {
  font-weight: 700;
  letter-spacing: 0.08em;
}

/* Tabular figures wherever digits are compared rather than read. */
td,
.phases li::before,
code {
  font-variant-numeric: tabular-nums;
}

/* Between 640px and the 960px breakout the phases were still four columns in
   a narrow container, about 160px each — the same cramping the breakout was
   added to fix, in the one range the breakout does not cover. Two columns
   until the breakout takes over, one on a phone. */
@media (max-width: 59.9375rem) {
  .phases {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 30rem) {
  .phases {
    grid-template-columns: 1fr;
    gap: 1.3rem;
  }
}
