/*
 * MakeHybrid design system.
 *
 * A superset of the original styles.css class vocabulary: every selector that
 * file defined is defined here too, with the same meaning, so a page can move
 * between the two stylesheets by changing one <link> and nothing else.
 * docs.html deliberately still points at styles.css -- the Unlimited API
 * reference belongs to the other track and is not changed from here.
 *
 * Layers, in order: tokens -> base -> layout -> components -> docs -> utility.
 */

/* ---------------------------------------------------------------- tokens -- */

:root {
  color-scheme: light;

  /* Brand. --blue is kept as the historical name of the accent. */
  --blue: #2563eb;
  /* The foreground for anything sitting ON --blue. A hard-coded #fff was
     fine in light mode and 2.43:1 in dark, where --blue is a pale tint. */
  --on-accent: #fff;
  --blue-dark: #1d4ed8;
  --blue-soft: #eff4ff;
  --blue-line: #c7d9fb;

  --bg: #f7f8fa;
  --bg-sunken: #eef1f5;
  --card: #ffffff;
  --border: #e4e7ec;
  --border-strong: #d2d7df;

  --text: #121417;
  --text-soft: #40464f;
  --muted: #666d78;
  --faint: #6b7280;

  --danger: #d6342c;
  --danger-soft: #fdeceb;
  --ok: #17824a;
  --ok-soft: #e7f5ec;
  --warn: #9a6400;
  --warn-soft: #fdf3e0;
  --violet: #6d3fd4;
  --violet-soft: #f1ecfd;

  /*
   * The brand mark, [@], as two mask shapes: the brackets and the @. Not colours: each is painted by
   * .brand-mark with a colour that is decided there, which is the whole
   * reason the mark is two layers instead of one picture.
   *
   * Defined once, in :root, so the dark block below inherits them -- the
   * shape does not change between themes, only what paints it.
   */
  --brand-mark-ink: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M6.6 3.2H2.2v25.6h4.4M25.4 3.2h4.4v25.6h-4.4' fill='none' stroke='%23000' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --brand-mark-accent: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M18.88 13.12v3.74a1.92 1.92 0 0 0 3.84 0v-.86a6.72 6.72 0 1 0-2.74 5.4M18.88 16a2.88 2.88 0 1 1-5.76 0a2.88 2.88 0 1 1 5.76 0' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* Code surfaces stay dark in both themes -- a terminal reads as a terminal. */
  --code-bg: #10141b;
  --code-fg: #d6dde8;
  --code-dim: #7d8899;

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;

  --shadow-sm: 0 1px 2px rgba(16, 20, 27, .05);
  --shadow: 0 1px 3px rgba(16, 20, 27, .07), 0 8px 24px -12px rgba(16, 20, 27, .14);
  --shadow-lg: 0 2px 6px rgba(16, 20, 27, .07), 0 24px 56px -24px rgba(16, 20, 27, .26);

  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
          "Liberation Mono", monospace;

  --header-h: 58px;
  --page-max: 1120px;
  --sidebar-w: 268px;
}

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

    --blue: #7aa5ff;
    --on-accent: #0b1220;
    --blue-dark: #9bbcff;
    --blue-soft: #16203a;
    --blue-line: #2b3c63;

    --bg: #0d1016;
    --bg-sunken: #0a0d12;
    --card: #141922;
    --border: #242c38;
    --border-strong: #333d4d;

    --text: #eef1f6;
    --text-soft: #c2c9d4;
    --muted: #949cab;
    --faint: #99a1b0;

    --danger: #ff8b84;
    --danger-soft: #2d1817;
    --ok: #68d79a;
    --ok-soft: #10251a;
    --warn: #e9b65c;
    --warn-soft: #2a2113;
    --violet: #b89bf5;
    --violet-soft: #1e1733;

    --code-bg: #090c11;
    --code-fg: #d6dde8;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow: 0 1px 3px rgba(0, 0, 0, .5), 0 8px 24px -12px rgba(0, 0, 0, .6);
    --shadow-lg: 0 2px 6px rgba(0, 0, 0, .5), 0 24px 56px -24px rgba(0, 0, 0, .8);
  }
}

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

  --blue: #7aa5ff;
  --on-accent: #0b1220;
  --blue-dark: #9bbcff;
  --blue-soft: #16203a;
  --blue-line: #2b3c63;

  --bg: #0d1016;
  --bg-sunken: #0a0d12;
  --card: #141922;
  --border: #242c38;
  --border-strong: #333d4d;

  --text: #eef1f6;
  --text-soft: #c2c9d4;
  --muted: #949cab;
  --faint: #99a1b0;

  --danger: #ff8b84;
  --danger-soft: #2d1817;
  --ok: #68d79a;
  --ok-soft: #10251a;
  --warn: #e9b65c;
  --warn-soft: #2a2113;
  --violet: #b89bf5;
  --violet-soft: #1e1733;

  --code-bg: #090c11;
  --code-fg: #d6dde8;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow: 0 1px 3px rgba(0, 0, 0, .5), 0 8px 24px -12px rgba(0, 0, 0, .6);
  --shadow-lg: 0 2px 6px rgba(0, 0, 0, .5), 0 24px 56px -24px rgba(0, 0, 0, .8);
}

/* ------------------------------------------------------------------ base -- */

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  /*
   * A link to a heading on the page it is already on should travel, not
   * teleport. A jump leaves the reader to work out whether the page
   * changed or merely moved; a scroll shows them the distance and they
   * arrive already knowing where they are.
   *
   * Anchors on this site are mostly in a sticky-header layout, so the
   * scroll-margin-top rules further down are the other half of this --
   * without them smooth scrolling just glides the target neatly under the
   * header. Both halves, or neither.
   *
   * Overridden by the prefers-reduced-motion block at the end of this
   * file: its universal selector covers <html> and carries !important, so
   * a reader who has asked their system for less movement still gets the
   * instant jump. Motion is the default here, not the requirement.
   */
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font: 400 15px/1.6 var(--font);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

h1, h2, h3, h4 {
  color: var(--text);
  letter-spacing: -.015em;
  line-height: 1.25;
  font-weight: 650;
}

h1 { font-size: 30px; margin: 0 0 10px; }
h2 { font-size: 20px; margin: 36px 0 12px; }
h3 { font-size: 15px; margin: 0 0 12px; }

p { margin: 0 0 12px; }
p.lead { color: var(--muted); font-size: 16px; margin-bottom: 26px; }

hr { border: 0; border-top: 1px solid var(--border); margin: 28px 0; }

/*
 * One rule for every image on every page.
 *
 * There was none, which is fine while a stylesheet has no images in it and
 * stops being fine the moment one does: an <img> renders at its intrinsic
 * width, so a 320px portrait inside a card at a 320px viewport overflows
 * its own column and gives the whole page horizontal scroll.
 */
img { max-width: 100%; height: auto; }

::selection { background: var(--blue-soft); color: var(--text); }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 8px;
  z-index: 100;
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  font-weight: 600;
}
.skip-link:focus { left: 8px; }

/* ---------------------------------------------------------------- layout -- */

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  height: var(--header-h);
  padding: 0 22px;
  background: color-mix(in srgb, var(--card) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 40;
}

header .brand {
  display: flex;
  align-items: center;
  /* Tight: the mark's brackets reach the edges of its box, so the box's
     own edge is the mark's edge and this is the whole distance to the name. */
  gap: 7px;
  font-weight: 700;
  font-size: 15.5px;
  letter-spacing: -.02em;
  color: var(--text);
}
header .brand a { color: inherit; text-decoration: none; }
header .brand:hover { text-decoration: none; }

/*
 * The brand mark: two brackets holding one opening between them.
 *
 * It was a lone capital M, white, on a violet gradient. Make.com is an
 * automation and integration platform with a strongly violet identity
 * selling into developer and automation tooling, which overlaps this; a
 * violet rounded square with an M in it sat about as close to their mark
 * as a mark can without meaning to. A logo cannot cure a name conflict --
 * that is not what this is for -- but it can stop the identity adding to
 * one. Six directions were drawn side by side and this is the one that was
 * picked; the page they were drawn on is gone, and is in git if it is ever
 * wanted back.
 *
 * Drawn here rather than in markup so the mark lives in exactly one file:
 * changing it is this rule, not fourteen pages.
 *
 * Two mask layers rather than one picture, and that is the load-bearing
 * part. The left bracket is painted in `currentColor`, so it follows the
 * text beside it and needs no dark-mode variant at all; the right is
 * painted in --blue, so a white-labelled brand's own accent reaches the
 * mark exactly the way it already reaches every button on the page. A
 * baked-in two-colour image would lose both.
 *
 * The element itself paints nothing; see the @supports block below for
 * why that matters.
 */
.brand-mark {
  width: 22px;
  height: 22px;
  flex: none;
  position: relative;
}

/*
 * BOTH brackets are pseudo-elements, and that is not a style choice.
 *
 * The first version masked the element itself for one bracket and used
 * ::after for the other. A mask applies to an element's whole subtree,
 * pseudo-elements included -- so the second bracket was being clipped by
 * the first bracket's mask, and since the two shapes do not overlap, it
 * was clipped to nothing. The header rendered a lone `[`, which is a
 * perfectly valid stylesheet and the wrong mark. Nothing but looking at it
 * would have caught that.
 *
 * Behind @supports because the fallback for a mask nobody honours is two
 * solid 22px blocks -- a black square in the header, which is worse than
 * no mark at all. Without mask support there is simply no mark.
 */
@supports ((-webkit-mask-image: linear-gradient(#000, #000)) or (mask-image: linear-gradient(#000, #000))) {
  .brand-mark::before,
  .brand-mark::after {
    content: "";
    position: absolute;
    inset: 0;
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
  }
  .brand-mark::before {
    background-color: currentColor;
    -webkit-mask-image: var(--brand-mark-ink);
            mask-image: var(--brand-mark-ink);
  }
  .brand-mark::after {
    background-color: var(--blue);
    -webkit-mask-image: var(--brand-mark-accent);
            mask-image: var(--brand-mark-accent);
  }
}

/*
 * A white-labelled brand with a name but no logo of its own falls back to
 * its own initial, which brand.js writes in. The mask has to come off for
 * that: the brackets are pseudo-elements, and a letter sitting under two
 * opaque layers is a letter nobody sees.
 */
.brand-mark.is-initial {
  background: var(--blue);
  border-radius: 6px;
  display: grid;
  place-items: center;
  color: var(--on-accent);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -.04em;
}
.brand-mark.is-initial::before,
.brand-mark.is-initial::after { content: none; }

header nav {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
header nav a {
  margin-left: 0;
  font-size: 13.5px;
  color: var(--text-soft);
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
header nav a:hover { background: var(--bg-sunken); color: var(--text); text-decoration: none; }
header nav a[aria-current="page"] { color: var(--blue); background: var(--blue-soft); }
header nav .muted { padding: 0 6px; }
/*
 * The public site's menu: the products, the guides and the price beside
 * the name, then the trial and the sign-in at the right edge, ahead of
 * the language and theme controls. The nav takes the row's spare width
 * and `.nav-end` -- the first link of the right-hand pair, or the
 * member's own links that nav-session.js puts in their place -- spends it.
 */
header nav.site-nav { flex: 1 1 auto; }
header nav.site-nav .nav-end { margin-inline-start: auto; }

/*
 * The header is sticky, so anything an in-page link targets has to reserve
 * its height -- otherwise "Plans" scrolls the top of the first card
 * underneath it. The docs page sets this per-element; this covers the
 * marketing pages.
 */
:where(main, .home-stack) > section[id],
:where(main, .home-stack) > [id]:not(:first-child) {
  scroll-margin-top: calc(var(--header-h) + 16px);
}

main {
  max-width: 760px;
  margin: 0 auto;
  padding: 44px 20px 64px;
}
main.wide { max-width: var(--page-max); }
main.narrow { max-width: 440px; }

footer {
  text-align: center;
  color: var(--muted);
  font-size: 12.5px;
  padding: 28px 20px 40px;
  border-top: 1px solid var(--border);
}
footer a { color: var(--muted); }
footer a:hover { color: var(--text); }

/* ------------------------------------------------------------ components -- */

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 18px;
  box-shadow: var(--shadow-sm);
}
.card h3 { margin: 0 0 12px; font-size: 15px; }
/*
 * Trim the trailing gap under a card's last block -- but a <dialog> is not
 * one of its blocks.
 *
 * This rule is more specific than `.modal`, so on a card whose last child
 * is the verification dialog it was setting `margin-bottom: 0` on a box
 * that centres itself with `margin: auto`. Auto margins split the free
 * space between them; with the bottom one pinned to zero, all of it went to
 * the top and the dialog sat flush against the bottom of the screen. It
 * looked like a positioning bug in the modal and was a text rule reaching
 * into the top layer.
 */
.card > :last-child:not(dialog) { margin-bottom: 0; }

.card-tight { padding: 14px 16px; }

form { display: flex; flex-direction: column; gap: 12px; max-width: 380px; }
form.wide-form { max-width: none; }

label {
  font-size: 12.5px;
  color: var(--text-soft);
  font-weight: 600;
  display: block;
  margin-bottom: -4px;
}

input, select, textarea {
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14.5px;
  width: 100%;
  background: var(--card);
  color: var(--text);
  transition: border-color .12s, box-shadow .12s;
}
input::placeholder, textarea::placeholder { color: var(--faint); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent);
}
input:disabled, select:disabled, textarea:disabled { opacity: .6; cursor: not-allowed; }
textarea { resize: vertical; min-height: 84px; font-family: var(--mono); font-size: 13px; }

button {
  padding: 10px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--blue);
  color: var(--on-accent);
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: background .12s, border-color .12s, opacity .12s;
  line-height: 1.3;
}
button:hover { background: var(--blue-dark); }
button:disabled { opacity: .5; cursor: default; }
button.secondary {
  background: var(--card);
  color: var(--text);
  border-color: var(--border-strong);
}
button.secondary:hover { background: var(--bg-sunken); }
button.ghost { background: transparent; color: var(--blue); border-color: transparent; }
button.ghost:hover { background: var(--blue-soft); }
button.danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
button.danger:hover { background: var(--danger-soft); filter: brightness(.96); }
button.small { padding: 6px 11px; font-size: 12.5px; width: auto; }
button.block { width: 100%; }

:root[data-theme="dark"] button.secondary,
:root[data-theme="dark"] button.danger { color: var(--text); }

/*
 * `.btn` exists so a navigation control can be an <a> and still look like a
 * button. Wrapping a <button> in an <a> is invalid HTML -- interactive
 * content inside a link -- and gives screen readers two nested controls and
 * the keyboard two tab stops for one action.
 */
a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--blue);
  color: var(--on-accent);
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  line-height: 1.3;
  cursor: pointer;
  text-decoration: none;
  transition: background .12s, border-color .12s;
}
a.btn:hover { background: var(--blue-dark); text-decoration: none; }
a.btn.secondary {
  background: var(--card);
  color: var(--text);
  border-color: var(--border-strong);
}
a.btn.secondary:hover { background: var(--bg-sunken); }
a.btn.ghost { background: transparent; color: var(--blue); border-color: transparent; }
a.btn.ghost:hover { background: var(--blue-soft); }
a.btn.small { padding: 6px 11px; font-size: 12.5px; }
a.btn.block { width: 100%; }
.pricing a.btn { width: 100%; }

.btn-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

.error { color: var(--danger); font-size: 13px; min-height: 18px; }
/* Out of the flow entirely, not merely zero-height: an empty slot was still
   taking the form's 12px gap and a paragraph margin above every submit
   button. role="alert" still announces, because writing text re-enters it. */
.error:empty { display: none; }
.ok-text { color: var(--ok); font-size: 13px; }
.muted { color: var(--muted); font-size: 13.5px; }
.small-text { font-size: 12.5px; }

.row {
  /* A long account name used to push Remove past the right edge with nothing
     able to wrap. */
  flex-wrap: wrap;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
  gap: 12px;
}
.row:last-child { border-bottom: none; }
.row:first-child { padding-top: 0; }
/* The id a member passes as account_id, under each connected account. */
.account-id { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px; }

.dot {
  width: 8px; height: 8px; border-radius: 50%;
  display: inline-block; margin-right: 7px; flex-shrink: 0;
  background: var(--faint);
}
.dot.healthy, .dot.ok { background: var(--ok); }
.dot.needs_reconnect, .dot.checkpoint, .dot.credentials { background: var(--warn); }
.dot.halted, .dot.banned, .dot.error { background: var(--danger); }
.dot.paused, .dot.stopped { background: var(--faint); }

code, pre, .mono { font-family: var(--mono); font-size: 13px; }

pre {
  background: var(--code-bg);
  color: var(--code-fg);
  padding: 15px 16px;
  border-radius: var(--radius-sm);
  overflow-x: auto;
  line-height: 1.6;
  margin: 0 0 14px;
  border: 1px solid rgba(255, 255, 255, .06);
  tab-size: 2;
}
pre:last-child { margin-bottom: 0; }

code.inline {
  background: var(--bg-sunken);
  border: 1px solid var(--border);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 12.5px;
  /*
   * `nowrap` was right for what this class was made for -- `/v1`,
   * `X-API-KEY`, a path -- and wrong for the one place it carries a whole
   * JSON error body, which at 320px hung 67px past the edge of the screen
   * and gave the landing page horizontal scroll.
   *
   * `pre-wrap` keeps the spaces inside a chip and `anywhere` breaks a token
   * only when it would otherwise overflow, so every short chip still sits
   * on one line exactly as before.
   */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text-soft);
}

/* Code block with a copy affordance. */
.code-wrap { position: relative; margin: 0 0 14px; }
.code-wrap pre { margin: 0; }
.copy-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 4px 9px;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 5px;
  background: rgba(255, 255, 255, .09);
  color: var(--code-fg);
  border: 1px solid rgba(255, 255, 255, .14);
  opacity: 0;
  transition: opacity .12s, background .12s;
  cursor: pointer;
}
.code-wrap:hover .copy-btn,
.copy-btn:focus-visible { opacity: 1; }
.copy-btn:hover { background: rgba(255, 255, 255, .17); }
.copy-btn.copied { color: #8fe0ae; }
@media (hover: none) { .copy-btn { opacity: 1; } }

.keyval {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--blue-soft);
  border: 1px solid var(--blue-line);
  border-radius: var(--radius-sm);
  padding: 9px 11px;
  word-break: break-all;
}

.badge {
  display: inline-block;
  /*
   * .option-card and .plan-card are flex columns, which BLOCKIFIES an
   * inline-block child and stretches it across the cross axis. The pill
   * became a full-width bar with its label stranded at the left -- the
   * loudest thing wrong with the connect and pricing cards. align-self is
   * inert outside a flex or grid parent, so every inline use is untouched.
   */
  align-self: start;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--blue-soft);
  color: var(--blue);
  border: 1px solid var(--blue-line);
  letter-spacing: .01em;
  vertical-align: middle;
}
.badge.neutral { background: var(--bg-sunken); color: var(--muted); border-color: var(--border); }
.badge.ok { background: var(--ok-soft); color: var(--ok); border-color: transparent; }
.badge.warn { background: var(--warn-soft); color: var(--warn); border-color: transparent; }
.badge.danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.badge.violet { background: var(--violet-soft); color: var(--violet); border-color: transparent; }

.kbd {
  font-family: var(--mono);
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 5px;
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  background: var(--card);
  color: var(--muted);
}

.hidden { display: none !important; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table th, table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
table th {
  color: var(--muted);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
}
table tr:last-child td { border-bottom: none; }
.table-scroll { overflow-x: auto; }

.method {
  font-weight: 700;
  font-size: 10.5px;
  padding: 3px 7px;
  border-radius: 5px;
  margin-right: 8px;
  letter-spacing: .04em;
  font-family: var(--mono);
  display: inline-block;
  vertical-align: middle;
  text-transform: uppercase;
}
.method.get { background: var(--ok-soft); color: var(--ok); }
.method.post { background: var(--blue-soft); color: var(--blue); }
.method.patch, .method.put { background: var(--warn-soft); color: var(--warn); }
.method.delete { background: var(--danger-soft); color: var(--danger); }

.endpoint {
  margin-bottom: 24px;
  scroll-margin-top: calc(var(--header-h) + 16px);
}
.endpoint .path {
  font-size: 14px;
  font-weight: 600;
  font-family: var(--mono);
  display: flex;
  align-items: center;
  gap: 2px;
  flex-wrap: wrap;
  word-break: break-all;
}

/* Callouts. */
.callout {
  border: 1px solid var(--border);
  border-left: 3px solid var(--muted);
  background: var(--bg-sunken);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin: 0 0 14px;
  font-size: 13.5px;
  color: var(--text-soft);
}
.callout > :last-child { margin-bottom: 0; }
.callout b, .callout strong { color: var(--text); }
.callout.info { border-left-color: var(--blue); background: var(--blue-soft); }
.callout.warn { border-left-color: var(--warn); background: var(--warn-soft); }
.callout.danger { border-left-color: var(--danger); background: var(--danger-soft); }
.callout.ok { border-left-color: var(--ok); background: var(--ok-soft); }

/* Numbered steps. */
.steps { list-style: none; counter-reset: step; margin: 0; padding: 0; }
.steps > li {
  counter-increment: step;
  position: relative;
  padding: 0 0 20px 38px;
  border-left: 1px solid var(--border);
  margin-left: 13px;
}
.steps > li:last-child { border-left-color: transparent; padding-bottom: 0; }
.steps > li::before {
  content: counter(step);
  position: absolute;
  left: -13px;
  top: -2px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--card);
  border: 1px solid var(--border-strong);
  color: var(--text-soft);
  font-size: 12px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
.steps > li > b:first-child,
.steps > li > strong:first-child { display: block; margin-bottom: 3px; }

/*
 * A short numbered how-to inside a card.
 *
 * Deliberately not .steps, which draws a numbered disc and a rule down the
 * side: right for the three stages of getting an account connected, far too
 * loud for "click this, then that". This is a plain ordered list with its
 * indent pulled in to the card's own rhythm.
 */
.howto {
  margin: 0 0 12px;
  padding-left: 20px;
}
.howto > li { margin-bottom: 5px; }
.howto > li:last-child { margin-bottom: 0; }

/* Segmented control / tabs. */
.seg {
  display: inline-flex;
  padding: 3px;
  gap: 3px;
  background: var(--bg-sunken);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.seg button, .seg .tab {
  background: transparent;
  color: var(--muted);
  border: none;
  padding: 6px 13px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 6px;
  cursor: pointer;
}
.seg button:hover, .seg .tab:hover { color: var(--text); background: transparent; }
.seg button[aria-selected="true"], .seg .tab[aria-selected="true"] {
  background: var(--card);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

/* Choice cards -- two ways to do the same thing. */
.option-grid {
  display: grid;
  /* min() lets the single-column case collapse to the container instead of
     overflowing it: at 360px the card's content box is ~234px, narrower than
     a bare 260px floor, and the cards broke out through its rounded edge. */
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 16px;
}
/*
 * A grid's gap sits between its own children and leaves nothing after
 * itself, and `.card` carries only a bottom margin -- so a card following
 * a grid sat flush against it, which is what the account page looked like.
 * Today only that page has the adjacency; this is written for any element
 * so the next one to appear does not reintroduce it.
 */
.option-grid + * { margin-top: 18px; }
/*
 * Two across, never three.
 *
 * `auto-fit` is right for cards that hold a sentence each and wrong for
 * cards that hold a list of ten article titles: at this container's width
 * it fits three and leaves the fourth alone on a row of its own, with
 * every title in all four wrapping twice to make it fit. The general index
 * is the one grid here whose cards have real content in them.
 */
@media (min-width: 760px) {
  .option-grid.pairs { grid-template-columns: 1fr 1fr; }
}

.option-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-sm);
}
.option-card.recommended { border-color: var(--blue); box-shadow: 0 0 0 1px var(--blue), var(--shadow-sm); }
.option-card :is(h3, h4) { margin: 8px 0 6px; font-size: 15.5px; }
/*
 * The body no longer grows. It used to carry `flex: 1`, with the form a
 * sibling AFTER it, so on the shorter of the two cards the form was shoved
 * to the bottom and the middle of the card was a chasm. Content now runs
 * top-down and the leftover height falls at the BOTTOM of the card, where it
 * reads as padding rather than as something missing.
 */
.option-card .option-body { flex: 0 0 auto; }
/* `form` caps at 380px for the 408px auth card. Inside a wider card that
   left every input, the textarea and the full-width submit ending 67px short
   of the copy above them. */
.option-card form,
.modal form:not(.modal-dismiss) { max-width: none; }
.option-card form { margin-top: 14px; }
.option-card .option-cta { margin-top: 14px; }
/* The two routes are a comparison, so their headings and first lines must sit
   on the same baseline regardless of how much copy each one carries. */
.option-grid { align-items: start; }

/* ----------------------------------------------------------------- modal -- */

/*
 * A challenge is a hard stop: nothing else on the connect card can be done
 * until it is answered. It gets a modal rather than a notice further down a
 * long page, which is read as commentary on a page that still looks usable.
 */
.modal {
  /*
   * A modal dialog is centred by the user agent through `margin: auto` on an
   * `inset: 0` box -- but only while nothing else claims those properties.
   * Declared here so the dialog's position does not depend on which other
   * rules happen to match it, which is how it ended up sitting low and left.
   */
  position: fixed;
  inset: 0;
  margin: auto;
  /* Taller than the viewport is a dead end otherwise: no scroll, no buttons. */
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  width: min(460px, calc(100vw - 32px));
  height: fit-content;
  padding: 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--text);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .45);
}
.modal::backdrop { background: rgba(8, 11, 18, .66); }
.modal h3 { font-size: 17px; letter-spacing: -.01em; }
.modal > p.muted { margin-bottom: 16px; }
.modal form:not(.modal-dismiss) { margin-top: 4px; }
.modal-dismiss { position: absolute; top: 10px; right: 10px; margin: 0; }
.modal-dismiss button {
  width: 30px;
  height: 30px;
  padding: 0;
  font-size: 19px;
  line-height: 1;
  background: transparent;
  color: var(--muted);
  border: 1px solid transparent;
  border-radius: 8px;
}
.modal-dismiss button:hover { background: var(--bg-sunken); color: var(--text); border-color: var(--border); }

.waiting { display: flex; align-items: center; gap: 10px; color: var(--muted); margin: 2px 0 0; }
.spinner {
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  border: 2px solid var(--border);
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: mh-spin .8s linear infinite;
}
@keyframes mh-spin { to { transform: rotate(360deg); } }
/* A spinner that never stops is a worse signal than none for anyone who finds
   motion distracting; the text alone still says what is happening. */
@media (prefers-reduced-motion: reduce) {
  .spinner { animation: none; border-top-color: var(--border); }
}

/* ------------------------------------------------------------------ home -- */

.hero { margin-bottom: 30px; }
.hero h1 {
  font-size: clamp(30px, 5vw, 44px);
  line-height: 1.12;
  max-width: 17em;
  letter-spacing: -.03em;
  margin-bottom: 14px;
}
.hero .lead { max-width: 56ch; font-size: 17px; }
.hero-cta { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 22px; }
.hero-cta button { width: auto; padding: 11px 20px; font-size: 14.5px; }

.home-stack { display: flex; flex-direction: column; gap: 18px; }
.home-stack > .card { margin-bottom: 0; }

.pricing {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  gap: 18px;
  margin: 0;
  align-items: stretch;
}
.pricing .card,
.plan-card {
  margin-bottom: 0;
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  width: 50%;
  min-width: 0;
  position: relative;
}
.pricing .price,
.price {
  font-size: 34px;
  font-weight: 700;
  margin: 6px 0 8px;
  letter-spacing: -.03em;
}
.price span.muted { font-size: 14px; font-weight: 400; letter-spacing: 0; }
.pricing button { width: 100%; }
.plan-card.featured { border-color: var(--blue); box-shadow: 0 0 0 1px var(--blue), var(--shadow); }
/* Beside the plan card, what the plan buys. Same column rules as the card. */
.plan-includes .plan-list li b { color: var(--text); }
.plan-list { margin: 0 0 18px; padding-left: 0; list-style: none; flex: 1; }
.plan-list li {
  margin: 9px 0;
  padding-left: 24px;
  position: relative;
  color: var(--text-soft);
  font-size: 13.5px;
}
.plan-list li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 7px;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--ok);
  border-bottom: 2px solid var(--ok);
  transform: rotate(-45deg);
}
.plan-cta { margin-top: auto; }
.plan-cta p { margin: 10px 0 0; }
/* A link line brand.js emptied still takes a line, so the cards' buttons stay level. */
.plan-cta p:empty::before { content: "\00a0"; }

/* The guides index: one subject gathered from every section, above them. */
.topic { margin-bottom: 18px; }
.topic-list { columns: 2; column-gap: 32px; }
.topic-list li { break-inside: avoid; }

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 16px;
}
.feature h4 { margin: 0 0 5px; font-size: 14.5px; }
.feature p { margin: 0; color: var(--muted); font-size: 13.5px; }

/* ------------------------------------------------------------------ auth -- */

.auth-wrap {
  min-height: calc(100vh - var(--header-h));
  display: grid;
  grid-template-columns: 1fr;
  place-items: start center;
  padding: 48px 20px 64px;
}
.auth-card {
  width: 100%;
  max-width: 408px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 30px 28px;
  box-shadow: var(--shadow-lg);
}
.auth-card h1 { font-size: 23px; margin-bottom: 6px; }
.auth-card form { max-width: none; gap: 14px; }
.auth-card .lead { font-size: 14px; margin-bottom: 22px; }
.auth-foot {
  margin: 20px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--muted);
  text-align: center;
}
.auth-aside {
  width: 100%;
  max-width: 408px;
  margin: 16px auto 0;
  font-size: 12.5px;
  color: var(--faint);
  text-align: center;
}
.label-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  /* The bare `label` rule tightens the gap to its input with a negative
     margin. Inside a flex container that margin applies to the label box,
     not the row, so the row has to carry it or the field below sits 4px
     lower than its neighbours. */
  margin-bottom: -4px;
}
.label-row label { margin-bottom: 0; }
.label-row a { font-size: 12.5px; font-weight: 500; }

/* ------------------------------------------------------------------ docs -- */

.docs-shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  gap: 36px;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 20px;
  align-items: start;
}
.docs-shell.with-toc {
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr) 190px;
}

.docs-sidebar {
  position: sticky;
  top: var(--header-h);
  max-height: calc(100vh - var(--header-h));
  overflow-y: auto;
  padding: 24px 6px 48px 0;
  font-size: 13.5px;
  scrollbar-width: thin;
}

.doc-search { position: relative; margin-bottom: 18px; }
.doc-search input { padding: 8px 11px 8px 30px; font-size: 13.5px; }
.doc-search::before {
  content: "";
  position: absolute;
  left: 11px;
  top: 50%;
  width: 11px;
  height: 11px;
  margin-top: -7px;
  border: 1.6px solid var(--faint);
  border-radius: 50%;
  pointer-events: none;
}
.doc-search::after {
  content: "";
  position: absolute;
  left: 20px;
  top: 50%;
  width: 6px;
  height: 1.6px;
  margin-top: 3px;
  background: var(--faint);
  transform: rotate(45deg);
  pointer-events: none;
}

.side-group { margin-bottom: 20px; }
.side-group > h4 {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--faint);
  margin: 0 0 7px 10px;
  font-weight: 700;
}
.side-group ul { list-style: none; margin: 0; padding: 0; }

.side-link {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  color: var(--text-soft);
  line-height: 1.4;
}
.side-link:hover { background: var(--bg-sunken); color: var(--text); text-decoration: none; }
.side-link[aria-current="true"],
.side-link.active {
  background: var(--blue-soft);
  color: var(--blue);
  font-weight: 600;
}
.side-link .method { margin-right: 0; font-size: 9px; padding: 2px 5px; flex: none; }
.side-link .side-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/*
 * margin: 0 overrides `main { margin: 0 auto }`. An auto margin makes a grid
 * item size to its content rather than its column, and the widest code line
 * in the catalog then pushed the column out under "On this page".
 */
.docs-main { padding: 24px 0 72px; min-width: 0; margin: 0; }
.docs-main h2 {
  scroll-margin-top: calc(var(--header-h) + 16px);
  padding-top: 8px;
  margin-top: 44px;
}
.docs-main h2:first-of-type { margin-top: 8px; }
.docs-main h3 { font-size: 16px; margin: 26px 0 10px; scroll-margin-top: calc(var(--header-h) + 16px); }

.onthispage {
  position: sticky;
  top: var(--header-h);
  padding: 28px 0 40px;
  font-size: 12.5px;
  max-height: calc(100vh - var(--header-h));
  overflow-y: auto;
}
.onthispage h4 {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--faint);
  margin: 0 0 8px;
  font-weight: 700;
}
.onthispage ul { list-style: none; margin: 0; padding: 0; }
.onthispage a {
  display: block;
  padding: 4px 0 4px 11px;
  border-left: 2px solid var(--border);
  color: var(--muted);
  line-height: 1.45;
}
.onthispage a:hover { color: var(--text); text-decoration: none; }
.onthispage a.active { border-left-color: var(--blue); color: var(--blue); font-weight: 600; }

/* Anchor affordance on headings. */
.anchor {
  color: var(--faint);
  margin-left: 8px;
  font-weight: 400;
  opacity: 0;
  text-decoration: none;
  font-size: .8em;
}
h2:hover .anchor,
h3:hover .anchor,
.op > summary:hover .anchor,
.anchor:focus-visible { opacity: 1; }

/* Endpoint card used by the generated reference. */
.op {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  padding: 16px 18px;
  margin: 0 0 14px;
  scroll-margin-top: calc(var(--header-h) + 16px);
  box-shadow: var(--shadow-sm);
}
.op > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: -16px -18px;
  padding: 16px 18px;
  border-radius: var(--radius);
}
.op > summary::-webkit-details-marker { display: none; }
.op > summary:hover { background: var(--bg-sunken); }
.op[open] > summary { margin-bottom: 4px; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.op .op-path {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  word-break: break-all;
  min-width: 0;
}
.op .op-summary { color: var(--muted); font-size: 13px; width: 100%; margin: 0; }
.op .op-body { padding-top: 14px; border-top: 1px solid var(--border); margin-top: 12px; }

.filter-bar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 16px;
}
.filter-bar input { max-width: 300px; }
.result-count { color: var(--muted); font-size: 13px; }

.breadcrumb { font-size: 12.5px; color: var(--muted); margin-bottom: 10px; }
.breadcrumb a { color: var(--muted); }

.pager {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  margin-top: 44px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}
.pager a {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 14px;
  flex: 1 1 0;
  background: var(--card);
}
.pager a:hover { border-color: var(--blue); text-decoration: none; }
.pager .pager-dir { display: block; font-size: 11px; color: var(--faint); text-transform: uppercase; letter-spacing: .06em; }
.pager .pager-next { text-align: right; }

/* The sidebar toggle only exists on narrow screens. */
.sidebar-toggle { display: none; }

.theme-toggle {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-soft);
  padding: 5px 9px;
  border-radius: var(--radius-sm);
  font-size: 12.5px;
  line-height: 1;
  cursor: pointer;
}
.theme-toggle:hover { background: var(--bg-sunken); }

/* --------------------------------------------------------------- utility -- */

.stack-sm > * + * { margin-top: 8px; }
.stack > * + * { margin-top: 16px; }
.mt-0 { margin-top: 0 !important; }
.mb-0 { margin-bottom: 0 !important; }

/*
 * The quiet last line of a card, under whatever it was asking you to do.
 *
 * `p` is `margin: 0 0 12px`, so a paragraph after a button row had no top
 * margin at all and the only gap was its line-height -- the reference
 * link sat against the bottom of "Add a card" as though it were part of
 * the control. Named rather than an `.mt-3` utility, because the existing
 * utilities here are only ever zero and one member of a numeric scale is
 * not a scale.
 */
.card-foot { margin: 18px 0 0; }
.nowrap { white-space: nowrap; }
.flex-between { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }

/* The TOC card from the original stylesheet. */
.toc p { margin: 0; }
.toc a { white-space: nowrap; }

/* ----------------------------------------------------------- responsive -- */

@media (max-width: 1080px) {
  .docs-shell.with-toc { grid-template-columns: var(--sidebar-w) minmax(0, 1fr); }
  .onthispage { display: none; }
}

@media (max-width: 860px) {
  .docs-shell, .docs-shell.with-toc { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .docs-sidebar {
    position: static;
    max-height: none;
    overflow: visible;
    padding: 16px 0 0;
    border-bottom: 1px solid var(--border);
    margin-bottom: 20px;
  }
  .docs-sidebar[hidden] { display: none; }
  .sidebar-toggle {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 18px 0 0;
    width: auto;
  }
  .docs-main { padding-top: 16px; }
}

@media (max-width: 639px) {
  :root { --header-h: auto; }
  header {
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 16px;
    position: static;
  }
  header nav { gap: 2px; }
  header nav a { padding: 5px 8px; font-size: 13px; }
  main { padding: 28px 16px 48px; }
  .pricing { flex-direction: column; flex-wrap: wrap; }
  .pricing .card, .plan-card { width: 100%; max-width: none; }
  .topic-list { columns: 1; }
  .hero h1 { font-size: 28px; }
  .auth-wrap { padding: 24px 16px 48px; }
  .auth-card { padding: 24px 20px; border-radius: var(--radius); }
  .docs-shell { padding: 0 16px; }
  .pager { flex-direction: column; }
  .pager .pager-next { text-align: left; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

@media print {
  header, footer, .docs-sidebar, .onthispage, .copy-btn, .pager { display: none !important; }
  .docs-shell { grid-template-columns: 1fr; }
  body { background: #fff; }
}

/* ------------------------------------------------- small screens, touch -- */

/*
 * Anything under 16px makes iOS zoom the page on focus, and the verification
 * modal autofocuses its code box -- so the one moment the member most needs
 * to see the whole dialog is the moment the page jumps. Only below the
 * pointer-fine widths, so the denser desktop form keeps its sizing.
 */
@media (max-width: 860px) {
  input,
  select,
  textarea { font-size: 16px; }
  textarea { font-size: 15px; }
}

/*
 * A coarse pointer needs a target it can actually hit. The visual size of
 * these controls is deliberate, so the padding grows rather than the type.
 */
@media (pointer: coarse) {
  button,
  a.btn {
    min-height: 44px;
  }
  button.small,
  a.btn.small {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-block: 0;
    padding-inline: 14px;
  }
  .modal-dismiss button { width: 44px; height: 44px; }
  header nav a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .option-card summary { padding-block: 10px; }
}

/*
 * The connect card is reached by #connect from the landing page and from the
 * dashboard's own links. The existing scroll-margin rule only covers direct
 * children of main, and this one is nested inside the step rail, so the
 * sticky header sat on top of the heading it had just jumped to.
 */
.steps > li[id],
main[id] { scroll-margin-top: calc(var(--header-h) + 16px); }

/* The hero's actions are <a class="btn">, which the button-only rule above
   never matched, so the primary CTA rendered at ordinary body-button size. */
.hero-cta a.btn { width: auto; padding: 13px 22px; font-size: 15.5px; }

/* ----------------------------------------------------------- marketplace -- */

/*
 * A logo belonging to somebody else, on a plate.
 *
 * The white is deliberately a literal rather than a token: it is not a
 * surface colour that should follow the theme, it is a sheet of paper to
 * print a logo on. Most logos are dark ink on transparency, and on the dark
 * theme's #141922 card they would simply disappear.
 */
.logo-mark {
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 8px;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--border);
  padding: 4px;
}

/* A face, cropped square and round, however it was shot. */
.avatar { width: 72px; height: 72px; flex: none; border-radius: 50%; object-fit: cover; }

/*
 * A figure beside a column of text, which stacks on a phone by itself.
 *
 * None of the three flex rows already here would do: `.row` is
 * space-between with a rule under it, `.flex-between` spreads, and `.check`
 * is a form control. The 220px basis on the text column is what makes it
 * wrap rather than squeeze.
 */
.media { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
.media > :last-child { flex: 1 1 220px; min-width: 0; }

/*
 * Cards in a row of equals, rather than a row of comparisons.
 *
 * `.option-grid` sets `align-items: start` so two cards being compared
 * share a baseline. In a row of three products that leaves each card as
 * tall as its own text and the buttons at three different heights.
 */
.option-grid.even { align-items: stretch; }
.option-grid.even > .option-card { height: 100%; }

/* A list that is a list, not a list of things you get. `.plan-list` ticks
   every item, which reads as "included" wherever it is used. */
.plain-list { margin: 0 0 12px; padding-left: 18px; color: var(--text-soft); }
.plain-list li { margin: 6px 0; }

/* A price inside a product card. `.price` is 34px, which is right for the
   two plan cards and shouts over the heading of anything smaller. */
.meta-price { font-size: 15px; font-weight: 650; color: var(--text); letter-spacing: -.01em; margin: 0 0 8px; }

/* The action at the foot of a card, pushed down so a row of cards lines up. */
.card-cta { margin-top: auto; padding-top: 14px; }

/*
 * A textarea for prose rather than for code.
 *
 * The base `textarea` is monospace at 13px, which is right for a request
 * body and wrong for "what are you working on" -- it makes an ordinary
 * sentence look like something that has to be typed exactly.
 */
textarea.prose {
  font-family: inherit;
  font-size: 13.5px;
  min-height: 72px;
  line-height: 1.5;
}

/* The price is the number a visitor came for, so it sits on its own line
   under the headline rather than as a clause inside the lead paragraph. */
.hero-price {
  margin: 0 0 10px;
  font-size: 17px;
  color: var(--text);
}
.hero-price strong { font-size: 24px; font-weight: 700; letter-spacing: -.02em; }
.hero-price .muted { font-size: 14.5px; }

/* ------------------------------------------------------------- webhooks -- */

.events { border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; margin: 0; }
.events legend { font-size: 12.5px; font-weight: 600; color: var(--text-soft); padding: 0 6px; }
.check {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  font-weight: 400;
  color: var(--text);
  margin: 0;
  padding: 5px 0;
}
.check input { width: auto; margin: 0; }
/* A secret shown once has to survive being copied out of a narrow column. */
.break-all { overflow-wrap: anywhere; word-break: break-all; }

/* The dialog's own actions, so dismissing it is not a 30px glyph hunt. */
.modal-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 16px;
}
.modal-actions button { width: auto; flex: 1 1 auto; }

/*
 * A card's blurb may be mostly one unbreakable token.
 *
 * The blurb of a generated page starts with the route, and a route like
 * /linkedin/v2/{account_id}/posts/{post_id}/comments/{comment_id}/reactions
 * has no space in it to wrap at -- so it ran straight out of the card and
 * was clipped by the grid. It shows on the English index too; it is only
 * obvious in a language whose own words are short enough that the path is
 * the widest thing on the page.
 */
.option-card .option-body p { overflow-wrap: anywhere; }

/* ------------------------------------------------------------ languages -- */

/*
 * The language picker in the footer of a written page.
 *
 * Plain links, wrapping, because there are seventeen of them and they are
 * the one piece of chrome that must work with no JavaScript: a picker a
 * crawler cannot follow is a picker that does half its job. The separator
 * is a border rather than a character so it never ends up read aloud.
 */
/*
 * A row of links under the footer's main line: the language picker on a
 * written page, and the links to the written sections on every other page.
 *
 * Those links are the reason this exists twice over. The glossary,
 * templates, notes and examples are thousands of pages and NOTHING on the
 * site linked to them -- they were reachable only from sitemap.xml, which
 * is the weakest form of discovery there is and leaves them orphaned for
 * ranking purposes. It is also how the language picker became invisible:
 * it lives on those pages, and there was no way to reach one.
 */
.lang-row,
.foot-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 4px 10px;
  margin-top: 14px;
  line-height: 1.7;
}
/* The fallback sits above the legal line, where the columns go. */
.foot-nav { margin-bottom: 14px; }
.lang-row a,
.foot-nav a { white-space: nowrap; }
.lang-row a:hover,
.foot-nav a:hover { color: var(--text); }

/*
 * The footer's columns: one per written section, its recent pages in it.
 *
 * The row above was the first attempt and it was not enough. Four words on
 * one line, in the footer's 12.5px muted grey, under a sentence about
 * LinkedIn affiliation -- the links were there and nobody saw them, which
 * the brief put plainly: "hardly even noticable".
 *
 * A column each, with real titles under it, is what a footer is for. It
 * also does the job the one-line row could not: a crawler arriving on any
 * page now has a dozen article URLs in front of it instead of four index
 * pages it has to decide to open.
 *
 * `text-align: start` rather than `left` -- `footer` centres everything,
 * and these have to un-centre in a way that still flips for Arabic.
 */
.foot-guides { margin-bottom: 26px; padding-bottom: 26px; border-bottom: 1px solid var(--border); }
.foot-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: 22px 28px;
  max-width: 1040px;
  margin: 0 auto;
  padding-bottom: 22px;
  text-align: start;
}
.foot-col h2 {
  margin: 0 0 10px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text);
}
.foot-col h2 a { color: inherit; text-decoration: none; }
.foot-col h2 a:hover { text-decoration: underline; }
.foot-col ul { list-style: none; margin: 0; padding: 0; }
.foot-col li { margin: 0 0 6px; line-height: 1.45; }
/*
 * Titles wrap rather than being cut off. A truncated one is a link whose
 * destination the reader cannot tell apart from its neighbour, and these
 * are generated titles that frequently share a first three words.
 */
.foot-col a { text-decoration: none; }
.foot-col a:hover { text-decoration: underline; color: var(--text); }
.foot-all { display: inline-block; margin-top: 8px; font-weight: 500; }

/*
 * Right-to-left, for the languages that are written that way.
 *
 * Only the rules the translated pages actually use -- the written pages,
 * the funnel, and the account and dashboard screens. A blanket flip of the
 * whole stylesheet would reach the reference pages, which are not
 * translated and would be flipped for nothing -- and the rules below are
 * the ones whose left/right is decoration rather than meaning. Code is
 * NOT one of them: a curl command reads left-to-right in every language,
 * so `pre` and inline code are pinned back.
 *
 * A field that holds an identifier -- an email, a URL, a key, a host --
 * carries `dir="auto"` in the markup instead of a rule here: empty or Latin,
 * it lays out left-to-right, so `price_…` does not render as `…price_`.
 *
 * Inline code needs `unicode-bidi: isolate` as well. On an inline element
 * `direction` does nothing by itself, so `direction: ltr` alone left a
 * header like `t=<seconds>,v1=<hex>` to the surrounding Arabic, which
 * reorders its punctuation.
 */
[dir="rtl"] .callout {
  border-left: 1px solid var(--border);
  border-right: 3px solid var(--muted);
}
[dir="rtl"] .callout.info { border-right-color: var(--blue); border-left-color: var(--border); }
[dir="rtl"] .callout.warn { border-right-color: var(--warn); border-left-color: var(--border); }
[dir="rtl"] .callout.danger { border-right-color: var(--danger); border-left-color: var(--border); }
[dir="rtl"] .callout.ok { border-right-color: var(--ok); border-left-color: var(--border); }
[dir="rtl"] .plain-list { padding-left: 0; padding-right: 18px; }
[dir="rtl"] .skip-link { left: auto; right: -9999px; }
[dir="rtl"] .skip-link:focus { left: auto; right: 8px; }
/* The numbered steps -- the dashboard's four, the landing page's "how it
 * starts" -- draw their disc and rule on the side a reader starts from. */
[dir="rtl"] .steps > li {
  padding: 0 38px 20px 0;
  border-left: 0;
  border-right: 1px solid var(--border);
  margin-left: 0;
  margin-right: 13px;
}
[dir="rtl"] .steps > li:last-child { border-right-color: transparent; }
[dir="rtl"] .steps > li::before { left: auto; right: -13px; }
[dir="rtl"] .howto { padding-left: 0; padding-right: 20px; }
/* The dialog's × sits in the corner the title does not start from. */
[dir="rtl"] .modal-dismiss { right: auto; left: 10px; }
[dir="rtl"] pre { direction: ltr; text-align: left; }
[dir="rtl"] code.inline { direction: ltr; unicode-bidi: isolate; }

/* ------------------------------------------------- header tools (right) -- */

/*
 * Language and theme, in the corner of the header.
 *
 * The footer keeps its language row. These are not two copies of one
 * control: this one is for the reader who has just arrived and is reading
 * the wrong language, and that one is for the reader who got to the bottom
 * -- and on a written page that does not exist in every language, the
 * footer row is the only one of the two that can say so.
 *
 * They carry no `data-brand-hide`: brand.js strips MakeHybrid's own
 * promotional furniture from a white-labelled page, and these are not
 * that. A customer's own customers still need to read in their language.
 */
.header-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-inline-start: auto;
}

/*
 * A <details> rather than a <select>: the list is real links, so a crawler
 * follows them and a reader can open one in a new tab. The cost is having
 * to position the panel, which is all the rest of this block is.
 */
.lang-menu { position: relative; }

.lang-menu > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 9px;
  border: 1px solid var(--border);
  border-radius: 7px;
  font-size: 12.5px;
  color: var(--text-soft);
  background: var(--card);
  white-space: nowrap;
}
/* Safari still paints its own triangle without this. */
.lang-menu > summary::-webkit-details-marker { display: none; }

.lang-menu > summary::after {
  content: "";
  width: 0;
  height: 0;
  border-inline: 3.5px solid transparent;
  border-top: 4px solid currentColor;
  opacity: .65;
}
.lang-menu > summary:hover { color: var(--text); border-color: var(--border-strong); }
.lang-menu[open] > summary::after { transform: rotate(180deg); }

.lang-menu-list {
  position: absolute;
  /* `inset-inline-end` rather than `right` so it flips for Arabic. */
  inset-inline-end: 0;
  top: calc(100% + 6px);
  z-index: 50;
  display: grid;
  /*
   * Seventeen languages is too many for one column on a laptop and far
   * too many for a phone, so it wraps into however many fit and scrolls
   * only if it still cannot.
   */
  grid-template-columns: repeat(2, minmax(104px, 1fr));
  gap: 1px 10px;
  max-height: min(64vh, 420px);
  overflow-y: auto;
  padding: 8px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 9px;
  box-shadow: var(--shadow-lg);
}

.lang-menu-list a {
  padding: 5px 7px;
  border-radius: 5px;
  font-size: 12.5px;
  color: var(--text-soft);
  white-space: nowrap;
}
.lang-menu-list a:hover { background: var(--bg-sunken); color: var(--text); }

/*
 * One icon button, at the right end of the header. It shows the mode in
 * force and a press moves to the next one; its label says the mode in
 * words. The picture is chosen here, from `data-theme` on <html> --
 * which THEME_BOOT sets before the first paint -- rather than by a
 * script, so the icon is never the wrong one for a moment.
 *
 * Quiet, not accented. --blue belongs to the one thing in the header a
 * reader is being asked to press; a theme control wearing it competes
 * with the trial button beside it, and the loudest thing on the page
 * ends up being the one that changes the least.
 */
.theme-toggle {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--card);
  color: var(--text-soft);
  cursor: pointer;
  flex: none;
}
.theme-toggle:hover { color: var(--text); border-color: var(--border-strong); background: var(--bg-sunken); }
.theme-toggle .theme-icon { display: none; }
:root:not([data-theme="light"]):not([data-theme="dark"]) .theme-toggle .theme-icon[data-mode="system"],
:root[data-theme="light"] .theme-toggle .theme-icon[data-mode="light"],
:root[data-theme="dark"] .theme-toggle .theme-icon[data-mode="dark"] { display: block; }
@media (pointer: coarse) {
  .theme-toggle { width: 44px; height: 44px; }
}

/*
 * The header is the one row on the page with no slack in it. On a phone
 * the nav already wraps; the language menu tightens, and the theme
 * button, one icon wide, stays.
 */
@media (max-width: 720px) {
  .lang-menu > summary { padding: 4px 7px; font-size: 12px; }
  .lang-menu-list { grid-template-columns: repeat(2, minmax(92px, 1fr)); }
}

/*
 * Hybrid Rooms: a chat app.
 *
 * Three columns under the header: the organization's rooms (and the keys
 * and servers every room shares) on the left, the conversation in the
 * middle, the open room's people, agents and settings on the right. The
 * conversation scrolls inside its column and the composer stays put under
 * it, the way every chat app a member already knows behaves. A column that
 * is hidden -- the left one for a guest, the right one before a room is
 * open -- gives its width back to the conversation.
 *
 * Under 960px the conversation has the screen, and each side column is a
 * drawer that opens over it from a button in the room's header.
 */
main.rooms-app {
  max-width: none;
  padding: 0;
  display: grid;
  grid-template-columns: 272px minmax(0, 1fr) 320px;
  /* --rooms-top is the header's real height, measured by rooms.js: on a
     phone the header wraps onto two lines and --header-h is `auto`. */
  height: calc(100dvh - var(--rooms-top, 58px));
  min-height: 420px;
}
main.rooms-app:has(> .rooms-left.hidden) { grid-template-columns: minmax(0, 1fr) 320px; }
main.rooms-app:has(> .rooms-right.hidden) { grid-template-columns: 272px minmax(0, 1fr); }
main.rooms-app:has(> .rooms-left.hidden):has(> .rooms-right.hidden) { grid-template-columns: minmax(0, 1fr); }

.rooms-side {
  min-height: 0;
  overflow-y: auto;
  padding: 12px 14px 16px;
  background: var(--card);
  border-right: 1px solid var(--border);
}
.rooms-right { border-right: 0; border-left: 1px solid var(--border); }
.rooms-side-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.rooms-title { font-size: 18px; margin: 0; }
.rooms-side-head h2 { font-size: 15px; margin: 0; }
.rooms-list { list-style: none; margin: 0 0 10px; padding: 0; }
.rooms-list a {
  display: block;
  padding: 7px 10px;
  border-radius: 8px;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rooms-list a:hover { background: var(--bg-sunken); }
.rooms-list a[aria-current] { background: var(--blue-soft); color: var(--blue); font-weight: 600; }
.rooms-inline { display: flex; gap: 8px; max-width: none; margin: 0 0 14px; }
.rooms-inline input { flex: 1; min-width: 0; }
.rooms-panel { border-top: 1px solid var(--border); padding: 6px 0 5px; }
.rooms-panel.rooms-first { border-top: 0; padding-top: 0; }
.rooms-panel > summary, .rooms-panel-title { cursor: pointer; font-weight: 600; font-size: 13.5px; color: var(--text); margin: 0; }
.rooms-panel-title { cursor: default; }
.rooms-panel[open] > summary { margin-bottom: 4px; }
.rooms-panel form { max-width: none; }

/*
 * The side columns are dense on purpose: a member should see every panel
 * of a room, open, without scrolling a 900-pixel window. So the controls
 * here are a size smaller than a form page's, related fields share a row,
 * and each panel says what it is for in one short line, not a paragraph.
 */
.rooms-side form, .rooms-form { display: flex; flex-direction: column; gap: 5px; margin: 0; }
.rooms-side form.rooms-inline { flex-direction: row; }
.rooms-side label:not(.check), .rooms-side legend { font-size: 11.5px; margin: 0; padding: 0; }
.rooms-side input, .rooms-side select, .rooms-side textarea { padding: 4px 7px; font-size: 12.5px; line-height: 1.35; }
.rooms-side textarea.prose { min-height: 0; font-size: 12.5px; line-height: 1.35; }
.rooms-side button { padding: 4px 10px; font-size: 12.5px; line-height: 1.35; }
.rooms-side .rooms-list a { padding: 5px 10px; }
.rooms-side .btn-row { gap: 6px; }
.rooms-side .check { padding: 0; gap: 7px; font-size: 12.5px; line-height: 1.35; align-items: flex-start; }
.rooms-side .check input { margin-top: 2px; }
.rooms-side fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.rooms-field { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rooms-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6px; }
/* A select whose choices are words, not values, keeps its own width rather than cutting them off. */
.rooms-pair.select-first { grid-template-columns: minmax(0, max-content) minmax(6em, 1fr); }
.rooms-pair.select-last { grid-template-columns: minmax(7em, 1fr) minmax(0, max-content); }
.rooms-checks { display: flex; flex-wrap: wrap; gap: 0 12px; }
.rooms-note { margin: 0 0 4px; font-size: 12px; line-height: 1.35; color: var(--muted); }
.rooms-rows { list-style: none; margin: 0 0 6px; padding: 0; font-size: 12.5px; color: var(--text-soft); }
.rooms-rows li { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 2px 0; min-width: 0; }
.rooms-rows li > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rooms-rows button { padding: 1px 6px; font-size: 12px; }
/* A row's button keeps its width: squeezed, a CJK label wraps one character per line. */
.rooms-rows button, .rooms-connect button { flex: none; white-space: nowrap; }
.rooms-connect { border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px; margin: 0 0 8px; font-size: 12.5px; }
.rooms-connect-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rooms-connect .rooms-note { margin: 3px 0 0; }

/* The built-in agents: one chip per @handle, so fourteen fit in five short rows. */
.rooms-chips { display: flex; flex-wrap: wrap; gap: 3px; margin: 0 0 5px; }
.room-chip {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card);
  color: var(--text);
  font-size: 11px;
  font-weight: 500;
  line-height: 1.45;
}
.rooms-side button.room-chip { padding: 1px 6px; font-size: 11px; font-weight: 500; line-height: 1.45; }
button.room-chip:hover { background: var(--bg-sunken); }
.room-chip[aria-pressed="true"] { border-color: color-mix(in srgb, var(--blue) 45%, var(--border-strong)); background: var(--blue-soft); color: var(--blue); }
.room-chip[aria-pressed="false"] { color: var(--faint); text-decoration: line-through; }
.room-chip.needs-connect { border-style: dashed; }
.room-chip:disabled, .room-chip[aria-disabled="true"] { opacity: .55; text-decoration: line-through; cursor: default; }

.rooms-center { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.rooms-center > .callout { margin: 12px 18px 0; }
.rooms-empty { margin: auto; max-width: 560px; padding: 40px 24px; text-align: center; }
.rooms-join { margin: 40px auto; width: calc(100% - 32px); max-width: 420px; }
.rooms-chat { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.rooms-chat-head { display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-bottom: 1px solid var(--border); }
.rooms-chat-title { flex: 1; min-width: 0; }
.rooms-chat-title h2 { font-size: 17px; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The installed app's two buttons: beside the title on a wide screen, on a line of their own on a phone. */
.rooms-chat-head #installApp, .rooms-chat-head #pushToggle { width: auto; flex: none; }
@media (max-width: 600px) {
  .rooms-chat-head { flex-wrap: wrap; row-gap: 8px; }
  .rooms-chat-head .rooms-chat-title { min-width: 45%; }
  .rooms-chat-head #installApp, .rooms-chat-head #pushToggle { order: 10; flex: 1 1 40%; padding: 6px 11px; font-size: 13px; }
}

/* A conversation, so it reads like one: each message a block with who said
   it above what they said, the room's own notices quieter than people.
   `pre-wrap` because a message's line breaks are the writer's, and an
   agent's numbered list is lines. */
.room-messages { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 18px; }
.room-msg { max-width: 820px; margin: 0 auto; padding: 9px 0; border-bottom: 1px solid var(--border); }
.room-msg:last-child { border-bottom: 0; }
.room-msg-who { font-size: 12.5px; color: var(--text-soft); margin-bottom: 2px; }
.room-msg-who b { color: var(--text); }
.room-msg-text { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.55; }
.room-msg.is-system .room-msg-text { color: var(--text-soft); font-size: 13px; font-style: italic; }
.room-msg.is-ai .room-msg-who b { color: var(--blue); }
.rooms-typing { margin: 0; padding: 0 18px; min-height: 18px; }
form.room-composer {
  display: flex;
  flex-direction: row;
  gap: 10px;
  align-items: flex-end;
  max-width: none;
  margin: 0;
  padding: 10px 18px 4px;
  border-top: 1px solid var(--border);
}
.room-composer textarea { flex: 1; min-height: 46px; max-height: 220px; margin: 0; }

/* @ in the composer: the room's agents in a list just above it. */
form.room-composer { position: relative; }
.room-mentions {
  position: absolute;
  inset-inline-start: 18px;
  bottom: calc(100% + 4px);
  width: min(380px, calc(100% - 36px));
  max-height: 268px;
  overflow-y: auto;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--card);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-lg);
  z-index: 20;
}
.room-mentions li { padding: 5px 8px; border-radius: 6px; cursor: pointer; min-width: 0; }
.room-mentions li[aria-selected="true"] { background: var(--blue-soft); }
.room-mention-who { font-size: 13px; color: var(--text); }
.room-mention-who b { color: var(--blue); font-weight: 600; }
.room-mention-about { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* An @agent's card: what it does, whether it answers here, and where to read more. */
.room-card {
  position: fixed;
  z-index: 70;
  width: 280px;
  max-width: calc(100vw - 16px);
  padding: 10px 12px;
  background: var(--card);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-lg);
  font-size: 12.5px;
  line-height: 1.45;
}
.room-card-head { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; margin-bottom: 2px; }
.room-card-head b { font-size: 13.5px; color: var(--text); }
.room-card-head span { color: var(--blue); }
.room-card-meta { color: var(--muted); font-size: 11.5px; margin: 0 0 6px; }
.room-card p { margin: 0 0 6px; color: var(--text-soft); }
.room-card .room-card-quote { white-space: pre-wrap; font-style: italic; }
.room-card .room-card-warn { color: var(--warn, var(--text-soft)); }
.room-card a { font-size: 12px; overflow-wrap: anywhere; }
.room-card > :last-child { margin-bottom: 0; }
.rooms-hint { margin: 0; padding: 0 18px 12px; }

/* The buttons that open and close a drawer exist only where there are drawers. */
.rooms-close, .rooms-open-left, .rooms-chat-head [data-open="right"] { display: none; }
.rooms-drawer-head { display: none; }

@media (max-width: 960px) {
  main.rooms-app,
  main.rooms-app:has(> .rooms-left.hidden),
  main.rooms-app:has(> .rooms-right.hidden) { grid-template-columns: minmax(0, 1fr); }
  /* Over the header too, so the drawer's own Close is always on screen. */
  .rooms-side {
    position: fixed;
    top: 0;
    bottom: 0;
    width: min(340px, 88vw);
    z-index: 60;
    box-shadow: var(--shadow-lg);
    transition: transform .18s ease;
  }
  .rooms-left { left: 0; transform: translateX(-105%); }
  .rooms-right { right: 0; transform: translateX(105%); }
  main.show-left .rooms-left,
  main.show-right .rooms-right { transform: none; }
  .rooms-close, .rooms-open-left, .rooms-chat-head [data-open="right"] { display: inline-flex; }
  .rooms-drawer-head { display: flex; justify-content: flex-end; }
}

/* A token or an invite link is one long word: wrap it rather than cut it off. */
.room-token { white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-all; }
/*
 * A callout straight after a list of steps. The last step has no bottom
 * padding of its own, so without this the callout sat against the step's
 * last line and read as part of it.
 */
.steps + .callout { margin-top: 28px; }

/* White-label settings: the done-for-you prices, a step apart from the choice above them. */
#readyPrices { margin-top: 12px; }

/* Hybrid Rooms settings: a dialog over the rooms, presets first, then every number they set. */
.rooms-side-head .rooms-settings-open { padding: 3px 9px; font-size: 12px; margin-inline-start: auto; }
dialog.rooms-dialog {
  width: min(640px, calc(100vw - 24px));
  max-height: calc(100dvh - 32px);
  padding: 20px 22px;
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  background: var(--card);
  color: var(--text);
  box-shadow: var(--shadow-lg);
}
dialog.rooms-dialog::backdrop { background: rgba(16, 20, 27, .45); }
form.rooms-settings { max-width: none; gap: 12px; }
.rooms-settings h2 { font-size: 18px; margin: 0; }
.rooms-presets { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 8px; }
.rooms-preset {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 0;
  padding: 9px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  font-weight: 400;
  font-size: 12px;
  color: var(--text-soft);
  cursor: pointer;
}
.rooms-preset b { font-size: 13.5px; color: var(--text); }
.rooms-preset input { position: absolute; opacity: 0; pointer-events: none; }
.rooms-preset:has(input:checked) { border-color: var(--blue); background: var(--blue-soft); }
.rooms-preset:has(input:focus-visible) { outline: 2px solid var(--blue); outline-offset: 2px; }
fieldset.rooms-set { border: 1px solid var(--border); border-radius: 10px; margin: 0; padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 8px; }
fieldset.rooms-set legend { font-weight: 600; font-size: 13.5px; color: var(--text); padding: 0 4px; }
/* The white-label page's ready-made products: each one's mark beside its name. */
fieldset.rooms-set legend .muted { font-weight: 400; }
.ready-logo { width: 20px; height: 20px; border-radius: 5px; vertical-align: -5px; margin-right: 4px; }

/* The white-label page's assistant: a short conversation above the full form. */
.wl-assistant { margin-bottom: 18px; }
.wl-chat { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 6px; max-height: 360px; overflow-y: auto; }
.wl-msg { max-width: 88%; padding: 8px 12px; border-radius: 12px; line-height: 1.45; overflow-wrap: anywhere; }
.wl-bot { align-self: flex-start; background: var(--bg-sunken); color: var(--text); border-bottom-left-radius: 4px; }
.wl-me { align-self: flex-end; background: var(--blue-soft); color: var(--text); border: 1px solid var(--blue-line); border-bottom-right-radius: 4px; }
.wl-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 4px; border: 1px solid var(--border-strong); vertical-align: -2px; margin-right: 6px; }
.wl-logo-preview { width: 32px; height: 32px; border-radius: 6px; object-fit: contain; vertical-align: middle; margin-right: 8px; background: var(--card); border: 1px solid var(--border); }
.wl-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.wl-chips:empty { display: none; }
.wl-assistant form.wl-ask { display: flex; flex-direction: row; align-items: stretch; gap: 8px; max-width: none; margin: 0; }
.wl-ask input { flex: 1; min-width: 0; margin: 0; }
.wl-assistant .wl-ask button { width: auto; flex: none; }
.wl-all > summary { cursor: pointer; font-weight: 600; margin: 0 0 12px; }
.rooms-set-row { display: grid; grid-template-columns: minmax(0, 1fr) 220px; gap: 10px; align-items: center; }
.rooms-set-row label { margin: 0; font-size: 13px; font-weight: 500; color: var(--text); }
.rooms-set-row input, .rooms-set-row select { padding: 5px 8px; font-size: 13px; }
.rooms-unit { display: block; font-size: 11.5px; font-weight: 400; color: var(--muted); }
.rooms-usage { list-style: none; margin: 0; padding: 0; font-size: 12px; color: var(--muted); }
.rooms-set-actions { justify-content: flex-end; }
@media (max-width: 560px) {
  .rooms-set-row { grid-template-columns: minmax(0, 1fr); gap: 3px; }
}

/* A mention held for a member, above the composer. */
.room-handoffs { display: flex; flex-direction: column; gap: 6px; padding: 8px 18px 0; }
.room-handoff {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid color-mix(in srgb, var(--blue) 35%, var(--border));
  border-radius: 10px;
  background: var(--blue-soft);
  font-size: 13px;
}
.room-handoff span { flex: 1; min-width: 12em; }
.room-handoff button { padding: 4px 10px; font-size: 12.5px; }

/* White-label settings: a Google Ads ID beside its button, a customer picker beside the ID. */
.btn-row .gads-cid { width: 15ch; flex: none; font-family: var(--mono); }
.btn-row .gads-org { width: auto; flex: 1 1 14em; min-width: 0; }
#gadsStep .row .badge { margin-inline-start: 6px; }
#gadsStep h3 { margin-top: 20px; }
/* Admin: a partner's Google Ads link request, with the note staff leave for it. */
[data-gads] > div:first-child { flex: 1 1 18em; min-width: 0; }
[data-gads] input { margin-top: 6px; padding: 6px 9px; }
/* A Google Ads change an agent proposed: amber, because applying it changes a live account. */
.room-change { border-color: color-mix(in srgb, var(--warn) 40%, var(--border)); background: var(--warn-soft); }
.room-change details { flex-basis: 100%; font-size: 12.5px; }
.room-change summary { cursor: pointer; color: var(--muted); }
.room-change pre { max-height: 180px; overflow: auto; margin: 6px 0 0; padding: 8px; background: var(--card); border-radius: 8px; font-size: 12px; white-space: pre-wrap; word-break: break-word; }
/* From the account to the customer, in the direction the line reads. */
.gads-arrow { display: inline-block; }
[dir="rtl"] .gads-arrow { transform: scaleX(-1); }

/* Guides: a page's questions, each a heading a reader can scan for, its answer under it. */
.faq h3 { margin: 18px 0 4px; font-size: 16px; }
.faq h3:first-child { margin-top: 6px; }
.faq p { margin-top: 0; }

/*
 * The Hybrid Rooms landing page's example room: the room's own classes
 * (.rooms-chat-head, .room-msg, .room-handoff), in a frame of its own,
 * at a reading width rather than the app's full-height columns. Nothing
 * in it can be pressed, so its "buttons" are spans dressed as buttons.
 */
.rooms-preview { margin: 0; }
.rooms-preview-frame {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.rooms-preview .rooms-chat-title h3 { font-size: 16px; margin: 0; }
.rooms-preview .room-messages { overflow: visible; }
.rooms-preview .room-handoff { max-width: 820px; margin: 10px auto 0; }
.rooms-preview .room-handoff .rooms-preview-btn { flex: none; min-width: 0; }
.rooms-preview-btn {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border: 1px solid var(--blue);
  border-radius: var(--radius-sm);
  background: var(--blue);
  color: #fff;
  font-size: 12.5px;
  font-weight: 600;
}
.rooms-preview-btn.secondary { background: var(--card); color: var(--text); border-color: var(--border-strong); }
.rooms-preview-composer {
  margin: 0 18px 14px;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: 13.5px;
}
.rooms-preview figcaption { margin-top: 8px; }

/* A room's tabs: its conversation, and the work beside it. */
.rooms-tabs { padding: 8px 18px 0; }
.rooms-tab { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.rooms-work { overflow-y: auto; padding: 12px 18px; gap: 10px; }
.rooms-work .rooms-rows { font-size: 13.5px; }
.rooms-tasks li { align-items: flex-start; padding: 6px 0; border-bottom: 1px solid var(--border); }
.rooms-tasks li > div { flex: 1; min-width: 0; }
.rooms-tasks li.is-done b { text-decoration: line-through; color: var(--muted); }
.rooms-tasks select { flex: none; width: auto; padding: 2px 6px; font-size: 12.5px; }
.rooms-rows li:has(.rooms-error) { flex-wrap: wrap; }
.rooms-error { flex-basis: 100%; color: var(--danger); }
.rooms-qr { display: block; width: 220px; height: 220px; margin: 8px auto 0; background: #fff; padding: 6px; border-radius: 8px; }

/* ------------------------------------------------------ builders' group -- */

/*
 * The builders' group on the landing page: what it is on the left, the
 * join form on the right.
 *
 * `form` caps at 380px for the auth card, so in this card's right column
 * every field stopped ~130px short of the card's edge while the copy on
 * the left ran the full width of its own. And `.option-grid` starts both
 * columns at the top and leaves each as tall as its content, so the copy
 * ended half way down a card the form filled. The columns now stretch,
 * the form fills its column, and the founder's line is pushed to the foot
 * of the copy, level with the submit button beside it. Where the copy is
 * the taller column, the textarea takes up the difference, so the two
 * buttons still end on one line.
 *
 * Two columns from a fixed width rather than `auto-fit`, so the stacked
 * layout -- where the founder's line needs a rule under it as well, or the
 * form's first label reads as its caption -- has a breakpoint to hang on.
 */
.community-grid { grid-template-columns: 1fr; align-items: stretch; }
@media (min-width: 721px) {
  .community-grid { grid-template-columns: 1fr 1fr; }
}
.community-grid form { max-width: none; }
.community-grid textarea { flex: 1 0 auto; }
.community-copy { display: flex; flex-direction: column; }
/* An empty status line kept the form's 12px gap and its own 12px margin,
   so "Ask to join" sat 36px under the textarea where every other gap is
   12. Out of the flow rather than `display: none` like `.error:empty`: a
   polite live region that is not in the tree when its text arrives is not
   reliably announced, where role="alert" is. */
.community-grid .ok-text:empty { position: absolute; margin: 0; }

.founder {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.founder-photo { width: 40px; height: 40px; border-radius: 50%; flex: none; object-fit: cover; }
.founder-who { flex: 1 1 140px; min-width: 0; margin: 0; font-size: 13.5px; line-height: 1.35; }
.founder-who b { display: block; color: var(--text); }
.founder-who span { color: var(--muted); }
.founder-cta { flex: none; gap: 8px; }
.founder-cta svg { flex: none; }
@media (max-width: 720px) {
  .founder { padding-bottom: 16px; border-bottom: 1px solid var(--border); }
}
