/*
 * CommonLynk — Component Classes
 * Reusable UI primitives that consume the design tokens in
 * commonlynk.tokens.css. Load AFTER the tokens file.
 *
 * Always prefer these classes over bespoke per-page button/badge/card CSS so
 * the whole platform stays visually consistent. New variants belong here, not
 * in template <style> blocks.
 */

/* ── Buttons ──────────────────────────────────────────── */

.cl-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: var(--cl-btn-padding-y) var(--cl-btn-padding-x);
  font-size: var(--cl-btn-font-size);
  font-weight: var(--cl-btn-font-weight);
  font-family: var(--cl-font-sans);
  line-height: 1.4;
  border-radius: var(--cl-btn-radius);
  border: none;
  /* A .cl-btn with no variant reads as a quiet secondary, never the browser's
     grey button face (D1) — the variants below set their own fill. */
  background: var(--cl-white);
  color: var(--cl-ink);
  cursor: pointer;
  text-decoration: none;
  transition: var(--cl-btn-transition);
  white-space: nowrap;
}
/* `hidden` means hidden (D1, Build 5). `.cl-btn` sets `display`, which beats
   the browser's own `[hidden] { display: none }` — so a dialog button a script
   had hidden (the LynkView confirm's empty alternative, the shared dialog's
   Cancel under clModal.notice, a Confirm with nothing to confirm) still drew. */
.cl-btn[hidden] { display: none !important; }
.cl-btn:disabled,
.cl-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* Variants and sizes: the BEM names below (`.cl-btn--primary`, `--sm`…) are
   the ONLY button vocabulary (D1, Build 5). The single-dash aliases this
   block used to define are gone: the single-dash "secondary" was not an alias at all
   but the retired TEAL, so a "secondary" button rendered in a colour the
   design system had dropped. `core.tests_design_guard` refuses a single-dash
   button class anywhere in the tree. */

/* Outline danger — quiet until hover; used for Suspend/Delete actions that
   shouldn't shout in their resting state (was the bespoke admin .btn-danger). */
.cl-btn--danger-outline { background: var(--cl-white); color: var(--cl-danger); border: 1px solid var(--cl-border); }
.cl-btn--danger-outline:hover { background: var(--cl-danger); color: var(--cl-white); border-color: var(--cl-danger); }

.cl-btn--muted     { background: var(--cl-border);  color: var(--cl-muted); }

/* ── Design conformance at the source (design system §10, Build 3) ───────
   Defaults every product page inherits, each with ZERO specificity (:where)
   or an element selector, so any component rule still wins:
   - form controls use the product font and ink (D1, D6) — the browser's
     Arial and black were on every unstyled button and field;
   - checkboxes and radios select in INK, never the browser's blue (D11,
     §4.3, §5.7);
   - a bare link in page content is ink, underlined on hover only, :visited
     included (D5, §5.11.4); a link inside running text keeps its underline,
     which is what tells it apart from the words around it (WCAG 1.4.1). */
button, input, select, textarea { font-family: inherit; }
button { color: inherit; font-size: inherit; }
input, select, textarea { color: var(--cl-ink); }
/* The workspace's body text is 14 px (design system §4.4, D6): the shell set no
   size, so every unstyled paragraph, list item and label rendered at the
   browser's 16 px — off the type scale. */
#cl-main { font-size: var(--cl-fs-body); }
input[type="checkbox"], input[type="radio"] { accent-color: var(--cl-ink); }
:where(#cl-main, .content) a { color: var(--cl-ink); text-decoration: none; }
:where(#cl-main, .content) a:hover { text-decoration: underline; }
:where(#cl-main, .content) :where(p, li > p, .cl-prose) a { text-decoration: underline; }

/* ── Badges ───────────────────────────────────────────── */

.cl-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.2em 0.65em;
  font-size: var(--cl-fs-small);   /* on the type scale (D6); was 0.78rem = 12.48px */
  font-weight: 600;
  border-radius: var(--cl-radius-badge);
  line-height: 1.4;
  white-space: nowrap;
}
.cl-badge-success  { background: var(--cl-teal-bg);    color: var(--cl-teal-dark); }
.cl-badge-warning  { background: var(--cl-warning-bg); color: var(--cl-warning); }
.cl-badge-danger   { background: var(--cl-danger-bg);  color: var(--cl-danger); }
.cl-badge-info     { background: var(--cl-info-bg);    color: var(--cl-info); }
/* Neutral pairs (§5.3, D8): muted on the paper tint; a category on --cl-warm. */
.cl-badge-muted    { background: var(--cl-paper);      color: var(--cl-muted); }
.cl-badge-accent   { background: var(--cl-warm);       color: var(--cl-ink); }
.cl-badge-teal     { background: var(--cl-teal-bg);    color: var(--cl-teal-dark); }  /* same as success but explicit */
.cl-badge-gold     { background: var(--cl-warn-bg);     color: var(--cl-warn-text); }
.cl-badge-linked   { background: var(--cl-info-bg);    color: var(--cl-info); }
.cl-badge-unlinked { background: var(--cl-paper);      color: var(--cl-muted); }
.cl-badge-solid    { background: var(--cl-ink);        color: var(--cl-white); }
.cl-badge-outline  { background: transparent;          color: var(--cl-ink); border: 1px solid var(--cl-ink); }

/* ── Cards ────────────────────────────────────────────── */

.cl-card {
  background: var(--cl-white);
  border-radius: var(--cl-radius-card);
  border: 1px solid var(--cl-border);
  box-shadow: var(--cl-shadow-sm);
  padding: var(--cl-space-card);   /* D1 density: 18px, 12px compact */
}

/* ── Responsive Table Wrapper ─────────────────────────── */
.cl-table-wrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--cl-radius-md);
  border: 1px solid var(--cl-border);
}
/* WCAG 2.1.1 (§4j rule 1): a horizontally scrollable table must be reachable and
   scrollable by keyboard. shell.js adds tabindex="0" + role="region" + a label to
   any .cl-table-wrap that actually overflows; this gives it a visible focus ring. */
.cl-table-wrap:focus-visible,
.table-wrap:focus-visible {
  outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring);
  outline-offset: 2px;
}

/* ── The page's ONE top-bar primary (Build 3 Stage 0f; token v4, owner 2026-10-18) ──
   Drawn only by _partials/cl_page_action.html ({% cl_page_action %}), so it is
   the same control on every page of every module. Token v4: it DRAWS 32 px
   tall, 13/500, centred in the top bar — lighter than the 44 px block it was —
   while its TAP area stays 44 x 44 (§4e, WCAG 2.5.8): an invisible ::after,
   centred on it, max(its size, 44 px) each way. It is left out of the
   coarse-pointer min-height below for that reason: it never DRAWS 44 px. The label ellipsis lives on
   the inner span, because overflow:hidden on the link would clip that hit
   area. The ⚙ page-menu trigger is the same 32 drawn / 44 hit
   (.lv-iconbtn / .cl-pagemenu__trigger); ui_conformance measures all three. */
.cl-topbar-add {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  box-sizing: border-box; height: 32px; min-width: 32px; padding-block: 0; padding-inline: 12px;
  font-size: var(--cl-fs-control); font-weight: var(--cl-fw-medium);
  line-height: 1.2; white-space: nowrap; max-width: 100%;
}
/* The hit area: the shape the coarse-pointer block below uses for every small
   control, centred on the control and at least 44 x 44 — at EVERY pointer. */
.cl-topbar-add::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%);
}
.cl-topbar-add__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* A section heading inside a page body (an <h2> under the page's single <h1>). */
.cl-section-title { margin: 28px 0 8px; font-size: var(--cl-fs-h3); font-weight: var(--cl-fw-semibold); color: var(--cl-ink); }

/* ── ImportView modal (design system §5.12; moved here from
   templates/core/imports/_modal.html, Build 3 — S2) ─────────────────── */
  .cl-import-modal { position:fixed; inset:0; z-index:1000; display:flex;
                     align-items:center; justify-content:center;
                     background:rgba(var(--cl-ink-rgb), .55); }
  .cl-import-modal[hidden] { display:none; }
  .cl-import-modal [hidden] { display:none; }
  .cl-import-modal__panel { background:var(--cl-white); border-radius:14px; padding:28px;
                            width:min(660px, 92vw); max-height:90vh; overflow-y:auto;
                            box-shadow:0 20px 60px rgba(var(--cl-ink-rgb), .35); }
  .cl-import-modal__title { margin:0 0 8px; font-size:var(--cl-fs-h3); font-weight:700; color:var(--cl-ink); }
  .cl-import-modal__lead { font-size:13px; color:var(--cl-muted); margin:0 0 18px; }
  .cl-import-modal__link, .cl-import-modal__link:visited { color:var(--cl-ink); text-decoration:underline; }
  .cl-import-modal__warning { border-radius:8px; padding:12px 14px; margin-bottom:18px;
                              font-size:12px; color:var(--cl-ink);
                              background:var(--cl-warning-bg);
                              border:1px solid var(--cl-border); }
  .cl-import-modal__error { border-radius:8px; padding:12px 14px; margin-bottom:18px;
                            font-size:13px; color:var(--cl-danger);
                            background:var(--cl-danger-bg);
                            border:1px solid var(--cl-danger); }
  .cl-import-modal__file { width:100%; margin-bottom:16px; font-size:13px; }
  .cl-import-modal__option { display:flex; gap:8px; align-items:flex-start; font-size:13px; color:var(--cl-ink); margin:0 0 4px; }
  .cl-import-modal__option-help { font-size:12px; color:var(--cl-muted); margin:0 0 16px 24px; }
  .cl-import-modal__actions { display:flex; gap:10px; justify-content:flex-end; flex-wrap:wrap; }
  .cl-import-modal__prep { position:static; transform:none; inset:auto;
                           min-width:0; max-width:100%; margin-bottom:16px; }

  .cl-import-tally { display:flex; flex-wrap:wrap; gap:10px; margin-bottom:18px; }
  .cl-import-tally__item { font-size:13px; font-weight:600; border-radius:8px;
                           padding:8px 12px; border:1px solid var(--cl-border); }
  .cl-import-tally__item--ok   { color:var(--cl-teal-dark); background:var(--cl-teal-bg); }
  .cl-import-tally__item--warn { color:var(--cl-warning);   background:var(--cl-warning-bg); }
  .cl-import-tally__item--bad  { color:var(--cl-danger);    background:var(--cl-danger-bg); }

  .cl-import-rows { border:1px solid var(--cl-border); border-radius:8px;
                    margin-bottom:18px; max-height:260px; overflow:auto; }
  .cl-import-rows__table { width:100%; border-collapse:collapse; font-size:12px; }
  .cl-import-rows__table th, .cl-import-rows__table td { text-align:start; padding:8px 10px;
                                                         border-block-end:1px solid var(--cl-border);
                                                         vertical-align:top; }
  .cl-import-rows__table th { color:var(--cl-muted); font-weight:600; white-space:nowrap;
                              position:sticky; inset-block-start:0; background:var(--cl-white); }
  .cl-import-rows__table td { color:var(--cl-ink); }
  .cl-import-rows__outcome--skipped { color:var(--cl-warning); font-weight:600; }
  .cl-import-rows__outcome--failed  { color:var(--cl-danger);  font-weight:600; }
  .cl-import-rows__more { margin:0; padding:8px 10px; font-size:12px; color:var(--cl-muted); }

  @media (max-width: 480px) {
    .cl-import-modal__panel { padding:20px; }
    .cl-import-modal__actions .cl-btn { flex:1 1 auto; }
  }

/* ── Report table (design system §5.5 + §5.11.4) ─────────────────────────
   A cross-tab of records × periods (the IPTT and every report like it). Lives
   inside the shared .cl-table-wrap, which scrolls it on both axes; the header
   rows and the first column stay put while it scrolls. Mark the wrapper
   `data-cl-report-table` so the conformance check (ui_conformance --design)
   finds it.
   - header: muted small labels on the paper tint, a hairline under them; an
     optional period GROUP row (th scope="colgroup") above Target / Actual / %;
   - NO navy fill anywhere — not the header, not the first column;
   - first column sticky on white: the name in ink, code · level · unit muted
     below (.cl-report-table__name / __meta);
   - numbers at the END (.is-num), through the unit filter; "N/A" when empty;
   - links ink, underlined on hover only — :visited too. */
.cl-report-wrap { max-height: 70vh; overflow: auto; background: var(--cl-white); }
.cl-report-table { border-collapse: separate; border-spacing: 0; width: 100%; font-size: var(--cl-fs-body); color: var(--cl-ink); }
.cl-report-table thead th {
  position: sticky; top: 0; z-index: 2;
  padding: 8px 12px; text-align: start; white-space: nowrap;
  font-size: var(--cl-fs-small); font-weight: var(--cl-fw-medium); color: var(--cl-muted);
  background: var(--cl-paper); border-block-end: 1px solid var(--cl-border);
}
.cl-report-table thead tr + tr th { top: var(--cl-report-head-row, 37px); }
.cl-report-table thead th[scope="colgroup"] { text-align: center; border-inline-start: 1px solid var(--cl-border); }
.cl-report-table thead th.is-group-start { border-inline-start: 1px solid var(--cl-border); }
.cl-report-table td { padding: 8px 12px; white-space: nowrap; border-block-end: 1px solid var(--cl-border); background: var(--cl-white); }
.cl-report-table td.is-group-start { border-inline-start: 1px solid var(--cl-border); }
.cl-report-table .is-num { text-align: end; font-variant-numeric: tabular-nums; }
.cl-report-table tbody tr > :first-child {
  position: sticky; inset-inline-start: 0; z-index: 1;
  min-width: 240px; white-space: normal; text-align: start; background: var(--cl-white);
}
.cl-report-table thead tr:first-child > th:first-child { inset-inline-start: 0; z-index: 3; }
.cl-report-table tbody th { padding: 8px 12px; font-weight: var(--cl-fw-regular); border-block-end: 1px solid var(--cl-border); vertical-align: top; }
.cl-report-table__name { color: var(--cl-ink); font-weight: var(--cl-fw-medium); }
/* Build 6 (§5.11.8): a report table with row actions pins them at the END
   edge, as a LynkView does; its first column stays pinned at the start. */
.cl-report-table .cl-row-actions-cell { position: sticky; inset-inline-end: 0; z-index: 1; background: var(--cl-white); box-shadow: var(--cl-shadow-pin-end); }
.cl-report-table thead tr:first-child > th.cl-row-actions-cell { inset-inline-end: 0; z-index: 3; background: var(--cl-paper); }
/* The SUMMARY table (§5.11.6): the report table's rules on a small table of
   records inside a page — no max-height scroll box, no 240 px first column. */
.cl-summary-wrap { overflow-x: auto; background: var(--cl-white); border: 1px solid var(--cl-border); border-radius: var(--cl-radius-md); }
.cl-summary-table tbody tr > :first-child { min-width: 0; }
/* A second line inside a table cell (a phone under a name, a record's type
   under its label, who invited a pending account) — LynkView rows and the
   summary table alike (Build 4). */
.cl-cell-sub { margin-top: 2px; font-size: 12px; color: var(--cl-muted); }
.cl-summary-table tbody tr:last-child > td { border-block-end: 0; }
/* The summary table's "nothing to show" row: a table CELL, so never the
   flex empty-state component (.cl-empty), which broke its colspan (Build 5). */
.cl-summary__empty { padding: 1.25rem 12px; text-align: center; color: var(--cl-muted); white-space: normal; }
.cl-summary-table a, .cl-summary-table a:visited { color: var(--cl-ink); text-decoration: none; }
.cl-summary-table a:hover, .cl-summary-table a:focus-visible { text-decoration: underline; }
.cl-report-table__toggle {
  display: inline-flex; align-items: center; min-height: 44px; margin-top: 2px; padding: 0;
  border: 0; background: none; font: inherit; font-size: var(--cl-fs-small); color: var(--cl-ink);
  text-decoration: underline; cursor: pointer;
}
.cl-report-table__toggle:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; }
.cl-report-legend { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 0; padding: 0; list-style: none; }
.cl-report-table__meta { margin-top: 2px; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-report-table__sub > :first-child { padding-inline-start: 28px; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-report-table a, .cl-report-table a:visited { color: var(--cl-ink); text-decoration: none; }
.cl-report-table a:hover, .cl-report-table a:focus-visible { text-decoration: underline; }

/* Skip-to-content link (§4j rule 1): hidden with the clip technique (NOT
   left:-9999px, which pushes a box off-canvas and can create horizontal overflow
   / a stray scroll offset). On focus it becomes a real top-left (top-right in RTL)
   button so a keyboard user jumps past the sidebar. */
.cl-skip-link {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap;
  z-index: 10000;
  background: var(--cl-ink);
  color: var(--cl-white);
  border-radius: 0 0 var(--cl-radius-md) 0;
  font-weight: var(--cl-fw-semibold);
  text-decoration: none;
}
.cl-skip-link:focus,
.cl-skip-link:focus-visible {
  width: auto; height: auto; margin: 0; padding: 10px 16px;
  overflow: visible; clip: auto; clip-path: none;
  left: 0; top: 0;
  outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring);
  outline-offset: 2px;
}
html[dir="rtl"] .cl-skip-link:focus,
html[dir="rtl"] .cl-skip-link:focus-visible { left: auto; right: 0; border-radius: 0 0 0 var(--cl-radius-md); }
/* A <main> given tabindex="-1" (so the skip link can move focus to it) must not
   show a focus ring — it is a programmatic target, not an interactive control. */
main:focus { outline: none; }

/* Screen-reader-only utility (shared; support.css has its own scoped copy). */
.cl-sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* Legacy `.table-wrap` (used widely on tenant pages and Platform Admin pages
   that extend superadmin/base.html, where it was never defined). Borderless so
   it doesn't double up when nested inside a .card. Gives every existing wrapped
   table horizontal scroll on narrow screens. */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ── Responsive Grid Helpers ──────────────────────────── */
/* Tracks are minmax(0, 1fr), never bare 1fr: a bare `1fr` track cannot shrink
   below its content's min-content width, so one wide table or long word in a
   column pushed the whole grid past the screen (REM-364). Use these instead of
   an inline `style="grid-template-columns:…"`, which no stylesheet can
   override at phone width (REM-363). */
.cl-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
.cl-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
.cl-grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem; }

@media (max-width: 768px) {
  .cl-grid-2 { grid-template-columns: minmax(0, 1fr); }
  .cl-grid-3 { grid-template-columns: minmax(0, 1fr); }
  .cl-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .cl-grid-4 { grid-template-columns: minmax(0, 1fr); }
}

/* ── Responsive Form Rows ─────────────────────────────── */
.cl-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; }

/* ── Stack / split utilities ──────────────────────────── */
.cl-stack { display: flex; flex-direction: column; gap: 1rem; }
/* A list of choices (cl-option rows) that read as one group (MC4). */
.cl-stack--tight { gap: 0.4rem; }
.cl-split { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem; }
/* A row of buttons under a page's text (a confirmation's Archive · Cancel). */
.cl-button-row { display: flex; align-items: center; flex-wrap: wrap; gap: 0.75rem; margin-block-start: 1rem; }
.cl-button-row form { margin: 0; }

/* ── Hide/show ────────────────────────────────────────── */
@media (max-width: 768px) {
  .cl-hide-mobile { display: none !important; }
}
@media (min-width: 769px) {
  .cl-hide-desktop { display: none !important; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   DESIGN SYSTEM v2 (2026-08-27)
   ───────────────────────────────────────────────────────────────────────────
   Everything above this line predates the design system. This block ADDS the
   system's vocabulary.

   Naming: BEM (`.cl-btn--primary`) and nothing else. Until Build 5
   (2026-10-20) the single-dash form was kept as an "equal-weight alias
   forever" — but the secondary one never was an alias: it painted the retired
   teal, which is how the shared confirm dialog's Cancel shipped in it (D1).
   The rename was finished in one commit, tree-wide, and is guard-enforced.

   Colour rule: this file may name a colour only as var(--cl-*),
   rgba(var(--cl-*-rgb), …) or color-mix() over those. A raw hex here is the
   same defect the deploy guard fails templates for — it just isn't scanned,
   which makes it MORE important to hold the line by hand.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ── Buttons — the five roles ──────────────────────────────────────────────
   primary   navy, white text   the one affirmative action on a light ground
                                (Add, Save, Sign up, Get Started, Continue)
   secondary white, hairline    the alternative to primary; sits beside it
   danger    red                destructive, and only destructive
   accent    gold               accent emphasis on a light ground
   on-navy   gold / white       the primary action ON a navy surface, where a
                                navy button would vanish
   Sentence case. A line icon is fine; an emoji is not (guard-enforced). */

/* The hairline a variant-less .cl-btn needs to read as a button (every
   variant draws its own edge). */
.cl-btn:not(.cl-btn--primary):not(.cl-btn--secondary):not(.cl-btn--ghost):not(.cl-btn--danger):not(.cl-btn--accent):not(.cl-btn--on-navy):not(.cl-btn--on-navy-quiet):not(.cl-btn--danger-outline):not(.cl-btn--muted) {
  box-shadow: inset 0 0 0 1px var(--cl-border);
}

.cl-btn--primary { background: var(--cl-btn-primary); color: var(--cl-btn-text); border: 1px solid transparent; }
.cl-btn--primary:hover { background: color-mix(in srgb, var(--cl-btn-primary) 85%, var(--cl-btn-text)); }

/* The alternative action. White ground + hairline — which is exactly what
   `.cl-btn--ghost` already renders, so the two are one rule, not two looks. */
.cl-btn--secondary,
.cl-btn--ghost {
  background: var(--cl-white);
  color: var(--cl-ink);
  border: 1px solid var(--cl-border);
}
.cl-btn--secondary:hover,
.cl-btn--ghost:hover { background: var(--cl-paper); border-color: color-mix(in srgb, var(--cl-ink) 22%, transparent); }

.cl-btn--danger { background: var(--cl-danger); color: var(--cl-white); border: 1px solid transparent; }
.cl-btn--danger:hover { background: color-mix(in srgb, var(--cl-danger) 86%, var(--cl-ink)); }

.cl-btn--accent { background: var(--cl-accent); color: var(--cl-ink); border: 1px solid transparent; }
.cl-btn--accent:hover { background: var(--cl-accent-deep); color: var(--cl-white); }

/* The LABELLED face of the row-action dropdown — the import menu
   (`{% cl_import_menu %}` → `{% cl_kebab label labelled %}`). Same shell,
   same cl_menu.js behaviour; the trigger is drawn as a secondary button
   carrying its label instead of the `⋮` glyph. Declared here, after the
   tokens file, so the button rules win over `.cl-actions-btn`'s bare-icon
   defaults on the properties both set. */
.cl-row-actions--labelled { display: inline-flex; vertical-align: middle; }
.cl-actions-btn--labelled { font-size: var(--cl-btn-font-size); line-height: 1.4; }
.cl-actions-caret { margin-inline-start: 0.35em; font-size: 0.8em; opacity: 0.8; }
.cl-import-menu { display: inline-flex; }

/* On a navy surface (the sidebar, a navy hero, a navy card). Gold fill, ink
   text — the inversion of --primary, and the ONLY other place gold carries an
   action. */
.cl-btn--on-navy { background: var(--cl-accent); color: var(--cl-on-gold); border: 1px solid transparent; }
.cl-btn--on-navy:hover { background: color-mix(in srgb, var(--cl-accent) 84%, var(--cl-white)); }
/* Quiet variant of the same, for a secondary action on navy. */
.cl-btn--on-navy-quiet {
  background: transparent;
  color: var(--cl-on-surface);
  border: 1px solid rgba(var(--cl-on-surface-rgb), 0.32);
}
.cl-btn--on-navy-quiet:hover { background: rgba(var(--cl-on-surface-rgb), 0.10); border-color: rgba(var(--cl-on-surface-rgb), 0.5); }

/* Size aliases in the BEM form. */
.cl-btn--sm { padding: var(--cl-btn-padding-y-sm) var(--cl-btn-padding-x-sm); font-size: var(--cl-btn-font-size-sm); }
.cl-btn--lg { padding: var(--cl-btn-padding-y-lg) var(--cl-btn-padding-x-lg); font-size: 1rem; }
.cl-btn--block { width: 100%; justify-content: center; }

/* Keyboard operators must be able to see which control they are on. */
/* A white gap, then the ink ring (token v4): ink drawn straight against a navy
   primary would vanish into it, so the ring always sits on its own ground. */
.cl-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--cl-white), 0 0 0 calc(2px + var(--cl-focus-ring-width)) var(--cl-focus-ring); }

/* A line icon inside a button inherits the text colour and never grows. */
.cl-btn > svg { width: 1em; height: 1em; flex: none; stroke: currentColor; fill: none; }


/* ── Pills — semantic status ───────────────────────────────────────────────
   Distinct from `.cl-badge` above (which carries a dozen ad-hoc variants).
   `.cl-pill` is the SEMANTIC set only: five meanings, five looks, no more. */

.cl-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.2em 0.7em;
  font-size: var(--cl-fs-small);
  font-weight: var(--cl-fw-semibold);
  line-height: 1.5;
  border-radius: var(--cl-radius-badge);
  white-space: nowrap;
}
.cl-pill--success { background: var(--cl-teal-bg);    color: var(--cl-teal-dark); }
.cl-pill--info    { background: var(--cl-info-bg);    color: var(--cl-info); }
.cl-pill--warning { background: var(--cl-warning-bg); color: var(--cl-warning); }
.cl-pill--danger  { background: var(--cl-danger-bg);  color: var(--cl-danger); }
.cl-pill--neutral { background: var(--cl-paper);      color: var(--cl-muted); border: 1px solid var(--cl-border); }
/* A CATEGORY value (sector, level, method, type) — neutral, never a status
   colour and never blue (design system §5.3, §5.11.4). */
.cl-pill--category { background: var(--cl-warm); color: var(--cl-ink); }
/* A leading dot reads as a status light without any colour-only meaning. */
.cl-pill__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }


/* ── Stat ─────────────────────────────────────────────────────────────────
   Uppercase muted label over a large ink number. The label is tracked out
   (--cl-track-label) so it reads as a field name, not a heading. */

.cl-stat {
  background: var(--cl-white);
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-card);
  padding: 1.1rem 1.25rem;
}
.cl-stat__label {
  font-size: var(--cl-fs-label);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: var(--cl-track-label);
  text-transform: uppercase;
  color: var(--cl-muted);
  margin-bottom: 0.5rem;
}
.cl-stat__value {
  /* A figure (D1): Inter Tight in every language, semibold, tracked in. */
  font-family: var(--cl-font-figure);
  font-size: var(--cl-fs-h1);
  font-weight: var(--cl-fw-figure);
  letter-spacing: var(--cl-track-figure);
  color: var(--cl-ink);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.cl-stat__sub { margin-top: 0.35rem; font-size: var(--cl-fs-small); color: var(--cl-text-2); }
/* Accent rule on the inline-start edge, for the one stat that leads. */
.cl-stat--accent { border-inline-start: 3px solid var(--cl-accent); }


/* ── Card chrome ──────────────────────────────────────────────────────────
   `.cl-card` itself is defined above. These are its parts. */

.cl-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: calc(-1 * var(--cl-space-card)) calc(-1 * var(--cl-space-card)) 1.25rem;
  padding: 1rem var(--cl-space-card);
  border-bottom: 1px solid var(--cl-border);
}
.cl-card__title {
  font-size: var(--cl-fs-h2);
  font-weight: var(--cl-fw-medium);
  letter-spacing: var(--cl-track-heading);
  color: var(--cl-ink);
  margin: 0;
}
.cl-card__flush { margin: 0 calc(-1 * var(--cl-space-card)) calc(-1 * var(--cl-space-card)); }


/* ── Table ────────────────────────────────────────────────────────────────
   Uppercase muted header, hairline rows, paper hover. Row actions use the
   EXISTING `.cl-row-actions` / `.cl-actions-*` dropdown from the tokens file —
   there is deliberately no second kebab component. */

.cl-table { width: 100%; border-collapse: collapse; font-size: var(--cl-fs-body); }
.cl-table thead th {
  text-align: start;
  padding: 0.7rem 0.9rem;
  font-size: var(--cl-fs-label);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: var(--cl-track-label);
  text-transform: uppercase;
  color: var(--cl-muted);
  border-bottom: 1px solid var(--cl-border);
  white-space: nowrap;
}
.cl-table tbody td {
  /* D1 density: the row is --cl-row-h tall (44px; 36px compact, fine pointer). */
  height: var(--cl-row-h);
  padding: calc((var(--cl-row-h) - 20px) / 2) 0.9rem;
  border-bottom: 1px solid var(--cl-border);
  color: var(--cl-ink);
  vertical-align: middle;
}
.cl-table tbody tr:last-child td { border-bottom: none; }
.cl-table tbody tr:hover { background: var(--cl-paper); }
.cl-table__num { text-align: end; font-variant-numeric: tabular-nums; }
/* The action column hugs the inline-end edge and never wraps. */
.cl-table__actions { width: 1%; white-space: nowrap; text-align: end; }


/* ── Avatar ───────────────────────────────────────────────────────────────
   Initials on warm gold. Used in the sidebar footer and beside a person's
   name in a list. */

.cl-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 50%;
  background: var(--cl-accent);
  color: var(--cl-on-gold);
  font-size: var(--cl-fs-small);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  user-select: none;
}
.cl-avatar--sm { width: 24px; height: 24px; font-size: 12px; }
.cl-avatar--lg { width: 44px; height: 44px; font-size: var(--cl-fs-body); }
/* On the navy rail the gold disc needs no border; on paper it does. */
.cl-avatar--on-paper { box-shadow: 0 0 0 1px rgba(var(--cl-ink-rgb), 0.08); }
.cl-avatar--xl { width: 88px; height: 88px; font-size: var(--cl-fs-h1); font-weight: var(--cl-fw-medium); }
/* Squircle, per the 2026 shape review — brand tiles and record avatars. */
.cl-avatar--square { border-radius: var(--cl-radius-lg); }
/* Gold is the CURRENT USER (design system 5.6). A record gets a quiet warm
   tint instead, so a 25-row list is not a wall of accent colour. */
.cl-avatar--record { background: var(--cl-paper); color: var(--cl-ink); box-shadow: inset 0 0 0 1px var(--cl-border); }


/* ── Form controls ────────────────────────────────────────────────────────
   Accent focus ring, ink text, hairline border. Never blue: the browser
   default focus/selected blue is the single most common way a page stops
   looking like CommonLynk. */

.cl-label {
  display: block;
  font-size: var(--cl-fs-label);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: var(--cl-track-label);
  text-transform: uppercase;
  color: var(--cl-muted);
  margin-bottom: 0.4rem;
}
.cl-label__required { color: var(--cl-danger); margin-inline-start: 2px; }

/* Form FIELD label — the text that sits directly above an input.
   Distinct from `.cl-label` above, which is the uppercase tracked EYEBROW
   (10px / 0.18em): correct over a section or a stat, far too small for a field
   a user has to read and fill. Using the eyebrow token on a field label is what
   made the phone widget's Arabic labels (`هاتف`, `هاتف بديل`) render visibly
   smaller and lighter than every other label on the same form — at 10px an
   Arabic face loses its diacritics and simply reads as a different font.
   Matches the 13px / 600 / ink convention the tenant registration forms already
   use inline; new form markup should use this class instead of repeating it. */
.cl-field-label {
  display: block;
  font-size: var(--cl-fs-field-label);
  font-weight: var(--cl-fw-semibold);
  color: var(--cl-ink);
  margin-bottom: 6px;
  letter-spacing: normal;
  text-transform: none;
}
.cl-field-label__required { color: var(--cl-danger); margin-inline-start: 2px; }

.cl-input, .cl-select, .cl-textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 0.55rem 0.75rem;
  font-family: var(--cl-font-sans);
  font-size: var(--cl-fs-body);
  color: var(--cl-ink);
  background: var(--cl-white);
  /* D1: a control's edge must reach 3:1 (WCAG 1.4.11) — --cl-border is decorative. */
  border: 1px solid var(--cl-control-border);
  border-radius: var(--cl-btn-radius);
  transition: border-color var(--cl-transition-fast), box-shadow var(--cl-transition-fast);
}
.cl-input, .cl-select { min-height: var(--cl-control-h); }
.cl-textarea { min-height: 96px; resize: vertical; }
.cl-select { appearance: auto; }
.cl-input::placeholder, .cl-textarea::placeholder { color: var(--cl-muted); }
.cl-input:focus, .cl-select:focus, .cl-textarea:focus {
  outline: none;
  border-color: var(--cl-accent);
  box-shadow: 0 0 0 var(--cl-focus-ring-width) var(--cl-focus-ring);
}
.cl-input:disabled, .cl-select:disabled, .cl-textarea:disabled {
  background: var(--cl-paper);
  color: var(--cl-muted);
  cursor: not-allowed;
}
.cl-input--error, .cl-select--error, .cl-textarea--error { border-color: var(--cl-danger); }
.cl-field { margin-bottom: 1.1rem; }
.cl-field__hint  { margin-top: 0.35rem; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-field__error { margin-top: 0.35rem; font-size: var(--cl-fs-small); color: var(--cl-danger); }

/* Radio + checkbox — ink when checked, accent ring on focus. `accent-color`
   does both the fill and the tick in one property on every current engine. */
.cl-check, .cl-radio {
  width: 16px;
  height: 16px;
  flex: none;
  accent-color: var(--cl-ink);
  cursor: pointer;
}
.cl-check:focus-visible, .cl-radio:focus-visible { outline: none; box-shadow: 0 0 0 var(--cl-focus-ring-width) var(--cl-focus-ring); }

/* Selectable card — the big tappable option (a tenant type, a plan, a survey
   answer). SELECTED IS INK + ACCENT, never blue. */
.cl-option {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  box-sizing: border-box;
  padding: 0.85rem 1rem;
  text-align: start;
  background: var(--cl-white);
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-card);
  color: var(--cl-ink);
  font-size: var(--cl-fs-body);
  font-family: var(--cl-font-sans);
  cursor: pointer;
  transition: border-color var(--cl-transition-fast), background var(--cl-transition-fast), box-shadow var(--cl-transition-fast);
}
.cl-option:hover { border-color: color-mix(in srgb, var(--cl-ink) 28%, transparent); background: var(--cl-paper); }
.cl-option:focus-visible { outline: none; box-shadow: 0 0 0 var(--cl-focus-ring-width) var(--cl-focus-ring); }
.cl-option.is-selected,
.cl-option[aria-pressed="true"],
.cl-option:has(input:checked) {
  border-color: var(--cl-ink);
  background: rgba(var(--cl-accent-rgb), 0.10);
  box-shadow: inset 3px 0 0 0 var(--cl-accent);
}
.cl-option__title { font-weight: var(--cl-fw-medium); }
.cl-option__desc  { font-size: var(--cl-fs-small); color: var(--cl-muted); margin-top: 2px; }
.cl-option__body  { flex: 1; min-width: 0; }
/* Compact row — the density the one-question-per-page layout needs so four
   options fit one viewport without scrolling. */
.cl-option--compact { padding: 0.6rem 0.85rem; border-radius: var(--cl-radius-md); }

/* A group of related inputs with a legend that reads as a field label —
   a checkbox or radio group (the user page's Countries, MC4). No browser
   frame; the legend takes the field label's place. */
.cl-fieldset { border: 0; margin: 0 0 1rem; padding: 0; min-inline-size: 0; }
.cl-fieldset > legend { padding: 0; margin-block-end: 0.35rem; }
.cl-fieldset .cl-fieldset { margin-block-end: 0; }
.cl-fieldset__detail { margin-block-start: 0.75rem; }

/* Bilingual EN/AR inline toggle — the little segmented control that sits on a
   field label. Cosmetic only; the popup partial owns the behaviour. */
.cl-lang-toggle {
  display: inline-flex;
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-badge);
  overflow: hidden;
  background: var(--cl-white);
}
.cl-lang-toggle__btn {
  padding: 2px 0.6em;
  font-size: var(--cl-fs-label);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--cl-muted);
  background: transparent;
  border: none;
  cursor: pointer;
}
.cl-lang-toggle__btn.is-active { background: var(--cl-ink); color: var(--cl-white); }
.cl-lang-toggle__btn:focus-visible { outline: none; box-shadow: inset 0 0 0 var(--cl-focus-ring-width) var(--cl-focus-ring); }


/* ── Wizard ───────────────────────────────────────────────────────────────
   Two layouts that share one vocabulary:
     (a) the STEPPER — completed / current / upcoming, with a footer of
         Back · Save draft · Continue;
     (b) ONE QUESTION PER PAGE — a progress bar, one question, compact option
         rows. A four-option question must fit one viewport on a phone, which
         is why the options are `.cl-option--compact` and the footer is sticky
         rather than below the fold. */

.cl-wizard { display: flex; flex-direction: column; gap: 1.5rem; }

.cl-wizard__steps { display: flex; align-items: flex-start; gap: 0; list-style: none; margin: 0; padding: 0; }
.cl-wizard__step { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 0.4rem; position: relative; text-align: center; }
/* The connector sits BEHIND the markers and stops at the last step. */
.cl-wizard__step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 13px;
  inset-inline-start: 50%;
  width: 100%;
  height: 1px;
  background: var(--cl-border);
  z-index: 0;
}
.cl-wizard__marker {
  position: relative;
  z-index: 1;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--cl-fs-small);
  font-weight: var(--cl-fw-semibold);
  background: var(--cl-white);
  border: 1px solid var(--cl-border);
  color: var(--cl-muted);
  font-variant-numeric: tabular-nums;
}
.cl-wizard__label { font-size: var(--cl-fs-small); color: var(--cl-muted); max-width: 11ch; }

.cl-wizard__step.is-complete .cl-wizard__marker { background: var(--cl-ink); border-color: var(--cl-ink); color: var(--cl-white); }
.cl-wizard__step.is-complete:not(:last-child)::after { background: var(--cl-ink); }
.cl-wizard__step.is-complete .cl-wizard__label { color: var(--cl-ink); }

.cl-wizard__step.is-current .cl-wizard__marker {
  background: var(--cl-white);
  border-color: var(--cl-ink);
  color: var(--cl-ink);
  box-shadow: 0 0 0 3px rgba(var(--cl-accent-rgb), 0.30);
}
.cl-wizard__step.is-current .cl-wizard__label { color: var(--cl-ink); font-weight: var(--cl-fw-semibold); }

/* upcoming = the resting state above; named so a template can be explicit */
.cl-wizard__step.is-upcoming .cl-wizard__marker { background: var(--cl-white); }

.cl-wizard__footer {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--cl-border);
}
/* Back sits at the inline-start; Save draft + Continue at the inline-end. */
.cl-wizard__footer > .cl-wizard__spacer { flex: 1; }

/* (b) one question per page */
.cl-wizard__progress { height: 3px; border-radius: 2px; background: var(--cl-border); overflow: hidden; }
.cl-wizard__progress > span { display: block; height: 100%; background: var(--cl-accent); transition: width var(--cl-transition); }
.cl-wizard__count { font-size: var(--cl-fs-label); letter-spacing: var(--cl-track-label); text-transform: uppercase; color: var(--cl-muted); }
.cl-wizard__question {
  font-size: var(--cl-fs-h2);
  font-weight: var(--cl-fw-medium);
  letter-spacing: var(--cl-track-heading);
  color: var(--cl-ink);
  line-height: 1.35;
  margin: 0;
}
.cl-wizard__help { font-size: var(--cl-fs-small); color: var(--cl-muted); margin-top: 0.4rem; }
.cl-wizard__options { display: flex; flex-direction: column; gap: 0.5rem; }
.cl-wizard--single { max-width: 640px; margin-inline: auto; }

@media (max-width: 640px) {
  /* Visually hidden, NOT display:none — the label is the step button's only
     accessible name (the marker is aria-hidden), and `display:none` left every
     step an unnamed button on a phone: the 28 axe button-name criticals of
     REM-670 on indicators create/edit. */
  .cl-wizard__label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  .cl-wizard__footer { flex-wrap: wrap; }
}


/* ── Empty state ──────────────────────────────────────────────────────────
   A line icon, one sentence of what is missing, one action. No emoji, no
   illustration — the same restraint the rest of the system uses. */

.cl-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  padding: 3rem 1.5rem;
  text-align: center;
  color: var(--cl-muted);
}
.cl-empty__icon { width: 28px; height: 28px; stroke: currentColor; fill: none; opacity: 0.5; }
.cl-empty__title { font-size: var(--cl-fs-body); font-weight: var(--cl-fw-semibold); color: var(--cl-ink); }
.cl-empty__body  { font-size: var(--cl-fs-small); max-width: 44ch; line-height: 1.5; }
.cl-empty__action { margin-top: 0.5rem; }


/* ── Sidebar rail ─────────────────────────────────────────────────────────
   The shared shell behind templates/_partials/cl_sidebar.html. Background is
   var(--cl-sidebar), which templates/base.html overrides per
   OrgProfile.nav_color — so a tenant's chosen navy is honoured and the
   Platform Admin rail stays --cl-ink. Nothing here hardcodes a brand colour.

   The two live bases keep their own `.sidebar` / `.nav-item` rules; these
   `.cl-nav-*` classes are the version new pages compose. */

.cl-rail {
  display: flex;
  flex-direction: column;
  background: var(--cl-sidebar);
  color: rgba(var(--cl-on-surface-rgb), 0.72);
  height: 100%;
  min-height: 0;
}
.cl-rail__brand { display: flex; align-items: center; gap: 0.6rem; padding: 1.1rem 1.1rem 0.5rem; }
.cl-rail__mark { width: 28px; height: 28px; flex: none; }
.cl-rail__name { font-size: var(--cl-fs-body); font-weight: var(--cl-fw-semibold); color: var(--cl-on-surface); letter-spacing: var(--cl-track-heading); }
/* The role label under the brand — gold, tracked out, tiny. */
.cl-rail__role {
  padding: 0 1.1rem 0.9rem;
  font-size: var(--cl-fs-label);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: var(--cl-track-label);
  text-transform: uppercase;
  color: var(--cl-accent);
}
.cl-rail__nav { flex: 1; min-height: 0; overflow-y: auto; padding-bottom: 0.75rem; }

.cl-nav-section {
  padding: 0.9rem 1.1rem 0.35rem;
  font-size: var(--cl-fs-label);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: var(--cl-track-label);
  text-transform: uppercase;
  color: rgba(var(--cl-on-surface-rgb), 0.38);
}
.cl-nav-item {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.5rem 1.1rem;
  font-size: var(--cl-fs-body);
  color: rgba(var(--cl-on-surface-rgb), 0.72);
  text-decoration: none;
  border-inline-start: 2px solid transparent;
  transition: background var(--cl-transition-fast), color var(--cl-transition-fast);
}
.cl-nav-item:hover { background: rgba(var(--cl-on-surface-rgb), 0.07); color: var(--cl-on-surface); }
.cl-nav-item.is-active {
  background: rgba(var(--cl-on-surface-rgb), 0.10);
  color: var(--cl-on-surface);
  border-inline-start-color: var(--cl-accent);
  font-weight: var(--cl-fw-medium);
}
.cl-nav-item__icon { width: 16px; height: 16px; flex: none; stroke: currentColor; fill: none; opacity: 0.75; }
.cl-nav-item.is-active .cl-nav-item__icon { opacity: 1; }
.cl-nav-item__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cl-nav-item__badge { margin-inline-start: auto; }

.cl-rail__user {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.1rem;
  border-top: 1px solid rgba(var(--cl-on-surface-rgb), 0.12);
}
.cl-rail__user-name { font-size: var(--cl-fs-small); color: var(--cl-on-surface); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cl-rail__user-meta { font-size: var(--cl-fs-label); color: rgba(var(--cl-on-surface-rgb), 0.5); }
.cl-rail__user-body { min-width: 0; flex: 1; }

/* ── Modal / dialog ─────────────────────────────────────────────────────
   ONE modal component, built on the native <dialog> element.

   Native `showModal()` already supplies the backdrop, the focus trap, the
   inert-page behaviour and Escape-to-close. A hand-rolled overlay has to
   re-implement all four, and the four bespoke ones this replaces
   (`.pa-modal`, `.modal-overlay`, `.lang-modal`, `.cl-import-modal__panel`)
   between them got two of them wrong. Behaviour is `static/js/cl_modal.js`,
   loaded once per shell — do not re-implement it per page.

   A <dialog> opened with showModal() renders in the browser's top layer, so
   an ancestor's `overflow` or `z-index` cannot clip it. That is what makes it
   safe to declare one INSIDE a table cell, next to the row's kebab, where the
   form it carries can still read the row's own template context. */
dialog.cl-modal {
  padding: 0;
  /* Both shells open with `*, *::before, *::after { margin: 0 }`, which beats
     the UA stylesheet's `dialog { margin: auto }`. A modal <dialog> is
     `position: fixed; inset: 0`, so with the margin zeroed it collapsed into
     the TOP-LEFT corner instead of centring. Restated here, in the component,
     so no shell's reset can un-centre it again. */
  margin: auto;
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-lg);
  background: var(--cl-white);
  color: var(--cl-ink);
  box-shadow: 0 12px 40px var(--cl-shadow);
  width: min(30rem, calc(100vw - 2rem));
  max-height: calc(100dvh - 2rem);
  overflow: auto;
  font-family: inherit;
}
dialog.cl-modal::backdrop { background: rgba(var(--cl-ink-rgb), 0.45); }

.cl-modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1rem 1.15rem 0.75rem;
  border-bottom: 1px solid var(--cl-border);
}
.cl-modal__title { margin: 0; font-size: var(--cl-fs-body); font-weight: var(--cl-fw-semibold); color: var(--cl-ink); }
.cl-modal__sub { margin: 0.25rem 0 0; font-size: var(--cl-fs-small); color: var(--cl-text-2); }
.cl-modal__close {
  flex: none; background: none; border: none; cursor: pointer; line-height: 1;
  /* on the type scale (D6) and a 44 px tap target (Rule 25; axe target-size) */
  font-size: var(--cl-fs-h2); color: var(--cl-muted); padding: 0; border-radius: var(--cl-radius-sm);
  display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px;
  margin-block: -10px; margin-inline-end: -10px;
}
.cl-modal__close:hover { color: var(--cl-ink); background: var(--cl-paper); }
.cl-modal__close:focus-visible { outline: none; box-shadow: 0 0 0 var(--cl-focus-ring-width) var(--cl-focus-ring); }

.cl-modal__body { padding: 1.15rem; display: flex; flex-direction: column; gap: 0.75rem; }
.cl-modal__foot {
  display: flex; justify-content: flex-end; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.85rem 1.15rem; border-top: 1px solid var(--cl-border); background: var(--cl-paper);
}
.cl-modal__note { font-size: var(--cl-fs-label); color: var(--cl-muted); margin: 0; }
.cl-modal__warn { font-size: var(--cl-fs-label); color: var(--cl-danger); font-weight: var(--cl-fw-semibold); margin: 0; }

/* Field rows inside a modal — the same shape whatever form is carried. */
.cl-modal__field { display: flex; flex-direction: column; gap: 0.25rem; }
.cl-modal__label { font-size: var(--cl-fs-label); color: var(--cl-muted); font-weight: var(--cl-fw-medium); }
.cl-modal__row { display: flex; gap: 0.5rem; align-items: center; }
.cl-modal__check { display: flex; gap: 0.5rem; align-items: flex-start; font-size: var(--cl-fs-small); }
/* A check is a tap target like any other (WCAG 2.5.8, ≥24px). */
.cl-modal__check input[type="checkbox"], .cl-modal__check input[type="radio"] { inline-size: 1.5rem; block-size: 1.5rem; margin: 0; flex-shrink: 0; }
/* Build 5: a second section of one dialog (the registry's purge, below the
   soft delete); a check that carries danger (an override). */
.cl-modal__body--split { border-block-start: 1px solid var(--cl-border); }
.cl-modal__check--danger { color: var(--cl-danger); }

/* A record's facts as label / value pairs (Build 5: a stored API key's
   details in its dialog). */
.cl-facts { display: grid; grid-template-columns: 8.5rem 1fr; gap: 6px 12px; margin: 0; padding: 12px 14px; background: var(--cl-paper); border-radius: var(--cl-radius-md); font-size: var(--cl-fs-body); }
.cl-facts dt { color: var(--cl-muted); }
.cl-facts dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 768px) { .cl-facts { grid-template-columns: 1fr; } }

/* Platform audit log (Build 5): a row's before / after, behind a disclosure. */
.cl-audit-diff > summary { cursor: pointer; font-size: var(--cl-fs-small); text-decoration: underline; }
.cl-audit-diff dl { margin: 2px 0; font-size: var(--cl-fs-small); }
.cl-audit-diff dt { font-weight: var(--cl-fw-semibold); }
.cl-audit-diff dd { margin: 0 0 4px; }
.cl-audit-diff { max-width: 100%; overflow-wrap: anywhere; }
.cl-audit-diff__part { display: block; min-width: 0; margin-block-end: 6px; }

/* A notice with its one action at the end (Build 5: the contact archive's
   "Mark all as read"). */
.cl-notice-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }

/* A form page's one card (Build 5): the measure every admin form wrote inline
   as `style="max-width:720px"`. */
.cl-form-card { max-width: 720px; }

/* The registry's tier legend (Build 5): what each tier includes. */
.cl-tier-legend { display: flex; flex-wrap: wrap; gap: 12px; margin-block-end: 16px; }
.cl-tier-legend__item { background: var(--cl-white); border: 1px solid var(--cl-border); border-radius: var(--cl-radius-md); padding: 10px 16px; min-width: 150px; }
.cl-tier-legend__name { font-size: var(--cl-fs-small); font-weight: var(--cl-fw-semibold); color: var(--cl-ink); margin-block-end: 4px; }
.cl-modal input[type="text"], .cl-modal input[type="number"], .cl-modal select {
  width: 100%; box-sizing: border-box; font-family: inherit; font-size: var(--cl-fs-small);
  padding: 0.45rem 0.6rem; border: 1px solid var(--cl-border); border-radius: var(--cl-btn-radius);
  background: var(--cl-white); color: var(--cl-ink);
}
.cl-modal input:focus-visible, .cl-modal select:focus-visible {
  outline: none; border-color: var(--cl-accent); box-shadow: 0 0 0 var(--cl-focus-ring-width) var(--cl-focus-ring);
}


/* ── Profile header ───────────────────────────────────────────────────────
   The record-view pattern (design system §3, §5): a soft banner, an initials
   avatar breaking the banner edge, the name in ONE language, the mono id, then
   status pills and a row of plain facts. Used by the individual, household and
   establishment detail pages so a record reads the same whatever kind it is.

   It is a card, so it composes `.cl-card`'s surface rather than restating it —
   the only thing added here is the banner/avatar geometry. */

.cl-profile {
  background: var(--cl-white);
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-card);
  box-shadow: var(--cl-shadow-sm);
  overflow: hidden;
}
/* Warm-to-cool wash, mixed FROM the tokens so a brand or tenant re-theme
   carries it — a literal gradient here would be a fourth palette. */
.cl-profile__banner {
  height: 84px;
  background: linear-gradient(
    105deg,
    color-mix(in srgb, var(--cl-accent) 30%, var(--cl-white)),
    var(--cl-paper) 58%,
    color-mix(in srgb, var(--cl-info) 14%, var(--cl-white)));
}
.cl-profile__body {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 1.25rem;
  padding: 0 1.5rem 1.25rem;
}
/* The avatar overlaps the banner. The white ring is what separates it from
   the wash behind it at any banner colour. */
.cl-profile__avatar {
  margin-top: -2.5rem;
  border: 4px solid var(--cl-white);
  box-shadow: var(--cl-shadow-sm);
}
.cl-profile__main { flex: 1 1 20rem; min-width: 0; padding-top: 0.9rem; }
.cl-profile__name {
  margin: 0;
  font-size: var(--cl-fs-h1);
  font-weight: var(--cl-fw-semibold);
  letter-spacing: var(--cl-track-heading);
  color: var(--cl-ink);
  line-height: 1.2;
  overflow-wrap: anywhere;
}
/* The back control on the profile card's name row (REM-729): one row, the
   name's FIRST line on the 44 px button's centre line and the row aligned to
   its top, so a name that wraps on a phone never pushes the back control onto
   a row of its own (measured: centred, it sat 21 px below the name at 320 px). */
.cl-profile__namerow { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.cl-profile__namerow > .cl-profile__name {
  flex: 1 1 auto; min-width: 0;
  padding-block-start: max(0px, calc((44px - 1.2em) / 2));
}
.cl-profile__id {
  margin-top: 0.25rem;
  font-family: var(--cl-font-mono);
  font-size: var(--cl-fs-label);
  color: var(--cl-muted);
}
.cl-profile__pills { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.75rem; }
.cl-profile__facts {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  margin-top: 0.6rem; font-size: var(--cl-fs-small); color: var(--cl-muted);
}
.cl-profile__fact { display: inline-flex; align-items: center; gap: 0.35rem; }
.cl-profile__fact > svg { width: 1em; height: 1em; flex: none; stroke: currentColor; fill: none; }
/* A dot separator, not a slash: it never reads as part of the value beside it. */
.cl-profile__sep { width: 3px; height: 3px; border-radius: 50%; background: var(--cl-muted); flex: none; }
.cl-profile__actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding-top: 0.9rem;
}


/* ── Lynks — a record's connections ───────────────────────────────────────
   A Lynk is a CONNECTION, so it renders like one: the other record's icon, its
   name, its own mono id as the meta line, and the typed role as a neutral pill.
   The whole row is the link — never a "view" button hidden at the end. */

.cl-lynks { display: flex; flex-direction: column; }
.cl-lynk {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.7rem 0.5rem;
  border-radius: var(--cl-radius-sm);
  color: inherit; text-decoration: none;
  transition: var(--cl-transition-fast);
}
.cl-lynk + .cl-lynk { border-top: 1px solid var(--cl-border); border-radius: 0; }
.cl-lynk:hover { background: var(--cl-paper); }
.cl-lynk__icon {
  width: 38px; height: 38px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--cl-radius-md);
  background: var(--cl-paper); color: var(--cl-ink);
}
.cl-lynk__icon > svg { width: 18px; height: 18px; stroke: currentColor; fill: none; }
.cl-lynk__icon--household     { background: var(--cl-teal-bg); color: var(--cl-teal-dark); }
.cl-lynk__icon--establishment { background: var(--cl-info-bg); color: var(--cl-info); }
.cl-lynk__body { flex: 1; min-width: 0; }
.cl-lynk__name {
  font-size: var(--cl-fs-body); font-weight: var(--cl-fw-semibold);
  color: var(--cl-ink); overflow-wrap: anywhere;
}
.cl-lynk__meta {
  margin-top: 1px; font-family: var(--cl-font-mono);
  font-size: var(--cl-fs-label); color: var(--cl-muted);
}


/* ── Activity feed ────────────────────────────────────────────────────────
   What happened to this record, newest first, as a timeline: a line icon in a
   tinted tile, a one-line sentence, and the timestamp in mono. The connector
   rule is drawn on the item, not between items, so the last row never trails a
   dangling line. */

.cl-feed { list-style: none; margin: 0; padding: 0; }
.cl-feed__item { display: flex; gap: 0.85rem; padding: 0.7rem 0; position: relative; }
.cl-feed__item:not(:last-child)::before {
  content: ''; position: absolute; inset-inline-start: 15px;
  top: 2.5rem; bottom: -0.7rem; width: 2px; background: var(--cl-border);
}
.cl-feed__icon {
  position: relative; z-index: 1;
  width: 32px; height: 32px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--cl-radius-md);
  background: var(--cl-paper); color: var(--cl-muted);
}
.cl-feed__icon > svg { width: 16px; height: 16px; stroke: currentColor; fill: none; }
.cl-feed__icon--success { background: var(--cl-teal-bg);  color: var(--cl-teal-dark); }
.cl-feed__icon--info    { background: var(--cl-info-bg);  color: var(--cl-info); }
.cl-feed__icon--accent  { background: var(--cl-warn-bg);  color: var(--cl-warn-text); }
.cl-feed__body { flex: 1; min-width: 0; padding-top: 0.2rem; }
.cl-feed__title { font-size: var(--cl-fs-body); color: var(--cl-ink); line-height: 1.5; }
.cl-feed__title strong { font-weight: var(--cl-fw-semibold); }
.cl-feed__time {
  margin-top: 0.15rem; font-family: var(--cl-font-mono);
  font-size: var(--cl-fs-label); color: var(--cl-muted);
}

/* ── Hub grid + Hub card ──────────────────────────────────────────────────
   Design system §9.2 (Hub archetype) and §9.3 (concrete spec).

   The defect this closes: a Hub used to be a bare `auto-fill` grid of cards
   that each sized themselves to their own text, so a two-word blurb and a
   three-line one produced two different card heights side by side and the
   CTA sat at a different vertical position in every column. §9.2 makes the
   ARCHETYPE decide: uniform cards, equal height, CTA pinned bottom, text
   truncated, never shrink-to-fit.

   `grid-auto-rows: 1fr` is what makes EVERY row equal, not merely the cards
   within one row — with `stretch` alone a short final row would still be
   shorter than the rest. The card is a flex column so `margin-top:auto` on
   the CTA does the pinning; that pairing is the whole mechanism and neither
   half works alone. */
.cl-hub {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  grid-auto-rows: 1fr;
  gap: var(--cl-gap);
}
.cl-hub-card {
  display: flex;
  flex-direction: column;
  min-height: 168px;
  height: 100%;
  padding: 24px;
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-card);
  box-shadow: var(--cl-shadow-sm);
  background: var(--cl-white);
  color: inherit;
  text-decoration: none;
  transition: box-shadow var(--cl-transition-fast);
}
a.cl-hub-card:hover,
a.cl-hub-card:focus-visible { box-shadow: var(--cl-shadow-lift); }
.cl-hub-card__icon { color: var(--cl-accent); line-height: 0; margin-bottom: 10px; }
.cl-hub-card__icon > svg { stroke: currentColor; fill: none; }
.cl-hub-card__title {
  margin: 0 0 4px;
  font-size: var(--cl-fs-h3);
  font-weight: var(--cl-fw-semibold);
  color: var(--cl-ink);
}
/* Clamped to two lines: a longer blurb TRUNCATES, it never resizes the card.
   `min-height` on the clamp keeps a one-line blurb from pulling the CTA up,
   so the pinned row lands identically across the grid. */
.cl-hub-card__blurb {
  margin: 0;
  font-size: var(--cl-fs-body);
  color: var(--cl-muted);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cl-hub-card__cta {
  margin-top: auto;          /* the pin — §9.2's "CTA pinned bottom" */
  padding-top: 12px;
  font-size: var(--cl-fs-small);
  font-weight: var(--cl-fw-semibold);
  color: var(--cl-teal);
}
.cl-hub-card--disabled { opacity: 0.6; cursor: default; }
.cl-hub-card--disabled .cl-hub-card__cta { color: var(--cl-muted); }

/* ── Sections bar ─────────────────────────────────────────────────────────
   Design system §9.3. The ONE horizontal sub-navigation, rendered only when a
   destination declares 2+ sibling sections. Never a filled pill: the active
   state is ink text plus a 2px accent underline, which is why the rule below
   and the item underline share an edge.

   RTL: `gap`, `border-block-end` and `inline-size` are direction-agnostic, so
   the strip mirrors with the document rather than needing an `[dir]` rule.
   Overflow scrolls; the scrollbar is hidden because the strip is short enough
   to swipe and a visible bar on a 3-item menu reads as a defect. */
.cl-sections {
  display: flex;
  gap: 24px;
  border-block-end: 1px solid var(--cl-border);
  margin-block-end: 20px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.cl-sections::-webkit-scrollbar { display: none; }
.cl-sections__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 12px 0;               /* 12px + 20px line box = the 44px hit target */
  border: 0;
  border-block-end: 2px solid transparent;
  margin-block-end: -1px;        /* the item underline sits ON the bar's rule */
  background: none;
  white-space: nowrap;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--cl-fs-body);
  font-weight: var(--cl-fw-medium);
  line-height: 20px;
  color: var(--cl-muted);
  text-decoration: none;
  transition: color var(--cl-transition-fast);
}
.cl-sections__item:hover { color: var(--cl-ink); }
.cl-sections__item.is-active {
  color: var(--cl-ink);
  border-block-end-color: var(--cl-ink);
}
/* "More ▾" — MEASURED overflow (design system §5.11.4, replacing "4 tabs +
   More"). A linked tenant bar draws every tab; without JavaScript it WRAPS
   onto a second line and More stays hidden, so nothing is ever out of reach.
   static/js/cl_sections.js adds .is-measured: one row, the tabs that do not
   fit move (from the end) into More — the ONE menu component — and More shows
   only when something overflowed. The active tab never overflows. */
.cl-sections[data-cl-sections-measure] { flex-wrap: wrap; column-gap: 24px; row-gap: 0; overflow-x: visible; }
.cl-sections[data-cl-sections-measure] .cl-sections__more { display: none; }
.cl-sections[data-cl-sections-measure].is-measured { flex-wrap: nowrap; overflow: visible; }
.cl-sections[data-cl-sections-measure].is-measured .cl-sections__item[data-cl-tab][hidden] { display: none; }
.cl-sections[data-cl-sections-measure].is-measured .cl-sections__more.is-needed { display: inline-flex; }
.cl-sections__more { display: inline-flex; flex: 0 0 auto; }
.cl-sections__more > summary .cl-icon { width: 14px; height: 14px; }
.cl-sections__item:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: -3px; border-radius: 2px; }
.cl-sections__item > svg { width: 15px; height: 15px; stroke: currentColor; fill: none; }
.cl-sections__count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; box-sizing: border-box;
  border-radius: var(--cl-radius-badge);
  background: var(--cl-paper); border: 1px solid var(--cl-border);
  font-family: var(--cl-font-mono);
  font-size: var(--cl-fs-label);
  color: var(--cl-ink);
}

/* ── Filter bar (List archetype) ──────────────────────────────────────────
   NOT a Sections bar, and the distinction is the point (§9.2/§9.3). A Sections
   bar moves between sibling SECTIONS of one subject; a filter bar narrows the
   SAME list and belongs to the List archetype's own nav pattern ("filters +
   one primary Add"). They are drawn differently on purpose so a reader can
   tell at a glance which one they are looking at: filters are pills, sections
   are underlined text. Conflating them is what made the debt register treat a
   status filter and a settings menu as the same defect. */
.cl-filter-bar { display: flex; flex-wrap: wrap; gap: 8px; margin-block-end: 16px; }
.cl-filter-bar__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-badge);
  background: var(--cl-white);
  font-family: inherit;
  font-size: var(--cl-fs-body);
  font-weight: var(--cl-fw-medium);
  color: var(--cl-muted);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--cl-transition-fast), color var(--cl-transition-fast);
}
.cl-filter-bar__item:hover { color: var(--cl-ink); }
.cl-filter-bar__item.is-active {
  background: var(--cl-ink);
  border-color: var(--cl-ink);
  color: var(--cl-white);
}

/* ── The reporting filter (MC5 B, design system §5.12) ─────────────────
   Country (and country groups) and implementing partner on a report page
   that is not a LynkView — the map, the report builder, the PDF dialogs.
   Fields wrap on a phone; every control keeps a 44 px target. */
.cl-reporting-filter { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-block-end: 16px; }
.cl-reporting-filter__field { flex: 1 1 12rem; min-inline-size: 0; max-inline-size: 22rem; margin: 0; }
.cl-reporting-filter__field .cl-select { inline-size: 100%; min-block-size: 44px; }
.cl-reporting-filter__actions { flex: 0 0 auto; }
.cl-reporting-filter__actions .cl-btn { min-block-size: 44px; }

/* Removal from a project (MC5 F): the person's notice and the seat notice. */
.cl-removal-notice { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 12px 16px; margin-block-end: 12px; border-inline-start: 4px solid var(--cl-warning); }
.cl-removal-notice p { margin: 0; }
.cl-removal-notice ul { list-style: none; margin: 0; padding: 0; inline-size: 100%; }
.cl-removal-notice__row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.cl-removal-notice .cl-btn { min-block-size: 44px; }

/* The dashboard's country and partner breakdowns (MC5 B). */
.cl-dashboard-breakdowns { margin-block-end: 1.25rem; }

/* ── List search box (List archetype, amended 2026-10-15) ────────────────
   A magnifier inside a box of bounded width that submits on Enter — no Apply
   button. Bounded because a search spanning the whole toolbar reads as the
   page's main control and pushes the filters onto a second line on a laptop.
   Markup: templates/_partials/cl_list_search.html. */
.cl-list-search { position: relative; display: flex; align-items: center; width: 100%; max-width: 360px; min-width: 0; }
.cl-list-search__icon {
  position: absolute;
  inset-inline-start: 12px;
  display: inline-flex;
  color: var(--cl-muted);
  pointer-events: none;
}
.cl-list-search .cl-list-search__input { width: 100%; min-width: 0; padding-inline-start: 36px; }

/* ── Segmented control ────────────────────────────────────────────────────
   Also not navigation: it switches the MODE of one panel (e.g. compose a new
   question vs pick one from the bank) without leaving the page or changing
   what the page is about. Declared here so such a control has a governed
   shape instead of being drawn as counterfeit tabs. */
.cl-segmented {
  display: inline-flex;
  padding: 3px;
  gap: 3px;
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-md);
  background: var(--cl-paper);
}
.cl-segmented__item {
  padding: 6px 14px;
  border: 0;
  border-radius: var(--cl-radius-sm);
  background: none;
  font-family: inherit;
  font-size: var(--cl-fs-body);
  font-weight: var(--cl-fw-medium);
  color: var(--cl-muted);
  cursor: pointer;
}
.cl-segmented__item.is-active { background: var(--cl-white); color: var(--cl-ink); box-shadow: var(--cl-shadow-sm); }
/* A segmented control built from radios (a form-driven mode, e.g. the map's
   Actual / % of target): the label is the item, the checked radio its state,
   and the radio's own focus shows on the label. */
.cl-segmented > legend { padding: 0; }
.cl-segmented__item:has(input:checked) { background: var(--cl-white); color: var(--cl-ink); box-shadow: var(--cl-shadow-sm); }
.cl-segmented__item:has(input:focus-visible) { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 1px; }
label.cl-segmented__item { display: inline-flex; align-items: center; min-height: 44px; }

/* The Profile archetype's page measure (§9.2). One declaration, so the
   Sections bar and the panels beneath it share an edge on every record type. */
.cl-profile-page { max-width: 960px; }

/* ── DNS records (custom-domain setup) ────────────────────────────────────
   core/_domain_dns_records.html. Each record is drawn as the row a provider's
   DNS editor shows — Type · Name/Host · Value/Target · TTL — so the customer
   copies field-for-field in the same order. It is sized by its CONTAINER, not
   the viewport: the same partial sits in the wide Settings page and the narrow
   signup wizard, so below ~620px of card width the four columns stack into
   labelled rows and nothing ever scrolls sideways. Logical properties only, so
   RTL mirrors without a second rule set; values stay dir="ltr" in the markup. */
.cl-dns-records { container-type: inline-size; display: grid; gap: 12px; }
.cl-dns-record {
  border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-sm);
  background: var(--cl-white);
  overflow: hidden;
}
.cl-dns-record-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  padding: 8px 12px;
  background: var(--cl-paper);
  border-block-end: 1px solid var(--cl-border);
}
.cl-dns-record-step { font-size: 13px; font-weight: 600; color: var(--cl-ink); }
.cl-dns-record-purpose { font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-dns-fields { display: grid; grid-template-columns: minmax(0, 1fr); margin: 0; }
.cl-dns-field { padding: 10px 12px; min-width: 0; }
.cl-dns-field + .cl-dns-field { border-block-start: 1px solid var(--cl-border); }
.cl-dns-field dt { margin: 0 0 6px; }
.cl-dns-field-label {
  display: block; font-size: var(--cl-fs-small); font-weight: 600;
  color: var(--cl-ink); text-transform: uppercase; letter-spacing: .04em;
}
.cl-dns-field-aka { display: block; font-size: 12px; color: var(--cl-muted); margin-block-start: 2px; }
.cl-dns-field dd { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.cl-dns-value {
  flex: 1 1 8rem; min-width: 0;
  font-family: var(--cl-font-mono); font-size: 13px; color: var(--cl-ink);
  background: var(--cl-paper); border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-sm); padding: 5px 8px;
  overflow-wrap: anywhere; word-break: break-all; text-align: start;
}
.cl-dns-copy { flex: 0 0 auto; }
.cl-dns-copy.is-copied { border-color: var(--cl-success); color: var(--cl-success); }
.cl-dns-field-hint { flex-basis: 100%; font-size: 12px; color: var(--cl-muted); }
@container (min-width: 620px) {
  .cl-dns-fields { grid-template-columns: minmax(7rem, .7fr) minmax(0, 1.5fr) minmax(0, 2fr) minmax(7rem, .7fr); }
  .cl-dns-field + .cl-dns-field { border-block-start: 0; border-inline-start: 1px solid var(--cl-border); }
}
.cl-dns-note {
  padding: 12px 14px;
  background: var(--cl-info-bg);
  border-inline-start: 3px solid var(--cl-info);
  border-radius: var(--cl-radius-sm);
  font-size: 13px; color: var(--cl-ink);
}
.cl-dns-note p { margin: 0 0 6px; }
.cl-dns-note-title { font-weight: 600; }
.cl-dns-example {
  display: grid; grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
  gap: 4px 12px; align-items: baseline; margin-block-start: 4px;
}
.cl-dns-example-head { font-size: 12px; color: var(--cl-muted); text-transform: uppercase; letter-spacing: .04em; }
.cl-dns-example code { font-family: var(--cl-font-mono); font-size: 12px; overflow-wrap: anywhere; word-break: break-all; text-align: start; }
.cl-dns-ttl-note { margin: 0; font-size: var(--cl-fs-small); color: var(--cl-muted); }

/* ── Touch targets (REM-369, mobile cluster C7) ───────────────────────────
   On a touch screen every control is at least 44 × 44 CSS px — the size a
   fingertip hits reliably (WCAG 2.5.5, and both phone platforms' guidance).
   `pointer: coarse` is the primary input being a finger, so a desktop with a
   mouse keeps today's density. Two shapes, pinned by core/tests_mobile_layout.py:

   * a control whose visual can grow gets min-height (buttons, fields, nav rows);
   * a control whose visual must stay small — a checkbox, a language badge, a
     table row's small button, a menu trigger — keeps it and gets an invisible
     hit area: an absolutely placed ::after, centred on the control, max(its own
     size, 44px) each way. A pseudo-element is part of its element for
     hit-testing, so a tap on that area IS a tap on the control. None of these
     components used ::after before; do not give one a second ::after. */
@media (pointer: coarse) {
  .cl-btn:not(.cl-btn--sm):not(.cl-topbar-add),
  .btn:not(.btn-sm),
  .cl-sections__item,
  .cl-option,
  .nav-item,
  .user-menu__item,
  .topnav-link,
  .sp-help-item,
  .cl-topbar-more__sheet > *,
  .cl-actions-dropdown a, .cl-actions-dropdown button,
  .cl-input, .cl-select,
  select,
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="color"]):not([type="file"]) {
    min-height: 44px;
  }
  .cl-mobile-menu-btn,
  .cl-nav-close,
  .cl-topbar-more > summary,
  .sp-help--header .sp-help-btn {
    min-width: 44px;
    min-height: 44px;
  }

  input[type="checkbox"], input[type="radio"], .cl-check, .cl-radio {
    width: 22px;
    height: 22px;
  }

  input[type="checkbox"], input[type="radio"],
  .cl-btn--sm, .btn-sm,
  .cl-lang-badge,
  .cl-actions-btn,
  .user-menu__lang-btn, .topnav-lang-btn,
  .sp-intro-dismiss,
  .remove-instance-btn,
  summary {
    position: relative;
  }
  input[type="checkbox"]::after, input[type="radio"]::after,
  .cl-btn--sm::after, .btn-sm::after,
  .cl-lang-badge::after,
  .cl-actions-btn::after,
  .user-menu__lang-btn::after, .topnav-lang-btn::after,
  .sp-intro-dismiss::after,
  .remove-instance-btn::after,
  summary::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: max(100%, 44px);
    height: max(100%, 44px);
    transform: translate(-50%, -50%);
  }
}

/* ── Legible text (REM-370, mobile cluster C8) ────────────────────────────
   Nothing a person has to read is under 12px. The eyebrow token was 10px
   (commonlynk.tokens.css, now 12px) and the shell's table head and hints were
   11px (templates/base.html). The badge on the translation popup is raised in
   translation_popup.css, and the avatar and DNS-field sizes above (10-11px)
   are 12px at source. core/tests_mobile_layout.py fails on any shared rule
   under 12px. */

/* ── Account-holder password checklist (templates/core/_password_policy.html) ──
   Display only; core.passwords.account_password_errors enforces. A line icon
   (a ring, then a tick or a cross) drawn in CSS, never an emoji. */
.cl-pw-policy { margin-top: 0.5rem; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-pw-policy__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.2rem; }
.cl-pw-policy__list li { position: relative; padding-inline-start: 1.35rem; line-height: 1.45; }
.cl-pw-policy__list li::before {
  content: ''; position: absolute; inset-inline-start: 0; top: 0.3em;
  width: 0.8rem; height: 0.8rem; border: 1.5px solid var(--cl-border); border-radius: 50%;
}
.cl-pw-policy__list li.is-ok { color: var(--cl-teal-dark); }
.cl-pw-policy__list li.is-ok::before { border-color: var(--cl-teal); background: var(--cl-teal-bg); }
.cl-pw-policy__list li.is-ok::after {
  content: ''; position: absolute; inset-inline-start: 0.27rem; top: 0.42em;
  width: 0.25rem; height: 0.45rem; border: solid var(--cl-teal-dark);
  border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
.cl-pw-policy__list li.is-bad { color: var(--cl-danger); }
.cl-pw-policy__list li.is-bad::before { border-color: var(--cl-danger); }
.cl-pw-policy__list li.is-server::before { border-style: dashed; }
.cl-pw-policy__hint { margin: 0.4rem 0 0; color: var(--cl-ink); font-weight: var(--cl-fw-medium); }

/* The rail's lockup brand row (cl_rail_lockup — the account portal). Sized
   past the marketing header's 36px lockup on purpose: the lockup's glyphs fill
   about a third of its artboard. Width beside height, so an img reset cannot
   letterbox it. */
.cl-rail__brand--lockup { padding: 1.1rem 1.1rem 0.75rem; text-decoration: none; }
.cl-rail__brand--lockup img { width: 192px; height: 48px; max-width: 100%; display: block; }

/* The map component (static/js/cl_map.js — GIS, 2026-10-11). Touch first
   (Rule 25): every Leaflet control is a 44 px target, nothing is hover-only,
   and the attribution is our own text control. */
.cl-map { position: relative; width: 100%; height: min(60vh, 460px); min-height: 260px;
  border-radius: var(--cl-radius-card); background: var(--cl-map-none); overflow: hidden; }
.cl-map--plain { background: var(--cl-map-none); }
.cl-map .leaflet-bar a {
  width: 44px; height: 44px; line-height: 44px; font-size: 20px; }
.cl-map-attribution { background: var(--cl-paper); color: var(--cl-muted); font-size: var(--cl-fs-small);
  padding: 2px 6px; border-radius: var(--cl-radius-sm); max-width: calc(100vw - 32px);
  overflow-wrap: anywhere; }
/* D1: the leaflet chrome on tokens, both themes; the focused map shows its
   ring (arrow keys move between places); layer chips; value labels with a
   surface halo. */
.cl-map:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; }
.cl-map .leaflet-bar a { background: var(--cl-white); color: var(--cl-ink); border-color: var(--cl-border); }
.cl-map .leaflet-bar a:hover { background: var(--cl-paper); }
.cl-map-attribution a { color: var(--cl-ink); }
.cl-map-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-block: 0 10px; }
.cl-map-chips:empty { display: none; }
.cl-map-chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px;
  border: 1px solid var(--cl-control-border); border-radius: var(--cl-radius-badge);
  background: var(--cl-white); color: var(--cl-text-2); font: inherit; font-size: var(--cl-fs-small); cursor: pointer;
}
/* D1b: a layer chip is a tinted toggle — status-ok tint and a ✓ when on, an
   outline when off — never navy, which stays for navigation and buttons. */
.cl-map-chip[aria-pressed="true"] { background: var(--cl-status-ok-bg); border-color: var(--cl-status-ok); color: var(--cl-status-ok-text); }
.cl-map-chip[aria-pressed="true"]::before { content: "✓" / ""; font-weight: var(--cl-fw-semibold); }
.cl-map-chip:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; }
.cl-map-value {
  font-family: var(--cl-font-figure); font-variant-numeric: tabular-nums; font-weight: var(--cl-fw-semibold);
  font-size: var(--cl-fs-small); color: var(--cl-ink); white-space: nowrap; pointer-events: none;
  text-shadow: 0 0 2px var(--cl-white), 0 0 2px var(--cl-white), 0 0 3px var(--cl-white);
  transform: translate(-50%, -50%);
}

/* ── Combobox (static/js/cl_combobox.js) ─────────────────────────────────────
   Type-to-filter over a native <select>; ARIA 1.2 editable combobox. The input
   takes the select's own cl-input look; the toggle and every option are 44px
   tap targets (§4e). */
.cl-combobox { position: relative; }
.cl-combobox__input { padding-inline-end: 44px; min-height: 44px; }
.cl-combobox__toggle {
  position: absolute; inset-block-start: 0; inset-inline-end: 0;
  width: 44px; height: 44px; min-height: 100%;
  border: 0; background: transparent; color: var(--cl-muted); cursor: pointer;
}
.cl-combobox__list {
  position: absolute; z-index: 30; inset-inline: 0; margin-top: 4px;
  max-height: 280px; overflow-y: auto;
  background: var(--cl-white); border: 1px solid var(--cl-border);
  border-radius: var(--cl-radius-card); box-shadow: var(--cl-shadow-md);
}
.cl-combobox__group {
  padding: 8px 12px 4px; font-size: var(--cl-fs-small); color: var(--cl-muted);
  font-weight: var(--cl-fw-semibold);
}
.cl-combobox__option {
  display: flex; align-items: center; min-height: 44px; padding: 0 12px;
  color: var(--cl-ink); cursor: pointer;
}
.cl-combobox__option.is-active { background: var(--cl-paper); box-shadow: inset 3px 0 0 var(--cl-focus-ring); }
[dir="rtl"] .cl-combobox__option.is-active { box-shadow: inset -3px 0 0 var(--cl-focus-ring); }
.cl-combobox__option[aria-selected="true"] { font-weight: var(--cl-fw-semibold); }
.cl-combobox__empty { padding: 10px 12px; font-size: var(--cl-fs-small); color: var(--cl-muted); }

/* ── Page header + back control (docs/LYNKVIEW.md §G) ────────────────────
   Rendered by `_archetypes/_headed.html`, `profile.html` and
   `_page_header.html` from `cl_page` (core/page_tree.py). The breadcrumb sits
   above; the back control — 44 × 44, always the first thing on the title row,
   at its start side — then the single <h1>, then the page's actions at the end.
   Logical properties only: the whole row mirrors in RTL, and the arrow and the
   breadcrumb separator are flipped explicitly because a glyph does not. */
.cl-pagehead { margin-block-end: 20px; min-width: 0; }
.cl-pagehead__row { display: flex; align-items: center; gap: 8px 12px; min-width: 0; flex-wrap: wrap; }
.cl-pagehead__text { flex: 1 1 0; min-width: 0; }   /* basis 0: never wraps below the back control */
.cl-pagehead__title { margin: 0 0 4px; font-size: var(--cl-fs-h2); font-weight: var(--cl-fw-semibold); color: var(--cl-ink); overflow-wrap: anywhere; }
.cl-pagehead__sub { margin: 0; font-size: var(--cl-fs-small); color: var(--cl-text-2); }
.cl-pagehead__sub:empty { display: none; }
.cl-pagehead__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cl-pagehead__actions:empty { display: none; }
.cl-pagehead--profile .cl-pagehead__row { align-items: flex-start; flex-wrap: nowrap; }
.cl-pagehead__profile { flex: 1 1 auto; min-width: 0; }
.cl-back {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 44px; height: 44px;
  border: 1px solid var(--cl-border); border-radius: var(--cl-radius-md);
  background: var(--cl-white); color: var(--cl-ink); text-decoration: none;
}
.cl-back:hover { background: var(--cl-paper); }
.cl-back:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; }
.cl-back__icon { width: 20px; height: 20px; }
/* Beside a back control, the title's FIRST line sits on the 44 px button's
   centre line and the row aligns to its top — so the back control, the title
   and the subtitle never stack into three header rows on a phone (mobile_check
   counted three on 29 pages with align-items:center, 2026-10-16). */
.cl-pagehead__row:has(> .cl-back) { align-items: flex-start; }
.cl-back + .cl-pagehead__text > .cl-pagehead__title,
.cl-back + .cl-pagehead__profile { padding-block-start: max(0px, calc((44px - 1.3em) / 2)); }
.cl-back + .cl-pagehead__text > .cl-pagehead__title { line-height: 1.3; }
[dir="rtl"] .cl-back__icon { transform: scaleX(-1); }
.cl-crumbs { margin-block-end: 6px; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-crumbs__list { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 0; margin: 0; padding: 0; list-style: none; }
.cl-crumbs__item { display: inline-flex; align-items: center; }
.cl-crumbs__item + .cl-crumbs__item::before { content: "\203A"; display: inline-block; margin-inline: 6px; color: var(--cl-muted); }
[dir="rtl"] .cl-crumbs__item + .cl-crumbs__item::before { transform: scaleX(-1); }
/* Navigation, not running text: underlined on hover only (D5, §5.11.4); the
   chevrons between items and the position above the title mark them. */
.cl-crumbs__link { display: inline-flex; align-items: center; min-height: 24px; color: var(--cl-muted); text-decoration: none; text-underline-offset: 2px; }
.cl-crumbs__link:hover, .cl-crumbs__link:focus-visible { color: var(--cl-ink); text-decoration: underline; }
.cl-crumbs__link:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; border-radius: 2px; }
/* No breadcrumb on a phone, held either way up (spec §G): narrow, or short
   like a phone in landscape (740 × 360). */
@media (max-width: 767px), (max-height: 500px) {
  .cl-crumbs { display: none; }
}
@media (max-width: 599px) {
  .cl-pagehead__row { flex-wrap: nowrap; }
  .cl-pagehead__title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; overflow-wrap: normal; }
  .cl-pagehead__actions { flex-basis: 100%; }
  .cl-pagehead__row:has(.cl-pagehead__actions:not(:empty)) { flex-wrap: wrap; }
  .cl-pagehead__row:has(.cl-pagehead__actions:not(:empty)) .cl-pagehead__text { flex-basis: calc(100% - 56px); }
}

/* ── ImportView — the import page (templates/core/imports/page.html, §5.12) ─
   Tokens only. Nothing here is gold (§5.2: never on Import or Continue): the
   loader's bar is ink on a hairline track, counts are mono (§4.4), Stop is the
   one red control. Logical properties throughout, so RTL mirrors. */
.cl-import { display: flex; flex-direction: column; gap: 1.25rem; margin-block-end: 1.5rem; }
/* `hidden` must win over the component displays (.cl-btn is inline-flex, a
   step is flex): the script hides footer buttons and whole steps with it. */
.cl-import [hidden] { display: none !important; }
.cl-import__step { display: flex; flex-direction: column; gap: 1rem; }
.cl-import__steptitle { font-size: var(--cl-fs-h3); font-weight: var(--cl-fw-semibold); color: var(--cl-ink); margin: 0; }
.cl-import__steptitle:focus { outline: none; }
.cl-import__steptitle:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; }
.cl-import__stepcount { display: none; }
.cl-import__lead, .cl-import__caps, .cl-import__prereq, .cl-import__note,
.cl-import__option-help { font-size: var(--cl-fs-small); color: var(--cl-muted); margin: 0; }
.cl-import__guide, .cl-import__upload { display: flex; flex-direction: column; gap: 0.75rem; }
.cl-import__file { min-height: 44px; max-width: 100%; }
.cl-import__option { display: flex; align-items: center; gap: 0.5rem; min-height: 44px; font-size: var(--cl-fs-body); }
.cl-import__refused { border: 1px solid var(--cl-danger); background: var(--cl-danger-bg); color: var(--cl-ink);
                      border-radius: var(--cl-radius-card); padding: 0.75rem 1rem; }
.cl-import__refused-lead { font-weight: var(--cl-fw-semibold); margin: 0 0 0.25rem; }
.cl-import__banner { margin: 0; padding: 0.6rem 0.9rem; border-radius: var(--cl-radius-md);
                     border: 1px solid var(--cl-border); background: var(--cl-paper); color: var(--cl-ink);
                     font-weight: var(--cl-fw-semibold); }
.cl-import__banner--warn { border-color: var(--cl-warn-border); background: var(--cl-warn-bg); }
.cl-import__banner--bad { border-color: var(--cl-danger); background: var(--cl-danger-bg); }
.cl-import__meta { font-size: var(--cl-fs-small); color: var(--cl-muted); margin: 0; overflow-wrap: anywhere; }
.cl-import__notices p { margin: 0 0 0.4rem; font-size: var(--cl-fs-small); color: var(--cl-ink); }
.cl-import__footer { position: sticky; inset-block-end: 0; background: var(--cl-page); padding-block: 0.75rem;
                     border-block-start: 1px solid var(--cl-border); z-index: 2; }
.cl-import__footer .cl-btn { min-height: 44px; }

.cl-import-tally { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.75rem; }
.cl-import-tally__item { margin: 0; display: flex; flex-direction: column; gap: 0.15rem; padding: 0.75rem;
                         background: var(--cl-white); border: 1px solid var(--cl-border);
                         border-radius: var(--cl-radius-card); font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-import-tally__n { font-family: var(--cl-font-mono); font-size: var(--cl-fs-h2); color: var(--cl-ink);
                      font-variant-numeric: tabular-nums; }
.cl-import-rows__caption { text-align: start; font-size: var(--cl-fs-small); color: var(--cl-muted); padding-block-end: 0.4rem; }
.cl-import-rows__more { font-size: var(--cl-fs-small); color: var(--cl-muted); }

.cl-import-loader { display: flex; flex-direction: column; gap: 0.5rem; padding: 1rem;
                    background: var(--cl-white); border: 1px solid var(--cl-border); border-radius: var(--cl-radius-card); }
.cl-import-loader__status { margin: 0; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-import-loader__status:empty { display: none; }
.cl-import-loader__label { margin: 0; font-size: var(--cl-fs-label); letter-spacing: var(--cl-track-label);
                           text-transform: uppercase; color: var(--cl-muted); }
.cl-import-loader__count { margin: 0; font-family: var(--cl-font-mono); font-size: var(--cl-fs-h1);
                           color: var(--cl-ink); font-variant-numeric: tabular-nums; }
.cl-import-loader__bar { height: 4px; background: var(--cl-border); border-radius: 2px; overflow: hidden; }
.cl-import-loader__bar > span { display: block; height: 100%; width: 0; background: var(--cl-ink);
                                transition: width var(--cl-transition); }
.cl-import-loader__facts { margin: 0; display: flex; flex-wrap: wrap; gap: 0.35rem 1.25rem;
                           font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-import-loader__facts span:empty { display: none; }
.cl-import-loader__ops { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.cl-import-loader__op { display: flex; align-items: baseline; gap: 0.6rem; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-import-loader__op.is-running { color: var(--cl-ink); font-weight: var(--cl-fw-semibold); }
.cl-import-loader__op > span:nth-child(2) { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.cl-import-loader__mark { width: 1rem; text-align: center; color: var(--cl-ink); }
.cl-import-loader__time { font-family: var(--cl-font-mono); font-variant-numeric: tabular-nums; }
.cl-import-loader__leave { margin: 0.5rem 0 0; font-size: var(--cl-fs-small); color: var(--cl-ink); }

.cl-import-map__rows { display: flex; flex-direction: column; gap: 0.6rem; }
.cl-import-map__row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.cl-import-map__row > label { flex: 1 1 10rem; min-width: 0; overflow-wrap: anywhere; font-family: var(--cl-font-mono); }
.cl-import-map__row > select { flex: 1 1 10rem; min-width: 0; min-height: 44px; }
.cl-import-map__save { display: flex; flex-direction: column; gap: 0.25rem; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-import-map__save input { min-height: 44px; }

/* The reference sections carried over from the import hub. */
.cl-import-step__title { margin: 0 0 0.5rem; font-size: var(--cl-fs-body); font-weight: var(--cl-fw-semibold); color: var(--cl-ink);
                         display: flex; align-items: center; gap: 0.6rem; }
.cl-import-step__n { display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem;
                     border-radius: 50%; font-size: var(--cl-fs-small); border: 1px solid var(--cl-ink); color: var(--cl-ink); }
.cl-import-step__lead { font-size: var(--cl-fs-small); color: var(--cl-muted); margin: 0 0 0.9rem; }
.cl-import-columns, .cl-import-history, .cl-import-mappings { margin-block-end: 1.25rem; }
.cl-import-sheet__caption { margin: 0 0 0.6rem; color: var(--cl-muted); }
.cl-import-notes { margin: 0.9rem 0 0; padding-inline-start: 1.25rem; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-import-notes li { margin-block-end: 0.4rem; }
.cl-undo-blocked { font-size: var(--cl-fs-small); color: var(--cl-muted); cursor: help; border-block-end: 1px dotted var(--cl-muted); }
.cl-import-pick { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: flex-end; }
.cl-import-pick .cl-select { min-width: min(16rem, 100%); }

@media (max-width: 640px) {
  /* "Step 4 of 4 · Result" with the bar; the footer stays pinned. */
  .cl-import__stepcount { display: block; }
  .cl-import__footer { flex-wrap: wrap; }
  .cl-import-loader__count { font-size: var(--cl-fs-h2); }
}

/* The ⚙ page menu's trigger on a page that is not a LynkView yet
   (templates/_archetypes/_page_menu.html) — the same 44×44 icon button. */
.cl-pagemenu { display: inline-flex; }
/* Token v4: 32 px drawn, the 44 x 44 tap area through ::after (as the top-bar Add). */
.cl-pagemenu__trigger { position: relative; display: inline-flex; align-items: center; justify-content: center;
                        width: 32px; height: 32px; box-sizing: border-box;
                        border: 1px solid var(--cl-border); border-radius: var(--cl-radius-md);
                        background: var(--cl-white); color: var(--cl-ink); }
.cl-pagemenu__trigger::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%);
}
.cl-pagemenu__trigger:hover { background: var(--cl-paper); }
.cl-pagemenu__trigger:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; }

/* ── Tenant shell menus (Build 5, Stage 2): the user menu's language row and
   the top-nav language menu, on the ONE menu component (cl_menu.js places
   the panels). Colours are tokens; the user menu itself is styled in the
   shell (base.html) because it follows the workspace's nav colour. ── */
.user-menu__lang { cursor: default; }
.user-menu__lang--stack { flex-direction: column; align-items: flex-start; }
.user-menu__lang-head { display: flex; align-items: center; gap: 8px; }
.user-menu__lang--stack .user-menu__lang-head { width: 100%; margin-bottom: 6px; }
.user-menu__lang-list { display: flex; flex-direction: column; gap: 2px; width: 100%; }
.user-menu__lang-option {
  width: 100%; padding: 6px 10px; background: transparent; border: 1px solid transparent;
  text-align: start; font: inherit; font-size: var(--cl-fs-small); color: inherit; cursor: pointer;
  border-radius: var(--cl-radius-sm); min-height: 36px;
}
.user-menu__lang-option.is-current { background: rgba(var(--cl-on-surface-rgb), 0.12); font-weight: var(--cl-fw-semibold); }
.user-menu__lang-option:hover, .user-menu__lang-option:focus-visible { background: rgba(var(--cl-on-surface-rgb), 0.08); }
.topnav-lang-menu__panel {
  background: var(--cl-white); border: 1px solid var(--cl-border); border-radius: var(--cl-radius-md);
  box-shadow: var(--cl-shadow-lg); min-width: 180px; padding: 6px 0;
}
.topnav-lang-menu__form { margin: 0; }
.topnav-lang-menu__item {
  display: block; width: 100%; padding: 8px 14px; min-height: 44px; background: transparent; border: none;
  text-align: start; font: inherit; font-size: var(--cl-fs-control); color: var(--cl-ink); cursor: pointer;
}
.topnav-lang-menu__item:hover, .topnav-lang-menu__item:focus-visible { background: var(--cl-paper); }
.topnav-lang-menu__item.is-current { background: var(--cl-paper); font-weight: var(--cl-fw-semibold); }

/* The website's language picker (_lang_selector.html) on the shared dialog:
   wider than a confirmation, for a grid of languages (Build 5). */
dialog.lang-modal { max-width: 640px; width: 90%; }

/* ── Record history (MC3d B; design system §5.11) ───────────────────────────
   The History tab: the .cl-feed timeline, each change as a .cl-change row —
   label, the old value struck in the muted ink, an arrow, the new value in
   ink. Long values wrap (never a silent ellipsis). RTL mirrors the arrow and
   the reading order follows the document direction, logical properties only. */
.cl-history { display: flex; flex-direction: column; gap: 1rem; }
/* The record's name in the page title: the carrier of the title's own phone
   ellipsis (the H1 is nowrap below 600px), so a long name is shortened, never cut. */
.cl-history__title { display: block; overflow: hidden; text-overflow: ellipsis; }
.cl-history__filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1.25rem; }
.cl-history__filters .cl-filter-bar { margin-block-end: 0; }
.cl-history__person { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.cl-history__person .cl-field-label { margin-block-end: 0; }
.cl-history__person .cl-select { inline-size: auto; min-inline-size: 12rem; max-inline-size: 100%; }
.cl-history__head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem; }
.cl-history__actor { color: var(--cl-ink); font-weight: var(--cl-fw-semibold); overflow-wrap: anywhere; }
.cl-history__aside { margin-block: 0.35rem 0; font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-history__note {
  margin-block: 0.5rem 0; padding: 0.6rem 0.8rem; border-inline-start: 3px solid var(--cl-accent);
  background: var(--cl-paper); border-radius: var(--cl-radius-md); color: var(--cl-ink);
  overflow-wrap: anywhere; white-space: normal;
}
.cl-history__archive { margin-block-start: 0.35rem; }
.cl-history__pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.75rem; }
.cl-history__pageno { font-size: var(--cl-fs-small); color: var(--cl-muted); }
.cl-change-list { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.cl-change { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.6rem; font-size: var(--cl-fs-body); }
.cl-change__label { color: var(--cl-muted); font-weight: var(--cl-fw-semibold); }
.cl-change__part { font-weight: normal; }
.cl-change__values { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.4rem; min-inline-size: 0; }
.cl-change__old { color: var(--cl-muted); text-decoration: line-through; overflow-wrap: anywhere; }
.cl-change__new { color: var(--cl-ink); text-decoration: none; overflow-wrap: anywhere; }
.cl-change__arrow { display: inline-flex; color: var(--cl-muted); }
.cl-change__arrow > svg { inline-size: 14px; block-size: 14px; stroke: currentColor; fill: none; }
[dir="rtl"] .cl-change__arrow { transform: scaleX(-1); }
.cl-note-composer { display: flex; flex-direction: column; gap: 0.4rem; }
.cl-note-composer .cl-textarea { inline-size: 100%; }
.cl-note-composer__actions { display: flex; justify-content: flex-end; }

/* The drawer: the shared dialog docked to the inline end, full height (MC3d;
   the attendance list and the activity page open a record's History in it). */
dialog.cl-modal.cl-modal--drawer {
  margin-block: 0; margin-inline: auto 0; block-size: 100dvh; max-block-size: 100dvh;
  inline-size: min(32rem, 100vw); max-inline-size: 100vw; border-radius: 0;
  display: none; flex-direction: column;
}
dialog.cl-modal.cl-modal--drawer[open] { display: flex; }
.cl-modal--drawer .cl-modal__body { overflow-y: auto; flex: 1; }

/* ── Utility bar (D1, design system §D1.5) ───────────────────────────────
   The shell's fourth surface: a 44 px bar across the top of the CONTENT
   area (never across the Rail), status and tools only. Items are declared in
   manifests (`utility_items`, core.utility) and drawn by
   templates/_partials/cl_utility_bar.html; static/js/cl_utility.js runs the
   Rail toggle, badges, offline state and the phone merge. On a phone the bar
   and the top bar share one row (.cl-chrome); the workspace item and the
   Rail toggle leave it, and every item but the two highest-priority ones with
   a badge goes into "More tools". */
.cl-chrome { display: flex; flex-direction: column; flex-shrink: 0; }
.cl-utility {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 44px; padding-inline: 8px;
  background: var(--cl-white); border-block-end: 1px solid var(--cl-border);
}
.cl-utility__group { display: flex; align-items: center; gap: 2px; min-width: 0; }
.cl-utility__item { position: relative; display: inline-flex; align-items: center; min-width: 0; }
.cl-utility__item[data-in-more] { display: none; }
.cl-utility__btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-width: 44px; min-height: 44px; padding: 0 10px; margin: 0;
  border: 0; border-radius: var(--cl-radius-md); background: transparent;
  color: var(--cl-text-2); font: inherit; font-size: var(--cl-fs-control); cursor: pointer;
}
.cl-utility__btn .cl-icon { width: 18px; height: 18px; flex: none; }
.cl-utility__btn:hover { background: var(--cl-paper); color: var(--cl-ink); }
.cl-utility__btn:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: -2px; }
.cl-utility [aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.cl-utility__text {
  max-width: 28ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--cl-ink); font-weight: var(--cl-fw-medium);
}
/* A count, at the inline-end corner, on the status-risk fill: white by day,
   navy by night (--cl-badge-text; core.tests_theme_tokens holds both 4.5:1). */
.cl-utility__badge {
  position: absolute; top: 3px; inset-inline-end: 1px;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--cl-radius-badge);
  background: var(--cl-status-risk); color: var(--cl-badge-text);
  font-size: var(--cl-fs-small); font-weight: var(--cl-fw-semibold); line-height: 18px;
  font-variant-numeric: tabular-nums; text-align: center; pointer-events: none;
}
.cl-utility__badge[hidden] { display: none; }
.cl-utility__tip {
  position: absolute; top: calc(100% + 4px); inset-inline-start: 0; z-index: 40;
  padding: 4px 8px; border-radius: var(--cl-radius-sm);
  background: var(--cl-surface); color: var(--cl-on-surface);
  font-size: var(--cl-fs-small); white-space: nowrap; pointer-events: none;
  opacity: 0; visibility: hidden;
}
.cl-utility__btn:hover + .cl-utility__tip,
.cl-utility__btn:focus-visible + .cl-utility__tip { opacity: 1; visibility: visible; }
.cl-utility__more[hidden] { display: none; }
.cl-utility .sp-help--header .sp-help-btn { min-width: 44px; min-height: 44px; }
.cl-utility__item--help .cl-utility__badge { top: 3px; }
/* D1b: one row at every width. Above a phone the top bar used to be a row of
   its own under the utility bar — an empty 48 px band on every page without
   actions of its own. Now the page's actions take the end of the utility
   bar's row, after the tools (the phone merge below keeps its own order). */
@media (min-width: 769px) {
  .cl-chrome { flex-direction: row; align-items: center; background: var(--cl-white);
               border-block-end: 1px solid var(--cl-border); }
  .cl-chrome > .cl-utility { flex: 1 1 auto; min-width: 0; border-block-end: 0; }
  .cl-chrome > .topbar { flex: 0 1 auto; min-width: 0; min-height: 44px; margin-inline-start: auto;
                         border-block-end: 0; padding-inline: 0 8px; }
}
/* The Rail toggle works from 1024 px; below that the Rail is the drawer. */
@media (max-width: 1023px) {
  .cl-utility__item--rail { display: none; }
}
@media (max-width: 768px) {
  .cl-chrome { flex-direction: row; align-items: center; background: var(--cl-white);
               border-block-end: 1px solid var(--cl-border); }
  .cl-chrome > .topbar { flex: 1 1 auto; min-width: 0; border-block-end: 0; }
  .cl-chrome > .cl-utility { order: 2; flex: 0 0 auto; border: 0; padding-inline: 0 4px; }
  .cl-utility__group--start { display: none; }
  .cl-utility [data-phone-hidden] { display: none; }
  /* A page whose own actions cannot fit beside the tools (a menu never moves
     into "More actions", so the bar goes tight) gets the whole row back: the
     tools wrap to a line of their own rather than overlap the ☰ button. */
  .cl-chrome:has(> .topbar.cl-topbar--tight) { flex-wrap: wrap; }
  .cl-chrome:has(> .topbar.cl-topbar--tight) > .cl-utility {
    flex: 1 0 100%; justify-content: flex-end; border-block-start: 1px solid var(--cl-border);
  }
}

/* ── D1 Rail states (design system §D1.4) ──────────────
   Full 220 px · Icons 64 px · Hidden 0 — <html data-rail>, from 1024 px.
   Below 1024 px the Rail is what it always was (the drawer on a phone).
   Same Rail, same manifest; only width and labels change. RTL needs
   nothing: the Rail is the inline-start flex item, so it sits on the right
   and shrinks toward the right edge. Hidden leaves the Tab order. */
.sidebar .nav-item { position: relative; }
.sidebar .nav-item .nav-icon { display: none; }
.sidebar [data-nav-icons] .nav-item .nav-icon { display: inline-block; }
@media (min-width: 1024px) {
  .sidebar { transition: width .2s ease; }
  :root[data-rail="icons"] .sidebar { width: 64px; }
  :root[data-rail="icons"] .sidebar .brand { justify-content: center; padding-inline: 8px; }
  :root[data-rail="icons"] .sidebar .brand-ngo,
  :root[data-rail="icons"] .sidebar .nav-label,
  :root[data-rail="icons"] .sidebar .user-info,
  :root[data-rail="icons"] .sidebar .user-chevron,
  :root[data-rail="icons"] .sidebar .cl-rail-storage {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  :root[data-rail="icons"] .sidebar .nav-section {
    height: 1px; margin: 8px 14px; padding: 0; overflow: hidden; font-size: 0;
    background: rgba(var(--cl-on-surface-rgb), 0.18);
  }
  :root[data-rail="icons"] .sidebar .nav-item { justify-content: center; padding: 10px 0; }
  :root[data-rail="icons"] .sidebar .nav-item .nav-icon { display: inline-block; }
  :root[data-rail="icons"] .sidebar .nav-item .nav-dot { display: none; }
  :root[data-rail="icons"] .sidebar .nav-badge { position: absolute; top: 2px; inset-inline-end: 6px; margin: 0; }
  :root[data-rail="icons"] .sidebar .user-avatar-card { justify-content: center; padding: 8px 0; }
  :root[data-rail="hidden"] .sidebar { width: 0; visibility: hidden; transition: width .2s ease, visibility 0s linear .2s; }
}
@media (prefers-reduced-motion: reduce) {
  .sidebar, :root[data-rail="hidden"] .sidebar { transition: none; }
}

/* ── Chart frame (D1, design system §D1.6; _partials/cl_chart.html) ──────
   The figure is role="img" with the finding as its name; the table version
   sits beside it (role="img" hides children from assistive technology).
   Charts are drawn by static/js/cl_charts.js only. */
.cl-chart { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.cl-chart__figure { position: relative; margin: 0; width: 100%; height: var(--cl-chart-h, 260px); }
.cl-chart__table > summary {
  display: inline-flex; align-items: center; min-height: 44px; cursor: pointer;
  font-size: var(--cl-fs-small); color: var(--cl-text-2);
}
.cl-chart__table > summary:focus-visible { outline: var(--cl-focus-ring-width) solid var(--cl-focus-ring); outline-offset: 2px; }
.cl-chart__table .cl-table { margin-block-start: 4px; }
