/* WorkPro — product pages.
   ---------------------------------------------------------------------------
   Kept in a file on purpose: the site's `_headers` sets style-src 'self', so an
   inline <style> block or a style="" attribute is refused by the browser and
   silently does nothing. The same policy blocks scripts outright, so everything
   here is CSS-only by necessity — and, as it turns out, by preference.

   The palette is the app's, and it means what it means there: green is on site,
   amber is moving or needs a decision, red is off site — the thing that costs
   money if nobody looks. The page's own neutrals carry a slight blue bias so
   they sit under those colours rather than fighting them, and nothing else on
   the page is allowed to be saturated. */

:root {
  /* Neutrals, biased a few degrees toward the accent so they read as chosen. */
  --ground: #f4f6fa;
  --raise: #ffffff;
  --sink: #e8edf5;
  --line: #e2e6ee;
  --rule: #ccd4e0;

  --ink: #0b0d12;
  --ink-2: #3e4757;
  --muted: #7a8496;

  --accent: #14306f;
  --accent-ink: #ffffff;
  --deep: #14306f;

  --good: #1c8a4e;
  --warn: #a86a05;
  --bad: #c1323b;

  --shadow-1: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-2: 0 1px 2px rgba(16, 24, 40, .05), 0 20px 44px -26px rgba(20, 45, 85, .35);
  --shadow-3: 0 30px 80px -34px rgba(20, 45, 85, .55);

  --radius: 18px;
  --radius-lg: 24px;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground: #0b0d12;
    --raise: #12151d;
    --sink: #171b25;
    --line: #222836;
    --rule: #2b3242;

    --ink: #edeff3;
    --ink-2: #c3cad6;
    --muted: #98a1b2;

    --accent: #6fa6e4;
    --accent-ink: #0b0d12;
    --deep: #6fa6e4;

    --good: #4ec984;
    --warn: #e0a33c;
    --bad: #ef6b72;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
    --shadow-2: 0 1px 2px rgba(0, 0, 0, .5), 0 22px 48px -26px rgba(0, 0, 0, .85);
    --shadow-3: 0 34px 90px -34px rgba(0, 0, 0, .9);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --ground: #0b0d12;
  --raise: #12151d;
  --sink: #171b25;
  --line: #222836;
  --rule: #2b3242;
  --ink: #edeff3;
  --ink-2: #c3cad6;
  --muted: #98a1b2;
  --accent: #6fa6e4;
  --accent-ink: #0b0d12;
  --deep: #6fa6e4;
  --good: #4ec984;
  --warn: #e0a33c;
  --bad: #ef6b72;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-2: 0 1px 2px rgba(0, 0, 0, .5), 0 22px 48px -26px rgba(0, 0, 0, .85);
  --shadow-3: 0 34px 90px -34px rgba(0, 0, 0, .9);
  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

body {
  margin: 0;
  padding: 0;
  background: var(--ground);
  color: var(--ink);
  font: 17px/1.62 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
        Roboto, Helvetica, Arial, sans-serif;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1000px; margin: 0 auto; padding: 0 22px; }

/* The data face. Timestamps, durations, rates, counts — anything a decision is
   read off gets tabular figures so columns line up and nothing shifts. */
.mono {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

a { color: var(--accent); text-underline-offset: 2px; }
a:focus-visible, summary:focus-visible, .cta:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--accent); color: var(--accent-ink);
  padding: 12px 18px; border-radius: 0 0 12px 0; font-weight: 640; z-index: 10;
}
.skip:focus { left: 0; }

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

h1 {
  font-size: clamp(34px, 5.4vw, 54px);
  line-height: 1.03;
  letter-spacing: -0.035em;
  font-weight: 800;
  margin: 14px 0 16px;
  text-wrap: balance;
}
h2 {
  font-size: clamp(24px, 3.6vw, 33px);
  line-height: 1.12;
  letter-spacing: -0.025em;
  font-weight: 760;
  margin: 0 0 12px;
  text-wrap: balance;
}
h3 { font-size: 18px; letter-spacing: -0.012em; font-weight: 700; margin: 0 0 6px; }
p { margin: 0 0 13px; }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: clamp(18px, 2.1vw, 21px);
  line-height: 1.48;
  color: var(--ink-2);
  max-width: 34em;
}
.quiet { color: var(--muted); }
.small { font-size: 15px; }

.label {
  display: inline-block;
  font-size: 11.5px; font-weight: 800; letter-spacing: .13em;
  text-transform: uppercase; color: var(--accent);
}

/* A section that does not exist yet. Amber rather than the accent, because the
   accent on this page means "here is a thing you can use" on every other
   heading, and a reader who cannot tell the difference has been misled. */
.label.soon { color: var(--warn); }

.pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
  font-size: 11.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-radius: 999px; padding: 5px 13px;
}
.pill.plain {
  color: var(--muted);
  background: color-mix(in srgb, var(--muted) 10%, transparent);
  border-color: var(--line);
}

.cta {
  display: inline-block;
  background: var(--deep); color: #fff;
  text-decoration: none; font-weight: 680; font-size: 16.5px;
  padding: 14px 26px; border-radius: 13px;
  box-shadow: 0 12px 26px -14px color-mix(in srgb, var(--deep) 85%, transparent);
  transition: transform .15s ease, filter .15s ease;
}
.cta:hover { filter: brightness(1.1); transform: translateY(-1px); }
.cta.ghost {
  background: transparent; color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  box-shadow: none;
}

/* --------------------------------------------------------------------------
   Structure
   -------------------------------------------------------------------------- */

.mark {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none; color: inherit; font-size: 16.5px; letter-spacing: -0.012em;
}
.mark svg { display: block; border-radius: 9px; }
.mark strong { font-weight: 700; }
.mark { white-space: nowrap; flex: none; }
/* The nav used to be hidden below 560px, leaving a phone with no way out of the
   page at all. Letting it wrap was worse in a different way: it dropped to a
   second row still left-aligned, reading as something spilled rather than part
   of the masthead. On a narrow screen it becomes what it actually is — a nav
   strip under the mark, ruled off, its items spread across the full width. */

section { padding: 54px 0; }
section + section { border-top: 1px solid var(--line); }
.sec-head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 28px; max-width: 40em; }

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

.hero {
  display: grid; grid-template-columns: 1fr 236px; gap: 52px; align-items: center;
  padding: 34px 0 50px; border-top: 0;
}
.hero-copy { min-width: 0; display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin: 10px 0 0; }

/* The legend. Stated once, up front, because every screenshot below depends on
   knowing it and it is the first thing a foreman learns in the app. */
.legend {
  margin-top: 24px; padding: 14px 18px; border-radius: var(--radius);
  background: var(--raise); border: 1px solid var(--line); box-shadow: var(--shadow-1);
  display: flex; flex-wrap: wrap; gap: 6px 22px;
}
.legend span { display: inline-flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 560; }
.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.dot.on { background: var(--good); }
.dot.moving { background: var(--warn); }
.dot.off { background: var(--bad); }
.dot.unknown { background: var(--muted); }

/* --------------------------------------------------------------------------
   Phone
   -------------------------------------------------------------------------- */

.phone {
  justify-self: center; width: 100%; max-width: 236px; padding: 9px 9px 0;
  background: color-mix(in srgb, var(--ink) 88%, #000);
  border-radius: 38px 38px 9px 9px;
  box-shadow: var(--shadow-3);
  border: 1px solid rgba(255, 255, 255, .07);
  align-self: start;
}
.phone img {
  display: block; width: 100%; height: 500px;
  object-fit: cover; object-position: top center;
  border-radius: 30px 30px 0 0;
  background: var(--sink);
}
.feature .phone { max-width: 210px; }
.feature .phone img { height: 380px; }

/* --------------------------------------------------------------------------
   A day, told against the clock
   ---------------------------------------------------------------------------
   The one structural device on this page, and it earns its place: a day *is* a
   sequence, so the timestamps are information rather than decoration. The rule
   down the left is the route line from the app, and each dot carries the same
   meaning it does on the map. */

.day { list-style: none; margin: 0; padding: 0; position: relative; }
.day::before {
  content: ""; position: absolute; left: 79px; top: 14px; bottom: 14px;
  width: 2px; background: var(--rule); border-radius: 2px;
}
.day li {
  display: grid; grid-template-columns: 62px 34px 1fr; align-items: start;
  gap: 0 14px; padding: 13px 0;
}
.day .t { color: var(--muted); font-size: 14px; padding-top: 2px; text-align: right; }
.day .pip { position: relative; width: 34px; height: 24px; }
.day .pip::after {
  content: ""; position: absolute; left: 8px; top: 6px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--muted);
  box-shadow: 0 0 0 4px var(--ground);
}
.day li.on .pip::after { background: var(--good); }
.day li.moving .pip::after { background: var(--warn); }
.day li.off .pip::after { background: var(--bad); }
.day li.think .pip::after {
  background: var(--raise); border: 2px solid var(--accent); width: 14px; height: 14px;
  left: 7px; top: 5px;
}
.day .what { min-width: 0; }
.day .what strong { font-weight: 680; }
.day .what p { color: var(--muted); font-size: 15px; margin: 3px 0 0; }
.day .dur { color: var(--ink-2); font-weight: 640; }

@media (max-width: 620px) {
  .day::before { left: 17px; }
  .day li { grid-template-columns: 34px 1fr; gap: 0 12px; }
  .day .t { grid-column: 2; text-align: left; font-size: 13px; padding: 0 0 2px; }
  .day .pip { grid-row: 1 / span 2; }
  .day .what { grid-column: 2; }
}

/* --------------------------------------------------------------------------
   Feature rows
   -------------------------------------------------------------------------- */

.feature {
  display: grid; grid-template-columns: 210px 1fr; gap: 46px; align-items: center;
  padding: 34px 0;
}
.feature + .feature { border-top: 1px solid var(--line); }
.feature.flip { grid-template-columns: 1fr 210px; }
.feature.flip .phone { order: 2; }
.feature .body { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.feature .body p { color: var(--ink-2); }

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */

.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid.three { grid-template-columns: repeat(3, 1fr); }
.card {
  background: var(--raise); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 22px 24px; box-shadow: var(--shadow-1);
  display: flex; flex-direction: column; gap: 6px;
}
.card p { color: var(--muted); font-size: 15.5px; line-height: 1.5; margin: 0; }
.card .label { margin-bottom: 4px; }

.block {
  background: var(--raise); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 28px 30px; box-shadow: var(--shadow-2);
}
.block ul { padding-left: 20px; margin: 10px 0 0; }
.block li { margin: 8px 0; }
.block li::marker { color: var(--accent); }

/* The closing call, given weight without a gradient. */
.finale {
  background: var(--raise); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 40px; box-shadow: var(--shadow-2);
  display: flex; flex-direction: column; gap: 14px; align-items: flex-start;
}

/* --------------------------------------------------------------------------
   Questions — <details> so it works with no script at all
   -------------------------------------------------------------------------- */

.qa { border-top: 1px solid var(--line); }
.qa details { border-bottom: 1px solid var(--line); }
.qa summary {
  cursor: pointer; list-style: none; padding: 18px 40px 18px 0; position: relative;
  font-weight: 660; font-size: 17px; letter-spacing: -0.01em;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after {
  content: ""; position: absolute; right: 8px; top: 50%;
  width: 10px; height: 10px; margin-top: -6px;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg); transition: transform .18s ease;
}
.qa details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.qa .answer { padding: 0 0 20px; color: var(--ink-2); max-width: 62ch; }

/* --------------------------------------------------------------------------
   Prose (privacy, support)
   -------------------------------------------------------------------------- */

.page-head { padding: 34px 0 10px; display: flex; flex-direction: column; gap: 6px; }
.prose h2 { margin: 30px 0 8px; font-size: 23px; }
.prose h2:first-child { margin-top: 0; }
.prose strong { font-weight: 680; }
.prose ul { padding-left: 20px; }
.prose li { margin: 7px 0; }
.prose li::marker { color: var(--accent); }

/* --------------------------------------------------------------------------
   Footer
   ---------------------------------------------------------------------------
   The site map first, the studio underneath it. The identity block used to sit
   in the left column beside the links, which put "who made this" above "where
   can I go" — the wrong way round for a footer, which is read by somebody
   looking for a way onward. */

.foot {
  border-top: 1px solid var(--line); margin-top: 20px; padding: 40px 0 56px;
  display: flex; flex-direction: column; gap: 34px;
}
.foot-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
.foot .foot-h {
  margin: 0 0 10px; font-size: 11.5px; font-weight: 800; letter-spacing: .13em;
  text-transform: uppercase; color: var(--muted);
}
.foot ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.foot a { text-decoration: none; font-size: 15px; color: var(--ink-2); }
.foot a:hover { color: var(--accent); }

.foot-base {
  border-top: 1px solid var(--line); padding-top: 26px;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
  color: var(--muted); font-size: 14.5px; max-width: 46em;
}
.foot-base .mark { margin-bottom: 2px; }
.foot-base p { margin: 0; }
.foot-links a { font-size: 14.5px; }
/* Which version the page is describing.
   "Is that screenshot the app I have?" had no answer here, and a beta whose
   site never says what it is a site for reads as abandoned. Kept quiet — it is
   a fact, not a headline — and checked against the Xcode project by
   scripts/check-version.sh so it cannot go stale the next time the build is
   bumped. */
.version { color: var(--muted); font-size: 13px; margin-top: 10px; }
.version strong { color: var(--ink); font-weight: 600; }

.copyright { color: var(--muted); font-size: 13.5px; margin-top: 4px; }

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

@media (max-width: 760px) {
  .hero { grid-template-columns: 1fr; gap: 30px; }
  .hero .phone { max-width: 224px; justify-self: start; }
  .feature, .feature.flip { grid-template-columns: 1fr; gap: 22px; }
  .feature .phone, .feature.flip .phone { order: 0; max-width: 210px; justify-self: start; }
  .grid, .grid.three { grid-template-columns: 1fr; }
  .finale { padding: 28px; }
}

@media print {
  body { background: #fff; color: #000; padding: 0; }
  .phone, .cta, .topnav, .skip { display: none; }
  section { padding: 18px 0; border: 0; }
}

/* --------------------------------------------------------------------------
   The web preview gate
   ---------------------------------------------------------------------------
   Deliberately not a landing page: no nav, no product pitch, no footer full of
   links. A system saying no looks like a system — a status code, the facts it
   would have on hand, and the one action that gets you further.

   There is no password field here on purpose. A form that appears to
   authenticate and cannot would collect real passwords into nothing, and the
   policy sets form-action 'none' regardless. Invite-only is the honest gate. */

.gate-body {
  min-height: 100vh;
  display: flex; flex-direction: column;
  padding: 0;
  background:
    radial-gradient(900px 480px at 50% -220px,
      color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%),
    var(--ground);
}

.gate-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 22px; border-bottom: 1px solid var(--line);
  background: var(--raise);
}
.gate-env {
  font-size: 12px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px;
}

.gate {
  flex: 1; display: flex; align-items: center; justify-content: center;
  padding: 48px 22px 80px;
}
.gate-card {
  width: 100%; max-width: 520px;
  background: var(--raise); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 34px 36px 30px;
  box-shadow: var(--shadow-2);
  display: flex; flex-direction: column; gap: 14px; align-items: flex-start;
}

.gate-status { display: flex; align-items: center; gap: 12px; }
.gate-code {
  font-size: 13px; font-weight: 700; letter-spacing: .06em;
  color: var(--bad);
  background: color-mix(in srgb, var(--bad) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--bad) 30%, transparent);
  border-radius: 8px; padding: 4px 10px;
}
.gate-lock {
  color: var(--muted); display: inline-flex;
}

.gate h1 { font-size: clamp(26px, 4vw, 34px); margin: 0; letter-spacing: -0.028em; }
.gate-lede { color: var(--ink-2); margin: 0; max-width: 44ch; }

/* The facts a real gate would have on hand, and nothing invented beyond them. */
.gate-facts {
  width: 100%; margin: 4px 0 2px; padding: 14px 16px;
  background: var(--sink); border: 1px solid var(--line); border-radius: 12px;
  display: flex; flex-direction: column; gap: 7px; font-size: 13px;
}
.gate-facts > div { display: flex; justify-content: space-between; gap: 16px; }
.gate-facts dt { color: var(--muted); margin: 0; }
.gate-facts dd { margin: 0; color: var(--ink); }

.gate-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; }
.gate-note { color: var(--muted); font-size: 14.5px; margin: 6px 0 0; max-width: 46ch; }

@media (max-width: 520px) {
  .gate-card { padding: 26px 22px 24px; }
  .gate-env { display: none; }
}

.web-cta { margin-top: 20px; }

/* --------------------------------------------------------------------------
   The header bar
   ---------------------------------------------------------------------------
   It used to be a row inside the content column, so it began and ended with the
   text and read as the first paragraph rather than as chrome. It is now a bar
   in its own right: full width, ruled off, and stuck to the top so the way out
   of a page is reachable from anywhere in it — which on a long product page is
   most of the time. */

.bar {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--ground) 86%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--line);
}
.bar-in {
  max-width: 1000px; margin: 0 auto; padding: 11px 22px;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.bar .topnav { display: flex; gap: 20px; }
.bar .topnav a { font-size: 14.5px; font-weight: 600; text-decoration: none; color: var(--muted); }
.bar .topnav a:hover { color: var(--ink); }

/* On a phone the bar stays one row. Stacking the nav under the mark made the
   header a fifth of the screen and read as two separate things; dropping the
   in-page anchors — links to a section of the page you are already reading —
   leaves only the destinations, which is what a header is for, and they fit. */
@media (max-width: 620px) {
  .bar-in { padding: 9px 22px; gap: 12px; }
  .bar .topnav { gap: 16px; }
  .bar .topnav a { font-size: 14px; }
  .bar .topnav .sec-link { display: none; }
  .mark { font-size: 15.5px; gap: 9px; }
  .mark svg, .mark img { width: 26px; height: 26px; }
}

/* Nothing inside the bar draws a rule of its own — the bar's own bottom edge is
   the only line the header gets. */
.bar .topnav, .bar .topnav a, .bar .mark { border: 0; }
.bar-in { align-items: center; }

/* The stance. Flat on the ground rather than in a card — it is the one place
   the page speaks in the first person, and a card would make it a feature. */
.stance { max-width: 64ch; display: flex; flex-direction: column; gap: 14px; }
.stance p { margin: 0; }
.stance .lede { max-width: none; }

/* A guide in the index: the whole card is the link, so the target is the card
   rather than four words inside it. */
.guide-card { text-decoration: none; color: inherit; transition: transform .15s ease, border-color .15s ease; }
.guide-card:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.guide-card h2 { font-size: 20px; margin: 0 0 4px; }

/* ---------------------------------------------------------------------------
   Quick start: a numbered sequence, and the colour legend.

   Numbers because setting up genuinely is a sequence — first, then, then. They
   are not decoration and would be wrong on a page whose parts can be read in
   any order.
   --------------------------------------------------------------------------- */

.steps { display: flex; flex-direction: column; gap: 14px; margin: 0; padding: 0; list-style: none; }

.step {
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 16px;
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  padding: 18px 20px;
}

.step > .num {
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--sink);
  color: var(--accent);
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}

.step h3 { margin: 0 0 6px; font-size: 18px; letter-spacing: -.01em; text-wrap: balance; }
.step p { margin: 0 0 9px; color: var(--ink-2); font-size: 15.5px; line-height: 1.55; }
.step p:last-child { margin-bottom: 0; }

/* The colour key. Semantic tokens, so it stays true in both themes and cannot
   drift from what the app draws. */
.legend { display: flex; flex-direction: column; gap: 13px; margin: 0; padding: 0; list-style: none; }
.legend li { display: grid; grid-template-columns: 11px 1fr; gap: 14px; align-items: start; }

.legend .dot { width: 11px; height: 11px; border-radius: 50%; margin-top: 7px; }
.legend .dot.is-good { background: var(--good); }
.legend .dot.is-warn { background: var(--warn); }
.legend .dot.is-bad  { background: var(--bad); }
.legend .dot.is-idle { background: var(--muted); }

.legend b { display: block; font-size: 15.5px; }
.legend span { color: var(--ink-2); font-size: 15.5px; line-height: 1.5; }
