/*
 * CRM Contacts admin styles — Direction A "The Ledger"
 *
 * Implements the approved corrected prototype design_preview.html
 * (Blackboard record e25226f4-f026-4cd8-b853-752353f66c65).
 *
 * ---------------------------------------------------------------------------
 * IMPLEMENTATION POSTURE
 * ---------------------------------------------------------------------------
 * The design specification requires components to be authored against Wagtail
 * 6.3 semantic aliases, because the host (playactive-backend) loads its own
 * playactive/css/admin.css which CONSUMES those aliases. A hard-coded hex does
 * not track host theming and does not flip under `.w-theme-dark`.
 *
 * So: every colour in this file is written as `var(--w-color-…, <fallback>)`.
 * The fallback is the value that alias resolves to in stock light-theme
 * Wagtail 6.3.8 — it is a redundant restatement of the same colour, not a
 * second palette, and it is only reached if Wagtail's core.css is absent.
 * There is no bare colour literal in this file outside a `var()` fallback.
 *
 * Every fallback is a value present in design_tokens.json v1.0.0. There are no
 * remaining exceptions to that. The one there used to be — `--w-color-warning-50`
 * (#faecd5), the "too many to compare" chip fill, which the token file had no
 * pale warning surface for — was resolved by adding `warning-50` to the token
 * file on 2026-07-28. It is an inherited Wagtail alias, which suits the token
 * file's own provenance policy better than the #fff8e8 the approved prototype
 * invented for the same purpose.
 *
 * The single carve-out left is about SHAPE, not palette: `--suppression-ink`
 * (#a8a8b2 light / #8f8f9c dark) is written as a bare literal rather than a
 * `var()` fallback, because a repeating-linear-gradient needs one reusable
 * stop. Both values ARE approved additions in design_tokens.json
 * (`suppression-ink-light` / `suppression-ink-dark`).
 *
 * None of the three paragraphs above is taken on trust. See
 * contacts/tests/test_stylesheet_tokens.py, which reads this file with its
 * comments stripped — prose in a comment is not evidence about a declaration —
 * and checks both claims against design_tokens.json.
 *
 * ---------------------------------------------------------------------------
 * COLOUR IS NEVER THE ONLY CHANNEL
 * ---------------------------------------------------------------------------
 * Anti-goal: consent must never degrade to a colour code. The three consent
 * chips differ by FILL / HEAVY OUTLINE / DASHED OUTLINE, the four band chips by
 * FILL / SOLID / DOTTED / DOUBLE-RULE, and suppression by a 45-degree HATCH.
 * All of those survive greyscale printing and monochrome displays. Do not
 * "tidy" any of them into a colour-only variant.
 *
 * ---------------------------------------------------------------------------
 * RESPONSIVE
 * ---------------------------------------------------------------------------
 * Contracted viewports are 390x844 and 1440x1000. The stacking breakpoint is
 * 49.9375em (799px), matching the approved prototype's single admin
 * breakpoint. Every hand-authored table on these surfaces carries
 * `.crm-stacked-table` and per-cell `data-label`, so below the breakpoint it
 * becomes labelled stacked pairs instead of overflowing sideways.
 *
 * NG-4: no bespoke chrome; stays in Wagtail idiom throughout.
 */

/* =========================================================================
   SUPPRESSION TEXTURE (DEVIATION TEX-1)
   45-degree hatching; texture not colour is the discriminating channel so
   the chip survives greyscale printing (design anti-goal 4).
   Widened to 4px pitch (cycle-2 correction — 2px aliased to flat grey).
   ========================================================================= */
:root {
  --suppression-ink:    #a8a8b2;  /* design_tokens color.suppression-ink-light */
  --suppression-pitch:  4px;
  --suppression-stroke: 1.5px;
}

/* Wagtail's own dark-theme idiom: an explicit `.w-theme-dark`, plus
   `.w-theme-system` under the OS preference. design_tokens.json declares
   `suppression-ink-dark` for exactly this and nothing was consuming it. */
.w-theme-dark {
  --suppression-ink: #8f8f9c;  /* design_tokens color.suppression-ink-dark */
}

@media (prefers-color-scheme: dark) {
  .w-theme-system {
    --suppression-ink: #8f8f9c;
  }
}

/* =========================================================================
   BASE STATUS TAG
   All consent / band / suppression chips share this class.
   --radius-pill: 2px per spec.
   ========================================================================= */
.status-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.5rem;
  border-radius: 2px;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
  border: 1px solid transparent;
}

/* =========================================================================
   CONSENT STATE CHIPS  (three visually distinct states — never boolean)
   Shapes differ (fill / heavy-outline / dashed) so they survive greyscale.
   ========================================================================= */

/* Subscribed — filled dark teal */
.status-tag.consent.consent--subscribed {
  background-color: var(--w-color-secondary-600, #004345);
  border-color: var(--w-color-secondary-600, #004345);
  color: var(--w-color-white, #ffffff);
}

/* Unsubscribed — outlined, heavy 2px border, dark text */
.status-tag.consent.consent--unsubscribed {
  background-color: var(--w-color-surface-page, #ffffff);
  border: 2px solid var(--w-color-grey-500, #333333);
  color: var(--w-color-grey-500, #333333);
  font-weight: 800;
}

/* Never asked — dashed border, italic; REFUSAL not absence */
.status-tag.consent.consent--never {
  background-color: var(--w-color-surface-page, #ffffff);
  border: 2px dashed var(--w-color-grey-400, #5c5c5c);
  color: var(--w-color-grey-400, #5c5c5c);
  font-style: italic;
}

/* Suppressed — hatched texture; placed BESIDE consent, never replacing it */
.status-tag.suppression {
  background-color: var(--w-color-surface-page, #ffffff);
  background-image: repeating-linear-gradient(
    45deg,
    var(--suppression-ink) 0,
    var(--suppression-ink) var(--suppression-stroke),
    transparent var(--suppression-stroke),
    transparent var(--suppression-pitch)
  );
  border: 2px solid var(--w-color-grey-500, #333333);
  color: var(--w-color-grey-600, #262626);
  font-weight: 800;
  /* Text shadow provides legibility over the diagonal stripe texture */
  text-shadow:
    0 0 3px var(--w-color-surface-page, #ffffff),
    0 0 3px var(--w-color-surface-page, #ffffff);
}

/* Dark theme: the grey scale does not flip, so the chips that draw their
   outline from it are re-pointed at the light end of the same scale. Same
   rules as the approved prototype's `html.w-theme-dark` block. */
.w-theme-dark .status-tag.consent.consent--unsubscribed {
  border-color: var(--w-color-grey-50, #f6f6f8);
  color: var(--w-color-grey-50, #f6f6f8);
}

.w-theme-dark .status-tag.consent.consent--never {
  border-color: var(--w-color-grey-150, #c8c8c8);
  color: var(--w-color-grey-150, #c8c8c8);
}

.w-theme-dark .status-tag.suppression {
  border-color: var(--w-color-grey-100, #e0e0e0);
  color: var(--w-color-grey-50, #f6f6f8);
}

@media (prefers-color-scheme: dark) {
  .w-theme-system .status-tag.consent.consent--unsubscribed {
    border-color: var(--w-color-grey-50, #f6f6f8);
    color: var(--w-color-grey-50, #f6f6f8);
  }

  .w-theme-system .status-tag.consent.consent--never {
    border-color: var(--w-color-grey-150, #c8c8c8);
    color: var(--w-color-grey-150, #c8c8c8);
  }

  .w-theme-system .status-tag.suppression {
    border-color: var(--w-color-grey-100, #e0e0e0);
    color: var(--w-color-grey-50, #f6f6f8);
  }
}

/* =========================================================================
   MATCH STRENGTH BAND CHIPS  (S3 Possible Duplicates)
   Four variants with distinct shape+weight encoding (not colour alone).
   ========================================================================= */

.status-tag.band {
  font-weight: 700;
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
}

/* Strong — filled. Ink and fill are taken from opposite ends of the theme's
   own text/surface pair, so the chip inverts rather than going light-on-light
   when --w-color-text-context flips under .w-theme-dark. */
.status-tag.band.band--strong {
  background-color: var(--w-color-text-context, #262626);
  border-color: var(--w-color-text-context, #262626);
  color: var(--w-color-surface-page, #ffffff);
}

/* Probable — 2px solid outline, no fill */
.status-tag.band.band--probable {
  background-color: transparent;
  border: 2px solid var(--w-color-grey-500, #333333);
  color: var(--w-color-grey-500, #333333);
}

/* Weak — 2px dotted outline */
.status-tag.band.band--weak {
  background-color: transparent;
  border: 2px dotted var(--w-color-grey-400, #5c5c5c);
  color: var(--w-color-grey-400, #5c5c5c);
}

/* Dark theme: probable and weak draw their outline from the fixed grey scale,
   which does not flip, so they are re-pointed at its light end. Measured at
   1.20:1 and 2.26:1 respectively without this. */
.w-theme-dark .status-tag.band.band--probable {
  border-color: var(--w-color-grey-50, #f6f6f8);
  color: var(--w-color-grey-50, #f6f6f8);
}

.w-theme-dark .status-tag.band.band--weak {
  border-color: var(--w-color-grey-150, #c8c8c8);
  color: var(--w-color-grey-150, #c8c8c8);
}

@media (prefers-color-scheme: dark) {
  .w-theme-system .status-tag.band.band--probable {
    border-color: var(--w-color-grey-50, #f6f6f8);
    color: var(--w-color-grey-50, #f6f6f8);
  }

  .w-theme-system .status-tag.band.band--weak {
    border-color: var(--w-color-grey-150, #c8c8c8);
    color: var(--w-color-grey-150, #c8c8c8);
  }
}

/* Too many — terminal state.
 *
 * A11Y FIX. The approved prototype draws this chip as a 2px
 * `--w-color-warning-100` (#faa500) rule on a #fff8e8 fill. Measured, that
 * boundary is 1.90:1 against its own fill and 2.01:1 against the page — below
 * the 3:1 that SC 1.4.11 asks of meaningful non-text UI, and the amber rule is
 * also the only thing separating this chip's SHAPE from `band--probable`.
 *
 * The amber is kept, as an inset ring, because amber is the design's caution
 * signal. The identifying boundary is the outer grey-600 rule instead, and the
 * doubled ring is a second, greyscale-surviving shape channel: fill / solid /
 * dotted / double-ring across the four bands.
 *
 * Re-measured 2026-07-30 in the rendered cascade — Wagtail 6.3.8 core.css plus
 * the host's admin.css, read back as computed style rather than from the
 * values written here — on /admin/overflow-groups/ at 1440x1000:
 *
 *   label #262626 on fill #faecd5 ............ 12.99:1  (SC 1.4.3, needs 4.5)
 *   outer rule #262626 vs the page #ffffff ... 15.13:1  (SC 1.4.11, needs 3)
 *   outer rule vs its own fill ............... 12.99:1
 *   amber inset ring #faa500 vs fill ......... 1.73:1
 *
 * The ring's 1.73:1 is deliberate and is not a failure: it is decoration
 * inside the identifying boundary, not the boundary. SC 1.4.11 applies to the
 * part that says where the component is, and that is the 15.13:1 outer rule.
 * Removing the ring would leave `band--toomany` shaped exactly like
 * `band--probable`, which is the defect this whole block exists to fix.
 *
 * `--w-color-warning-50` resolves to #faecd5 in that cascade — the host does
 * not retheme it — and #faecd5 is `warning-50` in design_tokens.json since
 * 2026-07-28. contacts/tests/test_stylesheet_tokens.py holds that.
 */
.status-tag.band.band--toomany {
  background-color: var(--w-color-warning-50, #faecd5);
  border: 2px solid var(--w-color-grey-600, #262626);
  /* The fill is a fixed light amber in both themes, so the ink is pinned to
     the dark end of the scale rather than to the theme's text colour. */
  color: var(--w-color-grey-600, #262626);
  box-shadow: inset 0 0 0 2px var(--w-color-warning-100, #faa500);
}

/* =========================================================================
   TAG ROW  — flex wrapper holding consent + optional suppression side-by-side
   ========================================================================= */
.crm-tag-row {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  flex-wrap: wrap;
}

/* =========================================================================
   EFFECTIVE CONSENT SENTENCE  (Graft 4 — always visible, never tooltip)
   Appears below the chip row on every consent display at every viewport.
   ========================================================================= */
.crm-effective {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--w-color-text-meta, #5c5c5c);
  line-height: 1.4;
}

.crm-effective__kind {
  font-weight: 600;
  color: var(--w-color-text-context, #262626);
}

.crm-effective__kind::after {
  content: " — ";
  font-weight: 400;
}

/* =========================================================================
   MONOSPACE INLINE SPAN — email addresses, error codes
   ========================================================================= */
.crm-mono,
.crm-contacts-page .mono {
  font-family: var(--w-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  font-size: 0.875em;
  /* A long address wraps rather than widening the reading column. */
  overflow-wrap: anywhere;
}

/* =========================================================================
   MATCH REASONS TEXT  (S3 below the band chip)
   ========================================================================= */
.crm-reasons {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.8125rem;
  color: var(--w-color-text-meta, #5c5c5c);
}

/* =========================================================================
   REVERSAL STATE COLUMN  (S7 Merge Audit)

   Four per-record states, each visually distinct: reversible, reversed,
   expired, forfeited. There is no "never" state — that is a standing
   caveat about every merge (.crm-never-reversible below), not a status a
   row can hold.

   Colour is never the only channel (design a11y rule): each state also
   carries its own leading symbol from the column, its own wording, and a
   distinct weight/style combination, so the whole cell survives greyscale
   and monochrome printing.
   ========================================================================= */
.crm-reversal__symbol {
  margin-right: 0.3rem;
  font-weight: 700;
}

/* Reversible — the only actionable state. Upright, medium weight. */
.crm-reversal--reversible {
  color: var(--w-color-text-context, #262626);
  font-weight: 500;
}

/* Reversed — done, and a success. Upright and quiet, NOT italic: it is
   not a degraded state and must not read as one. */
.crm-reversal--reversed {
  color: var(--w-color-text-meta, #5c5c5c);
  font-weight: 500;
}

/* Expired — lapsed by time. Italic, no border. */
.crm-reversal--expired {
  color: var(--w-color-text-meta, #5c5c5c);
  font-style: italic;
}

/* Forfeited — destroyed by an erasure, not merely lapsed. Italic AND a
   leading rule, so it is distinguishable from Expired without colour. */
.crm-reversal--forfeited {
  color: var(--w-color-text-meta, #5c5c5c);
  font-style: italic;
  border-left: 3px solid var(--w-color-border-furniture-more-contrast, #929292);
  padding-left: 0.4rem;
}

/* The standing category caveat beneath the merge audit listing. */
.crm-never-reversible {
  margin-top: 1rem;
  border-top: 1px solid var(--w-color-border-furniture, #e0e0e0);
  padding-top: 0.75rem;
}

/* =========================================================================
   ACCOUNTABILITY BLOCK  (ADR-10 governance quartet)
   ========================================================================= */
.crm-accountability {
  border-left: 4px solid var(--w-color-primary, #2e1f5e);
  background: var(--w-color-surface-field-inactive, #f6f6f8);
  padding: 0.75rem 0.9rem;
  margin: 0 0 1rem;
  font-size: 0.95em;
}

/* =========================================================================
   CONSENT-STATUS STANDING NOTICE
   Shown on contacts index: "Contacts are importable, but not marketable"

   Was three inline `style=` attributes on the template. The inline block also
   hard-coded a 2rem inline margin, which at 390px is 10% of the viewport on
   each side; the padding now tracks Wagtail's own .nice-padding breakpoint.
   ========================================================================= */
.crm-standing-notice {
  margin: 0 1rem 1.5rem;
  padding: 1rem 1.25rem;
}

@media (min-width: 50em) {
  .crm-standing-notice {
    margin-inline: 2rem;
  }
}

.crm-standing-notice__heading {
  margin-top: 0;
}

.crm-standing-notice__body {
  margin-bottom: 0;
}

/* =========================================================================
   CONTACTS STAT TILES — inert vs linked
   Some header summary tiles (e.g. "Contacts", "With a consent record") have
   no filtered listing to link to and are deliberately rendered as plain text
   rather than an <a>. Undecorated, the two states are visually identical —
   nothing tells an operator which tiles do something before they try
   clicking. This muted, no-pointer treatment is the tell.
   ========================================================================= */
.crm-stat--inert {
  color: var(--w-color-text-meta, #5c5c5c);
}

.crm-stat--inert span {
  cursor: default;
}

/* =========================================================================
   MERGE DOSSIER  (S4 — adjudication surface)
   ========================================================================= */

/* Band chip row at the top of the dossier */
.crm-merge-band {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

/* Field comparison table — diff rows are visually distinguished */
.crm-merge-comparison {
  width: 100%;
  margin-bottom: 1.5rem;
}

/* A changed row is marked by a rule down its leading edge as well as by a
   tint, so the distinction is positional and survives greyscale. The tint is
   an inactive-surface alias rather than the invented cream #fffbe8, so it
   also inverts correctly in dark theme along with the cell text. */
.crm-merge-comparison__diff td {
  background-color: var(--w-color-surface-field-inactive, #f6f6f8);
}

.crm-merge-comparison__diff td:first-child {
  box-shadow: inset 4px 0 0 var(--w-color-text-context, #262626);
}

.crm-merge-comparison__lost {
  margin-left: 0.3rem;
  color: var(--w-color-text-error, #ca3b3b);
  font-size: 0.85em;
}

/* Tombstone resolvability + the counts for this pair. Reads as prose, not
   as a panel: it is a statement about what the identifiers do afterwards. */
.crm-merge-resolvability {
  max-width: 62ch;
  margin: 0 0 1.25rem;
  line-height: 1.55;
}

/* Mandatory point-of-action copy, item 1. Sits above both consequence
   panels because it is true of the pair of actions rather than of either
   side, and the operator must not be able to read one panel and stop. */
.crm-merge-consequences__mandate {
  border: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  border-left: 4px solid var(--w-color-text-error, #ca3b3b);
  border-radius: 3px;
  padding: 0.9rem 1rem;
  margin-bottom: 1.25rem;
  background: var(--w-color-surface-field-inactive, #f6f6f8);
  line-height: 1.55;
}

.crm-merge-consequences__mandate p {
  max-width: 78ch;
}

/* Consequences side-by-side panels */
.crm-merge-consequences {
  display: flex;
  gap: 1.25rem;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
}

.crm-merge-consequences__panel {
  flex: 1 1 300px;
  border: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  border-radius: 3px;
  padding: 0.9rem 1rem;
  background: var(--w-color-surface-field-inactive, #f6f6f8);
}

/* Prototype rule: the permanent panel is NOT flagged in red. A red panel
   reads as an error, and neither of these panels is one — they are two
   complete, equally weighted claims. The heading carries the distinction;
   the rule carries weight, not alarm. */
.crm-merge-consequences__panel--permanent {
  border-left: 4px solid var(--w-color-text-context, #262626);
}

/* secondary-600, not secondary: a host may retheme --w-color-secondary to a
   light accent (this repo's own Concord branding maps it to #4fc3f7, measured
   2.00:1 against the page), while secondary-600 stays a deep teal. */
.crm-merge-consequences__panel--reversible {
  border-left: 4px solid var(--w-color-secondary-600, #004345);
}

.crm-merge-consequences__heading {
  font-size: 0.95rem;
  font-weight: 700;
  margin: 0 0 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.crm-merge-consequences__list {
  margin: 0 0 0.5rem 0;
  padding-left: 1.2rem;
  font-size: 0.9rem;
  line-height: 1.5;
}

.crm-merge-consequences__list li {
  margin-bottom: 0.4rem;
}

.crm-merge-consequences__note {
  font-size: 0.85rem;
  color: var(--w-color-text-meta, #5c5c5c);
  margin: 0.5rem 0 0;
}

/* Merge reason textarea */
.crm-merge-reason {
  margin-bottom: 1rem;
  max-width: 600px;
}

.crm-merge-reason__required {
  color: var(--w-color-text-error, #ca3b3b);
}

/* ADR-10's external case/ticket reference, beside the reason. */
.crm-merge-reference {
  margin-bottom: 1rem;
  max-width: 600px;
}

.crm-merge-reason__textarea {
  width: 100%;
  max-width: 100%;
  font-family: inherit;
  font-size: 0.9375rem;
  /* 3.11:1 against white — A11Y-1 compliant. The alias is Wagtail's own
     name for the raised-contrast furniture border. */
  border: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  border-radius: 3px;
  padding: 0.4rem 0.5rem;
  line-height: 1.5;
  resize: vertical;
}

/* Three-action button row */
.crm-merge-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding-top: 0.5rem;
}

.crm-merge-actions__primary {
  /* Inherits .button.button-primary — no additional styles needed */
}

.crm-merge-actions__secondary {
  /* Inherits .button.button-secondary */
}

/* =========================================================================
   ACCESSIBILITY REMEDIATION  (DEVIATION A11Y-1)

   Stock Wagtail's resting field border is --w-color-border-field-default
   (grey-150, #c8c8c8) and its furniture border is grey-100 (#e0e0e0) — 1.32:1
   against white, which fails SC 1.4.11 for the boundary of a user interface
   component. Raised to --w-color-border-furniture-more-contrast (grey-200,
   #929292 = design_tokens `border-accessible`), measured 3.11:1.

   SCOPE. `.crm-contacts-page` is now applied to the BODY element of every CRM
   surface via `{% block bodyclass %}`, not only to one wrapper div on one
   template. It previously reached exactly one template — merge_dossier.html —
   while the import wizard, which holds most of the form controls in the whole
   phase, kept the failing stock border. The class is still a scope: this
   stylesheet is injected globally by insert_global_admin_css, and must not
   restyle the rest of the host's admin.
   ========================================================================= */
.crm-contacts-page .w-field__input,
.crm-contacts-page input[type="text"],
.crm-contacts-page input[type="email"],
.crm-contacts-page input[type="search"],
.crm-contacts-page input[type="tel"],
.crm-contacts-page input[type="url"],
.crm-contacts-page input[type="number"],
.crm-contacts-page input[type="password"],
.crm-contacts-page input[type="date"],
.crm-contacts-page input[type="file"],
.crm-contacts-page select,
.crm-contacts-page textarea {
  border-color: var(--w-color-border-furniture-more-contrast, #929292);
}

/* --w-color-border-furniture-more-contrast resolves to grey-400 under
   .w-theme-dark, which measures 2.26:1 against the dark field surface and so
   would undo the remediation in the other theme. grey-200 — the value
   design_tokens.json names `border-accessible` — measures 4.86:1 there. */
.w-theme-dark .crm-contacts-page .w-field__input,
.w-theme-dark .crm-contacts-page input[type="text"],
.w-theme-dark .crm-contacts-page input[type="email"],
.w-theme-dark .crm-contacts-page input[type="search"],
.w-theme-dark .crm-contacts-page input[type="tel"],
.w-theme-dark .crm-contacts-page input[type="url"],
.w-theme-dark .crm-contacts-page input[type="number"],
.w-theme-dark .crm-contacts-page input[type="password"],
.w-theme-dark .crm-contacts-page input[type="date"],
.w-theme-dark .crm-contacts-page input[type="file"],
.w-theme-dark .crm-contacts-page select,
.w-theme-dark .crm-contacts-page textarea,
.w-theme-dark .crm-merge-reason__textarea {
  border-color: var(--w-color-grey-200, #929292);
}

@media (prefers-color-scheme: dark) {
  .w-theme-system .crm-contacts-page .w-field__input,
  .w-theme-system .crm-contacts-page input[type="text"],
  .w-theme-system .crm-contacts-page input[type="email"],
  .w-theme-system .crm-contacts-page input[type="search"],
  .w-theme-system .crm-contacts-page select,
  .w-theme-system .crm-contacts-page textarea,
  .w-theme-system .crm-merge-reason__textarea {
    border-color: var(--w-color-grey-200, #929292);
  }
}

/* =========================================================================
   SHARED STACKED-TABLE TREATMENT  (SC 1.4.10 reflow)

   Wagtail's admin has one layout breakpoint and its `.listing` does not
   reflow at all: the header cells are nowrap, so the table keeps an
   un-shrinkable minimum width, and `body { overflow-x: hidden }` then makes
   the overflowing columns unreachable rather than scrollable. At 390px that
   silently truncates data.

   Every hand-authored table on these surfaces therefore carries
   `.crm-stacked-table` plus a `data-label` on each cell, and below the
   prototype's 799px breakpoint becomes labelled stacked pairs. One rule set,
   applied consistently, rather than a copy per surface.

   The six index listings Wagtail generates for the CRM are in the same rule
   set. They get there through `StackedListingMixin`
   (zyrous_wagtail_crm/contacts/tables.py), which supplies both halves the
   rules need: `crm-stacked-table` on the table, and a cell template that emits
   `data-label`. Before that they scrolled sideways while the hand-authored
   table beneath them stacked — two behaviours for the same content on one
   screen — and the import history listing, which had no scope class at all,
   did not even scroll: 20 elements were measured overflowing the 390px content
   wrapper with nothing scrollable above them, so its last two columns were
   simply unreachable.
   ========================================================================= */
@media (max-width: 49.9375em) {
  .crm-stacked-table,
  .crm-stacked-table thead,
  .crm-stacked-table tbody,
  .crm-stacked-table tr,
  .crm-stacked-table td {
    display: block;
    width: 100%;
  }

  /* Kept in the accessibility tree — the header cells are still the row's
     programmatic labels; only the visual header is replaced. */
  .crm-stacked-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .crm-stacked-table tr {
    border: 1px solid var(--w-color-border-furniture, #e0e0e0);
    border-radius: 0.3125rem;
    margin-bottom: 0.6rem;
    padding: 0.2rem 0;
  }

  .crm-stacked-table td {
    border-bottom: 1px dashed var(--w-color-border-furniture, #e0e0e0);
    padding: 0.5rem 0.7rem;
    /* A long identifier wraps; it never widens the reading column. */
    overflow-wrap: anywhere;
  }

  .crm-stacked-table td:last-child {
    border-bottom: 0;
  }

  .crm-stacked-table td::before {
    content: attr(data-label);
    display: block;
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
    color: var(--w-color-text-meta, #5c5c5c);
  }

  .crm-stacked-table td[data-label=""]::before,
  .crm-stacked-table td:not([data-label])::before {
    display: none;
  }

  /* DEFECT: `.status-tag { white-space: nowrap }` sits in the consent column,
     which also carries the full derived sentence. Below the breakpoint that
     column is 150-200px wide, and an unbreakable chip in it is a direct cause
     of horizontal overflow — measured at 194px of chip in a 390px viewport,
     taking the listing to a 449px scroll width.
     Chips are allowed to wrap here, but only between words: Wagtail's
     `.listing td { overflow-wrap: anywhere }` is inherited by the chip's text
     and would otherwise break a single-word label like "STRONG" one letter per
     line inside a narrow generated column. The nowrap is kept at desktop,
     where the columns are wide and a split chip would read as two chips. */
  .crm-contacts-page .status-tag {
    white-space: normal;
    overflow-wrap: normal;
    word-break: normal;
  }

  /* A generated listing that has NOT been given the stacking treatment. Stock
     Wagtail's cell template renders `<td class="…">` and nothing else, so
     without a `data-label` hook there is nothing for the rules above to read
     and the table cannot stack from CSS alone. Those are made scrollable
     instead, which is permitted for a data table under SC 1.4.10 and is
     strictly better than the stock behaviour of clipping the overflow out of
     reach.

     No CRM listing lands here any more. `StackedListingMixin` in
     contacts/tables.py points all six at crm_contacts/tables/{cell,title_cell}
     .html, which emit the label, and puts `crm-stacked-table` on the table.
     The rule is kept as the fallback it was written to be. A CRM surface can
     still acquire a `.listing` nobody has given the mixin — a chooser panel,
     or a listing added later — and scrollable is still better than clipped. */
  .crm-contacts-page .listing:not(.crm-stacked-table) {
    display: block;
    overflow-x: auto;
  }
}

/* Chips must never be the thing that widens a column, at any viewport. */
.crm-contacts-page .status-tag {
  max-width: 100%;
}

/* =========================================================================
   CANDIDATE-SET OVERFLOW — terminal review surface (design oracle #overflow)
   Nothing here styles an action, because the screen deliberately has none.
   ========================================================================= */

.crm-overflow {
  max-width: 78ch;
}

/* Eyebrow — "Candidate group · flagged for manual review". Sits directly
   under Wagtail's own h1 because the stock slim header owns the region above
   it and we do not build a second header shell. */
.crm-overflow__eyebrow {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 700;
  margin: 0 0 0.75rem;
  color: var(--w-color-text-meta, #5c5c5c);
}

/* Immutable-policy block — states the refusal ABOVE everything it applies to,
   so the operator reads "this cannot be merged here" before hunting for a
   control that does not exist. */
.crm-overflow__immutable {
  border: 2px solid var(--w-color-text-context, #262626);
  border-radius: 0.3125rem;
  padding: 0.85rem 1rem;
  margin: 0 0 1.1rem;
  background: var(--w-color-surface-field-inactive, #f6f6f8);
  color: var(--w-color-text-context, #262626);
}

.crm-overflow__immutable-head {
  font-weight: 800;
  display: block;
  margin-bottom: 0.25rem;
}

.crm-overflow__immutable p {
  margin-bottom: 0.85em;
}

.crm-overflow__immutable .crm-overflow__immutable-last {
  margin-bottom: 0;
}

.crm-overflow__key {
  margin-bottom: 0.85em;
}

/* Row error code chip — the same string that appears in the import error CSV
   and the merge audit, so it is rendered as a literal token, never prose. */
.crm-errcode,
.crm-contacts-page .errcode {
  font-family: var(--w-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  font-size: 0.82em;
  background: var(--w-color-surface-field-inactive, #f6f6f8);
  border: 1px solid var(--w-color-grey-200, #929292);
  border-radius: 2px;
  padding: 0.05rem 0.35rem;
  white-space: nowrap;
}

.crm-overflow__detection,
.crm-overflow__resolved {
  font-size: 0.95em;
  color: var(--w-color-text-meta, #5c5c5c);
}

.crm-overflow__members {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 1rem;
}

.crm-overflow__members thead th {
  text-align: left;
  font-weight: 700;
  font-size: 0.82em;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  color: var(--w-color-text-context, #262626);
  vertical-align: bottom;
}

.crm-overflow__members td {
  padding: 0.7rem 0.6rem;
  vertical-align: top;
  border-bottom: 1px dashed var(--w-color-border-furniture, #e0e0e0);
}

.crm-overflow__footer {
  color: var(--w-color-text-meta, #5c5c5c);
  font-size: 0.95em;
}

/* Listing-column state labels. Colour is never the only channel — the words
   "Awaiting manual review" / "Resolved" carry the state on their own. */
.crm-overflow-state {
  font-weight: 600;
}

.crm-overflow-state--open {
  color: var(--w-color-text-context, #262626);
}

.crm-overflow-state--resolved {
  color: var(--w-color-text-meta, #5c5c5c);
  font-weight: 400;
}

/* =========================================================================
   MERGE REVERSAL  (S6 — the ADR-10 governed action)

   Colour is never the only channel here either: the immutable block, the
   state banner and the current-state row all carry a border, a symbol or
   a word in addition to their colour.
   ========================================================================= */

.crm-merge-reversal {
  /* Prose surface: a reading measure, not a full-bleed table page. */
  max-width: 52rem;
}

.crm-eyebrow {
  margin: 0 0 0.15rem;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--w-color-text-meta, #5c5c5c);
}

.crm-merge-reversal__id {
  display: inline-block;
  margin-left: 0.35rem;
  /* Long identifiers wrap rather than pushing the reading column wide. */
  overflow-wrap: anywhere;
  word-break: break-word;
}

.crm-merge-reversal__h2 {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 1.75rem 0 0.6rem;
}

/* -- the immutable block ------------------------------------------------ */
/* Heavy left rule + weight, so it reads as policy rather than as a tip,
   and survives greyscale. */
.crm-immutable {
  border: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  border-left: 5px solid var(--w-color-text-context, #262626);
  background: var(--w-color-surface-field-inactive, #f6f6f8);
  padding: 0.9rem 1rem;
  margin: 0 0 1.25rem;
}

.crm-immutable__head {
  margin: 0 0 0.4rem;
  font-weight: 800;
  font-size: 1rem;
  color: var(--w-color-text-context, #262626);
}

.crm-immutable__body {
  margin: 0;
  line-height: 1.55;
}

/* -- this merge's own state --------------------------------------------- */
.crm-reversal-status {
  border: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  border-left-width: 5px;
  padding: 0.75rem 0.9rem;
  margin: 0 0 1.25rem;
}

.crm-reversal-status--reversible {
  border-left-color: var(--w-color-secondary-600, #004345);
}

/* Refusals share a heavier left rule; the wording and the ✗ symbol, not the
   colour, say which refusal it is. */
.crm-reversal-status--reversed,
.crm-reversal-status--expired,
.crm-reversal-status--forfeited {
  border-left-color: var(--w-color-text-error, #ca3b3b);
  background: var(--w-color-surface-field-inactive, #f6f6f8);
}

.crm-reversal-status__head {
  margin: 0 0 0.3rem;
  font-weight: 700;
}

.crm-reversal-status__body {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.5;
}

.crm-reversal-symbol {
  margin-right: 0.35rem;
  font-weight: 700;
}

/* -- the four-states table ---------------------------------------------- */
.crm-reversal-states {
  width: 100%;
  margin-bottom: 0.75rem;
}

.crm-reversal-states__current td {
  background: var(--w-color-surface-field-inactive, #f6f6f8);
}

/* The word, not the shading, is what says "this one". */
.crm-reversal-states__marker {
  display: inline-block;
  margin-left: 0.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--w-color-text-context, #262626);
}

.crm-reversal-states__caveat {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.78rem;
  font-style: italic;
  color: var(--w-color-text-meta, #5c5c5c);
}

.crm-merge-reversal__retention {
  margin-bottom: 1.5rem;
}

/* -- the governed-action form ------------------------------------------- */
.crm-governed-action {
  border: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  border-radius: 3px;
  padding: 1rem 1.1rem 1.25rem;
  background: var(--w-color-surface-page, #ffffff);
}

.crm-governed-action__field {
  margin-bottom: 1.1rem;
}

.crm-governed-action__field input[type="text"],
.crm-governed-action__field select,
.crm-governed-action__field textarea {
  width: 100%;
  max-width: 36rem;
}

/* Required from first paint — visibly and programmatically. The asterisk
   is aria-hidden; the field carries aria-required="true". */
.crm-required-mark {
  color: var(--w-color-text-error, #ca3b3b);
  font-weight: 700;
  margin-left: 0.15rem;
}

.crm-governed-action .error-message {
  margin: 0.3rem 0 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--w-color-text-error, #ca3b3b);
}

.crm-governed-action__footer {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 1.25rem;
}

/* The serious button. Not the ordinary primary: this action moves live
 * relationships between two people's records.
 *
 * It carries NO colour of its own. The template gives it Wagtail 6.3's own
 * `serious` class, whose resting and hover colours are already
 * --w-color-text-error / --w-color-surface-button-critical-hover /
 * --w-color-text-button-critical-outline-hover — the three aliases that flip
 * correctly under .w-theme-dark. The previous bespoke version was a solid red
 * fill with a dead hover: resting and hover both read
 * `var(--w-color-text-error, …)` and differed only in a fallback that never
 * applies while Wagtail's core.css is loaded, so hovering changed nothing.
 *
 * All this class adds is weight and a minimum target size, which is met by the
 * padding rather than by the length of the label.
 */
.crm-button-serious {
  font-weight: 700;
  min-height: 2.25rem;
  padding-inline: 1.1rem;
}

@media (max-width: 49.9375em) {
  .crm-governed-action__footer {
    align-items: stretch;
    flex-direction: column;
  }
}

/* Tombstoned / Survivor / Merged / Stated reason, above the fold. */
.crm-merge-reversal__subject {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.2rem 0.9rem;
  margin: 0 0 1.25rem;
  font-size: 0.92rem;
}

.crm-merge-reversal__subject dt {
  font-weight: 700;
  color: var(--w-color-text-meta, #5c5c5c);
}

.crm-merge-reversal__subject dd {
  margin: 0;
  color: var(--w-color-text-context, #262626);
  /* Long identifiers wrap; the reading column never scrolls sideways. */
  overflow-wrap: anywhere;
}

@media (max-width: 30em) {
  .crm-merge-reversal__subject {
    grid-template-columns: 1fr;
  }

  .crm-merge-reversal__subject dd {
    margin-bottom: 0.4rem;
  }
}

/* =========================================================================
   S2 · CONTACT DETAIL SURFACE

   Addresses, consent, stage exclusion, import lineage, merge lineage.
   Stock Wagtail chrome throughout — these rules do layout and spacing only,
   and every chip, sentence and table reuses the classes declared above.
   ========================================================================= */

.crm-contact-detail {
  margin-top: 1.5rem;
}

.crm-contact-detail--before {
  margin-top: 0;
  margin-bottom: 1rem;
}

.crm-panel {
  margin: 0 0 1.75rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--w-color-border-furniture, #e0e0e0);
  border-radius: 3px;
  background-color: var(--w-color-surface-page, #ffffff);
}

.crm-panel > .h-section {
  margin-top: 0;
  margin-bottom: 0.75rem;
}

/* Read the values, not the grid: long identifiers and addresses wrap rather
   than pushing the primary reading column sideways. */
.crm-contact-table {
  width: 100%;
  table-layout: auto;
}

.crm-contact-table td,
.crm-contact-table th {
  vertical-align: top;
  overflow-wrap: anywhere;
}

.crm-contact-lookup-note {
  margin-top: 0.75rem;
  margin-bottom: 0;
}

.crm-contact-duplicates__list {
  margin: 0.5rem 0 0.75rem;
  padding-left: 1.1rem;
}

.crm-contact-duplicates__list li {
  margin-bottom: 0.4rem;
}

/* The stage exclusion. Deliberately not styled as an error: a contracted
   element held back by an unresolved precondition is a correct refusal, and
   presenting a correct refusal as a fault is its own failure mode. */
.crm-contact-excluded {
  margin: 0 0 0.6rem;
  padding: 0.6rem 0.75rem;
  border-left: 4px solid var(--w-color-grey-200, #929292);
  background-color: var(--w-color-surface-field-inactive, #f6f6f8);
  color: var(--w-color-text-context, #262626);
}

.crm-contact-lineage {
  margin: 0;
  padding-left: 1.1rem;
}

.crm-contact-lineage li {
  margin-bottom: 0.5rem;
}

.crm-contact-merged-away {
  margin: 0 0 0.75rem;
}

/* =========================================================================
   ORPHAN SUPPRESSION SECTION (contacts index)

   A first-class section, not a warning strip: the whole point of the row is
   that it is normal. Same table idiom as the listing above it.
   ========================================================================= */

.crm-orphan-suppressions {
  margin-top: 2rem;
  margin-bottom: 2rem;
}

.crm-orphan-suppressions > .h-section {
  margin-bottom: 0.75rem;
}

/* =========================================================================
   S8 · CSV IMPORT — MAPPING WIZARD

   Was four inline `style=` attributes, including two fixed max-widths and a
   flex action row, none of which could respond to a viewport.
   ========================================================================= */

.crm-import-mapping {
  max-width: 640px;
}

/* The mapping select must not force the table wider than the column. */
.crm-import-mapping select {
  width: 100%;
  max-width: 100%;
}

.crm-import-profile {
  max-width: 34rem;
}

.crm-import-actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
}

.crm-import-actions form {
  display: inline;
}

@media (max-width: 49.9375em) {
  .crm-import-actions {
    align-items: stretch;
    flex-direction: column;
  }
}

/* =========================================================================
   S9 · CSV IMPORT — REVIEW / RESULT

   Five plain figures. Deliberately not a segmented or stacked bar: these are
   counts that must be read and added up, not a shape.

   The figures previously carried per-figure colours as inline styles. Two
   problems, both measured: the amber "flagged" figure rendered at
   --w-color-warning-100 (#faa500), 2.01:1 against the page — a fail for large
   text, which needs 3:1 — and the inline fallbacks (#1a7a4b, #b04e00, #cd4444)
   were not the values their aliases actually resolve to, so the file
   documented one palette and rendered another. The approved prototype draws
   these figures with no colour at all; the labels beneath carry the meaning.
   ========================================================================= */

.crm-import-figures {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
}

.crm-import-figures__item {
  border: 1px solid var(--w-color-border-furniture-more-contrast, #929292);
  border-radius: 0.3125rem;
  padding: 0.7rem 0.8rem;
}

.crm-import-figures__value {
  display: block;
  font-size: 26px;
  font-weight: 800;
  line-height: 1.1;
  color: var(--w-color-text-context, #262626);
}

.crm-import-figures__label {
  display: block;
  font-size: 0.84em;
  color: var(--w-color-text-meta, #5c5c5c);
}

.crm-import-errors__row {
  width: 6rem;
}

.crm-import-errors__data {
  font-size: 0.8em;
  overflow-wrap: anywhere;
  word-break: break-all;
}

/* -------------------------------------------------------------------------
   "N rows you can fix here" — the inline correct-and-re-run block.

   Deliberately drawn as an ordinary listing table with inputs in it, not as a
   panel: it is the counterpart of the refused block below and the two must not
   look like variants of one thing. The refused block is a bounded statement
   with no control; this one is a form. Colour is not the channel that tells
   them apart — the heading and the presence or absence of a control is.
   ------------------------------------------------------------------------- */

.crm-import-fix__field + .crm-import-fix__field {
  margin-top: 0.6rem;
}

.crm-import-fix__label {
  display: block;
  font-size: 0.84em;
  color: var(--w-color-text-meta, #5c5c5c);
  margin-bottom: 0.15rem;
}

.crm-import-fix__table input[type="text"],
.crm-import-fix__table input[type="email"] {
  width: 100%;
  max-width: 26rem;
  /* 24×24 CSS-pixel minimum target, per the accessibility rules. */
  min-height: 1.5rem;
}

/* The correction column carries the widest content, so it takes the slack
   rather than letting the row number and the error code stretch. */
@media (min-width: 50em) {
  .crm-import-fix__table th:last-child,
  .crm-import-fix__table td:last-child {
    width: 40%;
  }
}

/* The refused block. It carries NO control of any kind: no override, no
   "import anyway", no clear-suppression link. The prohibition is enforced by
   the absence of a control, so the block is drawn as a bounded statement. */
.crm-contacts-page .refused {
  border: 2px solid var(--w-color-text-context, #262626);
  border-radius: 0.3125rem;
  padding: 1rem 1.1rem;
  margin: 0 0 1.2rem;
  background: var(--w-color-surface-page, #ffffff);
}

.crm-contacts-page .refused__row {
  border-left: 4px solid var(--w-color-border-furniture-more-contrast, #929292);
  padding-left: 1rem;
}

.crm-contacts-page .refused__row p {
  margin-bottom: 0.3rem;
}

.crm-contacts-page .refused__row p:last-child {
  margin-bottom: 0;
}

.crm-contacts-page .refused__addr {
  font-weight: 700;
  overflow-wrap: anywhere;
}

/* =========================================================================
   S8b · CSV IMPORT — MAPPING PROFILES

   Three surfaces that used to render a JSON object: the profile editor, the
   profile detail screen, and the profile chooser at step 1 of the wizard.
   None of them introduces a new visual language — they reuse the wizard's
   own two-column mapping table (.crm-import-mapping), the panel and lineage
   idioms from the contact detail surface (.crm-panel, .crm-contact-lineage),
   and .crm-reasons for the sentence under a value. Every colour is a Wagtail
   semantic alias with the stock light-theme value as its fallback, as
   everywhere else in this file.
   ========================================================================= */

/* The guided editor. Same width and select behaviour as the wizard's table,
   because it is the same task. */
.crm-mapping-editor {
  max-width: 640px;
  width: 100%;
}

.crm-mapping-editor input[type="text"],
.crm-mapping-editor select {
  width: 100%;
  max-width: 100%;
}

/* A target the profile names that this system no longer has. It is rendered
   as a selected-but-disabled option so the operator can read what was stored
   before replacing it; the muted treatment says it is not a choice. */
.crm-mapping-editor option:disabled {
  color: var(--w-color-text-meta, #5c5c5c);
  font-style: italic;
}

.crm-mapping-editor__help {
  max-width: 640px;
  margin-top: 0.5rem;
}

/* The profile chooser at step 1 — the table an operator actually picks from. */
.crm-profile-choices {
  max-width: 46rem;
}

.crm-profile-choices__stale {
  color: var(--w-color-text-context, #262626);
  font-weight: 600;
}

/* What a chosen profile did to the uploaded file, stated at step 2 before
   anything is imported. Bulleted rather than prose: each line is one part of
   the profile that could not be applied, and they are counted above. */
.crm-import-assessment__list {
  margin: 0.25rem 0 0.75rem;
  padding-left: 1.1rem;
}

.crm-import-assessment__list li {
  margin-bottom: 0.35rem;
}

/* The opt-in save block. The checkbox and its words are one target, and the
   two controls that say *where* to save sit indented beneath it so their
   dependence on it is structural rather than only stated. Nothing is disabled
   by script — the server decides, and a name typed with the box unticked is
   simply not used. */
.crm-import-profile__toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  font-weight: 600;
  cursor: pointer;
}

.crm-import-profile__toggle input[type="checkbox"] {
  flex: none;
  width: 1rem;
  height: 1rem;
  margin: 0;
}

.crm-import-profile__where {
  padding-left: 1rem;
  border-left: 3px solid var(--w-color-border-furniture, #e0e0e0);
}

/* =========================================================================
   S8c · IMPORT PROFILE — DETAIL

   The mapping table lists every target field, including the ones nothing
   feeds. A row that needs attention is distinguished by a rule and a weight
   as well as by its explanatory sentence, so it survives greyscale — colour
   is never the only channel on these surfaces.
   ========================================================================= */

.crm-profile__mapping-summary {
  margin-bottom: 0.75rem;
}

.crm-profile__table {
  margin-bottom: 0.75rem;
}

.crm-profile__row--unmapped td:first-child {
  color: var(--w-color-text-meta, #5c5c5c);
}

.crm-profile__row--unknown,
.crm-profile__row--protected,
.crm-profile__row--duplicate {
  border-left: 4px solid var(--w-color-text-context, #262626);
}

.crm-profile__row--unknown td:first-child,
.crm-profile__row--protected td:first-child,
.crm-profile__row--duplicate td:first-child {
  font-weight: 600;
}

.crm-profile__problem-list {
  margin: 0.25rem 0 0;
  padding-left: 1.1rem;
}

.crm-profile__problem-list li {
  margin-bottom: 0.35rem;
}

.crm-profile__imports {
  margin-top: 0.9rem;
}
