/* ============================================================================
   Contract-Management — single global stylesheet (no scoped CSS).
   Font: Inter. Palette:
     #546A76 Blue Slate · #88A0A8 Cool Steel · #B4CEB3 Celadon
     #DBD3C9 Dust Grey  · #FAD4D8 Petal Frost
   Shell: white topbar + dark left sidebar + light content (admin-console style).
   ========================================================================== */

/* Cascade layers (T7.1 / D2, 2026-07-14 CSS assessment): declared once, in priority order —
   a layer declared later always beats an earlier one, REGARDLESS of selector specificity. This
   is what let the 13 pre-existing no-descending-specificity findings get fixed by moving a
   handful of single-purpose "override a base component in one specific place" rules into the
   final `utilities` layer, instead of reordering lines. Every rule below lives in one of these six
   layers except :root (see the `tokens` layer, which holds nothing else and never competes with
   anything, so its position is purely documentation). */
@layer reset, base, tokens, layout, components, utilities;

@layer tokens {
:root {
    /* Brand palette */
    --cm-blue-slate:  #546A76;
    --cm-cool-steel:  #88A0A8;
    --cm-celadon:     #B4CEB3;
    --cm-dust-grey:   #DBD3C9;
    --cm-petal-frost: #FAD4D8;

    /* Derived tokens */
    --cm-blue-slate-dark: #3f515b;
    --cm-text:        #2b343a;
    --cm-text-muted:  #5f6b72;
    --cm-bg:          #eef2f2;
    --cm-surface:     #ffffff;
    --cm-border:      #e1e5e3;
    --cm-tint:        #e9eef0;   /* subtle selected/hover fill */
    --cm-danger:      #b3404a;
    /* Hover-darken sibling for --cm-danger, mirrors the --cm-blue-slate-dark convention
       (T4.1, 2026-07-14 CSS assessment — cm-button--danger). */
    --cm-danger-dark: #98363f;

    /* Dark sidebar */
    --cm-sidebar-bg:     #1f3231;
    --cm-sidebar-hover:  #2a4140;
    --cm-sidebar-active: #2f4746;
    --cm-sidebar-text:   #b8c7c4;

    /* Alias: same value as --cm-sidebar-bg, distinct semantic role (dark ink-on-pastel
       badge text, not the dark sidebar surface) — see A1 in the 2026-07-14 CSS assessment. */
    --cm-steel-ink: #1f3231;

    /* Semantic status layer (A2, 2026-07-14 CSS assessment) — the palette previously had
       no success/warn/focus/scrim tokens, so every status surface hand-rolled its own hex. */
    --cm-success:     #2f7d4f;
    /* The two ambers in the app (#9a6a00 plain text, #7a5500 badge/lamp ink) were 32 units
       of unintentional drift on the same "needs review / expires soon" role — collapsed here
       onto one value. */
    --cm-warn:      #7a5500;   /* plain-text warn (e.g. days-until-expiry copy) */
    --cm-warn-ink:  #7a5500;   /* ink paired with --cm-warn-bg inside a pastel badge/lamp */
    --cm-warn-bg:   #f3e2c2;
    --cm-danger-tint: rgba(179, 64, 74, .08);   /* one opacity for all danger-tinted row/panel fills */
    --cm-focus-ring:  0 0 0 3px rgba(136,160,168,.25);
    --cm-scrim:       rgba(43,52,58,.45);   /* modal/dialog backdrop */
    --cm-shadow-hover: 0 2px 6px rgba(43,52,58,.08), 0 10px 28px rgba(43,52,58,.08);
    --cm-text-inverse: #fff;   /* text on a colored/dark fill, e.g. buttons, badges, sidebar */
    --cm-font-mono:   ui-monospace, "SFMono-Regular", Menlo, monospace;

    /* Ink-on-pastel pairs: each ink is always used together with its matching brand pastel
       (--cm-celadon / --cm-dust-grey / --cm-petal-frost) as the badge/alert background. */
    --cm-celadon-ink: #2f4a32;
    --cm-dust-ink:    #5a5347;
    /* #8a3a45 and #7c2e39 were a 14-unit drift on the same role (ink on --cm-petal-frost);
       collapsed onto one value. */
    --cm-petal-ink:    #8a3a45;
    --cm-petal-border: #e6b9bf;

    /* Green-tint surface family (A3, 2026-07-14 CSS assessment): #e7efee/#eef4f3/#f5f8f7 were
       three near-identical off-white teal tints (a ~7-unit RGB drift with no design intent) —
       collapsed onto two tokens. --cm-tint (existing, L24) stays the darker "subtle selected/
       hover fill" used on the cockpit's sticky header/rowhead — those stay opaque and untouched. */
    --cm-tint-cool:   #e7efee;
    --cm-surface-alt: #f5f8f7;
    --cm-tint-hover:  #dde9e7;   /* cockpit sortable-column-header hover, one shade below --cm-tint */

    --cm-radius:    .55rem;
    --cm-radius-sm: .4rem;
    --cm-shadow:    0 1px 2px rgba(43,52,58,.05), 0 4px 14px rgba(43,52,58,.05);
    --cm-font:      "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    /* Type scale (T3.3 / A7, 2026-07-14 CSS assessment): 23 distinct font sizes collapsed onto
       9 steps, each within .05rem of its nearest neighbor - the .75-.82rem band (6 values) all
       land on --cm-fs-78. Deliberate literal holdouts that exceed the .05rem sanctioned shift
       (not tokenized, see T3.3 note in the remediation report): .cm-bell__badge (.65rem),
       .cm-metric__value/.cm-about__sectiontitle (1.4rem), .cm-kpi__num (1.7rem), the About-page
       hero title's clamp() (decorative, deferral #3), and the body 15px base (deferral #11 -
       do not touch). */
    --cm-fs-72:  .72rem;
    --cm-fs-78:  .78rem;
    --cm-fs-85:  .85rem;
    --cm-fs-90:  .9rem;
    --cm-fs-100: 1rem;
    --cm-fs-110: 1.1rem;
    --cm-fs-120: 1.2rem;
    --cm-fs-160: 1.6rem;
    --cm-fs-200: 2rem;

    /* Spacing scale (T3.4 / A8, 2026-07-14 CSS assessment). --cm-space-page is the one
       page-level outer-breathing-room value actually in use (.cm-panel's centering margin,
       .cm-explorer__welcome's padding) - both were already 3rem, so this is documentation, not
       a value change; .cm-login__card's 2.5rem is component padding, not this "page margin"
       role, and is left as its own literal. --cm-pad-control is a deliberate escape hatch (not
       one of the 8 scale steps): the .55-.65rem control-padding cluster snaps here instead of
       onto --cm-space-3/4 wherever landing on the scale would visibly resize a button/input.
       --cm-stack is the ONE section rhythm value, replacing five different gap values
       (1/1.1/1.25/1.6/2rem) that all served the same "separate this block from the page
       content above it" role - including the former .cm-mt ad hoc patch, which now resolves
       to this token instead of its own private 1rem. */
    --cm-space-1: .15rem;
    --cm-space-2: .3rem;
    --cm-space-3: .5rem;
    --cm-space-4: .75rem;
    --cm-space-5: 1rem;
    --cm-space-6: 1.25rem;
    --cm-space-7: 1.5rem;
    --cm-space-8: 2rem;
    --cm-space-page: 3rem;
    --cm-pad-control: .6rem;
    --cm-stack: 1.25rem;

    /* Control sizing (2026-07-15): ONE size for every button and every input, app-wide —
       the former .5rem/1rem buttons and --cm-pad-control-tall inputs read as consumer-app
       chunky in a data-dense line-of-business tool. Change these four tokens, never a rule. */
    --cm-btn-pad-y:   .35rem;
    --cm-btn-pad-x:   .8rem;
    --cm-control-pad-y: .4rem;
    --cm-control-pad-x: .6rem;
    --cm-control-fs:  var(--cm-fs-90);
}
}

/* --- Reset ------------------------------------------------------------------ */
@layer reset {
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
}

/* --- Base (bare element defaults) -------------------------------------------- */
@layer base {
body {
    font-family: var(--cm-font);
    font-size: 15px;
    line-height: 1.55;
    color: var(--cm-text);
    background: var(--cm-bg);
    -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { line-height: 1.25; margin: 0 0 .5rem; font-weight: 600; letter-spacing: -.01em; }
h1 { font-size: var(--cm-fs-160); }
h2 { font-size: var(--cm-fs-120); }
p  { margin: 0 0 .75rem; }
a  { color: var(--cm-blue-slate); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--cm-cool-steel); outline-offset: 2px; }
}

/* --- Layout (app shell chrome: topbar, sidebar, main, admin shell) ----------- */
@layer layout {
/* Locked app shell: the shell is exactly one viewport tall; the CONTENT scrolls inside
   .cm-main while topbar and sidebar stay put (the sidebar must be full-height at all
   times, never growing/scrolling with the page). 100dvh guards mobile browser chrome. */
.cm-shell { display: flex; flex-direction: column; height: 100vh; height: 100dvh; }

/* Topbar retired (2026-07-15, Clockopus-style shell): brand, notifications, user and sign-out
   all live in the sidebar now — the content pane gets the full viewport height. */
.cm-sidebar__brand { display: flex; align-items: center; gap: var(--cm-space-3); font-weight: 700;
    font-size: var(--cm-fs-110); color: var(--cm-text-inverse);
    padding: var(--cm-space-2) .85rem var(--cm-space-4); margin-bottom: var(--cm-space-3);
    border-bottom: 1px solid rgba(255,255,255,.08); }
.cm-sidebar__brand:hover { color: var(--cm-text-inverse); text-decoration: none; }
.cm-sidebar__brand img { width: 48px; height: 48px; display: block; }
.cm-sidebar__brandtext { display: flex; flex-direction: column; line-height: 1.15; }
.cm-sidebar__badge { display: inline-block; margin-left: var(--cm-space-2); background: var(--cm-danger);
    color: var(--cm-text-inverse); font-size: var(--cm-fs-72); font-weight: 700; line-height: 1;
    padding: .15rem .4rem; border-radius: 999px; vertical-align: text-top; }
.cm-sidebar__user { display: flex; align-items: center; gap: var(--cm-space-3);
    padding: var(--cm-space-4) .85rem; margin-bottom: var(--cm-space-2);
    border-bottom: 1px solid rgba(255,255,255,.08); }
.cm-sidebar__usertext { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.cm-sidebar__username { color: var(--cm-text-inverse); font-weight: 600; font-size: var(--cm-fs-90);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-sidebar__usermeta { color: var(--cm-sidebar-text); font-size: var(--cm-fs-72);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-sidebar__signout { display: inline-flex; flex-shrink: 0; padding: var(--cm-space-2);
    color: var(--cm-sidebar-text); border-radius: var(--cm-radius-sm); }
.cm-sidebar__signout:hover { color: var(--cm-text-inverse); background: rgba(255,255,255,.08); text-decoration: none; }

.cm-search__snippet { color: var(--cm-text-muted); font-size: var(--cm-fs-85); line-height: 1.4; }
.cm-search__snippet mark { background: var(--cm-celadon); color: inherit; padding: 0 .1em; border-radius: 2px; }
.cm-pager { display: flex; align-items: center; gap: .75rem; margin-top: var(--cm-stack); }
.cm-pager__info { color: var(--cm-text-muted); font-size: var(--cm-fs-85); }
/* T6.5 / C5: CSS-drawn chevrons replace the "← Previous"/"Next →" text-glyph arrows — same
   border-triangle technique as .cm-collapse__summary::before (components layer). */
.cm-pager__prev::before, .cm-pager__next::after {
    content: ""; display: inline-block; width: .4rem; height: .4rem;
    border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
}
.cm-pager__prev::before { transform: rotate(135deg); margin-right: .4rem; }
.cm-pager__next::after { transform: rotate(-45deg); margin-left: .4rem; }

.cm-body { display: flex; flex: 1; align-items: stretch; min-height: 0; }

/* Dark left sidebar */
.cm-sidebar { width: 232px; flex: none; background: var(--cm-sidebar-bg);
    padding: 1.1rem var(--cm-space-3); display: flex; flex-direction: column; gap: .15rem;
    overflow-y: auto; }
.cm-sidebar .cm-sidebar__link {
    display: flex; align-items: flex-start; gap: .7rem; padding: var(--cm-pad-control) .85rem;
    border-radius: var(--cm-radius-sm); color: var(--cm-sidebar-text); font-weight: 500;
}
.cm-sidebar .cm-sidebar__link:hover { background: var(--cm-sidebar-hover); color: var(--cm-text-inverse); text-decoration: none; }
.cm-sidebar .cm-sidebar__link.active { background: var(--cm-sidebar-active); color: var(--cm-text-inverse); }
.cm-sidebar .cm-icon { width: 18px; height: 18px; flex: none; }
.cm-sidebar__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cm-sidebar__desc { font-size: var(--cm-fs-72); color: var(--cm-sidebar-text); opacity: .75; line-height: 1.3; white-space: normal; font-weight: 400; }

/* sidebar footer (About / vendor link / build version) — pinned to the bottom */
.cm-sidebar__footer { margin-top: auto; padding-top: var(--cm-space-3); display: flex; flex-direction: column;
    gap: .15rem; border-top: 1px solid rgba(255,255,255,.08); }
/* Single About line (Clockopus-style, 2026-07-15): "About Contract-Management (version)" — the
   About nav entry, vendor link and separate version line collapsed into one footer row; the
   vendor link lives on the About page itself. */
.cm-sidebar__about { display: block; padding: .3rem .85rem .1rem; font-size: var(--cm-fs-78); color: var(--cm-sidebar-text); }
.cm-sidebar__about:hover { color: var(--cm-text-inverse); text-decoration: underline; }
.cm-sidebar__aboutversion { color: rgba(184,199,196,.6); }

.cm-main { flex: 1; min-width: 0; padding: 1.75rem 2.25rem; overflow-y: auto; }
/* FocusOnNavigate (Routes.razor) programmatically focuses the page h1 after every navigation
   for screen readers — keep the focus, drop the visual ring: a heading is not interactive,
   the browser outline reads as a stray frame around the title. This must win over both the
   base-layer :focus-visible rule AND components-layer .cm-toolbar h1 — it does, because `layout`
   is declared after `base`; `.cm-toolbar h1` only ever sets margin, never outline, so the two
   never actually compete despite historically tripping the no-descending-specificity linter. */
.cm-main h1:focus, .cm-main h1:focus-visible { outline: none; }

/* --- Administration shell (two-pane: sub-nav + content) -------------------- */
.cm-admin__head { display: flex; align-items: center; gap: .9rem;
    padding-bottom: 1.1rem; margin-bottom: 1.5rem; border-bottom: 1px solid var(--cm-border); }
.cm-admin__icon { display: inline-flex; align-items: center; justify-content: center;
    width: 2.6rem; height: 2.6rem; flex: none; border-radius: 50%;
    background: var(--cm-tint); color: var(--cm-blue-slate); }
.cm-admin__icon svg { width: 1.35rem; height: 1.35rem; }
.cm-admin__title { font-size: var(--cm-fs-160); font-weight: 600; letter-spacing: -.01em; margin: 0; }
.cm-admin__subtitle { color: var(--cm-text-muted); margin: .15rem 0 0; }

.cm-admin__body { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: 2rem; align-items: start; }
.cm-admin__nav { position: sticky; top: 1.75rem; display: flex; flex-direction: column; gap: 1.25rem; }
.cm-admin__group { display: flex; flex-direction: column; gap: .15rem; }
.cm-admin__group-label { font-size: var(--cm-fs-72); font-weight: 600; text-transform: uppercase;
    letter-spacing: .06em; color: var(--cm-text-muted); padding: 0 .7rem; margin-bottom: .3rem; }
.cm-admin__link { display: block; padding: .45rem .7rem; border-radius: var(--cm-radius-sm);
    color: var(--cm-text); font-weight: 500; text-decoration: none; box-shadow: inset 3px 0 0 transparent; }
.cm-admin__link:hover { background: var(--cm-tint); text-decoration: none; }
.cm-admin__link.active { background: var(--cm-tint); color: var(--cm-blue-slate-dark);
    font-weight: 600; box-shadow: inset 3px 0 0 var(--cm-blue-slate); }
.cm-admin__content { min-width: 0; }
}

/* --- Components (widgets: cards, buttons, tables, forms, badges, dialog, ...) */
@layer components {
/* --- Surfaces -------------------------------------------------------------- */
/* Shared card-like surface base (T3.2 / A6, merge-candidate #3): .cm-card, .cm-login__card,
   .cm-explorer__tree, .cm-kpi, .cm-about__fact, .cm-about__card all declared the identical
   background/border/radius/shadow four-up - grouped here once; each selector's own rule
   (at its topical location) keeps only its padding and other unique layout declarations. */
.cm-card, .cm-login__card, .cm-explorer__tree, .cm-kpi, .cm-about__fact, .cm-about__card {
    background: var(--cm-surface); border: 1px solid var(--cm-border);
    border-radius: var(--cm-radius); box-shadow: var(--cm-shadow);
}
.cm-card { padding: 1.25rem 1.5rem; margin-bottom: 1.1rem; }
.cm-cards .cm-card { margin-bottom: 0; }   /* grid uses gap for spacing */

/* Header rule (T5.6 / B8): wrap the h1 in .cm-toolbar ONLY when the page has header-level
   actions (a button/link beside the title) - a bare h1 with nothing to align against gets no
   wrapper. This was previously a 9/9 split (toolbar-with-nothing-to-toolbar vs plain h1) with two
   different h1-to-lead spacings; now one rule, one rhythm. */
.cm-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    margin-bottom: 1rem; flex-wrap: wrap; }
.cm-toolbar h1 { margin: 0; }
/* Group for a toolbar with more than one header-level action (first user: Dossier types'
   Import-from-JSON beside + New template) — keeps space-between pinning h1 left, buttons right. */
.cm-toolbar__actions { display: flex; align-items: center; gap: var(--cm-space-3); }
.cm-empty { color: var(--cm-text-muted); padding: .5rem 0; }
.cm-section__title { margin-top: var(--cm-stack); color: var(--cm-text); font-size: var(--cm-fs-110); }
.cm-lead { color: var(--cm-text-muted); margin: -.25rem 0 1.25rem; }

/* --- Dashboard stat cards (clickable, clean) ------------------------------ */
.cm-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 1rem; margin: var(--cm-stack) 0 var(--cm-stack); }
.cm-stat { display: flex; flex-direction: column; gap: .3rem; }
.cm-stat__label { color: var(--cm-text-muted); font-size: var(--cm-fs-78); text-transform: uppercase; letter-spacing: .04em; }
.cm-stat__value { font-size: var(--cm-fs-200); font-weight: 600; line-height: 1.1; color: var(--cm-blue-slate); }
.cm-stat__hint { color: var(--cm-text-muted); font-size: var(--cm-fs-78); }
a.cm-card { text-decoration: none; color: inherit;
    transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease; }
a.cm-card:hover { text-decoration: none; border-color: var(--cm-cool-steel);
    box-shadow: var(--cm-shadow-hover); transform: translateY(-2px); }

/* Task-first home tiles */
.cm-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .9rem; margin-bottom: var(--cm-stack); }
.cm-tile { display: flex; flex-direction: column; gap: .5rem; text-decoration: none; color: var(--cm-text); position: relative; }
.cm-tile__title { font-weight: 600; font-size: var(--cm-fs-110); }
.cm-tile__hint { color: var(--cm-text-muted); font-size: var(--cm-fs-90); }
.cm-actionrow { display: block; text-decoration: none; color: var(--cm-text); margin-bottom: .9rem; }
.cm-statline { color: var(--cm-text-muted); font-size: var(--cm-fs-78); margin-top: var(--cm-stack); }
/* Home tiles: clickable cards — icon + title + hint + trailing arrow. a.cm-card already lifts
   on hover (app.css:301); no coloured border (style guide: no coloured card borders). */
.cm-tile__ic { width: 24px; height: 24px; color: var(--cm-blue-slate); margin-bottom: var(--cm-space-1); }
/* The search tile is a form, not a link: the query box sits at the bottom of the tile and the tile
   keeps the same height as its siblings in the grid (issue #16). */
.cm-tile--search { justify-content: flex-start; }
.cm-tile__search { margin-top: auto; padding-top: var(--cm-space-3); }
.cm-tile__go { position: absolute; top: 1.25rem; right: 1.5rem; color: var(--cm-cool-steel);
    font-size: var(--cm-fs-110); transition: transform .12s ease, color .12s ease; }
a.cm-tile:hover .cm-tile__go { transform: translateX(3px); color: var(--cm-blue-slate); }
/* Positive "nothing to do" confirmation — centered (fixes off-center empty text), no card frame. */
.cm-emptyok { text-align: center; color: var(--cm-success); padding: var(--cm-space-6) 0; font-weight: 500; }
.cm-statline__link { font-weight: inherit; }

/* --- Buttons --------------------------------------------------------------- */
.cm-button { display: inline-flex; align-items: center; gap: .4rem; padding: var(--cm-btn-pad-y) var(--cm-btn-pad-x);
    border: 1px solid transparent; border-radius: var(--cm-radius-sm); background: var(--cm-blue-slate);
    color: var(--cm-text-inverse); font: inherit; font-size: var(--cm-control-fs); font-weight: 500; cursor: pointer; transition: background .12s ease; }
.cm-button:hover { background: var(--cm-blue-slate-dark); text-decoration: none; color: var(--cm-text-inverse); }
/* Button variant policy (T5.3 / B5): ghost = secondary action, soft = tertiary action (see
   .cm-button--soft below), danger = destructive action. .cm-button--secondary retired (its one
   use point is now ghost - it was never a distinct semantic, just an unused third grey). */
.cm-button--ghost { background: transparent; color: var(--cm-blue-slate); border-color: var(--cm-border); }
.cm-button--ghost:hover { background: var(--cm-tint-cool); color: var(--cm-blue-slate); }
.cm-button--danger { background: var(--cm-danger); color: var(--cm-text-inverse); }
.cm-button--danger:hover { background: var(--cm-danger-dark); color: var(--cm-text-inverse); }
.cm-button--sm { padding: .25rem var(--cm-space-4); font-size: var(--cm-fs-78); }
/* .cm-linkbutton (T5.3 / B5, renamed from the modifier-only .cm-button--link): a standalone
   text-link-styled button/anchor that is NEVER combined with the .cm-button base class - it is
   its own block, not a .cm-button modifier. That "modifier that must not combine with its base"
   shape is exactly what produced the five broken ghost buttons fixed in T2.1/B1. */
.cm-linkbutton { background: transparent; color: var(--cm-blue-slate); padding: 0; border: none;
    font: inherit; font-weight: 500; cursor: pointer; text-decoration: underline;
    text-underline-offset: 2px; text-decoration-color: var(--cm-cool-steel); }
.cm-linkbutton:hover { color: var(--cm-blue-slate-dark); text-decoration-color: currentColor; }
.cm-linkbutton:disabled { color: var(--cm-text-muted); cursor: default; text-decoration: none; }

/* Status-line docs disclosure: cancel the inherited .cm-collapse margin-top so the summary sits on
   the signals' baseline while collapsed; once expanded, the panel spans the full status-line row
   instead of sizing to a chip's width (M-6) — attribute selector after the base one, ascending
   specificity, lint-safe (no-descending-specificity). */
.cm-statusline__docs { margin-top: 0; }
.cm-statusline__docs[open] { flex-basis: 100%; }

/* Actions menu: native <details>/<summary> (same no-JS idiom as .cm-collapse). The summary is
   styled as a soft button; the list floats below it. margin-left: auto right-aligns the whole
   Actions cluster within .cm-statusline per spec §2.4 (M-6) — folded into this rule rather than a
   second `.cm-menu { … }` block to keep `no-duplicate-selectors` clean. */
.cm-menu { position: relative; display: inline-block; margin-left: auto; }
.cm-menu__trigger { list-style: none; cursor: pointer; }
.cm-menu__trigger::-webkit-details-marker { display: none; }
.cm-menu__list { position: absolute; top: calc(100% + var(--cm-space-2)); right: 0; z-index: 900;
    min-width: 15rem; display: flex; flex-direction: column; padding: var(--cm-space-2);
    background: var(--cm-surface); border: 1px solid var(--cm-border); border-radius: var(--cm-radius-sm);
    box-shadow: var(--cm-shadow-hover); }
.cm-menu__item { display: flex; align-items: center; gap: var(--cm-space-3); position: relative;
    padding: var(--cm-space-3) var(--cm-space-4); background: transparent; border: 0; border-radius: var(--cm-radius-sm);
    font: inherit; color: var(--cm-text); text-align: left; cursor: pointer; }
.cm-menu__item:hover { background: var(--cm-tint-cool); }
.cm-menu__item:disabled { color: var(--cm-text-muted); cursor: default; background: transparent; }
/* The Upload menu item wraps a hidden native file input covering the row (click = open picker). */
.cm-menu__file { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
/* Toolbar Upload button (DossierDetail dense rebuild §G): a .cm-button-styled <label> that wraps a
   hidden native file input covering it — same hidden-input idiom as .cm-menu__file / .cm-dropzone__input,
   but for a compact toolbar button rather than a menu row or a full dropzone. relative+overflow clip the
   input to the button; the input accepts both a click (opens the picker) and a native file drop. */
.cm-filelabel { position: relative; overflow: hidden; }
.cm-filelabel__input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.cm-filelabel__input:disabled { cursor: default; }

/* --- Model list (AI providers) -------------------------------------------- */
/* Bare flex-column list reset (T3.2 / A6, merge-candidate #5): .cm-modellist, .cm-runlog__list,
   .cm-chat-sessions__list and .cm-completeness__list all reset an unbulleted list to a vertical
   flex stack identically - grouped once; each keeps its own gap + any other unique declaration. */
.cm-modellist, .cm-runlog__list, .cm-chat-sessions__list, .cm-completeness__list {
    list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column;
}
.cm-modellist__item { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: .5rem .25rem; border-bottom: 1px solid var(--cm-border); }
.cm-modellist__item:last-child { border-bottom: none; }
.cm-modellist__name { min-width: 0; }

/* --- Tables ---------------------------------------------------------------- */
.cm-table { width: 100%; border-collapse: collapse; background: var(--cm-surface);
    border: 1px solid var(--cm-border); border-radius: var(--cm-radius); overflow: hidden; }
/* Content-cell font size is standardized on the base so EVERY cm-table matches the Dossier-facts
   reference (Christian 2026-09-13): one content size across all tables. Header th keeps its own
   smaller uppercase size via the more-specific .cm-table thead th rule below. The cockpit (higher
   specificity) still sets its own denser sizes and is unaffected. */
.cm-table th, .cm-table td { text-align: left; padding: var(--cm-space-4) .9rem; border-bottom: 1px solid var(--cm-border); font-size: var(--cm-fs-85); }
/* Dense table variant (DossierDetail dense rebuild, issue #4 §G): slim rows for the utilitarian
   data-tool surfaces (facts, the in-dossier doc list, the optional-fields + structure tables).
   Same specificity as the base cell rule above and declared immediately after it, so it overrides
   the cell padding by source order while every higher-specificity .cm-table cell rule that follows
   (thead/last-child/hover/selected) still wins over it — no descending specificity. Padding only. */
.cm-table--dense th, .cm-table--dense td { padding: var(--cm-space-2) var(--cm-space-3); }
.cm-table thead th { background: var(--cm-tint-cool); color: var(--cm-blue-slate-dark); font-weight: 600; font-size: var(--cm-fs-78);
    text-transform: uppercase; letter-spacing: .03em; }
.cm-table tbody tr:last-child td { border-bottom: none; }
.cm-table tbody tr:hover { background: var(--cm-surface-alt); }
/* current row for a master/detail table (e.g. Settings > Groups' group list) — reuses
   --cm-tint, the shared "subtle selected/hover fill" token */
.cm-table tbody tr.cm-table__row--selected { background: var(--cm-tint); }

/* --- Lists ------------------------------------------------------------------
   Generic unbulleted list of items each ending in an inline action (e.g. group
   members with a trailing Remove button). Deliberately plain — cm-filesteps__files
   is the file-staging-specific sibling of this shape. */
.cm-list { list-style: none; padding: 0; margin: .5rem 0 0; display: grid; gap: .4rem; }
.cm-list li { display: flex; align-items: center; gap: .5rem; }

/* --- Forms ----------------------------------------------------------------- */
.cm-form { display: flex; flex-direction: column; gap: var(--cm-space-4); max-width: 34rem; }
.cm-form__field { display: flex; flex-direction: column; gap: var(--cm-space-1); }
.cm-form__field > label { font-size: var(--cm-fs-85); color: var(--cm-text-muted); }
/* Checkbox group with per-option explanations (first user: the template editor's Add-field
   dialog). Each option is a bordered, clickable row — bare native checkboxes floating in the
   form read as an afterthought; the row makes the whole option one obvious touch target. */
.cm-checkgroup { border: 0; padding: 0; margin: var(--cm-space-5) 0; display: flex; flex-direction: column; gap: var(--cm-space-3); }
.cm-checkgroup__item { display: flex; align-items: flex-start; gap: var(--cm-space-4); cursor: pointer;
    padding: var(--cm-space-4); border: 1px solid var(--cm-border); border-radius: var(--cm-radius-sm);
    background: var(--cm-surface); transition: background .12s ease, border-color .12s ease; }
.cm-checkgroup__item:hover { background: var(--cm-surface-alt); border-color: var(--cm-blue-slate); }
.cm-checkgroup__item:has(input:checked) { background: var(--cm-tint-cool); border-color: var(--cm-blue-slate); }
.cm-checkgroup__item input { width: 1.05rem; height: 1.05rem; margin: var(--cm-space-1) 0 0; flex-shrink: 0; cursor: pointer; }
.cm-checkgroup__desc { display: block; color: var(--cm-text-muted); font-size: var(--cm-fs-85); font-weight: 400; margin-top: var(--cm-space-1); }
.cm-form__field label { font-weight: 500; font-size: var(--cm-fs-90); color: var(--cm-text-muted); }
.cm-input { padding: var(--cm-control-pad-y) var(--cm-control-pad-x); border: 1px solid var(--cm-border); border-radius: var(--cm-radius-sm);
    font: inherit; font-size: var(--cm-control-fs); background: var(--cm-surface); color: var(--cm-text); }
.cm-input:focus { border-color: var(--cm-cool-steel); outline: none; box-shadow: var(--cm-focus-ring); }
.cm-input--full { width: 100%; }
.cm-input--xs { width: 5rem; }
/* T5.5 / B7: checkboxes are native/unstyled everywhere in the app with no focus/brand treatment -
   one accent-color rule closes that gap without a bespoke checkbox component. */
input[type="checkbox"] { accent-color: var(--cm-blue-slate); }

/* compact "Template & extraction" bar: inline select & buttons on one row */
.cm-tplbar { display: flex; flex-direction: column; gap: .75rem; }
.cm-tplbar__row { display: flex; align-items: center; gap: var(--cm-space-3); flex-wrap: wrap; }
.cm-tplbar__row .cm-input { flex: 1 1 14rem; min-width: 12rem; }

/* two equal-width columns (e.g. Template & extraction | Upload) */
.cm-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.4rem; align-items: start; }
.cm-2col .cm-card { margin-bottom: 0; }
/* A .cm-2col column that stacks more than one card (DossierDetail rebuild, issue #4: Countries +
   Effective-date left, Documents + In-this-dossier + Structure right) needs its own vertical
   rhythm - .cm-2col .cm-card above already zeroes each card's margin-bottom, so this column
   wrapper supplies the gap between them instead. */
.cm-2col__col { display: flex; flex-direction: column; gap: 1.1rem; }
.cm-filters { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--cm-space-3) 1rem; width: 100%; margin-bottom: 1.1rem; }
/* Merged toolbar action slot (Cockpit redesign): spans the filters row's full width and right-aligns
   its buttons — the existing .cm-filters row IS the toolbar, this is not a new one-off container. */
.cm-filters__actions { grid-column: 1 / -1; display: flex; align-items: center; justify-content: flex-end;
    gap: var(--cm-space-3); margin-left: auto; flex-wrap: wrap; }
.cm-pre { background: var(--cm-surface-alt); border: 1px solid var(--cm-border); border-radius: var(--cm-radius-sm);
    padding: .75rem; overflow: auto; max-height: 28rem; font-size: var(--cm-fs-78); white-space: pre-wrap; word-break: break-word; }
.cm-docview { width: 100%; height: 70vh; border: 1px solid var(--cm-border); border-radius: var(--cm-radius-sm); background: var(--cm-surface); }

/* --- Cockpit (transposed matrix) ------------------------------------------ */
/* Excel-like frozen panes: scroll both axes; first column + header row stay put. */
/* overflow-x here is what keeps horizontal scroll INSIDE the card — never a page-level scrollbar */
.cm-cockpit { overflow: auto; max-height: 78vh; border: 1px solid var(--cm-border); border-radius: var(--cm-radius); }
.cm-cockpit__table { border: none; min-width: 100%; white-space: nowrap; }
/* #e7efee tokenized to --cm-tint (nearest existing "subtle fill" token) — both rules touched by this redesign. */
.cm-cockpit__table thead th { position: sticky; top: 0; z-index: 2; background: var(--cm-tint); }
.cm-cockpit__rowhead { position: sticky; left: 0; z-index: 1; background: var(--cm-tint); font-weight: 600; max-width: 22rem; }
.cm-cockpit__table thead th.cm-cockpit__rowhead { z-index: 3; }   /* top-left corner above both */
.cm-cockpit__table tbody .cm-cockpit__rowhead { background: var(--cm-surface); }
.cm-cockpit__table .cm-cell--num { text-align: right; font-variant-numeric: tabular-nums; }
.cm-cockpit__sortable { cursor: pointer; user-select: none; }
.cm-cockpit__sortable:hover { background: var(--cm-tint-hover); }
/* T6.5 / C5 (final-review I1): sort direction as CSS-drawn chevrons — same border-triangle
   technique as .cm-pager (no text glyphs). .cm-sort without a direction renders nothing. */
.cm-sort { display: inline-block; margin-left: .3rem; }
.cm-sort--asc::after, .cm-sort--desc::after {
    content: ""; display: inline-block; width: .34rem; height: .34rem;
    border-right: 2px solid var(--cm-text-muted); border-bottom: 2px solid var(--cm-text-muted);
}
.cm-sort--asc::after { transform: rotate(-135deg) translate(-1px, -1px); }
.cm-sort--desc::after { transform: rotate(45deg); }
.cm-cell--draft { color: var(--cm-text-muted); font-style: italic; }
/* Unverified/conflict cell markers (redesign 2026-07-14): verified is the silent default; only these two
   exceptions are marked, quietly, with no layout-shifting pill. */
.cm-cell--unverified { border-bottom: 2px dotted var(--cm-warn-ink); }
.cm-cell__conflict { margin-left: .35rem; color: var(--cm-danger); cursor: help; }
.cm-resultcount { color: var(--cm-text-muted); font-size: var(--cm-fs-90); margin: 1.25rem 0 .75rem; }

/* --- Collapsible section (native details/summary) ------------------------- */
.cm-collapse { margin-top: var(--cm-stack); }
.cm-collapse__summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: .5rem;
    font-size: var(--cm-fs-110); font-weight: 600; color: var(--cm-text); letter-spacing: -.01em;
    padding: .35rem 0; user-select: none; }
.cm-collapse__summary::-webkit-details-marker { display: none; }
.cm-collapse__summary::before { content: ""; width: .55rem; height: .55rem; flex: none;
    border-right: 2px solid var(--cm-cool-steel); border-bottom: 2px solid var(--cm-cool-steel);
    transform: rotate(-45deg); transition: transform .15s ease; margin-left: .15rem; }
.cm-collapse[open] > .cm-collapse__summary::before { transform: rotate(45deg); }
.cm-collapse__summary:hover { color: var(--cm-blue-slate); }
.cm-collapse > *:not(summary):first-of-type { margin-top: var(--cm-space-3); }

/* --- File drop zone -------------------------------------------------------- */
.cm-dropzone { position: relative; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: .45rem; text-align: center; padding: 2.4rem 1.5rem;
    border: 2px dashed var(--cm-cool-steel); border-radius: var(--cm-radius); background: var(--cm-surface-alt);
    color: var(--cm-text-muted); cursor: pointer; transition: border-color .12s ease, background .12s ease; }
.cm-dropzone:hover { border-color: var(--cm-blue-slate); background: var(--cm-tint-cool); }
.cm-dropzone--over { border-color: var(--cm-blue-slate); background: var(--cm-tint-cool);
    box-shadow: var(--cm-focus-ring); }
.cm-dropzone--busy { opacity: .6; pointer-events: none; }
/* native file input covers the zone so browser drag-drop works without JS */
.cm-dropzone__input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.cm-dropzone__input:disabled { cursor: default; }
/* Icon stroke-weight convention (T6.5 / C5, 2026-07-14 CSS assessment): every inline-SVG icon in the
   app uses stroke-width 2 at 16-20px (sidebar/topbar/bell/admin icons, small chrome icons) or
   stroke-width 1.5 at >=32px (dropzone icons, Explorer/Assistant empty-state icons) - the three
   previously-undocumented weights (2 / 1.6 / 1.5) collapse onto this one rule. Applied on the <svg>
   itself (these are hand-inlined markup, not a shared component), not here in CSS, but documented
   once, centrally, so new icons follow it instead of picking a fourth weight. */
.cm-dropzone__icon { width: 34px; height: 34px; color: var(--cm-cool-steel); margin-bottom: .15rem; }
.cm-dropzone__title { font-weight: 600; font-size: var(--cm-fs-100); color: var(--cm-text); }
.cm-dropzone__hint { font-size: var(--cm-fs-85); }

/* Drop-anywhere overlay: hidden until JS flips .cm-dropoverlay--active on window dragenter.
   The <InputFile> inside covers the viewport so the native drop lands on it (reuses OnFilesSelected). */
.cm-dropoverlay { position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center;
    background: var(--cm-scrim); opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .1s ease; }
.cm-dropoverlay--active { opacity: 1; visibility: visible; pointer-events: auto; }
.cm-dropoverlay__label { position: relative; display: flex; align-items: center; justify-content: center;
    width: min(46rem, 82vw); height: 60vh; border: 2px dashed var(--cm-text-inverse); border-radius: var(--cm-radius); }
.cm-dropoverlay__input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: copy; }
.cm-dropoverlay__text { color: var(--cm-text-inverse); font-size: var(--cm-fs-120); font-weight: 500; pointer-events: none; }

/* Guided filing (/file) */
.cm-filesteps { margin-bottom: 1rem; }
.cm-filesteps__files { list-style: none; padding: 0; margin: .75rem 0 0; display: grid; gap: .5rem; }
.cm-filesteps__size { color: var(--cm-text-muted); font-size: var(--cm-fs-78); }
.cm-filesteps__suggest { list-style: none; padding: 0; margin: .5rem 0 0; display: flex; flex-wrap: wrap; gap: .5rem; }
/* Inline "+ Create partner …" button needs air to the search box beside/above it. */
.cm-filesteps__create { margin: var(--cm-space-3) 0 0 var(--cm-space-3); }
.cm-filesteps__choice { display: block; margin: .25rem 0; }

/* --- Explorer ---------------------------------------------------------------
   Hover/active reuse --cm-tint (documented above as "subtle selected/hover
   fill") and the --cm-admin__link.active pattern (blue-slate accent bar) —
   the dark --cm-sidebar-hover/--cm-sidebar-active tokens are tuned for the
   dark --cm-sidebar-bg and would be illegible on this light content surface. */
.cm-explorer { display: grid; grid-template-columns: minmax(230px, 320px) 1fr; gap: 1.25rem; align-items: start; }
.cm-explorer__tree { display: flex; flex-direction: column; gap: .1rem;
    padding: var(--cm-space-3) var(--cm-space-3); position: sticky; top: 1.75rem; }
.cm-explorer__children { margin-left: .7rem; padding-left: var(--cm-space-3); border-left: 1px solid var(--cm-border);
    display: flex; flex-direction: column; gap: .1rem; }
.cm-explorer__node { display: flex; align-items: center; gap: .5rem; width: 100%; text-align: left;
    padding: .38rem var(--cm-space-3); border: 0; background: none; border-radius: var(--cm-radius-sm);
    cursor: pointer; color: var(--cm-text); font-size: var(--cm-fs-90); line-height: 1.3; }
.cm-explorer__node:hover { background: var(--cm-tint); }
.cm-explorer__node--active { background: var(--cm-tint); color: var(--cm-blue-slate-dark); font-weight: 600; box-shadow: inset 3px 0 0 var(--cm-blue-slate); }
.cm-explorer__node--vault { font-weight: 600; font-size: var(--cm-fs-100); }
.cm-explorer__node .cm-icon { width: 16px; height: 16px; flex: none; color: var(--cm-cool-steel); }
.cm-explorer__node--active .cm-icon { color: var(--cm-blue-slate); }
.cm-explorer__label { flex: 1; min-width: 0; }
.cm-explorer__count { flex: none; background: var(--cm-tint); color: var(--cm-text-muted); font-size: var(--cm-fs-72);
    font-weight: 600; line-height: 1; padding: .18rem .45rem; border-radius: 999px; font-variant-numeric: tabular-nums; }
.cm-explorer__node--active .cm-explorer__count { background: var(--cm-surface); }
.cm-explorer__emptyhint { padding: .3rem var(--cm-space-3); margin: 0; }

/* Explorer "nothing selected" welcome panel — a finished teaching state, not a bare stub. */
.cm-explorer__welcome { display: flex; flex-direction: column; align-items: center;
    text-align: center; padding: var(--cm-space-page) 2rem; gap: .35rem; }
.cm-explorer__welcome h2 { margin: 0; color: var(--cm-text); }
.cm-explorer__welcomeicon { width: 40px; height: 40px; color: var(--cm-text-muted); opacity: .7; margin-bottom: .4rem; }
.cm-explorer__welcomelead { margin: 0; color: var(--cm-text-muted); }
/* Explorer content panel (2026-07-15 UX feedback, 2nd round): partner/dossier panels use the
   same .cm-detail label-over-value grid as the document header, with the child lists as tables. */
.cm-explorer__doctable { margin-top: var(--cm-space-5); }
/* Issue #3 (customer feedback 2026-09-12): the summary labels above the explorer tables must
   share the tables' column edges. Table cells carry .9rem inline padding, so the summary dl
   gets the same inline padding and a fixed two-column grid — PARTNER sits exactly over
   DOSSIER, DOSSIERS over DOCUMENTS. The 50% column split only applies to two-column tables
   (:not(:only-child)); the dossier panel's single-column document table keeps full width. */
.cm-explorer__summary { grid-template-columns: 1fr 1fr; padding-inline: .9rem; }
.cm-table.cm-explorer__doctable th:not(:only-child), .cm-table.cm-explorer__doctable td:not(:only-child) { width: 50%; }
.cm-completeness__table { margin-top: var(--cm-space-3); }
.cm-explorer__welcomelist { margin: .8rem 0 0; padding: 0; list-style: none; display: flex;
    flex-direction: column; gap: .35rem; color: var(--cm-text-muted); font-size: var(--cm-fs-90); max-width: 34rem; }
/* Explorer's collapse rules moved into the single 900px breakpoint (utilities layer, T3.5 / A9) */

/* --- Badges / lamps (shared pill component, T3.1 / A5, 2026-07-14 CSS assessment) ----------
   .cm-badge and .cm-lamp were declaration-identical (merge-candidate #1) — merged into one
   pill base; both class names stay valid so existing razor markup (cm-lamp--*) is untouched.
   The color-pair modifiers below collapse five duplicate bg/ink declarations onto the Stage-1
   semantic ink tokens (merge-candidate #2). A few group in controls that are not badges/lamps
   themselves but happen to share the exact same pair byte-for-byte (some pills' own
   layout-only rule stays in the topbar section above; cm-alert--ok stays semantically a
   message variant) — grouped here purely because the declared value is identical, same
   precedent as the pre-existing --warn/--amber pairing. */
.cm-badge, .cm-lamp { display: inline-block; padding: .15rem var(--cm-space-3); border-radius: 999px; font-size: var(--cm-fs-78); font-weight: 600;
    white-space: nowrap; /* a pill must never wrap mid-word ("auto-/confirmed") */ }
/* A badge trailing text needs breathing room ("P10Y[verified]", "Facts[4 to review]" read as one
   token) — cover the two places a pill directly follows inline text: table cells and headings. */
td .cm-badge, h1 .cm-badge, h2 .cm-badge, h3 .cm-badge { margin-left: var(--cm-space-2); }
/* Dedicated status column of the dossier facts table: pills align in their own column, so no
   text-trailing indent — cancel it; spacing between clustered pills now comes from .cm-badge-group. */
td.cm-factstatus .cm-badge { margin-left: 0; }
/* Shared cluster: any run of badges (STATUS column, the progress badge) gets one token gap and wraps
   cleanly instead of touching (2026-09-02 extraction-progress-ux). One central rule. */
.cm-badge-group { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--cm-space-2); }

/* celadon / celadon-ink — affirmative: active, manual-sourced, ok, on-time, role pill */
.cm-badge--active, .cm-badge--manual, .cm-alert--ok, .cm-lamp--green {
    background: var(--cm-celadon); color: var(--cm-celadon-ink);
}
/* dust-grey / dust-ink — neutral: inactive, contract-sourced, and (T6.2 / C2, 2026-07-14 CSS
   assessment) --soft, which used to sit on petal-frost pink alongside the true danger pair below —
   pink is now danger-family ONLY, so every non-danger "soft" badge (kind/status/amendment labels)
   moved here onto the same neutral dust pair as --inactive/--contract. */
.cm-badge--inactive, .cm-badge--contract, .cm-badge--soft { background: var(--cm-dust-grey); color: var(--cm-dust-ink); }
/* petal-frost / danger — conflict + overdue/red time states */
.cm-badge--conflict, .cm-lamp--overdue, .cm-lamp--red { background: var(--cm-petal-frost); color: var(--cm-danger); }
/* cool-steel / steel-ink — derived value, dossier type */
.cm-badge--derived, .cm-badge--type { background: var(--cm-cool-steel); color: var(--cm-steel-ink); }
/* warn-bg / warn-ink — needs review / expires soon (already shared pre-merge) */
.cm-badge--warn, .cm-lamp--amber { background: var(--cm-warn-bg); color: var(--cm-warn-ink); }
/* standalones — no duplicate partner within the badge/lamp family */
.cm-lamp--none { background: var(--cm-dust-grey); color: var(--cm-text-muted); }
.cm-badge--end { background: var(--cm-blue-slate); color: var(--cm-text-inverse); }   /* template's designated end-of-term field marker */

/* --- Detail list ----------------------------------------------------------- */
.cm-detail { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: .75rem 1.5rem; margin: 0; }
.cm-detail dd { margin: .1rem 0 0; }

/* --- Messages -------------------------------------------------------------- */
/* .cm-error retired T5.1/B2: the app's single error/info idiom is now .cm-alert
   .cm-alert--error|--ok everywhere (grep-confirmed zero remaining .cm-error message
   sites; .cm-error-inline below is a distinct structural "required" tag, unrelated). */

/* Inline alert for form/extraction errors: subtle tint + leading icon, wraps a long
   message cleanly inside the box (no raw payload overflow, no coloured card border). */
.cm-alert { display: flex; align-items: flex-start; gap: var(--cm-space-3); margin: var(--cm-stack) 0 var(--cm-space-5);
    padding: .7rem .85rem; border-radius: var(--cm-radius); font-size: var(--cm-fs-90); line-height: 1.45;
    overflow-wrap: anywhere; }
.cm-alert__icon { flex: none; width: 1.15rem; height: 1.15rem; margin-top: .05rem; }
.cm-alert__text { min-width: 0; }
.cm-alert--error { background: var(--cm-danger-tint); color: var(--cm-danger); }

/* --- Login screen ---------------------------------------------------------- */
.cm-login { min-height: 100vh; display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, #dceae8 0%, #e9e3dd 55%, #f5dde1 100%); padding: 1.5rem; }
.cm-login__card { padding: 2.5rem 2.25rem; width: 100%; max-width: 24rem; text-align: center; }
.cm-login__brand { display: flex; align-items: center; justify-content: center; gap: var(--cm-space-3);
    font-size: var(--cm-fs-120); font-weight: 600; margin-bottom: .4rem; color: var(--cm-blue-slate); }
.cm-login__brand img { width: 32px; height: 32px; }
.cm-login__tagline { color: var(--cm-text-muted); margin-bottom: 1.75rem; }
.cm-login__button { width: 100%; justify-content: center; padding: var(--cm-pad-control) 1rem; }
.cm-login__footer { margin-top: 1.75rem; color: var(--cm-cool-steel); font-size: var(--cm-fs-78); letter-spacing: .02em; }

/* --- Blazor error UI ------------------------------------------------------- */
#blazor-error-ui { display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000;
    padding: .75rem 1.25rem; background: var(--cm-petal-frost); color: var(--cm-petal-ink);
    border-top: 1px solid var(--cm-petal-border); box-shadow: 0 -2px 12px rgba(0,0,0,.08); }
#blazor-error-ui .reload { color: var(--cm-petal-ink); text-decoration: underline; margin-left: .5rem; }
#blazor-error-ui .dismiss { cursor: pointer; float: right; }

/* --- Dialog (CmDialog shared component, T4.1, 2026-07-14 CSS assessment B4; scroll model and
   backdrop padding tokenized in the Stage-4a review follow-up wave) -
   Backdrop + centered card; the ESC/backdrop-mousedown/focus-on-open behavior lives in the
   component's C#, not here. Two sizes: sm (default — confirm dialogs) and md (wider —
   edit-form dialogs added in a later Stage-4 task). Scroll lives on .cm-dialog__body, not the
   card: header and footer stay pinned, only the body scrolls when content overflows the card's
   max-height. Two literals below stay un-tokenized on purpose (same "documented keep" convention
   as .cm-login__card's 2.5rem above): the card's calc() viewport gutter (2.5rem — a viewport-
   relative margin, not a spacing-scale value) and the close button's own tight .2rem/.35rem
   click-target padding (between --cm-space-1/.15rem and --cm-space-2/.3rem; landing on either
   token would visibly resize the control). */
.cm-dialog__backdrop { position: fixed; inset: 0; z-index: 1000; background: var(--cm-scrim);
    display: flex; align-items: center; justify-content: center; padding: var(--cm-space-6); }
.cm-dialog { background: var(--cm-surface); border-radius: var(--cm-radius); box-shadow: var(--cm-shadow-hover);
    width: 100%; max-height: calc(100vh - 2.5rem); display: flex; flex-direction: column; }
.cm-dialog--sm { max-width: 26rem; }
.cm-dialog--md { max-width: 38rem; }
.cm-dialog--lg { max-width: 54rem; }
/* Section rhythm inside busy dialogs (first user: cockpit Edit columns) — an h3 that starts a
   new section needs clear air above it, and a primary button ending a section needs air below. */
.cm-dialog__section-title { margin: var(--cm-space-7) 0 var(--cm-space-4); padding-top: var(--cm-space-5);
    border-top: 1px solid var(--cm-border); font-size: var(--cm-fs-110); }
.cm-dialog__section-end { margin-top: var(--cm-space-4); }
.cm-table__actions { text-align: right; }
/* Move-to-vault control on the document header: an inline row capped at a sensible width —
   the bare .cm-input select otherwise spans the whole detail grid (full-page Move button). */
.cm-movevault__row { max-width: 28rem; }
.cm-dialog:focus { outline: none; }
.cm-dialog__header { display: flex; align-items: center; justify-content: space-between; gap: var(--cm-space-3);
    padding: var(--cm-space-6) var(--cm-space-6) 0; }
.cm-dialog__title { margin: 0; font-size: var(--cm-fs-110); }
.cm-dialog__close { flex: none; border: 0; background: transparent; color: var(--cm-text-muted);
    font-size: var(--cm-fs-110); line-height: 1; cursor: pointer; padding: .2rem .35rem; border-radius: var(--cm-radius-sm); }
.cm-dialog__close:hover { background: var(--cm-tint); color: var(--cm-text); }
.cm-dialog__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--cm-space-5) var(--cm-space-6); }
.cm-dialog__footer { display: flex; justify-content: flex-end; gap: var(--cm-space-3);
    padding: 0 var(--cm-space-6) var(--cm-space-6); }

/* --- Reconnect modal (Blazor Server) ---------------------------------------
   Ported from the .NET template's ReconnectModal.razor.css (T1.4, 2026-07-14 CSS
   assessment A4): the markup is a native <dialog id="components-reconnect-modal">
   (ReconnectModal.razor:3) — blazor.web.js toggles state CLASSES on that same element
   (components-reconnect-show/-retrying/-paused/-resume-failed/-failed) and calls
   showModal()/close() on it. The two rules this replaced (`.components-reconnect-modal`,
   `.components-reconnect-modal > div`) were CLASS selectors that never matched anything
   — the dialog never rendered styled. Colors/radius/backdrop use our tokens; the template's
   own accent blue (#6b9ed2) and rejoin-spinner blue (#0087ff) are replaced with our brand
   primary/cool-steel so the dialog matches the rest of the app. */
.components-reconnect-first-attempt-visible,
.components-reconnect-repeated-attempt-visible,
.components-reconnect-failed-visible,
.components-pause-visible,
.components-resume-failed-visible,
.components-rejoining-animation {
    display: none;
}
/* shape rule kept ahead of the higher-specificity #components-reconnect-modal.state selectors
   below so no-descending-specificity doesn't flag a same-selector reorder */
.components-rejoining-animation { position: relative; width: 80px; height: 80px; }

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible,
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-paused .components-pause-visible,
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible,
#components-reconnect-modal.components-reconnect-retrying,
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible,
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible {
    display: block;
}

#components-reconnect-modal {
    background-color: var(--cm-surface);
    color: var(--cm-text);
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: var(--cm-radius);
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, .3);
    opacity: 0;
    transition: display .5s allow-discrete, overlay .5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity .5s both;
}
#components-reconnect-modal[open] {
    animation: components-reconnect-modal-slideUp 1.5s cubic-bezier(.05, .89, .25, 1.02) .3s,
               components-reconnect-modal-fadeInOpacity .5s ease-in-out .3s;
    animation-fill-mode: both;
}
#components-reconnect-modal::backdrop {
    background-color: var(--cm-scrim);
    animation: components-reconnect-modal-fadeInOpacity .5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp {
    0%   { transform: translateY(30px) scale(.95); }
    100% { transform: translateY(0); }
}
@keyframes components-reconnect-modal-fadeInOpacity {
    0%   { opacity: 0; }
    100% { opacity: 1; }
}
@keyframes components-reconnect-modal-fadeOutOpacity {
    0%   { opacity: 1; }
    100% { opacity: 0; }
}

.components-reconnect-container { display: flex; flex-direction: column; align-items: center; gap: 1rem; }
#components-reconnect-modal p { margin: 0; text-align: center; }
#components-reconnect-modal button { border: 0; background-color: var(--cm-blue-slate);
    color: var(--cm-text-inverse); padding: 4px 24px; border-radius: var(--cm-radius-sm);
    font: inherit; font-weight: 500; cursor: pointer; }
#components-reconnect-modal button:hover  { background-color: var(--cm-blue-slate-dark); }
#components-reconnect-modal button:active { background-color: var(--cm-blue-slate); }

.components-rejoining-animation div { position: absolute; border: 3px solid var(--cm-cool-steel);
    opacity: 1; border-radius: 50%; animation: components-rejoining-animation 1.5s cubic-bezier(0, .2, .8, 1) infinite; }
.components-rejoining-animation div:nth-child(2) { animation-delay: -.5s; }
@keyframes components-rejoining-animation {
    0%    { top: 40px; left: 40px; width: 0; height: 0; opacity: 0; }
    4.9%  { top: 40px; left: 40px; width: 0; height: 0; opacity: 0; }
    5%    { top: 40px; left: 40px; width: 0; height: 0; opacity: 1; }
    100%  { top: 0; left: 0; width: 80px; height: 80px; opacity: 0; }
}

/* --- Extraction run log (upload progress) --------------------------------- */
.cm-runlog { margin-top: var(--cm-stack); padding: .9rem 1rem; background: var(--cm-bg);
    border: 1px solid var(--cm-border); border-radius: var(--cm-radius); }
.cm-runlog__head { margin: 0 0 var(--cm-space-3); font-weight: 600; color: var(--cm-text); }
.cm-runlog__list { gap: .45rem; font-variant-numeric: tabular-nums; }
.cm-runlog__item { display: flex; align-items: center; gap: var(--cm-space-3); font-size: var(--cm-fs-90); color: var(--cm-text-muted); }
.cm-runlog__icon { flex: none; width: 1.1rem; height: 1.1rem; display: inline-flex;
    align-items: center; justify-content: center; font-size: var(--cm-fs-85); line-height: 1; }
.cm-runlog__label { color: inherit; }
.cm-runlog__detail { color: var(--cm-text-muted); font-size: var(--cm-fs-78); min-width: 0; }
.cm-runlog__detail::before { content: "— "; }
.cm-runlog__time { margin-left: auto; color: var(--cm-text-muted); font-size: var(--cm-fs-78); font-variant-numeric: tabular-nums; }

/* per-state styling */
.cm-runlog__item--pending { opacity: .55; }
.cm-runlog__item--active  { color: var(--cm-text); font-weight: 500; }
.cm-runlog__item--done    { color: var(--cm-text); }
.cm-runlog__item--done .cm-runlog__icon  { color: var(--cm-success); }
.cm-runlog__item--error   { color: var(--cm-danger); font-weight: 500; }
.cm-runlog__item--error .cm-runlog__icon { color: var(--cm-danger); }

.cm-runlog__dot { width: .55rem; height: .55rem; border-radius: 50%;
    border: 1.5px solid var(--cm-cool-steel); }

.cm-spinner { width: .95rem; height: .95rem; border-radius: 50%;
    border: 2px solid var(--cm-cool-steel); border-top-color: transparent;
    animation: cm-spin .7s linear infinite; }
.cm-spinner--inline { display: inline-block; width: .8rem; height: .8rem; vertical-align: -1px; margin-right: .35rem; }
@keyframes cm-spin { to { transform: rotate(360deg); } }

/* live extraction status (contract detail) */
.cm-live { display: inline-flex; align-items: center; gap: .35rem; margin-left: var(--cm-space-3);
    font-size: var(--cm-fs-78); font-weight: 600; color: var(--cm-cool-steel); vertical-align: middle; }
.cm-extstatus { font-size: var(--cm-fs-85); }
.cm-extstatus--pending, .cm-extstatus--normalizing, .cm-extstatus--extracting { color: var(--cm-text-muted); }
.cm-extstatus--extracted { color: var(--cm-success); font-weight: 600; }
.cm-extstatus--failed { color: var(--cm-danger); font-weight: 600; }

/* --- Extracted-field evidence (grounding quote) --------------------------- */
.cm-evidence { margin-top: .2rem; font-size: var(--cm-fs-78); line-height: 1.35;
    color: var(--cm-text-muted); font-style: italic; max-width: 32rem;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.cm-evidence::before { content: "\201C"; }
.cm-evidence::after  { content: "\201D"; }
.cm-grounding { display: flex; align-items: center; gap: .4rem; margin-top: .25rem; flex-wrap: wrap; }
.cm-page { font-size: var(--cm-fs-78); color: var(--cm-text-muted); white-space: nowrap; }

/* --- Field history timeline (multi-document consolidation) ---------------- */
.cm-history { margin-top: .4rem; }
.cm-history__toggle { font-size: var(--cm-fs-78); color: var(--cm-blue-slate); cursor: pointer;
    list-style: disclosure-closed; user-select: none; }
details[open] > .cm-history__toggle { list-style: disclosure-open; }
.cm-history__rows { display: flex; flex-direction: column; gap: .15rem; padding: .25rem 0 .1rem; }
/* Structured history timeline (2026-07-15): the flat "old → new · doc · date" run-on line was
   unreadable — one row per change, columns Effective | Change | Source document. */
.cm-history__table { margin: var(--cm-space-2) 0 var(--cm-space-2); border-collapse: collapse; font-size: var(--cm-fs-78); }
.cm-history__th { text-align: left; padding: .2rem var(--cm-space-4) .2rem 0; color: var(--cm-text-muted);
    font-weight: 500; border-bottom: 1px solid var(--cm-border); }
.cm-history__td { padding: .25rem var(--cm-space-4) .25rem 0; vertical-align: top; }
.cm-history__date { color: var(--cm-text-muted); white-space: nowrap; }
.cm-history__old { color: var(--cm-text-muted); }
.cm-history__arrow { color: var(--cm-text-muted); padding: 0 .15rem; }
/* Source-document link (field grounding + history): same quiet size as .cm-page, but clickable. */
.cm-srclink { color: var(--cm-blue-slate); text-decoration: none; }
.cm-srclink:hover { text-decoration: underline; }
/* Dossier processing banner (2026-07-15): after filing, the page opened on "Pending/0 facts"
   with the only sign of life below the fold — this banner states, at the top, that extraction
   is running and the page updates itself. Shown only while the poll is active. */
.cm-processing { display: flex; align-items: flex-start; gap: var(--cm-space-4);
    margin: var(--cm-space-5) 0; padding: var(--cm-space-4) var(--cm-space-5);
    background: var(--cm-tint-cool); border: 1px solid var(--cm-border); border-radius: var(--cm-radius);
    color: var(--cm-text); font-size: var(--cm-fs-90); }
.cm-processing__spinner { width: 1rem; height: 1rem; flex-shrink: 0; margin-top: .15rem;
    border: 2px solid var(--cm-border); border-top-color: var(--cm-blue-slate); border-radius: 50%;
    animation: cm-spin .9s linear infinite; }
/* @keyframes cm-spin defined once above (app.css ~826); the duplicate here was removed
   (S2 CSS consolidation, Christian 2026-09-13) — keyframe names are global, one definition suffices. */

/* Extraction progress badge (2026-09-02 extraction-progress-ux). The bar is a semantic <progress>
   element — its width comes from value/max attributes, so no inline style is needed. */
.cm-exprog__bar { -webkit-appearance: none; appearance: none; width: 6rem; height: .4rem; border: 0;
    border-radius: 999px; background: var(--cm-dust-grey); overflow: hidden; }
.cm-exprog__bar::-webkit-progress-bar { background: var(--cm-dust-grey); border-radius: 999px; }
.cm-exprog__bar::-webkit-progress-value { background: var(--cm-blue-slate); border-radius: 999px; }
.cm-exprog__bar::-moz-progress-bar { background: var(--cm-blue-slate); border-radius: 999px; }
.cm-exprog__elapsed { color: var(--cm-text-muted); font-size: var(--cm-fs-78); font-variant-numeric: tabular-nums; }

/* Hover detail popup (2026-09-02 §10 addendum): pure CSS :hover + transition-delay → appears only after a
   500ms dwell. No JS, no component state, so it can never get "stuck" — the whole badge (and this child)
   unmounts on Done/Failed. The inbox table opts into .cm-table--pop (overflow:visible) so this absolute
   popup escapes .cm-table's corner-rounding overflow:hidden; the dossier banner is already unclipped. */
.cm-exprog__badge { position: relative; display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--cm-space-2); }
.cm-exprog__pop { position: absolute; top: calc(100% + var(--cm-space-2)); left: 0; z-index: 900;
    min-width: 15rem; max-width: 22rem; display: flex; flex-direction: column; gap: var(--cm-space-2);
    padding: var(--cm-space-4); background: var(--cm-surface); border: 1px solid var(--cm-border);
    border-radius: var(--cm-radius); box-shadow: var(--cm-shadow); color: var(--cm-text); font-size: var(--cm-fs-78);
    opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .12s ease, visibility .12s ease;
    transition-delay: 0s; }
.cm-exprog__badge:hover .cm-exprog__pop, .cm-exprog__badge:focus-within .cm-exprog__pop {
    opacity: 1; visibility: visible; transition-delay: 500ms; }
.cm-exprog__poptitle { font-weight: 600; word-break: break-word; }
.cm-exprog__popphase { color: var(--cm-text-muted); }
.cm-exprog__popmeta { color: var(--cm-text-muted); font-variant-numeric: tabular-nums; }
.cm-exprog__poperr { color: var(--cm-danger); }
.cm-exprog__poplist { display: flex; flex-direction: column; gap: var(--cm-space-1); margin-top: var(--cm-space-1);
    padding-top: var(--cm-space-2); border-top: 1px solid var(--cm-border); }
.cm-exprog__popmember { display: flex; align-items: center; gap: var(--cm-space-2); }
.cm-exprog__popstatus { width: .7rem; height: .7rem; flex: none; border-radius: 50%; }
.cm-exprog__popstatus--run { border: 2px solid var(--cm-border); border-top-color: var(--cm-blue-slate);
    animation: cm-spin .9s linear infinite; }
.cm-exprog__popstatus--done { background: var(--cm-celadon); }
.cm-exprog__popname { flex: 1; min-width: 0; word-break: break-word; }
.cm-exprog__popstate { color: var(--cm-text-muted); }
/* Inbox table opts out of corner-clip so the badge popup can escape the cell (see popup note above). */
.cm-table--pop { overflow: visible; }

/* Copy-quote icon button next to the evidence quote. */
.cm-copy { display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem;
    margin-left: var(--cm-space-2); padding: 0; border: 0; background: none; color: var(--cm-text-muted);
    cursor: pointer; border-radius: var(--cm-radius-sm); vertical-align: middle; }
.cm-copy:hover { color: var(--cm-blue-slate); background: var(--cm-tint); }
.cm-copy svg { width: .9rem; height: .9rem; }
.cm-history__row { display: flex; gap: .3rem; flex-wrap: wrap; font-size: var(--cm-fs-78);
    color: var(--cm-text-muted); align-items: baseline; }

/* --- Required-field gating (upload review) --------------------------------- */
.cm-req { color: var(--cm-danger); font-weight: 700; margin-left: .15rem; }
.cm-error-inline { display: inline-block; margin-left: .5rem; font-size: var(--cm-fs-78); font-weight: 600; color: var(--cm-danger); }
.cm-panel--warn { border-left: 3px solid var(--cm-danger); background: var(--cm-danger-tint); }
.cm-panel--warn label { display: inline-flex; align-items: center; gap: .4rem; margin-top: .4rem; font-weight: 500; }

/* --- Contracts list: KPIs, clickable rows, expiry highlight --------------- */
.cm-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: .75rem; margin-bottom: var(--cm-stack); }
.cm-kpi { padding: .95rem 1.05rem; display: flex; flex-direction: column; gap: .35rem; }
.cm-kpi__num { font-size: 1.7rem; font-weight: 700; color: var(--cm-text); line-height: 1; letter-spacing: -.01em; }
.cm-kpi__label { font-size: var(--cm-fs-72); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--cm-text-muted); }
/* Home reuses these KPI cards as clickable .cm-card links; expiring/review get an accent number. */
.cm-kpi--warn .cm-kpi__num { color: var(--cm-warn); }
.cm-kpi--act .cm-kpi__num { color: var(--cm-success); }

.cm-table--rows tbody tr.cm-rowlink { cursor: pointer; }
.cm-table--rows tbody tr.cm-rowlink:hover { background: var(--cm-bg); }

.cm-days--over { color: var(--cm-danger); font-weight: 700; }
.cm-days--soon { color: var(--cm-danger); font-weight: 600; }
.cm-days--warn { color: var(--cm-warn); font-weight: 600; }

/* --- About page (branded) -------------------------------------------------- */
.cm-about { max-width: 1020px; margin: 0 auto; }

.cm-about__hero { position: relative; overflow: hidden; border-radius: calc(var(--cm-radius) * 1.6);
    background:
        radial-gradient(120% 140% at 12% -10%, var(--cm-sidebar-active) 0%, transparent 55%),
        linear-gradient(135deg, #20332f 0%, #1a2a2c 60%, #16221f 100%);
    color: #eef3f1; padding: 3.2rem 3rem 2.8rem; box-shadow: 0 20px 50px rgba(20,32,30,.28); }
.cm-about__halo { position: absolute; inset: auto -8% -55% auto; width: 26rem; height: 26rem; right: -6%;
    background: radial-gradient(circle, rgba(180,206,179,.45) 0%, rgba(180,206,179,0) 68%);
    filter: blur(8px); pointer-events: none; }
.cm-about__hero::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .5;
    background-image: radial-gradient(rgba(255,255,255,.045) 1px, transparent 1px); background-size: 4px 4px; }
.cm-about__heroinner { position: relative; z-index: 1; }
@keyframes cm-about-rise { to { opacity: 1; transform: none; } }

.cm-about__eyebrow { display: inline-block; font-size: var(--cm-fs-72); font-weight: 600; letter-spacing: .22em;
    text-transform: uppercase; color: var(--cm-celadon); margin-bottom: .9rem; }
.cm-about__title { font-weight: 700; font-size: clamp(2.2rem, 5vw, 3.2rem); line-height: 1.04; letter-spacing: -.02em;
    margin: 0 0 .9rem; color: #f6f9f7; }
.cm-about__lede { max-width: 40ch; margin: 0 0 1.5rem; font-size: var(--cm-fs-110); line-height: 1.55; color: #c7d6d1; }
.cm-about__version { display: inline-block; font-family: var(--cm-font-mono);
    font-size: var(--cm-fs-78); color: var(--cm-celadon); border: 1px solid rgba(180,206,179,.4);
    border-radius: 2rem; padding: .3rem .85rem; }

.cm-about__facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem;
    margin: -1.4rem 1.2rem 0; position: relative; z-index: 2; }
.cm-about__fact { padding: .9rem 1.1rem; display: flex; flex-direction: column; gap: .25rem; }
.cm-about__fact-k { font-size: var(--cm-fs-72); letter-spacing: .12em; text-transform: uppercase; color: var(--cm-text-muted); }
.cm-about__fact-v { font-weight: 600; color: var(--cm-text); }

.cm-about__sectiontitle { font-weight: 700; font-size: 1.4rem; letter-spacing: -.01em;
    color: var(--cm-text); margin: 2.4rem 0 1rem; }
.cm-about__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1.1rem; }
.cm-about__card { position: relative; padding: 1.4rem 1.3rem 1.3rem;
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
.cm-about__card::before { content: ""; position: absolute; left: 0; top: 0; height: 3px; width: 2.6rem;
    border-radius: 0 0 3px 0; background: linear-gradient(90deg, var(--cm-blue-slate), var(--cm-celadon)); }
.cm-about__card:hover { transform: translateY(-3px); box-shadow: var(--cm-shadow-hover); border-color: var(--cm-cool-steel); }
.cm-about__icon { width: 26px; height: 26px; color: var(--cm-blue-slate); margin-bottom: .7rem; }
.cm-about__card h3 { margin: 0 0 .4rem; font-size: var(--cm-fs-100); color: var(--cm-text); }

.cm-about__footer { display: flex; align-items: center; justify-content: center; gap: .5rem; flex-wrap: wrap;
    margin: 2.4rem 0 .5rem; font-size: var(--cm-fs-85); color: var(--cm-text-muted); }
.cm-about__dot { opacity: .5; }

/* --- Eval harness --------------------------------------------------------- */
.cm-metric { display: inline-flex; flex-direction: column; gap: .15rem; margin-right: 1.5rem; }
.cm-metric__value { font-size: 1.4rem; font-weight: 600; color: var(--cm-blue-slate); }
.cm-cell--miss { background: var(--cm-danger-tint); }

/* --- License banner -------------------------------------------------------- */
.cm-licbanner { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
    padding: var(--cm-space-3) 1rem; margin-bottom: 1.1rem; border-radius: var(--cm-radius-sm);
    border: 1px solid var(--cm-border); font-size: var(--cm-fs-90); }
.cm-licbanner a { font-weight: 600; }
.cm-licbanner--warn   { background: var(--cm-dust-grey); color: var(--cm-text); }
.cm-licbanner--danger { background: var(--cm-petal-frost); color: var(--cm-petal-ink); border-color: var(--cm-petal-border); }

/* ---- Fact-graph deal views ---- */
/* .cm-factpage / .cm-factpage__title (ghost scaffold, never had CSS rules) and .cm-factpage__lead
   retired T5.5/B7: Dossiers/DossierDetail now use the app's standard h1/.cm-lead scaffold like
   every other page. .cm-form-grid stays - still used by Cockpit's column-picker checkbox grid
   (a genuinely different grid-of-checkboxes layout, not a form-field scaffold). */
.cm-card__title { font-size: var(--cm-fs-100); font-weight: 600; margin: 0 0 .75rem; color: var(--cm-text); }
.cm-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: .75rem 1rem; margin-bottom: 1rem; }
.cm-inline-create { display: flex; gap: .5rem; align-items: center; }
.cm-inline-create .cm-input { flex: 1 1 auto; min-width: 0; }
/* Search page's query bar reuses the inline row (input grows, button stays natural size —
   the former .cm-filters grid stretched the Search button across the remaining row width). */
.cm-searchbar { margin-bottom: 1.1rem; }
/* A small action beside a card title (Explorer inbox "Refresh") needs a gap to the text. */
.cm-card__title .cm-button { margin-left: var(--cm-space-3); }
/* Dossier facts hero (issue #4): the retitled facts table is the page's one hero block.
   Placed after the base .cm-card__title rule (not near .cm-lead) so the more specific
   .cm-facts__head .cm-card__title override sorts after it (no-descending-specificity). */
.cm-facts__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--cm-space-4);
    flex-wrap: wrap; margin-bottom: var(--cm-space-4); }
.cm-facts__head .cm-card__title { margin-bottom: 0; }
.cm-facts__head .cm-hint { margin: 0; }
.cm-facts__filter { min-width: 14rem; max-width: 22rem; flex: 0 1 18rem; }
/* Facts-table content size (Christian 2026-09-13). This is now the STANDARD for every cm-table and
   is carried by the base .cm-table th/td rule above; this scoped rule is a redundant explicit anchor
   (kept, not deleted) — the facts table remains the visual reference the base was aligned to. */
.cm-facts__table { font-size: var(--cm-fs-85); }
/* Links: underlined only on hover by default, so dense tables and breadcrumbs stay calm.
   BUT a link embedded in running text (inside a paragraph — hints, lead text, the stat line)
   stays underlined at rest: colour alone is not a sufficient affordance mid-sentence and fails
   WCAG 1.4.1 (feedback issue #9 — the "Application settings" hint link). Rules are ordered by
   ascending specificity for no-descending-specificity. */
.cm-link { color: var(--cm-blue-slate); font-weight: 500; text-decoration: none; text-underline-offset: 2px; }
p .cm-link { text-decoration: underline; }
.cm-link:hover { text-decoration: underline; }
.cm-derived { font-size: var(--cm-fs-110); }
/* T6.2 / C2: "pending" is a calm teaching state (e.g. "Pending — no anchor date yet"), not an
   error — it was sitting on --cm-danger (red) before; muted text matches its actual meaning. */
.cm-pending { color: var(--cm-text-muted); font-weight: 500; }
/* Button variant policy (T5.3 / B5, see the canonical comment at .cm-button--ghost): soft is the
   tertiary action - lower emphasis than ghost, used for calmer secondary actions (Move, Remove,
   Change) that sit beside a primary .cm-button in the same row/card. */
.cm-button--soft { background: var(--cm-dust-grey); color: var(--cm-text); }
/* .cm-alert--ok, .cm-badge--manual/--derived/--contract/--conflict/--end moved to the
   "Badges / lamps" section (T3.1 / A5) — grouped there with their duplicate-pair siblings. */

/* ---- Portfolio cockpit group header ---- */
/* Group header slim strip (redesign 2026-07-14): a small muted label row instead of a full-height band —
   background reuses --cm-tint, the existing "subtle selected/hover fill" token. */
/* .cm-lamp base + modifiers moved to the "Badges / lamps" section (T3.1 / A5) */

/* ---- Assistant (grounded chat) ---- */
/* Session sidebar + main pane, re-homed here from a chronological-append tail location (T3.1 / A5
   "chat to chat" re-home) — this is the outer layout for the whole Assistant page. */
.cm-chat-layout { display: grid; grid-template-columns: 240px 1fr; gap: 0 1.4rem; align-items: stretch; flex: 1; min-height: 0; }
.cm-chat-main { min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.cm-chat-sessions { display: flex; flex-direction: column; gap: var(--cm-space-3); }
.cm-chat-sessions__new { width: 100%; }
.cm-chat-sessions__list { gap: .3rem; max-height: 32rem; overflow-y: auto; }
.cm-chat-sessions__item { width: 100%; text-align: left; background: var(--cm-surface); border: 1px solid var(--cm-border);
    border-radius: var(--cm-radius-sm); padding: .5rem var(--cm-space-4); cursor: pointer; display: flex; flex-direction: column; gap: .15rem; }
.cm-chat-sessions__item:hover { border-color: var(--cm-cool-steel); }
.cm-chat-sessions__item:disabled { cursor: default; opacity: .6; }
.cm-chat-sessions__item--active { background: var(--cm-dust-grey); border-color: var(--cm-blue-slate); }
.cm-chat-sessions__title { font-weight: 500; color: var(--cm-text); }
.cm-chat-sessions__meta { font-size: var(--cm-fs-78); color: var(--cm-text-muted); }

/* Page root (redesign 2026-07-14): h1 + lead stay in normal flow at top; the chat grid below fills the
   REMAINING .cm-main height (the app shell is height-locked — .cm-main itself scrolls, this page's own
   content should not need to). */
.cm-chat-page { display: flex; flex-direction: column; height: 100%; min-height: 0; }
/* One card, flex column: messages scroll internally (flex:1; min-height:0; overflow-y:auto below),
   composer stays pinned at the bottom. */
.cm-chat-canvas { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.cm-chat { display: flex; flex-direction: column; gap: .9rem; flex: 1; min-height: 0; overflow-y: auto; }
.cm-chat__msg { display: flex; flex-direction: column; max-width: 42rem; }
.cm-chat__msg--user { align-items: flex-end; align-self: flex-end; }
.cm-chat__msg--assistant { align-items: flex-start; align-self: flex-start; }
.cm-chat__bubble { border-radius: var(--cm-radius); padding: var(--cm-space-4) .9rem; box-shadow: var(--cm-shadow);
    white-space: pre-wrap; word-break: break-word; }
.cm-chat__msg--user .cm-chat__bubble { background: var(--cm-blue-slate); color: var(--cm-text-inverse); }
.cm-chat__msg--assistant .cm-chat__bubble { background: var(--cm-surface); border: 1px solid var(--cm-border); }
.cm-chat__composer { display: flex; gap: var(--cm-space-3); align-items: flex-start; flex: none;
    border-top: 1px solid var(--cm-border); padding-top: .9rem; margin-top: .9rem; }
.cm-chat__composer .cm-input { flex: 1 1 auto; resize: vertical; }

/* Canvas empty state (redesign 2026-07-14): centered teaching block instead of a lone floating sentence. */
.cm-chat__emptystate { display: flex; flex-direction: column; align-items: center; justify-content: center;
    text-align: center; flex: 1; min-height: 0; gap: .35rem; padding: 2rem 1rem; }
.cm-chat__emptyicon { width: 40px; height: 40px; color: var(--cm-text-muted); opacity: .7; margin-bottom: .4rem; }
.cm-chat__emptylead { margin: 0; color: var(--cm-text-muted); }
.cm-chat__examples { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; margin-top: var(--cm-stack); max-width: 42rem; }
.cm-chat__examplechip { border: none; cursor: pointer; font: inherit; }
.cm-chat__examplechip:hover { background: var(--cm-tint); }

/* ---- Dossier type badge + completeness card / pill (Task 10) ---- */
.cm-typebadge { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cm-space-3); margin: -.3rem 0 1rem; }
.cm-typebadge__editor { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
/* .cm-badge--type moved to the "Badges / lamps" section (T3.1 / A5), grouped with --derived */

/* Identity row + status line (issue #4 "calm stage"): one wrap-tolerant row of compact signals,
   no card frames. Replaces the former Countries/End-date/Completeness cards. */
.cm-identity { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cm-space-3); margin-bottom: var(--cm-space-3); }
.cm-identity h1 { margin: 0; }
.cm-statusline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cm-space-3) var(--cm-space-6);
    margin: var(--cm-space-3) 0 var(--cm-stack); }
.cm-statusline__item { display: inline-flex; align-items: center; }
.cm-statusline__muted { color: var(--cm-text-muted); }
/* Signal = a text-styled trigger; reuses the linkbutton palette but stays unadorned until hover. */
.cm-statusline__signal { display: inline-flex; align-items: center; gap: var(--cm-space-2);
    background: transparent; border: 0; padding: var(--cm-space-1) 0; font: inherit; color: var(--cm-text);
    cursor: pointer; text-decoration: none; }
.cm-statusline__signal:hover { color: var(--cm-blue-slate); }
.cm-statusline__signal:focus-visible { outline: none; box-shadow: var(--cm-focus-ring); border-radius: var(--cm-radius-sm); }
/* Country chips in the status line (DossierDetail dense rebuild §G): the country list wraps on its own
   so a long territory doesn't blow out the one-row status line; each chip pairs a status badge
   (green = confirmed, amber = unconfirmed) with its inline per-item action(s) — the "×" remove, or
   Confirm/Dismiss for an unconfirmed country. */
.cm-ctrylist { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--cm-space-2); }
.cm-ctrychip { display: inline-flex; align-items: center; gap: var(--cm-space-1); }
/* Territories tab: one territory per row (badge left, actions right) — not the header's inline run. */
.cm-ctryrows { display: flex; flex-direction: column; max-width: 34rem; }
.cm-ctryrow { display: flex; align-items: center; justify-content: space-between; gap: var(--cm-space-4);
    padding: var(--cm-space-2) 0; border-bottom: 1px solid var(--cm-border); }
.cm-ctryrow:last-child { border-bottom: none; }
/* Inline row actions — two or three small actions side by side in one cell/row. Generalised
   from the country-row variant so the next table gets the established spacing, not a new one. */
.cm-inlineactions, .cm-ctryrow__actions { display: inline-flex; align-items: center; gap: var(--cm-space-2); }

/* Read-only click/focus popover (end-date pending reason) — same :focus-within idiom as
   .cm-exprog__pop, generalized. CmDialog is used for editors; this is for a one-line read-only note. */
.cm-pop { position: relative; }
.cm-pop__panel { position: absolute; top: calc(100% + var(--cm-space-2)); left: 0; z-index: 900;
    min-width: 14rem; max-width: 22rem; padding: var(--cm-space-4); background: var(--cm-surface);
    border: 1px solid var(--cm-border); border-radius: var(--cm-radius-sm); box-shadow: var(--cm-shadow-hover);
    color: var(--cm-text-muted); font-size: var(--cm-fs-85); opacity: 0; visibility: hidden; }
.cm-pop:hover .cm-pop__panel, .cm-pop:focus-within .cm-pop__panel { opacity: 1; visibility: visible; }

.cm-completeness__stat { font-weight: 600; font-size: var(--cm-fs-100); margin: 0 0 var(--cm-space-3); }
.cm-completeness__list { gap: var(--cm-space-3); }
.cm-completeness__row { display: flex; align-items: center; justify-content: space-between; gap: .75rem;
    flex-wrap: wrap; padding: .5rem 0; border-top: 1px solid var(--cm-border); }
.cm-completeness__row:first-child { border-top: 0; padding-top: 0; }
.cm-completeness__field { display: flex; align-items: baseline; gap: .5rem; }
.cm-completeness__label { font-weight: 500; }
.cm-completeness__entry { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.cm-completeness__optional { margin-top: .75rem; font-size: var(--cm-fs-85); color: var(--cm-text-muted); }
.cm-completeness__optional summary { cursor: pointer; }
.cm-completeness__pill { background: var(--cm-dust-grey); color: var(--cm-text); font-variant-numeric: tabular-nums; }

/* ---- Inline fact editing in the Dossier facts table (issue #13) ----
   Deliberately the SAME flex row as .cm-completeness__entry: the editor is the same shared
   TypedValueInput, so it must not look like a second kind of control. */
.cm-factedit { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
/* The document value a manual correction hides — quiet, under the value it was replaced by. */
.cm-factedit__overridden { color: var(--cm-text-muted); font-size: var(--cm-fs-78); margin-top: .2rem; }
/* Why a calculated row has no Edit button, in the action column's own type scale. */
.cm-factedit__locked { color: var(--cm-text-muted); font-size: var(--cm-fs-78); }

/* ---- Derived-value formula chip + shadowed-snapshot surfacing (Task 9, event anchors) ---- */
.cm-chip { display: inline-flex; flex-direction: column; gap: .35rem; margin-left: .5rem;
    padding: .35rem var(--cm-space-3); border-radius: var(--cm-radius-sm); background: var(--cm-dust-grey);
    font-size: var(--cm-fs-78); color: var(--cm-text-muted); vertical-align: top; }
.cm-chip__formula { font-family: var(--cm-font-mono); color: var(--cm-text); }
.cm-chip__shadow { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
    padding-top: .35rem; border-top: 1px dashed var(--cm-border); color: var(--cm-danger); }
.cm-chip__shadow-actions { display: flex; gap: .5rem; }

/* Condition status segmented control (Open / Met), reusing the chip surface */
.cm-chip--segment { flex-direction: row; display: inline-flex; padding: .15rem; gap: 0; }
.cm-chip__seg { border: 0; background: transparent; padding: .3rem .7rem; border-radius: var(--cm-radius-sm);
    font-size: var(--cm-fs-78); font-weight: 500; color: var(--cm-text-muted); cursor: pointer; }
.cm-chip__seg--active { background: var(--cm-surface); color: var(--cm-text); box-shadow: var(--cm-shadow); }

/* ---- Dossier type field editor: derivation rule sub-row (Task 8, event anchors) ---- */
.cm-fieldrule { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .75rem 1.5rem; }
.cm-fieldrule .cm-form__field { min-width: 12rem; gap: .3rem; }
/* Quiet underline tabs (first user: the partner dialog's Partner/Contacts split — the single
   scrolling form buried the contacts editor below the fold). */
.cm-tabs { display: flex; gap: var(--cm-space-5); border-bottom: 1px solid var(--cm-border); margin-bottom: var(--cm-space-5); }
.cm-tabs__tab { border: 0; background: none; padding: var(--cm-space-2) var(--cm-space-1) var(--cm-space-3);
    margin-bottom: -1px; font: inherit; font-size: var(--cm-control-fs); font-weight: 500; cursor: pointer;
    color: var(--cm-text-muted); border-bottom: 2px solid transparent; }
.cm-tabs__tab:hover { color: var(--cm-blue-slate); }
.cm-tabs__tab--active { color: var(--cm-blue-slate); border-bottom-color: var(--cm-blue-slate); font-weight: 600; }
/* Tab pane with a floor height, so switching tabs never resizes the dialog under the cursor. */
.cm-tabpane { min-height: 21rem; }

/* Contact editor rows in the partner dialog: one bordered card per contact with a labeled 2×2
   field grid — four inputs squeezed into table columns were unusably narrow in an md dialog. */
.cm-contactrow { border: 1px solid var(--cm-border); border-radius: var(--cm-radius-sm);
    padding: var(--cm-space-4); margin-bottom: var(--cm-space-4); }
.cm-contactrow__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--cm-space-3); }
.cm-contactrow__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--cm-space-3) var(--cm-space-5); }

/* Two related rule inputs side by side in the field editor (notify lead + fallback). */
.cm-fieldrule__pair { display: flex; gap: var(--cm-space-5); flex-wrap: wrap; margin-bottom: var(--cm-space-4); }
.cm-fieldrule__pair .cm-form__field { flex: 1 1 14rem; }
}

/* --- Utilities (single-purpose helper classes + place-specific overrides) ---- */
@layer utilities {
/* .cm-mt is no longer a private ad hoc patch value (T3.4 / A8) - it now resolves to the
   canonical section rhythm, same as every other selector in this unification. */
.cm-mt { margin-top: var(--cm-stack); }
.cm-panel { max-width: 40rem; margin: var(--cm-space-page) auto; }
.cm-form--wide { max-width: none; }
/* caption/footnote under a table or list (e.g. "X of Y shown") */
.cm-table-note { color: var(--cm-text-muted); font-size: var(--cm-fs-85); margin: .7rem 0 0; }
/* "working…" indicator (e.g. while re-extracting) */
.cm-busy { color: var(--cm-text-muted); font-style: italic; animation: cm-busy-pulse 1.1s ease-in-out infinite; }
@keyframes cm-busy-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

/* .cm-truncate utility (T3.2 / A6, merge-candidate #7): single-line ellipsis truncation,
   byte-identical across .cm-explorer__label, .cm-runlog__detail, .cm-chat-sessions__title -
   grouped once; each keeps its own unique declarations in its topical (components-layer) rule. */
.cm-truncate, .cm-explorer__label, .cm-runlog__detail, .cm-chat-sessions__title {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* .cm-hint did not exist anywhere in app.css — added here as it's used across
   the Explorer content panel for secondary/explanatory text under a heading. */
.cm-hint { color: var(--cm-text-muted); font-size: var(--cm-fs-85); }

/* .cm-microlabel utility (T3.2 / A6, merge-candidate #4): .cm-detail dt, .cm-metric__label and
   .cm-completeness__kind were byte-identical uppercase micro-labels - grouped once here. Near
   siblings (.cm-stat__label, .cm-kpi__label, .cm-admin__group-label, .cm-about__fact-k) keep
   their own slightly different values; those get tokenized onto the type scale in T3.3. */
.cm-microlabel, .cm-detail dt, .cm-metric__label, .cm-completeness__kind {
    color: var(--cm-text-muted); font-size: var(--cm-fs-78); text-transform: uppercase; letter-spacing: .03em;
}

/* --- Place-specific overrides (T7.1 / D2) --------------------------------------
   These selectors are more specific compositions that need to beat a shared components-layer
   base rule in one particular place (a cockpit cell, a missing-row highlight, an about-page
   stagger, a notification row, a field-rule row) — exactly the "descending specificity" shape
   the stylelint gate previously flagged 13 times, because the override sat later in the file at
   EQUAL OR LOWER specificity than the base rule it was overriding. Cascade layers fix this
   category outright: this layer is declared last, so every rule here wins over its components-
   layer base regardless of selector specificity or file order — no line-reordering needed, and
   no risk of a future edit accidentally undoing a fragile specificity ordering. */

/* Compact cockpit table cells (redesign 2026-07-14; densified 2026-07-15 — with a 20-field type
   the old 16rem/roomy-padding cells forced three screens of horizontal scroll, which is the
   opposite of a cockpit): tighter padding, smaller type, narrower cap, and HEADERS may wrap to
   two lines instead of dictating the column width. */
.cm-cockpit__table th, .cm-cockpit__table td { white-space: nowrap; max-width: 11rem; overflow: hidden; text-overflow: ellipsis;
    padding: var(--cm-space-2) var(--cm-space-3); font-size: var(--cm-fs-85); }
/* Headers stay ONE line (wrapping produced ragged multi-height headers) — long labels truncate
   with an ellipsis; the full name is in the tooltip. */
.cm-cockpit__table thead th { font-size: var(--cm-fs-72); }

/* Missing-required-field row highlight overrides the base .cm-table row border-bottom cadence. */
.cm-row--missing > td { background: var(--cm-danger-tint); }

/* About-page hero stagger-in animation overrides .cm-collapse's generic ">*:first-of-type" margin
   reset for the (unrelated, but selector-overlapping) hero children. */
.cm-about__heroinner > * { opacity: 0; transform: translateY(12px); animation: cm-about-rise .6s cubic-bezier(.2,.7,.2,1) forwards; }
.cm-about__heroinner > *:nth-child(1) { animation-delay: .05s; }
.cm-about__heroinner > *:nth-child(2) { animation-delay: .14s; }
.cm-about__heroinner > *:nth-child(3) { animation-delay: .23s; }
.cm-about__heroinner > *:nth-child(4) { animation-delay: .32s; }

/* About-card body copy overrides the reconnect-modal's generic "p" reset (never actually
   co-rendered — same page never shows both — but the selectors overlap enough to trip the linter). */
.cm-about__card p { margin: 0; font-size: var(--cm-fs-90); line-height: 1.5; color: var(--cm-text-muted); }

/* Cockpit group-header row overrides the base .cm-table thead th treatment (it is itself a
   <th>, styled as a slim label strip instead of the column-header banner). */
.cm-cockpit__table .cm-cockpit__group th { background: var(--cm-tint); color: var(--cm-text-muted); font-size: var(--cm-fs-78); max-width: none;
    font-weight: 600; padding: .3rem .75rem; text-align: left; }

/* Unread notification row overrides the base .cm-table row treatment with bold text. */
.cm-notif--unread td { font-weight: 600; }

/* Dossier-type field editor's inline derivation-rule sub-row overrides the base .cm-table row
   background with the shared "subtle fill" tint. */
.cm-fieldrule-row td { background: var(--cm-tint); }

/* --- Responsive --------------------------------------------------------------
   Single breakpoint (T3.5 / A9, 2026-07-14 CSS assessment): the shell-collapse rules moved
   here from their own 820px query (the 80px gap to the explorer's breakpoint encoded no design
   decision) and merged with the Explorer's collapse rules - one 900px breakpoint for the whole
   app. Lives in the utilities layer (last) because its overrides span both the layout layer
   (.cm-body/.cm-sidebar/.cm-main) and the components layer (.cm-2col/
   .cm-admin__body/.cm-admin__nav/.cm-chat-layout/.cm-explorer/.cm-explorer__tree) — a layer
   earlier than components could never win against a components-layer base rule, media query
   or not, so this has to be the last-declared layer to correctly override everything it targets. */
@media (max-width: 900px) {
    .cm-body { flex-direction: column; }
    /* Narrow width (issue #11): the sidebar becomes a single compact, horizontally-scrollable
       top strip — icon + label only. The old rule kept every description subline and wrapped the
       full-height nav into a tall dark block that shoved the content far down the page. */
    .cm-sidebar { width: auto; flex-direction: row; flex-wrap: nowrap; align-items: center;
        gap: .1rem; overflow-x: auto; overflow-y: hidden; padding: .35rem .6rem; }
    .cm-sidebar .cm-sidebar__link { align-items: center; padding: .4rem .6rem; white-space: nowrap; }
    .cm-sidebar__desc, .cm-sidebar__usermeta, .cm-sidebar__about, .cm-sidebar__brandtext { display: none; }
    .cm-sidebar__footer { margin: 0 0 0 auto; padding-top: 0; border-top: none; flex-direction: row;
        align-items: center; gap: .5rem; }
    .cm-sidebar__user { border-top: none; padding-top: 0; }
    .cm-main { padding: 1.25rem 1.1rem; }
    .cm-2col { grid-template-columns: 1fr; }
    .cm-admin__body { grid-template-columns: 1fr; gap: 1.25rem; }
    .cm-admin__nav { position: static; flex-direction: row; flex-wrap: wrap; gap: .75rem 1.25rem; }
    .cm-chat-layout { grid-template-columns: 1fr; }
    .cm-explorer { grid-template-columns: 1fr; }
    .cm-explorer__tree { position: static; }
}
}
