/* c:\Code\21-prompt-manager\pocketbase\pb_public\assets\css\wired.css
   Wired editorial system — ported from 04-checklist so this app reads as
   sibling software the firm already trusts (masterplan §4.3).

   The rules that must not be negotiated away:
     warm paper ground; white only where you type or where the next action is
     square corners, hairline rules, softened ink
     EXACTLY ONE filled (--ink) element per screen
     one accent (--link), never two
     serif carries narrative, sans carries structure
     mobile-first, 44px minimum touch targets

   Everything below the "prompt manager" divider is new to this app and written
   in the same idiom: quiet boxes, hairline separation, no second accent. */

/* Lora, served from this origin. Google shipped one variable file covering the
   whole 400–700 range and declared 400/500/600 against it; declaring the range
   as 400–600 here reproduces exactly what the app rendered before, including
   the way a font-weight:700 serif falls back to 600.

   latin-ext is a separate file and its unicode-range means a browser only
   fetches it when a page actually contains one of those characters — an
   accented client name, a € sign. Only the latin file is precached. */
@font-face {
  font-family: "Lora";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/fonts/lora-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Lora";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/fonts/lora-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --ink: #1c1a17;
  --ink-soft: #3f3a33;
  --body: #3f3a33;
  --muted: #6b6459;
  --hairline: #ddd7ca;
  --border: #cfcabf;
  --canvas: #f5f2ec;          /* warm paper — the page ground */
  --canvas-soft: #ede9e0;
  --surface: #ffffff;         /* inputs + the card holding the next action */
  --link: #057dbc;            /* the only accent — never two per screen */
  /* Kind swatches. Not accents and not status: three matte pigments off the
     same warm ground, used ONLY as the 8–10px square that says what kind of
     thing a row is before the word does. Saturating any of them would put a
     second accent on the page. */
  --kind-prompt: #b5714f;     /* clay */
  --kind-cluster: #7d8c6f;    /* sage */
  --kind-session: #7b89a3;    /* dusty slate */
  --serif-display: "Lora", Georgia, "Times New Roman", serif;
  --serif-body: "Lora", Georgia, "Times New Roman", serif;
  --sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.5;
  min-height: 100vh;
}

/* ---------------------------------------------------------------- shell */
.wrap {
  width: 100%;
  max-width: 72rem;
  margin-inline: auto;
  padding-inline: 20px;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--canvas);
  border-bottom: 1px solid var(--hairline);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 3.75rem;
}
.site-header__inner.center { justify-content: center; }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--serif-display);
  font-size: 18px;
  font-weight: 500;
  line-height: 1;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.brand__mark {
  flex: none;
  width: 2rem;
  height: 2rem;
  object-fit: contain;
  opacity: 0.85;
}
.brand__suffix { font-weight: 500; color: var(--muted); }

.header-actions { display: flex; align-items: center; gap: 0.5rem; }
.header-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: -12px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  cursor: pointer;
  color: var(--ink-soft);
  text-decoration: none;
}
.header-back:hover { color: var(--link); }
.header-back:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.header-quiet-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 15px;
  color: var(--muted);
  text-decoration: none;
}
.header-quiet-link:hover { color: var(--ink); }

/* ONE measure, every page. 680px is a comfortable line length for the serif
   this system reads in; a page that widens to 72rem to hold a list of one-line
   rows just puts the content in the left third and leaves the rest empty. The
   few things genuinely wider than the column (a rendered markdown table, an
   assembled prompt) scroll inside their own box rather than widening the page. */
main { max-width: 680px; margin: 0 auto; padding: 32px 24px 96px; }

/* ------------------------------------------------------------ typography */
h1 {
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.12;
  letter-spacing: -0.5px;
  margin: 14px 0 0;
}
.prompt-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 14px 0 0;
}
.prompt-title-row h1 { margin: 0; flex: 1; min-width: 0; }
h2 { font-family: var(--serif-display); font-weight: 400; font-size: 26px; line-height: 1.15; margin: 12px 0 8px; }
h3 { font-family: var(--serif-body); font-weight: 400; font-size: 20px; line-height: 1.25; margin: 8px 0; }
.eyebrow {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.9px;
  color: var(--muted);
}
.lead { font-family: var(--serif-body); font-size: 19px; line-height: 1.6; color: var(--ink-soft); margin: 16px 0 0; }
.muted { color: var(--muted); font-size: 15px; }
.small { font-size: 14px; }
a { color: var(--link); }
a:hover { color: var(--ink); }
code, .mono { font-family: var(--mono); font-size: 0.92em; }

/* -------------------------------------------------------------- buttons */
.btn, .btn-outline, .btn-quiet {
  display: inline-block;
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: none;
  margin: 0;
  padding: 12px 20px;
  border-radius: 0;               /* square corners are non-negotiable */
  border: 1px solid var(--ink);
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  min-height: 44px;
  background: var(--ink);
  color: var(--surface);
}
.btn-outline { background: var(--surface); color: var(--ink); }
.btn-quiet { background: transparent; color: var(--ink); border-color: var(--border); font-weight: 400; }
.btn:hover, .btn:focus-visible { color: var(--surface); }
.btn-outline:hover, .btn-outline:focus-visible { color: var(--ink); }
.btn-quiet:hover, .btn-quiet:focus-visible { color: var(--ink); border-color: var(--ink); }
.btn:disabled, .btn-outline:disabled, .btn-quiet:disabled { opacity: 0.35; cursor: default; }
.btn-block { display: block; width: 100%; }
.btn-lg { font-size: 18px; padding: 18px 20px; min-height: 58px; }
.btn-sm { font-size: 14px; padding: 10px 14px; min-height: 44px; font-weight: 400; }

.action-bar {
  position: sticky;
  bottom: 0;
  background: var(--canvas);
  margin-top: 40px;
  padding: 18px 0 22px;
  border-top: 1px solid var(--hairline);
  z-index: 20;
}
main > div:has(+ .action-bar) + .action-bar { border-top: 0; }
.action-link { text-align: center; margin: 16px 0 0; font-size: 16px; }
.action-hint { text-align: center; margin: 12px 0 0; font-size: 15px; color: var(--muted); }
.link-label {
  display: block;
  text-align: center;
  margin: 16px 0 0;
  font-size: 16px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--link);
  cursor: pointer;
}
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.select-inline {
  width: auto;
  min-height: 44px;
  padding: 10px 12px;
  font-size: 15px;
}

/* ---------------------------------------------------------------- forms */
label { display: block; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px; color: var(--muted); margin: 28px 0 10px; }
label.inline { display: inline-flex; align-items: center; gap: 8px; margin: 0; text-transform: none; letter-spacing: 0; font-weight: 400; font-size: 15px; color: var(--ink); }
input[type="text"], input[type="email"], input[type="url"], input[type="password"], input[type="number"], input[type="search"], textarea, select {
  width: 100%;
  font-family: var(--sans);
  font-size: 19px;
  padding: 15px 16px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: var(--surface);
  color: var(--ink);
  min-height: 56px;
}
textarea { min-height: 130px; resize: vertical; line-height: 1.5; }
input:focus, textarea:focus, select:focus { outline: 2px solid var(--ink); outline-offset: -1px; }
input[type="checkbox"] { width: 20px; height: 20px; min-height: 0; accent-color: var(--ink); }
.field-error { color: var(--ink); background: var(--canvas-soft); border-left: 3px solid var(--ink); padding: 8px 12px; font-size: 14px; margin-top: 6px; }
.code-input { font-size: 28px; letter-spacing: 10px; text-align: center; min-height: 68px; }

/* ---------------------------------------------------------------- cards */
.card { border: 1px solid var(--border); padding: 24px; margin: 16px 0; background: var(--surface); }
.card-soft { background: var(--canvas-soft); border: 0; padding: 20px; margin: 16px 0; }
.next-card { background: var(--surface); border: 1px solid var(--border); padding: 28px; margin-top: 32px; }
.quiet-card { border: 1px solid var(--hairline); background: transparent; padding: 24px; margin-top: 16px; }
a.next-card, a.quiet-card { display: block; text-decoration: none; color: var(--ink); }
.reason-card {
  background: var(--canvas-soft);
  border-left: 3px solid var(--ink);
  padding: 12px 16px;
  font-family: var(--serif-body);
  font-size: 15px;
  margin: 12px 0;
}
.reason-card.soft { border-left-color: var(--border); }

.status-tag {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding: 3px 8px;
  border: 1px solid var(--ink);
}
.status-tag.on { background: var(--ink); color: var(--surface); }
.status-tag.soft { border-color: var(--border); color: var(--muted); font-weight: 400; }
.status-tag.dashed { border-style: dashed; }

.ticks { display: flex; gap: 6px; }
.ticks span { flex: 1; height: 4px; background: var(--hairline); }
.ticks span.on { background: var(--ink); }
.progress-row { display: flex; align-items: center; gap: 14px; margin-top: 20px; }
.progress-row .ticks { flex: 1; }
.progress-fraction { font-size: 16px; color: var(--muted); white-space: nowrap; }

.empty { text-align: center; padding: 48px 12px; }
.empty .title { font-family: var(--serif-body); font-size: 21px; color: var(--ink-soft); }
.empty .muted { margin-top: 8px; }

/* ══════════════════════════════════════════════ prompt manager ══════════ */

/* ------------------------------------------------------- search (home) */
.search-form { margin-top: 24px; position: relative; }
.search-field {
  display: flex;
  align-items: center;
  gap: 14px;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 0 14px;
  min-height: 48px;
}
.search-field label {
  flex: none;
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--muted);
  line-height: 1;
}
.search-field input[type="search"] {
  flex: 1;
  min-width: 0;
  font-family: var(--sans);
  font-size: 18px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  min-height: 46px;
  line-height: 1.2;
}
.search-field input[type="search"]:focus { outline: none; }
.search-form:focus-within .search-field { outline: 2px solid var(--ink); outline-offset: -1px; }
.search-note { margin-top: 10px; font-size: 14px; color: var(--muted); }
.search-modes { display: flex; gap: 0; margin-top: 12px; border: 1px solid var(--border); width: fit-content; background: var(--surface); }
.search-modes button {
  font-family: var(--sans);
  font-size: 14px;
  padding: 11px 16px;
  min-height: 44px;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.search-modes button.on { background: var(--ink); color: var(--surface); font-weight: 700; }
/* Hybrid is the only exposed mode; picker DOM kept for a future release. */
.search-mode-picker { display: none !important; }

/* The sentence a panel opens with — what is left to do, in words, before the
   controls that do it. Serif, because it is prose and not chrome. */
.bench-lede {
  font-family: var(--serif-body);
  font-size: 17px;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-top: 6px;
}

.result-row {
  display: flex;
  gap: 16px;
  align-items: baseline;
  border-top: 1px solid var(--hairline);
  padding: 18px 0;
  text-decoration: none;
  color: var(--ink);
}
.result-row:last-of-type { border-bottom: 1px solid var(--hairline); }
.result-main { flex: 1; min-width: 0; }
.result-title { display: block; font-family: var(--serif-body); font-size: 21px; line-height: 1.3; color: var(--ink); }
.result-sub { display: block; font-size: 15px; line-height: 1.5; color: var(--muted); margin-top: 4px; }
.result-kind { flex: none; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.7px; color: var(--muted); }

/* The swatch. Square, matte, no border — it reads as a key, not a badge, and
   it is the same pigment whether it sits in a section eyebrow on the idle page
   or beside the kind label of a search result. */
.kind-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: 8px;
  vertical-align: baseline;
  background: var(--muted);
}
.result-kind .kind-dot { width: 8px; height: 8px; margin-right: 6px; }
.kind-dot--prompt { background: var(--kind-prompt); }
.kind-dot--cluster { background: var(--kind-cluster); }
.kind-dot--session { background: var(--kind-session); }

/* One section of the idle home directory: eyebrow, a few rows, one way out.
   The gap is what separates them — the rows bring their own hairlines, and a
   rule between sections would make three lists read as one table. */
.home-group { margin-top: 44px; }

/* The way out rides the eyebrow's line, hard right, so it costs no row of its
   own and reads as part of the section head rather than as a fourth entry in
   the list. */
.home-group__head { display: flex; align-items: baseline; gap: 12px; }
.home-group__head .eyebrow { flex: 1; min-width: 0; }

/* A bare +. It must be capped to the eyebrow's own line box: the shared
   .disclosure-toggle carries a 44px min-height, and on this row that made the
   glyph hang down THROUGH the hairline below the eyebrow — the button looked
   like it belonged to the first result. Height and line-height are the fix,
   and the tap target comes back invisibly through the ::after box, which grows
   UPWARD into the 44px gap above the section. Growing it downward instead
   would put a hit area over the first row's right edge, where a mis-tap sends
   you to the library instead of the prompt you aimed at. */
.home-group__more {
  flex: none;
  height: 18px;
  line-height: 18px;
  position: relative;
  font-family: var(--sans);
  font-size: 17px;
  color: var(--link);
  text-decoration: none;
}
.home-group__more:hover { color: var(--ink); }
.home-group__more::after {
  content: "";
  position: absolute;
  right: -10px;
  bottom: -2px;
  width: 44px;
  height: 40px;
}
.result-score { flex: none; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Provenance, not a percentage — a fused rank has no meaningful number to show.
   "Both" is the only one worth emphasising: it is the row both engines agreed
   on, and the reason to run hybrid search at all. */
.result-match {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  border: 1px solid var(--hairline);
  padding: 3px 7px;
}
.result-match.on { border-color: var(--ink); color: var(--ink); }

/* One line above the results that says what the search did: count, whether
   the meaning pass is still coming, why it degraded. Fixed slot — the tier-2
   repaint swaps its text, never the geometry of the rows below it. */
.search-status {
  min-height: 20px;
  margin: 20px 0 4px;
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.search-status.working::after {
  content: "";
  display: inline-block;
  width: 5px; height: 5px;
  margin-left: 7px;
  border-radius: 50%;
  background: var(--muted);
  vertical-align: 2px;
  animation: search-pulse 1s ease-in-out infinite;
}
@keyframes search-pulse { 50% { opacity: 0.25; } }

/* The matched words, marked. This answers "why is this row here?" without a
   score — a wash of the page's own soft tone, not a highlighter color. */
.result-row mark {
  background: var(--canvas-soft);
  color: inherit;
  padding: 0 1px;
  border-radius: 2px;
}
.result-title mark { background: var(--canvas-soft); box-shadow: inset 0 -2px 0 var(--border); }

/* Rows the meaning pass added settle in rather than pop — motion to confirm
   the list changed, nothing more. */
@keyframes result-in { from { background: var(--canvas-soft); } to { background: transparent; } }
.result-new { animation: result-in 1.4s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .result-new { animation: none; }
  .search-status.working::after { animation: none; }
}

/* --------------------------------------------- search (library tables) */
/* The quiet strip under a list's search box. One row, hard right, for the
   controls that are ABOUT the list rather than in it — today just the way out
   to what the list is keeping back. */
.list-tools { display: flex; justify-content: flex-end; margin-top: 8px; }
.table-search { margin: 22px 0 4px; }
.table-search input[type="search"] { font-size: 17px; }
.table-search .search-modes { margin-top: 10px; }
.index-count {
  margin-top: 10px;
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.index-count.ready { color: var(--ink-soft); }

.tag-row { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.tag {
  font-size: 12px;
  color: var(--muted);
  border: 1px solid var(--hairline);
  padding: 2px 7px;
  text-decoration: none;
}
a.tag:hover { border-color: var(--ink); color: var(--ink); }

/* A tag the model proposed but nobody has accepted yet. Dashed says "not
   real until you say so"; the two buttons are the only way it becomes real. */
.chip-suggest {
  display: inline-flex;
  align-items: center;
  border: 1px dashed var(--border);
  font-size: 13px;
  color: var(--muted);
}
.chip-suggest .chip-name { padding: 0 4px 0 10px; }
.chip-suggest button {
  background: none;
  border: 0;
  min-width: 40px;
  min-height: 44px;
  font-size: 15px;
  color: var(--muted);
  cursor: pointer;
}
.chip-suggest button:hover, .chip-suggest button:focus-visible { color: var(--ink); }

/* Document chips — Cursor-style attachments above the Input (bench).
   Dashed while processing = "not real until the text lands", the same promise
   .chip-suggest makes; solid once the session holds the text; a failure gets
   the .field-error left bar rather than a color this palette doesn't have. */
.attach { margin-bottom: 6px; }
.chip-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.doc-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: 13px;
  color: var(--ink-soft);
  padding: 3px 2px 3px 10px;
}
.doc-chip-name {
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-chip-meta { font-size: 11.5px; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.doc-chip-x, .doc-chip-retry {
  background: none;
  border: 0;
  min-width: 36px;
  min-height: 40px;
  color: var(--muted);
  cursor: pointer;
}
.doc-chip-x { font-size: 16px; }
.doc-chip-retry { font-size: 12.5px; text-decoration: underline; min-width: 0; padding: 0 4px; }
.doc-chip-x:hover, .doc-chip-x:focus-visible,
.doc-chip-retry:hover, .doc-chip-retry:focus-visible { color: var(--ink); }
.doc-chip.is-processing { border-style: dashed; color: var(--muted); }
.doc-chip.is-processing::before {
  content: "";
  flex: none;
  width: 10px;
  height: 10px;
  border: 1.5px solid var(--hairline);
  border-top-color: var(--ink);
  border-radius: 50%;
  animation: chip-spin 0.8s linear infinite;
}
@keyframes chip-spin { to { transform: rotate(360deg); } }
.doc-chip.is-error { border-left: 3px solid var(--ink); background: var(--canvas-soft); }
.doc-chip.is-warn .doc-chip-meta { color: var(--ink); font-weight: 700; }
.doc-chip.is-done[draggable="true"] { cursor: grab; }
.doc-chip.is-dragging { opacity: 0.45; cursor: grabbing; }

/* ----------------------------------------------------------------- tabs */
/* The library's top-level directory. 48px tall because a thumb has to hit it,
   and the active one changes THREE ways — colour, weight, and the rule under
   it — so you never have to squint to work out where you are. */
.tabs {
  display: flex;
  gap: 4px;
  margin-top: 26px;
  border-bottom: 1px solid var(--hairline);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.tabs a {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 14px;
  font-size: 15px;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.tabs a:hover { color: var(--ink); }
.tabs a.on { color: var(--ink); font-weight: 700; border-bottom-color: var(--ink); }
.tabs button {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 14px;
  font-family: var(--sans);
  font-size: 15px;
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  cursor: pointer;
}
.tabs button:hover { color: var(--ink); }
.tabs button.on { color: var(--ink); font-weight: 700; border-bottom-color: var(--ink); }

/* ------------------------------------------------------------ list rows */
/* What replaced the library tables. The whole row is the link; at most ONE
   button sits beside it, outside the anchor, so a tap never lands ambiguously. */
.list-row { display: flex; align-items: center; gap: 12px; border-top: 1px solid var(--hairline); }
.list-row:last-child { border-bottom: 1px solid var(--hairline); }
.list-row-link { flex: 1; min-width: 0; display: block; padding: 16px 0; text-decoration: none; color: var(--ink); }
.list-row-link:hover .list-row-title { color: var(--link); }
.list-row-title { display: block; font-family: var(--serif-body); font-size: 19px; line-height: 1.3; }
.list-row-sub { display: block; font-size: 14px; color: var(--muted); margin-top: 4px; }
.list-row-body { flex: 1; min-width: 0; padding: 16px 0; }

/* A title that opens something instead of navigating somewhere. It is a real
   button for the keyboard and the screen reader, and identical to the span it
   replaces for everyone else — a row where one title is a link and the next is
   a control should not look like two kinds of row. */
.list-row-title--action {
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  color: var(--ink);
  cursor: pointer;
}
.list-row-title--action:hover { color: var(--link); }

/* Builder machinery below a library list — the list's closing hairline is
   enough; a second rule here read as two blank rows above Import. */
.builder-tools {
  margin-top: 56px;
  border-top: 1px solid var(--hairline);
  padding-top: 28px;
}
.builder-tools--after-list {
  margin-top: 24px;
  border-top: 0;
  padding-top: 4px;
}
body[data-is-builder="0"] .builder-tools {
  display: none;
}

/* ----------------------------------------------------------- disclosure */
/* Depth without clutter: the surface stays calm, the option is one tap away. */
.disclosure-toggle {
  display: block;
  background: none;
  border: 0;
  padding: 10px 0;
  min-height: 44px;
  font-family: var(--sans);
  font-size: 15px;
  color: var(--link);
  cursor: pointer;
  text-align: left;
}
.disclosure-toggle::before { content: "+ "; }
.disclosure-toggle[aria-expanded="true"]::before { content: "\2212 "; }
.disclosure-toggle[data-about-toggle] {
  display: inline-block;
  width: auto;
  font-size: 0;
  padding: 0 4px;
  min-height: 44px;
  flex-shrink: 0;
  align-self: flex-start;
  margin-top: 2px;
}
.disclosure-toggle[data-about-toggle]::before {
  content: "+";
  font-size: 15px;
}
.disclosure-toggle[data-about-toggle][aria-expanded="true"]::before { content: "\2212"; }
.disclosure-toggle:hover { color: var(--ink); }
a.disclosure-toggle { text-decoration: none; }
a.disclosure-toggle::before { content: none; }

/* Sibling of the disclosure toggle: a borderless 44px action for a row's own
   small verbs. Ink, not link — the accent is spent once per screen already,
   and a bordered button repeated down a list reads as a toolbar. */
.btn-text {
  display: inline-block;
  background: none;
  border: 0;
  padding: 10px 0;
  min-height: 44px;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--muted);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.btn-text:hover, .btn-text:focus-visible { color: var(--ink); }
.action-bar .search-modes--bar { margin-top: 0; margin-bottom: 12px; }
.disclosure-toggle--bar { width: 100%; text-align: center; }

/* A provider card on Settings. The provider on the first line, what it can
   reach behind a fold on the second — identical shape whether the key writes
   or transcribes, because it is the same key doing a different job. */
.key-card { border-bottom: 1px solid var(--hairline); padding-bottom: 8px; margin-bottom: 8px; }
.key-card .list-row { border-bottom: 0; }
.key-card > .disclosure-toggle { padding-left: 0; }

/* The fold itself: chevron · what is behind it · how much. Deliberately NOT a
   .disclosure-toggle — that one is a link-coloured invitation, and this is a
   quiet second line under a card that already has two buttons on it. */
.key-fold {
  display: flex;
  width: 100%;
  align-items: baseline;
  gap: 8px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink-soft);
  text-align: left;
  cursor: pointer;
}
.key-fold::before { content: "\25BC"; flex: none; font-size: 10px; color: var(--muted); }
.key-fold[aria-expanded="true"]::before { content: "\25B2"; }
.key-fold:hover, .key-fold:focus-visible { color: var(--ink); }
.key-fold-label { flex: 1; min-width: 0; }
/* Shrinkable, not flex:none. "2 MODELS" always fits; "SPANISH (ESPAÑOL) ·
   ENHANCED" does not, and a rigid box here is how this row starts scrolling
   sideways on a phone. It gives ground and wraps instead. */
.key-fold-count {
  flex: 0 1 auto;
  min-width: 0;
  text-align: right;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
/* Indented under the chevron, so an open fold reads as belonging to its card
   rather than as the next thing on the page. */
.key-fold-body { padding: 0 0 4px 18px; }
.key-fold-body > label:first-child { margin-top: 0; }

/* Model names as they are actually written. Bordered mono chips, nothing else
   on them: no default marker, no note. Which model runs belongs to a prompt or
   a workflow, and repeating it here only invites the two to disagree. */
.model-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 0 12px; }
.model-chip {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 11px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink);
  word-break: break-all;
}
.model-add { border-top: 1px solid var(--hairline); }
.model-add > .model-add-toggle { font-size: 14px; color: var(--ink-soft); }
.model-add > .model-add-toggle:hover { color: var(--ink); }
.model-add-row { display: flex; gap: 8px; flex-wrap: wrap; }
.model-add-row input { flex: 1; min-width: 180px; margin-top: 0; }

/* A voice card's settings, behind the same fold the Models list uses. Spaced
   by the container's gap rather than by each label's own 28px top margin —
   siblings in a group are the group's business, and stacked margins are what
   made these two selects sit further apart than the card is tall. */
.voice-cfg { display: flex; flex-direction: column; gap: 12px; padding: 2px 0 12px; }
.voice-field > label { margin: 0 0 6px; }
.voice-cfg > p { margin: 0; }

/* The provider's known models, offered as chips rather than through a native
   <datalist>. That popup is drawn by the browser — its own font, its own
   coordinates — and under page zoom it lands away from the field it belongs
   to, which nothing on this page can correct. Dashed, so "one you could add"
   never reads as "one you have". */
.model-suggest { display: flex; flex-wrap: wrap; gap: 6px; padding: 12px 0; }
.model-chip--add {
  border-style: dashed;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
}
.model-chip--add::before { content: "+"; margin-right: 7px; color: var(--muted); }
.model-chip--add:hover, .model-chip--add:focus-visible { border-style: solid; color: var(--ink); }
.model-chip--add:disabled { opacity: .5; cursor: default; }

/* Rule form — the shortcut past the form. Quiet card, one size down on the
   textarea: it is a way in, not the thing being filled. */
.draft-rule { margin: 24px 0 8px; }
.draft-rule > label:first-child { margin-top: 0; }
.draft-rule textarea { min-height: 96px; font-size: 17px; }
.draft-note {
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--canvas-soft);
  border-left: 3px solid var(--ink);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
}

/* Rule form — field-level help. The trigger sits BELOW its control, and it is
   a plain button over a [hidden] panel, not a <details>: native disclosure
   collapsed the moment the select above it took focus. */
.help-anchor { position: relative; }
.help-pop__trigger {
  display: block;
  margin-top: 8px;
  padding: 0;
  min-height: 44px;
  background: none;
  border: 0;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--muted);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-align: left;
}
.help-pop__trigger:hover,
.help-pop__trigger:focus-visible { color: var(--ink); }
.help-popover {
  margin-top: 4px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: 14px;
  line-height: 1.5;
}
.help-popover__title {
  margin: 0 0 6px;
  font-family: var(--serif-body);
  font-size: 17px;
  line-height: 1.3;
  color: var(--ink);
}
.help-popover__lede,
.help-popover__note {
  margin: 0 0 10px;
  font-size: 14px;
  color: var(--muted);
}
.help-popover__note:last-child { margin-bottom: 0; }
.help-popover__table {
  width: 100%;
  margin: 12px 0;
  border-collapse: collapse;
  font-size: 13px;
  line-height: 1.45;
}
.help-popover__table th,
.help-popover__table td {
  padding: 8px 10px;
  border-top: 1px solid var(--hairline);
  text-align: left;
  vertical-align: top;
}
/* Two columns: the option, then what it does. The option column is fixed so the
   three labels stack in the same shape and the eye can scan straight down. */
.help-popover__table th:first-child,
.help-popover__table td:first-child { width: 38%; }
/* The row for the value currently in the select. Weight and a ground tint, not
   a second accent — the card is already quiet and this has to stay that way. */
.help-popover__table tr.is-selected td { background: var(--canvas-soft); color: var(--ink); }
.help-popover__table tr.is-selected td:first-child {
  box-shadow: inset 2px 0 0 var(--ink);
  font-weight: 600;
}
.help-popover__table thead th {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted);
  border-top: 0;
}
.help-popover__table code {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
}

/* Prompt editor — placeholder reference under the body. Compact legend only;
   kept light and small so it reads as reference, not instruction. */
.ph-ref { margin-top: 8px; font-size: 12px; line-height: 1.45; color: #a39d93; }
.ph-ref__legend {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 3px 12px;
  margin: 0;
}
.ph-ref__legend > div { display: contents; }
.ph-ref__legend dt { margin: 0; font-weight: 400; }
.ph-ref__copy {
  font-family: var(--mono);
  font-size: 11px;
  color: #9a9388;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  text-align: left;
  border-radius: 2px;
}
.ph-ref__copy:hover,
.ph-ref__copy:focus-visible { color: var(--ink); }
.ph-ref__copy:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.ph-ref__copy.copied { color: var(--ink); }
.ph-ref__legend dd { margin: 0; color: #a39d93; font-size: 12px; }

/* Placeholder chips under the payload textarea. Solid = real (declared on the
   prompt / always available); dashed = AI-proposed, not yet saved — the same
   promise .chip-suggest makes. */
.ph-chips { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.ph-chips:empty { display: none; }
.ph-chips-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ph-chips-label { flex: none; width: 74px; font-size: 12px; color: var(--muted); }
.ph-chip {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
}
.ph-chip:hover,
.ph-chip:focus-visible { border-color: var(--ink); color: var(--ink); }
.ph-chip:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.ph-chip.is-suggest { border-style: dashed; color: var(--muted); }

/* ------------------------------------------------- markdown write/preview */
.md-tabs {
  display: flex;
  gap: 0;
  border: 1px solid var(--border);
  border-bottom: 0;
  width: fit-content;
  background: var(--surface);
}
.md-tabs button {
  font-family: var(--sans);
  font-size: 14px;
  padding: 0 16px;
  min-height: 44px;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.md-tabs button.on { background: var(--ink); color: var(--surface); font-weight: 700; }

/* The same switch inside the workbench's Prompt tab. The panel opens flush
   against the tab strip above it, and whichever view is showing hangs off the
   switch with no seam — the assembled <pre> carries a margin of its own for
   the screens that show it alone. */
.bench-md-tabs { margin-top: 20px; }
.bench-md-tabs + [data-prompt-view] .assembled { margin-top: 0; }

/* The one place a <table> is allowed: rendered markdown CONTENT. The chrome
   of this app has no tables — but a prompt body that ships one must show it. */
.md-preview {
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 18px;
  min-height: 130px;
  max-height: 60vh;
  overflow: auto;
  font-family: var(--serif-body);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-soft);
}
.md-preview > :first-child { margin-top: 0; }
.md-preview h1, .md-preview h2, .md-preview h3, .md-preview h4 {
  font-family: var(--serif-display);
  color: var(--ink);
  margin: 18px 0 8px;
  line-height: 1.25;
}
.md-preview h1 { font-size: 24px; }
.md-preview h2 { font-size: 20px; }
.md-preview h3, .md-preview h4 { font-size: 17px; }
.md-preview p { margin: 10px 0; }
.md-preview ul, .md-preview ol { margin: 10px 0 10px 22px; }
.md-preview li { margin: 4px 0; }
.md-preview a { color: var(--link); }
.md-preview hr { border: 0; border-top: 1px solid var(--hairline); margin: 18px 0; }
.md-preview code { font-family: var(--mono); font-size: 13px; background: var(--canvas-soft); padding: 1px 5px; }
.md-preview pre { background: var(--canvas-soft); padding: 12px; overflow-x: auto; margin: 12px 0; }
.md-preview pre code { background: none; padding: 0; }
.md-preview blockquote {
  border-left: 3px solid var(--hairline);
  padding-left: 14px;
  margin: 12px 0;
  color: var(--muted);
}
.md-preview table { border-collapse: collapse; width: 100%; margin: 14px 0; font-family: var(--sans); font-size: 14px; }
.md-preview th, .md-preview td { border: 1px solid var(--hairline); padding: 8px 10px; text-align: left; vertical-align: top; }
.md-preview th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); font-weight: 700; }
.md-preview img { max-width: 100%; }
.md-preview:empty::before { content: "Nothing to preview yet."; color: var(--muted); font-family: var(--sans); font-size: 15px; }

/* ------------------------------------------------------- prompt summary */
/* Em-dash bullets, serif body — the summary reads as prose, not as a list of
   fields. Three points maximum; the discipline is in the prompt, not the CSS. */
.points { list-style: none; margin: 10px 0 0; padding: 0; }
.points li { font-family: var(--serif-body); font-size: 16px; line-height: 1.55; padding: 4px 0; color: var(--ink-soft); }
.points li::before { content: "\2014\00a0"; color: var(--muted); }
.summary-meta { margin-top: 12px; font-size: 13px; color: var(--muted); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* The masthead's edit view commits itself, next to the rows it commits — the
   sticky bar belongs to the bench and only sticks while the bench is on screen.
   Save and Cancel share a line so they never read as a stacked choice;
   outline, not ink, because Copy is still the one filled element on this
   screen. */
.detail-actions { display: flex; align-items: center; gap: 18px; margin-top: 20px; }

/* ------------------------------------------------------------ workbench */
/* One column at every width. Copy and Paste actions sit at the foot of the
   Fields panel only — other tabs have nothing to put on a clipboard. */
.bench { display: block; margin-top: 24px; max-width: 680px; }
.bench-panel > .action-bar { border-top: 0; }
.bench-panel[data-bench-panel="fill"] > .action-bar { margin-top: 32px; }
.bench-panel { margin-top: 20px; }
.bench-panel[hidden] { display: none !important; }

.bench-section { border-top: 1px solid var(--hairline); padding-top: 18px; margin-top: 24px; }
.bench-section:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.bench-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.bench-head .eyebrow { margin: 0; }

.field { margin-top: 18px; }
.field > label { margin-top: 0; }
.field .help { font-size: 14px; color: var(--muted); margin-top: 6px; }
.field.shared .float-wrap > label::after {
  content: "shared";
  margin-left: 8px;
  font-size: 10px;
  letter-spacing: 0.6px;
  color: var(--muted);
  border: 1px solid var(--hairline);
  padding: 1px 5px;
  text-transform: lowercase;
  font-weight: 400;
}

/* Floating labels on the workbench — single-line controls rest center-left;
   textareas rest upper-left where the cursor lands. Both float smaller to the
   top corner when focused or filled. */
.bench .float-wrap { position: relative; }
.bench .float-wrap > input,
.bench .float-wrap > textarea,
.bench .float-wrap > select { transition: padding-top 0.14s ease; }
.bench .float-wrap > label {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  margin: 0;
  z-index: 1;
  pointer-events: none;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--muted);
  transition: top 0.14s ease, transform 0.14s ease, font-size 0.14s ease, font-weight 0.14s ease, letter-spacing 0.14s ease, text-transform 0.14s ease;
}
/* Long text: label sits on the first line, not in the vertical middle. */
.bench .float-wrap > textarea + label {
  top: 15px;
  transform: translateY(0);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
}
.bench .float-wrap.is-active > label,
.bench .float-wrap:focus-within > label {
  top: 8px;
  transform: translateY(0);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.7px;
  line-height: 1.2;
}
.bench .float-wrap.is-active > input,
.bench .float-wrap:focus-within > input,
.bench .float-wrap.is-active > select,
.bench .float-wrap:focus-within > select {
  padding-top: 30px;
}
.bench .float-wrap.is-active > textarea,
.bench .float-wrap:focus-within > textarea {
  padding-top: 32px;
}

/* ----------------------------------------------- field-definition editor
   Defining what the sidecar asks for. This used to be four controls on one
   flex line inside a grey box: at 680px every one of them sat at its
   min-width, the name truncated and the type read "Short te". Nothing was
   wrong with the controls — there were just too many sharing a line.

   So: name on its own line; type, required and hint fold behind a disclosure
   toggle (defaults: short text, required, no hint). One row open at a time.
   Hairline separation instead of grey blocks; options and Remove share one
   line under the name. */
.var-row { border-top: 1px solid var(--hairline); padding: 20px 0 30px; }
.var-row:first-child { border-top: 0; padding-top: 4px; }

/* The name is an identifier the prompt body has to match character for
   character, so it is set in the same face the body is. */
input[type="text"].var-name { font-family: var(--mono); font-size: 17px; }

.var-row-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 4px;
}
.var-row-foot .var-row-options { margin-top: 0; flex: 1 1 auto; min-width: 0; }

.var-row-details { margin-top: 4px; }
.var-row-details .var-row-meta { margin-top: 0; }
.var-row-details > label,
.var-row-details [data-vf-choices] > label { margin: 24px 0 10px; }

/* Choices are a list of short strings, so the box is sized for the list and
   set in the same face as the name it will fill. */
.var-row-details [data-vf-choices] textarea { font-family: var(--mono); font-size: 15px; }

.var-row-meta { display: flex; align-items: flex-end; gap: 28px; flex-wrap: wrap; margin-top: 22px; }
.var-row-type { flex: 0 1 250px; min-width: 190px; }
.var-row-type > label { margin: 0 0 10px; }
.var-row-meta > .inline { min-height: 56px; }

/* An add button that sits where the thing it adds will appear. Centred
   explicitly: the attach control is a <label> wrapping a hidden file input,
   and a label does not centre its text the way a button does. */
.var-add { display: block; width: 100%; border-style: dashed; margin-top: 22px; text-align: center; }

/* ------------------------------------------------------------- rule picker
   The sibling of .var-row, and the same lesson: the rule itself is the only
   part anyone reads, so it gets the line. Level and placement are the aside,
   so they go underneath in muted small — on one line they pushed the rule text
   into wrapping around its own metadata. The whole row is the label, so the
   target is the row and not a 20px box. */
.rule-list { margin-top: 4px; }
.rule-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin: 0;
  padding: 18px 0;
  border-top: 1px solid var(--hairline);
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
  cursor: pointer;
}
/* Visible rows are moved to the END of the list, so :first-child is a hidden
   row far more often than it is the row on top. The client stamps .is-first on
   whatever actually leads the list; :first-child still covers the full editor,
   where nothing reorders anything. */
.rule-row:first-child { border-top: 0; }
.rule-list > .is-first { border-top: 0; }
.rule-row input[type="checkbox"] { flex: none; margin-top: 4px; }
.rule-row-body { flex: 1; min-width: 0; }
.rule-row-title { display: block; font-family: var(--serif-body); font-size: 18px; line-height: 1.4; }
.rule-row-meta { display: block; font-size: 14px; color: var(--muted); margin-top: 5px; }

/* Editing a rule in place (/library?tab=rules). The editor is a third child of
   the flex row, so the row wraps and hands it a whole line of its own — the
   title and Delete keep sharing the first one. Only the Rules tab wraps: a
   library row has nothing to put on a second line, and letting it wrap would
   drop the button under a long title at narrow widths. */
.rule-list .list-row { flex-wrap: wrap; }
.rule-edit { flex: 0 0 100%; min-width: 0; padding-bottom: 26px; }
/* The row's own bottom padding already sits above this; a second 28px gap read
   as the form having come loose from the rule it belongs to. */
.rule-edit form > label:first-child { margin-top: 6px; }

/* The Keys tab's group header. Reads as the eyebrow it is — the key is a slug,
   not prose, so it gets the uppercase treatment rather than the serif. */
.rule-group {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 30px 0 0;
  padding-bottom: 4px;
}

/* While a query is running the list is one flat relevance order across every
   level, so the tabs are no longer describing what is on screen. They dim to
   say so — still clickable, and clicking one clears the search. */
.tabs.is-searching button.on {
  color: var(--muted);
  font-weight: 400;
  border-bottom-color: transparent;
}

/* The assembled text. Monospace because this is the artifact, not prose —
   whitespace is meaningful and the user is about to paste it verbatim. */
.assembled {
  font-family: var(--mono);
  font-size: 13.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 18px;
  max-height: 46vh;
  overflow: auto;
  margin-top: 12px;
}
.assembled:empty::before { content: "Fill in the sidecar to see the prompt."; color: var(--muted); font-family: var(--sans); }

/* Token budget — a bar and a number, no sentence. Amber and red are STATE,
   not decoration, which is why they are the only colours outside the palette
   and appear nowhere else. */
.budget { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
.budget-bar { flex: 1; height: 4px; background: var(--hairline); position: relative; }
.budget-bar span { display: block; height: 100%; background: var(--ink); max-width: 100%; }
.budget.warn .budget-bar span { background: #a8730a; }
.budget.over .budget-bar span { background: #a32020; }
.budget-count { font-size: 14px; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.budget.warn .budget-count, .budget.over .budget-count { color: var(--ink); font-weight: 700; }

/* Assembly report — what the engine did. Never a silent decision. */
.report { margin-top: 14px; font-size: 14px; }
.report-line { display: flex; gap: 8px; align-items: baseline; padding: 5px 0; color: var(--muted); }
.report-line .mark { flex: none; width: 8px; height: 8px; border: 1px solid var(--muted); margin-top: 6px; }
.report-line.warn { color: var(--ink); }
.report-line.warn .mark { border-color: var(--ink); border-style: dashed; }
.report-toggle { background: none; border: 0; padding: 10px 0; min-height: 44px; font-family: var(--sans); font-size: 14px; color: var(--link); cursor: pointer; text-align: left; }

/* ------------------------------------------------- the prompt map (Rules tab)
   The prompt drawn as it is built: bands top to bottom in emission order, the
   body sitting in its real place among them, rules numbered straight through
   so the number IS the reading position. A spine down the left side is what
   makes it one document rather than four lists.

   No filled ink here — that belongs to Copy. The body band is the one shaded
   surface, because it is the only band that is not rules. */
.pmap { margin-top: 2px; }
.pmap-lede { font-size: 15px; color: var(--muted); margin-bottom: 16px; }
.pmap-lede strong { color: var(--ink); font-weight: 700; }

.pmap-slots { list-style: none; margin: 0; padding: 0; }
.pmap-slot { border-left: 2px solid var(--hairline); padding: 12px 0 14px 16px; }
.pmap-slot.is-body { border-left-color: var(--ink); background: var(--canvas-soft); padding-right: 14px; }

.pmap-slot-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.pmap-slot-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.7px; color: var(--ink); }
.pmap-slot-where { font-size: 13px; color: var(--muted); }

/* Where ${ rules } put them — named in the template's own syntax, because the
   user fixes this by editing that placeholder and nothing else. */
.pmap-inline-mark { margin-top: 10px; font-size: 14px; color: var(--ink-soft); }
.pmap-inline-mark code { background: var(--surface); border: 1px solid var(--border); padding: 1px 5px; }

.pmap-rules { list-style: none; margin: 8px 0 0; padding: 0; }
.pmap-rule { display: flex; gap: 12px; align-items: baseline; padding: 8px 0; border-top: 1px solid var(--hairline); }
.pmap-rule:first-child { border-top: 0; }
/* The number is the whole point of the panel — it is the rule's position in
   the finished text — so it carries ink, not the grey of a list bullet. */
.pmap-pos {
  flex: none;
  width: 18px;
  font-family: var(--serif-body);
  font-size: 16px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.pmap-rule-main { flex: 1; min-width: 0; }
/* The name opens the rule's text. Dotted rather than solid so it reads as
   "there is more here", not as a link to somewhere else. */
.pmap-rule-name {
  display: inline-block;
  background: none;
  border: 0;
  border-bottom: 1px dotted var(--border);
  padding: 3px 0;
  font-family: var(--serif-body);
  font-size: 17px;
  line-height: 1.35;
  text-align: left;
  color: var(--ink);
  cursor: pointer;
}
.pmap-rule-name:hover { border-bottom-color: var(--ink); }
.pmap-rule-meta { display: block; font-size: 13px; color: var(--muted); margin-top: 3px; }
.pmap-rule-beat { display: block; font-size: 13px; color: var(--ink-soft); margin-top: 3px; }
/* U+2192, not the prettier U+21B3 — the arrow has to exist in the sans stack
   on a plain Windows box, and the hooked one falls back to a tofu glyph. */
.pmap-rule-beat::before { content: "\2192\00A0"; color: var(--muted); }
.pmap-rule-body {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--ink-soft);
}

/* Struck through, not merely greyed: an attached rule that never reached the
   model has to look different in kind from one that did. */
.pmap-out { margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--hairline); }
.pmap-drop { padding: 8px 0; }
.pmap-drop-name {
  font-family: var(--serif-body);
  font-size: 17px;
  line-height: 1.35;
  color: var(--muted);
  text-decoration: line-through;
  text-decoration-color: var(--border);
}

/* ------------------------------------------------------- corpus picker */
.chunk {
  border-top: 1px solid var(--hairline);
  padding: 14px 0;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.chunk:last-of-type { border-bottom: 1px solid var(--hairline); }
.chunk input[type="checkbox"] { margin-top: 4px; flex: none; }
.chunk-main { flex: 1; min-width: 0; }
.chunk-text { font-family: var(--serif-body); font-size: 16px; line-height: 1.45; }
.chunk-meta { font-size: 13px; color: var(--muted); margin-top: 6px; display: flex; gap: 10px; flex-wrap: wrap; }
.chunk-score { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------- workflow flow */
/* The "How it runs" diagram on /c/{id}. Layout rides inline on the markup
   (ported from the design export); only STATE lives here, because unplugging
   flips a card between two looks and a class flip is the honest mechanism. */
.flow-card { border: 1px solid var(--border); background: var(--surface); }
.flow-card.flow-skipped {
  border: 1px dashed var(--hairline);
  background: transparent;
  opacity: 0.55;
}
.flow-num {
  flex: none;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--canvas);
  font-family: var(--sans);
  font-size: 14px;
}
.flow-skipped .flow-num {
  border-color: var(--hairline);
  background: transparent;
  color: var(--muted);
}
.flow-caret { transition: transform 0.15s ease; }
.flow-card.open .flow-caret { transform: rotate(180deg); }

/* ------------------------------------------------------------- steps */
.step-row {
  display: flex;
  gap: 14px;
  align-items: baseline;
  border-top: 1px solid var(--hairline);
  padding: 16px 0;
  text-decoration: none;
  color: var(--ink);
}
.step-row:last-of-type { border-bottom: 1px solid var(--hairline); }
.step-n { flex: none; width: 22px; font-family: var(--serif-body); font-size: 19px; color: var(--muted); }
.step-main { flex: 1; min-width: 0; }
.step-title { display: block; font-family: var(--serif-body); font-size: 20px; line-height: 1.3; }
a.step-title { color: var(--ink); text-decoration: none; }
a.step-title:hover { color: var(--ink-soft); }
.step-sub { display: block; font-size: 14px; color: var(--muted); margin-top: 4px; }
.step-row.done .step-title { color: var(--muted); }
.step-mark { flex: none; width: 12px; height: 12px; border: 1px solid var(--ink); }
.step-mark.done { background: var(--ink); }
.step-mark.missing { border-style: dashed; border-color: var(--muted); }

/* ------------------------------------------------------- session naming
   The run's title is editable right where it shows. The input dresses as the
   heading it replaces; the placeholder ("Extract Wisdom · Aug 9") IS the
   unnamed state — muted italic, visibly not a real title. */
.session-head { flex: 1; min-width: 0; }
.session-head-tool { margin: 0 0 2px; }
input[type="text"].session-title {
  width: 100%;
  min-height: 0;
  padding: 0;
  border: 0;
  border-bottom: 1px dashed transparent;
  background: transparent;
  font-family: var(--serif-display);
  font-size: 34px;
  line-height: 1.12;
  letter-spacing: -0.5px;
  color: var(--ink);
}
input[type="text"].session-title:focus { outline: 0; border-bottom-color: var(--muted); }
input[type="text"].session-title::placeholder { color: var(--muted); font-style: italic; opacity: 1; }
input[type="text"].session-title--inline {
  display: inline-block;
  width: auto;
  max-width: 100%;
  vertical-align: baseline;
  font-family: var(--serif-body);
  font-size: 17px;
  line-height: 1.4;
  letter-spacing: 0;
  border-bottom: 1px dashed var(--hairline);
}
input[type="text"].session-title--inline:focus { border-bottom-color: var(--muted); }
.session-unnamed, a.step-title.session-unnamed, .result-title.session-unnamed { color: var(--muted); font-style: italic; }
input[type="text"].session-rename-input {
  min-height: 0;
  padding: 2px 0;
  font-family: var(--serif-body);
  font-size: 20px;
  line-height: 1.3;
  border: 0;
  border-bottom: 1px dashed var(--muted);
  background: transparent;
}
input[type="text"].session-rename-input:focus { outline: 0; }

.step-pos {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  border: 1px solid var(--hairline);
  padding: 8px 16px;
  color: var(--ink);
  text-decoration: none;
}
.step-pos:hover { border-color: var(--ink); }
.step-pos .pos-n { font-family: var(--serif-display); font-size: 32px; line-height: 1; letter-spacing: -1px; }
.step-pos .pos-of { font-family: var(--serif-display); font-size: 18px; line-height: 1; color: var(--muted); }

/* ------------------------------------------------------------ wizard */
.turn { border-top: 1px solid var(--hairline); padding: 18px 0; }
.turn:first-of-type { border-top: 0; }
.turn-who { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.7px; color: var(--muted); }
.turn-text { font-family: var(--serif-body); font-size: 18px; line-height: 1.55; margin-top: 8px; white-space: pre-wrap; }
.turn.mine .turn-text { color: var(--ink-soft); }
/* An interview turn rendered as markdown: borrow .md-preview's element styles
   (lists, bold, code, tables) but shed its editor-preview box — a chat turn is
   flow, not a framed pane. */
.turn-text.turn-md {
  border: 0;
  background: none;
  padding: 0;
  min-height: 0;
  max-height: none;
  overflow: visible;
  white-space: normal;
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink);
}
.turn-working { color: var(--muted); font-size: 15px; padding: 18px 0; }
/* A document that entered the conversation: the transcript shows the chip,
   the model reads the extracted text. Dumping 200k characters of OCR into a
   chat log buries the interview it belongs to. */
.turn-file {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 8px; padding: 6px 12px;
  border: 1px solid var(--border); background: var(--surface);
  font-family: var(--sans); font-size: 13px; color: var(--ink-soft);
}

/* ---- the build screen: one quiet door to the other mode */
.mode-flip {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; margin-top: 2px;
  font-family: var(--sans); font-size: 14px; color: var(--muted); text-decoration: none;
}
.mode-flip:hover, .mode-flip:focus-visible { color: var(--ink); }

/* ---- chat shell: transcript flows, composer docks */
.chat-screen { display: flex; flex-direction: column; min-height: calc(100dvh - 300px); margin-top: 18px; }
.chat-log { flex: 1; min-height: 0; }
.composer-wrap {
  position: sticky; bottom: 0; z-index: 20; padding-top: 18px;
  background: linear-gradient(to bottom, transparent, var(--canvas) 18px);
}
/* .action-bar is sticky app-wide; inside the already-sticky composer wrap that
   would stack two pinned layers and double the hairline over the composer. */
.composer-wrap .action-bar { position: static; margin-top: 0; border-top: 0; padding: 14px 0 22px; }
.composer { border: 1px solid var(--border); background: var(--surface); }
.composer textarea {
  width: 100%; display: block; border: 0; background: none; padding: 14px;
  font-family: var(--serif-body); font-size: 17px; line-height: 1.5; color: var(--ink);
  resize: none; outline: none; overflow-y: auto; max-height: 220px;
}
.composer-bar { display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 6px; border-top: 1px solid var(--hairline); }
.composer-attach {
  flex: none; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  border: 0; background: none; color: var(--muted); cursor: pointer;
}
.composer-attach:hover, .composer-attach:focus-visible { color: var(--ink); }
.composer-note { flex: 1; min-width: 0; font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.composer-send {
  flex: none; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; border: 1px solid var(--ink); background: var(--ink); color: var(--canvas); cursor: pointer;
}
.composer-send:disabled { border-color: var(--border); background: var(--surface); color: var(--muted); cursor: default; opacity: 1; }

/* ---- the interview's draft, shown as what it will become */
.draft-card { margin-top: 20px; border: 1px solid var(--border); background: var(--surface); padding: 20px; }
.draft-card-title { font-family: var(--serif-display); font-size: 24px; line-height: 1.25; margin-top: 10px; }
.draft-row { display: flex; gap: 12px; align-items: baseline; border-top: 1px solid var(--hairline); padding: 12px 0; }
.draft-row-n { flex: none; font-family: var(--sans); font-size: 12px; color: var(--muted); width: 16px; }
.draft-row-label { flex: 1; min-width: 0; font-family: var(--sans); font-size: 16px; color: var(--ink); }

/* ---- manual builders */
.mp-title {
  width: 100%; display: block; min-height: 52px; padding: 0 14px;
  border: 1px solid var(--border); background: var(--surface);
  font-family: var(--sans); font-size: 16px; color: var(--ink);
}
.mc-step { display: flex; align-items: flex-start; gap: 12px; border: 1px solid var(--border); background: var(--surface); padding: 14px; }
.mc-step-n {
  flex: none; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: var(--canvas); font-family: var(--sans); font-size: 13px;
}
.mc-step-main { flex: 1; min-width: 0; }
.mc-step select {
  width: 100%; min-height: 44px; padding: 0 8px; border: 1px solid var(--border);
  background: var(--canvas); font-family: var(--sans); font-size: 15px; color: var(--ink);
}
.mc-step-remove {
  flex: none; width: 44px; height: 44px; border: 0; background: none;
  color: var(--muted); font-family: var(--sans); font-size: 18px; cursor: pointer;
}
.mc-step-remove:hover, .mc-step-remove:focus-visible { color: var(--ink); }
.mc-connector { display: flex; align-items: center; gap: 8px; margin: 0; padding: 10px 0 10px 14px; font-size: 13px; color: var(--muted); }
.mc-add {
  display: flex; width: 100%; align-items: center; justify-content: center; gap: 8px; min-height: 56px;
  border: 1px dashed var(--border); background: none;
  font-family: var(--sans); font-size: 15px; color: var(--muted); cursor: pointer;
}
.mc-add:hover, .mc-add:focus-visible { color: var(--ink); border-color: var(--ink); }

/* ------------------------------------------------------------- tables */
.rows { width: 100%; border-collapse: collapse; margin-top: 16px; }
.rows th {
  text-align: left;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.7px;
  color: var(--muted);
  padding: 0 12px 10px 0;
  border-bottom: 1px solid var(--hairline);
}
.rows td { padding: 14px 12px 14px 0; border-bottom: 1px solid var(--hairline); vertical-align: top; font-size: 15px; }
.rows td:last-child, .rows th:last-child { padding-right: 0; }
.rows .num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.table-scroll { overflow-x: auto; }

/* Secrets shown once. Monospace, selectable, visually quarantined. */
.secret {
  font-family: var(--mono);
  font-size: 14px;
  background: var(--canvas-soft);
  border: 1px dashed var(--ink);
  padding: 12px 14px;
  margin-top: 10px;
  word-break: break-all;
  user-select: all;
}

/* ------------------------------------------------------------- the menu */
/* One control in the bar, one panel holding every destination. Replaces both
   the top-nav strip and the phone bottom-nav: five links and a sign-out spread
   across two bars was the app describing itself in two places at once, in the
   two places the eye lands first. */

.menu-toggle {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  margin-right: -10px;      /* optical: the bars align with the text edge */
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  cursor: pointer;
}
.menu-toggle__bar { width: 22px; height: 1px; background: var(--ink); }
.menu-toggle:hover .menu-toggle__bar { background: var(--link); }
.menu-toggle:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

.menu-panel {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.menu-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 3.75rem;
  flex: none;
}
.menu-panel__head .brand__name {
  font-family: var(--serif-display);
  font-size: 18px;
  font-weight: 500;
  color: var(--ink);
}
.menu-close {
  width: 44px;
  height: 44px;
  margin-right: -10px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  font-family: var(--sans);
  font-size: 30px;
  line-height: 1;
  color: var(--ink);
  cursor: pointer;
}
.menu-close:hover { color: var(--link); }
.menu-close:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

/* The destinations. Centred and set in the display serif on a phone, because
   with the whole window to work in there is no reason to make them small. */
.menu-nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 24px;
}
.menu-nav a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  padding: 0 16px;
  font-family: var(--serif-display);
  font-size: 30px;
  line-height: 1.2;
  color: var(--muted);
  text-decoration: none;
}
.menu-nav a:hover { color: var(--ink); }
/* Two changes, not one: colour AND weight. Where you are should not need a
   second look. */
.menu-nav a.on { color: var(--ink); font-weight: 600; }

.menu-foot {
  flex: none;
  display: flex;
  justify-content: center;
  gap: 10px;
  padding: 24px 24px calc(32px + env(safe-area-inset-bottom, 0px));
}
/* Install and Sign out are the same kind of thing — a quiet bordered control
   at the foot of the menu, neither of them the page's one filled element. */
.menu-signout, .menu-install {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 20px;
  font-family: var(--sans);
  font-size: 15px;
  color: var(--muted);
  text-decoration: none;
  background: none;
  border: 1px solid var(--border);
  border-radius: 0;
  cursor: pointer;
}
.menu-signout:hover, .menu-install:hover { color: var(--ink); border-color: var(--ink); }

/* A phone cannot scroll the page behind a full-window menu. A desk can, and
   locking it there would be taking something away for no reason. */
@media (max-width: 899px) {
  body.menu-open { overflow: hidden; }
}

/* On a desk the panel drops out of the bar instead of swallowing the window:
   the screen is not scarce, and covering a wide layout to show five links
   reads as a malfunction. */
@media (min-width: 900px) {
  .menu-panel {
    inset: auto;
    position: fixed;
    top: 3.75rem;
    /* Right edge lands on the same line as the bar's content edge: .wrap is
       72rem wide with 20px of padding, so past that width the gutter grows. */
    right: max(20px, calc((100vw - 72rem) / 2 + 20px));
    width: 260px;
    max-height: calc(100vh - 5rem);
    border: 1px solid var(--border);
    box-shadow: 0 8px 24px rgba(28, 26, 23, 0.08);
  }
  .menu-panel__head { display: none; }
  .menu-nav {
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    padding: 8px 0;
  }
  .menu-nav a {
    justify-content: flex-start;
    min-height: 48px;
    padding: 0 20px;
    font-family: var(--sans);
    font-size: 16px;
  }
  .menu-nav a.on { font-weight: 700; }
  .menu-foot {
    justify-content: stretch;
    padding: 8px 20px 16px;
    border-top: 1px solid var(--hairline);
  }
  .menu-signout { width: 100%; }
}

/* toast — a save confirmation that does not move the page */
.toast {
  position: fixed;
  /* Anchored to both edges and centred inside them, NOT left:50% — anchoring
     one edge to the middle leaves a long message only half the window to wrap
     into, which on a phone turned a sentence into a five-line column. */
  left: 16px;
  right: 16px;
  bottom: 24px;
  width: fit-content;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 44px;
  background: var(--ink);
  color: var(--surface);
  font-size: 15px;
  padding: 10px 20px;
  z-index: 60;
  max-width: calc(100% - 32px);
}
/* A toast that asks for something — so far only "a new version is ready".
   The toast is already the filled element, so the action inside it is text. */
.toast__action {
  flex: none;
  background: none;
  border: 0;
  padding: 0;
  min-height: 44px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 700;
  color: var(--surface);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* An iPhone never offers to install anything, so the one-time hint is the only
   way this ever gets onto a home screen. It sits at the foot of the window,
   says the two steps, and does not come back once dismissed. */
.install-hint {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 55;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 20px calc(14px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-top: 1px solid var(--border);
}
.install-hint p { flex: 1; font-size: 15px; line-height: 1.4; color: var(--ink); margin: 0; }
.install-hint .btn-text { flex: none; padding: 0; min-height: 44px; }

/* -------------------------------------------------------------- desktop */
@media (min-width: 768px) {
  h1 { font-size: 42px; letter-spacing: -0.6px; }
  main { padding-top: 48px; }
}

/* ------------------------------------------------------------- variants
   The Variants tab (story rows + 48px ownership control), the active-variant
   banner, and the full-screen save-as-variant sheet.
   docs/plans/prompt-variants.md */

.vbanner { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 4px; }
.vbanner .btn-text { flex-shrink: 0; }

.status-tag.warn { border-color: #a4553a; color: #a4553a; font-weight: 400; }

.vrow { display: flex; align-items: stretch; border-bottom: 1px solid var(--hairline); }
.vrow-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 16px 8px 16px 0;
  cursor: pointer;
  font: inherit;
  color: var(--ink);
}
.vrow-main:hover .vrow-name, .vrow-main:focus-visible .vrow-name { text-decoration: underline; }
.vrow-name { font-weight: 600; font-size: 17px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.vrow-meta { color: var(--muted); font-size: 14px; }
.vrow-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.vrow-tags .tag { pointer-events: none; }

/* The ownership control: one glyph, one word, 48px target, no names.
   Faint = private, ink = shared; the inbound tray = shared TO you. */
.vrow-own {
  flex-shrink: 0;
  width: 56px;
  min-height: 48px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: 11px;
  letter-spacing: 0.4px;
}
.vrow-own.is-private { color: var(--muted); }
.vrow-own.is-shared, .vrow-own.is-theirs { color: var(--ink); }
.vrow-own:hover, .vrow-own:focus-visible { color: var(--ink); }
.vrow-own svg { display: block; }

.vrow-panel { border-bottom: 1px solid var(--hairline); padding: 14px 8px 18px 0; background: var(--canvas-soft, transparent); }


/* tag chips act as filters on this tab */
[data-variant-chip] { cursor: pointer; background: transparent; font: inherit; }
[data-variant-chip].on { background: var(--ink); color: var(--surface); border-color: var(--ink); }

/* ---- the save sheet: a full-window layer, like the phone menu */
.vsheet {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: var(--canvas);
  display: flex;
  flex-direction: column;
}
.vsheet-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
}
.vsheet-head strong { flex: 1; text-align: center; font-size: 16px; }
.vsheet-step { color: var(--muted); font-size: 14px; min-width: 28px; text-align: right; }
.vsheet-x {
  background: transparent;
  border: 0;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  color: var(--ink);
  min-width: 44px;
  min-height: 44px;
}
.vsheet-body { flex: 1; overflow-y: auto; padding: 20px 16px 32px; max-width: 720px; width: 100%; margin: 0 auto; }
.vsheet-foot { border-top: 1px solid var(--hairline); padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px)); background: var(--canvas); }
.vsheet-foot .btn { max-width: 720px; margin: 0 auto; }

/* ---- bottom sheet: a picker that rises from the foot of the window. The
   strip's Examples and Sources rows open one each. Unlike the full-window
   vsheet, the page stays visible behind a dimmed backdrop — the sheet is a
   quick errand, not a change of place. */
.bsheet {
  position: fixed; inset: 0; z-index: 70;
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(31, 27, 20, 0.35);
}
.bsheet-panel {
  width: 100%; max-width: 720px; max-height: 82dvh;
  background: var(--canvas);
  border: 1px solid var(--hairline); border-bottom: 0;
  border-radius: 14px 14px 0 0;
  display: flex; flex-direction: column;
}
.bsheet-head { display: flex; align-items: center; gap: 12px; padding: 8px 8px 8px 20px; border-bottom: 1px solid var(--hairline); }
.bsheet-head strong { flex: 1; font-size: 16px; }
.bsheet-body { overflow-y: auto; padding: 14px 20px calc(20px + env(safe-area-inset-bottom, 0px)); }
.bsheet-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--hairline); margin: 0;
  cursor: pointer; font-size: 15px; color: var(--ink);
  text-transform: none; letter-spacing: 0; font-weight: 400;
}
.bsheet-row input[type="checkbox"] { margin-top: 3px; }
.bsheet-row-main { min-width: 0; }
.strip-line[data-sheet-open] { cursor: pointer; }
.strip-note { margin: 2px 0 10px; }
.strip-note:empty { display: none; }

.vout-group { margin-top: 26px; }
.vout-group:first-child { margin-top: 8px; }
.vout-head { display: flex; align-items: baseline; justify-content: space-between; border-bottom: 1px solid var(--hairline); padding-bottom: 8px; }
.vout-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--hairline);
  margin: 0;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  font-size: 16px;
  color: var(--ink);
  cursor: pointer;
}
.vout-row input[type="checkbox"] { margin-top: 3px; }
.vout-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.vout-label { overflow-wrap: anywhere; }
.vout-row.is-off .vout-label { text-decoration: line-through; color: var(--muted); }
.vout-row.is-beaten .vout-label { text-decoration: line-through; color: var(--muted); }
.vout-row.is-done { opacity: 0.55; }
.vout-meta { font-size: 13px; color: var(--muted); }
.vout-meta.warn { color: #a4553a; }

/* the batch anonymize control — dashed, like every add-control in the app */
.vout-anon {
  display: block;
  width: 100%;
  margin-top: 12px;
  padding: 14px;
  background: transparent;
  border: 1px dashed var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  color: var(--ink);
}
.vout-anon:disabled { opacity: 0.5; cursor: default; }

.vsheet-sharerow { border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); margin-top: 24px; }
.vsheet-sharemain {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: transparent;
  border: 0;
  padding: 16px 4px;
  font: inherit;
  font-size: 16px;
  color: var(--ink);
  cursor: pointer;
}
.vsheet-sharemain::after { content: "\203A"; color: var(--muted); }
.vsheet-summary {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  padding: 16px 4px;
  font: inherit;
  font-size: 15px;
  color: var(--muted);
  cursor: pointer;
}
.vsheet-summary:hover { color: var(--ink); }

/* ---- Drive-style share sheet, ported from the Claude-Design share layer:
   scope rows with icon + radio dot, role rows, people picker, Copy link. */
.share-sheet { z-index: 80; background: var(--canvas); }
.share-sheet .vsheet-foot { background: var(--canvas); }
.share-sheet .eyebrow { margin-top: 26px; }
.share-sheet .vsheet-body > .eyebrow:first-child { margin-top: 4px; }
.share-row {
  display: flex;
  width: 100%;
  text-align: left;
  align-items: center;
  gap: 14px;
  min-height: 64px;
  padding: 12px 0;
  border: 0;
  border-top: 1px solid var(--hairline);
  background: none;
  font-family: var(--sans);
  cursor: pointer;
}
.share-row-icon { flex: none; display: flex; color: var(--muted); }
.share-row.on .share-row-icon { color: var(--ink); }
.share-row-main { flex: 1; min-width: 0; }
.share-row-label { display: block; font-size: 16px; color: var(--ink); }
.share-row-sub { display: block; font-size: 13px; color: var(--muted); margin-top: 3px; }
.share-dot { position: relative; flex: none; width: 18px; height: 18px; border: 1.3px solid var(--muted); border-radius: 50%; }
.share-row.on .share-dot { border-color: var(--ink); }
.share-row.on .share-dot::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--ink); }
.share-cut { border-top: 1px solid var(--hairline); }
.share-suggest {
  display: flex;
  width: 100%;
  text-align: left;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 8px 0;
  border: 0;
  border-top: 1px solid var(--hairline);
  background: none;
  font-family: var(--sans);
  cursor: pointer;
}
.share-avatar {
  flex: none;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--hairline);
  font-size: 12px;
  color: var(--muted);
}
.share-suggest-main { flex: 1; min-width: 0; }
.share-suggest-name { display: block; font-size: 15px; color: var(--ink); }
.share-suggest-mail { display: block; font-size: 13px; color: var(--muted); margin-top: 2px; }
.share-plus { flex: none; font-size: 15px; color: var(--muted); }
.share-picked { display: flex; align-items: center; gap: 10px; min-height: 52px; border-top: 1px solid var(--hairline); }
.share-picked-name { flex: 1; min-width: 0; font-size: 15px; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-rolecycle {
  flex: none;
  min-height: 44px;
  padding: 0 8px;
  border: 0;
  background: none;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--muted);
  cursor: pointer;
}
.share-rolecycle:hover, .share-rolecycle:focus-visible { color: var(--ink); }
.share-picked-x { flex: none; width: 44px; height: 44px; border: 0; background: none; color: var(--muted); font-size: 18px; cursor: pointer; }
.share-picked-x:hover, .share-picked-x:focus-visible { color: var(--ink); }
.share-copylink {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  margin-top: 20px;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--sans);
  cursor: pointer;
  color: var(--ink-soft);
}
.share-copylink:hover, .share-copylink:focus-visible { color: var(--ink); }
.share-copylink strong { flex: 1; min-width: 0; text-align: left; font-size: 15px; font-weight: 600; }

/* ------------------------------------------------- workbench, redesigned
   Numbered steps on the Fields tab, the facts strip beneath them, the rules
   stack, and the Prompt tab drawn as a document. */

/* ---- the two things to do, each raised on surface */
.bench-step { background: var(--surface); border: 1px solid var(--border); padding: 24px 20px 20px; margin-top: 20px; }
.bench-step-head { display: flex; align-items: baseline; gap: 12px; }
.bench-step-n { flex: none; font-family: var(--serif-display); font-size: 22px; color: var(--muted); line-height: 1; }
.bench-step-head h2 { flex: 1; min-width: 0; font-family: var(--serif-display); font-size: 22px; font-weight: 500; margin: 0; line-height: 1.15; }
.bench-step-edit {
  flex: none; width: 44px; height: 44px; margin: -8px -10px 0 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted);
}
.bench-step-edit:hover, .bench-step-edit:focus-visible { color: var(--ink); }

/* the way out of typing, beside the progress it interrupts */
.paste-icon {
  flex: none; width: 32px; height: 32px; margin: -6px 0 -6px -6px; padding: 0;
  border: 0; background: none; color: var(--muted); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.paste-icon:hover, .paste-icon:focus-visible { color: var(--ink); }

/* ---- facts and shortcuts: one row each, the count on the right */
.bench-strip { margin-top: 32px; }
.strip-row { border-top: 1px solid var(--hairline); }
.bench-strip > .strip-row:last-child { border-bottom: 1px solid var(--hairline); }
.strip-line { display: flex; align-items: center; gap: 10px; min-height: 52px; }
.strip-action {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 0; margin: 0; border: 0; background: none;
  color: var(--ink-soft); font-family: var(--sans); font-size: 15px; font-weight: 600;
  cursor: pointer; text-transform: none; letter-spacing: 0;
}
.strip-action:hover, .strip-action:focus-visible { color: var(--ink); }
.strip-action.is-static { cursor: default; }
a.strip-action { text-decoration: none; }
.strip-count {
  display: flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 0 0 0 8px; border: 0; background: none;
  color: var(--muted); font-family: var(--sans); font-size: 13px; cursor: pointer;
}
.strip-count:hover, .strip-count:focus-visible { color: var(--ink); }
.strip-count .chev { display: inline-block; transition: transform 0.12s ease; }
.strip-count[aria-expanded="true"] .chev { transform: rotate(180deg); }
.strip-item { display: flex; align-items: center; gap: 10px; min-height: 40px; font-size: 14px; }
.strip-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-soft); }
.strip-item-meta { flex: none; color: var(--muted); font-size: 13px; }

/* attachments read as rows here, not chips - same markup, same handlers */
.strip-row .chip-row { display: block; margin: 0; }
.strip-row .doc-chip {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 40px; margin: 0; padding: 0; border: 0; background: none; font-size: 14px;
}
.strip-row .doc-chip-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-soft); }
.strip-row .doc-chip-meta { flex: none; color: var(--muted); font-size: 13px; }
.strip-row .doc-chip-x { flex: none; width: 40px; height: 40px; }

/* ---- the rules stack: what the model reads, top to bottom */
.rstack { margin-top: 20px; }
.rstack-arrow { display: flex; justify-content: center; padding: 2px 0; color: var(--muted); font-size: 15px; line-height: 1; }
.rstack-band { border: 1px solid var(--hairline); background: var(--surface); padding: 12px 16px 2px; }
.rstack-band.is-body { border-color: var(--ink); background: var(--ink); padding: 14px 16px 16px; }
.rstack-head { display: flex; align-items: baseline; gap: 10px; }
.rstack-head-name { flex: 1; min-width: 0; font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); }
.rstack-head-count { flex: none; font-size: 12px; color: var(--muted); }
.rstack-band.is-body .rstack-head-name, .rstack-band.is-body .rstack-head-count { color: rgba(245, 242, 236, 0.7); }
.rstack-title { margin: 10px 0 0; font-family: var(--serif-display); font-size: 20px; line-height: 1.25; color: var(--surface); }
.rstack-inline { margin: 8px 0 0; font-family: var(--mono); font-size: 12px; color: rgba(245, 242, 236, 0.7); }
.rstack-rule {
  display: flex; width: 100%; text-align: left; align-items: flex-start; gap: 12px;
  min-height: 48px; padding: 10px 0; border: 0; background: none;
  font-family: var(--sans); cursor: pointer;
}
div.rstack-rule { cursor: default; }
.rstack-dot { flex: none; width: 12px; height: 12px; margin-top: 5px; }
.rstack-dot.is-prompt { background: var(--ink); }
.rstack-dot.is-domain { background: var(--muted); }
.rstack-dot.is-global { background: var(--hairline); }
.rstack-rule.is-beaten .rstack-dot { opacity: 0.5; }
.rstack-rule-main { flex: 1; min-width: 0; }
.rstack-rule-name { display: block; font-size: 16px; line-height: 1.3; color: var(--ink); }
.rstack-rule.is-beaten .rstack-rule-name { color: var(--muted); text-decoration: line-through; }
.rstack-rule-note { display: block; font-size: 13px; color: var(--muted); margin-top: 4px; }
.rstack-rule-body {
  display: block; font-family: var(--mono); font-size: 13px; line-height: 1.5;
  color: var(--ink-soft); background: var(--canvas-soft); padding: 10px 12px; margin-top: 10px;
  white-space: pre-wrap;
}
.rstack-legend {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 24px; padding-top: 14px; border-top: 1px solid var(--hairline);
  font-size: 12px; color: var(--muted);
}
.rstack-legend span { display: flex; align-items: center; gap: 6px; }
.rstack-legend i { width: 10px; height: 10px; display: block; }
.rstack-legend i.is-prompt { background: var(--ink); }
.rstack-legend i.is-domain { background: var(--muted); }
.rstack-legend i.is-global { background: var(--hairline); }
.rstack-legend-note { flex: 1; min-width: 0; justify-content: flex-end; }
.rstack-edit {
  display: flex; align-items: center; gap: 8px; min-height: 44px;
  color: var(--muted); font-family: var(--sans); font-size: 14px; font-weight: 600; text-decoration: none;
}
.rstack-edit:hover, .rstack-edit:focus-visible { color: var(--ink); }

/* ---- the prompt, as a document */
.doc { margin-top: 16px; border: 1px solid var(--border); background: var(--surface); }
.doc-bar { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--hairline); background: var(--canvas-soft); }
.doc-ins-btn {
  display: flex; align-items: center; gap: 7px; min-height: 36px; padding: 0 10px;
  border: 0; background: none; font-family: var(--sans); font-size: 14px; color: var(--ink-soft); cursor: pointer;
}
.doc-ins-btn:hover, .doc-ins-btn:focus-visible { color: var(--ink); }
.doc-ins-btn .chev { font-size: 10px; color: var(--muted); }
.doc-ins-menu { border-bottom: 1px solid var(--hairline); background: var(--canvas-soft); padding: 2px 8px 8px; }
.doc-ins-menu button {
  display: flex; width: 100%; text-align: left; align-items: baseline; gap: 10px;
  min-height: 44px; padding: 6px 8px; border: 0; background: none; font-family: var(--sans); cursor: pointer;
}
.doc-ins-menu button:hover { background: var(--surface); }
.doc-ins-label { flex: none; font-size: 15px; color: var(--ink); }
.doc-ins-help { flex: 1; min-width: 0; font-size: 13px; color: var(--muted); }
.doc-modes { display: flex; gap: 2px; flex: none; }
.doc-modes button {
  min-height: 34px; padding: 0 12px; border: 1px solid transparent; background: none;
  font-family: var(--sans); font-size: 13px; color: var(--muted); cursor: pointer;
}
.doc-modes button.on { border-color: var(--ink); background: var(--surface); color: var(--ink); }
.doc-paper { padding: 26px 28px; }
textarea.doc-write {
  width: 100%; display: block; border: 0; background: transparent; color: var(--ink);
  font-family: var(--sans); font-size: 16px; line-height: 1.75; resize: vertical; outline: none;
}
.doc-p { margin: 0 0 12px; font-family: var(--sans); font-size: 16px; line-height: 1.75; color: var(--ink); }
.doc-h { margin: 20px 0 8px; font-family: var(--serif-display); font-size: 19px; font-weight: 500; line-height: 1.25; color: var(--ink); }
.doc-li { margin: 0 0 6px 18px; font-family: var(--sans); font-size: 16px; line-height: 1.7; color: var(--ink); text-indent: -14px; }
/* an answer that landed, and a hole where one did not */
.doc-val { background: rgba(5, 125, 188, 0.10); border-radius: 2px; padding: 0 2px; }
.doc-hole { background: rgba(168, 115, 10, 0.12); color: #7a5406; border-radius: 2px; padding: 0 6px; font-size: 14px; }
.doc-rule { color: var(--ink-soft); }
.doc-status {
  display: flex; align-items: center; gap: 14px; padding: 8px 14px;
  border-top: 1px solid var(--hairline); background: var(--canvas-soft);
  font-size: 13px; color: var(--muted);
}
.doc .budget { margin: 0; padding: 0 14px 10px; background: var(--canvas-soft); }

/* ---- connections, drawn as a flow */
.wire-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.wire-card { border: 1px solid var(--border); background: var(--surface); }
.wire-head { display: flex; align-items: center; gap: 12px; padding: 12px 14px; }
.wire-icon {
  flex: none; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--canvas-soft); color: var(--ink-soft);
}
.wire-main { flex: 1; min-width: 0; }
.wire-name { font-family: var(--sans); font-size: 16px; color: var(--ink); }
.wire-sub { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wire-pill {
  position: relative;
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  min-height: 36px; padding: 0 14px; margin: 0; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--muted);
  font-family: var(--sans); font-size: 13px; text-transform: none; letter-spacing: 0; font-weight: 400;
}
.wire-pill.is-on { border-color: var(--ink); background: var(--ink); color: var(--canvas); }
.wire-pill input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.wire-body { border-top: 1px solid var(--hairline); padding: 14px; display: flex; flex-direction: column; gap: 12px; }
.wire-row { display: flex; align-items: center; gap: 12px; margin: 0; text-transform: none; letter-spacing: 0; font-weight: 400; }
.wire-row-label { flex: none; width: 74px; font-size: 13px; color: var(--muted); }
.wire-row select { flex: 1; min-width: 0; min-height: 44px; }
.wire-note { margin: 0; font-size: 13px; color: var(--muted); }
.wire-body .secret { margin: 0; }
.secret[data-copy-secret] { cursor: pointer; }
.secret[data-copy-secret].copied { border-style: solid; }
.wire-foot {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  border-top: 1px solid var(--hairline); background: var(--canvas-soft); font-size: 13px; color: var(--muted);
}
.wire-foot .is-paused { color: #7a5406; }
.wire-flow { display: flex; flex-direction: column; align-items: center; margin-top: 14px; }
.wire-stem { width: 1px; height: 20px; background: var(--border); }
.wire-chip {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px;
  border: 1px solid var(--ink); background: var(--ink); color: var(--canvas);
  font-family: var(--sans); font-size: 14px;
}
.wire-add { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px dashed var(--border); }

/* ---- variant rows: the in-use pill, and the way into what one carries */
.vrow-pill {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: 0.5px;
  text-transform: uppercase; color: var(--surface); background: var(--ink);
  padding: 3px 7px; margin-left: 10px; vertical-align: middle;
}
.vrow-pencil {
  flex: none; min-width: 44px; min-height: 48px;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: none; cursor: pointer; color: var(--muted);
}
.vrow-pencil:hover, .vrow-pencil:focus-visible { color: var(--ink); }

/* ---- the variant contents sheet */
.vsheet-ro { margin-top: 18px; }
.vsheet-desc { border-bottom: 1px solid var(--hairline); margin-top: 18px; padding-bottom: 4px; }
.vsheet-desc-head { display: flex; align-items: baseline; gap: 12px; }
.vsheet-desc-head .eyebrow { flex: 1; min-width: 0; }
.vsheet-describe {
  flex: none; display: flex; align-items: center; gap: 7px; min-height: 44px; padding: 0;
  border: 0; background: none; color: var(--ink-soft);
  font-family: var(--sans); font-size: 14px; font-weight: 600; cursor: pointer;
}
.vsheet-describe:hover, .vsheet-describe:focus-visible { color: var(--ink); }
.vsheet-desc-text { font-family: var(--serif-body); font-size: 17px; line-height: 1.45; margin: 2px 0 12px; color: var(--ink-soft); }
.vsheet-desc-text.is-empty { color: var(--muted); }
.vgroup { margin-top: 22px; }
.vgroup-head { display: flex; align-items: baseline; gap: 12px; }
.vgroup-head .eyebrow { flex: 1; min-width: 0; }
.vitem {
  display: flex; width: 100%; text-align: left; align-items: center; gap: 14px;
  min-height: 56px; padding: 10px 0; border: 0; border-top: 1px solid var(--hairline);
  background: none; font-family: var(--sans); cursor: pointer;
}
.vitem[disabled] { cursor: default; }
.vitem-box {
  flex: none; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;
  font-size: 14px; border: 1px solid var(--ink); background: var(--ink); color: var(--surface);
}
.vitem.is-off .vitem-box { border-color: var(--border); background: transparent; color: transparent; }
.vitem-main { flex: 1; min-width: 0; }
.vitem-label { display: block; font-size: 16px; line-height: 1.35; color: var(--ink-soft); }
.vitem.is-off .vitem-label { color: var(--muted); text-decoration: line-through; }
.vitem-meta { display: block; font-size: 13px; color: var(--muted); margin-top: 3px; }
.vitem-anon {
  flex: none; min-height: 36px; padding: 0 10px; border: 1px solid var(--border);
  background: var(--surface); color: var(--muted); font-family: var(--sans); font-size: 13px; cursor: pointer;
}
.vitem-anon:hover { border-color: var(--ink); color: var(--ink); }

/* ============================================================ automations
   The workbench's Automations tab, redesigned to the Claude-Design export
   (docs/Mobile-first web app simplification): each automation is a sentence
   card — closed, one readable line; open, a short stack of selects and row
   cards. The one place this paper allows color: a schedule's health (green
   running, red failing) — status, not decoration. */

.auto-stack { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.auto-card { border: 1px solid var(--border); background: var(--surface); }
.auto-card.is-paused { opacity: 0.75; }
.auto-head {
  display: flex; width: 100%; text-align: left; align-items: flex-start; gap: 12px;
  min-height: 56px; padding: 14px 16px; border: 0; background: none; cursor: pointer;
  font-family: var(--sans);
}
.auto-ico { flex: none; margin-top: 3px; color: var(--muted); }
.auto-ico.is-on { color: #3e7a4e; }
.auto-ico.is-bad { color: #a13d2d; }
.auto-head-main { flex: 1; min-width: 0; }
.auto-title { display: block; font-size: 16px; font-weight: 600; color: var(--ink); }
.auto-sentence { display: block; margin-top: 3px; font-size: 14px; line-height: 1.5; color: var(--muted); }
.auto-state {
  flex: none; margin-top: 2px; font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.auto-state.is-on { color: #3e7a4e; }
.auto-state.is-bad { color: #a13d2d; }
.auto-body { padding: 2px 16px 16px 46px; }
.auto-error { margin: 0 0 8px; font-size: 13px; color: #a13d2d; }
.auto-fieldblock { display: block; margin-top: 10px; text-transform: none; letter-spacing: 0; font-weight: 400; }
.auto-microlabel {
  display: block; font-size: 12px; font-weight: 700; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--muted);
}
.auto-microlabel-soft { display: block; font-size: 12px; color: var(--muted); }
.auto-select, .auto-input {
  width: 100%; display: block; margin-top: 6px; min-height: 48px; padding: 0 12px;
  border: 1px solid var(--border); background: var(--surface); font-family: var(--sans);
  font-size: 15px; color: var(--ink);
}
.auto-note { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.auto-rows { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.auto-rowcard { border: 1px solid var(--hairline); background: var(--canvas-soft); }
.auto-rowcard.is-off { opacity: 0.55; }
.auto-rowcard .auto-input { min-height: 44px; margin-top: 4px; background: var(--surface); }
.auto-row-head {
  display: flex; width: 100%; text-align: left; align-items: baseline; gap: 10px;
  min-height: 48px; padding: 12px 14px; border: 0; background: none; cursor: pointer;
  font-family: var(--sans);
}
.auto-row-main { flex: 1; min-width: 0; }
.auto-row-title { display: block; font-size: 15px; font-weight: 600; color: var(--ink); }
.auto-row-sub {
  display: block; margin-top: 2px; font-size: 13px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.auto-row-chev { flex: none; font-size: 11px; color: var(--muted); }
.auto-row-head[aria-expanded="true"] .auto-row-chev { display: inline-block; transform: rotate(180deg); }
.auto-row-body { padding: 0 14px 14px; }
.auto-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; align-self: center; background: var(--border); }
.auto-row-head .auto-dot { align-self: flex-start; margin-top: 6px; }
.auto-dot.is-ok, .auto-dot.is-dispatched { background: #3e7a4e; }
.auto-dot.is-running, .auto-dot.is-pending, .auto-dot.is-waiting,
.auto-dot.is-baseline, .auto-dot.is-skipped { background: var(--muted); }
.auto-dot.is-fetch_failed, .auto-dot.is-run_failed, .auto-dot.is-deliver_failed,
.auto-dot.is-config_error, .auto-dot.is-failed, .auto-dot.is-warning { background: #a13d2d; }
.auto-links { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 12px; }
.btn-text.is-link { color: var(--link); }
.btn-text.is-link:hover, .btn-text.is-link:focus-visible { color: var(--ink); }
.auto-add {
  display: flex; width: 100%; align-items: center; justify-content: center; gap: 8px;
  min-height: 52px; margin-top: 10px; border: 1px dashed var(--border); background: none;
  font-family: var(--sans); font-size: 15px; color: var(--ink-soft); cursor: pointer;
}
.auto-add:hover, .auto-add:focus-visible { border-color: var(--ink-soft); color: var(--ink); }
.auto-runs { margin-top: 10px; border-top: 1px solid var(--hairline); }
.auto-run { display: flex; align-items: baseline; gap: 12px; padding: 13px 2px; border-bottom: 1px solid var(--hairline); }
.auto-run .auto-dot { align-self: center; }
.auto-run-when { flex: none; width: 112px; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.auto-run-what { flex: 1; min-width: 0; font-size: 14px; color: var(--ink-soft); }
.auto-import textarea { width: 100%; font-family: var(--mono); font-size: 13px; }

/* The 46px head indent is generous on a desktop, greedy on a phone. */
@media (max-width: 560px) {
  .auto-body { padding-left: 16px; }
}

[data-auto-test-note] { white-space: pre-wrap; font-family: var(--mono); font-size: 12.5px; max-height: 260px; overflow-y: auto; }

/* ---- Settings › Account: the identity block, and the experience ladder.

   The identity block is a photo and your own name in the page's display face,
   with the address you sign in with under it. The name is an INPUT wearing that
   face rather than a label above a box: there is one fact here, it is already
   on screen, and a field that looks like what it edits needs no caption saying
   so. It saves on blur (app.js), which is why there is no button. */
.account-hero {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 22px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--hairline);
}
.account-avatar {
  flex: none;
  width: 64px;
  height: 64px;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: 50%;
  background: var(--surface);
  overflow: hidden;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.account-avatar:hover, .account-avatar:focus-visible { border-color: var(--ink); }
.account-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The display face, not the body serif: this line sits where an <h1> would and
   has to belong to the same page as the one above it. */
.account-avatar__initial { font-family: var(--serif-display); font-size: 26px; line-height: 1; color: var(--ink-soft); }
.account-hero__body { min-width: 0; flex: 1; }
.account-hero__name {
  width: 100%;
  min-height: 38px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--serif-display);
  font-size: 21px;
  line-height: 1.2;
  color: var(--ink);
}
.account-hero__name::placeholder { color: var(--muted); }
.account-hero__name:focus { outline: none; box-shadow: none; }

/* The ladder. Three rows, hairline-separated, reading dot · label · depth.
   It no longer reuses .share-row: the share sheet's row carries a subtitle and
   this one deliberately does not, and the meter on the right is what replaced
   it — the same fact (how much of the app this is) drawn instead of described,
   so the three options are one glance rather than three paragraphs. */
.tier-list { margin-top: 12px; border-top: 1px solid var(--hairline); }
.tier-row {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 12px 0;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  background: none;
  text-align: left;
  cursor: pointer;
}
.tier-label { flex: 1; min-width: 0; font-family: var(--sans); font-size: 16px; color: var(--ink-soft); }
.tier-row.on .tier-label { color: var(--ink); }
.tier-dot { position: relative; flex: none; width: 18px; height: 18px; border: 1.3px solid var(--muted); border-radius: 50%; }
.tier-row.on .tier-dot { border-color: var(--ink); }
.tier-row.on .tier-dot::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--ink); }
/* Three segments; the first N are filled, where N is how deep that rung goes.
   Grey on the rows you are not on, ink on the row you are — so the meter reads
   as "how much" first and "which one" second, which is the order the question
   is actually asked in. */
.tier-bars { flex: none; display: flex; gap: 3px; }
.tier-bars span { width: 14px; height: 6px; border: 1px solid var(--border); background: transparent; }
.tier-bars span.on { background: var(--border); }
.tier-row.on .tier-bars span.on { border-color: var(--ink); background: var(--ink); }

/* The row you are already on. Disabled so it cannot be re-posted, but a button
   greyed by the browser reads as "broken", and this one is the answer to the
   question — so it keeps full contrast and drops only the pointer. */
.tier-row:disabled, .share-row:disabled { opacity: 1; cursor: default; }

/* --------------------------------------------------- navigation feedback */
/* Full-document navigation means the old page sits on screen until the new
   one arrives. This is the tap's acknowledgment: the page steps back and a
   thin bar starts along the top within one frame, so the wait reads as "on
   its way" rather than "did that register?". app.js adds the class on any
   real link tap; the navigation replacing the document is what removes it.
   The bar decelerates toward 85% and parks — it never pretends to finish. */
html.nav-pending main {
  opacity: 0.45;
  transition: opacity 0.12s ease;
  pointer-events: none;
}
html.nav-pending::after {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  width: 0;
  background: var(--link);
  z-index: 200;
  animation: nav-crawl 8s cubic-bezier(0.15, 0.8, 0.25, 1) forwards;
}
@keyframes nav-crawl {
  from { width: 0; }
  to { width: 85%; }
}
@media (prefers-reduced-motion: reduce) {
  html.nav-pending main { transition: none; }
  html.nav-pending::after { animation: none; width: 40%; }
}
