/* Collecxo UI — design system v1 (light theme). Spec: docs/design/system.md
   Plain CSS, no build step. Logical properties (RTL-ready). Dev lifts this file
   into app/public/ when a page is implemented; mockups link it directly. */

:root {
  /* Color — surface and text */
  --bg: #F5F6F8;
  --surface: #FFFFFF;
  --ink: #0F1C2E;          /* headings, primary buttons */
  --text: #2B3646;         /* body */
  --muted: #5B6675;        /* secondary text, 5.9:1 on white */
  --line: #E3E6EB;         /* card + divider borders */
  --line-strong: #8A94A3;  /* input and button borders, 3.07:1 on white (WCAG 1.4.11) */

  /* Brand accent (brass). Fills and highlights only. Text on white uses --accent-ink. */
  --accent: #9C7A3C;
  --accent-ink: #7A5F2E;   /* 5.9:1 on white */
  --accent-tint: #F7F1E6;

  /* Status — each has ink (text/icon, AA on its tint), tint (background), edge (border) */
  --ok-ink: #1F6B4A;       --ok-tint: #E6F3EC;      --ok-edge: #B9DCC9;
  --warn-ink: #8A5A00;     --warn-tint: #FDF3DC;    --warn-edge: #EBD196;
  --bad-ink: #B3322B;      --bad-tint: #FCEBEA;     --bad-edge: #F0BDB9;
  --info-ink: #2E5C8A;     --info-tint: #EAF1F8;    --info-edge: #BCD3E8;

  /* Type */
  --font: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --fs-xs: 12px; --fs-sm: 13px; --fs-base: 15px; --fs-md: 17px; --fs-lg: 20px; --fs-xl: 28px;

  /* Space (4px base) */
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px; --s-6: 32px; --s-7: 48px;

  /* Shape and depth */
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(15, 28, 46, .06);
  --shadow-md: 0 4px 20px rgba(15, 28, 46, .08);
  --ring: 0 0 0 3px rgba(156, 122, 60, .35);

  --page-w: 1040px;
  --form-w: 640px;
}
/* issue 103 UI languages: Arabic pages use IBM Plex Sans Arabic (the boot block loads it only for lang="ar"). */
:root[lang="ar"] { --font: "IBM Plex Sans Arabic", "IBM Plex Sans", system-ui, sans-serif; }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font-family: var(--font); font-size: var(--fs-base); line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { color: var(--ink); margin: 0; font-weight: 600; letter-spacing: -.01em; line-height: 1.25; }
h1 { font-size: var(--fs-xl); }
h2 { font-size: var(--fs-lg); }
h3 { font-size: var(--fs-md); }
p { margin: 0; }
a { color: var(--accent-ink); }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: var(--ring); border-radius: 6px; }
.num { font-variant-numeric: tabular-nums; }
.sr-only { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ---------- Top bar ---------- */
.topbar { position: sticky; inset-block-start: 0; z-index: 20; background: rgba(255,255,255,.92);
  backdrop-filter: saturate(1.4) blur(8px); border-block-end: 1px solid var(--line); }
.topbar-inner { max-inline-size: var(--page-w); margin-inline: auto; padding: 0 var(--s-5);
  block-size: 60px; display: flex; align-items: center; gap: var(--s-5); }
.wordmark { font-weight: 600; font-size: 18px; color: var(--ink); text-decoration: none; letter-spacing: -.01em;
  display: inline-flex; align-items: center; gap: 8px; }
.wordmark::before { content: ""; inline-size: 10px; block-size: 10px; border-radius: 3px; background: var(--accent); }
.nav { display: flex; align-items: center; gap: 2px; flex: 1; }
.nav a, .nav button.nav-link { font: inherit; font-size: 14px; font-weight: 500; color: var(--muted); text-decoration: none;
  background: none; border: 0; cursor: pointer; padding: 8px 12px; border-radius: var(--r-sm); }
.nav a:hover, .nav button.nav-link:hover { background: var(--bg); color: var(--ink); }
.nav a[aria-current="page"], .nav button[aria-current="page"] { color: var(--ink); background: var(--bg); }
.nav-end { margin-inline-start: auto; display: flex; align-items: center; gap: var(--s-2); }
/* qa-26 (Dan, 2026-10-08): company name + signed-in email in the nav, so an
   admin can see at a glance which company/account the browser is on. Reuses
   --muted (already used throughout this file, e.g. .hint/.card-sub) — no new
   colour. Truncates instead of wrapping/overflowing at narrow widths (qa-26's
   own check: long names/emails must not break the nav at 1280px or 390px). */
.nav-detail { font-size: var(--fs-sm); color: var(--muted); max-inline-size: 180px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
/* A commit on this same branch (92a95e0) narrowed the rule above from
   180px to 130px globally, to fix the nav overflowing at 1200px once
   Overview (a 6th link) was added — but Overview's 6th link went onto
   all 18 pages in Phase 4 (docs/plans/overview-phase1.md), not onto
   Overview alone, so EVERY page has the same 6-link nav and the same
   overflow risk at that width. A page-scoped fix (narrow only on
   overview.html) was tried and measured in a real browser before
   shipping: at a 1200px viewport, a 6-link nav with 180px .nav-detail
   needs 1234px and overflows by ~34px — true on every page, not just
   Overview, so scoping by page alone would have silently reopened the
   same overflow on the other 17 pages, while only fixing truncation.
   The actual constraint is available width, not which page this is, so
   it's fixed here by width instead: 130px only in the narrow band where
   6 links + 180px don't fit, qa-26's 180px default everywhere wider
   (measured: no overflow already at 1280px, qa-26's own tested width).
   docs/decisions.md, 2026-10-10. */
@media (max-width: 1240px) {
  .nav-detail { max-inline-size: 130px; }
}
/* arhitect-237/240 (dev-nav lane) — new, additive rule, not an edit of the
   .nav/.nav-end rules above (collecxo-ui.css is shared with the Overview
   and Installments lanes right now; this only adds a narrower-width case).
   Real-browser measurement (Chromium via Playwright): even with the
   130px .nav-detail narrowing just above, the 6-link nav + Settings +
   nav-end (name, email, Sign out — none of which can shrink any further:
   the links' text can't break, .nav-detail is already at its narrowed
   floor, .btn already carries white-space:nowrap) needs ~1008px, which
   overflows the page at exactly 1000px (not at 1200/1280 — that was
   dev-228's own already-closed check, still correct for those two
   widths). Below --page-w (1040px, used as the breakpoint since that is
   this design system's own "nav fits comfortably" width), nav-end wraps
   onto its own row below the links — the same direction the existing
   <=760px rule already wraps it, not a new pattern. */
@media (max-width: 1040px) {
  /* topbar-inner's base rule fixes block-size: 60px and centers its
     children -- both assume a single-line nav. Once .nav wraps onto two
     lines: (1) center alignment put the wordmark vertically mid-height
     across both lines, floating below the links row instead of pinned to
     the top beside it; (2) the fixed 60px height clipped the second line
     (name/email/Sign out) entirely off the bottom of the header. Both
     confirmed visually in real screenshots before adding this rule. */
  .topbar-inner { align-items: flex-start; block-size: auto; min-block-size: 60px; padding-block: var(--s-2); }
  .nav { flex-wrap: wrap; row-gap: var(--s-2); }
  .nav-end { flex-basis: 100%; justify-content: flex-end; margin-inline-start: 0; }
}
.menu { position: relative; }
.menu-panel { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 6px); min-inline-size: 200px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--shadow-md);
  padding: 6px; z-index: 30; }
.menu-panel a { display: block; padding: 9px 12px; border-radius: 8px; white-space: nowrap; }
/* issue #7 (settings-menu.md: "Current page item is bold with
   aria-current=page") — the existing top-level `.nav a[aria-current]` rule
   (above) never covered items INSIDE the dropdown panel; this was a real
   gap (3 of the Settings dropdown's own pages already set the attribute
   with zero visible effect). Mirrors the design's own approved mockup rule
   (mockups/settings-menu.html: background var(--bg), font-weight 600),
   using the existing --bg token, not a new colour. */
.menu-panel a[aria-current="page"] { background: var(--bg); font-weight: 600; }
.menu-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  padding: 8px 12px 4px; font-weight: 600; }
.btn.nav-toggle { display: none; }
@media (max-width: 760px) {
  .topbar-inner { padding: 0 var(--s-4); gap: var(--s-3); }
  .btn.nav-toggle { display: inline-flex; margin-inline-start: auto; }
  .nav { display: none; position: absolute; inset-inline: 0; inset-block-start: 60px; background: var(--surface);
    border-block-end: 1px solid var(--line); padding: var(--s-3) var(--s-4) var(--s-4); flex-direction: column; align-items: stretch; gap: 2px; }
  .nav.open { display: flex; }
  .nav a, .nav button.nav-link { padding: 12px; font-size: var(--fs-base); text-align: start; }
  .nav-end { margin: var(--s-2) 0 0; padding-block-start: var(--s-2); border-block-start: 1px solid var(--line);
    flex-wrap: wrap; }
  /* qa-26: two nav-detail spans (company name, email) at up to 180px each
     can exceed a 390px row alongside Sign out — wrap onto their own line
     and cap width to the viewport so a single very long string still
     truncates instead of causing horizontal overflow. */
  .nav-detail { max-inline-size: calc(100vw - 2 * var(--s-4)); }
  .menu-panel { position: static; box-shadow: none; border: 0; padding: 0 0 0 var(--s-3); }
}

/* ---------- Page ---------- */
.page { max-inline-size: var(--page-w); margin-inline: auto; padding: var(--s-6) var(--s-5) var(--s-7); }
.page-narrow { max-inline-size: calc(var(--form-w) + 2 * var(--s-5)); }
.page-header { margin-block-end: var(--s-5); }
.page-header p { color: var(--muted); margin-block-start: var(--s-2); max-inline-size: 60ch; }
.crumb { font-size: var(--fs-sm); color: var(--muted); margin-block-end: var(--s-2); }
@media (max-width: 760px) {
  .page { padding: var(--s-5) var(--s-4) var(--s-7); }
  h1 { font-size: 24px; }
}

/* ---------- Card ---------- */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: var(--shadow-sm); padding: var(--s-5); }
.card + .card { margin-block-start: var(--s-4); }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); margin-block-end: var(--s-4); }
.card-sub { color: var(--muted); font-size: var(--fs-sm); }
@media (max-width: 760px) { .card { padding: var(--s-4); } }

/* ---------- Buttons ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-block-size: 44px;
  padding: 0 var(--s-4); font: inherit; font-size: var(--fs-base); font-weight: 500; border-radius: var(--r-sm);
  border: 1px solid transparent; cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background .12s, border-color .12s, box-shadow .12s; }
.btn-primary { background: var(--ink); color: var(--on-ink); }
.btn-primary:hover { background: #1B2E47; }
.btn-secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn-secondary:hover { border-color: var(--ink); }
.btn-ghost { background: transparent; color: var(--accent-ink); padding: 0 var(--s-3); }
.btn-ghost:hover { background: var(--accent-tint); }
.btn-danger { background: var(--surface); color: var(--bad-ink); border-color: var(--bad-edge); }
.btn-danger:hover { background: var(--bad-tint); }
.btn-danger-solid { background: var(--bad-ink); color: #fff; border-color: var(--bad-ink); }
.btn-danger-solid:hover { background: #7E1F1A; }
.btn-sm { min-block-size: 36px; font-size: var(--fs-sm); padding: 0 var(--s-3); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.btn-row { display: flex; gap: var(--s-3); flex-wrap: wrap; align-items: center; }
/* Playbook "On these days" chips (issue #44) — checked state reuses the
   same --ok-tint/--ok-ink pair .badge-ok already uses; unchecked is
   explicitly muted/dashed rather than left to look the same as "on". */
.day-chip .chk { display: none; inline-size: 14px; block-size: 14px; }
.day-chip[aria-pressed="true"] { background: var(--ok-tint); color: var(--ok-ink); border-color: var(--ok-ink); font-weight: 600; }
.day-chip[aria-pressed="true"] .chk { display: inline-block; }
.day-chip[aria-pressed="false"] { background: var(--bg); color: var(--muted); border-style: dashed; }
.spinner { inline-size: 16px; block-size: 16px; border-radius: 50%; border: 2px solid currentColor; border-inline-end-color: transparent;
  animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2s; } * { transition: none !important; } }
@media (max-width: 480px) { .btn-row .btn { flex: 1 1 auto; } }

/* ---------- Form ---------- */
.field { margin-block-end: var(--s-4); }
.field > label, .label { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--ink); margin-block-end: 6px; }
.input, .select { inline-size: 100%; min-block-size: 44px; padding: 0 var(--s-3); font: inherit; font-size: var(--fs-base);
  color: var(--ink); background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-sm); }
.select { appearance: none; -webkit-appearance: none; block-size: 44px; padding-inline-end: 40px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%230F1C2E' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; }
.input::placeholder { color: #6B7686; }
.input:hover, .select:hover { border-color: var(--muted); }
.input:focus, .select:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.input[aria-invalid="true"] { border-color: var(--bad-ink); }
.hint { font-size: var(--fs-sm); color: var(--muted); margin-block-start: 6px; }
.field-error { font-size: var(--fs-sm); color: var(--bad-ink); margin-block-start: 6px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--s-4); }
.grid-host { display: grid; grid-template-columns: 1fr 140px; gap: 0 var(--s-4); }
@media (max-width: 560px) { .grid-2, .grid-host { grid-template-columns: 1fr; } }
.check { display: flex; gap: var(--s-3); align-items: flex-start; font-size: var(--fs-base); cursor: pointer; padding-block: var(--s-2); }
.check input { inline-size: 20px; block-size: 20px; margin: 2px 0 0; accent-color: var(--ink); flex-shrink: 0; }
.form-actions { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; margin-block-start: var(--s-5);
  padding-block-start: var(--s-4); border-block-start: 1px solid var(--line); }

/* ---------- Badge ---------- */
.badge { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; line-height: 1;
  padding: 5px 10px; border-radius: var(--r-pill); white-space: nowrap; border: 1px solid transparent; }
.badge::before { content: ""; inline-size: 6px; block-size: 6px; border-radius: 50%; background: currentColor; }
.badge-ok { background: var(--ok-tint); color: var(--ok-ink); }
.badge-warn { background: var(--warn-tint); color: var(--warn-ink); }
.badge-bad { background: var(--bad-tint); color: var(--bad-ink); }
.badge-info { background: var(--info-tint); color: var(--info-ink); }
.badge-neutral { background: var(--bg); color: var(--muted); border-color: var(--line); }

/* ---------- Nav count (docs/plans/replies-c-and-nav-badge.md, §2.5) ----------
   The nav's "Replies N" badge. Reuses only existing tokens (--accent-ink,
   --r-pill, --fs-xs) — no new hex/font-size. Flagged in that plan as the
   implementer's own derivation, not yet a design-system-signed-off rule;
   needs a one-line arhitect/design OK before being treated as permanently
   settled. */
.nav-count { display: inline-flex; align-items: center; justify-content: center;
  min-inline-size: 18px; block-size: 18px; padding: 0 5px; margin-inline-start: 4px;
  border-radius: var(--r-pill); background: var(--accent-ink); color: var(--on-ink);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1; }
.nav-count:empty { display: none; }

/* ---------- Alert (inline message) ---------- */
.alert { display: flex; gap: var(--s-3); align-items: flex-start; padding: var(--s-3) var(--s-4); border-radius: var(--r-sm);
  border: 1px solid; font-size: var(--fs-sm); line-height: 1.5; }
.alert + .alert, .alert + .field, .alert + .btn-row { margin-block-start: var(--s-3); }
.alert svg { flex-shrink: 0; margin-block-start: 2px; }
.alert strong { display: block; font-size: var(--fs-base); margin-block-end: 2px; }
.alert-ok { background: var(--ok-tint); border-color: var(--ok-edge); color: #14492F; }
.alert-warn { background: var(--warn-tint); border-color: var(--warn-edge); color: #5E3D00; }
.alert-bad { background: var(--bad-tint); border-color: var(--bad-edge); color: #7E1F1A; }
.alert-info { background: var(--info-tint); border-color: var(--info-edge); color: #1D3E60; }

/* ---------- Status banner (issue #7, docs/design/specs/company.md
   "Banners", every page) ----------
   A full-width bar above the top bar, not a card-contained box, so it
   can't reuse .alert's own layout — but it DOES reuse .alert-bad/-warn/
   -info directly (combined in markup, e.g. class="status-banner
   alert-bad") for colour: those classes set background/border-color/text
   colour only, no layout, so composing them here adds zero new colour
   literals. border-block-end (no colour given) inherits the colour
   .alert-bad/etc.'s own `border-color` declaration sets — cascade is
   per-property, so that still applies even though it's declared on a
   different class. */
.status-banner { padding: 10px var(--s-5); font-size: var(--fs-sm); display: flex; gap: var(--s-3);
  flex-wrap: wrap; align-items: center; justify-content: center; text-align: center;
  border-block-end: 1px solid; }
.status-banner button { font: inherit; font-weight: 600; background: none; border: 0; color: inherit;
  text-decoration: underline; cursor: pointer; padding: 0; min-block-size: 32px; }
.status-banner a { color: inherit; font-weight: 600; }

/* ---------- Switch (issue #7, Company page Sending/Test-mode rows) ----------
   Formalizes the design's own already-approved, already-token-resolved
   mockup (docs/design/mockups/company.html's .sw/.hdr-sw, lines 14-24 —
   every colour there was already a var(--token), not dev inventing a new
   component; see docs/plans/company-page-settings-menu.md §3 Alternatives).
   Checkbox-based (native keyboard/AT semantics), knob uses --surface
   (not a literal white) and --shadow-sm (not a new rgba literal). .hdr is
   the smaller size used in the header "Sending" switch (Phase C). */
.switch { position: relative; display: inline-flex; flex: none; align-items: center; gap: var(--s-2);
  font-weight: 500; color: var(--ink); cursor: pointer; }
.switch input { position: absolute; opacity: 0; inline-size: 1px; block-size: 1px; }
.switch .track { inline-size: 44px; block-size: 26px; border-radius: var(--r-pill); background: var(--line-strong);
  position: relative; transition: background .15s; flex: none; }
.switch .track::after { content: ""; position: absolute; inset-block-start: 3px; inset-inline-start: 3px;
  inline-size: 20px; block-size: 20px; border-radius: 50%; background: var(--surface); box-shadow: var(--shadow-sm);
  transition: transform .15s; }
.switch input:checked + .track { background: var(--ok-ink); }
.switch input:checked + .track::after { transform: translateX(18px); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: var(--ring); }
.switch.warn input:checked + .track { background: var(--warn-ink); }
.switch.hdr { font-size: var(--fs-sm); margin-inline-start: var(--s-3); }
.switch.hdr .track { inline-size: 36px; block-size: 20px; }
.switch.hdr .track::after { inline-size: 14px; block-size: 14px; }
.switch.hdr input:checked + .track::after { transform: translateX(16px); }

/* ---------- Option tiles (radio cards) ---------- */
.tiles { display: flex; flex-direction: column; border: 1px solid var(--line-strong); border-radius: var(--r-md); overflow: hidden; background: var(--surface); }
.tile { position: relative; display: flex; flex-direction: column; gap: 4px; padding: var(--s-4); cursor: pointer;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-md); text-align: start; font: inherit; color: inherit; }
.tile:hover { border-color: var(--ink); }
.tile-name { font-weight: 600; color: var(--ink); }
.tile-desc { font-size: var(--fs-sm); color: var(--muted); }
.tile[aria-pressed="true"] { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); background: #FBFBFC; }
.tile[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }
.tile[aria-disabled="true"]:hover { border-color: var(--line-strong); }
.tile .badge { align-self: flex-start; margin-block-start: 6px; }

/* ---------- Step list (stepper) ---------- */
.steps { list-style: none; margin: 0; padding: 0; }
.step { position: relative; display: grid; grid-template-columns: 32px 1fr; gap: var(--s-4); padding-block-end: var(--s-4); }
.step:last-child { padding-block-end: 0; }
.step::before { content: ""; position: absolute; inset-inline-start: 15px; inset-block: 36px 0; inline-size: 2px; background: var(--line); }
.step:last-child::before { display: none; }
.step-dot { inline-size: 32px; block-size: 32px; border-radius: 50%; display: grid; place-items: center; font-size: var(--fs-sm); font-weight: 600;
  background: var(--surface); border: 2px solid var(--line-strong); color: var(--muted); z-index: 1; }
.step-done .step-dot { background: var(--ok-ink); border-color: var(--ok-ink); color: var(--on-ink); }
.step-done::before { background: var(--ok-ink); }
.step-now .step-dot { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.step-body { min-inline-size: 0; }
.step-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-4) var(--s-5); box-shadow: var(--shadow-sm); }
.step-now .step-card { border-color: var(--ink); box-shadow: var(--shadow-md); }
.step-next .step-card { background: transparent; box-shadow: none; border-style: dashed; }
.step-top { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; }
.step-title { font-weight: 600; color: var(--ink); font-size: var(--fs-md); }
.step-text { color: var(--muted); font-size: var(--fs-sm); margin-block-start: 4px; overflow-wrap: anywhere; }
.step-actions { margin-block-start: var(--s-3); display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap; }
@media (max-width: 560px) { .step { grid-template-columns: 28px 1fr; gap: var(--s-3); } .step-dot { inline-size: 28px; block-size: 28px; } .step::before { inset-inline-start: 13px; inset-block-start: 32px; } .step-card { padding: var(--s-4); } }

/* ---------- Progress ---------- */
.progress { block-size: 8px; background: var(--line); border-radius: var(--r-pill); overflow: hidden; }
.progress > span { display: block; block-size: 100%; background: var(--ok-ink); border-radius: inherit; transition: inline-size .3s; }

/* ---------- Disclosure ---------- */
.disclosure { border-block-start: 1px solid var(--line); margin-block-start: var(--s-3); }
.disclosure > summary { list-style: none; cursor: pointer; padding: var(--s-3) 0; font-weight: 500; color: var(--accent-ink);
  display: flex; align-items: center; gap: 8px; }
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::before { content: ""; inline-size: 7px; block-size: 7px; border-inline-end: 2px solid currentColor; border-block-end: 2px solid currentColor;
  transform: rotate(-45deg); transition: transform .12s; }
.disclosure[open] > summary::before { transform: rotate(45deg); }

/* ---------- Connected-account row ---------- */
.account { display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; }
/* .avatar (the lettered-circle mark) removed here (docs/plans/
   provider-marks.md, Phase 4 / adversarial review M1) — its only 5
   consumers, all in smtp.html, were swapped for the real provider marks
   below; zero consumers remained anywhere in the repo, so it was deleted
   rather than left as dead CSS. Ported verbatim from the approved mockup,
   docs/design/mockups/smtp-b.html:19 — tokens only, no new colour. */
.pmark { flex: none; inline-size: 40px; block-size: 40px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--line);
  display: grid; place-items: center; overflow: hidden; }
.pmark img, .pmark svg { display: block; }
.pmark-g { border: 0; background: none; overflow: visible; }
.pmark-mail { color: var(--accent-ink); background: var(--accent-tint); border-color: transparent; }
.account-main { min-inline-size: 0; flex: 1; }
.account-name { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.account-meta { font-size: var(--fs-sm); color: var(--muted); }
@media (max-width: 560px) { .account { flex-wrap: wrap; } }

/* ---------- Toast ---------- */
.toast { position: fixed; inset-block-end: var(--s-5); inset-inline: var(--s-4); margin-inline: auto; max-inline-size: 420px; z-index: 50;
  background: var(--ink); color: var(--on-ink); padding: var(--s-3) var(--s-4); border-radius: var(--r-sm); box-shadow: var(--shadow-md);
  display: flex; gap: var(--s-3); align-items: center; font-size: var(--fs-sm); }

/* ---------- Empty state ---------- */
.empty { text-align: center; padding: var(--s-7) var(--s-5); color: var(--muted); }
.empty h3 { margin-block-end: var(--s-2); }

/* ---------- Mockup-only chrome (not part of the system) ---------- */
.demo-bar { background: #FFFBEB; border-block-end: 1px solid var(--warn-edge); font-size: var(--fs-sm); color: #5E3D00; }
.demo-bar-inner { max-inline-size: var(--page-w); margin-inline: auto; padding: 8px var(--s-5); display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap; }
.demo-bar label { display: inline-flex; gap: 6px; align-items: center; margin: 0; font-weight: 500; }
.demo-bar select { font: inherit; padding: 4px 8px; border-radius: 6px; border: 1px solid var(--warn-edge); background: #fff; }

/* Provider list: one vertical list, like the Add Account screen on iPhone/Mac */
.tiles .tile { border: 0; border-radius: 0; border-block-end: 1px solid var(--line); flex-direction: row; flex-wrap: wrap; align-items: center; column-gap: var(--s-3); padding: var(--s-4); position: relative; padding-inline-end: 44px; }
.tiles .tile:last-child { border-block-end: 0; }
.tiles .tile::after { content: ""; position: absolute; inset-inline-end: var(--s-4); inset-block-start: 50%; inline-size: 8px; block-size: 8px; margin-block-start: -4px; border-inline-end: 2px solid var(--muted); border-block-end: 2px solid var(--muted); transform: rotate(-45deg); }
.tiles .tile:hover { background: var(--bg); }
.tiles .tile[aria-pressed="true"] { box-shadow: inset 3px 0 0 var(--ink); background: var(--bg); }
.tiles .tile-desc { flex-basis: 100%; }
.tiles .tile .badge { margin-block-start: 0; margin-inline-start: auto; margin-inline-end: var(--s-3); }

/* Shared patterns added with the Replies mockup (also used by Dashboard) */
.tabs { display: flex; gap: var(--s-1); border-block-end: 1px solid var(--line); margin-block-end: var(--s-5); overflow-x: auto; }
.tab { font: inherit; font-weight: 500; color: var(--muted); background: none; border: 0; border-block-end: 3px solid transparent; padding: 12px var(--s-4); cursor: pointer; white-space: nowrap; min-block-size: 44px; display: inline-flex; gap: 8px; align-items: center; }
.tab:hover { color: var(--ink); }
.tab[aria-selected="true"] { color: var(--ink); border-block-end-color: var(--accent); }
.tab .badge { padding: 3px 8px; }
.textarea { inline-size: 100%; min-block-size: 140px; padding: var(--s-3); font: inherit; font-size: var(--fs-base); color: var(--ink); background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-sm); resize: vertical; line-height: 1.5; }
.textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.link { color: var(--accent-ink); font-weight: 500; text-decoration: none; background: none; border: 0; padding: 0; font-family: inherit; font-size: inherit; cursor: pointer; }
.link:hover { text-decoration: underline; }

/* ---------- Spacing utilities ----------
   Added for the Mailbox settings redesign (docs/plans/mailbox-settings-redesign.md,
   Phase 1, Round 1 adversarial review Material M1): the approved mockup
   (smtp-b.html) itself uses 12 inline margin-block style="..." attributes
   across 6 distinct values. "No inline style" and "ship the mockup's markup
   verbatim" can't both hold, so these resolve it as pure composition of the
   design system's own existing --s-N tokens — not a new design decision. */
.mb-end-4 { margin-block-end: var(--s-4); }
.mb-start-3 { margin-block-start: var(--s-3); }
.mb-start-4 { margin-block-start: var(--s-4); }
.mb-0-3 { margin-block: 0 var(--s-3); }
.mb-1 { margin-block: var(--s-1); }
.mb-2-4 { margin-block: var(--s-2) var(--s-4); }

/* ---------- Home (app.html) redesign ----------
   Added for the Home redesign (docs/plans/home-redesign.md, Phase 2): page-
   composition classes ported from the approved mockup (docs/design/mockups/
   app.html, lines 6-16, values unchanged except one token substitution noted
   below), one new spacing utility, and the progress-fill selectors that
   replace the mockup's dynamic inline style="inline-size:...%" with a
   data-n attribute selector — n only ever takes 6 values (0..5), so a
   static CSS table fully replaces the per-render inline style, no
   style= attribute needed. */
.prow { display: flex; align-items: center; gap: var(--s-4); margin-block-end: var(--s-5); }
.prow .progress { flex: 1; max-inline-size: 320px; }
.prow > span { font-size: var(--fs-sm); color: var(--muted); font-weight: 500; }
.step-done .step-card { background: transparent; box-shadow: none; }
.step-done .step-title { font-weight: 500; color: var(--text); }
.step-done .step-text { display: none; }
/* 32px substituted with var(--s-6), already equal to 32px — token reuse, not
   a new value (same reasoning the Mailbox task used for its own --s-1 case). */
.step-done .step-actions .btn-secondary { border-color: transparent; background: transparent; color: var(--accent-ink); text-decoration: underline; padding-inline: 0; min-block-size: var(--s-6); }
.step-next .step-title { color: var(--text); }
.ask { font-size: var(--fs-sm); color: var(--muted); }
.done-line { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; }
.done-line p { margin: 0; display: flex; gap: var(--s-3); align-items: center; color: var(--ink); font-weight: 500; }
.wel { max-inline-size: var(--form-w); }
.mb-start-5 { margin-block-start: var(--s-5); }
.progress[data-n="0"] > span { inline-size: 0%; }
.progress[data-n="1"] > span { inline-size: 20%; }
.progress[data-n="2"] > span { inline-size: 40%; }
.progress[data-n="3"] > span { inline-size: 60%; }
.progress[data-n="4"] > span { inline-size: 80%; }
.progress[data-n="5"] > span { inline-size: 100%; }

/* ---------- Home step 2: recommended-rules card ----------
   Added for docs/plans/recommended-playbook.md, Phase 4 — ported from the
   approved mockup's own local <style> block (docs/design/mockups/app.html,
   "Revision: recommended rules"), unchanged, composed from existing tokens
   only (no new colours or sizes). A plain list, used both for the active
   card's 4-5 line summary and for the .disclosure's 6-7 "show all" lines. */
.rules { margin: var(--s-3) 0; padding-inline-start: 20px; color: var(--text); }
.rules li { margin-block-end: 6px; }
.rules-more { margin-block-start: 0; }

/* ---------- Overview page: needs-you chips, stage bar ----------
   Ported from the approved mockup (docs/design/mockups/overview-final.html,
   docs/plans/overview-phase1.md Finding F11) — no equivalent component
   existed in this design system yet (system.md's own component list has
   no multi-segment bar or chip-link shape). Flagged for the same one-line
   design/arhitect sign-off system.md's own .nav-count precedent needed —
   not yet confirmed blessed.
   Six of the seven stage colours below reuse an EXISTING token rather than
   the mockup's own near-duplicate literal hex (same "token reuse, not a
   new value" precedent as this file's own --s-6 substitution above):
   reminded->--muted, replied->--ink, promised->--accent-ink,
   broken->--bad-ink, team->--info-ink, partial->--ok-ink. promised uses
   --accent-ink rather than the brighter --accent (found live during
   verification: --accent itself clears the 4.5:1 rule with neither white
   text, 3.99:1, nor dark ink text, 4.29:1 — its own darker sibling,
   already used elsewhere in this system as brass TEXT on white, passes
   white text at 5.99:1 as a FILL instead).
   --stage-new is the one genuinely new colour this component needs (a
   light "nothing sent yet" neutral with no existing equivalent — every
   current token close to it is a border/text colour, too dark for a
   filled bar segment that often carries white text on top). */
:root {
  --stage-new: #B8BFC9;
}

.needs-you { display: flex; gap: var(--s-3); flex-wrap: wrap; }
.needs-you a { display: flex; gap: var(--s-2); align-items: center; padding: 10px 16px 10px 10px;
  border: 2px solid var(--ink); border-radius: var(--r-md); background: var(--surface); color: var(--ink);
  text-decoration: none; font-weight: 600; min-block-size: 48px; }
.needs-you a:hover, .needs-you a:focus-visible { background: var(--ink); color: #fff; }
.needs-you a b { background: var(--bad-ink); color: #fff; border-radius: var(--r-pill); min-inline-size: 28px;
  padding: 2px 9px; text-align: center; }
.needs-you a.warn b { background: var(--warn-ink); }
.needs-you.done { color: var(--ok-ink); font-weight: 600; }

/* Segment width/colour are continuous, per-render values — set via JS
   el.style.setProperty("--w"/"--c", ...), never a literal style=""
   attribute, same escape hatch replies.html's own .prog .progress
   already uses for an identical reason (see that file's own comment). */
.stage-bar { display: flex; block-size: 44px; border-radius: var(--r-sm); overflow: hidden;
  margin-block: var(--s-4); background: var(--bg); }
.stage-bar-segment { display: flex; align-items: center; justify-content: center; gap: 6px;
  min-inline-size: 3px; inline-size: var(--w, 0%); background: var(--c, var(--line-strong)); color: #fff;
  font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; overflow: hidden; font-variant-numeric: tabular-nums; }
.stage-bar-segment.lt { color: var(--ink); }
.stage-legend { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); }
@media (max-width: 900px) { .stage-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stage-legend .dot { display: inline-block; inline-size: 12px; block-size: 12px; border-radius: var(--r-sm);
  background: var(--c, var(--line-strong)); margin-inline-end: 8px; flex-shrink: 0; }
.stage-legend-row { display: flex; align-items: center; gap: 8px; }

/* ---------- Account menu (#41) ---------- */
.acct { position: relative; }
.acct-btn { display: inline-flex; align-items: center; gap: 6px; padding-block: 3px; padding-inline: 3px 8px; border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--surface); color: var(--ink); font: inherit; cursor: pointer; min-block-size: 36px; }
.acct-btn:hover { background: var(--bg); }
.acct-av { inline-size: 28px; block-size: 28px; border-radius: 50%; background: var(--accent-tint); color: var(--accent-ink);
  display: inline-grid; place-items: center; font-size: var(--fs-xs); font-weight: 600; letter-spacing: .02em; }
.acct-chev { inline-size: 14px; block-size: 14px; color: var(--muted); transition: transform .12s; }
.acct-btn[aria-expanded="true"] .acct-chev { transform: rotate(180deg); }
.acct-panel { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 6px); inline-size: 280px; max-inline-size: calc(100vw - 24px);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--shadow-md); padding: 6px; z-index: 30; }
.acct-who { padding: 10px 12px 12px; border-block-end: 1px solid var(--line); margin-block-end: 6px; }
.acct-co { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.acct-em { font-size: var(--fs-sm); color: var(--muted); overflow-wrap: anywhere; margin-block-start: 2px; }
.acct-panel .acct-item { display: block; inline-size: 100%; text-align: start; font: inherit; color: var(--ink); background: none; border: 0; cursor: pointer;
  padding: 9px 12px; border-radius: 8px; text-decoration: none; }
.acct-panel .acct-item:hover { background: var(--bg); }
.acct-inline { display: none; }
@media (min-width: 761px) and (max-width: 1400px) { .nav a, .nav button.nav-link { padding: 8px 9px; } .topbar-inner { gap: var(--s-4); } }
@media (max-width: 760px) {
  .acct-btn, .acct-panel { display: none; }
  .acct-inline { display: block; padding: var(--s-2) 12px; }
  .nav-end { flex-direction: column; align-items: stretch; }
}

/* ---------- Assistant panel (#38) ----------
   Copied from docs/design/mockups/assistant.html, classes prefixed asst- so
   they cannot collide with page rules (.msg, .fab, .toast exist elsewhere).
   No new colours: the mockup's .cant amber maps to --warn-tint/--warn-edge,
   its .warn red to --bad-tint/--bad-edge, white text to --surface, shadows
   to --shadow-md. Font sizes use the type tokens. */
.asst-fab { position: fixed; inset-inline-end: 24px; inset-block-end: 24px; z-index: 15; border: 0; border-radius: var(--r-pill);
  background: var(--ink); color: var(--surface); font: inherit; font-weight: 500; padding: 12px 20px; cursor: pointer; box-shadow: var(--shadow-md); }
.asst-panel { position: fixed; inset-block: 0; inset-inline-end: 0; inline-size: min(440px, 100%); background: var(--surface); z-index: 30;
  display: flex; flex-direction: column; box-shadow: var(--shadow-md); border-inline-start: 1px solid var(--line); }
.asst-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding: var(--s-4); border-block-end: 1px solid var(--line); }
.asst-head h2 { font-size: var(--fs-md); }
.asst-actions { display: flex; gap: var(--s-1); }
.asst-sub { color: var(--muted); font-size: var(--fs-sm); }
.asst-thread { flex: 1; min-block-size: 0; overflow: auto; padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); }
.asst-msg { max-inline-size: 92%; border-radius: var(--r-md); padding: 10px 14px; font-size: var(--fs-base); line-height: 1.45; overflow-wrap: anywhere; }
.asst-user { align-self: flex-end; background: var(--ink); color: var(--surface); }
.asst-bot { align-self: flex-start; background: var(--bg); }
.asst-msg p { margin: 0 0 8px; }
.asst-msg p:last-child { margin: 0; }
.asst-msg ul { margin: 6px 0; padding-inline-start: 18px; }
.asst-src { font-size: var(--fs-xs); color: var(--muted); margin-block-start: 8px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.asst-src a, .asst-msg a, .asst-linkbtn { color: var(--accent-ink); font-weight: 500; }
.asst-linkbtn { font: inherit; font-weight: 500; background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline; }
.asst-work { align-self: flex-start; color: var(--muted); font-size: var(--fs-sm); }
.asst-hello p { margin: 0 0 var(--s-2); }
.asst-starters { display: flex; flex-direction: column; gap: 8px; }
.asst-starter { font: inherit; font-size: var(--fs-sm); text-align: start; border: 1px solid var(--line); background: var(--surface); border-radius: var(--r-sm);
  padding: 9px 12px; cursor: pointer; color: var(--ink); }
.asst-starter:hover { border-color: var(--accent-ink); }
.asst-form { border-block-start: 1px solid var(--line); padding: var(--s-3) var(--s-4); }
.asst-form form { display: flex; gap: 8px; }
.asst-form .input { flex: 1; min-inline-size: 0; }
.asst-note { margin: 8px 0 0; font-size: var(--fs-xs); color: var(--muted); }
.asst-cant { border: 1px solid var(--warn-edge); background: var(--warn-tint); }
.asst-cant .btn { margin-block-start: 6px; }
.asst-err { border: 1px solid var(--bad-edge); background: var(--bad-tint); }
.asst-err .btn { margin-block-start: 6px; }
.asst-cap { background: var(--bg); border-radius: var(--r-sm); padding: 10px 12px; font-size: var(--fs-sm); margin: 0 var(--s-4) var(--s-3); }
.asst-cards { display: flex; flex-direction: column; gap: 8px; margin-block-start: 8px; }
.asst-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 12px; font-size: var(--fs-sm); }
.asst-card b { display: block; color: var(--ink); margin-block-end: 4px; }
.asst-line-muted { color: var(--muted); }
.asst-line-bad { color: var(--bad-ink); }
/* Hidden while a drawer is open (side panel: body.sidepanel-open; Overview/
   Playbook drawer: body.drawer-open), back on close (issue 128, QA 2026-10-29). */
body.sidepanel-open .asst-fab, body.drawer-open .asst-fab { display: none; }
@media (max-width: 760px) {
  .asst-panel { inline-size: 100%; border-inline-start: 0; }
  .asst-fab { inset-inline-end: 16px; inset-block-end: 16px; }
}

/* ==========================================================================
   Onboarding components (#78, design H-1..H-5, 2026-10-23)
   Append to app/public/collecxo-ui.css (and docs/design/mockups/collecxo-ui.css).
   Tokens: existing ones only, plus two new tokens declared below.
   Logical properties only, so RTL needs no extra rules unless marked.
   ========================================================================== */

/* New tokens (add inside the existing :root block).
   --on-ink: text and icons on an ink, ok or bad fill. Replaces the literal #fff
             in .btn-primary, .toast, .step-dot etc. over time (no visual change).
   --topbar-h: height of .topbar-inner (today the literal 60px there). */
:root { --on-ink: #FFFFFF; --topbar-h: 60px; }

/* H-1 Side panel (drawer). Opens from the inline end: right in LTR, left in RTL.
   Markup:
   <div class="sidepanel-scrim" data-close></div>
   <aside class="sidepanel" role="dialog" aria-modal="true" aria-labelledby="…">
     <div class="sidepanel-head"><div><h2>…</h2><p class="sub">…</p></div><button class="btn btn-ghost btn-sm">Close</button></div>
     <div class="sidepanel-body">…</div>
     <div class="sidepanel-foot">…</div>
   </aside>
   Behaviour (dev): focus moves to the first control on open and back to the opener on close;
   Tab is trapped inside; Esc, Close and a click on the scrim close it; body gets
   .sidepanel-open (no page scroll behind). */
.sidepanel-scrim { position: fixed; inset: 0; z-index: 30; background: rgba(15, 28, 46, .35); }
.sidepanel { position: fixed; z-index: 31; inset-block: 0; inset-inline-end: 0;
  inline-size: 460px; max-inline-size: 100%; display: flex; flex-direction: column;
  background: var(--surface); box-shadow: var(--shadow-md); }
.sidepanel-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-4) var(--s-5); border-block-end: 1px solid var(--line); }
.sidepanel-head h2 { font-size: var(--fs-lg); }
.sidepanel-body { flex: 1; overflow-y: auto; padding: var(--s-5); }
.sidepanel-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-5); border-block-start: 1px solid var(--line); }
body.sidepanel-open { overflow: hidden; }
@media (max-width: 560px) { .sidepanel { inset: 0; inline-size: 100%; } }

/* H-2 Chat bubbles. Assistant at the inline start, the user at the inline end
   (they swap sides in RTL by themselves). */
.chat-log { display: flex; flex-direction: column; gap: var(--s-3); }
.chat-msg { max-inline-size: 85%; padding: 10px 14px; border-radius: var(--r-md); font-size: var(--fs-base); line-height: 1.5; overflow-wrap: anywhere; }
.chat-msg.bot { align-self: flex-start; background: var(--bg); color: var(--ink); border-end-start-radius: 4px; }
.chat-msg.me { align-self: flex-end; background: var(--ink); color: var(--on-ink); border-end-end-radius: 4px; }
.chat-msg .why { display: block; margin-block-start: var(--s-1); font-size: var(--fs-sm); color: var(--muted); }
.chat-msg.note { align-self: flex-start; background: var(--warn-tint); color: var(--warn-ink); border: 1px solid var(--warn-edge); }

/* H-3 Answer chips (existing .chip with aria-pressed) and the free-text row. */
.chat-answers { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-block-start: var(--s-3); }
.chat-own { display: flex; gap: var(--s-2); margin-block-start: var(--s-3); }
.chat-own .input { flex: 1; min-inline-size: 0; }

/* H-3b Typing indicator (issue 113, dev; for design review): "Thinking…" and three
   dots while the assistant works on a question. Existing tokens only. */
.chat-typing { display: inline-flex; align-items: center; gap: var(--s-2); color: var(--muted); }
.typing-dots { display: inline-flex; gap: var(--s-1); }
.typing-dots span { inline-size: 6px; block-size: 6px; border-radius: 50%; background: currentColor;
  animation: typing-dot 1.2s infinite ease-in-out; }
.typing-dots span:nth-child(2) { animation-delay: .2s; }
.typing-dots span:nth-child(3) { animation-delay: .4s; }
@keyframes typing-dot { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .typing-dots span { animation-duration: 2.4s; } }

/* H-4 Email preview frame: holds a sandboxed iframe with the real email HTML.
   The email keeps its own inline colours inside the iframe; the page stays hex-free.
   Height: dev sets the iframe height from its content after load.
   Width: phone width everywhere, centred, no toggle (#75, Dan 2026-10-29):
   390 px of email plus the borders; narrower screens keep 100%. */
.mail-frame { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3);
  max-inline-size: 392px; margin-inline: auto; }
.mail-frame iframe { display: block; inline-size: 100%; min-block-size: 320px; border: 0; background: var(--surface); border-radius: var(--r-sm); }

/* H-5 Small pieces. */
.draftbox { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-4); }
.draftbox .rules { list-style: none; margin: 0; padding: 0; }
.draftbox .rules li { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s-3);
  padding-block: var(--s-3); border-block-start: 1px solid var(--line); color: var(--ink); }
.draftbox .rules li:first-child { border-block-start: 0; }
.oneline { background: var(--accent-tint); border-inline-start: 3px solid var(--accent); color: var(--ink);
  padding: var(--s-3); border-start-end-radius: var(--r-sm); border-end-end-radius: var(--r-sm); font-size: var(--fs-sm); }
/* A step number that is also a button (step 3 opens the assistant). */
.dotbtn { all: unset; display: block; position: relative; z-index: 1; cursor: pointer; border-radius: 50%; }
.dotbtn .step-dot { box-shadow: 0 0 0 3px var(--accent-tint); }
.dotbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.done-line { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--s-3);
  margin-block-start: var(--s-2); font-size: var(--fs-sm); }
/* RTL fix for the existing switch: the thumb must move to the inline end.
   translateX is physical, so it is flipped for dir="rtl". */
[dir="rtl"] .switch input:checked + .track::after { transform: translateX(-18px); }

/* Addendum 2026-10-24 (#78 dev-338): the .chip component exists in the design
   system but was never copied to app/public/collecxo-ui.css. Append it and use
   it for the answer chips instead of btn btn-secondary btn-sm. */
.chips { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.chip { font: inherit; font-size: var(--fs-sm); font-weight: 500; padding: 6px 12px; border-radius: var(--r-pill);
  border: 1px solid var(--line-strong); background: var(--surface); cursor: pointer; color: var(--ink); min-block-size: 36px; }
.chip:hover { border-color: var(--ink); }
.chip[aria-pressed="true"] { background: var(--ink); color: var(--on-ink); border-color: var(--ink); }
@media (max-width: 560px) { .chip { min-block-size: 44px; } }

/* ==========================================================================
   Language switcher (#114, design 4.0, 2026-10-24)
   Append verbatim to app/public/collecxo-ui.css, app/public/app.css and
   app/public/signin.css. Every var() has a fallback (app.css and signin.css use
   other token names). Logical properties only.

   Markup (rendered by lang-switch.js into the mount):
   <ul class="lang-switch" aria-label="Language" data-i18n-aria-label="shell.lang.label"
       data-explain="…shell.explain.langSwitch…">
     <li><span class="lang-opt" aria-current="true" lang="en" translate="no">English</span></li>
     <li><button type="button" class="lang-opt" lang="ar" dir="rtl" translate="no">العربية</button></li>
   </ul>
   - Each language is written in its own language (endonym), never translated.
   - The current language is a span with aria-current="true" (not a button).
   - The others are real buttons: Tab reaches them, Enter/Space switches.
   - Fewer than two languages: render nothing (plan 3.1).

   Placement (outside .nav / .app-nav, so it shows before /me and under 760 px):
   - .topbar pages:   <div class="topbar-inner"> wordmark · nav · [mount] · Menu button </div>
   - .app-nav pages:  <div class="app-header-inner"> wordmark · nav · [mount] </div>
   - signin.html:     <div class="lang-corner" data-lang-switch="public"></div> as the first child of <body>
   - survey/interview: the .brand line becomes a div (a <ul> cannot sit inside <p>):
       <div class="brand brand-row"><span translate="no">Collecxo</span><span data-lang-switch="public"></span></div>
   ========================================================================== */

.lang-switch { display: flex; align-items: center; gap: 2px; margin: 0; padding: 0; list-style: none;
  flex: none; font-size: var(--fs-sm, 13px); line-height: 1; }
.lang-switch li { display: flex; }
.lang-opt { font: inherit; display: inline-flex; align-items: center; min-block-size: 32px;
  padding-block: 0; padding-inline: var(--s-2, 8px); border: 1px solid transparent; border-radius: 999px;
  background: none; color: var(--muted, #5B6675); cursor: pointer; white-space: nowrap; text-decoration: none; }
.lang-opt[lang="ar"] { font-family: "IBM Plex Sans Arabic", var(--font, system-ui, sans-serif); font-size: 14px; }
button.lang-opt:hover { color: var(--ink, #0F1C2E); background: var(--bg, #F5F6F8); }
button.lang-opt:focus-visible { outline: 2px solid var(--accent, #9C7A3C); outline-offset: 2px; }
.lang-opt[aria-current="true"] { color: var(--ink, #0F1C2E); font-weight: 600; cursor: default;
  background: var(--bg, #F5F6F8); border-color: var(--line, #E3E6EB); }
/* Busy while the switch saves and reloads. */
.lang-switch[aria-busy="true"] .lang-opt { opacity: .6; pointer-events: none; }

/* In the bars: a little space from the nav. */
.topbar-inner > .lang-switch, .app-header-inner > .lang-switch,
.topbar-inner > [data-lang-switch], .app-header-inner > [data-lang-switch] { margin-inline-start: var(--s-3, 12px); }
/* Under 760 px the nav collapses; the switcher stays next to the Menu button. */
@media (max-width: 760px) {
  .topbar-inner > [data-lang-switch] { margin-inline-start: auto; margin-inline-end: var(--s-2, 8px); }
}

/* Sign-in page: top inline-end corner of the page, above the card. */
.lang-corner { display: flex; justify-content: flex-end; padding: var(--s-3, 12px) var(--s-4, 16px) 0; }

/* Survey / interview: the brand line becomes a row. */
.brand-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3, 12px); }

/* ---- RTL fixes found for #114 (4.4) --------------------------------------
   translateX is physical; the switch thumb must go to the inline end in RTL.
   For app.css (.switch 18px, .switch.hdr 16px) and collecxo-ui.css (.switch.hdr 16px;
   .switch 18px is already in onboarding.css). */
[dir="rtl"] .switch input:checked + .track::after { transform: translateX(-18px); }
[dir="rtl"] .switch.hdr input:checked + .track::after { transform: translateX(-16px); }
/* .acct-btn used physical padding (3px 8px 3px 3px); the avatar side must follow the direction.
   Replace the padding in collecxo-ui.css:518 with: */
.acct-btn { padding-block: 3px; padding-inline: 3px 8px; }

/* Language switcher placement glue (dev, #114 4.3; layout only, for design review).
   The Menu button keeps its place before the nav (focus order: Menu, then the
   opened links), so on a phone the switcher sits after Menu. Both carried an
   auto start margin, which split the free space; the button's one is enough. */
@media (max-width: 760px) {
  .topbar-inner > .nav-toggle ~ [data-lang-switch] { margin-inline-start: 0; }
}

/* ---- Addendum 2026-10-24 (#118, blocking): select chevron in RTL ---------
   collecxo-ui.css .select draws its chevron with background-position: right
   (physical). padding-inline-end is already logical, so in RTL the text moves
   right while the chevron stays right and overlaps it. Append to
   collecxo-ui.css (app.css selects use the native arrow, which flips by itself). */
[dir="rtl"] .select { background-position: left 14px center; }

/* ---------- Reminder schedule (#128; docs/design/specs/reminder-schedule.md,
   mockups/reminder-schedule.html). Ported from the mockup with existing
   tokens only; classes prefixed (.steps / .dot / .legend exist elsewhere).
   Positions on the line come from --x, set by script (style.setProperty),
   and use logical properties, so the line mirrors in RTL. ---------- */
.tl { position: relative; block-size: 90px; margin: var(--s-3) 12px 0; }
.tl-axis { position: absolute; inset-inline: 0; inset-block-start: 34px; block-size: 2px; background: var(--line-strong); }
.tl-seg { position: absolute; inset-block-start: 33px; block-size: 4px; border-radius: 2px; opacity: .35;
  inset-inline-start: var(--x); inline-size: var(--w); }
.tl-seg.pre { background: var(--info-ink); }
.tl-seg.post { background: var(--warn-ink); }
.tl-dot { position: absolute; inset-block-start: 27px; inset-inline-start: var(--x); inline-size: 16px; block-size: 16px; margin-inline-start: -8px;
  border-radius: 50%; border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--line-strong); padding: 0; cursor: pointer; }
.tl-dot.pre { background: var(--info-ink); }
.tl-dot.post { background: var(--warn-ink); }
.tl-dot.rep { background: var(--surface); box-shadow: 0 0 0 2px var(--warn-ink); inline-size: 12px; block-size: 12px; inset-block-start: 29px; margin-inline-start: -6px; }
.tl-dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tl-due { position: absolute; inset-block-start: 18px; inset-inline-start: var(--x); block-size: 44px; inline-size: 2px; margin-inline-start: -1px; background: var(--ink); }
.tl-lbl { position: absolute; inset-block-start: 66px; inset-inline-start: var(--x); font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; transform: translateX(-50%); }
.tl-lbl.due { color: var(--ink); font-weight: 600; inset-block-start: 0; }
.tl-lbl.start { transform: none; }
.tl-lbl.end { transform: translateX(-100%); }
[dir="rtl"] .tl-lbl { transform: translateX(50%); }
[dir="rtl"] .tl-lbl.start { transform: none; }
[dir="rtl"] .tl-lbl.end { transform: translateX(100%); }
.tl-legend { display: flex; flex-wrap: wrap; gap: var(--s-4); font-size: var(--fs-sm); color: var(--muted); margin-block-start: var(--s-2); }
.tl-legend i { display: inline-block; inline-size: 10px; block-size: 10px; border-radius: 50%; margin-inline-end: 6px; vertical-align: -1px; }
.tl-legend i.pre { background: var(--info-ink); }
.tl-legend i.post { background: var(--warn-ink); }
.tl-legend i.rep { background: var(--surface); box-shadow: 0 0 0 2px var(--warn-ink); }
.sumbox { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-3); margin-block-start: var(--s-4); }
@media (max-width: 760px) { .sumbox { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sumbox button { font: inherit; text-align: start; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3); cursor: pointer; }
.sumbox button:hover { border-color: var(--ink); }
.sumbox b { display: block; color: var(--ink); font-weight: 600; }
.sumbox span { font-size: var(--fs-sm); color: var(--muted); }
.sched-head { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.sched-head h2 { font-size: var(--fs-md); margin: 0; }
.sched-sub { font-size: var(--fs-sm); color: var(--muted); margin: var(--s-2) 0 0; }
.sched-h3 { font-size: var(--fs-base); margin: var(--s-5) 0 var(--s-2); }
.sched-steps { list-style: none; margin: 0; padding: 0; }
.sched-steps li { display: grid; grid-template-columns: 24px 76px minmax(0, 1fr) auto; gap: var(--s-2); align-items: center; padding: 6px 0; border-block-start: 1px solid var(--line); }
.sched-steps li:first-child { border-block-start: 0; }
.sched-steps .n { font-size: var(--fs-sm); color: var(--muted); text-align: center; }
.sched-steps .input, .sched-steps .select { min-block-size: 40px; }
.sched-steps li.bad .input { border-color: var(--bad-ink); }
.sched-steps .date { grid-column: 2 / -1; font-size: var(--fs-xs); color: var(--muted); margin-block-start: -2px; }
.sched-rep { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: center; font-size: var(--fs-sm); }
.sched-rep .input { inline-size: 72px; min-block-size: 40px; }
.sched-dates { list-style: none; margin: var(--s-2) 0 0; padding: 0; font-size: var(--fs-sm); columns: 2; column-gap: var(--s-5); }
@media (max-width: 560px) { .sched-dates { columns: 1; } }
.sched-dates li { padding: 3px 0; break-inside: avoid; color: var(--ink); }
.sched-dates li span { color: var(--muted); }
.sched-dates li span.mv { color: var(--warn-ink); }
.sidepanel.wide2 { inline-size: min(640px, 100%); }
.sched-card { margin-block-end: var(--s-5); }
/* Schedule history (design-139): the version list in its side panel. */
.hlist { list-style: none; margin: 0 0 var(--s-3); padding: 0; }
.hrow { padding-block: var(--s-3); border-block-end: 1px solid var(--line); }
.hrow .sched-sub { margin-block-start: 4px; }
.hrow-sum { font-size: var(--fs-sm); color: var(--ink); margin: var(--s-2) 0 0; }
.hrow .btn-row, .hrow .alert { margin-block-start: var(--s-2); }

/* A fixed bottom bar (Playbook's Save/Publish .savebar, 96px reserved by the
   page's body padding): the toast sits above it, not on it (design-139). */
body:has(.savebar) .toast, body.has-savebar .toast { inset-block-end: calc(96px + var(--s-3)); }

/* ---- Required/Optional boxes in the empty-list state (Overview and
   Installments before the first import; #131, from
   docs/design/components/onboarding.css, design 2026-10-29). ---- */
.needs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); margin-block-start: var(--s-3); text-align: start; }
@media (max-width: 560px) { .needs { grid-template-columns: 1fr; } }
.needs div { border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3); font-size: var(--fs-sm); }
.needs b { display: block; color: var(--ink); margin-block-end: 4px; }

/* ---- Meter (issue 135, Company page "Active installments"; ported from the
   approved mockup docs/design/mockups/p0-small-screens.html, tokens only).
   The fill width comes from data-pct in 5% steps (the page rounds), not an
   inline style, as .progress[data-n] above. warn = 90% of the plan or more,
   bad = over the plan. ---- */
.meter { block-size: 8px; border-radius: var(--r-pill); background: var(--bg); overflow: hidden; max-inline-size: 360px; margin-block-start: var(--s-2); }
.meter > i { display: block; block-size: 100%; inline-size: 0%; background: var(--ink); }
.meter.warn > i { background: var(--warn-ink); }
.meter.bad > i { background: var(--bad-ink); }
/* The Company page card around it (moved from the page's own style block, review m3). */
.active-card p { margin: 0; }
.active-card .active-month:not([hidden]) ~ .active-today { margin-block-start: var(--s-2); }
.meter[data-pct="0"] > i { inline-size: 0%; }
.meter[data-pct="5"] > i { inline-size: 5%; }
.meter[data-pct="10"] > i { inline-size: 10%; }
.meter[data-pct="15"] > i { inline-size: 15%; }
.meter[data-pct="20"] > i { inline-size: 20%; }
.meter[data-pct="25"] > i { inline-size: 25%; }
.meter[data-pct="30"] > i { inline-size: 30%; }
.meter[data-pct="35"] > i { inline-size: 35%; }
.meter[data-pct="40"] > i { inline-size: 40%; }
.meter[data-pct="45"] > i { inline-size: 45%; }
.meter[data-pct="50"] > i { inline-size: 50%; }
.meter[data-pct="55"] > i { inline-size: 55%; }
.meter[data-pct="60"] > i { inline-size: 60%; }
.meter[data-pct="65"] > i { inline-size: 65%; }
.meter[data-pct="70"] > i { inline-size: 70%; }
.meter[data-pct="75"] > i { inline-size: 75%; }
.meter[data-pct="80"] > i { inline-size: 80%; }
.meter[data-pct="85"] > i { inline-size: 85%; }
.meter[data-pct="90"] > i { inline-size: 90%; }
.meter[data-pct="95"] > i { inline-size: 95%; }
.meter[data-pct="100"] > i { inline-size: 100%; }

/* ---- Stage summary card in the assistant panel (#125 Phase 7,
   docs/design/specs/assistant-stage-summary.md): the chart card and its
   bar list (docs/design/components/chart-card.css, #124 form) with the
   data-ui tiles and table (data-ui.css), scoped to .chat-chart so a page's
   own .tbl / .tile4 stay as they are. Tokens only. ---- */
.chat-chart { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-4); margin-block-start: var(--s-2); }
.chat-chart .hd { font-weight: 600; color: var(--ink); margin-block-end: var(--s-3); }
.chat-chart .sec { font-size: var(--fs-sm); font-weight: 600; color: var(--muted); margin: var(--s-4) 0 var(--s-2); }
.chat-chart .tiles4 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
.chat-chart .tile4 { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3); overflow-wrap: anywhere; }
.chat-chart .tile4 b { display: block; font-size: var(--fs-md); color: var(--ink); font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
.chat-chart .tile4 span { font-size: var(--fs-sm); color: var(--muted); }
.chat-chart .bar-row { display: flex; align-items: center; gap: var(--s-3); block-size: 32px; }
.chat-chart .bar-row .cat { inline-size: 120px; flex: 0 0 auto; font-size: var(--fs-sm); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* #143: a split's label links to Installments; the bar keeps its look, underline on hover. */
.chat-chart .bar-row a.cat { text-decoration: none; }
.chat-chart .bar-row a.cat:hover, .chat-chart .bar-row a.cat:focus-visible { text-decoration: underline; }
.chat-chart .bar-row .track { flex: 1 1 auto; block-size: 10px; background: var(--bg); border-radius: var(--r-sm); position: relative; }
.chat-chart .bar-row .fill { position: absolute; inset-block: 0; inset-inline-start: 0; inline-size: var(--w, 0%); border-radius: 0 var(--r-sm) var(--r-sm) 0; background: var(--accent); }
[dir="rtl"] .chat-chart .bar-row .fill { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.chat-chart .bar-row .val { flex: 0 0 auto; font-size: var(--fs-sm); font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; min-inline-size: 72px; text-align: end; }
.chat-chart .wrapx { overflow-x: auto; }
.chat-chart .tbl { inline-size: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.chat-chart .tbl th, .chat-chart .tbl td { text-align: start; padding: 10px 8px; border-block-end: 1px solid var(--line); vertical-align: top; }
.chat-chart .tbl th { color: var(--muted); font-weight: 500; }
.chat-chart .tbl .r { text-align: end; font-variant-numeric: tabular-nums; }

/* ---- Installments filtered to one Overview stage (#125 Phase 7,
   docs/design/specs/installments.md, mockups/installments.html .sfilt):
   "Filtered: <stage>" with Clear, above the search/Due/chips bar. ---- */
.sfilt { display: flex; gap: var(--s-2); align-items: center; background: var(--accent-tint); border: 1px solid var(--accent); border-radius: var(--r-md); padding: var(--s-2) var(--s-3); margin-block-end: var(--s-3); font-size: var(--fs-sm); }
.sfilt b { font-weight: 600; }
.sfilt button { font: inherit; background: none; border: 0; padding: 0; color: var(--accent-ink); font-weight: 500; cursor: pointer; text-decoration: underline; }

/* ---- Data UI components (#111 follow-up, design-144; from
   docs/design/components/data-ui.css, design 2026-10-27): stat tiles, data
   table, pager, filter bar, segmented control, key-value list, check dots,
   tags, side panel variants, proof grid, document preview, password eye.
   Tokens only (the source file's hex/px fallbacks are dropped, every token is
   defined above). Two changes from the source, so no other page moves:
   - .tbl is scoped to <table> with :where() (same specificity as .tbl):
     Overview, Dashboard and Replies use a <div class="tbl"> box of grid rows
     with their own page rules, which the table rules must not reach.
   - .tag's margin is written with logical properties (RTL).
   A page using these classes does not redeclare them. ---- */

/* Stat tiles: a row of 4 numbers; a tile can be a button that filters. */
.tiles4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-3); }
@media (max-width: 760px) { .tiles4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.tile4 { font: inherit; text-align: start; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: var(--s-3) var(--s-4); }
button.tile4 { cursor: pointer; }
button.tile4:hover, .tile4[aria-pressed="true"] { border-color: var(--ink); }
.tile4 b { display: block; font-size: var(--fs-xl); color: var(--ink); font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
.tile4 span { font-size: var(--fs-sm); color: var(--muted); }

/* Data table. Add .stack to turn each row into a block under 600 px. */
.tbl:where(table) { inline-size: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.tbl:where(table) th, .tbl:where(table) td { text-align: start; padding: 10px 8px; border-block-end: 1px solid var(--line); vertical-align: top; }
.tbl:where(table) th { color: var(--muted); font-weight: 500; }
.tbl:where(table) .r { text-align: end; font-variant-numeric: tabular-nums; }
.tbl:where(table) b { color: var(--ink); font-weight: 500; }
.tbl:where(table) tbody tr.click, .tbl:where(table) tbody tr[data-open] { cursor: pointer; }
.tbl:where(table) tbody tr.click:hover, .tbl:where(table) tbody tr[data-open]:hover { background: var(--bg); }
.wrapx { overflow-x: auto; }
@media (max-width: 600px) {
  .tbl.stack:where(table) thead { display: none; }
  .tbl.stack:where(table) tr { display: block; padding-block: var(--s-2); border-block-end: 1px solid var(--line); }
  .tbl.stack:where(table) td { display: block; border: 0; padding: 3px 0; }
  .tbl.stack:where(table) td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
}

/* Pager: "1–25 of N" + Previous / Next. Server-side, 25 per page (qa-69). */
.pager { display: flex; gap: var(--s-2); align-items: center; justify-content: flex-end; margin-block-start: var(--s-3); flex-wrap: wrap; }
.pager .sub { margin-inline-end: auto; }

/* Filter bar: search + selects + checkbox, wraps. */
.fbar { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: center; margin-block-start: var(--s-3); }
.fbar .input, .fbar .select { inline-size: auto; min-inline-size: 0; flex: 1 1 150px; min-block-size: 38px; padding-block: 4px; }

/* Segmented control (levels, views). aria-pressed marks the current one. */
.seg { display: inline-flex; border: 1px solid var(--line-strong); border-radius: var(--r-sm); overflow: hidden; }
.seg button { font: inherit; font-size: var(--fs-sm); background: var(--surface); color: var(--ink); border: 0;
  padding: 6px 12px; min-block-size: 36px; cursor: pointer; white-space: nowrap; }
.seg button + button { border-inline-start: 1px solid var(--line-strong); }
.seg button[aria-pressed="true"] { background: var(--ink); color: var(--on-ink); }
.seg button:disabled { color: var(--muted); cursor: not-allowed; }
@media (max-width: 600px) { .seg { display: flex; flex-wrap: wrap; } .seg button { flex: 1 1 auto; } }

/* Key-value list. */
.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px var(--s-4); font-size: var(--fs-sm); margin: 0; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; color: var(--ink); font-weight: 500; overflow-wrap: anywhere; }

/* Check dots (8 proof checks) and check list. */
.chk { display: inline-flex; gap: 3px; }
.chk i { inline-size: 10px; block-size: 10px; border-radius: 2px; display: inline-block; }
.ck-pass { background: var(--ok-ink); } .ck-flag { background: var(--bad-ink); } .ck-unknown { background: var(--line-strong); }
.checks { list-style: none; margin: 0; padding: 0; }
.checks li { display: flex; gap: var(--s-3); align-items: flex-start; padding: 8px 0; border-block-start: 1px solid var(--line); font-size: var(--fs-sm); }
.checks li:first-child { border-block-start: 0; }

/* Tags (departments, "· manager"). */
.tag { display: inline-flex; align-items: center; font-size: var(--fs-xs); padding: 2px 8px; border: 1px solid var(--line);
  border-radius: 999px; color: var(--ink); background: var(--surface); margin: 0; margin-block-end: 4px; margin-inline-end: 4px; white-space: nowrap; }
.tag.mgr { border-color: var(--accent); color: var(--accent-ink); }

/* Keyboard hint. */
kbd { font-family: ui-monospace, Menlo, monospace; font-size: var(--fs-xs); border: 1px solid var(--line-strong);
  border-radius: 4px; padding: 0 4px; background: var(--surface); }

/* Side panel variants (base .sidepanel in onboarding.css).
   - Without scrim: role="complementary", no .sidepanel-scrim; the page stays usable (assistant).
   - Wide: proof panel with preview + fields side by side. */
.sidepanel.wide { inline-size: min(980px, 96vw); }
.sidepanel.ask { z-index: 25; }
.sidepanel .can { font-size: var(--fs-sm); background: var(--bg); border-block-end: 1px solid var(--line);
  padding: var(--s-3) var(--s-5); line-height: 1.5; }
.sidepanel .can b { color: var(--ink); font-weight: 600; }

/* Two-column panel grid: preview | fields (Payments proof panel). */
.pgrid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-5); }
@media (max-width: 760px) { .pgrid { grid-template-columns: 1fr; } }

/* Document preview box: an image, or a "no preview" placeholder (PDFs, v1). */
.doc { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-4); }
.doc img { display: block; max-inline-size: 100%; block-size: auto; }
.doc.nopv { text-align: center; padding-block: var(--s-6); }
.doc .hd { font-weight: 600; margin-block-end: var(--s-2); color: var(--ink); }

/* Table cell: an amount that differs from what is expected (red, same meaning as .badge-bad). */
.tbl:where(table) .differs { color: var(--bad-ink); font-weight: 500; }

/* Side panel footer stacked vertically, for 3+ actions (Payments proof panel). */
.sidepanel-foot.stack { flex-direction: column; align-items: stretch; }

/* Two-tab layout (Payments: Payment proofs / Proof vs your file) uses the
   existing .tabs/.tab. Password field with show/hide (Dan, 2026-10-25): */
.pw-wrap { position: relative; }
.pw-wrap .input { padding-inline-end: 48px; }
.pw-eye { position: absolute; inset-block: 0; inset-inline-end: 4px; margin-block: auto; block-size: 40px; inline-size: 40px;
  display: grid; place-items: center; border: 0; background: none; color: var(--muted); border-radius: var(--r-sm); cursor: pointer; }
.pw-eye:hover { color: var(--ink); background: var(--bg); }
.pw-eye:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------- PDF report page (#134 pilot report; the print block of
   docs/design/mockups/pilot-report.html, shared with #124's summary and
   brief, arhitect-412). One A4 page: on screen inside .pdf-wrap, printed
   alone through .print-root (the page puts a copy there and calls print).
   The mockup's literal colours map to tokens; numbers inside Arabic text are
   isolated with <bdi dir="ltr"> by the page code (#124 spike condition 4). */
.pdf-wrap { background: var(--line); border-radius: var(--r-md); padding: var(--s-5) var(--s-3); display: flex; justify-content: center; margin-block-start: var(--s-4); }
.pdf-page { background: var(--surface); inline-size: min(595px, 100%); box-shadow: var(--shadow-md); padding: 36px 40px;
  font-size: var(--fs-xs); line-height: 1.5; color: var(--ink); display: flex; flex-direction: column; gap: var(--s-3); }
@media (max-width: 560px) { .pdf-page { padding: 22px 18px; } }
.pdf-h { display: flex; justify-content: space-between; gap: var(--s-3); font-size: var(--fs-xs); color: var(--muted);
  border-block-end: 1px solid var(--line); padding-block-end: 6px; }
.pdf-page h1 { font-size: var(--fs-md); margin: 0; }
.pdf-page h2 { font-size: var(--fs-sm); margin: 6px 0 0; border-block-end: 1px solid var(--line); padding-block-end: 4px; }
.pdf-page .pdf-sub { color: var(--muted); }
.kp { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
.kp > div { border: 1px solid var(--line); border-radius: 6px; padding: 10px; color: var(--muted); }
.kp .kp-n { font-size: var(--fs-lg); font-weight: 600; line-height: 1.2; color: var(--ink); }
.bars { list-style: none; margin: 0; padding: 0; }
.bars li { display: grid; grid-template-columns: minmax(0, 1fr) 110px 44px; gap: var(--s-2); align-items: center; padding: 2px 0; }
.bars svg { display: block; inline-size: 100%; block-size: 8px; }
.bars rect { fill: var(--ink); }
.bars .n, .pt .r { text-align: end; color: var(--muted); }
.pt { inline-size: 100%; border-collapse: collapse; }
.pt td, .pt th { border-block-end: 1px solid var(--line); padding: 4px 6px; text-align: start; }
.pt th.r { color: var(--ink); }
.est { background: var(--accent-tint); border-radius: 6px; padding: 10px; }
.est p { margin: 0; }
.pdf-f { margin-block-start: auto; display: flex; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; font-size: var(--fs-xs);
  color: var(--muted); border-block-start: 1px solid var(--line); padding-block-start: 8px; }
.print-root { display: none; }
@page { size: A4; margin: 13mm 14mm 16mm; }
@media print {
  body.print-report { background: var(--surface); }
  body.print-report > :not(.print-root) { display: none !important; }
  body.print-report > .print-root { display: block; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .print-root .pdf-page { inline-size: auto; box-shadow: none; padding: 0; min-block-size: 0; }
  .print-root .kp > div, .print-root .bars li, .print-root .pt tr { break-inside: avoid; }
  .print-root h2 { break-after: avoid; }
}

/* Module switcher (#48 phase 1, design-147; docs/design/components/module-switcher.css). Markup: js/module-switch.js. */
.mod-switch { display: inline-flex; flex: none; align-items: center; gap: 1px;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 2px; margin-inline-end: var(--s-3); }
.mod-switch button { font: inherit; font-size: var(--fs-sm); font-weight: 500; color: var(--muted);
  background: none; border: 0; border-radius: var(--r-pill); padding: 5px 12px; cursor: pointer; }
.mod-switch button:hover { color: var(--ink); }
.mod-switch button[aria-current="true"] { background: var(--surface); color: var(--ink);
  box-shadow: 0 1px 2px rgba(0,0,0,.08); cursor: default; }
.mod-switch button:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

@media (max-width: 760px) {
  .mod-switch { order: 3; inline-size: 100%; margin: var(--s-2) 0 0; padding: 3px; }
  .mod-switch button { flex: 1; padding: 10px; }
}

/* ==========================================================================
   Import fixes (design, 2026-11-02; #139, docs/design/specs/import-fix.md).
   Append to app/public/collecxo-ui.css. Logical properties only, tokens with
   fallbacks, same convention as data-ui.css. Used by Import preview only.
   ========================================================================== */

/* Fixes card, above the preview rows. */
.fixes { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s-5); }
.fixes h2 { font-size: var(--fs-md); margin: 0; }

/* One line per fix kind: label + example on the start side, "Fix all N" button on the end side. */
.fx { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s-2) var(--s-4); align-items: center;
  padding: var(--s-3) 0; border-block-start: 1px solid var(--line); }
.fx:first-of-type { border-block-start: 0; }
.fx b { color: var(--ink); font-weight: 500; }
.fx .ex { font-size: var(--fs-sm); color: var(--muted); }
.fx .ex code { font-family: inherit; background: var(--bg); border-radius: 4px; padding: 0 4px; color: var(--ink); }
@media (max-width: 560px) { .fx { grid-template-columns: 1fr; } }

/* "Needs you" list: problems with no fix, inside the same card. */
.nofix { margin-block-start: var(--s-4); padding-block-start: var(--s-3); border-block-start: 1px solid var(--line); }
.nofix h3 { font-size: var(--fs-sm); margin: 0 0 var(--s-2); }
.nofix li { font-size: var(--fs-sm); padding: 2px 0; }

/* Row-card problem line: bad (unfixed) or ok (just fixed, with Undo). */
.iss { margin: var(--s-3) 0 0; padding: var(--s-2) var(--s-3); border-radius: var(--r-sm); font-size: var(--fs-sm);
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-3); align-items: center; }
.iss.bad { background: var(--bad-tint); color: var(--bad-ink); }
.iss.ok { background: var(--ok-tint); color: var(--ok-ink); }
.iss .t { flex: 1 1 260px; }
.iss .btn { min-block-size: 36px; }
@media (max-width: 560px) { .iss .btn { min-block-size: 44px; } }

/* ==========================================================================
   Owner assign / handover (design, 2026-11-05; #172 §7/§8,
   docs/design/components/owner-handover.css, docs/design/specs/owner-assign-172.md,
   docs/design/specs/officer-handover-172.md). Appended as the #139
   section was: tokens only, logical properties. Used by the assign screen,
   the Investor page's owner line, and later the deactivate split step,
   delegate access and the signature setting.
   ========================================================================== */

/* Radio-with-hint fieldset: deactivate's 3 choices, signature's 3 options,
   company.html's close-account reasons. One label, one hint line under it. */
.close-reasons { border: 0; padding: 0; margin: 0 0 var(--s-4); }
.close-reasons legend { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); margin-block-end: 6px; }
.close-reasons label { display: block; font-weight: 400; margin-block-end: 4px; }
.optline { margin-block: 0 var(--s-3); margin-inline: 26px 0; color: var(--muted); font-size: var(--fs-sm); }

/* One line pairing a person badge with an action (owner line on the
   Investor page, the "Omar Faris (you)" + Propose move row). */
.ownerline { display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap; }

/* Group-by + scope controls above a grouped-assign table (deactivate's
   split step, the general assign screen). */
.splitbar { display: flex; gap: var(--s-3); align-items: flex-end; flex-wrap: wrap; }
.splitbar .select { min-inline-size: 200px; }

/* Summary line under a grouped-assign table ("Omar gets 46, Sara gets 43…"). */
.sum { font-weight: 600; color: var(--ink); margin-block-end: 0; }

/* ==========================================================================
   My work (#192, docs/design/components/my-work.css, the parts the page uses
   today). Tokens only; kind chips reuse the bad / warn / info sets.
   ========================================================================== */
/* A section: title with its count. */
.grp { margin-block-start: var(--s-5); }
.grp > h2 { display: flex; align-items: baseline; gap: var(--s-2); font-size: var(--fs-md); margin: 0 0 var(--s-2); }
.grp > h2 .n { font-size: var(--fs-sm); color: var(--muted); font-weight: 500; }

/* Kind chip on every item row: talk (reply, call, follow-up), money (proof,
   statement line, delay), risk (discrepancy, broken promise, escalation). */
.kind { display: inline-block; font-size: var(--fs-xs); font-weight: 600; padding: 2px 8px; border-radius: 999px; white-space: nowrap;
  background: var(--bg); border: 1px solid var(--line); color: var(--ink); }
.kind.risk { background: var(--bad-tint); border-color: var(--bad-edge); color: var(--bad-ink); }
.kind.money { background: var(--warn-tint); border-color: var(--warn-edge); color: var(--warn-ink); }
.kind.talk { background: var(--info-tint); border-color: var(--info-edge); color: var(--info-ink); }

/* Item table extras (on top of .tbl / .tbl.stack). */
.tbl td .sub { color: var(--muted); font-size: var(--fs-xs); }
.tbl td.reason { color: var(--muted); min-inline-size: 220px; }
.tbl td.r { white-space: nowrap; }
.tbl tbody tr[data-open]:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.tbl.dec td.act { text-align: end; white-space: nowrap; }
@media (max-width: 600px) {
  .tbl.stack td.reason { min-inline-size: 0; }
  .tbl.stack td.r, .tbl.dec td.act { text-align: start; }
}

/* Manager tiles used as tabs: the selected one, the small word after the number. */
.tile4[aria-selected="true"] { border-color: var(--ink); }
.tile4 b small { font-size: var(--fs-sm); font-weight: 500; color: var(--muted); white-space: nowrap; }

/* Done today's Who (Collecxo in the accent ink) and the Team table's Overdue above 0. */
.who { white-space: nowrap; }
.who.ai { color: var(--accent-ink); font-weight: 500; }
.ovd { color: var(--bad-ink); font-weight: 600; }

/* Person select + Move on one line (#192 P3 Move), and the manager's
   "Collecxo gave 7 new investors an owner today · See and move" line. */
.prop { display: flex; gap: var(--s-2); align-items: center; flex-wrap: wrap; }
.prop .select { min-inline-size: 150px; inline-size: auto; }
.sidepanel .prop { flex-wrap: nowrap; }
.autoline { display: flex; justify-content: space-between; gap: var(--s-3); align-items: center; flex-wrap: wrap; inline-size: 100%;
  text-align: start; font: inherit; font-size: var(--fs-sm); background: var(--accent-tint); color: var(--ink);
  border: 1px solid var(--warn-edge); border-radius: var(--r-md); padding: var(--s-2) var(--s-3); cursor: pointer; margin-block-end: var(--s-3); }
.autoline .see { font-weight: 600; text-decoration: underline; }
