:root {
  /**
   * Near neutral surfaces, one accent, hairline borders.
   *
   * The old palette tinted every surface purple and used a vivid magenta as a
   * background, which is the look that reads as generated: colour everywhere
   * and nothing earning it. This keeps the brand hue but spends it only on the
   * things you can interact with, and lets the greys be grey.
   */
  --bg: #0e0f13;
  --surface: #15171c;
  --surface-2: #1b1e24;
  --surface-3: #22262d;
  /* Hairlines. A border should separate, not draw attention to itself. */
  --border: #262a32;
  --border-soft: #1d2027;
  --text: #dfe3ea;
  --muted: #99a1ae;
  --faint: #6d7480;
  /* One accent, muted enough to sit next to text without shouting. */
  --accent: #8f7ae0;
  --accent-soft: #7563bd;
  --accent-dim: rgba(143, 122, 224, 0.1);
  --danger: #d95c63;
  /* Matches COLORS.warn in core/theme.js, so a warning looks the same whether
     it arrives in Discord or in the browser. Same for danger and the accent. */
  --warn: #d9a03c;
  --ok: #43c476;
  --radius: 8px;
  --radius-sm: 6px;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  min-height: 100%;
}

body {
  /* Flat. Two purple radial washes bleeding out of the corners is the single
     most recognisable "generated landing page" signature there is, and they
     were doing nothing but tinting the page. */
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 "Segoe UI", system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}

button,
input,
select {
  font: inherit;
  color: inherit;
}

/* ---------------------------------------------------------------- shell -- */

.boot {
  display: grid;
  place-items: center;
  min-height: 100vh;
  color: var(--faint);
  letter-spacing: 0.04em;
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 24px;
  height: 60px;
  background: rgba(13, 10, 18, 0.86);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border-soft);
}

/* A button now, since it goes home. Stripped back to looking like text. */
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 650;
  letter-spacing: -0.01em;
  background: none;
  border: 0;
  padding: 0;
  color: var(--text);
  font-size: inherit;
  font-family: inherit;
  cursor: pointer;
}

.brand:hover {
  color: var(--accent);
}

/* Unscoped, because the login card uses the same mark as the header. */
.dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  /* A dot, not a light source. The glow was the other half of the same tell. */
  background: var(--accent);
}

.topbar .spacer {
  flex: 1;
}

.who {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--muted);
  font-size: 13.5px;
}

.who img {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--border);
}

.layout {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  gap: 28px;
  max-width: 1120px;
  margin: 0 auto;
  padding: 28px 24px 72px;
}

@media (max-width: 780px) {
  .layout {
    grid-template-columns: 1fr;
    gap: 18px;
  }
}

/* ----------------------------------------------------------------- nav -- */

/**
 * The nav scrolls itself, not the page.
 *
 * It was sticky but unbounded, so a catalogue of eighteen features made the nav
 * taller than the window and the whole page grew to fit it. Scrolling down the
 * list and clicking something near the top then redrew the content at the top
 * of a page you were still parked at the bottom of, which read as the tab
 * loading wrong.
 */
.nav {
  display: flex;
  flex-direction: column;
  gap: 0;
  align-self: start;
  position: sticky;
  top: 84px;
  max-height: calc(100vh - 108px);
  overflow-y: auto;
  /* Room for its own scrollbar so the items do not sit under it. */
  padding-right: 6px;
  scrollbar-width: thin;
}

@media (max-width: 820px) {
  /* Stacked on a phone, where a scrollable side rail makes no sense. */
  .layout {
    grid-template-columns: 1fr;
    gap: 18px;
  }

  .nav {
    position: static;
    max-height: none;
    overflow: visible;
  }
}

.nav h2 {
  margin: 0 0 8px 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--faint);
}

.nav button {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 10px;
  border: 0;
  font-size: 13.5px;
  line-height: 1.45;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  text-align: left;
  cursor: pointer;
  transition: background 0.13s, color 0.13s;
}

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

/* Selected is one signal: the tinted row. It used to be the tint AND an accent
   bar down the left edge, and two markers for one state reads as a stray
   element rather than a deliberate one. Hover is the plain surface, so the two
   never look alike. */

.nav button[aria-current="true"] {
  background: var(--accent-dim);
  color: var(--text);
  font-weight: 600;
}

/* A feature the server hasn't bought. Shown, not hidden, because the settings
   screen is where people find out a feature exists at all. */

.nav-lock {
  margin-left: auto;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--faint);
  font-size: 11px;
  letter-spacing: 0.02em;
}

/* A feature that can't run. Amber rather than red, because nothing is broken,
   something is just missing and it's usually one click away. */

.nav-warn {
  display: inline-grid;
  place-items: center;
  width: 17px;
  height: 17px;
  margin-left: auto;
  border-radius: 50%;
  background: var(--warn);
  color: #1a1206;
  font-size: 11px;
  font-weight: 700;
}

.health-banner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 18px;
  padding: 14px 16px;
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  background: rgba(245, 158, 11, 0.09);
}

.health-banner ul {
  margin: 0;
  padding-left: 18px;
  color: var(--muted);
  font-size: 13px;
}

.health-banner li + li {
  margin-top: 3px;
}

.locked-banner {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 18px;
  padding: 13px 16px;
  border: 1px solid var(--accent-soft);
  border-radius: var(--radius);
  background: var(--accent-dim);
}

.locked-banner span {
  color: var(--muted);
  font-size: 13px;
}

.host-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border-soft);
}

.locked-settings {
  /* Readable, obviously not usable, and impossible to click by accident. The
     API refuses these writes as well, this is only the half a person sees. */
  opacity: 0.5;
  pointer-events: none;
  user-select: none;
}

/* --------------------------------------------------------------- cards -- */

.panel-head {
  margin-bottom: 20px;
}

.panel-head h1 {
  margin: 0 0 4px;
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -0.02em;
}

.panel-head p {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}

.setting {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px 24px;
  align-items: center;
  padding: 14px 16px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: 10px;
  transition: border-color 0.15s;
}

.setting:hover {
  border-color: var(--border);
}

.setting.stacked {
  grid-template-columns: minmax(0, 1fr);
}

.setting .label {
  font-weight: 550;
}

.setting .hint {
  margin-top: 2px;
  color: var(--muted);
  font-size: 13px;
}

.setting .control {
  justify-self: end;
}

.setting.stacked .control {
  justify-self: stretch;
  width: 100%;
}

.saved {
  display: inline-block;
  margin-left: 8px;
  color: var(--accent);
  font-size: 12px;
  opacity: 0;
  transition: opacity 0.2s;
}

.saved.show {
  opacity: 1;
}

.usage {
  margin-top: 22px;
  padding: 13px 18px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--muted);
  font-size: 13px;
}

.usage-allowance {
  margin-top: 4px;
  opacity: 0.75;
}

/* ------------------------------------------------------------ controls -- */

.switch {
  position: relative;
  width: 46px;
  height: 26px;
  border: 0;
  padding: 0;
  border-radius: 999px;
  background: var(--surface-3);
  cursor: pointer;
  transition: background 0.18s;
}

.switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #b6a9cc;
  transition: transform 0.18s, background 0.18s;
}

.switch[aria-checked="true"] {
  background: var(--accent);
}

.switch[aria-checked="true"]::after {
  transform: translateX(20px);
  background: #fff;
}

select,
input[type="text"],
input[type="number"] {
  min-width: 190px;
  padding: 8px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  outline: none;
  transition: border-color 0.14s, box-shadow 0.14s;
}

select:focus,
input:focus {
  border-color: var(--accent-soft);
  box-shadow: 0 0 0 3px var(--accent-dim);
}

input[type="number"] {
  min-width: 110px;
}

.picker {
  margin-top: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  overflow: hidden;
}

.picker .search {
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--border-soft);
  border-radius: 0;
  background: transparent;
  padding: 9px 12px;
}

.picker .search:focus {
  box-shadow: none;
  border-color: var(--border-soft);
}

.picker .list {
  max-height: 210px;
  overflow-y: auto;
  padding: 5px;
}

.picker .row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 9px;
  border-radius: 6px;
  cursor: pointer;
  color: var(--muted);
}

.picker .row:hover {
  background: var(--surface-3);
  color: var(--text);
}

.picker .row input {
  accent-color: var(--accent);
  margin: 0;
}

.picker .row.on {
  color: var(--text);
}

.picker .empty {
  padding: 14px;
  color: var(--faint);
  font-size: 13px;
  text-align: center;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.chip {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--accent-dim);
  border: 1px solid rgba(192, 38, 211, 0.32);
  color: #eabaf5;
  font-size: 12.5px;
}

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

.btn {
  display: inline-block;
  padding: 8px 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  cursor: pointer;
  /* The login button is an anchor, so kill the underline it inherits. */
  text-decoration: none;
  transition: background 0.14s, border-color 0.14s;
}

.btn:hover {
  background: var(--surface-3);
  border-color: var(--accent-soft);
}

.btn.ghost {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  padding: 6px 10px;
  font-size: 13px;
}

.btn.ghost:hover {
  color: var(--text);
  background: var(--surface-2);
}

.btn.primary {
  border: 0;
  background: var(--accent);
  color: #fff;
  font-weight: 550;
  padding: 11px 22px;
}

.btn.primary:hover {
  filter: brightness(1.09);
}

/* --------------------------------------------------------------- login -- */

.login {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 24px;
}

.login .card {
  width: min(440px, 100%);
  padding: 32px;
  border: 1px solid var(--border-soft);
  border-radius: 16px;
  background: var(--surface);
}

.login .mark {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 22px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.login h1 {
  margin: 0 0 8px;
  font-size: 23px;
  letter-spacing: -0.02em;
}

.login .lead {
  margin: 0 0 22px;
  color: var(--muted);
  font-size: 14px;
}

.login .note {
  margin: 16px 0 0;
  color: var(--muted);
  font-size: 13px;
}

.login .foot {
  margin: 20px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--border-soft);
  color: var(--faint);
  font-size: 12.5px;
}

.login .err {
  margin-bottom: 18px;
  padding: 9px 13px;
  border-radius: var(--radius-sm);
  background: rgba(225, 29, 72, 0.12);
  border: 1px solid rgba(225, 29, 72, 0.3);
  color: #ffa8bd;
  font-size: 13.5px;
}

/* ------------------------------------------------------------- picker -- */

/* The guild picker is a single narrow column, so the heading and the cards
   share one width instead of the heading running the full page. */
.narrow {
  max-width: 460px;
  margin: 0 auto;
}

.guilds {
  display: grid;
  gap: 9px;
  margin-top: 22px;
}

.guilds button {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 13px 16px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.14s, background 0.14s;
}

.guilds button:hover {
  border-color: var(--accent-soft);
  background: var(--surface-2);
}

.avatar {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--surface-3);
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  overflow: hidden;
  flex: none;
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.empty-state {
  max-width: 460px;
  margin: 40px auto;
  padding: 26px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--muted);
  text-align: center;
}

/* --------------------------------------------------------------- toast -- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translate(-50%, 14px);
  padding: 10px 18px;
  border-radius: 999px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  font-size: 13.5px;
  opacity: 0;
  transition: opacity 0.2s, transform 0.2s;
  pointer-events: none;
}

.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

.toast.bad {
  border-color: rgba(225, 29, 72, 0.5);
  color: #ffa8bd;
}

/* --------------------------------------------------------------- pages -- */

/* A records page: a table of rows a module owns, rather than a list of
   switches. Nothing in here knows what the records are. */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 18px;
}

.filter {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.02em;
}

.filter select,
.filter input {
  min-width: 200px;
  padding: 8px 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  outline: none;
}

.filter select:focus,
.filter input:focus {
  border-color: var(--accent-soft);
}

.page-body {
  /* The table sets its own width from its content, so on a narrow window it
     scrolls inside here instead of pushing the whole page sideways. */
  overflow-x: auto;
}

table.records {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

table.records th {
  padding: 0 12px 8px;
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
  white-space: nowrap;
}

table.records td {
  padding: 11px 12px;
  border-top: 1px solid var(--border-soft);
  vertical-align: top;
}

table.records tr:hover td {
  background: var(--surface);
}

table.records td.faint {
  color: var(--faint);
}

.cell-user {
  white-space: nowrap;
}

.cell-sub {
  margin-top: 2px;
  font-size: 11px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* Reasons are the one column that runs long, so it gets the slack and
   everything else stays on one line. */
.cell-long {
  min-width: 220px;
  max-width: 460px;
}

.badge {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  background: var(--surface-3);
  border: 1px solid var(--border);
}

.badge.bad {
  color: #ffb3c4;
  background: rgba(225, 29, 72, 0.14);
  border-color: rgba(225, 29, 72, 0.35);
}

.badge.warn {
  color: #f6cf87;
  background: rgba(245, 158, 11, 0.13);
  border-color: rgba(245, 158, 11, 0.32);
}

.badge.good {
  color: #d3b6ff;
  background: rgba(147, 51, 234, 0.16);
  border-color: rgba(147, 51, 234, 0.38);
}

.row-actions {
  white-space: nowrap;
  text-align: right;
}

.row-actions button {
  margin-left: 6px;
}

button.ghost {
  padding: 6px 11px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--muted);
  cursor: pointer;
}

button.ghost:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--accent-soft);
  background: var(--surface-2);
}

button.ghost:disabled {
  opacity: 0.4;
  cursor: default;
}

.pager {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border-soft);
}

.pager .hint {
  margin-right: auto;
}

/* The builder's running total. Sticks to the bottom of the plan screen so the
   number stays in view while somebody works down a long list of features. */
.plan-total {
  position: sticky;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  margin-top: 22px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
}

.plan-total strong {
  font-size: 19px;
}

/* The number and the sentence under it. Without this they are two inline
   elements with nothing between them, which is why the card read
   "No creditPays for AI features" and "£2.00 a month2 selected". */
.plan-figure {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.plan-figure .hint {
  line-height: 1.45;
}

.plan-buttons {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

.plan-reason {
  flex-basis: 100%;
}

/* A button that can't do anything has to look like it. The plan screen had a
   disabled Subscribe that was styled exactly like a working one, so it read as
   a click the panel had ignored. */
.btn:disabled,
button.primary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* What ticking this one would do to the bill. Quieter than the description
   until it's on, then it's the line that matters. */
.plan-effect {
  margin-top: 3px;
  color: var(--faint);
}

.plan-effect.on {
  color: var(--accent-soft);
}

/* A balance that has run out is the one number somebody needs to see, so it
   stops being a quiet grey line. */
.usage-empty {
  color: var(--warn);
}

.usage .btn {
  margin-top: 10px;
}

/* The warning settings, which are billing's rather than any feature's, so they
   sit under the balance on the plan screen instead of in a settings tab. */
.plan-warnings,
.plan-spend {
  margin-top: 26px;
}

.plan-warnings .panel-head,
.plan-spend .panel-head {
  margin-bottom: 14px;
}

.plan-warnings h2,
.plan-spend h2 {
  font-size: 17px;
  margin: 0 0 4px;
}

/* The privacy and terms pages. Plain documents rather than app screens, so they
   get their own narrow column and nothing else from the panel. */
.legal {
  max-width: 720px;
  margin: 0 auto;
  padding: 48px 22px 80px;
  line-height: 1.65;
}

.legal h1 {
  font-size: 30px;
  margin: 0 0 6px;
}

.legal h2 {
  font-size: 18px;
  margin: 34px 0 8px;
}

.legal p,
.legal li {
  color: var(--muted);
}

.legal strong {
  color: var(--text);
}

.legal ul {
  padding-left: 20px;
}

.legal li {
  margin-bottom: 8px;
}

.legal-date {
  color: var(--faint);
  font-size: 13px;
  margin-top: 0;
}

.legal-back {
  font-size: 14px;
}

/* The account page has no server nav beside it, so its column stands alone
   rather than leaving a gap where the sidebar would be. */
.layout.wide {
  display: block;
  max-width: 780px;
  margin: 0 auto;
}

/* The per-server spending ceiling on the account page. A number box rather than
   presets, since the right figure depends on what somebody is willing to lose
   to one server having a busy month. */
.cap-control {
  display: flex;
  align-items: center;
  gap: 6px;
}

.cap-control input {
  width: 88px;
  text-align: right;
}

/* The three lines that answer every question people ask about who pays. Set
   apart from the page rather than buried in a paragraph, because somebody
   confused is scanning rather than reading. */
.explainer {
  margin-bottom: 22px;
  padding: 14px 18px;
  border-left: 3px solid var(--accent-soft);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--muted);
  font-size: 14px;
  line-height: 1.7;
}

.explainer strong {
  display: block;
  margin-bottom: 4px;
  color: var(--text);
}

/* ---------------------------------------------------------- picking a plan */

/* Two across on a desktop, one on a phone. The plan screen was a single column
   of full width cards, which on a wide screen is an endless scroll with most of
   the room wasted, and the list only gets longer as the catalogue grows. */
.pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 12px;
  margin-bottom: 22px;
}

.pick {
  align-items: start;
  margin: 0;
}

/* What is on the plan reads at a glance, without a line of text per row that
   changes every time something else is ticked. */
.pick.on {
  border-color: var(--accent-soft);
  background: var(--accent-dim);
}

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

  .plan-total,
  .plan-figure {
    flex-direction: column;
    align-items: flex-start;
  }

  .plan-buttons {
    margin-left: 0;
    width: 100%;
  }

  .plan-buttons .btn {
    flex: 1;
  }
}

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

/* Channel and role pickers stay shut until asked for. What matters at rest is
   what is picked, not the whole list of things that could be. */
.picker-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.picker-toggle {
  flex: 0 0 auto;
  padding: 4px 12px;
  font-size: 13px;
}

.picker-field .picker {
  margin-top: 10px;
}

/* Settings sit two across on a wide screen. One column of full width rows is
   an endless scroll on a monitor and the list only grows with the catalogue. */
/* Dense, because a full-width picker dropped into a two column grid leaves the
   rest of its row empty and the page ends up half air. Dense pulls the next
   card that fits back into the hole, so the columns stay packed. */

.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  grid-auto-flow: dense;
  gap: 10px;
  /* Stretch, so two cards side by side end at the same line. Left to their own
     heights the bottom edge of every row came out ragged. */
  align-items: stretch;
}

/* The cards were built for a single column and carry their own bottom margin,
   which doubles up with the grid gap. */

.settings-grid .setting {
  margin-bottom: 0;
}

/* A picker takes the full width while it's open, because a searchable list of
   channels squeezed into half a column is worse than the scroll. Shut, it is a
   line of chips and a Change button, so it sits in one column like everything
   else instead of stretching a nearly empty card across the page. */

.settings-grid .setting.stacked:has(.picker:not([hidden])) {
  grid-column: 1 / -1;
}

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

/* ------------------------------------------------------------- nav groups */

/* A feature and its pages are one block with air around it, rather than
   eighteen identical rows where the only clue about what belongs to what was a
   hyphen that blended into the background. */

.nav-group {
  display: flex;
  flex-direction: column;
  margin-bottom: 5px;
}

/* The feature itself reads as the heading through colour and weight, its pages
   read as contents through being dimmer and smaller. No decoration doing the
   job that type can do on its own. */

.nav-feature {
  color: var(--text);
  font-weight: 500;
}

/* No rail, no dash, no marker of any kind.
 *
 * Both attempts at drawing the relationship failed for the same reason: nearly
 * every feature here has exactly one page, so any line or tick ends up as a
 * stray few pixels beside a single row and reads as something half rendered.
 * An indent and a dimmer, smaller label say "belongs to the thing above" on
 * their own, and a page sits tight under its feature while the features
 * themselves have air between them, so the grouping comes from the spacing. */

.nav-pages {
  display: flex;
  flex-direction: column;
  margin-left: 16px;
}

.nav .sub {
  font-size: 13px;
  font-weight: 400;
  color: var(--muted);
}

/* A heading that is not a destination. Only used by a feature with several
   pages and nothing to configure, so it never looks clickable. */
.nav-heading {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px 3px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
}

/* The phone version of the feature list.
 *
 * Stacked above the content, eighteen features push everything off the screen,
 * so on a narrow window the list hides behind one row naming where you are.
 * The button does not exist on a desktop, where the column is beside the
 * content and always useful. */

.nav .nav-toggle {
  display: none;
}

@media (max-width: 820px) {
  .nav .nav-toggle {
    display: flex;
    justify-content: space-between;
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-weight: 550;
    cursor: pointer;
  }

  .nav .nav-toggle:hover {
    background: var(--surface-2);
  }

  .nav-toggle-hint {
    color: var(--accent);
    font-weight: 400;
  }

  .nav h2 {
    display: none;
  }

  .nav:not(.nav-open) > .nav-group,
  .nav:not(.nav-open) > button:not(.nav-toggle) {
    display: none;
  }

  .nav.nav-open {
    gap: 2px;
  }
}
