/* Aetherma design direction.
   Canvas Beige, body text Prune, Forest for cards and engagement/CTA,
   Vert clair as the single accent. Afacad primary typeface. Editorial, airy.
   Rule of thumb: dark ground -> light text; light ground -> dark text. */

:root {
  --beige: #FCF9F0;
  --prune: #353242;
  --vert-clair: #93966B;
  --forest: #002319;
  --vert-fonce: #272E21;
  --beige-70: rgba(252, 249, 240, 0.7);
  --beige-85: rgba(252, 249, 240, 0.85);
  --prune-15: rgba(53, 50, 66, 0.15);
  --prune-20: rgba(53, 50, 66, 0.2);
  --error: #7A2E2E;

  /* Cockpit shell tokens (chantier 13). Derived from the DA so a palette change
     stays in one place. color-mix keeps the rail/lines tied to Prune + Beige. */
  --ink: var(--prune);
  --ink-2: color-mix(in srgb, var(--prune) 72%, var(--beige));
  --line: color-mix(in srgb, var(--prune) 14%, transparent);
  --surface: color-mix(in srgb, var(--prune) 4%, var(--beige));
  --field: #ffffff;
  --rail-w: 216px;
  --rail-w-narrow: 56px;
  --insp-w: 384px;
  /* Single width for every dense work screen (lists, dashboard, detail). One
     value, so no screen drifts; fills the work column below it, caps for
     readability above. Editorial forms keep this page width and cap their own
     fields at --form-max instead of narrowing the page (Salesforce/HubSpot). */
  --work-max: 1600px;
  --form-max: 720px;
  --work-gut: clamp(18px, 3vw, 28px); /* cockpit work-area side gutter (was inlined per view) */
  --mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  /* Semantic z-index scale (dropdown < sticky < resizer < toast < tooltip). */
  --z-dropdown: 20; --z-sticky: 30; --z-resizer: 40; --z-toast: 60; --z-tooltip: 70;
}

/* ---------- Fonts ---------- */
@font-face {
  font-family: 'Afacad';
  src: url('/public/fonts/Afacad-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Afacad';
  src: url('/public/fonts/Afacad-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: 'Afacad', system-ui, sans-serif;
  color: var(--prune);
  background: var(--beige);
  line-height: 1.6;
}

.wrap { max-width: 980px; margin: 0 auto; padding: 48px 32px; }

/* ---------- Typography (on Beige) ---------- */
h1 { font-size: 40px; font-weight: 700; margin: 4px 0 32px; }
h2 { font-size: 24px; font-weight: 700; margin: 0 0 8px; }
a  { color: var(--forest); }

.label {
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--vert-clair);
}
/* Back link on record pages: sits above the breadcrumb, quiet until hover. */
.back-link {
  display: inline-block; margin-bottom: 8px;
  font-size: 13px; color: rgba(53, 50, 66, 0.6); text-decoration: none;
}
.back-link:hover { color: var(--forest); }

/* Record header (shared views/_record_header.ejs). One shell for the four detail
   sheets: a quiet piloting nav row, then an identity row where the title, the
   meta and the per-record actions sit on ONE line. Actions are pushed right and
   self-centred on that line, so a sheet's action (Archiver, Approuver…) aligns
   on its title. The lead sheet used to centre its actions against the whole
   two-row block, which floated them ~12px above the name. */
.rh-header { flex: none; padding: 12px clamp(18px, 3vw, 28px); border-bottom: 1px solid var(--line); }
.rh-nav { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.rh-nav .back-link { margin: 0; }
.rh-piloting { display: inline-flex; align-items: center; gap: 6px; }
.rh-arrow { padding: 3px 8px; }
.rh-arrow.is-off { opacity: .4; }
.rh-pos { font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* Header meta subtitle under the title (domain / role / id / count), shared by the
   four detail sheets. Was the same inline on each. */
.rh-sub { font-size: 14px; color: var(--ink-2); }
.rh-note { font-size: 12.5px; color: var(--ink-2); }
.rh-idrow { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; margin-top: 3px; }
.rh-title { margin: 0; font-size: 22px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; min-width: 0; }
.rh-title-trunc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.rh-actions { margin-left: auto; align-self: center; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Record-header action buttons sit in a row; their forms carry no margin (was inline
   on every form). Same pattern as .ct-actions form / .deal-actions form. */
.rh-actions form { margin: 0; }
/* Header status label. Colour by tone (was a colour computed inside the inline
   style): lost recedes, a won/meeting lead reads in the accent, the rest plain. */
.rh-stat { font-size: 13px; font-weight: 700; color: var(--ink); }
.rh-stat.is-lost { color: var(--ink-2); }
.rh-stat.is-warm { color: var(--vert-clair); }
.meta   { font-size: 14px; color: rgba(53, 50, 66, 0.7); }
.figure { color: var(--vert-clair); font-weight: 700; }
.frozen { font-size: 13px; color: rgba(53, 50, 66, 0.6); font-style: italic; }

/* ---------- Cards (Forest ground -> light text) ---------- */
.card {
  background: var(--forest);
  color: var(--beige);
  border-radius: 10px;
  padding: 20px 24px;
  margin-bottom: 16px;
}
.card h1,
.card h2,
.card p,
.card a,
.card label { color: var(--beige); }
.card .label  { color: var(--vert-clair); }
/* Secondary text (.meta, .frozen, .var-hint) and labels default to
   prune-on-light. Inside ANY dark card they must flip to the light palette, or
   they render prune on forest — illegible. Covers every dark container in one
   place so a new card never reintroduces the bug. */
.card .meta,   .card-detached .meta,
.card .var-hint { color: var(--beige-85); }
.card .frozen, .card-detached .frozen { color: var(--beige-70); }

/* Actions inside a Forest card: light ground rules -> use the Vert clair
   accent (never Prune, which is too dark on Forest). */
.card .btn-save  { background: var(--beige); color: var(--prune); }
.card .btn-ghost,
.rec-card .btn-ghost { background: transparent; color: var(--beige);
                   border: 1px solid var(--beige-70); }

/* ---------- Form controls (Beige field, Prune text) ---------- */
textarea,
input[type=text],
input[type=password],
input[type=number],
select {
  width: 100%;
  font-family: inherit;
  font-size: 15px;
  color: var(--prune);
  background: var(--beige);
  border: 1px solid var(--prune-15);
  border-radius: 8px;
  padding: 12px 14px;
  margin: 6px 0 16px;
}
textarea { min-height: 180px; resize: vertical; }
textarea[disabled], input[disabled] { opacity: 0.6; }

/* Green everywhere — the DA rule "anneau de focus Vert clair 2px partout",
   enforced globally so no control falls back to the browser's blue: focus ring,
   text selection, caret and control accent. Component rules with their own green
   ring still win (higher specificity); plain controls (search, cfg-num spinners,
   selects, checkboxes) inherit this. */
::selection { background: color-mix(in srgb, var(--vert-clair) 40%, transparent); }
input, textarea, select { accent-color: var(--forest); caret-color: var(--vert-clair); }
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--vert-clair); outline-offset: -2px;
}
input[type=checkbox]:focus-visible, input[type=radio]:focus-visible { outline-offset: 2px; }

/* ---------- Buttons (on Beige) ---------- */
button {
  font-family: inherit;
  font-size: 15px;
  cursor: pointer;
  border: none;
  border-radius: 8px;
  padding: 12px 22px;
}
/* Self-contained so a link carries the full prune button (shape + fill), the way
   .ct-btn does: the base button {} rule only reaches <button>, so an
   <a class="btn-save"> would otherwise get the fill without the shape. Redundant
   for <button> (same values; more specific context rules still win). */
.btn-save    { background: var(--prune);  color: var(--beige);
               display: inline-block; border: none; border-radius: 8px;
               padding: 12px 22px; font-size: 15px; line-height: 1.2;
               text-decoration: none; cursor: pointer; }
.btn-approve { background: var(--forest); color: var(--beige); }
.btn-ghost   { background: transparent; color: var(--prune);
               border: 1px solid var(--prune-20); }

/* ---------- Flash messages ---------- */
.flash {
  background: var(--forest);
  color: var(--beige);
  padding: 12px 18px;
  border-radius: 8px;
  margin-bottom: 24px;
}
.flash.error { background: var(--error); }

/* ============================================================
   Work surfaces (tools, not editorial pages)
   Full-width plane for dense lists. Editorial .wrap (980px) stays
   for detail pages and forms. DA kept: Beige ground, Prune text,
   Vert clair accents; Forest reserved for engagement, not list rows.
   ============================================================ */
.wrap-wide {
  max-width: var(--work-max);
  margin: 0 auto;
  padding: 40px clamp(24px, 4vw, 48px);
}

.work-head { margin-bottom: 24px; }
.work-head h1 { margin: 4px 0 8px; }
.work-head .meta { max-width: 720px; }

/* ---------- Tabs (segmented, quiet) ---------- */
.tabs {
  display: flex; gap: 4px;
  border-bottom: 1px solid var(--prune-15);
  margin: 8px 0 24px;
}
.tab {
  appearance: none; text-decoration: none;
  font-size: 15px; color: rgba(53, 50, 66, 0.6);
  padding: 12px 18px; border: none; background: transparent;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  display: inline-flex; align-items: center; gap: 8px;
}
.tab:hover { color: var(--prune); }
.tab.is-active { color: var(--prune); border-bottom-color: var(--vert-clair); font-weight: 700; }
.tab .count {
  font-size: 13px; font-weight: 700; color: var(--vert-clair);
  background: rgba(147, 150, 107, 0.12); border-radius: 20px;
  padding: 1px 9px; min-width: 22px; text-align: center;
}
.tab.is-active .count { background: rgba(147, 150, 107, 0.2); }

/* ---------- Action toolbar above a table ---------- */
.toolbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px 16px; margin-bottom: 0;
  background: rgba(53, 50, 66, 0.03);
  border: 1px solid var(--prune-15); border-bottom: none;
  border-radius: 10px 10px 0 0;
}
.toolbar .spacer { flex: 1; }
.toolbar select { width: auto; margin: 0; }
.toolbar .sel-count { font-size: 14px; color: rgba(53,50,66,0.7); }

/* ---------- Dense data table ---------- */
.table-wrap {
  border: 1px solid var(--prune-15); border-radius: 10px;
  overflow: hidden; background: var(--beige);
}
.toolbar + .table-wrap { border-radius: 0 0 10px 10px; border-top: none; }
table.grid { width: 100%; border-collapse: collapse; font-size: 15px; }
table.grid thead th {
  text-align: left; font-weight: 700; font-size: 12px;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: rgba(53, 50, 66, 0.55);
  padding: 12px 16px; border-bottom: 1px solid var(--prune-15);
  white-space: nowrap;
}
table.grid tbody td {
  padding: 14px 16px; border-bottom: 1px solid rgba(53, 50, 66, 0.07);
  vertical-align: middle;
}
table.grid tbody tr:last-child td { border-bottom: none; }
table.grid tbody tr:hover { background: rgba(53, 50, 66, 0.025); }
table.grid td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.grid td.cb, table.grid th.cb { width: 44px; text-align: center; }
table.grid .name { font-weight: 700; color: var(--prune); text-decoration: none; }
table.grid .name:hover { text-decoration: underline; }
table.grid .sub { color: rgba(53, 50, 66, 0.6); font-size: 13px; }
table.grid input[type=checkbox] { width: 18px; height: 18px; margin: 0; }

.score-cell { display: inline-flex; align-items: baseline; gap: 6px; }
.score-cell .val { color: var(--vert-clair); font-weight: 700; font-size: 17px; }
.score-cell .seg { font-size: 12px; color: rgba(53, 50, 66, 0.55);
                   text-transform: uppercase; letter-spacing: 0.04em; }

.empty {
  padding: 40px 16px; text-align: center; color: rgba(53, 50, 66, 0.5);
  border: 1px dashed var(--prune-15); border-radius: 10px; background: transparent;
}
.toolbar + .empty { border-radius: 0 0 10px 10px; }

.row-actions { display: inline-flex; gap: 8px; }
.row-actions button { padding: 7px 12px; font-size: 13px; }

/* ============================================================
   Compact Forest row-cards (dense list with brand ground)
   One lead per row, Forest ground, Beige text, Vert clair figure.
   Denser than full cards, keeps the brand's dark-card identity.
   ============================================================ */
.rowcard-list { display: flex; flex-direction: column; gap: 0; }

/* Header and rows share ONE grid template so every cell falls under its label.
   Columns: [checkbox] [lead: flexible] [company] [score] [wide/misc] [narrow/actions]
   A view leaves unused cells empty; the track still holds the column. */
.rowcard-head,
.rowcard {
  display: grid;
  /* Five data tracks with BOUNDED widths, then a 1fr buffer that carries the
     actions and soaks up all slack on the right. Before, tracks 2 and 5 were
     1fr / 1.2fr: on the wide work plane (up to 1600px) the lead track ballooned
     to ~440px and the status track to ~520px, tearing a gap between name and
     company and making the columns look unaligned card to card. Capping them
     keeps every column at a stable width and pushes the empty space past the
     buttons instead of between the data. The trailing 1fr replaces the old
     'auto': actions still sit flush right via their own justify-content. */
  grid-template-columns: 24px minmax(180px, 320px) 200px 90px minmax(160px, 240px) 1fr;
  align-items: baseline;
  gap: 16px;
}
/* Cells hold text at different sizes (name 16px, company 14px, score 18px);
   baseline alignment puts their first text lines on one line. Boxes that hold
   controls, not text (checkbox, action buttons) carry no baseline, so they were
   centered -- but centering is over the WHOLE row height, which grows with a
   multi-line lead cell (name + job title). The button then sank to the middle
   of a tall card. Pin them to the FIRST line instead: align to the top of the
   row and center within a single 24px line box, so a checkbox and an action stay
   level with the name no matter how many lines the lead cell spans. */
.rowcard .actions,
.rowcard > .cbcol {
  align-self: start;
  min-height: 24px;
  align-items: center;
}
/* List row on the light ground: a hairline-separated row on the canvas, hover
   lifts to Surface — the validated À recontacter (.rc-row) treatment, kept on the
   shared rowcard grid so columns still align. Forest is reserved for engagement,
   never an ordinary list row (DA). */
.rowcard {
  color: var(--ink);
  padding: 13px 16px; border-bottom: 1px solid var(--line);
}
.rowcard:last-child { border-bottom: none; }
.rowcard:hover { background: var(--surface); }
.rowcard-head {
  padding: 4px 16px 8px; color: var(--ink-2);
  font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}
/* A column header pinned to the top of its scrolling list. Opt-in: the fiche
   sub-tables (company detail) keep a non-sticky header. */
/* Sticky is structural, not opt-in: any column header inside a scrolling list
   sticks, so no view can forget it. Sub-tables outside .list-scroll (company
   detail) keep a non-sticky header, as intended. */
.list-scroll > .rowcard-head { position: sticky; top: 0; background: var(--beige); z-index: 2; }
/* Dense-list scaffold (was repeated inline per list): the bulk-action form is a
   flex column; its rows scroll inside while the toolbar and header stay pinned. */
.list-col { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.list-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 0 var(--work-gut); margin-top: 10px; }
.rowcard > .cbcol, .rowcard-head > .cbcol { display: flex; align-items: center; }
.rowcard input[type=checkbox] { width: 18px; height: 18px; margin: 0; }
.rowcard .who { min-width: 0; }
/* Row name/link reads as Forest on the light ground (the .rc-lead treatment). */
.rowcard .nm { color: var(--forest); text-decoration: none; }
/* Only actual links underline on hover. A span.nm (non-clickable name, or the
   due date on the recontact queue) must not look clickable. */
.rowcard a.nm:hover { text-decoration: underline; }
.rowcard .who .nm { font-weight: 700; font-size: 16px; }
/* Secondary line under a value. Not scoped to .who: any cell may need one. */
.rowcard .sub { color: var(--ink-2); font-size: 13px; }
.rowcard .co { color: var(--ink); font-size: 14px;
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Two related values stacked in one track (e.g. company category + headcount).
   Avoids parking a short value in the trailing 'auto' track, which would push it
   against the card's right edge. min-width:0 lets long labels ellipsize. */
.rowcard .pair { min-width: 0; }
.rowcard .pair .val { color: var(--ink); font-size: 14px;
                      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rowcard .sc { display: inline-flex; align-items: baseline; gap: 6px; }
.rowcard .sc .val { color: var(--ink); font-weight: 700; font-size: 18px;
                    font-variant-numeric: tabular-nums; }
.rowcard .sc .seg { color: var(--ink-2); font-size: 11px;
                    text-transform: uppercase; letter-spacing: 0.05em; }
.rowcard .own { color: var(--ink-2); font-size: 14px;
                white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rowcard .miss { color: var(--error); font-size: 13px; }
/* A missing value the human can fix: same red as .miss, but actionable. Links
   to the screen where the field lives (guardrail: a gap must be clickable). */
.rowcard .miss-link { color: var(--error); font-size: 13px; text-decoration: underline; }
.rowcard .miss-link:hover { color: var(--prune); }
.rowcard .actions { display: inline-flex; gap: 8px; justify-content: flex-end; }
.rowcard .actions button { padding: 7px 12px; font-size: 13px; }
/* On the light ground, row buttons use the global .btn-save / .btn-ghost. */
.rowcard .link-complete {
  color: var(--forest); text-decoration: underline; font-size: 14px;
}

/* Draft "ready" view: department and language were stacked in one .pair cell
   under a single "Département · Langue" header, so the language pill sat below
   the department instead of aligning under its own label. Split them into two
   real columns with their own headers. This needs a 7th track, so this view
   opts into a dedicated grid (same pattern as .rc-grid) rather than bending the
   shared 6-track grid the other seven views depend on. align-items:start caps
   the small vertical drift between cells of different font sizes. */
.rowcard-head.dr-grid,
.dr-grid .rowcard {
  grid-template-columns: 24px minmax(180px, 320px) 180px 90px minmax(140px, 220px) minmax(120px, 200px) 90px;
  align-items: start;
}
.dr-grid .rowcard .dept {
  color: var(--ink); font-size: 14px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* Pill left-aligned under the "Langue" header, on the name's line. */
.dr-grid .rowcard .lang { display: flex; justify-content: flex-start; }

/* Rejects queue: a tabular grid on the shared .rowcard (like À drafter opts into
   .dr-grid). Columns: checkbox | email | reason | context | date | action. */
.rowcard-head.rj-grid,
.rj-grid .rowcard {
  grid-template-columns: 24px minmax(200px, 1.6fr) 190px minmax(150px, 1fr) 130px 90px;
  align-items: center;
}
.rj-grid .rowcard .rj-email { color: var(--forest); font-weight: 600; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rj-grid .rowcard .rj-reason { color: var(--ink); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.rj-grid .rowcard .rj-ctx { color: var(--ink-2); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

/* Export queue: the same tabular .rowcard, two sections (à envoyer / envoyés).
   Columns: checkbox | lead | email | company | date | action. The second section
   header is spaced from the first section's table. */
.rowcard-head.ex-grid,
.ex-grid .rowcard {
  grid-template-columns: 24px minmax(160px, 1.3fr) minmax(170px, 1.3fr) minmax(130px, 1fr) 120px 84px;
  align-items: center;
}
.ex-grid .rowcard .ex-email { color: var(--ink); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
#exlist [data-select-scope] + .toolbar { margin-top: 24px; }

/* Qualification "à préparer": language, category and size each earn their own
   aligned, sortable column (a premium CRM sorts by any of them). Needs a tidy
   trailing track for size rather than the shared grid's wide 1fr, same reasoning
   as .dr-grid. */
.rowcard-head.sp-grid,
.sp-grid .rowcard {
  grid-template-columns: 24px minmax(180px, 320px) minmax(150px, 240px) 90px minmax(150px, 220px) 120px;
  align-items: start;
}

/* Narrow screens: the shared grid's fixed tracks (24 + 200 + 90 + bounded
   flex + gaps) exceed the viewport well before phone width. Rather than let
   columns overflow, stack every cell into one column and drop the header row
   (its labels no longer sit above anything). Controls return to normal flow. */
@media (max-width: 900px) {
  .rowcard-head { display: none; }
  .rowcard,
  .rc-grid .rowcard,
  .dr-grid .rowcard,
  .sp-grid .rowcard {
    grid-template-columns: 1fr;
    gap: 4px;
  }
  .rowcard .actions,
  .rowcard > .cbcol {
    align-self: start;
    justify-self: start;
    min-height: 0;
  }
  .rowcard .actions { justify-content: flex-start; margin-top: 6px; }
}

/* ---------- Search + pagination ---------- */
.searchbar { display: flex; gap: 10px; align-items: stretch; margin-bottom: 16px; }
/* All controls share one height so the button lines up with the selects.
   Fields carry a border, buttons don't; box-sizing + a fixed height on every
   child makes them equal regardless of internal padding. */
.searchbar input[type=text],
.searchbar select,
.searchbar button {
  height: 46px; margin: 0; box-sizing: border-box;
  display: inline-flex; align-items: center;
}
.searchbar input[type=text] { max-width: 340px; }
.searchbar button { padding: 0 20px; }
.searchbar .clear { color: rgba(53,50,66,0.6); text-decoration: none;
                    font-size: 14px; display: inline-flex; align-items: center; }

.pager { display: flex; align-items: center; gap: 16px; margin-top: 20px; }
.pager .count { font-size: 14px; color: rgba(53,50,66,0.6); }
.pager .spacer { flex: 1; }
/* Shared list pager (rendered by _pager.ejs): pinned foot of every list, one look
   for all. Replaces the per-view inline styles the copied blocks used to carry. */
.pager-list { margin: 0; gap: 12px; padding: 9px clamp(18px, 3vw, 28px); border-top: 1px solid var(--line); }
.pager-total, .pager-pos, .pager-size label { font-size: 12.5px; color: var(--ink-2); }
.pager-pos { font-variant-numeric: tabular-nums; }
.pager-size { display: inline-flex; align-items: center; gap: 7px; margin: 0; }
.pager-size select { width: auto; margin: 0; padding: 5px 8px; font-size: 12.5px; }
.pager-arrow { padding: 4px 9px; }
.pager-arrow.is-off { opacity: 0.4; }
/* Tighter fit for a pager pinned inside a narrow panel (quarantine desk). */
.pager-tight { gap: 10px; padding: 9px clamp(12px, 2vw, 16px); }

/* Grouped primary action (field + button share a visual unit) vs detached
   secondary action separated by a divider. Keeps related controls together. */
.action-group {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px; border-radius: 10px;
  background: rgba(53, 50, 66, 0.04);
  border: 1px solid var(--prune-15);
}
.action-group select { margin: 0; }
.action-sep { position: relative; margin-left: 8px; }
.action-sep::before {
  content: ""; position: absolute; left: -12px; top: 50%;
  transform: translateY(-50%); width: 1px; height: 24px;
  background: var(--prune-15);
}

/* Leads toolbar: search + filters + result count + selection in one row. Reuses
   the field tokens; selects use a custom chevron with controlled right padding so
   the option text never meets the arrow. An active filter reads in the Vert clair
   accent (the DA "selected/active" language). */
.lt { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 14px var(--work-gut) 0; flex: none; }
/* One centralized sizing contract for EVERY control in the bar, specific enough
   (.lt input[type=text] = 0,2,1) to beat the base input[type=text]/select rules —
   the specificity asymmetry that left a single-class field misaligned. Height +
   margin:0 + border-box is shared; per-control rules add only what differs. */
.lt input[type=text], .lt select, .lt .btn-ghost, .lt .btn-save { height: 44px; margin: 0; box-sizing: border-box; }
.lt input[type=text], .lt select {
  border: 1px solid var(--prune-15); border-radius: 8px;
  background-color: var(--beige); color: var(--ink); font: inherit; font-size: 14px;
}
.lt input[type=text] { padding: 0 13px; }
.lt-search { flex: 1 1 260px; max-width: 440px; }
/* Selects: custom chevron + controlled right padding so text never meets the arrow. */
.lt select {
  width: auto; cursor: pointer; padding: 0 34px 0 13px;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M1 1l4 4 4-4' fill='none' stroke='%236D6A73' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat; background-position: right 13px center;
}
.lt-sel.is-active { border-color: var(--vert-clair); background-color: color-mix(in srgb, var(--vert-clair) 12%, var(--beige)); font-weight: 600; color: var(--forest); }
.lt-reset { font-size: 13px; color: var(--ink-2); text-decoration: underline; white-space: nowrap; }
.lt-spacer { flex: 1; }
.lt-count { font-size: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.lt-count b { color: var(--ink); font-weight: 700; }
/* Current order-by, always shown (incl. the "Récent" default) so the sort condition is never a guess. */
.lt-sort { font-size: 13px; color: var(--ink-2); white-space: nowrap; }
.lt-sort b { color: var(--forest); font-weight: 700; }

/* Sortable column header: label + direction arrow, click to sort. Active column
   reads in Forest with a solid arrow; the others show a faint ↕ affordance. */
.sort-h { display: inline-flex; align-items: center; gap: 5px; color: inherit; text-decoration: none;
          font: inherit; text-transform: inherit; letter-spacing: inherit; cursor: pointer; }
.sort-h:hover { color: var(--ink); }
.sort-i { font-size: 9px; opacity: 0.35; }
.sort-h:hover .sort-i { opacity: 0.6; }
.sort-h.is-sorted { color: var(--forest); font-weight: 700; }
.sort-h.is-sorted .sort-i { opacity: 1; color: var(--forest); }
.sort-h:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: 2px; border-radius: 4px; }

/* ============================================================
   Shared selection mode (reused by every list page)
   Put `class="selectable"` on <body>. Toggling `.selecting` on <body>
   reveals checkboxes + the bulk action bar. Replaces the per-page inline
   <style> blocks (leads/scoring/archived/draft) with one source.
   ============================================================ */
body.selectable:not(.selecting) .cbcol { visibility: hidden; }
body.selectable:not(.selecting) #bulkActions { display: none; }
body.selectable.selecting #selectBtn { display: none; }

/* Live client-side filter: rows hidden by the search box get this. */
/* Live-filter hide state, for every filterable row type (shared initLiveFilters).
   The JS is generic; the hide rule must cover each row/header it can mark. */
.rowcard.is-hidden, .rc-row.is-hidden, .rc-group.is-hidden, .iq-row.is-hidden { display: none; }
/* Quarantine inbound row (was an inline-styled div): a class so the live filter
   can hide it (an inline display:flex would otherwise win over .is-hidden). */
.iq-row { display: flex; align-items: center; gap: 6px; }

/* Opener hook-confidence badge (Forest ground). Low draws the eye (review it),
   high recedes (safe to bulk-approve). Small, uppercase, scannable at volume. */
.conf {
  display: inline-block; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--beige-70); color: var(--beige);
}
.conf-high   { background: var(--vert-clair); border-color: var(--vert-clair);
               color: var(--forest); }
.conf-medium { background: transparent; }
.conf-low    { background: var(--error); border-color: var(--error);
               color: var(--beige); }
.conf-none   { opacity: 0.5; }
/* On a light rowcard (openers list) the confidence badge flips to dark ink; the
   Forest openers-detail keeps the base above. high/low are filled, so they read
   on either ground. */
.rowcard .conf { border-color: var(--prune-20); color: var(--ink-2); }
.rowcard .conf-high { background: var(--vert-clair); border-color: var(--vert-clair); color: var(--forest); }
.rowcard .conf-low  { background: var(--error); border-color: var(--error); color: var(--beige); }

/* ---------- AI config: model picker (two radio cards) ---------- */
.ai-banner {
  background: rgba(147, 150, 107, 0.15);
  border: 1px solid var(--vert-clair);
  color: var(--prune); border-radius: 8px;
  padding: 12px 16px; margin: 0 0 20px; font-size: 14px;
}
.model-pick { display: flex; gap: 16px; flex-wrap: wrap; margin: 6px 0 20px; }
.model-pick label {
  flex: 1 1 240px; cursor: pointer; position: relative;
  border: 1px solid var(--prune-20); border-radius: 10px;
  padding: 16px 18px 16px 46px; background: var(--beige);
  transition: border-color 0.15s, background 0.15s;
}
.model-pick input[type=radio] { position: absolute; left: 16px; top: 18px; width: 18px; height: 18px; margin: 0; }
.model-pick label:has(input:checked) {
  border-color: var(--forest); background: #fff;
  box-shadow: inset 0 0 0 1px var(--forest);
}
.model-pick .mp-title { font-weight: 700; color: var(--prune); display: block; }
.model-pick .mp-note  { font-size: 13px; color: rgba(53,50,66,0.7); display: block; margin-top: 4px; }
.model-pick .mp-id    { font-size: 11px; color: rgba(53,50,66,0.5); font-family: monospace; display: block; margin-top: 6px; }

/* ============================================================
   Top navigation (replaces the inline-styled _header.ejs)
   Prune ground, Beige text (dark ground -> light text). Active link
   marked with a Vert clair underline, matching the .tab convention.
   Dropdown groups use native <details>, no JS. DA colors only.
   ============================================================ */
.topnav {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; padding: 0 32px;
  background: var(--prune); color: var(--beige);
}
.topnav-links { display: flex; align-items: stretch; gap: 0; flex-wrap: wrap; }

/* Pipeline grouped by kind of work. Links inside a group sit close; a thin
   rule separates families so the bar reads as Entry | Preparation | Validation
   | Follow-up. Visual only — every link stays independent. */
.navgroup { display: inline-flex; align-items: stretch; gap: 2px; }
.navsep {
  align-self: center; width: 1px; height: 20px; margin: 0 10px;
  background: rgba(252, 249, 240, 0.22);
}
/* Validation step (Openers): a quiet marker sets the "judge the output" moment
   apart from the "prepare & launch" families, without shouting. A small dot
   before the label, in the brand accent. */
.navgroup--review .navlink::before {
  content: "•"; margin-right: 6px; color: var(--vert-clair); opacity: 0.9;
}

/* Every clickable nav item shares one look. Underline grows on the active one,
   so the row reads as tabs rather than a wall of equal links. */
.navlink {
  display: inline-flex; align-items: center;
  color: var(--beige); text-decoration: none;
  font-size: 15px; line-height: 1;
  padding: 18px 14px;
  border-bottom: 2px solid transparent;
}
.navlink:hover { color: #fff; }
.navlink.is-active { font-weight: 700; border-bottom-color: var(--vert-clair); }

/* Dropdown group (Données, Admin). <details>/<summary> = zero-JS disclosure.
   The summary looks like a navlink; when a child route is active the whole
   group carries the accent so the user sees where they are while it is closed. */
.navmenu { position: relative; }
.navmenu > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--beige); font-size: 15px; line-height: 1;
  padding: 18px 14px; border-bottom: 2px solid transparent;
}
.navmenu > summary::-webkit-details-marker { display: none; }
.navmenu > summary::after {
  content: "▾"; font-size: 11px; opacity: 0.7;
}
.navmenu > summary:hover { color: #fff; }
.navmenu.is-active > summary { font-weight: 700; border-bottom-color: var(--vert-clair); }
.navmenu[open] > summary::after { content: "▴"; }

/* Panel floats below the summary so opening it never reflows the bar. */
.navmenu-panel {
  position: absolute; top: 100%; left: 0; z-index: 20;
  display: flex; flex-direction: column; min-width: 180px;
  background: var(--prune);
  border: 1px solid rgba(252, 249, 240, 0.15);
  border-radius: 0 0 10px 10px;
  padding: 6px; gap: 2px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}
.navmenu-panel .navlink {
  padding: 10px 12px; border-bottom: none; border-radius: 6px;
}
.navmenu-panel .navlink:hover { background: rgba(252, 249, 240, 0.08); }
.navmenu-panel .navlink.is-active {
  border-bottom: none; background: rgba(147, 150, 107, 0.2);
}

/* Right cluster: system-settings gear (admin only) + user menu. Separated from
   the daily-work links on the left, matching the CRM convention (settings is a
   gear, not a nav tab). */
.topnav-right { display: flex; align-items: center; gap: 8px; white-space: nowrap; }

/* Icon-only dropdowns (gear, avatar): square summary, no text underline. */
.navmenu.iconmenu > summary,
.navmenu.usermenu > summary {
  padding: 14px 12px; border-bottom: none;
}
.navmenu.iconmenu > summary::after,
.navmenu.usermenu > summary::after { content: none; }

.navmenu.iconmenu .gear { font-size: 18px; line-height: 1; opacity: 0.85; }
.navmenu.iconmenu > summary:hover .gear { opacity: 1; }
.navmenu.iconmenu.is-active .gear { opacity: 1; color: var(--vert-clair); }

/* Avatar pill: initials on a quiet Vert clair ground, the one brand accent. */
.navmenu.usermenu .avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 999px;
  background: var(--vert-clair); color: var(--forest);
  font-size: 13px; font-weight: 700; letter-spacing: 0.02em;
}
.navmenu.usermenu.is-active .avatar { box-shadow: 0 0 0 2px var(--beige-70); }

/* Right-anchored panels so the gear/avatar menus open flush to the bar's edge
   instead of overflowing past it. */
.navmenu-panel--right { left: auto; right: 0; }

/* User name header inside the user menu (not a link). */
.usermenu-name {
  padding: 8px 12px 6px; font-size: 13px; color: var(--beige-85);
  border-bottom: 1px solid rgba(252, 249, 240, 0.12); margin-bottom: 4px;
}

/* Close an open dropdown when another gets focus/opened is a JS concern;
   left out on purpose (guardrail 3). Native <details> allows two open at once;
   acceptable here. */

/* ============================================================
   Leads reference index — row emphasis
   Company is the visual anchor (reps reason by target account); status is a
   readable pill, not a raw DB value; score is weighted by segment. These
   classes sit on the shared .rowcard grid (6 tracks unchanged) — only the
   in-cell rendering differs, so the 7 other .rowcard views are untouched.
   ============================================================ */

/* Company anchor: the primary line of the row. */
.rowcard .co-anchor { min-width: 0; }
.rowcard .co-name {
  color: var(--forest); text-decoration: none;
  font-weight: 700; font-size: 16px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;
}
.rowcard a.co-name:hover { text-decoration: underline; }
.rowcard .co-name-empty { color: var(--ink-2); font-weight: 400; }

/* Lead name demoted to secondary (was the anchor before). */
.rowcard .who .nm { font-weight: 400; font-size: 15px; color: var(--ink-2); }

/* Score weighted by segment on the light ground: hot draws the eye with strong
   Forest ink, cold recedes to Ink-2. The Vert clair accent stays for fills and
   markers, never low-contrast text. */
.rowcard .sc.seg-hot  .val { color: var(--forest); }
.rowcard .sc.seg-warm .val { color: var(--ink); }
.rowcard .sc.seg-cold .val { color: var(--ink-2); }
.rowcard .sc.seg-hot  .seg { color: var(--forest); }

/* Status pill: readable label on a quiet tone band. Tones stay within the DA
   (Vert clair accent, Beige neutrals, error red); no new hues. */
.pill {
  display: inline-block; font-size: 12px; font-weight: 700;
  letter-spacing: 0.03em; padding: 3px 10px; border-radius: 999px;
  white-space: nowrap; border: 1px solid transparent;
}
/* DA canonical: dark ink on the light reading ground (the two-grounds rule).
   live and attn carry Vert clair, so they read on either ground and take no
   split. */
.pill-neutral { background: color-mix(in srgb, var(--prune) 8%, var(--beige)); color: var(--ink);
                border-color: var(--line); }
.pill-wait    { background: transparent; color: var(--ink-2);
                border-color: var(--prune-20); }
.pill-live    { background: var(--vert-clair); color: var(--forest);
                border-color: var(--vert-clair); }
.pill-attn    { background: transparent; color: var(--vert-clair);
                border-color: var(--vert-clair); }
.pill-good    { background: color-mix(in srgb, var(--vert-clair) 22%, var(--beige)); color: var(--vert-fonce);
                border-color: var(--vert-clair); }
.pill-off     { background: transparent; color: var(--ink-2);
                border-color: var(--line); }


/* Row action button, the row's primary action. Quiet ghost at rest so a long
   list stays light; it fills Forest (the .btn-approve engagement colour) when the
   row is hovered or the button focused — weight appears only where the eye is. */
.rowcard .actions .btn-row {
  display: inline-flex; align-items: center;
  padding: 6px 12px; font-size: 13px; border-radius: 6px;
  color: var(--forest); text-decoration: none;
  border: 1px solid var(--prune-20); background: transparent;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.rowcard:hover .actions .btn-row,
.rowcard .actions .btn-row:hover,
.rowcard .actions .btn-row:focus-visible {
  background: var(--forest); border-color: var(--forest); color: var(--beige);
}




/* Triage form (reply to handle). */
.triage-form { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-top: 14px; }
.triage-form .tf-field { display: flex; flex-direction: column; gap: 4px; }
.triage-form .tf-field label {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2);
}
.triage-form .tf-field input, .triage-form .tf-field select { margin: 0; }
.triage-form .tf-grow { flex: 1; min-width: 200px; }
.triage-form .tf-grow input { width: 100%; box-sizing: border-box; }
.triage-lost { margin-top: 12px; }


/* ============================================================
   Recontact queue — due-date group headers
   Tasks grouped overdue / today / upcoming (HubSpot model). Each header is a
   full-width band above its rows, with a count. Overdue carries the error tone
   so lateness reads first. On the light page ground.
   ============================================================ */
.due-group {
  display: flex; align-items: center; gap: 10px;
  margin: 18px 0 4px; padding: 0 4px;
}
.due-group:first-child { margin-top: 4px; }
.due-group-label {
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--prune);
}
.due-group-count {
  font-size: 11px; font-weight: 700; line-height: 1;
  padding: 3px 8px; border-radius: 999px;
  background: rgba(53, 50, 66, 0.10); color: var(--prune);
}
.due-group-late .due-group-label { color: var(--error); }
.due-group-late .due-group-count { background: rgba(178, 58, 58, 0.14); color: var(--error); }

/* ============================================================
   Recontact queue — dedicated grid
   This view has no checkbox and no score; it detourned the shared .rowcard grid
   (a date fell into the 24px checkbox track, colliding "Quand"/"Lead"). Give it
   its own column template on both header and rows so columns line up. Justified.
   Columns: [when] [lead] [company] [type] [note] [actions]
   ============================================================ */
.rowcard-head.rc-grid,
.rc-grid .rowcard {
  grid-template-columns: 150px minmax(160px, 280px) minmax(140px, 200px) 90px minmax(160px, 260px) 1fr;
}

/* ============================================================
   Record pages (lead / company detail) — three-column layout
   Left: identity + qualification, inline-editable (read + pencil, input on
   click). Center: relationship thread. Right: associations (company,
   conversations, tasks). Stacks on narrow screens. DA colors only.
   ============================================================ */

/* Header: name + key actions across the top. */
.record-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: 20px;
}
.record-head-main h1 { margin: 4px 0 2px; }
.record-head-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

/* The grid: left flexible-narrow, center widest, right narrow. */
.record-grid {
  display: grid;
  grid-template-columns: minmax(280px, 340px) minmax(0, 1fr) minmax(240px, 300px);
  gap: 20px; align-items: start;
}
@media (max-width: 1100px) {
  .record-grid { grid-template-columns: 1fr; }
}

.record-left, .record-right { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
/* Left column wraps its cards in one <form> (inline edit submits them together),
   so the column gap lands on the form, not between cards. Carry it on the form. */
.record-left > form { display: flex; flex-direction: column; gap: 16px; }
.record-center { min-width: 0; }

/* Cards on record pages: dark, on-DA. */
.rec-card {
  background: var(--forest); color: var(--beige);
  border-radius: 10px; padding: 18px 20px;
}
.rec-card-title {
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--vert-clair); margin-bottom: 12px;
}
.record-center > .rec-card-title { color: var(--prune); }
.rec-card a, .record-right a { color: var(--beige); }
.rec-card .meta, .rec-card .frozen { color: var(--beige-70); }
.rec-note { font-size: 13px; color: var(--beige-70); margin: 0 0 10px; line-height: 1.5; }

/* Inline-editable field: read view (value + pencil) by default; edit view
   (input) hidden until .is-editing. */
.rec-field {
  display: flex; align-items: baseline; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid rgba(252,249,240,0.10);
}
.rec-field:last-of-type { border-bottom: none; }
.rec-field-label {
  flex: none; width: 92px; font-size: 12px; color: var(--beige-70);
  text-transform: uppercase; letter-spacing: 0.03em;
}
.rec-field-read { display: flex; align-items: baseline; gap: 8px; flex: 1; min-width: 0; }
.rec-field-value { color: var(--beige); font-size: 14px; word-break: break-word; }
.rec-edit {
  background: none; border: none; cursor: pointer; padding: 0 2px;
  color: var(--beige-70); font-size: 13px; line-height: 1; flex: none;
  opacity: 0; transition: opacity 0.12s;
}
.rec-field:hover .rec-edit { opacity: 1; }
.rec-edit:hover { color: var(--vert-clair); }
.rec-lock { font-size: 10px; color: var(--beige-70); text-transform: uppercase; letter-spacing: 0.04em; }

/* Edit view: shown only when the field is editing. */
.rec-field-edit { display: none; flex: 1; min-width: 0; }
.rec-field.is-editing .rec-field-read { display: none; }
.rec-field.is-editing .rec-field-edit { display: block; }
.rec-field-edit input, .rec-field-edit select, .rec-field-edit textarea {
  width: 100%; box-sizing: border-box; margin: 0;
}

.rec-check { display: flex; gap: 8px; align-items: center; font-size: 14px; color: var(--beige); margin-top: 12px; }
.rec-check input { width: auto; }

/* Save bar: hidden until a field is opened for edit. */
.rec-save-bar { display: none; margin-top: 4px; }
.rec-save-bar.is-visible { display: block; }

.rec-company-form { display: flex; flex-direction: column; gap: 10px; }
.rec-company-form select { margin: 0; }

/* Associations (right) — used by the company sheet (rec-card ground). */
.rec-assoc { padding: 8px 0; border-bottom: 1px solid rgba(252,249,240,0.10); }
.rec-assoc:last-child { border-bottom: none; }
.rec-assoc a { font-weight: 700; }
.rec-assoc-sub { display: block; font-size: 12px; color: var(--beige-70); margin-top: 2px; }

/* AI research config: two-column layout (config + test bench) */
.ai-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  align-items: start;
}
@media (max-width: 800px) {
  .ai-grid { grid-template-columns: 1fr; }
}
.two-col {
  display: flex;
  gap: 12px;
}
.two-col > div { flex: 1; }
.preview-out {
  margin: 12px 0 0;
  padding: 12px 14px;
  background: var(--beige);
  color: var(--prune);
  border: 1px solid var(--prune-15);
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.5;
  max-height: 340px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
}
/* readable preview of the assembled prompt (not raw JSON) */
.preview-readable { margin: 12px 0 0; }
.preview-block {
  border: 1px solid var(--prune-15);
  border-radius: 8px;
  background: var(--beige);
  padding: 12px 14px;
  margin-bottom: 8px;
}
.preview-block-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--prune);
  opacity: 0.6;
  margin-bottom: 6px;
}
.preview-block-body {
  font-size: 13px;
  line-height: 1.6;
  color: var(--prune);
  white-space: pre-wrap;
  word-break: break-word;
}
.preview-meta { font-size: 12px; color: var(--prune); opacity: 0.7; margin: 4px 0 10px; display: flex; gap: 14px; flex-wrap: wrap; }
.preview-meta b { font-weight: 600; opacity: 1; }
.preview-raw-toggle {
  background: transparent; border: 0; color: var(--prune);
  font-size: 12px; text-decoration: underline; cursor: pointer; padding: 0; margin-top: 4px;
}

/* AI research: informational note (not a warning) */
.ai-note {
  background: var(--vert-clair);
  color: var(--forest);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 13px;
  line-height: 1.5;
  margin-bottom: 16px;
}
/* Section header (groups the prompt sections and the bench) */
.section-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 20px 0 10px;
  flex-wrap: wrap;
}
.section-head > span:first-child {
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
}
.section-head-hint { font-size: 12px; color: var(--prune); opacity: 0.7; }
/* One editable prompt section */
.prompt-section {
  border: 1px solid var(--prune-15);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 10px;
  background: var(--beige);
}
.prompt-section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--prune-15);
  background: var(--beige-85);
}
.prompt-section-titles { display: flex; flex-direction: column; gap: 2px; }
.prompt-section-title { font-size: 14px; font-weight: 600; color: var(--prune); }
.prompt-section-hint { font-size: 12px; color: var(--prune); opacity: 0.7; }
.prompt-section-body {
  width: 100%;
  border: 0;
  border-radius: 0;
  padding: 12px 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  line-height: 1.6;
  background: var(--beige);
  color: var(--prune);
  resize: vertical;
  box-sizing: border-box;
}
.prompt-section-body:focus { outline: 2px solid var(--vert-clair); outline-offset: -2px; }
/* "guaranteed" chip on the output-contract section */
.chip-ok {
  font-size: 11px;
  padding: 2px 10px;
  border-radius: 20px;
  background: var(--vert-clair);
  color: var(--forest);
  white-space: nowrap;
}
/* Same chip, "needs attention" state: a half-filled sender identity breaks the
   generation later, so it has to read as a problem, not as a neutral fact. */
.chip-warn {
  font-size: 11px;
  padding: 2px 10px;
  border-radius: 20px;
  background: var(--error);
  color: var(--beige);
  white-space: nowrap;
}
/* injected-variable hint + token */
.var-hint { font-size: 12px; color: var(--prune); opacity: 0.85; margin: 8px 0 16px; }
.var-token {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 6px;
  background: var(--prune-15);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
}
/* typeahead for company search in the test bench */
.typeahead { position: relative; }
.typeahead-list {
  position: absolute;
  top: 100%; left: 0; right: 0;
  background: var(--beige);
  border: 1px solid var(--prune-15);
  border-radius: 8px;
  margin-top: 4px;
  z-index: 10;
  overflow: hidden;
  box-shadow: 0 4px 12px var(--prune-20);
}
.typeahead-item { padding: 8px 12px; font-size: 13px; cursor: pointer; color: var(--prune); }
.typeahead-item:hover { background: var(--beige-85); }

/* typeahead: constant visual feedback + chosen-company confirmation */
.typeahead-feedback { font-size: 12px; color: var(--prune); opacity: 0.75; margin: 6px 0 0; }
.typeahead-feedback.feedback-empty { color: var(--error); opacity: 1; }
.typeahead-item { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.ta-name { font-weight: 600; }
.ta-domain { font-size: 12px; color: var(--prune); opacity: 0.6; }
.chosen-company {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--vert-clair);
  color: var(--forest);
  font-size: 14px;
}
.chosen-check { font-style: normal; font-weight: 700; }
.chosen-clear {
  margin-left: auto;
  background: transparent;
  border: 0;
  color: var(--forest);
  font-size: 12px;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
}
.btn-save:disabled { opacity: 0.5; cursor: not-allowed; }

/* --- Company research panel (right column of the company sheet) --- */
.research-panel { display: flex; flex-direction: column; gap: 10px; }
.research-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.research-state { font-size: 12px; color: var(--prune); opacity: 0.75; }
.research-notif {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: 8px; font-size: 13px;
  background: var(--vert-clair); color: var(--forest);
}
.research-notif.notif-fail { background: #f6e0e0; color: var(--error); }
.research-notif.notif-info { background: var(--beige-85); color: var(--prune); }
.notif-reload {
  margin-left: auto; background: transparent; border: 0;
  color: inherit; font-size: 12px; text-decoration: underline; cursor: pointer; padding: 0;
}
.research-section-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--prune); opacity: 0.6; margin: 8px 0 2px;
}
.research-item {
  border: 1px solid var(--prune-15); border-radius: 8px;
  padding: 10px 12px; background: var(--beige);
}
.research-item.is-stale { opacity: 0.6; }
.research-item-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 4px; }
.research-type { font-size: 12px; color: var(--prune); opacity: 0.7; font-family: ui-monospace, Menlo, monospace; }
.research-badges { display: flex; gap: 4px; flex-wrap: wrap; }
.research-value { font-size: 14px; color: var(--prune); line-height: 1.45; }
.research-sub { font-size: 12px; color: var(--prune); opacity: 0.7; margin-top: 4px; }
.research-sub a { color: var(--forest); }
.conf { font-size: 10px; padding: 1px 7px; border-radius: 20px; }
.conf-high { background: var(--vert-clair); color: var(--forest); }
.conf-medium { background: #f7edd3; color: #6b5410; }
.conf-low { background: #f0e2e2; color: #7a3a3a; }
.verified, .by-human, .stale {
  font-size: 10px; padding: 1px 7px; border-radius: 20px;
  background: var(--prune-15); color: var(--prune);
}
.verified { background: var(--vert-clair); color: var(--forest); }

/* --- Validation desk: the gestures on a fact / trigger --- */
/* Actions sit UNDER the value, revealed on hover/focus-within on pointer
   devices and always visible on touch: twelve facts each showing three buttons
   at rest turns the panel into a wall of controls. */
.research-actions {
  display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap;
  opacity: 0; transition: opacity 0.12s ease;
}
.research-item:hover .research-actions,
.research-item:focus-within .research-actions,
.research-actions.is-busy { opacity: 1; }
@media (hover: none) { .research-actions { opacity: 1; } }

.rs-act {
  font-family: inherit; font-size: 12px; line-height: 1.2;
  padding: 4px 10px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--prune-20); background: transparent; color: var(--prune);
}
.rs-act:hover { background: var(--prune-15); }
.rs-act:disabled { opacity: 0.45; cursor: not-allowed; }
/* Keep is the affirmative gesture: it carries the accent. */
.rs-act.rs-keep { border-color: var(--vert-clair); color: var(--forest); }
.rs-act.rs-keep:hover { background: var(--vert-clair); }
/* Discard is destructive: signalled, never the easiest click. */
.rs-act.rs-discard { border-color: var(--error); color: var(--error); }
.rs-act.rs-discard:hover { background: #f0e2e2; }

/* Inline edit form, shown in place of the value while correcting. */
.rs-edit { margin-top: 8px; display: none; }
.research-item.is-editing .rs-edit { display: block; }
.research-item.is-editing .research-value,
.research-item.is-editing .research-actions { display: none; }
.rs-edit textarea {
  width: 100%; font-family: inherit; font-size: 14px; line-height: 1.45;
  color: var(--prune); background: var(--beige);
  border: 1px solid var(--prune-20); border-radius: 6px; padding: 8px;
  resize: vertical; min-height: 62px;
}
.rs-edit-row { display: flex; gap: 6px; align-items: center; margin-top: 6px; }
.rs-edit select, .rs-add select, .rs-add input {
  font-family: inherit; font-size: 13px; color: var(--prune);
  background: var(--beige); border: 1px solid var(--prune-20);
  border-radius: 6px; padding: 5px 8px;
}
.rs-edit-row .rs-act { margin-left: auto; }
.rs-edit-row .rs-act + .rs-act { margin-left: 0; }

/* An empty notification must not paint as a bar: [hidden] beats the flex layout. */
.research-notif[hidden] { display: none; }

/* Research facts/signals as a leads-style sortable, paginated table (company
   sheet). Reuses the .rowcard grid + the .sort-h header vocabulary. The reset
   below lets a <button class="sort-h"> read like the header link, not a filled
   button (the base button rule gives padding + radius otherwise). The two grids
   differ only by the "Vérifié" column, which facts carry and signals do not. The
   in-place correction editor and the per-row message span the whole row. */
.sort-h { background: none; border: 0; padding: 0; }
/* Follows the shared .rowcard rule (app.css ~282): BOUNDED data columns keep
   every column at a stable width card to card, and a trailing 1fr carries the
   actions flush right — never 'auto', which grows with the button count and tears
   the columns out of line. */
/* One flexible column absorbs the slack (Fait / Signal / Lead grows), every other
   column is FIXED so it holds the same width card to card and the actions land at
   the same right edge whatever the button count. Track count matches the row cells. */
.rowcard-head.rf-grid, .rf-grid .rowcard {
  grid-template-columns: minmax(160px, 1fr) 92px 92px 108px 190px;
}
.rowcard-head.rt-grid, .rt-grid .rowcard {
  grid-template-columns: minmax(160px, 1fr) 92px 108px 100px;
}
.rowcard-head.cl-grid, .cl-grid .rowcard {
  grid-template-columns: minmax(160px, 1fr) 150px 90px 110px;
}
.cl-grid .rowcard { align-items: center; }
.rf-grid .rowcard, .rt-grid .rowcard { align-items: center; }
.rf-grid .rowcard.is-stale, .rt-grid .rowcard.is-stale { opacity: 0.6; }
.rf-grid .rowcard .research-actions, .rt-grid .rowcard .research-actions { margin-top: 0; justify-content: flex-end; }
.rf-grid .rowcard:hover .research-actions, .rf-grid .rowcard:focus-within .research-actions,
.rt-grid .rowcard:hover .research-actions, .rt-grid .rowcard:focus-within .research-actions { opacity: 1; }
.rf-grid .rs-edit, .rf-grid .rs-msg,
.rt-grid .rs-edit, .rt-grid .rs-msg { grid-column: 1 / -1; }
.rf-grid .rowcard.is-editing .rs-edit { display: block; }
.rf-grid .rowcard.is-editing .research-actions { display: none; }
.research-cell-val { min-width: 0; }
.research-cell-val .val { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The correction editor's confidence select is content-width (not the global
   select width:100%), so Annuler / Enregistrer land flush right like the row's
   action buttons instead of being pushed off by a full-width select. */
.rs-edit-row select { width: auto; }
/* Stack the detour grids on narrow, declared AFTER their column templates so this
   wins on source order (equal specificity) and the table never overflows sideways. */
@media (max-width: 900px) {
  .rf-grid .rowcard, .rt-grid .rowcard, .cl-grid .rowcard { grid-template-columns: 1fr; gap: 4px; }
}

/* Per-item feedback: a refused gesture is said here, next to the fact it
   concerns, never as a silent no-op (guardrail 11). */
.rs-msg { font-size: 12px; margin-top: 6px; color: var(--error); }
.rs-msg.is-ok { color: var(--forest); }
.rs-msg:empty { display: none; }

/* Manual add: a disclosure, closed by default. The panel's job is to show the
   research; typing a fact is the exception, not the resting state. */
.rs-add { margin-top: 4px; }
.rs-add > summary {
  cursor: pointer; font-size: 12px; color: var(--prune); opacity: 0.75;
  padding: 4px 0; list-style: none;
}
.rs-add > summary::-webkit-details-marker { display: none; }
.rs-add > summary::before { content: '+ '; }
.rs-add[open] > summary { opacity: 1; }
.rs-add-body {
  border: 1px dashed var(--prune-20); border-radius: 8px;
  padding: 10px 12px; display: flex; flex-direction: column; gap: 8px;
}
.rs-add textarea {
  width: 100%; font-family: inherit; font-size: 14px; line-height: 1.45;
  color: var(--prune); background: var(--beige);
  border: 1px solid var(--prune-20); border-radius: 6px; padding: 8px;
  resize: vertical; min-height: 54px;
}
.rs-add select, .rs-add input[type="text"], .rs-add input[type="date"] { width: 100%; }
.rs-field-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--prune); opacity: 0.6;
}
/* One source row = url + optional title. A lived fact adds none; a researched
   one adds as many as the rep found (same shape as the AI's). */
.rs-src-row { display: flex; gap: 6px; }
.rs-src-row input { flex: 1; }
.rs-src-add {
  align-self: flex-start; background: transparent; border: 0; padding: 0;
  font-family: inherit; font-size: 12px; color: var(--forest);
  text-decoration: underline; cursor: pointer;
}
.rs-hint { font-size: 11px; color: var(--prune); opacity: 0.6; }

/* Inbound quarantine ("Entrants à qualifier"): a card layout, not the shared
   tabular grid. Subject and excerpt are free text and the triage carries a
   lead-ref input, so each entry is a stacked card. Scoped to .iq-* classes:
   overrides the .rowcard grid to a vertical flow without touching any shared
   list grid. */
.rowcard.iq-item { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.iq-item .iq-top { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.iq-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 4px; }
.iq-actions form { margin: 0; display: inline-flex; gap: 6px; align-items: center; }
/* margin: 0 so the link field sits at the same height as the buttons on the row
   (the base input rule adds 6px/16px margins, which broke the .iq-actions
   align-items:center and pushed "Relier" out of line with "Créer"/"Jeter"). */
.iq-actions input[type=text] { padding: 7px 10px; font-family: inherit; font-size: 13px; margin: 0; }
/* Inbound-message reader (quarantine right panel): sender/date meta strip, a rule,
   the pre-wrapped body, then the triage actions. One component so its spacing lives
   here, not inline on each element. .iq-actions is shared with the list items (4px
   there), so the reader's 16px is scoped under .iq-msg. */
.iq-meta { display: flex; gap: 24px; flex-wrap: wrap; align-items: baseline; margin-top: 8px; font-size: 15px; color: var(--ink); }
.iq-meta .aiq-strip-lab { margin-right: 8px; }
.iq-msg .dash-rule { margin: 14px 0 0; }
.iq-msg .aiq-ref-lab { margin-top: 16px; }
.iq-msg .aiq-note { white-space: pre-wrap; margin: 8px 0 0; }
.iq-msg .iq-actions { margin-top: 16px; }

.ex-all { display: inline-flex; gap: 8px; align-items: center; margin: 0; font-size: 14px; } /* export select-all label */

/* ============================================================
   COCKPIT SHELL (chantier 13)
   Surface de contrôle bornée à l'écran, en place du bandeau .topnav et
   du défilement pleine page. Trois zones : rail vertical de navigation
   (Prune) | zone de travail qui défile en interne (Beige) | inspecteur
   contextuel optionnel (surface). Le contenu des vues reste tel quel
   (rowcard, rec-card, tabs, pills) : seul le châssis est neuf.
   Ground rule DA: dark ground -> light text. Density is the register.
   ============================================================ */
body.cockpit { height: 100dvh; margin: 0; overflow: hidden; }
body.cockpit.resizing { cursor: col-resize; user-select: none; }

.app {
  height: 100dvh; position: relative;
  display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr);
  overflow: hidden;
  /* No width transition: animating grid-template-columns reflows the whole rail
     frame by frame, which slides the labels, dots and account block. The toggle
     snaps instead (a layout property should not be animated). */
}
.app.has-insp { grid-template-columns: var(--rail-w) minmax(0, 1fr) var(--insp-w); }

/* ---------- Rail (Prune ground -> light text) ---------- */
.rail {
  background: var(--prune); color: var(--beige);
  display: flex; flex-direction: column; min-height: 0;
  overflow: hidden; padding: 14px 10px; gap: 2px;
}
.rail .brand {
  display: flex; align-items: center; gap: 9px;
  /* Symmetric vertical padding so the brand box matches the hamburger height:
     the logo centres on the burger, and the burger doesn't shift when the brand
     hides in the narrow state. */
  padding: 6px 8px; font-weight: 700; font-size: 17px;
  color: var(--beige); text-decoration: none;
}
/* Dropped-in brand assets (web/public/img/). The wordmark shows in the wide
   rail; the compact mark (icon*) shows in the collapsed rail. */
.rail .brand-logo { display: block; height: 22px; width: auto; max-width: 150px; }
.rail .brand-icon { display: none; height: 28px; width: auto; }

/* The nav is the only scroll region (three-zone rail: rail-top and rail-foot
   stay pinned). scrollbar-gutter reserves the track in both states, so the items
   never shift when the scrollbar appears or the rail is toggled. */
.pipe {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden; scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--beige) 22%, transparent) transparent;
}
.pipe::-webkit-scrollbar { width: 8px; }
.pipe::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--beige) 20%, transparent); border-radius: 8px; }
.pipe::-webkit-scrollbar-track { background: transparent; }

.pipe-group { display: flex; flex-direction: column; gap: 1px; margin-top: 10px; }
.pipe-items { display: flex; flex-direction: column; gap: 1px; }
/* Family header doubles as the accordion toggle (a real button). */
.pipe-label {
  display: flex; align-items: center; gap: 6px; width: 100%;
  border: 0; background: transparent; cursor: pointer; font: inherit; text-align: left;
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.12em;
  color: color-mix(in srgb, var(--beige) 55%, transparent); padding: 6px 8px 4px;
  transition: color 0.12s;
}
.pipe-label:hover { color: color-mix(in srgb, var(--beige) 82%, transparent); }
.pipe-label-txt { flex: 1; min-width: 0; }
.pipe-caret {
  flex: none; width: 0; height: 0;
  border-left: 4px solid currentColor;
  border-top: 3px solid transparent; border-bottom: 3px solid transparent;
  transition: transform 0.15s ease-out;
}
.pipe-group:not(.is-folded) .pipe-caret { transform: rotate(90deg); }
/* Fold hides the items, but only while the rail is expanded (collapsed, every
   item shows as a dot regardless of accordion state). */
.app:not(.rail-narrow) .pipe-group.is-folded > .pipe-items { display: none; }
/* The family holding the current screen: header in the accent, so a folded
   family still shows it contains the active page. */
.pipe-group.has-active > .pipe-label { color: var(--vert-clair); }

/* One nav entry. A real <a> (works with JS off, keyboard-navigable). Active
   state is set server-side (navOn), marked by an accent bar + Vert clair dot. */
.rail .nav {
  display: flex; align-items: center; gap: 9px;
  height: 36px; box-sizing: border-box;
  padding: 8px; border-radius: 7px; position: relative;
  color: color-mix(in srgb, var(--beige) 86%, transparent);
  font-size: 14px; text-decoration: none;
  transition: background 0.12s, color 0.12s;
}
.rail .nav:hover { background: color-mix(in srgb, var(--beige) 8%, transparent); color: var(--beige); }
.rail .nav:active { background: color-mix(in srgb, var(--beige) 16%, transparent); }
.rail .nav .dot {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: color-mix(in srgb, var(--beige) 40%, transparent);
}
.rail .nav .label-txt {
  flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rail .nav.is-active {
  background: color-mix(in srgb, var(--beige) 11%, transparent);
  color: var(--beige); font-weight: 700;
}
.rail .nav.is-active::before {
  content: ""; position: absolute; left: -10px; top: 8px; bottom: 8px;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--vert-clair);
}
.rail .nav.is-active .dot { background: var(--vert-clair); }

/* Load badge: how much work waits in that queue. Quiet band at rest; the accent
   (.is-hot) is reserved for queues that genuinely need attention (inbound,
   conflicts, overdue recontacts). A count of zero emits no badge at all. */
.rail .badge {
  margin-left: auto; flex: none;
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
  line-height: 1; padding: 3px 7px; border-radius: 999px;
  background: color-mix(in srgb, var(--beige) 14%, transparent); color: var(--beige);
}
.rail .badge.is-hot { background: var(--vert-clair); color: var(--forest); }
.rail .nav.is-active .badge { background: color-mix(in srgb, var(--beige) 20%, transparent); }

/* The foot reserves the same scrollbar gutter as the nav, so its items line up
   with the nav items instead of drifting a gutter-width to the side. It never
   scrolls; the gutter is reserved, not shown. */
.rail-foot {
  flex: none; padding-top: 12px;
  overflow: hidden; scrollbar-gutter: stable; scrollbar-width: thin;
}
/* Folding the settings family hides its items in BOTH rail states, so the foot
   keeps a constant height and the account block never shifts on toggle. */
.rail-foot .pipe-group.is-folded > .pipe-items { display: none; }
.rail .user {
  display: flex; align-items: center; gap: 9px; margin-top: 12px;
  height: 44px; box-sizing: border-box;
  padding: 10px 8px 2px; text-decoration: none;
  border-top: 1px solid color-mix(in srgb, var(--beige) 14%, transparent);
}
.rail .user .avatar {
  width: 28px; height: 28px; border-radius: 50%; flex: none;
  background: var(--vert-clair); color: var(--forest);
  display: grid; place-items: center; font-size: 12px; font-weight: 700;
}
.rail .user .who { min-width: 0; }
.rail .user-name {
  display: block; font-size: 13px; color: color-mix(in srgb, var(--beige) 88%, transparent);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rail .user-sub { display: block; font-size: 11px; color: color-mix(in srgb, var(--beige) 55%, transparent); }
.rail .user-sub a { color: color-mix(in srgb, var(--beige) 78%, transparent); text-decoration: none; }
.rail .user-sub a:hover { color: var(--beige); text-decoration: underline; }

/* ---------- Rail header: hamburger + brand ---------- */
.rail-top { flex: none; display: flex; align-items: center; gap: 8px; padding: 4px 4px 12px; }
.rail-burger {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border: 0; border-radius: 7px;
  /* Override the global button padding (12px 22px): with border-box it would
     collapse the 34px box to zero content and crush the hamburger glyph. */
  padding: 0;
  background: transparent; color: var(--beige); cursor: pointer;
  transition: background 0.12s;
}
.rail-burger:hover { background: color-mix(in srgb, var(--beige) 10%, transparent); }
/* Thin three-line hamburger, drawn in CSS (DA §6: thin line, single color). */
.burger, .burger::before, .burger::after {
  content: ""; display: block; width: 18px; height: 2px;
  background: currentColor; border-radius: 2px;
}
.burger { position: relative; }
.burger::before, .burger::after { position: absolute; left: 0; }
.burger::before { top: -6px; }
.burger::after { top: 6px; }

/* ---------- Collapsed rail: the hamburger narrows the rail to a slim strip that
   keeps each item as a dot + its notification badge, plus the user avatar, all
   centred. Labels, family headers and the brand step aside; the name returns on
   hover. The current screen name lives on in the context banner. ---------- */
.app.rail-narrow { grid-template-columns: var(--rail-w-narrow) minmax(0, 1fr); }
.app.rail-narrow.has-insp { grid-template-columns: var(--rail-w-narrow) minmax(0, 1fr) var(--insp-w); }
.app.rail-narrow .rail-top { flex-direction: column; gap: 8px; padding: 4px 0 10px; }
.app.rail-narrow .pipe-label,
.app.rail-narrow .label-txt,
.app.rail-narrow .user .who { display: none; }
/* Collapsed brand: the wordmark gives way to the compact mark, stacked under the
   hamburger. Without a mark the brand hides entirely (hamburger only). */
.app.rail-narrow .brand:not(.has-icon) { display: none; }
.app.rail-narrow .brand { padding: 0; }
.app.rail-narrow .brand-logo, .app.rail-narrow .brand-txt { display: none; }
.app.rail-narrow .brand-icon { display: block; }
.app.rail-narrow .nav { justify-content: center; padding: 9px 8px; gap: 0; }
/* Collapsed active entry: a Vert clair pill (the accent bar is gone here), so
   "you are here" reads without the label. */
.app.rail-narrow .nav.is-active { background: color-mix(in srgb, var(--vert-clair) 20%, transparent); }
.app.rail-narrow .nav.is-active::before { display: none; }
/* Faint hairline between families, so the collapsed dot column stays scannable. */
.app.rail-narrow .pipe-group + .pipe-group {
  margin-top: 8px; padding-top: 9px;
  border-top: 1px solid color-mix(in srgb, var(--beige) 8%, transparent);
}
.app.rail-narrow .nav .badge {
  position: absolute; top: 1px; right: 3px; margin: 0; padding: 1px 5px; font-size: 10px;
}
.app.rail-narrow .user { justify-content: center; padding-left: 0; padding-right: 0; }
/* The foot keeps a constant height so its items and the account block never move
   on toggle: the settings header keeps its box (reserved, invisible) collapsed. */
.app.rail-narrow .rail-foot .pipe-label { display: flex; visibility: hidden; }

/* Keyboard focus (DA accent ring on the Prune ground). */
.rail .nav:focus-visible,
.rail .brand:focus-visible,
.rail-burger:focus-visible,
.rail .user-sub a:focus-visible {
  outline: 2px solid var(--vert-clair); outline-offset: 2px; border-radius: 6px;
}

/* Collapsed-rail tooltip: the item name on hover/focus. position:fixed on <body>
   so it escapes the rail's overflow clip (a right-side flyout). */
.rail-tip {
  position: fixed; z-index: var(--z-tooltip); transform: translateY(-50%);
  background: var(--prune); color: var(--beige);
  font-size: 12.5px; font-weight: 600; line-height: 1; white-space: nowrap;
  padding: 7px 10px; border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.28);
  pointer-events: none; opacity: 0; transition: opacity 0.1s ease-out;
}
.rail-tip.is-visible { opacity: 1; }

/* Toggle feedback: a quick content fade conveys the collapse/expand state change
   without moving anything (opacity only, no slide). Reduced-motion is covered by
   the global animation reset below. */
@keyframes railContentFade { from { opacity: 0.4; } to { opacity: 1; } }
.app.rail-animating .pipe,
.app.rail-animating .rail-foot { animation: railContentFade 0.16s ease-out; }

/* ---------- Work area (Beige ground, internal scroll only) ---------- */
.work { min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--beige); }
.work-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* Content wrapper inside the scroll owns width + padding. A converted view keeps
   its .wrap/.wrap-wide (editorial 980 vs wide 1400); a new view uses .work-body.
   The shell caps and centres them; an inline max-width on the view still wins. */
.work-body,
.cockpit .work-scroll > .wrap-wide {
  max-width: var(--work-max); margin: 0 auto; padding: 26px clamp(22px, 3.5vw, 52px) 56px;
}
.cockpit .work-scroll > .wrap {
  max-width: 980px; margin: 0 auto; padding: 26px clamp(22px, 3.5vw, 52px) 56px;
}
/* Cockpit resets the editorial 40px h1 to a denser 24px inside the work plane;
   the rest of the type scale is untouched. */
.cockpit .work-head { margin-bottom: 22px; }
.cockpit .work-head h1 { font-size: 24px; margin: 2px 0 6px; }

/* ---------- Context banner: names the current screen, pinned above the work
   scroll so "you are here" holds when the rail is narrow. One source: the
   canonical name from web/src/nav.js, rendered by _head. ---------- */
.ctx-bar {
  flex: none; display: flex; align-items: baseline; gap: 8px;
  padding: 12px clamp(22px, 3.5vw, 52px);
  background: var(--beige); border-bottom: 1px solid var(--line);
}
.ctx-name { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); letter-spacing: 0.01em; }
.ctx-count { font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--vert-clair); }
.ctx-count::before { content: "·"; margin-right: 7px; color: var(--ink-2); font-weight: 400; }

/* ---------- Inspector (optional third zone) ---------- */
.inspector {
  background: var(--surface); border-left: 1px solid var(--line);
  min-height: 0; display: flex; flex-direction: column; overflow: hidden;
}
.insp-head { flex: none; border-bottom: 1px solid var(--line); padding: 16px 18px 12px; }
.insp-head h2 { font-size: 15px; margin: 0; }
.insp-head p { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-2); }
/* Lean inspector (a title-only head, no mode toggle): its hairline lands at the
   same height as the context banner's, so the two top rules read as one line.
   Matches .ctx-bar's 12px vertical rhythm. Used by the openers detail sheet. */
.insp-lean .insp-head { padding: 12px 18px; }
.insp-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 16px 18px 28px; display: flex; flex-direction: column; gap: 13px; }

/* ---------- Inspector resizer (drag the border, keyboard-adjustable) ---------- */
.resizer {
  position: absolute; top: 0; bottom: 0; right: var(--insp-w);
  width: 11px; margin-right: -5px; cursor: col-resize;
  z-index: var(--z-resizer); display: flex; justify-content: center;
}
.resizer::before { content: ""; width: 1px; background: var(--line); transition: width 0.1s, background 0.1s; }
.resizer:hover::before, .resizer.is-drag::before, .resizer:focus-visible::before { width: 3px; background: var(--vert-clair); }
.resizer:focus-visible { outline: none; }

/* ---------- Rail collapses to icons on narrow screens ---------- */
/* The rail stays full width until the user folds it with the hamburger; only
   the inspector resizer steps aside on a small viewport. */
@media (max-width: 1080px) {
  .resizer { display: none; }
}

/* Phone: the shell stops being a cockpit. Rail becomes a sticky top strip and
   the page scrolls normally (reach over density). Rare for an internal CRM. */
@media (max-width: 720px) {
  body.cockpit { height: auto; overflow: auto; }
  .app, .app.has-insp { grid-template-columns: 1fr; height: auto; }
  .rail {
    flex-direction: row; flex-wrap: wrap; align-items: center;
    overflow: visible; position: sticky; top: 0; z-index: var(--z-sticky);
  }
  .rail .pipe-group { flex-direction: row; flex-wrap: wrap; gap: 2px; margin-top: 0; }
  .rail-foot { margin-top: 0; }
  .work, .work-scroll, .inspector { overflow: visible; }
}

@media (prefers-reduced-motion: reduce) {
  .app, .app *, .rail *, .resizer::before { transition: none !important; animation: none !important; }
}

/* ============================================================
   Error page (chantier 15): standalone, centred, DA. Used for 403/404/500.
   No rail — an error is not a work screen. Beige ground, Vert clair figure.
   ============================================================ */
.errpage {
  min-height: 100dvh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
  gap: 8px; padding: 40px;
}
.errpage-mark { color: var(--vert-clair); font-size: 26px; }
.errpage-code {
  font-size: 64px; font-weight: 700; line-height: 1;
  color: var(--vert-clair); font-variant-numeric: tabular-nums;
}
.errpage h1 { font-size: 26px; margin: 6px 0 0; }
.errpage p { color: rgba(53, 50, 66, 0.7); max-width: 46ch; margin: 0 0 10px; }
.errpage-actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
/* .btn-* set colour/border; the padding lives on the button selector, so give
   the anchor variants their own box here. */
.errpage-actions a {
  text-decoration: none; display: inline-flex; align-items: center;
  padding: 11px 20px; border-radius: 8px; font-size: 15px;
}

/* ============================================================
   Deals — light opportunity pipeline (chantier 14)
   Header stat tiles (KPI row, no gradient/hero) + three stage columns
   (meeting / won / lost). Deal cards keep the brand's dark-card identity.
   ============================================================ */
.deal-stats { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 22px; }
.deal-tile {
  flex: 1 1 150px; border: 1px solid var(--prune-15); border-radius: 10px;
  padding: 14px 16px; background: var(--surface); display: flex; flex-direction: column; gap: 2px;
}
.deal-tile .dt-val { font-size: 22px; font-weight: 700; color: var(--prune); font-variant-numeric: tabular-nums; }
.deal-tile .dt-lab { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-2); }

.deal-pipeline { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; align-items: start; }
@media (max-width: 900px) { .deal-pipeline { grid-template-columns: 1fr; } }

.deal-col { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.deal-col-head { display: flex; align-items: center; gap: 10px; padding: 0 2px 4px; }
.dch-label { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--prune); }
.dch-count {
  font-size: 12px; font-weight: 700; line-height: 1; padding: 3px 9px; border-radius: 999px;
  background: var(--prune-15); color: var(--prune);
}
.deal-empty {
  padding: 20px 14px; text-align: center; color: rgba(53, 50, 66, 0.5);
  border: 1px dashed var(--prune-15); border-radius: 10px; font-size: 13px;
}

.deal-card {
  background: var(--forest); color: var(--beige);
  border-radius: 10px; padding: 14px 16px; display: flex; flex-direction: column; gap: 4px;
}
.deal-lead { color: var(--beige); font-weight: 700; font-size: 15px; text-decoration: none; }
.deal-lead:hover { text-decoration: underline; }
.deal-co { color: var(--beige-85); font-size: 13px; }
.deal-meta { display: flex; align-items: baseline; gap: 12px; margin-top: 4px; }
.deal-value { color: var(--vert-clair); font-weight: 700; font-size: 16px; font-variant-numeric: tabular-nums; }
.deal-when { color: var(--beige-70); font-size: 12px; }
.deal-owner { color: var(--beige-70); font-size: 12px; }
.deal-actions { display: flex; gap: 8px; margin-top: 10px; }
.deal-actions form { margin: 0; }
.deal-card .btn-save { background: var(--beige); color: var(--prune); padding: 7px 14px; font-size: 13px; }
.deal-card .btn-ghost { background: transparent; color: var(--beige); border: 1px solid var(--beige-70); padding: 7px 14px; font-size: 13px; }
.deal-edit { margin-top: 8px; }
.deal-edit > summary { cursor: pointer; font-size: 12px; color: var(--beige-70); list-style: none; }
.deal-edit > summary::-webkit-details-marker { display: none; }
.deal-edit > summary::before { content: '+ '; }
.deal-value-form { display: flex; gap: 6px; margin-top: 8px; }
.deal-value-form input {
  margin: 0; padding: 7px 10px; font-size: 13px; width: auto; flex: 1;
  background: var(--beige); color: var(--prune); border: 1px solid var(--beige-70);
}
.deal-reopen { margin-top: 10px; }
.deal-reopen form, .deal-reopen { margin: 0; }

/* Deal card on the lead sheet: open with "RDV obtenu", then track it. Sits in
   the Forest rec-card, so buttons follow the dark-card rules. */
.rec-card .btn-save { background: var(--beige); color: var(--prune); }
.lead-deal-open { margin-top: 4px; }
.lead-deal-open > summary {
  cursor: pointer; font-size: 13px; font-weight: 700; color: var(--vert-clair); list-style: none;
}
.lead-deal-open > summary::-webkit-details-marker { display: none; }
.lead-deal-open > summary::before { content: '+ '; }
.lead-deal-form { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.lead-deal-form label { font-size: 12px; color: var(--beige-70); text-transform: uppercase; letter-spacing: 0.03em; }
.lead-deal-form input { margin: 0; background: var(--beige); color: var(--prune); border: 1px solid var(--beige-70); }
.lead-deal-form .btn-save { align-self: flex-start; padding: 8px 16px; }
.lead-deal-state { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.lead-deal-val { color: var(--vert-clair); font-weight: 700; font-variant-numeric: tabular-nums; }
.lead-deal-actions { display: flex; gap: 8px; margin: 4px 0 10px; }
.lead-deal-actions form { margin: 0; }
.lead-deal-actions .btn-save, .lead-deal-actions .btn-ghost { padding: 7px 14px; font-size: 13px; }
.lead-deal-link { display: inline-block; font-size: 13px; color: var(--beige); text-decoration: underline; }

/* ============================================================
   Bounded work column (chantier 13, refonte) — faithful to the Config IA mockup.
   A `bounded` screen owns the full .work column: a FIXED header (+ tabs), an
   internal .work-scroll for the body, and an optional pinned savebar. Only takes
   effect when .work-head is a DIRECT child of .work; editorial views keep their
   scrolling header untouched.
   ============================================================ */
.work > .work-head {
  flex: none; margin: 0; padding: 15px clamp(22px, 3.5vw, 52px) 0;
  border-bottom: 1px solid var(--line); background: var(--beige);
}
.work > .work-head .eyebrow {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.11em; color: var(--ink-2);
}
.work > .work-head h1 { font-size: 23px; font-weight: 700; margin: 2px 0 0; }
.work > .work-head .tabs { margin: 12px 0 0; border-bottom: none; }

/* Body padding inside the internal scroll of a bounded screen. Centred like the
   validated settings pages (cadence/dashboard use .work-body margin:0 auto): a
   left-pinned column left a dead strip on the wide work plane, so Config IA sat
   lopsided next to every page it should match. The draft tab opts out via
   .aiq-pad (full-bleed cockpit). */
.work-scroll > .ai-pad { padding: 22px clamp(22px, 3.5vw, 52px) 40px; max-width: var(--work-max); margin-inline: auto; }

/* Optimistic save bar pinned at the bottom of the work column. Hidden until a
   field changes, then slides in. JS toggles .is-visible / .is-saved. */
.savebar {
  flex: none; display: flex; align-items: center; gap: 12px;
  padding: 0 clamp(22px, 3.5vw, 52px); max-height: 0; opacity: 0; overflow: hidden;
  background: var(--surface); border-top: 0 solid var(--line);
  transition: max-height 0.18s ease-out, opacity 0.18s ease-out, padding 0.18s ease-out;
}
.savebar.is-visible { max-height: 72px; opacity: 1; padding: 13px clamp(22px, 3.5vw, 52px); border-top: 1px solid var(--line); }
.savebar .sb-msg { font-size: 13px; font-weight: 700; display: inline-flex; align-items: center; gap: 8px; }
.savebar .sb-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--vert-clair); }
.savebar.is-saved .sb-dot { background: var(--forest); }
.savebar .spacer { flex: 1; }
.savebar .btn-save, .savebar .btn-ghost { margin: 0; padding: 9px 18px; font-size: 14px; }

/* ============================================================
   Dashboard — home day-load view (chantier 7)
   Top: two zones. Left is the actionable worklist (hairline rules on the open
   canvas, act now); right is a follow-up panel (the second neutral surface:
   live campaign + deals portfolio, one link per section header so numbers never
   ask "am I clickable?"). Below, full width, a reminders timeline band (sooner
   to later). Colour is scarce and semantic: Vert clair marks a queue count where
   work waits, the error tone marks overdue reminders, everything else is Prune.
   No repeated cards, no icons; hierarchy comes from size and state.
   ============================================================ */
.dash { max-width: var(--work-max); }

/* A light human anchor. The canonical screen name lives in the context banner
   above (the page h1); this greeting is deliberately a <p>, not a heading. */
.dash-hd { margin-bottom: 28px; }
.dash-hello { margin: 0; font-size: 26px; font-weight: 700; color: var(--prune); letter-spacing: -0.01em; }
.dash-date { margin: 5px 0 0; font-size: 14px; color: var(--ink-2); }

/* Two zones: the worklist (fluid) and a fixed follow-up panel. Collapses to one
   column when the work area narrows. */
.dash-grid { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 32px; align-items: start; }
@media (max-width: 920px) { .dash-grid { grid-template-columns: 1fr; gap: 26px; } }

/* Section header, shared by both zones: a real heading plus optional meta/link. */
.dash-sec-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.dash-sec-hd h2 { margin: 0; font-size: 15px; font-weight: 700; color: var(--prune); letter-spacing: 0.01em; }
.dash-sec-meta { font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.dash-sec-link { font-size: 13px; color: var(--forest); text-decoration: none; }
.dash-sec-link:hover { text-decoration: underline; }

/* --- Worklist: a list with hairline rules, not a grid of cards. --- */
.dash-todo { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.dash-item { border-bottom: 1px solid var(--line); }
.dash-link {
  display: grid; grid-template-columns: 60px minmax(0, 1fr) auto; align-items: center;
  gap: 20px; padding: 16px 12px; text-decoration: none; color: inherit;
  border-radius: 9px; transition: background 0.16s ease-out;
}
.dash-link:hover { background: var(--surface); }
.dash-link:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: 2px; }
.di-n {
  font-size: 30px; font-weight: 700; line-height: 1; text-align: right;
  font-variant-numeric: tabular-nums; color: var(--vert-clair);
}
.dash-item.is-clear .di-n { color: color-mix(in srgb, var(--prune) 40%, transparent); font-weight: 600; }
.di-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.di-name { font-size: 15.5px; font-weight: 600; color: var(--prune); }
.dash-item.is-clear .di-name { color: var(--ink-2); font-weight: 500; }
.di-todo { font-size: 13px; color: var(--ink-2); }
/* Cleared-row subline stays readable (>=4.5:1): the row recedes through its
   muted number and lighter name, not through faint body text. */
.dash-item.is-clear .di-todo { color: var(--ink-2); }
.di-go {
  font-size: 13px; font-weight: 600; color: var(--forest); white-space: nowrap;
  opacity: 0; transform: translateX(-5px);
  transition: opacity 0.16s ease-out, transform 0.16s ease-out;
}
.dash-link:hover .di-go, .dash-link:focus-visible .di-go { opacity: 1; transform: none; }

/* All-clear state: teach, not "nothing here". */
.dash-allclear { padding: 24px 12px 20px; }
.dac-mark { margin: 0; font-size: 19px; font-weight: 700; color: var(--vert-clair); }
.dac-sub { margin: 5px 0 0; font-size: 13.5px; color: var(--ink-2); }

/* --- Follow-up panel: one calm surface, blocks split by a hairline (no nested
   cards). --- */
.dash-side { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 18px 20px; }
.dash-block { padding: 2px 0; }
.dash-rule { height: 1px; background: var(--line); margin: 16px 0; }

/* Panel stats are display-only: the single link per section lives in its header,
   so a number never poses the "is this clickable?" question. */
.dash-stat { display: block; }
.ds-n { display: block; font-size: 26px; font-weight: 700; color: var(--prune); line-height: 1.1; font-variant-numeric: tabular-nums; }
.ds-sub { font-size: 14px; font-weight: 600; color: var(--ink-2); }
.ds-lab { display: block; margin-top: 3px; font-size: 12.5px; color: var(--ink-2); }
.dash-port { display: flex; flex-direction: column; gap: 15px; }

/* --- Compact reminders cue (in the Suivi panel): the navigable calendar lives
   on /recontact; here it is one live line, overdue in the error tone. --- */
.dash-cue { margin: 2px 0 0; font-size: 14px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.cue-late { font-weight: 700; color: var(--error); }
.cue-soon { font-weight: 600; color: var(--prune); }
.cue-sep, .cue-none { color: var(--ink-2); }

/* ---------- Momentum band (chantier 7): movement over time. Left, a 14-day
   send/reply rhythm chart (data viz, not decoration); right, today's goal gauge
   with a streak, then this-week results with deltas vs last week. Colour is
   semantic: Forest for progress and gains, Vert clair for replies, the error
   tone for a down delta. Bars and the gauge rise on load; the global
   reduced-motion rule degrades them to their static end state. ---------- */
.dash-momentum { margin-top: 30px; }
.mom-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; background: var(--surface); border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
@media (max-width: 920px) { .mom-grid { grid-template-columns: 1fr; } }

.mom-chart { padding: 16px 20px 15px; min-width: 0; }
.mom-chart-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.mom-chart-title { font-size: 12.5px; color: var(--ink-2); }
.mom-legend { display: flex; gap: 14px; font-size: 11.5px; color: var(--ink-2); }
.mom-legend span { display: inline-flex; align-items: center; }
.mom-legend .ml-send::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: color-mix(in srgb, var(--prune) 32%, var(--beige)); margin-right: 6px; }
.mom-legend .ml-reply::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--vert-clair); margin-right: 6px; }
.mom-legend .ml-target::before { content: ""; width: 13px; height: 0; border-top: 1px dashed color-mix(in srgb, var(--forest) 60%, transparent); margin-right: 6px; }
.mom-bars { position: relative; display: flex; align-items: flex-end; gap: 6px; height: 80px; }
/* Goal line: the daily target across the 14 days. Bars scale to max(peak, target)
   so a day that beats quota rises above it. Sits over the bars, understated. */
.mom-target { position: absolute; left: 0; right: 0; height: 0; z-index: 2; pointer-events: none; border-top: 1px dashed color-mix(in srgb, var(--forest) 55%, transparent); }
.mom-col { flex: 1; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; position: relative; }
.mom-bar { width: 100%; max-width: 15px; border-radius: 3px 3px 0 0; background: color-mix(in srgb, var(--prune) 30%, var(--beige)); transform-origin: bottom; animation: momRise 0.5s cubic-bezier(0.22, 1, 0.36, 1) backwards; }
.mom-col.is-weekend .mom-bar { background: color-mix(in srgb, var(--prune) 15%, var(--beige)); }
.mom-col.is-today .mom-bar { background: var(--forest); }
.mom-dot { position: absolute; top: -12px; width: 7px; height: 7px; border-radius: 50%; background: var(--vert-clair); }
.mom-axis { display: flex; justify-content: space-between; margin-top: 9px; font-size: 11px; color: var(--ink-2); }
.mom-empty { margin: 8px 0 6px; font-size: 13px; color: var(--ink-2); }
@keyframes momRise { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.mom-side { border-left: 1px solid var(--line); padding: 16px 20px; display: flex; flex-direction: column; }
@media (max-width: 920px) { .mom-side { border-left: none; border-top: 1px solid var(--line); } }
.mg-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.mg-lab { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-2); }
.mg-streak { font-size: 11.5px; font-weight: 700; color: var(--vert-clair); white-space: nowrap; }
.mg-bar { height: 8px; border-radius: 999px; background: color-mix(in srgb, var(--prune) 12%, var(--beige)); overflow: hidden; }
.mg-fill { display: block; height: 100%; border-radius: 999px; background: var(--forest); transform-origin: left; animation: mgFill 0.6s cubic-bezier(0.22, 1, 0.36, 1) backwards; }
.mg-nums { margin-top: 8px; font-size: 13px; color: var(--ink-2); }
.mg-cur { font-weight: 700; font-size: 17px; color: var(--prune); font-variant-numeric: tabular-nums; }
@keyframes mgFill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.mom-rule { height: 1px; background: var(--line); margin: 16px 0; }
.mom-score { display: flex; flex-direction: column; }
.ms-row { display: grid; grid-template-columns: 1fr auto auto; align-items: baseline; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.ms-row:first-child { padding-top: 0; }
.ms-lab { font-size: 13.5px; color: var(--prune); }
.ms-n { font-size: 20px; font-weight: 700; color: var(--prune); font-variant-numeric: tabular-nums; }
.ms-delta { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; min-width: 28px; text-align: right; }
.ms-delta.up { color: var(--forest); }
.ms-delta.down { color: var(--error); }
.ms-delta.flat { color: var(--ink-2); }
.ms-foot { margin-top: 10px; font-size: 11.5px; color: var(--ink-2); }

/* ============================================================
   À recontacter — navigable month calendar (chantier 7 follow-up)
   Two view modes of one hub: a Calendrier that plans (left grid + day panel)
   and a Liste for bulk triage (existing rowcards). Today is a Forest disc, the
   selected day a Vert clair ring, a day holding an overdue reminder the error
   tone. No icons; markers are dots. Reminders are CREATED on the lead sheet.
   ============================================================ */
.rc-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
.rc-head .label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--vert-clair); font-weight: 700; }
.rc-head h1 { margin: 4px 0 0; font-size: 24px; }
/* Mode toggle: two links in a pill, one active. */
.rc-modes { display: inline-flex; gap: 2px; padding: 3px; background: var(--surface); border: 1px solid var(--line); border-radius: 999px; }
.rc-mode { font-size: 13px; font-weight: 600; padding: 6px 16px; border-radius: 999px; color: var(--ink-2); text-decoration: none;
  background: transparent; border: 0; cursor: pointer; font-family: inherit; -webkit-appearance: none; appearance: none; }
.rc-mode:hover { color: var(--prune); }
.rc-mode.is-active { background: var(--prune); color: var(--beige); }
.rc-mode:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: 2px; }

/* ---- Calendar header: month nav + legend ---- */
.cal-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 18px; flex-wrap: wrap; }
.cal-nav { display: flex; align-items: center; gap: 10px; }
.cal-title { font-size: 19px; font-weight: 700; color: var(--prune); min-width: 150px; }
.cal-arrow { width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--prune-15); background: var(--beige); color: var(--prune); font-size: 16px; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
.cal-arrow:hover { background: var(--surface); }
.cal-today-btn { font-size: 13px; padding: 7px 14px; border-radius: 8px; border: 1px solid var(--prune-20); background: transparent; color: var(--prune); text-decoration: none; }
.cal-today-btn:hover { background: var(--surface); }
.cal-legend { display: flex; gap: 14px; font-size: 12px; color: var(--ink-2); }
.cal-legend span { display: inline-flex; align-items: center; }
.cal-legend .cl-rem::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: color-mix(in srgb, var(--prune) 55%, var(--beige)); margin-right: 6px; }
.cal-legend .cl-late::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--error); margin-right: 6px; }

/* ---- Two zones: month grid + day panel ---- */
.cal-grid-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 24px; align-items: start; }
@media (max-width: 920px) { .cal-grid-wrap { grid-template-columns: 1fr; } }

.cal { border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.cal-dow { display: grid; grid-template-columns: repeat(7, 1fr); background: var(--surface); border-bottom: 1px solid var(--line); }
.cal-dow span { padding: 10px 11px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-2); }
.cal-weeks { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--line); }
.cal-cell { min-height: 92px; padding: 9px 10px; display: flex; flex-direction: column; gap: 6px; background: var(--beige); text-decoration: none; color: inherit; transition: background 0.12s; }
a.cal-cell:hover { background: var(--surface); }
.cal-cell.is-out { background: color-mix(in srgb, var(--beige) 55%, var(--surface)); }
.cal-cell.is-out .cal-date { color: color-mix(in srgb, var(--prune) 28%, transparent); }
.cal-date { font-size: 13px; font-weight: 600; color: var(--prune); font-variant-numeric: tabular-nums; align-self: flex-start; }
.cal-cell.is-today .cal-date { background: var(--forest); color: var(--beige); min-width: 24px; height: 24px; padding: 0 6px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; }
.cal-cell.is-overdue { background: rgba(122, 46, 46, 0.055); }
a.cal-cell.is-overdue:hover { background: rgba(122, 46, 46, 0.09); }
.cal-cell.is-selected { box-shadow: inset 0 0 0 2px var(--vert-clair); }
.cal-dots { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; margin-top: auto; }
.cal-dot { width: 6px; height: 6px; border-radius: 50%; background: color-mix(in srgb, var(--prune) 55%, var(--beige)); }
.cal-cell.is-overdue .cal-dot { background: var(--error); }
.cal-more { font-size: 11px; font-weight: 600; color: var(--ink-2); }
.cal-cell:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }

/* ---- Day panel: overdue (always) then the selected day, with actions ---- */
.cal-panel { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 18px 20px; }
.cp-sec { margin-bottom: 4px; }
.cp-sec + .cp-dayblock, .cp-sec + .cp-sec { margin-top: 18px; }
.cp-sec-title { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; color: var(--ink-2); margin: 0 0 6px; }
.cp-sec.is-late .cp-sec-title { color: var(--error); }
.cp-dayblock:not([hidden]) ~ .cp-sec, .cp-sec ~ .cp-dayblock:not(:first-child) { margin-top: 18px; }
.cp-day { font-size: 16px; font-weight: 700; color: var(--prune); margin: 0; }
.cp-sub { font-size: 12.5px; color: var(--ink-2); margin: 3px 0 0; }
.cp-empty { font-size: 13px; color: var(--ink-2); margin: 8px 0 2px; }
.ct-item { padding: 12px 0; border-top: 1px solid var(--line); }
.ct-item:first-of-type { border-top: none; }
.ct-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.ct-lead { font-size: 14.5px; font-weight: 600; color: var(--forest); text-decoration: none; }
.ct-lead:hover { text-decoration: underline; }
.ct-time { font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ct-item.is-late .ct-time { color: var(--error); }
.ct-meta { display: flex; align-items: center; gap: 8px; margin-top: 5px; }
.ct-kind { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; padding: 2px 8px; border-radius: 999px; background: color-mix(in srgb, var(--prune) 10%, var(--beige)); color: var(--prune); }
.ct-co { font-size: 12.5px; color: var(--ink-2); }
.ct-note { margin-top: 6px; font-size: 13px; color: var(--prune); }
.ct-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; align-items: flex-start; }
.ct-actions form { margin: 0; }
/* text-decoration:none so an <a class="ct-btn"> is not underlined by the default
   link style (same reason .btn-save carries it): the class must look identical on
   a <button>, an <a> or a <summary>. */
.ct-btn { font-size: 12.5px; padding: 6px 12px; border-radius: 7px; cursor: pointer; border: 1px solid var(--prune-20); background: transparent; color: var(--prune); font: inherit; line-height: 1.2; text-decoration: none; }
.ct-btn { transition: background 0.12s, border-color 0.12s, color 0.12s; }
.ct-btn:hover { background: color-mix(in srgb, var(--prune) 9%, var(--beige)); border-color: color-mix(in srgb, var(--prune) 42%, transparent); }
.ct-btn.done { background: var(--forest); color: var(--beige); border-color: var(--forest); }
.ct-btn.done:hover { background: color-mix(in srgb, var(--forest) 84%, var(--beige)); border-color: color-mix(in srgb, var(--forest) 84%, var(--beige)); }
.ct-btn.danger:hover { background: rgba(122, 46, 46, 0.1); border-color: var(--error); color: var(--error); }
.ct-btn:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: 1px; }
.ct-resched { position: relative; }
.ct-resched > summary { list-style: none; display: inline-block; }
.ct-resched > summary::-webkit-details-marker { display: none; }
.ct-resched-form { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.ct-resched-form input { margin: 0; padding: 6px 8px; font-size: 12.5px; background: var(--beige); color: var(--prune); border: 1px solid var(--prune-20); border-radius: 7px; }

/* ---- Liste (bulk triage): a dense, scannable task list (Linear / Superhuman
   register) in the Aetherma DA. Single-line rows so 50 stay light; sticky group
   headers keep the rep oriented while scrolling; actions stay out of the way
   until the row is hovered, each with a clear hover (Supprimer reads
   destructive). In the "Aujourd'hui" group the row shows only the time, since
   the day is already the header. ---- */
.rc-summary { font-size: 13px; color: var(--ink-2); margin: 2px 0 14px; }
.rc-sum-sep { color: color-mix(in srgb, var(--prune) 35%, transparent); margin: 0 3px; }
.rc-group {
  position: sticky; top: 0; z-index: 1; background: var(--beige);
  display: flex; align-items: center; gap: 10px; padding: 12px 10px 7px;
  box-shadow: 0 1px 0 var(--line);
}
.rc-group form { margin-left: auto; } /* a trailing action (e.g. Vider) in a group header */
.rc-group-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; color: var(--ink-2); }
.rc-group-late .rc-group-label { color: var(--error); }
.rc-group-count { font-size: 11px; font-weight: 700; line-height: 1; padding: 3px 8px; border-radius: 999px; background: var(--prune-15); color: var(--prune); }
.rc-group-late .rc-group-count { background: rgba(122, 46, 46, 0.12); color: var(--error); }
/* Fixed columns so every field lines up as a clean vertical column across rows
   (date | lead | nature | société | note); the note flexes and truncates. */
.rc-row {
  position: relative;
  display: grid; grid-template-columns: 100px 176px 60px 152px minmax(0, 1fr); gap: 14px; align-items: baseline;
  padding: 8px 10px; border-bottom: 1px solid var(--line);
}
.rc-row:last-child { border-bottom: none; }
.rc-row:hover { background: var(--surface); }
.rc-row.is-late { background: rgba(122, 46, 46, 0.03); }
.rc-row.is-late:hover { background: rgba(122, 46, 46, 0.06); }
.rc-when { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; overflow: hidden; }
.rc-when-main { font-size: 13px; font-weight: 600; color: var(--prune); font-variant-numeric: tabular-nums; }
.rc-row.is-late .rc-when-main { color: var(--error); font-weight: 700; }
.rc-when-time { font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.rc-lead { font-size: 14px; font-weight: 600; color: var(--forest); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-lead:hover { text-decoration: underline; }
.rc-kind { min-width: 0; }
.rc-co { font-size: 12.5px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-note { font-size: 12.5px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.rc-actions {
  position: absolute; right: 8px; top: 0; bottom: 0; display: flex; align-items: center; gap: 6px;
  opacity: 0; pointer-events: none; padding-left: 30px;
  background: linear-gradient(to right, transparent, var(--surface) 26px);
  transition: opacity 0.12s ease-out;
}
.rc-row:hover .rc-actions, .rc-row:focus-within .rc-actions { opacity: 1; pointer-events: auto; }
/* Reschedule floats as a small panel so it never grows a dense row. */
.rc-row .ct-resched { position: relative; }
.rc-row .ct-resched[open] .ct-resched-form {
  position: absolute; top: 100%; right: 0; margin-top: 5px; z-index: 5;
  background: var(--beige); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px; box-shadow: 0 8px 24px rgba(53, 50, 66, 0.14);
}
.rc-empty { padding: 34px 8px; }
.rc-empty-mark { margin: 0; font-size: 18px; font-weight: 700; color: var(--vert-clair); }
.rc-empty-sub { margin: 5px 0 0; font-size: 13.5px; color: var(--ink-2); }
@media (max-width: 720px) {
  .rc-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 10px; padding: 10px; }
  .rc-note { flex-basis: 100%; }
  .rc-actions { position: static; opacity: 1; pointer-events: auto; background: none; padding-left: 0; justify-content: flex-start; flex-basis: 100%; margin-top: 6px; }
  .rc-row .ct-resched[open] .ct-resched-form { position: static; box-shadow: none; margin-top: 6px; }
}

/* ============================================================
   Admin config register (chantier 13) — the settings zone in the cockpit's own
   language, reusing the dashboard vocabulary the DA already established: the
   .dash-grid two-zone layout, .dash-side surface panels, .ds-n / .ds-lab stat
   tiles, .dash-rule hairlines, .dash-sec-hd headers. Settings sit at rest as a
   status board; "Modifier" flips a panel into edit in place (initInlineEdit:
   [data-field] + [data-save-bar], zero extra JS). Forest for the save CTA,
   Vert clair for the one signature figure (the daily cap). Shared by Cadence,
   and next Scoring, Utilisateurs, Config IA.
   ============================================================ */
.cad-page { max-width: var(--work-max); }
.cad-lead { font-size: 15.5px; color: var(--ink-2); line-height: 1.55; margin: 2px 0 28px; max-width: 66ch; }
.cad-stack { display: flex; flex-direction: column; gap: 26px; }

/* Surface panel for a settings zone (same material as .dash-side). Editorial
   air: generous padding, the calm surface reads as a precision instrument. */
.cfg-panel { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 20px 24px; }

/* Header right cluster (meta + Modifier), sitting inside a .dash-sec-hd. */
.cad-hd-right { display: inline-flex; align-items: baseline; gap: 16px; }
.cfg-modif { background: none; border: 0; cursor: pointer; padding: 0; font: inherit; font-size: 13px; color: var(--forest); text-decoration: none; }
.cfg-modif:hover { text-decoration: underline; }
.cfg-modif:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: 2px; }

/* Read-first per panel: the whole panel is one [data-field]; Modifier flips it
   from the status board to the controls, in place. */
.cfg-edit-panel [data-edit] { display: none; }
.cfg-edit-panel.is-editing [data-read] { display: none; }
.cfg-edit-panel.is-editing [data-edit] { display: block; }
.cfg-edit-panel.is-editing .cfg-modif { visibility: hidden; }

/* Cadence tiles: the DA's numbered sequence, large numerals, figure and label
   tightly linked. Four across, ordered mail 1 then three relances. */
.cad-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-top: 16px; }
.cad-cell { display: flex; flex-direction: column; gap: 10px; }
.cad-cell-lab { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-2); }
/* Confident, instrument-like figures: bold, tight tracking (DA display floor
   -0.04em), tabular so the sequence reads as one aligned ramp. */
.cad-cell-fig { font-size: 34px; font-weight: 700; color: var(--prune); font-variant-numeric: tabular-nums; letter-spacing: -0.015em; line-height: 1; }
.cad-cell-edit { display: inline-flex; align-items: baseline; gap: 4px; }
.cad-plus { font-size: 18px; font-weight: 700; color: var(--ink-2); }
.cad-in { width: 66px; margin: 0; padding: 8px 6px; text-align: center; font-size: 16px; font-variant-numeric: tabular-nums; }

/* Fenêtre fields: a labelled block, read (pills / value) then edit (chips / input). */
.cad-read-fld + .cad-read-fld { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line); }
.cad-edit-fld + .cad-edit-fld { margin-top: 20px; }
.cad-fld-lab { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); margin-bottom: 10px; }
.cad-fld-val { font-size: 16px; color: var(--ink); font-variant-numeric: tabular-nums; }

/* Status pills (read) + toggle chips (edit) for the weekday / hour set. Pill off
   = muted ghost, on = Prune; the chip carries an invisible checkbox so the set
   submits with no JS. */
.cfg-pills, .cfg-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.cfg-pill { display: inline-flex; align-items: center; justify-content: center; min-width: 46px; padding: 8px 13px; border-radius: 999px; border: 1px solid var(--prune-20); background: var(--beige); font-size: 13px; font-weight: 600; color: color-mix(in srgb, var(--prune) 40%, var(--beige)); font-variant-numeric: tabular-nums; }
.cfg-pill.is-on { background: var(--prune); border-color: var(--prune); color: var(--beige); }
.cfg-chip { position: relative; display: inline-flex; }
.cfg-chip input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.cfg-chip-face { display: inline-flex; align-items: center; justify-content: center; min-width: 46px; padding: 8px 13px; border-radius: 999px; border: 1px solid var(--prune-20); background: var(--beige); font-size: 13px; font-weight: 600; color: var(--ink-2); font-variant-numeric: tabular-nums; transition: background 0.12s, border-color 0.12s, color 0.12s; }
.cfg-chip input:hover + .cfg-chip-face { border-color: color-mix(in srgb, var(--prune) 42%, transparent); color: var(--prune); }
.cfg-chip input:checked + .cfg-chip-face { background: var(--prune); border-color: var(--prune); color: var(--beige); }
.cfg-chip input:focus-visible + .cfg-chip-face { outline: 2px solid var(--vert-clair); outline-offset: 2px; }

/* Number edit control (durée, plafond, batch, marge). */
.cfg-help { font-size: 12.5px; color: var(--ink-2); margin: 0 0 11px; }
.cfg-inline-ctl { display: inline-flex; align-items: center; gap: 9px; }
.cfg-num { width: 84px; text-align: right; font-variant-numeric: tabular-nums; }
/* The base input rule sets margin 6px 0 16px; .cfg-num alone loses that on
   specificity (input[type=number] beats a plain class), so the reset that keeps
   the field centred in its row lives on input.cfg-num. */
input.cfg-num { margin: 0; }
.cfg-unit { font-size: 13px; color: var(--ink-2); }

/* The one signature figure: the daily cap, the precious number, in Vert clair
   (parcimonie) and a step larger than the batch/margin stats beneath it, so the
   throughput ceiling reads first. */
.ds-n.cfg-fig { color: var(--vert-clair); font-size: 32px; letter-spacing: -0.01em; }

/* Motion as state, not decoration (product register): flipping a panel into
   edit gives its controls a gentle rise, no page-load choreography. */
.cfg-edit-panel.is-editing [data-edit] { animation: cfgFlip 0.24s cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes cfgFlip { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .cfg-edit-panel.is-editing [data-edit] { animation: none; }
}

/* Contextual save bar: in-flow at the form's end, revealed only while a panel is
   editing (initInlineEdit adds .is-visible). Not pinned, not a permanent CTA. */
.cfg-save-bar { display: none; align-items: center; gap: 16px; margin: 2px 0 0; padding: 18px 2px 0; border-top: 1px solid var(--line); }
.cfg-save-bar.is-visible { display: flex; }
.cfg-sb-msg { font-size: 13px; color: var(--ink); font-weight: 600; display: inline-flex; align-items: center; gap: 8px; }
.cfg-sb-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--vert-clair); }
.cfg-sb-sp { flex: 1; }
.cfg-save-bar .ct-btn { font-size: 13px; }

@media (max-width: 640px) {
  .cad-row { grid-template-columns: repeat(2, 1fr); gap: 14px; }
}

/* ============================================================
   Config IA (chantier 13) — the four-tab admin editor in the premium register.
   Forest .card stacks and Vert clair banners give way to --surface panels and
   --line rules, a refined model picker, calm notes; the Vert clair tag marks the
   model's stance preciously. The bounded shell, tabs, slide-in savebar and banc
   d'essai inspector are unchanged. Editing here is direct (a prompt editor, not
   a status board), so the draft form keeps its savebar.
   ============================================================ */
.aiq-lead { font-size: 14.5px; color: var(--ink-2); line-height: 1.55; margin: 0 0 24px; max-width: 78ch; }
.aiq-lead strong { color: var(--ink); font-weight: 700; }
.aiq-note { font-size: 13px; color: var(--ink-2); line-height: 1.55; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 13px 16px; margin: 22px 0; }
.aiq-note strong { color: var(--ink); font-weight: 700; }

.aiq-sec-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 28px 0 12px; flex-wrap: wrap; }
.aiq-sec-hd h2 { font-size: 15px; font-weight: 700; color: var(--ink); margin: 0; letter-spacing: 0.01em; }
.aiq-sec-hint { font-size: 12.5px; color: var(--ink-2); max-width: 62ch; }

/* Model picker: two selectable cards in the light register; the checked one
   carries the Forest ring, its stance tag stays Vert clair (precious). */
.aiq-models { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 14px; }
@media (max-width: 760px) { .aiq-models { grid-template-columns: 1fr; } }
.aiq-model { position: relative; display: block; border: 1px solid var(--line); border-radius: 12px; padding: 15px 16px 15px 44px; background: var(--beige); cursor: pointer; transition: border-color 0.12s, box-shadow 0.12s; }
.aiq-model input { position: absolute; left: 16px; top: 17px; width: 16px; height: 16px; margin: 0; accent-color: var(--forest); }
.aiq-model:hover { border-color: color-mix(in srgb, var(--prune) 40%, transparent); }
.aiq-model:has(input:checked) { border-color: var(--forest); box-shadow: inset 0 0 0 1px var(--forest); }
.aiq-model:focus-within { outline: 2px solid var(--vert-clair); outline-offset: 2px; }
.aiq-model-title { font-size: 15px; font-weight: 700; color: var(--ink); }
.aiq-model-tag { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--vert-clair); margin-left: 9px; }
.aiq-model-note { display: block; font-size: 13px; color: var(--ink-2); margin-top: 5px; }
.aiq-model-id { display: block; font-family: var(--mono); font-size: 11px; color: color-mix(in srgb, var(--prune) 48%, var(--beige)); margin-top: 9px; }

/* Research model picker: the validated rc-modes pill in a panel (twin of the
   Rédaction strip), with a plain guidance line beneath instead of bespoke cards. */
.aiq-modelrow { margin: 6px 0 0; }
.aiq-model-help { margin-top: 12px; }
.aiq-model-help strong { color: var(--ink); font-weight: 700; }

/* Param fields (max_tokens, temperature, freshness). */
.aiq-params { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line); }
@media (max-width: 620px) { .aiq-params { grid-template-columns: 1fr; } }
.aiq-param label { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); margin-bottom: 9px; }
.aiq-param input { width: 150px; margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.aiq-help { font-size: 12.5px; color: var(--ink-2); margin: 9px 0 0; max-width: 52ch; }

/* Prompt section: a titled block with a mono editor. */
.aiq-prompt { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; margin-bottom: 12px; background: var(--beige); }
.aiq-prompt-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 12px 15px; border-bottom: 1px solid var(--line); background: var(--surface); }
.aiq-prompt-titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.aiq-prompt-title { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.aiq-prompt-hint { font-size: 12px; color: var(--ink-2); }
.aiq-prompt textarea { width: 100%; border: 0; background: var(--beige); font-family: var(--mono); font-size: 13px; line-height: 1.6; color: var(--prune); padding: 13px 15px; resize: vertical; box-sizing: border-box; margin: 0; min-height: 0; }
.aiq-prompt textarea:focus { outline: 2px solid var(--vert-clair); outline-offset: -2px; }
.aiq-guaranteed { font-size: 11px; font-weight: 700; padding: 2px 10px; border-radius: 999px; background: color-mix(in srgb, var(--vert-clair) 22%, var(--beige)); color: var(--vert-fonce); white-space: nowrap; flex: none; }

/* A form wrapped in a light panel (a sequence step, a template). */
.aiq-form { margin-bottom: 14px; }
/* Fields cap at a readable width inside the full-width page, rather than the page
   narrowing (Salesforce/HubSpot record pages, form-usability research). An input
   never stretches past --form-max; the page keeps the single --work-max width. */
.aiq-field { margin-bottom: 15px; max-width: var(--form-max); }
.aiq-field:last-of-type { margin-bottom: 18px; }
.aiq-field label { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-2); margin-bottom: 7px; }
.aiq-field input, .aiq-field textarea { margin: 0; }
.aiq-field textarea { font-family: var(--mono); font-size: 13px; line-height: 1.6; }
/* Vert clair focus ring, same as .pup-prose-ta (Rédaction/Recherche): without it
   the aiq-field inputs fall back to the browser's blue default ring. */
.aiq-field input:focus-visible, .aiq-field textarea:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }

/* Invariants: a read-only reference sheet. */
.aiq-ref-lab { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); margin-bottom: 10px; }
.aiq-ref-lab + .aiq-tokens { margin-bottom: 18px; }
.aiq-tokens { display: flex; flex-wrap: wrap; gap: 7px; }
.aiq-tok { font-family: var(--mono); font-size: 12px; padding: 4px 10px; border-radius: 7px; background: color-mix(in srgb, var(--prune) 9%, var(--beige)); color: var(--prune); border: 1px solid var(--line); }
.aiq-tok.is-forbidden { background: rgba(122, 46, 46, 0.08); color: var(--error); border-color: color-mix(in srgb, var(--error) 30%, transparent); }
.aiq-map { display: grid; gap: 9px; }
.aiq-map-row { display: flex; align-items: center; gap: 10px; font-size: 13.5px; flex-wrap: wrap; }
.aiq-arrow { color: var(--ink-2); }

/* The banc d'essai inspector: the inner card becomes a light panel (was Forest). */
.inspector .card { background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 12px; }
.inspector .card label { color: var(--ink-2); }
.inspector .card .meta, .inspector .card .aiq-help { color: var(--ink-2); }

/* Config IA save affordances: the slide-in savebar and the disabled preview
   button, both on the shared .ct-btn now. */
.savebar .ct-btn { margin: 0; padding: 9px 18px; font-size: 14px; }
.ct-btn:disabled { opacity: 0.5; cursor: default; }
.ct-btn:disabled:hover { background: transparent; border-color: var(--prune-20); color: var(--prune); }

/* ============================================================
   Config IA — Rédaction cockpit (chantier 13). A master-detail tool: a compact
   model strip, a section navigator (left), a focused editor (center), and the
   inspector as a live result panel (Système = the prompt assembled client-side,
   updating on each keystroke; Réel = the existing n8n preview for a chosen lead).
   The draft tab fills the work column with no page scroll; the panels scroll
   internally. Reuses the tool's own codes: .rc-modes pill, .cfg-num, .ct-btn,
   .preview-block. Wired by initAiCockpit in app.js.
   ============================================================ */
/* Centered tabs: the context banner already names the screen, so the header is
   just the tab row, centred on the work column. */
.work > .work-head.aiq-head { display: flex; justify-content: center; align-items: center; padding: 10px clamp(22px,3.5vw,52px) 0; }
.work > .work-head.aiq-head .tabs { margin: 0; }
.work-scroll.aiq-scroll { overflow: hidden; }
.ai-pad.aiq-pad { padding: 0; max-width: var(--work-max); margin-inline: auto; height: 100%; display: flex; flex-direction: column; min-height: 0; }
.aiq-pad > .flash { flex: none; margin: 12px var(--work-gut) 0; }

/* Bounded-queue building blocks, factored out of per-view inline styles that all
   repeated the same side gutter. One gutter token (--work-gut) feeds the lede
   under the toolbar and the empty state; the scrolling list body reuses the
   shared .list-scroll. */
.aiq-lede { flex: none; margin: 8px var(--work-gut) 0; max-width: 82ch; font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }
.aiq-pad > .empty { margin: 16px var(--work-gut); }
.aiq-pad > .dash-rule { margin: 12px var(--work-gut) 2px; } /* separator inset to the work gutter */
.aiq-pad > .aiq-note { margin: 16px var(--work-gut) 0; } /* a full-width note inset to the work gutter */
.hl { color: var(--vert-clair); } /* a value shown in the accent (import value, "sans numéro") */
.dim { color: var(--ink-2); } /* a value that recedes (secondary status marker) */
.link-count { font-size: 13px; text-decoration: underline; color: var(--prune); } /* small inline count link */

/* Bulk-action bar of a tabular .rowcard list (Leads, Rejets, and the other
   queues): a toolbar pinned above the list, laid out on the work gutter. Shown
   only under body.selecting (shared #bulkActions mechanism). Replaces the margin
   and inner-flex that each list inlined. */
.aiq-bulkbar { margin: 8px var(--work-gut) 0; flex: none; }
.aiq-bulkbar label { display: inline-flex; gap: 8px; align-items: center; margin: 0; font-size: 14px; }
.aiq-bulkbar label input { width: auto; }
/* Some bulk bars wrap their controls in a full-width flex row; the wrapper is
   this class instead of an inline style. */
.aiq-bulkbar-inner { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; width: 100%; }

/* Import screen (actions.ejs): a capped form column, plus the two report rows
   (conflicts / rejects pending). Free page, no list; these classes replace the
   card style that was repeated inline on both rows. The figure reuses .ds-n. */
.aiq-form { max-width: var(--form-max); width: 100%; padding: 18px var(--work-gut) 30px; display: flex; flex-direction: column; gap: 28px; }
.aiq-form .aiq-ref-lab + .aiq-note { margin: 8px 0 0; }
.aiq-form form { margin-top: 16px; }
.aiq-form .aiq-lede { margin: 6px 0 12px; }
.aiq-field input[type=file] { background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; margin: 0; width: 100%; box-sizing: border-box; }
.aiq-report { display: flex; flex-direction: column; gap: 10px; }
.aiq-report-row { display: flex; align-items: center; gap: 16px; border: 1px solid var(--line); border-radius: 12px; padding: 14px 18px; background: var(--surface); }
.aiq-report-row .spacer { flex: 1; }
.aiq-report-row .ds-n { color: var(--vert-fonce); margin-top: 2px; }

.aiq-form-cockpit { flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* Model + params strip, dense, always visible. */
.aiq-strip { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; padding: 12px clamp(18px,3vw,28px); border-bottom: 1px solid var(--line); background: var(--surface); flex: none; }
.aiq-strip-group { display: inline-flex; align-items: center; gap: 11px; }
.aiq-strip-lab { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-2); }
/* The value shown under an .aiq-strip-lab (sequence header key/value pairs on the
   campaign and openers sheets). Was repeated inline ~14 times; .num adds tabular
   figures for dates and scores. */
.aiq-strip-val { color: var(--ink); margin-top: 3px; }
.aiq-strip-val.num { font-variant-numeric: tabular-nums; }
/* Number fields in Config IA: wide + centered so the native spinner arrows
   keep clear of the digit (Cadence's roomy feel), and beat the base input
   width:100% (0,1,1) so they never stretch. */
.aiq-strip .cfg-num, .pup-ctl .cfg-num { width: 118px; text-align: center; }
.aiq-strip-sp { flex: 1; }
.aiq-strip-id { font-family: var(--mono); font-size: 11px; color: color-mix(in srgb, var(--prune) 48%, var(--beige)); }

/* Read-first params band (cadence pattern): calm figures at rest, "Modifier"
   flips to the validated model pill + cfg-inline-ctl controls. initInlineEdit
   toggles .is-editing on the [data-field] strip; the pinned savebar saves. */
.aiq-strip[data-field] [data-edit] { display: none; }
.aiq-strip[data-field].is-editing [data-read] { display: none; }
.aiq-strip[data-field].is-editing [data-edit] { display: flex; }
.aiq-strip-read, .aiq-strip-edit { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; width: 100%; }
.aiq-stat { display: inline-flex; flex-direction: column; gap: 3px; }
.aiq-stat-lab { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-2); }
.aiq-stat-val { font-size: 19px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; line-height: 1.15; }
.aiq-strip-edit .cfg-inline-ctl { gap: 8px; }
.aiq-strip .cfg-modif { font-size: 13px; }
/* Model choice on the .rc-modes pill: a radio hidden under each mode, :checked drives the fill. */
.rc-modes .aiq-model-pick { position: relative; cursor: pointer; }
.rc-modes .aiq-model-pick input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.rc-modes .aiq-model-pick:has(input:checked) { background: var(--prune); color: var(--beige); }
.rc-modes .aiq-model-pick:has(input:focus-visible) { outline: 2px solid var(--vert-clair); outline-offset: 2px; }

/* Master-detail: navigator + editor. */
.aiq-cockpit { flex: 1; min-height: 0; display: grid; grid-template-columns: 258px minmax(0, 1fr); }
/* Wider list variant for a working triage (Entrants, Conflits): the left column
   is a scan-and-act list, so it earns ~40% and the reader keeps a comfortable
   width. Shared by both screens instead of an inline grid-template on each. */
.aiq-cockpit.aiq-cockpit-wide { grid-template-columns: minmax(340px, 40%) minmax(0, 1fr); }
/* The left column stacks a scrolling list over a pinned pager, with the divider
   on the column so it spans the pager too; the nav inside drops its own border. */
.aiq-nav-col { display: flex; flex-direction: column; min-width: 0; min-height: 0; border-right: 1px solid var(--line); }
.aiq-nav-col > .aiq-nav { flex: 1; min-height: 0; border-right: 0; }
/* Bulk-arbitration chrome for a master-detail list (Entrants, Conflits): the
   "Sélectionner" affordance and the bar of batch actions. The reveal is the
   global body.selecting mechanism; these classes carry only the layout that was
   inlined per view. The row gives its nav button the remaining width beside the
   checkbox cell. */
.aiq-nav-selbar { display: flex; justify-content: flex-end; padding: 0 2px 8px; }
.aiq-bulk { padding: 2px 4px 10px; }
.aiq-bulk-all { display: flex; gap: 8px; align-items: center; margin: 0 0 8px; font-size: 12.5px; color: var(--ink-2); }
.aiq-bulk-all input { width: auto; margin: 0; }
.aiq-bulk-count { font-size: 12.5px; color: var(--ink-2); margin-bottom: 10px; }
.aiq-bulk-row { display: flex; gap: 8px; flex-wrap: wrap; }
.aiq-bulk-row .btn-save, .aiq-bulk-row .btn-ghost { padding: 8px 14px; font-size: 13px; }
.iq-row > .aiq-nav-item { flex: 1; min-width: 0; }
.aiq-nav { border-right: 1px solid var(--line); overflow-y: auto; padding: 12px 10px; display: flex; flex-direction: column; gap: 2px; }
.aiq-nav-hd { display: flex; align-items: baseline; justify-content: space-between; padding: 4px 12px 10px; }
.aiq-nav-hd-t { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-2); }
.aiq-nav-hd-n { font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.aiq-nav-item { text-align: left; border: 0; background: transparent; cursor: pointer; font: inherit; padding: 9px 12px; border-radius: 9px; display: flex; flex-direction: column; gap: 2px; transition: background 0.15s; position: relative; }
.aiq-nav-item:hover { background: var(--surface); }
.aiq-nav-item.is-active { background: color-mix(in srgb, var(--vert-clair) 15%, var(--beige)); }
.aiq-nav-item:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }
.aiq-nav-name { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.aiq-nav-item.is-active .aiq-nav-name { color: var(--vert-fonce); }
.aiq-nav-hint { font-size: 11.5px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.aiq-nav-dot { position: absolute; right: 12px; top: 13px; width: 6px; height: 6px; border-radius: 50%; background: var(--vert-clair); opacity: 0; transition: opacity 0.15s; }
.aiq-nav-item.is-active .aiq-nav-dot { opacity: 1; }
/* A facet that wants attention: a coloured, bolder hint and a visible dot, over
   the resting item. Two tones, informational (vert) and alert (error). Was repeated
   inline on the cockpit nav; the dot colour stays the default vert so the render
   is unchanged. */
.aiq-nav-item.is-flag  .aiq-nav-hint { color: var(--vert-clair); font-weight: 600; }
.aiq-nav-item.is-alert .aiq-nav-hint { color: var(--error); font-weight: 600; }
.aiq-nav-item.is-flag  .aiq-nav-dot,
.aiq-nav-item.is-alert .aiq-nav-dot  { opacity: 1; }
.aiq-editor { display: flex; flex-direction: column; min-height: 0; padding: 20px clamp(18px,3vw,30px) 22px; }
.aiq-editor-hd { flex: none; margin-bottom: 13px; display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.aiq-editor-hd h3 { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.aiq-editor-sub { font-size: 12.5px; color: var(--ink-2); }
.aiq-editor-body { flex: 1; min-height: 0; width: 100%; box-sizing: border-box; resize: none; margin: 0; border: 1px solid var(--line); border-radius: 10px; background: var(--beige); font-family: var(--mono); font-size: 13px; line-height: 1.6; color: var(--prune); padding: 12px 14px; }
.aiq-editor-body[hidden] { display: none; }
.aiq-editor-body:focus { outline: 2px solid var(--vert-clair); outline-offset: -2px; }

/* Inspector as a live result panel (Système / Réel). */
.aiq-insp-toggle { margin-top: 12px; }
.insp-body .aiq-live-hd { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-2); margin: 2px 0 10px; }
.aiq-live { border: 1px solid var(--line); border-radius: 12px; background: var(--beige); padding: 6px; }
.aiq-live-sec { padding: 9px 11px; border-radius: 8px; cursor: pointer; transition: background 0.15s; }
.aiq-live-sec.is-active { background: color-mix(in srgb, var(--vert-clair) 15%, var(--beige)); }
.aiq-live-sec:hover { background: var(--surface); }
.aiq-live-sec.is-active:hover { background: color-mix(in srgb, var(--vert-clair) 20%, var(--beige)); }
.aiq-live-lab { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); margin-bottom: 4px; }
.aiq-live-sec.is-active .aiq-live-lab { color: var(--vert-fonce); }
.aiq-live-txt { font-family: var(--mono); font-size: 11.5px; line-height: 1.55; color: color-mix(in srgb, var(--prune) 80%, var(--beige)); white-space: pre-wrap; }
.aiq-live-txt:empty::before { content: "(vide)"; color: color-mix(in srgb, var(--prune) 40%, var(--beige)); }
.aiq-live-fixed { margin-top: 8px; padding: 10px 11px; border: 1px dashed var(--line); border-radius: 8px; }
.aiq-live-fixed .aiq-live-lab { color: var(--vert-clair); }
.aiq-live-fixed .aiq-live-txt { color: var(--ink-2); }

/* Banc d'essai (inspector, mode Réel) retoned to the cockpit surface language:
   --surface / --line / --ink-2 in place of the old prune-15 borders and
   opacity-muted greys, and the chosen state as a quiet Vert clair TINT instead
   of a solid fill (DA: the accent marks, it never fills behind text). */
.inspector .aiq-ref-lab { color: var(--ink-2); }
.inspector .typeahead input[type=text] { border-color: var(--line); }
.inspector .typeahead input[type=text]:focus { outline: 2px solid var(--vert-clair); outline-offset: -2px; }
.inspector .typeahead-list { background: var(--beige); border: 1px solid var(--line); box-shadow: 0 10px 28px rgba(53, 50, 66, 0.14); }
.inspector .typeahead-item { color: var(--ink); }
.inspector .typeahead-item:hover { background: var(--surface); }
.inspector .ta-name { color: var(--ink); }
.inspector .ta-domain { color: var(--ink-2); opacity: 1; }
.inspector .typeahead-feedback { color: var(--ink-2); opacity: 1; }
.inspector .typeahead-feedback.feedback-empty { color: var(--error); }
.inspector .chosen-company {
  background: color-mix(in srgb, var(--vert-clair) 12%, var(--beige));
  border: 1px solid color-mix(in srgb, var(--vert-clair) 34%, transparent);
  color: var(--ink); border-radius: 10px;
}
.inspector .chosen-check { color: var(--vert-fonce); }
.inspector .chosen-clear { color: var(--ink-2); }
.inspector .chosen-clear:hover { color: var(--forest); }
.inspector .preview-meta { color: var(--ink-2); opacity: 1; }
.inspector .preview-meta b { color: var(--ink); }
.inspector .preview-block { background: var(--surface); border: 1px solid var(--line); }
.inspector .preview-block-label { color: var(--ink-2); opacity: 1; }
.inspector .preview-block-body { color: var(--ink); }
.inspector .preview-out { background: var(--surface); border: 1px solid var(--line); color: var(--ink); }
.inspector .preview-raw-toggle { color: var(--ink-2); }
.inspector .preview-raw-toggle:hover { color: var(--forest); }

/* Phone / narrow: the cockpit stops being fixed-height and scrolls normally. */
@media (max-width: 900px) {
  .work-scroll.aiq-scroll { overflow-y: auto; }
  .ai-pad.aiq-pad { height: auto; display: block; }
  .aiq-cockpit { display: block; }
  .aiq-nav { border-right: none; border-bottom: 1px solid var(--line); }
  .aiq-editor-body { min-height: 260px; }
}

/* ==========================================================================
   Draft style pupitre (onglet Rédaction). The paragraph/hooks rules become
   typed controls; the bandeau is always editable (no "Modifier" gate). Reuses
   .aiq-strip / .aiq-cockpit / .aiq-nav / .rc-modes; new controls are .pup-*.
   Values transcribed from the mock validated on screen (2026-07-24).
   ========================================================================== */

.pup-unit { font-family: var(--mono); font-size: 11.5px; color: color-mix(in srgb, var(--prune) 52%, var(--beige)); }

/* Stepper: shared by the bandeau and the pupitre. The value is a readonly
   number input so it submits with the form; the buttons clamp it. */
.pup-step { display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: 9px; overflow: hidden; background: var(--beige); }
.pup-step button { border: 0; background: transparent; cursor: pointer; font: inherit; font-size: 16px; color: var(--forest); width: 30px; height: 34px; line-height: 1; }
.pup-step button:hover { background: color-mix(in srgb, var(--forest) 10%, transparent); }
.pup-step button:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }
.pup-step-v { width: 56px; min-width: 0; text-align: center; font-variant-numeric: tabular-nums; font-size: 15px; font-weight: 700; color: var(--ink); background: transparent; border: 0; margin: 0; padding: 0; pointer-events: none; -moz-appearance: textfield; }
.pup-step-v::-webkit-outer-spin-button, .pup-step-v::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* The band holder (2nd cockpit cell): one band shown at a time. */
.pup-holder { min-height: 0; overflow-y: auto; }
.pup-band { padding: 16px clamp(18px, 3vw, 28px) 22px; }
.pup-band[hidden] { display: none; }
/* Conflicts reader: one arbitrated field per row (label, then Actuel -> Import
   with the incoming value in the accent), its two actions below via .iq-actions.
   Rows sit in the shared .pup-band; separated by a hairline. */
.cf-field { padding: 14px 2px; border-top: 1px solid var(--line); }
.cf-field:first-of-type { border-top: 0; }
.cf-vals { font-size: 14px; color: var(--ink); margin: 6px 0 10px; }
.cf-arrow { color: var(--ink-2); margin: 0 5px; }
.pup-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.pup-hd h3 { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.pup-hd .sub { font-size: 12px; color: var(--ink-2); }
.pup-note { font-size: 12.5px; color: var(--ink-2); line-height: 1.5; margin: 4px 0 6px; max-width: 72ch; }

/* Foldable sections (accordion), matching the rail's green language. */
.pup-fold { border-top: 1px solid var(--line); }
.pup-fold:first-of-type { border-top: 0; }
.pup-fold-hd { position: relative; display: flex; align-items: center; gap: 10px; width: 100%; background: none; border: 0; cursor: pointer; font: inherit; padding: 12px 24px 12px 2px; text-align: left; border-radius: 8px; }
.pup-fold-hd:hover { background: color-mix(in srgb, var(--forest) 6%, transparent); }
.pup-fold-hd:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }
/* Timeline entry heading (step label / reply marker) in the campaign fold. Was the
   same inline on each of the five entry types. */
.tl-hd { font-weight: 700; color: var(--ink); font-size: 15px; }
.pup-caret { flex: none; width: 0; height: 0; border-left: 5px solid var(--forest); border-top: 4px solid transparent; border-bottom: 4px solid transparent; transition: transform 0.15s; transform: rotate(90deg); }
.pup-fold.is-collapsed .pup-caret { transform: rotate(0deg); }
.pup-fold-t { font-size: 14px; font-weight: 700; color: var(--ink); }
.pup-fold-h { font-size: 11.5px; color: var(--ink-2); }
.pup-fold-bd { padding: 0 0 12px 15px; }
.pup-fold.is-collapsed .pup-fold-bd { display: none; }
/* Vert clair dot on an open fold, anchored exactly like .aiq-nav-dot. */
.pup-fold-dot { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); width: 6px; height: 6px; border-radius: 50%; background: var(--vert-clair); opacity: 0; transition: opacity 0.15s; }
.pup-fold:not(.is-collapsed) > .pup-fold-hd .pup-fold-dot { opacity: 1; }

/* Relationship thread (fiche lead · Fil de la relation): each event reuses the
   Rédaction fold (.pup-fold, collapsed at rest). The who pill states the nature
   per situation. The sequence link sits at the header's right as a Forest link,
   a sibling of the toggle button, so it stays navigable without nesting a link
   inside the <button>. Events are ruled between one another, not above the first. */
.rel-ev { position: relative; border-top: 0; }
.rel-ev + .rel-ev { border-top: 1px solid var(--line); }
.rel-ev .pup-fold-hd { padding-right: 96px; }
.rel-ev-when { font-size: 13px; color: var(--ink-2); }
.rel-ev-seq { position: absolute; top: 13px; right: 12px; z-index: 1;
              font-size: 12.5px; font-weight: 700; color: var(--forest);
              text-decoration: none; white-space: nowrap; }
.rel-ev-seq:hover { text-decoration: underline; }
.rel-ev-seq:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: 2px; border-radius: 4px; }
.rel-ev-subject { font-size: 15px; font-weight: 700; color: var(--ink); margin: 0 0 2px; }
.rel-ev .pup-fold-bd .aiq-note { margin: 8px 0 0; white-space: pre-wrap; }

/* Séquences facet (fiche lead): each campaign is a foldable card (Rédaction
   fold), collapsed at rest so the panel reads as an instrument, not an empty
   stub. Header states status + which sequence + a reply flag when it needs
   attention; the body opens progress, timing and the campaign link. Distinct
   from the Fil (the messages) and from /campaign (full management). */
.seq-fold { border-top: 0; }
.seq-fold + .seq-fold { border-top: 1px solid var(--line); }
.seq-fold .pup-fold-hd { flex-wrap: wrap; }
.seq-name { font-size: 14.5px; font-weight: 700; color: var(--ink); }
.seq-chips { display: inline-flex; gap: 6px; }
.seq-sig { margin-left: auto; font-size: 13px; font-weight: 700; color: var(--vert-clair); white-space: nowrap; }
.seq-line { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; font-size: 13px; color: var(--ink-2); margin-top: 8px; }
.seq-line:first-child { margin-top: 2px; }
.seq-fig { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.seq-dots { display: inline-flex; gap: 4px; align-items: center; margin-right: 4px; }
.seq-dot { width: 7px; height: 7px; border-radius: 999px; }
.seq-dot.done { background: var(--vert-fonce); }        /* a sent step */
.seq-dot.next { background: var(--vert-clair); }         /* the upcoming step (the one accent) */
.seq-dot.todo { background: transparent; border: 1px solid var(--prune-20); }
.seq-open { font-size: 12.5px; font-weight: 700; color: var(--forest); text-decoration: none; }
.seq-open:hover { text-decoration: underline; }
.seq-open:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: 2px; border-radius: 4px; }

/* Rappels facet (fiche lead): the reminder reuses the Rédaction fold, collapsed
   at rest. Header = the scannable date line (relative day · kind · time); body
   keeps the note and the Fait/Reprogrammer/Supprimer actions unchanged. */
.rel-task { border-top: 0; }
.rel-task + .rel-task { border-top: 1px solid var(--line); }
.rel-task-time { margin-left: auto; font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rel-task.is-late .rel-task-time { color: var(--error); }

/* Control rows inside a fold: label | control + compiled preview. */
.pup-row { display: grid; grid-template-columns: 190px 1fr; gap: 18px; align-items: start; padding: 11px 0; border-top: 1px dashed var(--line); }
.pup-row:first-child { border-top: 0; }
.pup-lab { font-size: 13.5px; font-weight: 600; color: var(--ink); padding-top: 6px; }
.pup-lab .s { display: block; font-size: 11.5px; font-weight: 400; color: var(--ink-2); margin-top: 2px; line-height: 1.4; }
.pup-ctl { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
/* Inline action forms in a control cell carry no margin (was inline on each form). */
.pup-ctl form { margin: 0; }
/* The deal band's state label + amount (was an inline colour computed per stage).
   Lost recedes to ink-2; won and meeting read in the accent. */
.deal-state { font-weight: 700; color: var(--vert-clair); }
.deal-state.is-lost { color: var(--ink-2); }
.deal-amt { font-size: 14px; color: var(--ink-2); }
.pup-comp { font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); }
.pup-comp b { color: var(--prune); font-weight: 400; }
.pup-sel { border: 1px solid var(--line); border-radius: 9px; padding: 7px 12px; font: inherit; font-size: 14px; color: var(--ink); background: var(--beige); }
.pup-sel:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }

/* Interdits (toggles): name | net status | switch. */
.pup-tgs { display: flex; flex-direction: column; width: 100%; }
.pup-tg { display: grid; grid-template-columns: 1fr auto 44px; gap: 16px; align-items: center; padding: 9px 0; border-top: 1px dashed var(--line); }
.pup-tg:first-child { border-top: 0; }
.pup-tg .n { font-size: 13.5px; color: var(--ink); }
.pup-tg .net { font-size: 11px; color: var(--ink-2); white-space: nowrap; }
.pup-tg .net.is-code { color: var(--vert-clair); font-weight: 600; }
.pup-tg .net.is-bare { color: var(--prune); }
/* Pure-CSS switch built on a checkbox, so it submits with the form, no JS. */
.pup-sw { position: relative; display: inline-block; width: 40px; height: 22px; cursor: pointer; }
.pup-sw input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }
.pup-sw .track { position: absolute; inset: 0; border-radius: 999px; background: var(--surface); border: 1px solid var(--line); }
.pup-sw .track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--prune); transition: left 0.12s, background 0.12s; }
.pup-sw input:checked + .track { background: var(--forest); border-color: var(--forest); }
.pup-sw input:checked + .track::after { left: auto; right: 2px; background: var(--beige); }
.pup-sw input:focus-visible + .track { outline: 2px solid var(--vert-clair); outline-offset: 2px; }

/* The two admin-extensible lists (banned words, forbidden phrasings). */
.pup-avoid { margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--line); }
.pup-avoid .t { font-size: 12.5px; font-weight: 700; color: var(--ink); margin-bottom: 3px; }
.pup-avoid .d { font-size: 11.5px; color: var(--ink-2); margin-bottom: 10px; line-height: 1.45; }
.pup-words { display: flex; flex-direction: column; gap: 8px; width: 100%; }
.pup-word { display: grid; gap: 10px; align-items: center; }
.pup-word.pair { grid-template-columns: 1fr 22px 1fr 26px; }
.pup-word.solo { grid-template-columns: 1fr 26px; }
.pup-word input { border: 1px solid var(--line); border-radius: 8px; padding: 7px 11px; font-family: var(--mono); font-size: 13px; background: var(--beige); color: var(--prune); margin: 0; }
.pup-word input:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }
.pup-word .a { text-align: center; color: var(--ink-2); }
.pup-x { flex: none; width: 26px; height: 26px; border: 0; background: none; color: var(--ink-2); cursor: pointer; font-size: 17px; line-height: 1; border-radius: 6px; }
.pup-x:hover { color: var(--error); background: color-mix(in srgb, var(--error) 10%, transparent); }
.pup-add { align-self: flex-start; background: none; border: 0; color: var(--forest); font: inherit; font-size: 12.5px; cursor: pointer; padding: 4px 0; margin-top: 2px; }
.pup-add:hover { text-decoration: underline; }

/* Prose band (Voix et stratégie): stacked labelled textareas. */
.pup-prose-field { margin-bottom: 16px; }
.pup-prose-field label { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-2); margin-bottom: 7px; }
.pup-prose-field .h { font-size: 11.5px; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--ink-2); margin-left: 8px; }
.pup-prose-field textarea, .pup-prose-ta { width: 100%; box-sizing: border-box; border: 1px solid var(--line); border-radius: 10px; background: var(--beige); font-family: var(--mono); font-size: 13px; line-height: 1.6; color: var(--prune); padding: 12px 14px; resize: vertical; margin: 0; }
.pup-prose-field textarea:focus-visible, .pup-prose-ta:focus-visible { outline: 2px solid var(--vert-clair); outline-offset: -2px; }

/* Read-only band (Garanti par la machine). */
.pup-fixed { padding: 11px 0; border-top: 1px dashed var(--line); }
.pup-fixed:first-child { border-top: 0; }
.pup-fixed .l { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); margin-bottom: 5px; }
.pup-fixed .v { font-size: 13px; color: var(--prune); line-height: 1.5; }

/* Rail cards get the same green hover as the folds, for one language. */
.aiq-nav-item:hover { background: color-mix(in srgb, var(--forest) 6%, transparent); }

/* Résultat panel (inspector, Réel mode): the lead-specific task, structured. */
.pup-r-chip { display: inline-flex; align-items: center; gap: 8px; border: 1px solid var(--line); border-radius: 9px; padding: 7px 11px; background: var(--surface); font-size: 13px; color: var(--ink); }
.pup-r-chip .chg { font-size: 11.5px; color: var(--forest); cursor: pointer; background: none; border: 0; text-decoration: none; }
.pup-r-chip .chg:hover { text-decoration: underline; }
.pup-r-meta { font-family: var(--mono); font-size: 11px; color: var(--ink-2); margin: 9px 0 0; }
.pup-r-part { padding: 9px 0; border-top: 1px dashed var(--line); }
.pup-r-part:first-child { border-top: 0; }
.pup-r-part .l { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); margin-bottom: 5px; }
.pup-r-part .b { font-family: var(--mono); font-size: 11.5px; line-height: 1.55; color: var(--prune); }
.pup-r-mail { display: flex; gap: 8px; font-family: var(--mono); font-size: 11.5px; color: var(--prune); padding: 2px 0; }
.pup-r-mail b { color: var(--ink); font-weight: 700; min-width: 46px; }
.pup-r-empty { font-size: 12px; color: var(--ink-2); line-height: 1.5; }
.pup-r-json { font-family: var(--mono); font-size: 10.5px; line-height: 1.5; color: color-mix(in srgb, var(--prune) 75%, var(--beige)); white-space: pre-wrap; margin: 0; }
